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 pci passthrough and a few other things
Jack Lange [Thu, 10 Sep 2009 23:26:54 +0000 (18:26 -0500)]
21 files changed:
palacios/include/devices/pci.h
palacios/include/devices/pci_passthrough.h [new file with mode: 0644]
palacios/include/palacios/vmm_io.h
palacios/include/palacios/vmm_mem.h
palacios/include/palacios/vmm_sym_swap.h
palacios/src/devices/Kconfig
palacios/src/devices/Makefile
palacios/src/devices/generic.c
palacios/src/devices/i440fx.c
palacios/src/devices/ide.c
palacios/src/devices/lnx_virtio_balloon.c
palacios/src/devices/lnx_virtio_blk.c
palacios/src/devices/lnx_virtio_sym.c
palacios/src/devices/pci.c
palacios/src/devices/pci_passthrough.c [new file with mode: 0644]
palacios/src/devices/piix3.c
palacios/src/palacios/vmm_config.c
palacios/src/palacios/vmm_io.c
palacios/src/palacios/vmm_mem.c
palacios/src/palacios/vmm_sprintf.c
palacios/src/palacios/vmm_telemetry.c

index 68ac2dc..41598d4 100644 (file)
 
 
 typedef enum { PCI_BAR_IO, 
-              PCI_BAR_MEM16, 
+              PCI_BAR_MEM24, 
               PCI_BAR_MEM32, 
               PCI_BAR_MEM64_LOW, 
               PCI_BAR_MEM64_HIGH, 
+              PCI_BAR_PASSTHROUGH,
               PCI_BAR_NONE } pci_bar_type_t;
 
-typedef enum {PCI_STD_DEVICE, PCI_TO_PCI_BRIDGE, PCI_CARDBUS, PCI_MULTIFUNCTION} pci_device_type_t;
+typedef enum {PCI_STD_DEVICE, PCI_TO_PCI_BRIDGE, PCI_CARDBUS, PCI_MULTIFUNCTION, PCI_PASSTHROUGH} pci_device_type_t;
 
 
 
@@ -66,6 +67,11 @@ struct v3_pci_bar {
            int (*io_read)(ushort_t port, void * dst, uint_t length, void * private_data);
            int (*io_write)(ushort_t port, void * src, uint_t length, void * private_data);
        };
+       
+       struct {
+           int (*bar_init)(int bar_num, uint32_t * dst,void * private_data);
+           int (*bar_write)(int bar_num, uint32_t * src, void * private_data);
+       };
     };
     
     void * private_data;
@@ -78,13 +84,17 @@ struct v3_pci_bar {
 
 
 #define PCI_IO_MASK 0xfffffffc
-#define PCI_MEM32_MASK 0xfffffff0
+#define PCI_MEM_MASK 0xfffffff0
+#define PCI_MEM24_MASK 0x000ffff0
 
 #define PCI_IO_BASE(bar_val) (bar_val & PCI_IO_MASK)
-#define PCI_MEM32_BASE(bar_val) (bar_val & PCI_MEM32_MASK)
+#define PCI_MEM32_BASE(bar_val) (bar_val & PCI_MEM_MASK)
+#define PCI_MEM24_BASE(bar_val) (bar_val & PCI_MEM24_MASK)
 
 struct pci_device {
 
+    pci_device_type_t type;
+
     union {
        uint8_t config_space[256];
 
@@ -112,10 +122,14 @@ struct pci_device {
 
     struct vm_device * vm_dev;  //the corresponding virtual device
 
-    int (*config_update)(struct pci_device * pci_dev, uint_t reg_num, int length);
+    int (*config_update)(uint_t reg_num, void * src, uint_t length, void * priv_data);
+
+    int (*cmd_update)(struct pci_device * pci_dev, uchar_t io_enabled, uchar_t mem_enabled);
+    int (*ext_rom_update)(struct pci_device * pci_dev);
+
+    int (*config_write)(uint_t reg_num, void * src, uint_t length, void * private_data);
+    int (*config_read)(uint_t reg_num, void * dst, uint_t length, void * private_data);
 
-    int (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled);
-    int (*ext_rom_update)(struct pci_device *pci_dev);
 
     int ext_rom_update_flag;
     int bar_update_flag;
@@ -141,10 +155,22 @@ v3_pci_register_device(struct vm_device * pci,
                       int fn_num,
                       const char * name,
                       struct v3_pci_bar * bars,
-                      int (*config_update)(struct pci_device * pci_dev, uint_t reg_num, int length),
+                      int (*config_update)(uint_t reg_num, void * src, uint_t length, void * private_data),
                       int (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled),
                       int (*ext_rom_update)(struct pci_device *pci_dev),
-                      struct vm_device * dev);
+                      struct vm_device * dev, void * priv_data);
+
+
+struct pci_device * 
+v3_pci_register_passthrough_device(struct vm_device * pci,
+                                  int bus_num,
+                                  int dev_num,
+                                  int fn_num,
+                                  const char * name,
+                                  int (*config_write)(uint_t reg_num, void * src, uint_t length, void * private_data),
+                                  int (*config_read)(uint_t reg_num, void * dst, uint_t length, void * private_data),
+                                  struct vm_device * dev, 
+                                  void * private_data);
 
 
 #endif
diff --git a/palacios/include/devices/pci_passthrough.h b/palacios/include/devices/pci_passthrough.h
new file mode 100644 (file)
index 0000000..8ac8580
--- /dev/null
@@ -0,0 +1,36 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __DEVICES_PCI_PASSTHROUGH_H__
+#define __DEVICES_PCI_PASSTHROUGH_H__
+
+#ifdef __V3VEE__
+
+struct pci_passthrough_cfg {
+    char pci_bus_name[32];
+
+    char name[32];
+    uint16_t   vendor_id;
+    uint16_t   device_id;
+};
+
+
+#endif
+
+#endif
index e2f4be5..1ceff4d 100644 (file)
@@ -38,12 +38,12 @@ void v3_init_io_map(struct guest_info * info);
 
 
 /* External API */
-int v3_hook_io_port(struct guest_info * info, uint_t port, 
+int v3_hook_io_port(struct guest_info * info, uint16_t port, 
                    int (*read)(uint16_t port, void * dst, uint_t length, void * priv_data),
                    int (*write)(uint16_t port, void * src, uint_t length, void * priv_data), 
                    void * priv_data);
 
-int v3_unhook_io_port(struct guest_info * info, uint_t port);
+int v3_unhook_io_port(struct guest_info * info, uint16_t port);
 
 
 
@@ -74,7 +74,7 @@ struct v3_io_map {
     void * arch_data;
 };
 
-struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint_t port);
+struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint16_t port);
 
 
 void v3_print_io_map(struct guest_info * info);
index 927577e..553497d 100644 (file)
@@ -114,7 +114,7 @@ addr_t v3_get_shadow_addr(struct v3_shadow_region * reg, addr_t guest_addr);
 
 
 
-void print_shadow_map(struct guest_info * info);
+void v3_print_mem_map(struct guest_info * info);
 
 
 
index 4e5f9cc..5f09c3b 100644 (file)
@@ -55,8 +55,8 @@ struct v3_sym_swap_state {
     struct hashtable * shdw_ptr_ht;
 };
 
-
-
+// Present = 0 and Dirty = 0
+// fixme
 static inline int is_swapped_pte32(pte32_t * pte) {
     return ((pte->present == 0) && (*(uint32_t *)pte != 0));
 }
index 6f63f23..dde39ab 100644 (file)
@@ -199,6 +199,13 @@ config PCI
        help
          Includes the Virtual PCI Bus
 
+config PASSTHROUGH_PCI
+       bool "Passthrough PCI"
+       default y 
+       depends on PCI && EXPERIMENTAL
+       help 
+         Enables hardware devices to be passed through to the VM
+
 config DEBUG_PCI
        bool "PCI debugging"
        depends on PCI && DEBUG_ON
index f720996..0e716aa 100644 (file)
@@ -25,3 +25,5 @@ obj-$(CONFIG_NET_HD) += net_hd.o
 
 obj-$(CONFIG_CGA) += cga.o
 obj-$(CONFIG_TELNET_CONSOLE) += telnet_cons.o
+
+obj-$(CONFIG_PASSTHROUGH_PCI) += pci_passthrough.o
\ No newline at end of file
index fbeff20..c6dd8d6 100644 (file)
@@ -92,11 +92,11 @@ static int generic_write_port_passthrough(uint16_t port, void * src,
            v3_outw(port,((uint16_t*)src)[0]);
            break;
        case 4:
-           v3_outdw(port,((uint_t*)src)[0]);
+           v3_outdw(port,((uint32_t *)src)[0]);
            break;
        default:
            for (i = 0; i < length; i++) { 
-               v3_outb(port, ((uchar_t*)src)[i]);
+               v3_outb(port, ((uchar_t *)src)[i]);
            }
     }
 
index 2408cdd..da26d6b 100644 (file)
@@ -94,7 +94,7 @@ static int i440_init(struct guest_info * vm, void * cfg_data) {
 
     pci_dev = v3_pci_register_device(state->pci, PCI_STD_DEVICE, 
                                     0, 0, 0, "i440FX", bars,
-                                    NULL, NULL, NULL, dev);
+                                    NULL, NULL, NULL, dev, NULL);
 
     if (!pci_dev) {
        return -1;
index 1776e9c..b1c13a6 100644 (file)
@@ -1397,7 +1397,7 @@ static void init_channel(struct ide_channel * channel) {
 }
 
 
-static int pci_config_update(struct pci_device * pci_dev, uint_t reg_num, int length) {
+static int pci_config_update(uint_t reg_num, void * src, uint_t length, void * private_data) {
     PrintDebug("PCI Config Update\n");
     PrintDebug("\t\tInterupt register (Dev=%s), irq=%d\n", pci_dev->name, pci_dev->config_header.intr_line);
 
@@ -1566,7 +1566,7 @@ static int ide_init(struct guest_info * vm, void * cfg_data) {
 
        pci_dev = v3_pci_register_device(ide->pci_bus, PCI_STD_DEVICE, 0, sb_pci->dev_num, 1, 
                                         "PIIX3_IDE", bars,
-                                        pci_config_update, NULL, NULL, dev);
+                                        pci_config_update, NULL, NULL, dev, dev);
 
        if (pci_dev == NULL) {
            PrintError("Failed to register IDE BUS %d with PCI\n", i); 
index fed0c83..e7a18aa 100644 (file)
@@ -481,7 +481,7 @@ static int virtio_init(struct guest_info * vm, void * cfg_data) {
        pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
                                         0, PCI_AUTO_DEV_NUM, 0,
                                         "LNX_VIRTIO_BALLOON", bars,
-                                        NULL, NULL, NULL, dev);
+                                        NULL, NULL, NULL, dev, NULL);
 
        if (!pci_dev) {
            PrintError("Could not register PCI Device\n");
index f71b559..0059fb6 100644 (file)
@@ -628,7 +628,7 @@ static int virtio_init(struct guest_info * vm, void * cfg_data) {
        pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
                                         0, PCI_AUTO_DEV_NUM, 0,
                                         "LNX_VIRTIO_BLK", bars,
-                                        NULL, NULL, NULL, dev);
+                                        NULL, NULL, NULL, dev, NULL);
 
        if (!pci_dev) {
            PrintError("Could not register PCI Device\n");
index 8f4401e..ad5cbbd 100644 (file)
@@ -414,7 +414,7 @@ static int virtio_init(struct guest_info * vm, void * cfg_data) {
        pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
                                         0, PCI_AUTO_DEV_NUM, 0,
                                         "LNX_VIRTIO_SYM", bars,
-                                        NULL, NULL, NULL, dev);
+                                        NULL, NULL, NULL, dev, NULL);
 
        if (!pci_dev) {
            PrintError("Could not register PCI Device\n");
index b65aefc..49ed5d5 100644 (file)
@@ -323,6 +323,15 @@ static int data_port_read(ushort_t port, void * dst, uint_t length, struct vm_de
        return length;
     }
 
+    if (pci_dev->type == PCI_PASSTHROUGH) {
+       if (pci_dev->config_read(reg_num, dst, length, pci_dev->priv_data) == -1) {
+           PrintError("Failed to handle configuration update for passthrough pci_device\n");
+           return -1;
+       }
+       
+       return 0;
+    }
+
     for (i = 0; i < length; i++) {
        *(uint8_t *)((uint8_t *)dst + i) = pci_dev->config_space[reg_num + i];
     }
@@ -414,6 +423,7 @@ static int bar_update(struct pci_device * pci, int bar_num, uint32_t new_val) {
 
                    PrintError("Could not hook PCI IO port (old port=%u) (new port=%u)\n",  
                               PCI_IO_BASE(bar->val) + i, PCI_IO_BASE(new_val) + i);
+                   v3_print_io_map(pci->vm_dev->vm);
                    return -1;
                }
            }
@@ -463,7 +473,7 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d
        return length;
     }
 
-    PrintDebug("Writing PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (%x) addr_reg = %x (val=%x, len=%d)\n", 
+    PrintDebug("Writing PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (0x%x) addr_reg = 0x%x (val=0x%x, len=%d)\n", 
               pci_state->addr_reg.bus_num, 
               pci_state->addr_reg.dev_num, 
               pci_state->addr_reg.fn_num,
@@ -480,6 +490,15 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d
        return -1;
     }
     
+    if (pci_dev->type == PCI_PASSTHROUGH) {
+       if (pci_dev->config_write(reg_num, src, length, pci_dev->priv_data) == -1) {
+           PrintError("Failed to handle configuration update for passthrough pci_device\n");
+           return -1;
+       }
+       
+       return 0;
+    }
+
 
     for (i = 0; i < length; i++) {
        uint_t cur_reg = reg_num + i;
@@ -530,7 +549,7 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d
     }
 
     if (pci_dev->config_update) {
-       pci_dev->config_update(pci_dev, reg_num, length);
+       pci_dev->config_update(reg_num, src, length, pci_dev->priv_data);
     }
 
     // Scan for BAR updated
@@ -539,13 +558,22 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d
            if (pci_dev->bar[i].updated) {
                int bar_offset = 0x10 + 4 * i;
 
-               *(uint32_t *)(pci_dev->config_space + bar_offset) &= pci_dev->bar[i].mask;
-               // check special flags....
 
-               // bar_update
-               if (bar_update(pci_dev, i, *(uint32_t *)(pci_dev->config_space + bar_offset)) == -1) {
-                   PrintError("PCI Device %s: Bar update Error Bar=%d\n", pci_dev->name, i);
-                   return -1;
+               if (pci_dev->bar[i].type == PCI_BAR_PASSTHROUGH) {
+                   if (pci_dev->bar[i].bar_write(i, (uint32_t *)(pci_dev->config_space + bar_offset), pci_dev->bar[i].private_data) == -1) {
+                       PrintError("Error in passthrough bar write operation\n");
+                       return -1;
+                   }
+               } else {
+
+                   *(uint32_t *)(pci_dev->config_space + bar_offset) &= pci_dev->bar[i].mask;
+                   // check special flags....
+
+                   // bar_update
+                   if (bar_update(pci_dev, i, *(uint32_t *)(pci_dev->config_space + bar_offset)) == -1) {
+                       PrintError("PCI Device %s: Bar update Error Bar=%d\n", pci_dev->name, i);
+                       return -1;
+                   }
                }
 
                pci_dev->bar[i].updated = 0;
@@ -718,13 +746,18 @@ static inline int init_bars(struct pci_device * pci_dev) {
 
            *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
 
-       } else if (pci_dev->bar[i].type == PCI_BAR_MEM16) {
+       } else if (pci_dev->bar[i].type == PCI_BAR_MEM24) {
            PrintError("16 Bit memory ranges not supported (reg: %d)\n", i);
            return -1;
        } else if (pci_dev->bar[i].type == PCI_BAR_NONE) {
            pci_dev->bar[i].val = 0x00000000;
            pci_dev->bar[i].mask = 0x00000000; // This ensures that all updates will be dropped
            *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
+       } else if (pci_dev->bar[i].type == PCI_BAR_PASSTHROUGH) {
+
+           // Call the bar init function to get the local cached value
+           pci_dev->bar[i].bar_init(i, &(pci_dev->bar[i].val), pci_dev->bar[i].private_data);
+
        } else {
            PrintError("Invalid BAR type for bar #%d\n", i);
            return -1;
@@ -771,10 +804,10 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
                                           int fn_num,
                                           const char * name,
                                           struct v3_pci_bar * bars,
-                                          int (*config_update)(struct pci_device * pci_dev, uint_t reg_num, int length),
+                                          int (*config_update)(uint_t reg_num, void * src, uint_t length, void * priv_data),
                                           int (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled),
                                           int (*ext_rom_update)(struct pci_device * pci_dev),
-                                          struct vm_device * dev) {
+                                          struct vm_device * dev, void * priv_data) {
 
     struct pci_internal * pci_state = (struct pci_internal *)pci->private_data;
     struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
@@ -812,8 +845,10 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
 
     memset(pci_dev, 0, sizeof(struct pci_device));
 
+
+    pci_dev->type = dev_type;
     
-    switch (dev_type) {
+    switch (pci_dev->type) {
        case PCI_STD_DEVICE:
            pci_dev->config_header.header_type = 0x00;
            break;
@@ -825,12 +860,15 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
            return NULL;
     }
 
+
+
     pci_dev->bus_num = bus_num;
     pci_dev->dev_num = dev_num;
     pci_dev->fn_num = fn_num;
 
     strncpy(pci_dev->name, name, sizeof(pci_dev->name));
     pci_dev->vm_dev = dev;
+    pci_dev->priv_data = priv_data;
 
     // register update callbacks
     pci_dev->config_update = config_update;
@@ -862,6 +900,9 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
            pci_dev->bar[i].default_base_addr = bars[i].default_base_addr;
            pci_dev->bar[i].mem_read = bars[i].mem_read;
            pci_dev->bar[i].mem_write = bars[i].mem_write;
+       } else if (pci_dev->bar[i].type == PCI_BAR_PASSTHROUGH) {
+           pci_dev->bar[i].bar_init = bars[i].bar_init;
+           pci_dev->bar[i].bar_write = bars[i].bar_write;
        } else {
            pci_dev->bar[i].num_pages = 0;
            pci_dev->bar[i].default_base_addr = 0;
@@ -884,3 +925,73 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
 
     return pci_dev;
 }
+
+
+
+// if dev_num == -1, auto assign 
+struct pci_device * v3_pci_register_passthrough_device(struct vm_device * pci,
+                                                      int bus_num,
+                                                      int dev_num,
+                                                      int fn_num,
+                                                      const char * name,
+                                                      int (*config_write)(uint_t reg_num, void * src, uint_t length, void * private_data),
+                                                      int (*config_read)(uint_t reg_num, void * dst, uint_t length, void * private_data),
+                                                      struct vm_device * dev,
+                                                      void * private_data) {
+
+    struct pci_internal * pci_state = (struct pci_internal *)pci->private_data;
+    struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
+    struct pci_device * pci_dev = NULL;
+
+    if (dev_num > MAX_BUS_DEVICES) {
+       PrintError("Requested Invalid device number (%d)\n", dev_num);
+       return NULL;
+    }
+
+    if (dev_num == PCI_AUTO_DEV_NUM) {
+       PrintDebug("Searching for free device number\n");
+       if ((dev_num = get_free_dev_num(bus)) == -1) {
+           PrintError("No more available PCI slots on bus %d\n", bus->bus_num);
+           return NULL;
+       }
+    }
+    
+    PrintDebug("Checking for PCI Device\n");
+
+    if (get_device(bus, dev_num, fn_num) != NULL) {
+       PrintError("PCI Device already registered at slot %d on bus %d\n", 
+                  dev_num, bus->bus_num);
+       return NULL;
+    }
+
+    
+    pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
+
+    if (pci_dev == NULL) {
+       PrintError("Could not allocate pci device\n");
+       return NULL;
+    }
+
+    memset(pci_dev, 0, sizeof(struct pci_device));
+    
+    pci_dev->bus_num = bus_num;
+    pci_dev->dev_num = dev_num;
+    pci_dev->fn_num = fn_num;
+
+    strncpy(pci_dev->name, name, sizeof(pci_dev->name));
+    pci_dev->vm_dev = dev;
+    pci_dev->priv_data = private_data;
+
+    // register update callbacks
+    pci_dev->config_write = config_write;
+    pci_dev->config_read = config_read;
+
+    // add the device
+    add_device_to_bus(bus, pci_dev);
+
+#ifdef CONFIG_DEBUG_PCI
+    pci_dump_state(pci_state);
+#endif
+
+    return pci_dev;
+}
diff --git a/palacios/src/devices/pci_passthrough.c b/palacios/src/devices/pci_passthrough.c
new file mode 100644 (file)
index 0000000..5c5a468
--- /dev/null
@@ -0,0 +1,565 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+/* This is the generic passthrough PCI virtual device */
+
+/* 
+ * The basic idea is that we do not change the hardware PCI configuration
+ * Instead we modify the guest environment to map onto the physical configuration
+ * 
+ * The pci subsystem handles most of the configuration space, except for the bar registers.
+ * We handle them here, by either letting them go directly to hardware or remapping through virtual hooks
+ * 
+ * Memory Bars are always remapped via the shadow map, 
+ * IO Bars are selectively remapped through hooks if the guest changes them 
+ */
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_dev_mgr.h>
+#include <palacios/vmm_sprintf.h>
+#include <palacios/vmm_lowlevel.h>
+
+
+#include <devices/pci.h>
+#include <devices/pci_types.h>
+#include <devices/pci_passthrough.h>
+
+
+// Hardcoded... Are these standard??
+#define PCI_CFG_ADDR    0xcf8
+#define PCI_CFG_DATA    0xcfc
+
+#define PCI_BUS_MAX  4
+#define PCI_DEV_MAX 32
+#define PCI_FN_MAX   7
+
+#define PCI_DEVICE 0x0
+#define PCI_PCI_BRIDGE 0x1
+#define PCI_CARDBUS_BRIDGE 0x2
+
+#define PCI_HDR_SIZE 256
+
+
+union pci_addr_reg {
+    uint32_t value;
+    struct {
+       uint_t rsvd1   : 2;
+       uint_t reg     : 6;
+       uint_t func    : 3;
+       uint_t dev     : 5;
+       uint_t bus     : 8;
+       uint_t rsvd2   : 7;
+       uint_t enable  : 1;
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+typedef enum { PT_BAR_NONE,
+              PT_BAR_IO, 
+              PT_BAR_MEM32, 
+              PT_BAR_MEM24, 
+              PT_BAR_MEM64_LOW, 
+              PT_BAR_MEM64_HIGH } pt_bar_type_t;
+
+struct pt_bar {
+    uint32_t size;
+    pt_bar_type_t type;
+    uint32_t addr;
+
+    uint32_t val;
+};
+
+struct pt_dev_state {
+    union {
+       uint8_t config_space[256];
+       struct pci_config_header real_hdr;
+    } __attribute__((packed));
+
+    struct pt_bar phys_bars[6];
+    struct pt_bar virt_bars[6];
+
+    
+    struct vm_device * pci_bus;
+    struct pci_device * pci_dev;
+
+    union pci_addr_reg phys_pci_addr;
+
+    char name[32];
+};
+
+
+static inline uint32_t pci_cfg_read32(uint32_t addr) {
+    v3_outdw(PCI_CFG_ADDR, addr);
+    return v3_indw(PCI_CFG_DATA);
+}
+
+
+
+static inline void pci_cfg_write32(uint32_t addr, uint32_t val) {
+    v3_outdw(PCI_CFG_ADDR, addr);
+    v3_outdw(PCI_CFG_DATA, val);
+}
+
+
+
+static inline uint16_t pci_cfg_read16(uint32_t addr) {
+    v3_outw(PCI_CFG_ADDR, addr);
+    return v3_inw(PCI_CFG_DATA);
+}
+
+
+
+static inline void pci_cfg_write16(uint32_t addr, uint16_t val) {
+    v3_outw(PCI_CFG_ADDR, addr);
+    v3_outw(PCI_CFG_DATA, val);
+}
+
+
+
+static inline uint8_t pci_cfg_read8(uint32_t addr) {
+    v3_outb(PCI_CFG_ADDR, addr);
+    return v3_inb(PCI_CFG_DATA);
+}
+
+
+
+static inline void pci_cfg_write8(uint32_t addr, uint8_t val) {
+    v3_outb(PCI_CFG_ADDR, addr);
+    v3_outb(PCI_CFG_DATA, val);
+}
+
+
+// We initialize this 
+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;
+    union pci_addr_reg pci_addr = {state->phys_pci_addr.value};
+    uint32_t bar_val = 0;
+    uint32_t max_val = 0;
+    //addr_t irq_state = 0;
+    struct pt_bar * pbar = &(state->phys_bars[bar_num]);
+
+
+    // should read from cached header
+    pci_addr.reg = bar_base_reg + bar_num;
+
+    PrintDebug("PCI Address = 0x%x\n", pci_addr.value);
+
+    bar_val = pci_cfg_read32(pci_addr.value);
+    pbar->val = bar_val;
+
+    if ((bar_val & 0x3) == 0x1) {
+       int i = 0;
+
+       // IO bar
+       pbar->type = PT_BAR_IO;
+       pbar->addr = PCI_IO_BASE(bar_val);
+
+       max_val = bar_val | PCI_IO_MASK;
+
+       // Cycle the physical bar, to determine the actual size
+       // Disable irqs, to try to prevent accesses to the space via a interrupt handler
+       // This is not SMP safe!!
+       // What we probably want to do is write a 0 to the command register
+       //irq_state = v3_irq_save();
+       
+       pci_cfg_write32(pci_addr.value, max_val);
+       max_val = pci_cfg_read32(pci_addr.value);
+       pci_cfg_write32(pci_addr.value, bar_val);
+
+       //v3_irq_restore(irq_state);
+
+       pbar->size = ~PCI_IO_BASE(max_val) + 1;
+
+       
+       // setup a set of null io hooks
+       // This allows the guest to do passthrough IO to these ports
+       // While still reserving them in the IO map
+       for (i = 0; i < pbar->size; i++) {
+           v3_hook_io_port(dev->vm, pbar->addr + i, NULL, NULL, NULL); 
+       }
+
+    } else {
+
+       // might be memory, might be nothing    
+
+       max_val = bar_val | PCI_MEM_MASK;
+
+       // Cycle the physical bar, to determine the actual size
+       // Disable irqs, to try to prevent accesses to the space via a interrupt handler
+       // This is not SMP safe!!
+       // What we probably want to do is write a 0 to the command register
+       //irq_state = v3_irq_save();
+       
+       pci_cfg_write32(pci_addr.value, max_val);
+       max_val = pci_cfg_read32(pci_addr.value);
+       pci_cfg_write32(pci_addr.value, bar_val);
+
+       //v3_irq_restore(irq_state);
+
+       
+       if (max_val == 0) {
+           pbar->type = PT_BAR_NONE;
+       } else {
+
+           // if its a memory region, setup passthrough mem mapping
+
+           if ((bar_val & 0x6) == 0x0) {
+               // MEM 32
+               pbar->type = PT_BAR_MEM32;
+               pbar->addr = PCI_MEM32_BASE(bar_val);
+               pbar->size = ~PCI_MEM32_BASE(max_val) + 1;
+
+               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, 
+                                 pbar->addr, 
+                                 pbar->addr + pbar->size - 1,
+                                 pbar->addr);
+
+           } else if ((bar_val & 0x6) == 0x2) {
+               // Mem 24
+               pbar->type = PT_BAR_MEM24;
+               pbar->addr = PCI_MEM24_BASE(bar_val);
+               pbar->size = ~PCI_MEM24_BASE(max_val) + 1;
+
+               v3_add_shadow_mem(dev->vm, 
+                                 pbar->addr, 
+                                 pbar->addr + pbar->size - 1,
+                                 pbar->addr);
+
+           } else if ((bar_val & 0x6) == 0x4) {
+               // Mem 64
+               PrintError("64 Bit PCI bars not supported\n");
+               return -1;
+           } else {
+               PrintError("Invalid Memory bar type\n");
+               return -1;
+           }
+
+       }
+    }
+    
+
+
+
+    // Initially the virtual bars match the physical ones
+    memcpy(&(state->virt_bars[bar_num]), &(state->phys_bars[bar_num]), sizeof(struct pt_bar));
+
+    PrintDebug("bar_num=%d, bar_val=0x%x\n", bar_num, bar_val);
+
+    PrintDebug("phys bar  type=%d, addr=0x%x, size=%d\n", 
+              pbar->type, pbar->addr, 
+              pbar->size);
+
+    PrintDebug("virt bar  type=%d, addr=0x%x, size=%d\n",
+              state->virt_bars[bar_num].type, state->virt_bars[bar_num].addr, 
+              state->virt_bars[bar_num].size);
+
+
+
+    // Update the pci subsystem versions
+    *dst = bar_val;
+
+    return 0;
+}
+
+static int pt_io_read(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;
+
+    if (length == 1) {
+       *(uint8_t *)dst = v3_inb(pbar->addr + port_offset);
+    } else if (length == 2) {
+       *(uint16_t *)dst = v3_inw(pbar->addr + port_offset);
+    } else if (length == 4) {
+       *(uint32_t *)dst = v3_indw(pbar->addr + port_offset);
+    } else {
+       PrintError("Invalid PCI passthrough IO Redirection size read\n");
+       return -1;
+    }
+
+    return length;
+}
+
+
+static int pt_io_write(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;
+    
+    if (length == 1) {
+       v3_outb(pbar->addr + port_offset, *(uint8_t *)src);
+    } else if (length == 2) {
+       v3_outw(pbar->addr + port_offset, *(uint16_t *)src);
+    } else if (length == 4) {
+       v3_outdw(pbar->addr + port_offset, *(uint32_t *)src);
+    } else {
+       PrintError("Invalid PCI passthrough IO Redirection size write\n");
+       return -1;
+    }
+    
+    return length;
+
+}
+
+
+
+
+
+static int pci_bar_write(int bar_num, uint32_t * src, void * private_data) {
+    struct vm_device * dev = (struct vm_device *)private_data;
+    struct pt_dev_state * state = (struct pt_dev_state *)dev->private_data;
+    
+    struct pt_bar * pbar = &(state->phys_bars[bar_num]);
+    struct pt_bar * vbar = &(state->virt_bars[bar_num]);
+
+    PrintDebug("Bar update src=0x%x\n", *src);
+
+    if (vbar->type == PT_BAR_NONE) {
+       return 0;
+    } else if (vbar->type == PT_BAR_IO) {
+       int i = 0;
+
+       // unhook old ports
+       for (i = 0; i < vbar->size; i++) {
+           if (v3_unhook_io_port(dev->vm, vbar->addr + i) == -1) {
+               PrintError("Could not unhook previously hooked port.... %d (0x%x)\n", 
+                          vbar->addr + i, vbar->addr + i);
+               return -1;
+           }
+       }
+
+       PrintDebug("Setting IO Port range size=%d\n", pbar->size);
+
+       // clear the low bits to match the size
+       *src &= ~(pbar->size - 1);
+
+       // Set reserved bits
+       *src |= (pbar->val & ~PCI_IO_MASK);
+
+       vbar->addr = PCI_IO_BASE(*src); 
+
+       PrintDebug("Cooked src=0x%x\n", *src);
+
+       PrintDebug("Rehooking passthrough IO ports starting at %d (0x%x)\n", 
+                  vbar->addr, vbar->addr);
+
+       if (vbar->addr == pbar->addr) {
+           // Map the io ports as passthrough
+           for (i = 0; i < pbar->size; i++) {
+               v3_hook_io_port(dev->vm, pbar->addr + i, NULL, NULL, NULL); 
+           }
+       } else {
+           // We have to manually handle the io redirection
+           for (i = 0; i < vbar->size; i++) {
+               v3_hook_io_port(dev->vm, vbar->addr + i, pt_io_read, pt_io_write, pbar); 
+           }
+       }
+    } else if (vbar->type == PT_BAR_MEM32) {
+       // remove old mapping
+       struct v3_shadow_region * old_reg = v3_get_shadow_region(dev->vm, vbar->addr);
+
+       if (old_reg == NULL) {
+           // uh oh...
+           PrintError("Could not find PCI Passthrough memory redirection region (addr=0x%x)\n", vbar->addr);
+           return -1;
+       }
+
+       v3_delete_shadow_region(dev->vm, old_reg);
+
+       // clear the low bits to match the size
+       *src &= ~(pbar->size - 1);
+
+       // Set reserved bits
+       *src |= (pbar->val & ~PCI_MEM_MASK);
+
+       PrintDebug("Cooked src=0x%x\n", *src);
+
+       vbar->addr = PCI_MEM32_BASE(*src);
+
+       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, 
+                         vbar->addr, 
+                         vbar->addr + vbar->size - 1,
+                         pbar->addr);
+       
+    } else {
+       PrintError("Unhandled Pasthrough PCI Bar type %d\n", vbar->type);
+       return -1;
+    }
+
+
+    vbar->val = *src;
+    
+
+    return 0;
+}
+
+
+static int pt_config_update(uint_t reg_num, void * src, uint_t length, void * private_data) {
+    struct vm_device * dev = (struct vm_device *)private_data;
+    struct pt_dev_state * state = (struct pt_dev_state *)dev->private_data;
+    union pci_addr_reg pci_addr = {state->phys_pci_addr.value};
+
+    pci_addr.reg = reg_num;
+
+    if (length == 1) {
+       pci_cfg_write8(pci_addr.value, *(uint8_t *)src);
+    } else if (length == 2) {
+       pci_cfg_write16(pci_addr.value, *(uint16_t *)src);
+    } else if (length == 4) {
+       pci_cfg_write32(pci_addr.value, *(uint32_t *)src);      
+    }
+
+    
+    return 0;
+}
+
+
+
+static int find_real_pci_dev(uint16_t vendor_id, uint16_t device_id, struct pt_dev_state * state) {
+    union pci_addr_reg pci_addr = {0x80000000};
+    uint_t i, j, k, m;    
+
+    union {
+       uint32_t value;
+       struct {
+           uint16_t vendor;
+           uint16_t device;
+       } __attribute__((packed));
+    } __attribute__((packed)) pci_hdr = {0};
+
+
+
+    for (i = 0, pci_addr.bus = 0; i < PCI_BUS_MAX; i++, pci_addr.bus++) {
+       for (j = 0, pci_addr.dev = 0; j < PCI_DEV_MAX; j++, pci_addr.dev++) {
+           for (k = 0, pci_addr.func = 0; k < PCI_FN_MAX; k++, pci_addr.func++) {
+
+               v3_outdw(PCI_CFG_ADDR, pci_addr.value);
+               pci_hdr.value = v3_indw(PCI_CFG_DATA);
+
+               if ((pci_hdr.vendor == vendor_id) && (pci_hdr.device == device_id)) {
+                   uint32_t * cfg_space = (uint32_t *)&state->real_hdr;
+    
+                   state->phys_pci_addr = pci_addr;
+
+                   // Copy the configuration space to the local cached version
+                   for (m = 0, pci_addr.reg = 0; m < PCI_HDR_SIZE; m += 4, pci_addr.reg++) {
+                       cfg_space[pci_addr.reg] = pci_cfg_read32(pci_addr.value);
+                   }
+
+
+                   PrintDebug("Found device %x:%x (bus=%d, dev=%d, func=%d)\n", 
+                              vendor_id, device_id, 
+                              pci_addr.bus, pci_addr.dev, pci_addr.func);
+
+                   return 0;
+               }
+           }
+       }
+    }
+
+    return -1;
+}
+
+
+
+static int setup_virt_pci_dev(struct guest_info * 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];
+    int bus_num = 0;
+    int i;
+
+    for (i = 0; i < 6; i++) {
+       bars[i].type = PCI_BAR_PASSTHROUGH;
+       bars[i].private_data = dev;
+       bars[i].bar_init = pci_bar_init;
+       bars[i].bar_write = pci_bar_write;
+    }
+
+    pci_dev = v3_pci_register_device(state->pci_bus,
+                                    PCI_STD_DEVICE,
+                                    bus_num, -1, 0, 
+                                    state->name, bars,
+                                    pt_config_update, NULL, NULL, 
+                                    dev, dev);
+    
+    // This will overwrite the bar registers.. but that should be ok.
+    memcpy(pci_dev->config_space, (uint8_t *)&(state->real_hdr), sizeof(struct pci_config_header));
+
+    return 0;
+}
+
+
+static struct v3_device_ops dev_ops = {
+    .free = NULL,
+    .reset = NULL,
+    .start = NULL,
+    .stop = NULL,
+};
+
+
+
+static int passthrough_init(struct guest_info * info, void * cfg_data) {
+    struct pci_passthrough_cfg * cfg = (struct pci_passthrough_cfg *)cfg_data;
+    struct pt_dev_state * state = V3_Malloc(sizeof(struct pt_dev_state));
+    struct vm_device * dev = NULL;
+    struct vm_device * pci = v3_find_dev(info, cfg->pci_bus_name);
+    
+
+    memset(state, 0, sizeof(struct pt_dev_state));
+
+    if (!pci) {
+       PrintError("Could not find PCI device\n");
+       return -1;
+    }
+    
+    state->pci_bus = pci;
+    strncpy(state->name, cfg->name, 32);
+
+
+
+    dev = v3_allocate_device("PCI_PASSTHROUGH", &dev_ops, state);
+
+    if (v3_attach_device(info, dev) == -1) {
+       PrintError("Could not attach device %s\n", "PCI_PASSTHROUGH");
+       return -1;
+    }
+
+
+    if (find_real_pci_dev(cfg->vendor_id, cfg->device_id, state) == -1) {
+       PrintError("Could not find PCI Device %x:%x\n", cfg->vendor_id, cfg->device_id);
+       return 0;
+    }
+
+    setup_virt_pci_dev(info, dev);
+
+    return 0;
+}
+
+
+
+
+device_register("PCI_PASSTHROUGH", passthrough_init)
index 8b2f627..9a69ed0 100644 (file)
@@ -421,7 +421,7 @@ static int setup_pci(struct vm_device * dev) {
     pci_dev = v3_pci_register_device(piix3->pci_bus, PCI_MULTIFUNCTION, 
                                     bus_num, -1, 0, 
                                     "PIIX3", bars, 
-                                    NULL, NULL, NULL, dev);
+                                    NULL, NULL, NULL, dev, NULL);
     if (pci_dev == NULL) {
        PrintError("Could not register PCI Device for PIIX3\n");
        return -1;
index c728223..ed54ab5 100644 (file)
@@ -31,7 +31,6 @@
 #include <palacios/vmm_sym_swap.h>
 #endif
 
-
 #include <devices/generic.h>
 #include <devices/ide.h>
 #include <devices/ram_cd.h>
@@ -40,6 +39,7 @@
 #include <devices/net_hd.h>
 
 #include <devices/telnet_cons.h>
+#include <devices/pci_passthrough.h>
 
 
 
@@ -227,7 +227,7 @@ static int setup_memory_map(struct guest_info * info, struct v3_vm_config * conf
     }
 #endif
 
-    print_shadow_map(info);
+    v3_print_mem_map(info);
 
     return 0;
 }
@@ -254,6 +254,7 @@ 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};
        
        v3_create_device(info, "PCI", NULL);
        v3_create_device(info, "i440FX", "PCI");
@@ -266,6 +267,9 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_
        v3_create_device(info, "SYM_SWAP", "LNX_VIRTIO_BLK");
 
        v3_create_device(info, "IDE", &ide_config);
+       
+       v3_create_device(info, "PCI_PASSTHROUGH", &pci_pt_cfg);
+
     } else {
        v3_create_device(info, "IDE", NULL);
     }
index 4dbd61d..c5cdb59 100644 (file)
@@ -81,7 +81,7 @@ static inline struct v3_io_hook * insert_io_hook(struct guest_info * info, struc
 }
 
 
-struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint_t port) {
+struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint16_t port) {
   struct rb_node * n = info->io_map.map.rb_node;
   struct v3_io_hook * hook = NULL;
 
@@ -105,7 +105,7 @@ struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint_t port) {
 
 
 
-int v3_hook_io_port(struct guest_info * info, uint_t port, 
+int v3_hook_io_port(struct guest_info * info, uint16_t port, 
                    int (*read)(uint16_t port, void * dst, uint_t length, void * priv_data),
                    int (*write)(uint16_t port, void * src, uint_t length, void * priv_data), 
                    void * priv_data) {
@@ -129,7 +129,7 @@ int v3_hook_io_port(struct guest_info * info, uint_t port,
   io_hook->priv_data = priv_data;
 
   if (insert_io_hook(info, io_hook)) {
-      PrintError("Could not insert IO hook for port %d\n", port);
+      PrintError("Could not insert IO hook for port %u (0x%x)\n", port, port);
       V3_Free(io_hook);
       return -1;
   }
@@ -138,7 +138,7 @@ int v3_hook_io_port(struct guest_info * info, uint_t port,
   if (info->io_map.update_map(info, port, 
                              ((read == NULL) ? 0 : 1), 
                              ((write == NULL) ? 0 : 1)) == -1) {
-      PrintError("Could not update IO map for port %d\n", port);
+      PrintError("Could not update IO map for port %u (0x%x)\n", port, port);
       V3_Free(io_hook);
       return -1;
   }
@@ -147,21 +147,22 @@ int v3_hook_io_port(struct guest_info * info, uint_t port,
   return 0;
 }
 
-int v3_unhook_io_port(struct guest_info * info, uint_t port) {
-  struct v3_io_hook * hook = v3_get_io_hook(info, port);
+int v3_unhook_io_port(struct guest_info * info, uint16_t port) {
+    struct v3_io_hook * hook = v3_get_io_hook(info, port);
 
-  if (hook == NULL) {
-    return -1;
-  }
+    if (hook == NULL) {
+       PrintError("Could not find port to unhook %u (0x%x)\n", port, port);
+       return -1;
+    }
 
-  v3_rb_erase(&(hook->tree_node), &(info->io_map.map));
+    v3_rb_erase(&(hook->tree_node), &(info->io_map.map));
 
-  // set the arch map to default (this should be 1, 1)
-  info->io_map.update_map(info, port, 0, 0);
+    // set the arch map to default (this should be 1, 1)
+    info->io_map.update_map(info, port, 0, 0);
 
-  V3_Free(hook);
+    V3_Free(hook);
 
-  return 0;
+    return 0;
 }
 
 
@@ -170,18 +171,18 @@ int v3_unhook_io_port(struct guest_info * info, uint_t port) {
 
 
 void v3_print_io_map(struct guest_info * info) {
-  struct v3_io_hook * tmp_hook = NULL;
-  struct rb_node * node = v3_rb_first(&(info->io_map.map));
+    struct v3_io_hook * tmp_hook = NULL;
+    struct rb_node * node = v3_rb_first(&(info->io_map.map));
 
-  PrintDebug("VMM IO Map\n");
+    V3_Print("VMM IO Map\n");
 
-  do {
-    tmp_hook = rb_entry(node, struct v3_io_hook, tree_node);
+    do {
+       tmp_hook = rb_entry(node, struct v3_io_hook, tree_node);
 
-    PrintDebug("IO Port: %hu (Read=%p) (Write=%p)\n", 
-              tmp_hook->port, 
-              (void *)(tmp_hook->read), (void *)(tmp_hook->write));
-  } while ((node = v3_rb_next(node)));
+       V3_Print("IO Port: %hu (Read=%p) (Write=%p)\n", 
+                tmp_hook->port, 
+                (void *)(tmp_hook->read), (void *)(tmp_hook->write));
+    } while ((node = v3_rb_next(node)));
 }
 
 
@@ -268,45 +269,30 @@ uint_t v3_indw(uint16_t port) {
 
 
 /* FIX ME */
-static int default_write(uint16_t port, void *src, uint_t length, void * priv_data) {
-  /*
+static int default_write(uint16_t port, void * src, uint_t length, void * priv_data) {
+    if (length == 1) {
+       v3_outb(port, *(uint8_t *)src);
+    } else if (length == 2) {
+       v3_outw(port, *(uint16_t *)src);
+    } else if (length == 4) {
+       v3_outdw(port, *(uint32_t *)src);
+    } else {
+       return -1;
+    }
     
-  if (length == 1) {
-  __asm__ __volatile__ (
-  "outb %b0, %w1"
-  :
-  : "a" (*dst), "Nd" (port)
-  );
-  } else if (length == 2) {
-  __asm__ __volatile__ (
-  "outw %b0, %w1"
-  :
-  : "a" (*dst), "Nd" (port)
-  );
-  } else if (length == 4) {
-  __asm__ __volatile__ (
-  "outw %b0, %w1"
-  :
-  : "a" (*dst), "Nd" (port)
-  );
-  }
-  */
-  return 0;
+    return length;
 }
 
 static int default_read(uint16_t port, void * dst, uint_t length, void * priv_data) {
+    if (length == 1) {
+       *(uint8_t *)dst = v3_inb(port);
+    } else if (length == 2) {
+       *(uint16_t *)dst = v3_inw(port);
+    } else if (length == 4) {
+       *(uint32_t *)dst = v3_indw(port);
+    } else {
+       return -1;
+    }
 
-  /*    
-       uint8_t value;
-
-    __asm__ __volatile__ (
-       "inb %w1, %b0"
-       : "=a" (value)
-       : "Nd" (port)
-    );
-
-    return value;
-  */
-
-  return 0;
+    return length;
 }
index 000dac0..0f1c004 100644 (file)
@@ -327,6 +327,8 @@ struct v3_shadow_region * v3_get_shadow_region(struct guest_info * info, addr_t
     if (guest_addr > info->mem_map.base_region.guest_end) {
        PrintError("Guest Address Exceeds Base Memory Size (ga=%p), (limit=%p)\n", 
                   (void *)guest_addr, (void *)info->mem_map.base_region.guest_end);
+       v3_print_mem_map(info);
+
        return NULL;
     }
     
@@ -393,15 +395,15 @@ addr_t v3_get_shadow_addr(struct v3_shadow_region * reg, addr_t guest_addr) {
 
 
 
-void print_shadow_map(struct guest_info * info) {
+void v3_print_mem_map(struct guest_info * info) {
     struct rb_node * node = v3_rb_first(&(info->mem_map.shdw_regions));
     struct v3_shadow_region * reg = &(info->mem_map.base_region);
     int i = 0;
 
-    PrintDebug("Memory Layout:\n");
+    V3_Print("Memory Layout:\n");
     
 
-    PrintDebug("Base Region:  0x%p - 0x%p -> 0x%p\n", 
+    V3_Print("Base Region:  0x%p - 0x%p -> 0x%p\n", 
               (void *)(reg->guest_start), 
               (void *)(reg->guest_end - 1), 
               (void *)(reg->host_addr));
@@ -415,12 +417,12 @@ void print_shadow_map(struct guest_info * info) {
     do {
        reg = rb_entry(node, struct v3_shadow_region, tree_node);
 
-       PrintDebug("%d:  0x%p - 0x%p -> 0x%p\n", i, 
+       V3_Print("%d:  0x%p - 0x%p -> 0x%p\n", i, 
                   (void *)(reg->guest_start), 
                   (void *)(reg->guest_end - 1), 
                   (void *)(reg->host_addr));
 
-       PrintDebug("\t(%s) (WriteHook = 0x%p) (ReadHook = 0x%p)\n", 
+       V3_Print("\t(%s) (WriteHook = 0x%p) (ReadHook = 0x%p)\n", 
                   v3_shdw_region_type_to_str(reg->host_type),
                   (void *)(reg->write_hook), 
                   (void *)(reg->read_hook));
index c1ca717..c573e3a 100644 (file)
@@ -576,35 +576,35 @@ void v3_hexdump(const void * ptr, int length, const char * hdr, int flags) {
     cp = ptr;
     for (i = 0; i < length; i+= cols) {
        if (hdr != NULL)
-           PrintDebug("%s", hdr);
+           V3_Print("%s", hdr);
 
        if ((flags & HD_OMIT_COUNT) == 0)
-           PrintDebug("%04x  ", i);
+           V3_Print("%04x  ", i);
 
        if ((flags & HD_OMIT_HEX) == 0) {
            for (j = 0; j < cols; j++) {
                k = i + j;
                if (k < length)
-                   PrintDebug("%c%02x", delim, cp[k]);
+                   V3_Print("%c%02x", delim, cp[k]);
                else
-                   PrintDebug("   ");
+                   V3_Print("   ");
            }
        }
 
        if ((flags & HD_OMIT_CHARS) == 0) {
-           PrintDebug("  |");
+           V3_Print("  |");
            for (j = 0; j < cols; j++) {
                k = i + j;
                if (k >= length)
-                   PrintDebug(" ");
+                   V3_Print(" ");
                else if (cp[k] >= ' ' && cp[k] <= '~')
-                   PrintDebug("%c", cp[k]);
+                   V3_Print("%c", cp[k]);
                else
-                   PrintDebug(".");
+                   V3_Print(".");
            }
-           PrintDebug("|");
+           V3_Print("|");
        }
-       PrintDebug("\n");
+       V3_Print("\n");
     }
 }
 
index 4a419a2..2d88d8b 100644 (file)
@@ -205,7 +205,7 @@ void v3_print_telemetry(struct guest_info * info) {
            V3_Print("%s%s:%sCnt=%u,%sAvg. Time=%u\n", 
                     hdr_buf,
                     code_str,
-                    (strlen(code_str) > 14) ? "\t" : "\t\t",
+                    (strlen(code_str) > 13) ? "\t" : "\t\t",
                     evt->cnt,
                     (evt->cnt >= 100) ? "\t" : "\t\t",
                     (uint32_t)(evt->handler_time / evt->cnt));