Commit 916391a2 authored by Tom Lendacky's avatar Tom Lendacky Committed by Paolo Bonzini

KVM: SVM: Add support for SEV-ES capability in KVM

Add support to KVM for determining if a system is capable of supporting
SEV-ES as well as determining if a guest is an SEV-ES guest.
Signed-off-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Message-Id: <e66792323982c822350e40c7a1cf67ea2978a70b.1607620209.git.thomas.lendacky@amd.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 9d4747d0
...@@ -100,7 +100,8 @@ config KVM_AMD_SEV ...@@ -100,7 +100,8 @@ config KVM_AMD_SEV
depends on KVM_AMD && X86_64 depends on KVM_AMD && X86_64
depends on CRYPTO_DEV_SP_PSP && !(KVM_AMD=y && CRYPTO_DEV_CCP_DD=m) depends on CRYPTO_DEV_SP_PSP && !(KVM_AMD=y && CRYPTO_DEV_CCP_DD=m)
help help
Provides support for launching Encrypted VMs on AMD processors. Provides support for launching Encrypted VMs (SEV) and Encrypted VMs
with Encrypted State (SEV-ES) on AMD processors.
config KVM_MMU_AUDIT config KVM_MMU_AUDIT
bool "Audit KVM MMU" bool "Audit KVM MMU"
......
...@@ -932,7 +932,7 @@ int svm_mem_enc_op(struct kvm *kvm, void __user *argp) ...@@ -932,7 +932,7 @@ int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
struct kvm_sev_cmd sev_cmd; struct kvm_sev_cmd sev_cmd;
int r; int r;
if (!svm_sev_enabled()) if (!svm_sev_enabled() || !sev)
return -ENOTTY; return -ENOTTY;
if (!argp) if (!argp)
...@@ -1125,29 +1125,58 @@ void sev_vm_destroy(struct kvm *kvm) ...@@ -1125,29 +1125,58 @@ void sev_vm_destroy(struct kvm *kvm)
sev_asid_free(sev->asid); sev_asid_free(sev->asid);
} }
int __init sev_hardware_setup(void) void __init sev_hardware_setup(void)
{ {
unsigned int eax, ebx, ecx, edx;
bool sev_es_supported = false;
bool sev_supported = false;
/* Does the CPU support SEV? */
if (!boot_cpu_has(X86_FEATURE_SEV))
goto out;
/* Retrieve SEV CPUID information */
cpuid(0x8000001f, &eax, &ebx, &ecx, &edx);
/* Maximum number of encrypted guests supported simultaneously */ /* Maximum number of encrypted guests supported simultaneously */
max_sev_asid = cpuid_ecx(0x8000001F); max_sev_asid = ecx;
if (!svm_sev_enabled()) if (!svm_sev_enabled())
return 1; goto out;
/* Minimum ASID value that should be used for SEV guest */ /* Minimum ASID value that should be used for SEV guest */
min_sev_asid = cpuid_edx(0x8000001F); min_sev_asid = edx;
/* Initialize SEV ASID bitmaps */ /* Initialize SEV ASID bitmaps */
sev_asid_bitmap = bitmap_zalloc(max_sev_asid, GFP_KERNEL); sev_asid_bitmap = bitmap_zalloc(max_sev_asid, GFP_KERNEL);
if (!sev_asid_bitmap) if (!sev_asid_bitmap)
return 1; goto out;
sev_reclaim_asid_bitmap = bitmap_zalloc(max_sev_asid, GFP_KERNEL); sev_reclaim_asid_bitmap = bitmap_zalloc(max_sev_asid, GFP_KERNEL);
if (!sev_reclaim_asid_bitmap) if (!sev_reclaim_asid_bitmap)
return 1; goto out;
pr_info("SEV supported\n"); pr_info("SEV supported: %u ASIDs\n", max_sev_asid - min_sev_asid + 1);
sev_supported = true;
return 0; /* SEV-ES support requested? */
if (!sev_es)
goto out;
/* Does the CPU support SEV-ES? */
if (!boot_cpu_has(X86_FEATURE_SEV_ES))
goto out;
/* Has the system been allocated ASIDs for SEV-ES? */
if (min_sev_asid == 1)
goto out;
pr_info("SEV-ES supported: %u ASIDs\n", min_sev_asid - 1);
sev_es_supported = true;
out:
sev = sev_supported;
sev_es = sev_es_supported;
} }
void sev_hardware_teardown(void) void sev_hardware_teardown(void)
......
...@@ -186,9 +186,13 @@ static int vgif = true; ...@@ -186,9 +186,13 @@ static int vgif = true;
module_param(vgif, int, 0444); module_param(vgif, int, 0444);
/* enable/disable SEV support */ /* enable/disable SEV support */
static int sev = IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT); int sev = IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT);
module_param(sev, int, 0444); module_param(sev, int, 0444);
/* enable/disable SEV-ES support */
int sev_es = IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT);
module_param(sev_es, int, 0444);
static bool __read_mostly dump_invalid_vmcb = 0; static bool __read_mostly dump_invalid_vmcb = 0;
module_param(dump_invalid_vmcb, bool, 0644); module_param(dump_invalid_vmcb, bool, 0644);
...@@ -958,15 +962,11 @@ static __init int svm_hardware_setup(void) ...@@ -958,15 +962,11 @@ static __init int svm_hardware_setup(void)
kvm_enable_efer_bits(EFER_SVME | EFER_LMSLE); kvm_enable_efer_bits(EFER_SVME | EFER_LMSLE);
} }
if (sev) { if (IS_ENABLED(CONFIG_KVM_AMD_SEV) && sev) {
if (boot_cpu_has(X86_FEATURE_SEV) && sev_hardware_setup();
IS_ENABLED(CONFIG_KVM_AMD_SEV)) { } else {
r = sev_hardware_setup(); sev = false;
if (r) sev_es = false;
sev = false;
} else {
sev = false;
}
} }
svm_adjust_mmio_mask(); svm_adjust_mmio_mask();
......
...@@ -61,6 +61,7 @@ enum { ...@@ -61,6 +61,7 @@ enum {
struct kvm_sev_info { struct kvm_sev_info {
bool active; /* SEV enabled guest */ bool active; /* SEV enabled guest */
bool es_active; /* SEV-ES enabled guest */
unsigned int asid; /* ASID used for this guest */ unsigned int asid; /* ASID used for this guest */
unsigned int handle; /* SEV firmware handle */ unsigned int handle; /* SEV firmware handle */
int fd; /* SEV device fd */ int fd; /* SEV device fd */
...@@ -194,6 +195,28 @@ static inline struct kvm_svm *to_kvm_svm(struct kvm *kvm) ...@@ -194,6 +195,28 @@ static inline struct kvm_svm *to_kvm_svm(struct kvm *kvm)
return container_of(kvm, struct kvm_svm, kvm); return container_of(kvm, struct kvm_svm, kvm);
} }
static inline bool sev_guest(struct kvm *kvm)
{
#ifdef CONFIG_KVM_AMD_SEV
struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
return sev->active;
#else
return false;
#endif
}
static inline bool sev_es_guest(struct kvm *kvm)
{
#ifdef CONFIG_KVM_AMD_SEV
struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
return sev_guest(kvm) && sev->es_active;
#else
return false;
#endif
}
static inline void vmcb_mark_all_dirty(struct vmcb *vmcb) static inline void vmcb_mark_all_dirty(struct vmcb *vmcb)
{ {
vmcb->control.clean = 0; vmcb->control.clean = 0;
...@@ -352,6 +375,9 @@ static inline bool gif_set(struct vcpu_svm *svm) ...@@ -352,6 +375,9 @@ static inline bool gif_set(struct vcpu_svm *svm)
#define MSR_CR3_LONG_MBZ_MASK 0xfff0000000000000U #define MSR_CR3_LONG_MBZ_MASK 0xfff0000000000000U
#define MSR_INVALID 0xffffffffU #define MSR_INVALID 0xffffffffU
extern int sev;
extern int sev_es;
u32 svm_msrpm_offset(u32 msr); u32 svm_msrpm_offset(u32 msr);
u32 *svm_vcpu_alloc_msrpm(void); u32 *svm_vcpu_alloc_msrpm(void);
void svm_vcpu_init_msrpm(struct kvm_vcpu *vcpu, u32 *msrpm); void svm_vcpu_init_msrpm(struct kvm_vcpu *vcpu, u32 *msrpm);
...@@ -473,17 +499,6 @@ void svm_vcpu_unblocking(struct kvm_vcpu *vcpu); ...@@ -473,17 +499,6 @@ void svm_vcpu_unblocking(struct kvm_vcpu *vcpu);
extern unsigned int max_sev_asid; extern unsigned int max_sev_asid;
static inline bool sev_guest(struct kvm *kvm)
{
#ifdef CONFIG_KVM_AMD_SEV
struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
return sev->active;
#else
return false;
#endif
}
static inline bool svm_sev_enabled(void) static inline bool svm_sev_enabled(void)
{ {
return IS_ENABLED(CONFIG_KVM_AMD_SEV) ? max_sev_asid : 0; return IS_ENABLED(CONFIG_KVM_AMD_SEV) ? max_sev_asid : 0;
...@@ -496,7 +511,7 @@ int svm_register_enc_region(struct kvm *kvm, ...@@ -496,7 +511,7 @@ int svm_register_enc_region(struct kvm *kvm,
int svm_unregister_enc_region(struct kvm *kvm, int svm_unregister_enc_region(struct kvm *kvm,
struct kvm_enc_region *range); struct kvm_enc_region *range);
void pre_sev_run(struct vcpu_svm *svm, int cpu); void pre_sev_run(struct vcpu_svm *svm, int cpu);
int __init sev_hardware_setup(void); void __init sev_hardware_setup(void);
void sev_hardware_teardown(void); void sev_hardware_teardown(void);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment