diff options
author | Neel Natu <neel@FreeBSD.org> | 2012-08-04 02:06:55 +0000 |
---|---|---|
committer | Neel Natu <neel@FreeBSD.org> | 2012-08-04 02:06:55 +0000 |
commit | 39c21c2db2d5f600f8f7ed87d1f6e7dc2e3073c8 (patch) | |
tree | 3da5056fa03213597ef70b339b09f5046dd288c6 | |
parent | 2bdc0d011ad14d391581d58a7b08c9ee0be8ed3e (diff) |
Notes
-rw-r--r-- | sys/amd64/vmm/intel/vmx.c | 68 |
1 files changed, 52 insertions, 16 deletions
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c index df28fe950b691..be58444baa28c 100644 --- a/sys/amd64/vmm/intel/vmx.c +++ b/sys/amd64/vmm/intel/vmx.c @@ -627,23 +627,38 @@ vmx_vpid(void) } static int -vmx_setup_cr0_shadow(struct vmcs *vmcs) +vmx_setup_cr_shadow(int which, struct vmcs *vmcs) { - int error; - uint64_t mask, shadow; + int error, mask_ident, shadow_ident; + uint64_t mask_value, shadow_value; + + if (which != 0 && which != 4) + panic("vmx_setup_cr_shadow: unknown cr%d", which); + + if (which == 0) { + mask_ident = VMCS_CR0_MASK; + mask_value = cr0_ones_mask | cr0_zeros_mask; + shadow_ident = VMCS_CR0_SHADOW; + shadow_value = cr0_ones_mask; + } else { + mask_ident = VMCS_CR4_MASK; + mask_value = cr4_ones_mask | cr4_zeros_mask; + shadow_ident = VMCS_CR4_SHADOW; + shadow_value = cr4_ones_mask; + } - mask = cr0_ones_mask | cr0_zeros_mask; - error = vmcs_setreg(vmcs, VMCS_IDENT(VMCS_CR0_MASK), mask); + error = vmcs_setreg(vmcs, VMCS_IDENT(mask_ident), mask_value); if (error) return (error); - shadow = cr0_ones_mask; - error = vmcs_setreg(vmcs, VMCS_IDENT(VMCS_CR0_SHADOW), shadow); + error = vmcs_setreg(vmcs, VMCS_IDENT(shadow_ident), shadow_value); if (error) return (error); return (0); } +#define vmx_setup_cr0_shadow(vmcs) vmx_setup_cr_shadow(0, (vmcs)) +#define vmx_setup_cr4_shadow(vmcs) vmx_setup_cr_shadow(4, (vmcs)) static void * vmx_vminit(struct vm *vm) @@ -744,6 +759,12 @@ vmx_vminit(struct vm *vm) panic("vmcs_set_msr_save error %d", error); error = vmx_setup_cr0_shadow(&vmx->vmcs[i]); + if (error != 0) + panic("vmx_setup_cr0_shadow %d", error); + + error = vmx_setup_cr4_shadow(&vmx->vmcs[i]); + if (error != 0) + panic("vmx_setup_cr4_shadow %d", error); } return (vmx); @@ -1031,12 +1052,16 @@ cantinject: static int vmx_emulate_cr_access(struct vmx *vmx, int vcpu, uint64_t exitqual) { - int error; - uint64_t regval; + int error, cr, vmcs_guest_cr; + uint64_t regval, ones_mask, zeros_mask; const struct vmxctx *vmxctx; - /* We only handle mov to %cr0 at this time */ - if ((exitqual & 0xff) != 0x00) + /* We only handle mov to %cr0 or %cr4 at this time */ + if ((exitqual & 0xf0) != 0x00) + return (UNHANDLED); + + cr = exitqual & 0xf; + if (cr != 0 && cr != 4) return (UNHANDLED); vmxctx = &vmx->ctx[vcpu]; @@ -1100,11 +1125,22 @@ vmx_emulate_cr_access(struct vmx *vmx, int vcpu, uint64_t exitqual) break; } - regval |= cr0_ones_mask; - regval &= ~cr0_zeros_mask; - error = vmwrite(VMCS_GUEST_CR0, regval); - if (error) - panic("vmx_emulate_cr_access: error %d writing cr0", error); + if (cr == 0) { + ones_mask = cr0_ones_mask; + zeros_mask = cr0_zeros_mask; + vmcs_guest_cr = VMCS_GUEST_CR0; + } else { + ones_mask = cr4_ones_mask; + zeros_mask = cr4_zeros_mask; + vmcs_guest_cr = VMCS_GUEST_CR4; + } + regval |= ones_mask; + regval &= ~zeros_mask; + error = vmwrite(vmcs_guest_cr, regval); + if (error) { + panic("vmx_emulate_cr_access: error %d writing cr%d", + error, cr); + } return (HANDLED); } |