X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmx_handler.c;h=be86fe29d65eb8d3a3d858912451815f7ae5567e;hb=5d1bbcc86de011e3f0d115b6f10fd8645cdf855e;hp=1da8a586cae9e3d05f9f947ef42ee9c42033f3c9;hpb=5c5dfe422e57ac9833dd3ed3a7d0f5c39557b86c;p=palacios.git diff --git a/palacios/src/palacios/vmx_handler.c b/palacios/src/palacios/vmx_handler.c index 1da8a58..be86fe2 100644 --- a/palacios/src/palacios/vmx_handler.c +++ b/palacios/src/palacios/vmx_handler.c @@ -31,17 +31,20 @@ #include #include #include +#include -#ifdef CONFIG_TELEMETRY -#include +#ifndef V3_CONFIG_DEBUG_VMX +#undef PrintDebug +#define PrintDebug(fmt, args...) #endif - - +#ifdef V3_CONFIG_TELEMETRY +#include +#endif /* At this point the GPRs are already copied into the guest_info state */ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_info) { - struct vmx_data * vmx_info = (struct vmx_data *)(info->vmm_data); + struct vmx_basic_exit_info * basic_info = (struct vmx_basic_exit_info *)&(exit_info->exit_reason); /* PrintError("Handling VMEXIT: %s (%u), %lu (0x%lx)\n", @@ -51,20 +54,41 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf v3_print_vmcs(); */ -#ifdef CONFIG_TELEMETRY - if (info->enable_telemetry) { + + + if (basic_info->entry_error == 1) { + switch (basic_info->reason) { + case VMEXIT_INVALID_GUEST_STATE: + PrintError("VM Entry failed due to invalid guest state\n"); + PrintError("Printing VMCS: (NOTE: This VMCS may not belong to the correct guest)\n"); + v3_print_vmcs(); + break; + case VMEXIT_INVALID_MSR_LOAD: + PrintError("VM Entry failed due to error loading MSRs\n"); + break; + default: + PrintError("Entry failed for unknown reason (%d)\n", basic_info->reason); + break; + } + + return -1; + } + + +#ifdef V3_CONFIG_TELEMETRY + if (info->vm_info->enable_telemetry) { v3_telemetry_start_exit(info); } #endif - switch (exit_info->exit_reason) { + switch (basic_info->reason) { case VMEXIT_INFO_EXCEPTION_OR_NMI: { pf_error_t error_code = *(pf_error_t *)&(exit_info->int_err); // JRL: Change "0x0e" to a macro value - if ((uint8_t)exit_info->int_info == 0x0e) { -#ifdef CONFIG_DEBUG_SHADOW_PAGING + if ((uint8_t)exit_info->int_info == 14) { +#ifdef V3_CONFIG_DEBUG_SHADOW_PAGING PrintDebug("Page Fault at %p error_code=%x\n", (void *)exit_info->exit_qual, *(uint32_t *)&error_code); #endif @@ -73,10 +97,14 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf PrintError("Error handling shadow page fault\n"); return -1; } + } else { PrintError("Page fault in unimplemented paging mode\n"); return -1; } + } else if ((uint8_t)exit_info->int_info == 2) { + // NMI. Don't do anything + V3_Print("NMI Exception Received\n"); } else { PrintError("Unknown exception: 0x%x\n", (uint8_t)exit_info->int_info); v3_print_GPRs(info); @@ -85,6 +113,16 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf break; } + case VMEXIT_EPT_VIOLATION: { + struct ept_exit_qual * ept_qual = (struct ept_exit_qual *)&(exit_info->exit_qual); + + if (v3_handle_ept_fault(info, exit_info->ept_fault_addr, ept_qual) == -1) { + PrintError("Error handling EPT fault\n"); + return -1; + } + + break; + } case VMEXIT_INVLPG: if (info->shdw_pg_mode == SHADOW_PAGING) { if (v3_handle_shadow_invlpg(info) == -1) { @@ -94,6 +132,18 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf } break; + + case VMEXIT_RDTSC: +#ifdef V3_CONFIG_DEBUG_TIME + PrintDebug("RDTSC\n"); +#endif + if (v3_handle_rdtsc(info) == -1) { + PrintError("Error Handling RDTSC instruction\n"); + return -1; + } + + break; + case VMEXIT_CPUID: if (v3_handle_cpuid(info) == -1) { PrintError("Error Handling CPUID instruction\n"); @@ -177,12 +227,22 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf return -1; } break; + case 4: + //PrintDebug("Handling CR4 Access\n"); + if (v3_vmx_handle_cr4_access(info, cr_qual) == -1) { + PrintError("Error in CR4 access handler\n"); + return -1; + } + break; default: PrintError("Unhandled CR access: %d\n", cr_qual->cr_id); return -1; } - info->rip += exit_info->instr_len; + // TODO: move RIP increment into all of the above individual CR + // handlers, not just v3_vmx_handle_cr4_access() + if (cr_qual->cr_id != 4) + info->rip += exit_info->instr_len; break; } @@ -195,6 +255,9 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf } break; + + + case VMEXIT_PAUSE: // Handled as NOP info->rip += 2; @@ -204,30 +267,27 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf // Interrupts are handled outside switch break; case VMEXIT_INTR_WINDOW: - - vmcs_read(VMCS_PROC_CTRLS, &(vmx_info->pri_proc_ctrls.value)); - vmx_info->pri_proc_ctrls.int_wndw_exit = 0; - vmcs_write(VMCS_PROC_CTRLS, vmx_info->pri_proc_ctrls.value); - -#ifdef CONFIG_DEBUG_INTERRUPTS - PrintDebug("Interrupts available again! (RIP=%llx)\n", info->rip); -#endif - + // This is handled in the atomic part of the vmx code, + // not in the generic (interruptable) vmx handler break; + + default: PrintError("Unhandled VMEXIT: %s (%u), %lu (0x%lx)\n", - v3_vmx_exit_code_to_str(exit_info->exit_reason), - exit_info->exit_reason, + v3_vmx_exit_code_to_str(basic_info->reason), + basic_info->reason, exit_info->exit_qual, exit_info->exit_qual); return -1; } -#ifdef CONFIG_TELEMETRY - if (info->enable_telemetry) { + +#ifdef V3_CONFIG_TELEMETRY + if (info->vm_info->enable_telemetry) { v3_telemetry_end_exit(info, exit_info->exit_reason); } #endif + return 0; } @@ -263,12 +323,12 @@ static const char VMEXIT_MOV_DR_STR[] = "VMEXIT_MOV_DR"; static const char VMEXIT_IO_INSTR_STR[] = "VMEXIT_IO_INSTR"; static const char VMEXIT_RDMSR_STR[] = "VMEXIT_RDMSR"; static const char VMEXIT_WRMSR_STR[] = "VMEXIT_WRMSR"; -static const char VMEXIT_ENTRY_FAIL_INVALID_GUEST_STATE_STR[] = "VMEXIT_ENTRY_FAIL_INVALID_GUEST_STATE"; -static const char VMEXIT_ENTRY_FAIL_MSR_LOAD_STR[] = "VMEXIT_ENTRY_FAIL_MSR_LOAD"; +static const char VMEXIT_INVALID_GUEST_STATE_STR[] = "VMEXIT_INVALID_GUEST_STATE"; +static const char VMEXIT_INVALID_MSR_LOAD_STR[] = "VMEXIT_INVALID_MSR_LOAD"; static const char VMEXIT_MWAIT_STR[] = "VMEXIT_MWAIT"; static const char VMEXIT_MONITOR_STR[] = "VMEXIT_MONITOR"; static const char VMEXIT_PAUSE_STR[] = "VMEXIT_PAUSE"; -static const char VMEXIT_ENTRY_FAILURE_MACHINE_CHECK_STR[] = "VMEXIT_ENTRY_FAILURE_MACHINE_CHECK"; +static const char VMEXIT_INVALID_MACHINE_CHECK_STR[] = "VMEXIT_INVALIDE_MACHINE_CHECK"; static const char VMEXIT_TPR_BELOW_THRESHOLD_STR[] = "VMEXIT_TPR_BELOW_THRESHOLD"; static const char VMEXIT_APIC_STR[] = "VMEXIT_APIC"; static const char VMEXIT_GDTR_IDTR_STR[] = "VMEXIT_GDTR_IDTR"; @@ -349,18 +409,18 @@ const char * v3_vmx_exit_code_to_str(vmx_exit_t exit) return VMEXIT_RDMSR_STR; case VMEXIT_WRMSR: return VMEXIT_WRMSR_STR; - case VMEXIT_ENTRY_FAIL_INVALID_GUEST_STATE: - return VMEXIT_ENTRY_FAIL_INVALID_GUEST_STATE_STR; - case VMEXIT_ENTRY_FAIL_MSR_LOAD: - return VMEXIT_ENTRY_FAIL_MSR_LOAD_STR; + case VMEXIT_INVALID_GUEST_STATE: + return VMEXIT_INVALID_GUEST_STATE_STR; + case VMEXIT_INVALID_MSR_LOAD: + return VMEXIT_INVALID_MSR_LOAD_STR; case VMEXIT_MWAIT: return VMEXIT_MWAIT_STR; case VMEXIT_MONITOR: return VMEXIT_MONITOR_STR; case VMEXIT_PAUSE: return VMEXIT_PAUSE_STR; - case VMEXIT_ENTRY_FAILURE_MACHINE_CHECK: - return VMEXIT_ENTRY_FAILURE_MACHINE_CHECK_STR; + case VMEXIT_INVALID_MACHINE_CHECK: + return VMEXIT_INVALID_MACHINE_CHECK_STR; case VMEXIT_TPR_BELOW_THRESHOLD: return VMEXIT_TPR_BELOW_THRESHOLD_STR; case VMEXIT_APIC: