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 pci irq support to properly route intr_pins through the southbridge.
Jack Lange [Fri, 31 Jul 2009 05:15:18 +0000 (00:15 -0500)]
PCI devices now have to raise irqs via the pci device, which calls a registered bridge handler...

The southbridge pci interconnect is a little obtuse. You configure the southbridge with the irq numbers for each of the 4 pci interrupt lines. When a pci device raises an irq, it raises its configured pci interrupt pin, which goes through the pci device to the southbridge, which translates that to the actual irq. So basically the southbridge sits in between the PCI bus and the CPU, which is odd because you configure the southbridge via PCI accesses.

palacios/include/devices/pci.h
palacios/src/devices/i440fx.c
palacios/src/devices/pci.c
palacios/src/devices/piix3.c

index d80530a..62060c5 100644 (file)
 #include <devices/pci_types.h>
 
 
-typedef enum {PCI_BAR_IO, PCI_BAR_MEM16, PCI_BAR_MEM32, PCI_BAR_MEM64_LOW, PCI_BAR_MEM64_HIGH, PCI_BAR_NONE} pci_bar_type_t;
+typedef enum { PCI_BAR_IO, 
+              PCI_BAR_MEM16, 
+              PCI_BAR_MEM32, 
+              PCI_BAR_MEM64_LOW, 
+              PCI_BAR_MEM64_HIGH, 
+              PCI_BAR_NONE } pci_bar_type_t;
 
 typedef enum {PCI_STD_DEVICE, PCI_TO_PCI_BRIDGE, PCI_CARDBUS, PCI_MULTIFUNCTION} pci_device_type_t;
 
@@ -114,8 +119,12 @@ struct pci_device {
 };
 
 
+int v3_pci_set_irq_bridge(struct vm_device * pci_bus, int bus_num,
+                         int (*raise_pci_irq)(struct vm_device * dev, uint_t intr_line), 
+                         struct vm_device * bridge_dev);
 
 
+int v3_pci_raise_irq(struct vm_device * pci_bus, int bus_num, struct pci_device * dev);
 
 struct pci_device * 
 v3_pci_register_device(struct vm_device * pci,
index 6d0740a..2408cdd 100644 (file)
@@ -21,6 +21,9 @@
 #include <palacios/vmm_dev_mgr.h>
 #include <devices/pci.h>
 
+
+// We Have to setup some sort of PIC interrupt mapping here....
+
 struct i440_state {
     struct vm_device * pci;
 };
index cce7aa8..606b38b 100644 (file)
@@ -74,6 +74,9 @@ struct pci_bus {
 
     // Bitmap of the allocated device numbers
     uint8_t dev_map[MAX_BUS_DEVICES / 8];
+
+    int (*raise_pci_irq)(struct vm_device * dev, uint_t intr_line);
+    struct vm_device * irq_bridge_dev;
 };
 
 
@@ -440,9 +443,10 @@ 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, reg = %d (%x) addr_reg = %x (val=%x, len=%d)\n", 
+    PrintDebug("Writing PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (%x) addr_reg = %x (val=%x, len=%d)\n", 
               pci_state->addr_reg.bus_num, 
               pci_state->addr_reg.dev_num, 
+              pci_state->addr_reg.fn_num,
               reg_num, reg_num, 
               pci_state->addr_reg.val,
               *(uint32_t *)src, length);
@@ -500,6 +504,8 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d
                // BIST update
                pci_dev->config_header.BIST = 0x00;
            }
+       } else {
+           PrintError("PCI Write to read only register %d\n", cur_reg);
        }
     }
 
@@ -698,6 +704,25 @@ static inline int init_bars(struct pci_device * pci_dev) {
 }
 
 
+int v3_pci_set_irq_bridge(struct  vm_device * pci_bus, int bus_num, 
+                         int (*raise_pci_irq)(struct vm_device * dev, uint_t intr_line), 
+                         struct vm_device * bridge_dev) {
+    struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data;
+
+
+    pci_state->bus_list[bus_num].raise_pci_irq = raise_pci_irq;
+    pci_state->bus_list[bus_num].irq_bridge_dev = bridge_dev;
+
+    return 0;
+}
+
+int v3_pci_raise_irq(struct vm_device * pci_bus, int bus_num, struct pci_device * dev) {
+   struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data;
+   struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
+
+   return bus->raise_pci_irq(bus->irq_bridge_dev, dev->config_header.intr_pin);
+}
+
 // if dev_num == -1, auto assign 
 struct pci_device * v3_pci_register_device(struct vm_device * pci,
                                           pci_device_type_t dev_type, 
index 2eae985..b5f1e45 100644 (file)
 #include <devices/pci.h>
 #include <devices/southbridge.h>
 
+struct iort_reg {
+    union {
+       uint8_t value;
+       struct {
+           uint8_t times_16bit   : 2;
+           uint8_t enable_16bit  : 1;
+           uint8_t times_8bit    : 3;
+           uint8_t enable_8bit   : 1;
+           uint8_t dmaac         : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+struct xbcs_reg {
+    union {
+       uint16_t value;
+       struct {
+           uint8_t rtc_addr_en        : 1;
+           uint8_t kb_ctrl_en         : 1;
+           uint8_t bioscs_wprot_en    : 1;
+           uint8_t rsvd1              : 1;
+           uint8_t irq12_mouse_fn_en  : 1;
+           uint8_t coproc_err_fn_en   : 1;
+           uint8_t lower_bios_en      : 1;
+           uint8_t ext_bios_en        : 1;
+           uint8_t apic_chip_sel      : 1;
+           uint8_t piix_rsvd          : 7;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+struct pirq_route_ctrl_req {
+    union {
+       uint8_t value;
+       struct {
+           uint8_t irq_routing        : 4;
+           uint8_t rsvd               : 3;
+           uint8_t irq_route_en       : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+struct top_of_mem_reg {
+    union {
+       uint8_t value;
+       struct {
+           uint8_t rsvd1                    : 1;
+           uint8_t isadma_reg_fwd_en        : 1;
+           uint8_t piix_rsvd                : 1;
+           uint8_t isadma_lo_bios_fwd_en    : 1;
+           uint8_t top_of_mem               : 4;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+// Miscellaneous Status register
+struct misc_stat_reg {
+    union {
+       uint16_t value;
+       struct {
+           uint8_t isa_clk_div              : 1;
+           uint8_t piix_rsvd1               : 1;
+           uint8_t pci_hdr_type_en          : 1;
+           uint8_t rsvd1                    : 1;
+           uint8_t usb_en                   : 1;
+           uint8_t rsvd2                    : 1;
+           uint8_t ext_sm_mode_en           : 1;
+           uint8_t nb_retry_en              : 1;
+           uint8_t rsvd3                    : 7;
+           uint8_t serr_gen_delayed_tranx   : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+// Motherboard Device IRQ route control register
+struct mb_irq_ctrl_reg {
+    union {
+       uint8_t value;
+       struct {
+           uint8_t irq_routing              : 4;
+           uint8_t rsvd                     : 1;
+           uint8_t irq0_en                  : 1;
+           uint8_t irq_sharing_en           : 1;
+           uint8_t irq_routing_en           : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+// Motherboard Device DMA control register
+struct mb_dma_ctrl_reg {
+    union {
+       uint8_t value;
+       struct {
+           uint8_t type_f_dma_routing       : 3;
+           uint8_t piix_rsvd                : 1;
+           uint8_t rsvd                     : 3;
+           uint8_t type_f_dma_buf_en        : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+// Programmable Chip Select Control Register
+struct prg_chip_sel_ctrl_reg {
+    union {
+       uint16_t value;
+       struct {
+           uint8_t pcs_addr_mask            : 2;
+           uint16_t pcs_addr                : 14;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+// APIC base address relocation register
+struct apic_base_addr_reg {
+    union {
+       uint8_t value;
+       struct {
+           uint8_t y_base_addr             : 2;
+           uint8_t x_base_addr             : 4;
+           uint8_t a12_mask                : 1;
+           uint8_t rsvd                    : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+// Deterministic Latency control register
+struct deter_lat_ctrl_reg {
+    union {
+       uint8_t value;
+       struct {
+           uint8_t delayed_trans_en        : 1;
+           uint8_t pass_release_en         : 1;
+           uint8_t usb_pass_release_en     : 1;
+           uint8_t serr_gen_trans_tmout_en : 1;
+           uint8_t rsvd                    : 4;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+// SMI Control Register
+struct smi_ctrl_reg {
+    union {
+       uint8_t value;
+       struct {
+           uint8_t smi_gate               : 1;
+           uint8_t stpclk_sig_en          : 1;
+           uint8_t stpclk_scaling_en      : 1;
+           uint8_t fast_off_tmr_freeze    : 2;
+           uint8_t rsvd                   : 3;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+// SMI Enable register
+struct smi_enable_reg {
+    union {
+       uint16_t value;
+       struct {
+           uint8_t irq1_smi_en            : 1; // (keyboard irq)
+           uint8_t irq3_smi_en            : 1; // (COM1/COM3/Mouse irq)
+           uint8_t irq4_smi_en            : 1; // (COM2/COM4/Mouse irq)
+           uint8_t irq8_smi_en            : 1; // (RTC irq)
+           uint8_t irq12_smi_en           : 1; // (PS/2 mouse irq)
+           uint8_t fast_off_tmr_en        : 1;
+           uint8_t ext_smi_en             : 1;
+           uint8_t apic_wr_smi_en         : 1;
+           uint8_t legacy_usb_smi_en      : 1;
+           uint8_t rsvd                   : 7;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+// System Event Enable register
+struct sys_evt_en_reg {
+    union {
+       uint32_t value;
+       struct {
+           uint8_t firq0_en               : 1;
+           uint8_t firq1_en               : 1;
+           uint8_t rsvd1                  : 1;
+           uint8_t firq3_en               : 1;
+           uint8_t firq4_en               : 1;
+           uint8_t firq5_en               : 1;
+           uint8_t firq6_en               : 1;
+           uint8_t firq7_en               : 1;
+           uint8_t firq8_en               : 1;
+           uint8_t firq9_en               : 1;
+           uint8_t firq10_en              : 1;
+           uint8_t firq11_en              : 1;
+           uint8_t firq12_en              : 1;
+           uint8_t firq13_en              : 1;
+           uint8_t firq14_en              : 1;
+           uint8_t firq15_en              : 1;
+           uint16_t rsvd2                 : 12;
+           uint8_t fast_off_apic_en       : 1;
+           uint8_t fast_off_nmi_en        : 1;
+           uint8_t intr_en                : 1;
+           uint8_t fast_off_smi_en        : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+// SMI Request Register
+struct smi_req_reg {
+    union {
+       uint16_t value;
+       struct {
+           uint8_t irq1_req_smi_stat      : 1;
+           uint8_t irq3_req_smi_stat      : 1;
+           uint8_t irq4_req_smi_stat      : 1;
+           uint8_t irq8_req_smi_stat      : 1;
+           uint8_t irq12_req_smi_stat     : 1;
+           uint8_t fast_off_tmr_exp_stat  : 1;
+           uint8_t extsmi_stat            : 1;
+           uint8_t apm_smi_stat           : 1;
+           uint8_t legacy_usb_smi_stat    : 1;
+           uint8_t rsvd                   : 7;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+struct piix3_config_space {
+    uint8_t rsvd1[12];            // 0x40 - 0x4b
+
+    // ISA I/O Recovery timer register
+    uint8_t iort;                 // 0x4c        (default 0x4d)
+    uint8_t rsvd2;                // 0x4d
+
+    // X-Bus Chip select register
+    uint16_t xbcs;                // 0x4e - 0x4f (default: 0x03)
+    uint8_t rsvd3[16];            // 0x50 - 0x5f
+
+    // pirq route control register (IRQs A-D)
+    uint8_t pirq_rc[4];           // 0x60 - 0x63 (default: 0x80) 
+    uint8_t rsvd4[5];             // 0x64 - 0x68
+
+    // top of memory register
+    uint8_t top_of_mem;           // 0x69        (default: 0x02)
+
+    // Miscellaneous status register
+    uint16_t mstat;               // 0x6A - 0x6B (default: undefined)
+    uint8_t rsvd5[4];             // 0x6c - 0x6f
+
+    // Motherboard device IRQ route control register
+    uint8_t mbirq0;                // 0x70        (default: 0x80)
+    uint8_t rsvd6;                 // 0x71 (piix only)
+    uint8_t rsvd7[4];              // 0x72 - 0x75
+
+    // Motherboard Device DMA Control registers
+    uint8_t mbdma0;                // 0x76        (default: 0x0c)
+    uint8_t mbdma1;                // 0x77        (default: 0x0c)
+
+    // Programmable Chip Select Control Register  
+    uint16_t pcsc;                 // 0x78 - 0x79 (default: 0x0002)
+    uint8_t rsvd8[6];              // 0x7A - 0x7F
+
+    // APIC base address relocation register
+    uint8_t apicbase;              // 0x80        (default: 0x00)
+    uint8_t rsvd9;                 // 0x81
+
+
+    // Deterministic Latency control register
+    uint8_t dlc;                   // 0x82        (default: 0x00)
+    uint8_t rsvd10[29];            // 0x83 - 0x9f
+
+
+    // SMI Control Register
+    uint8_t smicntl;               // 0xa0        (default: 0x08)
+    uint8_t rsvd11;                // 0xa1
+
+    // SMI Enable register
+    uint16_t smien;                // 0xa2 - 0xa3 (default: 0x0000)
+
+    // System Event Enable register
+    uint32_t see;                  // 0xa4 - 0xa7 (default: 0x00000000)
+
+    // Fast off timer register
+    uint8_t ftmr;                  // 0xa8        (default: 0x0f)
+    uint8_t rsvd12;                // 0xa9
+
+    // SMI Request Register
+    uint16_t smireq;               // 0xaa - 0xab (default: 0x0000)
+
+    // Clock Scale stpclk low timer
+    uint8_t ctltmr;                // 0xac        (default: 0x00)
+    uint8_t rsvd13;                // 0xad
+
+    // Slock Scale STPCLK high timer
+    uint8_t cthtmr;                // 0xae        (default: 0x00)
+
+} __attribute__((packed));
+
 
 
 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;
+    struct piix3_config_space * piix3_cfg = (struct piix3_config_space *)(pci_dev->config_data);
 
     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;
+    piix3_cfg->iort = 0x4d;
+    piix3_cfg->xbcs = 0x0003;
+    piix3_cfg->pirq_rc[0] = 0x80;
+    piix3_cfg->pirq_rc[1] = 0x80;
+    piix3_cfg->pirq_rc[2] = 0x80;
+    piix3_cfg->pirq_rc[3] = 0x80;
+    piix3_cfg->top_of_mem = 0x02;
+    piix3_cfg->mbirq0 = 0x80;
+    piix3_cfg->mbdma0 = 0x0c;
+    piix3_cfg->mbdma1 = 0x0c;
+    piix3_cfg->pcsc = 0x0002;
+    piix3_cfg->apicbase = 0x00;
+    piix3_cfg->dlc = 0x00;
+    piix3_cfg->smicntl = 0x08;
+    piix3_cfg->smien = 0x0000;
+    piix3_cfg->see = 0x00000000;
+    piix3_cfg->ftmr = 0x0f;
+    piix3_cfg->smireq = 0x0000;
+    piix3_cfg->ctltmr = 0x00;
+    piix3_cfg->cthtmr = 0x00;
 
     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]);
+    
+    v3_raise_irq(dev->vm, piix3_cfg->pirq_rc[intr_pin]);
 
+    return 0;
+}
 
 
 
@@ -87,13 +395,14 @@ static int setup_pci(struct vm_device * dev) {
     struct pci_device * pci_dev = NULL;
     struct v3_pci_bar bars[6];
     int i;
+    int bus_num = 0;
 
     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, 
+                                    bus_num, -1, 0, 
                                     "PIIX3", bars, 
                                     NULL, NULL, NULL, dev);
     if (pci_dev == NULL) {
@@ -108,6 +417,8 @@ 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);
+
     reset_piix3(dev);
 
     return 0;