1350bf64aSZixuan Wang /* 2350bf64aSZixuan Wang * AMD SEV support in kvm-unit-tests 3350bf64aSZixuan Wang * 4350bf64aSZixuan Wang * Copyright (c) 2021, Google Inc 5350bf64aSZixuan Wang * 6350bf64aSZixuan Wang * Authors: 7350bf64aSZixuan Wang * Zixuan Wang <zixuanwang@google.com> 8350bf64aSZixuan Wang * 9350bf64aSZixuan Wang * SPDX-License-Identifier: LGPL-2.0-or-later 10350bf64aSZixuan Wang */ 11350bf64aSZixuan Wang 12350bf64aSZixuan Wang #include "amd_sev.h" 13350bf64aSZixuan Wang #include "x86/processor.h" 14350bf64aSZixuan Wang 15350bf64aSZixuan Wang static unsigned short amd_sev_c_bit_pos; 16350bf64aSZixuan Wang 17350bf64aSZixuan Wang bool amd_sev_enabled(void) 18350bf64aSZixuan Wang { 19350bf64aSZixuan Wang struct cpuid cpuid_out; 20350bf64aSZixuan Wang static bool sev_enabled; 21350bf64aSZixuan Wang static bool initialized = false; 22350bf64aSZixuan Wang 23350bf64aSZixuan Wang /* Check CPUID and MSR for SEV status and store it for future function calls. */ 24350bf64aSZixuan Wang if (!initialized) { 25350bf64aSZixuan Wang sev_enabled = false; 26350bf64aSZixuan Wang initialized = true; 27350bf64aSZixuan Wang 28350bf64aSZixuan Wang /* Test if we can query SEV features */ 29350bf64aSZixuan Wang cpuid_out = cpuid(CPUID_FN_LARGEST_EXT_FUNC_NUM); 30350bf64aSZixuan Wang if (cpuid_out.a < CPUID_FN_ENCRYPT_MEM_CAPAB) { 31350bf64aSZixuan Wang return sev_enabled; 32350bf64aSZixuan Wang } 33350bf64aSZixuan Wang 34350bf64aSZixuan Wang /* Test if SEV is supported */ 35350bf64aSZixuan Wang cpuid_out = cpuid(CPUID_FN_ENCRYPT_MEM_CAPAB); 36350bf64aSZixuan Wang if (!(cpuid_out.a & SEV_SUPPORT_MASK)) { 37350bf64aSZixuan Wang return sev_enabled; 38350bf64aSZixuan Wang } 39350bf64aSZixuan Wang 40350bf64aSZixuan Wang /* Test if SEV is enabled */ 41350bf64aSZixuan Wang if (rdmsr(MSR_SEV_STATUS) & SEV_ENABLED_MASK) { 42350bf64aSZixuan Wang sev_enabled = true; 43350bf64aSZixuan Wang } 44350bf64aSZixuan Wang } 45350bf64aSZixuan Wang 46350bf64aSZixuan Wang return sev_enabled; 47350bf64aSZixuan Wang } 48350bf64aSZixuan Wang 49350bf64aSZixuan Wang efi_status_t setup_amd_sev(void) 50350bf64aSZixuan Wang { 51350bf64aSZixuan Wang struct cpuid cpuid_out; 52350bf64aSZixuan Wang 53350bf64aSZixuan Wang if (!amd_sev_enabled()) { 54350bf64aSZixuan Wang return EFI_UNSUPPORTED; 55350bf64aSZixuan Wang } 56350bf64aSZixuan Wang 57350bf64aSZixuan Wang /* 58350bf64aSZixuan Wang * Extract C-Bit position from ebx[5:0] 59350bf64aSZixuan Wang * AMD64 Architecture Programmer's Manual Volume 3 60350bf64aSZixuan Wang * - Section " Function 8000_001Fh - Encrypted Memory Capabilities" 61350bf64aSZixuan Wang */ 62350bf64aSZixuan Wang cpuid_out = cpuid(CPUID_FN_ENCRYPT_MEM_CAPAB); 63350bf64aSZixuan Wang amd_sev_c_bit_pos = (unsigned short)(cpuid_out.b & 0x3f); 64350bf64aSZixuan Wang 65350bf64aSZixuan Wang return EFI_SUCCESS; 66350bf64aSZixuan Wang } 67350bf64aSZixuan Wang 68bf812590SZixuan Wang bool amd_sev_es_enabled(void) 69bf812590SZixuan Wang { 70bf812590SZixuan Wang static bool sev_es_enabled; 71bf812590SZixuan Wang static bool initialized = false; 72bf812590SZixuan Wang 73bf812590SZixuan Wang if (!initialized) { 74bf812590SZixuan Wang sev_es_enabled = false; 75bf812590SZixuan Wang initialized = true; 76bf812590SZixuan Wang 77bf812590SZixuan Wang if (!amd_sev_enabled()) { 78bf812590SZixuan Wang return sev_es_enabled; 79bf812590SZixuan Wang } 80bf812590SZixuan Wang 81bf812590SZixuan Wang /* Test if SEV-ES is enabled */ 82bf812590SZixuan Wang if (rdmsr(MSR_SEV_STATUS) & SEV_ES_ENABLED_MASK) { 83bf812590SZixuan Wang sev_es_enabled = true; 84bf812590SZixuan Wang } 85bf812590SZixuan Wang } 86bf812590SZixuan Wang 87bf812590SZixuan Wang return sev_es_enabled; 88bf812590SZixuan Wang } 89bf812590SZixuan Wang 90*706ede18SZixuan Wang efi_status_t setup_amd_sev_es(void) 91*706ede18SZixuan Wang { 92*706ede18SZixuan Wang struct descriptor_table_ptr idtr; 93*706ede18SZixuan Wang idt_entry_t *idt; 94*706ede18SZixuan Wang idt_entry_t vc_handler_idt; 95*706ede18SZixuan Wang 96*706ede18SZixuan Wang if (!amd_sev_es_enabled()) { 97*706ede18SZixuan Wang return EFI_UNSUPPORTED; 98*706ede18SZixuan Wang } 99*706ede18SZixuan Wang 100*706ede18SZixuan Wang /* 101*706ede18SZixuan Wang * Copy UEFI's #VC IDT entry, so KVM-Unit-Tests can reuse it and does 102*706ede18SZixuan Wang * not have to re-implement a #VC handler. Also update the #VC IDT code 103*706ede18SZixuan Wang * segment to use KVM-Unit-Tests segments, KERNEL_CS, so that we do not 104*706ede18SZixuan Wang * have to copy the UEFI GDT entries into KVM-Unit-Tests GDT. 105*706ede18SZixuan Wang * 106*706ede18SZixuan Wang * TODO: Reusing UEFI #VC handler is a temporary workaround to simplify 107*706ede18SZixuan Wang * the boot up process, the long-term solution is to implement a #VC 108*706ede18SZixuan Wang * handler in kvm-unit-tests and load it, so that kvm-unit-tests does 109*706ede18SZixuan Wang * not depend on specific UEFI #VC handler implementation. 110*706ede18SZixuan Wang */ 111*706ede18SZixuan Wang sidt(&idtr); 112*706ede18SZixuan Wang idt = (idt_entry_t *)idtr.base; 113*706ede18SZixuan Wang vc_handler_idt = idt[SEV_ES_VC_HANDLER_VECTOR]; 114*706ede18SZixuan Wang vc_handler_idt.selector = KERNEL_CS; 115*706ede18SZixuan Wang boot_idt[SEV_ES_VC_HANDLER_VECTOR] = vc_handler_idt; 116*706ede18SZixuan Wang 117*706ede18SZixuan Wang return EFI_SUCCESS; 118*706ede18SZixuan Wang } 119*706ede18SZixuan Wang 120350bf64aSZixuan Wang unsigned long long get_amd_sev_c_bit_mask(void) 121350bf64aSZixuan Wang { 122350bf64aSZixuan Wang if (amd_sev_enabled()) { 123350bf64aSZixuan Wang return 1ull << amd_sev_c_bit_pos; 124350bf64aSZixuan Wang } else { 125350bf64aSZixuan Wang return 0; 126350bf64aSZixuan Wang } 127350bf64aSZixuan Wang } 12830203ea5SZixuan Wang 12930203ea5SZixuan Wang unsigned long long get_amd_sev_addr_upperbound(void) 13030203ea5SZixuan Wang { 13130203ea5SZixuan Wang if (amd_sev_enabled()) { 13230203ea5SZixuan Wang return amd_sev_c_bit_pos - 1; 13330203ea5SZixuan Wang } else { 13430203ea5SZixuan Wang /* Default memory upper bound */ 13530203ea5SZixuan Wang return PT_ADDR_UPPER_BOUND_DEFAULT; 13630203ea5SZixuan Wang } 13730203ea5SZixuan Wang } 138