All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/19] spapr: IRQ subsystem cleanup
@ 2019-10-09  6:07 David Gibson
  2019-10-09  6:08 ` [PATCH v4 01/19] xive: Make some device types not user creatable David Gibson
                   ` (20 more replies)
  0 siblings, 21 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:07 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

This is a substantial rework to clean up the handling of IRQs in
spapr.  It includes some cleanups to both the XICS and XIVE interrupt
controller backends, as well as more to the common spapr irq handling
infrastructure.

The last two patches of this series, dealing with VFIO devices, are
RFC only - there some problems that I'm discussing with Alex
Williamson.

Changes since v3:
 * Further minor tweaks to error handling
 * Other minor polishes from feedback
 * Added some patches to address VFIO irq routing
 * Removed the first ~20 patches, which are now merged

Changes since v2:
 * Fixed a bug where the "move handling multiple irq frees" to
   frontend patch was actually freeing one irq over and over, rather
   than freeing multiple irqs
 * Fixed some places I missed still using only-Error * style, and flow
   on adjustments
 * New idiom to iterate across all constructed backends for the things
   that need that (cpu_intc_create, claim & freem), rather than
   open-coding a call on the xics, then xive versions.

Changes since v1:
 * Lots of extra patches
 * Many minor adjustments based on feedback
 * Moved towards return value + Error * style, instead of just Error *
   style

David Gibson (16):
  spapr, xics, xive: Introduce SpaprInterruptController QOM interface
  spapr, xics, xive: Move cpu_intc_create from SpaprIrq to
    SpaprInterruptController
  spapr, xics, xive: Move irq claim and free from SpaprIrq to
    SpaprInterruptController
  spapr: Formalize notion of active interrupt controller
  spapr, xics, xive: Move set_irq from SpaprIrq to
    SpaprInterruptController
  spapr, xics, xive: Move print_info from SpaprIrq to
    SpaprInterruptController
  spapr, xics, xive: Move dt_populate from SpaprIrq to
    SpaprInterruptController
  spapr, xics, xive: Match signatures for XICS and XIVE KVM connect
    routines
  spapr: Remove SpaprIrq::init_kvm hook
  spapr, xics, xive: Move SpaprIrq::reset hook logic into
    activate/deactivate
  spapr, xics, xive: Move SpaprIrq::post_load hook to backends
  spapr: Remove SpaprIrq::nr_msis
  spapr: Move SpaprIrq::nr_xirqs to SpaprMachineClass
  spapr: Remove last pieces of SpaprIrq
  spapr: Handle irq backend changes with VFIO PCI devices
  spapr: Work around spurious warnings from vfio INTx initialization

Greg Kurz (2):
  xive: Make some device types not user creatable
  xics: Make some device types not user creatable

Stefan Brankovic (1):
  target/ppc: Fix for optimized vsl/vsr instructions

 hw/intc/spapr_xive.c                | 295 ++++++++----
 hw/intc/spapr_xive_kvm.c            |  22 +-
 hw/intc/xics.c                      |  10 +
 hw/intc/xics_kvm.c                  |   9 +-
 hw/intc/xics_spapr.c                | 110 ++++-
 hw/intc/xive.c                      |  15 +
 hw/ppc/spapr.c                      |  52 ++-
 hw/ppc/spapr_caps.c                 |  64 +++
 hw/ppc/spapr_cpu_core.c             |   3 +-
 hw/ppc/spapr_hcall.c                |   7 +-
 hw/ppc/spapr_irq.c                  | 668 +++++++++-------------------
 hw/ppc/spapr_pci.c                  |  16 +-
 include/hw/pci-host/spapr.h         |   4 +-
 include/hw/ppc/spapr.h              |  17 +-
 include/hw/ppc/spapr_irq.h          |  72 +--
 include/hw/ppc/spapr_xive.h         |   9 +-
 include/hw/ppc/xics_spapr.h         |   6 +-
 target/ppc/translate/vmx-impl.inc.c |  84 ++--
 18 files changed, 769 insertions(+), 694 deletions(-)

-- 
2.21.0



^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v4 01/19] xive: Make some device types not user creatable
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09  6:08 ` [PATCH v4 02/19] xics: " David Gibson
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

From: Greg Kurz <groug@kaod.org>

Some device types of the XIVE model are exposed to the QEMU command
line:

$ ppc64-softmmu/qemu-system-ppc64 -device help | grep xive
name "xive-end-source", desc "XIVE END Source"
name "xive-source", desc "XIVE Interrupt Source"
name "xive-tctx", desc "XIVE Interrupt Thread Context"

These are internal devices that shouldn't be instantiable by the
user. By the way, they can't be because their respective realize
functions expect link properties that can't be set from the command
line:

qemu-system-ppc64: -device xive-source: required link 'xive' not found:
 Property '.xive' not found
qemu-system-ppc64: -device xive-end-source: required link 'xive' not found:
 Property '.xive' not found
qemu-system-ppc64: -device xive-tctx: required link 'cpu' not found:
 Property '.cpu' not found

Hide them by setting dc->user_creatable to false in their respective
class init functions.

Signed-off-by: Greg Kurz <groug@kaod.org>
Message-Id: <157017473006.331610.2983143972519884544.stgit@bahia.lan>
Message-Id: <157045578401.865784.6058183726552779559.stgit@bahia.lan>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
[dwg: Folded comment update into base patch]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/intc/xive.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 29df06df11..453d389848 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -670,6 +670,11 @@ static void xive_tctx_class_init(ObjectClass *klass, void *data)
     dc->realize = xive_tctx_realize;
     dc->unrealize = xive_tctx_unrealize;
     dc->vmsd = &vmstate_xive_tctx;
+    /*
+     * Reason: part of XIVE interrupt controller, needs to be wired up
+     * by xive_tctx_create().
+     */
+    dc->user_creatable = false;
 }
 
 static const TypeInfo xive_tctx_info = {
@@ -1118,6 +1123,11 @@ static void xive_source_class_init(ObjectClass *klass, void *data)
     dc->props   = xive_source_properties;
     dc->realize = xive_source_realize;
     dc->vmsd    = &vmstate_xive_source;
+    /*
+     * Reason: part of XIVE interrupt controller, needs to be wired up,
+     * e.g. by spapr_xive_instance_init().
+     */
+    dc->user_creatable = false;
 }
 
 static const TypeInfo xive_source_info = {
@@ -1853,6 +1863,11 @@ static void xive_end_source_class_init(ObjectClass *klass, void *data)
     dc->desc    = "XIVE END Source";
     dc->props   = xive_end_source_properties;
     dc->realize = xive_end_source_realize;
+    /*
+     * Reason: part of XIVE interrupt controller, needs to be wired up,
+     * e.g. by spapr_xive_instance_init().
+     */
+    dc->user_creatable = false;
 }
 
 static const TypeInfo xive_end_source_info = {
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 02/19] xics: Make some device types not user creatable
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
  2019-10-09  6:08 ` [PATCH v4 01/19] xive: Make some device types not user creatable David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09  6:08 ` [PATCH v4 03/19] target/ppc: Fix for optimized vsl/vsr instructions David Gibson
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

From: Greg Kurz <groug@kaod.org>

Some device types of the XICS model are exposed to the QEMU command
line:

$ ppc64-softmmu/qemu-system-ppc64 -device help | grep ic[sp]
name "icp"
name "ics"
name "ics-spapr"
name "pnv-icp", desc "PowerNV ICP"

These are internal devices that shouldn't be instantiable by the
user. By the way, they can't be because their respective realize
functions expect link properties that can't be set from the command
line:

qemu-system-ppc64: -device icp: required link 'xics' not found:
 Property '.xics' not found
qemu-system-ppc64: -device ics: required link 'xics' not found:
 Property '.xics' not found
qemu-system-ppc64: -device ics-spapr: required link 'xics' not found:
 Property '.xics' not found
qemu-system-ppc64: -device pnv-icp: required link 'xics' not found:
 Property '.xics' not found

Hide them by setting dc->user_creatable to false in the base class
"icp" and "ics" init functions.

Signed-off-by: Greg Kurz <groug@kaod.org>
Message-Id: <157017826724.337875.14822177178282524024.stgit@bahia.lan>
Message-Id: <157045578962.865784.8551555523533955113.stgit@bahia.lan>
[dwg: Folded reason comment into base patch]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/intc/xics.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index dfe7dbd254..b5ac408f7b 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -369,6 +369,11 @@ static void icp_class_init(ObjectClass *klass, void *data)
 
     dc->realize = icp_realize;
     dc->unrealize = icp_unrealize;
+    /*
+     * Reason: part of XICS interrupt controller, needs to be wired up
+     * by icp_create().
+     */
+    dc->user_creatable = false;
 }
 
 static const TypeInfo icp_info = {
@@ -689,6 +694,11 @@ static void ics_class_init(ObjectClass *klass, void *data)
     dc->props = ics_properties;
     dc->reset = ics_reset;
     dc->vmsd = &vmstate_ics;
+    /*
+     * Reason: part of XICS interrupt controller, needs to be wired up,
+     * e.g. by spapr_irq_init().
+     */
+    dc->user_creatable = false;
 }
 
 static const TypeInfo ics_info = {
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 03/19] target/ppc: Fix for optimized vsl/vsr instructions
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
  2019-10-09  6:08 ` [PATCH v4 01/19] xive: Make some device types not user creatable David Gibson
  2019-10-09  6:08 ` [PATCH v4 02/19] xics: " David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09  6:08 ` [PATCH v4 04/19] spapr, xics, xive: Introduce SpaprInterruptController QOM interface David Gibson
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Stefan Brankovic, Jason Wang, Riku Voipio, Mark Cave-Ayland,
	groug, Laurent Vivier, Aleksandar Markovic, Paul A. Clark,
	Paolo Bonzini, Marc-André Lureau, philmd, David Gibson

From: Stefan Brankovic <stefan.brankovic@rt-rk.com>

In previous implementation, invocation of TCG shift function could request
shift of TCG variable by 64 bits when variable 'sh' is 0, which is not
supported in TCG (values can be shifted by 0 to 63 bits). This patch fixes
this by using two separate invocation of TCG shift functions, with maximum
shift amount of 32.

Name of variable 'shifted' is changed to 'carry' so variable naming
is similar to old helper implementation.

Variables 'avrA' and 'avrB' are replaced with variable 'avr'.

Fixes: 4e6d0920e7547e6af4bbac5ffe9adfe6ea621822
Reported-by: "Paul A. Clark" <pc@us.ibm.com>
Reported-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Suggested-by: Aleksandar Markovic <aleksandar.markovic@rt-rk.com>
Signed-off-by: Stefan Brankovic <stefan.brankovic@rt-rk.com>
Message-Id: <1570196639-7025-2-git-send-email-stefan.brankovic@rt-rk.com>
Tested-by: Paul A. Clarke  <pc@us.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 target/ppc/translate/vmx-impl.inc.c | 84 ++++++++++++++---------------
 1 file changed, 40 insertions(+), 44 deletions(-)

diff --git a/target/ppc/translate/vmx-impl.inc.c b/target/ppc/translate/vmx-impl.inc.c
index 2472a5217a..81d5a7a341 100644
--- a/target/ppc/translate/vmx-impl.inc.c
+++ b/target/ppc/translate/vmx-impl.inc.c
@@ -590,40 +590,38 @@ static void trans_vsl(DisasContext *ctx)
     int VT = rD(ctx->opcode);
     int VA = rA(ctx->opcode);
     int VB = rB(ctx->opcode);
-    TCGv_i64 avrA = tcg_temp_new_i64();
-    TCGv_i64 avrB = tcg_temp_new_i64();
+    TCGv_i64 avr = tcg_temp_new_i64();
     TCGv_i64 sh = tcg_temp_new_i64();
-    TCGv_i64 shifted = tcg_temp_new_i64();
+    TCGv_i64 carry = tcg_temp_new_i64();
     TCGv_i64 tmp = tcg_temp_new_i64();
 
-    /* Place bits 125-127 of vB in sh. */
-    get_avr64(avrB, VB, false);
-    tcg_gen_andi_i64(sh, avrB, 0x07ULL);
+    /* Place bits 125-127 of vB in 'sh'. */
+    get_avr64(avr, VB, false);
+    tcg_gen_andi_i64(sh, avr, 0x07ULL);
 
     /*
-     * Save highest sh bits of lower doubleword element of vA in variable
-     * shifted and perform shift on lower doubleword.
+     * Save highest 'sh' bits of lower doubleword element of vA in variable
+     * 'carry' and perform shift on lower doubleword.
      */
-    get_avr64(avrA, VA, false);
-    tcg_gen_subfi_i64(tmp, 64, sh);
-    tcg_gen_shr_i64(shifted, avrA, tmp);
-    tcg_gen_andi_i64(shifted, shifted, 0x7fULL);
-    tcg_gen_shl_i64(avrA, avrA, sh);
-    set_avr64(VT, avrA, false);
+    get_avr64(avr, VA, false);
+    tcg_gen_subfi_i64(tmp, 32, sh);
+    tcg_gen_shri_i64(carry, avr, 32);
+    tcg_gen_shr_i64(carry, carry, tmp);
+    tcg_gen_shl_i64(avr, avr, sh);
+    set_avr64(VT, avr, false);
 
     /*
      * Perform shift on higher doubleword element of vA and replace lowest
-     * sh bits with shifted.
+     * 'sh' bits with 'carry'.
      */
-    get_avr64(avrA, VA, true);
-    tcg_gen_shl_i64(avrA, avrA, sh);
-    tcg_gen_or_i64(avrA, avrA, shifted);
-    set_avr64(VT, avrA, true);
+    get_avr64(avr, VA, true);
+    tcg_gen_shl_i64(avr, avr, sh);
+    tcg_gen_or_i64(avr, avr, carry);
+    set_avr64(VT, avr, true);
 
-    tcg_temp_free_i64(avrA);
-    tcg_temp_free_i64(avrB);
+    tcg_temp_free_i64(avr);
     tcg_temp_free_i64(sh);
-    tcg_temp_free_i64(shifted);
+    tcg_temp_free_i64(carry);
     tcg_temp_free_i64(tmp);
 }
 
@@ -639,39 +637,37 @@ static void trans_vsr(DisasContext *ctx)
     int VT = rD(ctx->opcode);
     int VA = rA(ctx->opcode);
     int VB = rB(ctx->opcode);
-    TCGv_i64 avrA = tcg_temp_new_i64();
-    TCGv_i64 avrB = tcg_temp_new_i64();
+    TCGv_i64 avr = tcg_temp_new_i64();
     TCGv_i64 sh = tcg_temp_new_i64();
-    TCGv_i64 shifted = tcg_temp_new_i64();
+    TCGv_i64 carry = tcg_temp_new_i64();
     TCGv_i64 tmp = tcg_temp_new_i64();
 
-    /* Place bits 125-127 of vB in sh. */
-    get_avr64(avrB, VB, false);
-    tcg_gen_andi_i64(sh, avrB, 0x07ULL);
+    /* Place bits 125-127 of vB in 'sh'. */
+    get_avr64(avr, VB, false);
+    tcg_gen_andi_i64(sh, avr, 0x07ULL);
 
     /*
-     * Save lowest sh bits of higher doubleword element of vA in variable
-     * shifted and perform shift on higher doubleword.
+     * Save lowest 'sh' bits of higher doubleword element of vA in variable
+     * 'carry' and perform shift on higher doubleword.
      */
-    get_avr64(avrA, VA, true);
-    tcg_gen_subfi_i64(tmp, 64, sh);
-    tcg_gen_shl_i64(shifted, avrA, tmp);
-    tcg_gen_andi_i64(shifted, shifted, 0xfe00000000000000ULL);
-    tcg_gen_shr_i64(avrA, avrA, sh);
-    set_avr64(VT, avrA, true);
+    get_avr64(avr, VA, true);
+    tcg_gen_subfi_i64(tmp, 32, sh);
+    tcg_gen_shli_i64(carry, avr, 32);
+    tcg_gen_shl_i64(carry, carry, tmp);
+    tcg_gen_shr_i64(avr, avr, sh);
+    set_avr64(VT, avr, true);
     /*
      * Perform shift on lower doubleword element of vA and replace highest
-     * sh bits with shifted.
+     * 'sh' bits with 'carry'.
      */
-    get_avr64(avrA, VA, false);
-    tcg_gen_shr_i64(avrA, avrA, sh);
-    tcg_gen_or_i64(avrA, avrA, shifted);
-    set_avr64(VT, avrA, false);
+    get_avr64(avr, VA, false);
+    tcg_gen_shr_i64(avr, avr, sh);
+    tcg_gen_or_i64(avr, avr, carry);
+    set_avr64(VT, avr, false);
 
-    tcg_temp_free_i64(avrA);
-    tcg_temp_free_i64(avrB);
+    tcg_temp_free_i64(avr);
     tcg_temp_free_i64(sh);
-    tcg_temp_free_i64(shifted);
+    tcg_temp_free_i64(carry);
     tcg_temp_free_i64(tmp);
 }
 
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 04/19] spapr, xics, xive: Introduce SpaprInterruptController QOM interface
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (2 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 03/19] target/ppc: Fix for optimized vsl/vsr instructions David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09  6:08 ` [PATCH v4 05/19] spapr, xics, xive: Move cpu_intc_create from SpaprIrq to SpaprInterruptController David Gibson
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

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 <david@gibson.dropbear.id.au>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
---
 hw/intc/spapr_xive.c       |  4 ++++
 hw/intc/xics_spapr.c       |  4 ++++
 hw/ppc/spapr_irq.c         | 13 +++++++++++++
 include/hw/ppc/spapr_irq.h | 14 ++++++++++++++
 4 files changed, 35 insertions(+)

diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index 04879abf2e..b67e9c3245 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)
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 6e5eb24b3c..4874e6be55 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -343,6 +343,10 @@ static const TypeInfo ics_spapr_info = {
     .name = TYPE_ICS_SPAPR,
     .parent = TYPE_ICS,
     .class_init = ics_spapr_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_SPAPR_INTC },
+        { }
+    },
 };
 
 static void xics_spapr_register_types(void)
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 457eabe24c..8791dec1ba 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -23,6 +23,12 @@
 
 #include "trace.h"
 
+static const TypeInfo spapr_intc_info = {
+    .name = TYPE_SPAPR_INTC,
+    .parent = TYPE_INTERFACE,
+    .class_size = sizeof(SpaprInterruptControllerClass),
+};
+
 void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis)
 {
     spapr->irq_map_nr = nr_msis;
@@ -762,3 +768,10 @@ SpaprIrq spapr_irq_xics_legacy = {
     .set_irq     = spapr_irq_set_irq_xics,
     .init_kvm    = spapr_irq_init_kvm_xics,
 };
+
+static void spapr_irq_register_types(void)
+{
+    type_register_static(&spapr_intc_info);
+}
+
+type_init(spapr_irq_register_types)
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index 69a37f608e..b9398e0be3 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -31,6 +31,20 @@
 
 typedef struct SpaprMachineState SpaprMachineState;
 
+typedef struct SpaprInterruptController SpaprInterruptController;
+
+#define TYPE_SPAPR_INTC "spapr-interrupt-controller"
+#define SPAPR_INTC(obj)                                     \
+    INTERFACE_CHECK(SpaprInterruptController, (obj), TYPE_SPAPR_INTC)
+#define SPAPR_INTC_CLASS(klass)                                     \
+    OBJECT_CLASS_CHECK(SpaprInterruptControllerClass, (klass), TYPE_SPAPR_INTC)
+#define SPAPR_INTC_GET_CLASS(obj)                                   \
+    OBJECT_GET_CLASS(SpaprInterruptControllerClass, (obj), TYPE_SPAPR_INTC)
+
+typedef struct SpaprInterruptControllerClass {
+    InterfaceClass parent;
+} SpaprInterruptControllerClass;
+
 void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
 int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
                         Error **errp);
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 05/19] spapr, xics, xive: Move cpu_intc_create from SpaprIrq to SpaprInterruptController
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (3 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 04/19] spapr, xics, xive: Introduce SpaprInterruptController QOM interface David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09  6:08 ` [PATCH v4 06/19] spapr, xics, xive: Move irq claim and free " David Gibson
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

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 <david@gibson.dropbear.id.au>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
---
 hw/intc/spapr_xive.c       | 25 ++++++++++++
 hw/intc/xics_spapr.c       | 18 +++++++++
 hw/ppc/spapr_cpu_core.c    |  3 +-
 hw/ppc/spapr_irq.c         | 81 +++++++++++---------------------------
 include/hw/ppc/spapr_irq.h | 13 +++++-
 5 files changed, 79 insertions(+), 61 deletions(-)

diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index b67e9c3245..9338daba3d 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 = {
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 4874e6be55..946311b858 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -330,13 +330,31 @@ void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
     _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle));
 }
 
+static int xics_spapr_cpu_intc_create(SpaprInterruptController *intc,
+                                       PowerPCCPU *cpu, Error **errp)
+{
+    ICSState *ics = ICS_SPAPR(intc);
+    Object *obj;
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
+
+    obj = icp_create(OBJECT(cpu), TYPE_ICP, ics->xics, errp);
+    if (!obj) {
+        return -1;
+    }
+
+    spapr_cpu->icp = ICP(obj);
+    return 0;
+}
+
 static void ics_spapr_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     ICSStateClass *isc = ICS_CLASS(klass);
+    SpaprInterruptControllerClass *sicc = SPAPR_INTC_CLASS(klass);
 
     device_class_set_parent_realize(dc, ics_spapr_realize,
                                     &isc->parent_realize);
+    sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
 }
 
 static const TypeInfo ics_spapr_info = {
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 1d93de8161..3e4302c7d5 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -237,8 +237,7 @@ static void spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr,
     qemu_register_reset(spapr_cpu_reset, cpu);
     spapr_cpu_reset(cpu);
 
-    spapr->irq->cpu_intc_create(spapr, cpu, &local_err);
-    if (local_err) {
+    if (spapr_irq_cpu_intc_create(spapr, cpu, &local_err) < 0) {
         goto error_unregister;
     }
 
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 8791dec1ba..9cb2fc71ca 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -138,23 +138,6 @@ static void spapr_irq_print_info_xics(SpaprMachineState *spapr, Monitor *mon)
     ics_pic_print_info(spapr->ics, mon);
 }
 
-static void spapr_irq_cpu_intc_create_xics(SpaprMachineState *spapr,
-                                           PowerPCCPU *cpu, Error **errp)
-{
-    Error *local_err = NULL;
-    Object *obj;
-    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
-
-    obj = icp_create(OBJECT(cpu), TYPE_ICP, XICS_FABRIC(spapr),
-                     &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
-    }
-
-    spapr_cpu->icp = ICP(obj);
-}
-
 static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
 {
     if (!kvm_irqchip_in_kernel()) {
@@ -203,7 +186,6 @@ SpaprIrq spapr_irq_xics = {
     .free        = spapr_irq_free_xics,
     .print_info  = spapr_irq_print_info_xics,
     .dt_populate = spapr_dt_xics,
-    .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
     .post_load   = spapr_irq_post_load_xics,
     .reset       = spapr_irq_reset_xics,
     .set_irq     = spapr_irq_set_irq_xics,
@@ -239,28 +221,6 @@ static void spapr_irq_print_info_xive(SpaprMachineState *spapr,
     spapr_xive_pic_print_info(spapr->xive, mon);
 }
 
-static void spapr_irq_cpu_intc_create_xive(SpaprMachineState *spapr,
-                                           PowerPCCPU *cpu, Error **errp)
-{
-    Error *local_err = NULL;
-    Object *obj;
-    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
-
-    obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(spapr->xive), &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
-    }
-
-    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);
-}
-
 static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
 {
     return spapr_xive_post_load(spapr->xive, version_id);
@@ -316,7 +276,6 @@ SpaprIrq spapr_irq_xive = {
     .free        = spapr_irq_free_xive,
     .print_info  = spapr_irq_print_info_xive,
     .dt_populate = spapr_dt_xive,
-    .cpu_intc_create = spapr_irq_cpu_intc_create_xive,
     .post_load   = spapr_irq_post_load_xive,
     .reset       = spapr_irq_reset_xive,
     .set_irq     = spapr_irq_set_irq_xive,
@@ -381,20 +340,6 @@ static void spapr_irq_dt_populate_dual(SpaprMachineState *spapr,
     spapr_irq_current(spapr)->dt_populate(spapr, nr_servers, fdt, phandle);
 }
 
-static void spapr_irq_cpu_intc_create_dual(SpaprMachineState *spapr,
-                                           PowerPCCPU *cpu, Error **errp)
-{
-    Error *local_err = NULL;
-
-    spapr_irq_xive.cpu_intc_create(spapr, cpu, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
-    }
-
-    spapr_irq_xics.cpu_intc_create(spapr, cpu, errp);
-}
-
 static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
 {
     /*
@@ -460,7 +405,6 @@ SpaprIrq spapr_irq_dual = {
     .free        = spapr_irq_free_dual,
     .print_info  = spapr_irq_print_info_dual,
     .dt_populate = spapr_irq_dt_populate_dual,
-    .cpu_intc_create = spapr_irq_cpu_intc_create_dual,
     .post_load   = spapr_irq_post_load_dual,
     .reset       = spapr_irq_reset_dual,
     .set_irq     = spapr_irq_set_irq_dual,
@@ -527,6 +471,30 @@ static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
 /*
  * sPAPR IRQ frontend routines for devices
  */
+#define ALL_INTCS(spapr_) \
+    { SPAPR_INTC((spapr_)->ics), SPAPR_INTC((spapr_)->xive), }
+
+int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
+                              PowerPCCPU *cpu, Error **errp)
+{
+    SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
+    int i;
+    int rc;
+
+    for (i = 0; i < ARRAY_SIZE(intcs); i++) {
+        SpaprInterruptController *intc = intcs[i];
+        if (intc) {
+            SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
+            rc = sicc->cpu_intc_create(intc, cpu, errp);
+            if (rc < 0) {
+                return rc;
+            }
+        }
+    }
+
+    return 0;
+}
+
 void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
 {
     MachineState *machine = MACHINE(spapr);
@@ -762,7 +730,6 @@ SpaprIrq spapr_irq_xics_legacy = {
     .free        = spapr_irq_free_xics,
     .print_info  = spapr_irq_print_info_xics,
     .dt_populate = spapr_dt_xics,
-    .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
     .post_load   = spapr_irq_post_load_xics,
     .reset       = spapr_irq_reset_xics,
     .set_irq     = spapr_irq_set_irq_xics,
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index b9398e0be3..5e641e23c1 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -43,8 +43,19 @@ typedef struct SpaprInterruptController SpaprInterruptController;
 
 typedef struct SpaprInterruptControllerClass {
     InterfaceClass parent;
+
+    /*
+     * These methods will typically be called on all intcs, active and
+     * inactive
+     */
+    int (*cpu_intc_create)(SpaprInterruptController *intc,
+                            PowerPCCPU *cpu, Error **errp);
 } SpaprInterruptControllerClass;
 
+int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
+                              PowerPCCPU *cpu, Error **errp);
+
+
 void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
 int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
                         Error **errp);
@@ -61,8 +72,6 @@ typedef struct SpaprIrq {
     void (*print_info)(SpaprMachineState *spapr, Monitor *mon);
     void (*dt_populate)(SpaprMachineState *spapr, uint32_t nr_servers,
                         void *fdt, uint32_t phandle);
-    void (*cpu_intc_create)(SpaprMachineState *spapr, PowerPCCPU *cpu,
-                            Error **errp);
     int (*post_load)(SpaprMachineState *spapr, int version_id);
     void (*reset)(SpaprMachineState *spapr, Error **errp);
     void (*set_irq)(void *opaque, int srcno, int val);
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 06/19] spapr, xics, xive: Move irq claim and free from SpaprIrq to SpaprInterruptController
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (4 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 05/19] spapr, xics, xive: Move cpu_intc_create from SpaprIrq to SpaprInterruptController David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09  6:08 ` [PATCH v4 07/19] spapr: Formalize notion of active interrupt controller David Gibson
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

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 <david@gibson.dropbear.id.au>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
---
 hw/intc/spapr_xive.c        |  71 ++++++++++++-----------
 hw/intc/xics_spapr.c        |  29 ++++++++++
 hw/ppc/spapr_irq.c          | 110 +++++++++++-------------------------
 include/hw/ppc/spapr_irq.h  |   5 +-
 include/hw/ppc/spapr_xive.h |   2 -
 5 files changed, 102 insertions(+), 115 deletions(-)

diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index 9338daba3d..ff1a175b44 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
  *
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 946311b858..224fe1efcd 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -346,6 +346,33 @@ static int xics_spapr_cpu_intc_create(SpaprInterruptController *intc,
     return 0;
 }
 
+static int xics_spapr_claim_irq(SpaprInterruptController *intc, int irq,
+                                bool lsi, Error **errp)
+{
+    ICSState *ics = ICS_SPAPR(intc);
+
+    assert(ics);
+    assert(ics_valid_irq(ics, irq));
+
+    if (!ics_irq_free(ics, irq - ics->offset)) {
+        error_setg(errp, "IRQ %d is not free", irq);
+        return -EBUSY;
+    }
+
+    ics_set_irq_type(ics, irq - ics->offset, lsi);
+    return 0;
+}
+
+static void xics_spapr_free_irq(SpaprInterruptController *intc, int irq)
+{
+    ICSState *ics = ICS_SPAPR(intc);
+    uint32_t srcno = irq - ics->offset;
+
+    assert(ics_valid_irq(ics, irq));
+
+    memset(&ics->irqs[srcno], 0, sizeof(ICSIRQState));
+}
+
 static void ics_spapr_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -355,6 +382,8 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
     device_class_set_parent_realize(dc, ics_spapr_realize,
                                     &isc->parent_realize);
     sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
+    sicc->claim_irq = xics_spapr_claim_irq;
+    sicc->free_irq = xics_spapr_free_irq;
 }
 
 static const TypeInfo ics_spapr_info = {
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 9cb2fc71ca..83882cfad3 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -98,33 +98,6 @@ static void spapr_irq_init_kvm(SpaprMachineState *spapr,
  * XICS IRQ backend.
  */
 
-static int spapr_irq_claim_xics(SpaprMachineState *spapr, int irq, bool lsi,
-                                Error **errp)
-{
-    ICSState *ics = spapr->ics;
-
-    assert(ics);
-    assert(ics_valid_irq(ics, irq));
-
-    if (!ics_irq_free(ics, irq - ics->offset)) {
-        error_setg(errp, "IRQ %d is not free", irq);
-        return -1;
-    }
-
-    ics_set_irq_type(ics, irq - ics->offset, lsi);
-    return 0;
-}
-
-static void spapr_irq_free_xics(SpaprMachineState *spapr, int irq)
-{
-    ICSState *ics = spapr->ics;
-    uint32_t srcno = irq - ics->offset;
-
-    assert(ics_valid_irq(ics, irq));
-
-    memset(&ics->irqs[srcno], 0, sizeof(ICSIRQState));
-}
-
 static void spapr_irq_print_info_xics(SpaprMachineState *spapr, Monitor *mon)
 {
     CPUState *cs;
@@ -182,8 +155,6 @@ SpaprIrq spapr_irq_xics = {
     .xics        = true,
     .xive        = false,
 
-    .claim       = spapr_irq_claim_xics,
-    .free        = spapr_irq_free_xics,
     .print_info  = spapr_irq_print_info_xics,
     .dt_populate = spapr_dt_xics,
     .post_load   = spapr_irq_post_load_xics,
@@ -196,17 +167,6 @@ SpaprIrq spapr_irq_xics = {
  * XIVE IRQ backend.
  */
 
-static int spapr_irq_claim_xive(SpaprMachineState *spapr, int irq, bool lsi,
-                                Error **errp)
-{
-    return spapr_xive_irq_claim(spapr->xive, irq, lsi, errp);
-}
-
-static void spapr_irq_free_xive(SpaprMachineState *spapr, int irq)
-{
-    spapr_xive_irq_free(spapr->xive, irq);
-}
-
 static void spapr_irq_print_info_xive(SpaprMachineState *spapr,
                                       Monitor *mon)
 {
@@ -272,8 +232,6 @@ SpaprIrq spapr_irq_xive = {
     .xics        = false,
     .xive        = true,
 
-    .claim       = spapr_irq_claim_xive,
-    .free        = spapr_irq_free_xive,
     .print_info  = spapr_irq_print_info_xive,
     .dt_populate = spapr_dt_xive,
     .post_load   = spapr_irq_post_load_xive,
@@ -301,33 +259,6 @@ static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr)
         &spapr_irq_xive : &spapr_irq_xics;
 }
 
-static int spapr_irq_claim_dual(SpaprMachineState *spapr, int irq, bool lsi,
-                                Error **errp)
-{
-    Error *local_err = NULL;
-    int ret;
-
-    ret = spapr_irq_xics.claim(spapr, irq, lsi, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return ret;
-    }
-
-    ret = spapr_irq_xive.claim(spapr, irq, lsi, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return ret;
-    }
-
-    return ret;
-}
-
-static void spapr_irq_free_dual(SpaprMachineState *spapr, int irq)
-{
-    spapr_irq_xics.free(spapr, irq);
-    spapr_irq_xive.free(spapr, irq);
-}
-
 static void spapr_irq_print_info_dual(SpaprMachineState *spapr, Monitor *mon)
 {
     spapr_irq_current(spapr)->print_info(spapr, mon);
@@ -401,8 +332,6 @@ SpaprIrq spapr_irq_dual = {
     .xics        = true,
     .xive        = true,
 
-    .claim       = spapr_irq_claim_dual,
-    .free        = spapr_irq_free_dual,
     .print_info  = spapr_irq_print_info_dual,
     .dt_populate = spapr_irq_dt_populate_dual,
     .post_load   = spapr_irq_post_load_dual,
@@ -572,8 +501,11 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
 
         /* Enable the CPU IPIs */
         for (i = 0; i < nr_servers; ++i) {
-            if (spapr_xive_irq_claim(spapr->xive, SPAPR_IRQ_IPI + i,
-                                     false, errp) < 0) {
+            SpaprInterruptControllerClass *sicc
+                = SPAPR_INTC_GET_CLASS(spapr->xive);
+
+            if (sicc->claim_irq(SPAPR_INTC(spapr->xive), SPAPR_IRQ_IPI + i,
+                                false, errp) < 0) {
                 return;
             }
         }
@@ -587,21 +519,45 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
 
 int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp)
 {
+    SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
+    int i;
+    int rc;
+
     assert(irq >= SPAPR_XIRQ_BASE);
     assert(irq < (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE));
 
-    return spapr->irq->claim(spapr, irq, lsi, errp);
+    for (i = 0; i < ARRAY_SIZE(intcs); i++) {
+        SpaprInterruptController *intc = intcs[i];
+        if (intc) {
+            SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
+            rc = sicc->claim_irq(intc, irq, lsi, errp);
+            if (rc < 0) {
+                return rc;
+            }
+        }
+    }
+
+    return 0;
 }
 
 void spapr_irq_free(SpaprMachineState *spapr, int irq, int num)
 {
-    int i;
+    SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
+    int i, j;
 
     assert(irq >= SPAPR_XIRQ_BASE);
     assert((irq + num) <= (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE));
 
     for (i = irq; i < (irq + num); i++) {
-        spapr->irq->free(spapr, i);
+        for (j = 0; j < ARRAY_SIZE(intcs); j++) {
+            SpaprInterruptController *intc = intcs[j];
+
+            if (intc) {
+                SpaprInterruptControllerClass *sicc
+                    = SPAPR_INTC_GET_CLASS(intc);
+                sicc->free_irq(intc, i);
+            }
+        }
     }
 }
 
@@ -726,8 +682,6 @@ SpaprIrq spapr_irq_xics_legacy = {
     .xics        = true,
     .xive        = false,
 
-    .claim       = spapr_irq_claim_xics,
-    .free        = spapr_irq_free_xics,
     .print_info  = spapr_irq_print_info_xics,
     .dt_populate = spapr_dt_xics,
     .post_load   = spapr_irq_post_load_xics,
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index 5e641e23c1..adfef0fcbe 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -50,6 +50,9 @@ typedef struct SpaprInterruptControllerClass {
      */
     int (*cpu_intc_create)(SpaprInterruptController *intc,
                             PowerPCCPU *cpu, Error **errp);
+    int (*claim_irq)(SpaprInterruptController *intc, int irq, bool lsi,
+                     Error **errp);
+    void (*free_irq)(SpaprInterruptController *intc, int irq);
 } SpaprInterruptControllerClass;
 
 int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
@@ -67,8 +70,6 @@ typedef struct SpaprIrq {
     bool        xics;
     bool        xive;
 
-    int (*claim)(SpaprMachineState *spapr, int irq, bool lsi, Error **errp);
-    void (*free)(SpaprMachineState *spapr, int irq);
     void (*print_info)(SpaprMachineState *spapr, Monitor *mon);
     void (*dt_populate)(SpaprMachineState *spapr, uint32_t nr_servers,
                         void *fdt, uint32_t phandle);
diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
index 0df20a6590..8f875673f5 100644
--- a/include/hw/ppc/spapr_xive.h
+++ b/include/hw/ppc/spapr_xive.h
@@ -54,8 +54,6 @@ typedef struct SpaprXive {
  */
 #define SPAPR_XIVE_BLOCK_ID 0x0
 
-int spapr_xive_irq_claim(SpaprXive *xive, int lisn, bool lsi, Error **errp);
-void spapr_xive_irq_free(SpaprXive *xive, int lisn);
 void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon);
 int spapr_xive_post_load(SpaprXive *xive, int version_id);
 
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 07/19] spapr: Formalize notion of active interrupt controller
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (5 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 06/19] spapr, xics, xive: Move irq claim and free " David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09  9:16   ` Cédric Le Goater
  2019-10-09  9:19   ` Cédric Le Goater
  2019-10-09  6:08 ` [PATCH v4 08/19] spapr, xics, xive: Move set_irq from SpaprIrq to SpaprInterruptController David Gibson
                   ` (13 subsequent siblings)
  20 siblings, 2 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

spapr now has the mechanism of constructing both XICS and XIVE instances of
the SpaprInterruptController interface.  However, only one of the interrupt
controllers will actually be active at any given time, depending on feature
negotiation with the guest.  This is handled in the current code via
spapr_irq_current() which checks the OV5 vector from feature negotiation to
determine the current backend.

Determining the active controller at the point we need it like this
can be pretty confusing, because it makes it very non obvious at what
points the active controller can change.  This can make it difficult
to reason about the code and where a change of active controller could
appear in sequence with other events.

Make this mechanism more explicit by adding an 'active_intc' pointer
and an explicit spapr_irq_update_active_intc() function to update it
from the CAS state.  We also add hooks on the intc backend which will
get called when it is activated or deactivated.

For now we just introduce the switch and hooks, later patches will
actually start using them.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 hw/ppc/spapr_irq.c         | 51 ++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/spapr.h     |  5 ++--
 include/hw/ppc/spapr_irq.h |  5 ++++
 3 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 83882cfad3..249a2688ac 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -586,6 +586,7 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
 
 int spapr_irq_post_load(SpaprMachineState *spapr, int version_id)
 {
+    spapr_irq_update_active_intc(spapr);
     return spapr->irq->post_load(spapr, version_id);
 }
 
@@ -593,6 +594,8 @@ void spapr_irq_reset(SpaprMachineState *spapr, Error **errp)
 {
     assert(!spapr->irq_map || bitmap_empty(spapr->irq_map, spapr->irq_map_nr));
 
+    spapr_irq_update_active_intc(spapr);
+
     if (spapr->irq->reset) {
         spapr->irq->reset(spapr, errp);
     }
@@ -619,6 +622,54 @@ int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp)
     return phandle;
 }
 
+static void set_active_intc(SpaprMachineState *spapr,
+                            SpaprInterruptController *new_intc)
+{
+    SpaprInterruptControllerClass *sicc;
+
+    assert(new_intc);
+
+    if (new_intc == spapr->active_intc) {
+        /* Nothing to do */
+        return;
+    }
+
+    if (spapr->active_intc) {
+        sicc = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+        if (sicc->deactivate) {
+            sicc->deactivate(spapr->active_intc);
+        }
+    }
+
+    sicc = SPAPR_INTC_GET_CLASS(new_intc);
+    if (sicc->activate) {
+        sicc->activate(new_intc, &error_fatal);
+    }
+
+    spapr->active_intc = new_intc;
+}
+
+void spapr_irq_update_active_intc(SpaprMachineState *spapr)
+{
+    SpaprInterruptController *new_intc;
+
+    if (!spapr->ics) {
+        /*
+         * XXX before we run CAS, ov5_cas is initialized empty, which
+         * indicates XICS, even if we have ic-mode=xive.  TODO: clean
+         * up the CAS path so that we have a clearer way of handling
+         * this.
+         */
+        new_intc = SPAPR_INTC(spapr->xive);
+    } else if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
+        new_intc = SPAPR_INTC(spapr->xive);
+    } else {
+        new_intc = SPAPR_INTC(spapr->ics);
+    }
+
+    set_active_intc(spapr, new_intc);
+}
+
 /*
  * XICS legacy routines - to deprecate one day
  */
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index cbd1a4c9f3..763da757f0 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -143,7 +143,6 @@ struct SpaprMachineState {
     struct SpaprVioBus *vio_bus;
     QLIST_HEAD(, SpaprPhbState) phbs;
     struct SpaprNvram *nvram;
-    ICSState *ics;
     SpaprRtcState rtc;
 
     SpaprResizeHpt resize_hpt;
@@ -195,9 +194,11 @@ struct SpaprMachineState {
 
     int32_t irq_map_nr;
     unsigned long *irq_map;
-    SpaprXive  *xive;
     SpaprIrq *irq;
     qemu_irq *qirqs;
+    SpaprInterruptController *active_intc;
+    ICSState *ics;
+    SpaprXive *xive;
 
     bool cmd_line_caps[SPAPR_CAP_NUM];
     SpaprCapabilities def, eff, mig;
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index adfef0fcbe..593059eff5 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -44,6 +44,9 @@ typedef struct SpaprInterruptController SpaprInterruptController;
 typedef struct SpaprInterruptControllerClass {
     InterfaceClass parent;
 
+    int (*activate)(SpaprInterruptController *intc, Error **errp);
+    void (*deactivate)(SpaprInterruptController *intc);
+
     /*
      * These methods will typically be called on all intcs, active and
      * inactive
@@ -55,6 +58,8 @@ typedef struct SpaprInterruptControllerClass {
     void (*free_irq)(SpaprInterruptController *intc, int irq);
 } SpaprInterruptControllerClass;
 
+void spapr_irq_update_active_intc(SpaprMachineState *spapr);
+
 int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
                               PowerPCCPU *cpu, Error **errp);
 
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 08/19] spapr, xics, xive: Move set_irq from SpaprIrq to SpaprInterruptController
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (6 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 07/19] spapr: Formalize notion of active interrupt controller David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09  9:18   ` Cédric Le Goater
  2019-10-09  6:08 ` [PATCH v4 09/19] spapr, xics, xive: Move print_info " David Gibson
                   ` (12 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

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 <david@gibson.dropbear.id.au>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 hw/intc/spapr_xive.c       | 12 +++++++++++
 hw/intc/xics_spapr.c       |  9 +++++++++
 hw/ppc/spapr_irq.c         | 41 ++++++++++----------------------------
 include/hw/ppc/spapr_irq.h |  4 +++-
 4 files changed, 34 insertions(+), 32 deletions(-)

diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index ff1a175b44..52d5e71793 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 = {
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 224fe1efcd..02372697f6 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -373,6 +373,14 @@ static void xics_spapr_free_irq(SpaprInterruptController *intc, int irq)
     memset(&ics->irqs[srcno], 0, sizeof(ICSIRQState));
 }
 
+static void xics_spapr_set_irq(SpaprInterruptController *intc, int irq, int val)
+{
+    ICSState *ics = ICS_SPAPR(intc);
+    uint32_t srcno = irq - ics->offset;
+
+    ics_set_irq(ics, srcno, val);
+}
+
 static void ics_spapr_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -384,6 +392,7 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
     sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
     sicc->claim_irq = xics_spapr_claim_irq;
     sicc->free_irq = xics_spapr_free_irq;
+    sicc->set_irq = xics_spapr_set_irq;
 }
 
 static const TypeInfo ics_spapr_info = {
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 249a2688ac..bfccb815ed 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -123,14 +123,6 @@ static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
     return 0;
 }
 
-static void spapr_irq_set_irq_xics(void *opaque, int irq, int val)
-{
-    SpaprMachineState *spapr = opaque;
-    uint32_t srcno = irq - spapr->ics->offset;
-
-    ics_set_irq(spapr->ics, srcno, val);
-}
-
 static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp)
 {
     Error *local_err = NULL;
@@ -159,7 +151,6 @@ SpaprIrq spapr_irq_xics = {
     .dt_populate = spapr_dt_xics,
     .post_load   = spapr_irq_post_load_xics,
     .reset       = spapr_irq_reset_xics,
-    .set_irq     = spapr_irq_set_irq_xics,
     .init_kvm    = spapr_irq_init_kvm_xics,
 };
 
@@ -208,17 +199,6 @@ static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp)
     spapr_xive_mmio_set_enabled(spapr->xive, true);
 }
 
-static void spapr_irq_set_irq_xive(void *opaque, int irq, int val)
-{
-    SpaprMachineState *spapr = opaque;
-
-    if (kvm_irqchip_in_kernel()) {
-        kvmppc_xive_source_set_irq(&spapr->xive->source, irq, val);
-    } else {
-        xive_source_set_irq(&spapr->xive->source, irq, val);
-    }
-}
-
 static void spapr_irq_init_kvm_xive(SpaprMachineState *spapr, Error **errp)
 {
     if (kvm_enabled()) {
@@ -236,7 +216,6 @@ SpaprIrq spapr_irq_xive = {
     .dt_populate = spapr_dt_xive,
     .post_load   = spapr_irq_post_load_xive,
     .reset       = spapr_irq_reset_xive,
-    .set_irq     = spapr_irq_set_irq_xive,
     .init_kvm    = spapr_irq_init_kvm_xive,
 };
 
@@ -316,13 +295,6 @@ static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp)
     spapr_irq_current(spapr)->reset(spapr, errp);
 }
 
-static void spapr_irq_set_irq_dual(void *opaque, int irq, int val)
-{
-    SpaprMachineState *spapr = opaque;
-
-    spapr_irq_current(spapr)->set_irq(spapr, irq, val);
-}
-
 /*
  * Define values in sync with the XIVE and XICS backend
  */
@@ -336,7 +308,6 @@ SpaprIrq spapr_irq_dual = {
     .dt_populate = spapr_irq_dt_populate_dual,
     .post_load   = spapr_irq_post_load_dual,
     .reset       = spapr_irq_reset_dual,
-    .set_irq     = spapr_irq_set_irq_dual,
     .init_kvm    = NULL, /* should not be used */
 };
 
@@ -424,6 +395,15 @@ int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
     return 0;
 }
 
+static void spapr_set_irq(void *opaque, int irq, int level)
+{
+    SpaprMachineState *spapr = SPAPR_MACHINE(opaque);
+    SpaprInterruptControllerClass *sicc
+        = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+
+    sicc->set_irq(spapr->active_intc, irq, level);
+}
+
 void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
 {
     MachineState *machine = MACHINE(spapr);
@@ -513,7 +493,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
         spapr_xive_hcall_init(spapr);
     }
 
-    spapr->qirqs = qemu_allocate_irqs(spapr->irq->set_irq, spapr,
+    spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr,
                                       spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE);
 }
 
@@ -737,7 +717,6 @@ SpaprIrq spapr_irq_xics_legacy = {
     .dt_populate = spapr_dt_xics,
     .post_load   = spapr_irq_post_load_xics,
     .reset       = spapr_irq_reset_xics,
-    .set_irq     = spapr_irq_set_irq_xics,
     .init_kvm    = spapr_irq_init_kvm_xics,
 };
 
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index 593059eff5..ece8d2ea48 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -56,6 +56,9 @@ typedef struct SpaprInterruptControllerClass {
     int (*claim_irq)(SpaprInterruptController *intc, int irq, bool lsi,
                      Error **errp);
     void (*free_irq)(SpaprInterruptController *intc, int irq);
+
+    /* These methods should only be called on the active intc */
+    void (*set_irq)(SpaprInterruptController *intc, int irq, int val);
 } SpaprInterruptControllerClass;
 
 void spapr_irq_update_active_intc(SpaprMachineState *spapr);
@@ -80,7 +83,6 @@ typedef struct SpaprIrq {
                         void *fdt, uint32_t phandle);
     int (*post_load)(SpaprMachineState *spapr, int version_id);
     void (*reset)(SpaprMachineState *spapr, Error **errp);
-    void (*set_irq)(void *opaque, int srcno, int val);
     void (*init_kvm)(SpaprMachineState *spapr, Error **errp);
 } SpaprIrq;
 
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 09/19] spapr, xics, xive: Move print_info from SpaprIrq to SpaprInterruptController
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (7 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 08/19] spapr, xics, xive: Move set_irq from SpaprIrq to SpaprInterruptController David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09  9:19   ` Cédric Le Goater
  2019-10-09  6:08 ` [PATCH v4 10/19] spapr, xics, xive: Move dt_populate " David Gibson
                   ` (11 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

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 <david@gibson.dropbear.id.au>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 hw/intc/spapr_xive.c       | 15 +++++++++++++
 hw/intc/xics_spapr.c       | 15 +++++++++++++
 hw/ppc/spapr.c             |  2 +-
 hw/ppc/spapr_irq.c         | 44 +++++++-------------------------------
 include/hw/ppc/spapr_irq.h |  4 ++--
 5 files changed, 41 insertions(+), 39 deletions(-)

diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index 52d5e71793..700ec5c9c1 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 = {
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 02372697f6..415defe394 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -381,6 +381,20 @@ static void xics_spapr_set_irq(SpaprInterruptController *intc, int irq, int val)
     ics_set_irq(ics, srcno, val);
 }
 
+static void xics_spapr_print_info(SpaprInterruptController *intc, Monitor *mon)
+{
+    ICSState *ics = ICS_SPAPR(intc);
+    CPUState *cs;
+
+    CPU_FOREACH(cs) {
+        PowerPCCPU *cpu = POWERPC_CPU(cs);
+
+        icp_pic_print_info(spapr_cpu_state(cpu)->icp, mon);
+    }
+
+    ics_pic_print_info(ics, mon);
+}
+
 static void ics_spapr_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -393,6 +407,7 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
     sicc->claim_irq = xics_spapr_claim_irq;
     sicc->free_irq = xics_spapr_free_irq;
     sicc->set_irq = xics_spapr_set_irq;
+    sicc->print_info = xics_spapr_print_info;
 }
 
 static const TypeInfo ics_spapr_info = {
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 514a17ae74..6c38de5927 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4271,7 +4271,7 @@ static void spapr_pic_print_info(InterruptStatsProvider *obj,
 {
     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
-    spapr->irq->print_info(spapr, mon);
+    spapr_irq_print_info(spapr, mon);
     monitor_printf(mon, "irqchip: %s\n",
                    kvm_irqchip_in_kernel() ? "in-kernel" : "emulated");
 }
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index bfccb815ed..a29b527232 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -98,19 +98,6 @@ static void spapr_irq_init_kvm(SpaprMachineState *spapr,
  * XICS IRQ backend.
  */
 
-static void spapr_irq_print_info_xics(SpaprMachineState *spapr, Monitor *mon)
-{
-    CPUState *cs;
-
-    CPU_FOREACH(cs) {
-        PowerPCCPU *cpu = POWERPC_CPU(cs);
-
-        icp_pic_print_info(spapr_cpu_state(cpu)->icp, mon);
-    }
-
-    ics_pic_print_info(spapr->ics, mon);
-}
-
 static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
 {
     if (!kvm_irqchip_in_kernel()) {
@@ -147,7 +134,6 @@ SpaprIrq spapr_irq_xics = {
     .xics        = true,
     .xive        = false,
 
-    .print_info  = spapr_irq_print_info_xics,
     .dt_populate = spapr_dt_xics,
     .post_load   = spapr_irq_post_load_xics,
     .reset       = spapr_irq_reset_xics,
@@ -158,20 +144,6 @@ SpaprIrq spapr_irq_xics = {
  * XIVE IRQ backend.
  */
 
-static void spapr_irq_print_info_xive(SpaprMachineState *spapr,
-                                      Monitor *mon)
-{
-    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(spapr->xive, mon);
-}
-
 static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
 {
     return spapr_xive_post_load(spapr->xive, version_id);
@@ -212,7 +184,6 @@ SpaprIrq spapr_irq_xive = {
     .xics        = false,
     .xive        = true,
 
-    .print_info  = spapr_irq_print_info_xive,
     .dt_populate = spapr_dt_xive,
     .post_load   = spapr_irq_post_load_xive,
     .reset       = spapr_irq_reset_xive,
@@ -238,11 +209,6 @@ static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr)
         &spapr_irq_xive : &spapr_irq_xics;
 }
 
-static void spapr_irq_print_info_dual(SpaprMachineState *spapr, Monitor *mon)
-{
-    spapr_irq_current(spapr)->print_info(spapr, mon);
-}
-
 static void spapr_irq_dt_populate_dual(SpaprMachineState *spapr,
                                        uint32_t nr_servers, void *fdt,
                                        uint32_t phandle)
@@ -304,7 +270,6 @@ SpaprIrq spapr_irq_dual = {
     .xics        = true,
     .xive        = true,
 
-    .print_info  = spapr_irq_print_info_dual,
     .dt_populate = spapr_irq_dt_populate_dual,
     .post_load   = spapr_irq_post_load_dual,
     .reset       = spapr_irq_reset_dual,
@@ -404,6 +369,14 @@ static void spapr_set_irq(void *opaque, int irq, int level)
     sicc->set_irq(spapr->active_intc, irq, level);
 }
 
+void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon)
+{
+    SpaprInterruptControllerClass *sicc
+        = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+
+    sicc->print_info(spapr->active_intc, mon);
+}
+
 void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
 {
     MachineState *machine = MACHINE(spapr);
@@ -713,7 +686,6 @@ SpaprIrq spapr_irq_xics_legacy = {
     .xics        = true,
     .xive        = false,
 
-    .print_info  = spapr_irq_print_info_xics,
     .dt_populate = spapr_dt_xics,
     .post_load   = spapr_irq_post_load_xics,
     .reset       = spapr_irq_reset_xics,
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index ece8d2ea48..bdfeb3b107 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -59,13 +59,14 @@ typedef struct SpaprInterruptControllerClass {
 
     /* These methods should only be called on the active intc */
     void (*set_irq)(SpaprInterruptController *intc, int irq, int val);
+    void (*print_info)(SpaprInterruptController *intc, Monitor *mon);
 } SpaprInterruptControllerClass;
 
 void spapr_irq_update_active_intc(SpaprMachineState *spapr);
 
 int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
                               PowerPCCPU *cpu, Error **errp);
-
+void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon);
 
 void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
 int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
@@ -78,7 +79,6 @@ typedef struct SpaprIrq {
     bool        xics;
     bool        xive;
 
-    void (*print_info)(SpaprMachineState *spapr, Monitor *mon);
     void (*dt_populate)(SpaprMachineState *spapr, uint32_t nr_servers,
                         void *fdt, uint32_t phandle);
     int (*post_load)(SpaprMachineState *spapr, int version_id);
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 10/19] spapr, xics, xive: Move dt_populate from SpaprIrq to SpaprInterruptController
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (8 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 09/19] spapr, xics, xive: Move print_info " David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09  9:20   ` Cédric Le Goater
  2019-10-09  6:08 ` [PATCH v4 11/19] spapr, xics, xive: Match signatures for XICS and XIVE KVM connect routines David Gibson
                   ` (10 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

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 <david@gibson.dropbear.id.au>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 hw/intc/spapr_xive.c        | 125 ++++++++++++++++++------------------
 hw/intc/xics_spapr.c        |   5 +-
 hw/ppc/spapr.c              |   3 +-
 hw/ppc/spapr_irq.c          |  20 +++---
 include/hw/ppc/spapr_irq.h  |   6 +-
 include/hw/ppc/spapr_xive.h |   2 -
 include/hw/ppc/xics_spapr.h |   2 -
 7 files changed, 80 insertions(+), 83 deletions(-)

diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index 700ec5c9c1..37ffb74ca5 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)));
-}
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 415defe394..4eabafc7e1 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -308,8 +308,8 @@ static void ics_spapr_realize(DeviceState *dev, Error **errp)
     spapr_register_hypercall(H_IPOLL, h_ipoll);
 }
 
-void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
-                   uint32_t phandle)
+static void xics_spapr_dt(SpaprInterruptController *intc, uint32_t nr_servers,
+                          void *fdt, uint32_t phandle)
 {
     uint32_t interrupt_server_ranges_prop[] = {
         0, cpu_to_be32(nr_servers),
@@ -408,6 +408,7 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
     sicc->free_irq = xics_spapr_free_irq;
     sicc->set_irq = xics_spapr_set_irq;
     sicc->print_info = xics_spapr_print_info;
+    sicc->dt = xics_spapr_dt;
 }
 
 static const TypeInfo ics_spapr_info = {
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 6c38de5927..e880db5d38 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1255,8 +1255,7 @@ static void *spapr_build_fdt(SpaprMachineState *spapr)
     _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2));
 
     /* /interrupt controller */
-    spapr->irq->dt_populate(spapr, spapr_max_server_number(spapr), fdt,
-                          PHANDLE_INTC);
+    spapr_irq_dt(spapr, spapr_max_server_number(spapr), fdt, PHANDLE_INTC);
 
     ret = spapr_populate_memory(spapr, fdt);
     if (ret < 0) {
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index a29b527232..a8005072e6 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -134,7 +134,6 @@ SpaprIrq spapr_irq_xics = {
     .xics        = true,
     .xive        = false,
 
-    .dt_populate = spapr_dt_xics,
     .post_load   = spapr_irq_post_load_xics,
     .reset       = spapr_irq_reset_xics,
     .init_kvm    = spapr_irq_init_kvm_xics,
@@ -184,7 +183,6 @@ SpaprIrq spapr_irq_xive = {
     .xics        = false,
     .xive        = true,
 
-    .dt_populate = spapr_dt_xive,
     .post_load   = spapr_irq_post_load_xive,
     .reset       = spapr_irq_reset_xive,
     .init_kvm    = spapr_irq_init_kvm_xive,
@@ -209,13 +207,6 @@ static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr)
         &spapr_irq_xive : &spapr_irq_xics;
 }
 
-static void spapr_irq_dt_populate_dual(SpaprMachineState *spapr,
-                                       uint32_t nr_servers, void *fdt,
-                                       uint32_t phandle)
-{
-    spapr_irq_current(spapr)->dt_populate(spapr, nr_servers, fdt, phandle);
-}
-
 static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
 {
     /*
@@ -270,7 +261,6 @@ SpaprIrq spapr_irq_dual = {
     .xics        = true,
     .xive        = true,
 
-    .dt_populate = spapr_irq_dt_populate_dual,
     .post_load   = spapr_irq_post_load_dual,
     .reset       = spapr_irq_reset_dual,
     .init_kvm    = NULL, /* should not be used */
@@ -377,6 +367,15 @@ void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon)
     sicc->print_info(spapr->active_intc, mon);
 }
 
+void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
+                  void *fdt, uint32_t phandle)
+{
+    SpaprInterruptControllerClass *sicc
+        = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+
+    sicc->dt(spapr->active_intc, nr_servers, fdt, phandle);
+}
+
 void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
 {
     MachineState *machine = MACHINE(spapr);
@@ -686,7 +685,6 @@ SpaprIrq spapr_irq_xics_legacy = {
     .xics        = true,
     .xive        = false,
 
-    .dt_populate = spapr_dt_xics,
     .post_load   = spapr_irq_post_load_xics,
     .reset       = spapr_irq_reset_xics,
     .init_kvm    = spapr_irq_init_kvm_xics,
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index bdfeb3b107..0df95e1b5a 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -60,6 +60,8 @@ typedef struct SpaprInterruptControllerClass {
     /* These methods should only be called on the active intc */
     void (*set_irq)(SpaprInterruptController *intc, int irq, int val);
     void (*print_info)(SpaprInterruptController *intc, Monitor *mon);
+    void (*dt)(SpaprInterruptController *intc, uint32_t nr_servers,
+               void *fdt, uint32_t phandle);
 } SpaprInterruptControllerClass;
 
 void spapr_irq_update_active_intc(SpaprMachineState *spapr);
@@ -67,6 +69,8 @@ void spapr_irq_update_active_intc(SpaprMachineState *spapr);
 int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
                               PowerPCCPU *cpu, Error **errp);
 void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon);
+void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
+                  void *fdt, uint32_t phandle);
 
 void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
 int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
@@ -79,8 +83,6 @@ typedef struct SpaprIrq {
     bool        xics;
     bool        xive;
 
-    void (*dt_populate)(SpaprMachineState *spapr, uint32_t nr_servers,
-                        void *fdt, uint32_t phandle);
     int (*post_load)(SpaprMachineState *spapr, int version_id);
     void (*reset)(SpaprMachineState *spapr, Error **errp);
     void (*init_kvm)(SpaprMachineState *spapr, Error **errp);
diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
index 8f875673f5..ebe156eb30 100644
--- a/include/hw/ppc/spapr_xive.h
+++ b/include/hw/ppc/spapr_xive.h
@@ -58,8 +58,6 @@ void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon);
 int spapr_xive_post_load(SpaprXive *xive, int version_id);
 
 void spapr_xive_hcall_init(SpaprMachineState *spapr);
-void spapr_dt_xive(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
-                   uint32_t phandle);
 void spapr_xive_set_tctx_os_cam(XiveTCTX *tctx);
 void spapr_xive_mmio_set_enabled(SpaprXive *xive, bool enable);
 void spapr_xive_map_mmio(SpaprXive *xive);
diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h
index 0b35e85c26..8e4fb6adce 100644
--- a/include/hw/ppc/xics_spapr.h
+++ b/include/hw/ppc/xics_spapr.h
@@ -32,8 +32,6 @@
 #define TYPE_ICS_SPAPR "ics-spapr"
 #define ICS_SPAPR(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SPAPR)
 
-void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
-                   uint32_t phandle);
 int xics_kvm_connect(SpaprMachineState *spapr, Error **errp);
 void xics_kvm_disconnect(SpaprMachineState *spapr, Error **errp);
 bool xics_kvm_has_broken_disconnect(SpaprMachineState *spapr);
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 11/19] spapr, xics, xive: Match signatures for XICS and XIVE KVM connect routines
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (9 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 10/19] spapr, xics, xive: Move dt_populate " David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09  6:08 ` [PATCH v4 12/19] spapr: Remove SpaprIrq::init_kvm hook David Gibson
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

Both XICS and XIVE have routines to connect and disconnect KVM with
similar but not identical signatures.  This adjusts them to match
exactly, which will be useful for further cleanups later.

While we're there, we add an explicit return value to the connect path
to streamline error reporting in the callers.  We remove error
reporting the disconnect path.  In the XICS case this wasn't used at
all.  In the XIVE case the only error case was if the KVM device was
set up, but KVM didn't have the capability to do so which is pretty
obviously impossible.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
---
 hw/intc/spapr_xive_kvm.c    | 22 ++++++++++------------
 hw/intc/xics_kvm.c          |  9 +++++----
 hw/ppc/spapr_irq.c          | 22 +++++-----------------
 include/hw/ppc/spapr_xive.h |  4 ++--
 include/hw/ppc/xics_spapr.h |  4 ++--
 5 files changed, 24 insertions(+), 37 deletions(-)

diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c
index 51b334b676..08012ac7cd 100644
--- a/hw/intc/spapr_xive_kvm.c
+++ b/hw/intc/spapr_xive_kvm.c
@@ -740,8 +740,9 @@ static void *kvmppc_xive_mmap(SpaprXive *xive, int pgoff, size_t len,
  * All the XIVE memory regions are now backed by mappings from the KVM
  * XIVE device.
  */
-void kvmppc_xive_connect(SpaprXive *xive, Error **errp)
+int kvmppc_xive_connect(SpaprInterruptController *intc, Error **errp)
 {
+    SpaprXive *xive = SPAPR_XIVE(intc);
     XiveSource *xsrc = &xive->source;
     Error *local_err = NULL;
     size_t esb_len = (1ull << xsrc->esb_shift) * xsrc->nr_irqs;
@@ -753,19 +754,19 @@ void kvmppc_xive_connect(SpaprXive *xive, Error **errp)
      * rebooting under the XIVE-only interrupt mode.
      */
     if (xive->fd != -1) {
-        return;
+        return 0;
     }
 
     if (!kvmppc_has_cap_xive()) {
         error_setg(errp, "IRQ_XIVE capability must be present for KVM");
-        return;
+        return -1;
     }
 
     /* First, create the KVM XIVE device */
     xive->fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_XIVE, false);
     if (xive->fd < 0) {
         error_setg_errno(errp, -xive->fd, "XIVE: error creating KVM device");
-        return;
+        return -1;
     }
 
     /*
@@ -821,15 +822,17 @@ void kvmppc_xive_connect(SpaprXive *xive, Error **errp)
     kvm_kernel_irqchip = true;
     kvm_msi_via_irqfd_allowed = true;
     kvm_gsi_direct_mapping = true;
-    return;
+    return 0;
 
 fail:
     error_propagate(errp, local_err);
-    kvmppc_xive_disconnect(xive, NULL);
+    kvmppc_xive_disconnect(intc);
+    return -1;
 }
 
-void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp)
+void kvmppc_xive_disconnect(SpaprInterruptController *intc)
 {
+    SpaprXive *xive = SPAPR_XIVE(intc);
     XiveSource *xsrc;
     size_t esb_len;
 
@@ -838,11 +841,6 @@ void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp)
         return;
     }
 
-    if (!kvmppc_has_cap_xive()) {
-        error_setg(errp, "IRQ_XIVE capability must be present for KVM");
-        return;
-    }
-
     /* Clear the KVM mapping */
     xsrc = &xive->source;
     esb_len = (1ull << xsrc->esb_shift) * xsrc->nr_irqs;
diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
index ba90d6dc96..954c424b36 100644
--- a/hw/intc/xics_kvm.c
+++ b/hw/intc/xics_kvm.c
@@ -342,8 +342,9 @@ void ics_kvm_set_irq(ICSState *ics, int srcno, int val)
     }
 }
 
-int xics_kvm_connect(SpaprMachineState *spapr, Error **errp)
+int xics_kvm_connect(SpaprInterruptController *intc, Error **errp)
 {
+    ICSState *ics = ICS_SPAPR(intc);
     int rc;
     CPUState *cs;
     Error *local_err = NULL;
@@ -413,7 +414,7 @@ int xics_kvm_connect(SpaprMachineState *spapr, Error **errp)
     }
 
     /* Update the KVM sources */
-    ics_set_kvm_state(spapr->ics, &local_err);
+    ics_set_kvm_state(ics, &local_err);
     if (local_err) {
         goto fail;
     }
@@ -431,11 +432,11 @@ int xics_kvm_connect(SpaprMachineState *spapr, Error **errp)
 
 fail:
     error_propagate(errp, local_err);
-    xics_kvm_disconnect(spapr, NULL);
+    xics_kvm_disconnect(intc);
     return -1;
 }
 
-void xics_kvm_disconnect(SpaprMachineState *spapr, Error **errp)
+void xics_kvm_disconnect(SpaprInterruptController *intc)
 {
     /*
      * Only on P9 using the XICS-on XIVE KVM device:
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index a8005072e6..5c8ffb27da 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -124,7 +124,7 @@ static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp)
 static void spapr_irq_init_kvm_xics(SpaprMachineState *spapr, Error **errp)
 {
     if (kvm_enabled()) {
-        xics_kvm_connect(spapr, errp);
+        xics_kvm_connect(SPAPR_INTC(spapr->ics), errp);
     }
 }
 
@@ -173,7 +173,7 @@ static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp)
 static void spapr_irq_init_kvm_xive(SpaprMachineState *spapr, Error **errp)
 {
     if (kvm_enabled()) {
-        kvmppc_xive_connect(spapr->xive, errp);
+        kvmppc_xive_connect(SPAPR_INTC(spapr->xive), errp);
     }
 }
 
@@ -215,7 +215,7 @@ static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
      */
     if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
         if (kvm_irqchip_in_kernel()) {
-            xics_kvm_disconnect(spapr, &error_fatal);
+            xics_kvm_disconnect(SPAPR_INTC(spapr->ics));
         }
         spapr_irq_xive.reset(spapr, &error_fatal);
     }
@@ -225,8 +225,6 @@ static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
 
 static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp)
 {
-    Error *local_err = NULL;
-
     /*
      * Deactivate the XIVE MMIOs. The XIVE backend will reenable them
      * if selected.
@@ -235,18 +233,8 @@ static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp)
 
     /* Destroy all KVM devices */
     if (kvm_irqchip_in_kernel()) {
-        xics_kvm_disconnect(spapr, &local_err);
-        if (local_err) {
-            error_propagate(errp, local_err);
-            error_prepend(errp, "KVM XICS disconnect failed: ");
-            return;
-        }
-        kvmppc_xive_disconnect(spapr->xive, &local_err);
-        if (local_err) {
-            error_propagate(errp, local_err);
-            error_prepend(errp, "KVM XIVE disconnect failed: ");
-            return;
-        }
+        xics_kvm_disconnect(SPAPR_INTC(spapr->ics));
+        kvmppc_xive_disconnect(SPAPR_INTC(spapr->xive));
     }
 
     spapr_irq_current(spapr)->reset(spapr, errp);
diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
index ebe156eb30..64972754f9 100644
--- a/include/hw/ppc/spapr_xive.h
+++ b/include/hw/ppc/spapr_xive.h
@@ -68,8 +68,8 @@ int spapr_xive_end_to_target(uint8_t end_blk, uint32_t end_idx,
 /*
  * KVM XIVE device helpers
  */
-void kvmppc_xive_connect(SpaprXive *xive, Error **errp);
-void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp);
+int kvmppc_xive_connect(SpaprInterruptController *intc, Error **errp);
+void kvmppc_xive_disconnect(SpaprInterruptController *intc);
 void kvmppc_xive_reset(SpaprXive *xive, Error **errp);
 void kvmppc_xive_set_source_config(SpaprXive *xive, uint32_t lisn, XiveEAS *eas,
                                    Error **errp);
diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h
index 8e4fb6adce..28b87038c8 100644
--- a/include/hw/ppc/xics_spapr.h
+++ b/include/hw/ppc/xics_spapr.h
@@ -32,8 +32,8 @@
 #define TYPE_ICS_SPAPR "ics-spapr"
 #define ICS_SPAPR(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SPAPR)
 
-int xics_kvm_connect(SpaprMachineState *spapr, Error **errp);
-void xics_kvm_disconnect(SpaprMachineState *spapr, Error **errp);
+int xics_kvm_connect(SpaprInterruptController *intc, Error **errp);
+void xics_kvm_disconnect(SpaprInterruptController *intc);
 bool xics_kvm_has_broken_disconnect(SpaprMachineState *spapr);
 
 #endif /* XICS_SPAPR_H */
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 12/19] spapr: Remove SpaprIrq::init_kvm hook
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (10 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 11/19] spapr, xics, xive: Match signatures for XICS and XIVE KVM connect routines David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09  6:08 ` [PATCH v4 13/19] spapr, xics, xive: Move SpaprIrq::reset hook logic into activate/deactivate David Gibson
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

This hook is a bit odd.  The only caller is spapr_irq_init_kvm(), but
it explicitly takes an SpaprIrq *, so it's never really called through the
current SpaprIrq.  Essentially this is just a way of passing through a
function pointer so that spapr_irq_init_kvm() can handle some
configuration and error handling logic without duplicating it between the
xics and xive reset paths.

So, make it just take that function pointer.  Because of earlier reworks
to the KVM connect/disconnect code in the xics and xive backends we can
also eliminate some wrapper functions and streamline error handling a bit.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ppc/spapr_irq.c         | 74 +++++++++++++-------------------------
 include/hw/ppc/spapr_irq.h |  1 -
 2 files changed, 25 insertions(+), 50 deletions(-)

diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 5c8ffb27da..7cd18e5b15 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -65,33 +65,35 @@ void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num)
     bitmap_clear(spapr->irq_map, irq - SPAPR_IRQ_MSI, num);
 }
 
-static void spapr_irq_init_kvm(SpaprMachineState *spapr,
-                                  SpaprIrq *irq, Error **errp)
+static int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
+                              SpaprInterruptController *intc,
+                              Error **errp)
 {
-    MachineState *machine = MACHINE(spapr);
+    MachineState *machine = MACHINE(qdev_get_machine());
     Error *local_err = NULL;
 
     if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) {
-        irq->init_kvm(spapr, &local_err);
-        if (local_err && machine_kernel_irqchip_required(machine)) {
-            error_prepend(&local_err,
-                          "kernel_irqchip requested but unavailable: ");
-            error_propagate(errp, local_err);
-            return;
-        }
+        if (fn(intc, &local_err) < 0) {
+            if (machine_kernel_irqchip_required(machine)) {
+                error_prepend(&local_err,
+                              "kernel_irqchip requested but unavailable: ");
+                error_propagate(errp, local_err);
+                return -1;
+            }
 
-        if (!local_err) {
-            return;
+            /*
+             * We failed to initialize the KVM device, fallback to
+             * emulated mode
+             */
+            error_prepend(&local_err,
+                          "kernel_irqchip allowed but unavailable: ");
+            error_append_hint(&local_err,
+                              "Falling back to kernel-irqchip=off\n");
+            warn_report_err(local_err);
         }
-
-        /*
-         * We failed to initialize the KVM device, fallback to
-         * emulated mode
-         */
-        error_prepend(&local_err, "kernel_irqchip allowed but unavailable: ");
-        error_append_hint(&local_err, "Falling back to kernel-irqchip=off\n");
-        warn_report_err(local_err);
     }
+
+    return 0;
 }
 
 /*
@@ -112,20 +114,7 @@ static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
 
 static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp)
 {
-    Error *local_err = NULL;
-
-    spapr_irq_init_kvm(spapr, &spapr_irq_xics, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
-        return;
-    }
-}
-
-static void spapr_irq_init_kvm_xics(SpaprMachineState *spapr, Error **errp)
-{
-    if (kvm_enabled()) {
-        xics_kvm_connect(SPAPR_INTC(spapr->ics), errp);
-    }
+    spapr_irq_init_kvm(xics_kvm_connect, SPAPR_INTC(spapr->ics), errp);
 }
 
 SpaprIrq spapr_irq_xics = {
@@ -136,7 +125,6 @@ SpaprIrq spapr_irq_xics = {
 
     .post_load   = spapr_irq_post_load_xics,
     .reset       = spapr_irq_reset_xics,
-    .init_kvm    = spapr_irq_init_kvm_xics,
 };
 
 /*
@@ -151,7 +139,6 @@ static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
 static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp)
 {
     CPUState *cs;
-    Error *local_err = NULL;
 
     CPU_FOREACH(cs) {
         PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -160,9 +147,8 @@ static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp)
         spapr_xive_set_tctx_os_cam(spapr_cpu_state(cpu)->tctx);
     }
 
-    spapr_irq_init_kvm(spapr, &spapr_irq_xive, &local_err);
-    if (local_err) {
-        error_propagate(errp, local_err);
+    if (spapr_irq_init_kvm(kvmppc_xive_connect,
+                           SPAPR_INTC(spapr->xive), errp) < 0) {
         return;
     }
 
@@ -170,13 +156,6 @@ static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp)
     spapr_xive_mmio_set_enabled(spapr->xive, true);
 }
 
-static void spapr_irq_init_kvm_xive(SpaprMachineState *spapr, Error **errp)
-{
-    if (kvm_enabled()) {
-        kvmppc_xive_connect(SPAPR_INTC(spapr->xive), errp);
-    }
-}
-
 SpaprIrq spapr_irq_xive = {
     .nr_xirqs    = SPAPR_NR_XIRQS,
     .nr_msis     = SPAPR_NR_MSIS,
@@ -185,7 +164,6 @@ SpaprIrq spapr_irq_xive = {
 
     .post_load   = spapr_irq_post_load_xive,
     .reset       = spapr_irq_reset_xive,
-    .init_kvm    = spapr_irq_init_kvm_xive,
 };
 
 /*
@@ -251,7 +229,6 @@ SpaprIrq spapr_irq_dual = {
 
     .post_load   = spapr_irq_post_load_dual,
     .reset       = spapr_irq_reset_dual,
-    .init_kvm    = NULL, /* should not be used */
 };
 
 
@@ -675,7 +652,6 @@ SpaprIrq spapr_irq_xics_legacy = {
 
     .post_load   = spapr_irq_post_load_xics,
     .reset       = spapr_irq_reset_xics,
-    .init_kvm    = spapr_irq_init_kvm_xics,
 };
 
 static void spapr_irq_register_types(void)
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index 0df95e1b5a..06179b271f 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -85,7 +85,6 @@ typedef struct SpaprIrq {
 
     int (*post_load)(SpaprMachineState *spapr, int version_id);
     void (*reset)(SpaprMachineState *spapr, Error **errp);
-    void (*init_kvm)(SpaprMachineState *spapr, Error **errp);
 } SpaprIrq;
 
 extern SpaprIrq spapr_irq_xics;
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 13/19] spapr, xics, xive: Move SpaprIrq::reset hook logic into activate/deactivate
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (11 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 12/19] spapr: Remove SpaprIrq::init_kvm hook David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09 14:25   ` Greg Kurz
  2019-10-09 15:56   ` Cédric Le Goater
  2019-10-09  6:08 ` [PATCH v4 14/19] spapr, xics, xive: Move SpaprIrq::post_load hook to backends David Gibson
                   ` (7 subsequent siblings)
  20 siblings, 2 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

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 <david@gibson.dropbear.id.au>
---
 hw/intc/spapr_xive.c       | 38 +++++++++++++++++++++
 hw/intc/xics_spapr.c       | 17 ++++++++++
 hw/ppc/spapr_irq.c         | 67 ++------------------------------------
 include/hw/ppc/spapr_irq.h |  4 ++-
 4 files changed, 61 insertions(+), 65 deletions(-)

diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index 37ffb74ca5..1811653aac 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;
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 4eabafc7e1..90b4d48877 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -395,6 +395,21 @@ static void xics_spapr_print_info(SpaprInterruptController *intc, Monitor *mon)
     ics_pic_print_info(ics, mon);
 }
 
+static int xics_spapr_activate(SpaprInterruptController *intc, Error **errp)
+{
+    if (kvm_enabled()) {
+        return spapr_irq_init_kvm(xics_kvm_connect, intc, errp);
+    }
+    return 0;
+}
+
+static void xics_spapr_deactivate(SpaprInterruptController *intc)
+{
+    if (kvm_irqchip_in_kernel()) {
+        xics_kvm_disconnect(intc);
+    }
+}
+
 static void ics_spapr_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -403,6 +418,8 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
 
     device_class_set_parent_realize(dc, ics_spapr_realize,
                                     &isc->parent_realize);
+    sicc->activate = xics_spapr_activate;
+    sicc->deactivate = xics_spapr_deactivate;
     sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
     sicc->claim_irq = xics_spapr_claim_irq;
     sicc->free_irq = xics_spapr_free_irq;
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 7cd18e5b15..f70b331f44 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -65,9 +65,9 @@ void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num)
     bitmap_clear(spapr->irq_map, irq - SPAPR_IRQ_MSI, num);
 }
 
-static int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
-                              SpaprInterruptController *intc,
-                              Error **errp)
+int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
+                       SpaprInterruptController *intc,
+                       Error **errp)
 {
     MachineState *machine = MACHINE(qdev_get_machine());
     Error *local_err = NULL;
@@ -112,11 +112,6 @@ static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
     return 0;
 }
 
-static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp)
-{
-    spapr_irq_init_kvm(xics_kvm_connect, SPAPR_INTC(spapr->ics), errp);
-}
-
 SpaprIrq spapr_irq_xics = {
     .nr_xirqs    = SPAPR_NR_XIRQS,
     .nr_msis     = SPAPR_NR_MSIS,
@@ -124,7 +119,6 @@ SpaprIrq spapr_irq_xics = {
     .xive        = false,
 
     .post_load   = spapr_irq_post_load_xics,
-    .reset       = spapr_irq_reset_xics,
 };
 
 /*
@@ -136,26 +130,6 @@ static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
     return spapr_xive_post_load(spapr->xive, version_id);
 }
 
-static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp)
-{
-    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 (spapr_irq_init_kvm(kvmppc_xive_connect,
-                           SPAPR_INTC(spapr->xive), errp) < 0) {
-        return;
-    }
-
-    /* Activate the XIVE MMIOs */
-    spapr_xive_mmio_set_enabled(spapr->xive, true);
-}
-
 SpaprIrq spapr_irq_xive = {
     .nr_xirqs    = SPAPR_NR_XIRQS,
     .nr_msis     = SPAPR_NR_MSIS,
@@ -163,7 +137,6 @@ SpaprIrq spapr_irq_xive = {
     .xive        = true,
 
     .post_load   = spapr_irq_post_load_xive,
-    .reset       = spapr_irq_reset_xive,
 };
 
 /*
@@ -187,37 +160,9 @@ static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr)
 
 static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
 {
-    /*
-     * Force a reset of the XIVE backend after migration. The machine
-     * defaults to XICS at startup.
-     */
-    if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
-        if (kvm_irqchip_in_kernel()) {
-            xics_kvm_disconnect(SPAPR_INTC(spapr->ics));
-        }
-        spapr_irq_xive.reset(spapr, &error_fatal);
-    }
-
     return spapr_irq_current(spapr)->post_load(spapr, version_id);
 }
 
-static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp)
-{
-    /*
-     * Deactivate the XIVE MMIOs. The XIVE backend will reenable them
-     * if selected.
-     */
-    spapr_xive_mmio_set_enabled(spapr->xive, false);
-
-    /* Destroy all KVM devices */
-    if (kvm_irqchip_in_kernel()) {
-        xics_kvm_disconnect(SPAPR_INTC(spapr->ics));
-        kvmppc_xive_disconnect(SPAPR_INTC(spapr->xive));
-    }
-
-    spapr_irq_current(spapr)->reset(spapr, errp);
-}
-
 /*
  * Define values in sync with the XIVE and XICS backend
  */
@@ -228,7 +173,6 @@ SpaprIrq spapr_irq_dual = {
     .xive        = true,
 
     .post_load   = spapr_irq_post_load_dual,
-    .reset       = spapr_irq_reset_dual,
 };
 
 
@@ -512,10 +456,6 @@ void spapr_irq_reset(SpaprMachineState *spapr, Error **errp)
     assert(!spapr->irq_map || bitmap_empty(spapr->irq_map, spapr->irq_map_nr));
 
     spapr_irq_update_active_intc(spapr);
-
-    if (spapr->irq->reset) {
-        spapr->irq->reset(spapr, errp);
-    }
 }
 
 int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp)
@@ -651,7 +591,6 @@ SpaprIrq spapr_irq_xics_legacy = {
     .xive        = false,
 
     .post_load   = spapr_irq_post_load_xics,
-    .reset       = spapr_irq_reset_xics,
 };
 
 static void spapr_irq_register_types(void)
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index 06179b271f..e02e44624b 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -84,7 +84,6 @@ typedef struct SpaprIrq {
     bool        xive;
 
     int (*post_load)(SpaprMachineState *spapr, int version_id);
-    void (*reset)(SpaprMachineState *spapr, Error **errp);
 } SpaprIrq;
 
 extern SpaprIrq spapr_irq_xics;
@@ -99,6 +98,9 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq);
 int spapr_irq_post_load(SpaprMachineState *spapr, int version_id);
 void spapr_irq_reset(SpaprMachineState *spapr, Error **errp);
 int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp);
+int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
+                       SpaprInterruptController *intc,
+                       Error **errp);
 
 /*
  * XICS legacy routines
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 14/19] spapr, xics, xive: Move SpaprIrq::post_load hook to backends
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (12 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 13/19] spapr, xics, xive: Move SpaprIrq::reset hook logic into activate/deactivate David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09 15:57   ` Cédric Le Goater
  2019-10-09  6:08 ` [PATCH v4 15/19] spapr: Remove SpaprIrq::nr_msis David Gibson
                   ` (6 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

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 <david@gibson.dropbear.id.au>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 hw/intc/spapr_xive.c        |  5 +++--
 hw/intc/xics_spapr.c        | 13 +++++++++++
 hw/ppc/spapr_irq.c          | 45 ++++---------------------------------
 include/hw/ppc/spapr_irq.h  |  3 +--
 include/hw/ppc/spapr_xive.h |  1 -
 5 files changed, 21 insertions(+), 46 deletions(-)

diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index 1811653aac..ba32d2cc5b 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 = {
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 90b4d48877..4f64b9a9fc 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -395,6 +395,18 @@ static void xics_spapr_print_info(SpaprInterruptController *intc, Monitor *mon)
     ics_pic_print_info(ics, mon);
 }
 
+static int xics_spapr_post_load(SpaprInterruptController *intc, int version_id)
+{
+    if (!kvm_irqchip_in_kernel()) {
+        CPUState *cs;
+        CPU_FOREACH(cs) {
+            PowerPCCPU *cpu = POWERPC_CPU(cs);
+            icp_resend(spapr_cpu_state(cpu)->icp);
+        }
+    }
+    return 0;
+}
+
 static int xics_spapr_activate(SpaprInterruptController *intc, Error **errp)
 {
     if (kvm_enabled()) {
@@ -426,6 +438,7 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
     sicc->set_irq = xics_spapr_set_irq;
     sicc->print_info = xics_spapr_print_info;
     sicc->dt = xics_spapr_dt;
+    sicc->post_load = xics_spapr_post_load;
 }
 
 static const TypeInfo ics_spapr_info = {
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index f70b331f44..f3d18b1dad 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -100,43 +100,22 @@ int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
  * XICS IRQ backend.
  */
 
-static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
-{
-    if (!kvm_irqchip_in_kernel()) {
-        CPUState *cs;
-        CPU_FOREACH(cs) {
-            PowerPCCPU *cpu = POWERPC_CPU(cs);
-            icp_resend(spapr_cpu_state(cpu)->icp);
-        }
-    }
-    return 0;
-}
-
 SpaprIrq spapr_irq_xics = {
     .nr_xirqs    = SPAPR_NR_XIRQS,
     .nr_msis     = SPAPR_NR_MSIS,
     .xics        = true,
     .xive        = false,
-
-    .post_load   = spapr_irq_post_load_xics,
 };
 
 /*
  * XIVE IRQ backend.
  */
 
-static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
-{
-    return spapr_xive_post_load(spapr->xive, version_id);
-}
-
 SpaprIrq spapr_irq_xive = {
     .nr_xirqs    = SPAPR_NR_XIRQS,
     .nr_msis     = SPAPR_NR_MSIS,
     .xics        = false,
     .xive        = true,
-
-    .post_load   = spapr_irq_post_load_xive,
 };
 
 /*
@@ -148,21 +127,6 @@ SpaprIrq spapr_irq_xive = {
  * activated after an extra machine reset.
  */
 
-/*
- * Returns the sPAPR IRQ backend negotiated by CAS. XICS is the
- * default.
- */
-static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr)
-{
-    return spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT) ?
-        &spapr_irq_xive : &spapr_irq_xics;
-}
-
-static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
-{
-    return spapr_irq_current(spapr)->post_load(spapr, version_id);
-}
-
 /*
  * Define values in sync with the XIVE and XICS backend
  */
@@ -171,8 +135,6 @@ SpaprIrq spapr_irq_dual = {
     .nr_msis     = SPAPR_NR_MSIS,
     .xics        = true,
     .xive        = true,
-
-    .post_load   = spapr_irq_post_load_dual,
 };
 
 
@@ -447,8 +409,11 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
 
 int spapr_irq_post_load(SpaprMachineState *spapr, int version_id)
 {
+    SpaprInterruptControllerClass *sicc;
+
     spapr_irq_update_active_intc(spapr);
-    return spapr->irq->post_load(spapr, version_id);
+    sicc = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+    return sicc->post_load(spapr->active_intc, version_id);
 }
 
 void spapr_irq_reset(SpaprMachineState *spapr, Error **errp)
@@ -589,8 +554,6 @@ SpaprIrq spapr_irq_xics_legacy = {
     .nr_msis     = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS,
     .xics        = true,
     .xive        = false,
-
-    .post_load   = spapr_irq_post_load_xics,
 };
 
 static void spapr_irq_register_types(void)
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index e02e44624b..08173e714c 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -62,6 +62,7 @@ typedef struct SpaprInterruptControllerClass {
     void (*print_info)(SpaprInterruptController *intc, Monitor *mon);
     void (*dt)(SpaprInterruptController *intc, uint32_t nr_servers,
                void *fdt, uint32_t phandle);
+    int (*post_load)(SpaprInterruptController *intc, int version_id);
 } SpaprInterruptControllerClass;
 
 void spapr_irq_update_active_intc(SpaprMachineState *spapr);
@@ -82,8 +83,6 @@ typedef struct SpaprIrq {
     uint32_t    nr_msis;
     bool        xics;
     bool        xive;
-
-    int (*post_load)(SpaprMachineState *spapr, int version_id);
 } SpaprIrq;
 
 extern SpaprIrq spapr_irq_xics;
diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
index 64972754f9..d84bd5c229 100644
--- a/include/hw/ppc/spapr_xive.h
+++ b/include/hw/ppc/spapr_xive.h
@@ -55,7 +55,6 @@ typedef struct SpaprXive {
 #define SPAPR_XIVE_BLOCK_ID 0x0
 
 void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon);
-int spapr_xive_post_load(SpaprXive *xive, int version_id);
 
 void spapr_xive_hcall_init(SpaprMachineState *spapr);
 void spapr_xive_set_tctx_os_cam(XiveTCTX *tctx);
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 15/19] spapr: Remove SpaprIrq::nr_msis
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (13 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 14/19] spapr, xics, xive: Move SpaprIrq::post_load hook to backends David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09 15:59   ` Cédric Le Goater
  2019-10-09  6:08 ` [PATCH v4 16/19] spapr: Move SpaprIrq::nr_xirqs to SpaprMachineClass David Gibson
                   ` (5 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

The nr_msis value we use here has to line up with whether we're using
legacy or modern irq allocation.  Therefore it's safer to derive it based
on legacy_irq_allocation rather than having SpaprIrq contain a canned
value.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 hw/ppc/spapr.c              |  5 ++---
 hw/ppc/spapr_irq.c          | 26 +++++++++++++++++---------
 hw/ppc/spapr_pci.c          |  7 ++++---
 include/hw/pci-host/spapr.h |  4 ++--
 include/hw/ppc/spapr_irq.h  |  4 +---
 5 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index e880db5d38..153cc54354 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1275,7 +1275,7 @@ static void *spapr_build_fdt(SpaprMachineState *spapr)
     }
 
     QLIST_FOREACH(phb, &spapr->phbs, list) {
-        ret = spapr_dt_phb(phb, PHANDLE_INTC, fdt, spapr->irq->nr_msis, NULL);
+        ret = spapr_dt_phb(spapr, phb, PHANDLE_INTC, fdt, NULL);
         if (ret < 0) {
             error_report("couldn't setup PCI devices in fdt");
             exit(1);
@@ -3910,8 +3910,7 @@ int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
         return -1;
     }
 
-    if (spapr_dt_phb(sphb, intc_phandle, fdt, spapr->irq->nr_msis,
-                     fdt_start_offset)) {
+    if (spapr_dt_phb(spapr, sphb, intc_phandle, fdt, fdt_start_offset)) {
         error_setg(errp, "unable to create FDT node for PHB %d", sphb->index);
         return -1;
     }
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index f3d18b1dad..076da31501 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -29,9 +29,14 @@ static const TypeInfo spapr_intc_info = {
     .class_size = sizeof(SpaprInterruptControllerClass),
 };
 
-void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis)
+static void spapr_irq_msi_init(SpaprMachineState *spapr)
 {
-    spapr->irq_map_nr = nr_msis;
+    if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
+        /* Legacy mode doesn't use this allocater */
+        return;
+    }
+
+    spapr->irq_map_nr = spapr_irq_nr_msis(spapr);
     spapr->irq_map = bitmap_new(spapr->irq_map_nr);
 }
 
@@ -102,7 +107,6 @@ int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
 
 SpaprIrq spapr_irq_xics = {
     .nr_xirqs    = SPAPR_NR_XIRQS,
-    .nr_msis     = SPAPR_NR_MSIS,
     .xics        = true,
     .xive        = false,
 };
@@ -113,7 +117,6 @@ SpaprIrq spapr_irq_xics = {
 
 SpaprIrq spapr_irq_xive = {
     .nr_xirqs    = SPAPR_NR_XIRQS,
-    .nr_msis     = SPAPR_NR_MSIS,
     .xics        = false,
     .xive        = true,
 };
@@ -132,7 +135,6 @@ SpaprIrq spapr_irq_xive = {
  */
 SpaprIrq spapr_irq_dual = {
     .nr_xirqs    = SPAPR_NR_XIRQS,
-    .nr_msis     = SPAPR_NR_MSIS,
     .xics        = true,
     .xive        = true,
 };
@@ -247,6 +249,15 @@ void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
     sicc->dt(spapr->active_intc, nr_servers, fdt, phandle);
 }
 
+uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr)
+{
+    if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
+        return spapr->irq->nr_xirqs;
+    } else {
+        return SPAPR_XIRQ_BASE + spapr->irq->nr_xirqs - SPAPR_IRQ_MSI;
+    }
+}
+
 void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
 {
     MachineState *machine = MACHINE(spapr);
@@ -267,9 +278,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
     }
 
     /* Initialize the MSI IRQ allocator. */
-    if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
-        spapr_irq_msi_init(spapr, spapr->irq->nr_msis);
-    }
+    spapr_irq_msi_init(spapr);
 
     if (spapr->irq->xics) {
         Error *local_err = NULL;
@@ -551,7 +560,6 @@ int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
 
 SpaprIrq spapr_irq_xics_legacy = {
     .nr_xirqs    = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS,
-    .nr_msis     = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS,
     .xics        = true,
     .xive        = false,
 };
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 01ff41d4c4..cc0e7829b6 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -2277,8 +2277,8 @@ static void spapr_phb_pci_enumerate(SpaprPhbState *phb)
 
 }
 
-int spapr_dt_phb(SpaprPhbState *phb, uint32_t intc_phandle, void *fdt,
-                 uint32_t nr_msis, int *node_offset)
+int spapr_dt_phb(SpaprMachineState *spapr, SpaprPhbState *phb,
+                 uint32_t intc_phandle, void *fdt, int *node_offset)
 {
     int bus_off, i, j, ret;
     uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) };
@@ -2343,7 +2343,8 @@ int spapr_dt_phb(SpaprPhbState *phb, uint32_t intc_phandle, void *fdt,
     _FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof_ranges));
     _FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg)));
     _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pci-config-space-type", 0x1));
-    _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi", nr_msis));
+    _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi",
+                          spapr_irq_nr_msis(spapr)));
 
     /* Dynamic DMA window */
     if (phb->ddw_enabled) {
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 23506f05d9..8877ff51fb 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -128,8 +128,8 @@ struct SpaprPhbState {
 #define SPAPR_PCI_NV2ATSD_WIN_SIZE   (NVGPU_MAX_NUM * NVGPU_MAX_LINKS * \
                                       64 * KiB)
 
-int spapr_dt_phb(SpaprPhbState *phb, uint32_t intc_phandle, void *fdt,
-                 uint32_t nr_msis, int *node_offset);
+int spapr_dt_phb(SpaprMachineState *spapr, SpaprPhbState *phb,
+                 uint32_t intc_phandle, void *fdt, int *node_offset);
 
 void spapr_pci_rtas_init(void);
 
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index 08173e714c..befe8e01dc 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -27,7 +27,6 @@
 #define SPAPR_IRQ_MSI        (SPAPR_XIRQ_BASE + 0x0300)
 
 #define SPAPR_NR_XIRQS       0x1000
-#define SPAPR_NR_MSIS        (SPAPR_XIRQ_BASE + SPAPR_NR_XIRQS - SPAPR_IRQ_MSI)
 
 typedef struct SpaprMachineState SpaprMachineState;
 
@@ -73,14 +72,13 @@ void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon);
 void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
                   void *fdt, uint32_t phandle);
 
-void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
+uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr);
 int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
                         Error **errp);
 void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num);
 
 typedef struct SpaprIrq {
     uint32_t    nr_xirqs;
-    uint32_t    nr_msis;
     bool        xics;
     bool        xive;
 } SpaprIrq;
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 16/19] spapr: Move SpaprIrq::nr_xirqs to SpaprMachineClass
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (14 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 15/19] spapr: Remove SpaprIrq::nr_msis David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09 16:01   ` Cédric Le Goater
  2019-10-09  6:08 ` [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq David Gibson
                   ` (4 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

For the benefit of peripheral device allocation, the number of available
irqs really wants to be the same on a given machine type version,
regardless of what irq backends we are using.  That's the case now, but
only because we make sure the different SpaprIrq instances have the same
value except for the special legacy one.

Since this really only depends on machine type version, move the value to
SpaprMachineClass instead of SpaprIrq.  This also puts the code to set it
to the lower value on old machine types right next to setting
legacy_irq_allocation, which needs to go hand in hand.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 hw/ppc/spapr.c             |  2 ++
 hw/ppc/spapr_irq.c         | 33 ++++++++++++++++-----------------
 include/hw/ppc/spapr.h     |  1 +
 include/hw/ppc/spapr_irq.h |  1 -
 4 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 153cc54354..e1ff03152e 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4443,6 +4443,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
     smc->irq = &spapr_irq_dual;
     smc->dr_phb_enabled = true;
     smc->linux_pci_probe = true;
+    smc->nr_xirqs = SPAPR_NR_XIRQS;
 }
 
 static const TypeInfo spapr_machine_info = {
@@ -4578,6 +4579,7 @@ static void spapr_machine_3_0_class_options(MachineClass *mc)
     compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len);
 
     smc->legacy_irq_allocation = true;
+    smc->nr_xirqs = 0x400;
     smc->irq = &spapr_irq_xics_legacy;
 }
 
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 076da31501..2768f9a765 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -106,7 +106,6 @@ int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
  */
 
 SpaprIrq spapr_irq_xics = {
-    .nr_xirqs    = SPAPR_NR_XIRQS,
     .xics        = true,
     .xive        = false,
 };
@@ -116,7 +115,6 @@ SpaprIrq spapr_irq_xics = {
  */
 
 SpaprIrq spapr_irq_xive = {
-    .nr_xirqs    = SPAPR_NR_XIRQS,
     .xics        = false,
     .xive        = true,
 };
@@ -134,7 +132,6 @@ SpaprIrq spapr_irq_xive = {
  * Define values in sync with the XIVE and XICS backend
  */
 SpaprIrq spapr_irq_dual = {
-    .nr_xirqs    = SPAPR_NR_XIRQS,
     .xics        = true,
     .xive        = true,
 };
@@ -251,16 +248,19 @@ void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
 
 uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr)
 {
-    if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
-        return spapr->irq->nr_xirqs;
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+
+    if (smc->legacy_irq_allocation) {
+        return smc->nr_xirqs;
     } else {
-        return SPAPR_XIRQ_BASE + spapr->irq->nr_xirqs - SPAPR_IRQ_MSI;
+        return SPAPR_XIRQ_BASE + smc->nr_xirqs - SPAPR_IRQ_MSI;
     }
 }
 
 void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
 {
     MachineState *machine = MACHINE(spapr);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
 
     if (machine_kernel_irqchip_split(machine)) {
         error_setg(errp, "kernel_irqchip split mode not supported on pseries");
@@ -298,8 +298,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
             return;
         }
 
-        object_property_set_int(obj, spapr->irq->nr_xirqs, "nr-irqs",
-                                &local_err);
+        object_property_set_int(obj, smc->nr_xirqs, "nr-irqs", &local_err);
         if (local_err) {
             error_propagate(errp, local_err);
             return;
@@ -320,8 +319,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
         int i;
 
         dev = qdev_create(NULL, TYPE_SPAPR_XIVE);
-        qdev_prop_set_uint32(dev, "nr-irqs",
-                             spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE);
+        qdev_prop_set_uint32(dev, "nr-irqs", smc->nr_xirqs + SPAPR_XIRQ_BASE);
         /*
          * 8 XIVE END structures per CPU. One for each available
          * priority
@@ -346,17 +344,18 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
     }
 
     spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr,
-                                      spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE);
+                                      smc->nr_xirqs + SPAPR_XIRQ_BASE);
 }
 
 int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp)
 {
     SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
     int i;
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
     int rc;
 
     assert(irq >= SPAPR_XIRQ_BASE);
-    assert(irq < (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE));
+    assert(irq < (smc->nr_xirqs + SPAPR_XIRQ_BASE));
 
     for (i = 0; i < ARRAY_SIZE(intcs); i++) {
         SpaprInterruptController *intc = intcs[i];
@@ -376,9 +375,10 @@ void spapr_irq_free(SpaprMachineState *spapr, int irq, int num)
 {
     SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
     int i, j;
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
 
     assert(irq >= SPAPR_XIRQ_BASE);
-    assert((irq + num) <= (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE));
+    assert((irq + num) <= (smc->nr_xirqs + SPAPR_XIRQ_BASE));
 
     for (i = irq; i < (irq + num); i++) {
         for (j = 0; j < ARRAY_SIZE(intcs); j++) {
@@ -395,6 +395,8 @@ void spapr_irq_free(SpaprMachineState *spapr, int irq, int num)
 
 qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
 {
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+
     /*
      * This interface is basically for VIO and PHB devices to find the
      * right qemu_irq to manipulate, so we only allow access to the
@@ -403,7 +405,7 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
      * interfaces, we can change this if we need to in future.
      */
     assert(irq >= SPAPR_XIRQ_BASE);
-    assert(irq < (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE));
+    assert(irq < (smc->nr_xirqs + SPAPR_XIRQ_BASE));
 
     if (spapr->ics) {
         assert(ics_valid_irq(spapr->ics, irq));
@@ -556,10 +558,7 @@ int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
     return first + ics->offset;
 }
 
-#define SPAPR_IRQ_XICS_LEGACY_NR_XIRQS     0x400
-
 SpaprIrq spapr_irq_xics_legacy = {
-    .nr_xirqs    = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS,
     .xics        = true,
     .xive        = false,
 };
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 763da757f0..623e8e3f93 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -119,6 +119,7 @@ struct SpaprMachineClass {
     bool use_ohci_by_default;  /* use USB-OHCI instead of XHCI */
     bool pre_2_10_has_unused_icps;
     bool legacy_irq_allocation;
+    uint32_t nr_xirqs;
     bool broken_host_serial_model; /* present real host info to the guest */
     bool pre_4_1_migration; /* don't migrate hpt-max-page-size */
     bool linux_pci_probe;
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index befe8e01dc..5e150a6679 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -78,7 +78,6 @@ int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
 void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num);
 
 typedef struct SpaprIrq {
-    uint32_t    nr_xirqs;
     bool        xics;
     bool        xive;
 } SpaprIrq;
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (15 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 16/19] spapr: Move SpaprIrq::nr_xirqs to SpaprMachineClass David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09 16:44   ` Cédric Le Goater
  2019-10-09 17:02   ` Greg Kurz
  2019-10-09  6:08 ` [PATCH v4 18/19] spapr: Handle irq backend changes with VFIO PCI devices David Gibson
                   ` (3 subsequent siblings)
  20 siblings, 2 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

The only thing remaining in this structure are the flags to allow either
XICS or XIVE to be present.  These actually make more sense as spapr
capabilities - that way they can take advantage of the existing
infrastructure to sanity check capability states across migration and so
forth.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr.c             | 40 ++++++++++--------
 hw/ppc/spapr_caps.c        | 64 +++++++++++++++++++++++++++++
 hw/ppc/spapr_hcall.c       |  7 ++--
 hw/ppc/spapr_irq.c         | 84 ++------------------------------------
 include/hw/ppc/spapr.h     | 10 +++--
 include/hw/ppc/spapr_irq.h | 10 -----
 6 files changed, 103 insertions(+), 112 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index e1ff03152e..bf9fdb1693 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1072,12 +1072,13 @@ static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
         26, 0x40, /* Radix options: GTSE == yes. */
     };
 
-    if (spapr->irq->xics && spapr->irq->xive) {
+    if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
+        && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
         val[1] = SPAPR_OV5_XIVE_BOTH;
-    } else if (spapr->irq->xive) {
+    } else if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
         val[1] = SPAPR_OV5_XIVE_EXPLOIT;
     } else {
-        assert(spapr->irq->xics);
+        assert(spapr_get_cap(spapr, SPAPR_CAP_XICS));
         val[1] = SPAPR_OV5_XIVE_LEGACY;
     }
 
@@ -2075,6 +2076,8 @@ static const VMStateDescription vmstate_spapr = {
         &vmstate_spapr_dtb,
         &vmstate_spapr_cap_large_decr,
         &vmstate_spapr_cap_ccf_assist,
+        &vmstate_spapr_cap_xics,
+        &vmstate_spapr_cap_xive,
         NULL
     }
 };
@@ -2775,7 +2778,7 @@ static void spapr_machine_init(MachineState *machine)
     spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2);
 
     /* advertise XIVE on POWER9 machines */
-    if (spapr->irq->xive) {
+    if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
         spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
     }
 
@@ -3242,14 +3245,18 @@ static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name,
 static char *spapr_get_ic_mode(Object *obj, Error **errp)
 {
     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
 
-    if (spapr->irq == &spapr_irq_xics_legacy) {
+    if (smc->legacy_irq_allocation) {
         return g_strdup("legacy");
-    } else if (spapr->irq == &spapr_irq_xics) {
+    } else if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
+               && !spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
         return g_strdup("xics");
-    } else if (spapr->irq == &spapr_irq_xive) {
+    } else if (!spapr_get_cap(spapr, SPAPR_CAP_XICS)
+               && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
         return g_strdup("xive");
-    } else if (spapr->irq == &spapr_irq_dual) {
+    } else if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
+               && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
         return g_strdup("dual");
     }
     g_assert_not_reached();
@@ -3266,11 +3273,14 @@ static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
 
     /* The legacy IRQ backend can not be set */
     if (strcmp(value, "xics") == 0) {
-        spapr->irq = &spapr_irq_xics;
+        object_property_set_bool(obj, true, "cap-xics", errp);
+        object_property_set_bool(obj, false, "cap-xive", errp);
     } else if (strcmp(value, "xive") == 0) {
-        spapr->irq = &spapr_irq_xive;
+        object_property_set_bool(obj, false, "cap-xics", errp);
+        object_property_set_bool(obj, true, "cap-xive", errp);
     } else if (strcmp(value, "dual") == 0) {
-        spapr->irq = &spapr_irq_dual;
+        object_property_set_bool(obj, true, "cap-xics", errp);
+        object_property_set_bool(obj, true, "cap-xive", errp);
     } else {
         error_setg(errp, "Bad value for \"ic-mode\" property");
     }
@@ -3309,7 +3319,6 @@ static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
 static void spapr_instance_init(Object *obj)
 {
     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
-    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
 
     spapr->htab_fd = -1;
     spapr->use_hotplug_event_source = true;
@@ -3345,7 +3354,6 @@ static void spapr_instance_init(Object *obj)
                              spapr_get_msix_emulation, NULL, NULL);
 
     /* The machine class defines the default interrupt controller mode */
-    spapr->irq = smc->irq;
     object_property_add_str(obj, "ic-mode", spapr_get_ic_mode,
                             spapr_set_ic_mode, NULL);
     object_property_set_description(obj, "ic-mode",
@@ -4439,8 +4447,9 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
     smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
     smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
     smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
+    smc->default_caps.caps[SPAPR_CAP_XICS] = SPAPR_CAP_ON;
+    smc->default_caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_ON;
     spapr_caps_add_properties(smc, &error_abort);
-    smc->irq = &spapr_irq_dual;
     smc->dr_phb_enabled = true;
     smc->linux_pci_probe = true;
     smc->nr_xirqs = SPAPR_NR_XIRQS;
@@ -4539,7 +4548,7 @@ static void spapr_machine_4_0_class_options(MachineClass *mc)
     spapr_machine_4_1_class_options(mc);
     compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
     smc->phb_placement = phb_placement_4_0;
-    smc->irq = &spapr_irq_xics;
+    smc->default_caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_OFF;
     smc->pre_4_1_migration = true;
 }
 
@@ -4580,7 +4589,6 @@ static void spapr_machine_3_0_class_options(MachineClass *mc)
 
     smc->legacy_irq_allocation = true;
     smc->nr_xirqs = 0x400;
-    smc->irq = &spapr_irq_xics_legacy;
 }
 
 DEFINE_SPAPR_MACHINE(3_0, "3.0", false);
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 481dfd2a27..e06fd386f6 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -496,6 +496,42 @@ static void cap_ccf_assist_apply(SpaprMachineState *spapr, uint8_t val,
     }
 }
 
+static void cap_xics_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
+{
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+
+    if (!val) {
+        if (!spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
+            error_setg(errp,
+"No interrupt controllers enabled, try cap-xics=on or cap-xive=on");
+            return;
+        }
+
+        if (smc->legacy_irq_allocation) {
+            error_setg(errp, "This machine version requires XICS support");
+            return;
+        }
+    }
+}
+
+static void cap_xive_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
+{
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+    PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
+
+    if (val) {
+        if (smc->legacy_irq_allocation) {
+            error_setg(errp, "This machine version cannot support XIVE");
+            return;
+        }
+        if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0,
+                              spapr->max_compat_pvr)) {
+            error_setg(errp, "XIVE requires POWER9 CPU");
+            return;
+        }
+    }
+}
+
 SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
     [SPAPR_CAP_HTM] = {
         .name = "htm",
@@ -595,6 +631,24 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
         .type = "bool",
         .apply = cap_ccf_assist_apply,
     },
+    [SPAPR_CAP_XICS] = {
+        .name = "xics",
+        .description = "Allow XICS interrupt controller",
+        .index = SPAPR_CAP_XICS,
+        .get = spapr_cap_get_bool,
+        .set = spapr_cap_set_bool,
+        .type = "bool",
+        .apply = cap_xics_apply,
+    },
+    [SPAPR_CAP_XIVE] = {
+        .name = "xive",
+        .description = "Allow XIVE interrupt controller",
+        .index = SPAPR_CAP_XIVE,
+        .get = spapr_cap_get_bool,
+        .set = spapr_cap_set_bool,
+        .type = "bool",
+        .apply = cap_xive_apply,
+    },
 };
 
 static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
@@ -641,6 +695,14 @@ static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
         caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = mps;
     }
 
+    /*
+     * POWER8 machines don't have XIVE
+     */
+    if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_3_00,
+                               0, spapr->max_compat_pvr)) {
+        caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_OFF;
+    }
+
     return caps;
 }
 
@@ -734,6 +796,8 @@ SPAPR_CAP_MIG_STATE(hpt_maxpagesize, SPAPR_CAP_HPT_MAXPAGESIZE);
 SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
 SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
 SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
+SPAPR_CAP_MIG_STATE(xics, SPAPR_CAP_XICS);
+SPAPR_CAP_MIG_STATE(xive, SPAPR_CAP_XIVE);
 
 void spapr_caps_init(SpaprMachineState *spapr)
 {
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 140f05c1c6..cb4c6edf63 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1784,13 +1784,13 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
      * terminate the boot.
      */
     if (guest_xive) {
-        if (!spapr->irq->xive) {
+        if (!spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
             error_report(
 "Guest requested unavailable interrupt mode (XIVE), try the ic-mode=xive or ic-mode=dual machine property");
             exit(EXIT_FAILURE);
         }
     } else {
-        if (!spapr->irq->xics) {
+        if (!spapr_get_cap(spapr, SPAPR_CAP_XICS)) {
             error_report(
 "Guest requested unavailable interrupt mode (XICS), either don't set the ic-mode machine property or try ic-mode=xics or ic-mode=dual");
             exit(EXIT_FAILURE);
@@ -1804,7 +1804,8 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
      */
     if (!spapr->cas_reboot) {
         spapr->cas_reboot = spapr_ovec_test(ov5_updates, OV5_XIVE_EXPLOIT)
-            && spapr->irq->xics && spapr->irq->xive;
+            && spapr_get_cap(spapr, SPAPR_CAP_XICS)
+            && spapr_get_cap(spapr, SPAPR_CAP_XIVE);
     }
 
     spapr_ovec_cleanup(ov5_updates);
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 2768f9a765..473fc8780a 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -101,90 +101,19 @@ int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
     return 0;
 }
 
-/*
- * XICS IRQ backend.
- */
-
-SpaprIrq spapr_irq_xics = {
-    .xics        = true,
-    .xive        = false,
-};
-
-/*
- * XIVE IRQ backend.
- */
-
-SpaprIrq spapr_irq_xive = {
-    .xics        = false,
-    .xive        = true,
-};
-
-/*
- * Dual XIVE and XICS IRQ backend.
- *
- * Both interrupt mode, XIVE and XICS, objects are created but the
- * machine starts in legacy interrupt mode (XICS). It can be changed
- * by the CAS negotiation process and, in that case, the new mode is
- * activated after an extra machine reset.
- */
-
-/*
- * Define values in sync with the XIVE and XICS backend
- */
-SpaprIrq spapr_irq_dual = {
-    .xics        = true,
-    .xive        = true,
-};
-
-
 static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
 {
     MachineState *machine = MACHINE(spapr);
 
-    /*
-     * Sanity checks on non-P9 machines. On these, XIVE is not
-     * advertised, see spapr_dt_ov5_platform_support()
-     */
-    if (!ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00,
-                               0, spapr->max_compat_pvr)) {
-        /*
-         * If the 'dual' interrupt mode is selected, force XICS as CAS
-         * negotiation is useless.
-         */
-        if (spapr->irq == &spapr_irq_dual) {
-            spapr->irq = &spapr_irq_xics;
-            return 0;
-        }
-
-        /*
-         * Non-P9 machines using only XIVE is a bogus setup. We have two
-         * scenarios to take into account because of the compat mode:
-         *
-         * 1. POWER7/8 machines should fail to init later on when creating
-         *    the XIVE interrupt presenters because a POWER9 exception
-         *    model is required.
-
-         * 2. POWER9 machines using the POWER8 compat mode won't fail and
-         *    will let the OS boot with a partial XIVE setup : DT
-         *    properties but no hcalls.
-         *
-         * To cover both and not confuse the OS, add an early failure in
-         * QEMU.
-         */
-        if (spapr->irq == &spapr_irq_xive) {
-            error_setg(errp, "XIVE-only machines require a POWER9 CPU");
-            return -1;
-        }
-    }
-
     /*
      * On a POWER9 host, some older KVM XICS devices cannot be destroyed and
      * re-created. Detect that early to avoid QEMU to exit later when the
      * guest reboots.
      */
     if (kvm_enabled() &&
-        spapr->irq == &spapr_irq_dual &&
         machine_kernel_irqchip_required(machine) &&
+        spapr_get_cap(spapr, SPAPR_CAP_XICS) &&
+        spapr_get_cap(spapr, SPAPR_CAP_XIVE) &&
         xics_kvm_has_broken_disconnect(spapr)) {
         error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on");
         return -1;
@@ -280,7 +209,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
     /* Initialize the MSI IRQ allocator. */
     spapr_irq_msi_init(spapr);
 
-    if (spapr->irq->xics) {
+    if (spapr_get_cap(spapr, SPAPR_CAP_XICS)) {
         Error *local_err = NULL;
         Object *obj;
 
@@ -313,7 +242,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
         spapr->ics = ICS_SPAPR(obj);
     }
 
-    if (spapr->irq->xive) {
+    if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
         uint32_t nr_servers = spapr_max_server_number(spapr);
         DeviceState *dev;
         int i;
@@ -558,11 +487,6 @@ int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
     return first + ics->offset;
 }
 
-SpaprIrq spapr_irq_xics_legacy = {
-    .xics        = true,
-    .xive        = false,
-};
-
 static void spapr_irq_register_types(void)
 {
     type_register_static(&spapr_intc_info);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 623e8e3f93..d3b4dd7de3 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -79,8 +79,12 @@ typedef enum {
 #define SPAPR_CAP_LARGE_DECREMENTER     0x08
 /* Count Cache Flush Assist HW Instruction */
 #define SPAPR_CAP_CCF_ASSIST            0x09
+/* XICS interrupt controller */
+#define SPAPR_CAP_XICS                  0x0a
+/* XIVE interrupt controller */
+#define SPAPR_CAP_XIVE                  0x0b
 /* Num Caps */
-#define SPAPR_CAP_NUM                   (SPAPR_CAP_CCF_ASSIST + 1)
+#define SPAPR_CAP_NUM                   (SPAPR_CAP_XIVE + 1)
 
 /*
  * Capability Values
@@ -131,7 +135,6 @@ struct SpaprMachineClass {
                           hwaddr *nv2atsd, Error **errp);
     SpaprResizeHpt resize_hpt_default;
     SpaprCapabilities default_caps;
-    SpaprIrq *irq;
 };
 
 /**
@@ -195,7 +198,6 @@ struct SpaprMachineState {
 
     int32_t irq_map_nr;
     unsigned long *irq_map;
-    SpaprIrq *irq;
     qemu_irq *qirqs;
     SpaprInterruptController *active_intc;
     ICSState *ics;
@@ -870,6 +872,8 @@ extern const VMStateDescription vmstate_spapr_cap_hpt_maxpagesize;
 extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
 extern const VMStateDescription vmstate_spapr_cap_large_decr;
 extern const VMStateDescription vmstate_spapr_cap_ccf_assist;
+extern const VMStateDescription vmstate_spapr_cap_xics;
+extern const VMStateDescription vmstate_spapr_cap_xive;
 
 static inline uint8_t spapr_get_cap(SpaprMachineState *spapr, int cap)
 {
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index 5e150a6679..71aee13743 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -77,16 +77,6 @@ int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
                         Error **errp);
 void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num);
 
-typedef struct SpaprIrq {
-    bool        xics;
-    bool        xive;
-} SpaprIrq;
-
-extern SpaprIrq spapr_irq_xics;
-extern SpaprIrq spapr_irq_xics_legacy;
-extern SpaprIrq spapr_irq_xive;
-extern SpaprIrq spapr_irq_dual;
-
 void spapr_irq_init(SpaprMachineState *spapr, Error **errp);
 int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp);
 void spapr_irq_free(SpaprMachineState *spapr, int irq, int num);
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 18/19] spapr: Handle irq backend changes with VFIO PCI devices
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (16 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09  8:57   ` David Gibson
  2019-10-09  6:08 ` [PATCH v4 19/19] spapr: Work around spurious warnings from vfio INTx initialization David Gibson
                   ` (2 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Alexey Kardashevskiy, Jason Wang, Riku Voipio, groug,
	Laurent Vivier, Alex Williamson, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

pseries machine type can have one of two different interrupt controllers in
use depending on feature negotiation with the guest.  Usually this is
invisible to devices, because they route to a common set of qemu_irqs which
in turn dispatch to the correct back end.

VFIO passthrough devices, however, wire themselves up directly to the KVM
irqchip for performance, which means they are affected by this change in
interrupt controller.

Luckily, there's a notifier chain that will tell VFIO devices to update
their mappings - we just need to call it whenever the intc backend might
change.

In addition, we make sure we set an active intc earlier, because otherwise
vfio can issue a false warning, because it doesn't think a KVM irqchip is
in use (which is essentially for good INTx performance).

Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Alexey Kardashevskiy <aik@ozlabs.ru>

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr_irq.c     | 6 ++++++
 hw/ppc/spapr_pci.c     | 9 +++++++++
 include/hw/ppc/spapr.h | 1 +
 3 files changed, 16 insertions(+)

diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 473fc8780a..7964e4a1b8 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -409,6 +409,12 @@ static void set_active_intc(SpaprMachineState *spapr,
     }
 
     spapr->active_intc = new_intc;
+
+    /*
+     * We've changed the interrupt routing at the KVM level, let VFIO
+     * devices know they need to readjust.
+     */
+    spapr_pci_fire_intx_routing_notifiers(spapr);
 }
 
 void spapr_irq_update_active_intc(SpaprMachineState *spapr)
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index cc0e7829b6..3bcf6325d4 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -93,6 +93,15 @@ PCIDevice *spapr_pci_find_dev(SpaprMachineState *spapr, uint64_t buid,
     return pci_find_device(phb->bus, bus_num, devfn);
 }
 
+void spapr_pci_fire_intx_routing_notifiers(SpaprMachineState *spapr)
+{
+    SpaprPhbState *sphb;
+
+    QLIST_FOREACH(sphb, &spapr->phbs, list) {
+        pci_bus_fire_intx_routing_notifier(PCI_HOST_BRIDGE(sphb)->bus);
+    }
+}
+
 static uint32_t rtas_pci_cfgaddr(uint32_t arg)
 {
     /* This handles the encoding of extended config space addresses */
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index d3b4dd7de3..66b68fdd5e 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -805,6 +805,7 @@ void spapr_clear_pending_events(SpaprMachineState *spapr);
 int spapr_max_server_number(SpaprMachineState *spapr);
 void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
                       uint64_t pte0, uint64_t pte1);
+void spapr_pci_fire_intx_routing_notifiers(SpaprMachineState *spapr);
 
 /* DRC callbacks. */
 void spapr_core_release(DeviceState *dev);
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v4 19/19] spapr: Work around spurious warnings from vfio INTx initialization
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (17 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 18/19] spapr: Handle irq backend changes with VFIO PCI devices David Gibson
@ 2019-10-09  6:08 ` David Gibson
  2019-10-09  8:37   ` Greg Kurz
  2019-10-09  9:02 ` [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
  2019-10-16 16:04 ` Greg Kurz
  20 siblings, 1 reply; 54+ messages in thread
From: David Gibson @ 2019-10-09  6:08 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Alexey Kardashevskiy, Jason Wang, Riku Voipio, groug,
	Laurent Vivier, Alex Williamson, Paolo Bonzini,
	Marc-André Lureau, philmd, David Gibson

Traditional PCI INTx for vfio devices can only perform well if using
an in-kernel irqchip.  Therefore, vfio_intx_update() issues a warning
if an in kernel irqchip is not available.

We usually do have an in-kernel irqchip available for pseries machines
on POWER hosts.  However, because the platform allows feature
negotiation of what interrupt controller model to use, we don't
currently initialize it until machine reset.  vfio_intx_update() is
called (first) from vfio_realize() before that, so it can issue a
spurious warning, even if we will have an in kernel irqchip by the
time we need it.

To workaround this, make a call to spapr_irq_update_active_intc() from
spapr_irq_init() which is called at machine realize time, before the
vfio realize.  This call will be pretty much obsoleted by the later
call at reset time, but it serves to suppress the spurious warning
from VFIO.

Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Alexey Kardashevskiy <aik@ozlabs.ru>

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr_irq.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 7964e4a1b8..3aeb523f3e 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -274,6 +274,14 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
 
     spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr,
                                       smc->nr_xirqs + SPAPR_XIRQ_BASE);
+
+    /*
+     * Mostly we don't actually need this until reset, except that not
+     * having this set up can cause VFIO devices to issue a
+     * false-positive warning during realize(), because they don't yet
+     * have an in-kernel irq chip.
+     */
+    spapr_irq_update_active_intc(spapr);
 }
 
 int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp)
@@ -429,7 +437,8 @@ void spapr_irq_update_active_intc(SpaprMachineState *spapr)
          * this.
          */
         new_intc = SPAPR_INTC(spapr->xive);
-    } else if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
+    } else if (spapr->ov5_cas
+               && spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
         new_intc = SPAPR_INTC(spapr->xive);
     } else {
         new_intc = SPAPR_INTC(spapr->ics);
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 19/19] spapr: Work around spurious warnings from vfio INTx initialization
  2019-10-09  6:08 ` [PATCH v4 19/19] spapr: Work around spurious warnings from vfio INTx initialization David Gibson
@ 2019-10-09  8:37   ` Greg Kurz
  2019-10-09  8:52     ` David Gibson
  0 siblings, 1 reply; 54+ messages in thread
From: Greg Kurz @ 2019-10-09  8:37 UTC (permalink / raw)
  To: David Gibson
  Cc: Alexey Kardashevskiy, Jason Wang, Riku Voipio, qemu-devel,
	Laurent Vivier, Alex Williamson, qemu-ppc, clg, Paolo Bonzini,
	Marc-André Lureau, philmd

On Wed,  9 Oct 2019 17:08:18 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:

> Traditional PCI INTx for vfio devices can only perform well if using
> an in-kernel irqchip.  Therefore, vfio_intx_update() issues a warning
> if an in kernel irqchip is not available.
> 

Can you elaborate on what doesn't "perform well" without an
in-kernel irqchip ? Is it a matter of performance or is it
actually broken or something else ?

What is the impact on -machine accel=kvm,kernel-irqchip=off which
always spit this warning ?

> We usually do have an in-kernel irqchip available for pseries machines
> on POWER hosts.  However, because the platform allows feature
> negotiation of what interrupt controller model to use, we don't
> currently initialize it until machine reset.  vfio_intx_update() is
> called (first) from vfio_realize() before that, so it can issue a
> spurious warning, even if we will have an in kernel irqchip by the
> time we need it.
> 
> To workaround this, make a call to spapr_irq_update_active_intc() from
> spapr_irq_init() which is called at machine realize time, before the
> vfio realize.  This call will be pretty much obsoleted by the later
> call at reset time, but it serves to suppress the spurious warning
> from VFIO.
> 
> Cc: Alex Williamson <alex.williamson@redhat.com>
> Cc: Alexey Kardashevskiy <aik@ozlabs.ru>
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
>  hw/ppc/spapr_irq.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index 7964e4a1b8..3aeb523f3e 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -274,6 +274,14 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>  
>      spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr,
>                                        smc->nr_xirqs + SPAPR_XIRQ_BASE);
> +
> +    /*
> +     * Mostly we don't actually need this until reset, except that not
> +     * having this set up can cause VFIO devices to issue a
> +     * false-positive warning during realize(), because they don't yet
> +     * have an in-kernel irq chip.
> +     */
> +    spapr_irq_update_active_intc(spapr);
>  }
>  
>  int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp)
> @@ -429,7 +437,8 @@ void spapr_irq_update_active_intc(SpaprMachineState *spapr)
>           * this.
>           */
>          new_intc = SPAPR_INTC(spapr->xive);
> -    } else if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
> +    } else if (spapr->ov5_cas
> +               && spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
>          new_intc = SPAPR_INTC(spapr->xive);
>      } else {
>          new_intc = SPAPR_INTC(spapr->ics);



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 19/19] spapr: Work around spurious warnings from vfio INTx initialization
  2019-10-09  8:37   ` Greg Kurz
@ 2019-10-09  8:52     ` David Gibson
  2019-10-09 17:16       ` Greg Kurz
  0 siblings, 1 reply; 54+ messages in thread
From: David Gibson @ 2019-10-09  8:52 UTC (permalink / raw)
  To: Greg Kurz
  Cc: Alexey Kardashevskiy, Jason Wang, Riku Voipio, qemu-devel,
	Laurent Vivier, Alex Williamson, qemu-ppc, clg, Paolo Bonzini,
	Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 3431 bytes --]

On Wed, Oct 09, 2019 at 10:37:38AM +0200, Greg Kurz wrote:
> On Wed,  9 Oct 2019 17:08:18 +1100
> David Gibson <david@gibson.dropbear.id.au> wrote:
> 
> > Traditional PCI INTx for vfio devices can only perform well if using
> > an in-kernel irqchip.  Therefore, vfio_intx_update() issues a warning
> > if an in kernel irqchip is not available.
> 
> Can you elaborate on what doesn't "perform well" without an
> in-kernel irqchip ?

Not really, no, but Alex Williamson tells me it is soo.

> Is it a matter of performance or is it
> actually broken or something else ?

I believe it's a matter of performance, but such a big one that it
makes using it without kernel irqchip infeasible in many cases.

> What is the impact on -machine accel=kvm,kernel-irqchip=off which
> always spit this warning ?

It should still spit that warning.

> > We usually do have an in-kernel irqchip available for pseries machines
> > on POWER hosts.  However, because the platform allows feature
> > negotiation of what interrupt controller model to use, we don't
> > currently initialize it until machine reset.  vfio_intx_update() is
> > called (first) from vfio_realize() before that, so it can issue a
> > spurious warning, even if we will have an in kernel irqchip by the
> > time we need it.
> > 
> > To workaround this, make a call to spapr_irq_update_active_intc() from
> > spapr_irq_init() which is called at machine realize time, before the
> > vfio realize.  This call will be pretty much obsoleted by the later
> > call at reset time, but it serves to suppress the spurious warning
> > from VFIO.
> > 
> > Cc: Alex Williamson <alex.williamson@redhat.com>
> > Cc: Alexey Kardashevskiy <aik@ozlabs.ru>
> > 
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> >  hw/ppc/spapr_irq.c | 11 ++++++++++-
> >  1 file changed, 10 insertions(+), 1 deletion(-)
> > 
> > diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> > index 7964e4a1b8..3aeb523f3e 100644
> > --- a/hw/ppc/spapr_irq.c
> > +++ b/hw/ppc/spapr_irq.c
> > @@ -274,6 +274,14 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
> >  
> >      spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr,
> >                                        smc->nr_xirqs + SPAPR_XIRQ_BASE);
> > +
> > +    /*
> > +     * Mostly we don't actually need this until reset, except that not
> > +     * having this set up can cause VFIO devices to issue a
> > +     * false-positive warning during realize(), because they don't yet
> > +     * have an in-kernel irq chip.
> > +     */
> > +    spapr_irq_update_active_intc(spapr);
> >  }
> >  
> >  int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp)
> > @@ -429,7 +437,8 @@ void spapr_irq_update_active_intc(SpaprMachineState *spapr)
> >           * this.
> >           */
> >          new_intc = SPAPR_INTC(spapr->xive);
> > -    } else if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
> > +    } else if (spapr->ov5_cas
> > +               && spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
> >          new_intc = SPAPR_INTC(spapr->xive);
> >      } else {
> >          new_intc = SPAPR_INTC(spapr->ics);
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 18/19] spapr: Handle irq backend changes with VFIO PCI devices
  2019-10-09  6:08 ` [PATCH v4 18/19] spapr: Handle irq backend changes with VFIO PCI devices David Gibson
@ 2019-10-09  8:57   ` David Gibson
  0 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09  8:57 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Alexey Kardashevskiy, Jason Wang, Riku Voipio, groug,
	Laurent Vivier, Alex Williamson, Paolo Bonzini,
	Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 3979 bytes --]

On Wed, Oct 09, 2019 at 05:08:17PM +1100, David Gibson wrote:
> pseries machine type can have one of two different interrupt controllers in
> use depending on feature negotiation with the guest.  Usually this is
> invisible to devices, because they route to a common set of qemu_irqs which
> in turn dispatch to the correct back end.
> 
> VFIO passthrough devices, however, wire themselves up directly to the KVM
> irqchip for performance, which means they are affected by this change in
> interrupt controller.
> 
> Luckily, there's a notifier chain that will tell VFIO devices to update
> their mappings - we just need to call it whenever the intc backend might
> change.
> 
> In addition, we make sure we set an active intc earlier, because otherwise
> vfio can issue a false warning, because it doesn't think a KVM irqchip is
> in use (which is essentially for good INTx performance).
> 
> Cc: Alex Williamson <alex.williamson@redhat.com>
> Cc: Alexey Kardashevskiy <aik@ozlabs.ru>
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

For reference, the reason I described this as RFC only in the cover
letter, is that this doesn't work as it stands.

With this patch, when we switch intc we call the intx_routing
notifiers, and vfio_intx_update() in particular.  However that exits
early without calling vfio_intx_enable_kvm() - the bit we actually
need - because the test on pci_intx_route_changed() thinks there's
nothing to do.  The difficulty is that our use case isn't really the
same as the x86 one this notifier path was designed for: they're
changing routing of INTx to global interrupts.  For us the routing to
global interrupts remains the same, but the interrupt controller
handling those global interrupts has changed.

> ---
>  hw/ppc/spapr_irq.c     | 6 ++++++
>  hw/ppc/spapr_pci.c     | 9 +++++++++
>  include/hw/ppc/spapr.h | 1 +
>  3 files changed, 16 insertions(+)
> 
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index 473fc8780a..7964e4a1b8 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -409,6 +409,12 @@ static void set_active_intc(SpaprMachineState *spapr,
>      }
>  
>      spapr->active_intc = new_intc;
> +
> +    /*
> +     * We've changed the interrupt routing at the KVM level, let VFIO
> +     * devices know they need to readjust.
> +     */
> +    spapr_pci_fire_intx_routing_notifiers(spapr);
>  }
>  
>  void spapr_irq_update_active_intc(SpaprMachineState *spapr)
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index cc0e7829b6..3bcf6325d4 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -93,6 +93,15 @@ PCIDevice *spapr_pci_find_dev(SpaprMachineState *spapr, uint64_t buid,
>      return pci_find_device(phb->bus, bus_num, devfn);
>  }
>  
> +void spapr_pci_fire_intx_routing_notifiers(SpaprMachineState *spapr)
> +{
> +    SpaprPhbState *sphb;
> +
> +    QLIST_FOREACH(sphb, &spapr->phbs, list) {
> +        pci_bus_fire_intx_routing_notifier(PCI_HOST_BRIDGE(sphb)->bus);
> +    }
> +}
> +
>  static uint32_t rtas_pci_cfgaddr(uint32_t arg)
>  {
>      /* This handles the encoding of extended config space addresses */
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index d3b4dd7de3..66b68fdd5e 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -805,6 +805,7 @@ void spapr_clear_pending_events(SpaprMachineState *spapr);
>  int spapr_max_server_number(SpaprMachineState *spapr);
>  void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
>                        uint64_t pte0, uint64_t pte1);
> +void spapr_pci_fire_intx_routing_notifiers(SpaprMachineState *spapr);
>  
>  /* DRC callbacks. */
>  void spapr_core_release(DeviceState *dev);

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 00/19] spapr: IRQ subsystem cleanup
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (18 preceding siblings ...)
  2019-10-09  6:08 ` [PATCH v4 19/19] spapr: Work around spurious warnings from vfio INTx initialization David Gibson
@ 2019-10-09  9:02 ` David Gibson
  2019-10-16 16:04 ` Greg Kurz
  20 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09  9:02 UTC (permalink / raw)
  To: qemu-devel, clg, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 809 bytes --]

On Wed, Oct 09, 2019 at 05:07:59PM +1100, David Gibson wrote:
> This is a substantial rework to clean up the handling of IRQs in
> spapr.  It includes some cleanups to both the XICS and XIVE interrupt
> controller backends, as well as more to the common spapr irq handling
> infrastructure.
> 
> The last two patches of this series, dealing with VFIO devices, are
> RFC only - there some problems that I'm discussing with Alex
> Williamson.

Oops, I screwed up my base branch selection for git-publish - patches
1..3 aren't supposed to be in this series (although 1..2 fit well
enough thematically).

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 07/19] spapr: Formalize notion of active interrupt controller
  2019-10-09  6:08 ` [PATCH v4 07/19] spapr: Formalize notion of active interrupt controller David Gibson
@ 2019-10-09  9:16   ` Cédric Le Goater
  2019-10-09  9:19   ` Cédric Le Goater
  1 sibling, 0 replies; 54+ messages in thread
From: Cédric Le Goater @ 2019-10-09  9:16 UTC (permalink / raw)
  To: David Gibson, qemu-devel, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd

On 09/10/2019 08:08, David Gibson wrote:
> spapr now has the mechanism of constructing both XICS and XIVE instances of
> the SpaprInterruptController interface.  However, only one of the interrupt
> controllers will actually be active at any given time, depending on feature
> negotiation with the guest.  This is handled in the current code via
> spapr_irq_current() which checks the OV5 vector from feature negotiation to
> determine the current backend.
> 
> Determining the active controller at the point we need it like this
> can be pretty confusing, because it makes it very non obvious at what
> points the active controller can change.  This can make it difficult
> to reason about the code and where a change of active controller could
> appear in sequence with other events.
> 
> Make this mechanism more explicit by adding an 'active_intc' pointer
> and an explicit spapr_irq_update_active_intc() function to update it
> from the CAS state.  We also add hooks on the intc backend which will
> get called when it is activated or deactivated.
> 
> For now we just introduce the switch and hooks, later patches will
> actually start using them.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> Reviewed-by: Greg Kurz <groug@kaod.org>

Reviewed-by: Cédric Le Goater <clg@kaod.org>

> ---
>  hw/ppc/spapr_irq.c         | 51 ++++++++++++++++++++++++++++++++++++++
>  include/hw/ppc/spapr.h     |  5 ++--
>  include/hw/ppc/spapr_irq.h |  5 ++++
>  3 files changed, 59 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index 83882cfad3..249a2688ac 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -586,6 +586,7 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
>  
>  int spapr_irq_post_load(SpaprMachineState *spapr, int version_id)
>  {
> +    spapr_irq_update_active_intc(spapr);
>      return spapr->irq->post_load(spapr, version_id);
>  }
>  
> @@ -593,6 +594,8 @@ void spapr_irq_reset(SpaprMachineState *spapr, Error **errp)
>  {
>      assert(!spapr->irq_map || bitmap_empty(spapr->irq_map, spapr->irq_map_nr));
>  
> +    spapr_irq_update_active_intc(spapr);
> +
>      if (spapr->irq->reset) {
>          spapr->irq->reset(spapr, errp);
>      }
> @@ -619,6 +622,54 @@ int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp)
>      return phandle;
>  }
>  
> +static void set_active_intc(SpaprMachineState *spapr,
> +                            SpaprInterruptController *new_intc)
> +{
> +    SpaprInterruptControllerClass *sicc;
> +
> +    assert(new_intc);
> +
> +    if (new_intc == spapr->active_intc) {
> +        /* Nothing to do */
> +        return;
> +    }
> +
> +    if (spapr->active_intc) {
> +        sicc = SPAPR_INTC_GET_CLASS(spapr->active_intc);
> +        if (sicc->deactivate) {
> +            sicc->deactivate(spapr->active_intc);
> +        }
> +    }
> +
> +    sicc = SPAPR_INTC_GET_CLASS(new_intc);
> +    if (sicc->activate) {
> +        sicc->activate(new_intc, &error_fatal);
> +    }
> +
> +    spapr->active_intc = new_intc;
> +}
> +
> +void spapr_irq_update_active_intc(SpaprMachineState *spapr)
> +{
> +    SpaprInterruptController *new_intc;
> +
> +    if (!spapr->ics) {
> +        /*
> +         * XXX before we run CAS, ov5_cas is initialized empty, which
> +         * indicates XICS, even if we have ic-mode=xive.  TODO: clean
> +         * up the CAS path so that we have a clearer way of handling
> +         * this.
> +         */
> +        new_intc = SPAPR_INTC(spapr->xive);
> +    } else if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
> +        new_intc = SPAPR_INTC(spapr->xive);
> +    } else {
> +        new_intc = SPAPR_INTC(spapr->ics);
> +    }
> +
> +    set_active_intc(spapr, new_intc);
> +}
> +
>  /*
>   * XICS legacy routines - to deprecate one day
>   */
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index cbd1a4c9f3..763da757f0 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -143,7 +143,6 @@ struct SpaprMachineState {
>      struct SpaprVioBus *vio_bus;
>      QLIST_HEAD(, SpaprPhbState) phbs;
>      struct SpaprNvram *nvram;
> -    ICSState *ics;
>      SpaprRtcState rtc;
>  
>      SpaprResizeHpt resize_hpt;
> @@ -195,9 +194,11 @@ struct SpaprMachineState {
>  
>      int32_t irq_map_nr;
>      unsigned long *irq_map;
> -    SpaprXive  *xive;
>      SpaprIrq *irq;
>      qemu_irq *qirqs;
> +    SpaprInterruptController *active_intc;
> +    ICSState *ics;
> +    SpaprXive *xive;
>  
>      bool cmd_line_caps[SPAPR_CAP_NUM];
>      SpaprCapabilities def, eff, mig;
> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> index adfef0fcbe..593059eff5 100644
> --- a/include/hw/ppc/spapr_irq.h
> +++ b/include/hw/ppc/spapr_irq.h
> @@ -44,6 +44,9 @@ typedef struct SpaprInterruptController SpaprInterruptController;
>  typedef struct SpaprInterruptControllerClass {
>      InterfaceClass parent;
>  
> +    int (*activate)(SpaprInterruptController *intc, Error **errp);
> +    void (*deactivate)(SpaprInterruptController *intc);
> +
>      /*
>       * These methods will typically be called on all intcs, active and
>       * inactive
> @@ -55,6 +58,8 @@ typedef struct SpaprInterruptControllerClass {
>      void (*free_irq)(SpaprInterruptController *intc, int irq);
>  } SpaprInterruptControllerClass;
>  
> +void spapr_irq_update_active_intc(SpaprMachineState *spapr);
> +
>  int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
>                                PowerPCCPU *cpu, Error **errp);
>  
> 



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 08/19] spapr, xics, xive: Move set_irq from SpaprIrq to SpaprInterruptController
  2019-10-09  6:08 ` [PATCH v4 08/19] spapr, xics, xive: Move set_irq from SpaprIrq to SpaprInterruptController David Gibson
@ 2019-10-09  9:18   ` Cédric Le Goater
  0 siblings, 0 replies; 54+ messages in thread
From: Cédric Le Goater @ 2019-10-09  9:18 UTC (permalink / raw)
  To: David Gibson, qemu-devel, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd

On 09/10/2019 08:08, David Gibson wrote:
> 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 <david@gibson.dropbear.id.au>
> Reviewed-by: Greg Kurz <groug@kaod.org>


Reviewed-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/intc/spapr_xive.c       | 12 +++++++++++
>  hw/intc/xics_spapr.c       |  9 +++++++++
>  hw/ppc/spapr_irq.c         | 41 ++++++++++----------------------------
>  include/hw/ppc/spapr_irq.h |  4 +++-
>  4 files changed, 34 insertions(+), 32 deletions(-)
> 
> diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
> index ff1a175b44..52d5e71793 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 = {
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> index 224fe1efcd..02372697f6 100644
> --- a/hw/intc/xics_spapr.c
> +++ b/hw/intc/xics_spapr.c
> @@ -373,6 +373,14 @@ static void xics_spapr_free_irq(SpaprInterruptController *intc, int irq)
>      memset(&ics->irqs[srcno], 0, sizeof(ICSIRQState));
>  }
>  
> +static void xics_spapr_set_irq(SpaprInterruptController *intc, int irq, int val)
> +{
> +    ICSState *ics = ICS_SPAPR(intc);
> +    uint32_t srcno = irq - ics->offset;
> +
> +    ics_set_irq(ics, srcno, val);
> +}
> +
>  static void ics_spapr_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> @@ -384,6 +392,7 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
>      sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
>      sicc->claim_irq = xics_spapr_claim_irq;
>      sicc->free_irq = xics_spapr_free_irq;
> +    sicc->set_irq = xics_spapr_set_irq;
>  }
>  
>  static const TypeInfo ics_spapr_info = {
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index 249a2688ac..bfccb815ed 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -123,14 +123,6 @@ static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
>      return 0;
>  }
>  
> -static void spapr_irq_set_irq_xics(void *opaque, int irq, int val)
> -{
> -    SpaprMachineState *spapr = opaque;
> -    uint32_t srcno = irq - spapr->ics->offset;
> -
> -    ics_set_irq(spapr->ics, srcno, val);
> -}
> -
>  static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp)
>  {
>      Error *local_err = NULL;
> @@ -159,7 +151,6 @@ SpaprIrq spapr_irq_xics = {
>      .dt_populate = spapr_dt_xics,
>      .post_load   = spapr_irq_post_load_xics,
>      .reset       = spapr_irq_reset_xics,
> -    .set_irq     = spapr_irq_set_irq_xics,
>      .init_kvm    = spapr_irq_init_kvm_xics,
>  };
>  
> @@ -208,17 +199,6 @@ static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp)
>      spapr_xive_mmio_set_enabled(spapr->xive, true);
>  }
>  
> -static void spapr_irq_set_irq_xive(void *opaque, int irq, int val)
> -{
> -    SpaprMachineState *spapr = opaque;
> -
> -    if (kvm_irqchip_in_kernel()) {
> -        kvmppc_xive_source_set_irq(&spapr->xive->source, irq, val);
> -    } else {
> -        xive_source_set_irq(&spapr->xive->source, irq, val);
> -    }
> -}
> -
>  static void spapr_irq_init_kvm_xive(SpaprMachineState *spapr, Error **errp)
>  {
>      if (kvm_enabled()) {
> @@ -236,7 +216,6 @@ SpaprIrq spapr_irq_xive = {
>      .dt_populate = spapr_dt_xive,
>      .post_load   = spapr_irq_post_load_xive,
>      .reset       = spapr_irq_reset_xive,
> -    .set_irq     = spapr_irq_set_irq_xive,
>      .init_kvm    = spapr_irq_init_kvm_xive,
>  };
>  
> @@ -316,13 +295,6 @@ static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp)
>      spapr_irq_current(spapr)->reset(spapr, errp);
>  }
>  
> -static void spapr_irq_set_irq_dual(void *opaque, int irq, int val)
> -{
> -    SpaprMachineState *spapr = opaque;
> -
> -    spapr_irq_current(spapr)->set_irq(spapr, irq, val);
> -}
> -
>  /*
>   * Define values in sync with the XIVE and XICS backend
>   */
> @@ -336,7 +308,6 @@ SpaprIrq spapr_irq_dual = {
>      .dt_populate = spapr_irq_dt_populate_dual,
>      .post_load   = spapr_irq_post_load_dual,
>      .reset       = spapr_irq_reset_dual,
> -    .set_irq     = spapr_irq_set_irq_dual,
>      .init_kvm    = NULL, /* should not be used */
>  };
>  
> @@ -424,6 +395,15 @@ int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
>      return 0;
>  }
>  
> +static void spapr_set_irq(void *opaque, int irq, int level)
> +{
> +    SpaprMachineState *spapr = SPAPR_MACHINE(opaque);
> +    SpaprInterruptControllerClass *sicc
> +        = SPAPR_INTC_GET_CLASS(spapr->active_intc);
> +
> +    sicc->set_irq(spapr->active_intc, irq, level);
> +}
> +
>  void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>  {
>      MachineState *machine = MACHINE(spapr);
> @@ -513,7 +493,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>          spapr_xive_hcall_init(spapr);
>      }
>  
> -    spapr->qirqs = qemu_allocate_irqs(spapr->irq->set_irq, spapr,
> +    spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr,
>                                        spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE);
>  }
>  
> @@ -737,7 +717,6 @@ SpaprIrq spapr_irq_xics_legacy = {
>      .dt_populate = spapr_dt_xics,
>      .post_load   = spapr_irq_post_load_xics,
>      .reset       = spapr_irq_reset_xics,
> -    .set_irq     = spapr_irq_set_irq_xics,
>      .init_kvm    = spapr_irq_init_kvm_xics,
>  };
>  
> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> index 593059eff5..ece8d2ea48 100644
> --- a/include/hw/ppc/spapr_irq.h
> +++ b/include/hw/ppc/spapr_irq.h
> @@ -56,6 +56,9 @@ typedef struct SpaprInterruptControllerClass {
>      int (*claim_irq)(SpaprInterruptController *intc, int irq, bool lsi,
>                       Error **errp);
>      void (*free_irq)(SpaprInterruptController *intc, int irq);
> +
> +    /* These methods should only be called on the active intc */
> +    void (*set_irq)(SpaprInterruptController *intc, int irq, int val);
>  } SpaprInterruptControllerClass;
>  
>  void spapr_irq_update_active_intc(SpaprMachineState *spapr);
> @@ -80,7 +83,6 @@ typedef struct SpaprIrq {
>                          void *fdt, uint32_t phandle);
>      int (*post_load)(SpaprMachineState *spapr, int version_id);
>      void (*reset)(SpaprMachineState *spapr, Error **errp);
> -    void (*set_irq)(void *opaque, int srcno, int val);
>      void (*init_kvm)(SpaprMachineState *spapr, Error **errp);
>  } SpaprIrq;
>  
> 



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 07/19] spapr: Formalize notion of active interrupt controller
  2019-10-09  6:08 ` [PATCH v4 07/19] spapr: Formalize notion of active interrupt controller David Gibson
  2019-10-09  9:16   ` Cédric Le Goater
@ 2019-10-09  9:19   ` Cédric Le Goater
  2019-10-09 11:38     ` David Gibson
  1 sibling, 1 reply; 54+ messages in thread
From: Cédric Le Goater @ 2019-10-09  9:19 UTC (permalink / raw)
  To: David Gibson, qemu-devel, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd

On 09/10/2019 08:08, David Gibson wrote:
> spapr now has the mechanism of constructing both XICS and XIVE instances of
> the SpaprInterruptController interface.  However, only one of the interrupt
> controllers will actually be active at any given time, depending on feature
> negotiation with the guest.  This is handled in the current code via
> spapr_irq_current() which checks the OV5 vector from feature negotiation to
> determine the current backend.
> 
> Determining the active controller at the point we need it like this
> can be pretty confusing, because it makes it very non obvious at what
> points the active controller can change.  This can make it difficult
> to reason about the code and where a change of active controller could
> appear in sequence with other events.
> 
> Make this mechanism more explicit by adding an 'active_intc' pointer
> and an explicit spapr_irq_update_active_intc() function to update it
> from the CAS state.  We also add hooks on the intc backend which will
> get called when it is activated or deactivated.
> 
> For now we just introduce the switch and hooks, later patches will
> actually start using them.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> Reviewed-by: Greg Kurz <groug@kaod.org>
Btw, we will need an extra xive2 pointer for the Power10 interrupt 
controller.

C.

> ---
>  hw/ppc/spapr_irq.c         | 51 ++++++++++++++++++++++++++++++++++++++
>  include/hw/ppc/spapr.h     |  5 ++--
>  include/hw/ppc/spapr_irq.h |  5 ++++
>  3 files changed, 59 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index 83882cfad3..249a2688ac 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -586,6 +586,7 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
>  
>  int spapr_irq_post_load(SpaprMachineState *spapr, int version_id)
>  {
> +    spapr_irq_update_active_intc(spapr);
>      return spapr->irq->post_load(spapr, version_id);
>  }
>  
> @@ -593,6 +594,8 @@ void spapr_irq_reset(SpaprMachineState *spapr, Error **errp)
>  {
>      assert(!spapr->irq_map || bitmap_empty(spapr->irq_map, spapr->irq_map_nr));
>  
> +    spapr_irq_update_active_intc(spapr);
> +
>      if (spapr->irq->reset) {
>          spapr->irq->reset(spapr, errp);
>      }
> @@ -619,6 +622,54 @@ int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp)
>      return phandle;
>  }
>  
> +static void set_active_intc(SpaprMachineState *spapr,
> +                            SpaprInterruptController *new_intc)
> +{
> +    SpaprInterruptControllerClass *sicc;
> +
> +    assert(new_intc);
> +
> +    if (new_intc == spapr->active_intc) {
> +        /* Nothing to do */
> +        return;
> +    }
> +
> +    if (spapr->active_intc) {
> +        sicc = SPAPR_INTC_GET_CLASS(spapr->active_intc);
> +        if (sicc->deactivate) {
> +            sicc->deactivate(spapr->active_intc);
> +        }
> +    }
> +
> +    sicc = SPAPR_INTC_GET_CLASS(new_intc);
> +    if (sicc->activate) {
> +        sicc->activate(new_intc, &error_fatal);
> +    }
> +
> +    spapr->active_intc = new_intc;
> +}
> +
> +void spapr_irq_update_active_intc(SpaprMachineState *spapr)
> +{
> +    SpaprInterruptController *new_intc;
> +
> +    if (!spapr->ics) {
> +        /*
> +         * XXX before we run CAS, ov5_cas is initialized empty, which
> +         * indicates XICS, even if we have ic-mode=xive.  TODO: clean
> +         * up the CAS path so that we have a clearer way of handling
> +         * this.
> +         */
> +        new_intc = SPAPR_INTC(spapr->xive);
> +    } else if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
> +        new_intc = SPAPR_INTC(spapr->xive);
> +    } else {
> +        new_intc = SPAPR_INTC(spapr->ics);
> +    }
> +
> +    set_active_intc(spapr, new_intc);
> +}
> +
>  /*
>   * XICS legacy routines - to deprecate one day
>   */
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index cbd1a4c9f3..763da757f0 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -143,7 +143,6 @@ struct SpaprMachineState {
>      struct SpaprVioBus *vio_bus;
>      QLIST_HEAD(, SpaprPhbState) phbs;
>      struct SpaprNvram *nvram;
> -    ICSState *ics;
>      SpaprRtcState rtc;
>  
>      SpaprResizeHpt resize_hpt;
> @@ -195,9 +194,11 @@ struct SpaprMachineState {
>  
>      int32_t irq_map_nr;
>      unsigned long *irq_map;
> -    SpaprXive  *xive;
>      SpaprIrq *irq;
>      qemu_irq *qirqs;
> +    SpaprInterruptController *active_intc;
> +    ICSState *ics;
> +    SpaprXive *xive;
>  
>      bool cmd_line_caps[SPAPR_CAP_NUM];
>      SpaprCapabilities def, eff, mig;
> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> index adfef0fcbe..593059eff5 100644
> --- a/include/hw/ppc/spapr_irq.h
> +++ b/include/hw/ppc/spapr_irq.h
> @@ -44,6 +44,9 @@ typedef struct SpaprInterruptController SpaprInterruptController;
>  typedef struct SpaprInterruptControllerClass {
>      InterfaceClass parent;
>  
> +    int (*activate)(SpaprInterruptController *intc, Error **errp);
> +    void (*deactivate)(SpaprInterruptController *intc);
> +
>      /*
>       * These methods will typically be called on all intcs, active and
>       * inactive
> @@ -55,6 +58,8 @@ typedef struct SpaprInterruptControllerClass {
>      void (*free_irq)(SpaprInterruptController *intc, int irq);
>  } SpaprInterruptControllerClass;
>  
> +void spapr_irq_update_active_intc(SpaprMachineState *spapr);
> +
>  int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
>                                PowerPCCPU *cpu, Error **errp);
>  
> 



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 09/19] spapr, xics, xive: Move print_info from SpaprIrq to SpaprInterruptController
  2019-10-09  6:08 ` [PATCH v4 09/19] spapr, xics, xive: Move print_info " David Gibson
@ 2019-10-09  9:19   ` Cédric Le Goater
  0 siblings, 0 replies; 54+ messages in thread
From: Cédric Le Goater @ 2019-10-09  9:19 UTC (permalink / raw)
  To: David Gibson, qemu-devel, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd

On 09/10/2019 08:08, David Gibson wrote:
> 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 <david@gibson.dropbear.id.au>
> Reviewed-by: Greg Kurz <groug@kaod.org>

Reviewed-by: Cédric Le Goater <clg@kaod.org>

> ---
>  hw/intc/spapr_xive.c       | 15 +++++++++++++
>  hw/intc/xics_spapr.c       | 15 +++++++++++++
>  hw/ppc/spapr.c             |  2 +-
>  hw/ppc/spapr_irq.c         | 44 +++++++-------------------------------
>  include/hw/ppc/spapr_irq.h |  4 ++--
>  5 files changed, 41 insertions(+), 39 deletions(-)
> 
> diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
> index 52d5e71793..700ec5c9c1 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 = {
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> index 02372697f6..415defe394 100644
> --- a/hw/intc/xics_spapr.c
> +++ b/hw/intc/xics_spapr.c
> @@ -381,6 +381,20 @@ static void xics_spapr_set_irq(SpaprInterruptController *intc, int irq, int val)
>      ics_set_irq(ics, srcno, val);
>  }
>  
> +static void xics_spapr_print_info(SpaprInterruptController *intc, Monitor *mon)
> +{
> +    ICSState *ics = ICS_SPAPR(intc);
> +    CPUState *cs;
> +
> +    CPU_FOREACH(cs) {
> +        PowerPCCPU *cpu = POWERPC_CPU(cs);
> +
> +        icp_pic_print_info(spapr_cpu_state(cpu)->icp, mon);
> +    }
> +
> +    ics_pic_print_info(ics, mon);
> +}
> +
>  static void ics_spapr_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> @@ -393,6 +407,7 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
>      sicc->claim_irq = xics_spapr_claim_irq;
>      sicc->free_irq = xics_spapr_free_irq;
>      sicc->set_irq = xics_spapr_set_irq;
> +    sicc->print_info = xics_spapr_print_info;
>  }
>  
>  static const TypeInfo ics_spapr_info = {
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 514a17ae74..6c38de5927 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -4271,7 +4271,7 @@ static void spapr_pic_print_info(InterruptStatsProvider *obj,
>  {
>      SpaprMachineState *spapr = SPAPR_MACHINE(obj);
>  
> -    spapr->irq->print_info(spapr, mon);
> +    spapr_irq_print_info(spapr, mon);
>      monitor_printf(mon, "irqchip: %s\n",
>                     kvm_irqchip_in_kernel() ? "in-kernel" : "emulated");
>  }
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index bfccb815ed..a29b527232 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -98,19 +98,6 @@ static void spapr_irq_init_kvm(SpaprMachineState *spapr,
>   * XICS IRQ backend.
>   */
>  
> -static void spapr_irq_print_info_xics(SpaprMachineState *spapr, Monitor *mon)
> -{
> -    CPUState *cs;
> -
> -    CPU_FOREACH(cs) {
> -        PowerPCCPU *cpu = POWERPC_CPU(cs);
> -
> -        icp_pic_print_info(spapr_cpu_state(cpu)->icp, mon);
> -    }
> -
> -    ics_pic_print_info(spapr->ics, mon);
> -}
> -
>  static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
>  {
>      if (!kvm_irqchip_in_kernel()) {
> @@ -147,7 +134,6 @@ SpaprIrq spapr_irq_xics = {
>      .xics        = true,
>      .xive        = false,
>  
> -    .print_info  = spapr_irq_print_info_xics,
>      .dt_populate = spapr_dt_xics,
>      .post_load   = spapr_irq_post_load_xics,
>      .reset       = spapr_irq_reset_xics,
> @@ -158,20 +144,6 @@ SpaprIrq spapr_irq_xics = {
>   * XIVE IRQ backend.
>   */
>  
> -static void spapr_irq_print_info_xive(SpaprMachineState *spapr,
> -                                      Monitor *mon)
> -{
> -    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(spapr->xive, mon);
> -}
> -
>  static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
>  {
>      return spapr_xive_post_load(spapr->xive, version_id);
> @@ -212,7 +184,6 @@ SpaprIrq spapr_irq_xive = {
>      .xics        = false,
>      .xive        = true,
>  
> -    .print_info  = spapr_irq_print_info_xive,
>      .dt_populate = spapr_dt_xive,
>      .post_load   = spapr_irq_post_load_xive,
>      .reset       = spapr_irq_reset_xive,
> @@ -238,11 +209,6 @@ static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr)
>          &spapr_irq_xive : &spapr_irq_xics;
>  }
>  
> -static void spapr_irq_print_info_dual(SpaprMachineState *spapr, Monitor *mon)
> -{
> -    spapr_irq_current(spapr)->print_info(spapr, mon);
> -}
> -
>  static void spapr_irq_dt_populate_dual(SpaprMachineState *spapr,
>                                         uint32_t nr_servers, void *fdt,
>                                         uint32_t phandle)
> @@ -304,7 +270,6 @@ SpaprIrq spapr_irq_dual = {
>      .xics        = true,
>      .xive        = true,
>  
> -    .print_info  = spapr_irq_print_info_dual,
>      .dt_populate = spapr_irq_dt_populate_dual,
>      .post_load   = spapr_irq_post_load_dual,
>      .reset       = spapr_irq_reset_dual,
> @@ -404,6 +369,14 @@ static void spapr_set_irq(void *opaque, int irq, int level)
>      sicc->set_irq(spapr->active_intc, irq, level);
>  }
>  
> +void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon)
> +{
> +    SpaprInterruptControllerClass *sicc
> +        = SPAPR_INTC_GET_CLASS(spapr->active_intc);
> +
> +    sicc->print_info(spapr->active_intc, mon);
> +}
> +
>  void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>  {
>      MachineState *machine = MACHINE(spapr);
> @@ -713,7 +686,6 @@ SpaprIrq spapr_irq_xics_legacy = {
>      .xics        = true,
>      .xive        = false,
>  
> -    .print_info  = spapr_irq_print_info_xics,
>      .dt_populate = spapr_dt_xics,
>      .post_load   = spapr_irq_post_load_xics,
>      .reset       = spapr_irq_reset_xics,
> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> index ece8d2ea48..bdfeb3b107 100644
> --- a/include/hw/ppc/spapr_irq.h
> +++ b/include/hw/ppc/spapr_irq.h
> @@ -59,13 +59,14 @@ typedef struct SpaprInterruptControllerClass {
>  
>      /* These methods should only be called on the active intc */
>      void (*set_irq)(SpaprInterruptController *intc, int irq, int val);
> +    void (*print_info)(SpaprInterruptController *intc, Monitor *mon);
>  } SpaprInterruptControllerClass;
>  
>  void spapr_irq_update_active_intc(SpaprMachineState *spapr);
>  
>  int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
>                                PowerPCCPU *cpu, Error **errp);
> -
> +void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon);
>  
>  void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
>  int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
> @@ -78,7 +79,6 @@ typedef struct SpaprIrq {
>      bool        xics;
>      bool        xive;
>  
> -    void (*print_info)(SpaprMachineState *spapr, Monitor *mon);
>      void (*dt_populate)(SpaprMachineState *spapr, uint32_t nr_servers,
>                          void *fdt, uint32_t phandle);
>      int (*post_load)(SpaprMachineState *spapr, int version_id);
> 



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 10/19] spapr, xics, xive: Move dt_populate from SpaprIrq to SpaprInterruptController
  2019-10-09  6:08 ` [PATCH v4 10/19] spapr, xics, xive: Move dt_populate " David Gibson
@ 2019-10-09  9:20   ` Cédric Le Goater
  0 siblings, 0 replies; 54+ messages in thread
From: Cédric Le Goater @ 2019-10-09  9:20 UTC (permalink / raw)
  To: David Gibson, qemu-devel, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd

On 09/10/2019 08:08, David Gibson wrote:
> 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 <david@gibson.dropbear.id.au>
> Reviewed-by: Greg Kurz <groug@kaod.org>


Reviewed-by: Cédric Le Goater <clg@kaod.org>

> ---
>  hw/intc/spapr_xive.c        | 125 ++++++++++++++++++------------------
>  hw/intc/xics_spapr.c        |   5 +-
>  hw/ppc/spapr.c              |   3 +-
>  hw/ppc/spapr_irq.c          |  20 +++---
>  include/hw/ppc/spapr_irq.h  |   6 +-
>  include/hw/ppc/spapr_xive.h |   2 -
>  include/hw/ppc/xics_spapr.h |   2 -
>  7 files changed, 80 insertions(+), 83 deletions(-)
> 
> diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
> index 700ec5c9c1..37ffb74ca5 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)));
> -}
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> index 415defe394..4eabafc7e1 100644
> --- a/hw/intc/xics_spapr.c
> +++ b/hw/intc/xics_spapr.c
> @@ -308,8 +308,8 @@ static void ics_spapr_realize(DeviceState *dev, Error **errp)
>      spapr_register_hypercall(H_IPOLL, h_ipoll);
>  }
>  
> -void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
> -                   uint32_t phandle)
> +static void xics_spapr_dt(SpaprInterruptController *intc, uint32_t nr_servers,
> +                          void *fdt, uint32_t phandle)
>  {
>      uint32_t interrupt_server_ranges_prop[] = {
>          0, cpu_to_be32(nr_servers),
> @@ -408,6 +408,7 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
>      sicc->free_irq = xics_spapr_free_irq;
>      sicc->set_irq = xics_spapr_set_irq;
>      sicc->print_info = xics_spapr_print_info;
> +    sicc->dt = xics_spapr_dt;
>  }
>  
>  static const TypeInfo ics_spapr_info = {
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 6c38de5927..e880db5d38 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -1255,8 +1255,7 @@ static void *spapr_build_fdt(SpaprMachineState *spapr)
>      _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2));
>  
>      /* /interrupt controller */
> -    spapr->irq->dt_populate(spapr, spapr_max_server_number(spapr), fdt,
> -                          PHANDLE_INTC);
> +    spapr_irq_dt(spapr, spapr_max_server_number(spapr), fdt, PHANDLE_INTC);
>  
>      ret = spapr_populate_memory(spapr, fdt);
>      if (ret < 0) {
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index a29b527232..a8005072e6 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -134,7 +134,6 @@ SpaprIrq spapr_irq_xics = {
>      .xics        = true,
>      .xive        = false,
>  
> -    .dt_populate = spapr_dt_xics,
>      .post_load   = spapr_irq_post_load_xics,
>      .reset       = spapr_irq_reset_xics,
>      .init_kvm    = spapr_irq_init_kvm_xics,
> @@ -184,7 +183,6 @@ SpaprIrq spapr_irq_xive = {
>      .xics        = false,
>      .xive        = true,
>  
> -    .dt_populate = spapr_dt_xive,
>      .post_load   = spapr_irq_post_load_xive,
>      .reset       = spapr_irq_reset_xive,
>      .init_kvm    = spapr_irq_init_kvm_xive,
> @@ -209,13 +207,6 @@ static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr)
>          &spapr_irq_xive : &spapr_irq_xics;
>  }
>  
> -static void spapr_irq_dt_populate_dual(SpaprMachineState *spapr,
> -                                       uint32_t nr_servers, void *fdt,
> -                                       uint32_t phandle)
> -{
> -    spapr_irq_current(spapr)->dt_populate(spapr, nr_servers, fdt, phandle);
> -}
> -
>  static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
>  {
>      /*
> @@ -270,7 +261,6 @@ SpaprIrq spapr_irq_dual = {
>      .xics        = true,
>      .xive        = true,
>  
> -    .dt_populate = spapr_irq_dt_populate_dual,
>      .post_load   = spapr_irq_post_load_dual,
>      .reset       = spapr_irq_reset_dual,
>      .init_kvm    = NULL, /* should not be used */
> @@ -377,6 +367,15 @@ void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon)
>      sicc->print_info(spapr->active_intc, mon);
>  }
>  
> +void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
> +                  void *fdt, uint32_t phandle)
> +{
> +    SpaprInterruptControllerClass *sicc
> +        = SPAPR_INTC_GET_CLASS(spapr->active_intc);
> +
> +    sicc->dt(spapr->active_intc, nr_servers, fdt, phandle);
> +}
> +
>  void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>  {
>      MachineState *machine = MACHINE(spapr);
> @@ -686,7 +685,6 @@ SpaprIrq spapr_irq_xics_legacy = {
>      .xics        = true,
>      .xive        = false,
>  
> -    .dt_populate = spapr_dt_xics,
>      .post_load   = spapr_irq_post_load_xics,
>      .reset       = spapr_irq_reset_xics,
>      .init_kvm    = spapr_irq_init_kvm_xics,
> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> index bdfeb3b107..0df95e1b5a 100644
> --- a/include/hw/ppc/spapr_irq.h
> +++ b/include/hw/ppc/spapr_irq.h
> @@ -60,6 +60,8 @@ typedef struct SpaprInterruptControllerClass {
>      /* These methods should only be called on the active intc */
>      void (*set_irq)(SpaprInterruptController *intc, int irq, int val);
>      void (*print_info)(SpaprInterruptController *intc, Monitor *mon);
> +    void (*dt)(SpaprInterruptController *intc, uint32_t nr_servers,
> +               void *fdt, uint32_t phandle);
>  } SpaprInterruptControllerClass;
>  
>  void spapr_irq_update_active_intc(SpaprMachineState *spapr);
> @@ -67,6 +69,8 @@ void spapr_irq_update_active_intc(SpaprMachineState *spapr);
>  int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
>                                PowerPCCPU *cpu, Error **errp);
>  void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon);
> +void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
> +                  void *fdt, uint32_t phandle);
>  
>  void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
>  int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
> @@ -79,8 +83,6 @@ typedef struct SpaprIrq {
>      bool        xics;
>      bool        xive;
>  
> -    void (*dt_populate)(SpaprMachineState *spapr, uint32_t nr_servers,
> -                        void *fdt, uint32_t phandle);
>      int (*post_load)(SpaprMachineState *spapr, int version_id);
>      void (*reset)(SpaprMachineState *spapr, Error **errp);
>      void (*init_kvm)(SpaprMachineState *spapr, Error **errp);
> diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
> index 8f875673f5..ebe156eb30 100644
> --- a/include/hw/ppc/spapr_xive.h
> +++ b/include/hw/ppc/spapr_xive.h
> @@ -58,8 +58,6 @@ void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon);
>  int spapr_xive_post_load(SpaprXive *xive, int version_id);
>  
>  void spapr_xive_hcall_init(SpaprMachineState *spapr);
> -void spapr_dt_xive(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
> -                   uint32_t phandle);
>  void spapr_xive_set_tctx_os_cam(XiveTCTX *tctx);
>  void spapr_xive_mmio_set_enabled(SpaprXive *xive, bool enable);
>  void spapr_xive_map_mmio(SpaprXive *xive);
> diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h
> index 0b35e85c26..8e4fb6adce 100644
> --- a/include/hw/ppc/xics_spapr.h
> +++ b/include/hw/ppc/xics_spapr.h
> @@ -32,8 +32,6 @@
>  #define TYPE_ICS_SPAPR "ics-spapr"
>  #define ICS_SPAPR(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SPAPR)
>  
> -void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
> -                   uint32_t phandle);
>  int xics_kvm_connect(SpaprMachineState *spapr, Error **errp);
>  void xics_kvm_disconnect(SpaprMachineState *spapr, Error **errp);
>  bool xics_kvm_has_broken_disconnect(SpaprMachineState *spapr);
> 



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 07/19] spapr: Formalize notion of active interrupt controller
  2019-10-09  9:19   ` Cédric Le Goater
@ 2019-10-09 11:38     ` David Gibson
  0 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-09 11:38 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: Jason Wang, Riku Voipio, Laurent Vivier, qemu-devel, groug,
	qemu-ppc, Paolo Bonzini, Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 1779 bytes --]

On Wed, Oct 09, 2019 at 11:19:26AM +0200, Cédric Le Goater wrote:
> On 09/10/2019 08:08, David Gibson wrote:
> > spapr now has the mechanism of constructing both XICS and XIVE instances of
> > the SpaprInterruptController interface.  However, only one of the interrupt
> > controllers will actually be active at any given time, depending on feature
> > negotiation with the guest.  This is handled in the current code via
> > spapr_irq_current() which checks the OV5 vector from feature negotiation to
> > determine the current backend.
> > 
> > Determining the active controller at the point we need it like this
> > can be pretty confusing, because it makes it very non obvious at what
> > points the active controller can change.  This can make it difficult
> > to reason about the code and where a change of active controller could
> > appear in sequence with other events.
> > 
> > Make this mechanism more explicit by adding an 'active_intc' pointer
> > and an explicit spapr_irq_update_active_intc() function to update it
> > from the CAS state.  We also add hooks on the intc backend which will
> > get called when it is activated or deactivated.
> > 
> > For now we just introduce the switch and hooks, later patches will
> > actually start using them.
> > 
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > Reviewed-by: Greg Kurz <groug@kaod.org>
> Btw, we will need an extra xive2 pointer for the Power10 interrupt 
> controller.

Yeah, I figured.  I think it should be easier to add more irq backends
with the new structure.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 13/19] spapr, xics, xive: Move SpaprIrq::reset hook logic into activate/deactivate
  2019-10-09  6:08 ` [PATCH v4 13/19] spapr, xics, xive: Move SpaprIrq::reset hook logic into activate/deactivate David Gibson
@ 2019-10-09 14:25   ` Greg Kurz
  2019-10-09 15:56     ` Cédric Le Goater
  2019-10-09 15:56   ` Cédric Le Goater
  1 sibling, 1 reply; 54+ messages in thread
From: Greg Kurz @ 2019-10-09 14:25 UTC (permalink / raw)
  To: David Gibson
  Cc: Jason Wang, Riku Voipio, qemu-devel, Laurent Vivier, qemu-ppc,
	clg, Paolo Bonzini, Marc-André Lureau, philmd

On Wed,  9 Oct 2019 17:08:12 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:

> 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 <david@gibson.dropbear.id.au>
> ---
>  hw/intc/spapr_xive.c       | 38 +++++++++++++++++++++
>  hw/intc/xics_spapr.c       | 17 ++++++++++
>  hw/ppc/spapr_irq.c         | 67 ++------------------------------------
>  include/hw/ppc/spapr_irq.h |  4 ++-
>  4 files changed, 61 insertions(+), 65 deletions(-)
> 
> diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
> index 37ffb74ca5..1811653aac 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;
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> index 4eabafc7e1..90b4d48877 100644
> --- a/hw/intc/xics_spapr.c
> +++ b/hw/intc/xics_spapr.c
> @@ -395,6 +395,21 @@ static void xics_spapr_print_info(SpaprInterruptController *intc, Monitor *mon)
>      ics_pic_print_info(ics, mon);
>  }
>  
> +static int xics_spapr_activate(SpaprInterruptController *intc, Error **errp)
> +{
> +    if (kvm_enabled()) {
> +        return spapr_irq_init_kvm(xics_kvm_connect, intc, errp);
> +    }
> +    return 0;
> +}
> +
> +static void xics_spapr_deactivate(SpaprInterruptController *intc)
> +{
> +    if (kvm_irqchip_in_kernel()) {
> +        xics_kvm_disconnect(intc);
> +    }
> +}
> +
>  static void ics_spapr_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> @@ -403,6 +418,8 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
>  
>      device_class_set_parent_realize(dc, ics_spapr_realize,
>                                      &isc->parent_realize);
> +    sicc->activate = xics_spapr_activate;
> +    sicc->deactivate = xics_spapr_deactivate;
>      sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
>      sicc->claim_irq = xics_spapr_claim_irq;
>      sicc->free_irq = xics_spapr_free_irq;
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index 7cd18e5b15..f70b331f44 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -65,9 +65,9 @@ void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num)
>      bitmap_clear(spapr->irq_map, irq - SPAPR_IRQ_MSI, num);
>  }
>  
> -static int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
> -                              SpaprInterruptController *intc,
> -                              Error **errp)
> +int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
> +                       SpaprInterruptController *intc,
> +                       Error **errp)
>  {
>      MachineState *machine = MACHINE(qdev_get_machine());
>      Error *local_err = NULL;
> @@ -112,11 +112,6 @@ static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
>      return 0;
>  }
>  
> -static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp)
> -{
> -    spapr_irq_init_kvm(xics_kvm_connect, SPAPR_INTC(spapr->ics), errp);
> -}
> -
>  SpaprIrq spapr_irq_xics = {
>      .nr_xirqs    = SPAPR_NR_XIRQS,
>      .nr_msis     = SPAPR_NR_MSIS,
> @@ -124,7 +119,6 @@ SpaprIrq spapr_irq_xics = {
>      .xive        = false,
>  
>      .post_load   = spapr_irq_post_load_xics,
> -    .reset       = spapr_irq_reset_xics,
>  };
>  
>  /*
> @@ -136,26 +130,6 @@ static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
>      return spapr_xive_post_load(spapr->xive, version_id);
>  }
>  
> -static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp)
> -{
> -    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 (spapr_irq_init_kvm(kvmppc_xive_connect,
> -                           SPAPR_INTC(spapr->xive), errp) < 0) {
> -        return;
> -    }
> -
> -    /* Activate the XIVE MMIOs */
> -    spapr_xive_mmio_set_enabled(spapr->xive, true);
> -}
> -
>  SpaprIrq spapr_irq_xive = {
>      .nr_xirqs    = SPAPR_NR_XIRQS,
>      .nr_msis     = SPAPR_NR_MSIS,
> @@ -163,7 +137,6 @@ SpaprIrq spapr_irq_xive = {
>      .xive        = true,
>  
>      .post_load   = spapr_irq_post_load_xive,
> -    .reset       = spapr_irq_reset_xive,
>  };
>  
>  /*
> @@ -187,37 +160,9 @@ static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr)
>  
>  static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
>  {
> -    /*
> -     * Force a reset of the XIVE backend after migration. The machine
> -     * defaults to XICS at startup.
> -     */
> -    if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
> -        if (kvm_irqchip_in_kernel()) {
> -            xics_kvm_disconnect(SPAPR_INTC(spapr->ics));
> -        }
> -        spapr_irq_xive.reset(spapr, &error_fatal);
> -    }
> -
>      return spapr_irq_current(spapr)->post_load(spapr, version_id);
>  }
>  
> -static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp)
> -{
> -    /*
> -     * Deactivate the XIVE MMIOs. The XIVE backend will reenable them
> -     * if selected.
> -     */
> -    spapr_xive_mmio_set_enabled(spapr->xive, false);
> -
> -    /* Destroy all KVM devices */
> -    if (kvm_irqchip_in_kernel()) {
> -        xics_kvm_disconnect(SPAPR_INTC(spapr->ics));
> -        kvmppc_xive_disconnect(SPAPR_INTC(spapr->xive));

With this going away, we don't need to check the KVM device fd is valid in
xics_kvm_disconnect() and spapr_xive_disconnect() anymore. Cool !

Reviewed-by: Greg Kurz <groug@kaod.org>

> -    }
> -
> -    spapr_irq_current(spapr)->reset(spapr, errp);
> -}
> -
>  /*
>   * Define values in sync with the XIVE and XICS backend
>   */
> @@ -228,7 +173,6 @@ SpaprIrq spapr_irq_dual = {
>      .xive        = true,
>  
>      .post_load   = spapr_irq_post_load_dual,
> -    .reset       = spapr_irq_reset_dual,
>  };
>  
>  
> @@ -512,10 +456,6 @@ void spapr_irq_reset(SpaprMachineState *spapr, Error **errp)
>      assert(!spapr->irq_map || bitmap_empty(spapr->irq_map, spapr->irq_map_nr));
>  
>      spapr_irq_update_active_intc(spapr);
> -
> -    if (spapr->irq->reset) {
> -        spapr->irq->reset(spapr, errp);
> -    }
>  }
>  
>  int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp)
> @@ -651,7 +591,6 @@ SpaprIrq spapr_irq_xics_legacy = {
>      .xive        = false,
>  
>      .post_load   = spapr_irq_post_load_xics,
> -    .reset       = spapr_irq_reset_xics,
>  };
>  
>  static void spapr_irq_register_types(void)
> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> index 06179b271f..e02e44624b 100644
> --- a/include/hw/ppc/spapr_irq.h
> +++ b/include/hw/ppc/spapr_irq.h
> @@ -84,7 +84,6 @@ typedef struct SpaprIrq {
>      bool        xive;
>  
>      int (*post_load)(SpaprMachineState *spapr, int version_id);
> -    void (*reset)(SpaprMachineState *spapr, Error **errp);
>  } SpaprIrq;
>  
>  extern SpaprIrq spapr_irq_xics;
> @@ -99,6 +98,9 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq);
>  int spapr_irq_post_load(SpaprMachineState *spapr, int version_id);
>  void spapr_irq_reset(SpaprMachineState *spapr, Error **errp);
>  int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp);
> +int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
> +                       SpaprInterruptController *intc,
> +                       Error **errp);
>  
>  /*
>   * XICS legacy routines



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 13/19] spapr, xics, xive: Move SpaprIrq::reset hook logic into activate/deactivate
  2019-10-09 14:25   ` Greg Kurz
@ 2019-10-09 15:56     ` Cédric Le Goater
  0 siblings, 0 replies; 54+ messages in thread
From: Cédric Le Goater @ 2019-10-09 15:56 UTC (permalink / raw)
  To: Greg Kurz, David Gibson
  Cc: Jason Wang, Riku Voipio, Laurent Vivier, qemu-devel, qemu-ppc,
	Paolo Bonzini, Marc-André Lureau, philmd

On 09/10/2019 16:25, Greg Kurz wrote:
> On Wed,  9 Oct 2019 17:08:12 +1100
> David Gibson <david@gibson.dropbear.id.au> wrote:
> 
>> 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 <david@gibson.dropbear.id.au>
>> ---
>>  hw/intc/spapr_xive.c       | 38 +++++++++++++++++++++
>>  hw/intc/xics_spapr.c       | 17 ++++++++++
>>  hw/ppc/spapr_irq.c         | 67 ++------------------------------------
>>  include/hw/ppc/spapr_irq.h |  4 ++-
>>  4 files changed, 61 insertions(+), 65 deletions(-)
>>
>> diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
>> index 37ffb74ca5..1811653aac 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;
>> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
>> index 4eabafc7e1..90b4d48877 100644
>> --- a/hw/intc/xics_spapr.c
>> +++ b/hw/intc/xics_spapr.c
>> @@ -395,6 +395,21 @@ static void xics_spapr_print_info(SpaprInterruptController *intc, Monitor *mon)
>>      ics_pic_print_info(ics, mon);
>>  }
>>  
>> +static int xics_spapr_activate(SpaprInterruptController *intc, Error **errp)
>> +{
>> +    if (kvm_enabled()) {
>> +        return spapr_irq_init_kvm(xics_kvm_connect, intc, errp);
>> +    }
>> +    return 0;
>> +}
>> +
>> +static void xics_spapr_deactivate(SpaprInterruptController *intc)
>> +{
>> +    if (kvm_irqchip_in_kernel()) {
>> +        xics_kvm_disconnect(intc);
>> +    }
>> +}
>> +
>>  static void ics_spapr_class_init(ObjectClass *klass, void *data)
>>  {
>>      DeviceClass *dc = DEVICE_CLASS(klass);
>> @@ -403,6 +418,8 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
>>  
>>      device_class_set_parent_realize(dc, ics_spapr_realize,
>>                                      &isc->parent_realize);
>> +    sicc->activate = xics_spapr_activate;
>> +    sicc->deactivate = xics_spapr_deactivate;
>>      sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
>>      sicc->claim_irq = xics_spapr_claim_irq;
>>      sicc->free_irq = xics_spapr_free_irq;
>> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
>> index 7cd18e5b15..f70b331f44 100644
>> --- a/hw/ppc/spapr_irq.c
>> +++ b/hw/ppc/spapr_irq.c
>> @@ -65,9 +65,9 @@ void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num)
>>      bitmap_clear(spapr->irq_map, irq - SPAPR_IRQ_MSI, num);
>>  }
>>  
>> -static int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
>> -                              SpaprInterruptController *intc,
>> -                              Error **errp)
>> +int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
>> +                       SpaprInterruptController *intc,
>> +                       Error **errp)
>>  {
>>      MachineState *machine = MACHINE(qdev_get_machine());
>>      Error *local_err = NULL;
>> @@ -112,11 +112,6 @@ static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
>>      return 0;
>>  }
>>  
>> -static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp)
>> -{
>> -    spapr_irq_init_kvm(xics_kvm_connect, SPAPR_INTC(spapr->ics), errp);
>> -}
>> -
>>  SpaprIrq spapr_irq_xics = {
>>      .nr_xirqs    = SPAPR_NR_XIRQS,
>>      .nr_msis     = SPAPR_NR_MSIS,
>> @@ -124,7 +119,6 @@ SpaprIrq spapr_irq_xics = {
>>      .xive        = false,
>>  
>>      .post_load   = spapr_irq_post_load_xics,
>> -    .reset       = spapr_irq_reset_xics,
>>  };
>>  
>>  /*
>> @@ -136,26 +130,6 @@ static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
>>      return spapr_xive_post_load(spapr->xive, version_id);
>>  }
>>  
>> -static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp)
>> -{
>> -    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 (spapr_irq_init_kvm(kvmppc_xive_connect,
>> -                           SPAPR_INTC(spapr->xive), errp) < 0) {
>> -        return;
>> -    }
>> -
>> -    /* Activate the XIVE MMIOs */
>> -    spapr_xive_mmio_set_enabled(spapr->xive, true);
>> -}
>> -
>>  SpaprIrq spapr_irq_xive = {
>>      .nr_xirqs    = SPAPR_NR_XIRQS,
>>      .nr_msis     = SPAPR_NR_MSIS,
>> @@ -163,7 +137,6 @@ SpaprIrq spapr_irq_xive = {
>>      .xive        = true,
>>  
>>      .post_load   = spapr_irq_post_load_xive,
>> -    .reset       = spapr_irq_reset_xive,
>>  };
>>  
>>  /*
>> @@ -187,37 +160,9 @@ static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr)
>>  
>>  static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
>>  {
>> -    /*
>> -     * Force a reset of the XIVE backend after migration. The machine
>> -     * defaults to XICS at startup.
>> -     */
>> -    if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
>> -        if (kvm_irqchip_in_kernel()) {
>> -            xics_kvm_disconnect(SPAPR_INTC(spapr->ics));
>> -        }
>> -        spapr_irq_xive.reset(spapr, &error_fatal);
>> -    }
>> -
>>      return spapr_irq_current(spapr)->post_load(spapr, version_id);
>>  }
>>  
>> -static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp)
>> -{
>> -    /*
>> -     * Deactivate the XIVE MMIOs. The XIVE backend will reenable them
>> -     * if selected.
>> -     */
>> -    spapr_xive_mmio_set_enabled(spapr->xive, false);
>> -
>> -    /* Destroy all KVM devices */
>> -    if (kvm_irqchip_in_kernel()) {
>> -        xics_kvm_disconnect(SPAPR_INTC(spapr->ics));
>> -        kvmppc_xive_disconnect(SPAPR_INTC(spapr->xive));
> 
> With this going away, we don't need to check the KVM device fd is valid in
> xics_kvm_disconnect() and spapr_xive_disconnect() anymore. Cool !

Yes. That was ugly-hacky. 

C. 

> 
> Reviewed-by: Greg Kurz <groug@kaod.org>
> 
>> -    }
>> -
>> -    spapr_irq_current(spapr)->reset(spapr, errp);
>> -}
>> -
>>  /*
>>   * Define values in sync with the XIVE and XICS backend
>>   */
>> @@ -228,7 +173,6 @@ SpaprIrq spapr_irq_dual = {
>>      .xive        = true,
>>  
>>      .post_load   = spapr_irq_post_load_dual,
>> -    .reset       = spapr_irq_reset_dual,
>>  };
>>  
>>  
>> @@ -512,10 +456,6 @@ void spapr_irq_reset(SpaprMachineState *spapr, Error **errp)
>>      assert(!spapr->irq_map || bitmap_empty(spapr->irq_map, spapr->irq_map_nr));
>>  
>>      spapr_irq_update_active_intc(spapr);
>> -
>> -    if (spapr->irq->reset) {
>> -        spapr->irq->reset(spapr, errp);
>> -    }
>>  }
>>  
>>  int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp)
>> @@ -651,7 +591,6 @@ SpaprIrq spapr_irq_xics_legacy = {
>>      .xive        = false,
>>  
>>      .post_load   = spapr_irq_post_load_xics,
>> -    .reset       = spapr_irq_reset_xics,
>>  };
>>  
>>  static void spapr_irq_register_types(void)
>> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
>> index 06179b271f..e02e44624b 100644
>> --- a/include/hw/ppc/spapr_irq.h
>> +++ b/include/hw/ppc/spapr_irq.h
>> @@ -84,7 +84,6 @@ typedef struct SpaprIrq {
>>      bool        xive;
>>  
>>      int (*post_load)(SpaprMachineState *spapr, int version_id);
>> -    void (*reset)(SpaprMachineState *spapr, Error **errp);
>>  } SpaprIrq;
>>  
>>  extern SpaprIrq spapr_irq_xics;
>> @@ -99,6 +98,9 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq);
>>  int spapr_irq_post_load(SpaprMachineState *spapr, int version_id);
>>  void spapr_irq_reset(SpaprMachineState *spapr, Error **errp);
>>  int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp);
>> +int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
>> +                       SpaprInterruptController *intc,
>> +                       Error **errp);
>>  
>>  /*
>>   * XICS legacy routines
> 



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 13/19] spapr, xics, xive: Move SpaprIrq::reset hook logic into activate/deactivate
  2019-10-09  6:08 ` [PATCH v4 13/19] spapr, xics, xive: Move SpaprIrq::reset hook logic into activate/deactivate David Gibson
  2019-10-09 14:25   ` Greg Kurz
@ 2019-10-09 15:56   ` Cédric Le Goater
  1 sibling, 0 replies; 54+ messages in thread
From: Cédric Le Goater @ 2019-10-09 15:56 UTC (permalink / raw)
  To: David Gibson, qemu-devel, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd

On 09/10/2019 08:08, David Gibson wrote:
> 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 <david@gibson.dropbear.id.au>
> ---
>  hw/intc/spapr_xive.c       | 38 +++++++++++++++++++++
>  hw/intc/xics_spapr.c       | 17 ++++++++++
>  hw/ppc/spapr_irq.c         | 67 ++------------------------------------
>  include/hw/ppc/spapr_irq.h |  4 ++-
>  4 files changed, 61 insertions(+), 65 deletions(-)
> 
> diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
> index 37ffb74ca5..1811653aac 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);
> +    }


Greg, we will have to rework that loop also.


Reviewed-by: Cédric Le Goater <clg@kaod.org>

C.

> +
> +    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;
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> index 4eabafc7e1..90b4d48877 100644
> --- a/hw/intc/xics_spapr.c
> +++ b/hw/intc/xics_spapr.c
> @@ -395,6 +395,21 @@ static void xics_spapr_print_info(SpaprInterruptController *intc, Monitor *mon)
>      ics_pic_print_info(ics, mon);
>  }
>  
> +static int xics_spapr_activate(SpaprInterruptController *intc, Error **errp)
> +{
> +    if (kvm_enabled()) {
> +        return spapr_irq_init_kvm(xics_kvm_connect, intc, errp);
> +    }
> +    return 0;
> +}
> +
> +static void xics_spapr_deactivate(SpaprInterruptController *intc)
> +{
> +    if (kvm_irqchip_in_kernel()) {
> +        xics_kvm_disconnect(intc);
> +    }
> +}
> +
>  static void ics_spapr_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> @@ -403,6 +418,8 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
>  
>      device_class_set_parent_realize(dc, ics_spapr_realize,
>                                      &isc->parent_realize);
> +    sicc->activate = xics_spapr_activate;
> +    sicc->deactivate = xics_spapr_deactivate;
>      sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
>      sicc->claim_irq = xics_spapr_claim_irq;
>      sicc->free_irq = xics_spapr_free_irq;
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index 7cd18e5b15..f70b331f44 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -65,9 +65,9 @@ void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num)
>      bitmap_clear(spapr->irq_map, irq - SPAPR_IRQ_MSI, num);
>  }
>  
> -static int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
> -                              SpaprInterruptController *intc,
> -                              Error **errp)
> +int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
> +                       SpaprInterruptController *intc,
> +                       Error **errp)
>  {
>      MachineState *machine = MACHINE(qdev_get_machine());
>      Error *local_err = NULL;
> @@ -112,11 +112,6 @@ static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
>      return 0;
>  }
>  
> -static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp)
> -{
> -    spapr_irq_init_kvm(xics_kvm_connect, SPAPR_INTC(spapr->ics), errp);
> -}
> -
>  SpaprIrq spapr_irq_xics = {
>      .nr_xirqs    = SPAPR_NR_XIRQS,
>      .nr_msis     = SPAPR_NR_MSIS,
> @@ -124,7 +119,6 @@ SpaprIrq spapr_irq_xics = {
>      .xive        = false,
>  
>      .post_load   = spapr_irq_post_load_xics,
> -    .reset       = spapr_irq_reset_xics,
>  };
>  
>  /*
> @@ -136,26 +130,6 @@ static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
>      return spapr_xive_post_load(spapr->xive, version_id);
>  }
>  
> -static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp)
> -{
> -    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 (spapr_irq_init_kvm(kvmppc_xive_connect,
> -                           SPAPR_INTC(spapr->xive), errp) < 0) {
> -        return;
> -    }
> -
> -    /* Activate the XIVE MMIOs */
> -    spapr_xive_mmio_set_enabled(spapr->xive, true);
> -}
> -
>  SpaprIrq spapr_irq_xive = {
>      .nr_xirqs    = SPAPR_NR_XIRQS,
>      .nr_msis     = SPAPR_NR_MSIS,
> @@ -163,7 +137,6 @@ SpaprIrq spapr_irq_xive = {
>      .xive        = true,
>  
>      .post_load   = spapr_irq_post_load_xive,
> -    .reset       = spapr_irq_reset_xive,
>  };
>  
>  /*
> @@ -187,37 +160,9 @@ static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr)
>  
>  static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
>  {
> -    /*
> -     * Force a reset of the XIVE backend after migration. The machine
> -     * defaults to XICS at startup.
> -     */
> -    if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
> -        if (kvm_irqchip_in_kernel()) {
> -            xics_kvm_disconnect(SPAPR_INTC(spapr->ics));
> -        }
> -        spapr_irq_xive.reset(spapr, &error_fatal);
> -    }
> -
>      return spapr_irq_current(spapr)->post_load(spapr, version_id);
>  }
>  
> -static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp)
> -{
> -    /*
> -     * Deactivate the XIVE MMIOs. The XIVE backend will reenable them
> -     * if selected.
> -     */
> -    spapr_xive_mmio_set_enabled(spapr->xive, false);
> -
> -    /* Destroy all KVM devices */
> -    if (kvm_irqchip_in_kernel()) {
> -        xics_kvm_disconnect(SPAPR_INTC(spapr->ics));
> -        kvmppc_xive_disconnect(SPAPR_INTC(spapr->xive));
> -    }
> -
> -    spapr_irq_current(spapr)->reset(spapr, errp);
> -}
> -
>  /*
>   * Define values in sync with the XIVE and XICS backend
>   */
> @@ -228,7 +173,6 @@ SpaprIrq spapr_irq_dual = {
>      .xive        = true,
>  
>      .post_load   = spapr_irq_post_load_dual,
> -    .reset       = spapr_irq_reset_dual,
>  };
>  
>  
> @@ -512,10 +456,6 @@ void spapr_irq_reset(SpaprMachineState *spapr, Error **errp)
>      assert(!spapr->irq_map || bitmap_empty(spapr->irq_map, spapr->irq_map_nr));
>  
>      spapr_irq_update_active_intc(spapr);
> -
> -    if (spapr->irq->reset) {
> -        spapr->irq->reset(spapr, errp);
> -    }
>  }
>  
>  int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp)
> @@ -651,7 +591,6 @@ SpaprIrq spapr_irq_xics_legacy = {
>      .xive        = false,
>  
>      .post_load   = spapr_irq_post_load_xics,
> -    .reset       = spapr_irq_reset_xics,
>  };
>  
>  static void spapr_irq_register_types(void)
> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> index 06179b271f..e02e44624b 100644
> --- a/include/hw/ppc/spapr_irq.h
> +++ b/include/hw/ppc/spapr_irq.h
> @@ -84,7 +84,6 @@ typedef struct SpaprIrq {
>      bool        xive;
>  
>      int (*post_load)(SpaprMachineState *spapr, int version_id);
> -    void (*reset)(SpaprMachineState *spapr, Error **errp);
>  } SpaprIrq;
>  
>  extern SpaprIrq spapr_irq_xics;
> @@ -99,6 +98,9 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq);
>  int spapr_irq_post_load(SpaprMachineState *spapr, int version_id);
>  void spapr_irq_reset(SpaprMachineState *spapr, Error **errp);
>  int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp);
> +int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
> +                       SpaprInterruptController *intc,
> +                       Error **errp);
>  
>  /*
>   * XICS legacy routines
> 



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 14/19] spapr, xics, xive: Move SpaprIrq::post_load hook to backends
  2019-10-09  6:08 ` [PATCH v4 14/19] spapr, xics, xive: Move SpaprIrq::post_load hook to backends David Gibson
@ 2019-10-09 15:57   ` Cédric Le Goater
  0 siblings, 0 replies; 54+ messages in thread
From: Cédric Le Goater @ 2019-10-09 15:57 UTC (permalink / raw)
  To: David Gibson, qemu-devel, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd

On 09/10/2019 08:08, David Gibson wrote:
> 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 <david@gibson.dropbear.id.au>
> Reviewed-by: Greg Kurz <groug@kaod.org>


Reviewed-by: Cédric Le Goater <clg@kaod.org>

> ---
>  hw/intc/spapr_xive.c        |  5 +++--
>  hw/intc/xics_spapr.c        | 13 +++++++++++
>  hw/ppc/spapr_irq.c          | 45 ++++---------------------------------
>  include/hw/ppc/spapr_irq.h  |  3 +--
>  include/hw/ppc/spapr_xive.h |  1 -
>  5 files changed, 21 insertions(+), 46 deletions(-)
> 
> diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
> index 1811653aac..ba32d2cc5b 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 = {
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> index 90b4d48877..4f64b9a9fc 100644
> --- a/hw/intc/xics_spapr.c
> +++ b/hw/intc/xics_spapr.c
> @@ -395,6 +395,18 @@ static void xics_spapr_print_info(SpaprInterruptController *intc, Monitor *mon)
>      ics_pic_print_info(ics, mon);
>  }
>  
> +static int xics_spapr_post_load(SpaprInterruptController *intc, int version_id)
> +{
> +    if (!kvm_irqchip_in_kernel()) {
> +        CPUState *cs;
> +        CPU_FOREACH(cs) {
> +            PowerPCCPU *cpu = POWERPC_CPU(cs);
> +            icp_resend(spapr_cpu_state(cpu)->icp);
> +        }
> +    }
> +    return 0;
> +}
> +
>  static int xics_spapr_activate(SpaprInterruptController *intc, Error **errp)
>  {
>      if (kvm_enabled()) {
> @@ -426,6 +438,7 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
>      sicc->set_irq = xics_spapr_set_irq;
>      sicc->print_info = xics_spapr_print_info;
>      sicc->dt = xics_spapr_dt;
> +    sicc->post_load = xics_spapr_post_load;
>  }
>  
>  static const TypeInfo ics_spapr_info = {
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index f70b331f44..f3d18b1dad 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -100,43 +100,22 @@ int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
>   * XICS IRQ backend.
>   */
>  
> -static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
> -{
> -    if (!kvm_irqchip_in_kernel()) {
> -        CPUState *cs;
> -        CPU_FOREACH(cs) {
> -            PowerPCCPU *cpu = POWERPC_CPU(cs);
> -            icp_resend(spapr_cpu_state(cpu)->icp);
> -        }
> -    }
> -    return 0;
> -}
> -
>  SpaprIrq spapr_irq_xics = {
>      .nr_xirqs    = SPAPR_NR_XIRQS,
>      .nr_msis     = SPAPR_NR_MSIS,
>      .xics        = true,
>      .xive        = false,
> -
> -    .post_load   = spapr_irq_post_load_xics,
>  };
>  
>  /*
>   * XIVE IRQ backend.
>   */
>  
> -static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
> -{
> -    return spapr_xive_post_load(spapr->xive, version_id);
> -}
> -
>  SpaprIrq spapr_irq_xive = {
>      .nr_xirqs    = SPAPR_NR_XIRQS,
>      .nr_msis     = SPAPR_NR_MSIS,
>      .xics        = false,
>      .xive        = true,
> -
> -    .post_load   = spapr_irq_post_load_xive,
>  };
>  
>  /*
> @@ -148,21 +127,6 @@ SpaprIrq spapr_irq_xive = {
>   * activated after an extra machine reset.
>   */
>  
> -/*
> - * Returns the sPAPR IRQ backend negotiated by CAS. XICS is the
> - * default.
> - */
> -static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr)
> -{
> -    return spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT) ?
> -        &spapr_irq_xive : &spapr_irq_xics;
> -}
> -
> -static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
> -{
> -    return spapr_irq_current(spapr)->post_load(spapr, version_id);
> -}
> -
>  /*
>   * Define values in sync with the XIVE and XICS backend
>   */
> @@ -171,8 +135,6 @@ SpaprIrq spapr_irq_dual = {
>      .nr_msis     = SPAPR_NR_MSIS,
>      .xics        = true,
>      .xive        = true,
> -
> -    .post_load   = spapr_irq_post_load_dual,
>  };
>  
>  
> @@ -447,8 +409,11 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
>  
>  int spapr_irq_post_load(SpaprMachineState *spapr, int version_id)
>  {
> +    SpaprInterruptControllerClass *sicc;
> +
>      spapr_irq_update_active_intc(spapr);
> -    return spapr->irq->post_load(spapr, version_id);
> +    sicc = SPAPR_INTC_GET_CLASS(spapr->active_intc);
> +    return sicc->post_load(spapr->active_intc, version_id);
>  }
>  
>  void spapr_irq_reset(SpaprMachineState *spapr, Error **errp)
> @@ -589,8 +554,6 @@ SpaprIrq spapr_irq_xics_legacy = {
>      .nr_msis     = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS,
>      .xics        = true,
>      .xive        = false,
> -
> -    .post_load   = spapr_irq_post_load_xics,
>  };
>  
>  static void spapr_irq_register_types(void)
> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> index e02e44624b..08173e714c 100644
> --- a/include/hw/ppc/spapr_irq.h
> +++ b/include/hw/ppc/spapr_irq.h
> @@ -62,6 +62,7 @@ typedef struct SpaprInterruptControllerClass {
>      void (*print_info)(SpaprInterruptController *intc, Monitor *mon);
>      void (*dt)(SpaprInterruptController *intc, uint32_t nr_servers,
>                 void *fdt, uint32_t phandle);
> +    int (*post_load)(SpaprInterruptController *intc, int version_id);
>  } SpaprInterruptControllerClass;
>  
>  void spapr_irq_update_active_intc(SpaprMachineState *spapr);
> @@ -82,8 +83,6 @@ typedef struct SpaprIrq {
>      uint32_t    nr_msis;
>      bool        xics;
>      bool        xive;
> -
> -    int (*post_load)(SpaprMachineState *spapr, int version_id);
>  } SpaprIrq;
>  
>  extern SpaprIrq spapr_irq_xics;
> diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
> index 64972754f9..d84bd5c229 100644
> --- a/include/hw/ppc/spapr_xive.h
> +++ b/include/hw/ppc/spapr_xive.h
> @@ -55,7 +55,6 @@ typedef struct SpaprXive {
>  #define SPAPR_XIVE_BLOCK_ID 0x0
>  
>  void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon);
> -int spapr_xive_post_load(SpaprXive *xive, int version_id);
>  
>  void spapr_xive_hcall_init(SpaprMachineState *spapr);
>  void spapr_xive_set_tctx_os_cam(XiveTCTX *tctx);
> 



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 15/19] spapr: Remove SpaprIrq::nr_msis
  2019-10-09  6:08 ` [PATCH v4 15/19] spapr: Remove SpaprIrq::nr_msis David Gibson
@ 2019-10-09 15:59   ` Cédric Le Goater
  2019-10-10  1:56     ` David Gibson
  0 siblings, 1 reply; 54+ messages in thread
From: Cédric Le Goater @ 2019-10-09 15:59 UTC (permalink / raw)
  To: David Gibson, qemu-devel, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd

On 09/10/2019 08:08, David Gibson wrote:
> The nr_msis value we use here has to line up with whether we're using
> legacy or modern irq allocation.  Therefore it's safer to derive it based
> on legacy_irq_allocation rather than having SpaprIrq contain a canned
> value.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> Reviewed-by: Greg Kurz <groug@kaod.org>


Reviewed-by: Cédric Le Goater <clg@kaod.org>

one minor typo below,

> ---
>  hw/ppc/spapr.c              |  5 ++---
>  hw/ppc/spapr_irq.c          | 26 +++++++++++++++++---------
>  hw/ppc/spapr_pci.c          |  7 ++++---
>  include/hw/pci-host/spapr.h |  4 ++--
>  include/hw/ppc/spapr_irq.h  |  4 +---
>  5 files changed, 26 insertions(+), 20 deletions(-)
> 
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index e880db5d38..153cc54354 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -1275,7 +1275,7 @@ static void *spapr_build_fdt(SpaprMachineState *spapr)
>      }
>  
>      QLIST_FOREACH(phb, &spapr->phbs, list) {
> -        ret = spapr_dt_phb(phb, PHANDLE_INTC, fdt, spapr->irq->nr_msis, NULL);
> +        ret = spapr_dt_phb(spapr, phb, PHANDLE_INTC, fdt, NULL);
>          if (ret < 0) {
>              error_report("couldn't setup PCI devices in fdt");
>              exit(1);
> @@ -3910,8 +3910,7 @@ int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
>          return -1;
>      }
>  
> -    if (spapr_dt_phb(sphb, intc_phandle, fdt, spapr->irq->nr_msis,
> -                     fdt_start_offset)) {
> +    if (spapr_dt_phb(spapr, sphb, intc_phandle, fdt, fdt_start_offset)) {
>          error_setg(errp, "unable to create FDT node for PHB %d", sphb->index);
>          return -1;
>      }
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index f3d18b1dad..076da31501 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -29,9 +29,14 @@ static const TypeInfo spapr_intc_info = {
>      .class_size = sizeof(SpaprInterruptControllerClass),
>  };
>  
> -void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis)
> +static void spapr_irq_msi_init(SpaprMachineState *spapr)
>  {
> -    spapr->irq_map_nr = nr_msis;
> +    if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
> +        /* Legacy mode doesn't use this allocater */

allocater -> allocator

> +        return;
> +    }
> +
> +    spapr->irq_map_nr = spapr_irq_nr_msis(spapr);
>      spapr->irq_map = bitmap_new(spapr->irq_map_nr);
>  }
>  
> @@ -102,7 +107,6 @@ int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
>  
>  SpaprIrq spapr_irq_xics = {
>      .nr_xirqs    = SPAPR_NR_XIRQS,
> -    .nr_msis     = SPAPR_NR_MSIS,
>      .xics        = true,
>      .xive        = false,
>  };
> @@ -113,7 +117,6 @@ SpaprIrq spapr_irq_xics = {
>  
>  SpaprIrq spapr_irq_xive = {
>      .nr_xirqs    = SPAPR_NR_XIRQS,
> -    .nr_msis     = SPAPR_NR_MSIS,
>      .xics        = false,
>      .xive        = true,
>  };
> @@ -132,7 +135,6 @@ SpaprIrq spapr_irq_xive = {
>   */
>  SpaprIrq spapr_irq_dual = {
>      .nr_xirqs    = SPAPR_NR_XIRQS,
> -    .nr_msis     = SPAPR_NR_MSIS,
>      .xics        = true,
>      .xive        = true,
>  };
> @@ -247,6 +249,15 @@ void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
>      sicc->dt(spapr->active_intc, nr_servers, fdt, phandle);
>  }
>  
> +uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr)
> +{
> +    if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
> +        return spapr->irq->nr_xirqs;
> +    } else {
> +        return SPAPR_XIRQ_BASE + spapr->irq->nr_xirqs - SPAPR_IRQ_MSI;
> +    }
> +}
> +
>  void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>  {
>      MachineState *machine = MACHINE(spapr);
> @@ -267,9 +278,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>      }
>  
>      /* Initialize the MSI IRQ allocator. */
> -    if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
> -        spapr_irq_msi_init(spapr, spapr->irq->nr_msis);
> -    }
> +    spapr_irq_msi_init(spapr);
>  
>      if (spapr->irq->xics) {
>          Error *local_err = NULL;
> @@ -551,7 +560,6 @@ int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
>  
>  SpaprIrq spapr_irq_xics_legacy = {
>      .nr_xirqs    = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS,
> -    .nr_msis     = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS,
>      .xics        = true,
>      .xive        = false,
>  };
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index 01ff41d4c4..cc0e7829b6 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -2277,8 +2277,8 @@ static void spapr_phb_pci_enumerate(SpaprPhbState *phb)
>  
>  }
>  
> -int spapr_dt_phb(SpaprPhbState *phb, uint32_t intc_phandle, void *fdt,
> -                 uint32_t nr_msis, int *node_offset)
> +int spapr_dt_phb(SpaprMachineState *spapr, SpaprPhbState *phb,
> +                 uint32_t intc_phandle, void *fdt, int *node_offset)
>  {
>      int bus_off, i, j, ret;
>      uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) };
> @@ -2343,7 +2343,8 @@ int spapr_dt_phb(SpaprPhbState *phb, uint32_t intc_phandle, void *fdt,
>      _FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof_ranges));
>      _FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg)));
>      _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pci-config-space-type", 0x1));
> -    _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi", nr_msis));
> +    _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi",
> +                          spapr_irq_nr_msis(spapr)));
>  
>      /* Dynamic DMA window */
>      if (phb->ddw_enabled) {
> diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
> index 23506f05d9..8877ff51fb 100644
> --- a/include/hw/pci-host/spapr.h
> +++ b/include/hw/pci-host/spapr.h
> @@ -128,8 +128,8 @@ struct SpaprPhbState {
>  #define SPAPR_PCI_NV2ATSD_WIN_SIZE   (NVGPU_MAX_NUM * NVGPU_MAX_LINKS * \
>                                        64 * KiB)
>  
> -int spapr_dt_phb(SpaprPhbState *phb, uint32_t intc_phandle, void *fdt,
> -                 uint32_t nr_msis, int *node_offset);
> +int spapr_dt_phb(SpaprMachineState *spapr, SpaprPhbState *phb,
> +                 uint32_t intc_phandle, void *fdt, int *node_offset);
>  
>  void spapr_pci_rtas_init(void);
>  
> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> index 08173e714c..befe8e01dc 100644
> --- a/include/hw/ppc/spapr_irq.h
> +++ b/include/hw/ppc/spapr_irq.h
> @@ -27,7 +27,6 @@
>  #define SPAPR_IRQ_MSI        (SPAPR_XIRQ_BASE + 0x0300)
>  
>  #define SPAPR_NR_XIRQS       0x1000
> -#define SPAPR_NR_MSIS        (SPAPR_XIRQ_BASE + SPAPR_NR_XIRQS - SPAPR_IRQ_MSI)
>  
>  typedef struct SpaprMachineState SpaprMachineState;
>  
> @@ -73,14 +72,13 @@ void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon);
>  void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
>                    void *fdt, uint32_t phandle);
>  
> -void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
> +uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr);
>  int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
>                          Error **errp);
>  void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num);
>  
>  typedef struct SpaprIrq {
>      uint32_t    nr_xirqs;
> -    uint32_t    nr_msis;
>      bool        xics;
>      bool        xive;
>  } SpaprIrq;
> 



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 16/19] spapr: Move SpaprIrq::nr_xirqs to SpaprMachineClass
  2019-10-09  6:08 ` [PATCH v4 16/19] spapr: Move SpaprIrq::nr_xirqs to SpaprMachineClass David Gibson
@ 2019-10-09 16:01   ` Cédric Le Goater
  0 siblings, 0 replies; 54+ messages in thread
From: Cédric Le Goater @ 2019-10-09 16:01 UTC (permalink / raw)
  To: David Gibson, qemu-devel, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd

On 09/10/2019 08:08, David Gibson wrote:
> For the benefit of peripheral device allocation, the number of available
> irqs really wants to be the same on a given machine type version,
> regardless of what irq backends we are using.  That's the case now, but
> only because we make sure the different SpaprIrq instances have the same
> value except for the special legacy one.
> 
> Since this really only depends on machine type version, move the value to
> SpaprMachineClass instead of SpaprIrq.  This also puts the code to set it
> to the lower value on old machine types right next to setting
> legacy_irq_allocation, which needs to go hand in hand.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> Reviewed-by: Greg Kurz <groug@kaod.org>


Reviewed-by: Cédric Le Goater <clg@kaod.org>

> ---
>  hw/ppc/spapr.c             |  2 ++
>  hw/ppc/spapr_irq.c         | 33 ++++++++++++++++-----------------
>  include/hw/ppc/spapr.h     |  1 +
>  include/hw/ppc/spapr_irq.h |  1 -
>  4 files changed, 19 insertions(+), 18 deletions(-)
> 
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 153cc54354..e1ff03152e 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -4443,6 +4443,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
>      smc->irq = &spapr_irq_dual;
>      smc->dr_phb_enabled = true;
>      smc->linux_pci_probe = true;
> +    smc->nr_xirqs = SPAPR_NR_XIRQS;
>  }
>  
>  static const TypeInfo spapr_machine_info = {
> @@ -4578,6 +4579,7 @@ static void spapr_machine_3_0_class_options(MachineClass *mc)
>      compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len);
>  
>      smc->legacy_irq_allocation = true;
> +    smc->nr_xirqs = 0x400;
>      smc->irq = &spapr_irq_xics_legacy;

yes. this is clearly better to this constant at the machine level.

c. 


>  }
>  
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index 076da31501..2768f9a765 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -106,7 +106,6 @@ int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
>   */
>  
>  SpaprIrq spapr_irq_xics = {
> -    .nr_xirqs    = SPAPR_NR_XIRQS,
>      .xics        = true,
>      .xive        = false,
>  };
> @@ -116,7 +115,6 @@ SpaprIrq spapr_irq_xics = {
>   */
>  
>  SpaprIrq spapr_irq_xive = {
> -    .nr_xirqs    = SPAPR_NR_XIRQS,
>      .xics        = false,
>      .xive        = true,
>  };
> @@ -134,7 +132,6 @@ SpaprIrq spapr_irq_xive = {
>   * Define values in sync with the XIVE and XICS backend
>   */
>  SpaprIrq spapr_irq_dual = {
> -    .nr_xirqs    = SPAPR_NR_XIRQS,
>      .xics        = true,
>      .xive        = true,
>  };
> @@ -251,16 +248,19 @@ void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
>  
>  uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr)
>  {
> -    if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
> -        return spapr->irq->nr_xirqs;
> +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> +
> +    if (smc->legacy_irq_allocation) {
> +        return smc->nr_xirqs;
>      } else {
> -        return SPAPR_XIRQ_BASE + spapr->irq->nr_xirqs - SPAPR_IRQ_MSI;
> +        return SPAPR_XIRQ_BASE + smc->nr_xirqs - SPAPR_IRQ_MSI;
>      }
>  }
>  
>  void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>  {
>      MachineState *machine = MACHINE(spapr);
> +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
>  
>      if (machine_kernel_irqchip_split(machine)) {
>          error_setg(errp, "kernel_irqchip split mode not supported on pseries");
> @@ -298,8 +298,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>              return;
>          }
>  
> -        object_property_set_int(obj, spapr->irq->nr_xirqs, "nr-irqs",
> -                                &local_err);
> +        object_property_set_int(obj, smc->nr_xirqs, "nr-irqs", &local_err);
>          if (local_err) {
>              error_propagate(errp, local_err);
>              return;
> @@ -320,8 +319,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>          int i;
>  
>          dev = qdev_create(NULL, TYPE_SPAPR_XIVE);
> -        qdev_prop_set_uint32(dev, "nr-irqs",
> -                             spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE);
> +        qdev_prop_set_uint32(dev, "nr-irqs", smc->nr_xirqs + SPAPR_XIRQ_BASE);
>          /*
>           * 8 XIVE END structures per CPU. One for each available
>           * priority
> @@ -346,17 +344,18 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>      }
>  
>      spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr,
> -                                      spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE);
> +                                      smc->nr_xirqs + SPAPR_XIRQ_BASE);
>  }
>  
>  int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp)
>  {
>      SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
>      int i;
> +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
>      int rc;
>  
>      assert(irq >= SPAPR_XIRQ_BASE);
> -    assert(irq < (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE));
> +    assert(irq < (smc->nr_xirqs + SPAPR_XIRQ_BASE));
>  
>      for (i = 0; i < ARRAY_SIZE(intcs); i++) {
>          SpaprInterruptController *intc = intcs[i];
> @@ -376,9 +375,10 @@ void spapr_irq_free(SpaprMachineState *spapr, int irq, int num)
>  {
>      SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
>      int i, j;
> +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
>  
>      assert(irq >= SPAPR_XIRQ_BASE);
> -    assert((irq + num) <= (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE));
> +    assert((irq + num) <= (smc->nr_xirqs + SPAPR_XIRQ_BASE));
>  
>      for (i = irq; i < (irq + num); i++) {
>          for (j = 0; j < ARRAY_SIZE(intcs); j++) {
> @@ -395,6 +395,8 @@ void spapr_irq_free(SpaprMachineState *spapr, int irq, int num)
>  
>  qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
>  {
> +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> +
>      /*
>       * This interface is basically for VIO and PHB devices to find the
>       * right qemu_irq to manipulate, so we only allow access to the
> @@ -403,7 +405,7 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
>       * interfaces, we can change this if we need to in future.
>       */
>      assert(irq >= SPAPR_XIRQ_BASE);
> -    assert(irq < (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE));
> +    assert(irq < (smc->nr_xirqs + SPAPR_XIRQ_BASE));
>  
>      if (spapr->ics) {
>          assert(ics_valid_irq(spapr->ics, irq));
> @@ -556,10 +558,7 @@ int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
>      return first + ics->offset;
>  }
>  
> -#define SPAPR_IRQ_XICS_LEGACY_NR_XIRQS     0x400
> -
>  SpaprIrq spapr_irq_xics_legacy = {
> -    .nr_xirqs    = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS,
>      .xics        = true,
>      .xive        = false,
>  };
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index 763da757f0..623e8e3f93 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -119,6 +119,7 @@ struct SpaprMachineClass {
>      bool use_ohci_by_default;  /* use USB-OHCI instead of XHCI */
>      bool pre_2_10_has_unused_icps;
>      bool legacy_irq_allocation;
> +    uint32_t nr_xirqs;
>      bool broken_host_serial_model; /* present real host info to the guest */
>      bool pre_4_1_migration; /* don't migrate hpt-max-page-size */
>      bool linux_pci_probe;
> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> index befe8e01dc..5e150a6679 100644
> --- a/include/hw/ppc/spapr_irq.h
> +++ b/include/hw/ppc/spapr_irq.h
> @@ -78,7 +78,6 @@ int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
>  void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num);
>  
>  typedef struct SpaprIrq {
> -    uint32_t    nr_xirqs;
>      bool        xics;
>      bool        xive;
>  } SpaprIrq;
> 



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq
  2019-10-09  6:08 ` [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq David Gibson
@ 2019-10-09 16:44   ` Cédric Le Goater
  2019-10-10  1:59     ` David Gibson
  2019-10-09 17:02   ` Greg Kurz
  1 sibling, 1 reply; 54+ messages in thread
From: Cédric Le Goater @ 2019-10-09 16:44 UTC (permalink / raw)
  To: David Gibson, qemu-devel, qemu-ppc
  Cc: Jason Wang, Riku Voipio, groug, Laurent Vivier, Paolo Bonzini,
	Marc-André Lureau, philmd

On 09/10/2019 08:08, David Gibson wrote:
> The only thing remaining in this structure are the flags to allow either
> XICS or XIVE to be present.  These actually make more sense as spapr
> capabilities - that way they can take advantage of the existing
> infrastructure to sanity check capability states across migration and so
> forth.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

Nice. That is what you had in mind :) Let's make sure we use your
cap framework for the next major change, power10. ic-mode should
be deprecated one day I suppose.


Reviewed-by: Cédric Le Goater <clg@kaod.org>

C.


> ---
>  hw/ppc/spapr.c             | 40 ++++++++++--------
>  hw/ppc/spapr_caps.c        | 64 +++++++++++++++++++++++++++++
>  hw/ppc/spapr_hcall.c       |  7 ++--
>  hw/ppc/spapr_irq.c         | 84 ++------------------------------------
>  include/hw/ppc/spapr.h     | 10 +++--
>  include/hw/ppc/spapr_irq.h | 10 -----
>  6 files changed, 103 insertions(+), 112 deletions(-)
> 
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index e1ff03152e..bf9fdb1693 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -1072,12 +1072,13 @@ static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
>          26, 0x40, /* Radix options: GTSE == yes. */
>      };
>  
> -    if (spapr->irq->xics && spapr->irq->xive) {
> +    if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> +        && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>          val[1] = SPAPR_OV5_XIVE_BOTH;
> -    } else if (spapr->irq->xive) {
> +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>          val[1] = SPAPR_OV5_XIVE_EXPLOIT;
>      } else {
> -        assert(spapr->irq->xics);
> +        assert(spapr_get_cap(spapr, SPAPR_CAP_XICS));
>          val[1] = SPAPR_OV5_XIVE_LEGACY;
>      }
>  
> @@ -2075,6 +2076,8 @@ static const VMStateDescription vmstate_spapr = {
>          &vmstate_spapr_dtb,
>          &vmstate_spapr_cap_large_decr,
>          &vmstate_spapr_cap_ccf_assist,
> +        &vmstate_spapr_cap_xics,
> +        &vmstate_spapr_cap_xive,
>          NULL
>      }
>  };
> @@ -2775,7 +2778,7 @@ static void spapr_machine_init(MachineState *machine)
>      spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2);
>  
>      /* advertise XIVE on POWER9 machines */
> -    if (spapr->irq->xive) {
> +    if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>          spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
>      }
>  
> @@ -3242,14 +3245,18 @@ static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name,
>  static char *spapr_get_ic_mode(Object *obj, Error **errp)
>  {
>      SpaprMachineState *spapr = SPAPR_MACHINE(obj);
> +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
>  
> -    if (spapr->irq == &spapr_irq_xics_legacy) {
> +    if (smc->legacy_irq_allocation) {
>          return g_strdup("legacy");
> -    } else if (spapr->irq == &spapr_irq_xics) {
> +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> +               && !spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>          return g_strdup("xics");
> -    } else if (spapr->irq == &spapr_irq_xive) {
> +    } else if (!spapr_get_cap(spapr, SPAPR_CAP_XICS)
> +               && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>          return g_strdup("xive");
> -    } else if (spapr->irq == &spapr_irq_dual) {
> +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> +               && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>          return g_strdup("dual");
>      }
>      g_assert_not_reached();
> @@ -3266,11 +3273,14 @@ static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
>  
>      /* The legacy IRQ backend can not be set */
>      if (strcmp(value, "xics") == 0) {
> -        spapr->irq = &spapr_irq_xics;
> +        object_property_set_bool(obj, true, "cap-xics", errp);
> +        object_property_set_bool(obj, false, "cap-xive", errp);
>      } else if (strcmp(value, "xive") == 0) {
> -        spapr->irq = &spapr_irq_xive;
> +        object_property_set_bool(obj, false, "cap-xics", errp);
> +        object_property_set_bool(obj, true, "cap-xive", errp);
>      } else if (strcmp(value, "dual") == 0) {
> -        spapr->irq = &spapr_irq_dual;
> +        object_property_set_bool(obj, true, "cap-xics", errp);
> +        object_property_set_bool(obj, true, "cap-xive", errp);
>      } else {
>          error_setg(errp, "Bad value for \"ic-mode\" property");
>      }
> @@ -3309,7 +3319,6 @@ static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
>  static void spapr_instance_init(Object *obj)
>  {
>      SpaprMachineState *spapr = SPAPR_MACHINE(obj);
> -    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
>  
>      spapr->htab_fd = -1;
>      spapr->use_hotplug_event_source = true;
> @@ -3345,7 +3354,6 @@ static void spapr_instance_init(Object *obj)
>                               spapr_get_msix_emulation, NULL, NULL);
>  
>      /* The machine class defines the default interrupt controller mode */
> -    spapr->irq = smc->irq;
>      object_property_add_str(obj, "ic-mode", spapr_get_ic_mode,
>                              spapr_set_ic_mode, NULL);
>      object_property_set_description(obj, "ic-mode",
> @@ -4439,8 +4447,9 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
>      smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
>      smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
>      smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
> +    smc->default_caps.caps[SPAPR_CAP_XICS] = SPAPR_CAP_ON;
> +    smc->default_caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_ON;
>      spapr_caps_add_properties(smc, &error_abort);
> -    smc->irq = &spapr_irq_dual;
>      smc->dr_phb_enabled = true;
>      smc->linux_pci_probe = true;
>      smc->nr_xirqs = SPAPR_NR_XIRQS;
> @@ -4539,7 +4548,7 @@ static void spapr_machine_4_0_class_options(MachineClass *mc)
>      spapr_machine_4_1_class_options(mc);
>      compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
>      smc->phb_placement = phb_placement_4_0;
> -    smc->irq = &spapr_irq_xics;
> +    smc->default_caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_OFF;
>      smc->pre_4_1_migration = true;
>  }
>  
> @@ -4580,7 +4589,6 @@ static void spapr_machine_3_0_class_options(MachineClass *mc)
>  
>      smc->legacy_irq_allocation = true;
>      smc->nr_xirqs = 0x400;
> -    smc->irq = &spapr_irq_xics_legacy;
>  }
>  
>  DEFINE_SPAPR_MACHINE(3_0, "3.0", false);
> diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
> index 481dfd2a27..e06fd386f6 100644
> --- a/hw/ppc/spapr_caps.c
> +++ b/hw/ppc/spapr_caps.c
> @@ -496,6 +496,42 @@ static void cap_ccf_assist_apply(SpaprMachineState *spapr, uint8_t val,
>      }
>  }
>  
> +static void cap_xics_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
> +{
> +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> +
> +    if (!val) {
> +        if (!spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> +            error_setg(errp,
> +"No interrupt controllers enabled, try cap-xics=on or cap-xive=on");
> +            return;
> +        }
> +
> +        if (smc->legacy_irq_allocation) {
> +            error_setg(errp, "This machine version requires XICS support");
> +            return;
> +        }
> +    }
> +}
> +
> +static void cap_xive_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
> +{
> +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> +    PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
> +
> +    if (val) {
> +        if (smc->legacy_irq_allocation) {
> +            error_setg(errp, "This machine version cannot support XIVE");
> +            return;
> +        }
> +        if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0,
> +                              spapr->max_compat_pvr)) {
> +            error_setg(errp, "XIVE requires POWER9 CPU");
> +            return;
> +        }
> +    }
> +}
> +
>  SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
>      [SPAPR_CAP_HTM] = {
>          .name = "htm",
> @@ -595,6 +631,24 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
>          .type = "bool",
>          .apply = cap_ccf_assist_apply,
>      },
> +    [SPAPR_CAP_XICS] = {
> +        .name = "xics",
> +        .description = "Allow XICS interrupt controller",
> +        .index = SPAPR_CAP_XICS,
> +        .get = spapr_cap_get_bool,
> +        .set = spapr_cap_set_bool,
> +        .type = "bool",
> +        .apply = cap_xics_apply,
> +    },
> +    [SPAPR_CAP_XIVE] = {
> +        .name = "xive",
> +        .description = "Allow XIVE interrupt controller",
> +        .index = SPAPR_CAP_XIVE,
> +        .get = spapr_cap_get_bool,
> +        .set = spapr_cap_set_bool,
> +        .type = "bool",
> +        .apply = cap_xive_apply,
> +    },
>  };
>  
>  static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
> @@ -641,6 +695,14 @@ static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
>          caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = mps;
>      }
>  
> +    /*
> +     * POWER8 machines don't have XIVE
> +     */
> +    if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_3_00,
> +                               0, spapr->max_compat_pvr)) {
> +        caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_OFF;
> +    }
> +
>      return caps;
>  }
>  
> @@ -734,6 +796,8 @@ SPAPR_CAP_MIG_STATE(hpt_maxpagesize, SPAPR_CAP_HPT_MAXPAGESIZE);
>  SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
>  SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
>  SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
> +SPAPR_CAP_MIG_STATE(xics, SPAPR_CAP_XICS);
> +SPAPR_CAP_MIG_STATE(xive, SPAPR_CAP_XIVE);
>  
>  void spapr_caps_init(SpaprMachineState *spapr)
>  {
> diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> index 140f05c1c6..cb4c6edf63 100644
> --- a/hw/ppc/spapr_hcall.c
> +++ b/hw/ppc/spapr_hcall.c
> @@ -1784,13 +1784,13 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
>       * terminate the boot.
>       */
>      if (guest_xive) {
> -        if (!spapr->irq->xive) {
> +        if (!spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>              error_report(
>  "Guest requested unavailable interrupt mode (XIVE), try the ic-mode=xive or ic-mode=dual machine property");
>              exit(EXIT_FAILURE);
>          }
>      } else {
> -        if (!spapr->irq->xics) {
> +        if (!spapr_get_cap(spapr, SPAPR_CAP_XICS)) {
>              error_report(
>  "Guest requested unavailable interrupt mode (XICS), either don't set the ic-mode machine property or try ic-mode=xics or ic-mode=dual");
>              exit(EXIT_FAILURE);
> @@ -1804,7 +1804,8 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
>       */
>      if (!spapr->cas_reboot) {
>          spapr->cas_reboot = spapr_ovec_test(ov5_updates, OV5_XIVE_EXPLOIT)
> -            && spapr->irq->xics && spapr->irq->xive;
> +            && spapr_get_cap(spapr, SPAPR_CAP_XICS)
> +            && spapr_get_cap(spapr, SPAPR_CAP_XIVE);
>      }
>  
>      spapr_ovec_cleanup(ov5_updates);
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index 2768f9a765..473fc8780a 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -101,90 +101,19 @@ int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
>      return 0;
>  }
>  
> -/*
> - * XICS IRQ backend.
> - */
> -
> -SpaprIrq spapr_irq_xics = {
> -    .xics        = true,
> -    .xive        = false,
> -};
> -
> -/*
> - * XIVE IRQ backend.
> - */
> -
> -SpaprIrq spapr_irq_xive = {
> -    .xics        = false,
> -    .xive        = true,
> -};
> -
> -/*
> - * Dual XIVE and XICS IRQ backend.
> - *
> - * Both interrupt mode, XIVE and XICS, objects are created but the
> - * machine starts in legacy interrupt mode (XICS). It can be changed
> - * by the CAS negotiation process and, in that case, the new mode is
> - * activated after an extra machine reset.
> - */
> -
> -/*
> - * Define values in sync with the XIVE and XICS backend
> - */
> -SpaprIrq spapr_irq_dual = {
> -    .xics        = true,
> -    .xive        = true,
> -};
> -
> -
>  static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
>  {
>      MachineState *machine = MACHINE(spapr);
>  
> -    /*
> -     * Sanity checks on non-P9 machines. On these, XIVE is not
> -     * advertised, see spapr_dt_ov5_platform_support()
> -     */
> -    if (!ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00,
> -                               0, spapr->max_compat_pvr)) {
> -        /*
> -         * If the 'dual' interrupt mode is selected, force XICS as CAS
> -         * negotiation is useless.
> -         */
> -        if (spapr->irq == &spapr_irq_dual) {
> -            spapr->irq = &spapr_irq_xics;
> -            return 0;
> -        }
> -
> -        /*
> -         * Non-P9 machines using only XIVE is a bogus setup. We have two
> -         * scenarios to take into account because of the compat mode:
> -         *
> -         * 1. POWER7/8 machines should fail to init later on when creating
> -         *    the XIVE interrupt presenters because a POWER9 exception
> -         *    model is required.
> -
> -         * 2. POWER9 machines using the POWER8 compat mode won't fail and
> -         *    will let the OS boot with a partial XIVE setup : DT
> -         *    properties but no hcalls.
> -         *
> -         * To cover both and not confuse the OS, add an early failure in
> -         * QEMU.
> -         */
> -        if (spapr->irq == &spapr_irq_xive) {
> -            error_setg(errp, "XIVE-only machines require a POWER9 CPU");
> -            return -1;
> -        }
> -    }
> -
>      /*
>       * On a POWER9 host, some older KVM XICS devices cannot be destroyed and
>       * re-created. Detect that early to avoid QEMU to exit later when the
>       * guest reboots.
>       */
>      if (kvm_enabled() &&
> -        spapr->irq == &spapr_irq_dual &&
>          machine_kernel_irqchip_required(machine) &&
> +        spapr_get_cap(spapr, SPAPR_CAP_XICS) &&
> +        spapr_get_cap(spapr, SPAPR_CAP_XIVE) &&
>          xics_kvm_has_broken_disconnect(spapr)) {
>          error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on");
>          return -1;
> @@ -280,7 +209,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>      /* Initialize the MSI IRQ allocator. */
>      spapr_irq_msi_init(spapr);
>  
> -    if (spapr->irq->xics) {
> +    if (spapr_get_cap(spapr, SPAPR_CAP_XICS)) {
>          Error *local_err = NULL;
>          Object *obj;
>  
> @@ -313,7 +242,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>          spapr->ics = ICS_SPAPR(obj);
>      }
>  
> -    if (spapr->irq->xive) {
> +    if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>          uint32_t nr_servers = spapr_max_server_number(spapr);
>          DeviceState *dev;
>          int i;
> @@ -558,11 +487,6 @@ int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
>      return first + ics->offset;
>  }
>  
> -SpaprIrq spapr_irq_xics_legacy = {
> -    .xics        = true,
> -    .xive        = false,
> -};
> -
>  static void spapr_irq_register_types(void)
>  {
>      type_register_static(&spapr_intc_info);
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index 623e8e3f93..d3b4dd7de3 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -79,8 +79,12 @@ typedef enum {
>  #define SPAPR_CAP_LARGE_DECREMENTER     0x08
>  /* Count Cache Flush Assist HW Instruction */
>  #define SPAPR_CAP_CCF_ASSIST            0x09
> +/* XICS interrupt controller */
> +#define SPAPR_CAP_XICS                  0x0a
> +/* XIVE interrupt controller */
> +#define SPAPR_CAP_XIVE                  0x0b
>  /* Num Caps */
> -#define SPAPR_CAP_NUM                   (SPAPR_CAP_CCF_ASSIST + 1)
> +#define SPAPR_CAP_NUM                   (SPAPR_CAP_XIVE + 1)
>  
>  /*
>   * Capability Values
> @@ -131,7 +135,6 @@ struct SpaprMachineClass {
>                            hwaddr *nv2atsd, Error **errp);
>      SpaprResizeHpt resize_hpt_default;
>      SpaprCapabilities default_caps;
> -    SpaprIrq *irq;
>  };
>  
>  /**
> @@ -195,7 +198,6 @@ struct SpaprMachineState {
>  
>      int32_t irq_map_nr;
>      unsigned long *irq_map;
> -    SpaprIrq *irq;
>      qemu_irq *qirqs;
>      SpaprInterruptController *active_intc;
>      ICSState *ics;
> @@ -870,6 +872,8 @@ extern const VMStateDescription vmstate_spapr_cap_hpt_maxpagesize;
>  extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
>  extern const VMStateDescription vmstate_spapr_cap_large_decr;
>  extern const VMStateDescription vmstate_spapr_cap_ccf_assist;
> +extern const VMStateDescription vmstate_spapr_cap_xics;
> +extern const VMStateDescription vmstate_spapr_cap_xive;
>  
>  static inline uint8_t spapr_get_cap(SpaprMachineState *spapr, int cap)
>  {
> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> index 5e150a6679..71aee13743 100644
> --- a/include/hw/ppc/spapr_irq.h
> +++ b/include/hw/ppc/spapr_irq.h
> @@ -77,16 +77,6 @@ int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
>                          Error **errp);
>  void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num);
>  
> -typedef struct SpaprIrq {
> -    bool        xics;
> -    bool        xive;
> -} SpaprIrq;
> -
> -extern SpaprIrq spapr_irq_xics;
> -extern SpaprIrq spapr_irq_xics_legacy;
> -extern SpaprIrq spapr_irq_xive;
> -extern SpaprIrq spapr_irq_dual;
> -
>  void spapr_irq_init(SpaprMachineState *spapr, Error **errp);
>  int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp);
>  void spapr_irq_free(SpaprMachineState *spapr, int irq, int num);
> 



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq
  2019-10-09  6:08 ` [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq David Gibson
  2019-10-09 16:44   ` Cédric Le Goater
@ 2019-10-09 17:02   ` Greg Kurz
  2019-10-10  2:02     ` David Gibson
  1 sibling, 1 reply; 54+ messages in thread
From: Greg Kurz @ 2019-10-09 17:02 UTC (permalink / raw)
  To: David Gibson
  Cc: Jason Wang, Riku Voipio, qemu-devel, Laurent Vivier, qemu-ppc,
	clg, Paolo Bonzini, Marc-André Lureau, philmd

On Wed,  9 Oct 2019 17:08:16 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:

> The only thing remaining in this structure are the flags to allow either
> XICS or XIVE to be present.  These actually make more sense as spapr
> capabilities - that way they can take advantage of the existing
> infrastructure to sanity check capability states across migration and so
> forth.
> 

The user can now choose the interrupt controller mode either through
ic-mode or through cap-xics/cap-xive. I guess it doesn't break anything
to expose another API to do the same thing but it raises some questions.

We should at least document somewhere that ic-mode is an alias to these
caps, and maybe state which is the preferred method (I personally vote
for the caps).

Also, we must keep ic-mode for the moment to stay compatible with the
existing pseries-4.0 and pseries-4.1 machine types, but will we
keep ic-mode forever ? If no, maybe start by not allowing it for
pseries-4.2 ?

> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
>  hw/ppc/spapr.c             | 40 ++++++++++--------
>  hw/ppc/spapr_caps.c        | 64 +++++++++++++++++++++++++++++
>  hw/ppc/spapr_hcall.c       |  7 ++--
>  hw/ppc/spapr_irq.c         | 84 ++------------------------------------
>  include/hw/ppc/spapr.h     | 10 +++--
>  include/hw/ppc/spapr_irq.h | 10 -----
>  6 files changed, 103 insertions(+), 112 deletions(-)
> 
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index e1ff03152e..bf9fdb1693 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -1072,12 +1072,13 @@ static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
>          26, 0x40, /* Radix options: GTSE == yes. */
>      };
>  
> -    if (spapr->irq->xics && spapr->irq->xive) {
> +    if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> +        && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>          val[1] = SPAPR_OV5_XIVE_BOTH;
> -    } else if (spapr->irq->xive) {
> +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>          val[1] = SPAPR_OV5_XIVE_EXPLOIT;
>      } else {
> -        assert(spapr->irq->xics);
> +        assert(spapr_get_cap(spapr, SPAPR_CAP_XICS));
>          val[1] = SPAPR_OV5_XIVE_LEGACY;
>      }
>  
> @@ -2075,6 +2076,8 @@ static const VMStateDescription vmstate_spapr = {
>          &vmstate_spapr_dtb,
>          &vmstate_spapr_cap_large_decr,
>          &vmstate_spapr_cap_ccf_assist,
> +        &vmstate_spapr_cap_xics,
> +        &vmstate_spapr_cap_xive,
>          NULL
>      }
>  };
> @@ -2775,7 +2778,7 @@ static void spapr_machine_init(MachineState *machine)
>      spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2);
>  
>      /* advertise XIVE on POWER9 machines */
> -    if (spapr->irq->xive) {
> +    if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>          spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
>      }
>  
> @@ -3242,14 +3245,18 @@ static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name,
>  static char *spapr_get_ic_mode(Object *obj, Error **errp)
>  {
>      SpaprMachineState *spapr = SPAPR_MACHINE(obj);
> +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
>  
> -    if (spapr->irq == &spapr_irq_xics_legacy) {
> +    if (smc->legacy_irq_allocation) {
>          return g_strdup("legacy");
> -    } else if (spapr->irq == &spapr_irq_xics) {
> +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> +               && !spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>          return g_strdup("xics");
> -    } else if (spapr->irq == &spapr_irq_xive) {
> +    } else if (!spapr_get_cap(spapr, SPAPR_CAP_XICS)
> +               && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>          return g_strdup("xive");
> -    } else if (spapr->irq == &spapr_irq_dual) {
> +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> +               && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>          return g_strdup("dual");
>      }
>      g_assert_not_reached();
> @@ -3266,11 +3273,14 @@ static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
>  
>      /* The legacy IRQ backend can not be set */
>      if (strcmp(value, "xics") == 0) {
> -        spapr->irq = &spapr_irq_xics;
> +        object_property_set_bool(obj, true, "cap-xics", errp);
> +        object_property_set_bool(obj, false, "cap-xive", errp);
>      } else if (strcmp(value, "xive") == 0) {
> -        spapr->irq = &spapr_irq_xive;
> +        object_property_set_bool(obj, false, "cap-xics", errp);
> +        object_property_set_bool(obj, true, "cap-xive", errp);
>      } else if (strcmp(value, "dual") == 0) {
> -        spapr->irq = &spapr_irq_dual;
> +        object_property_set_bool(obj, true, "cap-xics", errp);
> +        object_property_set_bool(obj, true, "cap-xive", errp);
>      } else {
>          error_setg(errp, "Bad value for \"ic-mode\" property");
>      }
> @@ -3309,7 +3319,6 @@ static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
>  static void spapr_instance_init(Object *obj)
>  {
>      SpaprMachineState *spapr = SPAPR_MACHINE(obj);
> -    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
>  
>      spapr->htab_fd = -1;
>      spapr->use_hotplug_event_source = true;
> @@ -3345,7 +3354,6 @@ static void spapr_instance_init(Object *obj)
>                               spapr_get_msix_emulation, NULL, NULL);
>  
>      /* The machine class defines the default interrupt controller mode */
> -    spapr->irq = smc->irq;
>      object_property_add_str(obj, "ic-mode", spapr_get_ic_mode,
>                              spapr_set_ic_mode, NULL);
>      object_property_set_description(obj, "ic-mode",
> @@ -4439,8 +4447,9 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
>      smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
>      smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
>      smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
> +    smc->default_caps.caps[SPAPR_CAP_XICS] = SPAPR_CAP_ON;
> +    smc->default_caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_ON;
>      spapr_caps_add_properties(smc, &error_abort);
> -    smc->irq = &spapr_irq_dual;
>      smc->dr_phb_enabled = true;
>      smc->linux_pci_probe = true;
>      smc->nr_xirqs = SPAPR_NR_XIRQS;
> @@ -4539,7 +4548,7 @@ static void spapr_machine_4_0_class_options(MachineClass *mc)
>      spapr_machine_4_1_class_options(mc);
>      compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
>      smc->phb_placement = phb_placement_4_0;
> -    smc->irq = &spapr_irq_xics;
> +    smc->default_caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_OFF;
>      smc->pre_4_1_migration = true;
>  }
>  
> @@ -4580,7 +4589,6 @@ static void spapr_machine_3_0_class_options(MachineClass *mc)
>  
>      smc->legacy_irq_allocation = true;
>      smc->nr_xirqs = 0x400;
> -    smc->irq = &spapr_irq_xics_legacy;
>  }
>  
>  DEFINE_SPAPR_MACHINE(3_0, "3.0", false);
> diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
> index 481dfd2a27..e06fd386f6 100644
> --- a/hw/ppc/spapr_caps.c
> +++ b/hw/ppc/spapr_caps.c
> @@ -496,6 +496,42 @@ static void cap_ccf_assist_apply(SpaprMachineState *spapr, uint8_t val,
>      }
>  }
>  
> +static void cap_xics_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
> +{
> +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> +
> +    if (!val) {
> +        if (!spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> +            error_setg(errp,
> +"No interrupt controllers enabled, try cap-xics=on or cap-xive=on");
> +            return;
> +        }
> +
> +        if (smc->legacy_irq_allocation) {
> +            error_setg(errp, "This machine version requires XICS support");
> +            return;
> +        }
> +    }
> +}
> +
> +static void cap_xive_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
> +{
> +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> +    PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
> +
> +    if (val) {
> +        if (smc->legacy_irq_allocation) {
> +            error_setg(errp, "This machine version cannot support XIVE");
> +            return;
> +        }
> +        if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0,
> +                              spapr->max_compat_pvr)) {
> +            error_setg(errp, "XIVE requires POWER9 CPU");
> +            return;
> +        }
> +    }
> +}
> +
>  SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
>      [SPAPR_CAP_HTM] = {
>          .name = "htm",
> @@ -595,6 +631,24 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
>          .type = "bool",
>          .apply = cap_ccf_assist_apply,
>      },
> +    [SPAPR_CAP_XICS] = {
> +        .name = "xics",
> +        .description = "Allow XICS interrupt controller",
> +        .index = SPAPR_CAP_XICS,
> +        .get = spapr_cap_get_bool,
> +        .set = spapr_cap_set_bool,
> +        .type = "bool",
> +        .apply = cap_xics_apply,
> +    },
> +    [SPAPR_CAP_XIVE] = {
> +        .name = "xive",
> +        .description = "Allow XIVE interrupt controller",
> +        .index = SPAPR_CAP_XIVE,
> +        .get = spapr_cap_get_bool,
> +        .set = spapr_cap_set_bool,
> +        .type = "bool",
> +        .apply = cap_xive_apply,
> +    },
>  };
>  
>  static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
> @@ -641,6 +695,14 @@ static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
>          caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = mps;
>      }
>  
> +    /*
> +     * POWER8 machines don't have XIVE
> +     */
> +    if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_3_00,
> +                               0, spapr->max_compat_pvr)) {
> +        caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_OFF;
> +    }
> +
>      return caps;
>  }
>  
> @@ -734,6 +796,8 @@ SPAPR_CAP_MIG_STATE(hpt_maxpagesize, SPAPR_CAP_HPT_MAXPAGESIZE);
>  SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
>  SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
>  SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
> +SPAPR_CAP_MIG_STATE(xics, SPAPR_CAP_XICS);
> +SPAPR_CAP_MIG_STATE(xive, SPAPR_CAP_XIVE);
>  
>  void spapr_caps_init(SpaprMachineState *spapr)
>  {
> diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> index 140f05c1c6..cb4c6edf63 100644
> --- a/hw/ppc/spapr_hcall.c
> +++ b/hw/ppc/spapr_hcall.c
> @@ -1784,13 +1784,13 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
>       * terminate the boot.
>       */
>      if (guest_xive) {
> -        if (!spapr->irq->xive) {
> +        if (!spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>              error_report(
>  "Guest requested unavailable interrupt mode (XIVE), try the ic-mode=xive or ic-mode=dual machine property");
>              exit(EXIT_FAILURE);
>          }
>      } else {
> -        if (!spapr->irq->xics) {
> +        if (!spapr_get_cap(spapr, SPAPR_CAP_XICS)) {
>              error_report(
>  "Guest requested unavailable interrupt mode (XICS), either don't set the ic-mode machine property or try ic-mode=xics or ic-mode=dual");
>              exit(EXIT_FAILURE);
> @@ -1804,7 +1804,8 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
>       */
>      if (!spapr->cas_reboot) {
>          spapr->cas_reboot = spapr_ovec_test(ov5_updates, OV5_XIVE_EXPLOIT)
> -            && spapr->irq->xics && spapr->irq->xive;
> +            && spapr_get_cap(spapr, SPAPR_CAP_XICS)
> +            && spapr_get_cap(spapr, SPAPR_CAP_XIVE);
>      }
>  
>      spapr_ovec_cleanup(ov5_updates);
> diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> index 2768f9a765..473fc8780a 100644
> --- a/hw/ppc/spapr_irq.c
> +++ b/hw/ppc/spapr_irq.c
> @@ -101,90 +101,19 @@ int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
>      return 0;
>  }
>  
> -/*
> - * XICS IRQ backend.
> - */
> -
> -SpaprIrq spapr_irq_xics = {
> -    .xics        = true,
> -    .xive        = false,
> -};
> -
> -/*
> - * XIVE IRQ backend.
> - */
> -
> -SpaprIrq spapr_irq_xive = {
> -    .xics        = false,
> -    .xive        = true,
> -};
> -
> -/*
> - * Dual XIVE and XICS IRQ backend.
> - *
> - * Both interrupt mode, XIVE and XICS, objects are created but the
> - * machine starts in legacy interrupt mode (XICS). It can be changed
> - * by the CAS negotiation process and, in that case, the new mode is
> - * activated after an extra machine reset.
> - */
> -
> -/*
> - * Define values in sync with the XIVE and XICS backend
> - */
> -SpaprIrq spapr_irq_dual = {
> -    .xics        = true,
> -    .xive        = true,
> -};
> -
> -
>  static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
>  {
>      MachineState *machine = MACHINE(spapr);
>  
> -    /*
> -     * Sanity checks on non-P9 machines. On these, XIVE is not
> -     * advertised, see spapr_dt_ov5_platform_support()
> -     */
> -    if (!ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00,
> -                               0, spapr->max_compat_pvr)) {
> -        /*
> -         * If the 'dual' interrupt mode is selected, force XICS as CAS
> -         * negotiation is useless.
> -         */
> -        if (spapr->irq == &spapr_irq_dual) {
> -            spapr->irq = &spapr_irq_xics;
> -            return 0;
> -        }
> -
> -        /*
> -         * Non-P9 machines using only XIVE is a bogus setup. We have two
> -         * scenarios to take into account because of the compat mode:
> -         *
> -         * 1. POWER7/8 machines should fail to init later on when creating
> -         *    the XIVE interrupt presenters because a POWER9 exception
> -         *    model is required.
> -
> -         * 2. POWER9 machines using the POWER8 compat mode won't fail and
> -         *    will let the OS boot with a partial XIVE setup : DT
> -         *    properties but no hcalls.
> -         *
> -         * To cover both and not confuse the OS, add an early failure in
> -         * QEMU.
> -         */
> -        if (spapr->irq == &spapr_irq_xive) {
> -            error_setg(errp, "XIVE-only machines require a POWER9 CPU");
> -            return -1;
> -        }
> -    }
> -
>      /*
>       * On a POWER9 host, some older KVM XICS devices cannot be destroyed and
>       * re-created. Detect that early to avoid QEMU to exit later when the
>       * guest reboots.
>       */
>      if (kvm_enabled() &&
> -        spapr->irq == &spapr_irq_dual &&
>          machine_kernel_irqchip_required(machine) &&
> +        spapr_get_cap(spapr, SPAPR_CAP_XICS) &&
> +        spapr_get_cap(spapr, SPAPR_CAP_XIVE) &&
>          xics_kvm_has_broken_disconnect(spapr)) {
>          error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on");
>          return -1;
> @@ -280,7 +209,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>      /* Initialize the MSI IRQ allocator. */
>      spapr_irq_msi_init(spapr);
>  
> -    if (spapr->irq->xics) {
> +    if (spapr_get_cap(spapr, SPAPR_CAP_XICS)) {
>          Error *local_err = NULL;
>          Object *obj;
>  
> @@ -313,7 +242,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
>          spapr->ics = ICS_SPAPR(obj);
>      }
>  
> -    if (spapr->irq->xive) {
> +    if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
>          uint32_t nr_servers = spapr_max_server_number(spapr);
>          DeviceState *dev;
>          int i;
> @@ -558,11 +487,6 @@ int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
>      return first + ics->offset;
>  }
>  
> -SpaprIrq spapr_irq_xics_legacy = {
> -    .xics        = true,
> -    .xive        = false,
> -};
> -
>  static void spapr_irq_register_types(void)
>  {
>      type_register_static(&spapr_intc_info);
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index 623e8e3f93..d3b4dd7de3 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -79,8 +79,12 @@ typedef enum {
>  #define SPAPR_CAP_LARGE_DECREMENTER     0x08
>  /* Count Cache Flush Assist HW Instruction */
>  #define SPAPR_CAP_CCF_ASSIST            0x09
> +/* XICS interrupt controller */
> +#define SPAPR_CAP_XICS                  0x0a
> +/* XIVE interrupt controller */
> +#define SPAPR_CAP_XIVE                  0x0b
>  /* Num Caps */
> -#define SPAPR_CAP_NUM                   (SPAPR_CAP_CCF_ASSIST + 1)
> +#define SPAPR_CAP_NUM                   (SPAPR_CAP_XIVE + 1)
>  
>  /*
>   * Capability Values
> @@ -131,7 +135,6 @@ struct SpaprMachineClass {
>                            hwaddr *nv2atsd, Error **errp);
>      SpaprResizeHpt resize_hpt_default;
>      SpaprCapabilities default_caps;
> -    SpaprIrq *irq;
>  };
>  
>  /**
> @@ -195,7 +198,6 @@ struct SpaprMachineState {
>  
>      int32_t irq_map_nr;
>      unsigned long *irq_map;
> -    SpaprIrq *irq;
>      qemu_irq *qirqs;
>      SpaprInterruptController *active_intc;
>      ICSState *ics;
> @@ -870,6 +872,8 @@ extern const VMStateDescription vmstate_spapr_cap_hpt_maxpagesize;
>  extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
>  extern const VMStateDescription vmstate_spapr_cap_large_decr;
>  extern const VMStateDescription vmstate_spapr_cap_ccf_assist;
> +extern const VMStateDescription vmstate_spapr_cap_xics;
> +extern const VMStateDescription vmstate_spapr_cap_xive;
>  
>  static inline uint8_t spapr_get_cap(SpaprMachineState *spapr, int cap)
>  {
> diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> index 5e150a6679..71aee13743 100644
> --- a/include/hw/ppc/spapr_irq.h
> +++ b/include/hw/ppc/spapr_irq.h
> @@ -77,16 +77,6 @@ int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
>                          Error **errp);
>  void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num);
>  
> -typedef struct SpaprIrq {
> -    bool        xics;
> -    bool        xive;
> -} SpaprIrq;
> -
> -extern SpaprIrq spapr_irq_xics;
> -extern SpaprIrq spapr_irq_xics_legacy;
> -extern SpaprIrq spapr_irq_xive;
> -extern SpaprIrq spapr_irq_dual;
> -
>  void spapr_irq_init(SpaprMachineState *spapr, Error **errp);
>  int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp);
>  void spapr_irq_free(SpaprMachineState *spapr, int irq, int num);



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 19/19] spapr: Work around spurious warnings from vfio INTx initialization
  2019-10-09  8:52     ` David Gibson
@ 2019-10-09 17:16       ` Greg Kurz
  2019-10-10  2:02         ` David Gibson
  0 siblings, 1 reply; 54+ messages in thread
From: Greg Kurz @ 2019-10-09 17:16 UTC (permalink / raw)
  To: David Gibson
  Cc: Alexey Kardashevskiy, Jason Wang, Riku Voipio, qemu-devel,
	Laurent Vivier, Alex Williamson, qemu-ppc, clg, Paolo Bonzini,
	Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 3785 bytes --]

On Wed, 9 Oct 2019 19:52:59 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:

> On Wed, Oct 09, 2019 at 10:37:38AM +0200, Greg Kurz wrote:
> > On Wed,  9 Oct 2019 17:08:18 +1100
> > David Gibson <david@gibson.dropbear.id.au> wrote:
> > 
> > > Traditional PCI INTx for vfio devices can only perform well if using
> > > an in-kernel irqchip.  Therefore, vfio_intx_update() issues a warning
> > > if an in kernel irqchip is not available.
> > 
> > Can you elaborate on what doesn't "perform well" without an
> > in-kernel irqchip ?
> 
> Not really, no, but Alex Williamson tells me it is soo.
> 
> > Is it a matter of performance or is it
> > actually broken or something else ?
> 
> I believe it's a matter of performance, but such a big one that it
> makes using it without kernel irqchip infeasible in many cases.
> 
> > What is the impact on -machine accel=kvm,kernel-irqchip=off which
> > always spit this warning ?
> 
> It should still spit that warning.
> 

Yeah of course it does, but it is expected that we cannot setup
the irqfd since we deliberately don't have an in-kernel irqchip,
isn't it ? Why spit a warning in this case ? Or is it just a not
very user friendly way of saying "you will have poor performance
if the VFIO device uses PCI INTx" ?

> > > We usually do have an in-kernel irqchip available for pseries machines
> > > on POWER hosts.  However, because the platform allows feature
> > > negotiation of what interrupt controller model to use, we don't
> > > currently initialize it until machine reset.  vfio_intx_update() is
> > > called (first) from vfio_realize() before that, so it can issue a
> > > spurious warning, even if we will have an in kernel irqchip by the
> > > time we need it.
> > > 
> > > To workaround this, make a call to spapr_irq_update_active_intc() from
> > > spapr_irq_init() which is called at machine realize time, before the
> > > vfio realize.  This call will be pretty much obsoleted by the later
> > > call at reset time, but it serves to suppress the spurious warning
> > > from VFIO.
> > > 
> > > Cc: Alex Williamson <alex.williamson@redhat.com>
> > > Cc: Alexey Kardashevskiy <aik@ozlabs.ru>
> > > 
> > > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > > ---
> > >  hw/ppc/spapr_irq.c | 11 ++++++++++-
> > >  1 file changed, 10 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> > > index 7964e4a1b8..3aeb523f3e 100644
> > > --- a/hw/ppc/spapr_irq.c
> > > +++ b/hw/ppc/spapr_irq.c
> > > @@ -274,6 +274,14 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
> > >  
> > >      spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr,
> > >                                        smc->nr_xirqs + SPAPR_XIRQ_BASE);
> > > +
> > > +    /*
> > > +     * Mostly we don't actually need this until reset, except that not
> > > +     * having this set up can cause VFIO devices to issue a
> > > +     * false-positive warning during realize(), because they don't yet
> > > +     * have an in-kernel irq chip.
> > > +     */
> > > +    spapr_irq_update_active_intc(spapr);
> > >  }
> > >  
> > >  int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp)
> > > @@ -429,7 +437,8 @@ void spapr_irq_update_active_intc(SpaprMachineState *spapr)
> > >           * this.
> > >           */
> > >          new_intc = SPAPR_INTC(spapr->xive);
> > > -    } else if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
> > > +    } else if (spapr->ov5_cas
> > > +               && spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
> > >          new_intc = SPAPR_INTC(spapr->xive);
> > >      } else {
> > >          new_intc = SPAPR_INTC(spapr->ics);
> > 
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 15/19] spapr: Remove SpaprIrq::nr_msis
  2019-10-09 15:59   ` Cédric Le Goater
@ 2019-10-10  1:56     ` David Gibson
  0 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-10  1:56 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: Jason Wang, Riku Voipio, Laurent Vivier, qemu-devel, groug,
	qemu-ppc, Paolo Bonzini, Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 3024 bytes --]

On Wed, Oct 09, 2019 at 05:59:13PM +0200, Cédric Le Goater wrote:
> On 09/10/2019 08:08, David Gibson wrote:
> > The nr_msis value we use here has to line up with whether we're using
> > legacy or modern irq allocation.  Therefore it's safer to derive it based
> > on legacy_irq_allocation rather than having SpaprIrq contain a canned
> > value.
> > 
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > Reviewed-by: Greg Kurz <groug@kaod.org>
> 
> 
> Reviewed-by: Cédric Le Goater <clg@kaod.org>
> 
> one minor typo below,
> 
> > ---
> >  hw/ppc/spapr.c              |  5 ++---
> >  hw/ppc/spapr_irq.c          | 26 +++++++++++++++++---------
> >  hw/ppc/spapr_pci.c          |  7 ++++---
> >  include/hw/pci-host/spapr.h |  4 ++--
> >  include/hw/ppc/spapr_irq.h  |  4 +---
> >  5 files changed, 26 insertions(+), 20 deletions(-)
> > 
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index e880db5d38..153cc54354 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -1275,7 +1275,7 @@ static void *spapr_build_fdt(SpaprMachineState *spapr)
> >      }
> >  
> >      QLIST_FOREACH(phb, &spapr->phbs, list) {
> > -        ret = spapr_dt_phb(phb, PHANDLE_INTC, fdt, spapr->irq->nr_msis, NULL);
> > +        ret = spapr_dt_phb(spapr, phb, PHANDLE_INTC, fdt, NULL);
> >          if (ret < 0) {
> >              error_report("couldn't setup PCI devices in fdt");
> >              exit(1);
> > @@ -3910,8 +3910,7 @@ int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
> >          return -1;
> >      }
> >  
> > -    if (spapr_dt_phb(sphb, intc_phandle, fdt, spapr->irq->nr_msis,
> > -                     fdt_start_offset)) {
> > +    if (spapr_dt_phb(spapr, sphb, intc_phandle, fdt, fdt_start_offset)) {
> >          error_setg(errp, "unable to create FDT node for PHB %d", sphb->index);
> >          return -1;
> >      }
> > diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> > index f3d18b1dad..076da31501 100644
> > --- a/hw/ppc/spapr_irq.c
> > +++ b/hw/ppc/spapr_irq.c
> > @@ -29,9 +29,14 @@ static const TypeInfo spapr_intc_info = {
> >      .class_size = sizeof(SpaprInterruptControllerClass),
> >  };
> >  
> > -void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis)
> > +static void spapr_irq_msi_init(SpaprMachineState *spapr)
> >  {
> > -    spapr->irq_map_nr = nr_msis;
> > +    if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
> > +        /* Legacy mode doesn't use this allocater */
> 
> allocater -> allocator

Huh.  I had surprising difficulty trying to confirm what the correct
spelling really is here.  Actual dictionaries seem to thing that
neither "allocater" nor "allocator" are words.  Still "allocator"
seems to be by far the more common variant, so I've changed it.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq
  2019-10-09 16:44   ` Cédric Le Goater
@ 2019-10-10  1:59     ` David Gibson
  0 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-10  1:59 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: Jason Wang, Riku Voipio, Laurent Vivier, qemu-devel, groug,
	qemu-ppc, Paolo Bonzini, Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 19600 bytes --]

On Wed, Oct 09, 2019 at 06:44:53PM +0200, Cédric Le Goater wrote:
> On 09/10/2019 08:08, David Gibson wrote:
> > The only thing remaining in this structure are the flags to allow either
> > XICS or XIVE to be present.  These actually make more sense as spapr
> > capabilities - that way they can take advantage of the existing
> > infrastructure to sanity check capability states across migration and so
> > forth.
> > 
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> 
> Nice. That is what you had in mind :) Let's make sure we use your
> cap framework for the next major change, power10.

Yeah, adding a cap-xive2 should be pretty straightforward.

> ic-mode should
> be deprecated one day I suppose.

I guess.  I'm not in a great rush, since the compat code for it is
pretty simple and localized.

> Reviewed-by: Cédric Le Goater <clg@kaod.org>
> 
> C.
> 
> 
> > ---
> >  hw/ppc/spapr.c             | 40 ++++++++++--------
> >  hw/ppc/spapr_caps.c        | 64 +++++++++++++++++++++++++++++
> >  hw/ppc/spapr_hcall.c       |  7 ++--
> >  hw/ppc/spapr_irq.c         | 84 ++------------------------------------
> >  include/hw/ppc/spapr.h     | 10 +++--
> >  include/hw/ppc/spapr_irq.h | 10 -----
> >  6 files changed, 103 insertions(+), 112 deletions(-)
> > 
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index e1ff03152e..bf9fdb1693 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -1072,12 +1072,13 @@ static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
> >          26, 0x40, /* Radix options: GTSE == yes. */
> >      };
> >  
> > -    if (spapr->irq->xics && spapr->irq->xive) {
> > +    if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > +        && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >          val[1] = SPAPR_OV5_XIVE_BOTH;
> > -    } else if (spapr->irq->xive) {
> > +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >          val[1] = SPAPR_OV5_XIVE_EXPLOIT;
> >      } else {
> > -        assert(spapr->irq->xics);
> > +        assert(spapr_get_cap(spapr, SPAPR_CAP_XICS));
> >          val[1] = SPAPR_OV5_XIVE_LEGACY;
> >      }
> >  
> > @@ -2075,6 +2076,8 @@ static const VMStateDescription vmstate_spapr = {
> >          &vmstate_spapr_dtb,
> >          &vmstate_spapr_cap_large_decr,
> >          &vmstate_spapr_cap_ccf_assist,
> > +        &vmstate_spapr_cap_xics,
> > +        &vmstate_spapr_cap_xive,
> >          NULL
> >      }
> >  };
> > @@ -2775,7 +2778,7 @@ static void spapr_machine_init(MachineState *machine)
> >      spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2);
> >  
> >      /* advertise XIVE on POWER9 machines */
> > -    if (spapr->irq->xive) {
> > +    if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >          spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
> >      }
> >  
> > @@ -3242,14 +3245,18 @@ static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name,
> >  static char *spapr_get_ic_mode(Object *obj, Error **errp)
> >  {
> >      SpaprMachineState *spapr = SPAPR_MACHINE(obj);
> > +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> >  
> > -    if (spapr->irq == &spapr_irq_xics_legacy) {
> > +    if (smc->legacy_irq_allocation) {
> >          return g_strdup("legacy");
> > -    } else if (spapr->irq == &spapr_irq_xics) {
> > +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > +               && !spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >          return g_strdup("xics");
> > -    } else if (spapr->irq == &spapr_irq_xive) {
> > +    } else if (!spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > +               && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >          return g_strdup("xive");
> > -    } else if (spapr->irq == &spapr_irq_dual) {
> > +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > +               && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >          return g_strdup("dual");
> >      }
> >      g_assert_not_reached();
> > @@ -3266,11 +3273,14 @@ static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
> >  
> >      /* The legacy IRQ backend can not be set */
> >      if (strcmp(value, "xics") == 0) {
> > -        spapr->irq = &spapr_irq_xics;
> > +        object_property_set_bool(obj, true, "cap-xics", errp);
> > +        object_property_set_bool(obj, false, "cap-xive", errp);
> >      } else if (strcmp(value, "xive") == 0) {
> > -        spapr->irq = &spapr_irq_xive;
> > +        object_property_set_bool(obj, false, "cap-xics", errp);
> > +        object_property_set_bool(obj, true, "cap-xive", errp);
> >      } else if (strcmp(value, "dual") == 0) {
> > -        spapr->irq = &spapr_irq_dual;
> > +        object_property_set_bool(obj, true, "cap-xics", errp);
> > +        object_property_set_bool(obj, true, "cap-xive", errp);
> >      } else {
> >          error_setg(errp, "Bad value for \"ic-mode\" property");
> >      }
> > @@ -3309,7 +3319,6 @@ static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
> >  static void spapr_instance_init(Object *obj)
> >  {
> >      SpaprMachineState *spapr = SPAPR_MACHINE(obj);
> > -    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> >  
> >      spapr->htab_fd = -1;
> >      spapr->use_hotplug_event_source = true;
> > @@ -3345,7 +3354,6 @@ static void spapr_instance_init(Object *obj)
> >                               spapr_get_msix_emulation, NULL, NULL);
> >  
> >      /* The machine class defines the default interrupt controller mode */
> > -    spapr->irq = smc->irq;
> >      object_property_add_str(obj, "ic-mode", spapr_get_ic_mode,
> >                              spapr_set_ic_mode, NULL);
> >      object_property_set_description(obj, "ic-mode",
> > @@ -4439,8 +4447,9 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
> >      smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
> >      smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
> >      smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
> > +    smc->default_caps.caps[SPAPR_CAP_XICS] = SPAPR_CAP_ON;
> > +    smc->default_caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_ON;
> >      spapr_caps_add_properties(smc, &error_abort);
> > -    smc->irq = &spapr_irq_dual;
> >      smc->dr_phb_enabled = true;
> >      smc->linux_pci_probe = true;
> >      smc->nr_xirqs = SPAPR_NR_XIRQS;
> > @@ -4539,7 +4548,7 @@ static void spapr_machine_4_0_class_options(MachineClass *mc)
> >      spapr_machine_4_1_class_options(mc);
> >      compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
> >      smc->phb_placement = phb_placement_4_0;
> > -    smc->irq = &spapr_irq_xics;
> > +    smc->default_caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_OFF;
> >      smc->pre_4_1_migration = true;
> >  }
> >  
> > @@ -4580,7 +4589,6 @@ static void spapr_machine_3_0_class_options(MachineClass *mc)
> >  
> >      smc->legacy_irq_allocation = true;
> >      smc->nr_xirqs = 0x400;
> > -    smc->irq = &spapr_irq_xics_legacy;
> >  }
> >  
> >  DEFINE_SPAPR_MACHINE(3_0, "3.0", false);
> > diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
> > index 481dfd2a27..e06fd386f6 100644
> > --- a/hw/ppc/spapr_caps.c
> > +++ b/hw/ppc/spapr_caps.c
> > @@ -496,6 +496,42 @@ static void cap_ccf_assist_apply(SpaprMachineState *spapr, uint8_t val,
> >      }
> >  }
> >  
> > +static void cap_xics_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
> > +{
> > +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> > +
> > +    if (!val) {
> > +        if (!spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > +            error_setg(errp,
> > +"No interrupt controllers enabled, try cap-xics=on or cap-xive=on");
> > +            return;
> > +        }
> > +
> > +        if (smc->legacy_irq_allocation) {
> > +            error_setg(errp, "This machine version requires XICS support");
> > +            return;
> > +        }
> > +    }
> > +}
> > +
> > +static void cap_xive_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
> > +{
> > +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> > +    PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
> > +
> > +    if (val) {
> > +        if (smc->legacy_irq_allocation) {
> > +            error_setg(errp, "This machine version cannot support XIVE");
> > +            return;
> > +        }
> > +        if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0,
> > +                              spapr->max_compat_pvr)) {
> > +            error_setg(errp, "XIVE requires POWER9 CPU");
> > +            return;
> > +        }
> > +    }
> > +}
> > +
> >  SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
> >      [SPAPR_CAP_HTM] = {
> >          .name = "htm",
> > @@ -595,6 +631,24 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
> >          .type = "bool",
> >          .apply = cap_ccf_assist_apply,
> >      },
> > +    [SPAPR_CAP_XICS] = {
> > +        .name = "xics",
> > +        .description = "Allow XICS interrupt controller",
> > +        .index = SPAPR_CAP_XICS,
> > +        .get = spapr_cap_get_bool,
> > +        .set = spapr_cap_set_bool,
> > +        .type = "bool",
> > +        .apply = cap_xics_apply,
> > +    },
> > +    [SPAPR_CAP_XIVE] = {
> > +        .name = "xive",
> > +        .description = "Allow XIVE interrupt controller",
> > +        .index = SPAPR_CAP_XIVE,
> > +        .get = spapr_cap_get_bool,
> > +        .set = spapr_cap_set_bool,
> > +        .type = "bool",
> > +        .apply = cap_xive_apply,
> > +    },
> >  };
> >  
> >  static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
> > @@ -641,6 +695,14 @@ static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
> >          caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = mps;
> >      }
> >  
> > +    /*
> > +     * POWER8 machines don't have XIVE
> > +     */
> > +    if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_3_00,
> > +                               0, spapr->max_compat_pvr)) {
> > +        caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_OFF;
> > +    }
> > +
> >      return caps;
> >  }
> >  
> > @@ -734,6 +796,8 @@ SPAPR_CAP_MIG_STATE(hpt_maxpagesize, SPAPR_CAP_HPT_MAXPAGESIZE);
> >  SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
> >  SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
> >  SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
> > +SPAPR_CAP_MIG_STATE(xics, SPAPR_CAP_XICS);
> > +SPAPR_CAP_MIG_STATE(xive, SPAPR_CAP_XIVE);
> >  
> >  void spapr_caps_init(SpaprMachineState *spapr)
> >  {
> > diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> > index 140f05c1c6..cb4c6edf63 100644
> > --- a/hw/ppc/spapr_hcall.c
> > +++ b/hw/ppc/spapr_hcall.c
> > @@ -1784,13 +1784,13 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
> >       * terminate the boot.
> >       */
> >      if (guest_xive) {
> > -        if (!spapr->irq->xive) {
> > +        if (!spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >              error_report(
> >  "Guest requested unavailable interrupt mode (XIVE), try the ic-mode=xive or ic-mode=dual machine property");
> >              exit(EXIT_FAILURE);
> >          }
> >      } else {
> > -        if (!spapr->irq->xics) {
> > +        if (!spapr_get_cap(spapr, SPAPR_CAP_XICS)) {
> >              error_report(
> >  "Guest requested unavailable interrupt mode (XICS), either don't set the ic-mode machine property or try ic-mode=xics or ic-mode=dual");
> >              exit(EXIT_FAILURE);
> > @@ -1804,7 +1804,8 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
> >       */
> >      if (!spapr->cas_reboot) {
> >          spapr->cas_reboot = spapr_ovec_test(ov5_updates, OV5_XIVE_EXPLOIT)
> > -            && spapr->irq->xics && spapr->irq->xive;
> > +            && spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > +            && spapr_get_cap(spapr, SPAPR_CAP_XIVE);
> >      }
> >  
> >      spapr_ovec_cleanup(ov5_updates);
> > diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> > index 2768f9a765..473fc8780a 100644
> > --- a/hw/ppc/spapr_irq.c
> > +++ b/hw/ppc/spapr_irq.c
> > @@ -101,90 +101,19 @@ int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
> >      return 0;
> >  }
> >  
> > -/*
> > - * XICS IRQ backend.
> > - */
> > -
> > -SpaprIrq spapr_irq_xics = {
> > -    .xics        = true,
> > -    .xive        = false,
> > -};
> > -
> > -/*
> > - * XIVE IRQ backend.
> > - */
> > -
> > -SpaprIrq spapr_irq_xive = {
> > -    .xics        = false,
> > -    .xive        = true,
> > -};
> > -
> > -/*
> > - * Dual XIVE and XICS IRQ backend.
> > - *
> > - * Both interrupt mode, XIVE and XICS, objects are created but the
> > - * machine starts in legacy interrupt mode (XICS). It can be changed
> > - * by the CAS negotiation process and, in that case, the new mode is
> > - * activated after an extra machine reset.
> > - */
> > -
> > -/*
> > - * Define values in sync with the XIVE and XICS backend
> > - */
> > -SpaprIrq spapr_irq_dual = {
> > -    .xics        = true,
> > -    .xive        = true,
> > -};
> > -
> > -
> >  static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
> >  {
> >      MachineState *machine = MACHINE(spapr);
> >  
> > -    /*
> > -     * Sanity checks on non-P9 machines. On these, XIVE is not
> > -     * advertised, see spapr_dt_ov5_platform_support()
> > -     */
> > -    if (!ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00,
> > -                               0, spapr->max_compat_pvr)) {
> > -        /*
> > -         * If the 'dual' interrupt mode is selected, force XICS as CAS
> > -         * negotiation is useless.
> > -         */
> > -        if (spapr->irq == &spapr_irq_dual) {
> > -            spapr->irq = &spapr_irq_xics;
> > -            return 0;
> > -        }
> > -
> > -        /*
> > -         * Non-P9 machines using only XIVE is a bogus setup. We have two
> > -         * scenarios to take into account because of the compat mode:
> > -         *
> > -         * 1. POWER7/8 machines should fail to init later on when creating
> > -         *    the XIVE interrupt presenters because a POWER9 exception
> > -         *    model is required.
> > -
> > -         * 2. POWER9 machines using the POWER8 compat mode won't fail and
> > -         *    will let the OS boot with a partial XIVE setup : DT
> > -         *    properties but no hcalls.
> > -         *
> > -         * To cover both and not confuse the OS, add an early failure in
> > -         * QEMU.
> > -         */
> > -        if (spapr->irq == &spapr_irq_xive) {
> > -            error_setg(errp, "XIVE-only machines require a POWER9 CPU");
> > -            return -1;
> > -        }
> > -    }
> > -
> >      /*
> >       * On a POWER9 host, some older KVM XICS devices cannot be destroyed and
> >       * re-created. Detect that early to avoid QEMU to exit later when the
> >       * guest reboots.
> >       */
> >      if (kvm_enabled() &&
> > -        spapr->irq == &spapr_irq_dual &&
> >          machine_kernel_irqchip_required(machine) &&
> > +        spapr_get_cap(spapr, SPAPR_CAP_XICS) &&
> > +        spapr_get_cap(spapr, SPAPR_CAP_XIVE) &&
> >          xics_kvm_has_broken_disconnect(spapr)) {
> >          error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on");
> >          return -1;
> > @@ -280,7 +209,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
> >      /* Initialize the MSI IRQ allocator. */
> >      spapr_irq_msi_init(spapr);
> >  
> > -    if (spapr->irq->xics) {
> > +    if (spapr_get_cap(spapr, SPAPR_CAP_XICS)) {
> >          Error *local_err = NULL;
> >          Object *obj;
> >  
> > @@ -313,7 +242,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
> >          spapr->ics = ICS_SPAPR(obj);
> >      }
> >  
> > -    if (spapr->irq->xive) {
> > +    if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >          uint32_t nr_servers = spapr_max_server_number(spapr);
> >          DeviceState *dev;
> >          int i;
> > @@ -558,11 +487,6 @@ int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
> >      return first + ics->offset;
> >  }
> >  
> > -SpaprIrq spapr_irq_xics_legacy = {
> > -    .xics        = true,
> > -    .xive        = false,
> > -};
> > -
> >  static void spapr_irq_register_types(void)
> >  {
> >      type_register_static(&spapr_intc_info);
> > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> > index 623e8e3f93..d3b4dd7de3 100644
> > --- a/include/hw/ppc/spapr.h
> > +++ b/include/hw/ppc/spapr.h
> > @@ -79,8 +79,12 @@ typedef enum {
> >  #define SPAPR_CAP_LARGE_DECREMENTER     0x08
> >  /* Count Cache Flush Assist HW Instruction */
> >  #define SPAPR_CAP_CCF_ASSIST            0x09
> > +/* XICS interrupt controller */
> > +#define SPAPR_CAP_XICS                  0x0a
> > +/* XIVE interrupt controller */
> > +#define SPAPR_CAP_XIVE                  0x0b
> >  /* Num Caps */
> > -#define SPAPR_CAP_NUM                   (SPAPR_CAP_CCF_ASSIST + 1)
> > +#define SPAPR_CAP_NUM                   (SPAPR_CAP_XIVE + 1)
> >  
> >  /*
> >   * Capability Values
> > @@ -131,7 +135,6 @@ struct SpaprMachineClass {
> >                            hwaddr *nv2atsd, Error **errp);
> >      SpaprResizeHpt resize_hpt_default;
> >      SpaprCapabilities default_caps;
> > -    SpaprIrq *irq;
> >  };
> >  
> >  /**
> > @@ -195,7 +198,6 @@ struct SpaprMachineState {
> >  
> >      int32_t irq_map_nr;
> >      unsigned long *irq_map;
> > -    SpaprIrq *irq;
> >      qemu_irq *qirqs;
> >      SpaprInterruptController *active_intc;
> >      ICSState *ics;
> > @@ -870,6 +872,8 @@ extern const VMStateDescription vmstate_spapr_cap_hpt_maxpagesize;
> >  extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
> >  extern const VMStateDescription vmstate_spapr_cap_large_decr;
> >  extern const VMStateDescription vmstate_spapr_cap_ccf_assist;
> > +extern const VMStateDescription vmstate_spapr_cap_xics;
> > +extern const VMStateDescription vmstate_spapr_cap_xive;
> >  
> >  static inline uint8_t spapr_get_cap(SpaprMachineState *spapr, int cap)
> >  {
> > diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> > index 5e150a6679..71aee13743 100644
> > --- a/include/hw/ppc/spapr_irq.h
> > +++ b/include/hw/ppc/spapr_irq.h
> > @@ -77,16 +77,6 @@ int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
> >                          Error **errp);
> >  void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num);
> >  
> > -typedef struct SpaprIrq {
> > -    bool        xics;
> > -    bool        xive;
> > -} SpaprIrq;
> > -
> > -extern SpaprIrq spapr_irq_xics;
> > -extern SpaprIrq spapr_irq_xics_legacy;
> > -extern SpaprIrq spapr_irq_xive;
> > -extern SpaprIrq spapr_irq_dual;
> > -
> >  void spapr_irq_init(SpaprMachineState *spapr, Error **errp);
> >  int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp);
> >  void spapr_irq_free(SpaprMachineState *spapr, int irq, int num);
> > 
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq
  2019-10-09 17:02   ` Greg Kurz
@ 2019-10-10  2:02     ` David Gibson
  2019-10-10  6:29       ` Greg Kurz
  0 siblings, 1 reply; 54+ messages in thread
From: David Gibson @ 2019-10-10  2:02 UTC (permalink / raw)
  To: Greg Kurz
  Cc: Jason Wang, Riku Voipio, qemu-devel, Laurent Vivier, qemu-ppc,
	clg, Paolo Bonzini, Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 20230 bytes --]

On Wed, Oct 09, 2019 at 07:02:15PM +0200, Greg Kurz wrote:
> On Wed,  9 Oct 2019 17:08:16 +1100
> David Gibson <david@gibson.dropbear.id.au> wrote:
> 
> > The only thing remaining in this structure are the flags to allow either
> > XICS or XIVE to be present.  These actually make more sense as spapr
> > capabilities - that way they can take advantage of the existing
> > infrastructure to sanity check capability states across migration and so
> > forth.
> > 
> 
> The user can now choose the interrupt controller mode either through
> ic-mode or through cap-xics/cap-xive. I guess it doesn't break anything
> to expose another API to do the same thing but it raises some questions.
> 
> We should at least document somewhere that ic-mode is an alias to these
> caps, and maybe state which is the preferred method (I personally vote
> for the caps).
> 
> Also, we must keep ic-mode for the moment to stay compatible with the
> existing pseries-4.0 and pseries-4.1 machine types, but will we
> keep ic-mode forever ? If no, maybe start by not allowing it for
> pseries-4.2 ?

I'm actually inclined to keep it for now, maybe even leave it as the
suggested way to configure this.  The caps are nice from an internal
organization point of view, but ic-mode is arguably a more user
friendly way of configuring it.  The conversion of one to the other is
straightforward, isolated ans small, so I'm not especially bothered by
keeping it around.

> 
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> >  hw/ppc/spapr.c             | 40 ++++++++++--------
> >  hw/ppc/spapr_caps.c        | 64 +++++++++++++++++++++++++++++
> >  hw/ppc/spapr_hcall.c       |  7 ++--
> >  hw/ppc/spapr_irq.c         | 84 ++------------------------------------
> >  include/hw/ppc/spapr.h     | 10 +++--
> >  include/hw/ppc/spapr_irq.h | 10 -----
> >  6 files changed, 103 insertions(+), 112 deletions(-)
> > 
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index e1ff03152e..bf9fdb1693 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -1072,12 +1072,13 @@ static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
> >          26, 0x40, /* Radix options: GTSE == yes. */
> >      };
> >  
> > -    if (spapr->irq->xics && spapr->irq->xive) {
> > +    if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > +        && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >          val[1] = SPAPR_OV5_XIVE_BOTH;
> > -    } else if (spapr->irq->xive) {
> > +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >          val[1] = SPAPR_OV5_XIVE_EXPLOIT;
> >      } else {
> > -        assert(spapr->irq->xics);
> > +        assert(spapr_get_cap(spapr, SPAPR_CAP_XICS));
> >          val[1] = SPAPR_OV5_XIVE_LEGACY;
> >      }
> >  
> > @@ -2075,6 +2076,8 @@ static const VMStateDescription vmstate_spapr = {
> >          &vmstate_spapr_dtb,
> >          &vmstate_spapr_cap_large_decr,
> >          &vmstate_spapr_cap_ccf_assist,
> > +        &vmstate_spapr_cap_xics,
> > +        &vmstate_spapr_cap_xive,
> >          NULL
> >      }
> >  };
> > @@ -2775,7 +2778,7 @@ static void spapr_machine_init(MachineState *machine)
> >      spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2);
> >  
> >      /* advertise XIVE on POWER9 machines */
> > -    if (spapr->irq->xive) {
> > +    if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >          spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
> >      }
> >  
> > @@ -3242,14 +3245,18 @@ static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name,
> >  static char *spapr_get_ic_mode(Object *obj, Error **errp)
> >  {
> >      SpaprMachineState *spapr = SPAPR_MACHINE(obj);
> > +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> >  
> > -    if (spapr->irq == &spapr_irq_xics_legacy) {
> > +    if (smc->legacy_irq_allocation) {
> >          return g_strdup("legacy");
> > -    } else if (spapr->irq == &spapr_irq_xics) {
> > +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > +               && !spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >          return g_strdup("xics");
> > -    } else if (spapr->irq == &spapr_irq_xive) {
> > +    } else if (!spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > +               && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >          return g_strdup("xive");
> > -    } else if (spapr->irq == &spapr_irq_dual) {
> > +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > +               && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >          return g_strdup("dual");
> >      }
> >      g_assert_not_reached();
> > @@ -3266,11 +3273,14 @@ static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
> >  
> >      /* The legacy IRQ backend can not be set */
> >      if (strcmp(value, "xics") == 0) {
> > -        spapr->irq = &spapr_irq_xics;
> > +        object_property_set_bool(obj, true, "cap-xics", errp);
> > +        object_property_set_bool(obj, false, "cap-xive", errp);
> >      } else if (strcmp(value, "xive") == 0) {
> > -        spapr->irq = &spapr_irq_xive;
> > +        object_property_set_bool(obj, false, "cap-xics", errp);
> > +        object_property_set_bool(obj, true, "cap-xive", errp);
> >      } else if (strcmp(value, "dual") == 0) {
> > -        spapr->irq = &spapr_irq_dual;
> > +        object_property_set_bool(obj, true, "cap-xics", errp);
> > +        object_property_set_bool(obj, true, "cap-xive", errp);
> >      } else {
> >          error_setg(errp, "Bad value for \"ic-mode\" property");
> >      }
> > @@ -3309,7 +3319,6 @@ static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
> >  static void spapr_instance_init(Object *obj)
> >  {
> >      SpaprMachineState *spapr = SPAPR_MACHINE(obj);
> > -    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> >  
> >      spapr->htab_fd = -1;
> >      spapr->use_hotplug_event_source = true;
> > @@ -3345,7 +3354,6 @@ static void spapr_instance_init(Object *obj)
> >                               spapr_get_msix_emulation, NULL, NULL);
> >  
> >      /* The machine class defines the default interrupt controller mode */
> > -    spapr->irq = smc->irq;
> >      object_property_add_str(obj, "ic-mode", spapr_get_ic_mode,
> >                              spapr_set_ic_mode, NULL);
> >      object_property_set_description(obj, "ic-mode",
> > @@ -4439,8 +4447,9 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
> >      smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
> >      smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
> >      smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
> > +    smc->default_caps.caps[SPAPR_CAP_XICS] = SPAPR_CAP_ON;
> > +    smc->default_caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_ON;
> >      spapr_caps_add_properties(smc, &error_abort);
> > -    smc->irq = &spapr_irq_dual;
> >      smc->dr_phb_enabled = true;
> >      smc->linux_pci_probe = true;
> >      smc->nr_xirqs = SPAPR_NR_XIRQS;
> > @@ -4539,7 +4548,7 @@ static void spapr_machine_4_0_class_options(MachineClass *mc)
> >      spapr_machine_4_1_class_options(mc);
> >      compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
> >      smc->phb_placement = phb_placement_4_0;
> > -    smc->irq = &spapr_irq_xics;
> > +    smc->default_caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_OFF;
> >      smc->pre_4_1_migration = true;
> >  }
> >  
> > @@ -4580,7 +4589,6 @@ static void spapr_machine_3_0_class_options(MachineClass *mc)
> >  
> >      smc->legacy_irq_allocation = true;
> >      smc->nr_xirqs = 0x400;
> > -    smc->irq = &spapr_irq_xics_legacy;
> >  }
> >  
> >  DEFINE_SPAPR_MACHINE(3_0, "3.0", false);
> > diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
> > index 481dfd2a27..e06fd386f6 100644
> > --- a/hw/ppc/spapr_caps.c
> > +++ b/hw/ppc/spapr_caps.c
> > @@ -496,6 +496,42 @@ static void cap_ccf_assist_apply(SpaprMachineState *spapr, uint8_t val,
> >      }
> >  }
> >  
> > +static void cap_xics_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
> > +{
> > +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> > +
> > +    if (!val) {
> > +        if (!spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > +            error_setg(errp,
> > +"No interrupt controllers enabled, try cap-xics=on or cap-xive=on");
> > +            return;
> > +        }
> > +
> > +        if (smc->legacy_irq_allocation) {
> > +            error_setg(errp, "This machine version requires XICS support");
> > +            return;
> > +        }
> > +    }
> > +}
> > +
> > +static void cap_xive_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
> > +{
> > +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> > +    PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
> > +
> > +    if (val) {
> > +        if (smc->legacy_irq_allocation) {
> > +            error_setg(errp, "This machine version cannot support XIVE");
> > +            return;
> > +        }
> > +        if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0,
> > +                              spapr->max_compat_pvr)) {
> > +            error_setg(errp, "XIVE requires POWER9 CPU");
> > +            return;
> > +        }
> > +    }
> > +}
> > +
> >  SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
> >      [SPAPR_CAP_HTM] = {
> >          .name = "htm",
> > @@ -595,6 +631,24 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
> >          .type = "bool",
> >          .apply = cap_ccf_assist_apply,
> >      },
> > +    [SPAPR_CAP_XICS] = {
> > +        .name = "xics",
> > +        .description = "Allow XICS interrupt controller",
> > +        .index = SPAPR_CAP_XICS,
> > +        .get = spapr_cap_get_bool,
> > +        .set = spapr_cap_set_bool,
> > +        .type = "bool",
> > +        .apply = cap_xics_apply,
> > +    },
> > +    [SPAPR_CAP_XIVE] = {
> > +        .name = "xive",
> > +        .description = "Allow XIVE interrupt controller",
> > +        .index = SPAPR_CAP_XIVE,
> > +        .get = spapr_cap_get_bool,
> > +        .set = spapr_cap_set_bool,
> > +        .type = "bool",
> > +        .apply = cap_xive_apply,
> > +    },
> >  };
> >  
> >  static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
> > @@ -641,6 +695,14 @@ static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
> >          caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = mps;
> >      }
> >  
> > +    /*
> > +     * POWER8 machines don't have XIVE
> > +     */
> > +    if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_3_00,
> > +                               0, spapr->max_compat_pvr)) {
> > +        caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_OFF;
> > +    }
> > +
> >      return caps;
> >  }
> >  
> > @@ -734,6 +796,8 @@ SPAPR_CAP_MIG_STATE(hpt_maxpagesize, SPAPR_CAP_HPT_MAXPAGESIZE);
> >  SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
> >  SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
> >  SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
> > +SPAPR_CAP_MIG_STATE(xics, SPAPR_CAP_XICS);
> > +SPAPR_CAP_MIG_STATE(xive, SPAPR_CAP_XIVE);
> >  
> >  void spapr_caps_init(SpaprMachineState *spapr)
> >  {
> > diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> > index 140f05c1c6..cb4c6edf63 100644
> > --- a/hw/ppc/spapr_hcall.c
> > +++ b/hw/ppc/spapr_hcall.c
> > @@ -1784,13 +1784,13 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
> >       * terminate the boot.
> >       */
> >      if (guest_xive) {
> > -        if (!spapr->irq->xive) {
> > +        if (!spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >              error_report(
> >  "Guest requested unavailable interrupt mode (XIVE), try the ic-mode=xive or ic-mode=dual machine property");
> >              exit(EXIT_FAILURE);
> >          }
> >      } else {
> > -        if (!spapr->irq->xics) {
> > +        if (!spapr_get_cap(spapr, SPAPR_CAP_XICS)) {
> >              error_report(
> >  "Guest requested unavailable interrupt mode (XICS), either don't set the ic-mode machine property or try ic-mode=xics or ic-mode=dual");
> >              exit(EXIT_FAILURE);
> > @@ -1804,7 +1804,8 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
> >       */
> >      if (!spapr->cas_reboot) {
> >          spapr->cas_reboot = spapr_ovec_test(ov5_updates, OV5_XIVE_EXPLOIT)
> > -            && spapr->irq->xics && spapr->irq->xive;
> > +            && spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > +            && spapr_get_cap(spapr, SPAPR_CAP_XIVE);
> >      }
> >  
> >      spapr_ovec_cleanup(ov5_updates);
> > diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> > index 2768f9a765..473fc8780a 100644
> > --- a/hw/ppc/spapr_irq.c
> > +++ b/hw/ppc/spapr_irq.c
> > @@ -101,90 +101,19 @@ int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
> >      return 0;
> >  }
> >  
> > -/*
> > - * XICS IRQ backend.
> > - */
> > -
> > -SpaprIrq spapr_irq_xics = {
> > -    .xics        = true,
> > -    .xive        = false,
> > -};
> > -
> > -/*
> > - * XIVE IRQ backend.
> > - */
> > -
> > -SpaprIrq spapr_irq_xive = {
> > -    .xics        = false,
> > -    .xive        = true,
> > -};
> > -
> > -/*
> > - * Dual XIVE and XICS IRQ backend.
> > - *
> > - * Both interrupt mode, XIVE and XICS, objects are created but the
> > - * machine starts in legacy interrupt mode (XICS). It can be changed
> > - * by the CAS negotiation process and, in that case, the new mode is
> > - * activated after an extra machine reset.
> > - */
> > -
> > -/*
> > - * Define values in sync with the XIVE and XICS backend
> > - */
> > -SpaprIrq spapr_irq_dual = {
> > -    .xics        = true,
> > -    .xive        = true,
> > -};
> > -
> > -
> >  static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
> >  {
> >      MachineState *machine = MACHINE(spapr);
> >  
> > -    /*
> > -     * Sanity checks on non-P9 machines. On these, XIVE is not
> > -     * advertised, see spapr_dt_ov5_platform_support()
> > -     */
> > -    if (!ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00,
> > -                               0, spapr->max_compat_pvr)) {
> > -        /*
> > -         * If the 'dual' interrupt mode is selected, force XICS as CAS
> > -         * negotiation is useless.
> > -         */
> > -        if (spapr->irq == &spapr_irq_dual) {
> > -            spapr->irq = &spapr_irq_xics;
> > -            return 0;
> > -        }
> > -
> > -        /*
> > -         * Non-P9 machines using only XIVE is a bogus setup. We have two
> > -         * scenarios to take into account because of the compat mode:
> > -         *
> > -         * 1. POWER7/8 machines should fail to init later on when creating
> > -         *    the XIVE interrupt presenters because a POWER9 exception
> > -         *    model is required.
> > -
> > -         * 2. POWER9 machines using the POWER8 compat mode won't fail and
> > -         *    will let the OS boot with a partial XIVE setup : DT
> > -         *    properties but no hcalls.
> > -         *
> > -         * To cover both and not confuse the OS, add an early failure in
> > -         * QEMU.
> > -         */
> > -        if (spapr->irq == &spapr_irq_xive) {
> > -            error_setg(errp, "XIVE-only machines require a POWER9 CPU");
> > -            return -1;
> > -        }
> > -    }
> > -
> >      /*
> >       * On a POWER9 host, some older KVM XICS devices cannot be destroyed and
> >       * re-created. Detect that early to avoid QEMU to exit later when the
> >       * guest reboots.
> >       */
> >      if (kvm_enabled() &&
> > -        spapr->irq == &spapr_irq_dual &&
> >          machine_kernel_irqchip_required(machine) &&
> > +        spapr_get_cap(spapr, SPAPR_CAP_XICS) &&
> > +        spapr_get_cap(spapr, SPAPR_CAP_XIVE) &&
> >          xics_kvm_has_broken_disconnect(spapr)) {
> >          error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on");
> >          return -1;
> > @@ -280,7 +209,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
> >      /* Initialize the MSI IRQ allocator. */
> >      spapr_irq_msi_init(spapr);
> >  
> > -    if (spapr->irq->xics) {
> > +    if (spapr_get_cap(spapr, SPAPR_CAP_XICS)) {
> >          Error *local_err = NULL;
> >          Object *obj;
> >  
> > @@ -313,7 +242,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
> >          spapr->ics = ICS_SPAPR(obj);
> >      }
> >  
> > -    if (spapr->irq->xive) {
> > +    if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> >          uint32_t nr_servers = spapr_max_server_number(spapr);
> >          DeviceState *dev;
> >          int i;
> > @@ -558,11 +487,6 @@ int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
> >      return first + ics->offset;
> >  }
> >  
> > -SpaprIrq spapr_irq_xics_legacy = {
> > -    .xics        = true,
> > -    .xive        = false,
> > -};
> > -
> >  static void spapr_irq_register_types(void)
> >  {
> >      type_register_static(&spapr_intc_info);
> > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> > index 623e8e3f93..d3b4dd7de3 100644
> > --- a/include/hw/ppc/spapr.h
> > +++ b/include/hw/ppc/spapr.h
> > @@ -79,8 +79,12 @@ typedef enum {
> >  #define SPAPR_CAP_LARGE_DECREMENTER     0x08
> >  /* Count Cache Flush Assist HW Instruction */
> >  #define SPAPR_CAP_CCF_ASSIST            0x09
> > +/* XICS interrupt controller */
> > +#define SPAPR_CAP_XICS                  0x0a
> > +/* XIVE interrupt controller */
> > +#define SPAPR_CAP_XIVE                  0x0b
> >  /* Num Caps */
> > -#define SPAPR_CAP_NUM                   (SPAPR_CAP_CCF_ASSIST + 1)
> > +#define SPAPR_CAP_NUM                   (SPAPR_CAP_XIVE + 1)
> >  
> >  /*
> >   * Capability Values
> > @@ -131,7 +135,6 @@ struct SpaprMachineClass {
> >                            hwaddr *nv2atsd, Error **errp);
> >      SpaprResizeHpt resize_hpt_default;
> >      SpaprCapabilities default_caps;
> > -    SpaprIrq *irq;
> >  };
> >  
> >  /**
> > @@ -195,7 +198,6 @@ struct SpaprMachineState {
> >  
> >      int32_t irq_map_nr;
> >      unsigned long *irq_map;
> > -    SpaprIrq *irq;
> >      qemu_irq *qirqs;
> >      SpaprInterruptController *active_intc;
> >      ICSState *ics;
> > @@ -870,6 +872,8 @@ extern const VMStateDescription vmstate_spapr_cap_hpt_maxpagesize;
> >  extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
> >  extern const VMStateDescription vmstate_spapr_cap_large_decr;
> >  extern const VMStateDescription vmstate_spapr_cap_ccf_assist;
> > +extern const VMStateDescription vmstate_spapr_cap_xics;
> > +extern const VMStateDescription vmstate_spapr_cap_xive;
> >  
> >  static inline uint8_t spapr_get_cap(SpaprMachineState *spapr, int cap)
> >  {
> > diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> > index 5e150a6679..71aee13743 100644
> > --- a/include/hw/ppc/spapr_irq.h
> > +++ b/include/hw/ppc/spapr_irq.h
> > @@ -77,16 +77,6 @@ int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
> >                          Error **errp);
> >  void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num);
> >  
> > -typedef struct SpaprIrq {
> > -    bool        xics;
> > -    bool        xive;
> > -} SpaprIrq;
> > -
> > -extern SpaprIrq spapr_irq_xics;
> > -extern SpaprIrq spapr_irq_xics_legacy;
> > -extern SpaprIrq spapr_irq_xive;
> > -extern SpaprIrq spapr_irq_dual;
> > -
> >  void spapr_irq_init(SpaprMachineState *spapr, Error **errp);
> >  int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp);
> >  void spapr_irq_free(SpaprMachineState *spapr, int irq, int num);
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 19/19] spapr: Work around spurious warnings from vfio INTx initialization
  2019-10-09 17:16       ` Greg Kurz
@ 2019-10-10  2:02         ` David Gibson
  0 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-10  2:02 UTC (permalink / raw)
  To: Greg Kurz
  Cc: Alexey Kardashevskiy, Jason Wang, Riku Voipio, qemu-devel,
	Laurent Vivier, Alex Williamson, qemu-ppc, clg, Paolo Bonzini,
	Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 1644 bytes --]

On Wed, Oct 09, 2019 at 07:16:39PM +0200, Greg Kurz wrote:
> On Wed, 9 Oct 2019 19:52:59 +1100
> David Gibson <david@gibson.dropbear.id.au> wrote:
> 
> > On Wed, Oct 09, 2019 at 10:37:38AM +0200, Greg Kurz wrote:
> > > On Wed,  9 Oct 2019 17:08:18 +1100
> > > David Gibson <david@gibson.dropbear.id.au> wrote:
> > > 
> > > > Traditional PCI INTx for vfio devices can only perform well if using
> > > > an in-kernel irqchip.  Therefore, vfio_intx_update() issues a warning
> > > > if an in kernel irqchip is not available.
> > > 
> > > Can you elaborate on what doesn't "perform well" without an
> > > in-kernel irqchip ?
> > 
> > Not really, no, but Alex Williamson tells me it is soo.
> > 
> > > Is it a matter of performance or is it
> > > actually broken or something else ?
> > 
> > I believe it's a matter of performance, but such a big one that it
> > makes using it without kernel irqchip infeasible in many cases.
> > 
> > > What is the impact on -machine accel=kvm,kernel-irqchip=off which
> > > always spit this warning ?
> > 
> > It should still spit that warning.
> > 
> 
> Yeah of course it does, but it is expected that we cannot setup
> the irqfd since we deliberately don't have an in-kernel irqchip,
> isn't it ? Why spit a warning in this case ? Or is it just a not
> very user friendly way of saying "you will have poor performance
> if the VFIO device uses PCI INTx" ?

The last thing, AIUI.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq
  2019-10-10  2:02     ` David Gibson
@ 2019-10-10  6:29       ` Greg Kurz
  2019-10-10 20:33         ` Greg Kurz
  0 siblings, 1 reply; 54+ messages in thread
From: Greg Kurz @ 2019-10-10  6:29 UTC (permalink / raw)
  To: David Gibson
  Cc: Jason Wang, Riku Voipio, qemu-devel, Laurent Vivier, qemu-ppc,
	clg, Paolo Bonzini, Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 21158 bytes --]

On Thu, 10 Oct 2019 13:02:09 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:

> On Wed, Oct 09, 2019 at 07:02:15PM +0200, Greg Kurz wrote:
> > On Wed,  9 Oct 2019 17:08:16 +1100
> > David Gibson <david@gibson.dropbear.id.au> wrote:
> > 
> > > The only thing remaining in this structure are the flags to allow either
> > > XICS or XIVE to be present.  These actually make more sense as spapr
> > > capabilities - that way they can take advantage of the existing
> > > infrastructure to sanity check capability states across migration and so
> > > forth.
> > > 
> > 
> > The user can now choose the interrupt controller mode either through
> > ic-mode or through cap-xics/cap-xive. I guess it doesn't break anything
> > to expose another API to do the same thing but it raises some questions.
> > 
> > We should at least document somewhere that ic-mode is an alias to these
> > caps, and maybe state which is the preferred method (I personally vote
> > for the caps).
> > 
> > Also, we must keep ic-mode for the moment to stay compatible with the
> > existing pseries-4.0 and pseries-4.1 machine types, but will we
> > keep ic-mode forever ? If no, maybe start by not allowing it for
> > pseries-4.2 ?
> 
> I'm actually inclined to keep it for now, maybe even leave it as the
> suggested way to configure this.  The caps are nice from an internal
> organization point of view, but ic-mode is arguably a more user
> friendly way of configuring it.  The conversion of one to the other is
> straightforward, isolated ans small, so I'm not especially bothered by
> keeping it around.
> 

Fair enough.

Reviewed-by: Greg Kurz <groug@kaod.org>

> > 
> > > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > > ---
> > >  hw/ppc/spapr.c             | 40 ++++++++++--------
> > >  hw/ppc/spapr_caps.c        | 64 +++++++++++++++++++++++++++++
> > >  hw/ppc/spapr_hcall.c       |  7 ++--
> > >  hw/ppc/spapr_irq.c         | 84 ++------------------------------------
> > >  include/hw/ppc/spapr.h     | 10 +++--
> > >  include/hw/ppc/spapr_irq.h | 10 -----
> > >  6 files changed, 103 insertions(+), 112 deletions(-)
> > > 
> > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > > index e1ff03152e..bf9fdb1693 100644
> > > --- a/hw/ppc/spapr.c
> > > +++ b/hw/ppc/spapr.c
> > > @@ -1072,12 +1072,13 @@ static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
> > >          26, 0x40, /* Radix options: GTSE == yes. */
> > >      };
> > >  
> > > -    if (spapr->irq->xics && spapr->irq->xive) {
> > > +    if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > > +        && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > >          val[1] = SPAPR_OV5_XIVE_BOTH;
> > > -    } else if (spapr->irq->xive) {
> > > +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > >          val[1] = SPAPR_OV5_XIVE_EXPLOIT;
> > >      } else {
> > > -        assert(spapr->irq->xics);
> > > +        assert(spapr_get_cap(spapr, SPAPR_CAP_XICS));
> > >          val[1] = SPAPR_OV5_XIVE_LEGACY;
> > >      }
> > >  
> > > @@ -2075,6 +2076,8 @@ static const VMStateDescription vmstate_spapr = {
> > >          &vmstate_spapr_dtb,
> > >          &vmstate_spapr_cap_large_decr,
> > >          &vmstate_spapr_cap_ccf_assist,
> > > +        &vmstate_spapr_cap_xics,
> > > +        &vmstate_spapr_cap_xive,
> > >          NULL
> > >      }
> > >  };
> > > @@ -2775,7 +2778,7 @@ static void spapr_machine_init(MachineState *machine)
> > >      spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2);
> > >  
> > >      /* advertise XIVE on POWER9 machines */
> > > -    if (spapr->irq->xive) {
> > > +    if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > >          spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
> > >      }
> > >  
> > > @@ -3242,14 +3245,18 @@ static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name,
> > >  static char *spapr_get_ic_mode(Object *obj, Error **errp)
> > >  {
> > >      SpaprMachineState *spapr = SPAPR_MACHINE(obj);
> > > +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> > >  
> > > -    if (spapr->irq == &spapr_irq_xics_legacy) {
> > > +    if (smc->legacy_irq_allocation) {
> > >          return g_strdup("legacy");
> > > -    } else if (spapr->irq == &spapr_irq_xics) {
> > > +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > > +               && !spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > >          return g_strdup("xics");
> > > -    } else if (spapr->irq == &spapr_irq_xive) {
> > > +    } else if (!spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > > +               && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > >          return g_strdup("xive");
> > > -    } else if (spapr->irq == &spapr_irq_dual) {
> > > +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > > +               && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > >          return g_strdup("dual");
> > >      }
> > >      g_assert_not_reached();
> > > @@ -3266,11 +3273,14 @@ static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
> > >  
> > >      /* The legacy IRQ backend can not be set */
> > >      if (strcmp(value, "xics") == 0) {
> > > -        spapr->irq = &spapr_irq_xics;
> > > +        object_property_set_bool(obj, true, "cap-xics", errp);
> > > +        object_property_set_bool(obj, false, "cap-xive", errp);
> > >      } else if (strcmp(value, "xive") == 0) {
> > > -        spapr->irq = &spapr_irq_xive;
> > > +        object_property_set_bool(obj, false, "cap-xics", errp);
> > > +        object_property_set_bool(obj, true, "cap-xive", errp);
> > >      } else if (strcmp(value, "dual") == 0) {
> > > -        spapr->irq = &spapr_irq_dual;
> > > +        object_property_set_bool(obj, true, "cap-xics", errp);
> > > +        object_property_set_bool(obj, true, "cap-xive", errp);
> > >      } else {
> > >          error_setg(errp, "Bad value for \"ic-mode\" property");
> > >      }
> > > @@ -3309,7 +3319,6 @@ static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
> > >  static void spapr_instance_init(Object *obj)
> > >  {
> > >      SpaprMachineState *spapr = SPAPR_MACHINE(obj);
> > > -    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> > >  
> > >      spapr->htab_fd = -1;
> > >      spapr->use_hotplug_event_source = true;
> > > @@ -3345,7 +3354,6 @@ static void spapr_instance_init(Object *obj)
> > >                               spapr_get_msix_emulation, NULL, NULL);
> > >  
> > >      /* The machine class defines the default interrupt controller mode */
> > > -    spapr->irq = smc->irq;
> > >      object_property_add_str(obj, "ic-mode", spapr_get_ic_mode,
> > >                              spapr_set_ic_mode, NULL);
> > >      object_property_set_description(obj, "ic-mode",
> > > @@ -4439,8 +4447,9 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
> > >      smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
> > >      smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
> > >      smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
> > > +    smc->default_caps.caps[SPAPR_CAP_XICS] = SPAPR_CAP_ON;
> > > +    smc->default_caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_ON;
> > >      spapr_caps_add_properties(smc, &error_abort);
> > > -    smc->irq = &spapr_irq_dual;
> > >      smc->dr_phb_enabled = true;
> > >      smc->linux_pci_probe = true;
> > >      smc->nr_xirqs = SPAPR_NR_XIRQS;
> > > @@ -4539,7 +4548,7 @@ static void spapr_machine_4_0_class_options(MachineClass *mc)
> > >      spapr_machine_4_1_class_options(mc);
> > >      compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
> > >      smc->phb_placement = phb_placement_4_0;
> > > -    smc->irq = &spapr_irq_xics;
> > > +    smc->default_caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_OFF;
> > >      smc->pre_4_1_migration = true;
> > >  }
> > >  
> > > @@ -4580,7 +4589,6 @@ static void spapr_machine_3_0_class_options(MachineClass *mc)
> > >  
> > >      smc->legacy_irq_allocation = true;
> > >      smc->nr_xirqs = 0x400;
> > > -    smc->irq = &spapr_irq_xics_legacy;
> > >  }
> > >  
> > >  DEFINE_SPAPR_MACHINE(3_0, "3.0", false);
> > > diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
> > > index 481dfd2a27..e06fd386f6 100644
> > > --- a/hw/ppc/spapr_caps.c
> > > +++ b/hw/ppc/spapr_caps.c
> > > @@ -496,6 +496,42 @@ static void cap_ccf_assist_apply(SpaprMachineState *spapr, uint8_t val,
> > >      }
> > >  }
> > >  
> > > +static void cap_xics_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
> > > +{
> > > +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> > > +
> > > +    if (!val) {
> > > +        if (!spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > > +            error_setg(errp,
> > > +"No interrupt controllers enabled, try cap-xics=on or cap-xive=on");
> > > +            return;
> > > +        }
> > > +
> > > +        if (smc->legacy_irq_allocation) {
> > > +            error_setg(errp, "This machine version requires XICS support");
> > > +            return;
> > > +        }
> > > +    }
> > > +}
> > > +
> > > +static void cap_xive_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
> > > +{
> > > +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> > > +    PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
> > > +
> > > +    if (val) {
> > > +        if (smc->legacy_irq_allocation) {
> > > +            error_setg(errp, "This machine version cannot support XIVE");
> > > +            return;
> > > +        }
> > > +        if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0,
> > > +                              spapr->max_compat_pvr)) {
> > > +            error_setg(errp, "XIVE requires POWER9 CPU");
> > > +            return;
> > > +        }
> > > +    }
> > > +}
> > > +
> > >  SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
> > >      [SPAPR_CAP_HTM] = {
> > >          .name = "htm",
> > > @@ -595,6 +631,24 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
> > >          .type = "bool",
> > >          .apply = cap_ccf_assist_apply,
> > >      },
> > > +    [SPAPR_CAP_XICS] = {
> > > +        .name = "xics",
> > > +        .description = "Allow XICS interrupt controller",
> > > +        .index = SPAPR_CAP_XICS,
> > > +        .get = spapr_cap_get_bool,
> > > +        .set = spapr_cap_set_bool,
> > > +        .type = "bool",
> > > +        .apply = cap_xics_apply,
> > > +    },
> > > +    [SPAPR_CAP_XIVE] = {
> > > +        .name = "xive",
> > > +        .description = "Allow XIVE interrupt controller",
> > > +        .index = SPAPR_CAP_XIVE,
> > > +        .get = spapr_cap_get_bool,
> > > +        .set = spapr_cap_set_bool,
> > > +        .type = "bool",
> > > +        .apply = cap_xive_apply,
> > > +    },
> > >  };
> > >  
> > >  static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
> > > @@ -641,6 +695,14 @@ static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
> > >          caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = mps;
> > >      }
> > >  
> > > +    /*
> > > +     * POWER8 machines don't have XIVE
> > > +     */
> > > +    if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_3_00,
> > > +                               0, spapr->max_compat_pvr)) {
> > > +        caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_OFF;
> > > +    }
> > > +
> > >      return caps;
> > >  }
> > >  
> > > @@ -734,6 +796,8 @@ SPAPR_CAP_MIG_STATE(hpt_maxpagesize, SPAPR_CAP_HPT_MAXPAGESIZE);
> > >  SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
> > >  SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
> > >  SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
> > > +SPAPR_CAP_MIG_STATE(xics, SPAPR_CAP_XICS);
> > > +SPAPR_CAP_MIG_STATE(xive, SPAPR_CAP_XIVE);
> > >  
> > >  void spapr_caps_init(SpaprMachineState *spapr)
> > >  {
> > > diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> > > index 140f05c1c6..cb4c6edf63 100644
> > > --- a/hw/ppc/spapr_hcall.c
> > > +++ b/hw/ppc/spapr_hcall.c
> > > @@ -1784,13 +1784,13 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
> > >       * terminate the boot.
> > >       */
> > >      if (guest_xive) {
> > > -        if (!spapr->irq->xive) {
> > > +        if (!spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > >              error_report(
> > >  "Guest requested unavailable interrupt mode (XIVE), try the ic-mode=xive or ic-mode=dual machine property");
> > >              exit(EXIT_FAILURE);
> > >          }
> > >      } else {
> > > -        if (!spapr->irq->xics) {
> > > +        if (!spapr_get_cap(spapr, SPAPR_CAP_XICS)) {
> > >              error_report(
> > >  "Guest requested unavailable interrupt mode (XICS), either don't set the ic-mode machine property or try ic-mode=xics or ic-mode=dual");
> > >              exit(EXIT_FAILURE);
> > > @@ -1804,7 +1804,8 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
> > >       */
> > >      if (!spapr->cas_reboot) {
> > >          spapr->cas_reboot = spapr_ovec_test(ov5_updates, OV5_XIVE_EXPLOIT)
> > > -            && spapr->irq->xics && spapr->irq->xive;
> > > +            && spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > > +            && spapr_get_cap(spapr, SPAPR_CAP_XIVE);
> > >      }
> > >  
> > >      spapr_ovec_cleanup(ov5_updates);
> > > diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> > > index 2768f9a765..473fc8780a 100644
> > > --- a/hw/ppc/spapr_irq.c
> > > +++ b/hw/ppc/spapr_irq.c
> > > @@ -101,90 +101,19 @@ int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
> > >      return 0;
> > >  }
> > >  
> > > -/*
> > > - * XICS IRQ backend.
> > > - */
> > > -
> > > -SpaprIrq spapr_irq_xics = {
> > > -    .xics        = true,
> > > -    .xive        = false,
> > > -};
> > > -
> > > -/*
> > > - * XIVE IRQ backend.
> > > - */
> > > -
> > > -SpaprIrq spapr_irq_xive = {
> > > -    .xics        = false,
> > > -    .xive        = true,
> > > -};
> > > -
> > > -/*
> > > - * Dual XIVE and XICS IRQ backend.
> > > - *
> > > - * Both interrupt mode, XIVE and XICS, objects are created but the
> > > - * machine starts in legacy interrupt mode (XICS). It can be changed
> > > - * by the CAS negotiation process and, in that case, the new mode is
> > > - * activated after an extra machine reset.
> > > - */
> > > -
> > > -/*
> > > - * Define values in sync with the XIVE and XICS backend
> > > - */
> > > -SpaprIrq spapr_irq_dual = {
> > > -    .xics        = true,
> > > -    .xive        = true,
> > > -};
> > > -
> > > -
> > >  static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
> > >  {
> > >      MachineState *machine = MACHINE(spapr);
> > >  
> > > -    /*
> > > -     * Sanity checks on non-P9 machines. On these, XIVE is not
> > > -     * advertised, see spapr_dt_ov5_platform_support()
> > > -     */
> > > -    if (!ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00,
> > > -                               0, spapr->max_compat_pvr)) {
> > > -        /*
> > > -         * If the 'dual' interrupt mode is selected, force XICS as CAS
> > > -         * negotiation is useless.
> > > -         */
> > > -        if (spapr->irq == &spapr_irq_dual) {
> > > -            spapr->irq = &spapr_irq_xics;
> > > -            return 0;
> > > -        }
> > > -
> > > -        /*
> > > -         * Non-P9 machines using only XIVE is a bogus setup. We have two
> > > -         * scenarios to take into account because of the compat mode:
> > > -         *
> > > -         * 1. POWER7/8 machines should fail to init later on when creating
> > > -         *    the XIVE interrupt presenters because a POWER9 exception
> > > -         *    model is required.
> > > -
> > > -         * 2. POWER9 machines using the POWER8 compat mode won't fail and
> > > -         *    will let the OS boot with a partial XIVE setup : DT
> > > -         *    properties but no hcalls.
> > > -         *
> > > -         * To cover both and not confuse the OS, add an early failure in
> > > -         * QEMU.
> > > -         */
> > > -        if (spapr->irq == &spapr_irq_xive) {
> > > -            error_setg(errp, "XIVE-only machines require a POWER9 CPU");
> > > -            return -1;
> > > -        }
> > > -    }
> > > -
> > >      /*
> > >       * On a POWER9 host, some older KVM XICS devices cannot be destroyed and
> > >       * re-created. Detect that early to avoid QEMU to exit later when the
> > >       * guest reboots.
> > >       */
> > >      if (kvm_enabled() &&
> > > -        spapr->irq == &spapr_irq_dual &&
> > >          machine_kernel_irqchip_required(machine) &&
> > > +        spapr_get_cap(spapr, SPAPR_CAP_XICS) &&
> > > +        spapr_get_cap(spapr, SPAPR_CAP_XIVE) &&
> > >          xics_kvm_has_broken_disconnect(spapr)) {
> > >          error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on");
> > >          return -1;
> > > @@ -280,7 +209,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
> > >      /* Initialize the MSI IRQ allocator. */
> > >      spapr_irq_msi_init(spapr);
> > >  
> > > -    if (spapr->irq->xics) {
> > > +    if (spapr_get_cap(spapr, SPAPR_CAP_XICS)) {
> > >          Error *local_err = NULL;
> > >          Object *obj;
> > >  
> > > @@ -313,7 +242,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
> > >          spapr->ics = ICS_SPAPR(obj);
> > >      }
> > >  
> > > -    if (spapr->irq->xive) {
> > > +    if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > >          uint32_t nr_servers = spapr_max_server_number(spapr);
> > >          DeviceState *dev;
> > >          int i;
> > > @@ -558,11 +487,6 @@ int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
> > >      return first + ics->offset;
> > >  }
> > >  
> > > -SpaprIrq spapr_irq_xics_legacy = {
> > > -    .xics        = true,
> > > -    .xive        = false,
> > > -};
> > > -
> > >  static void spapr_irq_register_types(void)
> > >  {
> > >      type_register_static(&spapr_intc_info);
> > > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> > > index 623e8e3f93..d3b4dd7de3 100644
> > > --- a/include/hw/ppc/spapr.h
> > > +++ b/include/hw/ppc/spapr.h
> > > @@ -79,8 +79,12 @@ typedef enum {
> > >  #define SPAPR_CAP_LARGE_DECREMENTER     0x08
> > >  /* Count Cache Flush Assist HW Instruction */
> > >  #define SPAPR_CAP_CCF_ASSIST            0x09
> > > +/* XICS interrupt controller */
> > > +#define SPAPR_CAP_XICS                  0x0a
> > > +/* XIVE interrupt controller */
> > > +#define SPAPR_CAP_XIVE                  0x0b
> > >  /* Num Caps */
> > > -#define SPAPR_CAP_NUM                   (SPAPR_CAP_CCF_ASSIST + 1)
> > > +#define SPAPR_CAP_NUM                   (SPAPR_CAP_XIVE + 1)
> > >  
> > >  /*
> > >   * Capability Values
> > > @@ -131,7 +135,6 @@ struct SpaprMachineClass {
> > >                            hwaddr *nv2atsd, Error **errp);
> > >      SpaprResizeHpt resize_hpt_default;
> > >      SpaprCapabilities default_caps;
> > > -    SpaprIrq *irq;
> > >  };
> > >  
> > >  /**
> > > @@ -195,7 +198,6 @@ struct SpaprMachineState {
> > >  
> > >      int32_t irq_map_nr;
> > >      unsigned long *irq_map;
> > > -    SpaprIrq *irq;
> > >      qemu_irq *qirqs;
> > >      SpaprInterruptController *active_intc;
> > >      ICSState *ics;
> > > @@ -870,6 +872,8 @@ extern const VMStateDescription vmstate_spapr_cap_hpt_maxpagesize;
> > >  extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
> > >  extern const VMStateDescription vmstate_spapr_cap_large_decr;
> > >  extern const VMStateDescription vmstate_spapr_cap_ccf_assist;
> > > +extern const VMStateDescription vmstate_spapr_cap_xics;
> > > +extern const VMStateDescription vmstate_spapr_cap_xive;
> > >  
> > >  static inline uint8_t spapr_get_cap(SpaprMachineState *spapr, int cap)
> > >  {
> > > diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> > > index 5e150a6679..71aee13743 100644
> > > --- a/include/hw/ppc/spapr_irq.h
> > > +++ b/include/hw/ppc/spapr_irq.h
> > > @@ -77,16 +77,6 @@ int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
> > >                          Error **errp);
> > >  void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num);
> > >  
> > > -typedef struct SpaprIrq {
> > > -    bool        xics;
> > > -    bool        xive;
> > > -} SpaprIrq;
> > > -
> > > -extern SpaprIrq spapr_irq_xics;
> > > -extern SpaprIrq spapr_irq_xics_legacy;
> > > -extern SpaprIrq spapr_irq_xive;
> > > -extern SpaprIrq spapr_irq_dual;
> > > -
> > >  void spapr_irq_init(SpaprMachineState *spapr, Error **errp);
> > >  int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp);
> > >  void spapr_irq_free(SpaprMachineState *spapr, int irq, int num);
> > 
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq
  2019-10-10  6:29       ` Greg Kurz
@ 2019-10-10 20:33         ` Greg Kurz
  2019-10-11  5:07           ` David Gibson
  0 siblings, 1 reply; 54+ messages in thread
From: Greg Kurz @ 2019-10-10 20:33 UTC (permalink / raw)
  To: David Gibson
  Cc: Jason Wang, Riku Voipio, qemu-devel, qemu-ppc, clg,
	Marc-André Lureau, Paolo Bonzini, philmd

[-- Attachment #1: Type: text/plain, Size: 24085 bytes --]

On Thu, 10 Oct 2019 08:29:58 +0200
Greg Kurz <groug@kaod.org> wrote:

> On Thu, 10 Oct 2019 13:02:09 +1100
> David Gibson <david@gibson.dropbear.id.au> wrote:
> 
> > On Wed, Oct 09, 2019 at 07:02:15PM +0200, Greg Kurz wrote:
> > > On Wed,  9 Oct 2019 17:08:16 +1100
> > > David Gibson <david@gibson.dropbear.id.au> wrote:
> > > 
> > > > The only thing remaining in this structure are the flags to allow either
> > > > XICS or XIVE to be present.  These actually make more sense as spapr
> > > > capabilities - that way they can take advantage of the existing
> > > > infrastructure to sanity check capability states across migration and so
> > > > forth.
> > > > 
> > > 
> > > The user can now choose the interrupt controller mode either through
> > > ic-mode or through cap-xics/cap-xive. I guess it doesn't break anything
> > > to expose another API to do the same thing but it raises some questions.
> > > 
> > > We should at least document somewhere that ic-mode is an alias to these
> > > caps, and maybe state which is the preferred method (I personally vote
> > > for the caps).
> > > 
> > > Also, we must keep ic-mode for the moment to stay compatible with the
> > > existing pseries-4.0 and pseries-4.1 machine types, but will we
> > > keep ic-mode forever ? If no, maybe start by not allowing it for
> > > pseries-4.2 ?
> > 
> > I'm actually inclined to keep it for now, maybe even leave it as the
> > suggested way to configure this.  The caps are nice from an internal
> > organization point of view, but ic-mode is arguably a more user
> > friendly way of configuring it.  The conversion of one to the other is
> > straightforward, isolated ans small, so I'm not especially bothered by
> > keeping it around.
> > 
> 
> Fair enough.
> 
> Reviewed-by: Greg Kurz <groug@kaod.org>
> 

But unfortunately this still requires care :-\

qemu-system-ppc64: cap-xive higher level (1) in incoming stream than on destination (0)
qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr'
qemu-system-ppc64: load of migration failed: Invalid argument

or

qemu-system-ppc64: cap-xics higher level (1) in incoming stream than on destination (0)
qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr'
qemu-system-ppc64: load of migration failed: Invalid argument

when migrating from QEMU 4.1 with ic-mode=xics and ic-mode=xive respectively.

This happens because the existing pseries-4.1 machine type doesn't send the
new caps and the logic in spapr_caps_post_migration() wrongly assumes that
the source has both caps set:

    srccaps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
    for (i = 0; i < SPAPR_CAP_NUM; i++) {
        /* If not default value then assume came in with the migration */
        if (spapr->mig.caps[i] != spapr->def.caps[i]) {

spapr->mig.caps[SPAPR_CAP_XICS] = 0
spapr->mig.caps[SPAPR_CAP_XIVE] = 0

            srccaps.caps[i] = spapr->mig.caps[i];

srcaps.caps[SPAPR_CAP_XICS] = 1
srcaps.caps[SPAPR_CAP_XIVE] = 1

        }
    }

and breaks

    for (i = 0; i < SPAPR_CAP_NUM; i++) {
        SpaprCapabilityInfo *info = &capability_table[i];

        if (srccaps.caps[i] > dstcaps.caps[i]) {

srcaps.caps[SPAPR_CAP_XICS] = 0 when ic-mode=xive
srcaps.caps[SPAPR_CAP_XIVE] = 0 when ic-mode=xics

            error_report("cap-%s higher level (%d) in incoming stream than on destination (%d)",
                         info->name, srccaps.caps[i], dstcaps.caps[i]);
            ok = false;
        }

Maybe we shouldn't check capabilities that we know the source
isn't supposed to send, eg. by having a smc->max_cap ?

> > > 
> > > > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > > > ---
> > > >  hw/ppc/spapr.c             | 40 ++++++++++--------
> > > >  hw/ppc/spapr_caps.c        | 64 +++++++++++++++++++++++++++++
> > > >  hw/ppc/spapr_hcall.c       |  7 ++--
> > > >  hw/ppc/spapr_irq.c         | 84 ++------------------------------------
> > > >  include/hw/ppc/spapr.h     | 10 +++--
> > > >  include/hw/ppc/spapr_irq.h | 10 -----
> > > >  6 files changed, 103 insertions(+), 112 deletions(-)
> > > > 
> > > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > > > index e1ff03152e..bf9fdb1693 100644
> > > > --- a/hw/ppc/spapr.c
> > > > +++ b/hw/ppc/spapr.c
> > > > @@ -1072,12 +1072,13 @@ static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
> > > >          26, 0x40, /* Radix options: GTSE == yes. */
> > > >      };
> > > >  
> > > > -    if (spapr->irq->xics && spapr->irq->xive) {
> > > > +    if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > > > +        && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > > >          val[1] = SPAPR_OV5_XIVE_BOTH;
> > > > -    } else if (spapr->irq->xive) {
> > > > +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > > >          val[1] = SPAPR_OV5_XIVE_EXPLOIT;
> > > >      } else {
> > > > -        assert(spapr->irq->xics);
> > > > +        assert(spapr_get_cap(spapr, SPAPR_CAP_XICS));
> > > >          val[1] = SPAPR_OV5_XIVE_LEGACY;
> > > >      }
> > > >  
> > > > @@ -2075,6 +2076,8 @@ static const VMStateDescription vmstate_spapr = {
> > > >          &vmstate_spapr_dtb,
> > > >          &vmstate_spapr_cap_large_decr,
> > > >          &vmstate_spapr_cap_ccf_assist,
> > > > +        &vmstate_spapr_cap_xics,
> > > > +        &vmstate_spapr_cap_xive,
> > > >          NULL
> > > >      }
> > > >  };
> > > > @@ -2775,7 +2778,7 @@ static void spapr_machine_init(MachineState *machine)
> > > >      spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2);
> > > >  
> > > >      /* advertise XIVE on POWER9 machines */
> > > > -    if (spapr->irq->xive) {
> > > > +    if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > > >          spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
> > > >      }
> > > >  
> > > > @@ -3242,14 +3245,18 @@ static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name,
> > > >  static char *spapr_get_ic_mode(Object *obj, Error **errp)
> > > >  {
> > > >      SpaprMachineState *spapr = SPAPR_MACHINE(obj);
> > > > +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> > > >  
> > > > -    if (spapr->irq == &spapr_irq_xics_legacy) {
> > > > +    if (smc->legacy_irq_allocation) {
> > > >          return g_strdup("legacy");
> > > > -    } else if (spapr->irq == &spapr_irq_xics) {
> > > > +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > > > +               && !spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > > >          return g_strdup("xics");
> > > > -    } else if (spapr->irq == &spapr_irq_xive) {
> > > > +    } else if (!spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > > > +               && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > > >          return g_strdup("xive");
> > > > -    } else if (spapr->irq == &spapr_irq_dual) {
> > > > +    } else if (spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > > > +               && spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > > >          return g_strdup("dual");
> > > >      }
> > > >      g_assert_not_reached();
> > > > @@ -3266,11 +3273,14 @@ static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
> > > >  
> > > >      /* The legacy IRQ backend can not be set */
> > > >      if (strcmp(value, "xics") == 0) {
> > > > -        spapr->irq = &spapr_irq_xics;
> > > > +        object_property_set_bool(obj, true, "cap-xics", errp);
> > > > +        object_property_set_bool(obj, false, "cap-xive", errp);
> > > >      } else if (strcmp(value, "xive") == 0) {
> > > > -        spapr->irq = &spapr_irq_xive;
> > > > +        object_property_set_bool(obj, false, "cap-xics", errp);
> > > > +        object_property_set_bool(obj, true, "cap-xive", errp);
> > > >      } else if (strcmp(value, "dual") == 0) {
> > > > -        spapr->irq = &spapr_irq_dual;
> > > > +        object_property_set_bool(obj, true, "cap-xics", errp);
> > > > +        object_property_set_bool(obj, true, "cap-xive", errp);
> > > >      } else {
> > > >          error_setg(errp, "Bad value for \"ic-mode\" property");
> > > >      }
> > > > @@ -3309,7 +3319,6 @@ static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
> > > >  static void spapr_instance_init(Object *obj)
> > > >  {
> > > >      SpaprMachineState *spapr = SPAPR_MACHINE(obj);
> > > > -    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> > > >  
> > > >      spapr->htab_fd = -1;
> > > >      spapr->use_hotplug_event_source = true;
> > > > @@ -3345,7 +3354,6 @@ static void spapr_instance_init(Object *obj)
> > > >                               spapr_get_msix_emulation, NULL, NULL);
> > > >  
> > > >      /* The machine class defines the default interrupt controller mode */
> > > > -    spapr->irq = smc->irq;
> > > >      object_property_add_str(obj, "ic-mode", spapr_get_ic_mode,
> > > >                              spapr_set_ic_mode, NULL);
> > > >      object_property_set_description(obj, "ic-mode",
> > > > @@ -4439,8 +4447,9 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
> > > >      smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
> > > >      smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
> > > >      smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
> > > > +    smc->default_caps.caps[SPAPR_CAP_XICS] = SPAPR_CAP_ON;
> > > > +    smc->default_caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_ON;
> > > >      spapr_caps_add_properties(smc, &error_abort);
> > > > -    smc->irq = &spapr_irq_dual;
> > > >      smc->dr_phb_enabled = true;
> > > >      smc->linux_pci_probe = true;
> > > >      smc->nr_xirqs = SPAPR_NR_XIRQS;
> > > > @@ -4539,7 +4548,7 @@ static void spapr_machine_4_0_class_options(MachineClass *mc)
> > > >      spapr_machine_4_1_class_options(mc);
> > > >      compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
> > > >      smc->phb_placement = phb_placement_4_0;
> > > > -    smc->irq = &spapr_irq_xics;
> > > > +    smc->default_caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_OFF;
> > > >      smc->pre_4_1_migration = true;
> > > >  }
> > > >  
> > > > @@ -4580,7 +4589,6 @@ static void spapr_machine_3_0_class_options(MachineClass *mc)
> > > >  
> > > >      smc->legacy_irq_allocation = true;
> > > >      smc->nr_xirqs = 0x400;
> > > > -    smc->irq = &spapr_irq_xics_legacy;
> > > >  }
> > > >  
> > > >  DEFINE_SPAPR_MACHINE(3_0, "3.0", false);
> > > > diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
> > > > index 481dfd2a27..e06fd386f6 100644
> > > > --- a/hw/ppc/spapr_caps.c
> > > > +++ b/hw/ppc/spapr_caps.c
> > > > @@ -496,6 +496,42 @@ static void cap_ccf_assist_apply(SpaprMachineState *spapr, uint8_t val,
> > > >      }
> > > >  }
> > > >  
> > > > +static void cap_xics_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
> > > > +{
> > > > +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> > > > +
> > > > +    if (!val) {
> > > > +        if (!spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > > > +            error_setg(errp,
> > > > +"No interrupt controllers enabled, try cap-xics=on or cap-xive=on");
> > > > +            return;
> > > > +        }
> > > > +
> > > > +        if (smc->legacy_irq_allocation) {
> > > > +            error_setg(errp, "This machine version requires XICS support");
> > > > +            return;
> > > > +        }
> > > > +    }
> > > > +}
> > > > +
> > > > +static void cap_xive_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
> > > > +{
> > > > +    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
> > > > +    PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
> > > > +
> > > > +    if (val) {
> > > > +        if (smc->legacy_irq_allocation) {
> > > > +            error_setg(errp, "This machine version cannot support XIVE");
> > > > +            return;
> > > > +        }
> > > > +        if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0,
> > > > +                              spapr->max_compat_pvr)) {
> > > > +            error_setg(errp, "XIVE requires POWER9 CPU");
> > > > +            return;
> > > > +        }
> > > > +    }
> > > > +}
> > > > +
> > > >  SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
> > > >      [SPAPR_CAP_HTM] = {
> > > >          .name = "htm",
> > > > @@ -595,6 +631,24 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
> > > >          .type = "bool",
> > > >          .apply = cap_ccf_assist_apply,
> > > >      },
> > > > +    [SPAPR_CAP_XICS] = {
> > > > +        .name = "xics",
> > > > +        .description = "Allow XICS interrupt controller",
> > > > +        .index = SPAPR_CAP_XICS,
> > > > +        .get = spapr_cap_get_bool,
> > > > +        .set = spapr_cap_set_bool,
> > > > +        .type = "bool",
> > > > +        .apply = cap_xics_apply,
> > > > +    },
> > > > +    [SPAPR_CAP_XIVE] = {
> > > > +        .name = "xive",
> > > > +        .description = "Allow XIVE interrupt controller",
> > > > +        .index = SPAPR_CAP_XIVE,
> > > > +        .get = spapr_cap_get_bool,
> > > > +        .set = spapr_cap_set_bool,
> > > > +        .type = "bool",
> > > > +        .apply = cap_xive_apply,
> > > > +    },
> > > >  };
> > > >  
> > > >  static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
> > > > @@ -641,6 +695,14 @@ static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
> > > >          caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = mps;
> > > >      }
> > > >  
> > > > +    /*
> > > > +     * POWER8 machines don't have XIVE
> > > > +     */
> > > > +    if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_3_00,
> > > > +                               0, spapr->max_compat_pvr)) {
> > > > +        caps.caps[SPAPR_CAP_XIVE] = SPAPR_CAP_OFF;
> > > > +    }
> > > > +
> > > >      return caps;
> > > >  }
> > > >  
> > > > @@ -734,6 +796,8 @@ SPAPR_CAP_MIG_STATE(hpt_maxpagesize, SPAPR_CAP_HPT_MAXPAGESIZE);
> > > >  SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
> > > >  SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
> > > >  SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
> > > > +SPAPR_CAP_MIG_STATE(xics, SPAPR_CAP_XICS);
> > > > +SPAPR_CAP_MIG_STATE(xive, SPAPR_CAP_XIVE);
> > > >  
> > > >  void spapr_caps_init(SpaprMachineState *spapr)
> > > >  {
> > > > diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> > > > index 140f05c1c6..cb4c6edf63 100644
> > > > --- a/hw/ppc/spapr_hcall.c
> > > > +++ b/hw/ppc/spapr_hcall.c
> > > > @@ -1784,13 +1784,13 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
> > > >       * terminate the boot.
> > > >       */
> > > >      if (guest_xive) {
> > > > -        if (!spapr->irq->xive) {
> > > > +        if (!spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > > >              error_report(
> > > >  "Guest requested unavailable interrupt mode (XIVE), try the ic-mode=xive or ic-mode=dual machine property");
> > > >              exit(EXIT_FAILURE);
> > > >          }
> > > >      } else {
> > > > -        if (!spapr->irq->xics) {
> > > > +        if (!spapr_get_cap(spapr, SPAPR_CAP_XICS)) {
> > > >              error_report(
> > > >  "Guest requested unavailable interrupt mode (XICS), either don't set the ic-mode machine property or try ic-mode=xics or ic-mode=dual");
> > > >              exit(EXIT_FAILURE);
> > > > @@ -1804,7 +1804,8 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
> > > >       */
> > > >      if (!spapr->cas_reboot) {
> > > >          spapr->cas_reboot = spapr_ovec_test(ov5_updates, OV5_XIVE_EXPLOIT)
> > > > -            && spapr->irq->xics && spapr->irq->xive;
> > > > +            && spapr_get_cap(spapr, SPAPR_CAP_XICS)
> > > > +            && spapr_get_cap(spapr, SPAPR_CAP_XIVE);
> > > >      }
> > > >  
> > > >      spapr_ovec_cleanup(ov5_updates);
> > > > diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
> > > > index 2768f9a765..473fc8780a 100644
> > > > --- a/hw/ppc/spapr_irq.c
> > > > +++ b/hw/ppc/spapr_irq.c
> > > > @@ -101,90 +101,19 @@ int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
> > > >      return 0;
> > > >  }
> > > >  
> > > > -/*
> > > > - * XICS IRQ backend.
> > > > - */
> > > > -
> > > > -SpaprIrq spapr_irq_xics = {
> > > > -    .xics        = true,
> > > > -    .xive        = false,
> > > > -};
> > > > -
> > > > -/*
> > > > - * XIVE IRQ backend.
> > > > - */
> > > > -
> > > > -SpaprIrq spapr_irq_xive = {
> > > > -    .xics        = false,
> > > > -    .xive        = true,
> > > > -};
> > > > -
> > > > -/*
> > > > - * Dual XIVE and XICS IRQ backend.
> > > > - *
> > > > - * Both interrupt mode, XIVE and XICS, objects are created but the
> > > > - * machine starts in legacy interrupt mode (XICS). It can be changed
> > > > - * by the CAS negotiation process and, in that case, the new mode is
> > > > - * activated after an extra machine reset.
> > > > - */
> > > > -
> > > > -/*
> > > > - * Define values in sync with the XIVE and XICS backend
> > > > - */
> > > > -SpaprIrq spapr_irq_dual = {
> > > > -    .xics        = true,
> > > > -    .xive        = true,
> > > > -};
> > > > -
> > > > -
> > > >  static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
> > > >  {
> > > >      MachineState *machine = MACHINE(spapr);
> > > >  
> > > > -    /*
> > > > -     * Sanity checks on non-P9 machines. On these, XIVE is not
> > > > -     * advertised, see spapr_dt_ov5_platform_support()
> > > > -     */
> > > > -    if (!ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00,
> > > > -                               0, spapr->max_compat_pvr)) {
> > > > -        /*
> > > > -         * If the 'dual' interrupt mode is selected, force XICS as CAS
> > > > -         * negotiation is useless.
> > > > -         */
> > > > -        if (spapr->irq == &spapr_irq_dual) {
> > > > -            spapr->irq = &spapr_irq_xics;
> > > > -            return 0;
> > > > -        }
> > > > -
> > > > -        /*
> > > > -         * Non-P9 machines using only XIVE is a bogus setup. We have two
> > > > -         * scenarios to take into account because of the compat mode:
> > > > -         *
> > > > -         * 1. POWER7/8 machines should fail to init later on when creating
> > > > -         *    the XIVE interrupt presenters because a POWER9 exception
> > > > -         *    model is required.
> > > > -
> > > > -         * 2. POWER9 machines using the POWER8 compat mode won't fail and
> > > > -         *    will let the OS boot with a partial XIVE setup : DT
> > > > -         *    properties but no hcalls.
> > > > -         *
> > > > -         * To cover both and not confuse the OS, add an early failure in
> > > > -         * QEMU.
> > > > -         */
> > > > -        if (spapr->irq == &spapr_irq_xive) {
> > > > -            error_setg(errp, "XIVE-only machines require a POWER9 CPU");
> > > > -            return -1;
> > > > -        }
> > > > -    }
> > > > -
> > > >      /*
> > > >       * On a POWER9 host, some older KVM XICS devices cannot be destroyed and
> > > >       * re-created. Detect that early to avoid QEMU to exit later when the
> > > >       * guest reboots.
> > > >       */
> > > >      if (kvm_enabled() &&
> > > > -        spapr->irq == &spapr_irq_dual &&
> > > >          machine_kernel_irqchip_required(machine) &&
> > > > +        spapr_get_cap(spapr, SPAPR_CAP_XICS) &&
> > > > +        spapr_get_cap(spapr, SPAPR_CAP_XIVE) &&
> > > >          xics_kvm_has_broken_disconnect(spapr)) {
> > > >          error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on");
> > > >          return -1;
> > > > @@ -280,7 +209,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
> > > >      /* Initialize the MSI IRQ allocator. */
> > > >      spapr_irq_msi_init(spapr);
> > > >  
> > > > -    if (spapr->irq->xics) {
> > > > +    if (spapr_get_cap(spapr, SPAPR_CAP_XICS)) {
> > > >          Error *local_err = NULL;
> > > >          Object *obj;
> > > >  
> > > > @@ -313,7 +242,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
> > > >          spapr->ics = ICS_SPAPR(obj);
> > > >      }
> > > >  
> > > > -    if (spapr->irq->xive) {
> > > > +    if (spapr_get_cap(spapr, SPAPR_CAP_XIVE)) {
> > > >          uint32_t nr_servers = spapr_max_server_number(spapr);
> > > >          DeviceState *dev;
> > > >          int i;
> > > > @@ -558,11 +487,6 @@ int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
> > > >      return first + ics->offset;
> > > >  }
> > > >  
> > > > -SpaprIrq spapr_irq_xics_legacy = {
> > > > -    .xics        = true,
> > > > -    .xive        = false,
> > > > -};
> > > > -
> > > >  static void spapr_irq_register_types(void)
> > > >  {
> > > >      type_register_static(&spapr_intc_info);
> > > > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> > > > index 623e8e3f93..d3b4dd7de3 100644
> > > > --- a/include/hw/ppc/spapr.h
> > > > +++ b/include/hw/ppc/spapr.h
> > > > @@ -79,8 +79,12 @@ typedef enum {
> > > >  #define SPAPR_CAP_LARGE_DECREMENTER     0x08
> > > >  /* Count Cache Flush Assist HW Instruction */
> > > >  #define SPAPR_CAP_CCF_ASSIST            0x09
> > > > +/* XICS interrupt controller */
> > > > +#define SPAPR_CAP_XICS                  0x0a
> > > > +/* XIVE interrupt controller */
> > > > +#define SPAPR_CAP_XIVE                  0x0b
> > > >  /* Num Caps */
> > > > -#define SPAPR_CAP_NUM                   (SPAPR_CAP_CCF_ASSIST + 1)
> > > > +#define SPAPR_CAP_NUM                   (SPAPR_CAP_XIVE + 1)
> > > >  
> > > >  /*
> > > >   * Capability Values
> > > > @@ -131,7 +135,6 @@ struct SpaprMachineClass {
> > > >                            hwaddr *nv2atsd, Error **errp);
> > > >      SpaprResizeHpt resize_hpt_default;
> > > >      SpaprCapabilities default_caps;
> > > > -    SpaprIrq *irq;
> > > >  };
> > > >  
> > > >  /**
> > > > @@ -195,7 +198,6 @@ struct SpaprMachineState {
> > > >  
> > > >      int32_t irq_map_nr;
> > > >      unsigned long *irq_map;
> > > > -    SpaprIrq *irq;
> > > >      qemu_irq *qirqs;
> > > >      SpaprInterruptController *active_intc;
> > > >      ICSState *ics;
> > > > @@ -870,6 +872,8 @@ extern const VMStateDescription vmstate_spapr_cap_hpt_maxpagesize;
> > > >  extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
> > > >  extern const VMStateDescription vmstate_spapr_cap_large_decr;
> > > >  extern const VMStateDescription vmstate_spapr_cap_ccf_assist;
> > > > +extern const VMStateDescription vmstate_spapr_cap_xics;
> > > > +extern const VMStateDescription vmstate_spapr_cap_xive;
> > > >  
> > > >  static inline uint8_t spapr_get_cap(SpaprMachineState *spapr, int cap)
> > > >  {
> > > > diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
> > > > index 5e150a6679..71aee13743 100644
> > > > --- a/include/hw/ppc/spapr_irq.h
> > > > +++ b/include/hw/ppc/spapr_irq.h
> > > > @@ -77,16 +77,6 @@ int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
> > > >                          Error **errp);
> > > >  void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num);
> > > >  
> > > > -typedef struct SpaprIrq {
> > > > -    bool        xics;
> > > > -    bool        xive;
> > > > -} SpaprIrq;
> > > > -
> > > > -extern SpaprIrq spapr_irq_xics;
> > > > -extern SpaprIrq spapr_irq_xics_legacy;
> > > > -extern SpaprIrq spapr_irq_xive;
> > > > -extern SpaprIrq spapr_irq_dual;
> > > > -
> > > >  void spapr_irq_init(SpaprMachineState *spapr, Error **errp);
> > > >  int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp);
> > > >  void spapr_irq_free(SpaprMachineState *spapr, int irq, int num);
> > > 
> > 
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq
  2019-10-10 20:33         ` Greg Kurz
@ 2019-10-11  5:07           ` David Gibson
  2019-10-11  6:13             ` Greg Kurz
  0 siblings, 1 reply; 54+ messages in thread
From: David Gibson @ 2019-10-11  5:07 UTC (permalink / raw)
  To: Greg Kurz
  Cc: Jason Wang, Riku Voipio, qemu-devel, qemu-ppc, clg,
	Marc-André Lureau, Paolo Bonzini, philmd

[-- Attachment #1: Type: text/plain, Size: 4533 bytes --]

On Thu, Oct 10, 2019 at 10:33:04PM +0200, Greg Kurz wrote:
> On Thu, 10 Oct 2019 08:29:58 +0200
> Greg Kurz <groug@kaod.org> wrote:
> 
> > On Thu, 10 Oct 2019 13:02:09 +1100
> > David Gibson <david@gibson.dropbear.id.au> wrote:
> > 
> > > On Wed, Oct 09, 2019 at 07:02:15PM +0200, Greg Kurz wrote:
> > > > On Wed,  9 Oct 2019 17:08:16 +1100
> > > > David Gibson <david@gibson.dropbear.id.au> wrote:
> > > > 
> > > > > The only thing remaining in this structure are the flags to allow either
> > > > > XICS or XIVE to be present.  These actually make more sense as spapr
> > > > > capabilities - that way they can take advantage of the existing
> > > > > infrastructure to sanity check capability states across migration and so
> > > > > forth.
> > > > > 
> > > > 
> > > > The user can now choose the interrupt controller mode either through
> > > > ic-mode or through cap-xics/cap-xive. I guess it doesn't break anything
> > > > to expose another API to do the same thing but it raises some questions.
> > > > 
> > > > We should at least document somewhere that ic-mode is an alias to these
> > > > caps, and maybe state which is the preferred method (I personally vote
> > > > for the caps).
> > > > 
> > > > Also, we must keep ic-mode for the moment to stay compatible with the
> > > > existing pseries-4.0 and pseries-4.1 machine types, but will we
> > > > keep ic-mode forever ? If no, maybe start by not allowing it for
> > > > pseries-4.2 ?
> > > 
> > > I'm actually inclined to keep it for now, maybe even leave it as the
> > > suggested way to configure this.  The caps are nice from an internal
> > > organization point of view, but ic-mode is arguably a more user
> > > friendly way of configuring it.  The conversion of one to the other is
> > > straightforward, isolated ans small, so I'm not especially bothered by
> > > keeping it around.
> > > 
> > 
> > Fair enough.
> > 
> > Reviewed-by: Greg Kurz <groug@kaod.org>
> > 
> 
> But unfortunately this still requires care :-\
> 
> qemu-system-ppc64: cap-xive higher level (1) in incoming stream than on destination (0)
> qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr'
> qemu-system-ppc64: load of migration failed: Invalid argument
> 
> or
> 
> qemu-system-ppc64: cap-xics higher level (1) in incoming stream than on destination (0)
> qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr'
> qemu-system-ppc64: load of migration failed: Invalid argument
> 
> when migrating from QEMU 4.1 with ic-mode=xics and ic-mode=xive respectively.
> 
> This happens because the existing pseries-4.1 machine type doesn't send the
> new caps and the logic in spapr_caps_post_migration() wrongly assumes that
> the source has both caps set:
> 
>     srccaps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
>     for (i = 0; i < SPAPR_CAP_NUM; i++) {
>         /* If not default value then assume came in with the migration */
>         if (spapr->mig.caps[i] != spapr->def.caps[i]) {
> 
> spapr->mig.caps[SPAPR_CAP_XICS] = 0
> spapr->mig.caps[SPAPR_CAP_XIVE] = 0
> 
>             srccaps.caps[i] = spapr->mig.caps[i];
> 
> srcaps.caps[SPAPR_CAP_XICS] = 1
> srcaps.caps[SPAPR_CAP_XIVE] = 1
> 
>         }
>     }
> 
> and breaks
> 
>     for (i = 0; i < SPAPR_CAP_NUM; i++) {
>         SpaprCapabilityInfo *info = &capability_table[i];
> 
>         if (srccaps.caps[i] > dstcaps.caps[i]) {
> 
> srcaps.caps[SPAPR_CAP_XICS] = 0 when ic-mode=xive
> srcaps.caps[SPAPR_CAP_XIVE] = 0 when ic-mode=xics
> 
>             error_report("cap-%s higher level (%d) in incoming stream than on destination (%d)",
>                          info->name, srccaps.caps[i], dstcaps.caps[i]);
>             ok = false;
>         }

Ah.. right.  I thought there would be problems with backwards
migration, but I didn't think of this problem even with forward
migration.

> Maybe we shouldn't check capabilities that we know the source
> isn't supposed to send, eg. by having a smc->max_cap ?

Uh.. I'm not really sure what exactly you're suggesting here.

I think what we need here is a custom migrate_needed function, like we
already have for cap_hpt_maxpagesize, to exclude it from the migration
stream for machine versions before 4.2.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq
  2019-10-11  5:07           ` David Gibson
@ 2019-10-11  6:13             ` Greg Kurz
  2019-10-11  8:33               ` Greg Kurz
  2019-10-12  0:00               ` David Gibson
  0 siblings, 2 replies; 54+ messages in thread
From: Greg Kurz @ 2019-10-11  6:13 UTC (permalink / raw)
  To: David Gibson
  Cc: Jason Wang, Riku Voipio, qemu-devel, qemu-ppc, clg,
	Paolo Bonzini, Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 5282 bytes --]

On Fri, 11 Oct 2019 16:07:58 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:

> On Thu, Oct 10, 2019 at 10:33:04PM +0200, Greg Kurz wrote:
> > On Thu, 10 Oct 2019 08:29:58 +0200
> > Greg Kurz <groug@kaod.org> wrote:
> > 
> > > On Thu, 10 Oct 2019 13:02:09 +1100
> > > David Gibson <david@gibson.dropbear.id.au> wrote:
> > > 
> > > > On Wed, Oct 09, 2019 at 07:02:15PM +0200, Greg Kurz wrote:
> > > > > On Wed,  9 Oct 2019 17:08:16 +1100
> > > > > David Gibson <david@gibson.dropbear.id.au> wrote:
> > > > > 
> > > > > > The only thing remaining in this structure are the flags to allow either
> > > > > > XICS or XIVE to be present.  These actually make more sense as spapr
> > > > > > capabilities - that way they can take advantage of the existing
> > > > > > infrastructure to sanity check capability states across migration and so
> > > > > > forth.
> > > > > > 
> > > > > 
> > > > > The user can now choose the interrupt controller mode either through
> > > > > ic-mode or through cap-xics/cap-xive. I guess it doesn't break anything
> > > > > to expose another API to do the same thing but it raises some questions.
> > > > > 
> > > > > We should at least document somewhere that ic-mode is an alias to these
> > > > > caps, and maybe state which is the preferred method (I personally vote
> > > > > for the caps).
> > > > > 
> > > > > Also, we must keep ic-mode for the moment to stay compatible with the
> > > > > existing pseries-4.0 and pseries-4.1 machine types, but will we
> > > > > keep ic-mode forever ? If no, maybe start by not allowing it for
> > > > > pseries-4.2 ?
> > > > 
> > > > I'm actually inclined to keep it for now, maybe even leave it as the
> > > > suggested way to configure this.  The caps are nice from an internal
> > > > organization point of view, but ic-mode is arguably a more user
> > > > friendly way of configuring it.  The conversion of one to the other is
> > > > straightforward, isolated ans small, so I'm not especially bothered by
> > > > keeping it around.
> > > > 
> > > 
> > > Fair enough.
> > > 
> > > Reviewed-by: Greg Kurz <groug@kaod.org>
> > > 
> > 
> > But unfortunately this still requires care :-\
> > 
> > qemu-system-ppc64: cap-xive higher level (1) in incoming stream than on destination (0)
> > qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr'
> > qemu-system-ppc64: load of migration failed: Invalid argument
> > 
> > or
> > 
> > qemu-system-ppc64: cap-xics higher level (1) in incoming stream than on destination (0)
> > qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr'
> > qemu-system-ppc64: load of migration failed: Invalid argument
> > 
> > when migrating from QEMU 4.1 with ic-mode=xics and ic-mode=xive respectively.
> > 
> > This happens because the existing pseries-4.1 machine type doesn't send the
> > new caps and the logic in spapr_caps_post_migration() wrongly assumes that
> > the source has both caps set:
> > 
> >     srccaps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
> >     for (i = 0; i < SPAPR_CAP_NUM; i++) {
> >         /* If not default value then assume came in with the migration */
> >         if (spapr->mig.caps[i] != spapr->def.caps[i]) {
> > 
> > spapr->mig.caps[SPAPR_CAP_XICS] = 0
> > spapr->mig.caps[SPAPR_CAP_XIVE] = 0
> > 
> >             srccaps.caps[i] = spapr->mig.caps[i];
> > 
> > srcaps.caps[SPAPR_CAP_XICS] = 1
> > srcaps.caps[SPAPR_CAP_XIVE] = 1
> > 
> >         }
> >     }
> > 
> > and breaks
> > 
> >     for (i = 0; i < SPAPR_CAP_NUM; i++) {
> >         SpaprCapabilityInfo *info = &capability_table[i];
> > 
> >         if (srccaps.caps[i] > dstcaps.caps[i]) {
> > 
> > srcaps.caps[SPAPR_CAP_XICS] = 0 when ic-mode=xive
> > srcaps.caps[SPAPR_CAP_XIVE] = 0 when ic-mode=xics
> > 
> >             error_report("cap-%s higher level (%d) in incoming stream than on destination (%d)",
> >                          info->name, srccaps.caps[i], dstcaps.caps[i]);
> >             ok = false;
> >         }
> 
> Ah.. right.  I thought there would be problems with backwards
> migration, but I didn't think of this problem even with forward
> migration.
> 
> > Maybe we shouldn't check capabilities that we know the source
> > isn't supposed to send, eg. by having a smc->max_cap ?
> 
> Uh.. I'm not really sure what exactly you're suggesting here.
> 

I'm suggesting to have a per-machine version smc->max_cap that
contains the highest supported cap index, to be used instead of
SPAPR_CAP_NUM in this functions, ie.

for (i = 0; i <= smc->max_cap; i++) {
    ...
}

where we would have

smc->max_cap = SPAPR_CAP_CCF_ASSIST for pseries-4.1

and

smc->max_cap = SPAPR_CAP_XIVE for psereis-4.2

> I think what we need here is a custom migrate_needed function, like we
> already have for cap_hpt_maxpagesize, to exclude it from the migration
> stream for machine versions before 4.2.
> 

No, VMState needed() hooks are for outgoing migration only.

bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque)
{
    if (vmsd->needed && !vmsd->needed(opaque)) {
        /* optional section not needed */
        return false;
    }
    return true;
}

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq
  2019-10-11  6:13             ` Greg Kurz
@ 2019-10-11  8:33               ` Greg Kurz
  2019-10-12  0:00               ` David Gibson
  1 sibling, 0 replies; 54+ messages in thread
From: Greg Kurz @ 2019-10-11  8:33 UTC (permalink / raw)
  To: David Gibson
  Cc: Jason Wang, Riku Voipio, qemu-devel, qemu-ppc, clg,
	Paolo Bonzini, Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 9657 bytes --]

On Fri, 11 Oct 2019 08:13:33 +0200
Greg Kurz <groug@kaod.org> wrote:

> On Fri, 11 Oct 2019 16:07:58 +1100
> David Gibson <david@gibson.dropbear.id.au> wrote:
> 
> > On Thu, Oct 10, 2019 at 10:33:04PM +0200, Greg Kurz wrote:
> > > On Thu, 10 Oct 2019 08:29:58 +0200
> > > Greg Kurz <groug@kaod.org> wrote:
> > > 
> > > > On Thu, 10 Oct 2019 13:02:09 +1100
> > > > David Gibson <david@gibson.dropbear.id.au> wrote:
> > > > 
> > > > > On Wed, Oct 09, 2019 at 07:02:15PM +0200, Greg Kurz wrote:
> > > > > > On Wed,  9 Oct 2019 17:08:16 +1100
> > > > > > David Gibson <david@gibson.dropbear.id.au> wrote:
> > > > > > 
> > > > > > > The only thing remaining in this structure are the flags to allow either
> > > > > > > XICS or XIVE to be present.  These actually make more sense as spapr
> > > > > > > capabilities - that way they can take advantage of the existing
> > > > > > > infrastructure to sanity check capability states across migration and so
> > > > > > > forth.
> > > > > > > 
> > > > > > 
> > > > > > The user can now choose the interrupt controller mode either through
> > > > > > ic-mode or through cap-xics/cap-xive. I guess it doesn't break anything
> > > > > > to expose another API to do the same thing but it raises some questions.
> > > > > > 
> > > > > > We should at least document somewhere that ic-mode is an alias to these
> > > > > > caps, and maybe state which is the preferred method (I personally vote
> > > > > > for the caps).
> > > > > > 
> > > > > > Also, we must keep ic-mode for the moment to stay compatible with the
> > > > > > existing pseries-4.0 and pseries-4.1 machine types, but will we
> > > > > > keep ic-mode forever ? If no, maybe start by not allowing it for
> > > > > > pseries-4.2 ?
> > > > > 
> > > > > I'm actually inclined to keep it for now, maybe even leave it as the
> > > > > suggested way to configure this.  The caps are nice from an internal
> > > > > organization point of view, but ic-mode is arguably a more user
> > > > > friendly way of configuring it.  The conversion of one to the other is
> > > > > straightforward, isolated ans small, so I'm not especially bothered by
> > > > > keeping it around.
> > > > > 
> > > > 
> > > > Fair enough.
> > > > 
> > > > Reviewed-by: Greg Kurz <groug@kaod.org>
> > > > 
> > > 
> > > But unfortunately this still requires care :-\
> > > 
> > > qemu-system-ppc64: cap-xive higher level (1) in incoming stream than on destination (0)
> > > qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr'
> > > qemu-system-ppc64: load of migration failed: Invalid argument
> > > 
> > > or
> > > 
> > > qemu-system-ppc64: cap-xics higher level (1) in incoming stream than on destination (0)
> > > qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr'
> > > qemu-system-ppc64: load of migration failed: Invalid argument
> > > 
> > > when migrating from QEMU 4.1 with ic-mode=xics and ic-mode=xive respectively.
> > > 
> > > This happens because the existing pseries-4.1 machine type doesn't send the
> > > new caps and the logic in spapr_caps_post_migration() wrongly assumes that
> > > the source has both caps set:
> > > 
> > >     srccaps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
> > >     for (i = 0; i < SPAPR_CAP_NUM; i++) {
> > >         /* If not default value then assume came in with the migration */
> > >         if (spapr->mig.caps[i] != spapr->def.caps[i]) {
> > > 
> > > spapr->mig.caps[SPAPR_CAP_XICS] = 0
> > > spapr->mig.caps[SPAPR_CAP_XIVE] = 0
> > > 
> > >             srccaps.caps[i] = spapr->mig.caps[i];
> > > 
> > > srcaps.caps[SPAPR_CAP_XICS] = 1
> > > srcaps.caps[SPAPR_CAP_XIVE] = 1
> > > 
> > >         }
> > >     }
> > > 
> > > and breaks
> > > 
> > >     for (i = 0; i < SPAPR_CAP_NUM; i++) {
> > >         SpaprCapabilityInfo *info = &capability_table[i];
> > > 
> > >         if (srccaps.caps[i] > dstcaps.caps[i]) {
> > > 
> > > srcaps.caps[SPAPR_CAP_XICS] = 0 when ic-mode=xive
> > > srcaps.caps[SPAPR_CAP_XIVE] = 0 when ic-mode=xics
> > > 
> > >             error_report("cap-%s higher level (%d) in incoming stream than on destination (%d)",
> > >                          info->name, srccaps.caps[i], dstcaps.caps[i]);
> > >             ok = false;
> > >         }
> > 
> > Ah.. right.  I thought there would be problems with backwards
> > migration, but I didn't think of this problem even with forward
> > migration.
> > 
> > > Maybe we shouldn't check capabilities that we know the source
> > > isn't supposed to send, eg. by having a smc->max_cap ?
> > 
> > Uh.. I'm not really sure what exactly you're suggesting here.
> > 
> 
> I'm suggesting to have a per-machine version smc->max_cap that
> contains the highest supported cap index, to be used instead of
> SPAPR_CAP_NUM in this functions, ie.
> 
> for (i = 0; i <= smc->max_cap; i++) {
>     ...
> }
> 
> where we would have
> 
> smc->max_cap = SPAPR_CAP_CCF_ASSIST for pseries-4.1
> 
> and
> 
> smc->max_cap = SPAPR_CAP_XIVE for psereis-4.2
> 
> > I think what we need here is a custom migrate_needed function, like we
> > already have for cap_hpt_maxpagesize, to exclude it from the migration
> > stream for machine versions before 4.2.
> > 
> 
> No, VMState needed() hooks are for outgoing migration only.
> 

Well we actually do need a needed() function to fix backward
migration, but it doesn't solve anything with forward migration.

I'm thinking about something like this to address both:

=======================================================================
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 66b68fdd5ef5..1342058c1aae 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -83,7 +83,12 @@ typedef enum {
 #define SPAPR_CAP_XICS                  0x0a
 /* XIVE interrupt controller */
 #define SPAPR_CAP_XIVE                  0x0b
-/* Num Caps */
+/*
+ * Num Caps.
+ *
+ * CAUTION: when new caps are being added, older machine types should
+ * set smc->mig_cap_num to the previous value of SPAPR_CAP_NUM.
+ */
 #define SPAPR_CAP_NUM                   (SPAPR_CAP_XIVE + 1)
 
 /*
@@ -135,6 +140,7 @@ struct SpaprMachineClass {
                           hwaddr *nv2atsd, Error **errp);
     SpaprResizeHpt resize_hpt_default;
     SpaprCapabilities default_caps;
+    int mig_cap_num; /* don't migrate newer capabilities */
 };
 
 /**
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index bf9fdb169303..fa81cedfbcc5 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4453,6 +4453,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
     smc->dr_phb_enabled = true;
     smc->linux_pci_probe = true;
     smc->nr_xirqs = SPAPR_NR_XIRQS;
+    smc->mig_cap_num = SPAPR_CAP_NUM;
 }
 
 static const TypeInfo spapr_machine_info = {
@@ -4520,6 +4521,7 @@ static void spapr_machine_4_1_class_options(MachineClass *mc)
 
     spapr_machine_4_2_class_options(mc);
     smc->linux_pci_probe = false;
+    smc->mig_cap_num = SPAPR_CAP_CCF_ASSIST + 1;
     compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len);
     compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
 }
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index e06fd386f6ac..ba079f46e084 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -532,6 +532,13 @@ static void cap_xive_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
     }
 }
 
+static bool cap_xics_xive_migrate_needed(void *opaque)
+{
+    int mig_cap_num = SPAPR_MACHINE_GET_CLASS(opaque)->mig_cap_num;
+
+    return mig_cap_num > SPAPR_CAP_XIVE && mig_cap_num > SPAPR_CAP_XICS;
+}
+
 SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
     [SPAPR_CAP_HTM] = {
         .name = "htm",
@@ -639,6 +646,7 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
         .set = spapr_cap_set_bool,
         .type = "bool",
         .apply = cap_xics_apply,
+        .migrate_needed = cap_xics_xive_migrate_needed,
     },
     [SPAPR_CAP_XIVE] = {
         .name = "xive",
@@ -648,6 +656,7 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
         .set = spapr_cap_set_bool,
         .type = "bool",
         .apply = cap_xive_apply,
+        .migrate_needed = cap_xics_xive_migrate_needed,
     },
 };
 
@@ -729,20 +738,21 @@ int spapr_caps_pre_save(void *opaque)
  * caps on the destination */
 int spapr_caps_post_migration(SpaprMachineState *spapr)
 {
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
     int i;
     bool ok = true;
     SpaprCapabilities dstcaps = spapr->eff;
     SpaprCapabilities srccaps;
 
     srccaps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
-    for (i = 0; i < SPAPR_CAP_NUM; i++) {
+    for (i = 0; i < smc->mig_cap_num; i++) {
         /* If not default value then assume came in with the migration */
         if (spapr->mig.caps[i] != spapr->def.caps[i]) {
             srccaps.caps[i] = spapr->mig.caps[i];
         }
     }
 
-    for (i = 0; i < SPAPR_CAP_NUM; i++) {
+    for (i = 0; i < smc->mig_cap_num; i++) {
         SpaprCapabilityInfo *info = &capability_table[i];
 
         if (srccaps.caps[i] > dstcaps.caps[i]) {
=======================================================================

> bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque)
> {
>     if (vmsd->needed && !vmsd->needed(opaque)) {
>         /* optional section not needed */
>         return false;
>     }
>     return true;
> }


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq
  2019-10-11  6:13             ` Greg Kurz
  2019-10-11  8:33               ` Greg Kurz
@ 2019-10-12  0:00               ` David Gibson
  2019-10-14  9:15                 ` Greg Kurz
  1 sibling, 1 reply; 54+ messages in thread
From: David Gibson @ 2019-10-12  0:00 UTC (permalink / raw)
  To: Greg Kurz
  Cc: Jason Wang, Riku Voipio, qemu-devel, qemu-ppc, clg,
	Paolo Bonzini, Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 6426 bytes --]

On Fri, Oct 11, 2019 at 08:13:33AM +0200, Greg Kurz wrote:
> On Fri, 11 Oct 2019 16:07:58 +1100
> David Gibson <david@gibson.dropbear.id.au> wrote:
> 
> > On Thu, Oct 10, 2019 at 10:33:04PM +0200, Greg Kurz wrote:
> > > On Thu, 10 Oct 2019 08:29:58 +0200
> > > Greg Kurz <groug@kaod.org> wrote:
> > > 
> > > > On Thu, 10 Oct 2019 13:02:09 +1100
> > > > David Gibson <david@gibson.dropbear.id.au> wrote:
> > > > 
> > > > > On Wed, Oct 09, 2019 at 07:02:15PM +0200, Greg Kurz wrote:
> > > > > > On Wed,  9 Oct 2019 17:08:16 +1100
> > > > > > David Gibson <david@gibson.dropbear.id.au> wrote:
> > > > > > 
> > > > > > > The only thing remaining in this structure are the flags to allow either
> > > > > > > XICS or XIVE to be present.  These actually make more sense as spapr
> > > > > > > capabilities - that way they can take advantage of the existing
> > > > > > > infrastructure to sanity check capability states across migration and so
> > > > > > > forth.
> > > > > > > 
> > > > > > 
> > > > > > The user can now choose the interrupt controller mode either through
> > > > > > ic-mode or through cap-xics/cap-xive. I guess it doesn't break anything
> > > > > > to expose another API to do the same thing but it raises some questions.
> > > > > > 
> > > > > > We should at least document somewhere that ic-mode is an alias to these
> > > > > > caps, and maybe state which is the preferred method (I personally vote
> > > > > > for the caps).
> > > > > > 
> > > > > > Also, we must keep ic-mode for the moment to stay compatible with the
> > > > > > existing pseries-4.0 and pseries-4.1 machine types, but will we
> > > > > > keep ic-mode forever ? If no, maybe start by not allowing it for
> > > > > > pseries-4.2 ?
> > > > > 
> > > > > I'm actually inclined to keep it for now, maybe even leave it as the
> > > > > suggested way to configure this.  The caps are nice from an internal
> > > > > organization point of view, but ic-mode is arguably a more user
> > > > > friendly way of configuring it.  The conversion of one to the other is
> > > > > straightforward, isolated ans small, so I'm not especially bothered by
> > > > > keeping it around.
> > > > > 
> > > > 
> > > > Fair enough.
> > > > 
> > > > Reviewed-by: Greg Kurz <groug@kaod.org>
> > > > 
> > > 
> > > But unfortunately this still requires care :-\
> > > 
> > > qemu-system-ppc64: cap-xive higher level (1) in incoming stream than on destination (0)
> > > qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr'
> > > qemu-system-ppc64: load of migration failed: Invalid argument
> > > 
> > > or
> > > 
> > > qemu-system-ppc64: cap-xics higher level (1) in incoming stream than on destination (0)
> > > qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr'
> > > qemu-system-ppc64: load of migration failed: Invalid argument
> > > 
> > > when migrating from QEMU 4.1 with ic-mode=xics and ic-mode=xive respectively.
> > > 
> > > This happens because the existing pseries-4.1 machine type doesn't send the
> > > new caps and the logic in spapr_caps_post_migration() wrongly assumes that
> > > the source has both caps set:
> > > 
> > >     srccaps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
> > >     for (i = 0; i < SPAPR_CAP_NUM; i++) {
> > >         /* If not default value then assume came in with the migration */
> > >         if (spapr->mig.caps[i] != spapr->def.caps[i]) {
> > > 
> > > spapr->mig.caps[SPAPR_CAP_XICS] = 0
> > > spapr->mig.caps[SPAPR_CAP_XIVE] = 0
> > > 
> > >             srccaps.caps[i] = spapr->mig.caps[i];
> > > 
> > > srcaps.caps[SPAPR_CAP_XICS] = 1
> > > srcaps.caps[SPAPR_CAP_XIVE] = 1
> > > 
> > >         }
> > >     }
> > > 
> > > and breaks
> > > 
> > >     for (i = 0; i < SPAPR_CAP_NUM; i++) {
> > >         SpaprCapabilityInfo *info = &capability_table[i];
> > > 
> > >         if (srccaps.caps[i] > dstcaps.caps[i]) {
> > > 
> > > srcaps.caps[SPAPR_CAP_XICS] = 0 when ic-mode=xive
> > > srcaps.caps[SPAPR_CAP_XIVE] = 0 when ic-mode=xics
> > > 
> > >             error_report("cap-%s higher level (%d) in incoming stream than on destination (%d)",
> > >                          info->name, srccaps.caps[i], dstcaps.caps[i]);
> > >             ok = false;
> > >         }
> > 
> > Ah.. right.  I thought there would be problems with backwards
> > migration, but I didn't think of this problem even with forward
> > migration.
> > 
> > > Maybe we shouldn't check capabilities that we know the source
> > > isn't supposed to send, eg. by having a smc->max_cap ?
> > 
> > Uh.. I'm not really sure what exactly you're suggesting here.
> > 
> 
> I'm suggesting to have a per-machine version smc->max_cap that
> contains the highest supported cap index, to be used instead of
> SPAPR_CAP_NUM in this functions, ie.
> 
> for (i = 0; i <= smc->max_cap; i++) {
>     ...
> }
> 
> where we would have
> 
> smc->max_cap = SPAPR_CAP_CCF_ASSIST for pseries-4.1
> 
> and
> 
> smc->max_cap = SPAPR_CAP_XIVE for psereis-4.2

Oh, I see, a max cap index.  I think that sounds fragile if we ever
deprecate any caps, and it also might be problematic for downstream
where we've sometimes selectively backported caps.

> > I think what we need here is a custom migrate_needed function, like we
> > already have for cap_hpt_maxpagesize, to exclude it from the migration
> > stream for machine versions before 4.2.
> > 
> 
> No, VMState needed() hooks are for outgoing migration only.

Ah, yeah, right.  Essentially the problem is that in the absence of
caps, the new qemu assumes they're in the default state, but if an old
source had ic-mode set, then they effectively aren't.  Or looked at
another way, it's now trying to check that the ends match w.r.t. intc
selection, but doesn't have enough information supplied by old sources
to do so correctly.

Ugh, that's a bit trickier to work around.

> bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque)
> {
>     if (vmsd->needed && !vmsd->needed(opaque)) {
>         /* optional section not needed */
>         return false;
>     }
>     return true;
> }



-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq
  2019-10-12  0:00               ` David Gibson
@ 2019-10-14  9:15                 ` Greg Kurz
  2019-11-20  5:38                   ` David Gibson
  0 siblings, 1 reply; 54+ messages in thread
From: Greg Kurz @ 2019-10-14  9:15 UTC (permalink / raw)
  To: David Gibson
  Cc: Jason Wang, Riku Voipio, qemu-devel, qemu-ppc, clg,
	Paolo Bonzini, Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 7719 bytes --]

On Sat, 12 Oct 2019 11:00:41 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:

> On Fri, Oct 11, 2019 at 08:13:33AM +0200, Greg Kurz wrote:
> > On Fri, 11 Oct 2019 16:07:58 +1100
> > David Gibson <david@gibson.dropbear.id.au> wrote:
> > 
> > > On Thu, Oct 10, 2019 at 10:33:04PM +0200, Greg Kurz wrote:
> > > > On Thu, 10 Oct 2019 08:29:58 +0200
> > > > Greg Kurz <groug@kaod.org> wrote:
> > > > 
> > > > > On Thu, 10 Oct 2019 13:02:09 +1100
> > > > > David Gibson <david@gibson.dropbear.id.au> wrote:
> > > > > 
> > > > > > On Wed, Oct 09, 2019 at 07:02:15PM +0200, Greg Kurz wrote:
> > > > > > > On Wed,  9 Oct 2019 17:08:16 +1100
> > > > > > > David Gibson <david@gibson.dropbear.id.au> wrote:
> > > > > > > 
> > > > > > > > The only thing remaining in this structure are the flags to allow either
> > > > > > > > XICS or XIVE to be present.  These actually make more sense as spapr
> > > > > > > > capabilities - that way they can take advantage of the existing
> > > > > > > > infrastructure to sanity check capability states across migration and so
> > > > > > > > forth.
> > > > > > > > 
> > > > > > > 
> > > > > > > The user can now choose the interrupt controller mode either through
> > > > > > > ic-mode or through cap-xics/cap-xive. I guess it doesn't break anything
> > > > > > > to expose another API to do the same thing but it raises some questions.
> > > > > > > 
> > > > > > > We should at least document somewhere that ic-mode is an alias to these
> > > > > > > caps, and maybe state which is the preferred method (I personally vote
> > > > > > > for the caps).
> > > > > > > 
> > > > > > > Also, we must keep ic-mode for the moment to stay compatible with the
> > > > > > > existing pseries-4.0 and pseries-4.1 machine types, but will we
> > > > > > > keep ic-mode forever ? If no, maybe start by not allowing it for
> > > > > > > pseries-4.2 ?
> > > > > > 
> > > > > > I'm actually inclined to keep it for now, maybe even leave it as the
> > > > > > suggested way to configure this.  The caps are nice from an internal
> > > > > > organization point of view, but ic-mode is arguably a more user
> > > > > > friendly way of configuring it.  The conversion of one to the other is
> > > > > > straightforward, isolated ans small, so I'm not especially bothered by
> > > > > > keeping it around.
> > > > > > 
> > > > > 
> > > > > Fair enough.
> > > > > 
> > > > > Reviewed-by: Greg Kurz <groug@kaod.org>
> > > > > 
> > > > 
> > > > But unfortunately this still requires care :-\
> > > > 
> > > > qemu-system-ppc64: cap-xive higher level (1) in incoming stream than on destination (0)
> > > > qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr'
> > > > qemu-system-ppc64: load of migration failed: Invalid argument
> > > > 
> > > > or
> > > > 
> > > > qemu-system-ppc64: cap-xics higher level (1) in incoming stream than on destination (0)
> > > > qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr'
> > > > qemu-system-ppc64: load of migration failed: Invalid argument
> > > > 
> > > > when migrating from QEMU 4.1 with ic-mode=xics and ic-mode=xive respectively.
> > > > 
> > > > This happens because the existing pseries-4.1 machine type doesn't send the
> > > > new caps and the logic in spapr_caps_post_migration() wrongly assumes that
> > > > the source has both caps set:
> > > > 
> > > >     srccaps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
> > > >     for (i = 0; i < SPAPR_CAP_NUM; i++) {
> > > >         /* If not default value then assume came in with the migration */
> > > >         if (spapr->mig.caps[i] != spapr->def.caps[i]) {
> > > > 
> > > > spapr->mig.caps[SPAPR_CAP_XICS] = 0
> > > > spapr->mig.caps[SPAPR_CAP_XIVE] = 0
> > > > 
> > > >             srccaps.caps[i] = spapr->mig.caps[i];
> > > > 
> > > > srcaps.caps[SPAPR_CAP_XICS] = 1
> > > > srcaps.caps[SPAPR_CAP_XIVE] = 1
> > > > 
> > > >         }
> > > >     }
> > > > 
> > > > and breaks
> > > > 
> > > >     for (i = 0; i < SPAPR_CAP_NUM; i++) {
> > > >         SpaprCapabilityInfo *info = &capability_table[i];
> > > > 
> > > >         if (srccaps.caps[i] > dstcaps.caps[i]) {
> > > > 
> > > > srcaps.caps[SPAPR_CAP_XICS] = 0 when ic-mode=xive
> > > > srcaps.caps[SPAPR_CAP_XIVE] = 0 when ic-mode=xics
> > > > 
> > > >             error_report("cap-%s higher level (%d) in incoming stream than on destination (%d)",
> > > >                          info->name, srccaps.caps[i], dstcaps.caps[i]);
> > > >             ok = false;
> > > >         }
> > > 
> > > Ah.. right.  I thought there would be problems with backwards
> > > migration, but I didn't think of this problem even with forward
> > > migration.
> > > 
> > > > Maybe we shouldn't check capabilities that we know the source
> > > > isn't supposed to send, eg. by having a smc->max_cap ?
> > > 
> > > Uh.. I'm not really sure what exactly you're suggesting here.
> > > 
> > 
> > I'm suggesting to have a per-machine version smc->max_cap that
> > contains the highest supported cap index, to be used instead of
> > SPAPR_CAP_NUM in this functions, ie.
> > 
> > for (i = 0; i <= smc->max_cap; i++) {
> >     ...
> > }
> > 
> > where we would have
> > 
> > smc->max_cap = SPAPR_CAP_CCF_ASSIST for pseries-4.1
> > 
> > and
> > 
> > smc->max_cap = SPAPR_CAP_XIVE for psereis-4.2
> 
> Oh, I see, a max cap index.  I think that sounds fragile if we ever
> deprecate any caps, 

Hmmm... I had the impression that capability numbers would stay
forever, even if at some point we may decide to not support some
of them for newer machine types... Can you elaborate on a
deprecating scenario that would break ?

> and it also might be problematic for downstream
> where we've sometimes selectively backported caps.
> 

Do you mean that capability numbers defined in spapr.h differ
from the ones in upstream QEMU ?

> > > I think what we need here is a custom migrate_needed function, like we
> > > already have for cap_hpt_maxpagesize, to exclude it from the migration
> > > stream for machine versions before 4.2.
> > > 
> > 
> > No, VMState needed() hooks are for outgoing migration only.
> 
> Ah, yeah, right.  Essentially the problem is that in the absence of
> caps, the new qemu assumes they're in the default state, but if an old
> source had ic-mode set, then they effectively aren't.  Or looked at
> another way, it's now trying to check that the ends match w.r.t. intc
> selection, but doesn't have enough information supplied by old sources
> to do so correctly.
> 

Yes, but do we really need to perform strict checks on ic-mode in the first
place ? I mean that migrating the state of XICS and/or XIVE entities _only_
requires the destination to have instantiated them, ie:

SOURCE/DEST | xics | xive | dual
------------+------+------+-------
xics        | ok   | fail | ok (*)
xive        | fail | ok   | ok (*)
dual        | fail | fail | ok

(*) missing migrated state for xics/xive means that the corresponding
    objects will have reset state, like after CAS.

> Ugh, that's a bit trickier to work around.
> 

Maybe have a migrate_needed() hook like this:

static bool cap_xics_xive_migrate_needed(void *opaque)
{
    return !SPAPR_MACHINE_GET_CLASS(opaque)->pre_4_2_migration;
}

and also use it in spapr_caps_post_migration() ?

> > bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque)
> > {
> >     if (vmsd->needed && !vmsd->needed(opaque)) {
> >         /* optional section not needed */
> >         return false;
> >     }
> >     return true;
> > }
> 
> 
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 00/19] spapr: IRQ subsystem cleanup
  2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
                   ` (19 preceding siblings ...)
  2019-10-09  9:02 ` [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
@ 2019-10-16 16:04 ` Greg Kurz
  2019-10-17  0:26   ` David Gibson
  20 siblings, 1 reply; 54+ messages in thread
From: Greg Kurz @ 2019-10-16 16:04 UTC (permalink / raw)
  To: David Gibson
  Cc: Jason Wang, Riku Voipio, qemu-devel, Laurent Vivier, qemu-ppc,
	clg, Paolo Bonzini, Marc-André Lureau, philmd

On Wed,  9 Oct 2019 17:07:59 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:

> This is a substantial rework to clean up the handling of IRQs in
> spapr.  It includes some cleanups to both the XICS and XIVE interrupt
> controller backends, as well as more to the common spapr irq handling
> infrastructure.
> 

Patches up to 16 have been reviewed. Any chance you merge them before
soft freeze (12 days left) ?

> The last two patches of this series, dealing with VFIO devices, are
> RFC only - there some problems that I'm discussing with Alex
> Williamson.
> 
> Changes since v3:
>  * Further minor tweaks to error handling
>  * Other minor polishes from feedback
>  * Added some patches to address VFIO irq routing
>  * Removed the first ~20 patches, which are now merged
> 
> Changes since v2:
>  * Fixed a bug where the "move handling multiple irq frees" to
>    frontend patch was actually freeing one irq over and over, rather
>    than freeing multiple irqs
>  * Fixed some places I missed still using only-Error * style, and flow
>    on adjustments
>  * New idiom to iterate across all constructed backends for the things
>    that need that (cpu_intc_create, claim & freem), rather than
>    open-coding a call on the xics, then xive versions.
> 
> Changes since v1:
>  * Lots of extra patches
>  * Many minor adjustments based on feedback
>  * Moved towards return value + Error * style, instead of just Error *
>    style
> 
> David Gibson (16):
>   spapr, xics, xive: Introduce SpaprInterruptController QOM interface
>   spapr, xics, xive: Move cpu_intc_create from SpaprIrq to
>     SpaprInterruptController
>   spapr, xics, xive: Move irq claim and free from SpaprIrq to
>     SpaprInterruptController
>   spapr: Formalize notion of active interrupt controller
>   spapr, xics, xive: Move set_irq from SpaprIrq to
>     SpaprInterruptController
>   spapr, xics, xive: Move print_info from SpaprIrq to
>     SpaprInterruptController
>   spapr, xics, xive: Move dt_populate from SpaprIrq to
>     SpaprInterruptController
>   spapr, xics, xive: Match signatures for XICS and XIVE KVM connect
>     routines
>   spapr: Remove SpaprIrq::init_kvm hook
>   spapr, xics, xive: Move SpaprIrq::reset hook logic into
>     activate/deactivate
>   spapr, xics, xive: Move SpaprIrq::post_load hook to backends
>   spapr: Remove SpaprIrq::nr_msis
>   spapr: Move SpaprIrq::nr_xirqs to SpaprMachineClass
>   spapr: Remove last pieces of SpaprIrq
>   spapr: Handle irq backend changes with VFIO PCI devices
>   spapr: Work around spurious warnings from vfio INTx initialization
> 
> Greg Kurz (2):
>   xive: Make some device types not user creatable
>   xics: Make some device types not user creatable
> 
> Stefan Brankovic (1):
>   target/ppc: Fix for optimized vsl/vsr instructions
> 
>  hw/intc/spapr_xive.c                | 295 ++++++++----
>  hw/intc/spapr_xive_kvm.c            |  22 +-
>  hw/intc/xics.c                      |  10 +
>  hw/intc/xics_kvm.c                  |   9 +-
>  hw/intc/xics_spapr.c                | 110 ++++-
>  hw/intc/xive.c                      |  15 +
>  hw/ppc/spapr.c                      |  52 ++-
>  hw/ppc/spapr_caps.c                 |  64 +++
>  hw/ppc/spapr_cpu_core.c             |   3 +-
>  hw/ppc/spapr_hcall.c                |   7 +-
>  hw/ppc/spapr_irq.c                  | 668 +++++++++-------------------
>  hw/ppc/spapr_pci.c                  |  16 +-
>  include/hw/pci-host/spapr.h         |   4 +-
>  include/hw/ppc/spapr.h              |  17 +-
>  include/hw/ppc/spapr_irq.h          |  72 +--
>  include/hw/ppc/spapr_xive.h         |   9 +-
>  include/hw/ppc/xics_spapr.h         |   6 +-
>  target/ppc/translate/vmx-impl.inc.c |  84 ++--
>  18 files changed, 769 insertions(+), 694 deletions(-)
> 



^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 00/19] spapr: IRQ subsystem cleanup
  2019-10-16 16:04 ` Greg Kurz
@ 2019-10-17  0:26   ` David Gibson
  0 siblings, 0 replies; 54+ messages in thread
From: David Gibson @ 2019-10-17  0:26 UTC (permalink / raw)
  To: Greg Kurz
  Cc: Jason Wang, Riku Voipio, qemu-devel, Laurent Vivier, qemu-ppc,
	clg, Paolo Bonzini, Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 751 bytes --]

On Wed, Oct 16, 2019 at 06:04:04PM +0200, Greg Kurz wrote:
> On Wed,  9 Oct 2019 17:07:59 +1100
> David Gibson <david@gibson.dropbear.id.au> wrote:
> 
> > This is a substantial rework to clean up the handling of IRQs in
> > spapr.  It includes some cleanups to both the XICS and XIVE interrupt
> > controller backends, as well as more to the common spapr irq handling
> > infrastructure.
> > 
> 
> Patches up to 16 have been reviewed. Any chance you merge them before
> soft freeze (12 days left) ?

Seems reasonable, merged to ppc-for-4.2.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq
  2019-10-14  9:15                 ` Greg Kurz
@ 2019-11-20  5:38                   ` David Gibson
  2019-11-20  8:36                     ` Greg Kurz
  0 siblings, 1 reply; 54+ messages in thread
From: David Gibson @ 2019-11-20  5:38 UTC (permalink / raw)
  To: Greg Kurz
  Cc: Jason Wang, Riku Voipio, qemu-devel, qemu-ppc, clg,
	Paolo Bonzini, Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 8641 bytes --]

On Mon, Oct 14, 2019 at 11:15:16AM +0200, Greg Kurz wrote:
> On Sat, 12 Oct 2019 11:00:41 +1100
> David Gibson <david@gibson.dropbear.id.au> wrote:
> 
> > On Fri, Oct 11, 2019 at 08:13:33AM +0200, Greg Kurz wrote:
> > > On Fri, 11 Oct 2019 16:07:58 +1100
> > > David Gibson <david@gibson.dropbear.id.au> wrote:
> > > 
> > > > On Thu, Oct 10, 2019 at 10:33:04PM +0200, Greg Kurz wrote:
> > > > > On Thu, 10 Oct 2019 08:29:58 +0200
> > > > > Greg Kurz <groug@kaod.org> wrote:
> > > > > 
> > > > > > On Thu, 10 Oct 2019 13:02:09 +1100
> > > > > > David Gibson <david@gibson.dropbear.id.au> wrote:
> > > > > > 
> > > > > > > On Wed, Oct 09, 2019 at 07:02:15PM +0200, Greg Kurz wrote:
> > > > > > > > On Wed,  9 Oct 2019 17:08:16 +1100
> > > > > > > > David Gibson <david@gibson.dropbear.id.au> wrote:
> > > > > > > > 
> > > > > > > > > The only thing remaining in this structure are the flags to allow either
> > > > > > > > > XICS or XIVE to be present.  These actually make more sense as spapr
> > > > > > > > > capabilities - that way they can take advantage of the existing
> > > > > > > > > infrastructure to sanity check capability states across migration and so
> > > > > > > > > forth.
> > > > > > > > > 
> > > > > > > > 
> > > > > > > > The user can now choose the interrupt controller mode either through
> > > > > > > > ic-mode or through cap-xics/cap-xive. I guess it doesn't break anything
> > > > > > > > to expose another API to do the same thing but it raises some questions.
> > > > > > > > 
> > > > > > > > We should at least document somewhere that ic-mode is an alias to these
> > > > > > > > caps, and maybe state which is the preferred method (I personally vote
> > > > > > > > for the caps).
> > > > > > > > 
> > > > > > > > Also, we must keep ic-mode for the moment to stay compatible with the
> > > > > > > > existing pseries-4.0 and pseries-4.1 machine types, but will we
> > > > > > > > keep ic-mode forever ? If no, maybe start by not allowing it for
> > > > > > > > pseries-4.2 ?
> > > > > > > 
> > > > > > > I'm actually inclined to keep it for now, maybe even leave it as the
> > > > > > > suggested way to configure this.  The caps are nice from an internal
> > > > > > > organization point of view, but ic-mode is arguably a more user
> > > > > > > friendly way of configuring it.  The conversion of one to the other is
> > > > > > > straightforward, isolated ans small, so I'm not especially bothered by
> > > > > > > keeping it around.
> > > > > > > 
> > > > > > 
> > > > > > Fair enough.
> > > > > > 
> > > > > > Reviewed-by: Greg Kurz <groug@kaod.org>
> > > > > > 
> > > > > 
> > > > > But unfortunately this still requires care :-\
> > > > > 
> > > > > qemu-system-ppc64: cap-xive higher level (1) in incoming stream than on destination (0)
> > > > > qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr'
> > > > > qemu-system-ppc64: load of migration failed: Invalid argument
> > > > > 
> > > > > or
> > > > > 
> > > > > qemu-system-ppc64: cap-xics higher level (1) in incoming stream than on destination (0)
> > > > > qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr'
> > > > > qemu-system-ppc64: load of migration failed: Invalid argument
> > > > > 
> > > > > when migrating from QEMU 4.1 with ic-mode=xics and ic-mode=xive respectively.
> > > > > 
> > > > > This happens because the existing pseries-4.1 machine type doesn't send the
> > > > > new caps and the logic in spapr_caps_post_migration() wrongly assumes that
> > > > > the source has both caps set:
> > > > > 
> > > > >     srccaps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
> > > > >     for (i = 0; i < SPAPR_CAP_NUM; i++) {
> > > > >         /* If not default value then assume came in with the migration */
> > > > >         if (spapr->mig.caps[i] != spapr->def.caps[i]) {
> > > > > 
> > > > > spapr->mig.caps[SPAPR_CAP_XICS] = 0
> > > > > spapr->mig.caps[SPAPR_CAP_XIVE] = 0
> > > > > 
> > > > >             srccaps.caps[i] = spapr->mig.caps[i];
> > > > > 
> > > > > srcaps.caps[SPAPR_CAP_XICS] = 1
> > > > > srcaps.caps[SPAPR_CAP_XIVE] = 1
> > > > > 
> > > > >         }
> > > > >     }
> > > > > 
> > > > > and breaks
> > > > > 
> > > > >     for (i = 0; i < SPAPR_CAP_NUM; i++) {
> > > > >         SpaprCapabilityInfo *info = &capability_table[i];
> > > > > 
> > > > >         if (srccaps.caps[i] > dstcaps.caps[i]) {
> > > > > 
> > > > > srcaps.caps[SPAPR_CAP_XICS] = 0 when ic-mode=xive
> > > > > srcaps.caps[SPAPR_CAP_XIVE] = 0 when ic-mode=xics
> > > > > 
> > > > >             error_report("cap-%s higher level (%d) in incoming stream than on destination (%d)",
> > > > >                          info->name, srccaps.caps[i], dstcaps.caps[i]);
> > > > >             ok = false;
> > > > >         }
> > > > 
> > > > Ah.. right.  I thought there would be problems with backwards
> > > > migration, but I didn't think of this problem even with forward
> > > > migration.
> > > > 
> > > > > Maybe we shouldn't check capabilities that we know the source
> > > > > isn't supposed to send, eg. by having a smc->max_cap ?
> > > > 
> > > > Uh.. I'm not really sure what exactly you're suggesting here.
> > > > 
> > > 
> > > I'm suggesting to have a per-machine version smc->max_cap that
> > > contains the highest supported cap index, to be used instead of
> > > SPAPR_CAP_NUM in this functions, ie.
> > > 
> > > for (i = 0; i <= smc->max_cap; i++) {
> > >     ...
> > > }
> > > 
> > > where we would have
> > > 
> > > smc->max_cap = SPAPR_CAP_CCF_ASSIST for pseries-4.1
> > > 
> > > and
> > > 
> > > smc->max_cap = SPAPR_CAP_XIVE for psereis-4.2
> > 
> > Oh, I see, a max cap index.  I think that sounds fragile if we ever
> > deprecate any caps, 
> 
> Hmmm... I had the impression that capability numbers would stay
> forever, even if at some point we may decide to not support some
> of them for newer machine types... Can you elaborate on a
> deprecating scenario that would break ?

Uhh... good point, I don't think that could break it.  Even if we
deprecated a capability we could still retain enough awareness of the
old number to sanity check this.

> > and it also might be problematic for downstream
> > where we've sometimes selectively backported caps.
> 
> Do you mean that capability numbers defined in spapr.h differ
> from the ones in upstream QEMU ?

No, they don't but that's actually the problem.  The point is that we
might backport some later caps without necessarily backporting all the
earlier ones - that means that the "max cap index" no longer implies
that all the lower indexed caps are present.

> 
> > > > I think what we need here is a custom migrate_needed function, like we
> > > > already have for cap_hpt_maxpagesize, to exclude it from the migration
> > > > stream for machine versions before 4.2.
> > > > 
> > > 
> > > No, VMState needed() hooks are for outgoing migration only.
> > 
> > Ah, yeah, right.  Essentially the problem is that in the absence of
> > caps, the new qemu assumes they're in the default state, but if an old
> > source had ic-mode set, then they effectively aren't.  Or looked at
> > another way, it's now trying to check that the ends match w.r.t. intc
> > selection, but doesn't have enough information supplied by old sources
> > to do so correctly.
> 
> Yes, but do we really need to perform strict checks on ic-mode in the first
> place ? I mean that migrating the state of XICS and/or XIVE entities _only_
> requires the destination to have instantiated them, ie:
> 
> SOURCE/DEST | xics | xive | dual
> ------------+------+------+-------
> xics        | ok   | fail | ok (*)
> xive        | fail | ok   | ok (*)
> dual        | fail | fail | ok
> 
> (*) missing migrated state for xics/xive means that the corresponding
>     objects will have reset state, like after CAS.

Yes... I don't really see where you're goig with that thought.

> > Ugh, that's a bit trickier to work around.
> > 
> 
> Maybe have a migrate_needed() hook like this:
> 
> static bool cap_xics_xive_migrate_needed(void *opaque)
> {
>     return !SPAPR_MACHINE_GET_CLASS(opaque)->pre_4_2_migration;
> }
> 
> and also use it in spapr_caps_post_migration() ?

Yeah, maybe.  I think we have a hack like this for one of the other
caps already.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq
  2019-11-20  5:38                   ` David Gibson
@ 2019-11-20  8:36                     ` Greg Kurz
  0 siblings, 0 replies; 54+ messages in thread
From: Greg Kurz @ 2019-11-20  8:36 UTC (permalink / raw)
  To: David Gibson
  Cc: Jason Wang, Riku Voipio, qemu-devel, qemu-ppc, clg,
	Paolo Bonzini, Marc-André Lureau, philmd

[-- Attachment #1: Type: text/plain, Size: 3400 bytes --]

On Wed, 20 Nov 2019 16:38:37 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:

[...]
> > 
> > Hmmm... I had the impression that capability numbers would stay
> > forever, even if at some point we may decide to not support some
> > of them for newer machine types... Can you elaborate on a
> > deprecating scenario that would break ?
> 
> Uhh... good point, I don't think that could break it.  Even if we
> deprecated a capability we could still retain enough awareness of the
> old number to sanity check this.
> 
> > > and it also might be problematic for downstream
> > > where we've sometimes selectively backported caps.
> > 
> > Do you mean that capability numbers defined in spapr.h differ
> > from the ones in upstream QEMU ?
> 
> No, they don't but that's actually the problem.  The point is that we
> might backport some later caps without necessarily backporting all the
> earlier ones - that means that the "max cap index" no longer implies
> that all the lower indexed caps are present.
> 

The idea with "max cap index" isn't that all the lower indexed caps are
present but rather higher indexed caps are absent. Maybe rename it to
something like "ignore higher cap index" or any better naming you can
think of ?

> > 
> > > > > I think what we need here is a custom migrate_needed function, like we
> > > > > already have for cap_hpt_maxpagesize, to exclude it from the migration
> > > > > stream for machine versions before 4.2.
> > > > > 
> > > > 
> > > > No, VMState needed() hooks are for outgoing migration only.
> > > 
> > > Ah, yeah, right.  Essentially the problem is that in the absence of
> > > caps, the new qemu assumes they're in the default state, but if an old
> > > source had ic-mode set, then they effectively aren't.  Or looked at
> > > another way, it's now trying to check that the ends match w.r.t. intc
> > > selection, but doesn't have enough information supplied by old sources
> > > to do so correctly.
> > 
> > Yes, but do we really need to perform strict checks on ic-mode in the first
> > place ? I mean that migrating the state of XICS and/or XIVE entities _only_
> > requires the destination to have instantiated them, ie:
> > 
> > SOURCE/DEST | xics | xive | dual
> > ------------+------+------+-------
> > xics        | ok   | fail | ok (*)
> > xive        | fail | ok   | ok (*)
> > dual        | fail | fail | ok
> > 
> > (*) missing migrated state for xics/xive means that the corresponding
> >     objects will have reset state, like after CAS.
> 
> Yes... I don't really see where you're goig with that thought.
> 

I mean that if we didn't check the XICS and XIVE capabilities, we
would still fail migration when it is really needed, ie. migrating
from ic-mode=xics to ic-mode=xive or the other way round. This
would it make it possible to migrate anything to ic-mode=dual though
but I don't think this is a problem since it doesn't break anything.

> > > Ugh, that's a bit trickier to work around.
> > > 
> > 
> > Maybe have a migrate_needed() hook like this:
> > 
> > static bool cap_xics_xive_migrate_needed(void *opaque)
> > {
> >     return !SPAPR_MACHINE_GET_CLASS(opaque)->pre_4_2_migration;
> > }
> > 
> > and also use it in spapr_caps_post_migration() ?
> 
> Yeah, maybe.  I think we have a hack like this for one of the other
> caps already.
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

end of thread, other threads:[~2019-11-20  8:38 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-09  6:07 [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
2019-10-09  6:08 ` [PATCH v4 01/19] xive: Make some device types not user creatable David Gibson
2019-10-09  6:08 ` [PATCH v4 02/19] xics: " David Gibson
2019-10-09  6:08 ` [PATCH v4 03/19] target/ppc: Fix for optimized vsl/vsr instructions David Gibson
2019-10-09  6:08 ` [PATCH v4 04/19] spapr, xics, xive: Introduce SpaprInterruptController QOM interface David Gibson
2019-10-09  6:08 ` [PATCH v4 05/19] spapr, xics, xive: Move cpu_intc_create from SpaprIrq to SpaprInterruptController David Gibson
2019-10-09  6:08 ` [PATCH v4 06/19] spapr, xics, xive: Move irq claim and free " David Gibson
2019-10-09  6:08 ` [PATCH v4 07/19] spapr: Formalize notion of active interrupt controller David Gibson
2019-10-09  9:16   ` Cédric Le Goater
2019-10-09  9:19   ` Cédric Le Goater
2019-10-09 11:38     ` David Gibson
2019-10-09  6:08 ` [PATCH v4 08/19] spapr, xics, xive: Move set_irq from SpaprIrq to SpaprInterruptController David Gibson
2019-10-09  9:18   ` Cédric Le Goater
2019-10-09  6:08 ` [PATCH v4 09/19] spapr, xics, xive: Move print_info " David Gibson
2019-10-09  9:19   ` Cédric Le Goater
2019-10-09  6:08 ` [PATCH v4 10/19] spapr, xics, xive: Move dt_populate " David Gibson
2019-10-09  9:20   ` Cédric Le Goater
2019-10-09  6:08 ` [PATCH v4 11/19] spapr, xics, xive: Match signatures for XICS and XIVE KVM connect routines David Gibson
2019-10-09  6:08 ` [PATCH v4 12/19] spapr: Remove SpaprIrq::init_kvm hook David Gibson
2019-10-09  6:08 ` [PATCH v4 13/19] spapr, xics, xive: Move SpaprIrq::reset hook logic into activate/deactivate David Gibson
2019-10-09 14:25   ` Greg Kurz
2019-10-09 15:56     ` Cédric Le Goater
2019-10-09 15:56   ` Cédric Le Goater
2019-10-09  6:08 ` [PATCH v4 14/19] spapr, xics, xive: Move SpaprIrq::post_load hook to backends David Gibson
2019-10-09 15:57   ` Cédric Le Goater
2019-10-09  6:08 ` [PATCH v4 15/19] spapr: Remove SpaprIrq::nr_msis David Gibson
2019-10-09 15:59   ` Cédric Le Goater
2019-10-10  1:56     ` David Gibson
2019-10-09  6:08 ` [PATCH v4 16/19] spapr: Move SpaprIrq::nr_xirqs to SpaprMachineClass David Gibson
2019-10-09 16:01   ` Cédric Le Goater
2019-10-09  6:08 ` [PATCH v4 17/19] spapr: Remove last pieces of SpaprIrq David Gibson
2019-10-09 16:44   ` Cédric Le Goater
2019-10-10  1:59     ` David Gibson
2019-10-09 17:02   ` Greg Kurz
2019-10-10  2:02     ` David Gibson
2019-10-10  6:29       ` Greg Kurz
2019-10-10 20:33         ` Greg Kurz
2019-10-11  5:07           ` David Gibson
2019-10-11  6:13             ` Greg Kurz
2019-10-11  8:33               ` Greg Kurz
2019-10-12  0:00               ` David Gibson
2019-10-14  9:15                 ` Greg Kurz
2019-11-20  5:38                   ` David Gibson
2019-11-20  8:36                     ` Greg Kurz
2019-10-09  6:08 ` [PATCH v4 18/19] spapr: Handle irq backend changes with VFIO PCI devices David Gibson
2019-10-09  8:57   ` David Gibson
2019-10-09  6:08 ` [PATCH v4 19/19] spapr: Work around spurious warnings from vfio INTx initialization David Gibson
2019-10-09  8:37   ` Greg Kurz
2019-10-09  8:52     ` David Gibson
2019-10-09 17:16       ` Greg Kurz
2019-10-10  2:02         ` David Gibson
2019-10-09  9:02 ` [PATCH v4 00/19] spapr: IRQ subsystem cleanup David Gibson
2019-10-16 16:04 ` Greg Kurz
2019-10-17  0:26   ` David Gibson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.