X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmx_handler.c;h=2bcc39423e8667c7e1d9b61f4f38aa51d7a16da7;hp=dafb2ffdb42c62bbd527bdecb39c320638a0d607;hb=52a58bb7bdf06ca22ad6883f8095f8aa5ca4b8a4;hpb=a24a1722328a575cec8dd8578902fd0f68c72c1c diff --git a/palacios/src/palacios/vmx_handler.c b/palacios/src/palacios/vmx_handler.c index dafb2ff..2bcc394 100644 --- a/palacios/src/palacios/vmx_handler.c +++ b/palacios/src/palacios/vmx_handler.c @@ -22,6 +22,7 @@ #include #include #include +#include static int inline check_vmcs_write(vmcs_field_t field, addr_t val) @@ -44,19 +45,93 @@ static int inline check_vmcs_read(vmcs_field_t field, void * val) if(ret != VMX_SUCCESS) { PrintError("VMREAD error on %s!: %d\n", v3_vmcs_field_to_str(field), ret); - return 1; + return ret; } return 0; } -int v3_handle_vmx_exit(struct v3_gprs * gprs) +int v3_handle_vmx_exit(struct v3_gprs * gprs, struct guest_info * info) { uint32_t exit_reason; ulong_t exit_qual; check_vmcs_read(VMCS_EXIT_REASON, &exit_reason); check_vmcs_read(VMCS_EXIT_QUAL, &exit_qual); - PrintDebug("VMX Exit taken, id-qual: %x-%ld\n", exit_reason, exit_qual); - return -1; + + PrintDebug("VMX Exit taken, id-qual: %d-%ld\n", exit_reason, exit_qual); + + /* Update guest state */ + check_vmcs_read(VMCS_GUEST_RIP, &(info->rip)); + check_vmcs_read(VMCS_GUEST_RSP, &(info->vm_regs.rsp)); + check_vmcs_read(VMCS_GUEST_CR0, &(info->ctrl_regs.cr0)); + check_vmcs_read(VMCS_GUEST_CR3, &(info->ctrl_regs.cr3)); + check_vmcs_read(VMCS_GUEST_CR4, &(info->ctrl_regs.cr4)); + + // read out segments + + switch(exit_reason) + { + case VMEXIT_INFO_EXCEPTION_OR_NMI: + { + uint32_t int_info; + pf_error_t error_code; + check_vmcs_read(VMCS_EXIT_INT_INFO, &int_info); + check_vmcs_read(VMCS_EXIT_INT_ERR, &error_code); + + if((uint8_t)int_info == 0x0e) { + PrintDebug("Page Fault at %p\n", (void*)exit_qual); + if(info->shdw_pg_mode == SHADOW_PAGING) { + if(v3_handle_shadow_pagefault(info, (addr_t)exit_qual, error_code) == -1) { + return -1; + } + } else { + PrintError("Page fault in unimplemented paging mode\n"); + return -1; + } + } + break; + } + + case VMEXIT_IO_INSTR: + { + struct vmcs_io_qual * io_qual = (struct vmcs_io_qual *)&exit_qual; + + if(io_qual->dir == 0) { + if(io_qual->string) { + if(v3_handle_vmx_io_outs(info) == -1) { + return -1; + } + } else { + if(v3_handle_vmx_io_out(info) == -1) { + return -1; + } + } + } else { + if(io_qual->string) { + if(v3_handle_vmx_io_ins(info) == -1) { + return -1; + } + } else { + if(v3_handle_vmx_io_in(info) == -1) { + return -1; + } + } + } + break; + } + + default: + PrintError("Unhandled VMEXIT\n"); + return -1; + } + + check_vmcs_write(VMCS_GUEST_CR0, info->ctrl_regs.cr0); + check_vmcs_write(VMCS_GUEST_CR3, info->ctrl_regs.cr3); + check_vmcs_write(VMCS_GUEST_CR4, info->ctrl_regs.cr4); + check_vmcs_write(VMCS_GUEST_RIP, info->rip); + check_vmcs_write(VMCS_GUEST_RSP, info->vm_regs.rsp); + + PrintDebug("Executing VMRESUME\n"); + return 0; }