#include <palacios/vmm_types.h>
#include <palacios/vmm_list.h>
+#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;
&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);
+ }
}
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);
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) {
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;
}
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");
//rep_num = info->vm_regs.rcx;
}
-
PrintDebug("INS size=%d for %d steps\n", read_size, rep_num);
while (rep_num > 0) {
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) {
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) {
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;
}
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) {
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;
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);
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;
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;
// 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;
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 */
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);
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;
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);
}
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;
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;
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;
}
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;
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);