aboutsummaryrefslogtreecommitdiff
path: root/hw/spapr.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/spapr.c')
-rw-r--r--hw/spapr.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/hw/spapr.c b/hw/spapr.c
index 6c64de82de..b5aefd72c3 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -34,6 +34,7 @@
#include "hw/spapr.h"
#include "hw/spapr_vio.h"
+#include "hw/xics.h"
#include <libfdt.h>
@@ -45,6 +46,7 @@
#define TIMEBASE_FREQ 512000000ULL
#define MAX_CPUS 32
+#define XICS_IRQS 1024
sPAPREnvironment *spapr;
@@ -64,6 +66,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr";
+ uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
int i;
char *modelname;
int ret;
@@ -125,6 +128,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
for (i = 0; i < smp_cpus; i++) {
CPUState *env = envs[i];
+ uint32_t gserver_prop[] = {cpu_to_be32(i), 0}; /* HACK! */
char *nodename;
uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
0xffffffff, 0xffffffff};
@@ -155,6 +159,9 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
pft_size_prop, sizeof(pft_size_prop))));
_FDT((fdt_property_string(fdt, "status", "okay")));
_FDT((fdt_property(fdt, "64-bit", NULL, 0)));
+ _FDT((fdt_property_cell(fdt, "ibm,ppc-interrupt-server#s", i)));
+ _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
+ gserver_prop, sizeof(gserver_prop))));
if (envs[i]->mmu_model & POWERPC_MMU_1TSEG) {
_FDT((fdt_property(fdt, "ibm,processor-segment-sizes",
@@ -176,6 +183,20 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
_FDT((fdt_end_node(fdt)));
+ /* interrupt controller */
+ _FDT((fdt_begin_node(fdt, "interrupt-controller@0")));
+
+ _FDT((fdt_property_string(fdt, "device_type",
+ "PowerPC-External-Interrupt-Presentation")));
+ _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
+ _FDT((fdt_property_cell(fdt, "reg", 0)));
+ _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
+ _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
+ interrupt_server_ranges_prop,
+ sizeof(interrupt_server_ranges_prop))));
+
+ _FDT((fdt_end_node(fdt)));
+
/* vdevice */
_FDT((fdt_begin_node(fdt, "vdevice")));
@@ -183,6 +204,8 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
_FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
_FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
_FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
+ _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
+ _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
_FDT((fdt_end_node(fdt)));
@@ -296,6 +319,10 @@ static void ppc_spapr_init(ram_addr_t ram_size,
}
qemu_free(filename);
+ /* Set up Interrupt Controller */
+ spapr->icp = xics_system_init(smp_cpus, envs, XICS_IRQS);
+
+ /* Set up VIO bus */
spapr->vio_bus = spapr_vio_bus_init();
for (i = 0; i < MAX_SERIAL_PORTS; i++) {