On 22/03/2016 09:51, Huaitong Han wrote: > X86_FEATURE_PKU is referred to as "PKU" in the hardware documentation: > CPUID.7.0.ECX[3]:PKU. X86_FEATURE_OSPKE is software support for pkeys, > enumerated with CPUID.7.0.ECX[4]:OSPKE, and it reflects the setting of > CR4.PKE(bit 22). > > This patch disables CPUID:PKU without ept, because pkeys is not yet > implemented for shadow paging. > > Signed-off-by: Huaitong Han <huaitong.han@xxxxxxxxx> > Reviewed-by: Xiao Guangrong <guangrong.xiao@xxxxxxxxxxxxxxx> > --- > arch/x86/include/asm/kvm_host.h | 3 ++- > arch/x86/kvm/cpuid.c | 25 +++++++++++++++++++++++-- > arch/x86/kvm/cpuid.h | 8 ++++++++ > arch/x86/kvm/x86.c | 9 ++++++--- > 4 files changed, 39 insertions(+), 6 deletions(-) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index 0d75ecd..f62a9f37 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -84,7 +84,8 @@ > | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \ > | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR | X86_CR4_PCIDE \ > | X86_CR4_OSXSAVE | X86_CR4_SMEP | X86_CR4_FSGSBASE \ > - | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE | X86_CR4_SMAP)) > + | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE | X86_CR4_SMAP \ > + | X86_CR4_PKE)) > > #define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR) > > diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c > index 00a69ec..d81709a 100644 > --- a/arch/x86/kvm/cpuid.c > +++ b/arch/x86/kvm/cpuid.c > @@ -88,6 +88,17 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu) > apic->lapic_timer.timer_mode_mask = 1 << 17; > } > > + best = kvm_find_cpuid_entry(vcpu, 7, 0); > + if (!best) > + return 0; Returning best here breaks CPU models that don't have leaf 7. Fix applied as follows: diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index b3d6d6535a2c..8efb839948e5 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -89,14 +89,13 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu) } best = kvm_find_cpuid_entry(vcpu, 7, 0); - if (!best) - return 0; - - /* Update OSPKE bit */ - if (boot_cpu_has(X86_FEATURE_PKU) && best->function == 0x7) { - best->ecx &= ~F(OSPKE); - if (kvm_read_cr4_bits(vcpu, X86_CR4_PKE)) - best->ecx |= F(OSPKE); + if (best) { + /* Update OSPKE bit */ + if (boot_cpu_has(X86_FEATURE_PKU) && best->function == 0x7) { + best->ecx &= ~F(OSPKE); + if (kvm_read_cr4_bits(vcpu, X86_CR4_PKE)) + best->ecx |= F(OSPKE); + } } best = kvm_find_cpuid_entry(vcpu, 0xD, 0); Paolo > + /* Update OSPKE bit */ > + if (boot_cpu_has(X86_FEATURE_PKU) && best->function == 0x7) { > + best->ecx &= ~F(OSPKE); > + if (kvm_read_cr4_bits(vcpu, X86_CR4_PKE)) > + best->ecx |= F(OSPKE); > + } > + > best = kvm_find_cpuid_entry(vcpu, 0xD, 0); > if (!best) { > vcpu->arch.guest_supported_xcr0 = 0; > @@ -360,6 +371,9 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, > const u32 kvm_cpuid_D_1_eax_x86_features = > F(XSAVEOPT) | F(XSAVEC) | F(XGETBV1) | f_xsaves; > > + /* cpuid 7.0.ecx*/ > + const u32 kvm_cpuid_7_0_ecx_x86_features = F(PKU) | 0 /*OSPKE*/; > + > /* all calls to cpuid_count() should be made on the same cpu */ > get_cpu(); > > @@ -437,10 +451,17 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, > cpuid_mask(&entry->ebx, CPUID_7_0_EBX); > // TSC_ADJUST is emulated > entry->ebx |= F(TSC_ADJUST); > - } else > + > + entry->ecx &= kvm_cpuid_7_0_ecx_x86_features; > + cpuid_mask(&entry->ecx, CPUID_7_ECX); > + /* PKU is not yet implemented for shadow paging. */ > + if (!tdp_enabled) > + entry->ecx &= ~F(PKU); > + } else{ > entry->ebx = 0; > + entry->ecx = 0; > + } > entry->eax = 0; > - entry->ecx = 0; > entry->edx = 0; > break; > } > diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h > index 66a6581..e17a74b 100644 > --- a/arch/x86/kvm/cpuid.h > +++ b/arch/x86/kvm/cpuid.h > @@ -80,6 +80,14 @@ static inline bool guest_cpuid_has_fsgsbase(struct kvm_vcpu *vcpu) > return best && (best->ebx & bit(X86_FEATURE_FSGSBASE)); > } > > +static inline bool guest_cpuid_has_pku(struct kvm_vcpu *vcpu) > +{ > + struct kvm_cpuid_entry2 *best; > + > + best = kvm_find_cpuid_entry(vcpu, 7, 0); > + return best && (best->ecx & bit(X86_FEATURE_PKU)); > +} > + > static inline bool guest_cpuid_has_longmode(struct kvm_vcpu *vcpu) > { > struct kvm_cpuid_entry2 *best; > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index d0a5918..98ae1fb 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -723,7 +723,7 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) > { > unsigned long old_cr4 = kvm_read_cr4(vcpu); > unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE | > - X86_CR4_SMEP | X86_CR4_SMAP; > + X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_PKE; > > if (cr4 & CR4_RESERVED_BITS) > return 1; > @@ -740,6 +740,9 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) > if (!guest_cpuid_has_fsgsbase(vcpu) && (cr4 & X86_CR4_FSGSBASE)) > return 1; > > + if (!guest_cpuid_has_pku(vcpu) && (cr4 & X86_CR4_PKE)) > + return 1; > + > if (is_long_mode(vcpu)) { > if (!(cr4 & X86_CR4_PAE)) > return 1; > @@ -765,7 +768,7 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) > (!(cr4 & X86_CR4_PCIDE) && (old_cr4 & X86_CR4_PCIDE))) > kvm_mmu_reset_context(vcpu); > > - if ((cr4 ^ old_cr4) & X86_CR4_OSXSAVE) > + if ((cr4 ^ old_cr4) & (X86_CR4_OSXSAVE | X86_CR4_PKE)) > kvm_update_cpuid(vcpu); > > return 0; > @@ -7128,7 +7131,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, > > mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4; > kvm_x86_ops->set_cr4(vcpu, sregs->cr4); > - if (sregs->cr4 & X86_CR4_OSXSAVE) > + if (sregs->cr4 & (X86_CR4_OSXSAVE | X86_CR4_PKE)) > kvm_update_cpuid(vcpu); > > idx = srcu_read_lock(&vcpu->kvm->srcu); > -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html