aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hw/pc.h1
-rw-r--r--hw/pc_piix.c6
-rw-r--r--hw/piix_pci.c49
-rw-r--r--hw/xen.h6
-rw-r--r--xen-all.c31
-rw-r--r--xen-stub.c13
6 files changed, 102 insertions, 4 deletions
diff --git a/hw/pc.h b/hw/pc.h
index 6d5730b26..0dcbee7ca 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -176,6 +176,7 @@ struct PCII440FXState;
typedef struct PCII440FXState PCII440FXState;
PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic, ram_addr_t ram_size);
+PCIBus *i440fx_xen_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *pic, ram_addr_t ram_size);
void i440fx_init_memory_mappings(PCII440FXState *d);
/* piix4.c */
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index e814f0053..9353b9110 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -120,7 +120,11 @@ static void pc_init1(ram_addr_t ram_size,
isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
if (pci_enabled) {
- pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
+ if (!xen_enabled()) {
+ pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
+ } else {
+ pci_bus = i440fx_xen_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
+ }
} else {
pci_bus = NULL;
i440fx_state = NULL;
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 5f0d92f10..7f1c4cca3 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -29,6 +29,7 @@
#include "isa.h"
#include "sysbus.h"
#include "range.h"
+#include "xen.h"
/*
* I440FX chipset data sheet.
@@ -172,6 +173,13 @@ static void i440fx_write_config(PCIDevice *dev,
}
}
+static void i440fx_write_config_xen(PCIDevice *dev,
+ uint32_t address, uint32_t val, int len)
+{
+ xen_piix_pci_write_config_client(address, val, len);
+ i440fx_write_config(dev, address, val, len);
+}
+
static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id)
{
PCII440FXState *d = opaque;
@@ -239,7 +247,10 @@ static int i440fx_initfn(PCIDevice *dev)
return 0;
}
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *pic, ram_addr_t ram_size)
+static PCIBus *i440fx_common_init(const char *device_name,
+ PCII440FXState **pi440fx_state,
+ int *piix3_devfn,
+ qemu_irq *pic, ram_addr_t ram_size)
{
DeviceState *dev;
PCIBus *b;
@@ -253,13 +264,13 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *
s->bus = b;
qdev_init_nofail(dev);
- d = pci_create_simple(b, 0, "i440FX");
+ d = pci_create_simple(b, 0, device_name);
*pi440fx_state = DO_UPCAST(PCII440FXState, dev, d);
piix3 = DO_UPCAST(PIIX3State, dev,
pci_create_simple_multifunction(b, -1, true, "PIIX3"));
piix3->pic = pic;
- pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, PIIX_NUM_PIRQS);
+
(*pi440fx_state)->piix3 = piix3;
*piix3_devfn = piix3->dev.devfn;
@@ -272,6 +283,30 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *
return b;
}
+PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
+ qemu_irq *pic, ram_addr_t ram_size)
+{
+ PCIBus *b;
+
+ b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic, ram_size);
+ pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, (*pi440fx_state)->piix3,
+ PIIX_NUM_PIRQS);
+
+ return b;
+}
+
+PCIBus *i440fx_xen_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
+ qemu_irq *pic, ram_addr_t ram_size)
+{
+ PCIBus *b;
+
+ b = i440fx_common_init("i440FX-xen", pi440fx_state, piix3_devfn, pic, ram_size);
+ pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq,
+ (*pi440fx_state)->piix3, PIIX_NUM_PIRQS);
+
+ return b;
+}
+
/* PIIX3 PCI to ISA bridge */
static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
{
@@ -430,6 +465,14 @@ static PCIDeviceInfo i440fx_info[] = {
.init = i440fx_initfn,
.config_write = i440fx_write_config,
},{
+ .qdev.name = "i440FX-xen",
+ .qdev.desc = "Host bridge",
+ .qdev.size = sizeof(PCII440FXState),
+ .qdev.vmsd = &vmstate_i440fx,
+ .qdev.no_user = 1,
+ .init = i440fx_initfn,
+ .config_write = i440fx_write_config_xen,
+ },{
.qdev.name = "PIIX3",
.qdev.desc = "ISA bridge",
.qdev.size = sizeof(PIIX3State),
diff --git a/hw/xen.h b/hw/xen.h
index bb4dcb5d1..a4096cadf 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -8,6 +8,8 @@
*/
#include <inttypes.h>
+#include "qemu-common.h"
+
/* xen-machine.c */
enum xen_mode {
XEN_EMULATE = 0, // xen emulation, using xenner (default)
@@ -29,6 +31,10 @@ static inline int xen_enabled(void)
#endif
}
+int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num);
+void xen_piix3_set_irq(void *opaque, int irq_num, int level);
+void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len);
+
int xen_init(void);
int xen_hvm_init(void);
void xen_vcpu_init(void);
diff --git a/xen-all.c b/xen-all.c
index 0b984b25a..acb051cff 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -6,9 +6,40 @@
*
*/
+#include "hw/pci.h"
#include "hw/xen_common.h"
#include "hw/xen_backend.h"
+/* Xen specific function for piix pci */
+
+int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+{
+ return irq_num + ((pci_dev->devfn >> 3) << 2);
+}
+
+void xen_piix3_set_irq(void *opaque, int irq_num, int level)
+{
+ xc_hvm_set_pci_intx_level(xen_xc, xen_domid, 0, 0, irq_num >> 2,
+ irq_num & 3, level);
+}
+
+void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
+{
+ int i;
+
+ /* Scan for updates to PCI link routes (0x60-0x63). */
+ for (i = 0; i < len; i++) {
+ uint8_t v = (val >> (8 * i)) & 0xff;
+ if (v & 0x80) {
+ v = 0;
+ }
+ v &= 0xf;
+ if (((address + i) >= 0x60) && ((address + i) <= 0x63)) {
+ xc_hvm_set_pci_link_route(xen_xc, xen_domid, address + i - 0x60, v);
+ }
+ }
+}
+
/* VCPU Operations, MMIO, IO ring ... */
static void xen_reset_vcpu(void *opaque)
diff --git a/xen-stub.c b/xen-stub.c
index beb982ff5..dc90f108c 100644
--- a/xen-stub.c
+++ b/xen-stub.c
@@ -9,6 +9,19 @@
#include "qemu-common.h"
#include "hw/xen.h"
+int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+{
+ return -1;
+}
+
+void xen_piix3_set_irq(void *opaque, int irq_num, int level)
+{
+}
+
+void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
+{
+}
+
int xen_init(void)
{
return -ENOSYS;