Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added symbiotic interface and a number of other small changes
Jack Lange [Wed, 23 Sep 2009 22:27:50 +0000 (17:27 -0500)]
16 files changed:
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmm_lowlevel.h
palacios/include/palacios/vmm_sym_iface.h
palacios/src/devices/keyboard.c
palacios/src/devices/piix3.c
palacios/src/palacios/svm_handler.c
palacios/src/palacios/svm_msr.c
palacios/src/palacios/vm_guest.c
palacios/src/palacios/vmm_config.c
palacios/src/palacios/vmm_cpuid.c
palacios/src/palacios/vmm_msr.c
palacios/src/palacios/vmm_shadow_paging_64.h
palacios/src/palacios/vmm_sym_iface.c
palacios/src/palacios/vmx_ctrl_regs.c
palacios/src/palacios/vmx_handler.c
test/geekos_test_vm/src/geekos/main.c

index 86a1cc4..d8444a6 100644 (file)
@@ -34,7 +34,7 @@
 #include <palacios/vmm_msr.h>
 #include <palacios/vmm_hypercall.h>
 #include <palacios/vmm_cpuid.h>
-#include <palacios/vmm_sym_iface.h>
+
 
 #ifdef CONFIG_TELEMETRY
 #include <palacios/vmm_telemetry.h>
@@ -45,6 +45,9 @@
 #endif
 
 
+
+
+
 struct v3_gprs {
     v3_reg_t rdi;
     v3_reg_t rsi;
@@ -116,6 +119,11 @@ struct v3_segments {
     struct v3_segment tr;
 };
 
+
+#ifdef CONFIG_SYMBIOTIC
+#include <palacios/vmm_sym_iface.h>
+#endif
+
 struct shadow_page_state;
 struct v3_intr_state;
 
@@ -127,6 +135,9 @@ struct v3_telemetry;
 struct v3_sym_swap_state;
 #endif
 
+#ifdef CONFIG_SYMBIOTIC
+struct v3_sym_state;
+#endif
 
 struct guest_info {
     uint64_t rip;
@@ -157,9 +168,10 @@ struct guest_info {
 
     struct v3_cpuid_map cpuid_map;
 
+#ifdef CONFIG_SYMBIOTIC
     // Symbiotic state
     struct v3_sym_state sym_state;
-
+#endif
 
     v3_hypercall_map_t hcall_map;
 
@@ -211,6 +223,8 @@ v3_mem_mode_t v3_get_vm_mem_mode(struct guest_info * info);
 const uchar_t * v3_cpu_mode_to_str(v3_cpu_mode_t mode);
 const uchar_t * v3_mem_mode_to_str(v3_mem_mode_t mode);
 
+int v3_translate_segment(struct guest_info * info, uint16_t selector, struct v3_segment * seg);
+
 
 void v3_print_guest_state(struct guest_info * info);
 
index f3c8db5..331a307 100644 (file)
 #define CPUID_FEATURE_IDS 0x00000001
 #define CPUID_EXT_FEATURE_IDS 0x80000001
 
+struct seg_selector {
+    union {
+       uint16_t value;
+       struct {
+           uint8_t rpl     : 2;
+           uint8_t ti      : 1;
+           uint16_t si     : 13;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+struct gen_segment {
+    uint16_t limit_lo;
+    uint32_t base_lo     : 24;
+    uint8_t type         : 4;
+    uint8_t system       : 1;
+    uint8_t dpl          : 2;
+    uint8_t present      : 1;
+    uint8_t limit_hi     : 4;
+    uint8_t avail        : 1;
+    uint8_t long_mode    : 1;
+    uint8_t db           : 1;
+    uint8_t granularity  : 1;
+    uint8_t base_hi      : 8;
+} __attribute__((packed));
+
+struct sys_segment64 {
+    uint16_t limit_lo;
+    uint32_t base_lo     : 24;
+    uint8_t type         : 4;
+    uint8_t rsvd0        : 1;
+    uint8_t dpl          : 2;
+    uint8_t present      : 1;
+    uint8_t limit_hi     : 4;
+    uint8_t avail        : 1;
+    uint8_t rsvd1        : 3;
+    uint8_t granularity  : 1;
+    uint64_t base_hi     : 40;
+    uint32_t rsvd2;
+} __attribute__((packed));
+
 
 
 static void __inline__ v3_cpuid(uint32_t target, 
index 5fcb69a..94b47ec 100644 (file)
@@ -23,7 +23,7 @@
 
 #ifdef __V3VEE__
 
-
+#include <palacios/vm_guest.h>
 
 
 
@@ -34,35 +34,100 @@ struct v3_sym_interface {
     union {
        uint32_t feature_flags;
        struct {
-           uint_t cur_proc_valid         : 1;
-           uint_t proc_list_valid        : 1;
+           uint_t pci_map_valid          : 1;
+           uint32_t sym_call_enabled       : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+
+    union { 
+       uint32_t state_flags;
+       struct {
+           uint32_t sym_call_active        : 1;
        } __attribute__((packed));
     } __attribute__((packed));
 
-    addr_t current_proc;
-    addr_t proc_list;
+    uint64_t current_proc;
+    uint64_t proc_list;
+    
+    uint8_t pci_pt_map[(4 * 256) / 8]; // we're hardcoding this: (4 busses, 256 max devs)
+
+
+    uint64_t sym_call_rip;
+    uint64_t sym_call_cs;
+    uint64_t sym_call_rsp;
+    uint64_t sym_call_gs;
+    uint64_t sym_call_ret_fn;
 
-    uint8_t pci_pt_map[256 / 8];
 } __attribute__((packed));
 
 
+
+
+struct v3_sym_context {
+    struct v3_gprs vm_regs;
+    struct v3_segment cs;
+    struct v3_segment ss;
+    uint64_t gs_base;
+    uint64_t fs_base;
+    uint64_t rip;
+    uint8_t cpl;
+};
+
+
+
 struct v3_sym_state {
     
     struct v3_sym_interface * sym_page;
     addr_t sym_page_pa;
 
-    uint_t active;
     uint64_t guest_pg_addr;
 
+    struct {
+       uint_t active              : 1;
+       uint_t call_pending        : 1;
+       uint_t call_active         : 1;
+    } __attribute__((packed));
+
+    struct v3_sym_context old_ctx;
+    uint64_t args[6];
+    int (*notifier)(struct guest_info * info, void * private_data);
+
+    void * private_data;
+
 };
 
 int v3_init_sym_iface(struct guest_info * info);
 
 
+
+#define v3_sym_call0(info, call_num, cb, priv)         \
+    v3_sym_call(info, call_num, 0, 0, 0, 0, 0, cb, priv)
+#define v3_sym_call1(info, call_num, arg1, cb, priv)           \
+    v3_sym_call(info, call_num, arg1, 0, 0, 0, 0, cb, priv)
+#define v3_sym_call2(info, call_num, arg1, arg2, cb, priv)     \
+    v3_sym_call(info, call_num, arg1, arg2, 0, 0, 0, cb, priv)
+#define v3_sym_call3(info, call_num, arg1, arg2, arg3, cb, priv)       \
+    v3_sym_call(info, call_num, arg1, arg2, arg3, 0, 0, cb, priv)
+#define v3_sym_call4(info, call_num, arg1, arg2, arg3, arg4, cb, priv) \
+    v3_sym_call(info, call_num, arg1, arg2, arg3, arg4, 0, cb, priv)
+#define v3_sym_call5(info, call_num, arg1, arg2, arg3, arg4, arg5, cb, priv)   \
+    v3_sym_call(info, call_num, arg1, arg2, arg3, arg4, arg5, cb, priv)
+
+
+
+
 int v3_sym_map_pci_passthrough(struct guest_info * info, uint_t bus, uint_t dev, uint_t fn);
 int v3_sym_unmap_pci_passthrough(struct guest_info * info, uint_t bus, uint_t dev, uint_t fn);
 
 
+int v3_sym_call(struct guest_info * info, 
+               uint64_t arg0, uint64_t arg1, 
+               uint64_t arg2, uint64_t arg3,
+               uint64_t arg4, uint64_t arg5, 
+               int (*notifier)(struct guest_info * info, void * private_data),
+               void * private_data);
+
+int v3_activate_sym_call(struct guest_info * info);
 
 #endif
 
index e9fff1f..c50374a 100644 (file)
@@ -327,6 +327,9 @@ static int key_event_handler(struct guest_info * info,
     if (evt->scan_code == 0x44) { // F10 debug dump
        v3_print_guest_state(info);
        //      PrintGuestPageTables(info, info->shdw_pg_state.guest_cr3);
+    } else if (evt->scan_code == 0x43) { // F9 Sym test
+       PrintDebug("Testing sym call\n");
+       v3_sym_call0(info, 0, NULL, NULL);
     }
 
     addr_t irq_state = v3_lock_irqsave(state->kb_lock);
index 9a69ed0..44a00ed 100644 (file)
@@ -367,7 +367,7 @@ static int raise_pci_irq(struct vm_device * dev, struct pci_device * pci_dev) {
     int intr_pin = pci_dev->config_header.intr_pin - 1;
     int irq_index = (intr_pin + pci_dev->dev_num - 1) & 0x3;
     
-        PrintError("Raising PCI IRQ %d\n", piix3_cfg->pirq_rc[irq_index]);
+    //        PrintError("Raising PCI IRQ %d\n", piix3_cfg->pirq_rc[irq_index]);
     
     v3_raise_irq(dev->vm, piix3_cfg->pirq_rc[irq_index]);
 
index 4c4aa2c..1c64657 100644 (file)
 #include <palacios/vmm_cpuid.h>
 #include <palacios/vmm_direct_paging.h>
 
+#ifdef CONFIG_SYMBIOTIC
+#include <palacios/vmm_sym_iface.h>
+#endif
+
 #ifdef CONFIG_TELEMETRY
 #include <palacios/vmm_telemetry.h>
 #endif
@@ -43,7 +47,12 @@ int v3_handle_svm_exit(struct guest_info * info) {
     vmcb_ctrl_t * guest_ctrl = 0;
     vmcb_saved_state_t * guest_state = 0;
     ulong_t exit_code = 0;
-    
+
+#ifdef CONFIG_SYMBIOTIC
+    static int sym_started = 0;
+#endif
+
+
     guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
     guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
   
@@ -70,8 +79,21 @@ int v3_handle_svm_exit(struct guest_info * info) {
 
     exit_code = guest_ctrl->exit_code;
 
-    //    PrintDebug("SVM Exit: %s (rip=%p) (info1=%p)\n", vmexit_code_to_str(exit_code), 
-    //        (void *)(addr_t)info->rip, (void *)(addr_t)guest_ctrl->exit_info1);
+
+
+#ifdef CONFIG_SYMBIOTIC
+    if (0) {
+       // ignore interrupt injection if we just started a symcall
+       PrintDebug("SVM Exit: %s (rip=%p) (info1=%p) (info2=%p)\n", vmexit_code_to_str(exit_code), 
+                  (void *)(addr_t)info->rip, (void *)(addr_t)guest_ctrl->exit_info1,
+                  (void *)(addr_t)guest_ctrl->exit_info2);
+       if (exit_code == VMEXIT_EXCP14) {
+           PrintGuestPageTree(info, guest_ctrl->exit_info2, info->shdw_pg_state.guest_cr3);
+       }
+
+    }
+#endif
+
 
     if ((info->intr_state.irq_pending == 1) && (guest_ctrl->guest_ctrl.V_IRQ == 0)) {
 
@@ -186,6 +208,7 @@ int v3_handle_svm_exit(struct guest_info * info) {
            if (v3_handle_cr3_write(info) == -1) {
                return -1;
            }    
+
            break;
        case  VMEXIT_CR3_READ: 
 #ifdef CONFIG_DEBUG_CTRL_REGS
@@ -256,13 +279,15 @@ int v3_handle_svm_exit(struct guest_info * info) {
            /* 
             * Hypercall 
             */
-               
+
+           // VMMCALL is a 3 byte op
+           // We do this early because some hypercalls can change the rip...
+           info->rip += 3;         
+
            if (v3_handle_hypercall(info) == -1) {
                return -1;
            }
-               
-           // VMMCALL is a 3 byte op
-           info->rip += 3;
+           
            break;          
        case VMEXIT_INTR:
            // handled by interrupt dispatch earlier
@@ -279,7 +304,7 @@ int v3_handle_svm_exit(struct guest_info * info) {
            }
            break;
        case VMEXIT_PAUSE:
-           //PrintDebug("Guest paused\n");
+           PrintDebug("Guest paused\n");
            if (v3_handle_svm_pause(info) == -1) { 
                return -1;
            }
@@ -339,6 +364,32 @@ int v3_handle_svm_exit(struct guest_info * info) {
 #endif
 
 
+
+#ifdef CONFIG_SYMBIOTIC
+    v3_activate_sym_call(info);
+#endif
+
+    guest_state->cr0 = info->ctrl_regs.cr0;
+    guest_state->cr2 = info->ctrl_regs.cr2;
+    guest_state->cr3 = info->ctrl_regs.cr3;
+    guest_state->cr4 = info->ctrl_regs.cr4;
+    guest_state->dr6 = info->dbg_regs.dr6;
+    guest_state->dr7 = info->dbg_regs.dr7;
+    guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff;
+    guest_state->rflags = info->ctrl_regs.rflags;
+    guest_state->efer = info->ctrl_regs.efer;
+    
+    guest_state->cpl = info->cpl;
+
+    v3_set_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
+
+    guest_state->rax = info->vm_regs.rax;
+    guest_state->rip = info->rip;
+    guest_state->rsp = info->vm_regs.rsp;
+
+
+
+
     if (v3_excp_pending(info)) {
        uint_t excp = v3_get_excp_number(info);
        
@@ -355,12 +406,27 @@ int v3_handle_svm_exit(struct guest_info * info) {
        guest_ctrl->EVENTINJ.vector = excp;
        
        guest_ctrl->EVENTINJ.valid = 1;
+
+       PrintDebug("Injecting Exception %d (EIP=%p)\n", 
+                  guest_ctrl->EVENTINJ.vector, 
+                  (void *)(addr_t)info->rip);
+
+
+
 #ifdef CONFIG_DEBUG_INTERRUPTS
        PrintDebug("Injecting Exception %d (EIP=%p)\n", 
                   guest_ctrl->EVENTINJ.vector, 
                   (void *)(addr_t)info->rip);
 #endif
        v3_injecting_excp(info, excp);
+
+#ifdef CONFIG_SYMBIOTIC
+    } else if (info->sym_state.call_active == 1) {
+       // ignore interrupt injection if we just started a symcall
+       PrintDebug("Symcall active\n");
+       sym_started = 1;
+#endif
+
     } else if (info->intr_state.irq_started == 1) {
 #ifdef CONFIG_DEBUG_INTERRUPTS
        PrintDebug("IRQ pending from previous injection\n");
@@ -409,24 +475,6 @@ int v3_handle_svm_exit(struct guest_info * info) {
     }
 
 
-    guest_state->cr0 = info->ctrl_regs.cr0;
-    guest_state->cr2 = info->ctrl_regs.cr2;
-    guest_state->cr3 = info->ctrl_regs.cr3;
-    guest_state->cr4 = info->ctrl_regs.cr4;
-    guest_state->dr6 = info->dbg_regs.dr6;
-    guest_state->dr7 = info->dbg_regs.dr7;
-    guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff;
-    guest_state->rflags = info->ctrl_regs.rflags;
-    guest_state->efer = info->ctrl_regs.efer;
-    
-    guest_state->cpl = info->cpl;
-
-    guest_state->rax = info->vm_regs.rax;
-    guest_state->rip = info->rip;
-    guest_state->rsp = info->vm_regs.rsp;
-
-
-    v3_set_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
 
     if (exit_code == VMEXIT_INTR) {
        //PrintDebug("INTR ret IP = %x\n", guest_state->rip);
index 22807a1..82614f1 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <palacios/svm_msr.h>
 #include <palacios/vmm_msr.h>
-
+#include <palacios/vmm_sprintf.h>
 #include <palacios/vmm_list.h>
 
 
@@ -30,9 +30,9 @@
 #define AMD_7_8_GEN_MSRS_START        0xc0010000
 #define AMD_7_8_GEN_MSRS_END          0xc0011fff
 
-#define PENTIUM_MSRS_INDEX            (0x0 * 4)
-#define AMD_6_GEN_MSRS_INDEX          (0x800 * 4)
-#define AMD_7_8_GEN_MSRS_INDEX        (0x1000 * 4)
+#define PENTIUM_MSRS_INDEX            (0)
+#define AMD_6_GEN_MSRS_INDEX          (0x2000)
+#define AMD_7_8_GEN_MSRS_INDEX        (0x4000)
 
 
 
@@ -71,7 +71,7 @@ static int update_map(struct guest_info * info, uint_t msr, int hook_reads, int
 
     *(bitmap + major) &= ~(mask << minor);
     *(bitmap + major) |= (val << minor);
-    
+
     return 0;
 }
 
index 8a2e4d4..94bbc7b 100644 (file)
 #include <palacios/vmm.h>
 #include <palacios/vmm_decoder.h>
 #include <palacios/vmcb.h>
+#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_lowlevel.h>
+#include <palacios/vmm_sprintf.h>
+
 
 
 v3_cpu_mode_t v3_get_vm_cpu_mode(struct guest_info * info) {
@@ -173,10 +177,67 @@ void v3_print_segments(struct guest_info * info) {
                   seg_ptr[i].long_mode, seg_ptr[i].db);
 
     }
+}
+
+//
+// We don't handle those fancy 64 bit system segments...
+//
+int v3_translate_segment(struct guest_info * info, uint16_t selector, struct v3_segment * seg) {
+    struct v3_segment * gdt = &(info->segments.gdtr);
+    addr_t gdt_addr = 0;
+    uint16_t seg_offset = (selector & ~0x7);
+    addr_t seg_addr = 0;
+    struct gen_segment * gen_seg = NULL;
+    struct seg_selector sel;
+
+    memset(seg, 0, sizeof(struct v3_segment));
+
+    sel.value = selector;
+
+    if (sel.ti == 1) {
+       PrintError("LDT translations not supported\n");
+       return -1;
+    }
 
+    if (guest_va_to_host_va(info, gdt->base, &gdt_addr) == -1) {
+       PrintError("Unable to translate GDT address\n");
+       return -1;
+    }
+
+    seg_addr = gdt_addr + seg_offset;
+    gen_seg = (struct gen_segment *)seg_addr;
+
+    //translate
+    seg->selector = selector;
+
+    seg->limit = gen_seg->limit_hi;
+    seg->limit <<= 16;
+    seg->limit += gen_seg->limit_lo;
+
+    seg->base = gen_seg->base_hi;
+    seg->base <<= 24;
+    seg->base += gen_seg->base_lo;
+
+    if (gen_seg->granularity == 1) {
+       seg->limit <<= 12;
+       seg->limit |= 0xfff;
+    }
+
+    seg->type = gen_seg->type;
+    seg->system = gen_seg->system;
+    seg->dpl = gen_seg->dpl;
+    seg->present = gen_seg->present;
+    seg->avail = gen_seg->avail;
+    seg->long_mode = gen_seg->long_mode;
+    seg->db = gen_seg->db;
+    seg->granularity = gen_seg->granularity;
+    
+    return 0;
 }
 
 
+
+
 void v3_print_ctrl_regs(struct guest_info * info) {
     struct v3_ctrl_regs * regs = &(info->ctrl_regs);
     int i = 0;
index 72887c6..44dbd50 100644 (file)
@@ -258,7 +258,8 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_
 
     if (config_ptr->enable_pci == 1) {
        struct ide_cfg ide_config = {"PCI", "PIIX3"};
-       struct pci_passthrough_cfg pci_pt_cfg = {"PCI", "E1000", 0x8086, 0x100e};
+       struct pci_passthrough_cfg pci_qemu_pt_cfg = {"PCI", "E1000", 0x8086, 0x100e};
+       struct pci_passthrough_cfg pci_hw_pt_cfg = {"PCI", "E1000", 0x8086, 0x107c};
        
        v3_create_device(info, "PCI", NULL);
        v3_create_device(info, "i440FX", "PCI");
@@ -272,7 +273,9 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_
 
        v3_create_device(info, "IDE", &ide_config);
        
-       v3_create_device(info, "PCI_PASSTHROUGH", &pci_pt_cfg);
+       v3_create_device(info, "PCI_PASSTHROUGH", &pci_qemu_pt_cfg);
+       v3_create_device(info, "PCI_PASSTHROUGH", &pci_hw_pt_cfg);
+
 
     } else {
        v3_create_device(info, "IDE", NULL);
index 6dc29eb..d0c3a32 100644 (file)
@@ -131,7 +131,10 @@ int v3_handle_cpuid(struct guest_info * info) {
     uint32_t cpuid = info->vm_regs.rax;
     struct v3_cpuid_hook * hook = get_cpuid_hook(info, cpuid);
 
+    //PrintDebug("CPUID called for 0x%x\n", cpuid);
+
     if (hook == NULL) {
+       //PrintDebug("Calling passthrough handler\n");
        // call the passthrough handler
        v3_cpuid(cpuid, 
                 (uint32_t *)&(info->vm_regs.rax), 
@@ -139,6 +142,8 @@ int v3_handle_cpuid(struct guest_info * info) {
                 (uint32_t *)&(info->vm_regs.rcx), 
                 (uint32_t *)&(info->vm_regs.rdx));
     } else {
+       //      PrintDebug("Calling hook function\n");
+
        if (hook->hook_fn(info, cpuid, 
                          (uint32_t *)&(info->vm_regs.rax), 
                          (uint32_t *)&(info->vm_regs.rbx), 
@@ -150,6 +155,8 @@ int v3_handle_cpuid(struct guest_info * info) {
        }
     }
 
+    //    PrintDebug("Cleaning up register contents\n");
+
     info->vm_regs.rax &= 0x00000000ffffffffLL;
     info->vm_regs.rbx &= 0x00000000ffffffffLL;
     info->vm_regs.rcx &= 0x00000000ffffffffLL;
index 8b70dd2..de68a86 100644 (file)
@@ -38,6 +38,8 @@ int v3_handle_msr_write(struct guest_info * info) {
     struct v3_msr msr_val;
     struct v3_msr_hook * hook = NULL;
 
+    PrintDebug("MSR write for msr 0x%x\n", msr_num);
+
     hook = v3_get_msr_hook(info, msr_num);
 
     if (!hook) {
@@ -151,6 +153,7 @@ void v3_refresh_msr_map(struct guest_info * info) {
     }
 
     list_for_each_entry(hook, &(msr_map->hook_list), link) {
+       PrintDebug("updating MSR map for msr %d\n", hook->msr);
        msr_map->update_map(info, hook->msr,    
                            (hook->read == NULL) ? 0 : 1,
                            (hook->write == NULL) ? 0 : 1);
@@ -162,7 +165,7 @@ void v3_print_msr_map(struct guest_info * info) {
     struct v3_msr_hook * hook = NULL;
 
     list_for_each_entry(hook, &(msr_map->hook_list), link) {
-       PrintDebug("MSR HOOK (MSR=%d) (read=0x%p) (write=0x%p)\n",
+       V3_Print("MSR HOOK (MSR=0x%x) (read=0x%p) (write=0x%p)\n",
                   hook->msr, hook->read, hook->write);
     }
 }
index 8ba9841..421707a 100644 (file)
@@ -154,7 +154,7 @@ static inline int handle_shadow_pagefault_64(struct guest_info * info, addr_t fa
 
     if (guest_pa_to_host_va(info, BASE_TO_PAGE_ADDR(guest_pml4e->pdp_base_addr), (addr_t *)&guest_pdp) == -1) {
        // Machine check the guest
-       PrintDebug("Invalid Guest PDP Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pml4e->pdp_base_addr));
+       PrintError("Invalid Guest PDP Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pml4e->pdp_base_addr));
        v3_raise_exception(info, MC_EXCEPTION);
        return 0;
     }
@@ -255,7 +255,7 @@ static int handle_pdpe_shadow_pagefault_64(struct guest_info * info, addr_t faul
 
     if (guest_pa_to_host_va(info, BASE_TO_PAGE_ADDR(guest_pdpe->pd_base_addr), (addr_t *)&guest_pd) == -1) {
        // Machine check the guest
-       PrintDebug("Invalid Guest PTE Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pdpe->pd_base_addr));
+       PrintError("Invalid Guest PTE Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pdpe->pd_base_addr));
        v3_raise_exception(info, MC_EXCEPTION);
        return 0;
     }
@@ -377,7 +377,7 @@ static int handle_pde_shadow_pagefault_64(struct guest_info * info, addr_t fault
     if (guest_pde->large_page == 0) {
        if (guest_pa_to_host_va(info, BASE_TO_PAGE_ADDR(guest_pde->pt_base_addr), (addr_t *)&guest_pt) == -1) {
            // Machine check the guest
-           PrintDebug("Invalid Guest PTE Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pde->pt_base_addr));
+           PrintError("Invalid Guest PTE Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pde->pt_base_addr));
            v3_raise_exception(info, MC_EXCEPTION);
            return 0;
        }
@@ -414,7 +414,7 @@ static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault
 
     if (shdw_reg == NULL) {
        // Inject a machine check in the guest
-       PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_pa);
+       PrintError("Invalid Guest Address in page table (0x%p)\n", (void *)guest_pa);
        v3_raise_exception(info, MC_EXCEPTION);
        return 0;
     }
@@ -541,7 +541,7 @@ static int handle_2MB_shadow_pagefault_64(struct guest_info * info,
  
     if (shdw_reg == NULL) {
        // Inject a machine check in the guest
-       PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa);
+       PrintError("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa);
        v3_raise_exception(info, MC_EXCEPTION);
        return 0;
     }
index 0c6414d..5cb4e35 100644 (file)
 #include <palacios/vmm.h>
 #include <palacios/vmm_msr.h>
 #include <palacios/vmm_mem.h>
+#include <palacios/vmm_hypercall.h>
 
-#define SYM_MSR_NUM 0x535
+#define SYM_PAGE_MSR 0x535
 
+#define SYM_CPUID_NUM 0x90000000
 
+#define SYM_CALL_RET_HCALL 0x535
 
 
 static int msr_read(uint_t msr, struct v3_msr * dst, void * priv_data) {
@@ -40,6 +43,9 @@ static int msr_write(uint_t msr, struct v3_msr src, void * priv_data) {
     struct guest_info * info = (struct guest_info *)priv_data;
     struct v3_sym_state * state = &(info->sym_state);
 
+
+    PrintDebug("Symbiotic MSR write for page %p\n", (void *)src.value);
+
     if (state->active == 1) {
        // unmap page
        struct v3_shadow_region * old_reg = v3_get_shadow_region(info, (addr_t)state->guest_pg_addr);
@@ -65,45 +71,216 @@ static int msr_write(uint_t msr, struct v3_msr src, void * priv_data) {
     return 0;
 }
 
+static int cpuid_fn(struct guest_info * info, uint32_t cpuid, 
+                   uint32_t * eax, uint32_t * ebx,
+                   uint32_t * ecx, uint32_t * edx,
+                   void * private_data) {
+
+    memset(eax, 0, sizeof(uint32_t));
+    memcpy(eax, "V3V", 3);
+
+    return 0;
+}
+    
+
+static int sym_call_ret(struct guest_info * info, uint_t hcall_id, void * private_data);
+
 
 
 int v3_init_sym_iface(struct guest_info * info) {
     struct v3_sym_state * state = &(info->sym_state);
-    
     memset(state, 0, sizeof(struct v3_sym_state));
 
-    PrintDebug("Allocating symbiotic page\n");
     state->sym_page_pa = (addr_t)V3_AllocPages(1);
     state->sym_page = (struct v3_sym_interface *)V3_VAddr((void *)state->sym_page_pa);
-
-    PrintDebug("Clearing symbiotic page\n");
     memset(state->sym_page, 0, PAGE_SIZE_4KB);
 
-    PrintDebug("hooking MSR\n");
-    v3_hook_msr(info, SYM_MSR_NUM, msr_read, msr_write, info);
+    
+    memcpy(&(state->sym_page->magic), "V3V", 3);
+
+    v3_hook_msr(info, SYM_PAGE_MSR, msr_read, msr_write, info);
+
+    v3_hook_cpuid(info, SYM_CPUID_NUM, cpuid_fn, info);
+
+
+    v3_register_hypercall(info, SYM_CALL_RET_HCALL, sym_call_ret, NULL);
 
-    PrintDebug("Done\n");
     return 0;
 }
 
 int v3_sym_map_pci_passthrough(struct guest_info * info, uint_t bus, uint_t dev, uint_t fn) {
     struct v3_sym_state * state = &(info->sym_state);
-    uint_t dev_index = (bus << 16) + (dev << 8) + fn;
+    uint_t dev_index = (bus << 8) + (dev << 3) + fn;
     uint_t major = dev_index / 8;
     uint_t minor = dev_index % 8;
 
+    if (bus > 3) {
+       PrintError("Invalid PCI bus %d\n", bus);
+       return -1;
+    }
+
+    PrintDebug("Setting passthrough pci map for index=%d\n", dev_index);
+
     state->sym_page->pci_pt_map[major] |= 0x1 << minor;
 
+    PrintDebug("pt_map entry=%x\n",   state->sym_page->pci_pt_map[major]);
+
+    PrintDebug("pt map vmm addr=%p\n", state->sym_page->pci_pt_map);
+
     return 0;
 }
 
 int v3_sym_unmap_pci_passthrough(struct guest_info * info, uint_t bus, uint_t dev, uint_t fn) {
     struct v3_sym_state * state = &(info->sym_state);
-    uint_t dev_index = (bus << 16) + (dev << 8) + fn;
+    uint_t dev_index = (bus << 8) + (dev << 3) + fn;
     uint_t major = dev_index / 8;
     uint_t minor = dev_index % 8;
 
+    if (bus > 3) {
+       PrintError("Invalid PCI bus %d\n", bus);
+       return -1;
+    }
+
     state->sym_page->pci_pt_map[major] &= ~(0x1 << minor);
 
     return 0;
 }
+
+
+
+static int sym_call_ret(struct guest_info * info, uint_t hcall_id, void * private_data) {
+    struct v3_sym_state * state = (struct v3_sym_state *)&(info->sym_state);
+    struct v3_sym_context * old_ctx = (struct v3_sym_context *)&(state->old_ctx);
+
+
+    PrintError("Return from sym call\n");
+    v3_print_guest_state(info);
+    v3_print_mem_map(info);
+
+
+    if (state->notifier != NULL) {
+       if (state->notifier(info, state->private_data) == -1) {
+           PrintError("Error in return from symcall.\n");
+           return -1;
+       }
+    }
+
+
+    // restore guest state
+    memcpy(&(info->vm_regs), &(old_ctx->vm_regs), sizeof(struct v3_gprs));
+    memcpy(&(info->segments.cs), &(old_ctx->cs), sizeof(struct v3_segment));
+    memcpy(&(info->segments.ss), &(old_ctx->ss), sizeof(struct v3_segment));
+    info->segments.gs.base = old_ctx->gs_base;
+    info->segments.fs.base = old_ctx->fs_base;
+    info->rip = old_ctx->rip;
+    info->cpl = old_ctx->cpl;
+
+
+    PrintDebug("restoring guest state\n");
+    v3_print_guest_state(info);
+
+    // clear sym flags
+    state->call_active = 0;
+
+
+    return 0;
+}
+
+
+int v3_sym_call(struct guest_info * info, 
+               uint64_t arg0, uint64_t arg1, 
+               uint64_t arg2, uint64_t arg3,
+               uint64_t arg4, uint64_t arg5, 
+               int (*notifier)(struct guest_info * info, void * private_data),
+               void * private_data) {
+    struct v3_sym_state * state = (struct v3_sym_state *)&(info->sym_state);
+
+
+    PrintDebug("Making Sym call\n");
+
+    if ((state->sym_page->sym_call_enabled == 0) ||
+       (state->call_active == 1) || 
+       (state->call_pending == 1)) {
+       return -1;
+    }
+
+    state->args[0] = arg0;
+    state->args[1] = arg1;
+    state->args[2] = arg2;
+    state->args[3] = arg3;
+    state->args[4] = arg4;
+    state->args[5] = arg5;
+
+    state->notifier = notifier;
+    state->private_data = private_data;
+
+    state->call_pending = 1;
+
+    return 0;
+}
+
+
+
+int v3_activate_sym_call(struct guest_info * info) {
+    struct v3_sym_state * state = (struct v3_sym_state *)&(info->sym_state);
+    struct v3_sym_context * old_ctx = (struct v3_sym_context *)&(state->old_ctx);
+    struct v3_segment sym_cs;
+    struct v3_segment sym_ss;
+
+
+    if ((state->sym_page->sym_call_enabled == 0) || 
+       (state->call_pending == 0)) {
+       // Unable to make sym call or none pending
+       if (state->call_active == 1) {
+           PrintError("handled exit while in symcall\n");
+       }
+       return 0;
+    }
+
+
+    PrintDebug("Activating Symbiotic call\n");
+    v3_print_guest_state(info);
+
+
+    // Save the old context
+    memcpy(&(old_ctx->vm_regs), &(info->vm_regs), sizeof(struct v3_gprs));
+    memcpy(&(old_ctx->cs), &(info->segments.cs), sizeof(struct v3_segment));
+    memcpy(&(old_ctx->ss), &(info->segments.ss), sizeof(struct v3_segment));
+    old_ctx->gs_base = info->segments.gs.base;
+    old_ctx->fs_base = info->segments.fs.base;
+    old_ctx->rip = info->rip;
+    old_ctx->cpl = info->cpl;
+
+    
+    // Setup the sym call context
+    info->rip = state->sym_page->sym_call_rip;
+    info->vm_regs.rsp = state->sym_page->sym_call_rsp;
+
+    v3_translate_segment(info, state->sym_page->sym_call_cs, &sym_cs);
+    memcpy(&(info->segments.cs), &sym_cs, sizeof(struct v3_segment));
+    v3_translate_segment(info, state->sym_page->sym_call_cs + 8, &sym_ss);
+    memcpy(&(info->segments.ss), &sym_ss, sizeof(struct v3_segment));
+
+    info->segments.gs.base = state->sym_page->sym_call_gs;
+    info->segments.fs.base = 0;
+    info->cpl = 0;
+
+    info->vm_regs.rax = state->args[0];
+    info->vm_regs.rbx = state->args[1];
+    info->vm_regs.rcx = state->args[2];
+    info->vm_regs.rdx = state->args[3];
+    info->vm_regs.rsi = state->args[4];
+    info->vm_regs.rdi = state->args[5];
+
+    // Mark sym call as active
+    state->call_pending = 0;
+    state->call_active = 1;
+
+
+    PrintDebug("Sym state\n");
+    v3_print_guest_state(info);
+
+    return 1;
+}
index 8fb7a81..00fd7e9 100644 (file)
@@ -83,10 +83,11 @@ static int handle_mov_to_cr3(struct guest_info * info, v3_reg_t * cr3_reg) {
 
     if (info->shdw_pg_mode == SHADOW_PAGING) {
 
+       /*
         PrintDebug("Old Guest CR3=%p, Old Shadow CR3=%p\n",
                   (void *)info->ctrl_regs.cr3,
                   (void *)info->shdw_pg_state.guest_cr3);
-
+       */
         if (info->cpu_mode == LONG) {
             info->shdw_pg_state.guest_cr3 = (uint64_t)*cr3_reg;
         } else {
@@ -100,11 +101,11 @@ static int handle_mov_to_cr3(struct guest_info * info, v3_reg_t * cr3_reg) {
                 return -1;
             }
         }
-
+       /*
         PrintDebug("New guest CR3=%p, New shadow CR3=%p\n",
                   (void *)info->ctrl_regs.cr3,
                   (void *)info->shdw_pg_state.guest_cr3);
-
+       */
     } else if (info->shdw_pg_mode == NESTED_PAGING) {
         PrintError("Nested paging not available in VMX right now!\n");
         return -1;
@@ -150,15 +151,17 @@ static int handle_mov_to_cr0(struct guest_info * info, v3_reg_t * new_cr0) {
     uint_t paging_transition = 0;
     int instr_len = 0;
 
+    /*
     PrintDebug("Old shadow CR0: 0x%x, New shadow CR0: 0x%x\n",
               (uint32_t)info->shdw_pg_state.guest_cr0, (uint32_t)*new_cr0);
-
+    */
 
     if (new_shdw_cr0->pe != shdw_cr0->pe) {
+       /*
         PrintDebug("Guest CR0: 0x%x\n", *(uint32_t *)guest_cr0);
         PrintDebug("Old shadow CR0: 0x%x\n", *(uint32_t *)shdw_cr0);
         PrintDebug("New shadow CR0: 0x%x\n", *(uint32_t *)new_shdw_cr0);
-
+       */
         if (v3_vmxassist_ctx_switch(info) != 0) {
             PrintError("Unable to execute VMXASSIST context switch!\n");
             return -1;
@@ -200,7 +203,7 @@ static int handle_mov_to_cr0(struct guest_info * info, v3_reg_t * new_cr0) {
             struct efer_64 * guest_efer = (struct efer_64 *)&(info->ctrl_regs.efer);
 
             if (guest_efer->lme == 1) {
-                PrintDebug("Enabling long mode\n");
+               //     PrintDebug("Enabling long mode\n");
 
                 guest_efer->lma = 1;
                 guest_efer->lme = 1;
@@ -208,7 +211,7 @@ static int handle_mov_to_cr0(struct guest_info * info, v3_reg_t * new_cr0) {
                 vmx_info->entry_ctrls.guest_ia32e = 1;
             }
 
-            PrintDebug("Activating Shadow Page tables\n");
+           //            PrintDebug("Activating Shadow Page tables\n");
 
             if (v3_activate_shadow_pt(info) == -1) {
                 PrintError("Failed to activate shadow page tables\n");
index ee1824f..1da5abd 100644 (file)
@@ -67,10 +67,10 @@ static int inline handle_cr_access(struct guest_info * info, ulong_t exit_qual)
     // PrintDebug("Control register: %d\n", cr_qual->access_type);
     switch(cr_qual->cr_id) {
         case 0:
-           PrintDebug("Handling CR0 Access\n");
+           //PrintDebug("Handling CR0 Access\n");
             return v3_vmx_handle_cr0_access(info);
         case 3:
-           PrintDebug("Handling CR3 Access\n");
+           //PrintDebug("Handling CR3 Access\n");
             return v3_vmx_handle_cr3_access(info);
         default:
             PrintError("Unhandled CR access: %d\n", cr_qual->cr_id);
@@ -201,6 +201,19 @@ int v3_handle_vmx_exit(struct v3_gprs * gprs, struct guest_info * info, struct v
            }
 
             break;
+       case VMEXIT_VMCALL:
+           /* 
+            * Hypercall 
+            */
+
+           // VMCALL is a 3 byte op
+           // We do this early because some hypercalls can change the rip...
+           info->rip += 3;         
+
+           if (v3_handle_hypercall(info) == -1) {
+               return -1;
+           }
+           break;
         case VMEXIT_IO_INSTR: {
            struct vmx_exit_io_qual * io_qual = (struct vmx_exit_io_qual *)&exit_qual;
 
@@ -293,12 +306,16 @@ int v3_handle_vmx_exit(struct v3_gprs * gprs, struct guest_info * info, struct v
             check_vmcs_write(VMCS_ENTRY_EXCP_ERR, info->excp_state.excp_error_code);
             int_info.error_code = 1;
 
+#ifdef CONFIG_DEBUG_INTERRUPTS
             PrintDebug("Injecting exception %d with error code %x\n", 
                     int_info.vector, info->excp_state.excp_error_code);
+#endif
         }
 
         int_info.valid = 1;
+#ifdef CONFIG_DEBUG_INTERRUPTS
         PrintDebug("Injecting exception %d (EIP=%p)\n", int_info.vector, (void *)info->rip);
+#endif
         check_vmcs_write(VMCS_ENTRY_INT_INFO, int_info.value);
 
         v3_injecting_excp(info, int_info.vector);
index 177771a..cc1f722 100644 (file)
@@ -291,8 +291,39 @@ void Main(struct Boot_Info* bootInfo)
 
 
   PrintBoth("Next: setup GDT\n");
+  {
+    uint_t addr = 0xe0000;
+    uint_t hi = 0;
+
+
+   
+    //    wrmsr(SYMBIOTIC_MSR, hi, addr);
+    {
+       uint_t msr_num = 0x0000001B;
+       __asm__ __volatile__ ("rdmsr" : : "c"(msr_num) : "%eax","%edx","memory");
+    }
+    {
+       uint_t msr_num = 0x0000001c;
+       __asm__ __volatile__ ("rdmsr" : : "c"(msr_num) : "%eax","%edx","memory");
+    }
+
+
+    {
+       uint_t msr_num = 0x0000001B;
+       __asm__ __volatile__ ("wrmsr" : : "c"(msr_num), "a"(hi), "d"(addr) : "memory");
+    }
+
 
 
+    {
+       uint_t msr_num = 0x535;
+       __asm__ __volatile__ ("wrmsr" : : "c"(msr_num), "a"(hi), "d"(addr) : "memory");
+    }
+
+
+    while (1) {}
+
+  }
   if (TEST_PAGING) {
       int i = 0;
       for (i = 0; i < 1024; i++) {