Skip to content

Commit 14bed9b

Browse files
committed
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
2 parents 01fce21 + a754963 commit 14bed9b

File tree

5 files changed

+70
-55
lines changed

5 files changed

+70
-55
lines changed

arch/x86/coco/sev/core.c

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,18 +1045,21 @@ int __init sev_es_setup_ap_jump_table(struct real_mode_header *rmh)
10451045
* This is needed by the OVMF UEFI firmware which will use whatever it finds in
10461046
* the GHCB MSR as its GHCB to talk to the hypervisor. So make sure the per-cpu
10471047
* 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.
10481050
*/
1049-
int __init sev_es_efi_map_ghcbs(pgd_t *pgd)
1051+
int __init sev_es_efi_map_ghcbs_cas(pgd_t *pgd)
10501052
{
1053+
unsigned long address, pflags, pflags_enc;
10511054
struct sev_es_runtime_data *data;
1052-
unsigned long address, pflags;
10531055
int cpu;
10541056
u64 pfn;
10551057

10561058
if (!cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT))
10571059
return 0;
10581060

10591061
pflags = _PAGE_NX | _PAGE_RW;
1062+
pflags_enc = cc_mkenc(pflags);
10601063

10611064
for_each_possible_cpu(cpu) {
10621065
data = per_cpu(runtime_data, cpu);
@@ -1066,6 +1069,16 @@ int __init sev_es_efi_map_ghcbs(pgd_t *pgd)
10661069

10671070
if (kernel_map_pages_in_pgd(pgd, pfn, address, 1, pflags))
10681071
return 1;
1072+
1073+
if (snp_vmpl) {
1074+
address = per_cpu(svsm_caa_pa, cpu);
1075+
if (!address)
1076+
return 1;
1077+
1078+
pfn = address >> PAGE_SHIFT;
1079+
if (kernel_map_pages_in_pgd(pgd, pfn, address, 1, pflags_enc))
1080+
return 1;
1081+
}
10691082
}
10701083

10711084
return 0;
@@ -1389,16 +1402,16 @@ int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call,
13891402
}
13901403
EXPORT_SYMBOL_GPL(snp_issue_svsm_attest_req);
13911404

1392-
static int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_data *input,
1393-
struct snp_guest_request_ioctl *rio)
1405+
static int snp_issue_guest_request(struct snp_guest_req *req)
13941406
{
1407+
struct snp_req_data *input = &req->input;
13951408
struct ghcb_state state;
13961409
struct es_em_ctxt ctxt;
13971410
unsigned long flags;
13981411
struct ghcb *ghcb;
13991412
int ret;
14001413

1401-
rio->exitinfo2 = SEV_RET_NO_FW_CALL;
1414+
req->exitinfo2 = SEV_RET_NO_FW_CALL;
14021415

14031416
/*
14041417
* __sev_get_ghcb() needs to run with IRQs disabled because it is using
@@ -1423,8 +1436,8 @@ static int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_dat
14231436
if (ret)
14241437
goto e_put;
14251438

1426-
rio->exitinfo2 = ghcb->save.sw_exit_info_2;
1427-
switch (rio->exitinfo2) {
1439+
req->exitinfo2 = ghcb->save.sw_exit_info_2;
1440+
switch (req->exitinfo2) {
14281441
case 0:
14291442
break;
14301443

@@ -1919,8 +1932,7 @@ static int enc_payload(struct snp_msg_desc *mdesc, u64 seqno, struct snp_guest_r
19191932
return 0;
19201933
}
19211934

1922-
static int __handle_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req,
1923-
struct snp_guest_request_ioctl *rio)
1935+
static int __handle_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req)
19241936
{
19251937
unsigned long req_start = jiffies;
19261938
unsigned int override_npages = 0;
@@ -1934,7 +1946,7 @@ static int __handle_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_r
19341946
* sequence number must be incremented or the VMPCK must be deleted to
19351947
* prevent reuse of the IV.
19361948
*/
1937-
rc = snp_issue_guest_request(req, &req->input, rio);
1949+
rc = snp_issue_guest_request(req);
19381950
switch (rc) {
19391951
case -ENOSPC:
19401952
/*
@@ -1987,7 +1999,7 @@ static int __handle_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_r
19871999
snp_inc_msg_seqno(mdesc);
19882000

19892001
if (override_err) {
1990-
rio->exitinfo2 = override_err;
2002+
req->exitinfo2 = override_err;
19912003

19922004
/*
19932005
* If an extended guest request was issued and the supplied certificate
@@ -2005,12 +2017,20 @@ static int __handle_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_r
20052017
return rc;
20062018
}
20072019

2008-
int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req,
2009-
struct snp_guest_request_ioctl *rio)
2020+
int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req)
20102021
{
20112022
u64 seqno;
20122023
int rc;
20132024

2025+
/*
2026+
* enc_payload() calls aesgcm_encrypt(), which can potentially offload to HW.
2027+
* The offload's DMA SG list of data to encrypt has to be in linear mapping.
2028+
*/
2029+
if (!virt_addr_valid(req->req_buf) || !virt_addr_valid(req->resp_buf)) {
2030+
pr_warn("AES-GSM buffers must be in linear mapping");
2031+
return -EINVAL;
2032+
}
2033+
20142034
guard(mutex)(&snp_cmd_mutex);
20152035

20162036
/* Check if the VMPCK is not empty */
@@ -2043,14 +2063,14 @@ int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req
20432063
req->input.resp_gpa = __pa(mdesc->response);
20442064
req->input.data_gpa = req->certs_data ? __pa(req->certs_data) : 0;
20452065

2046-
rc = __handle_guest_request(mdesc, req, rio);
2066+
rc = __handle_guest_request(mdesc, req);
20472067
if (rc) {
20482068
if (rc == -EIO &&
2049-
rio->exitinfo2 == SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN))
2069+
req->exitinfo2 == SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN))
20502070
return rc;
20512071

20522072
pr_alert("Detected error from ASP request. rc: %d, exitinfo2: 0x%llx\n",
2053-
rc, rio->exitinfo2);
2073+
rc, req->exitinfo2);
20542074

20552075
snp_disable_vmpck(mdesc);
20562076
return rc;
@@ -2069,11 +2089,10 @@ EXPORT_SYMBOL_GPL(snp_send_guest_request);
20692089

20702090
static int __init snp_get_tsc_info(void)
20712091
{
2072-
struct snp_guest_request_ioctl *rio;
20732092
struct snp_tsc_info_resp *tsc_resp;
20742093
struct snp_tsc_info_req *tsc_req;
20752094
struct snp_msg_desc *mdesc;
2076-
struct snp_guest_req *req;
2095+
struct snp_guest_req req = {};
20772096
int rc = -ENOMEM;
20782097

20792098
tsc_req = kzalloc(sizeof(*tsc_req), GFP_KERNEL);
@@ -2089,32 +2108,24 @@ static int __init snp_get_tsc_info(void)
20892108
if (!tsc_resp)
20902109
goto e_free_tsc_req;
20912110

2092-
req = kzalloc(sizeof(*req), GFP_KERNEL);
2093-
if (!req)
2094-
goto e_free_tsc_resp;
2095-
2096-
rio = kzalloc(sizeof(*rio), GFP_KERNEL);
2097-
if (!rio)
2098-
goto e_free_req;
2099-
21002111
mdesc = snp_msg_alloc();
21012112
if (IS_ERR_OR_NULL(mdesc))
2102-
goto e_free_rio;
2113+
goto e_free_tsc_resp;
21032114

21042115
rc = snp_msg_init(mdesc, snp_vmpl);
21052116
if (rc)
21062117
goto e_free_mdesc;
21072118

2108-
req->msg_version = MSG_HDR_VER;
2109-
req->msg_type = SNP_MSG_TSC_INFO_REQ;
2110-
req->vmpck_id = snp_vmpl;
2111-
req->req_buf = tsc_req;
2112-
req->req_sz = sizeof(*tsc_req);
2113-
req->resp_buf = (void *)tsc_resp;
2114-
req->resp_sz = sizeof(*tsc_resp) + AUTHTAG_LEN;
2115-
req->exit_code = SVM_VMGEXIT_GUEST_REQUEST;
2119+
req.msg_version = MSG_HDR_VER;
2120+
req.msg_type = SNP_MSG_TSC_INFO_REQ;
2121+
req.vmpck_id = snp_vmpl;
2122+
req.req_buf = tsc_req;
2123+
req.req_sz = sizeof(*tsc_req);
2124+
req.resp_buf = (void *)tsc_resp;
2125+
req.resp_sz = sizeof(*tsc_resp) + AUTHTAG_LEN;
2126+
req.exit_code = SVM_VMGEXIT_GUEST_REQUEST;
21162127

2117-
rc = snp_send_guest_request(mdesc, req, rio);
2128+
rc = snp_send_guest_request(mdesc, &req);
21182129
if (rc)
21192130
goto e_request;
21202131

@@ -2135,11 +2146,7 @@ static int __init snp_get_tsc_info(void)
21352146
memzero_explicit(tsc_resp, sizeof(*tsc_resp) + AUTHTAG_LEN);
21362147
e_free_mdesc:
21372148
snp_msg_free(mdesc);
2138-
e_free_rio:
2139-
kfree(rio);
2140-
e_free_req:
2141-
kfree(req);
2142-
e_free_tsc_resp:
2149+
e_free_tsc_resp:
21432150
kfree(tsc_resp);
21442151
e_free_tsc_req:
21452152
kfree(tsc_req);

arch/x86/coco/sev/vc-handle.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/mm.h>
1818
#include <linux/io.h>
1919
#include <linux/psp-sev.h>
20+
#include <linux/efi.h>
2021
#include <uapi/linux/sev-guest.h>
2122

2223
#include <asm/init.h>
@@ -178,9 +179,15 @@ static enum es_result __vc_decode_kern_insn(struct es_em_ctxt *ctxt)
178179
return ES_OK;
179180
}
180181

182+
/*
183+
* User instruction decoding is also required for the EFI runtime. Even though
184+
* the EFI runtime is running in kernel mode, it uses special EFI virtual
185+
* address mappings that require the use of efi_mm to properly address and
186+
* decode.
187+
*/
181188
static enum es_result vc_decode_insn(struct es_em_ctxt *ctxt)
182189
{
183-
if (user_mode(ctxt->regs))
190+
if (user_mode(ctxt->regs) || mm_is_efi(current->active_mm))
184191
return __vc_decode_user_insn(ctxt);
185192
else
186193
return __vc_decode_kern_insn(ctxt);

arch/x86/include/asm/sev.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ struct snp_guest_req {
243243
size_t resp_sz;
244244

245245
u64 exit_code;
246+
u64 exitinfo2;
246247
unsigned int vmpck_id;
247248
u8 msg_version;
248249
u8 msg_type;
@@ -460,7 +461,7 @@ static __always_inline void sev_es_nmi_complete(void)
460461
cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT))
461462
__sev_es_nmi_complete();
462463
}
463-
extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd);
464+
extern int __init sev_es_efi_map_ghcbs_cas(pgd_t *pgd);
464465
extern void sev_enable(struct boot_params *bp);
465466

466467
/*
@@ -501,8 +502,6 @@ static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate)
501502
return rc;
502503
}
503504

504-
struct snp_guest_request_ioctl;
505-
506505
void setup_ghcb(void);
507506
void early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr,
508507
unsigned long npages);
@@ -528,8 +527,7 @@ void snp_kexec_begin(void);
528527
int snp_msg_init(struct snp_msg_desc *mdesc, int vmpck_id);
529528
struct snp_msg_desc *snp_msg_alloc(void);
530529
void snp_msg_free(struct snp_msg_desc *mdesc);
531-
int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req,
532-
struct snp_guest_request_ioctl *rio);
530+
int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req);
533531

534532
int snp_svsm_vtpm_send_command(u8 *buffer);
535533

@@ -571,7 +569,7 @@ static inline void sev_es_ist_enter(struct pt_regs *regs) { }
571569
static inline void sev_es_ist_exit(void) { }
572570
static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { return 0; }
573571
static inline void sev_es_nmi_complete(void) { }
574-
static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; }
572+
static inline int sev_es_efi_map_ghcbs_cas(pgd_t *pgd) { return 0; }
575573
static inline void sev_enable(struct boot_params *bp) { }
576574
static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) { return 0; }
577575
static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs) { return 0; }
@@ -602,8 +600,8 @@ static inline void snp_kexec_begin(void) { }
602600
static inline int snp_msg_init(struct snp_msg_desc *mdesc, int vmpck_id) { return -1; }
603601
static inline struct snp_msg_desc *snp_msg_alloc(void) { return NULL; }
604602
static inline void snp_msg_free(struct snp_msg_desc *mdesc) { }
605-
static inline int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req,
606-
struct snp_guest_request_ioctl *rio) { return -ENODEV; }
603+
static inline int snp_send_guest_request(struct snp_msg_desc *mdesc,
604+
struct snp_guest_req *req) { return -ENODEV; }
607605
static inline int snp_svsm_vtpm_send_command(u8 *buffer) { return -ENODEV; }
608606
static inline void __init snp_secure_tsc_prepare(void) { }
609607
static inline void __init snp_secure_tsc_init(void) { }

arch/x86/platform/efi/efi_64.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,8 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
216216
* When SEV-ES is active, the GHCB as set by the kernel will be used
217217
* by firmware. Create a 1:1 unencrypted mapping for each GHCB.
218218
*/
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");
221221
return 1;
222222
}
223223

drivers/virt/coco/sev-guest/sev-guest.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_io
101101
req.resp_sz = resp_len;
102102
req.exit_code = SVM_VMGEXIT_GUEST_REQUEST;
103103

104-
rc = snp_send_guest_request(mdesc, &req, arg);
104+
rc = snp_send_guest_request(mdesc, &req);
105+
arg->exitinfo2 = req.exitinfo2;
105106
if (rc)
106107
goto e_free;
107108

@@ -152,7 +153,8 @@ static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_reque
152153
req.resp_sz = resp_len;
153154
req.exit_code = SVM_VMGEXIT_GUEST_REQUEST;
154155

155-
rc = snp_send_guest_request(mdesc, &req, arg);
156+
rc = snp_send_guest_request(mdesc, &req);
157+
arg->exitinfo2 = req.exitinfo2;
156158
if (rc)
157159
return rc;
158160

@@ -249,7 +251,8 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques
249251
req.resp_sz = resp_len;
250252
req.exit_code = SVM_VMGEXIT_EXT_GUEST_REQUEST;
251253

252-
ret = snp_send_guest_request(mdesc, &req, arg);
254+
ret = snp_send_guest_request(mdesc, &req);
255+
arg->exitinfo2 = req.exitinfo2;
253256

254257
/* If certs length is invalid then copy the returned length */
255258
if (arg->vmm_error == SNP_GUEST_VMM_ERR_INVALID_LEN) {

0 commit comments

Comments
 (0)