Message ID | 1467659769-15900-3-git-send-email-dgilbert@redhat.com |
---|---|
State | New |
Headers | show |
On Mon, Jul 04, 2016 at 08:16:05PM +0100, Dr. David Alan Gilbert (git) wrote: > From: "Dr. David Alan Gilbert" <dgilbert@redhat.com> > > 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> Why don't we mask with host bits? This is the kvm limitation, isn't it? This will make it possible to CC stable as well. > --- > target-i386/kvm.c | 11 +++++++++-- > 1 file changed, 9 insertions(+), 2 deletions(-) > > diff --git a/target-i386/kvm.c b/target-i386/kvm.c > index f3698f1..6429205 100644 > --- a/target-i386/kvm.c > +++ b/target-i386/kvm.c > @@ -1677,6 +1677,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]); > @@ -1690,10 +1692,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); > } > } > > -- > 2.7.4
On Mon, Jul 04, 2016 at 08:16:05PM +0100, Dr. David Alan Gilbert (git) wrote: > From: "Dr. David Alan Gilbert" <dgilbert@redhat.com> > > 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> > --- > target-i386/kvm.c | 11 +++++++++-- > 1 file changed, 9 insertions(+), 2 deletions(-) > > diff --git a/target-i386/kvm.c b/target-i386/kvm.c > index f3698f1..6429205 100644 > --- a/target-i386/kvm.c > +++ b/target-i386/kvm.c > @@ -1677,6 +1677,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]); > @@ -1690,10 +1692,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; > + I was arguing that we should print warnings when we really had to change the MTRR values on migration. But if we are already inside kvm_put_msrs() with a different phys_bits value, the best we can do is to trim the bits so they still make sense. If we want to print a warning, this can be done somewhere else. Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> > 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); > } > } > > -- > 2.7.4 >
On Mon, Jul 04, 2016 at 11:02:00PM +0300, Michael S. Tsirkin wrote: > On Mon, Jul 04, 2016 at 08:16:05PM +0100, Dr. David Alan Gilbert (git) wrote: > > From: "Dr. David Alan Gilbert" <dgilbert@redhat.com> > > > > 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> > > Why don't we mask with host bits? This is the kvm limitation, > isn't it? This will make it possible to CC stable as well. KVM validates the value written to the MSR using the guest CPUID data, not the host bits. If we trim using the host bits, we would still crash if cpu->phys_bits < host_phys_bits.
On Mon, Jul 04, 2016 at 05:05:36PM -0300, Eduardo Habkost wrote: > On Mon, Jul 04, 2016 at 11:02:00PM +0300, Michael S. Tsirkin wrote: > > On Mon, Jul 04, 2016 at 08:16:05PM +0100, Dr. David Alan Gilbert (git) wrote: > > > From: "Dr. David Alan Gilbert" <dgilbert@redhat.com> > > > > > > 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> > > > > Why don't we mask with host bits? This is the kvm limitation, > > isn't it? This will make it possible to CC stable as well. > > KVM validates the value written to the MSR using the guest CPUID > data, not the host bits. If we trim using the host bits, we would > still crash if cpu->phys_bits < host_phys_bits. I didn't realise. Will have to re-do the review. > -- > Eduardo
diff --git a/target-i386/kvm.c b/target-i386/kvm.c index f3698f1..6429205 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1677,6 +1677,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]); @@ -1690,10 +1692,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); } }