From: Patrick G. Bridges Date: Thu, 27 Oct 2011 21:01:28 +0000 (-0600) Subject: Merge branch 'devel' of ssh://newskysaw.cs.northwestern.edu/home/palacios/palacios... X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=95b1b11f48e19834fca26e87f594d6794f1c6d55;hp=ea98f071ad004a040cefbb494733f4f1cb0d75d7 Merge branch 'devel' of ssh://newskysaw.cs.northwestern.edu/home/palacios/palacios into devel --- diff --git a/palacios/include/interfaces/vmm_keyed_stream.h b/palacios/include/interfaces/vmm_keyed_stream.h index 06fafd5..d9a9eea 100644 --- a/palacios/include/interfaces/vmm_keyed_stream.h +++ b/palacios/include/interfaces/vmm_keyed_stream.h @@ -61,7 +61,9 @@ sint64_t v3_keyed_stream_read_key(v3_keyed_stream_t stream, void *buf, sint64_t len); -#define STD_SAVE(stream,ks,x) \ + + +#define STD_SAVE_RAW(stream,ks,x) \ do { \ if (sizeof((x)) != v3_keyed_stream_write_key((stream), (ks), &(x), sizeof((x)))) { \ v3_keyed_stream_close_key((stream),(ks)); \ @@ -69,7 +71,7 @@ sint64_t v3_keyed_stream_read_key(v3_keyed_stream_t stream, } \ } while (0) -#define STD_LOAD(stream,ks,x) \ +#define STD_LOAD_RAW(stream,ks,x) \ do { \ if (sizeof((x)) != v3_keyed_stream_read_key((stream), (ks), &(x), sizeof((x)))) { \ v3_keyed_stream_close_key((stream),(ks)); \ @@ -78,6 +80,89 @@ sint64_t v3_keyed_stream_read_key(v3_keyed_stream_t stream, } while (0) #endif +#define KSTREAM_MAGIC_COOKIE 0xabcd0123 + +#define STD_SAVE_TAGGED(stream,ks,tag,size,x) \ +do { \ +uint32_t temp; \ +temp=KSTREAM_MAGIC_COOKIE; \ +if (sizeof(temp) != v3_keyed_stream_write_key((stream),(ks),&temp,sizeof(temp))) { \ + v3_keyed_stream_close_key((stream),(ks)); \ + return -1; \ + } \ +temp=strlen(tag); \ +if (sizeof(temp) != v3_keyed_stream_write_key((stream),(ks),&temp,sizeof(temp))) { \ + v3_keyed_stream_close_key((stream),(ks)); \ + return -1; \ + } \ +if (temp != v3_keyed_stream_write_key((stream),(ks),tag,temp)) { \ + v3_keyed_stream_close_key((stream),(ks)); \ + return -1; \ + } \ +temp=(size); \ +if (sizeof(temp) != v3_keyed_stream_write_key((stream),(ks),&temp,sizeof(temp))) { \ + v3_keyed_stream_close_key((stream),(ks)); \ + return -1; \ + } \ +if ((size) != v3_keyed_stream_write_key((stream),(ks),&(x),(size))) { \ + v3_keyed_stream_close_key((stream),(ks)); \ + return -1; \ + } \ +} while (0) + +#define STD_LOAD_TAGGED(stream,ks,tag,size,x) \ +do { \ +uint32_t temp; \ +if (sizeof(temp) != v3_keyed_stream_read_key((stream),(ks),&temp,sizeof(temp))) { \ + v3_keyed_stream_close_key((stream),(ks)); \ + return -1; \ + } \ +if (temp!=KSTREAM_MAGIC_COOKIE) { \ + v3_keyed_stream_close_key((stream),(ks)); \ + return -1; \ +} \ +if (sizeof(temp) != v3_keyed_stream_read_key((stream),(ks),&temp,sizeof(temp))) { \ + v3_keyed_stream_close_key((stream),(ks)); \ + return -1; \ + } \ +if (strlen((tag))!=temp) { \ + v3_keyed_stream_close_key((stream),(ks)); \ + return -1; \ +} \ +{ char buf[temp+1]; \ + if (temp != v3_keyed_stream_read_key((stream),(ks),buf,temp)) { \ + v3_keyed_stream_close_key((stream),(ks)); \ + return -1; \ + } \ + buf[temp]=0; \ + if (strncasecmp(buf,tag,temp)) { \ + v3_keyed_stream_close_key((stream),(ks)); \ + return -1; \ + } \ +} \ +if (sizeof(temp) != v3_keyed_stream_read_key((stream),(ks),&temp,sizeof(temp))) { \ + v3_keyed_stream_close_key((stream),(ks)); \ + return -1; \ + } \ +if (temp!=(size)) { \ + v3_keyed_stream_close_key((stream),(ks)); \ + return -1; \ +} \ +if ((size) != v3_keyed_stream_read_key((stream),(ks),&(x),(size))) { \ + v3_keyed_stream_close_key((stream),(ks)); \ + return -1; \ + } \ +} while (0) + +#ifdef V3_CONFIG_KEYED_STREAMS_WITH_TAGS +#define STD_SAVE(stream,ks,x) STD_SAVE_TAGGED(stream,ks,#x,sizeof(x),x) +#define STD_LOAD(stream,ks,x) STD_LOAD_TAGGED(stream,ks,#x,sizeof(x),x) +#else +#define STD_SAVE(stream,ks,x) STD_SAVE_RAW(stream,ks,x) +#define STD_LOAD(stream,ks,x) STD_LOAD_RAW(stream,ks,x) +#endif + + struct v3_keyed_stream_hooks { // url is meaningful only to the host implementation 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/devices/ne2k.c b/palacios/src/devices/ne2k.c index ad0bda8..bc51c78 100644 --- a/palacios/src/devices/ne2k.c +++ b/palacios/src/devices/ne2k.c @@ -337,7 +337,7 @@ static int ne2k_update_irq(struct ne2k_state * nic_state) { v3_pci_raise_irq(nic_state->pci_bus, 0, nic_state->pci_dev); } - nic_state->statistics.interrupts ++; + nic_state->statistics.rx_interrupts ++; PrintDebug("NE2000: Raise IRQ\n"); } @@ -1176,10 +1176,7 @@ static int connect_fn(struct v3_vm_info * info, ops->recv = ne2k_rx; ops->poll = NULL; - ops->start_tx = NULL; - ops->stop_tx = NULL; - ops->frontend_data = nic_state; - memcpy(ops->fnt_mac, nic_state->mac, ETH_ALEN); + memcpy(ops->config.fnt_mac, nic_state->mac, ETH_ALEN); return 0; } diff --git a/palacios/src/devices/rtl8139.c b/palacios/src/devices/rtl8139.c index 4ef93df..0a1a335 100644 --- a/palacios/src/devices/rtl8139.c +++ b/palacios/src/devices/rtl8139.c @@ -171,16 +171,16 @@ struct rx_status_reg { union { uint16_t val; struct { - uint8_t rx_ok : 1; - uint8_t rx_bad_align : 1; - uint8_t rx_crc_err : 1; - uint8_t rx_too_long : 1; - uint8_t rx_runt : 1; - uint8_t rx_bad_sym : 1; - uint8_t reserved : 7; - uint8_t rx_brdcast : 1; - uint8_t rx_phys : 1; - uint8_t rx_multi : 1; + uint16_t rx_ok : 1; + uint16_t rx_bad_align : 1; + uint16_t rx_crc_err : 1; + uint16_t rx_too_long : 1; + uint16_t rx_runt : 1; + uint16_t rx_bad_sym : 1; + uint16_t reserved : 7; + uint16_t rx_brdcast : 1; + uint16_t rx_phys : 1; + uint16_t rx_multi : 1; } __attribute__((packed)); } __attribute__((packed)); } __attribute__((packed)); @@ -270,17 +270,17 @@ struct isr_imr_reg { union { uint16_t val; struct { - uint8_t rx_ok :1; - uint8_t rx_err : 1; - uint8_t tx_ok : 1; - uint8_t tx_err : 1; - uint8_t rx_ovw : 1; - uint8_t pun_linkchg : 1; - uint8_t rx_fifo_ovw : 1; - uint8_t reservd: 6; - uint8_t lenchg :1; - uint8_t timeout :1; - uint8_t syserr :1; + uint16_t rx_ok :1; + uint16_t rx_err : 1; + uint16_t tx_ok : 1; + uint16_t tx_err : 1; + uint16_t rx_ovw : 1; + uint16_t pun_linkchg : 1; + uint16_t rx_fifo_ovw : 1; + uint16_t reservd: 6; + uint16_t lenchg :1; + uint16_t timeout :1; + uint16_t syserr :1; } __attribute__((packed)); } __attribute__((packed)); } __attribute__((packed)); @@ -583,7 +583,7 @@ static inline void rtl8139_update_irq(struct rtl8139_state * nic_state) { if(isr & 0xffff){ v3_pci_raise_irq(nic_state->pci_bus, 0, nic_state->pci_dev); - nic_state->statistic.interrupts ++; + nic_state->statistic.tx_interrupts ++; } } @@ -1774,10 +1774,7 @@ static int connect_fn(struct v3_vm_info * info, ops->recv = rtl8139_rx; ops->poll = NULL; - ops->start_tx = NULL; - ops->stop_tx = NULL; - ops->frontend_data = nic_state; - memcpy(ops->fnt_mac, nic_state->mac, ETH_ALEN); + memcpy(ops->config.fnt_mac, nic_state->mac, ETH_ALEN); return 0; } diff --git a/palacios/src/interfaces/Kconfig b/palacios/src/interfaces/Kconfig index 270509a..61a7965 100644 --- a/palacios/src/interfaces/Kconfig +++ b/palacios/src/interfaces/Kconfig @@ -13,6 +13,16 @@ config KEYED_STREAMS Select this if your host OS supports keyed streams Palacios Checkpoint/Restore and Migration depends on this feature +config KEYED_STREAMS_WITH_TAGS + bool "Keyed streams will be written in verbose tagged style when std save/load macros are in use" + default n + depends on KEYED_STREAMS + help + Select this if you want the standard save and load macros + (STD_SAVE, STD_LOAD) to write to streams in the format: + [magic cookie][tag len][tag][data len][data] instead of the + default format of [data] + config STREAM bool "Stream support" default n 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);