From: Jack Lange Date: Thu, 27 Oct 2011 18:54:15 +0000 (-0400) Subject: Now by default IO and MSR operations are dropped by Palacios unless they have been... X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=5e5c8ee949fa45116d58b904fc11aab082f61607;p=palacios.git Now by default IO and MSR operations are dropped by Palacios unless they have been hooked. In order to provide passthrough access to hardware a resource needs to be hooked with a NULL read/write callback. --- diff --git a/palacios/include/palacios/vmm_msr.h b/palacios/include/palacios/vmm_msr.h index 0d2391a..87a8a7e 100644 --- a/palacios/include/palacios/vmm_msr.h +++ b/palacios/include/palacios/vmm_msr.h @@ -26,6 +26,19 @@ #include #include +#define SYSENTER_CS_MSR 0x00000174 +#define SYSENTER_ESP_MSR 0x00000175 +#define SYSENTER_EIP_MSR 0x00000176 +#define EFER_MSR 0xc0000080 +#define IA32_STAR_MSR 0xc0000081 +#define IA32_LSTAR_MSR 0xc0000082 +#define IA32_CSTAR_MSR 0xc0000083 +#define IA32_FMASK_MSR 0xc0000084 +#define FS_BASE_MSR 0xc0000100 +#define GS_BASE_MSR 0xc0000101 +#define IA32_KERN_GS_BASE_MSR 0xc0000102 + + struct guest_info; struct v3_vm_info; diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index f9dad0b..d583657 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -311,6 +311,19 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) { &v3_handle_vm_cr_read, &v3_handle_vm_cr_write, core); + + + { + v3_hook_msr(core->vm_info, IA32_STAR_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, IA32_LSTAR_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, IA32_FMASK_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, IA32_KERN_GS_BASE_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, IA32_CSTAR_MSR, NULL, NULL, NULL); + + v3_hook_msr(core->vm_info, SYSENTER_CS_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, SYSENTER_ESP_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, SYSENTER_EIP_MSR, NULL, NULL, NULL); + } } diff --git a/palacios/src/palacios/svm_io.c b/palacios/src/palacios/svm_io.c index 405acc2..e273466 100644 --- a/palacios/src/palacios/svm_io.c +++ b/palacios/src/palacios/svm_io.c @@ -49,7 +49,7 @@ int v3_init_svm_io_map(struct v3_vm_info * vm) { vm->io_map.update_map = update_map; vm->io_map.arch_data = V3_VAddr(V3_AllocPages(3)); - memset(vm->io_map.arch_data, 0, PAGE_SIZE_4KB * 3); + memset(vm->io_map.arch_data, 0xff, PAGE_SIZE_4KB * 3); v3_refresh_io_map(vm); @@ -69,13 +69,6 @@ int v3_handle_svm_io_in(struct guest_info * core, struct svm_io_info * io_info) struct v3_io_hook * hook = v3_get_io_hook(core->vm_info, io_info->port); int read_size = 0; - if (hook == NULL) { - PrintError("Hook Not present for in on port 0x%x\n", io_info->port); - // error, we should not have exited on this port - return -1; - } - - if (io_info->sz8) { read_size = 1; } else if (io_info->sz16) { @@ -86,11 +79,20 @@ int v3_handle_svm_io_in(struct guest_info * core, struct svm_io_info * io_info) PrintDebug("IN of %d bytes on port %d (0x%x)\n", read_size, io_info->port, io_info->port); - if (hook->read(core, io_info->port, &(core->vm_regs.rax), read_size, hook->priv_data) != read_size) { - // not sure how we handle errors..... - PrintError("Read Failure for in on port 0x%x\n", io_info->port); - return -1; + if (hook == NULL) { + PrintDebug("IN operation on unhooked IO port 0x%x\n", io_info->port); + + /* What are the HW semantics for an IN on an invalid port? + * Do we need to clear the register value or leave it untouched??? + */ + } else { + if (hook->read(core, io_info->port, &(core->vm_regs.rax), read_size, hook->priv_data) != read_size) { + // not sure how we handle errors..... + PrintError("Read Failure for in on port 0x%x\n", io_info->port); + return -1; + } } + return 0; } @@ -121,15 +123,7 @@ int v3_handle_svm_io_ins(struct guest_info * core, struct svm_io_info * io_info) if (flags->df) { direction = -1; } - - - if (hook == NULL) { - PrintError("Hook Not present for ins on port 0x%x\n", io_info->port); - // error, we should not have exited on this port - return -1; - } - - + if (v3_gva_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), &inst_ptr) == -1) { PrintError("Can't access instruction\n"); @@ -198,7 +192,6 @@ int v3_handle_svm_io_ins(struct guest_info * core, struct svm_io_info * io_info) //rep_num = info->vm_regs.rcx; } - PrintDebug("INS size=%d for %d steps\n", read_size, rep_num); while (rep_num > 0) { @@ -213,12 +206,19 @@ int v3_handle_svm_io_ins(struct guest_info * core, struct svm_io_info * io_info) return -1; } - if (hook->read(core, io_info->port, (char *)host_addr, read_size, hook->priv_data) != read_size) { - // not sure how we handle errors..... - PrintError("Read Failure for ins on port 0x%x\n", io_info->port); - return -1; + if (hook == NULL) { + PrintDebug("INS operation on unhooked IO port 0x%x\n", io_info->port); + /* What are the HW semantics for an INS on an invalid port? + * Do we need to clear the memory region or leave it untouched??? + */ + } else { + if (hook->read(core, io_info->port, (char *)host_addr, read_size, hook->priv_data) != read_size) { + // not sure how we handle errors..... + PrintError("Read Failure for ins on port 0x%x\n", io_info->port); + return -1; + } } - + core->vm_regs.rdi += (read_size * direction); if (io_info->rep) { @@ -235,13 +235,6 @@ int v3_handle_svm_io_out(struct guest_info * core, struct svm_io_info * io_info) struct v3_io_hook * hook = v3_get_io_hook(core->vm_info, io_info->port); int write_size = 0; - if (hook == NULL) { - PrintError("Hook Not present for out on port 0x%x\n", io_info->port); - // error, we should not have exited on this port - return -1; - } - - if (io_info->sz8) { write_size = 1; } else if (io_info->sz16) { @@ -252,11 +245,16 @@ int v3_handle_svm_io_out(struct guest_info * core, struct svm_io_info * io_info) PrintDebug("OUT of %d bytes on port %d (0x%x)\n", write_size, io_info->port, io_info->port); - if (hook->write(core, io_info->port, &(core->vm_regs.rax), write_size, hook->priv_data) != write_size) { - // not sure how we handle errors..... - PrintError("Write Failure for out on port 0x%x\n", io_info->port); - return -1; + if (hook == NULL) { + PrintDebug("OUT operation on unhooked IO port 0x%x\n", io_info->port); + } else { + if (hook->write(core, io_info->port, &(core->vm_regs.rax), write_size, hook->priv_data) != write_size) { + // not sure how we handle errors..... + PrintError("Write Failure for out on port 0x%x\n", io_info->port); + return -1; + } } + return 0; } @@ -286,13 +284,6 @@ int v3_handle_svm_io_outs(struct guest_info * core, struct svm_io_info * io_info direction = -1; } - - if (hook == NULL) { - PrintError("Hook Not present for outs on port 0x%x\n", io_info->port); - // error, we should not have exited on this port - return -1; - } - PrintDebug("OUTS on port %d (0x%x)\n", io_info->port, io_info->port); if (io_info->sz8) { @@ -373,11 +364,16 @@ int v3_handle_svm_io_outs(struct guest_info * core, struct svm_io_info * io_info return -1; } - if (hook->write(core, io_info->port, (char*)host_addr, write_size, hook->priv_data) != write_size) { - // not sure how we handle errors..... - PrintError("Write Failure for outs on port 0x%x\n", io_info->port); - return -1; + if (hook == NULL) { + PrintDebug("OUTS operation on unhooked IO port 0x%x\n", io_info->port); + } else { + if (hook->write(core, io_info->port, (char*)host_addr, write_size, hook->priv_data) != write_size) { + // not sure how we handle errors..... + PrintError("Write Failure for outs on port 0x%x\n", io_info->port); + return -1; + } } + core->vm_regs.rsi += write_size * direction; diff --git a/palacios/src/palacios/svm_msr.c b/palacios/src/palacios/svm_msr.c index 345ab1a..2ffcfac 100644 --- a/palacios/src/palacios/svm_msr.c +++ b/palacios/src/palacios/svm_msr.c @@ -82,7 +82,7 @@ int v3_init_svm_msr_map(struct v3_vm_info * vm) { msr_map->update_map = update_map; msr_map->arch_data = V3_VAddr(V3_AllocPages(2)); - memset(msr_map->arch_data, 0, PAGE_SIZE_4KB * 2); + memset(msr_map->arch_data, 0xff, PAGE_SIZE_4KB * 2); v3_refresh_msr_map(vm); diff --git a/palacios/src/palacios/vmm_msr.c b/palacios/src/palacios/vmm_msr.c index 68d4767..290398e 100644 --- a/palacios/src/palacios/vmm_msr.c +++ b/palacios/src/palacios/vmm_msr.c @@ -51,23 +51,23 @@ int v3_handle_msr_write(struct guest_info * info) { uint32_t msr_num = info->vm_regs.rcx; struct v3_msr msr_val; struct v3_msr_hook * hook = NULL; + + msr_val.value = 0; PrintDebug("MSR write for msr 0x%x\n", msr_num); hook = v3_get_msr_hook(info->vm_info, msr_num); - if (!hook) { - PrintError("Hook for MSR write %d not found\n", msr_num); - return -1; - } - - msr_val.value = 0; - msr_val.lo = info->vm_regs.rax; - msr_val.hi = info->vm_regs.rdx; - - if (hook->write(info, msr_num, msr_val, hook->priv_data) == -1) { - PrintError("Error in MSR hook Write\n"); - return -1; + if (hook == NULL) { + PrintError("Write to unhooked MSR 0x%x\n", msr_num); + } else { + msr_val.lo = info->vm_regs.rax; + msr_val.hi = info->vm_regs.rdx; + + if (hook->write(info, msr_num, msr_val, hook->priv_data) == -1) { + PrintError("Error in MSR hook Write\n"); + return -1; + } } info->rip += 2; @@ -81,20 +81,19 @@ int v3_handle_msr_read(struct guest_info * info) { struct v3_msr msr_val; struct v3_msr_hook * hook = NULL; - hook = v3_get_msr_hook(info->vm_info, msr_num); - - if (!hook) { - PrintError("Hook for MSR read 0x%x not found\n", msr_num); - return -1; - } - msr_val.value = 0; - if (hook->read(info, msr_num, &msr_val, hook->priv_data) == -1) { - PrintError("Error in MSR hook Read\n"); - return -1; + hook = v3_get_msr_hook(info->vm_info, msr_num); + + if (hook == NULL) { + PrintError("Read from unhooked MSR 0x%x\n", msr_num); + } else { + if (hook->read(info, msr_num, &msr_val, hook->priv_data) == -1) { + PrintError("Error in MSR hook Read\n"); + return -1; + } } - + info->vm_regs.rax = msr_val.lo; info->vm_regs.rdx = msr_val.hi; diff --git a/palacios/src/palacios/vmx.c b/palacios/src/palacios/vmx.c index ca875bb..73b5af9 100644 --- a/palacios/src/palacios/vmx.c +++ b/palacios/src/palacios/vmx.c @@ -349,13 +349,6 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state) // save STAR, LSTAR, FMASK, KERNEL_GS_BASE MSRs in MSR load/store area { -#define IA32_STAR 0xc0000081 -#define IA32_LSTAR 0xc0000082 -#define IA32_FMASK 0xc0000084 -#define IA32_KERN_GS_BASE 0xc0000102 - -#define IA32_CSTAR 0xc0000083 // Compatibility mode STAR (ignored for now... hopefully its not that important...) - int msr_ret = 0; struct vmcs_msr_entry * exit_store_msrs = NULL; @@ -387,24 +380,37 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state) entry_load_msrs = (struct vmcs_msr_entry *)(vmx_state->msr_area + (sizeof(struct vmcs_msr_entry) * 8)); - exit_store_msrs[0].index = IA32_STAR; - exit_store_msrs[1].index = IA32_LSTAR; - exit_store_msrs[2].index = IA32_FMASK; - exit_store_msrs[3].index = IA32_KERN_GS_BASE; + exit_store_msrs[0].index = IA32_STAR_MSR; + exit_store_msrs[1].index = IA32_LSTAR_MSR; + exit_store_msrs[2].index = IA32_FMASK_MSR; + exit_store_msrs[3].index = IA32_KERN_GS_BASE_MSR; memcpy(exit_store_msrs, exit_load_msrs, sizeof(struct vmcs_msr_entry) * 4); memcpy(exit_store_msrs, entry_load_msrs, sizeof(struct vmcs_msr_entry) * 4); - v3_get_msr(IA32_STAR, &(exit_load_msrs[0].hi), &(exit_load_msrs[0].lo)); - v3_get_msr(IA32_LSTAR, &(exit_load_msrs[1].hi), &(exit_load_msrs[1].lo)); - v3_get_msr(IA32_FMASK, &(exit_load_msrs[2].hi), &(exit_load_msrs[2].lo)); - v3_get_msr(IA32_KERN_GS_BASE, &(exit_load_msrs[3].hi), &(exit_load_msrs[3].lo)); + v3_get_msr(IA32_STAR_MSR, &(exit_load_msrs[0].hi), &(exit_load_msrs[0].lo)); + v3_get_msr(IA32_LSTAR_MSR, &(exit_load_msrs[1].hi), &(exit_load_msrs[1].lo)); + v3_get_msr(IA32_FMASK_MSR, &(exit_load_msrs[2].hi), &(exit_load_msrs[2].lo)); + v3_get_msr(IA32_KERN_GS_BASE_MSR, &(exit_load_msrs[3].hi), &(exit_load_msrs[3].lo)); msr_ret |= check_vmcs_write(VMCS_EXIT_MSR_STORE_ADDR, (addr_t)V3_PAddr(exit_store_msrs)); msr_ret |= check_vmcs_write(VMCS_EXIT_MSR_LOAD_ADDR, (addr_t)V3_PAddr(exit_load_msrs)); msr_ret |= check_vmcs_write(VMCS_ENTRY_MSR_LOAD_ADDR, (addr_t)V3_PAddr(entry_load_msrs)); + + v3_hook_msr(core->vm_info, IA32_STAR_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, IA32_LSTAR_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, IA32_FMASK_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, IA32_KERN_GS_BASE_MSR, NULL, NULL, NULL); + + + // IMPORTANT: These SYSCALL MSRs are currently not handled by hardware or cached + // We should really emulate these ourselves, or ideally include them in the MSR store area if there is room + v3_hook_msr(core->vm_info, IA32_CSTAR_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, SYSENTER_CS_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, SYSENTER_ESP_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, SYSENTER_EIP_MSR, NULL, NULL, NULL); } /* Sanity check ctrl/reg fields against hw_defaults */ diff --git a/palacios/src/palacios/vmx_io.c b/palacios/src/palacios/vmx_io.c index d69787a..9b02a0a 100644 --- a/palacios/src/palacios/vmx_io.c +++ b/palacios/src/palacios/vmx_io.c @@ -50,7 +50,7 @@ int v3_init_vmx_io_map(struct v3_vm_info * vm) { vm->io_map.update_map = update_map; vm->io_map.arch_data = V3_VAddr(V3_AllocPages(2)); - memset(vm->io_map.arch_data, 0, PAGE_SIZE_4KB * 2); + memset(vm->io_map.arch_data, 0xff, PAGE_SIZE_4KB * 2); v3_refresh_io_map(vm); @@ -68,23 +68,25 @@ int v3_handle_vmx_io_in(struct guest_info * core, struct vmx_exit_info * exit_in struct v3_io_hook * hook = NULL; int read_size = 0; - hook = v3_get_io_hook(core->vm_info, io_qual.port); - if (hook == NULL) { - PrintError("Hook not present for IN on port %x\n", io_qual.port); - return -1; - } - read_size = io_qual.access_size + 1; PrintDebug("IN of %d bytes on port %d (0x%x)\n", read_size, io_qual.port, io_qual.port); - if (hook->read(core, io_qual.port, &(core->vm_regs.rax), read_size, hook->priv_data) != read_size) { - PrintError("Read failure for IN on port %x\n", io_qual.port); - return -1; - } + if (hook == NULL) { + PrintDebug("IN operation on unhooked IO port 0x%x\n", io_qual.port); + /* What are the HW semantics for an IN on an invalid port? + * Do we need to clear the register value or leave it untouched??? + */ + } else { + if (hook->read(core, io_qual.port, &(core->vm_regs.rax), read_size, hook->priv_data) != read_size) { + PrintError("Read failure for IN on port %x\n", io_qual.port); + return -1; + } + } + core->rip += exit_info->instr_len; @@ -103,10 +105,6 @@ int v3_handle_vmx_io_ins(struct guest_info * core, struct vmx_exit_info * exit_i hook = v3_get_io_hook(core->vm_info, io_qual.port); - if (hook == NULL) { - PrintError("Hook not present for INS on port 0x%x\n", io_qual.port); - return -1; - } PrintDebug("INS on port 0x%x\n", io_qual.port); @@ -143,10 +141,20 @@ int v3_handle_vmx_io_ins(struct guest_info * core, struct vmx_exit_info * exit_i } do { - if (hook->read(core, io_qual.port, (char *)host_addr, read_size, hook->priv_data) != read_size) { - PrintError("Read Failure for INS on port 0x%x\n", io_qual.port); - return -1; - } + + if (hook == NULL) { + PrintDebug("INS operation on unhooked IO port 0x%x\n", io_qual.port); + + /* What are the HW semantics for an INS on an invalid port? + * Do we need to clear the memory region or leave it untouched??? + */ + } else { + if (hook->read(core, io_qual.port, (char *)host_addr, read_size, hook->priv_data) != read_size) { + PrintError("Read Failure for INS on port 0x%x\n", io_qual.port); + return -1; + } + } + host_addr += rdi_change; core->vm_regs.rdi += rdi_change; @@ -172,22 +180,20 @@ int v3_handle_vmx_io_out(struct guest_info * core, struct vmx_exit_info * exit_i hook = v3_get_io_hook(core->vm_info, io_qual.port); - if (hook == NULL) { - PrintError("Hook not present for out on port %x\n", io_qual.port); - return -1; - } write_size = io_qual.access_size + 1; PrintDebug("OUT of %d bytes on port %d (0x%x)\n", write_size, io_qual.port, io_qual.port); - if (hook->write(core, io_qual.port, &(core->vm_regs.rax), write_size, hook->priv_data) != write_size) { - PrintError("Write failure for out on port %x\n",io_qual.port); - return -1; + if (hook == NULL) { + PrintDebug("OUT operation on unhooked IO port 0x%x\n", io_qual.port); + } else { + if (hook->write(core, io_qual.port, &(core->vm_regs.rax), write_size, hook->priv_data) != write_size) { + PrintError("Write failure for out on port %x\n",io_qual.port); + return -1; + } } - - core->rip += exit_info->instr_len; return 0; @@ -207,11 +213,6 @@ int v3_handle_vmx_io_outs(struct guest_info * core, struct vmx_exit_info * exit_ hook = v3_get_io_hook(core->vm_info, io_qual.port); - if (hook == NULL) { - PrintError("Hook not present for OUTS on port 0x%x\n", io_qual.port); - return -1; - } - PrintDebug("OUTS on port 0x%x\n", io_qual.port); write_size = io_qual.access_size + 1; @@ -248,10 +249,16 @@ int v3_handle_vmx_io_outs(struct guest_info * core, struct vmx_exit_info * exit_ } do { - if (hook->write(core, io_qual.port, (char *)host_addr, write_size, hook->priv_data) != write_size) { - PrintError("Read failure for INS on port 0x%x\n", io_qual.port); - return -1; - } + + if (hook == NULL) { + PrintDebug("OUTS operation on unhooked IO port 0x%x\n", io_qual.port); + } else { + if (hook->write(core, io_qual.port, (char *)host_addr, write_size, hook->priv_data) != write_size) { + PrintError("Read failure for INS on port 0x%x\n", io_qual.port); + return -1; + } + } + host_addr += rsi_change; core->vm_regs.rsi += rsi_change; diff --git a/palacios/src/palacios/vmx_msr.c b/palacios/src/palacios/vmx_msr.c index e1ba86f..f470c37 100644 --- a/palacios/src/palacios/vmx_msr.c +++ b/palacios/src/palacios/vmx_msr.c @@ -66,7 +66,7 @@ int v3_init_vmx_msr_map(struct v3_vm_info * vm) { msr_map->update_map = update_map; msr_map->arch_data = V3_VAddr(V3_AllocPages(1)); - memset(msr_map->arch_data, 0, PAGE_SIZE_4KB); + memset(msr_map->arch_data, 0xff, PAGE_SIZE_4KB); v3_refresh_msr_map(vm);