blob: a00c101978203f5241a77881ec8f4f91b291123e [file] [log] [blame]
/*
* Copyright 2017, Data61
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
* ABN 41 687 119 230.
*
* 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(DATA61_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, seL4_Word field) {
seL4_X86_VCPU_ReadVMCS_t UNUSED result;
assert(vcpu);
result = seL4_X86_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, seL4_Word field, seL4_Word value) {
seL4_X86_VCPU_WriteVMCS_t UNUSED result;
assert(vcpu);
result = seL4_X86_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, BIT(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 = VMX_CONTROL_PPC_HLT_EXITING | VMX_CONTROL_PPC_CR3_LOAD_EXITING | VMX_CONTROL_PPC_CR3_STORE_EXITING;
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
}