qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 5/5] target-i386: implement PKE for TCG


From: Richard Henderson
Subject: Re: [Qemu-devel] [PATCH 5/5] target-i386: implement PKE for TCG
Date: Wed, 10 Feb 2016 05:13:45 +1100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.5.0

On 02/10/2016 04:13 AM, Paolo Bonzini wrote:
@@ -157,6 +157,7 @@
  #define HF_SMAP_SHIFT       23 /* CR4.SMAP */
  #define HF_IOBPT_SHIFT      24 /* an io breakpoint enabled */
  #define HF_OSXSAVE_SHIFT    25 /* CR4.OSXSAVE */
+#define HF_PKE_SHIFT        26 /* CR4.PKE enabled */

I don't believe you need this bit at all. Certainly you don't use it in translate.c, where any such test ought to have been.

  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, for state that is important
+     * enough to track in HFLAGS, we might as well use that here.
+     */
+    if ((env->hflags & HF_PKE_MASK) == 0) {
+       inuse &= ~XSTATE_PKRU;
+    }
+    return inuse;
+}

That does change this of course. But the entire state of the feature is one 32-bit integer -- it's just as easy to test that.

@@ -1357,6 +1399,10 @@ void helper_xrstor(CPUX86State *env, target_ulong ptr, 
uint64_t rfbm)
              memset(env->xmm_regs, 0, sizeof(env->xmm_regs));
          }
      }
+
+    if (rfbm & XSTATE_PKRU) {
+        do_xrstor_pkru(env, ptr, GETPC());
+    }

There should be an "ra" variable at the top of this function that already holds GETPC. Are you forgetting a check on xstate_bv here, to clear pkru?

diff --git a/target-i386/helper.c b/target-i386/helper.c
index f5f0bec..a55628f 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -689,6 +689,16 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
          hflags |= HF_SMAP_MASK;
      }

+    if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_PKU)) {
+        new_cr4 &= ~CR4_PKE_MASK;
+    }
+    env->hflags &= ~HF_PKE_MASK;
+    env->features[FEAT_7_0_ECX] &= ~CPUID_7_0_ECX_OSPKE;
+    if (new_cr4 & CR4_PKE_MASK) {
+        env->hflags |= HF_PKE_MASK;
+       env->features[FEAT_7_0_ECX] |= CPUID_7_0_ECX_OSPKE;
+    }

Don't change features bits. Do this test in cpu_x86_cpuid instead. See where we give the same treatment to OSXSAVE.

diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
index 460257f..b517559 100644
--- a/target-i386/misc_helper.c
+++ b/target-i386/misc_helper.c
@@ -600,3 +600,35 @@ void helper_debug(CPUX86State *env)
      cs->exception_index = EXCP_DEBUG;
      cpu_loop_exit(cs);
  }
+
+void helper_rdpkru(CPUX86State *env)
+{
+    if ((env->cr[4] & CR4_PKE_MASK) == 0) {
+        raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
+        return;
+    }

The document I have says #GP for this case, not #UD.

+    if (env->regs[R_ECX] != 0) {
+        raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
+        return;
+    }

In 64-bit mode, ecx 63:32 are ignored.

+
+    env->regs[R_EAX] = env->pkru;
+    env->regs[R_EDX] = 0;
+}

It would be better to return a 64-bit value, split and assign it to eax:edx in the translator, so that this function does not modify tcg registers.

+
+void helper_wrpkru(CPUX86State *env)
+{
+    CPUState *cs = CPU(x86_env_get_cpu(env));
+
+    if ((env->cr[4] & CR4_PKE_MASK) == 0) {
+        raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
+        return;
+    }

Similarly.

diff --git a/target-i386/translate.c b/target-i386/translate.c
index b84ce3b..e2726d4 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7262,6 +7262,16 @@ static target_ulong disas_insn(CPUX86State *env, 
DisasContext *s,
  #endif
              gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 1);
              break;
+        case 0xee: /* rdpkru */
+            gen_update_cc_op(s);
+            gen_jmp_im(pc_start - s->cs_base);
+            gen_helper_rdpkru(cpu_env);
+            break;

No need for either update_cc_op or gen_jmp_im, now that we've got raise_exception_err_ra.

Missing check for lock prefix.

If you make the change to return a 64-bit value, this would look like

  gen_helper_rdpkru(cpu_tmp1_i64, cpu_env);
  tcg_gen_extr_i64_tl(cpu_regs[REG_EAX], cpu_regs[REG_EDX], cpu_tmp1_i64);


+        case 0xef: /* wrpkru */
+            gen_update_cc_op(s);
+            gen_jmp_im(pc_start - s->cs_base);
+            gen_helper_wrpkru(cpu_env);
+            break;
          CASE_MEM_OP(6): /* lmsw */
              if (s->cpl != 0) {
                  gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);




r~



reply via email to

[Prev in Thread] Current Thread [Next in Thread]