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.


Updated symbiotic interfaces for multicore support
Jack Lange [Wed, 3 Feb 2010 23:00:28 +0000 (17:00 -0600)]
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmm_sym_iface.h
palacios/src/devices/keyboard.c
palacios/src/devices/lnx_virtio_sym.c
palacios/src/devices/pci_passthrough.c
palacios/src/palacios/svm.c
palacios/src/palacios/vmm_sym_iface.c
palacios/src/palacios/vmx.c

index 18b5004..bf9d302 100644 (file)
@@ -186,6 +186,11 @@ struct guest_info {
 
     void * decoder_state;
 
+#ifdef CONFIG_SYMBIOTIC
+    // Symbiotic state
+    struct v3_sym_local_state sym_local_state;
+#endif
+
 
     struct v3_vm_info * vm_info;
     // the logical cpu this guest context is executing on
@@ -221,7 +226,7 @@ struct v3_vm_info {
 
 #ifdef CONFIG_SYMBIOTIC
     // Symbiotic state
-    struct v3_sym_state sym_state;
+    struct v3_sym_global_state sym_global_state;
 #ifdef CONFIG_SYMBIOTIC_SWAP
     struct v3_sym_swap_state swap_state;
 #endif
index a37cc8e..2f1966a 100644 (file)
 
 
 
-struct v3_sym_interface {
+
+struct v3_sym_global_page {
     uint64_t magic;
 
     union {
        uint32_t feature_flags;
        struct {
-           uint_t pci_map_valid            : 1;
-           uint32_t sym_call_enabled       : 1;
+           uint_t pci_map_valid      : 1;
        } __attribute__((packed));
     } __attribute__((packed));
+    
+    uint8_t pci_pt_map[(4 * 256) / 8]; // we're hardcoding this: (4 busses, 256 max devs)
+
+} __attribute__((packed));
+
+struct v3_sym_local_page {
+    uint64_t magic;
 
     union { 
        uint32_t state_flags;
        struct {
            uint32_t sym_call_active        : 1;
+           uint32_t sym_call_enabled       : 1;
        } __attribute__((packed));
     } __attribute__((packed));
-
-    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)
-
-} __attribute__((packed));
-
+};
 
 
 #include <palacios/vm_guest.h>
 
 
-struct v3_sym_core_context {
+struct v3_sym_cpu_context {
     struct v3_gprs vm_regs;
     struct v3_segment cs;
     struct v3_segment ss;
@@ -66,17 +67,16 @@ struct v3_sym_core_context {
     uint8_t cpl;
 };
 
-struct v3_symcall_state{
+struct v3_symcall_state {
     struct {
-       uint_t active                  : 1; // activated when symbiotic page MSR is written
        uint_t sym_call_active         : 1;
        uint_t sym_call_returned       : 1;
        uint_t sym_call_error          : 1;
     } __attribute__((packed));
 
-    struct v3_sym_core_context old_ctx;
+    struct v3_sym_cpu_context old_ctx;
 
-    int sym_call_errno;    
+    int sym_call_errno;
 
     uint64_t sym_call_rip;
     uint64_t sym_call_cs;
@@ -85,17 +85,26 @@ struct v3_symcall_state{
     uint64_t sym_call_fs;
 };
 
-struct v3_sym_state {
-    
-    struct v3_sym_interface * sym_page;
-    addr_t sym_page_pa;
+struct v3_sym_global_state {
+    struct v3_sym_global_page * sym_page;
 
-    uint64_t guest_pg_addr;
+    addr_t global_page_pa;
+    uint64_t global_guest_pa;
 
-    struct v3_symcall_state * symcalls;
+    int active; // activated when symbiotic page MSR is written
 };
 
 
+struct v3_sym_local_state {
+    struct v3_sym_local_page * local_page;
+
+    addr_t local_page_pa;
+    uint64_t local_guest_pa;
+
+    struct v3_symcall_state symcall_state;
+
+    int active;  // activated when symbiotic page MSR is written
+};
 
 
 
index 08844e2..72b004d 100644 (file)
@@ -337,6 +337,7 @@ static int key_event_handler(struct v3_vm_info * vm,
     } 
 #ifdef CONFIG_SYMBIOTIC
     else if (evt->scan_code == 0x43) { // F9 Sym test
+       struct guest_info * core = &(vm->cores[0]);
        PrintDebug("Testing sym call\n");
        sym_arg_t a0 = 0x1111;
        sym_arg_t a1 = 0x2222;
@@ -346,13 +347,13 @@ static int key_event_handler(struct v3_vm_info * vm,
        uint64_t call_start = 0;
        uint64_t call_end = 0;
        
-       V3_Print("Exits before symcall: %d\n", (uint32_t)info->num_exits);
+       V3_Print("Exits before symcall: %d\n", (uint32_t)core->num_exits);
 
        rdtscll(call_start);
-       v3_sym_call5(info, SYMCALL_TEST, &a0, &a1, &a2, &a3, &a4);
+       v3_sym_call5(core, SYMCALL_TEST, &a0, &a1, &a2, &a3, &a4);
        rdtscll(call_end);
        
-       V3_Print("Symcall latency = %d cycles (%d exits)\n", (uint32_t)(call_end - call_start), (uint32_t)info->num_exits);
+       V3_Print("Symcall latency = %d cycles (%d exits)\n", (uint32_t)(call_end - call_start), (uint32_t)core->num_exits);
 
        V3_Print("Symcall  Test Returned arg0=%x, arg1=%x, arg2=%x, arg3=%x, arg4=%x\n",
                 (uint32_t)a0, (uint32_t)a1, (uint32_t)a2, (uint32_t)a3, (uint32_t)a4);
index 2cd3745..fcf7d70 100644 (file)
@@ -59,8 +59,7 @@ struct virtio_sym_state {
 
 
 
-static int virtio_reset(struct vm_device * dev) {
-    struct virtio_sym_state * virtio = (struct virtio_sym_state *)dev->private_data;
+static int virtio_reset(struct virtio_sym_state * virtio) {
 
     memset(virtio->queue, 0, sizeof(struct virtio_queue));
 
@@ -92,9 +91,8 @@ static int get_desc_count(struct virtio_queue * q, int index) {
 }
 
 
-static int handle_kick(struct vm_device * dev) {
-    struct virtio_sym_state * virtio = (struct virtio_sym_state *)dev->private_data;    
-    struct virtio_queue * q = virtio->cur_queue;
+static int handle_kick(struct guest_info * core, struct virtio_sym_state * sym_state) {
+    struct virtio_queue * q = sym_state->cur_queue;
 
     return -1;
 
@@ -121,7 +119,7 @@ static int handle_kick(struct vm_device * dev) {
                       tmp_desc->flags, tmp_desc->next);
        
 
-           if (guest_pa_to_host_va(dev->vm, tmp_desc->addr_gpa, (addr_t *)&(page_addr)) == -1) {
+           if (guest_pa_to_host_va(core, tmp_desc->addr_gpa, (addr_t *)&(page_addr)) == -1) {
                PrintError("Could not translate block header address\n");
                return -1;
            }
@@ -148,19 +146,18 @@ static int handle_kick(struct vm_device * dev) {
     }
 
     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
-       PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
-       v3_pci_raise_irq(virtio->pci_bus, 0, virtio->pci_dev);
-       virtio->virtio_cfg.pci_isr = VIRTIO_ISR_ACTIVE;
+       PrintDebug("Raising IRQ %d\n",  sym_state->pci_dev->config_header.intr_line);
+       v3_pci_raise_irq(sym_state->pci_bus, 0, sym_state->pci_dev);
+       sym_state->virtio_cfg.pci_isr = VIRTIO_ISR_ACTIVE;
     }
 
     return 0;
 }
 
 
-static int virtio_io_write(uint16_t port, void * src, uint_t length, void * private_data) {
-    struct vm_device * dev = (struct vm_device *)private_data;
-    struct virtio_sym_state * virtio = (struct virtio_sym_state *)dev->private_data;
-    int port_idx = port % virtio->io_range_size;
+static int virtio_io_write(struct guest_info * core, uint16_t port, void * src, uint_t length, void * private_data) {
+    struct virtio_sym_state * sym_state = (struct virtio_sym_state *)private_data;
+    int port_idx = port % sym_state->io_range_size;
 
 
 /*
@@ -176,7 +173,7 @@ static int virtio_io_write(uint16_t port, void * src, uint_t length, void * priv
                return -1;
            }
            
-           virtio->virtio_cfg.guest_features = *(uint32_t *)src;
+           sym_state->virtio_cfg.guest_features = *(uint32_t *)src;
 
            break;
        case VRING_PG_NUM_PORT:
@@ -185,41 +182,41 @@ static int virtio_io_write(uint16_t port, void * src, uint_t length, void * priv
                addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
 
 
-               virtio->cur_queue->pfn = pfn;
+               sym_state->cur_queue->pfn = pfn;
                
-               virtio->cur_queue->ring_desc_addr = page_addr ;
-               virtio->cur_queue->ring_avail_addr = page_addr + (QUEUE_SIZE * sizeof(struct vring_desc));
-               virtio->cur_queue->ring_used_addr = ( virtio->cur_queue->ring_avail_addr + \
+               sym_state->cur_queue->ring_desc_addr = page_addr ;
+               sym_state->cur_queue->ring_avail_addr = page_addr + (QUEUE_SIZE * sizeof(struct vring_desc));
+               sym_state->cur_queue->ring_used_addr = ( sym_state->cur_queue->ring_avail_addr + \
                                                 sizeof(struct vring_avail)    + \
                                                 (QUEUE_SIZE * sizeof(uint16_t)));
                
                // round up to next page boundary.
-               virtio->cur_queue->ring_used_addr = (virtio->cur_queue->ring_used_addr + 0xfff) & ~0xfff;
+               sym_state->cur_queue->ring_used_addr = (sym_state->cur_queue->ring_used_addr + 0xfff) & ~0xfff;
 
-               if (guest_pa_to_host_va(dev->vm, virtio->cur_queue->ring_desc_addr, (addr_t *)&(virtio->cur_queue->desc)) == -1) {
+               if (guest_pa_to_host_va(core, sym_state->cur_queue->ring_desc_addr, (addr_t *)&(sym_state->cur_queue->desc)) == -1) {
                    PrintError("Could not translate ring descriptor address\n");
                    return -1;
                }
 
 
-               if (guest_pa_to_host_va(dev->vm, virtio->cur_queue->ring_avail_addr, (addr_t *)&(virtio->cur_queue->avail)) == -1) {
+               if (guest_pa_to_host_va(core, sym_state->cur_queue->ring_avail_addr, (addr_t *)&(sym_state->cur_queue->avail)) == -1) {
                    PrintError("Could not translate ring available address\n");
                    return -1;
                }
 
 
-               if (guest_pa_to_host_va(dev->vm, virtio->cur_queue->ring_used_addr, (addr_t *)&(virtio->cur_queue->used)) == -1) {
+               if (guest_pa_to_host_va(core, sym_state->cur_queue->ring_used_addr, (addr_t *)&(sym_state->cur_queue->used)) == -1) {
                    PrintError("Could not translate ring used address\n");
                    return -1;
                }
 
                PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
-                          (void *)(virtio->cur_queue->ring_desc_addr),
-                          (void *)(virtio->cur_queue->ring_avail_addr),
-                          (void *)(virtio->cur_queue->ring_used_addr));
+                          (void *)(sym_state->cur_queue->ring_desc_addr),
+                          (void *)(sym_state->cur_queue->ring_avail_addr),
+                          (void *)(sym_state->cur_queue->ring_used_addr));
 
                PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
-                          virtio->cur_queue->desc, virtio->cur_queue->avail, virtio->cur_queue->used);
+                          sym_state->cur_queue->desc, sym_state->cur_queue->avail, sym_state->cur_queue->used);
 
            } else {
                PrintError("Illegal write length for page frame number\n");
@@ -227,36 +224,36 @@ static int virtio_io_write(uint16_t port, void * src, uint_t length, void * priv
            }
            break;
        case VRING_Q_SEL_PORT:
-           virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
+           sym_state->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
 
-           if (virtio->virtio_cfg.vring_queue_selector > 0) {
+           if (sym_state->virtio_cfg.vring_queue_selector > 0) {
                PrintError("Virtio Symbiotic device has not qeueues. Selected %d\n", 
-                          virtio->virtio_cfg.vring_queue_selector);
+                          sym_state->virtio_cfg.vring_queue_selector);
                return -1;
            }
            
-           virtio->cur_queue = &(virtio->queue[virtio->virtio_cfg.vring_queue_selector]);
+           sym_state->cur_queue = &(sym_state->queue[sym_state->virtio_cfg.vring_queue_selector]);
 
            break;
        case VRING_Q_NOTIFY_PORT:
            PrintDebug("Handling Kick\n");
-           if (handle_kick(dev) == -1) {
+           if (handle_kick(core, sym_state) == -1) {
                PrintError("Could not handle Symbiotic Notification\n");
                return -1;
            }
            break;
        case VIRTIO_STATUS_PORT:
-           virtio->virtio_cfg.status = *(uint8_t *)src;
+           sym_state->virtio_cfg.status = *(uint8_t *)src;
 
-           if (virtio->virtio_cfg.status == 0) {
+           if (sym_state->virtio_cfg.status == 0) {
                PrintDebug("Resetting device\n");
-               virtio_reset(dev);
+               virtio_reset(sym_state);
            }
 
            break;
 
        case VIRTIO_ISR_PORT:
-           virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
+           sym_state->virtio_cfg.pci_isr = *(uint8_t *)src;
            break;
        default:
            return -1;
@@ -267,10 +264,10 @@ static int virtio_io_write(uint16_t port, void * src, uint_t length, void * priv
 }
 
 
-static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * private_data) {
-    struct vm_device * dev = (struct vm_device *)private_data;
-    struct virtio_sym_state * virtio = (struct virtio_sym_state *)dev->private_data;
-    int port_idx = port % virtio->io_range_size;
+static int virtio_io_read(struct guest_info * core, uint16_t port, void * dst, uint_t length, void * private_data) {
+
+    struct virtio_sym_state * sym_state = (struct virtio_sym_state *)private_data;
+    int port_idx = port % sym_state->io_range_size;
 
 /*
     PrintDebug("VIRTIO SYMBIOTIC Read  for port %d (index =%d), length=%d\n", 
@@ -283,7 +280,7 @@ static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * priva
                return -1;
            }
 
-           *(uint32_t *)dst = virtio->virtio_cfg.host_features;
+           *(uint32_t *)dst = sym_state->virtio_cfg.host_features;
        
            break;
        case VRING_PG_NUM_PORT:
@@ -292,7 +289,7 @@ static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * priva
                return -1;
            }
 
-           *(uint32_t *)dst = virtio->cur_queue->pfn;
+           *(uint32_t *)dst = sym_state->cur_queue->pfn;
 
            break;
        case VRING_SIZE_PORT:
@@ -301,7 +298,7 @@ static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * priva
                return -1;
            }
                
-           *(uint16_t *)dst = virtio->cur_queue->queue_size;
+           *(uint16_t *)dst = sym_state->cur_queue->queue_size;
 
            break;
 
@@ -311,20 +308,20 @@ static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * priva
                return -1;
            }
 
-           *(uint8_t *)dst = virtio->virtio_cfg.status;
+           *(uint8_t *)dst = sym_state->virtio_cfg.status;
            break;
 
        case VIRTIO_ISR_PORT:
-           *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
-           virtio->virtio_cfg.pci_isr = 0;
-           v3_pci_lower_irq(virtio->pci_bus, 0, virtio->pci_dev);
+           *(uint8_t *)dst = sym_state->virtio_cfg.pci_isr;
+           sym_state->virtio_cfg.pci_isr = 0;
+           v3_pci_lower_irq(sym_state->pci_bus, 0, sym_state->pci_dev);
            break;
 
        default:
            if ( (port_idx >= sizeof(struct virtio_config)) && 
                 (port_idx < (sizeof(struct virtio_config) + sizeof(struct sym_config))) ) {
                int cfg_offset = port_idx - sizeof(struct virtio_config);
-               uint8_t * cfg_ptr = (uint8_t *)&(virtio->sym_cfg);
+               uint8_t * cfg_ptr = (uint8_t *)&(sym_state->sym_cfg);
 
                memcpy(dst, cfg_ptr + cfg_offset, length);
                
@@ -353,7 +350,7 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int virtio_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
+static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
     struct virtio_sym_state * virtio_state = NULL;
     struct pci_device * pci_dev = NULL;
@@ -444,7 +441,7 @@ static int virtio_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
        virtio_state->pci_bus = pci_bus;
     }
 
-    virtio_reset(dev);
+    virtio_reset(virtio_state);
 
 
     return 0;
index 4ccbba3..d574eee 100644 (file)
@@ -147,7 +147,7 @@ static inline void pci_cfg_write8(uint32_t addr, uint8_t val) {
 
 
 // We initialize this 
-static int pci_bar_init(int bar_num, uint32_t * dst,void * private_data) {
+static int pci_bar_init(int bar_num, uint32_t * dst, void * private_data) {
     struct vm_device * dev = (struct vm_device *)private_data;
     struct pt_dev_state * state = (struct pt_dev_state *)dev->private_data;
     const uint32_t bar_base_reg = 4;
@@ -234,7 +234,7 @@ static int pci_bar_init(int bar_num, uint32_t * dst,void * private_data) {
                PrintDebug("Adding 32 bit PCI mem region: start=0x%x, end=0x%x\n",
                           pbar->addr, pbar->addr + pbar->size);
 
-               v3_add_shadow_mem(dev->vm, 
+               v3_add_shadow_mem(dev->vm, V3_MEM_CORE_ANY,
                                  pbar->addr, 
                                  pbar->addr + pbar->size - 1,
                                  pbar->addr);
@@ -245,7 +245,7 @@ static int pci_bar_init(int bar_num, uint32_t * dst,void * private_data) {
                pbar->addr = PCI_MEM24_BASE(bar_val);
                pbar->size = ~PCI_MEM24_BASE(max_val) + 1;
 
-               v3_add_shadow_mem(dev->vm, 
+               v3_add_shadow_mem(dev->vm, V3_MEM_CORE_ANY,
                                  pbar->addr, 
                                  pbar->addr + pbar->size - 1,
                                  pbar->addr);
@@ -282,7 +282,7 @@ static int pci_bar_init(int bar_num, uint32_t * dst,void * private_data) {
     return 0;
 }
 
-static int pt_io_read(uint16_t port, void * dst, uint_t length, void * priv_data) {
+static int pt_io_read(struct guest_info * core, uint16_t port, void * dst, uint_t length, void * priv_data) {
     struct pt_bar * pbar = (struct pt_bar *)priv_data;
     int port_offset = port % pbar->size;
 
@@ -301,7 +301,7 @@ static int pt_io_read(uint16_t port, void * dst, uint_t length, void * priv_data
 }
 
 
-static int pt_io_write(uint16_t port, void * src, uint_t length, void * priv_data) {
+static int pt_io_write(struct guest_info * core, uint16_t port, void * src, uint_t length, void * priv_data) {
     struct pt_bar * pbar = (struct pt_bar *)priv_data;
     int port_offset = port % pbar->size;
     
@@ -379,7 +379,7 @@ static int pci_bar_write(int bar_num, uint32_t * src, void * private_data) {
        }
     } else if (vbar->type == PT_BAR_MEM32) {
        // remove old mapping
-       struct v3_shadow_region * old_reg = v3_get_shadow_region(dev->vm, vbar->addr);
+       struct v3_shadow_region * old_reg = v3_get_shadow_region(dev->vm, V3_MEM_CORE_ANY, vbar->addr);
 
        if (old_reg == NULL) {
            // uh oh...
@@ -402,7 +402,7 @@ static int pci_bar_write(int bar_num, uint32_t * src, void * private_data) {
        PrintDebug("Adding pci Passthrough remapping: start=0x%x, size=%d, end=0x%x\n", 
                   vbar->addr, vbar->size, vbar->addr + vbar->size);
 
-       v3_add_shadow_mem(dev->vm, 
+       v3_add_shadow_mem(dev->vm, V3_MEM_CORE_ANY, 
                          vbar->addr, 
                          vbar->addr + vbar->size - 1,
                          pbar->addr);
@@ -490,7 +490,7 @@ static int find_real_pci_dev(uint16_t vendor_id, uint16_t device_id, struct pt_d
 
 
 
-static int setup_virt_pci_dev(struct guest_info * info, struct vm_device * dev) {
+static int setup_virt_pci_dev(struct v3_vm_info * vm_info, struct vm_device * dev) {
     struct pt_dev_state * state = (struct pt_dev_state *)dev->private_data;
     struct pci_device * pci_dev = NULL;
     struct v3_pci_bar bars[6];
@@ -516,7 +516,7 @@ static int setup_virt_pci_dev(struct guest_info * info, struct vm_device * dev)
 
     state->pci_dev = pci_dev;
 
-    v3_sym_map_pci_passthrough(info, pci_dev->bus_num, pci_dev->dev_num, pci_dev->fn_num);
+    v3_sym_map_pci_passthrough(vm_info, pci_dev->bus_num, pci_dev->dev_num, pci_dev->fn_num);
 
 
     return 0;
@@ -532,7 +532,7 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int irq_handler(struct guest_info * info, struct v3_interrupt * intr, void * private_data) {
+static int irq_handler(struct v3_vm_info * vm, struct v3_interrupt * intr, void * private_data) {
     struct vm_device * dev = (struct vm_device *)private_data;
     struct pt_dev_state * state = (struct pt_dev_state *)dev->private_data;
 
index aeed691..75ba3a0 100644 (file)
@@ -442,7 +442,7 @@ int v3_svm_enter(struct guest_info * info) {
     guest_state->rsp = info->vm_regs.rsp;
 
 #ifdef CONFIG_SYMBIOTIC
-    if (info->vm_info->sym_state.symcalls[info->cpu_id].sym_call_active == 0) {
+    if (info->sym_local_state.symcall_state.sym_call_active == 0) {
        update_irq_entry_state(info);
     }
 #else 
@@ -459,7 +459,7 @@ int v3_svm_enter(struct guest_info * info) {
     */
 
 #ifdef CONFIG_SYMBIOTIC
-    if (info->vm_info->sym_state.symcalls[info->cpu_id].sym_call_active == 1) {
+    if (info->sym_local_state.symcall_state.sym_call_active == 1) {
        if (guest_ctrl->guest_ctrl.V_IRQ == 1) {
            V3_Print("!!! Injecting Interrupt during Sym call !!!\n");
        }
@@ -518,7 +518,7 @@ int v3_svm_enter(struct guest_info * info) {
 
 
 #ifdef CONFIG_SYMBIOTIC
-    if (info->vm_info->sym_state.symcalls[info->cpu_id].sym_call_active == 0) {
+    if (info->sym_local_state.symcall_state.sym_call_active == 0) {
        update_irq_exit_state(info);
     }
 #else
index e3d22d0..474ea0b 100644 (file)
 #include <palacios/vmm_mem.h>
 #include <palacios/vmm_hypercall.h>
 #include <palacios/vm_guest.h>
+#include <palacios/vmm_sprintf.h>
 
-#define SYM_PAGE_MSR 0x535
+
+#define SYMSPY_GLOBAL_MSR 0x534
+#define SYMSPY_LOCAL_MSR 0x535
 
 #define SYM_CPUID_NUM 0x90000000
 
 #define SYMCALL_GS_MSR  0x539
 #define SYMCALL_FS_MSR  0x540
 
-static int msr_read(uint_t msr, struct v3_msr * dst, void * priv_data) {
-    struct guest_info * info = (struct guest_info *)priv_data;
-    struct v3_sym_state * state = &(info->vm_info->sym_state);
+static int symspy_msr_read(struct guest_info * core, uint_t msr, 
+                   struct v3_msr * dst, void * priv_data) {
+    struct v3_sym_global_state * global_state = &(core->vm_info->sym_global_state);
+    struct v3_sym_local_state * local_state = &(core->sym_local_state);
 
     switch (msr) {
-       case SYM_PAGE_MSR:
-           dst->value = state->guest_pg_addr;
+       case SYMSPY_GLOBAL_MSR:
+           dst->value = global_state->global_guest_pa;
+           break;
+       case SYMSPY_LOCAL_MSR:
+           dst->value = local_state->local_guest_pa;
            break;
        default:
            return -1;
@@ -63,9 +70,9 @@ static int msr_read(uint_t msr, struct v3_msr * dst, void * priv_data) {
     return 0;
 }
 
-static int symcall_msr_read(uint_t msr, struct v3_msr * dst, void * priv_data) {
-    struct guest_info * info = (struct guest_info *)priv_data;
-    struct v3_symcall_state * state = &(info->vm_info->sym_state.symcalls[info->cpu_id]);
+static int symcall_msr_read(struct guest_info * core, uint_t msr, 
+                           struct v3_msr * dst, void * priv_data) {
+    struct v3_symcall_state * state = &(core->sym_local_state.symcall_state);
 
     switch (msr) {
        case SYMCALL_RIP_MSR:
@@ -90,34 +97,64 @@ static int symcall_msr_read(uint_t msr, struct v3_msr * dst, void * priv_data) {
     return 0;
 }
 
-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->vm_info->sym_state);
+static int symspy_msr_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
+
+    if (msr == SYMSPY_GLOBAL_MSR) {
+       struct v3_sym_global_state * global_state = &(core->vm_info->sym_global_state);
+
+       PrintDebug("Symbiotic Glbal MSR write for page %p\n", (void *)(addr_t)src.value);
+
+       if (global_state->active == 1) {
+           // unmap page
+           struct v3_shadow_region * old_reg = v3_get_shadow_region(core->vm_info, core->cpu_id, 
+                                                                    (addr_t)global_state->global_guest_pa);
+
+           if (old_reg == NULL) {
+               PrintError("Could not find previously active symbiotic page (%p)\n", 
+                          (void *)(addr_t)global_state->global_guest_pa);
+               return -1;
+           }
+
+           v3_delete_shadow_region(core->vm_info, old_reg);
+       }
+
+       global_state->global_guest_pa = src.value;
+       global_state->global_guest_pa &= ~0xfffLL;
+
+       global_state->active = 1;
 
-    if (msr == SYM_PAGE_MSR) {
-       PrintDebug("Symbiotic MSR write for page %p\n", (void *)(addr_t)src.value);
+       // map page
+       v3_add_shadow_mem(core->vm_info, V3_MEM_CORE_ANY, (addr_t)global_state->global_guest_pa, 
+                         (addr_t)(global_state->global_guest_pa + PAGE_SIZE_4KB - 1), 
+                         global_state->global_page_pa);
+    } else if (msr == SYMSPY_LOCAL_MSR) {
+       struct v3_sym_local_state * local_state = &(core->sym_local_state);
+
+       PrintDebug("Symbiotic Local MSR write for page %p\n", (void *)(addr_t)src.value);
 
-       if (state->active == 1) {
+       if (local_state->active == 1) {
            // unmap page
-           struct v3_shadow_region * old_reg = v3_get_shadow_region(info->vm_info, (addr_t)state->guest_pg_addr);
+           struct v3_shadow_region * old_reg = v3_get_shadow_region(core->vm_info, core->cpu_id,
+                                                                    (addr_t)local_state->local_guest_pa);
 
            if (old_reg == NULL) {
-               PrintError("Could not find previously active symbiotic page (%p)\n", (void *)(addr_t)state->guest_pg_addr);
+               PrintError("Could not find previously active symbiotic page (%p)\n", 
+                          (void *)(addr_t)local_state->local_guest_pa);
                return -1;
            }
 
-           v3_delete_shadow_region(info->vm_info, old_reg);
+           v3_delete_shadow_region(core->vm_info, old_reg);
        }
 
-       state->guest_pg_addr = src.value;
-       state->guest_pg_addr &= ~0xfffLL;
+       local_state->local_guest_pa = src.value;
+       local_state->local_guest_pa &= ~0xfffLL;
 
-       state->active = 1;
+       local_state->active = 1;
 
        // map page
-       v3_add_shadow_mem(info->vm_info, (addr_t)state->guest_pg_addr, 
-                         (addr_t)(state->guest_pg_addr + PAGE_SIZE_4KB - 1), 
-                         state->sym_page_pa);
+       v3_add_shadow_mem(core->vm_info, core->cpu_id, (addr_t)local_state->local_guest_pa, 
+                         (addr_t)(local_state->local_guest_pa + PAGE_SIZE_4KB - 1), 
+                         local_state->local_page_pa);
     } else {
        PrintError("Invalid Symbiotic MSR write (0x%x)\n", msr);
        return -1;
@@ -127,9 +164,8 @@ static int msr_write(uint_t msr, struct v3_msr src, void * priv_data) {
 }
 
 
-static int symcall_msr_write(uint_t msr, struct v3_msr src, void * priv_data) {
-    struct guest_info * info = (struct guest_info *)priv_data;
-    struct v3_symcall_state * state = &(info->vm_info->sym_state.symcalls[info->cpu_id]);
+static int symcall_msr_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
+    struct v3_symcall_state * state = &(core->sym_local_state.symcall_state);
 
     switch (msr) {
        case SYMCALL_RIP_MSR:
@@ -154,7 +190,7 @@ static int symcall_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, 
+static int cpuid_fn(struct guest_info * core, uint32_t cpuid, 
                    uint32_t * eax, uint32_t * ebx,
                    uint32_t * ecx, uint32_t * edx,
                    void * private_data) {
@@ -162,18 +198,18 @@ static int cpuid_fn(struct guest_info * info, uint32_t cpuid,
 
     *eax = *(uint32_t *)"V3V";
 
-    if ((v3_cpu_types[info->cpu_id] == V3_SVM_CPU) || 
-       (v3_cpu_types[info->cpu_id] == V3_SVM_REV3_CPU)) {
+    if ((v3_cpu_types[core->cpu_id] == V3_SVM_CPU) || 
+       (v3_cpu_types[core->cpu_id] == V3_SVM_REV3_CPU)) {
        *ebx = *(uint32_t *)"SVM";
-    } else if ((v3_cpu_types[info->cpu_id] == V3_VMX_CPU) || 
-              (v3_cpu_types[info->cpu_id] == V3_VMX_EPT_CPU)) {
+    } else if ((v3_cpu_types[core->cpu_id] == V3_VMX_CPU) || 
+              (v3_cpu_types[core->cpu_id] == V3_VMX_EPT_CPU)) {
        *ebx = *(uint32_t *)"VMX";
     }
 
 
     return 0;
 }
-    
+
 
 static int sym_call_ret(struct guest_info * info, uint_t hcall_id, void * private_data);
 static int sym_call_err(struct guest_info * info, uint_t hcall_id, void * private_data);
@@ -181,25 +217,25 @@ static int sym_call_err(struct guest_info * info, uint_t hcall_id, void * privat
 
 
 int v3_init_sym_iface(struct v3_vm_info * vm) {
-    struct v3_sym_state * state = &(vm->sym_state);
-    memset(state, 0, sizeof(struct v3_sym_state));
+    struct v3_sym_global_state * global_state = &(vm->sym_global_state);
+    memset(global_state, 0, sizeof(struct v3_sym_global_state));
 
-    state->sym_page_pa = (addr_t)V3_AllocPages(1);
-    state->sym_page = (struct v3_sym_interface *)V3_VAddr((void *)state->sym_page_pa);
-    memset(state->sym_page, 0, PAGE_SIZE_4KB);
+    global_state->global_page_pa = (addr_t)V3_AllocPages(1);
+    global_state->sym_page = (struct v3_sym_global_page *)V3_VAddr((void *)global_state->global_page_pa);
+    memset(global_state->sym_page, 0, PAGE_SIZE_4KB);
 
-    
-    memcpy(&(state->sym_page->magic), "V3V", 3);
+    memcpy(&(global_state->sym_page->magic), "V3V", 3);
 
-    v3_hook_msr(vm, SYM_PAGE_MSR, msr_read, msr_write, info);
+    v3_hook_msr(vm, SYMSPY_LOCAL_MSR, symspy_msr_read, symspy_msr_write, NULL);
+    v3_hook_msr(vm, SYMSPY_GLOBAL_MSR, symspy_msr_read, symspy_msr_write, NULL);
 
-    v3_hook_cpuid(vm, SYM_CPUID_NUM, cpuid_fn, info);
+    v3_hook_cpuid(vm, SYM_CPUID_NUM, cpuid_fn, NULL);
 
-    v3_hook_msr(vm, SYMCALL_RIP_MSR, symcall_msr_read, msr_write, info);
-    v3_hook_msr(vm, SYMCALL_RSP_MSR, symcall_msr_read, msr_write, info);
-    v3_hook_msr(vm, SYMCALL_CS_MSR, symcall_msr_read, msr_write, info);
-    v3_hook_msr(vm, SYMCALL_GS_MSR, symcall_msr_read, msr_write, info);
-    v3_hook_msr(vm, SYMCALL_FS_MSR, symcall_msr_read, msr_write, info);
+    v3_hook_msr(vm, SYMCALL_RIP_MSR, symcall_msr_read, symcall_msr_write, NULL);
+    v3_hook_msr(vm, SYMCALL_RSP_MSR, symcall_msr_read, symcall_msr_write, NULL);
+    v3_hook_msr(vm, SYMCALL_CS_MSR, symcall_msr_read, symcall_msr_write, NULL);
+    v3_hook_msr(vm, SYMCALL_GS_MSR, symcall_msr_read, symcall_msr_write, NULL);
+    v3_hook_msr(vm, SYMCALL_FS_MSR, symcall_msr_read, symcall_msr_write, NULL);
 
     v3_register_hypercall(vm, SYM_CALL_RET_HCALL, sym_call_ret, NULL);
     v3_register_hypercall(vm, SYM_CALL_ERR_HCALL, sym_call_err, NULL);
@@ -207,8 +243,23 @@ int v3_init_sym_iface(struct v3_vm_info * vm) {
     return 0;
 }
 
+
+int v3_init_sym_core(struct guest_info * core) {
+    struct v3_sym_local_state * local_state = &(core->sym_local_state);
+    memset(local_state, 0, sizeof(struct v3_sym_local_state));
+
+    local_state->local_page_pa = (addr_t)V3_AllocPages(1);
+    local_state->local_page = (struct v3_sym_local_page *)V3_VAddr((void *)local_state->local_page_pa);
+    memset(local_state->local_page, 0, PAGE_SIZE_4KB);
+
+    snprintf((uint8_t *)&(local_state->local_page->magic), 8, "V3V.%d", core->cpu_id);
+
+    return 0;
+}
+
+
 int v3_sym_map_pci_passthrough(struct v3_vm_info * vm, uint_t bus, uint_t dev, uint_t fn) {
-    struct v3_sym_state * state = &(vm->sym_state);
+    struct v3_sym_global_state * global_state = &(vm->sym_global_state);
     uint_t dev_index = (bus << 8) + (dev << 3) + fn;
     uint_t major = dev_index / 8;
     uint_t minor = dev_index % 8;
@@ -220,17 +271,17 @@ int v3_sym_map_pci_passthrough(struct v3_vm_info * vm, uint_t bus, uint_t dev, u
 
     PrintDebug("Setting passthrough pci map for index=%d\n", dev_index);
 
-    state->sym_page->pci_pt_map[major] |= 0x1 << minor;
+    global_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 entry=%x\n",   global_state->sym_page->pci_pt_map[major]);
 
-    PrintDebug("pt map vmm addr=%p\n", state->sym_page->pci_pt_map);
+    PrintDebug("pt map vmm addr=%p\n", global_state->sym_page->pci_pt_map);
 
     return 0;
 }
 
 int v3_sym_unmap_pci_passthrough(struct v3_vm_info * vm, uint_t bus, uint_t dev, uint_t fn) {
-    struct v3_sym_state * state = &(vm->sym_state);
+    struct v3_sym_global_state * global_state = &(vm->sym_global_state);
     uint_t dev_index = (bus << 8) + (dev << 3) + fn;
     uint_t major = dev_index / 8;
     uint_t minor = dev_index % 8;
@@ -240,20 +291,20 @@ int v3_sym_unmap_pci_passthrough(struct v3_vm_info * vm, uint_t bus, uint_t dev,
        return -1;
     }
 
-    state->sym_page->pci_pt_map[major] &= ~(0x1 << minor);
+    global_state->sym_page->pci_pt_map[major] &= ~(0x1 << minor);
 
     return 0;
 }
 
 
-static int sym_call_err(struct guest_info * info, uint_t hcall_id, void * private_data) {
-    struct v3_symcall_state * state = (struct v3_symcall_state *)&(info->sym_state.symcalls[info->cpu_id]);
+static int sym_call_err(struct guest_info * core, uint_t hcall_id, void * private_data) {
+    struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_local_state.symcall_state);
 
     PrintError("sym call error\n");
 
-    state->sym_call_errno = (int)info->vm_regs.rbx;
-    v3_print_guest_state(info);
-    v3_print_mem_map(info);
+    state->sym_call_errno = (int)core->vm_regs.rbx;
+    v3_print_guest_state(core);
+    v3_print_mem_map(core->vm_info);
 
     // clear sym flags
     state->sym_call_error = 1;
@@ -262,8 +313,8 @@ static int sym_call_err(struct guest_info * info, uint_t hcall_id, void * privat
     return -1;
 }
 
-static int sym_call_ret(struct guest_info * info, uint_t hcall_id, void * private_data) {
-    struct v3_symcall_state * state = (struct v3_symcall_state *)&(info->vm_info->sym_state.symcalls[info->cpu_id]);
+static int sym_call_ret(struct guest_info * core, uint_t hcall_id, void * private_data) {
+    struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_local_state.symcall_state);
 
     //    PrintError("Return from sym call (ID=%x)\n", hcall_id);
     //   v3_print_guest_state(info);
@@ -273,11 +324,11 @@ static int sym_call_ret(struct guest_info * info, uint_t hcall_id, void * privat
     return 0;
 }
 
-static int execute_symcall(struct guest_info * info) {
-    struct v3_symcall_state * state = (struct v3_symcall_state *)&(info->vm_info->sym_state.symcalls[info->cpu_id]);
+static int execute_symcall(struct guest_info * core) {
+    struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_local_state.symcall_state);
 
     while (state->sym_call_returned == 0) {
-       if (v3_vm_enter(info) == -1) {
+       if (v3_vm_enter(core) == -1) {
            PrintError("Error in Sym call\n");
            return -1;
        }
@@ -287,13 +338,13 @@ static int execute_symcall(struct guest_info * info) {
 }
 
 
-int v3_sym_call(struct guest_info * info, 
+int v3_sym_call(struct guest_info * core, 
                uint64_t call_num, sym_arg_t * arg0, 
                sym_arg_t * arg1, sym_arg_t * arg2,
                sym_arg_t * arg3, sym_arg_t * arg4) {
-    struct v3_sym_state * sym_state = (struct v3_sym_state *)&(info->vm_info->sym_sate);
-    struct v3_symcall_state * state = (struct v3_symcall_state *)&(sym_state->symcalls[info->cpu_id]);
-    struct v3_sym_context * old_ctx = (struct v3_sym_context *)&(state->old_ctx);
+    struct v3_sym_local_state * sym_state = (struct v3_sym_local_state *)&(core->sym_local_state);
+    struct v3_symcall_state * state = (struct v3_symcall_state *)&(sym_state->symcall_state);
+    struct v3_sym_cpu_context * old_ctx = (struct v3_sym_cpu_context *)&(state->old_ctx);
     struct v3_segment sym_cs;
     struct v3_segment sym_ss;
     uint64_t trash_args[5] = { [0 ... 4] = 0 };
@@ -301,7 +352,7 @@ int v3_sym_call(struct guest_info * info,
     //   PrintDebug("Making Sym call\n");
     //    v3_print_guest_state(info);
 
-    if ((sym_state->sym_page->sym_call_enabled == 0) ||
+    if ((sym_state->local_page->sym_call_enabled == 0) ||
        (state->sym_call_active == 1)) {
        return -1;
     }
@@ -313,45 +364,45 @@ int v3_sym_call(struct guest_info * info,
     if (!arg4) arg4 = &trash_args[4];
 
     // 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;
-    old_ctx->flags = info->ctrl_regs.rflags;
+    memcpy(&(old_ctx->vm_regs), &(core->vm_regs), sizeof(struct v3_gprs));
+    memcpy(&(old_ctx->cs), &(core->segments.cs), sizeof(struct v3_segment));
+    memcpy(&(old_ctx->ss), &(core->segments.ss), sizeof(struct v3_segment));
+    old_ctx->gs_base = core->segments.gs.base;
+    old_ctx->fs_base = core->segments.fs.base;
+    old_ctx->rip = core->rip;
+    old_ctx->cpl = core->cpl;
+    old_ctx->flags = core->ctrl_regs.rflags;
 
     // Setup the sym call context
-    info->rip = state->sym_call_rip;
-    info->vm_regs.rsp = state->sym_call_rsp; // old contest rsp is saved in vm_regs
+    core->rip = state->sym_call_rip;
+    core->vm_regs.rsp = state->sym_call_rsp; // old contest rsp is saved in vm_regs
 
-    v3_translate_segment(info, state->sym_call_cs, &sym_cs);
-    memcpy(&(info->segments.cs), &sym_cs, sizeof(struct v3_segment));
+    v3_translate_segment(core, state->sym_call_cs, &sym_cs);
+    memcpy(&(core->segments.cs), &sym_cs, sizeof(struct v3_segment));
  
-    v3_translate_segment(info, state->sym_call_cs + 8, &sym_ss);
-    memcpy(&(info->segments.ss), &sym_ss, sizeof(struct v3_segment));
+    v3_translate_segment(core, state->sym_call_cs + 8, &sym_ss);
+    memcpy(&(core->segments.ss), &sym_ss, sizeof(struct v3_segment));
 
-    info->segments.gs.base = state->sym_call_gs;
-    info->segments.fs.base = state->sym_call_fs;
-    info->cpl = 0;
+    core->segments.gs.base = state->sym_call_gs;
+    core->segments.fs.base = state->sym_call_fs;
+    core->cpl = 0;
 
-    info->vm_regs.rax = call_num;
-    info->vm_regs.rbx = *arg0;
-    info->vm_regs.rcx = *arg1;
-    info->vm_regs.rdx = *arg2;
-    info->vm_regs.rsi = *arg3;
-    info->vm_regs.rdi = *arg4;
+    core->vm_regs.rax = call_num;
+    core->vm_regs.rbx = *arg0;
+    core->vm_regs.rcx = *arg1;
+    core->vm_regs.rdx = *arg2;
+    core->vm_regs.rsi = *arg3;
+    core->vm_regs.rdi = *arg4;
 
     // Mark sym call as active
     state->sym_call_active = 1;
     state->sym_call_returned = 0;
 
     //    PrintDebug("Sym state\n");
-    //  v3_print_guest_state(info);
+    //  v3_print_guest_state(core);
 
     // Do the sym call entry
-    if (execute_symcall(info) == -1) {
+    if (execute_symcall(core) == -1) {
        PrintError("SYMCALL error\n");
        return -1;
     }
@@ -359,26 +410,26 @@ int v3_sym_call(struct guest_info * info,
     // clear sym flags
     state->sym_call_active = 0;
 
-    *arg0 = info->vm_regs.rbx;
-    *arg1 = info->vm_regs.rcx;
-    *arg2 = info->vm_regs.rdx;
-    *arg3 = info->vm_regs.rsi;
-    *arg4 = info->vm_regs.rdi;
+    *arg0 = core->vm_regs.rbx;
+    *arg1 = core->vm_regs.rcx;
+    *arg2 = core->vm_regs.rdx;
+    *arg3 = core->vm_regs.rsi;
+    *arg4 = core->vm_regs.rdi;
 
     // 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;
-    info->ctrl_regs.rflags = old_ctx->flags;
+    memcpy(&(core->vm_regs), &(old_ctx->vm_regs), sizeof(struct v3_gprs));
+    memcpy(&(core->segments.cs), &(old_ctx->cs), sizeof(struct v3_segment));
+    memcpy(&(core->segments.ss), &(old_ctx->ss), sizeof(struct v3_segment));
+    core->segments.gs.base = old_ctx->gs_base;
+    core->segments.fs.base = old_ctx->fs_base;
+    core->rip = old_ctx->rip;
+    core->cpl = old_ctx->cpl;
+    core->ctrl_regs.rflags = old_ctx->flags;
 
 
 
     //    PrintError("restoring guest state\n");
-    //    v3_print_guest_state(info);
+    //    v3_print_guest_state(core);
 
     return 0;
 }
index f3f51f1..4722fb5 100644 (file)
@@ -645,7 +645,7 @@ int v3_vmx_enter(struct guest_info * info) {
 
 
 #ifdef CONFIG_SYMBIOTIC
-    if (info->vm_info->sym_state.symcalls[info->cpu_id].sym_call_active == 0) {
+    if (info->sym_local_state.symcall_state.sym_call_active == 0) {
        update_irq_entry_state(info);
     }
 #else 
@@ -707,7 +707,7 @@ int v3_vmx_enter(struct guest_info * info) {
 
 
 #ifdef CONFIG_SYMBIOTIC
-    if (info->vm_info->sym_state.symcalls[info->cpu_id].sym_call_active == 0) {
+    if (info->sym_local_state.symcall_state.sym_call_active == 0) {
        update_irq_exit_state(info);
     }
 #else