diff mbox

[40/77] ppc/pnv: Wire up XICS native with PowerNV platform

Message ID 1447201710-10229-41-git-send-email-benh@kernel.crashing.org
State New
Headers show

Commit Message

Benjamin Herrenschmidt Nov. 11, 2015, 12:27 a.m. UTC
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 hw/ppc/pnv.c          | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/pnv.h  |  2 ++
 include/hw/ppc/xics.h |  2 ++
 3 files changed, 73 insertions(+)

Comments

David Gibson Dec. 1, 2015, 6:41 a.m. UTC | #1
On Wed, Nov 11, 2015 at 11:27:53AM +1100, Benjamin Herrenschmidt wrote:
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Looks sound enough, but will probably need some rework due to other
suggested changes in the new xics stuff.

> ---
>  hw/ppc/pnv.c          | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/hw/ppc/pnv.h  |  2 ++
>  include/hw/ppc/xics.h |  2 ++
>  3 files changed, 73 insertions(+)
> 
> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> index 2eac877..a7a9b0f 100644
> --- a/hw/ppc/pnv.c
> +++ b/hw/ppc/pnv.c
> @@ -41,6 +41,7 @@
>  #include "hw/ppc/ppc.h"
>  #include "hw/ppc/pnv.h"
>  #include "hw/loader.h"
> +#include "hw/ppc/xics.h"
>  #include "hw/ppc/pnv_xscom.h"
>  
>  #include "exec/address-spaces.h"
> @@ -81,6 +82,59 @@ struct sPowerNVMachineState {
>      PnvSystem sys;
>  };
>  
> +static XICSState *try_create_xics(const char *type, int nr_servers,
> +                                  int nr_irqs, Error **errp)
> +{
> +    Error *err = NULL;
> +    DeviceState *dev;
> +
> +    dev = qdev_create(NULL, type);
> +    qdev_prop_set_uint32(dev, "nr_servers", nr_servers);
> +    object_property_set_bool(OBJECT(dev), true, "realized", &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        object_unparent(OBJECT(dev));
> +        return NULL;
> +    }
> +
> +    return XICS_COMMON(dev);
> +}
> +
> +static XICSState *xics_system_init(int nr_servers, int nr_irqs)
> +{
> +    XICSState *xics = NULL;
> +
> +#if 0 /* Some fixing needed to handle native ICS in KVM mode */
> +    if (kvm_enabled()) {
> +        QemuOpts *machine_opts = qemu_get_machine_opts();
> +        bool irqchip_allowed = qemu_opt_get_bool(machine_opts,
> +                                                "kernel_irqchip", true);
> +        bool irqchip_required = qemu_opt_get_bool(machine_opts,
> +                                                  "kernel_irqchip", false);
> +        if (irqchip_allowed) {
> +                icp = try_create_xics(TYPE_KVM_XICS, nr_servers, nr_irqs,
> +                                      &error_abort);
> +        }
> +
> +        if (irqchip_required && !icp) {
> +            perror("Failed to create in-kernel XICS\n");
> +            abort();
> +        }
> +    }
> +#endif
> +
> +    if (!xics) {
> +        xics = try_create_xics(TYPE_XICS_NATIVE, nr_servers, nr_irqs,
> +                               &error_abort);
> +    }
> +
> +    if (!xics) {
> +        perror("Failed to create XICS\n");
> +        abort();
> +    }
> +    return xics;
> +}
> +
>  static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
>                                       size_t maxsize)
>  {
> @@ -366,6 +420,13 @@ static void *powernv_create_fdt(PnvSystem *sys, uint32_t initrd_base, uint32_t i
>  
>      _FDT((fdt_end_node(fdt)));
>  
> +    /* ICPs */
> +    CPU_FOREACH(cs) {
> +        PowerPCCPU *cpu = POWERPC_CPU(cs);
> +        uint32_t base_server = ppc_get_vcpu_dt_id(cpu);
> +        xics_create_native_icp_node(sys->xics, fdt, base_server, smt);
> +    }
> +
>      /* Memory */
>      _FDT((powernv_populate_memory(fdt)));
>  
> @@ -451,11 +512,17 @@ static void ppc_powernv_init(MachineState *machine)
>      MemoryRegion *ram = g_new(MemoryRegion, 1);
>      sPowerNVMachineState *pnv_machine = POWERNV_MACHINE(machine);
>      PnvSystem *sys = &pnv_machine->sys;
> +    XICSState *xics;
>      long fw_size;
>      char *filename;
>      void *fdt;
>      int i;
>  
> +    /* Set up Interrupt Controller before we create the VCPUs */
> +    xics = xics_system_init(smp_cpus * kvmppc_smt_threads() / smp_threads,
> +                            XICS_IRQS_POWERNV);
> +    sys->xics = xics;
> +
>      /* init CPUs */
>      if (cpu_model == NULL) {
>          cpu_model = kvm_enabled() ? "host" : "POWER8";
> @@ -475,6 +542,8 @@ static void ppc_powernv_init(MachineState *machine)
>          /* MSR[IP] doesn't exist nowadays */
>          env->msr_mask &= ~(1 << 6);
>  
> +        xics_cpu_setup(xics, cpu);
> +
>          qemu_register_reset(powernv_cpu_reset, cpu);
>      }
>  
> diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
> index cb157eb..80617b4 100644
> --- a/include/hw/ppc/pnv.h
> +++ b/include/hw/ppc/pnv.h
> @@ -21,6 +21,7 @@
>  
>  #include "hw/hw.h"
>  typedef struct XScomBus XScomBus;
> +typedef struct XICSState XICSState;
>  
>  /* Should we turn that into a QOjb of some sort ? */
>  typedef struct PnvChip {
> @@ -29,6 +30,7 @@ typedef struct PnvChip {
>  } PnvChip;
>  
>  typedef struct PnvSystem {
> +    XICSState *xics;
>      uint32_t  num_chips;
>  #define PNV_MAX_CHIPS		1
>      PnvChip   chips[PNV_MAX_CHIPS];
> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
> index 1cf7037..85d2fb9 100644
> --- a/include/hw/ppc/xics.h
> +++ b/include/hw/ppc/xics.h
> @@ -183,6 +183,8 @@ struct ICSIRQState {
>  };
>  
>  #define XICS_IRQS_SPAPR               1024
> +#define XICS_IRQS_POWERNV             (1 << 19)
> +
>  
>  qemu_irq xics_get_qirq(XICSState *icp, int irq);
>
diff mbox

Patch

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 2eac877..a7a9b0f 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -41,6 +41,7 @@ 
 #include "hw/ppc/ppc.h"
 #include "hw/ppc/pnv.h"
 #include "hw/loader.h"
+#include "hw/ppc/xics.h"
 #include "hw/ppc/pnv_xscom.h"
 
 #include "exec/address-spaces.h"
@@ -81,6 +82,59 @@  struct sPowerNVMachineState {
     PnvSystem sys;
 };
 
+static XICSState *try_create_xics(const char *type, int nr_servers,
+                                  int nr_irqs, Error **errp)
+{
+    Error *err = NULL;
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, type);
+    qdev_prop_set_uint32(dev, "nr_servers", nr_servers);
+    object_property_set_bool(OBJECT(dev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        object_unparent(OBJECT(dev));
+        return NULL;
+    }
+
+    return XICS_COMMON(dev);
+}
+
+static XICSState *xics_system_init(int nr_servers, int nr_irqs)
+{
+    XICSState *xics = NULL;
+
+#if 0 /* Some fixing needed to handle native ICS in KVM mode */
+    if (kvm_enabled()) {
+        QemuOpts *machine_opts = qemu_get_machine_opts();
+        bool irqchip_allowed = qemu_opt_get_bool(machine_opts,
+                                                "kernel_irqchip", true);
+        bool irqchip_required = qemu_opt_get_bool(machine_opts,
+                                                  "kernel_irqchip", false);
+        if (irqchip_allowed) {
+                icp = try_create_xics(TYPE_KVM_XICS, nr_servers, nr_irqs,
+                                      &error_abort);
+        }
+
+        if (irqchip_required && !icp) {
+            perror("Failed to create in-kernel XICS\n");
+            abort();
+        }
+    }
+#endif
+
+    if (!xics) {
+        xics = try_create_xics(TYPE_XICS_NATIVE, nr_servers, nr_irqs,
+                               &error_abort);
+    }
+
+    if (!xics) {
+        perror("Failed to create XICS\n");
+        abort();
+    }
+    return xics;
+}
+
 static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
                                      size_t maxsize)
 {
@@ -366,6 +420,13 @@  static void *powernv_create_fdt(PnvSystem *sys, uint32_t initrd_base, uint32_t i
 
     _FDT((fdt_end_node(fdt)));
 
+    /* ICPs */
+    CPU_FOREACH(cs) {
+        PowerPCCPU *cpu = POWERPC_CPU(cs);
+        uint32_t base_server = ppc_get_vcpu_dt_id(cpu);
+        xics_create_native_icp_node(sys->xics, fdt, base_server, smt);
+    }
+
     /* Memory */
     _FDT((powernv_populate_memory(fdt)));
 
@@ -451,11 +512,17 @@  static void ppc_powernv_init(MachineState *machine)
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     sPowerNVMachineState *pnv_machine = POWERNV_MACHINE(machine);
     PnvSystem *sys = &pnv_machine->sys;
+    XICSState *xics;
     long fw_size;
     char *filename;
     void *fdt;
     int i;
 
+    /* Set up Interrupt Controller before we create the VCPUs */
+    xics = xics_system_init(smp_cpus * kvmppc_smt_threads() / smp_threads,
+                            XICS_IRQS_POWERNV);
+    sys->xics = xics;
+
     /* init CPUs */
     if (cpu_model == NULL) {
         cpu_model = kvm_enabled() ? "host" : "POWER8";
@@ -475,6 +542,8 @@  static void ppc_powernv_init(MachineState *machine)
         /* MSR[IP] doesn't exist nowadays */
         env->msr_mask &= ~(1 << 6);
 
+        xics_cpu_setup(xics, cpu);
+
         qemu_register_reset(powernv_cpu_reset, cpu);
     }
 
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index cb157eb..80617b4 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -21,6 +21,7 @@ 
 
 #include "hw/hw.h"
 typedef struct XScomBus XScomBus;
+typedef struct XICSState XICSState;
 
 /* Should we turn that into a QOjb of some sort ? */
 typedef struct PnvChip {
@@ -29,6 +30,7 @@  typedef struct PnvChip {
 } PnvChip;
 
 typedef struct PnvSystem {
+    XICSState *xics;
     uint32_t  num_chips;
 #define PNV_MAX_CHIPS		1
     PnvChip   chips[PNV_MAX_CHIPS];
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index 1cf7037..85d2fb9 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -183,6 +183,8 @@  struct ICSIRQState {
 };
 
 #define XICS_IRQS_SPAPR               1024
+#define XICS_IRQS_POWERNV             (1 << 19)
+
 
 qemu_irq xics_get_qirq(XICSState *icp, int irq);