|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v3] x86/svm: Intercept CR0 writes selectively
Since 3356d685dbda ("x86/svm: Remove lazy FPU support"), Xen does not
need to track when the TS or MP bits change so opt to intercept CR0
writes selectively. Aside from potentially reducing a few VMEXITs, this
fixes a nested virt bug where L1 intercepts CR0_SEL_WRITE and L0
intercepts CR0_WRITE. The hardware prioritizes CR0_WRITE and so L1 never
sees any CR0 writes.
Since CR0 TS/MP bits may now change behind Xen's back, sync CR0 on
VMEXIT so that the emulator sees the correct values.
Shadow mode continues to use the full CR0_WRITE intercept since with
Shadow the CR0 in the VMCB is not the same as the value Xen tracks on
behalf of the guest and allowing the guest to change one of them
directly would be fragile.
Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
---
In v3: Change HAP only, not Shadow
xen/arch/x86/hvm/svm/svm.c | 7 ++++++-
xen/arch/x86/hvm/svm/vmcb.c | 7 +++++++
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 5f5d903d872d..4e0f3282251f 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -1640,7 +1640,8 @@ static void svm_vmexit_do_cr_access(
{
int gp, cr, dir, rc;
- cr = vmcb->exitcode - VMEXIT_CR0_READ;
+ cr = (vmcb->exitcode == VMEXIT_CR0_SEL_WRITE)
+ ? 16 : (vmcb->exitcode - VMEXIT_CR0_READ);
dir = (cr > 15);
cr &= 0xf;
gp = vmcb->ei.mov_cr.gpr;
@@ -2519,7 +2520,10 @@ void asmlinkage svm_vmexit_handler(void)
v->arch.hvm.guest_cr[2] = vmcb_get_cr2(vmcb);
if ( paging_mode_hap(v->domain) )
+ {
+ v->arch.hvm.guest_cr[0] = vmcb_get_cr0(vmcb);
v->arch.hvm.guest_cr[3] = v->arch.hvm.hw_cr[3] = vmcb_get_cr3(vmcb);
+ }
if ( nestedhvm_enabled(v->domain) && nestedhvm_vcpu_in_guestmode(v) )
vcpu_guestmode = 1;
@@ -2883,6 +2887,7 @@ void asmlinkage svm_vmexit_handler(void)
case VMEXIT_CR0_READ ... VMEXIT_CR15_READ:
case VMEXIT_CR0_WRITE ... VMEXIT_CR15_WRITE:
+ case VMEXIT_CR0_SEL_WRITE:
if ( cpu_has_svm_decode && vmcb->ei.mov_cr.mov_insn )
svm_vmexit_do_cr_access(vmcb, regs);
else if ( !hvm_emulate_one_insn(x86_insn_is_cr_access, "CR access") )
diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c
index 975a1eaef806..d069280a4da8 100644
--- a/xen/arch/x86/hvm/svm/vmcb.c
+++ b/xen/arch/x86/hvm/svm/vmcb.c
@@ -154,6 +154,13 @@ static int construct_vmcb(struct vcpu *v)
vmcb->_cr_intercepts &=
~(CR_INTERCEPT_CR3_READ|CR_INTERCEPT_CR3_WRITE);
+ /*
+ * Xen is not interested in changes to the MP and TS bits so use
+ * CR0_SEL_WRITE to avoid unnecessary intercepts.
+ */
+ vmcb->_cr_intercepts &= ~CR_INTERCEPT_CR0_WRITE;
+ vmcb->_general1_intercepts |= GENERAL1_INTERCEPT_CR0_SEL_WRITE;
+
/*
* No point in intercepting INVLPG if we don't have shadow pagetables
* that need to be fixed up.
--
2.53.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |