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.


Restructure of direct host network bridge.
[palacios.git] / palacios / src / devices / piix3.c
index b5f1e45..8752943 100644 (file)
@@ -7,15 +7,11 @@
  * 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, Jack Lange <jarusl@cs.northwestern.edu>
  * 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>
- *          Jack Lange <jarusl@cs.northwestern.edu>
+ * 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".
  
 
 #include <palacios/vmm.h>
+#include <palacios/vmm_dev_mgr.h>
+#include <palacios/vmm_intr.h>
+
 #include <devices/pci.h>
 #include <devices/southbridge.h>
 
+
 struct iort_reg {
     union {
        uint8_t value;
@@ -329,8 +329,7 @@ struct piix3_config_space {
 
 
 
-static int reset_piix3(struct vm_device * dev) {
-    struct v3_southbridge * piix3 = (struct v3_southbridge *)(dev->private_data);
+static int reset_piix3(struct v3_southbridge * piix3) {
     struct pci_device * pci_dev = piix3->southbridge_pci;
     struct piix3_config_space * piix3_cfg = (struct piix3_config_space *)(pci_dev->config_data);
 
@@ -361,37 +360,82 @@ static int reset_piix3(struct vm_device * dev) {
     return 0;
 }
 
-static int raise_pci_irq(struct vm_device * dev, uint_t intr_pin) {
-    struct v3_southbridge * piix3 = (struct v3_southbridge *)(dev->private_data);
-    struct pci_device * pci_dev = piix3->southbridge_pci;
-    struct piix3_config_space * piix3_cfg = (struct piix3_config_space *)(pci_dev->config_data);
 
-    PrintError("Raising PCI IRQ %d\n", piix3_cfg->pirq_rc[intr_pin]);
+//irq is pirq_rc[intr_pin + pci_dev_num - 1] & 0xf
+/*
+struct pirq_rc_reg {
+       uint8_t irq         : 4;
+       uint8_t rsvd        : 3;
+       uint8_t disabled    : 1; // (1=disabled, 0=enabled)
+}
+*/
+
+
+static int raise_pci_irq(struct pci_device * pci_dev, void * dev_data) {
+    struct v3_southbridge * piix3 = dev_data;
+    struct pci_device * piix3_pci = piix3->southbridge_pci;
+    struct piix3_config_space * piix3_cfg = (struct piix3_config_space *)(piix3_pci->config_data);
+    int intr_pin = pci_dev->config_header.intr_pin - 1;
+    int irq_index = (intr_pin + pci_dev->dev_num - 1) & 0x3;
+    
+    //PrintError("Raising PCI IRQ %d, %p\n", piix3_cfg->pirq_rc[irq_index], piix3->vm);
+    
+    if (piix3_cfg->pirq_rc[irq_index] < 16) {
+       v3_raise_irq(piix3->vm, piix3_cfg->pirq_rc[irq_index] & 0xf);
+    } else {
+       PrintError("Tried to raise interrupt on disabled PIRQ entry (%d)\n", irq_index);
+       PrintError("\tpirq_rc values: 0=0x%x, 1=0x%x, 2=0x%x, 3=0x%x\n", 
+                  piix3_cfg->pirq_rc[0], piix3_cfg->pirq_rc[1],
+                  piix3_cfg->pirq_rc[2], piix3_cfg->pirq_rc[3]);
+       return -1;
+    }
+
+    return 0;
+}
+
+
+
+static int lower_pci_irq(struct pci_device * pci_dev, void * dev_data) {
+    struct v3_southbridge * piix3 = dev_data;
+    struct pci_device * piix3_pci = piix3->southbridge_pci;
+    struct piix3_config_space * piix3_cfg = (struct piix3_config_space *)(piix3_pci->config_data);
+    int intr_pin = pci_dev->config_header.intr_pin - 1;
+    int irq_index = (intr_pin + pci_dev->dev_num - 1) & 0x3;
     
-    v3_raise_irq(dev->vm, piix3_cfg->pirq_rc[intr_pin]);
+    //    PrintError("Lowering PCI IRQ %d\n", piix3_cfg->pirq_rc[irq_index]);
+    
+    if (piix3_cfg->pirq_rc[irq_index] < 16) {
+       v3_lower_irq(piix3->vm, piix3_cfg->pirq_rc[irq_index] & 0xf);
+    } else {
+       PrintError("Tried to lower interrupt on disabled PIRQ entry (%d)\n", irq_index);
+       PrintError("\tpirq_rc values: 0=0x%x, 1=0x%x, 2=0x%x, 3=0x%x\n", 
+                  piix3_cfg->pirq_rc[0], piix3_cfg->pirq_rc[1],
+                  piix3_cfg->pirq_rc[2], piix3_cfg->pirq_rc[3]);
+       return -1;
+    }
 
     return 0;
 }
 
 
 
-static int piix_free(struct vm_device * dev) {
+static int piix_free(struct v3_southbridge * piix3) {
+
+    // unregister pci
+
+    V3_Free(piix3);
     return 0;
 }
 
 
 static struct v3_device_ops dev_ops = {
-    .free = piix_free,
-    .reset = reset_piix3,
-    .start = NULL,
-    .stop = NULL,
+    .free = (int (*)(void *))piix_free,
 };
 
 
 
 
-static int setup_pci(struct vm_device * dev) {
-    struct v3_southbridge * piix3 = (struct v3_southbridge *)(dev->private_data);
+static int setup_pci(struct v3_southbridge * piix3) {
     struct pci_device * pci_dev = NULL;
     struct v3_pci_bar bars[6];
     int i;
@@ -404,7 +448,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, piix3);
     if (pci_dev == NULL) {
        PrintError("Could not register PCI Device for PIIX3\n");
        return -1;
@@ -417,17 +461,18 @@ static int setup_pci(struct vm_device * dev) {
 
     piix3->southbridge_pci = pci_dev;
 
-    v3_pci_set_irq_bridge(piix3->pci_bus, bus_num, raise_pci_irq, dev);
+    v3_pci_set_irq_bridge(piix3->pci_bus, bus_num, raise_pci_irq, lower_pci_irq, piix3);
 
-    reset_piix3(dev);
+    reset_piix3(piix3);
 
     return 0;
 }
 
-static int piix3_init(struct guest_info * vm, void * cfg_data) {
+static int piix3_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct v3_southbridge * piix3 = (struct v3_southbridge *)V3_Malloc(sizeof(struct v3_southbridge));
     struct vm_device * dev = NULL;
-    struct vm_device * pci = v3_find_dev(vm, (char *)cfg_data);
+    struct vm_device * pci = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
+    char * dev_id = v3_cfg_val(cfg, "ID");
 
     if (!pci) {
        PrintError("Could not find PCI device\n");
@@ -436,17 +481,24 @@ static int piix3_init(struct guest_info * vm, void * cfg_data) {
 
     piix3->pci_bus = pci;
     piix3->type = V3_SB_PIIX3;
+    piix3->vm = vm;
     
-    dev = v3_allocate_device("PIIX3", &dev_ops, piix3);
+    dev = v3_add_device(vm, dev_id, &dev_ops, piix3);
 
-    if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "PIIX3");
+    if (dev == NULL) {
+       PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(piix3);
        return -1;
     }
 
     PrintDebug("Created PIIX3\n");
 
-    return setup_pci(dev);
+    if (setup_pci(piix3) == -1) {
+       v3_remove_device(dev);
+       return -1;
+    }
+
+    return 0;
 }