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.


updates to the PCI configuration for the southbridge and northbridge
Jack Lange [Wed, 8 Apr 2009 05:20:21 +0000 (00:20 -0500)]
palacios/include/devices/pci.h
palacios/include/devices/southbridge.h [new file with mode: 0644]
palacios/src/devices/i440fx.c
palacios/src/devices/ide.c
palacios/src/devices/pci.c
palacios/src/devices/piix3.c
palacios/src/palacios/vmm_config.c

index 6727e44..66841a8 100644 (file)
@@ -67,6 +67,7 @@ struct v3_pci_bar {
 #define PCI_MEM32_BASE(bar_val) (bar_val & 0xfffffff0)
 
 struct pci_device {
+
     union {
        uint8_t config_space[256];
 
@@ -76,14 +77,20 @@ struct pci_device {
        } __attribute__((packed));
     } __attribute__((packed));
 
-
-
     struct v3_pci_bar bar[6];
 
-    uint_t bus_num;
     struct rb_node dev_tree_node;
 
-    int dev_num;
+    uint_t bus_num;
+
+    union {
+       uint8_t devfn;
+       struct {
+           uint8_t fn_num       : 3;
+           uint8_t dev_num      : 5;
+       } __attribute__((packed));
+    } __attribute__((packed));
+
     char name[64];
 
     struct vm_device * vm_dev;  //the corresponding virtual device
@@ -93,7 +100,6 @@ struct pci_device {
     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;
 
@@ -107,9 +113,10 @@ struct vm_device * v3_create_pci();
 struct pci_device * 
 v3_pci_register_device(struct vm_device * pci,
                       pci_device_type_t dev_type, 
-                      uint_t bus_num,
-                      const char * name,
+                      int bus_num,
                       int dev_num,
+                      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 (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled),
diff --git a/palacios/include/devices/southbridge.h b/palacios/include/devices/southbridge.h
new file mode 100644 (file)
index 0000000..966d652
--- /dev/null
@@ -0,0 +1,41 @@
+/* 
+ * 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) 2009, Lei Xia <lxia@northwestern.edu>
+ * Copyright (c) 2009, Chang Seok Bae <jhuell@gmail.com>
+ * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author:  Lei Xia <lxia@northwestern.edu>
+ *             Chang Seok Bae <jhuell@gmail.com>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __DEVICES_SOUTHBRIDGE_H__
+#define __DEVICES_SOUTHBRIDGE_H__
+
+
+#ifdef __V3VEE__
+
+
+typedef enum {V3_SB_INVALID, V3_SB_PIIX3, V3_SB_PIIX4, V3_SB_CMD646} v3_southbridge_type_t;
+
+struct v3_southbridge {
+    struct vm_device * pci_bus;
+    struct pci_device * southbridge_pci;
+
+    v3_southbridge_type_t type;
+};
+
+
+#endif // ! __V3VEE__
+
+#endif
index 9d712df..793dc28 100644 (file)
 
 #include <palacios/vmm.h>
 #include <devices/i440fx.h>
+#include <devices/pci.h>
 
 struct i440_state {
-    int foo;
+    struct vm_device * pci;
 };
 
 
@@ -36,25 +37,38 @@ static int io_write(ushort_t port, void * src, uint_t length, struct vm_device *
 }
 
 
-static int i440_init(struct vm_device * dev) {
-    // struct i440_state * state = (struct i440_state *)(dev->private_data);
-
-   
-    v3_dev_hook_io(dev, 0x00b2, 
-                  &io_read, &io_write);
-    v3_dev_hook_io(dev, 0x00b3, 
-                  &io_read, &io_write);
 
+static int i440_init(struct vm_device * dev) {
+    struct i440_state * state = (struct i440_state *)(dev->private_data);
+    struct pci_device * pci_dev = NULL;
+    struct v3_pci_bar bars[6];
+    int i;
 
-    v3_dev_hook_io(dev, 0x0cf8, 
-                  &io_read, &io_write);
+    for (i = 0; i < 4; i++) {
+       v3_dev_hook_io(dev, 0x0cf8 + i,
+                      &io_read, &io_write);
+       v3_dev_hook_io(dev, 0x0cfc + i,
+                      &io_read, &io_write);
+    }
 
+    for (i = 0; i < 6; i++) {
+       bars[i].type = PCI_BAR_NONE;
+    }    
 
+    pci_dev = v3_pci_register_device(state->pci, PCI_STD_DEVICE, 0, 0, 0, "i440FX", bars,
+                                    NULL, NULL, NULL, dev);
 
-    v3_dev_hook_io(dev, 0x0cf9, 
-                  &io_read, &io_write);
+    if (!pci_dev) {
+       return -1;
+    }
 
+    pci_dev->config_header.vendor_id = 0x8086;
+    pci_dev->config_header.device_id = 0x1237;
+    pci_dev->config_header.revision = 0x0002;
+    pci_dev->config_header.subclass = 0x00; //  SubClass: host2pci
+    pci_dev->config_header.class = 0x06;    // Class: PCI bridge
 
+    pci_dev->config_space[0x72] = 0x02; // SMRAM (?)
 
     return 0;
 }
@@ -75,14 +89,13 @@ static struct vm_device_ops dev_ops = {
 
 
 struct vm_device * v3_create_i440fx(struct vm_device * pci) {
-
     struct i440_state * state = NULL;
 
-
     state = (struct i440_state *)V3_Malloc(sizeof(struct i440_state));
+
+    state->pci = pci;
        
     struct vm_device * i440_dev = v3_create_device("i440FX", &dev_ops, state);
 
     return i440_dev;
-
 }
index 562688f..505f5cf 100644 (file)
@@ -21,6 +21,7 @@
 #include <palacios/vm_guest_mem.h>
 #include <devices/ide.h>
 #include <devices/pci.h>
+#include <devices/southbridge.h>
 #include "ide-types.h"
 #include "atapi-types.h"
 
@@ -208,8 +209,6 @@ struct ide_channel {
 
     int irq; // this is temporary until we add PCI support
 
-    struct pci_device * pci_dev;
-
     // Control Registers
     struct ide_ctrl_reg ctrl_reg; // [write] 0x3f6,0x376
 
@@ -223,9 +222,11 @@ struct ide_channel {
 
 struct ide_internal {
     struct ide_channel channels[2];
-    struct vm_device * pci;
-    struct vm_device * southbridge;
-    struct pci_device * busmaster_pci;
+
+    struct v3_southbridge * southbridge;
+    struct vm_device * pci_bus;
+
+    struct pci_device * ide_pci;
 };
 
 
@@ -421,39 +422,6 @@ static int dma_write(struct vm_device * dev, struct ide_channel * channel) {
 }
 
 
-/* 
- * This is an ugly ugly ugly way to differentiate between the first and second DMA channels 
- */
-
-static int write_dma_port(ushort_t port_offset, void * src, uint_t length, struct vm_device * dev, struct ide_channel * channel);
-static int read_dma_port(ushort_t port_offset, void * dst, uint_t length, struct vm_device * dev, struct ide_channel * channel);
-
-
-static int write_pri_dma_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
-    PrintDebug("IDE: Writing PRI DMA Port %x (%s) (val=%x)\n", port, dma_port_to_str(port & 0x7), *(uint32_t *)src);
-    return write_dma_port(port & 0x7, src, length, dev, &(ide->channels[0]));
-}
-
-static int write_sec_dma_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
-    PrintDebug("IDE: Writing SEC DMA Port %x (%s) (val=%x)\n", port, dma_port_to_str(port & 0x7), *(uint32_t *)src);
-    return write_dma_port(port & 0x7, src, length, dev, &(ide->channels[1]));
-}
-
-
-static int read_pri_dma_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
-    PrintDebug("IDE: Reading PRI DMA Port %x (%s)\n", port, dma_port_to_str(port & 0x7));
-    return read_dma_port(port & 0x7, dst, length, dev, &(ide->channels[0]));
-}
-
-static int read_sec_dma_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
-    PrintDebug("IDE: Reading SEC DMA Port %x (%s)\n", port, dma_port_to_str(port & 0x7));
-    return read_dma_port(port & 0x7, dst, length, dev, &(ide->channels[1]));
-}
-
 
 #define DMA_CMD_PORT      0x00
 #define DMA_STATUS_PORT   0x02
@@ -462,9 +430,13 @@ static int read_sec_dma_port(ushort_t port, void * dst, uint_t length, struct vm
 #define DMA_PRD_PORT2     0x06
 #define DMA_PRD_PORT3     0x07
 
+#define DMA_CHANNEL_FLAG  0x08
 
-static int write_dma_port(ushort_t port_offset, void * src, uint_t length, 
-                         struct vm_device * dev, struct ide_channel * channel) {
+static int write_dma_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+    uint16_t port_offset = port & (DMA_CHANNEL_FLAG - 1);
+    uint_t channel_flag = (port & DMA_CHANNEL_FLAG) >> 3;
+    struct ide_channel * channel = &(ide->channels[channel_flag]);
 
     switch (port_offset) {
        case DMA_CMD_PORT:
@@ -533,8 +505,11 @@ static int write_dma_port(ushort_t port_offset, void * src, uint_t length,
 }
 
 
-static int read_dma_port(ushort_t port_offset, void * dst, uint_t length, 
-                        struct vm_device * dev, struct ide_channel * channel) {
+static int read_dma_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
+    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+    uint16_t port_offset = port & (DMA_CHANNEL_FLAG - 1);
+    uint_t channel_flag = (port & DMA_CHANNEL_FLAG) >> 3;
+    struct ide_channel * channel = &(ide->channels[channel_flag]);
 
     switch (port_offset) {
        case DMA_CMD_PORT:
@@ -1165,80 +1140,27 @@ static int pci_config_update(struct pci_device * pci_dev, uint_t reg_num, int le
 
 static int init_ide_state(struct vm_device * dev) {
     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
-    int i, j;
-
+    int i;
 
     /* 
-       Check if the PIIX 3 actually represents both IDE channels in a single PCI entry */
+     * Check if the PIIX 3 actually represents both IDE channels in a single PCI entry 
+     */
 
     for (i = 0; i < 1; i++) {
        init_channel(&(ide->channels[i]));
 
        // JRL: this is a terrible hack...
        ide->channels[i].irq = PRI_DEFAULT_IRQ + i;
-
-
-       if (ide->pci) {
-           struct v3_pci_bar bars[6];
-           struct pci_device * pci_dev = NULL;
-
-           for (j = 0; j < 6; j++) {
-               bars[j].type = PCI_BAR_NONE;
-           }
-
-
-           bars[4].type = PCI_BAR_IO;
-           bars[4].default_base_port = PRI_DEFAULT_DMA_PORT + (i * 0x8);
-           bars[4].num_ports = 8;
-           
-           if (i == 0) {
-               bars[4].io_read = read_pri_dma_port;
-               bars[4].io_write = write_pri_dma_port;
-           } else {
-               bars[4].io_read = read_sec_dma_port;
-               bars[4].io_write = write_sec_dma_port;
-           }
-
-           pci_dev = v3_pci_register_device(ide->pci, PCI_STD_DEVICE, 0, "V3_IDE", -1, bars,
-                                            pci_config_update, NULL, NULL, dev);
-
-           if (pci_dev == NULL) {
-               PrintError("Failed to register IDE BUS %d with PCI\n", i); 
-               return -1;
-           }
-
-           ide->channels[i].pci_dev = pci_dev;
-
-           /* This is for CMD646 devices 
-              pci_dev->config_header.vendor_id = 0x1095;
-              pci_dev->config_header.device_id = 0x0646;
-              pci_dev->config_header.revision = 0x8f07;
-           */
-           pci_dev->config_header.vendor_id = 0x8086;
-           pci_dev->config_header.device_id = 0x7010;
-           pci_dev->config_header.revision = 0x8000;
-           
-           pci_dev->config_header.subclass = 0x01;
-           pci_dev->config_header.class = 0x01;
-           
-           
-           pci_dev->config_header.command = 0;
-           pci_dev->config_header.status = 0x0280;
-           
-           //      pci_dev->config_header.intr_line = PRI_DEFAULT_IRQ + i;
-           //      pci_dev->config_header.intr_pin = 1;
-       }
-       
-
     }
 
+
     return 0;
 }
 
 
 
 static int init_ide(struct vm_device * dev) {
-    //struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
 
     PrintDebug("IDE: Initializing IDE\n");
 
@@ -1296,6 +1218,53 @@ static int init_ide(struct vm_device * dev) {
     v3_dev_hook_io(dev, PRI_ADDR_REG_PORT, 
                   &read_port_std, &write_port_std);
 
+
+
+
+    if (ide->pci_bus) {
+       struct v3_pci_bar bars[6];
+       struct v3_southbridge * southbridge = (struct v3_southbridge *)(ide->southbridge);
+       struct pci_device * sb_pci = (struct pci_device *)(southbridge->southbridge_pci);
+       struct pci_device * pci_dev = NULL;
+       int i;
+
+       for (i = 0; i < 6; i++) {
+           bars[i].type = PCI_BAR_NONE;
+       }
+
+       bars[4].type = PCI_BAR_IO;
+       bars[4].default_base_port = PRI_DEFAULT_DMA_PORT;
+       bars[4].num_ports = 16;
+
+       bars[4].io_read = read_dma_port;
+       bars[4].io_write = write_dma_port;
+       
+       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);
+
+       if (pci_dev == NULL) {
+           PrintError("Failed to register IDE BUS %d with PCI\n", i); 
+           return -1;
+       }
+
+       /* This is for CMD646 devices 
+          pci_dev->config_header.vendor_id = 0x1095;
+          pci_dev->config_header.device_id = 0x0646;
+          pci_dev->config_header.revision = 0x8f07;
+       */
+
+       pci_dev->config_header.vendor_id = 0x8086;
+       pci_dev->config_header.device_id = 0x7010;
+       pci_dev->config_header.revision = 0x8000;
+
+       pci_dev->config_header.subclass = 0x01;
+       pci_dev->config_header.class = 0x01;
+
+       pci_dev->config_header.command = 0;
+       pci_dev->config_header.status = 0x0280;
+    }
+
     return 0;
 }
 
@@ -1316,12 +1285,12 @@ static struct vm_device_ops dev_ops = {
 };
 
 
-struct vm_device *  v3_create_ide(struct vm_device * pci, struct vm_device * southbridge) {
+struct vm_device *  v3_create_ide(struct vm_device * pci_bus, struct vm_device * southbridge_dev) {
     struct ide_internal * ide  = (struct ide_internal *)V3_Malloc(sizeof(struct ide_internal));  
     struct vm_device * device = v3_create_device("IDE", &dev_ops, ide);
 
-    ide->pci = pci;
-    ide->southbridge = southbridge;
+    ide->pci_bus = pci_bus;
+    ide->southbridge = (struct v3_southbridge *)(southbridge_dev->private_data);
 
     PrintDebug("IDE: Creating IDE bus x 2\n");
 
index 102024c..6b5472d 100644 (file)
@@ -154,9 +154,9 @@ struct pci_device * __add_device_to_bus(struct pci_bus * bus, struct pci_device
     parent = *p;
     tmp_dev = rb_entry(parent, struct pci_device, dev_tree_node);
 
-    if (dev->dev_num < tmp_dev->dev_num) {
+    if (dev->devfn < tmp_dev->devfn) {
       p = &(*p)->rb_left;
-    } else if (dev->dev_num > tmp_dev->dev_num) {
+    } else if (dev->devfn > tmp_dev->devfn) {
       p = &(*p)->rb_right;
     } else {
       return tmp_dev;
@@ -186,16 +186,17 @@ struct pci_device * add_device_to_bus(struct pci_bus * bus, struct pci_device *
 }
 
 
-static struct pci_device * get_device(struct pci_bus * bus, int dev_num) {
+static struct pci_device * get_device(struct pci_bus * bus, uint8_t dev_num, uint8_t fn_num) {
     struct rb_node * n = bus->devices.rb_node;
     struct pci_device * dev = NULL;
+    uint8_t devfn = ((dev_num & 0x1f) << 3) | (fn_num & 0x7);
 
     while (n) {
        dev = rb_entry(n, struct pci_device, dev_tree_node);
        
-       if (dev_num < dev->dev_num) {
+       if (devfn < dev->devfn) {
            n = n->rb_left;
-       } else if (dev_num > dev->dev_num) {
+       } else if (devfn > dev->devfn) {
            n = n->rb_right;
        } else {
            return dev;
@@ -301,7 +302,7 @@ static int data_port_read(ushort_t port, void * dst, uint_t length, struct vm_de
               reg_num, reg_num, 
               pci_state->addr_reg.val);
 
-    pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num);
+    pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num);
     
     if (pci_dev == NULL) {
        for (i = 0; i < length; i++) {
@@ -340,6 +341,24 @@ static inline int is_cfg_reg_writable(uchar_t header_type, int reg_num) {
                return 1;
  
        }
+    } else if (header_type == 0x80) {
+       switch (reg_num) {
+           case 0x00:
+           case 0x01:
+           case 0x02:
+           case 0x03:
+           case 0x08:
+           case 0x09:
+           case 0x0a:
+           case 0x0b:
+           case 0x0e:
+           case 0x3d:
+               return 0;
+                           
+           default:
+               return 1;
+       }
     } else {
        // PCI to PCI Bridge = 0x01
        // CardBus Bridge = 0x02
@@ -411,7 +430,7 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d
               *(uint32_t *)src, length);
 
 
-    pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num);
+    pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num);
     
     if (pci_dev == NULL) {
        PrintError("Writing configuration space for non-present device (dev_num=%d)\n", 
@@ -422,8 +441,14 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d
 
     for (i = 0; i < length; i++) {
        uint_t cur_reg = reg_num + i;
+       int writable = is_cfg_reg_writable(pci_dev->config_header.header_type, cur_reg);
+       
+       if (writable == -1) {
+           PrintError("Invalid PCI configuration space\n");
+           return -1;
+       }
 
-       if (is_cfg_reg_writable(pci_dev->config_header.header_type, cur_reg)) {
+       if (writable) {
            pci_dev->config_space[cur_reg] = *(uint8_t *)((uint8_t *)src + i);
 
            if ((cur_reg >= 0x10) && (cur_reg < 0x28)) {
@@ -528,36 +553,6 @@ static int pci_deinit_device(struct vm_device * dev) {
 
 
 
-
-static int init_i440fx(struct vm_device * dev) {
-    struct pci_device * pci_dev = NULL;
-    struct v3_pci_bar bars[6];
-    int i;
-    
-    for (i = 0; i < 6; i++) {
-       bars[i].type = PCI_BAR_NONE;
-    }    
-
-    pci_dev = v3_pci_register_device(dev, PCI_STD_DEVICE, 0, "i440FX", 0, bars,
-                                    NULL, NULL, NULL, NULL);
-    
-    if (!pci_dev) {
-       return -1;
-    }
-    
-    pci_dev->config_header.vendor_id = 0x8086;
-    pci_dev->config_header.device_id = 0x1237;
-    pci_dev->config_header.revision = 0x0002;
-    pci_dev->config_header.subclass = 0x00; //  SubClass: host2pci
-    pci_dev->config_header.class = 0x06;    // Class: PCI bridge
-
-    pci_dev->bus_num = 0;
-    return 0;
-}
-
-
-
-
 static void init_pci_busses(struct pci_internal * pci_state) {
     int i;
 
@@ -582,11 +577,6 @@ static int pci_init_device(struct vm_device * dev) {
     pci_state->addr_reg.val = 0; 
 
     init_pci_busses(pci_state);
-
-    if (init_i440fx(dev) == -1) {
-       PrintError("Could not intialize i440fx\n");
-       return -1;
-    }
     
     PrintDebug("Sizeof config header=%d\n", (int)sizeof(struct pci_config_header));
     
@@ -693,9 +683,10 @@ static inline int init_bars(struct pci_device * pci_dev) {
 // if dev_num == -1, auto assign 
 struct pci_device * v3_pci_register_device(struct vm_device * pci,
                                           pci_device_type_t dev_type, 
-                                          uint_t bus_num,
-                                          const char * name,
+                                          int bus_num,
                                           int dev_num,
+                                          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 (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled),
@@ -719,7 +710,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
        }
     }
     
-    if (get_device(bus, dev_num) != NULL) {
+    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;
@@ -729,16 +720,20 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
     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));
-    
+
     
     switch (dev_type) {
        case PCI_STD_DEVICE:
            pci_dev->config_header.header_type = 0x00;
            break;
+       case PCI_MULTIFUNCTION:
+           pci_dev->config_header.header_type = 0x80;
+           break;
        default:
            PrintError("Unhandled PCI Device Type: %d\n", dev_type);
            return NULL;
@@ -746,6 +741,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
 
     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;
@@ -756,9 +752,8 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
     pci_dev->ext_rom_update = ext_rom_update;
 
 
-
     //copy bars
-    for (i = 0; i < 6; i ++){
+    for (i = 0; i < 6; i ++) {
        pci_dev->bar[i].type = bars[i].type;
 
        if (pci_dev->bar[i].type == PCI_BAR_IO) {
index 60bec64..7beb6dd 100644 (file)
 #include <devices/piix3.h>
 #include <palacios/vmm.h>
 #include <devices/pci.h>
+#include <devices/southbridge.h>
+
+
+
+static int reset_piix3(struct vm_device * dev) {
+    struct v3_southbridge * piix3 = (struct v3_southbridge *)(dev->private_data);
+    struct pci_device * pci_dev = piix3->southbridge_pci;
+
+    pci_dev->config_header.command = 0x0007; // master, memory and I/O
+    pci_dev->config_header.status = 0x0200;
+
+    pci_dev->config_space[0x4c] = 0x4d;
+    pci_dev->config_space[0x4e] = 0x03;
+    pci_dev->config_space[0x4f] = 0x00;
+    pci_dev->config_space[0x60] = 0x80;
+    pci_dev->config_space[0x69] = 0x02;
+    pci_dev->config_space[0x70] = 0x80;
+    pci_dev->config_space[0x76] = 0x0c;
+    pci_dev->config_space[0x77] = 0x0c;
+    pci_dev->config_space[0x78] = 0x02;
+    pci_dev->config_space[0x79] = 0x00;
+    pci_dev->config_space[0x80] = 0x00;
+    pci_dev->config_space[0x82] = 0x00;
+    pci_dev->config_space[0xa0] = 0x08;
+    pci_dev->config_space[0xa2] = 0x00;
+    pci_dev->config_space[0xa3] = 0x00;
+    pci_dev->config_space[0xa4] = 0x00;
+    pci_dev->config_space[0xa5] = 0x00;
+    pci_dev->config_space[0xa6] = 0x00;
+    pci_dev->config_space[0xa7] = 0x00;
+    pci_dev->config_space[0xa8] = 0x0f;
+    pci_dev->config_space[0xaa] = 0x00;
+    pci_dev->config_space[0xab] = 0x00;
+    pci_dev->config_space[0xac] = 0x00;
+    pci_dev->config_space[0xae] = 0x00;
 
+    return 0;
+}
 
-struct piix3_state {
-    uint8_t pci_dev_num;
 
-    struct vm_device * pci;
+static int init_piix3(struct vm_device * dev) {
+    struct v3_southbridge * piix3 = (struct v3_southbridge *)(dev->private_data);
+    struct pci_device * pci_dev = NULL;
+    struct v3_pci_bar bars[6];
+    int i;
 
-};
+    for (i = 0; i < 6; i++) {
+       bars[i].type = PCI_BAR_NONE;
+    }
 
+    pci_dev = v3_pci_register_device(piix3->pci_bus, PCI_MULTIFUNCTION, 
+                                    0, -1, 0, 
+                                    "PIIX3", bars, 
+                                    NULL, NULL, NULL, dev);
+    if (!pci_dev) {
+       PrintError("Could not register PCI Device for PIIX3\n");
+       return -1;
+    }
 
-static int init_piix3(struct vm_device * dev) {
+    pci_dev->config_header.vendor_id = 0x8086;
+    pci_dev->config_header.device_id = 0x7000; // PIIX4 is 0x7001
+    pci_dev->config_header.subclass = 0x01; //  SubClass: host2pci
+    pci_dev->config_header.class = 0x06;    // Class: PCI bridge
+
+    piix3->southbridge_pci = pci_dev;
+
+    reset_piix3(dev);
 
     return 0;
 }
@@ -48,17 +104,18 @@ static int deinit_piix3(struct vm_device * dev) {
 static struct vm_device_ops dev_ops = {
     .init = init_piix3,
     .deinit = deinit_piix3,
-    .reset = NULL,
+    .reset = reset_piix3,
     .start = NULL,
     .stop = NULL,
 };
 
 
 struct vm_device * v3_create_piix3(struct vm_device * pci) {
-    struct piix3_state * piix3 = (struct piix3_state *)V3_Malloc(sizeof(struct piix3_state));
+    struct v3_southbridge * piix3 = (struct v3_southbridge *)V3_Malloc(sizeof(struct v3_southbridge));
     struct vm_device * dev = NULL;
 
-    piix3->pci = pci;
+    piix3->pci_bus = pci;
+    piix3->type = V3_SB_PIIX3;
     
     dev = v3_create_device("PIIX3", &dev_ops, piix3);
 
index ff6dce4..1236a0b 100644 (file)
@@ -350,11 +350,15 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_
     v3_attach_device(info, para_net);
 
     if (config_ptr->enable_pci == 1) {
+       PrintDebug("Attaching PCI\n");
        v3_attach_device(info, pci);
+       PrintDebug("Attaching Northbridge\n");
        v3_attach_device(info, northbridge);
+       PrintDebug("Attaching Southbridge\n");
        v3_attach_device(info, southbridge);
     }
 
+    PrintDebug("Attaching IDE\n");
     v3_attach_device(info, ide);