1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Confidential Computing Platform Capability checks 4 * 5 * Copyright (C) 2021 Advanced Micro Devices, Inc. 6 * 7 * Author: Tom Lendacky <thomas.lendacky@amd.com> 8 */ 9 10 #include <linux/export.h> 11 #include <linux/cc_platform.h> 12 13 #include <asm/coco.h> 14 #include <asm/processor.h> 15 16 static enum cc_vendor vendor __ro_after_init; 17 18 static bool intel_cc_platform_has(enum cc_attr attr) 19 { 20 return false; 21 } 22 23 /* 24 * SME and SEV are very similar but they are not the same, so there are 25 * times that the kernel will need to distinguish between SME and SEV. The 26 * cc_platform_has() function is used for this. When a distinction isn't 27 * needed, the CC_ATTR_MEM_ENCRYPT attribute can be used. 28 * 29 * The trampoline code is a good example for this requirement. Before 30 * paging is activated, SME will access all memory as decrypted, but SEV 31 * will access all memory as encrypted. So, when APs are being brought 32 * up under SME the trampoline area cannot be encrypted, whereas under SEV 33 * the trampoline area must be encrypted. 34 */ 35 static bool amd_cc_platform_has(enum cc_attr attr) 36 { 37 #ifdef CONFIG_AMD_MEM_ENCRYPT 38 switch (attr) { 39 case CC_ATTR_MEM_ENCRYPT: 40 return sme_me_mask; 41 42 case CC_ATTR_HOST_MEM_ENCRYPT: 43 return sme_me_mask && !(sev_status & MSR_AMD64_SEV_ENABLED); 44 45 case CC_ATTR_GUEST_MEM_ENCRYPT: 46 return sev_status & MSR_AMD64_SEV_ENABLED; 47 48 case CC_ATTR_GUEST_STATE_ENCRYPT: 49 return sev_status & MSR_AMD64_SEV_ES_ENABLED; 50 51 /* 52 * With SEV, the rep string I/O instructions need to be unrolled 53 * but SEV-ES supports them through the #VC handler. 54 */ 55 case CC_ATTR_GUEST_UNROLL_STRING_IO: 56 return (sev_status & MSR_AMD64_SEV_ENABLED) && 57 !(sev_status & MSR_AMD64_SEV_ES_ENABLED); 58 59 default: 60 return false; 61 } 62 #else 63 return false; 64 #endif 65 } 66 67 static bool hyperv_cc_platform_has(enum cc_attr attr) 68 { 69 return attr == CC_ATTR_GUEST_MEM_ENCRYPT; 70 } 71 72 bool cc_platform_has(enum cc_attr attr) 73 { 74 switch (vendor) { 75 case CC_VENDOR_AMD: 76 return amd_cc_platform_has(attr); 77 case CC_VENDOR_INTEL: 78 return intel_cc_platform_has(attr); 79 case CC_VENDOR_HYPERV: 80 return hyperv_cc_platform_has(attr); 81 default: 82 return false; 83 } 84 } 85 EXPORT_SYMBOL_GPL(cc_platform_has); 86 87 __init void cc_set_vendor(enum cc_vendor v) 88 { 89 vendor = v; 90 } 91