All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: peter.maydell@linaro.org
Cc: agraf@suse.de, mdroth@linux.vnet.ibm.com, aik@ozlabs.ru,
	sam.bobroff@au1.ibm.com, imammedo@redhat.com,
	qemu-ppc@nongnu.org, qemu-devel@nongnu.org,
	David Gibson <david@gibson.dropbear.id.au>
Subject: [Qemu-devel] [PULL 31/40] PPC: KVM: Support machine option to set VSMT mode
Date: Fri,  8 Sep 2017 20:35:49 +1000	[thread overview]
Message-ID: <20170908103558.31632-32-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20170908103558.31632-1-david@gibson.dropbear.id.au>

From: Sam Bobroff <sam.bobroff@au1.ibm.com>

KVM now allows writing to KVM_CAP_PPC_SMT which has previously been
read only. Doing so causes KVM to act, for that VM, as if the host's
SMT mode was the given value. This is particularly important on Power
9 systems because their default value is 1, but they are able to
support values up to 8.

This patch introduces a way to control this capability via a new
machine property called VSMT ("Virtual SMT"). If the value is not set
on the command line a default is chosen that is, when possible,
compatible with legacy systems.

Note that the intialization of KVM_CAP_PPC_SMT has changed slightly
because it has changed (in KVM) from a global capability to a
VM-specific one. This won't cause a problem on older KVMs because VM
capabilities fall back to global ones.

Signed-off-by: Sam Bobroff <sam.bobroff@au1.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr.c              | 75 +++++++++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/spapr.h      |  1 +
 target/ppc/kvm.c            | 39 ++++++++++++++++++++++-
 target/ppc/kvm_ppc.h        | 12 ++++++++
 target/ppc/translate_init.c | 14 ---------
 5 files changed, 126 insertions(+), 15 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 067f571416..caffa12763 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -26,6 +26,7 @@
  */
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qapi/visitor.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/numa.h"
 #include "hw/hw.h"
@@ -2165,6 +2166,61 @@ static void spapr_init_cpus(sPAPRMachineState *spapr)
     g_free(type);
 }
 
+static void spapr_set_vsmt_mode(sPAPRMachineState *spapr, Error **errp)
+{
+    Error *local_err = NULL;
+    bool vsmt_user = !!spapr->vsmt;
+    int kvm_smt = kvmppc_smt_threads();
+    int ret;
+
+    if (!kvm_enabled() && (smp_threads > 1)) {
+        error_setg(&local_err, "TCG cannot support more than 1 thread/core "
+                     "on a pseries machine");
+        goto out;
+    }
+    if (!is_power_of_2(smp_threads)) {
+        error_setg(&local_err, "Cannot support %d threads/core on a pseries "
+                     "machine because it must be a power of 2", smp_threads);
+        goto out;
+    }
+
+    /* Detemine the VSMT mode to use: */
+    if (vsmt_user) {
+        if (spapr->vsmt < smp_threads) {
+            error_setg(&local_err, "Cannot support VSMT mode %d"
+                         " because it must be >= threads/core (%d)",
+                         spapr->vsmt, smp_threads);
+            goto out;
+        }
+        /* In this case, spapr->vsmt has been set by the command line */
+    } else {
+        /* Choose a VSMT mode that may be higher than necessary but is
+         * likely to be compatible with hosts that don't have VSMT. */
+        spapr->vsmt = MAX(kvm_smt, smp_threads);
+    }
+
+    /* KVM: If necessary, set the SMT mode: */
+    if (kvm_enabled() && (spapr->vsmt != kvm_smt)) {
+        ret = kvmppc_set_smt_threads(spapr->vsmt);
+        if (ret) {
+            error_setg(&local_err,
+                       "Failed to set KVM's VSMT mode to %d (errno %d)",
+                       spapr->vsmt, ret);
+            if (!vsmt_user) {
+                error_append_hint(&local_err, "On PPC, a VM with %d threads/"
+                             "core on a host with %d threads/core requires "
+                             " the use of VSMT mode %d.\n",
+                             smp_threads, kvm_smt, spapr->vsmt);
+            }
+            kvmppc_hint_smt_possible(&local_err);
+            goto out;
+        }
+    }
+    /* else TCG: nothing to do currently */
+out:
+    error_propagate(errp, local_err);
+}
+
 /* pSeries LPAR / sPAPR hardware init */
 static void ppc_spapr_init(MachineState *machine)
 {
@@ -2297,6 +2353,8 @@ static void ppc_spapr_init(MachineState *machine)
 
     spapr_cpu_parse_features(spapr);
 
+    spapr_set_vsmt_mode(spapr, &error_fatal);
+
     spapr_init_cpus(spapr);
 
     if (kvm_enabled()) {
@@ -2681,6 +2739,18 @@ static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp)
     }
 }
 
+static void spapr_get_vsmt(Object *obj, Visitor *v, const char *name,
+                                   void *opaque, Error **errp)
+{
+    visit_type_uint32(v, name, (uint32_t *)opaque, errp);
+}
+
+static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name,
+                                   void *opaque, Error **errp)
+{
+    visit_type_uint32(v, name, (uint32_t *)opaque, errp);
+}
+
 static void spapr_machine_initfn(Object *obj)
 {
     sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
@@ -2711,6 +2781,11 @@ static void spapr_machine_initfn(Object *obj)
     object_property_set_description(obj, "resize-hpt",
                                     "Resizing of the Hash Page Table (enabled, disabled, required)",
                                     NULL);
+    object_property_add(obj, "vsmt", "uint32", spapr_get_vsmt,
+                        spapr_set_vsmt, NULL, &spapr->vsmt, &error_abort);
+    object_property_set_description(obj, "vsmt",
+                                    "Virtual SMT: KVM behaves as if this were"
+                                    " the host's SMT mode", &error_abort);
 }
 
 static void spapr_machine_finalizefn(Object *obj)
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 91617e3277..c1b365f564 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -99,6 +99,7 @@ struct sPAPRMachineState {
     uint64_t rtc_offset; /* Now used only during incoming migration */
     struct PPCTimebase tb;
     bool has_graphics;
+    uint32_t vsmt;       /* Virtual SMT mode (KVM's "core stride") */
 
     Notifier epow_notifier;
     QTAILQ_HEAD(, sPAPREventLogEntry) pending_events;
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index f1d54106ac..b6bd0fa7a6 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -74,6 +74,7 @@ static int cap_interrupt_level = false;
 static int cap_segstate;
 static int cap_booke_sregs;
 static int cap_ppc_smt;
+static int cap_ppc_smt_possible;
 static int cap_ppc_rma;
 static int cap_spapr_tce;
 static int cap_spapr_tce_64;
@@ -130,7 +131,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
     cap_interrupt_level = kvm_check_extension(s, KVM_CAP_PPC_IRQ_LEVEL);
     cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE);
     cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS);
-    cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT);
+    cap_ppc_smt_possible = kvm_check_extension(s, KVM_CAP_PPC_SMT_POSSIBLE);
     cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA);
     cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
     cap_spapr_tce_64 = kvm_check_extension(s, KVM_CAP_SPAPR_TCE_64);
@@ -144,6 +145,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
      * only activated after this by kvmppc_set_papr() */
     cap_htab_fd = kvm_check_extension(s, KVM_CAP_PPC_HTAB_FD);
     cap_fixup_hcalls = kvm_check_extension(s, KVM_CAP_PPC_FIXUP_HCALL);
+    cap_ppc_smt = kvm_vm_check_extension(s, KVM_CAP_PPC_SMT);
     cap_htm = kvm_vm_check_extension(s, KVM_CAP_PPC_HTM);
     cap_mmu_radix = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_RADIX);
     cap_mmu_hash_v3 = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_HASH_V3);
@@ -2134,6 +2136,41 @@ int kvmppc_smt_threads(void)
     return cap_ppc_smt ? cap_ppc_smt : 1;
 }
 
+int kvmppc_set_smt_threads(int smt)
+{
+    int ret;
+
+    ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_SMT, 0, smt, 0);
+    if (!ret) {
+        cap_ppc_smt = smt;
+    }
+    return ret;
+}
+
+void kvmppc_hint_smt_possible(Error **errp)
+{
+    int i;
+    GString *g;
+    char *s;
+
+    assert(kvm_enabled());
+    if (cap_ppc_smt_possible) {
+        g = g_string_new("Available VSMT modes:");
+        for (i = 63; i >= 0; i--) {
+            if ((1UL << i) & cap_ppc_smt_possible) {
+                g_string_append_printf(g, " %lu", (1UL << i));
+            }
+        }
+        s = g_string_free(g, false);
+        error_append_hint(errp, "%s.\n", s);
+        g_free(s);
+    } else {
+        error_append_hint(errp,
+                          "This KVM seems to be too old to support VSMT.\n");
+    }
+}
+
+
 #ifdef TARGET_PPC64
 off_t kvmppc_alloc_rma(void **rma)
 {
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index 381afe6240..e6711fc2b7 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -29,6 +29,8 @@ void kvmppc_set_papr(PowerPCCPU *cpu);
 int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr);
 void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
 int kvmppc_smt_threads(void);
+void kvmppc_hint_smt_possible(Error **errp);
+int kvmppc_set_smt_threads(int smt);
 int kvmppc_clear_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits);
 int kvmppc_or_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits);
 int kvmppc_set_tcr(PowerPCCPU *cpu);
@@ -148,6 +150,16 @@ static inline int kvmppc_smt_threads(void)
     return 1;
 }
 
+static inline void kvmppc_hint_smt_possible(Error **errp)
+{
+    return;
+}
+
+static inline int kvmppc_set_smt_threads(int smt)
+{
+    return 0;
+}
+
 static inline int kvmppc_or_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits)
 {
     return 0;
diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
index 08ef74f064..703ea12f2a 100644
--- a/target/ppc/translate_init.c
+++ b/target/ppc/translate_init.c
@@ -9907,20 +9907,6 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
     int max_smt = kvmppc_smt_threads();
 #endif
 
-#if !defined(CONFIG_USER_ONLY)
-    if (smp_threads > max_smt) {
-        error_setg(errp, "Cannot support more than %d threads on PPC with %s",
-                   max_smt, kvm_enabled() ? "KVM" : "TCG");
-        return;
-    }
-    if (!is_power_of_2(smp_threads)) {
-        error_setg(errp, "Cannot support %d threads on PPC with %s, "
-                   "threads count must be a power of 2.",
-                   smp_threads, kvm_enabled() ? "KVM" : "TCG");
-        return;
-    }
-#endif
-
     cpu_exec_realizefn(cs, &local_err);
     if (local_err != NULL) {
         error_propagate(errp, local_err);
-- 
2.13.5

  parent reply	other threads:[~2017-09-08 10:36 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-08 10:35 [Qemu-devel] [PULL 00/40] ppc-for-2.11 queue 20170908 David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 01/40] hw/ppc/spapr_drc.c: change spapr_drc_needed to use drc->dev David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 02/40] hw/ppc: clear pending_events on machine reset David Gibson
2017-09-12 17:28   ` Peter Maydell
2017-09-12 18:27     ` [Qemu-devel] [Qemu-ppc] " Greg Kurz
2017-09-08 10:35 ` [Qemu-devel] [PULL 03/40] hw/ppc: CAS reset on early device hotplug David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 04/40] spapr_pci: use memory_region_add_subregion() with DMA windows David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 05/40] spapr_iommu: use g_strdup_printf() instead of snprintf() David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 06/40] spapr_drc: " David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 07/40] spapr_iommu: convert TCE table object to realize() David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 08/40] spapr_pci: parent the MSI memory region to the PHB David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 09/40] spapr_drc: add unrealize method to physical DRC class David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 10/40] spapr_drc: pass object ownership to parent/owner David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 11/40] spapr_iommu: " David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 12/40] spapr_iommu: unregister vmstate at unrealize time David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 13/40] spapr: add pseries-2.11 machine type David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 14/40] e500: Use cpu_index instead of vcpu_dt_id David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 15/40] ppc: spapr: Rename cpu_dt_id to vcpu_id David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 16/40] ppc: spapr: Make VCPU ID handling private to SPAPR David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 17/40] booke206: fix booke206_tlbnps for mav 2.0 David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 18/40] booke206: fix tlbnps for fixed size TLB David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 19/40] booke206: allow to specify an mmucfg value at the init David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 20/40] ppc64: introduce e6500 David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 21/40] spapr_iommu: Realloc guest visible TCE table when hot(un)plugging vfio-pci David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 22/40] ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 23/40] ppc4xx: Make MAL emulation more generic David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 24/40] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 25/40] ppc4xx_i2c: QOMify David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 26/40] ppc4xx_i2c: Move to hw/i2c David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 27/40] ppc4xx: Export ECB and PLB emulation David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 28/40] hw/ppc/spapr_cpu_core: Add a proper check for spapr machine David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 29/40] hw/nvram/spapr_nvram: Device can not be created by the users David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 30/40] spapr: fallback to raw mode if best compat mode cannot be set during CAS David Gibson
2017-09-08 10:35 ` David Gibson [this message]
2017-09-08 10:35 ` [Qemu-devel] [PULL 32/40] target/ppc: Remove old STATUS file David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 33/40] ppc: use macros to make cpu type name from string literal David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 34/40] ppc: make cpu_model translation to type consistent David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 35/40] ppc: make cpu alias point only to real cpu models David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 36/40] ppc: replace inter-function cyclic dependency/recurssion with 2 simple lookups David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 37/40] ppc: simplify cpu model lookup by PVR David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 38/40] ppc: drop caching ObjectClass from PowerPCCPUAlias David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 39/40] ppc: remove non implemented cpu models David Gibson
2017-09-08 10:35 ` [Qemu-devel] [PULL 40/40] ppc: spapr: Move VCPU ID calculation into sPAPR David Gibson
2017-09-08 15:04 ` [Qemu-devel] [PULL 00/40] ppc-for-2.11 queue 20170908 Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170908103558.31632-32-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=agraf@suse.de \
    --cc=aik@ozlabs.ru \
    --cc=imammedo@redhat.com \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    --cc=sam.bobroff@au1.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.