diff options
author | Peter Maydell | 2020-09-08 17:18:48 +0200 |
---|---|---|
committer | Peter Maydell | 2020-09-08 17:18:48 +0200 |
commit | b95ba83fc56ebfc4b6869f21db0c757c0c191104 (patch) | |
tree | c0ea2eeb9b2279f68561ea706e2e344471353667 /hw/intc/spapr_xive_kvm.c | |
parent | Merge remote-tracking branch 'remotes/rth/tags/pull-mb-20200907-2' into staging (diff) | |
parent | spapr_numa: use spapr_numa_get_vcpu_assoc() in home_node hcall (diff) | |
download | qemu-b95ba83fc56ebfc4b6869f21db0c757c0c191104.tar.gz qemu-b95ba83fc56ebfc4b6869f21db0c757c0c191104.tar.xz qemu-b95ba83fc56ebfc4b6869f21db0c757c0c191104.zip |
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-5.2-20200908' into staging
ppc patch queue 2020-09-08
This supersedes ppc-for-5.2-20200904, it fixes a couple of bugs in
that PR and adds a few extra patches.
Next pull request for qemu-5.2. The biggest thing here is the
generalization of ARM's start-powered-off machine property to all
targets. This can fix a number of odd little edge cases where KVM
could run vcpus before they were properly initialized. This does
include changes to a number of files that aren't normally in my
purview. There are suitable Acked-by lines and Peter requested this
come in via my tree, since the most pressing requirement for it is in
pseries machines with the POWER secure virtual machine facility.
In addition we have:
* Daniel Barboza's rework and clean up of pseries machine NUMA handling
* Correction to behaviour of the nvdimm= generic machine property on
pseries
* An optimization to the allocation of XIVE interrupts on KVM
* Some fixes for confused behaviour with kernel_irqchip when both
XICS and XIVE are in play
* Add HIOMAP comamnd to pnv flash
* Properly advertise the fact that spapr_vscsi doesn't handle
hotplugged disks
* Some assorted minor enhancements
# gpg: Signature made Tue 08 Sep 2020 06:19:34 BST
# gpg: using RSA key 75F46586AE61A66CC44E87DC6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" [full]
# gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" [full]
# gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" [full]
# gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" [unknown]
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392
* remotes/dgibson/tags/ppc-for-5.2-20200908: (33 commits)
spapr_numa: use spapr_numa_get_vcpu_assoc() in home_node hcall
spapr_numa: create a vcpu associativity helper
spapr: move h_home_node_associativity to spapr_numa.c
spapr_numa: move NVLink2 associativity handling to spapr_numa.c
spapr, spapr_numa: move lookup-arrays handling to spapr_numa.c
spapr, spapr_numa: handle vcpu ibm,associativity
spapr: introduce SpaprMachineState::numa_assoc_array
ppc/spapr_nvdimm: turn spapr_dt_nvdimm() static
ppc: introducing spapr_numa.c NUMA code helper
hw/ppc/ppc4xx_pci: Replace pointless warning by assert()
hw/ppc/ppc4xx_pci: Use ARRAY_SIZE() instead of magic value
target/s390x: Use start-powered-off CPUState property
sparc/sun4m: Use start-powered-off CPUState property
sparc/sun4m: Don't set cs->halted = 0 in main_cpu_reset()
mips/cps: Use start-powered-off CPUState property
ppc/e500: Use start-powered-off CPUState property
ppc/spapr: Use start-powered-off CPUState property
target/arm: Move setting of CPU halted state to generic code
target/arm: Move start-powered-off property to generic CPUState
ppc/spapr_nvdimm: do not enable support with 'nvdimm=off'
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/intc/spapr_xive_kvm.c')
-rw-r--r-- | hw/intc/spapr_xive_kvm.c | 102 |
1 files changed, 84 insertions, 18 deletions
diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c index e8667ce5f6..66bf4c06fe 100644 --- a/hw/intc/spapr_xive_kvm.c +++ b/hw/intc/spapr_xive_kvm.c @@ -36,10 +36,9 @@ typedef struct KVMEnabledCPU { static QLIST_HEAD(, KVMEnabledCPU) kvm_enabled_cpus = QLIST_HEAD_INITIALIZER(&kvm_enabled_cpus); -static bool kvm_cpu_is_enabled(CPUState *cs) +static bool kvm_cpu_is_enabled(unsigned long vcpu_id) { 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) { @@ -147,6 +146,45 @@ 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(); @@ -157,7 +195,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(tctx->cs)) { + if (kvm_cpu_is_enabled(kvm_arch_vcpu_id(tctx->cs))) { return 0; } @@ -176,6 +214,12 @@ 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; } @@ -235,6 +279,12 @@ 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) { @@ -246,12 +296,28 @@ 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; - for (i = 0; i < xsrc->nr_irqs; 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++) { int ret; if (!xive_eas_is_valid(&xive->eat[i])) { @@ -333,7 +399,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_valid(xive, i)) { continue; } @@ -516,7 +582,7 @@ static void kvmppc_xive_change_state_handler(void *opaque, int running, uint8_t pq; uint8_t old_pq; - if (!xive_eas_is_valid(&xive->eat[i])) { + if (!xive_source_is_valid(xive, i)) { continue; } @@ -544,7 +610,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_eas_is_valid(&xive->eat[i])) { + if (!xive_source_is_valid(xive, i)) { continue; } @@ -647,22 +713,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_eas_is_valid(&xive->eat[i])) { + if (!xive_source_is_valid(xive, 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; |