summaryrefslogtreecommitdiff
path: root/target-i386
diff options
context:
space:
mode:
authoraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2009-02-02 17:10:52 +0000
committeraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2009-02-02 17:10:52 +0000
commiteef26553c782c26646c8b5b63afa6182187104eb (patch)
tree178cd8b0639c9d988ff115a078f559eac0c16a07 /target-i386
parent059cef4092cc1f558f8f74cf2f762cef41237434 (diff)
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
Diffstat (limited to 'target-i386')
-rw-r--r--target-i386/op_helper.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index c2eda864a6..87c7a579e9 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -3030,6 +3030,8 @@ void helper_wrmsr(void)
update_mask |= MSR_EFER_NXE;
if (env->cpuid_ext3_features & CPUID_EXT3_SVM)
update_mask |= MSR_EFER_SVME;
+ if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
+ update_mask |= MSR_EFER_FFXSR;
cpu_load_efer(env, (env->efer & ~update_mask) |
(val & update_mask));
}
@@ -4352,10 +4354,15 @@ void helper_fxsave(target_ulong ptr, int data64)
else
nb_xmm_regs = 8;
addr = ptr + 0xa0;
- for(i = 0; i < nb_xmm_regs; i++) {
- stq(addr, env->xmm_regs[i].XMM_Q(0));
- stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
- addr += 16;
+ /* Fast FXSAVE leaves out the XMM registers */
+ if (!(env->efer & MSR_EFER_FFXSR)
+ || (env->hflags & HF_CPL_MASK)
+ || !(env->hflags & HF_LMA_MASK)) {
+ for(i = 0; i < nb_xmm_regs; i++) {
+ stq(addr, env->xmm_regs[i].XMM_Q(0));
+ stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
+ addr += 16;
+ }
}
}
}
@@ -4392,10 +4399,15 @@ void helper_fxrstor(target_ulong ptr, int data64)
else
nb_xmm_regs = 8;
addr = ptr + 0xa0;
- for(i = 0; i < nb_xmm_regs; i++) {
- env->xmm_regs[i].XMM_Q(0) = ldq(addr);
- env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
- addr += 16;
+ /* Fast FXRESTORE leaves out the XMM registers */
+ if (!(env->efer & MSR_EFER_FFXSR)
+ || (env->hflags & HF_CPL_MASK)
+ || !(env->hflags & HF_LMA_MASK)) {
+ for(i = 0; i < nb_xmm_regs; i++) {
+ env->xmm_regs[i].XMM_Q(0) = ldq(addr);
+ env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
+ addr += 16;
+ }
}
}
}