target-i386: Mask mtrr mask based on CPU physical address limits

The CPU GPs if we try and set a bit in a variable MTRR mask above
the limit of physical address bits on the host.  We hit this
when loading a migration from a host with a larger physical
address limit than our destination (e.g. a Xeon->i7 of same
generation) but previously used to get away with it
until 48e1a45 started checking that msr writes actually worked.

It seems in our case the GP probably comes from KVM emulating
that GP.

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
Dr. David Alan Gilbert 2016-07-08 16:01:37 +01:00 committed by Eduardo Habkost
parent af45907a13
commit 112dad69d7

View File

@ -1716,6 +1716,8 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
}
}
if (has_msr_mtrr) {
uint64_t phys_mask = MAKE_64BIT_MASK(0, cpu->phys_bits);
kvm_msr_entry_add(cpu, MSR_MTRRdefType, env->mtrr_deftype);
kvm_msr_entry_add(cpu, MSR_MTRRfix64K_00000, env->mtrr_fixed[0]);
kvm_msr_entry_add(cpu, MSR_MTRRfix16K_80000, env->mtrr_fixed[1]);
@ -1729,10 +1731,15 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
kvm_msr_entry_add(cpu, MSR_MTRRfix4K_F0000, env->mtrr_fixed[9]);
kvm_msr_entry_add(cpu, MSR_MTRRfix4K_F8000, env->mtrr_fixed[10]);
for (i = 0; i < MSR_MTRRcap_VCNT; i++) {
/* The CPU GPs if we write to a bit above the physical limit of
* the host CPU (and KVM emulates that)
*/
uint64_t mask = env->mtrr_var[i].mask;
mask &= phys_mask;
kvm_msr_entry_add(cpu, MSR_MTRRphysBase(i),
env->mtrr_var[i].base);
kvm_msr_entry_add(cpu, MSR_MTRRphysMask(i),
env->mtrr_var[i].mask);
kvm_msr_entry_add(cpu, MSR_MTRRphysMask(i), mask);
}
}