From: Richard Henderson <rth@twiddle.net>
To: qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, ehabkost@redhat.com
Subject: [Qemu-devel] [PATCH 05/14] target-i386: Enable control registers for MPX
Date: Thu, 9 Jul 2015 09:17:20 +0100 [thread overview]
Message-ID: <1436429849-18052-6-git-send-email-rth@twiddle.net> (raw)
In-Reply-To: <1436429849-18052-1-git-send-email-rth@twiddle.net>
Enable and disable at CPL changes, MSR changes, and XRSTOR changes.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-i386/Makefile.objs | 2 +-
target-i386/cpu.c | 18 +++++------
target-i386/cpu.h | 21 ++++++++++++-
target-i386/fpu_helper.c | 78 +++++++++++++++++++++++++++++++++++++++++++++--
target-i386/helper.c | 2 ++
target-i386/kvm.c | 5 +++
target-i386/misc_helper.c | 9 ++++++
target-i386/mpx_helper.c | 51 +++++++++++++++++++++++++++++++
target-i386/smm_helper.c | 4 +++
target-i386/translate.c | 5 +++
10 files changed, 179 insertions(+), 16 deletions(-)
create mode 100644 target-i386/mpx_helper.c
diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs
index 7a1df2c..2cb07e1 100644
--- a/target-i386/Makefile.objs
+++ b/target-i386/Makefile.objs
@@ -1,6 +1,6 @@
obj-y += translate.o helper.o cpu.o
obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o
-obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o
+obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o mpx_helper.o
obj-y += gdbstub.o
obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o
obj-$(CONFIG_KVM) += kvm.o
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index b2fc59f..c19ff8a 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -335,7 +335,8 @@ static const char *cpuid_xsave_feature_name[] = {
#define TCG_SVM_FEATURES 0
#define TCG_KVM_FEATURES 0
#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
- CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX)
+ CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
+ CPUID_7_0_EBX_MPX)
/* missing:
CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2,
CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
@@ -433,12 +434,7 @@ static const X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = {
};
#undef REGISTER
-typedef struct ExtSaveArea {
- uint32_t feature, bits;
- uint32_t offset, size;
-} ExtSaveArea;
-
-static const ExtSaveArea ext_save_areas[] = {
+const ExtSaveArea x86_ext_save_areas[] = {
[2] = { .feature = FEAT_1_ECX, .bits = CPUID_EXT_AVX,
.offset = 0x240, .size = 0x100 },
[3] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX,
@@ -2427,8 +2423,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
if (count == 0) {
*ecx = 0x240;
- for (i = 2; i < ARRAY_SIZE(ext_save_areas); i++) {
- const ExtSaveArea *esa = &ext_save_areas[i];
+ for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
+ const ExtSaveArea *esa = &x86_ext_save_areas[i];
if ((env->features[esa->feature] & esa->bits) == esa->bits
&& ((ena_mask >> i) & 1) != 0) {
if (i < 32) {
@@ -2443,8 +2439,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*ebx = *ecx;
} else if (count == 1) {
*eax = env->features[FEAT_XSAVE];
- } else if (count < ARRAY_SIZE(ext_save_areas)) {
- const ExtSaveArea *esa = &ext_save_areas[count];
+ } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
+ const ExtSaveArea *esa = &x86_ext_save_areas[count];
if ((env->features[esa->feature] & esa->bits) == esa->bits
&& ((ena_mask >> count) & 1) != 0) {
*eax = esa->size;
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index a8153c0..8f0fc35 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -155,6 +155,9 @@
#define HF_OSFXSR_SHIFT 22 /* CR4.OSFXSR */
#define HF_SMAP_SHIFT 23 /* CR4.SMAP */
#define HF_OSXSAVE_SHIFT 24 /* CR4.OSXSAVE */
+#define HF_MPX_EN_SHIFT 25 /* MPX Enabled (CR4+XCR0+BNDCFGx) */
+#define HF_MPX_PR_SHIFT 26 /* BNDCFGx.BNDPRESERVE */
+#define HF_MPX_IU_SHIFT 27 /* BND registers in-use */
#define HF_CPL_MASK (3 << HF_CPL_SHIFT)
#define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT)
@@ -179,6 +182,9 @@
#define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT)
#define HF_SMAP_MASK (1 << HF_SMAP_SHIFT)
#define HF_OSXSAVE_MASK (1 << HF_OSXSAVE_SHIFT)
+#define HF_MPX_EN_MASK (1 << HF_MPX_EN_SHIFT)
+#define HF_MPX_PR_MASK (1 << HF_MPX_PR_SHIFT)
+#define HF_MPX_IU_MASK (1 << HF_MPX_IU_SHIFT)
/* hflags2 */
@@ -741,6 +747,10 @@ typedef struct BNDCSReg {
uint64_t sts;
} BNDCSReg;
+#define BNDCFG_ENABLE 1ULL
+#define BNDCFG_BNDPRESERVE 2ULL
+#define BNDCFG_BDIR_MASK TARGET_PAGE_MASK
+
#ifdef HOST_WORDS_BIGENDIAN
#define XMM_B(n) _b[63 - (n)]
#define XMM_W(n) _w[31 - (n)]
@@ -1096,7 +1106,14 @@ void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32);
int cpu_x86_signal_handler(int host_signum, void *pinfo,
void *puc);
-/* cpuid.c */
+/* cpu.c */
+typedef struct ExtSaveArea {
+ uint32_t feature, bits;
+ uint32_t offset, size;
+} ExtSaveArea;
+
+extern const ExtSaveArea x86_ext_save_areas[];
+
void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx);
@@ -1336,6 +1353,8 @@ void x86_cpu_compat_set_features(const char *cpu_model, FeatureWord w,
void x86_cpu_compat_kvm_no_autoenable(FeatureWord w, uint32_t features);
void x86_cpu_compat_kvm_no_autodisable(FeatureWord w, uint32_t features);
+/* mpx_helper.c */
+void cpu_sync_bndcs_hf(CPUX86State *env);
/* Return name of 32-bit register, from a R_* constant */
const char *get_register_name_32(unsigned int reg);
diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c
index d0b960c..c3cb218 100644
--- a/target-i386/fpu_helper.c
+++ b/target-i386/fpu_helper.c
@@ -1154,6 +1154,22 @@ static void do_xsave_sse(CPUX86State *env, target_ulong ptr)
}
}
+static void do_xsave_bndregs(CPUX86State *env, target_ulong addr)
+{
+ int i;
+
+ for (i = 0; i < 4; i++, addr += 16) {
+ cpu_stq_data(env, addr, env->bnd_regs[i].lb);
+ cpu_stq_data(env, addr + 8, env->bnd_regs[i].ub);
+ }
+}
+
+static void do_xsave_bndcsr(CPUX86State *env, target_ulong addr)
+{
+ cpu_stq_data(env, addr, env->bndcs_regs.cfgu);
+ cpu_stq_data(env, addr + 8, env->bndcs_regs.sts);
+}
+
void helper_fxsave(CPUX86State *env, target_ulong ptr)
{
/* The operand must be 16 byte aligned */
@@ -1176,9 +1192,16 @@ void helper_fxsave(CPUX86State *env, target_ulong ptr)
static uint64_t get_xinuse(CPUX86State *env)
{
- /* We don't track XINUSE. We could calculate it here, but it's
- probably less work to simply indicate all components in use. */
- return -1;
+ uint64_t inuse = -1;
+
+ /* For the most part, we don't track XINUSE. We could calculate it
+ here for all components, but it's probably less work to simply
+ indicate in use. That said, the state of BNDREGS is important
+ enough to track in HFLAGS, so we might as well use that here. */
+ if ((env->hflags & HF_MPX_IU_MASK) == 0) {
+ inuse &= ~XSTATE_BNDREGS;
+ }
+ return inuse;
}
static void do_xsave(CPUX86State *env, target_ulong ptr,
@@ -1205,6 +1228,12 @@ static void do_xsave(CPUX86State *env, target_ulong ptr,
if (opt & XSTATE_SSE) {
do_xsave_sse(env, ptr);
}
+ if (opt & XSTATE_BNDREGS) {
+ do_xsave_bndregs(env, ptr + x86_ext_save_areas[XSTATE_BNDREGS].offset);
+ }
+ if (opt & XSTATE_BNDCSR) {
+ do_xsave_bndcsr(env, ptr + x86_ext_save_areas[XSTATE_BNDCSR].offset);
+ }
/* Update the XSTATE_BV field. */
old_bv = cpu_ldq_data(env, ptr + 512);
@@ -1270,6 +1299,24 @@ static void do_xrstor_sse(CPUX86State *env, target_ulong ptr)
}
}
+static void do_xrstor_bndregs(CPUX86State *env, target_ulong addr)
+{
+ int i;
+
+ for (i = 0; i < 4; i++, addr += 16) {
+ env->bnd_regs[i].lb = cpu_ldq_data(env, addr);
+ env->bnd_regs[i].ub = cpu_ldq_data(env, addr + 8);
+ }
+}
+
+static void do_xrstor_bndcsr(CPUX86State *env, target_ulong addr)
+{
+ /* FIXME: Extend highest implemented bit of linear address. */
+ env->bndcs_regs.cfgu = cpu_ldq_data(env, addr);
+ env->bndcs_regs.sts = cpu_ldq_data(env, addr + 8);
+ cpu_sync_bndcs_hf(env);
+}
+
void helper_fxrstor(CPUX86State *env, target_ulong ptr)
{
/* The operand must be 16 byte aligned */
@@ -1342,6 +1389,25 @@ void helper_xrstor(CPUX86State *env, target_ulong ptr, uint64_t rfbm)
memset(env->xmm_regs, 0, sizeof(env->xmm_regs));
}
}
+ if (rfbm & XSTATE_BNDREGS) {
+ if (xstate_bv & XSTATE_BNDREGS) {
+ do_xrstor_bndregs(env,
+ ptr + x86_ext_save_areas[XSTATE_BNDREGS].offset);
+ env->hflags |= HF_MPX_IU_MASK;
+ } else {
+ memset(env->bnd_regs, 0, sizeof(env->bnd_regs));
+ env->hflags &= ~HF_MPX_IU_MASK;
+ }
+ }
+ if (rfbm & XSTATE_BNDCSR) {
+ if (xstate_bv & XSTATE_BNDCSR) {
+ do_xrstor_bndcsr(env,
+ ptr + x86_ext_save_areas[XSTATE_BNDCSR].offset);
+ } else {
+ memset(&env->bndcs_regs, 0, sizeof(env->bndcs_regs));
+ }
+ cpu_sync_bndcs_hf(env);
+ }
}
uint64_t helper_xgetbv(CPUX86State *env, uint32_t ecx)
@@ -1375,7 +1441,13 @@ void helper_xsetbv(CPUX86State *env, uint32_t ecx, uint64_t mask)
goto do_gpf;
}
+ /* Disallow enabling only half of MPX. */
+ if ((mask ^ (mask * (XSTATE_BNDCSR / XSTATE_BNDREGS))) & XSTATE_BNDCSR) {
+ goto do_gpf;
+ }
+
env->xcr0 = mask;
+ cpu_sync_bndcs_hf(env);
return;
do_gpf:
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 5e8e63d..c7edaa4 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -489,6 +489,8 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
env->cr[4] = new_cr4;
env->hflags = hflags;
+
+ cpu_sync_bndcs_hf(env);
}
#if defined(CONFIG_USER_ONLY)
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index f057982..27ae029 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -2186,6 +2186,11 @@ int kvm_arch_get_registers(CPUState *cs)
if (ret < 0) {
return ret;
}
+
+ /* ??? HFLAGS may be out of sync if any of the above error out.
+ But there seems little point in recomputing this multiple times. */
+ cpu_sync_bndcs_hf(&cpu->env);
+
return 0;
}
diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
index 52c5d65..1e1cc4a 100644
--- a/target-i386/misc_helper.c
+++ b/target-i386/misc_helper.c
@@ -394,6 +394,12 @@ void helper_wrmsr(CPUX86State *env)
case MSR_IA32_MISC_ENABLE:
env->msr_ia32_misc_enable = val;
break;
+ case MSR_IA32_BNDCFGS:
+ /* FIXME: #GP if reserved bits are set. */
+ /* FIXME: Extend highest implemented bit of linear address. */
+ env->msr_bndcfgs = val;
+ cpu_sync_bndcs_hf(env);
+ break;
default:
if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
&& (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
@@ -539,6 +545,9 @@ void helper_rdmsr(CPUX86State *env)
case MSR_IA32_MISC_ENABLE:
val = env->msr_ia32_misc_enable;
break;
+ case MSR_IA32_BNDCFGS:
+ val = env->msr_bndcfgs;
+ break;
default:
if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
&& (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
diff --git a/target-i386/mpx_helper.c b/target-i386/mpx_helper.c
new file mode 100644
index 0000000..decb2ea
--- /dev/null
+++ b/target-i386/mpx_helper.c
@@ -0,0 +1,51 @@
+/*
+ * x86 MPX helpers
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "exec/helper-proto.h"
+#include "exec/cpu_ldst.h"
+
+
+void cpu_sync_bndcs_hf(CPUX86State *env)
+{
+ uint32_t hflags = env->hflags;
+ uint32_t bndcsr;
+
+ if ((hflags & HF_CPL_MASK) == 3) {
+ bndcsr = env->bndcs_regs.cfgu;
+ } else {
+ bndcsr = env->msr_bndcfgs;
+ }
+
+ if ((hflags & HF_OSXSAVE_MASK)
+ && (env->xcr0 & XSTATE_BNDCSR)
+ && (bndcsr & BNDCFG_ENABLE)) {
+ hflags |= HF_MPX_EN_MASK;
+ } else {
+ hflags &= ~HF_MPX_EN_MASK;
+ }
+
+ if (bndcsr & BNDCFG_BNDPRESERVE) {
+ hflags |= HF_MPX_PR_MASK;
+ } else {
+ hflags &= ~HF_MPX_PR_MASK;
+ }
+
+ env->hflags = hflags;
+}
diff --git a/target-i386/smm_helper.c b/target-i386/smm_helper.c
index 02e24b9..77fc1b8 100644
--- a/target-i386/smm_helper.c
+++ b/target-i386/smm_helper.c
@@ -97,6 +97,10 @@ void do_smm_enter(X86CPU *cpu)
x86_stl_phys(cs, sm_state + 0x7e94, env->tr.limit);
x86_stw_phys(cs, sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
+ /* ??? Vol 1, 16.5.6 Intel MPX and SMM says that IA32_BNDCFGS
+ is saved at offset 7ED0. Vol 3, 34.4.1.1, Table 32-2, has
+ 7EA0-7ED7 as "reserved". What's this, and what's really
+ supposed to happen? */
x86_stq_phys(cs, sm_state + 0x7ed0, env->efer);
x86_stq_phys(cs, sm_state + 0x7ff8, env->regs[R_EAX]);
diff --git a/target-i386/translate.c b/target-i386/translate.c
index a98347f..eb30401 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7714,6 +7714,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
cpu_regs[R_EDX]);
gen_helper_xrstor(cpu_env, cpu_A0, cpu_tmp1_i64);
+ /* XRSTOR is how MPX is enabled, which changes how
+ we translate. Thus we need to end the TB. */
+ gen_update_cc_op(s);
+ gen_jmp_im(s->pc - s->cs_base);
+ gen_eob(s);
}
break;
case 6:
--
2.4.3
next prev parent reply other threads:[~2015-07-09 8:18 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-09 8:17 [Qemu-devel] [PATCH 00/14] target-i386: Implement MPX extension Richard Henderson
2015-07-09 8:17 ` [Qemu-devel] [PATCH 01/14] target-i386: Split fxsave/fxrstor implementation Richard Henderson
2015-07-09 8:17 ` [Qemu-devel] [PATCH 02/14] target-i386: Rearrange processing of 0F 01 Richard Henderson
2015-07-09 8:17 ` [Qemu-devel] [PATCH 03/14] target-i386: Add XSAVE extension Richard Henderson
2015-07-09 13:16 ` Paolo Bonzini
2015-07-09 8:17 ` [Qemu-devel] [PATCH 04/14] target-i386: Implement XSAVEOPT Richard Henderson
2015-07-09 13:06 ` Paolo Bonzini
2015-07-10 7:00 ` Richard Henderson
2015-07-09 8:17 ` Richard Henderson [this message]
2015-07-09 13:12 ` [Qemu-devel] [PATCH 05/14] target-i386: Enable control registers for MPX Paolo Bonzini
2015-07-09 13:18 ` Paolo Bonzini
2015-07-10 7:44 ` Richard Henderson
2016-02-09 13:28 ` Paolo Bonzini
2016-02-09 15:50 ` Eric Blake
2016-02-09 15:50 ` Paolo Bonzini
2016-02-09 19:08 ` Richard Henderson
2015-07-09 8:17 ` [Qemu-devel] [PATCH 06/14] target-i386: Perform set/reset_inhibit_irq inline Richard Henderson
2015-07-09 8:17 ` [Qemu-devel] [PATCH 07/14] target-i386: Split up gen_lea_modrm Richard Henderson
2015-07-09 8:17 ` [Qemu-devel] [PATCH 08/14] target-i386: Implement BNDMK Richard Henderson
2015-07-09 8:17 ` [Qemu-devel] [PATCH 09/14] target-i386: Implement BNDMOV Richard Henderson
2015-07-09 8:17 ` [Qemu-devel] [PATCH 10/14] target-i386: Implement BNDCL, BNDCU, BNDCN Richard Henderson
2015-07-09 8:17 ` [Qemu-devel] [PATCH 11/14] target-i386: Update BNDSTATUS for exceptions raised by BOUND Richard Henderson
2015-07-09 8:17 ` [Qemu-devel] [PATCH 12/14] target-i386: Implement BNDLDX, BNDSTX Richard Henderson
2015-07-09 8:17 ` [Qemu-devel] [PATCH 13/14] target-i386: Clear bndregs during legacy near jumps Richard Henderson
2015-07-09 8:17 ` [Qemu-devel] [PATCH 14/14] target-i386: Enable XCR0 features for user-mode Richard Henderson
2015-07-09 13:15 ` Paolo Bonzini
2015-07-10 7:24 ` Richard Henderson
2015-07-10 9:36 ` Paolo Bonzini
2015-11-17 17:43 ` [Qemu-devel] [PATCH 00/14] target-i386: Implement MPX extension Paolo Bonzini
2015-11-18 9:43 ` Richard Henderson
2015-11-18 10:13 ` Paolo Bonzini
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=1436429849-18052-6-git-send-email-rth@twiddle.net \
--to=rth@twiddle.net \
--cc=ehabkost@redhat.com \
--cc=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).