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