diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-11-18 15:28:38 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-11-18 15:28:38 +0000 |
commit | 3d275bd17c7bdf5acd4e4f58fa7b8b9114bb7484 (patch) | |
tree | 3327d43c1305e3c009cd69a059c8c8ae21c67e81 /hw | |
parent | b696f2c6ba8c92ffb5eca49b88a5c7276d0a3e1e (diff) | |
parent | 6d24795ee7e3199d199d3c415312c93382ad1807 (diff) |
Merge remote-tracking branch 'remotes/gkurz/tags/ppc-for-5.2-20201118' into staging
ppc patch queue for 2020-11-18
This fixes a regression that badly breaks some guest setups because
IPIs end up misconfigured in the XIVE interrupt controller. Hopefully,
the last fix for sPAPR. I'm sending this PR with the blessing of David
who is currently on holidays.
# gpg: Signature made Wed 18 Nov 2020 10:26:31 GMT
# gpg: using RSA key B4828BAF943140CEF2A3491071D4D5E5822F73D6
# gpg: Good signature from "Greg Kurz <groug@kaod.org>" [full]
# gpg: aka "Gregory Kurz <gregory.kurz@free.fr>" [full]
# gpg: aka "[jpeg image of size 3330]" [full]
# Primary key fingerprint: B482 8BAF 9431 40CE F2A3 4910 71D4 D5E5 822F 73D6
* remotes/gkurz/tags/ppc-for-5.2-20201118:
Revert series "spapr/xive: Allocate vCPU IPIs from the vCPU contexts"
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/intc/spapr_xive_kvm.c | 102 |
1 files changed, 18 insertions, 84 deletions
diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c index 66bf4c06fe..e8667ce5f6 100644 --- a/hw/intc/spapr_xive_kvm.c +++ b/hw/intc/spapr_xive_kvm.c @@ -36,9 +36,10 @@ typedef struct KVMEnabledCPU { static QLIST_HEAD(, KVMEnabledCPU) kvm_enabled_cpus = QLIST_HEAD_INITIALIZER(&kvm_enabled_cpus); -static bool kvm_cpu_is_enabled(unsigned long vcpu_id) +static bool kvm_cpu_is_enabled(CPUState *cs) { KVMEnabledCPU *enabled_cpu; + unsigned long vcpu_id = kvm_arch_vcpu_id(cs); QLIST_FOREACH(enabled_cpu, &kvm_enabled_cpus, node) { if (enabled_cpu->vcpu_id == vcpu_id) { @@ -146,45 +147,6 @@ int kvmppc_xive_cpu_synchronize_state(XiveTCTX *tctx, Error **errp) return s.ret; } -/* - * Allocate the vCPU IPIs from the vCPU context. This will allocate - * the XIVE IPI interrupt on the chip on which the vCPU is running. - * This gives a better distribution of IPIs when the guest has a lot - * of vCPUs. When the vCPUs are pinned, this will make the IPI local - * to the chip of the vCPU. It will reduce rerouting between interrupt - * controllers and gives better performance. - */ -typedef struct { - SpaprXive *xive; - Error *err; - int rc; -} XiveInitIPI; - -static void kvmppc_xive_reset_ipi_on_cpu(CPUState *cs, run_on_cpu_data arg) -{ - unsigned long ipi = kvm_arch_vcpu_id(cs); - XiveInitIPI *s = arg.host_ptr; - uint64_t state = 0; - - s->rc = kvm_device_access(s->xive->fd, KVM_DEV_XIVE_GRP_SOURCE, ipi, - &state, true, &s->err); -} - -static int kvmppc_xive_reset_ipi(SpaprXive *xive, CPUState *cs, Error **errp) -{ - XiveInitIPI s = { - .xive = xive, - .err = NULL, - .rc = 0, - }; - - run_on_cpu(cs, kvmppc_xive_reset_ipi_on_cpu, RUN_ON_CPU_HOST_PTR(&s)); - if (s.err) { - error_propagate(errp, s.err); - } - return s.rc; -} - int kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp) { ERRP_GUARD(); @@ -195,7 +157,7 @@ int kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp) assert(xive->fd != -1); /* Check if CPU was hot unplugged and replugged. */ - if (kvm_cpu_is_enabled(kvm_arch_vcpu_id(tctx->cs))) { + if (kvm_cpu_is_enabled(tctx->cs)) { return 0; } @@ -214,12 +176,6 @@ int kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp) return ret; } - /* Create/reset the vCPU IPI */ - ret = kvmppc_xive_reset_ipi(xive, tctx->cs, errp); - if (ret < 0) { - return ret; - } - kvm_cpu_enable(tctx->cs); return 0; } @@ -279,12 +235,6 @@ int kvmppc_xive_source_reset_one(XiveSource *xsrc, int srcno, Error **errp) assert(xive->fd != -1); - /* - * The vCPU IPIs are now allocated in kvmppc_xive_cpu_connect() - * and not with all sources in kvmppc_xive_source_reset() - */ - assert(srcno >= SPAPR_XIRQ_BASE); - if (xive_source_irq_is_lsi(xsrc, srcno)) { state |= KVM_XIVE_LEVEL_SENSITIVE; if (xsrc->status[srcno] & XIVE_STATUS_ASSERTED) { @@ -296,28 +246,12 @@ int kvmppc_xive_source_reset_one(XiveSource *xsrc, int srcno, Error **errp) true, errp); } -/* - * To be valid, a source must have been claimed by the machine (valid - * entry in the EAS table) and if it is a vCPU IPI, the vCPU should - * have been enabled, which means the IPI has been allocated in - * kvmppc_xive_cpu_connect(). - */ -static bool xive_source_is_valid(SpaprXive *xive, int i) -{ - return xive_eas_is_valid(&xive->eat[i]) && - (i >= SPAPR_XIRQ_BASE || kvm_cpu_is_enabled(i)); -} - static int kvmppc_xive_source_reset(XiveSource *xsrc, Error **errp) { SpaprXive *xive = SPAPR_XIVE(xsrc->xive); int i; - /* - * Skip the vCPU IPIs. These are created/reset when the vCPUs are - * connected in kvmppc_xive_cpu_connect() - */ - for (i = SPAPR_XIRQ_BASE; i < xsrc->nr_irqs; i++) { + for (i = 0; i < xsrc->nr_irqs; i++) { int ret; if (!xive_eas_is_valid(&xive->eat[i])) { @@ -399,7 +333,7 @@ static void kvmppc_xive_source_get_state(XiveSource *xsrc) for (i = 0; i < xsrc->nr_irqs; i++) { uint8_t pq; - if (!xive_source_is_valid(xive, i)) { + if (!xive_eas_is_valid(&xive->eat[i])) { continue; } @@ -582,7 +516,7 @@ static void kvmppc_xive_change_state_handler(void *opaque, int running, uint8_t pq; uint8_t old_pq; - if (!xive_source_is_valid(xive, i)) { + if (!xive_eas_is_valid(&xive->eat[i])) { continue; } @@ -610,7 +544,7 @@ static void kvmppc_xive_change_state_handler(void *opaque, int running, for (i = 0; i < xsrc->nr_irqs; i++) { uint8_t pq; - if (!xive_source_is_valid(xive, i)) { + if (!xive_eas_is_valid(&xive->eat[i])) { continue; } @@ -713,22 +647,22 @@ int kvmppc_xive_post_load(SpaprXive *xive, int version_id) } } - /* - * We can only restore the source config if the source has been - * previously set in KVM. Since we don't do that at reset time - * when restoring a VM, let's do it now. - */ - ret = kvmppc_xive_source_reset(&xive->source, &local_err); - if (ret < 0) { - goto fail; - } - /* Restore the EAT */ for (i = 0; i < xive->nr_irqs; i++) { - if (!xive_source_is_valid(xive, i)) { + if (!xive_eas_is_valid(&xive->eat[i])) { continue; } + /* + * We can only restore the source config if the source has been + * previously set in KVM. Since we don't do that for all interrupts + * at reset time anymore, let's do it now. + */ + ret = kvmppc_xive_source_reset_one(&xive->source, i, &local_err); + if (ret < 0) { + goto fail; + } + ret = kvmppc_xive_set_source_config(xive, i, &xive->eat[i], &local_err); if (ret < 0) { goto fail; |