| From c8cf6db9a1336688ca606ff60d8560812bc559c7 Mon Sep 17 00:00:00 2001 |
| From: John Allen <john.allen@amd.com> |
| Date: Thu, 19 Dec 2019 14:17:59 -0600 |
| Subject: [PATCH] kvm/svm: PKU not currently supported |
| |
| commit a47970ed74a535b1accb4bc73643fd5a93993c3e upstream. |
| |
| Current SVM implementation does not have support for handling PKU. Guests |
| running on a host with future AMD cpus that support the feature will read |
| garbage from the PKRU register and will hit segmentation faults on boot as |
| memory is getting marked as protected that should not be. Ensure that cpuid |
| from SVM does not advertise the feature. |
| |
| Signed-off-by: John Allen <john.allen@amd.com> |
| Cc: stable@vger.kernel.org |
| Fixes: 0556cbdc2fbc ("x86/pkeys: Don't check if PKRU is zero before writing it") |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h |
| index a5a4e460bad5..e1746d22a202 100644 |
| --- a/arch/x86/include/asm/kvm_host.h |
| +++ b/arch/x86/include/asm/kvm_host.h |
| @@ -1125,6 +1125,7 @@ struct kvm_x86_ops { |
| bool (*xsaves_supported)(void); |
| bool (*umip_emulated)(void); |
| bool (*pt_supported)(void); |
| + bool (*pku_supported)(void); |
| |
| int (*check_nested_events)(struct kvm_vcpu *vcpu, bool external_intr); |
| void (*request_immediate_exit)(struct kvm_vcpu *vcpu); |
| diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c |
| index 4d2c84520bd2..e8e7d053c7b4 100644 |
| --- a/arch/x86/kvm/cpuid.c |
| +++ b/arch/x86/kvm/cpuid.c |
| @@ -333,6 +333,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, |
| unsigned f_umip = kvm_x86_ops->umip_emulated() ? F(UMIP) : 0; |
| unsigned f_intel_pt = kvm_x86_ops->pt_supported() ? F(INTEL_PT) : 0; |
| unsigned f_la57 = 0; |
| + unsigned f_pku = kvm_x86_ops->pku_supported() ? F(PKU) : 0; |
| |
| /* cpuid 1.edx */ |
| const u32 kvm_cpuid_1_edx_x86_features = |
| @@ -399,7 +400,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, |
| |
| /* cpuid 7.0.ecx*/ |
| const u32 kvm_cpuid_7_0_ecx_x86_features = |
| - F(AVX512VBMI) | F(LA57) | F(PKU) | 0 /*OSPKE*/ | |
| + F(AVX512VBMI) | F(LA57) | 0 /*PKU*/ | 0 /*OSPKE*/ | |
| F(AVX512_VPOPCNTDQ) | F(UMIP) | F(AVX512_VBMI2) | F(GFNI) | |
| F(VAES) | F(VPCLMULQDQ) | F(AVX512_VNNI) | F(AVX512_BITALG) | |
| F(CLDEMOTE) | F(MOVDIRI) | F(MOVDIR64B); |
| @@ -494,6 +495,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, |
| /* Set LA57 based on hardware capability. */ |
| entry->ecx |= f_la57; |
| entry->ecx |= f_umip; |
| + entry->ecx |= f_pku; |
| /* PKU is not yet implemented for shadow paging. */ |
| if (!tdp_enabled || !boot_cpu_has(X86_FEATURE_OSPKE)) |
| entry->ecx &= ~F(PKU); |
| diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c |
| index 450a72bbf231..0c6d1c297ac7 100644 |
| --- a/arch/x86/kvm/svm.c |
| +++ b/arch/x86/kvm/svm.c |
| @@ -5994,6 +5994,11 @@ static bool svm_has_wbinvd_exit(void) |
| return true; |
| } |
| |
| +static bool svm_pku_supported(void) |
| +{ |
| + return false; |
| +} |
| + |
| #define PRE_EX(exit) { .exit_code = (exit), \ |
| .stage = X86_ICPT_PRE_EXCEPT, } |
| #define POST_EX(exit) { .exit_code = (exit), \ |
| @@ -7283,6 +7288,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = { |
| .xsaves_supported = svm_xsaves_supported, |
| .umip_emulated = svm_umip_emulated, |
| .pt_supported = svm_pt_supported, |
| + .pku_supported = svm_pku_supported, |
| |
| .set_supported_cpuid = svm_set_supported_cpuid, |
| |
| diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilities.h |
| index d6664ee3d127..f6cd554ff2e8 100644 |
| --- a/arch/x86/kvm/vmx/capabilities.h |
| +++ b/arch/x86/kvm/vmx/capabilities.h |
| @@ -145,6 +145,11 @@ static inline bool vmx_umip_emulated(void) |
| SECONDARY_EXEC_DESC; |
| } |
| |
| +static inline bool vmx_pku_supported(void) |
| +{ |
| + return boot_cpu_has(X86_FEATURE_PKU); |
| +} |
| + |
| static inline bool cpu_has_vmx_rdtscp(void) |
| { |
| return vmcs_config.cpu_based_2nd_exec_ctrl & |
| diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c |
| index de290290affe..4b7598743ac0 100644 |
| --- a/arch/x86/kvm/vmx/vmx.c |
| +++ b/arch/x86/kvm/vmx/vmx.c |
| @@ -7705,6 +7705,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = { |
| .xsaves_supported = vmx_xsaves_supported, |
| .umip_emulated = vmx_umip_emulated, |
| .pt_supported = vmx_pt_supported, |
| + .pku_supported = vmx_pku_supported, |
| |
| .request_immediate_exit = vmx_request_immediate_exit, |
| |
| -- |
| 2.7.4 |
| |