From: Jack Lange Date: Thu, 22 May 2008 03:38:15 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: boot386puppy-26-to-ide~39 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=90b8236597004a37a9d5acb33a1b1f987fe9070c *** empty log message *** --- diff --git a/palacios/include/palacios/svm.h b/palacios/include/palacios/svm.h index 9c0912b..3ede354 100644 --- a/palacios/include/palacios/svm.h +++ b/palacios/include/palacios/svm.h @@ -5,6 +5,8 @@ #include #include +#ifdef __V3VEE__ + #define CPUID_FEATURE_IDS 0x80000001 #define CPUID_FEATURE_IDS_ecx_svm_avail 0x00000004 @@ -53,24 +55,13 @@ #define SVM_HANDLER_ERROR 0x1 #define SVM_HANDLER_HALT 0x2 - +#endif void Init_SVM(struct vmm_ctrl_ops * vmm_ops); int is_svm_capable(); -vmcb_t * Allocate_VMCB(); -void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info); -void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info); -void Init_VMCB_pe(vmcb_t * vmcb, struct guest_info vm_info); - -int init_svm_guest(struct guest_info *info); -int start_svm_guest(struct guest_info * info); - - -inline addr_t get_rip_linear(struct guest_info * info, addr_t rip, addr_t cs_base); - #endif diff --git a/palacios/include/palacios/vmm_time.h b/palacios/include/palacios/vmm_time.h index 2411187..9af1840 100644 --- a/palacios/include/palacios/vmm_time.h +++ b/palacios/include/palacios/vmm_time.h @@ -17,7 +17,7 @@ struct vm_time { ullong_t cached_host_tsc; // The number of cycles pending for notification to the timers - ullong_t pending_cycles; + //ullong_t pending_cycles; // Installed Timers uint_t num_timers; @@ -32,7 +32,7 @@ struct vm_timer_ops { struct vm_timer { void * private_data; - struct vm_timer_ops ops; + struct vm_timer_ops * ops; struct list_head timer_link; }; @@ -47,6 +47,6 @@ int v3_add_timer(struct guest_info * info, struct vm_timer_ops * ops, void * pri int v3_remove_timer(struct guest_info * info, struct vm_timer * timer); -void v3_update_timers(struct guest_info * info); +void v3_update_time(struct guest_info * info, ullong_t cycles); #endif diff --git a/palacios/src/devices/8254.c b/palacios/src/devices/8254.c index b11fb7e..2f589e5 100644 --- a/palacios/src/devices/8254.c +++ b/palacios/src/devices/8254.c @@ -29,56 +29,203 @@ struct channel { channel_op_mode_t op_mode; + + // Time til interrupt trigger - ullong_t ns; - uint_t ctr; - uint_t prg_ctr; + ushort_t counter; + ushort_t reload_value; + + uint_t output_pin : 1; + uint_t gate_input_pin : 1; }; struct pit { + ullong_t pit_counter; + ullong_t pit_reload; + + struct channel ch_0; struct channel ch_1; struct channel ch_2; }; -struct pit_cmd { - uint_t channel : 2; - uint_t access_mode : 2; - uint_t op_mode : 3; + +struct pit_cmd_word { uint_t bcd_mode : 1; + uint_t op_mode : 3; + uint_t access_mode : 2; + uint_t channel : 2; +}; + +struct pit_rdb_cmd_word { + uint_t rsvd : 1; // SBZ + uint_t ch_0 : 1; + uint_t ch_1 : 1; + uint_t ch_2 : 1; + uint_t latch_status : 1; + uint_t latch_count : 1; + uint_t readback_cmd : 2; // Must Be 0x3 }; +struct pit_rdb_status_word { + uint_t bcd_mode : 1; + uint_t op_mode : 3; + uint_t access_mode : 2; + uint_t null_count : 1; + uint_t pin_state : 1; +}; static void pit_update_time(ullong_t cpu_cycles, ullong_t cpu_freq, void * private_data) { - + PrintDebug("Adding %d cycles\n", cpu_cycles); + return; } +static int handle_channel_write(struct channel * ch, char val) { + // switch (ch->access_mode) { + + + //} + + + return -1; +} + + +static int handle_channel_read(struct channel * ch, char * val) { + return -1; +} + + + + + +static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) { + ch->op_mode = cmd.op_mode; + ch->access_mode = cmd.access_mode; + + switch (cmd.access_mode) { + case LATCH_COUNT: + return -1; + break; + case HIBYTE_ONLY: + ch->access_state = WAITING_HIBYTE; + break; + case LOBYTE_ONLY: + case LOBYTE_HIBYTE: + ch->access_state = WAITING_LOBYTE; + break; + } + + + switch (cmd.op_mode) { + case IRQ_ON_TERM_CNT: + ch->output_pin = 0; + break; + case ONE_SHOT: + ch->output_pin = 1; + break; + case RATE_GEN: + ch->output_pin = 1; + break; + default: + return -1; + } + + return 0; + +} + + + static int pit_read_channel(ushort_t port, void * dst, uint_t length, struct vm_device * dev) { + struct pit * state = (struct pit *)dev->private_data; + char * val = (char *)dst; + + if (length != 1) { + PrintDebug("8254 PIT: Invalid Read Write length \n"); + return -1; + } + PrintDebug("8254 PIT: Read of PIT Channel %d\n", port - CHANNEL0_PORT); + + switch (port) { + case CHANNEL0_PORT: + if (handle_channel_read(&(state->ch_0), val) == -1) { + return -1; + } + break; + case CHANNEL1_PORT: + if (handle_channel_read(&(state->ch_1), val) == -1) { + return -1; + } + break; + case CHANNEL2_PORT: + if (handle_channel_read(&(state->ch_2), val) == -1) { + return -1; + } + break; + default: + PrintDebug("8254 PIT: Read from invalid port (%d)\n", port); + return -1; + } + return length; } static int pit_write_channel(ushort_t port, void * src, uint_t length, struct vm_device * dev) { + struct pit * state = (struct pit *)dev->private_data; + char val = *(char *)src; + + if (length != 1) { + PrintDebug("8254 PIT: Invalid Write Length\n"); + return -1; + } + PrintDebug("8254 PIT: Write to PIT Channel %d\n", port - CHANNEL0_PORT); + + + switch (port) { + case CHANNEL0_PORT: + if (handle_channel_write(&(state->ch_0), val) == -1) { + return -1; + } + break; + case CHANNEL1_PORT: + if (handle_channel_write(&(state->ch_1), val) == -1) { + return -1; + } + break; + case CHANNEL2_PORT: + if (handle_channel_write(&(state->ch_2), val) == -1) { + return -1; + } + break; + default: + PrintDebug("8254 PIT: Write to invalid port (%d)\n", port); + return -1; + } + return length; } + + static int pit_write_command(ushort_t port, void * src, uint_t length, struct vm_device * dev) { struct pit * state = (struct pit *)dev->private_data; - struct pit_cmd * cmd = (struct pit_cmd *)src; + struct pit_cmd_word * cmd = (struct pit_cmd_word *)src; PrintDebug("8254 PIT: Write to PIT Command port\n"); @@ -89,11 +236,23 @@ static int pit_write_command(ushort_t port, void * src, uint_t length, struct vm switch (cmd->channel) { case 0: - state->ch_0.op_mode = cmd->op_mode; + if (handle_channel_cmd(&(state->ch_0), *cmd) == -1) { + return -1; + } break; case 1: + if (handle_channel_cmd(&(state->ch_1), *cmd) == -1) { + return -1; + } break; case 2: + if (handle_channel_cmd(&(state->ch_2), *cmd) == -1) { + return -1; + } + break; + case 3: + // Read Back command + return -1; break; default: break; @@ -120,6 +279,9 @@ static int pit_init(struct vm_device * dev) { v3_add_timer(dev->vm, &timer_ops, dev); + // Get cpu frequency and calculate the global pit oscilattor counter/cycle + + return 0; } diff --git a/palacios/src/geekos/vm.c b/palacios/src/geekos/vm.c index 86c9ebf..160be77 100644 --- a/palacios/src/geekos/vm.c +++ b/palacios/src/geekos/vm.c @@ -318,7 +318,7 @@ int RunVMM(struct Boot_Info * bootInfo) { //struct vm_device * timer = create_timer(); struct vm_device * pic = create_pic(); //struct vm_device * keyboard = create_keyboard(); - struct vm_device * pit= create_pit(); + struct vm_device * pit = create_pit(); attach_device(&(vm_info), nvram); //attach_device(&(vm_info), timer); diff --git a/palacios/src/geekos/vmm_stubs.c b/palacios/src/geekos/vmm_stubs.c index c83e6d5..15ae589 100644 --- a/palacios/src/geekos/vmm_stubs.c +++ b/palacios/src/geekos/vmm_stubs.c @@ -133,70 +133,3 @@ unsigned int get_cpu_khz() { return cpu_khz_freq; } - - - -#if 0 - - -/* ------ Calibrate the TSC ------- - * Return processor ticks per second / CALIBRATE_FRAC. - * - * Ported From Xen - */ -#define PIT_MODE 0x43 -#define PIT_CH2 0x42 -#define CLOCK_TICK_RATE 1193180 /* system crystal frequency (Hz) */ -#define CALIBRATE_FRAC 20 /* calibrate over 50ms */ -#define CALIBRATE_LATCH ((CLOCK_TICK_RATE+(CALIBRATE_FRAC/2))/CALIBRATE_FRAC) - - -unsigned long long get_cpu_khz() { - ullong_t start, end; - unsigned long count; - unsigned long long tmp; - unsigned long print_tmp; - - /* Set the Gate high, disable speaker */ - VM_Out_Byte((VM_In_Byte(0x61) & ~0x02) | 0x01, 0x61); - - /* - * Now let's take care of CTC channel 2 - * - * Set the Gate high, program CTC channel 2 for mode 0, (interrupt on - * terminal count mode), binary count, load 5 * LATCH count, (LSB and MSB) - * to begin countdown. - */ - VM_Out_Byte(0xb0, PIT_MODE); /* binary, mode 0, LSB/MSB, Ch 2 */ - VM_Out_Byte(CALIBRATE_LATCH & 0xff, PIT_CH2); /* LSB of count */ - VM_Out_Byte(CALIBRATE_LATCH >> 8, PIT_CH2); /* MSB of count */ - - rdtscll(start); - for ( count = 0; (VM_In_Byte(0x61) & 0x20) == 0; count++ ) - continue; - rdtscll(end); - - /* Error if the CTC doesn't behave itself. */ - if ( count == 0 ) { - PrintBoth("CPU Frequency Calibration Error\n"); - return 0; - } - - tmp = ((end - start) * (ullong_t)CALIBRATE_FRAC); - - do_div(tmp, 1000); - - tmp &= 0xffffffff; - print_tmp = (unsigned long)tmp; - - PrintBoth("Detected %lu.%lu MHz CPU\n", print_tmp / 1000, print_tmp % 1000); - return tmp; -} - -#undef PIT_CH2 -#undef PIT_MODE -#undef CLOCK_TICK_RATE -#undef CALIBRATE_FRAC -#undef CALIBRATE_LATCH - -#endif diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index e62f5a7..cbed250 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -29,76 +29,182 @@ extern uint_t Get_CR3(); extern void DisableInts(); -/* Checks machine SVM capability */ -/* Implemented from: AMD Arch Manual 3, sect 15.4 */ -int is_svm_capable() { - uint_t ret = cpuid_ecx(CPUID_FEATURE_IDS); - uint_t vm_cr_low = 0, vm_cr_high = 0; - if ((ret & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) { - PrintDebug("SVM Not Available\n"); - return 0; - } - Get_MSR(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low); - if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 1) { - PrintDebug("Nested Paging not supported\n"); - } - if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 0) { - return 1; - } - ret = cpuid_edx(CPUID_SVM_REV_AND_FEATURE_IDS); +static vmcb_t * Allocate_VMCB() { + vmcb_t * vmcb_page = (vmcb_t*)os_hooks->allocate_pages(1); - if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) { - PrintDebug("SVM BIOS Disabled, not unlockable\n"); - } else { - PrintDebug("SVM is locked with a key\n"); - } - return 0; + memset(vmcb_page, 0, 4096); + + return vmcb_page; } -void Init_SVM(struct vmm_ctrl_ops * vmm_ops) { - reg_ex_t msr; - void * host_state; - // Enable SVM on the CPU - Get_MSR(EFER_MSR, &(msr.e_reg.high), &(msr.e_reg.low)); - msr.e_reg.low |= EFER_MSR_svm_enable; - Set_MSR(EFER_MSR, 0, msr.e_reg.low); - - PrintDebug("SVM Enabled\n"); +static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { + vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb); + vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb); + uint_t i; - // Setup the host state save area - host_state = os_hooks->allocate_pages(4); + guest_state->rsp = vm_info.vm_regs.rsp; + // guest_state->rip = vm_info.rip; + guest_state->rip = 0xfff0; + + guest_state->cpl = 0; + + //ctrl_area->instrs.instrs.CR0 = 1; + ctrl_area->cr_reads.cr0 = 1; + ctrl_area->cr_writes.cr0 = 1; + + guest_state->efer |= EFER_MSR_svm_enable; + guest_state->rflags = 0x00000002; // The reserved bit is always 1 + ctrl_area->svm_instrs.VMRUN = 1; + ctrl_area->instrs.HLT = 1; + // guest_state->cr0 = 0x00000001; // PE + ctrl_area->guest_ASID = 1; + + ctrl_area->exceptions.de = 1; + ctrl_area->exceptions.df = 1; + ctrl_area->exceptions.pf = 1; + ctrl_area->exceptions.ts = 1; + ctrl_area->exceptions.ss = 1; + ctrl_area->exceptions.ac = 1; + ctrl_area->exceptions.mc = 1; + ctrl_area->exceptions.gp = 1; + ctrl_area->exceptions.ud = 1; + ctrl_area->exceptions.np = 1; + ctrl_area->exceptions.of = 1; + ctrl_area->exceptions.nmi = 1; + + vm_info.vm_regs.rdx = 0x00000f00; + + guest_state->cr0 = 0x60000010; + + guest_state->cs.selector = 0xf000; + guest_state->cs.limit=0xffff; + guest_state->cs.base = 0x0000000f0000LL; + guest_state->cs.attrib.raw = 0xf3; + - msr.e_reg.high = 0; - msr.e_reg.low = (uint_t)host_state; + struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL}; + for ( i = 0; segregs[i] != NULL; i++) { + struct vmcb_selector * seg = segregs[i]; + + seg->selector = 0x0000; + // 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; - PrintDebug("Host State being saved at %x\n", (uint_t)host_state); - Set_MSR(SVM_VM_HSAVE_PA_MSR, msr.e_reg.high, msr.e_reg.low); + 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; + + io_port_bitmap = (addr_t)os_hooks->allocate_pages(3); + memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3); + + ctrl_area->IOPM_BASE_PA = io_port_bitmap; + //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap); + + FOREACH_IO_HOOK(vm_info.io_map, iter) { + ushort_t port = iter->port; + uchar_t * bitmap = (uchar_t *)io_port_bitmap; + + bitmap += (port / 8); + PrintDebug("Setting Bit for port 0x%x\n", port); + *bitmap |= 1 << (port % 8); + } + + + //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2); + + ctrl_area->instrs.IOIO_PROT = 1; + } + + + + PrintDebug("Exiting on interrupts\n"); + ctrl_area->guest_ctrl.V_INTR_MASKING = 1; + ctrl_area->instrs.INTR = 1; + + + if (vm_info.page_mode == SHADOW_PAGING) { + PrintDebug("Creating initial shadow page table\n"); + vm_info.shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff); + PrintDebug("Created\n"); + + guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3; + + //PrintDebugPageTables((pde32_t*)(vm_info.shdw_pg_state.shadow_cr3.e_reg.low)); + + ctrl_area->cr_reads.cr3 = 1; + ctrl_area->cr_writes.cr3 = 1; + + + ctrl_area->instrs.INVLPG = 1; + ctrl_area->instrs.INVLPGA = 1; + + guest_state->g_pat = 0x7040600070406ULL; + + guest_state->cr0 |= 0x80000000; + } else if (vm_info.page_mode == NESTED_PAGING) { + // Flush the TLB on entries/exits + //ctrl_area->TLB_CONTROL = 1; + + // Enable Nested Paging + //ctrl_area->NP_ENABLE = 1; + + //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE)); + + // Set the Nested Page Table pointer + // ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables); + // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables); + + // ctrl_area->N_CR3 = Get_CR3(); + // guest_state->cr3 |= (Get_CR3() & 0xfffff000); + + // guest_state->g_pat = 0x7040600070406ULL; + } - // Setup the SVM specific vmm operations - vmm_ops->init_guest = &init_svm_guest; - vmm_ops->start_guest = &start_svm_guest; - return; } -int init_svm_guest(struct guest_info *info) { + + + + + + + +static int init_svm_guest(struct guest_info *info) { PrintDebug("Allocating VMCB\n"); info->vmm_data = (void*)Allocate_VMCB(); @@ -131,7 +237,7 @@ int init_svm_guest(struct guest_info *info) { // can we start a kernel thread here... -int start_svm_guest(struct guest_info *info) { +static int start_svm_guest(struct guest_info *info) { vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data)); vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data)); @@ -141,18 +247,19 @@ int start_svm_guest(struct guest_info *info) { while (1) { ullong_t tmp_tsc; + CLGI(); rdtscll(info->time_state.cached_host_tsc); guest_ctrl->TSC_OFFSET = info->time_state.guest_tsc - info->time_state.cached_host_tsc; - //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"); + rdtscll(tmp_tsc); - info->time_state.guest_tsc += tmp_tsc - info->time_state.cached_host_tsc; - + + //PrintDebug("SVM Returned\n"); + + v3_update_time(info, tmp_tsc - info->time_state.cached_host_tsc); STGI(); @@ -188,150 +295,135 @@ int start_svm_guest(struct guest_info *info) { -vmcb_t * Allocate_VMCB() { - vmcb_t * vmcb_page = (vmcb_t*)os_hooks->allocate_pages(1); - - memset(vmcb_page, 0, 4096); +/* Checks machine SVM capability */ +/* Implemented from: AMD Arch Manual 3, sect 15.4 */ +int is_svm_capable() { + uint_t ret = cpuid_ecx(CPUID_FEATURE_IDS); + uint_t vm_cr_low = 0, vm_cr_high = 0; - return vmcb_page; -} + if ((ret & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) { + PrintDebug("SVM Not Available\n"); + return 0; + } + Get_MSR(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low); -void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info) { - vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb); - vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb); - uint_t i; + if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 1) { + PrintDebug("Nested Paging not supported\n"); + } + if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 0) { + return 1; + } - guest_state->rsp = vm_info.vm_regs.rsp; - guest_state->rip = vm_info.rip; + ret = cpuid_edx(CPUID_SVM_REV_AND_FEATURE_IDS); + if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) { + PrintDebug("SVM BIOS Disabled, not unlockable\n"); + } else { + PrintDebug("SVM is locked with a key\n"); + } - //ctrl_area->instrs.instrs.CR0 = 1; - ctrl_area->cr_reads.cr0 = 1; - ctrl_area->cr_writes.cr0 = 1; + return 0; +} - guest_state->efer |= EFER_MSR_svm_enable; - guest_state->rflags = 0x00000002; // The reserved bit is always 1 - ctrl_area->svm_instrs.VMRUN = 1; - // guest_state->cr0 = 0x00000001; // PE - ctrl_area->guest_ASID = 1; - ctrl_area->exceptions.de = 1; - ctrl_area->exceptions.df = 1; - ctrl_area->exceptions.pf = 1; - ctrl_area->exceptions.ts = 1; - ctrl_area->exceptions.ss = 1; - ctrl_area->exceptions.ac = 1; - ctrl_area->exceptions.mc = 1; - ctrl_area->exceptions.gp = 1; - ctrl_area->exceptions.ud = 1; - ctrl_area->exceptions.np = 1; - ctrl_area->exceptions.of = 1; - ctrl_area->exceptions.nmi = 1; +void Init_SVM(struct vmm_ctrl_ops * vmm_ops) { + reg_ex_t msr; + void * host_state; - guest_state->cs.selector = 0x0000; - guest_state->cs.limit=~0u; - guest_state->cs.base = guest_state->cs.selector<<4; - guest_state->cs.attrib.raw = 0xf3; + // Enable SVM on the CPU + Get_MSR(EFER_MSR, &(msr.e_reg.high), &(msr.e_reg.low)); + msr.e_reg.low |= EFER_MSR_svm_enable; + Set_MSR(EFER_MSR, 0, msr.e_reg.low); - struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL}; - for ( i = 0; segregs[i] != NULL; i++) { - struct vmcb_selector * seg = segregs[i]; - - seg->selector = 0x0000; - seg->base = seg->selector << 4; - seg->attrib.raw = 0xf3; - seg->limit = ~0u; - } + PrintDebug("SVM Enabled\n"); + + + // Setup the host state save area + host_state = os_hooks->allocate_pages(4); - if (vm_info.io_map.num_ports > 0) { - vmm_io_hook_t * iter; - addr_t io_port_bitmap; - - io_port_bitmap = (addr_t)os_hooks->allocate_pages(3); - memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3); - - ctrl_area->IOPM_BASE_PA = io_port_bitmap; + msr.e_reg.high = 0; + msr.e_reg.low = (uint_t)host_state; - //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap); - FOREACH_IO_HOOK(vm_info.io_map, iter) { - ushort_t port = iter->port; - uchar_t * bitmap = (uchar_t *)io_port_bitmap; + PrintDebug("Host State being saved at %x\n", (uint_t)host_state); + Set_MSR(SVM_VM_HSAVE_PA_MSR, msr.e_reg.high, msr.e_reg.low); - bitmap += (port / 8); - PrintDebug("Setting Bit in block %x\n", bitmap); - *bitmap |= 1 << (port % 8); - } - //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2); + // Setup the SVM specific vmm operations + vmm_ops->init_guest = &init_svm_guest; + vmm_ops->start_guest = &start_svm_guest; - ctrl_area->instrs.IOIO_PROT = 1; - } - ctrl_area->instrs.INTR = 1; + return; +} + - if (vm_info.page_mode == SHADOW_PAGING) { - PrintDebug("Creating initial shadow page table\n"); - vm_info.shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff); - PrintDebug("Created\n"); - guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3; - ctrl_area->cr_reads.cr3 = 1; - ctrl_area->cr_writes.cr3 = 1; - ctrl_area->instrs.INVLPG = 1; - ctrl_area->instrs.INVLPGA = 1; - guest_state->g_pat = 0x7040600070406ULL; - guest_state->cr0 |= 0x80000000; - } else if (vm_info.page_mode == NESTED_PAGING) { - // Flush the TLB on entries/exits - //ctrl_area->TLB_CONTROL = 1; - // Enable Nested Paging - //ctrl_area->NP_ENABLE = 1; - //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE)); - // Set the Nested Page Table pointer - // ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables); - // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables); - // ctrl_area->N_CR3 = Get_CR3(); - // guest_state->cr3 |= (Get_CR3() & 0xfffff000); - // guest_state->g_pat = 0x7040600070406ULL; - } -} -void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/*static void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info) { vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb); vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb); uint_t i; guest_state->rsp = vm_info.vm_regs.rsp; - // guest_state->rip = vm_info.rip; - guest_state->rip = 0xfff0; + guest_state->rip = vm_info.rip; - guest_state->cpl = 0; //ctrl_area->instrs.instrs.CR0 = 1; ctrl_area->cr_reads.cr0 = 1; @@ -340,10 +432,10 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { guest_state->efer |= EFER_MSR_svm_enable; guest_state->rflags = 0x00000002; // The reserved bit is always 1 ctrl_area->svm_instrs.VMRUN = 1; - ctrl_area->instrs.HLT = 1; // guest_state->cr0 = 0x00000001; // PE ctrl_area->guest_ASID = 1; + ctrl_area->exceptions.de = 1; ctrl_area->exceptions.df = 1; ctrl_area->exceptions.pf = 1; @@ -357,13 +449,9 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { ctrl_area->exceptions.of = 1; ctrl_area->exceptions.nmi = 1; - vm_info.vm_regs.rdx = 0x00000f00; - - guest_state->cr0 = 0x60000010; - - guest_state->cs.selector = 0xf000; - guest_state->cs.limit=0xffff; - guest_state->cs.base = 0x0000000f0000LL; + guest_state->cs.selector = 0x0000; + guest_state->cs.limit=~0u; + guest_state->cs.base = guest_state->cs.selector<<4; guest_state->cs.attrib.raw = 0xf3; @@ -372,28 +460,11 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { struct vmcb_selector * seg = segregs[i]; seg->selector = 0x0000; - // seg->base = seg->selector << 4; - seg->base = 0x00000000; + seg->base = seg->selector << 4; 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; @@ -410,7 +481,7 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { uchar_t * bitmap = (uchar_t *)io_port_bitmap; bitmap += (port / 8); - PrintDebug("Setting Bit for port 0x%x\n", port); + PrintDebug("Setting Bit in block %x\n", bitmap); *bitmap |= 1 << (port % 8); } @@ -420,13 +491,10 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { ctrl_area->instrs.IOIO_PROT = 1; } - - - PrintDebug("Exiting on interrupts\n"); - ctrl_area->guest_ctrl.V_INTR_MASKING = 1; ctrl_area->instrs.INTR = 1; + if (vm_info.page_mode == SHADOW_PAGING) { PrintDebug("Creating initial shadow page table\n"); vm_info.shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff); @@ -434,8 +502,6 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3; - //PrintDebugPageTables((pde32_t*)(vm_info.shdw_pg_state.shadow_cr3.e_reg.low)); - ctrl_area->cr_reads.cr3 = 1; ctrl_area->cr_writes.cr3 = 1; @@ -468,6 +534,12 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { } +*/ + + + + + #if 0 @@ -637,157 +709,3 @@ void Init_VMCB_pe(vmcb_t *vmcb, struct guest_info vm_info) { #endif - - - - - - - - - - - - -/* - - -void Init_VMCB_Real(vmcb_t * vmcb, struct guest_info vm_info) { - vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb); - vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb); - uint_t i; - - - guest_state->rsp = vm_info.vm_regs.rsp; - 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; - ctrl_area->guest_ASID = 1; - guest_state->cr0 = 0x60000010; - - - ctrl_area->exceptions.de = 1; - ctrl_area->exceptions.df = 1; - ctrl_area->exceptions.pf = 1; - ctrl_area->exceptions.ts = 1; - ctrl_area->exceptions.ss = 1; - ctrl_area->exceptions.ac = 1; - ctrl_area->exceptions.mc = 1; - ctrl_area->exceptions.gp = 1; - ctrl_area->exceptions.ud = 1; - ctrl_area->exceptions.np = 1; - ctrl_area->exceptions.of = 1; - ctrl_area->exceptions.nmi = 1; - - guest_state->cs.selector = 0xf000; - guest_state->cs.limit=0xffff; - guest_state->cs.base = 0xffff0000; - guest_state->cs.attrib.raw = 0x9a; - - - struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL}; - for ( i = 0; segregs[i] != NULL; i++) { - struct vmcb_selector * seg = segregs[i]; - - seg->selector = 0x0000; - seg->base = 0xffff0000; - seg->attrib.raw = 0x9b; - seg->limit = 0xffff; - } - - // Set GPRs - // - // EDX == 0xfxx - // EAX, EBX, ECX, ESI, EDI, EBP, ESP == 0x0 - // - - guest_state->gdtr.base = 0; - guest_state->gdtr.limit = 0xffff; - guest_state->gdtr.attrib.raw = 0x0; - - guest_state->idtr.base = 0; - guest_state->idtr.limit = 0xffff; - guest_state->idtr.attrib.raw = 0x0; - - guest_state->ldtr.base = 0; - guest_state->ldtr.limit = 0xffff; - guest_state->ldtr.attrib.raw = 0x82; - - guest_state->tr.base = 0; - guest_state->tr.limit = 0xffff; - guest_state->tr.attrib.raw = 0x83; - - - - - if (vm_info.io_map.num_ports > 0) { - vmm_io_hook_t * iter; - addr_t io_port_bitmap; - - io_port_bitmap = (addr_t)os_hooks->allocate_pages(3); - memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3); - - ctrl_area->IOPM_BASE_PA = io_port_bitmap; - - //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap); - - FOREACH_IO_HOOK(vm_info.io_map, iter) { - ushort_t port = iter->port; - uchar_t * bitmap = (uchar_t *)io_port_bitmap; - - bitmap += (port / 8); - PrintDebug("Setting Bit in block %x\n", bitmap); - *bitmap |= 1 << (port % 8); - } - - ctrl_area->instrs.instrs.IOIO_PROT = 1; - } - - ctrl_area->instrs.instrs.INTR = 1; - - // also determine if CPU supports nested paging - - if (vm_info.page_mode == SHADOW_PAGING) { - PrintDebug("Creating initial shadow page table\n"); - vm_info.shdw_pg_state.shadow_cr3.e_reg.low |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff); - PrintDebug("Created\n"); - - guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3.r_reg; - - ctrl_area->cr_reads.crs.cr3 = 1; - ctrl_area->cr_writes.crs.cr3 = 1; - ctrl_area->cr_reads.crs.cr0 = 1; - ctrl_area->cr_writes.crs.cr0 = 1; - - ctrl_area->instrs.instrs.INVLPG = 1; - ctrl_area->instrs.instrs.INVLPGA = 1; - - - 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 - //ctrl_area->TLB_CONTROL = 1; - - // Enable Nested Paging - //ctrl_area->NP_ENABLE = 1; - - //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE)); - - // Set the Nested Page Table pointer - // ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables); - // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables); - - // ctrl_area->N_CR3 = Get_CR3(); - // guest_state->cr3 |= (Get_CR3() & 0xfffff000); - - // guest_state->g_pat = 0x7040600070406ULL; - } - -} -*/ diff --git a/palacios/src/palacios/vmm_time.c b/palacios/src/palacios/vmm_time.c index 027236d..a7cd626 100644 --- a/palacios/src/palacios/vmm_time.c +++ b/palacios/src/palacios/vmm_time.c @@ -12,7 +12,7 @@ void v3_init_time(struct vm_time * time_state) { time_state->guest_tsc = 0; time_state->cached_host_tsc = 0; - time_state->pending_cycles = 0; + // time_state->pending_cycles = 0; INIT_LIST_HEAD(&(time_state->timers)); time_state->num_timers = 0; @@ -20,30 +20,40 @@ void v3_init_time(struct vm_time * time_state) { int v3_add_timer(struct guest_info * info, struct vm_timer_ops * ops, void * private_data) { - // V3_Malloc + struct vm_timer * timer = NULL; + timer = (struct vm_timer *)V3_Malloc(sizeof(struct vm_timer)); + V3_ASSERT(timer != NULL); + + timer->ops = ops; + timer->private_data = private_data; - /* list_add(&(timer->timer_link), &(info->time_state.timers)); info->time_state.num_timers++; - */ + return 0; } -int remove_timer(struct guest_info * info, struct vm_timer * timer) { + +int v3_remove_timer(struct guest_info * info, struct vm_timer * timer) { list_del(&(timer->timer_link)); info->time_state.num_timers--; + V3_Free(timer); return 0; } -void update_timers(struct guest_info * info) { + +void v3_update_time(struct guest_info * info, ullong_t cycles) { struct vm_timer * tmp_timer; + info->time_state.guest_tsc += cycles; + list_for_each_entry(tmp_timer, &(info->time_state.timers), timer_link) { - tmp_timer->ops.update_time(info->time_state.pending_cycles, info->time_state.cpu_freq, tmp_timer->private_data); + tmp_timer->ops->update_time(cycles, info->time_state.cpu_freq, tmp_timer->private_data); } + - info->time_state.pending_cycles = 0; + //info->time_state.pending_cycles = 0; }