aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2012-10-08 18:17:36 +0000
committerAlexander Graf <agraf@suse.de>2012-10-29 11:45:54 +0100
commitc89d52997cf4849a9ee16b5d2cf462d0cd137634 (patch)
treef7df605ebd1f171f584cec1ffa71c674d69dc2f1
parent094b287f0b3b79d1e68df8f3a63cb144ec9cdfb6 (diff)
pseries: Don't allow duplicate registration of hcalls or RTAS calls
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>
-rw-r--r--hw/spapr_hcall.c3
-rw-r--r--hw/spapr_rtas.c9
2 files changed, 10 insertions, 2 deletions
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index 194d9c24b5..762493a0f7 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 67da27ba51..ce76c5856a 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;