Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: ccp - Add support for SEV-ES to the PSP driver

To provide support for SEV-ES, the hypervisor must provide an area of
memory to the PSP. Once this Trusted Memory Region (TMR) is provided to
the PSP, the contents of this area of memory are no longer available to
the x86.

Update the PSP driver to allocate a 1MB region for the TMR that is 1MB
aligned and then provide it to the PSP through the SEV INIT command.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Tom Lendacky and committed by
Herbert Xu
97f9ac3d 3c2214b6

+47
+43
drivers/crypto/ccp/sev-dev.c
··· 20 20 #include <linux/hw_random.h> 21 21 #include <linux/ccp.h> 22 22 #include <linux/firmware.h> 23 + #include <linux/gfp.h> 23 24 24 25 #include <asm/smp.h> 25 26 ··· 44 43 45 44 static bool psp_dead; 46 45 static int psp_timeout; 46 + 47 + /* Trusted Memory Region (TMR): 48 + * The TMR is a 1MB area that must be 1MB aligned. Use the page allocator 49 + * to allocate the memory, which will return aligned memory for the specified 50 + * allocation order. 51 + */ 52 + #define SEV_ES_TMR_SIZE (1024 * 1024) 53 + static void *sev_es_tmr; 47 54 48 55 static inline bool sev_version_greater_or_equal(u8 maj, u8 min) 49 56 { ··· 222 213 223 214 if (sev->state == SEV_STATE_INIT) 224 215 return 0; 216 + 217 + if (sev_es_tmr) { 218 + u64 tmr_pa; 219 + 220 + /* 221 + * Do not include the encryption mask on the physical 222 + * address of the TMR (firmware should clear it anyway). 223 + */ 224 + tmr_pa = __pa(sev_es_tmr); 225 + 226 + sev->init_cmd_buf.flags |= SEV_INIT_FLAGS_SEV_ES; 227 + sev->init_cmd_buf.tmr_address = tmr_pa; 228 + sev->init_cmd_buf.tmr_len = SEV_ES_TMR_SIZE; 229 + } 225 230 226 231 rc = __sev_do_cmd_locked(SEV_CMD_INIT, &sev->init_cmd_buf, error); 227 232 if (rc) ··· 1035 1012 void sev_pci_init(void) 1036 1013 { 1037 1014 struct sev_device *sev = psp_master->sev_data; 1015 + struct page *tmr_page; 1038 1016 int error, rc; 1039 1017 1040 1018 if (!sev) ··· 1064 1040 if (sev_version_greater_or_equal(0, 15) && 1065 1041 sev_update_firmware(sev->dev) == 0) 1066 1042 sev_get_api_version(); 1043 + 1044 + /* Obtain the TMR memory area for SEV-ES use */ 1045 + tmr_page = alloc_pages(GFP_KERNEL, get_order(SEV_ES_TMR_SIZE)); 1046 + if (tmr_page) { 1047 + sev_es_tmr = page_address(tmr_page); 1048 + } else { 1049 + sev_es_tmr = NULL; 1050 + dev_warn(sev->dev, 1051 + "SEV: TMR allocation failed, SEV-ES support unavailable\n"); 1052 + } 1067 1053 1068 1054 /* Initialize the platform */ 1069 1055 rc = sev_platform_init(&error); ··· 1109 1075 return; 1110 1076 1111 1077 sev_platform_shutdown(NULL); 1078 + 1079 + if (sev_es_tmr) { 1080 + /* The TMR area was encrypted, flush it from the cache */ 1081 + wbinvd_on_all_cpus(); 1082 + 1083 + free_pages((unsigned long)sev_es_tmr, 1084 + get_order(SEV_ES_TMR_SIZE)); 1085 + sev_es_tmr = NULL; 1086 + } 1112 1087 }
+2
include/linux/psp-sev.h
··· 100 100 u32 tmr_len; /* In */ 101 101 } __packed; 102 102 103 + #define SEV_INIT_FLAGS_SEV_ES 0x01 104 + 103 105 /** 104 106 * struct sev_data_pek_csr - PEK_CSR command parameters 105 107 *
+2
include/uapi/linux/psp-sev.h
··· 83 83 __u32 guest_count; /* Out */ 84 84 } __packed; 85 85 86 + #define SEV_STATUS_FLAGS_CONFIG_ES 0x0100 87 + 86 88 /** 87 89 * struct sev_user_data_pek_csr - PEK_CSR command parameters 88 90 *