| /* | |
| * Copyright 2014, NICTA | |
| * | |
| * This software may be distributed and modified according to the terms of | |
| * the GNU General Public License version 2. Note that NO WARRANTY is provided. | |
| * See "LICENSE_GPLv2.txt" for details. | |
| * | |
| * @TAG(NICTA_GPL) | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <sel4/sel4.h> | |
| #include "vmm/vmm.h" | |
| #include "vmm/platform/vmcs.h" | |
| int vmm_vmcs_read(seL4_CPtr vcpu, unsigned int field) { | |
| seL4_IA32_VCPU_ReadVMCS_t result; | |
| assert(vcpu); | |
| result = seL4_IA32_VCPU_ReadVMCS(vcpu, field); | |
| assert(result.error == seL4_NoError); | |
| return result.value; | |
| } | |
| /*write a field and its value into the VMCS*/ | |
| void vmm_vmcs_write(seL4_CPtr vcpu, unsigned int field, unsigned int value) { | |
| seL4_IA32_VCPU_WriteVMCS_t result; | |
| assert(vcpu); | |
| result = seL4_IA32_VCPU_WriteVMCS(vcpu, field, value); | |
| assert(result.error == seL4_NoError); | |
| } | |
| /*init the vmcs structure for a guest os thread*/ | |
| void vmm_vmcs_init_guest(vmm_vcpu_t *vcpu) { | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_ES_SELECTOR, 2 << 3); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_CS_SELECTOR, 1 << 3); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_SS_SELECTOR, 2 << 3); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_DS_SELECTOR, 2 << 3); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_FS_SELECTOR, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_GS_SELECTOR, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_LDTR_SELECTOR, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_TR_SELECTOR, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_ES_LIMIT, ~0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_CS_LIMIT, ~0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_SS_LIMIT, ~0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_DS_LIMIT, ~0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_FS_LIMIT, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_GS_LIMIT, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_LDTR_LIMIT, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_TR_LIMIT, 0x0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_GDTR_LIMIT, 0x0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_IDTR_LIMIT, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_ES_ACCESS_RIGHTS, 0xC093); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_CS_ACCESS_RIGHTS, 0xC09B); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_SS_ACCESS_RIGHTS, 0xC093); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_DS_ACCESS_RIGHTS, 0xC093); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_FS_ACCESS_RIGHTS, BIT(16)); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_GS_ACCESS_RIGHTS, BIT(16)); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_LDTR_ACCESS_RIGHTS, BIT(16)); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_TR_ACCESS_RIGHTS, 0x8B); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_SYSENTER_CS, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_CR0_MASK, vcpu->guest_state.virt.cr.cr0_mask); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_CR4_MASK, vcpu->guest_state.virt.cr.cr4_mask); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_CR0_READ_SHADOW, vcpu->guest_state.virt.cr.cr0_shadow); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_CR4_READ_SHADOW, vcpu->guest_state.virt.cr.cr4_shadow); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_ES_BASE, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_CS_BASE, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_SS_BASE, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_DS_BASE, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_FS_BASE, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_GS_BASE, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_LDTR_BASE, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_TR_BASE, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_GDTR_BASE, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_IDTR_BASE, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_RFLAGS, BIT(1)); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_SYSENTER_ESP, 0); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_SYSENTER_EIP, 0); | |
| vcpu->guest_state.machine.control_ppc = BIT(7); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_PRIMARY_PROCESSOR_CONTROLS, vcpu->guest_state.machine.control_ppc); | |
| vcpu->guest_state.machine.control_entry = vmm_vmcs_read(vcpu->guest_vcpu, VMX_CONTROL_ENTRY_INTERRUPTION_INFO); | |
| #ifdef CONFIG_LIB_VMM_VMX_TIMER_DEBUG | |
| /* Enable pre-emption timer */ | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_PIN_EXECUTION_CONTROLS, BIT(6)); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_CONTROL_EXIT_CONTROLS, BIT(22)); | |
| vmm_vmcs_write(vcpu->guest_vcpu, VMX_GUEST_VMX_PREEMPTION_TIMER_VALUE, CONFIG_LIB_VMM_VMX_TIMER_TIMEOUT); | |
| #endif | |
| } | |