All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: groug@kaod.org, clg@kaod.org, aik@ozlabs.ru,
	mdroth@linux.vnet.ibm.com, nikunj@linux.vnet.ibm.com
Cc: agraf@suse.de, qemu-ppc@nongnu.org, qemu-devel@nongnu.org,
	abologna@redhat.com, thuth@redhat.com, lvivier@redhat.com,
	David Gibson <david@gibson.dropbear.id.au>
Subject: [Qemu-devel] [RFCv2 07/12] ppc: Validate compatibility modes when setting
Date: Wed, 16 Nov 2016 09:17:50 +1100	[thread overview]
Message-ID: <1479248275-18889-8-git-send-email-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <1479248275-18889-1-git-send-email-david@gibson.dropbear.id.au>

Current ppc_set_compat() will attempt to set any compatiblity mode
specified, regardless of whether it's available on the CPU.  The caller is
expected to make sure it is setting a possible mode, which is awkwward
because most of the information to make that decision is at the CPU level.

This begins to clean this up by introducing a ppc_check_compat() function
which will determine if a given compatiblity mode is supported on a CPU
(and also whether it lies within specified minimum and maximum compat
levels, which will be useful later).  It also contains an assertion that
the CPU has a "virtual hypervisor"[1], that is, that the guest isn't
permitted to execute hypervisor privilege code.  Without that, the guest
would own the PCR and so could override any mode set here.  Only machine
types which use a virtual hypervisor (i.e. 'pseries') should use
ppc_check_compat().

ppc_set_compat() is modified to validate the compatibility mode it is given
and fail if it's not available on this CPU.

[1] Or user-only mode, which also obviously doesn't allow access to the
hypervisor privileged PCR.  We don't use that now, but could in future.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
 target-ppc/compat.c | 41 +++++++++++++++++++++++++++++++++++++++++
 target-ppc/cpu.h    |  2 ++
 2 files changed, 43 insertions(+)

diff --git a/target-ppc/compat.c b/target-ppc/compat.c
index 66529a6..1059555 100644
--- a/target-ppc/compat.c
+++ b/target-ppc/compat.c
@@ -28,29 +28,37 @@
 typedef struct {
     uint32_t pvr;
     uint64_t pcr;
+    uint64_t pcr_level;
     int max_threads;
 } CompatInfo;
 
 static const CompatInfo compat_table[] = {
+    /*
+     * Ordered from oldest to newest - the code relies on this
+     */
     { /* POWER6, ISA2.05 */
         .pvr = CPU_POWERPC_LOGICAL_2_05,
         .pcr = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05
                | PCR_TM_DIS | PCR_VSX_DIS,
+        .pcr_level = PCR_COMPAT_2_05,
         .max_threads = 2,
     },
     { /* POWER7, ISA2.06 */
         .pvr = CPU_POWERPC_LOGICAL_2_06,
         .pcr = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_TM_DIS,
+        .pcr_level = PCR_COMPAT_2_06,
         .max_threads = 4,
     },
     {
         .pvr = CPU_POWERPC_LOGICAL_2_06_PLUS,
         .pcr = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_TM_DIS,
+        .pcr_level = PCR_COMPAT_2_06,
         .max_threads = 4,
     },
     { /* POWER8, ISA2.07 */
         .pvr = CPU_POWERPC_LOGICAL_2_07,
         .pcr = PCR_COMPAT_2_07,
+        .pcr_level = PCR_COMPAT_2_07,
         .max_threads = 8,
     },
 };
@@ -67,6 +75,35 @@ static const CompatInfo *compat_by_pvr(uint32_t pvr)
     return NULL;
 }
 
+bool ppc_check_compat(PowerPCCPU *cpu, uint32_t compat_pvr,
+                      uint32_t min_compat_pvr, uint32_t max_compat_pvr)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+    const CompatInfo *compat = compat_by_pvr(compat_pvr);
+    const CompatInfo *min = compat_by_pvr(min_compat_pvr);
+    const CompatInfo *max = compat_by_pvr(max_compat_pvr);
+
+#if !defined(CONFIG_USER_ONLY)
+    g_assert(cpu->vhyp);
+#endif
+    g_assert(!min_compat_pvr || min);
+    g_assert(!max_compat_pvr || max);
+
+    if (!compat) {
+        /* Not a recognized logical PVR */
+        return false;
+    }
+    if ((min && (compat < min)) || (max && (compat > max))) {
+        /* Outside specified range */
+        return false;
+    }
+    if (!(pcc->pcr_supported & compat->pcr_level)) {
+        /* Not supported by this CPU */
+        return false;
+    }
+    return true;
+}
+
 void ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp)
 {
     const CompatInfo *compat = compat_by_pvr(compat_pvr);
@@ -79,6 +116,10 @@ void ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp)
     } else if (!compat) {
         error_setg(errp, "Unknown compatibility PVR 0x%08"PRIx32, compat_pvr);
         return;
+    } else if (!ppc_check_compat(cpu, compat_pvr, 0, 0)) {
+        error_setg(errp, "Compatibility PVR 0x%08"PRIx32" not valid for CPU",
+                   compat_pvr);
+        return;
     } else {
         pcr = compat->pcr;
     }
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index cfda7b2..91e8be8 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1314,6 +1314,8 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 
 /* Compatibility modes */
 #if defined(TARGET_PPC64)
+bool ppc_check_compat(PowerPCCPU *cpu, uint32_t compat_pvr,
+                      uint32_t min_compat_pvr, uint32_t max_compat_pvr);
 void ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp);
 int ppc_compat_max_threads(PowerPCCPU *cpu);
 #endif /* defined(TARGET_PPC64) */
-- 
2.7.4

  parent reply	other threads:[~2016-11-15 22:18 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-15 22:17 [Qemu-devel] [RFCv2 00/12] Clean up compatibility mode handling David Gibson
2016-11-15 22:17 ` [Qemu-devel] [RFCv2 01/12] pseries: Always use core objects for CPU construction David Gibson
2016-11-18 15:00   ` Greg Kurz
2016-11-15 22:17 ` [Qemu-devel] [RFCv2 02/12] pseries: Make cpu_update during CAS unconditional David Gibson
2016-11-15 22:17 ` [Qemu-devel] [RFCv2 03/12] ppc: Clean up and QOMify hypercall emulation David Gibson
2016-11-15 22:17 ` [Qemu-devel] [RFCv2 04/12] ppc: Rename cpu_version to compat_pvr David Gibson
2016-11-15 22:17 ` [Qemu-devel] [RFCv2 05/12] ppc: Rewrite ppc_set_compat() David Gibson
2016-11-15 22:17 ` [Qemu-devel] [RFCv2 06/12] ppc: Rewrite ppc_get_compat_smt_threads() David Gibson
2016-11-15 22:17 ` David Gibson [this message]
2016-11-15 22:17 ` [Qemu-devel] [RFCv2 08/12] pseries: Rewrite CAS PVR compatibility logic David Gibson
2016-11-15 22:17 ` [Qemu-devel] [RFCv2 09/12] ppc: Add ppc_set_compat_all() David Gibson
2016-11-15 22:17 ` [Qemu-devel] [RFCv2 10/12] pseries: Move CPU compatibility property to machine David Gibson
2016-11-19  8:27   ` Greg Kurz
2016-11-15 22:17 ` [Qemu-devel] [RFCv2 11/12] pseries: Reset CPU compatibility mode David Gibson
2016-11-15 22:17 ` [Qemu-devel] [RFCv2 12/12] ppc: Rework CPU compatibility testing across migration David Gibson
2016-12-02 14:48   ` [Qemu-devel] [Qemu-ppc] " Greg Kurz
2016-12-05  4:09     ` David Gibson
2016-12-13 17:58       ` Greg Kurz
2016-11-15 22:44 ` [Qemu-devel] [RFCv2 00/12] Clean up compatibility mode handling no-reply
2016-11-26  0:33 ` Greg Kurz
2016-11-28  4:23   ` David Gibson
2016-11-28  4:25     ` David Gibson
2016-12-01 13:16 ` Greg Kurz

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=1479248275-18889-8-git-send-email-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=abologna@redhat.com \
    --cc=agraf@suse.de \
    --cc=aik@ozlabs.ru \
    --cc=clg@kaod.org \
    --cc=groug@kaod.org \
    --cc=lvivier@redhat.com \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=nikunj@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    --cc=thuth@redhat.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.