# HG changeset patch
# User Eddie Dong <eddie.dong@xxxxxxxxx>
# Date 1307003601 -28800
# Node ID aacbe98da103be572c9f96d6c85788f74f574117
# Parent 279a27a3b1a90380c8fa579e87835cb58a8f4aac
Extend VMCS control fields for n2 guest
Signed-off-by: Qing He <qing.he@xxxxxxxxx>
Signed-off-by: Eddie Dong <eddie.dong@xxxxxxxxx>
diff -r 279a27a3b1a9 -r aacbe98da103 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Thu Jun 02 16:33:21 2011 +0800
+++ b/xen/arch/x86/hvm/vmx/vmx.c Thu Jun 02 16:33:21 2011 +0800
@@ -54,6 +54,7 @@
#include <asm/xenoprof.h>
#include <asm/debugger.h>
#include <asm/apic.h>
+#include <asm/hvm/nestedhvm.h>
enum handler_return { HNDL_done, HNDL_unhandled, HNDL_exception_raised };
@@ -361,18 +362,28 @@ long_mode_do_msr_write(unsigned int msr,
void vmx_update_cpu_exec_control(struct vcpu *v)
{
- __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control);
+ if ( nestedhvm_vcpu_in_guestmode(v) )
+ nvmx_update_exec_control(v, v->arch.hvm_vmx.exec_control);
+ else
+ __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control);
}
static void vmx_update_secondary_exec_control(struct vcpu *v)
{
- __vmwrite(SECONDARY_VM_EXEC_CONTROL,
- v->arch.hvm_vmx.secondary_exec_control);
+ if ( nestedhvm_vcpu_in_guestmode(v) )
+ nvmx_update_secondary_exec_control(v,
+ v->arch.hvm_vmx.secondary_exec_control);
+ else
+ __vmwrite(SECONDARY_VM_EXEC_CONTROL,
+ v->arch.hvm_vmx.secondary_exec_control);
}
void vmx_update_exception_bitmap(struct vcpu *v)
{
- __vmwrite(EXCEPTION_BITMAP, v->arch.hvm_vmx.exception_bitmap);
+ if ( nestedhvm_vcpu_in_guestmode(v) )
+ nvmx_update_exception_bitmap(v, v->arch.hvm_vmx.exception_bitmap);
+ else
+ __vmwrite(EXCEPTION_BITMAP, v->arch.hvm_vmx.exception_bitmap);
}
static int vmx_guest_x86_mode(struct vcpu *v)
diff -r 279a27a3b1a9 -r aacbe98da103 xen/arch/x86/hvm/vmx/vvmx.c
--- a/xen/arch/x86/hvm/vmx/vvmx.c Thu Jun 02 16:33:21 2011 +0800
+++ b/xen/arch/x86/hvm/vmx/vvmx.c Thu Jun 02 16:33:21 2011 +0800
@@ -25,6 +25,7 @@
#include <asm/p2m.h>
#include <asm/hvm/vmx/vmx.h>
#include <asm/hvm/vmx/vvmx.h>
+#include <asm/hvm/nestedhvm.h>
int nvmx_vcpu_initialise(struct vcpu *v)
{
@@ -391,6 +392,93 @@ static void vmreturn(struct cpu_user_reg
regs->eflags = eflags;
}
+/*
+ * Nested VMX uses "strict" condition to exit from
+ * L2 guest if either L1 VMM or L0 VMM expect to exit.
+ */
+static inline u32 __shadow_control(struct vcpu *v,
+ unsigned int field,
+ u32 host_value)
+{
+ struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v);
+
+ return (u32) __get_vvmcs(nvcpu->nv_vvmcx, field) | host_value;
+}
+
+static void set_shadow_control(struct vcpu *v,
+ unsigned int field,
+ u32 host_value)
+{
+ __vmwrite(field, __shadow_control(v, field, host_value));
+}
+
+unsigned long *_shadow_io_bitmap(struct vcpu *v)
+{
+ struct nestedvmx *nvmx = &vcpu_2_nvmx(v);
+ int port80, portED;
+ u8 *bitmap;
+
+ bitmap = nvmx->iobitmap[0];
+ port80 = bitmap[0x80 >> 3] & (1 << (0x80 & 0x7)) ? 1 : 0;
+ portED = bitmap[0xed >> 3] & (1 << (0xed & 0x7)) ? 1 : 0;
+
+ return nestedhvm_vcpu_iomap_get(port80, portED);
+}
+
+void nvmx_update_exec_control(struct vcpu *v, unsigned long host_cntrl)
+{
+#define PIO_CNTRL_BITS ( CPU_BASED_ACTIVATE_IO_BITMAP \
+ | CPU_BASED_UNCOND_IO_EXITING)
+ u32 pio_cntrl = PIO_CNTRL_BITS;
+ unsigned long *bitmap;
+ u32 shadow_cntrl;
+
+ shadow_cntrl = __n2_exec_control(v);
+ pio_cntrl &= shadow_cntrl;
+ /* Enforce the removed features */
+#define REMOVED_EXEC_CONTROL_BITS (CPU_BASED_TPR_SHADOW \
+ | CPU_BASED_ACTIVATE_MSR_BITMAP \
+ | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS \
+ | CPU_BASED_ACTIVATE_IO_BITMAP \
+ | CPU_BASED_UNCOND_IO_EXITING)
+ shadow_cntrl &= ~REMOVED_EXEC_CONTROL_BITS;
+ shadow_cntrl |= host_cntrl;
+ if ( pio_cntrl == CPU_BASED_UNCOND_IO_EXITING ) {
+ /* L1 VMM intercepts all I/O instructions */
+ shadow_cntrl |= CPU_BASED_UNCOND_IO_EXITING;
+ shadow_cntrl &= ~CPU_BASED_ACTIVATE_IO_BITMAP;
+ }
+ else {
+ /* Use IO_BITMAP in shadow */
+ if ( pio_cntrl == 0 ) {
+ /*
+ * L1 VMM doesn't intercept IO instruction.
+ * Use host configuration and reset IO_BITMAP
+ */
+ bitmap = hvm_io_bitmap;
+ }
+ else {
+ /* use IO bitmap */
+ bitmap = _shadow_io_bitmap(v);
+ }
+ __vmwrite(IO_BITMAP_A, virt_to_maddr(bitmap));
+ __vmwrite(IO_BITMAP_B, virt_to_maddr(bitmap) + PAGE_SIZE);
+ }
+
+ __vmwrite(CPU_BASED_VM_EXEC_CONTROL, shadow_cntrl);
+}
+
+void nvmx_update_secondary_exec_control(struct vcpu *v,
+ unsigned long value)
+{
+ set_shadow_control(v, SECONDARY_VM_EXEC_CONTROL, value);
+}
+
+void nvmx_update_exception_bitmap(struct vcpu *v, unsigned long value)
+{
+ set_shadow_control(v, EXCEPTION_BITMAP, value);
+}
+
static void __clear_current_vvmcs(struct vcpu *v)
{
struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v);
diff -r 279a27a3b1a9 -r aacbe98da103 xen/include/asm-x86/hvm/vmx/vvmx.h
--- a/xen/include/asm-x86/hvm/vmx/vvmx.h Thu Jun 02 16:33:21 2011 +0800
+++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Thu Jun 02 16:33:21 2011 +0800
@@ -161,5 +161,10 @@ int nvmx_handle_vmwrite(struct cpu_user_
int nvmx_handle_vmresume(struct cpu_user_regs *regs);
int nvmx_handle_vmlaunch(struct cpu_user_regs *regs);
+void nvmx_update_exec_control(struct vcpu *v, unsigned long value);
+void nvmx_update_secondary_exec_control(struct vcpu *v,
+ unsigned long value);
+void nvmx_update_exception_bitmap(struct vcpu *v, unsigned long value);
+
#endif /* __ASM_X86_HVM_VVMX_H__ */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|