5544c1b
From 45af32e160bf339974a74bb8a38384b95aa2f555 Mon Sep 17 00:00:00 2001
5544c1b
From: David Gibson <david@gibson.dropbear.id.au>
5544c1b
Date: Tue, 25 Sep 2012 17:12:20 +0000
5544c1b
Subject: [PATCH] pseries: Don't test for MSR_PR for hypercalls under KVM
5544c1b
5544c1b
PAPR hypercalls should only be invoked from the guest kernel, not guest
5544c1b
user programs, that is, with MSR[PR]=0.  Currently we check this in
5544c1b
spapr_hypercall, returning H_PRIVILEGE if MSR[PR]=1.
5544c1b
5544c1b
However, under KVM the state of MSR[PR] is already checked by the host
5544c1b
kernel before passing the hypercall to qemu, making this check redundant.
5544c1b
Worse, however, we don't generally synchronize KVM and qemu state on the
5544c1b
hypercall path, meaning that qemu could incorrectly reject a hypercall
5544c1b
because it has a stale MSR value.
5544c1b
5544c1b
This patch fixes the problem by moving the privilege test exclusively to
5544c1b
the TCG hypercall path.
5544c1b
5544c1b
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
5544c1b
CC: qemu-stable@nongnu.org
5544c1b
Signed-off-by: Alexander Graf <agraf@suse.de>
5544c1b
(cherry picked from commit efcb9383b974114e5f682e531346006f8f2466c0)
5544c1b
5544c1b
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
5544c1b
---
5544c1b
 hw/spapr.c       | 7 ++++++-
5544c1b
 hw/spapr_hcall.c | 5 -----
5544c1b
 2 files changed, 6 insertions(+), 6 deletions(-)
5544c1b
5544c1b
diff --git a/hw/spapr.c b/hw/spapr.c
5544c1b
index c34b767..5e55430 100644
5544c1b
--- a/hw/spapr.c
5544c1b
+++ b/hw/spapr.c
5544c1b
@@ -556,7 +556,12 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
5544c1b
 
5544c1b
 static void emulate_spapr_hypercall(CPUPPCState *env)
5544c1b
 {
5544c1b
-    env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]);
5544c1b
+    if (msr_pr) {
5544c1b
+        hcall_dprintf("Hypercall made with MSR[PR]=1\n");
5544c1b
+        env->gpr[3] = H_PRIVILEGE;
5544c1b
+    } else {
5544c1b
+        env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]);
5544c1b
+    }
5544c1b
 }
5544c1b
 
5544c1b
 static void spapr_reset(void *opaque)
5544c1b
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
5544c1b
index abd847f..38098f7 100644
5544c1b
--- a/hw/spapr_hcall.c
5544c1b
+++ b/hw/spapr_hcall.c
5544c1b
@@ -713,11 +713,6 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
5544c1b
 target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode,
5544c1b
                              target_ulong *args)
5544c1b
 {
5544c1b
-    if (msr_pr) {
5544c1b
-        hcall_dprintf("Hypercall made with MSR[PR]=1\n");
5544c1b
-        return H_PRIVILEGE;
5544c1b
-    }
5544c1b
-
5544c1b
     if ((opcode <= MAX_HCALL_OPCODE)
5544c1b
         && ((opcode & 0x3) == 0)) {
5544c1b
         spapr_hcall_fn fn = papr_hypercall_table[opcode / 4];