hw/intc/spapr_xive.c | 17 +++++++++++++++++
hw/intc/spapr_xive_kvm.c | 36 +++++++++++++++++++++++++++++++-----
2 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index 6f31ce74f198..2dc594a720b1 100644
--- a/hw/intc/spapr_xive.c
+++ b/hw/intc/spapr_xive.c
@@ -1089,6 +1089,23 @@ static target_ulong h_int_set_source_config(PowerPCCPU
*cpu,
if (spapr_xive_in_kernel(xive)) {
Error *local_err = NULL;
+ /*
+ * Initialize the vCPU IPIs from the vCPU context to allocate
+ * the backing HW IPI on the local chip. This improves
+ * distribution of the IPIs in the system and when the vCPUs
+ * are pinned, it reduces rerouting between interrupt
+ * controllers for better performance.
+ */
+ if (lisn < SPAPR_XIRQ_BASE) {
+ XiveSource *xsrc = &xive->source;
+
+ kvmppc_xive_source_reset_one(xsrc, lisn, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ return H_HARDWARE;
+ }
+ }
+
kvmppc_xive_set_source_config(xive, lisn, &new_eas, &local_err);
if (local_err) {
error_report_err(local_err);
diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c
index 53731d158625..1607a59e9483 100644
--- a/hw/intc/spapr_xive_kvm.c
+++ b/hw/intc/spapr_xive_kvm.c
@@ -254,7 +254,12 @@ static int kvmppc_xive_source_reset(XiveSource *xsrc,
Error **errp)
SpaprXive *xive = SPAPR_XIVE(xsrc->xive);
int i;
- for (i = 0; i < xsrc->nr_irqs; i++) {
+ /*
+ * vCPU IPIs are initialized at the KVM level when configured by
+ * H_INT_SET_SOURCE_CONFIG.
+ */
+
+ for (i = SPAPR_XIRQ_BASE; i < xsrc->nr_irqs; i++) {
int ret;
if (!xive_eas_is_valid(&xive->eat[i])) {
@@ -342,6 +347,27 @@ uint64_t kvmppc_xive_esb_rw(XiveSource *xsrc, int srcno,
uint32_t offset,
}
}
+static bool xive_source_is_initialized(SpaprXive *xive, int lisn)
+{
+ assert(lisn < xive->nr_irqs);
+
+ if (!xive_eas_is_valid(&xive->eat[lisn])) {
+ return false;
+ }
+
+ /*
+ * vCPU IPIs are initialized at the KVM level when configured by
+ * H_INT_SET_SOURCE_CONFIG, in which case, we should have a valid
+ * target (server, priority) in the END.
+ */
+ if (lisn < SPAPR_XIRQ_BASE) {
+ return !!xive_get_field64(EAS_END_INDEX, xive->eat[lisn].w);
+ }
+
+ /* Device sources */
+ return true;
+}
+
static void kvmppc_xive_source_get_state(XiveSource *xsrc)
{
SpaprXive *xive = SPAPR_XIVE(xsrc->xive);
@@ -350,7 +376,7 @@ static void kvmppc_xive_source_get_state(XiveSource *xsrc)
for (i = 0; i < xsrc->nr_irqs; i++) {
uint8_t pq;
- if (!xive_eas_is_valid(&xive->eat[i])) {
+ if (!xive_source_is_initialized(xive, i)) {
continue;
}
@@ -533,7 +559,7 @@ static void kvmppc_xive_change_state_handler(void *opaque, bool running,
uint8_t pq;
uint8_t old_pq;
- if (!xive_eas_is_valid(&xive->eat[i])) {
+ if (!xive_source_is_initialized(xive, i)) {
continue;
}
@@ -561,7 +587,7 @@ static void kvmppc_xive_change_state_handler(void *opaque, bool running,
for (i = 0; i < xsrc->nr_irqs; i++) {
uint8_t pq;
- if (!xive_eas_is_valid(&xive->eat[i])) {
+ if (!xive_source_is_initialized(xive, i)) {
continue;
}
@@ -666,7 +692,7 @@ int kvmppc_xive_post_load(SpaprXive *xive, int version_id)
/* Restore the EAT */
for (i = 0; i < xive->nr_irqs; i++) {
- if (!xive_eas_is_valid(&xive->eat[i])) {
+ if (!xive_source_is_initialized(xive, i)) {
continue;
}