Commit eef26553c782c26646c8b5b63afa6182187104eb

Authored by aliguori
1 parent 059cef40

Implement FFXSR (Alexander Graf)

Newer AMD CPUs have the FFXSR capability. This leaves out XMM
register in FXSAVE/FXRESTORE when in CPL=0 and 64-bit mode.

This is required for Hyper-V.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6500 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 20 additions and 8 deletions
target-i386/op_helper.c
... ... @@ -3030,6 +3030,8 @@ void helper_wrmsr(void)
3030 3030 update_mask |= MSR_EFER_NXE;
3031 3031 if (env->cpuid_ext3_features & CPUID_EXT3_SVM)
3032 3032 update_mask |= MSR_EFER_SVME;
  3033 + if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
  3034 + update_mask |= MSR_EFER_FFXSR;
3033 3035 cpu_load_efer(env, (env->efer & ~update_mask) |
3034 3036 (val & update_mask));
3035 3037 }
... ... @@ -4352,10 +4354,15 @@ void helper_fxsave(target_ulong ptr, int data64)
4352 4354 else
4353 4355 nb_xmm_regs = 8;
4354 4356 addr = ptr + 0xa0;
4355   - for(i = 0; i < nb_xmm_regs; i++) {
4356   - stq(addr, env->xmm_regs[i].XMM_Q(0));
4357   - stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
4358   - addr += 16;
  4357 + /* Fast FXSAVE leaves out the XMM registers */
  4358 + if (!(env->efer & MSR_EFER_FFXSR)
  4359 + || (env->hflags & HF_CPL_MASK)
  4360 + || !(env->hflags & HF_LMA_MASK)) {
  4361 + for(i = 0; i < nb_xmm_regs; i++) {
  4362 + stq(addr, env->xmm_regs[i].XMM_Q(0));
  4363 + stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
  4364 + addr += 16;
  4365 + }
4359 4366 }
4360 4367 }
4361 4368 }
... ... @@ -4392,10 +4399,15 @@ void helper_fxrstor(target_ulong ptr, int data64)
4392 4399 else
4393 4400 nb_xmm_regs = 8;
4394 4401 addr = ptr + 0xa0;
4395   - for(i = 0; i < nb_xmm_regs; i++) {
4396   - env->xmm_regs[i].XMM_Q(0) = ldq(addr);
4397   - env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
4398   - addr += 16;
  4402 + /* Fast FXRESTORE leaves out the XMM registers */
  4403 + if (!(env->efer & MSR_EFER_FFXSR)
  4404 + || (env->hflags & HF_CPL_MASK)
  4405 + || !(env->hflags & HF_LMA_MASK)) {
  4406 + for(i = 0; i < nb_xmm_regs; i++) {
  4407 + env->xmm_regs[i].XMM_Q(0) = ldq(addr);
  4408 + env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
  4409 + addr += 16;
  4410 + }
4399 4411 }
4400 4412 }
4401 4413 }
... ...