yeahuh / rpms / qemu-kvm

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