# Makefile for GeekOS kernel, userspace, and tools
# Copyright (c) 2004,2005 David H. Hovemeyer <daveho@cs.umd.edu>
-# $Revision: 1.20 $
+# $Revision: 1.21 $
# This is free software. You are permitted to use,
# redistribute, and modify it as specified in the file "COPYING".
serial.c reboot.c \
paging.c vm_guest.c \
svm.c svm_handler.c vmm.c vmm_util.c vmm_stubs.c svm_ctrl_regs.c \
- vmcb.c vmm_mem.c vmm_paging.c vmm_io.c vmm_debug.c \
+ vmcb.c vmm_mem.c vmm_paging.c vmm_io.c vmm_debug.c svm_io.c \
vmm_shadow_paging.c vm_guest_mem.c \
debug.c vmx.c vmcs_gen.c vmcs.c\
main.c
/******************************************/
-struct svm_io_info {
- uint_t type : 1 PACKED; // (0=out, 1=in)
- uint_t rsvd : 1 PACKED; // Must be Zero
- uint_t str : 1 PACKED; // string based io
- uint_t rep : 1 PACKED; // repeated io
- uint_t sz8 : 1 PACKED; // 8 bit op size
- uint_t sz16 : 1 PACKED; // 16 bit op size
- uint_t sz32 : 1 PACKED; // 32 bit op size
- uint_t A16 : 1 PACKED; // 16 bit addr
- uint_t A32 : 1 PACKED; // 32 bit addr
- uint_t A64 : 1 PACKED; // 64 bit addr
- uint_t rsvd2 : 6 PACKED; // Should be Zero
- ushort_t port PACKED; // port number
-};
-
-
-int handle_svm_io(struct guest_info * info);
+
+
int handle_shadow_paging(struct guest_info * info);
int handle_svm_exit(struct guest_info * info);
--- /dev/null
+#ifndef __SVM_IO_H
+#define __SVM_IO_H
+#include <geekos/vm_guest.h>
+#include <geekos/vmcb.h>
+#include <geekos/vmm.h>
+
+struct svm_io_info {
+ uint_t type : 1 PACKED; // (0=out, 1=in)
+ uint_t rsvd : 1 PACKED; // Must be Zero
+ uint_t str : 1 PACKED; // string based io
+ uint_t rep : 1 PACKED; // repeated io
+ uint_t sz8 : 1 PACKED; // 8 bit op size
+ uint_t sz16 : 1 PACKED; // 16 bit op size
+ uint_t sz32 : 1 PACKED; // 32 bit op size
+ uint_t A16 : 1 PACKED; // 16 bit addr
+ uint_t A32 : 1 PACKED; // 32 bit addr
+ uint_t A64 : 1 PACKED; // 64 bit addr
+ uint_t rsvd2 : 6 PACKED; // Should be Zero
+ ushort_t port PACKED; // port number
+};
+
+
+int handle_svm_io_in(struct guest_info * info);
+int handle_svm_io_ins(struct guest_info * info);
+int handle_svm_io_out(struct guest_info * info);
+int handle_svm_io_outs(struct guest_info * info);
+
+
+
+
+#endif
#include <geekos/vmm_util.h>
-// FOREACH_IO_HOOK(vmm_io_map_t io_map, vmm_io_hook_t * io_hook)
-#define FOREACH_IO_HOOK(io_map, io_hook) for (io_hook = io_map.head; io_hook != NULL; io_hook = io_hook->next)
+// FOREACH_IO_HOOK(vmm_io_map_t * io_map, vmm_io_hook_t * io_hook)
+#define FOREACH_IO_HOOK(io_map, io_hook) for (io_hook = (io_map).head; io_hook != NULL; io_hook = (io_hook)->next)
typedef struct vmm_io_hook {
ushort_t port;
// Reads data into the IO port (IN, INS)
- int (*read)(ushort_t port, void * dst, uint_t length);
+ int (*read)(ushort_t port, void * dst, uint_t length, uint_t io_width);
// Writes data from the IO port (OUT, OUTS)
- int (*write)(ushort_t port, void * src, uint_t length);
+ int (*write)(ushort_t port, void * src, uint_t length, uint_t io_width);
struct vmm_io_hook * next;
struct vmm_io_hook * prev;
+vmm_io_hook_t * get_io_hook(vmm_io_map_t * io_map, uint_t port);
+
/* External API */
void hook_io_port(vmm_io_map_t * io_map, uint_t port,
- int (*read)(ushort_t port, void * dst, uint_t length),
- int (*write)(ushort_t port, void * src, uint_t length));
+ int (*read)(ushort_t port, void * dst, uint_t length, uint_t io_width),
+ int (*write)(ushort_t port, void * src, uint_t length, uint_t io_width));
void init_vmm_io_map(vmm_io_map_t * io_map);
* Copyright (c) 2001,2003,2004 David H. Hovemeyer <daveho@cs.umd.edu>
* Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
* Copyright (c) 2004, Iulian Neamtiu <neamtiu@cs.umd.edu>
- * $Revision: 1.28 $
+ * $Revision: 1.29 $
*
* This is free software. You are permitted to use,
* redistribute, and modify it as specified in the file "COPYING".
-int IO_Read(ushort_t port, void * dst, uint_t length) {
+int IO_Read(ushort_t port, void * dst, uint_t length, uint_t io_width) {
uchar_t * iter = dst;
uint_t i;
-int IO_Write(ushort_t port, void * src, uint_t length) {
+int IO_Write(ushort_t port, void * src, uint_t length, uint_t io_width) {
uchar_t * iter = src;
uint_t i;
}
+
+int IO_Write_to_Serial(ushort_t port, void * src, uint_t length, uint_t io_width) {
+ SerialPrint("Output from Guest on port %d (0x%x) Length=%d\n", port, port, length);
+ SerialMemDump(src, length);
+ return length;
+}
+
+
void BuzzVM()
{
int x;
add_shadow_region(&(vm_info.mem_map),ent);
hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write);
- hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write);
+ hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial);
/*
vm_info.cr0 = 0;
guest_state->rip = vm_info.rip;
-
-
-
guest_state->efer |= EFER_MSR_svm_enable;
guest_state->rflags = 0x00000002; // The reserved bit is always 1
ctrl_area->svm_instrs.instrs.VMRUN = 1;
- // guest_state->cr0 = 0x00000001; // PE
ctrl_area->guest_ASID = 1;
guest_state->cr0 = 0x60000010;
guest_state->g_pat = 0x7040600070406ULL;
+ vm_info.shdw_pg_state.guest_cr0.e_reg.low = guest_state->cr0;
guest_state->cr0 |= 0x80000000;
} else if (vm_info.page_mode == NESTED_PAGING) {
// Flush the TLB on entries/exits
#include <geekos/vmm_ctrl_regs.h>
+/* Segmentation is a problem here...
+ *
+ * When we get a memory operand, presumably we use the default segment (which is?)
+ * unless an alternate segment was specfied in the prefix...
+ */
+
+
int handle_cr0_write(struct guest_info * info) {
//vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
int ret;
// The real rip address is actually a combination of the rip + CS base
- ret = read_guest_pa_memory(info, (addr_t)guest_state->rip, 15, instr);
+ ret = read_guest_pa_memory(info, (addr_t)guest_state->rip + (guest_state->cs.base << 4), 15, instr);
if (ret != 15) {
// I think we should inject a GPF into the guest
PrintDebug("Could not read instruction (ret=%d)\n", ret);
} else if (addr_type == MEM_OPERAND) {
addr_t host_addr;
- if (guest_pa_to_host_va(info, first_operand, &host_addr) == -1) {
+ if (guest_pa_to_host_va(info, first_operand + (guest_state->ds.base << 4), &host_addr) == -1) {
// gpf the guest
return -1;
}
PrintDebug("Protected Mode write to CR0\n");
// The real rip address is actually a combination of the rip + CS base
- ret = read_guest_pa_memory(info, (addr_t)guest_state->rip, 15, instr);
+ ret = read_guest_pa_memory(info, (addr_t)guest_state->rip + guest_state->cs.base, 15, instr);
if (ret != 0) {
// I think we should inject a GPF into the guest
PrintDebug("Could not read instruction (ret=%d)\n", ret);
} else if (addr_type == MEM_OPERAND) {
addr_t host_addr;
- if (guest_pa_to_host_va(info, first_operand, &host_addr) == -1) {
+ if (guest_pa_to_host_va(info, first_operand + guest_state->ds.base, &host_addr) == -1) {
// gpf the guest
return -1;
}
int ret;
// The real rip address is actually a combination of the rip + CS base
- ret = read_guest_pa_memory(info, (addr_t)guest_state->rip, 15, instr);
+ ret = read_guest_pa_memory(info, (addr_t)guest_state->rip + (guest_state->cs.base << 4), 15, instr);
if (ret != 15) {
// I think we should inject a GPF into the guest
PrintDebug("Could not read instruction (ret=%d)\n", ret);
if (addr_type == MEM_OPERAND) {
addr_t host_addr;
- if (guest_pa_to_host_va(info, first_operand, &host_addr) == -1) {
+ if (guest_pa_to_host_va(info, first_operand + (guest_state->ds.base << 4), &host_addr) == -1) {
// gpf the guest
return -1;
}
}
+ } else if (info->cpu_mode == PROTECTED) {
+ int index = 0;
+ int ret;
+
+ // The real rip address is actually a combination of the rip + CS base
+ ret = read_guest_pa_memory(info, (addr_t)guest_state->rip + guest_state->cs.base, 15, instr);
+ if (ret != 15) {
+ // I think we should inject a GPF into the guest
+ PrintDebug("Could not read instruction (ret=%d)\n", ret);
+ return -1;
+ }
+
+ while (is_prefix_byte(instr[index])) {
+ index++;
+ }
+
+
}
#include <geekos/svm_handler.h>
#include <geekos/vmm.h>
#include <geekos/svm_ctrl_regs.h>
+#include <geekos/svm_io.h>
extern struct vmm_os_hooks * os_hooks;
PrintDebug("io_info2 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info2));
PrintDebug("io_info2 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
+
if (exit_code == VMEXIT_IOIO) {
- handle_svm_io(info);
-
+ struct svm_io_info * io_info = (struct svm_io_info *)&(guest_ctrl->exit_info1);
+
+ if (io_info->type == 0) {
+ if (io_info->str) {
+ handle_svm_io_outs(info);
+ } else {
+ handle_svm_io_out(info);
+ }
+ } else {
+ if (io_info->str) {
+ handle_svm_io_ins(info);
+ } else {
+ handle_svm_io_in(info);
+ }
+ }
} else if (exit_code == VMEXIT_CR0_WRITE) {
PrintDebug("CR0 Write\n");
-// This should package up an IO request and call vmm_handle_io
-int handle_svm_io(struct guest_info * info) {
- vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
- vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
-
- PrintDebug("Ctrl Area=%x\n", ctrl_area);
-
- // struct svm_io_info * io_info = (struct svm_io_info *)&(ctrl_area->exit_info1);
-
-
-
- // PrintDebugVMCB((vmcb_t*)(info->vmm_data));
-
- guest_state->rip = ctrl_area->exit_info2;
-
-
-
-
- // PrintDebug("Exit On Port %d\n", io_info->port);
-
- return 0;
-}
-
int handle_shadow_paging(struct guest_info * info) {
vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
--- /dev/null
+#include <geekos/svm_io.h>
+#include <geekos/vmm_io.h>
+
+
+
+// This should package up an IO request and call vmm_handle_io
+int handle_svm_io_in(struct guest_info * info) {
+ vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
+ // vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
+ struct svm_io_info * io_info = (struct svm_io_info *)&(ctrl_area->exit_info1);
+
+ vmm_io_hook_t * hook = get_io_hook(&(info->io_map), io_info->port);
+ uint_t read_size = 0;
+
+ if (hook == NULL) {
+ // error, we should not have exited on this port
+ return -1;
+ }
+
+ PrintDebug("IN on port %d (0x%x)\n", io_info->port, io_info->port);
+
+ if (io_info->sz8) {
+ read_size = 1;
+ } else if (io_info->sz16) {
+ read_size = 2;
+ } else if (io_info->sz32) {
+ read_size = 4;
+ }
+
+
+ if (hook->read(io_info->port, &(info->vm_regs.rax), read_size, read_size) != read_size) {
+ // not sure how we handle errors.....
+ return -1;
+ }
+
+ info->rip = ctrl_area->exit_info2;
+
+ return 0;
+}
+
+
+int handle_svm_io_ins(struct guest_info * info) {
+
+ // PrintDebug("INS on port %d (0x%x)\n", io_info->port, io_info->port);
+
+ return -1;
+
+}
+
+int handle_svm_io_out(struct guest_info * info) {
+ vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
+ // vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
+ struct svm_io_info * io_info = (struct svm_io_info *)&(ctrl_area->exit_info1);
+
+ vmm_io_hook_t * hook = get_io_hook(&(info->io_map), io_info->port);
+ uint_t write_size = 0;
+
+ if (hook == NULL) {
+ // error, we should not have exited on this port
+ return -1;
+ }
+
+ PrintDebug("OUT on port %d (0x%x)\n", io_info->port, io_info->port);
+
+ if (io_info->sz8) {
+ write_size = 1;
+ } else if (io_info->sz16) {
+ write_size = 2;
+ } else if (io_info->sz32) {
+ write_size = 4;
+ }
+
+
+ if (hook->write(io_info->port, &(info->vm_regs.rax), write_size, write_size) != write_size) {
+ // not sure how we handle errors.....
+ return -1;
+ }
+
+ info->rip = ctrl_area->exit_info2;
+
+ return 0;
+}
+
+
+int handle_svm_io_outs(struct guest_info * info) {
+ return -1;
+}
}
void hook_io_port(vmm_io_map_t * io_map, uint_t port,
- int (*read)(ushort_t port, void * dst, uint_t length),
- int (*write)(ushort_t port, void * src, uint_t length)) {
+ int (*read)(ushort_t port, void * dst, uint_t length, uint_t io_width),
+ int (*write)(ushort_t port, void * src, uint_t length, uint_t io_width)) {
vmm_io_hook_t * io_hook = os_hooks->malloc(sizeof(vmm_io_hook_t));
io_hook->port = port;
}
+vmm_io_hook_t * get_io_hook(vmm_io_map_t * io_map, uint_t port) {
+ vmm_io_hook_t * tmp_hook;
+ FOREACH_IO_HOOK(*io_map, tmp_hook) {
+ if (tmp_hook->port == port) {
+ return tmp_hook;
+ }
+ }
+ return NULL;
+}
+
+
+
void PrintDebugIOMap(vmm_io_map_t * io_map) {
vmm_io_hook_t * iter = io_map->head;