Patchwork [06/22] pseries: Don't allow duplicate registration of hcalls or RTAS calls

login
register
mail settings
Submitter Alexander Graf
Date Oct. 29, 2012, 10:25 a.m.
Message ID <1351506371-23632-7-git-send-email-agraf@suse.de>
Download mbox | patch
Permalink /patch/194978/
State New
Headers show

Comments

Alexander Graf - Oct. 29, 2012, 10:25 a.m.
From: David Gibson <david@gibson.dropbear.id.au>

Currently the pseries machine code allows a callback to be registered
for a hypercall number twice, as long as it's the same callback the second
time.  We don't test for duplicate registrations of RTAS callbacks at all
so it will effectively be last registratiojn wins.

This was originally done because it was awkward to ensure that the
registration happened exactly once, but the code has since been
restructured so that's no longer the case.

Duplicate registration of a hypercall or RTAS call could well suggest
a duplicate initialization which could cause other problems, so this patch
makes duplicate registrations a bug, to prevent the old behaviour from
hiding other bugs.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
 hw/spapr_hcall.c |    3 +--
 hw/spapr_rtas.c  |    9 +++++++++
 2 files changed, 10 insertions(+), 2 deletions(-)

Patch

diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index 194d9c2..762493a 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -670,11 +670,10 @@  void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
     } else {
         assert((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX));
 
-
         slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
     }
 
-    assert(!(*slot) || (fn == *slot));
+    assert(!(*slot));
     *slot = fn;
 }
 
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index 67da27b..ce76c58 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -241,6 +241,15 @@  target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
 
 void spapr_rtas_register(const char *name, spapr_rtas_fn fn)
 {
+    int i;
+
+    for (i = 0; i < (rtas_next - rtas_table); i++) {
+        if (strcmp(name, rtas_table[i].name) == 0) {
+            fprintf(stderr, "RTAS call \"%s\" registered twice\n", name);
+            exit(1);
+        }
+    }
+
     assert(rtas_next < (rtas_table + TOKEN_MAX));
 
     rtas_next->name = name;