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 68*bf812590SZixuan Wang bool amd_sev_es_enabled(void) 69*bf812590SZixuan Wang { 70*bf812590SZixuan Wang static bool sev_es_enabled; 71*bf812590SZixuan Wang static bool initialized = false; 72*bf812590SZixuan Wang 73*bf812590SZixuan Wang if (!initialized) { 74*bf812590SZixuan Wang sev_es_enabled = false; 75*bf812590SZixuan Wang initialized = true; 76*bf812590SZixuan Wang 77*bf812590SZixuan Wang if (!amd_sev_enabled()) { 78*bf812590SZixuan Wang return sev_es_enabled; 79*bf812590SZixuan Wang } 80*bf812590SZixuan Wang 81*bf812590SZixuan Wang /* Test if SEV-ES is enabled */ 82*bf812590SZixuan Wang if (rdmsr(MSR_SEV_STATUS) & SEV_ES_ENABLED_MASK) { 83*bf812590SZixuan Wang sev_es_enabled = true; 84*bf812590SZixuan Wang } 85*bf812590SZixuan Wang } 86*bf812590SZixuan Wang 87*bf812590SZixuan Wang return sev_es_enabled; 88*bf812590SZixuan Wang } 89*bf812590SZixuan Wang 90350bf64aSZixuan Wang unsigned long long get_amd_sev_c_bit_mask(void) 91350bf64aSZixuan Wang { 92350bf64aSZixuan Wang if (amd_sev_enabled()) { 93350bf64aSZixuan Wang return 1ull << amd_sev_c_bit_pos; 94350bf64aSZixuan Wang } else { 95350bf64aSZixuan Wang return 0; 96350bf64aSZixuan Wang } 97350bf64aSZixuan Wang } 9830203ea5SZixuan Wang 9930203ea5SZixuan Wang unsigned long long get_amd_sev_addr_upperbound(void) 10030203ea5SZixuan Wang { 10130203ea5SZixuan Wang if (amd_sev_enabled()) { 10230203ea5SZixuan Wang return amd_sev_c_bit_pos - 1; 10330203ea5SZixuan Wang } else { 10430203ea5SZixuan Wang /* Default memory upper bound */ 10530203ea5SZixuan Wang return PT_ADDR_UPPER_BOUND_DEFAULT; 10630203ea5SZixuan Wang } 10730203ea5SZixuan Wang } 108