From 2df7b96a23b292136ce29b600d2bdf8104b3be1e Mon Sep 17 00:00:00 2001 From: Binbin Wu Date: Mon, 28 May 2018 13:59:10 +0800 Subject: [PATCH] hv: make control register handling functions to public Move from vmexit.c to vmx.c Declare the functions in vmx.h Rename the functions' name with prefix vmx_. Signed-off-by: Binbin Wu Reviewed-by: Kevin Tian --- hypervisor/arch/x86/vmexit.c | 100 ++---------------------------- hypervisor/arch/x86/vmx.c | 92 +++++++++++++++++++++++++++ hypervisor/include/arch/x86/vmx.h | 5 ++ 3 files changed, 101 insertions(+), 96 deletions(-) diff --git a/hypervisor/arch/x86/vmexit.c b/hypervisor/arch/x86/vmexit.c index d5af63f8c..670dafcf1 100644 --- a/hypervisor/arch/x86/vmexit.c +++ b/hypervisor/arch/x86/vmexit.c @@ -241,98 +241,6 @@ static int unhandled_vmexit_handler(__unused struct vcpu *vcpu) return 0; } -static int write_cr0(struct vcpu *vcpu, uint64_t value) -{ - uint32_t value32; - uint64_t value64; - - pr_dbg("VMM: Guest trying to write 0x%08x to CR0", value); - - /* Read host mask value */ - value64 = exec_vmread(VMX_CR0_MASK); - - /* Clear all bits being written by guest that are owned by host */ - value &= ~value64; - - /* Update CR0 in guest state */ - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr0 |= value; - exec_vmwrite(VMX_GUEST_CR0, - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr0); - pr_dbg("VMM: Guest allowed to write 0x%08x to CR0", - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr0); - - /* If guest is trying to transition vcpu from unpaged real mode to page - * protected mode make necessary changes to VMCS structure to reflect - * transition from real mode to paged-protected mode - */ - if (!is_vcpu_bsp(vcpu) && - (vcpu->arch_vcpu.cpu_mode == CPU_MODE_REAL) && - (value & CR0_PG) && (value & CR0_PE)) { - /* Enable protected mode */ - value32 = exec_vmread(VMX_ENTRY_CONTROLS); - value32 |= (VMX_ENTRY_CTLS_IA32E_MODE | - VMX_ENTRY_CTLS_LOAD_PAT | - VMX_ENTRY_CTLS_LOAD_EFER); - exec_vmwrite(VMX_ENTRY_CONTROLS, value32); - pr_dbg("VMX_ENTRY_CONTROLS: 0x%x ", value32); - - /* Set up EFER */ - value64 = exec_vmread64(VMX_GUEST_IA32_EFER_FULL); - value64 |= (MSR_IA32_EFER_SCE_BIT | - MSR_IA32_EFER_LME_BIT | - MSR_IA32_EFER_LMA_BIT | MSR_IA32_EFER_NXE_BIT); - exec_vmwrite64(VMX_GUEST_IA32_EFER_FULL, value64); - pr_dbg("VMX_GUEST_IA32_EFER: 0x%016llx ", value64); - } - - return 0; -} - -static int write_cr3(struct vcpu *vcpu, uint64_t value) -{ - /* Write to guest's CR3 */ - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr3 = value; - - /* Commit new value to VMCS */ - exec_vmwrite(VMX_GUEST_CR3, - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr3); - - return 0; -} - -static int write_cr4(struct vcpu *vcpu, uint64_t value) -{ - uint64_t temp64; - - pr_dbg("VMM: Guest trying to write 0x%08x to CR4", value); - - /* Read host mask value */ - temp64 = exec_vmread(VMX_CR4_MASK); - - /* Clear all bits being written by guest that are owned by host */ - value &= ~temp64; - - /* Write updated CR4 (bitwise OR of allowed guest bits and CR4 host - * value) - */ - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr4 |= value; - exec_vmwrite(VMX_GUEST_CR4, - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr4); - pr_dbg("VMM: Guest allowed to write 0x%08x to CR4", - vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr4); - - return 0; -} - -static int read_cr3(struct vcpu *vcpu, uint64_t *value) -{ - *value = vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr3; - - pr_dbg("VMM: reading 0x%08x from CR3", *value); - - return 0; -} - int cpuid_vmexit_handler(struct vcpu *vcpu) { struct run_context *cur_context = @@ -382,22 +290,22 @@ int cr_access_vmexit_handler(struct vcpu *vcpu) VM_EXIT_CR_ACCESS_CR_NUM(vcpu->arch_vcpu.exit_qualification)) { case 0x00: /* mov to cr0 */ - write_cr0(vcpu, *regptr); + vmx_write_cr0(vcpu, *regptr); break; case 0x03: /* mov to cr3 */ - write_cr3(vcpu, *regptr); + vmx_write_cr3(vcpu, *regptr); break; case 0x04: /* mov to cr4 */ - write_cr4(vcpu, *regptr); + vmx_write_cr4(vcpu, *regptr); break; case 0x13: /* mov from cr3 */ - read_cr3(vcpu, regptr); + vmx_read_cr3(vcpu, regptr); break; #if 0 case 0x14: diff --git a/hypervisor/arch/x86/vmx.c b/hypervisor/arch/x86/vmx.c index 41de3866c..976e3eb68 100644 --- a/hypervisor/arch/x86/vmx.c +++ b/hypervisor/arch/x86/vmx.c @@ -240,6 +240,98 @@ uint32_t get_cs_access_rights(void) return usable_ar; } +int vmx_write_cr0(struct vcpu *vcpu, uint64_t value) +{ + uint32_t value32; + uint64_t value64; + + pr_dbg("VMM: Guest trying to write 0x%08x to CR0", value); + + /* Read host mask value */ + value64 = exec_vmread(VMX_CR0_MASK); + + /* Clear all bits being written by guest that are owned by host */ + value &= ~value64; + + /* Update CR0 in guest state */ + vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr0 |= value; + exec_vmwrite(VMX_GUEST_CR0, + vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr0); + pr_dbg("VMM: Guest allowed to write 0x%08x to CR0", + vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr0); + + /* If guest is trying to transition vcpu from unpaged real mode to page + * protected mode make necessary changes to VMCS structure to reflect + * transition from real mode to paged-protected mode + */ + if (!is_vcpu_bsp(vcpu) && + (vcpu->arch_vcpu.cpu_mode == CPU_MODE_REAL) && + (value & CR0_PG) && (value & CR0_PE)) { + /* Enable protected mode */ + value32 = exec_vmread(VMX_ENTRY_CONTROLS); + value32 |= (VMX_ENTRY_CTLS_IA32E_MODE | + VMX_ENTRY_CTLS_LOAD_PAT | + VMX_ENTRY_CTLS_LOAD_EFER); + exec_vmwrite(VMX_ENTRY_CONTROLS, value32); + pr_dbg("VMX_ENTRY_CONTROLS: 0x%x ", value32); + + /* Set up EFER */ + value64 = exec_vmread64(VMX_GUEST_IA32_EFER_FULL); + value64 |= (MSR_IA32_EFER_SCE_BIT | + MSR_IA32_EFER_LME_BIT | + MSR_IA32_EFER_LMA_BIT | MSR_IA32_EFER_NXE_BIT); + exec_vmwrite64(VMX_GUEST_IA32_EFER_FULL, value64); + pr_dbg("VMX_GUEST_IA32_EFER: 0x%016llx ", value64); + } + + return 0; +} + +int vmx_read_cr3(struct vcpu *vcpu, uint64_t *value) +{ + *value = vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr3; + + pr_dbg("VMM: reading 0x%08x from CR3", *value); + + return 0; +} + +int vmx_write_cr3(struct vcpu *vcpu, uint64_t value) +{ + /* Write to guest's CR3 */ + vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr3 = value; + + /* Commit new value to VMCS */ + exec_vmwrite(VMX_GUEST_CR3, + vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr3); + + return 0; +} + +int vmx_write_cr4(struct vcpu *vcpu, uint64_t value) +{ + uint64_t temp64; + + pr_dbg("VMM: Guest trying to write 0x%08x to CR4", value); + + /* Read host mask value */ + temp64 = exec_vmread(VMX_CR4_MASK); + + /* Clear all bits being written by guest that are owned by host */ + value &= ~temp64; + + /* Write updated CR4 (bitwise OR of allowed guest bits and CR4 host + * value) + */ + vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr4 |= value; + exec_vmwrite(VMX_GUEST_CR4, + vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr4); + pr_dbg("VMM: Guest allowed to write 0x%08x to CR4", + vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr4); + + return 0; +} + static void init_guest_state(struct vcpu *vcpu) { uint64_t field; diff --git a/hypervisor/include/arch/x86/vmx.h b/hypervisor/include/arch/x86/vmx.h index 0c308890e..06c374ecb 100644 --- a/hypervisor/include/arch/x86/vmx.h +++ b/hypervisor/include/arch/x86/vmx.h @@ -464,6 +464,11 @@ int init_vmcs(struct vcpu *vcpu); int exec_vmclear(void *addr); int exec_vmptrld(void *addr); +int vmx_write_cr0(struct vcpu *vcpu, uint64_t cr0); +int vmx_read_cr3(struct vcpu *vcpu, uint64_t *cr3); +int vmx_write_cr3(struct vcpu *vcpu, uint64_t cr3); +int vmx_write_cr4(struct vcpu *vcpu, uint64_t cr4); + static inline uint8_t get_vcpu_mode(struct vcpu *vcpu) { return vcpu->arch_vcpu.cpu_mode;