|
|
958e1b |
From 848115120ffa7b2287069fe6d23683304b9ffec1 Mon Sep 17 00:00:00 2001
|
|
|
958e1b |
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
958e1b |
Date: Fri, 12 Sep 2014 11:56:31 +0200
|
|
|
958e1b |
Subject: [PATCH 31/43] target-i386: get CPL from SS.DPL
|
|
|
958e1b |
|
|
|
958e1b |
Message-id: <1410522991-11612-2-git-send-email-pbonzini@redhat.com>
|
|
|
958e1b |
Patchwork-id: 61022
|
|
|
958e1b |
O-Subject: [RHEL 7.1 qemu-kvm PATCH] target-i386: get CPL from SS.DPL
|
|
|
958e1b |
Bugzilla: 1097363
|
|
|
958e1b |
RH-Acked-by: wei@redhat.com
|
|
|
958e1b |
RH-Acked-by: Radim Krcmar <rkrcmar@redhat.com>
|
|
|
958e1b |
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
958e1b |
|
|
|
958e1b |
CS.RPL is not equal to the CPL in the few instructions between
|
|
|
958e1b |
setting CR0.PE and reloading CS. We get this right in the common
|
|
|
958e1b |
case, because writes to CR0 do not modify the CPL, but it would
|
|
|
958e1b |
not be enough if an SMI comes exactly during that brief period.
|
|
|
958e1b |
Were this to happen, the RSM instruction would erroneously set
|
|
|
958e1b |
CPL to the low two bits of the real-mode selector; and if they are
|
|
|
958e1b |
not 00, the next instruction fetch cannot access the code segment
|
|
|
958e1b |
and causes a triple fault.
|
|
|
958e1b |
|
|
|
958e1b |
However, SS.DPL *is* always equal to the CPL. In real processors
|
|
|
958e1b |
(AMD only) there is a weird case of SYSRET setting SS.DPL=SS.RPL
|
|
|
958e1b |
from the STAR register while forcing CPL=3, but we do not emulate
|
|
|
958e1b |
that.
|
|
|
958e1b |
|
|
|
958e1b |
Tested-by: Kevin O'Connor <kevin@koconnor.net>
|
|
|
958e1b |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
958e1b |
(cherry picked from commit 7125c937c97d9ec4a41b3cb6d1b3e805ec53e255)
|
|
|
958e1b |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
958e1b |
|
|
|
958e1b |
Conflicts:
|
|
|
958e1b |
target-i386/cpu.h [only needed for TCG and has other dependencies]
|
|
|
958e1b |
---
|
|
|
958e1b |
target-i386/kvm.c | 2 +-
|
|
|
958e1b |
target-i386/machine.c | 8 ++++++++
|
|
|
958e1b |
2 files changed, 9 insertions(+), 1 deletion(-)
|
|
|
958e1b |
|
|
|
958e1b |
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
|
|
|
958e1b |
index 6b250f5..65362ac 100644
|
|
|
958e1b |
--- a/target-i386/kvm.c
|
|
|
958e1b |
+++ b/target-i386/kvm.c
|
|
|
958e1b |
@@ -1381,7 +1381,7 @@ static int kvm_get_sregs(X86CPU *cpu)
|
|
|
958e1b |
HF_OSFXSR_MASK | HF_LMA_MASK | HF_CS32_MASK | \
|
|
|
958e1b |
HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)
|
|
|
958e1b |
|
|
|
958e1b |
- hflags = (env->segs[R_CS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
|
|
|
958e1b |
+ hflags = (env->segs[R_SS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
|
|
|
958e1b |
hflags |= (env->cr[0] & CR0_PE_MASK) << (HF_PE_SHIFT - CR0_PE_SHIFT);
|
|
|
958e1b |
hflags |= (env->cr[0] << (HF_MP_SHIFT - CR0_MP_SHIFT)) &
|
|
|
958e1b |
(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK);
|
|
|
958e1b |
diff --git a/target-i386/machine.c b/target-i386/machine.c
|
|
|
958e1b |
index 42b049b..87fd496 100644
|
|
|
958e1b |
--- a/target-i386/machine.c
|
|
|
958e1b |
+++ b/target-i386/machine.c
|
|
|
958e1b |
@@ -296,6 +296,14 @@ static int cpu_post_load(void *opaque, int version_id)
|
|
|
958e1b |
env->segs[R_SS].flags &= ~(env->segs[R_SS].flags & DESC_DPL_MASK);
|
|
|
958e1b |
}
|
|
|
958e1b |
|
|
|
958e1b |
+ /* Older versions of QEMU incorrectly used CS.DPL as the CPL when
|
|
|
958e1b |
+ * running under KVM. This is wrong for conforming code segments.
|
|
|
958e1b |
+ * Luckily, in our implementation the CPL field of hflags is redundant
|
|
|
958e1b |
+ * and we can get the right value from the SS descriptor privilege level.
|
|
|
958e1b |
+ */
|
|
|
958e1b |
+ env->hflags &= ~HF_CPL_MASK;
|
|
|
958e1b |
+ env->hflags |= (env->segs[R_SS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
|
|
|
958e1b |
+
|
|
|
958e1b |
/* XXX: restore FPU round state */
|
|
|
958e1b |
env->fpstt = (env->fpus_vmstate >> 11) & 7;
|
|
|
958e1b |
env->fpus = env->fpus_vmstate & ~0x3800;
|
|
|
958e1b |
--
|
|
|
958e1b |
1.8.3.1
|
|
|
958e1b |
|