diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2016-02-09 14:14:28 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2016-03-24 14:01:08 +0100 |
commit | 0f70ed4759a29ca932af1e9525729f4f455642f8 (patch) | |
tree | c5a8fb95b4971c83ba998045d43b73e926b084ef /target-i386/fpu_helper.c | |
parent | cf7cc9291bf7f2f6470815db876ed28eb474ea52 (diff) |
target-i386: implement PKE for TCG
Tested with kvm-unit-tests.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'target-i386/fpu_helper.c')
-rw-r--r-- | target-i386/fpu_helper.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c index d1a7f4cbec..fee5573a10 100644 --- a/target-i386/fpu_helper.c +++ b/target-i386/fpu_helper.c @@ -1184,6 +1184,11 @@ static void do_xsave_bndcsr(CPUX86State *env, target_ulong addr, uintptr_t ra) cpu_stq_data_ra(env, addr + 8, env->bndcs_regs.sts, ra); } +static void do_xsave_pkru(CPUX86State *env, target_ulong addr, uintptr_t ra) +{ + cpu_stq_data_ra(env, addr, env->pkru, ra); +} + void helper_fxsave(CPUX86State *env, target_ulong ptr) { uintptr_t ra = GETPC(); @@ -1257,6 +1262,10 @@ static void do_xsave(CPUX86State *env, target_ulong ptr, uint64_t rfbm, target_ulong off = x86_ext_save_areas[XSTATE_BNDCSR_BIT].offset; do_xsave_bndcsr(env, ptr + off, ra); } + if (opt & XSTATE_PKRU_MASK) { + target_ulong off = x86_ext_save_areas[XSTATE_PKRU_BIT].offset; + do_xsave_pkru(env, ptr + off, ra); + } /* Update the XSTATE_BV field. */ old_bv = cpu_ldq_data_ra(env, ptr + 512, ra); @@ -1339,6 +1348,11 @@ static void do_xrstor_bndcsr(CPUX86State *env, target_ulong addr, uintptr_t ra) env->bndcs_regs.sts = cpu_ldq_data_ra(env, addr + 8, ra); } +static void do_xrstor_pkru(CPUX86State *env, target_ulong addr, uintptr_t ra) +{ + env->pkru = cpu_ldq_data_ra(env, addr, ra); +} + void helper_fxrstor(CPUX86State *env, target_ulong ptr) { uintptr_t ra = GETPC(); @@ -1438,6 +1452,19 @@ void helper_xrstor(CPUX86State *env, target_ulong ptr, uint64_t rfbm) } cpu_sync_bndcs_hflags(env); } + if (rfbm & XSTATE_PKRU_MASK) { + uint64_t old_pkru = env->pkru; + if (xstate_bv & XSTATE_PKRU_MASK) { + target_ulong off = x86_ext_save_areas[XSTATE_PKRU_BIT].offset; + do_xrstor_pkru(env, ptr + off, ra); + } else { + env->pkru = 0; + } + if (env->pkru != old_pkru) { + CPUState *cs = CPU(x86_env_get_cpu(env)); + tlb_flush(cs, 1); + } + } } uint64_t helper_xgetbv(CPUX86State *env, uint32_t ecx) |