#include <palacios/vmm_decoder.h>
#include <palacios/vmm_barrier.h>
#include <palacios/vmm_timeout.h>
+#include <palacios/vmm_debug.h>
#ifdef V3_CONFIG_CHECKPOINT
#include <palacios/vmm_checkpoint.h>
static addr_t allocate_vmcs() {
+ void *temp;
struct vmcs_data * vmcs_page = NULL;
PrintDebug("Allocating page\n");
- vmcs_page = (struct vmcs_data *)V3_VAddr(V3_AllocPages(1));
+ temp = V3_AllocPages(1);
+ if (!temp) {
+ PrintError("Cannot allocate VMCS\n");
+ return -1;
+ }
+ vmcs_page = (struct vmcs_data *)V3_VAddr(temp);
memset(vmcs_page, 0, 4096);
vmcs_page->revision = hw_info.basic_info.revision;
vmx_ret |= check_vmcs_write(VMCS_CR4_MASK, CR4_VMXE);
#define CR0_NE 0x00000020
vmx_ret |= check_vmcs_write(VMCS_CR0_MASK, CR0_NE);
- //((struct cr0_32 *)&(core->shdw_pg_state.guest_cr0))->ne = 1;
+ ((struct cr0_32 *)&(core->shdw_pg_state.guest_cr0))->ne = 1;
if (v3_init_ept(core, &hw_info) == -1) {
PrintError("Error initializing EPT\n");
int vmx_ret = 0;
vmx_state = (struct vmx_data *)V3_Malloc(sizeof(struct vmx_data));
+
+ if (!vmx_state) {
+ PrintError("Unable to allocate in initializing vmx vmcs\n");
+ return;
+ }
+
memset(vmx_state, 0, sizeof(struct vmx_data));
PrintDebug("vmx_data pointer: %p\n", (void *)vmx_state);
* JRL: This is broken
*/
int v3_vmx_save_core(struct guest_info * core, void * ctx){
- uint64_t vmcs_ptr = vmcs_store();
+ struct vmx_data * vmx_info = (struct vmx_data *)(core->vmm_data);
- v3_chkpt_save(ctx, "vmcs_data", PAGE_SIZE, (void *)vmcs_ptr);
+ // note that the vmcs pointer is an HPA, but we need an HVA
+ if (v3_chkpt_save(ctx, "vmcs_data", PAGE_SIZE_4KB,
+ V3_VAddr((void*) (vmx_info->vmcs_ptr_phys))) ==-1) {
+ PrintError("Could not save vmcs data for VMX\n");
+ return -1;
+ }
return 0;
}
int v3_vmx_load_core(struct guest_info * core, void * ctx){
struct vmx_data * vmx_info = (struct vmx_data *)(core->vmm_data);
struct cr0_32 * shadow_cr0;
- char vmcs[PAGE_SIZE_4KB];
+ addr_t vmcs_page_paddr; //HPA
- v3_chkpt_load(ctx, "vmcs_data", PAGE_SIZE_4KB, vmcs);
+ vmcs_page_paddr = (addr_t) V3_AllocPages(1);
+
+ if (!vmcs_page_paddr) {
+ PrintError("Could not allocate space for a vmcs in VMX\n");
+ return -1;
+ }
+
+ if (v3_chkpt_load(ctx, "vmcs_data", PAGE_SIZE_4KB,
+ V3_VAddr((void *)vmcs_page_paddr)) == -1) {
+ PrintError("Could not load vmcs data for VMX\n");
+ return -1;
+ }
vmcs_clear(vmx_info->vmcs_ptr_phys);
- vmcs_load((addr_t)vmcs);
+
+ // Probably need to delete the old one...
+ V3_FreePages((void*)(vmx_info->vmcs_ptr_phys),1);
+
+ vmcs_load(vmcs_page_paddr);
v3_vmx_save_vmcs(core);
v3_vmx_config_tsc_virtualization(struct guest_info * info) {
struct vmx_data * vmx_info = (struct vmx_data *)(info->vmm_data);
- if (info->time_state.time_flags & V3_TIME_TRAP_RDTSC) {
+ if (info->time_state.flags & VM_TIME_TRAP_RDTSC) {
if (!vmx_info->pri_proc_ctrls.rdtsc_exit) {
vmx_info->pri_proc_ctrls.rdtsc_exit = 1;
check_vmcs_write(VMCS_PROC_CTRLS, vmx_info->pri_proc_ctrls.value);
check_vmcs_write(VMCS_PROC_CTRLS, vmx_info->pri_proc_ctrls.value);
}
- tsc_offset = v3_tsc_host_offset(&info->time_state);
+ if (info->time_state.flags & VM_TIME_TSC_PASSTHROUGH) {
+ tsc_offset = 0;
+ } else {
+ tsc_offset = v3_tsc_host_offset(&info->time_state);
+ }
tsc_offset_high = (uint32_t)(( tsc_offset >> 32) & 0xffffffff);
tsc_offset_low = (uint32_t)(tsc_offset & 0xffffffff);
uint64_t guest_cycles = 0;
// Conditionally yield the CPU if the timeslice has expired
- v3_yield_cond(info);
-
- // disable global interrupts for vm state transition
- v3_disable_ints();
+ v3_yield_cond(info,-1);
// Update timer devices late after being in the VM so that as much
// of the time in the VM is accounted for as possible. Also do it before
// updating IRQ entry state so that any interrupts the timers raise get
- // handled on the next VM entry. Must be done with interrupts disabled.
- v3_advance_time(info);
+ // handled on the next VM entry.
+ v3_advance_time(info, NULL);
v3_update_timers(info);
+ // disable global interrupts for vm state transition
+ v3_disable_ints();
+
if (vmcs_store() != vmx_info->vmcs_ptr_phys) {
vmcs_clear(vmx_info->vmcs_ptr_phys);
vmcs_load(vmx_info->vmcs_ptr_phys);
}
- // Perform last-minute time bookkeeping prior to entering the VM
- v3_time_enter_vm(info);
+ // Perform last-minute time setup prior to entering the VM
v3_vmx_config_tsc_virtualization(info);
-
-
if (v3_update_vmcs_host_state(info)) {
v3_enable_ints();
PrintError("Could not write host state\n");
}
// Immediate exit from VM time bookkeeping
- v3_time_exit_vm(info, &guest_cycles);
-
+ v3_advance_time(info, &guest_cycles);
/* Update guest state */
v3_vmx_save_vmcs(info);
v3_enable_ints();
// Conditionally yield the CPU if the timeslice has expired
- v3_yield_cond(info);
+ v3_yield_cond(info,-1);
+ v3_advance_time(info, NULL);
+ v3_update_timers(info);
if (v3_handle_vmx_exit(info, &exit_info) == -1) {
PrintError("Error in VMX exit handler (Exit reason=%x)\n", exit_info.exit_reason);
return 0;
}
- v3_yield(info);
+ v3_yield(info,-1);
//PrintDebug("VMX core %u: still waiting for INIT\n",info->vcpu_id);
}