From 150e25f85baa7b7952ddd1bdfd7ff7801213ce51 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 24 Sep 2019 16:25:08 +1000 Subject: spapr, xics, xive: Introduce SpaprInterruptController QOM interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SpaprIrq structure is used to represent ths spapr machine's irq backend. Except that it kind of conflates two concepts: one is the backend proper - a specific interrupt controller that we might or might not be using, the other is the irq configuration which covers the layout of irq space and which interrupt controllers are allowed. This leads to some pretty confusing code paths for the "dual" configuration where its hooks redirect to other SpaprIrq structures depending on the currently active irq controller. To clean this up, we start by introducing a new SpaprInterruptController QOM interface to represent strictly an interrupt controller backend, not counting anything configuration related. We implement this interface in the XICs and XIVE interrupt controllers, and in future we'll move relevant methods from SpaprIrq into it. Signed-off-by: David Gibson Reviewed-by: Greg Kurz Reviewed-by: Cédric Le Goater --- hw/intc/spapr_xive.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'hw/intc/spapr_xive.c') diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 04879ab..b67e9c3 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -519,6 +519,10 @@ static const TypeInfo spapr_xive_info = { .instance_init = spapr_xive_instance_init, .instance_size = sizeof(SpaprXive), .class_init = spapr_xive_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_SPAPR_INTC }, + { } + }, }; static void spapr_xive_register_types(void) -- cgit v1.1 From ebd6be089b4c87554362b516c3ba530217d3f3db Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 26 Sep 2019 14:11:23 +1000 Subject: spapr, xics, xive: Move cpu_intc_create from SpaprIrq to SpaprInterruptController MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This method essentially represents code which belongs to the interrupt controller, but needs to be called on all possible intcs, rather than just the currently active one. The "dual" version therefore calls into the xics and xive versions confusingly. Handle this more directly, by making it instead a method on the intc backend, and always calling it on every backend that exists. While we're there, streamline the error reporting a bit. Signed-off-by: David Gibson Reviewed-by: Greg Kurz Reviewed-by: Cédric Le Goater --- hw/intc/spapr_xive.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'hw/intc/spapr_xive.c') diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index b67e9c3..9338dab 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -495,10 +495,33 @@ static Property spapr_xive_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static int spapr_xive_cpu_intc_create(SpaprInterruptController *intc, + PowerPCCPU *cpu, Error **errp) +{ + SpaprXive *xive = SPAPR_XIVE(intc); + Object *obj; + SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); + + obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(xive), errp); + if (!obj) { + return -1; + } + + spapr_cpu->tctx = XIVE_TCTX(obj); + + /* + * (TCG) Early setting the OS CAM line for hotplugged CPUs as they + * don't beneficiate from the reset of the XIVE IRQ backend + */ + spapr_xive_set_tctx_os_cam(spapr_cpu->tctx); + return 0; +} + static void spapr_xive_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass); + SpaprInterruptControllerClass *sicc = SPAPR_INTC_CLASS(klass); dc->desc = "sPAPR XIVE Interrupt Controller"; dc->props = spapr_xive_properties; @@ -511,6 +534,8 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) xrc->get_nvt = spapr_xive_get_nvt; xrc->write_nvt = spapr_xive_write_nvt; xrc->get_tctx = spapr_xive_get_tctx; + + sicc->cpu_intc_create = spapr_xive_cpu_intc_create; } static const TypeInfo spapr_xive_info = { -- cgit v1.1 From 0b0e52b1317f2a51704cbf32047864869763dea3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 26 Sep 2019 14:31:13 +1000 Subject: spapr, xics, xive: Move irq claim and free from SpaprIrq to SpaprInterruptController MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These methods, like cpu_intc_create, really belong to the interrupt controller, but need to be called on all possible intcs. Like cpu_intc_create, therefore, make them methods on the intc and always call it for all existing intcs. Signed-off-by: David Gibson Reviewed-by: Greg Kurz Reviewed-by: Cédric Le Goater --- hw/intc/spapr_xive.c | 71 ++++++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 33 deletions(-) (limited to 'hw/intc/spapr_xive.c') diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 9338dab..ff1a175 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -487,6 +487,42 @@ static const VMStateDescription vmstate_spapr_xive = { }, }; +static int spapr_xive_claim_irq(SpaprInterruptController *intc, int lisn, + bool lsi, Error **errp) +{ + SpaprXive *xive = SPAPR_XIVE(intc); + XiveSource *xsrc = &xive->source; + + assert(lisn < xive->nr_irqs); + + if (xive_eas_is_valid(&xive->eat[lisn])) { + error_setg(errp, "IRQ %d is not free", lisn); + return -EBUSY; + } + + /* + * Set default values when allocating an IRQ number + */ + xive->eat[lisn].w |= cpu_to_be64(EAS_VALID | EAS_MASKED); + if (lsi) { + xive_source_irq_set_lsi(xsrc, lisn); + } + + if (kvm_irqchip_in_kernel()) { + return kvmppc_xive_source_reset_one(xsrc, lisn, errp); + } + + return 0; +} + +static void spapr_xive_free_irq(SpaprInterruptController *intc, int lisn) +{ + SpaprXive *xive = SPAPR_XIVE(intc); + assert(lisn < xive->nr_irqs); + + xive->eat[lisn].w &= cpu_to_be64(~EAS_VALID); +} + static Property spapr_xive_properties[] = { DEFINE_PROP_UINT32("nr-irqs", SpaprXive, nr_irqs, 0), DEFINE_PROP_UINT32("nr-ends", SpaprXive, nr_ends, 0), @@ -536,6 +572,8 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) xrc->get_tctx = spapr_xive_get_tctx; sicc->cpu_intc_create = spapr_xive_cpu_intc_create; + sicc->claim_irq = spapr_xive_claim_irq; + sicc->free_irq = spapr_xive_free_irq; } static const TypeInfo spapr_xive_info = { @@ -557,39 +595,6 @@ static void spapr_xive_register_types(void) type_init(spapr_xive_register_types) -int spapr_xive_irq_claim(SpaprXive *xive, int lisn, bool lsi, Error **errp) -{ - XiveSource *xsrc = &xive->source; - - assert(lisn < xive->nr_irqs); - - if (xive_eas_is_valid(&xive->eat[lisn])) { - error_setg(errp, "IRQ %d is not free", lisn); - return -EBUSY; - } - - /* - * Set default values when allocating an IRQ number - */ - xive->eat[lisn].w |= cpu_to_be64(EAS_VALID | EAS_MASKED); - if (lsi) { - xive_source_irq_set_lsi(xsrc, lisn); - } - - if (kvm_irqchip_in_kernel()) { - return kvmppc_xive_source_reset_one(xsrc, lisn, errp); - } - - return 0; -} - -void spapr_xive_irq_free(SpaprXive *xive, int lisn) -{ - assert(lisn < xive->nr_irqs); - - xive->eat[lisn].w &= cpu_to_be64(~EAS_VALID); -} - /* * XIVE hcalls * -- cgit v1.1 From 7bcdbcca2f498b8c93f33241488305a3694a941c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 26 Sep 2019 16:09:46 +1000 Subject: spapr, xics, xive: Move set_irq from SpaprIrq to SpaprInterruptController MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This method depends only on the active irq controller. Now that we've formalized the notion of active controller we can dispatch directly through that, rather than dispatching via SpaprIrq with the dual version having to do a second conditional dispatch. Signed-off-by: David Gibson Reviewed-by: Greg Kurz Reviewed-by: Cédric Le Goater --- hw/intc/spapr_xive.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'hw/intc/spapr_xive.c') diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index ff1a175..52d5e71 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -553,6 +553,17 @@ static int spapr_xive_cpu_intc_create(SpaprInterruptController *intc, return 0; } +static void spapr_xive_set_irq(SpaprInterruptController *intc, int irq, int val) +{ + SpaprXive *xive = SPAPR_XIVE(intc); + + if (kvm_irqchip_in_kernel()) { + kvmppc_xive_source_set_irq(&xive->source, irq, val); + } else { + xive_source_set_irq(&xive->source, irq, val); + } +} + static void spapr_xive_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -574,6 +585,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) sicc->cpu_intc_create = spapr_xive_cpu_intc_create; sicc->claim_irq = spapr_xive_claim_irq; sicc->free_irq = spapr_xive_free_irq; + sicc->set_irq = spapr_xive_set_irq; } static const TypeInfo spapr_xive_info = { -- cgit v1.1 From 328d8eb24db8ec415260ee7243adf2e3d7e81bad Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 26 Sep 2019 16:12:05 +1000 Subject: spapr, xics, xive: Move print_info from SpaprIrq to SpaprInterruptController MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This method depends only on the active irq controller. Now that we've formalized the notion of active controller we can dispatch directly through that, rather than dispatching via SpaprIrq with the dual version having to do a second conditional dispatch. Signed-off-by: David Gibson Reviewed-by: Greg Kurz Reviewed-by: Cédric Le Goater --- hw/intc/spapr_xive.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'hw/intc/spapr_xive.c') diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 52d5e71..700ec5c 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -564,6 +564,20 @@ static void spapr_xive_set_irq(SpaprInterruptController *intc, int irq, int val) } } +static void spapr_xive_print_info(SpaprInterruptController *intc, Monitor *mon) +{ + SpaprXive *xive = SPAPR_XIVE(intc); + CPUState *cs; + + CPU_FOREACH(cs) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + + xive_tctx_pic_print_info(spapr_cpu_state(cpu)->tctx, mon); + } + + spapr_xive_pic_print_info(xive, mon); +} + static void spapr_xive_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -586,6 +600,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) sicc->claim_irq = spapr_xive_claim_irq; sicc->free_irq = spapr_xive_free_irq; sicc->set_irq = spapr_xive_set_irq; + sicc->print_info = spapr_xive_print_info; } static const TypeInfo spapr_xive_info = { -- cgit v1.1 From 05289273c06de4bc6ece85a8bf672e588e34f36b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 30 Sep 2019 12:35:06 +1000 Subject: spapr, xics, xive: Move dt_populate from SpaprIrq to SpaprInterruptController MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This method depends only on the active irq controller. Now that we've formalized the notion of active controller we can dispatch directly through that, rather than dispatching via SpaprIrq with the dual version having to do a second conditional dispatch. Signed-off-by: David Gibson Reviewed-by: Greg Kurz Reviewed-by: Cédric Le Goater --- hw/intc/spapr_xive.c | 125 ++++++++++++++++++++++++++------------------------- 1 file changed, 63 insertions(+), 62 deletions(-) (limited to 'hw/intc/spapr_xive.c') diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 700ec5c..37ffb74 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -578,6 +578,68 @@ static void spapr_xive_print_info(SpaprInterruptController *intc, Monitor *mon) spapr_xive_pic_print_info(xive, mon); } +static void spapr_xive_dt(SpaprInterruptController *intc, uint32_t nr_servers, + void *fdt, uint32_t phandle) +{ + SpaprXive *xive = SPAPR_XIVE(intc); + int node; + uint64_t timas[2 * 2]; + /* Interrupt number ranges for the IPIs */ + uint32_t lisn_ranges[] = { + cpu_to_be32(0), + cpu_to_be32(nr_servers), + }; + /* + * EQ size - the sizes of pages supported by the system 4K, 64K, + * 2M, 16M. We only advertise 64K for the moment. + */ + uint32_t eq_sizes[] = { + cpu_to_be32(16), /* 64K */ + }; + /* + * The following array is in sync with the reserved priorities + * defined by the 'spapr_xive_priority_is_reserved' routine. + */ + uint32_t plat_res_int_priorities[] = { + cpu_to_be32(7), /* start */ + cpu_to_be32(0xf8), /* count */ + }; + + /* Thread Interrupt Management Area : User (ring 3) and OS (ring 2) */ + timas[0] = cpu_to_be64(xive->tm_base + + XIVE_TM_USER_PAGE * (1ull << TM_SHIFT)); + timas[1] = cpu_to_be64(1ull << TM_SHIFT); + timas[2] = cpu_to_be64(xive->tm_base + + XIVE_TM_OS_PAGE * (1ull << TM_SHIFT)); + timas[3] = cpu_to_be64(1ull << TM_SHIFT); + + _FDT(node = fdt_add_subnode(fdt, 0, xive->nodename)); + + _FDT(fdt_setprop_string(fdt, node, "device_type", "power-ivpe")); + _FDT(fdt_setprop(fdt, node, "reg", timas, sizeof(timas))); + + _FDT(fdt_setprop_string(fdt, node, "compatible", "ibm,power-ivpe")); + _FDT(fdt_setprop(fdt, node, "ibm,xive-eq-sizes", eq_sizes, + sizeof(eq_sizes))); + _FDT(fdt_setprop(fdt, node, "ibm,xive-lisn-ranges", lisn_ranges, + sizeof(lisn_ranges))); + + /* For Linux to link the LSIs to the interrupt controller. */ + _FDT(fdt_setprop(fdt, node, "interrupt-controller", NULL, 0)); + _FDT(fdt_setprop_cell(fdt, node, "#interrupt-cells", 2)); + + /* For SLOF */ + _FDT(fdt_setprop_cell(fdt, node, "linux,phandle", phandle)); + _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle)); + + /* + * The "ibm,plat-res-int-priorities" property defines the priority + * ranges reserved by the hypervisor + */ + _FDT(fdt_setprop(fdt, 0, "ibm,plat-res-int-priorities", + plat_res_int_priorities, sizeof(plat_res_int_priorities))); +} + static void spapr_xive_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -601,6 +663,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) sicc->free_irq = spapr_xive_free_irq; sicc->set_irq = spapr_xive_set_irq; sicc->print_info = spapr_xive_print_info; + sicc->dt = spapr_xive_dt; } static const TypeInfo spapr_xive_info = { @@ -1601,65 +1664,3 @@ void spapr_xive_hcall_init(SpaprMachineState *spapr) spapr_register_hypercall(H_INT_SYNC, h_int_sync); spapr_register_hypercall(H_INT_RESET, h_int_reset); } - -void spapr_dt_xive(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt, - uint32_t phandle) -{ - SpaprXive *xive = spapr->xive; - int node; - uint64_t timas[2 * 2]; - /* Interrupt number ranges for the IPIs */ - uint32_t lisn_ranges[] = { - cpu_to_be32(0), - cpu_to_be32(nr_servers), - }; - /* - * EQ size - the sizes of pages supported by the system 4K, 64K, - * 2M, 16M. We only advertise 64K for the moment. - */ - uint32_t eq_sizes[] = { - cpu_to_be32(16), /* 64K */ - }; - /* - * The following array is in sync with the reserved priorities - * defined by the 'spapr_xive_priority_is_reserved' routine. - */ - uint32_t plat_res_int_priorities[] = { - cpu_to_be32(7), /* start */ - cpu_to_be32(0xf8), /* count */ - }; - - /* Thread Interrupt Management Area : User (ring 3) and OS (ring 2) */ - timas[0] = cpu_to_be64(xive->tm_base + - XIVE_TM_USER_PAGE * (1ull << TM_SHIFT)); - timas[1] = cpu_to_be64(1ull << TM_SHIFT); - timas[2] = cpu_to_be64(xive->tm_base + - XIVE_TM_OS_PAGE * (1ull << TM_SHIFT)); - timas[3] = cpu_to_be64(1ull << TM_SHIFT); - - _FDT(node = fdt_add_subnode(fdt, 0, xive->nodename)); - - _FDT(fdt_setprop_string(fdt, node, "device_type", "power-ivpe")); - _FDT(fdt_setprop(fdt, node, "reg", timas, sizeof(timas))); - - _FDT(fdt_setprop_string(fdt, node, "compatible", "ibm,power-ivpe")); - _FDT(fdt_setprop(fdt, node, "ibm,xive-eq-sizes", eq_sizes, - sizeof(eq_sizes))); - _FDT(fdt_setprop(fdt, node, "ibm,xive-lisn-ranges", lisn_ranges, - sizeof(lisn_ranges))); - - /* For Linux to link the LSIs to the interrupt controller. */ - _FDT(fdt_setprop(fdt, node, "interrupt-controller", NULL, 0)); - _FDT(fdt_setprop_cell(fdt, node, "#interrupt-cells", 2)); - - /* For SLOF */ - _FDT(fdt_setprop_cell(fdt, node, "linux,phandle", phandle)); - _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle)); - - /* - * The "ibm,plat-res-int-priorities" property defines the priority - * ranges reserved by the hypervisor - */ - _FDT(fdt_setprop(fdt, 0, "ibm,plat-res-int-priorities", - plat_res_int_priorities, sizeof(plat_res_int_priorities))); -} -- cgit v1.1 From 567192d486cc3073eb097246acc98b200fa3d198 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 26 Sep 2019 23:58:36 +1000 Subject: spapr, xics, xive: Move SpaprIrq::reset hook logic into activate/deactivate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It turns out that all the logic in the SpaprIrq::reset hooks (and some in the SpaprIrq::post_load hooks) isn't really related to resetting the irq backend (that's handled by the backends' own reset routines). Rather its about getting the backend ready to be the active interrupt controller or stopping being the active interrupt controller - reset (and post_load) is just the only time that changes at present. To make this flow clearer, move the logic into the explicit backend activate and deactivate hooks. Signed-off-by: David Gibson Reviewed-by: Greg Kurz Reviewed-by: Cédric Le Goater --- hw/intc/spapr_xive.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'hw/intc/spapr_xive.c') diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 37ffb74..1811653 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -640,6 +640,42 @@ static void spapr_xive_dt(SpaprInterruptController *intc, uint32_t nr_servers, plat_res_int_priorities, sizeof(plat_res_int_priorities))); } +static int spapr_xive_activate(SpaprInterruptController *intc, Error **errp) +{ + SpaprXive *xive = SPAPR_XIVE(intc); + CPUState *cs; + + CPU_FOREACH(cs) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + + /* (TCG) Set the OS CAM line of the thread interrupt context. */ + spapr_xive_set_tctx_os_cam(spapr_cpu_state(cpu)->tctx); + } + + if (kvm_enabled()) { + int rc = spapr_irq_init_kvm(kvmppc_xive_connect, intc, errp); + if (rc < 0) { + return rc; + } + } + + /* Activate the XIVE MMIOs */ + spapr_xive_mmio_set_enabled(xive, true); + + return 0; +} + +static void spapr_xive_deactivate(SpaprInterruptController *intc) +{ + SpaprXive *xive = SPAPR_XIVE(intc); + + spapr_xive_mmio_set_enabled(xive, false); + + if (kvm_irqchip_in_kernel()) { + kvmppc_xive_disconnect(intc); + } +} + static void spapr_xive_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -658,6 +694,8 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) xrc->write_nvt = spapr_xive_write_nvt; xrc->get_tctx = spapr_xive_get_tctx; + sicc->activate = spapr_xive_activate; + sicc->deactivate = spapr_xive_deactivate; sicc->cpu_intc_create = spapr_xive_cpu_intc_create; sicc->claim_irq = spapr_xive_claim_irq; sicc->free_irq = spapr_xive_free_irq; -- cgit v1.1 From 605994e5b7d17dcc275465b4f89816d29105b238 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 27 Sep 2019 10:53:53 +1000 Subject: spapr, xics, xive: Move SpaprIrq::post_load hook to backends MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The remaining logic in the post_load hook really belongs to the interrupt controller backends, and just needs to be called on the active controller (after the active controller is set to the right thing based on the incoming migration in the generic spapr_irq_post_load() logic). Signed-off-by: David Gibson Reviewed-by: Greg Kurz Reviewed-by: Cédric Le Goater --- hw/intc/spapr_xive.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'hw/intc/spapr_xive.c') diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 1811653..ba32d2c 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -462,10 +462,10 @@ static int vmstate_spapr_xive_pre_save(void *opaque) * Called by the sPAPR IRQ backend 'post_load' method at the machine * level. */ -int spapr_xive_post_load(SpaprXive *xive, int version_id) +static int spapr_xive_post_load(SpaprInterruptController *intc, int version_id) { if (kvm_irqchip_in_kernel()) { - return kvmppc_xive_post_load(xive, version_id); + return kvmppc_xive_post_load(SPAPR_XIVE(intc), version_id); } return 0; @@ -702,6 +702,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) sicc->set_irq = spapr_xive_set_irq; sicc->print_info = spapr_xive_print_info; sicc->dt = spapr_xive_dt; + sicc->post_load = spapr_xive_post_load; } static const TypeInfo spapr_xive_info = { -- cgit v1.1 From d49e8a9b46e4594223806ae622af462ff7bfa158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 22 Oct 2019 18:38:10 +0200 Subject: ppc: Reset the interrupt presenter from the CPU reset handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On the sPAPR machine and PowerNV machine, the interrupt presenters are created by a machine handler at the core level and are reset independently. This is not consistent and it raises issues when it comes to handle hot-plugged CPUs. In that case, the presenters are not reset. This is less of an issue in XICS, although a zero MFFR could be a concern, but in XIVE, the OS CAM line is not set and this breaks the presenting algorithm. The current code has workarounds which need a global cleanup. Extend the sPAPR IRQ backend and the PowerNV Chip class with a new cpu_intc_reset() handler called by the CPU reset handler and remove the XiveTCTX reset handler which is now redundant. Signed-off-by: Cédric Le Goater Message-Id: <20191022163812.330-6-clg@kaod.org> Reviewed-by: Greg Kurz Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/intc/spapr_xive.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'hw/intc/spapr_xive.c') diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index ba32d2c..20a8d82 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -553,6 +553,14 @@ static int spapr_xive_cpu_intc_create(SpaprInterruptController *intc, return 0; } +static void spapr_xive_cpu_intc_reset(SpaprInterruptController *intc, + PowerPCCPU *cpu) +{ + XiveTCTX *tctx = spapr_cpu_state(cpu)->tctx; + + xive_tctx_reset(tctx); +} + static void spapr_xive_set_irq(SpaprInterruptController *intc, int irq, int val) { SpaprXive *xive = SPAPR_XIVE(intc); @@ -697,6 +705,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) sicc->activate = spapr_xive_activate; sicc->deactivate = spapr_xive_deactivate; sicc->cpu_intc_create = spapr_xive_cpu_intc_create; + sicc->cpu_intc_reset = spapr_xive_cpu_intc_reset; sicc->claim_irq = spapr_xive_claim_irq; sicc->free_irq = spapr_xive_free_irq; sicc->set_irq = spapr_xive_set_irq; -- cgit v1.1 From 97c00c54449b4ff349f85c6ce409dadd1b935a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 22 Oct 2019 18:38:12 +0200 Subject: spapr/xive: Set the OS CAM line at reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a Virtual Processor is scheduled to run on a HW thread, the hypervisor pushes its identifier in the OS CAM line. When running with kernel_irqchip=off, QEMU needs to emulate the same behavior. Set the OS CAM line when the interrupt presenter of the sPAPR core is reset. This will also cover the case of hot-plugged CPUs. This change also has the benefit to remove the use of CPU_FOREACH() which can be unsafe. Signed-off-by: Cédric Le Goater Reviewed-by: Greg Kurz Message-Id: <20191022163812.330-8-clg@kaod.org> Signed-off-by: David Gibson --- hw/intc/spapr_xive.c | 48 +++++++++++++++++------------------------------- 1 file changed, 17 insertions(+), 31 deletions(-) (limited to 'hw/intc/spapr_xive.c') diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 20a8d82..d8e1291 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -205,23 +205,6 @@ void spapr_xive_mmio_set_enabled(SpaprXive *xive, bool enable) memory_region_set_enabled(&xive->end_source.esb_mmio, false); } -/* - * When a Virtual Processor is scheduled to run on a HW thread, the - * hypervisor pushes its identifier in the OS CAM line. Emulate the - * same behavior under QEMU. - */ -void spapr_xive_set_tctx_os_cam(XiveTCTX *tctx) -{ - uint8_t nvt_blk; - uint32_t nvt_idx; - uint32_t nvt_cam; - - spapr_xive_cpu_to_nvt(POWERPC_CPU(tctx->cs), &nvt_blk, &nvt_idx); - - nvt_cam = cpu_to_be32(TM_QW1W2_VO | xive_nvt_cam_line(nvt_blk, nvt_idx)); - memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &nvt_cam, 4); -} - static void spapr_xive_end_reset(XiveEND *end) { memset(end, 0, sizeof(*end)); @@ -544,21 +527,32 @@ static int spapr_xive_cpu_intc_create(SpaprInterruptController *intc, } spapr_cpu->tctx = XIVE_TCTX(obj); - - /* - * (TCG) Early setting the OS CAM line for hotplugged CPUs as they - * don't beneficiate from the reset of the XIVE IRQ backend - */ - spapr_xive_set_tctx_os_cam(spapr_cpu->tctx); return 0; } +static void xive_tctx_set_os_cam(XiveTCTX *tctx, uint32_t os_cam) +{ + uint32_t qw1w2 = cpu_to_be32(TM_QW1W2_VO | os_cam); + memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &qw1w2, 4); +} + static void spapr_xive_cpu_intc_reset(SpaprInterruptController *intc, PowerPCCPU *cpu) { XiveTCTX *tctx = spapr_cpu_state(cpu)->tctx; + uint8_t nvt_blk; + uint32_t nvt_idx; xive_tctx_reset(tctx); + + /* + * When a Virtual Processor is scheduled to run on a HW thread, + * the hypervisor pushes its identifier in the OS CAM line. + * Emulate the same behavior under QEMU. + */ + spapr_xive_cpu_to_nvt(cpu, &nvt_blk, &nvt_idx); + + xive_tctx_set_os_cam(tctx, xive_nvt_cam_line(nvt_blk, nvt_idx)); } static void spapr_xive_set_irq(SpaprInterruptController *intc, int irq, int val) @@ -651,14 +645,6 @@ static void spapr_xive_dt(SpaprInterruptController *intc, uint32_t nr_servers, static int spapr_xive_activate(SpaprInterruptController *intc, Error **errp) { SpaprXive *xive = SPAPR_XIVE(intc); - CPUState *cs; - - CPU_FOREACH(cs) { - PowerPCCPU *cpu = POWERPC_CPU(cs); - - /* (TCG) Set the OS CAM line of the thread interrupt context. */ - spapr_xive_set_tctx_os_cam(spapr_cpu_state(cpu)->tctx); - } if (kvm_enabled()) { int rc = spapr_irq_init_kvm(kvmppc_xive_connect, intc, errp); -- cgit v1.1