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

Merge tag 'x86_sev_for_v6.17_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 SEV updates from Borislav Petkov:

- Map the SNP calling area pages too so that OVMF EFI fw can issue SVSM
calls properly with the goal of implementing EFI variable store in
the SVSM - a component which is trusted by the guest, vs in the
firmware, which is not

- Allow the kernel to handle #VC exceptions from EFI runtime services
properly when running as a SNP guest

- Rework and cleanup the SNP guest request issue glue code a bit

* tag 'x86_sev_for_v6.17_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/sev: Let sev_es_efi_map_ghcbs() map the CA pages too
x86/sev/vc: Fix EFI runtime instruction emulation
x86/sev: Drop unnecessary parameter in snp_issue_guest_request()
x86/sev: Document requirement for linear mapping of guest request buffers
x86/sev: Allocate request in TSC_INFO_REQ on stack
virt: sev-guest: Contain snp_guest_request_ioctl in sev-guest

+70 -55
+48 -41
arch/x86/coco/sev/core.c
··· 1045 1045 * This is needed by the OVMF UEFI firmware which will use whatever it finds in 1046 1046 * the GHCB MSR as its GHCB to talk to the hypervisor. So make sure the per-cpu 1047 1047 * runtime GHCBs used by the kernel are also mapped in the EFI page-table. 1048 + * 1049 + * When running under SVSM the CA page is needed too, so map it as well. 1048 1050 */ 1049 - int __init sev_es_efi_map_ghcbs(pgd_t *pgd) 1051 + int __init sev_es_efi_map_ghcbs_cas(pgd_t *pgd) 1050 1052 { 1053 + unsigned long address, pflags, pflags_enc; 1051 1054 struct sev_es_runtime_data *data; 1052 - unsigned long address, pflags; 1053 1055 int cpu; 1054 1056 u64 pfn; 1055 1057 ··· 1059 1057 return 0; 1060 1058 1061 1059 pflags = _PAGE_NX | _PAGE_RW; 1060 + pflags_enc = cc_mkenc(pflags); 1062 1061 1063 1062 for_each_possible_cpu(cpu) { 1064 1063 data = per_cpu(runtime_data, cpu); ··· 1069 1066 1070 1067 if (kernel_map_pages_in_pgd(pgd, pfn, address, 1, pflags)) 1071 1068 return 1; 1069 + 1070 + if (snp_vmpl) { 1071 + address = per_cpu(svsm_caa_pa, cpu); 1072 + if (!address) 1073 + return 1; 1074 + 1075 + pfn = address >> PAGE_SHIFT; 1076 + if (kernel_map_pages_in_pgd(pgd, pfn, address, 1, pflags_enc)) 1077 + return 1; 1078 + } 1072 1079 } 1073 1080 1074 1081 return 0; ··· 1402 1389 } 1403 1390 EXPORT_SYMBOL_GPL(snp_issue_svsm_attest_req); 1404 1391 1405 - static int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_data *input, 1406 - struct snp_guest_request_ioctl *rio) 1392 + static int snp_issue_guest_request(struct snp_guest_req *req) 1407 1393 { 1394 + struct snp_req_data *input = &req->input; 1408 1395 struct ghcb_state state; 1409 1396 struct es_em_ctxt ctxt; 1410 1397 unsigned long flags; 1411 1398 struct ghcb *ghcb; 1412 1399 int ret; 1413 1400 1414 - rio->exitinfo2 = SEV_RET_NO_FW_CALL; 1401 + req->exitinfo2 = SEV_RET_NO_FW_CALL; 1415 1402 1416 1403 /* 1417 1404 * __sev_get_ghcb() needs to run with IRQs disabled because it is using ··· 1436 1423 if (ret) 1437 1424 goto e_put; 1438 1425 1439 - rio->exitinfo2 = ghcb->save.sw_exit_info_2; 1440 - switch (rio->exitinfo2) { 1426 + req->exitinfo2 = ghcb->save.sw_exit_info_2; 1427 + switch (req->exitinfo2) { 1441 1428 case 0: 1442 1429 break; 1443 1430 ··· 1932 1919 return 0; 1933 1920 } 1934 1921 1935 - static int __handle_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req, 1936 - struct snp_guest_request_ioctl *rio) 1922 + static int __handle_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req) 1937 1923 { 1938 1924 unsigned long req_start = jiffies; 1939 1925 unsigned int override_npages = 0; ··· 1946 1934 * sequence number must be incremented or the VMPCK must be deleted to 1947 1935 * prevent reuse of the IV. 1948 1936 */ 1949 - rc = snp_issue_guest_request(req, &req->input, rio); 1937 + rc = snp_issue_guest_request(req); 1950 1938 switch (rc) { 1951 1939 case -ENOSPC: 1952 1940 /* ··· 1999 1987 snp_inc_msg_seqno(mdesc); 2000 1988 2001 1989 if (override_err) { 2002 - rio->exitinfo2 = override_err; 1990 + req->exitinfo2 = override_err; 2003 1991 2004 1992 /* 2005 1993 * If an extended guest request was issued and the supplied certificate ··· 2017 2005 return rc; 2018 2006 } 2019 2007 2020 - int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req, 2021 - struct snp_guest_request_ioctl *rio) 2008 + int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req) 2022 2009 { 2023 2010 u64 seqno; 2024 2011 int rc; 2012 + 2013 + /* 2014 + * enc_payload() calls aesgcm_encrypt(), which can potentially offload to HW. 2015 + * The offload's DMA SG list of data to encrypt has to be in linear mapping. 2016 + */ 2017 + if (!virt_addr_valid(req->req_buf) || !virt_addr_valid(req->resp_buf)) { 2018 + pr_warn("AES-GSM buffers must be in linear mapping"); 2019 + return -EINVAL; 2020 + } 2025 2021 2026 2022 guard(mutex)(&snp_cmd_mutex); 2027 2023 ··· 2063 2043 req->input.resp_gpa = __pa(mdesc->response); 2064 2044 req->input.data_gpa = req->certs_data ? __pa(req->certs_data) : 0; 2065 2045 2066 - rc = __handle_guest_request(mdesc, req, rio); 2046 + rc = __handle_guest_request(mdesc, req); 2067 2047 if (rc) { 2068 2048 if (rc == -EIO && 2069 - rio->exitinfo2 == SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN)) 2049 + req->exitinfo2 == SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN)) 2070 2050 return rc; 2071 2051 2072 2052 pr_alert("Detected error from ASP request. rc: %d, exitinfo2: 0x%llx\n", 2073 - rc, rio->exitinfo2); 2053 + rc, req->exitinfo2); 2074 2054 2075 2055 snp_disable_vmpck(mdesc); 2076 2056 return rc; ··· 2089 2069 2090 2070 static int __init snp_get_tsc_info(void) 2091 2071 { 2092 - struct snp_guest_request_ioctl *rio; 2093 2072 struct snp_tsc_info_resp *tsc_resp; 2094 2073 struct snp_tsc_info_req *tsc_req; 2095 2074 struct snp_msg_desc *mdesc; 2096 - struct snp_guest_req *req; 2075 + struct snp_guest_req req = {}; 2097 2076 int rc = -ENOMEM; 2098 2077 2099 2078 tsc_req = kzalloc(sizeof(*tsc_req), GFP_KERNEL); ··· 2108 2089 if (!tsc_resp) 2109 2090 goto e_free_tsc_req; 2110 2091 2111 - req = kzalloc(sizeof(*req), GFP_KERNEL); 2112 - if (!req) 2113 - goto e_free_tsc_resp; 2114 - 2115 - rio = kzalloc(sizeof(*rio), GFP_KERNEL); 2116 - if (!rio) 2117 - goto e_free_req; 2118 - 2119 2092 mdesc = snp_msg_alloc(); 2120 2093 if (IS_ERR_OR_NULL(mdesc)) 2121 - goto e_free_rio; 2094 + goto e_free_tsc_resp; 2122 2095 2123 2096 rc = snp_msg_init(mdesc, snp_vmpl); 2124 2097 if (rc) 2125 2098 goto e_free_mdesc; 2126 2099 2127 - req->msg_version = MSG_HDR_VER; 2128 - req->msg_type = SNP_MSG_TSC_INFO_REQ; 2129 - req->vmpck_id = snp_vmpl; 2130 - req->req_buf = tsc_req; 2131 - req->req_sz = sizeof(*tsc_req); 2132 - req->resp_buf = (void *)tsc_resp; 2133 - req->resp_sz = sizeof(*tsc_resp) + AUTHTAG_LEN; 2134 - req->exit_code = SVM_VMGEXIT_GUEST_REQUEST; 2100 + req.msg_version = MSG_HDR_VER; 2101 + req.msg_type = SNP_MSG_TSC_INFO_REQ; 2102 + req.vmpck_id = snp_vmpl; 2103 + req.req_buf = tsc_req; 2104 + req.req_sz = sizeof(*tsc_req); 2105 + req.resp_buf = (void *)tsc_resp; 2106 + req.resp_sz = sizeof(*tsc_resp) + AUTHTAG_LEN; 2107 + req.exit_code = SVM_VMGEXIT_GUEST_REQUEST; 2135 2108 2136 - rc = snp_send_guest_request(mdesc, req, rio); 2109 + rc = snp_send_guest_request(mdesc, &req); 2137 2110 if (rc) 2138 2111 goto e_request; 2139 2112 ··· 2146 2135 memzero_explicit(tsc_resp, sizeof(*tsc_resp) + AUTHTAG_LEN); 2147 2136 e_free_mdesc: 2148 2137 snp_msg_free(mdesc); 2149 - e_free_rio: 2150 - kfree(rio); 2151 - e_free_req: 2152 - kfree(req); 2153 - e_free_tsc_resp: 2138 + e_free_tsc_resp: 2154 2139 kfree(tsc_resp); 2155 2140 e_free_tsc_req: 2156 2141 kfree(tsc_req);
+8 -1
arch/x86/coco/sev/vc-handle.c
··· 17 17 #include <linux/mm.h> 18 18 #include <linux/io.h> 19 19 #include <linux/psp-sev.h> 20 + #include <linux/efi.h> 20 21 #include <uapi/linux/sev-guest.h> 21 22 22 23 #include <asm/init.h> ··· 179 178 return ES_OK; 180 179 } 181 180 181 + /* 182 + * User instruction decoding is also required for the EFI runtime. Even though 183 + * the EFI runtime is running in kernel mode, it uses special EFI virtual 184 + * address mappings that require the use of efi_mm to properly address and 185 + * decode. 186 + */ 182 187 static enum es_result vc_decode_insn(struct es_em_ctxt *ctxt) 183 188 { 184 - if (user_mode(ctxt->regs)) 189 + if (user_mode(ctxt->regs) || mm_is_efi(current->active_mm)) 185 190 return __vc_decode_user_insn(ctxt); 186 191 else 187 192 return __vc_decode_kern_insn(ctxt);
+6 -8
arch/x86/include/asm/sev.h
··· 243 243 size_t resp_sz; 244 244 245 245 u64 exit_code; 246 + u64 exitinfo2; 246 247 unsigned int vmpck_id; 247 248 u8 msg_version; 248 249 u8 msg_type; ··· 461 460 cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT)) 462 461 __sev_es_nmi_complete(); 463 462 } 464 - extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd); 463 + extern int __init sev_es_efi_map_ghcbs_cas(pgd_t *pgd); 465 464 extern void sev_enable(struct boot_params *bp); 466 465 467 466 /* ··· 502 501 return rc; 503 502 } 504 503 505 - struct snp_guest_request_ioctl; 506 - 507 504 void setup_ghcb(void); 508 505 void early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, 509 506 unsigned long npages); ··· 527 528 int snp_msg_init(struct snp_msg_desc *mdesc, int vmpck_id); 528 529 struct snp_msg_desc *snp_msg_alloc(void); 529 530 void snp_msg_free(struct snp_msg_desc *mdesc); 530 - int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req, 531 - struct snp_guest_request_ioctl *rio); 531 + int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req); 532 532 533 533 int snp_svsm_vtpm_send_command(u8 *buffer); 534 534 ··· 569 571 static inline void sev_es_ist_exit(void) { } 570 572 static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { return 0; } 571 573 static inline void sev_es_nmi_complete(void) { } 572 - static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; } 574 + static inline int sev_es_efi_map_ghcbs_cas(pgd_t *pgd) { return 0; } 573 575 static inline void sev_enable(struct boot_params *bp) { } 574 576 static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) { return 0; } 575 577 static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs) { return 0; } ··· 600 602 static inline int snp_msg_init(struct snp_msg_desc *mdesc, int vmpck_id) { return -1; } 601 603 static inline struct snp_msg_desc *snp_msg_alloc(void) { return NULL; } 602 604 static inline void snp_msg_free(struct snp_msg_desc *mdesc) { } 603 - static inline int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req, 604 - struct snp_guest_request_ioctl *rio) { return -ENODEV; } 605 + static inline int snp_send_guest_request(struct snp_msg_desc *mdesc, 606 + struct snp_guest_req *req) { return -ENODEV; } 605 607 static inline int snp_svsm_vtpm_send_command(u8 *buffer) { return -ENODEV; } 606 608 static inline void __init snp_secure_tsc_prepare(void) { } 607 609 static inline void __init snp_secure_tsc_init(void) { }
+2 -2
arch/x86/platform/efi/efi_64.c
··· 216 216 * When SEV-ES is active, the GHCB as set by the kernel will be used 217 217 * by firmware. Create a 1:1 unencrypted mapping for each GHCB. 218 218 */ 219 - if (sev_es_efi_map_ghcbs(pgd)) { 220 - pr_err("Failed to create 1:1 mapping for the GHCBs!\n"); 219 + if (sev_es_efi_map_ghcbs_cas(pgd)) { 220 + pr_err("Failed to create 1:1 mapping for the GHCBs and CAs!\n"); 221 221 return 1; 222 222 } 223 223
+6 -3
drivers/virt/coco/sev-guest/sev-guest.c
··· 101 101 req.resp_sz = resp_len; 102 102 req.exit_code = SVM_VMGEXIT_GUEST_REQUEST; 103 103 104 - rc = snp_send_guest_request(mdesc, &req, arg); 104 + rc = snp_send_guest_request(mdesc, &req); 105 + arg->exitinfo2 = req.exitinfo2; 105 106 if (rc) 106 107 goto e_free; 107 108 ··· 153 152 req.resp_sz = resp_len; 154 153 req.exit_code = SVM_VMGEXIT_GUEST_REQUEST; 155 154 156 - rc = snp_send_guest_request(mdesc, &req, arg); 155 + rc = snp_send_guest_request(mdesc, &req); 156 + arg->exitinfo2 = req.exitinfo2; 157 157 if (rc) 158 158 return rc; 159 159 ··· 251 249 req.resp_sz = resp_len; 252 250 req.exit_code = SVM_VMGEXIT_EXT_GUEST_REQUEST; 253 251 254 - ret = snp_send_guest_request(mdesc, &req, arg); 252 + ret = snp_send_guest_request(mdesc, &req); 253 + arg->exitinfo2 = req.exitinfo2; 255 254 256 255 /* If certs length is invalid then copy the returned length */ 257 256 if (arg->vmm_error == SNP_GUEST_VMM_ERR_INVALID_LEN) {