aboutsummaryrefslogtreecommitdiff
path: root/hw/spapr.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/spapr.c')
-rw-r--r--hw/spapr.c36
1 files changed, 32 insertions, 4 deletions
diff --git a/hw/spapr.c b/hw/spapr.c
index 933af322c5..bdaa938b6b 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -39,10 +39,12 @@
#include "hw/spapr.h"
#include "hw/spapr_vio.h"
+#include "hw/spapr_pci.h"
#include "hw/xics.h"
#include "kvm.h"
#include "kvm_ppc.h"
+#include "pci.h"
#include "exec-memory.h"
@@ -62,6 +64,11 @@
#define MAX_CPUS 256
#define XICS_IRQS 1024
+#define SPAPR_PCI_BUID 0x800000020000001ULL
+#define SPAPR_PCI_MEM_WIN_ADDR (0x10000000000ULL + 0xA0000000)
+#define SPAPR_PCI_MEM_WIN_SIZE 0x20000000
+#define SPAPR_PCI_IO_WIN_ADDR (0x10000000000ULL + 0x80000000)
+
#define PHANDLE_XICP 0x00001111
sPAPREnvironment *spapr;
@@ -146,6 +153,14 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
&end_prop, sizeof(end_prop))));
_FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));
+ /*
+ * Because we don't always invoke any firmware, we can't rely on
+ * that to do BAR allocation. Long term, we should probably do
+ * that ourselves, but for now, this setting (plus advertising the
+ * current BARs as 0) causes sufficiently recent kernels to to the
+ * BAR assignment themselves */
+ _FDT((fdt_property_cell(fdt, "linux,pci-probe-only", 0)));
+
_FDT((fdt_end_node(fdt)));
/* memory node(s) */
@@ -308,6 +323,7 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
{
int ret;
void *fdt;
+ sPAPRPHBState *phb;
fdt = g_malloc(FDT_MAX_SIZE);
@@ -320,6 +336,15 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
exit(1);
}
+ QLIST_FOREACH(phb, &spapr->phbs, list) {
+ ret = spapr_populate_pci_devices(phb, PHANDLE_XICP, fdt);
+ }
+
+ if (ret < 0) {
+ fprintf(stderr, "couldn't setup PCI devices in fdt\n");
+ exit(1);
+ }
+
/* RTAS */
ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size);
if (ret < 0) {
@@ -478,6 +503,12 @@ static void ppc_spapr_init(ram_addr_t ram_size,
}
}
+ /* Set up PCI */
+ spapr_create_phb(spapr, "pci", SPAPR_PCI_BUID,
+ SPAPR_PCI_MEM_WIN_ADDR,
+ SPAPR_PCI_MEM_WIN_SIZE,
+ SPAPR_PCI_IO_WIN_ADDR);
+
for (i = 0; i < nb_nics; i++) {
NICInfo *nd = &nd_table[i];
@@ -488,10 +519,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
if (strcmp(nd->model, "ibmveth") == 0) {
spapr_vlan_create(spapr->vio_bus, 0x1000 + i, nd);
} else {
- fprintf(stderr, "pSeries (sPAPR) platform does not support "
- "NIC model '%s' (only ibmveth is supported)\n",
- nd->model);
- exit(1);
+ pci_nic_init_nofail(&nd_table[i], nd->model, NULL);
}
}