Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Confidential Computing Platform Capability checks
0004  *
0005  * Copyright (C) 2021 Advanced Micro Devices, Inc.
0006  *
0007  * Author: Tom Lendacky <thomas.lendacky@amd.com>
0008  */
0009 
0010 #include <linux/export.h>
0011 #include <linux/cc_platform.h>
0012 
0013 #include <asm/coco.h>
0014 #include <asm/processor.h>
0015 
0016 static enum cc_vendor vendor __ro_after_init;
0017 static u64 cc_mask __ro_after_init;
0018 
0019 static bool intel_cc_platform_has(enum cc_attr attr)
0020 {
0021     switch (attr) {
0022     case CC_ATTR_GUEST_UNROLL_STRING_IO:
0023     case CC_ATTR_HOTPLUG_DISABLED:
0024     case CC_ATTR_GUEST_MEM_ENCRYPT:
0025     case CC_ATTR_MEM_ENCRYPT:
0026         return true;
0027     default:
0028         return false;
0029     }
0030 }
0031 
0032 /*
0033  * SME and SEV are very similar but they are not the same, so there are
0034  * times that the kernel will need to distinguish between SME and SEV. The
0035  * cc_platform_has() function is used for this.  When a distinction isn't
0036  * needed, the CC_ATTR_MEM_ENCRYPT attribute can be used.
0037  *
0038  * The trampoline code is a good example for this requirement.  Before
0039  * paging is activated, SME will access all memory as decrypted, but SEV
0040  * will access all memory as encrypted.  So, when APs are being brought
0041  * up under SME the trampoline area cannot be encrypted, whereas under SEV
0042  * the trampoline area must be encrypted.
0043  */
0044 static bool amd_cc_platform_has(enum cc_attr attr)
0045 {
0046 #ifdef CONFIG_AMD_MEM_ENCRYPT
0047     switch (attr) {
0048     case CC_ATTR_MEM_ENCRYPT:
0049         return sme_me_mask;
0050 
0051     case CC_ATTR_HOST_MEM_ENCRYPT:
0052         return sme_me_mask && !(sev_status & MSR_AMD64_SEV_ENABLED);
0053 
0054     case CC_ATTR_GUEST_MEM_ENCRYPT:
0055         return sev_status & MSR_AMD64_SEV_ENABLED;
0056 
0057     case CC_ATTR_GUEST_STATE_ENCRYPT:
0058         return sev_status & MSR_AMD64_SEV_ES_ENABLED;
0059 
0060     /*
0061      * With SEV, the rep string I/O instructions need to be unrolled
0062      * but SEV-ES supports them through the #VC handler.
0063      */
0064     case CC_ATTR_GUEST_UNROLL_STRING_IO:
0065         return (sev_status & MSR_AMD64_SEV_ENABLED) &&
0066             !(sev_status & MSR_AMD64_SEV_ES_ENABLED);
0067 
0068     case CC_ATTR_GUEST_SEV_SNP:
0069         return sev_status & MSR_AMD64_SEV_SNP_ENABLED;
0070 
0071     default:
0072         return false;
0073     }
0074 #else
0075     return false;
0076 #endif
0077 }
0078 
0079 static bool hyperv_cc_platform_has(enum cc_attr attr)
0080 {
0081     return attr == CC_ATTR_GUEST_MEM_ENCRYPT;
0082 }
0083 
0084 bool cc_platform_has(enum cc_attr attr)
0085 {
0086     switch (vendor) {
0087     case CC_VENDOR_AMD:
0088         return amd_cc_platform_has(attr);
0089     case CC_VENDOR_INTEL:
0090         return intel_cc_platform_has(attr);
0091     case CC_VENDOR_HYPERV:
0092         return hyperv_cc_platform_has(attr);
0093     default:
0094         return false;
0095     }
0096 }
0097 EXPORT_SYMBOL_GPL(cc_platform_has);
0098 
0099 u64 cc_mkenc(u64 val)
0100 {
0101     /*
0102      * Both AMD and Intel use a bit in the page table to indicate
0103      * encryption status of the page.
0104      *
0105      * - for AMD, bit *set* means the page is encrypted
0106      * - for Intel *clear* means encrypted.
0107      */
0108     switch (vendor) {
0109     case CC_VENDOR_AMD:
0110         return val | cc_mask;
0111     case CC_VENDOR_INTEL:
0112         return val & ~cc_mask;
0113     default:
0114         return val;
0115     }
0116 }
0117 
0118 u64 cc_mkdec(u64 val)
0119 {
0120     /* See comment in cc_mkenc() */
0121     switch (vendor) {
0122     case CC_VENDOR_AMD:
0123         return val & ~cc_mask;
0124     case CC_VENDOR_INTEL:
0125         return val | cc_mask;
0126     default:
0127         return val;
0128     }
0129 }
0130 EXPORT_SYMBOL_GPL(cc_mkdec);
0131 
0132 __init void cc_set_vendor(enum cc_vendor v)
0133 {
0134     vendor = v;
0135 }
0136 
0137 __init void cc_set_mask(u64 mask)
0138 {
0139     cc_mask = mask;
0140 }