--- /dev/null
+rombios:000f0000
+vgabios:000c0000
\ No newline at end of file
#ifndef __VM_H
#define __VM_H
+#define MAGIC_CODE 0xf1e2d3c4
+
+struct layout_region {
+ ulong_t length;
+ ulong_t final_addr;
+};
+
+struct guest_mem_layout {
+ ulong_t magic;
+ ulong_t num_regions;
+ struct layout_region regions[0];
+};
+
+
int RunVMM(struct Boot_Info * bootInfo);
struct shadow_page_state;
-
+struct shadow_map;
typedef enum {SHADOW_PAGING, NESTED_PAGING} vm_page_mode_t;
typedef enum {REAL, PROTECTED, PROTECTED_PG, PROTECTED_PAE, PROTECTED_PAE_PG, LONG, LONG_PG} vm_cpu_mode_t;
ullong_t rip;
- shadow_map_t mem_map;
+ struct shadow_map mem_map;
vm_page_mode_t page_mode;
#include <palacios/vmm_types.h>
+
typedef ulong_t addr_t;
+struct guest_info;
+
+
/*
Guest Shadow Host
-typedef struct shadow_map {
+struct shadow_map {
uint_t num_regions;
shadow_region_t * head;
-} shadow_map_t;
+};
void init_shadow_region(shadow_region_t * entry,
guest_region_type_t guest_region_type,
host_region_type_t host_region_type);
+/*
void init_shadow_region_physical(shadow_region_t * entry,
addr_t guest_addr_start,
addr_t guest_addr_end,
guest_region_type_t guest_region_type,
addr_t host_addr_start,
host_region_type_t host_region_type);
-
-void init_shadow_map(shadow_map_t * map);
-void free_shadow_map(shadow_map_t * map);
+*/
+
+int add_shadow_region_passthrough(struct guest_info * guest_info,
+ addr_t guest_addr_start,
+ addr_t guest_addr_end,
+ addr_t host_addr_start);
+
+void init_shadow_map(struct shadow_map * map);
+void free_shadow_map(struct shadow_map * map);
-shadow_region_t * get_shadow_region_by_addr(shadow_map_t * map, addr_t guest_addr);
+shadow_region_t * get_shadow_region_by_addr(struct shadow_map * map, addr_t guest_addr);
-shadow_region_t * get_shadow_region_by_index(shadow_map_t * map, uint_t index);
+shadow_region_t * get_shadow_region_by_index(struct shadow_map * map, uint_t index);
-host_region_type_t lookup_shadow_map_addr(shadow_map_t * map, addr_t guest_addr, addr_t * host_addr);
+host_region_type_t lookup_shadow_map_addr(struct shadow_map * map, addr_t guest_addr, addr_t * host_addr);
// Semantics:
// Adding a region that overlaps with an existing region results is undefined
// and will probably fail
-int add_shadow_region(shadow_map_t * map, shadow_region_t * entry);
+int add_shadow_region(struct shadow_map * map, shadow_region_t * entry);
// Semantics:
// Deletions result in splitting
-int delete_shadow_region(shadow_map_t * map,
+int delete_shadow_region(struct shadow_map * map,
addr_t guest_start,
addr_t guest_end);
-void print_shadow_map(shadow_map_t * map);
+void print_shadow_map(struct shadow_map * map);
#include <palacios/vmm.h>
#include <geekos/debug.h>
#include <geekos/serial.h>
-
+#include <geekos/vm.h>
+#include <geekos/screen.h>
#define SPEAKER_PORT 0x61
}
+char * bochs_debug_buf = NULL;
+int bochs_debug_offset = 0;
+
+
+int IO_BOCHS_debug(ushort_t port, void * src, uint_t length) {
+ if (!bochs_debug_buf) {
+ bochs_debug_buf = (char*)Malloc(1024);
+ }
+
+ bochs_debug_buf[bochs_debug_offset++] = *(char*)src;
+
+ if ((*(char*)src == '\n') || (bochs_debug_offset == 1023)) {
+ SerialPrint("BOCHS>%s", bochs_debug_buf);
+ memset(bochs_debug_buf, 0, 1024);
+ bochs_debug_offset = 0;
+ }
+
+ return length;
+}
+
int IO_Write_to_Serial(ushort_t port, void * src, uint_t length) {
- PrintBoth("Output from Guest on port %d (0x%x) Length=%d\n", port, port, length);
+ SerialPrint("Output from Guest on port %d (0x%x) Length=%d\n", port, port, length);
switch (length) {
case 1:
- PrintBoth(">0x%.2x\n", *(char*)src);
+ SerialPrint(">0x%.2x\n", *(char*)src);
break;
case 2:
- PrintBoth(">0x%.4x\n", *(ushort_t*)src);
+ SerialPrint(">0x%.4x\n", *(ushort_t*)src);
break;
case 4:
- PrintBoth(">0x%.8x\n", *(uint_t*)src);
+ SerialPrint(">0x%.8x\n", *(uint_t*)src);
break;
default:
break;
memset(&vmm_ops, 0, sizeof(struct vmm_ctrl_ops));
memset(&vm_info, 0, sizeof(struct guest_info));
- os_hooks.print_debug = &PrintBoth;
+ os_hooks.print_debug = &SerialPrint;
os_hooks.print_info = &Print;
os_hooks.print_trace = &SerialPrint;
os_hooks.allocate_pages = &Allocate_VMM_Pages;
//add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x1000, 0x100000);
// add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x100000, 0x0);
- shadow_region_t *ent = Malloc(sizeof(shadow_region_t));;
- init_shadow_region_physical(ent,0,0x100000,GUEST_REGION_PHYSICAL_MEMORY,
- 0x100000, HOST_REGION_PHYSICAL_MEMORY);
- add_shadow_region(&(vm_info.mem_map),ent);
+ /*
+ shadow_region_t *ent = Malloc(sizeof(shadow_region_t));;
+ init_shadow_region_physical(ent,0,0x100000,GUEST_REGION_PHYSICAL_MEMORY,
+ 0x100000, HOST_REGION_PHYSICAL_MEMORY);
+ add_shadow_region(&(vm_info.mem_map),ent);
+ */
+
+ add_shadow_region_passthrough(&vm_info, 0x0, 0x100000, 0x100000);
hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write);
hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial);
/*
- vm_info.cr0 = 0;
- vm_info.cs.base=0xf000;
- vm_info.cs.limit=0xffff;
+ vm_info.cr0 = 0;
+ vm_info.cs.base=0xf000;
+ vm_info.cs.limit=0xffff;
*/
//vm_info.rip = 0xfff0;
vm_info.rip = 0;
vm_info.vm_regs.rsp = 0x0;
} else {
- shadow_region_t *ent = Malloc(sizeof(shadow_region_t));
- /*
- init_shadow_region_physical(ent,0xf0000,0x100000,GUEST_REGION_PHYSICAL_MEMORY,
- 0x100000, HOST_REGION_PHYSICAL_MEMORY);
- add_shadow_region(&(vm_info.mem_map),ent);
- ent = Malloc(sizeof(shadow_region_t));
- */
- void * guest_mem = Allocate_VMM_Pages(256);
+ int i;
+ void * region_start;
+
PrintDebug("Guest Size: %lu\n", bootInfo->guest_size);
- memcpy((void *)(guest_mem + 0xf0000), (void *)0x100000, bootInfo->guest_size);
+ struct guest_mem_layout * layout = (struct guest_mem_layout *)0x100000;
+
+ if (layout->magic != MAGIC_CODE) {
+ PrintDebug("Layout Magic Mismatch (0x%x)\n", layout->magic);
+ }
+
+ PrintDebug("%d layout regions\n", layout->num_regions);
+ region_start = (void *)&(layout->regions[layout->num_regions]);
- SerialMemDump((unsigned char *)(guest_mem + 0xffff0), 16);
+ PrintDebug("region start = 0x%x\n", region_start);
- init_shadow_region_physical(ent, 0x0, 0x100000, GUEST_REGION_PHYSICAL_MEMORY,
- (addr_t)guest_mem, HOST_REGION_PHYSICAL_MEMORY);
- add_shadow_region(&(vm_info.mem_map),ent);
+ for (i = 0; i < layout->num_regions; i++) {
+ struct layout_region * reg = &(layout->regions[i]);
+ uint_t num_pages = (reg->length / PAGE_SIZE) + ((reg->length % PAGE_SIZE) ? 1 : 0);
+ void * guest_mem = Allocate_VMM_Pages(num_pages);
+
+ PrintDebug("Layout Region %d bytes\n", reg->length);
+ memcpy(guest_mem, region_start, reg->length);
+
+ SerialMemDump((unsigned char *)(guest_mem), 16);
+
+ add_shadow_region_passthrough(&vm_info, reg->final_addr, reg->final_addr + (num_pages * PAGE_SIZE), (addr_t)guest_mem);
+
+ PrintDebug("Adding Shadow Region (0x%x-0x%x) -> 0x%x\n", reg->final_addr, reg->final_addr + (num_pages * PAGE_SIZE), guest_mem);
+
+ region_start += reg->length;
+ }
+
+ add_shadow_region_passthrough(&vm_info, 0x0, 0xa0000, (addr_t)Allocate_VMM_Pages(160));
+ add_shadow_region_passthrough(&vm_info, 0xa0000, 0xc0000, 0xa0000);
+ if (add_shadow_region_passthrough(&vm_info, 0xc7000, 0xf0000, (addr_t)Allocate_VMM_Pages(41)) == -1) {
+ PrintDebug("Error adding shadow region\n");
+ }
+
+ print_shadow_map(&(vm_info.mem_map));
hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write);
hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial);
hook_io_port(&(vm_info.io_map), 0xa0, &IO_Read, &IO_Write_to_Serial);
hook_io_port(&(vm_info.io_map), 0xa1, &IO_Read, &IO_Write_to_Serial);
+ hook_io_port(&(vm_info.io_map), 0x400, &IO_Read, &IO_Write_to_Serial);
+ hook_io_port(&(vm_info.io_map), 0x401, &IO_Read, &IO_Write_to_Serial);
+ hook_io_port(&(vm_info.io_map), 0x402, &IO_Read, &IO_BOCHS_debug);
+ hook_io_port(&(vm_info.io_map), 0x403, &IO_Read, &IO_Write_to_Serial);
+
vm_info.rip = 0xfff0;
vm_info.vm_regs.rsp = 0x0;
}
PrintBoth("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", (uint_t)vm_info.rip,(uint_t)vm_info.vm_regs.rsp);
(vmm_ops).init_guest(&vm_info);
PrintBoth("Starting Guest\n");
+ Clear_Screen();
(vmm_ops).start_guest(&vm_info);
return 0;
while (1) {
- PrintDebug("SVM Launch Args (vmcb=%x), (info=%x), (vm_regs=%x)\n", info->vmm_data, &(info->vm_regs));
- PrintDebug("Launching to RIP: %x\n", info->rip);
+ //PrintDebug("SVM Launch Args (vmcb=%x), (info=%x), (vm_regs=%x)\n", info->vmm_data, &(info->vm_regs));
+ //PrintDebug("Launching to RIP: %x\n", info->rip);
safe_svm_launch((vmcb_t*)(info->vmm_data), &(info->vm_regs));
//launch_svm((vmcb_t*)(info->vmm_data));
- PrintDebug("SVM Returned\n");
+ //PrintDebug("SVM Returned\n");
if (handle_svm_exit(info) != 0) {
// handle exit code....
// guest_state->cr0 = 0x00000001; // PE
ctrl_area->guest_ASID = 1;
-
ctrl_area->exceptions.ex_names.de = 1;
ctrl_area->exceptions.ex_names.df = 1;
ctrl_area->exceptions.ex_names.pf = 1;
ctrl_area->exceptions.ex_names.of = 1;
ctrl_area->exceptions.ex_names.nmi = 1;
+ vm_info.vm_regs.rdx = 0x00000f00;
+
+ guest_state->cr0 = 0x60000010;
+
guest_state->cs.selector = 0xf000;
- guest_state->cs.limit=~0u;
- guest_state->cs.base = guest_state->cs.selector<<4;
+ guest_state->cs.limit=0xffff;
+ guest_state->cs.base = 0x0000000f0000LL;
guest_state->cs.attrib.raw = 0xf3;
struct vmcb_selector * seg = segregs[i];
seg->selector = 0x0000;
- seg->base = seg->selector << 4;
+ // seg->base = seg->selector << 4;
+ seg->base = 0x00000000;
seg->attrib.raw = 0xf3;
seg->limit = ~0u;
}
+ guest_state->gdtr.limit = 0x0000ffff;
+ guest_state->gdtr.base = 0x0000000000000000LL;
+ guest_state->idtr.limit = 0x0000ffff;
+ guest_state->idtr.base = 0x0000000000000000LL;
+
+ guest_state->ldtr.selector = 0x0000;
+ guest_state->ldtr.limit = 0x0000ffff;
+ guest_state->ldtr.base = 0x0000000000000000LL;
+ guest_state->tr.selector = 0x0000;
+ guest_state->tr.limit = 0x0000ffff;
+ guest_state->tr.base = 0x0000000000000000LL;
+
+
+ guest_state->dr6 = 0x00000000ffff0ff0LL;
+ guest_state->dr7 = 0x0000000000000400LL;
+
if (vm_info.io_map.num_ports > 0) {
vmm_io_hook_t * iter;
addr_t io_port_bitmap;
ctrl_area->instrs.instrs.IOIO_PROT = 1;
}
- ctrl_area->instrs.instrs.INTR = 1;
+ //ctrl_area->instrs.instrs.INTR = 1;
guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3.r_reg;
- //PrintDebugPageTables((pde32_t*)(vm_info.shdw_pg_state.shadow_cr3.e_reg.low));
+ PrintDebugPageTables((pde32_t*)(vm_info.shdw_pg_state.shadow_cr3.e_reg.low));
ctrl_area->cr_reads.crs.cr3 = 1;
ctrl_area->cr_writes.crs.cr3 = 1;
info->vm_regs.rsp = guest_state->rsp;
- PrintDebug("SVM Returned:(VMCB=%x)\n", info->vmm_data);
- PrintDebug("RIP: %x\n", guest_state->rip);
+
exit_code = guest_ctrl->exit_code;
// PrintDebugVMCB((vmcb_t*)(info->vmm_data));
- PrintDebug("SVM Returned: Exit Code: %x\n",exit_code);
-
- PrintDebug("io_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1));
- PrintDebug("io_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
-
- 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) {
char buf[15];
addr_t host_addr;
+
+ PrintDebug("SVM Returned:(VMCB=%x)\n", info->vmm_data);
+ PrintDebug("RIP: %x\n", guest_state->rip);
+ PrintDebug("RIP Linear: %x\n", rip_addr);
+
+ PrintDebug("SVM Returned: Exit Code: %x\n",exit_code);
+
+ PrintDebug("io_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1));
+ PrintDebug("io_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
+
+ 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 (guest_pa_to_host_pa(info, guest_state->rip, &host_addr) == -1) {
PrintDebug("Could not translate guest_state->rip to host address\n");
return -1;
PrintTraceMemDump(buf, 15);
+ while(1);
+
}
return -1;
}
- PrintDebug("IN on port %d (0x%x)\n", io_info->port, io_info->port);
+ //PrintDebug("IN on port %d (0x%x)\n", io_info->port, io_info->port);
if (io_info->sz8) {
read_size = 1;
return -1;
}
- PrintDebug("INS on port %d (0x%x)\n", io_info->port, io_info->port);
+ //PrintDebug("INS on port %d (0x%x)\n", io_info->port, io_info->port);
if (io_info->sz8) {
read_size = 1;
return -1;
}
- PrintDebug("OUT on port %d (0x%x)\n", io_info->port, io_info->port);
+ //PrintDebug("OUT on port %d (0x%x)\n", io_info->port, io_info->port);
if (io_info->sz8) {
write_size = 1;
return -1;
}
- PrintDebug("OUTS on port %d (0x%x)\n", io_info->port, io_info->port);
+ //PrintDebug("OUTS on port %d (0x%x)\n", io_info->port, io_info->port);
if (io_info->sz8) {
write_size = 1;
entry->next=entry->prev = NULL;
}
-void init_shadow_region_physical(shadow_region_t * entry,
- addr_t guest_addr_start,
- addr_t guest_addr_end,
- guest_region_type_t guest_region_type,
- addr_t host_addr_start,
- host_region_type_t host_region_type)
+int add_shadow_region_passthrough( struct guest_info * guest_info,
+ addr_t guest_addr_start,
+ addr_t guest_addr_end,
+ addr_t host_addr_start)
{
- init_shadow_region(entry, guest_addr_start, guest_addr_end, guest_region_type, host_region_type);
+ shadow_region_t * entry = os_hooks->malloc(sizeof(shadow_region_t));
+
+ init_shadow_region(entry, guest_addr_start, guest_addr_end,
+ GUEST_REGION_PHYSICAL_MEMORY, HOST_REGION_PHYSICAL_MEMORY);
entry->host_addr.phys_addr.host_start = host_addr_start;
+ return add_shadow_region(&(guest_info->mem_map), entry);
}
-
-void init_shadow_map(shadow_map_t * map) {
+
+
+
+void init_shadow_map(struct shadow_map * map) {
map->num_regions = 0;
map->head = NULL;
}
-void free_shadow_map(shadow_map_t * map) {
+void free_shadow_map(struct shadow_map * map) {
shadow_region_t * cursor = map->head;
shadow_region_t * tmp = NULL;
-int add_shadow_region(shadow_map_t * map,
+int add_shadow_region(struct shadow_map * map,
shadow_region_t * region)
{
shadow_region_t * cursor = map->head;
+ PrintDebug("Adding Shadow Region: (0x%x-0x%x)\n", region->guest_start, region->guest_end);
+
if ((!cursor) || (cursor->guest_start >= region->guest_end)) {
region->prev = NULL;
region->next = cursor;
map->num_regions++;
return 0;
- } else if (cursor->next->guest_end < region->guest_start) {
+ } else if (cursor->next->guest_end <= region->guest_start) {
cursor = cursor->next;
} else {
+ PrintDebug("WTF?\n");
// This cannot happen!
// we should panic here
return -1;
}
-int delete_shadow_region(shadow_map_t * map,
+int delete_shadow_region(struct shadow_map * map,
addr_t guest_start,
addr_t guest_end) {
return -1;
-shadow_region_t *get_shadow_region_by_index(shadow_map_t * map,
+shadow_region_t *get_shadow_region_by_index(struct shadow_map * map,
uint_t index) {
shadow_region_t * reg = map->head;
uint_t i = 0;
}
-shadow_region_t * get_shadow_region_by_addr(shadow_map_t * map,
+shadow_region_t * get_shadow_region_by_addr(struct shadow_map * map,
addr_t addr) {
shadow_region_t * reg = map->head;
-host_region_type_t lookup_shadow_map_addr(shadow_map_t * map, addr_t guest_addr, addr_t * host_addr) {
+host_region_type_t lookup_shadow_map_addr(struct shadow_map * map, addr_t guest_addr, addr_t * host_addr) {
shadow_region_t * reg = get_shadow_region_by_addr(map, guest_addr);
if (!reg) {
}
-void print_shadow_map(shadow_map_t * map) {
+void print_shadow_map(struct shadow_map * map) {
shadow_region_t * cur = map->head;
int i = 0;
pde32_t * create_passthrough_pde32_pts(struct guest_info * guest_info) {
ullong_t current_page_addr = 0;
int i, j;
- shadow_map_t * map = &(guest_info->mem_map);
+ struct shadow_map * map = &(guest_info->mem_map);
pde32_t * pde = os_hooks->allocate_pages(1);
int i;
PrintDebug("Page Directory at %p:\n", pde);
- for (i = 0; (i < MAX_PDE32_ENTRIES) && pde[i].present; i++) {
- PrintPDE32((void*)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), &(pde[i]));
+ for (i = 0; (i < MAX_PDE32_ENTRIES); i++) {
+ if ( pde[i].present) {
+ PrintPDE32((void*)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), &(pde[i]));
+ }
}
}
int i;
PrintDebug("Page Table at %p:\n", pte);
- for (i = 0; (i < MAX_PTE32_ENTRIES) && pte[i].present; i++) {
- PrintPTE32(starting_address + (PAGE_SIZE * i), &(pte[i]));
+ for (i = 0; (i < MAX_PTE32_ENTRIES) ; i++) {
+ if (pte[i].present) {
+ PrintPTE32(starting_address + (PAGE_SIZE * i), &(pte[i]));
+ }
}
}
PrintDebug("Dumping the pages starting with the pde page at %p\n", pde);
- for (i = 0; (i < MAX_PDE32_ENTRIES) && pde[i].present; i++) {
- PrintPDE32((void *)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), &(pde[i]));
- PrintPT32((void *)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), (void *)(pde[i].pt_base_addr << PAGE_POWER));
+ for (i = 0; (i < MAX_PDE32_ENTRIES); i++) {
+ if (pde[i].present) {
+ PrintPDE32((void *)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), &(pde[i]));
+ PrintPT32((void *)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), (void *)(pde[i].pt_base_addr << PAGE_POWER));
+ }
}
}