Skip to contentSkip to conversation

Nested Virtualization: CRn & paged real mode

PATCH In review Christoph Egger 1 participant 1 message Jun 3, 2010

lore
Share & tools
lore
#0 lore raw

PATCH 6/15 Nested Virtualization: CRn & paged real mode

Signature · 6 lines
---to satisfy European Law for business letters:
Advanced Micro Devices GmbH
Einsteinring 24, 85609 Dornach b. Muenchen
Geschaeftsfuehrer: Andrew Bowd, Thomas M. McCoy, Giuliano Meroni
Sitz: Dornach, Gemeinde Aschheim, Landkreis Muenchen
Registergericht Muenchen, HRB Nr. 43632

# HG changeset patch
# User cegger
# Date 1275382026 -7200
Allow paged real mode during vmrun emulation. Emulate cr0 and cr4 when guest does not intercept them.

xen/arch/x86/hvm/emulate.c +23 -4
diff -r 93d2b0f9f955 -r b009d9b7b708 xen/arch/x86/hvm/emulate.c
@@ -20,6 +20,7 @@
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/trace.h>
 #include <asm/hvm/support.h>
+#include <asm/hvm/nestedhvm.h>
 
 static void hvmtrace_io_assist(int is_mmio, ioreq_t *p)
 {
@@ -780,13 +781,17 @@ static int hvmemul_read_cr(
     unsigned long *val,
     struct x86_emulate_ctxt *ctxt)
 {
+    struct vcpu *v = current;
     switch ( reg )
     {
-    case 0:
     case 2:
     case 3:
+        *val = v->arch.hvm_vcpu.guest_cr[reg];
+        HVMTRACE_LONG_2D(CR_READ, reg, TRC_PAR_LONG(*val));
+        return X86EMUL_OKAY;
+    case 0:
     case 4:
-        *val = current->arch.hvm_vcpu.guest_cr[reg];
+        *val = hvm_get_cr(v, reg);
         HVMTRACE_LONG_2D(CR_READ, reg, TRC_PAR_LONG(*val));
         return X86EMUL_OKAY;
     default:
@@ -801,18 +806,32 @@ static int hvmemul_write_cr(
     unsigned long val,
     struct x86_emulate_ctxt *ctxt)
 {
+    struct vcpu *v = current;
+    bool_t vcpu_guestmode;
+
+    vcpu_guestmode = (nestedhvm_enabled(v->domain)
+        && nestedhvm_vcpu_in_guestmode(v));
+
     HVMTRACE_LONG_2D(CR_WRITE, reg, TRC_PAR_LONG(val));
     switch ( reg )
     {
     case 0:
-        return hvm_set_cr0(val);
+        if (vcpu_guestmode) {
+            VCPU_NESTEDHVM(v).nh_cr[0] = val;
+            return X86EMUL_OKAY;
+        } else
+            return hvm_set_cr0(val);
     case 2:
         current->arch.hvm_vcpu.guest_cr[2] = val;
         return X86EMUL_OKAY;
     case 3:
         return hvm_set_cr3(val);
     case 4:
-        return hvm_set_cr4(val);
+        if (vcpu_guestmode) {
+            VCPU_NESTEDHVM(v).nh_cr[4] = val;
+            return X86EMUL_OKAY;
+        } else
+            return hvm_set_cr4(val);
     default:
         break;
     }
xen/arch/x86/hvm/hvm.c +23 -1
diff -r 93d2b0f9f955 -r b009d9b7b708 xen/arch/x86/hvm/hvm.c
@@ -54,6 +54,7 @@
 #include <asm/hvm/support.h>
 #include <asm/hvm/cacheattr.h>
 #include <asm/hvm/trace.h>
+#include <asm/hvm/nestedhvm.h>
 #include <asm/mtrr.h>
 #include <public/sched.h>
 #include <public/hvm/ioreq.h>
@@ -1102,7 +1103,8 @@ int hvm_set_cr0(unsigned long value)
     /* ET is reserved and should be always be 1. */
     value |= X86_CR0_ET;
 
-    if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PG )
+    if ( !nestedhvm_emulate_vmrun(v) &&
+         (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PG )
         goto gpf;
 
     if ( (value & X86_CR0_PG) && !(old_value & X86_CR0_PG) )
@@ -1266,6 +1268,26 @@ int hvm_set_cr4(unsigned long value)
     return X86EMUL_EXCEPTION;
 }
 
+unsigned long hvm_get_cr(struct vcpu *v, unsigned int cr)
+{
+    switch (cr) {
+    case 1:
+    case 2:
+    case 3:
+        return v->arch.hvm_vcpu.guest_cr[cr];
+    case 0:
+    case 4:
+        break;
+    default:
+        BUG();
+    }
+
+    if (nestedhvm_enabled(v->domain) && nestedhvm_vcpu_in_guestmode(v)) {
+        return VCPU_NESTEDHVM(v).nh_cr[cr];
+    } else
+        return v->arch.hvm_vcpu.guest_cr[cr];
+}
+
 int hvm_virtual_to_linear_addr(
     enum x86_segment seg,
     struct segment_register *reg,
xen/include/asm-x86/hvm/support.h +2 -0
diff -r 93d2b0f9f955 -r b009d9b7b708 xen/include/asm-x86/hvm/support.h
@@ -136,4 +136,6 @@ int hvm_set_cr4(unsigned long value);
 int hvm_msr_read_intercept(struct cpu_user_regs *regs);
 int hvm_msr_write_intercept(struct cpu_user_regs *regs);
 
+unsigned long hvm_get_cr(struct vcpu *v, unsigned int cr);
+
 #endif /* __ASM_X86_HVM_SUPPORT_H__ */

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel