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