qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Subject: [PULL 18/46] target/i86: implement PKS
Date: Mon,  8 Feb 2021 19:23:03 +0100	[thread overview]
Message-ID: <20210208182331.58897-19-pbonzini@redhat.com> (raw)
In-Reply-To: <20210208182331.58897-1-pbonzini@redhat.com>

Protection Keys for Supervisor-mode pages is a simple extension of
the PKU feature that QEMU already implements.  For supervisor-mode
pages, protection key restrictions come from a new MSR.  The MSR
has no XSAVE state associated to it.

PKS is only respected in long mode.  However, in principle it is
possible to set the MSR even outside long mode, and in fact
even the XSAVE state for PKRU could be set outside long mode
using XRSTOR.  So do not limit the migration subsections for
PKRU and PKRS to long mode.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/cpu.c             |  4 ++--
 target/i386/cpu.h             |  5 +++++
 target/i386/helper.c          |  3 +++
 target/i386/machine.c         | 24 ++++++++++++++++++++----
 target/i386/tcg/excp_helper.c | 32 ++++++++++++++++++++------------
 target/i386/tcg/misc_helper.c | 14 ++++++++++++++
 6 files changed, 64 insertions(+), 18 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index ff25ad6f6c..0b0d65c21c 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -667,7 +667,7 @@ static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
           CPUID_7_0_EBX_RDSEED */
 #define TCG_7_0_ECX_FEATURES (CPUID_7_0_ECX_PKU | \
           /* CPUID_7_0_ECX_OSPKE is dynamic */ \
-          CPUID_7_0_ECX_LA57)
+          CPUID_7_0_ECX_LA57 | CPUID_7_0_ECX_PKS)
 #define TCG_7_0_EDX_FEATURES 0
 #define TCG_7_1_EAX_FEATURES 0
 #define TCG_APM_FEATURES 0
@@ -964,7 +964,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
             "la57", NULL, NULL, NULL,
             NULL, NULL, "rdpid", NULL,
             NULL, "cldemote", NULL, "movdiri",
-            "movdir64b", NULL, NULL, NULL,
+            "movdir64b", NULL, NULL, "pks",
         },
         .cpuid = {
             .eax = 7,
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index b39ec505de..cc5a26f35b 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -247,6 +247,7 @@ typedef enum X86Seg {
 #define CR4_SMEP_MASK   (1U << 20)
 #define CR4_SMAP_MASK   (1U << 21)
 #define CR4_PKE_MASK   (1U << 22)
+#define CR4_PKS_MASK   (1U << 24)
 
 #define DR6_BD          (1 << 13)
 #define DR6_BS          (1 << 14)
@@ -357,6 +358,7 @@ typedef enum X86Seg {
 
 #define MSR_IA32_TSX_CTRL		0x122
 #define MSR_IA32_TSCDEADLINE            0x6e0
+#define MSR_IA32_PKRS                   0x6e1
 
 #define FEATURE_CONTROL_LOCKED                    (1<<0)
 #define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX (1<<2)
@@ -772,6 +774,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_ECX_MOVDIRI           (1U << 27)
 /* Move 64 Bytes as Direct Store Instruction */
 #define CPUID_7_0_ECX_MOVDIR64B         (1U << 28)
+/* Protection Keys for Supervisor-mode Pages */
+#define CPUID_7_0_ECX_PKS               (1U << 31)
 
 /* AVX512 Neural Network Instructions */
 #define CPUID_7_0_EDX_AVX512_4VNNIW     (1U << 2)
@@ -1487,6 +1491,7 @@ typedef struct CPUX86State {
     uint64_t msr_smi_count;
 
     uint32_t pkru;
+    uint32_t pkrs;
     uint32_t tsx_ctrl;
 
     uint64_t spec_ctrl;
diff --git a/target/i386/helper.c b/target/i386/helper.c
index 6bb0c53182..618ad1c409 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -194,6 +194,9 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
     if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_PKU)) {
         new_cr4 &= ~CR4_PKE_MASK;
     }
+    if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_PKS)) {
+        new_cr4 &= ~CR4_PKS_MASK;
+    }
 
     env->cr[4] = new_cr4;
     env->hflags = hflags;
diff --git a/target/i386/machine.c b/target/i386/machine.c
index 1614e8c2f8..3768a753af 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -980,7 +980,6 @@ static const VMStateDescription vmstate_umwait = {
     }
 };
 
-#ifdef TARGET_X86_64
 static bool pkru_needed(void *opaque)
 {
     X86CPU *cpu = opaque;
@@ -999,7 +998,25 @@ static const VMStateDescription vmstate_pkru = {
         VMSTATE_END_OF_LIST()
     }
 };
-#endif
+
+static bool pkrs_needed(void *opaque)
+{
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
+
+    return env->pkrs != 0;
+}
+
+static const VMStateDescription vmstate_pkrs = {
+    .name = "cpu/pkrs",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = pkrs_needed,
+    .fields = (VMStateField[]){
+        VMSTATE_UINT32(env.pkrs, X86CPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static bool tsc_khz_needed(void *opaque)
 {
@@ -1480,9 +1497,8 @@ VMStateDescription vmstate_x86_cpu = {
         &vmstate_umwait,
         &vmstate_tsc_khz,
         &vmstate_msr_smi_count,
-#ifdef TARGET_X86_64
         &vmstate_pkru,
-#endif
+        &vmstate_pkrs,
         &vmstate_spec_ctrl,
         &vmstate_mcg_ext_ctl,
         &vmstate_msr_intel_pt,
diff --git a/target/i386/tcg/excp_helper.c b/target/i386/tcg/excp_helper.c
index a0f44431fe..b7d6259e4a 100644
--- a/target/i386/tcg/excp_helper.c
+++ b/target/i386/tcg/excp_helper.c
@@ -361,6 +361,7 @@ static int handle_mmu_fault(CPUState *cs, vaddr addr, int size,
     uint64_t rsvd_mask = PG_HI_RSVD_MASK;
     uint32_t page_offset;
     target_ulong vaddr;
+    uint32_t pkr;
 
     is_user = mmu_idx == MMU_USER_IDX;
 #if defined(DEBUG_MMU)
@@ -588,21 +589,28 @@ do_check_protect_pse36:
          !((env->cr[4] & CR4_SMEP_MASK) && (ptep & PG_USER_MASK)))) {
         prot |= PAGE_EXEC;
     }
-    if ((env->cr[4] & CR4_PKE_MASK) && (env->hflags & HF_LMA_MASK) &&
-        (ptep & PG_USER_MASK) && env->pkru) {
+
+    if (!(env->hflags & HF_LMA_MASK)) {
+        pkr = 0;
+    } else if (ptep & PG_USER_MASK) {
+        pkr = env->cr[4] & CR4_PKE_MASK ? env->pkru : 0;
+    } else {
+        pkr = env->cr[4] & CR4_PKS_MASK ? env->pkrs : 0;
+    }
+    if (pkr) {
         uint32_t pk = (pte & PG_PKRU_MASK) >> PG_PKRU_BIT;
-        uint32_t pkru_ad = (env->pkru >> pk * 2) & 1;
-        uint32_t pkru_wd = (env->pkru >> pk * 2) & 2;
-        uint32_t pkru_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
-
-        if (pkru_ad) {
-            pkru_prot &= ~(PAGE_READ | PAGE_WRITE);
-        } else if (pkru_wd && (is_user || env->cr[0] & CR0_WP_MASK)) {
-            pkru_prot &= ~PAGE_WRITE;
+        uint32_t pkr_ad = (pkr >> pk * 2) & 1;
+        uint32_t pkr_wd = (pkr >> pk * 2) & 2;
+        uint32_t pkr_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+
+        if (pkr_ad) {
+            pkr_prot &= ~(PAGE_READ | PAGE_WRITE);
+        } else if (pkr_wd && (is_user || env->cr[0] & CR0_WP_MASK)) {
+            pkr_prot &= ~PAGE_WRITE;
         }
 
-        prot &= pkru_prot;
-        if ((pkru_prot & (1 << is_write1)) == 0) {
+        prot &= pkr_prot;
+        if ((pkr_prot & (1 << is_write1)) == 0) {
             assert(is_write1 != 2);
             error_code |= PG_ERROR_PK_MASK;
             goto do_fault_protect;
diff --git a/target/i386/tcg/misc_helper.c b/target/i386/tcg/misc_helper.c
index 0bd6c95749..f02e4fd400 100644
--- a/target/i386/tcg/misc_helper.c
+++ b/target/i386/tcg/misc_helper.c
@@ -244,6 +244,7 @@ void helper_rdmsr(CPUX86State *env)
 void helper_wrmsr(CPUX86State *env)
 {
     uint64_t val;
+    CPUState *cs = env_cpu(env);
 
     cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
 
@@ -296,6 +297,13 @@ void helper_wrmsr(CPUX86State *env)
     case MSR_PAT:
         env->pat = val;
         break;
+    case MSR_IA32_PKRS:
+        if (val & 0xFFFFFFFF00000000ull) {
+            goto error;
+        }
+        env->pkrs = val;
+        tlb_flush(cs);
+        break;
     case MSR_VM_HSAVE_PA:
         env->vm_hsave = val;
         break;
@@ -399,6 +407,9 @@ void helper_wrmsr(CPUX86State *env)
         /* XXX: exception? */
         break;
     }
+    return;
+error:
+    raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
 }
 
 void helper_rdmsr(CPUX86State *env)
@@ -430,6 +441,9 @@ void helper_rdmsr(CPUX86State *env)
     case MSR_PAT:
         val = env->pat;
         break;
+    case MSR_IA32_PKRS:
+        val = env->pkrs;
+        break;
     case MSR_VM_HSAVE_PA:
         val = env->vm_hsave;
         break;
-- 
2.29.2




  parent reply	other threads:[~2021-02-08 23:04 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-08 18:22 [PULL 00/46] Misc patches for 2021-02-08 Paolo Bonzini
2021-02-08 18:22 ` [PULL 01/46] fuzz: ignore address_space_map is_write flag Paolo Bonzini
2021-02-08 18:22 ` [PULL 02/46] fuzz: refine the ide/ahci fuzzer configs Paolo Bonzini
2021-02-08 18:22 ` [PULL 03/46] docs/fuzz: fix pre-meson path Paolo Bonzini
2021-02-08 18:22 ` [PULL 04/46] fuzz: log the arguments used to initialize QEMU Paolo Bonzini
2021-02-08 18:22 ` [PULL 05/46] fuzz: enable dynamic args for generic-fuzz configs Paolo Bonzini
2021-02-08 18:22 ` [PULL 06/46] docs/fuzz: add some information about OSS-Fuzz Paolo Bonzini
2021-02-08 18:22 ` [PULL 07/46] fuzz: add virtio-9p configurations for fuzzing Paolo Bonzini
2021-02-08 18:22 ` [PULL 08/46] target/i386: do not set LM for 32-bit emulation "-cpu host/max" Paolo Bonzini
2021-02-08 18:22 ` [PULL 09/46] machine: add missing doc for memory-backend option Paolo Bonzini
2021-02-08 18:22 ` [PULL 10/46] meson: accept either shared or static libraries if --disable-static Paolo Bonzini
2021-02-08 18:22 ` [PULL 11/46] meson: honor --enable-rbd if cc.links test fails Paolo Bonzini
2021-02-08 18:22 ` [PULL 12/46] x86/cpu: Populate SVM CPUID feature bits Paolo Bonzini
2021-02-08 18:22 ` [PULL 13/46] fuzz: fix wrong index in clear_bits Paolo Bonzini
2021-02-08 18:22 ` [PULL 14/46] docs: don't install corresponding man page if guest agent is disabled Paolo Bonzini
2021-02-08 18:23 ` [PULL 15/46] virtio-scsi: don't uninitialize queues that we didn't initialize Paolo Bonzini
2021-02-08 18:23 ` [PULL 16/46] event_notifier: handle initialization failure better Paolo Bonzini
2021-02-08 18:23 ` [PULL 17/46] target/i386: Fix decoding of certain BMI instructions Paolo Bonzini
2021-02-08 18:23 ` Paolo Bonzini [this message]
2021-02-08 18:23 ` [PULL 19/46] configure: Improve TCI feature description Paolo Bonzini
2021-02-08 18:23 ` [PULL 20/46] meson: Explicit TCG backend used Paolo Bonzini
2021-02-08 18:23 ` [PULL 21/46] meson: Warn when TCI is selected but TCG backend is available Paolo Bonzini
2021-05-21  8:49   ` Peter Maydell
2021-02-08 18:23 ` [PULL 22/46] tests/meson: Only build softfloat objects if TCG is selected Paolo Bonzini
2021-02-08 18:23 ` [PULL 23/46] pc-bios/meson: Only install EDK2 blob firmwares with system emulation Paolo Bonzini
2021-02-08 18:23 ` [PULL 24/46] meson: Restrict block subsystem processing Paolo Bonzini
2021-02-08 18:23 ` [PULL 25/46] meson: Merge trace_events_subdirs array Paolo Bonzini
2021-02-08 18:23 ` [PULL 26/46] meson: Restrict some trace event directories to user/system emulation Paolo Bonzini
2021-02-08 18:23 ` [PULL 27/46] meson: Restrict emulation code Paolo Bonzini
2021-02-08 18:23 ` [PULL 28/46] qapi/meson: Restrict qdev code to system-mode emulation Paolo Bonzini
2021-02-08 18:23 ` [PULL 29/46] qapi/meson: Remove QMP from user-mode emulation Paolo Bonzini
2021-02-08 18:23 ` [PULL 30/46] qapi/meson: Restrict system-mode specific modules Paolo Bonzini
2021-02-08 18:23 ` [PULL 31/46] qapi/meson: Restrict UI module to system emulation and tools Paolo Bonzini
2021-02-08 18:23 ` [PULL 32/46] accel/kvm/kvm-all: Fix wrong return code handling in dirty log code Paolo Bonzini
2021-02-08 18:23 ` [PULL 33/46] replay: fix replay of the interrupts Paolo Bonzini
2021-02-08 18:23 ` [PULL 34/46] pc-bios/descriptors: fix paths in json files Paolo Bonzini
2021-02-08 18:23 ` [PULL 35/46] replay: rng-builtin support Paolo Bonzini
2021-02-08 18:23 ` [PULL 36/46] cpu-throttle: Remove timer_mod() from cpu_throttle_set() Paolo Bonzini
2021-02-08 18:23 ` [PULL 37/46] hw/pci-host: add pci-intack write method Paolo Bonzini
2021-02-08 18:23 ` [PULL 38/46] pci-host: designware: add pcie-msi read method Paolo Bonzini
2021-02-08 18:23 ` [PULL 39/46] vfio: add quirk device write method Paolo Bonzini
2021-02-08 18:23 ` [PULL 40/46] prep: add ppc-parity " Paolo Bonzini
2021-02-08 18:23 ` [PULL 41/46] nvram: add nrf51_soc flash read method Paolo Bonzini
2021-02-08 18:23 ` [PULL 42/46] spapr_pci: add spapr msi " Paolo Bonzini
2021-02-08 18:23 ` [PULL 43/46] tz-ppc: add dummy read/write methods Paolo Bonzini
2021-02-08 18:23 ` [PULL 44/46] imx7-ccm: add digprog mmio write method Paolo Bonzini
2021-02-08 18:23 ` [PULL 45/46] target/i386: Add support for save/load IA32_PKRS MSR Paolo Bonzini
2021-02-08 18:23 ` [PULL 46/46] target/i386: Expose VMX entry/exit load pkrs control bits Paolo Bonzini
2021-02-09 13:24 ` [PULL 00/46] Misc patches for 2021-02-08 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=20210208182331.58897-19-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).