Skip to content

Commit 7e20d34

Browse files
committed
Merge tag 'x86-urgent-2023-10-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull misc x86 fixes from Ingo Molnar: - Fix SEV-SNP guest crashes that may happen on NMIs - Fix a potential SEV platform memory setup overflow * tag 'x86-urgent-2023-10-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/sev: Change npages to unsigned long in snp_accept_memory() x86/sev: Use the GHCB protocol when available for SNP CPUID requests
2 parents b9ddbb0 + 62d5e97 commit 7e20d34

File tree

2 files changed

+56
-16
lines changed

2 files changed

+56
-16
lines changed

arch/x86/kernel/sev-shared.c

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ static int __sev_cpuid_hv(u32 fn, int reg_idx, u32 *reg)
256256
return 0;
257257
}
258258

259-
static int sev_cpuid_hv(struct cpuid_leaf *leaf)
259+
static int __sev_cpuid_hv_msr(struct cpuid_leaf *leaf)
260260
{
261261
int ret;
262262

@@ -279,6 +279,45 @@ static int sev_cpuid_hv(struct cpuid_leaf *leaf)
279279
return ret;
280280
}
281281

282+
static int __sev_cpuid_hv_ghcb(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
283+
{
284+
u32 cr4 = native_read_cr4();
285+
int ret;
286+
287+
ghcb_set_rax(ghcb, leaf->fn);
288+
ghcb_set_rcx(ghcb, leaf->subfn);
289+
290+
if (cr4 & X86_CR4_OSXSAVE)
291+
/* Safe to read xcr0 */
292+
ghcb_set_xcr0(ghcb, xgetbv(XCR_XFEATURE_ENABLED_MASK));
293+
else
294+
/* xgetbv will cause #UD - use reset value for xcr0 */
295+
ghcb_set_xcr0(ghcb, 1);
296+
297+
ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_CPUID, 0, 0);
298+
if (ret != ES_OK)
299+
return ret;
300+
301+
if (!(ghcb_rax_is_valid(ghcb) &&
302+
ghcb_rbx_is_valid(ghcb) &&
303+
ghcb_rcx_is_valid(ghcb) &&
304+
ghcb_rdx_is_valid(ghcb)))
305+
return ES_VMM_ERROR;
306+
307+
leaf->eax = ghcb->save.rax;
308+
leaf->ebx = ghcb->save.rbx;
309+
leaf->ecx = ghcb->save.rcx;
310+
leaf->edx = ghcb->save.rdx;
311+
312+
return ES_OK;
313+
}
314+
315+
static int sev_cpuid_hv(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
316+
{
317+
return ghcb ? __sev_cpuid_hv_ghcb(ghcb, ctxt, leaf)
318+
: __sev_cpuid_hv_msr(leaf);
319+
}
320+
282321
/*
283322
* This may be called early while still running on the initial identity
284323
* mapping. Use RIP-relative addressing to obtain the correct address
@@ -388,19 +427,20 @@ snp_cpuid_get_validated_func(struct cpuid_leaf *leaf)
388427
return false;
389428
}
390429

391-
static void snp_cpuid_hv(struct cpuid_leaf *leaf)
430+
static void snp_cpuid_hv(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
392431
{
393-
if (sev_cpuid_hv(leaf))
432+
if (sev_cpuid_hv(ghcb, ctxt, leaf))
394433
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID_HV);
395434
}
396435

397-
static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
436+
static int snp_cpuid_postprocess(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
437+
struct cpuid_leaf *leaf)
398438
{
399439
struct cpuid_leaf leaf_hv = *leaf;
400440

401441
switch (leaf->fn) {
402442
case 0x1:
403-
snp_cpuid_hv(&leaf_hv);
443+
snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
404444

405445
/* initial APIC ID */
406446
leaf->ebx = (leaf_hv.ebx & GENMASK(31, 24)) | (leaf->ebx & GENMASK(23, 0));
@@ -419,7 +459,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
419459
break;
420460
case 0xB:
421461
leaf_hv.subfn = 0;
422-
snp_cpuid_hv(&leaf_hv);
462+
snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
423463

424464
/* extended APIC ID */
425465
leaf->edx = leaf_hv.edx;
@@ -467,7 +507,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
467507
}
468508
break;
469509
case 0x8000001E:
470-
snp_cpuid_hv(&leaf_hv);
510+
snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
471511

472512
/* extended APIC ID */
473513
leaf->eax = leaf_hv.eax;
@@ -488,7 +528,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
488528
* Returns -EOPNOTSUPP if feature not enabled. Any other non-zero return value
489529
* should be treated as fatal by caller.
490530
*/
491-
static int snp_cpuid(struct cpuid_leaf *leaf)
531+
static int snp_cpuid(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
492532
{
493533
const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
494534

@@ -522,7 +562,7 @@ static int snp_cpuid(struct cpuid_leaf *leaf)
522562
return 0;
523563
}
524564

525-
return snp_cpuid_postprocess(leaf);
565+
return snp_cpuid_postprocess(ghcb, ctxt, leaf);
526566
}
527567

528568
/*
@@ -544,14 +584,14 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)
544584
leaf.fn = fn;
545585
leaf.subfn = subfn;
546586

547-
ret = snp_cpuid(&leaf);
587+
ret = snp_cpuid(NULL, NULL, &leaf);
548588
if (!ret)
549589
goto cpuid_done;
550590

551591
if (ret != -EOPNOTSUPP)
552592
goto fail;
553593

554-
if (sev_cpuid_hv(&leaf))
594+
if (__sev_cpuid_hv_msr(&leaf))
555595
goto fail;
556596

557597
cpuid_done:
@@ -848,14 +888,15 @@ static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
848888
return ret;
849889
}
850890

851-
static int vc_handle_cpuid_snp(struct pt_regs *regs)
891+
static int vc_handle_cpuid_snp(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
852892
{
893+
struct pt_regs *regs = ctxt->regs;
853894
struct cpuid_leaf leaf;
854895
int ret;
855896

856897
leaf.fn = regs->ax;
857898
leaf.subfn = regs->cx;
858-
ret = snp_cpuid(&leaf);
899+
ret = snp_cpuid(ghcb, ctxt, &leaf);
859900
if (!ret) {
860901
regs->ax = leaf.eax;
861902
regs->bx = leaf.ebx;
@@ -874,7 +915,7 @@ static enum es_result vc_handle_cpuid(struct ghcb *ghcb,
874915
enum es_result ret;
875916
int snp_cpuid_ret;
876917

877-
snp_cpuid_ret = vc_handle_cpuid_snp(regs);
918+
snp_cpuid_ret = vc_handle_cpuid_snp(ghcb, ctxt);
878919
if (!snp_cpuid_ret)
879920
return ES_OK;
880921
if (snp_cpuid_ret != -EOPNOTSUPP)

arch/x86/kernel/sev.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -868,8 +868,7 @@ void snp_set_memory_private(unsigned long vaddr, unsigned long npages)
868868

869869
void snp_accept_memory(phys_addr_t start, phys_addr_t end)
870870
{
871-
unsigned long vaddr;
872-
unsigned int npages;
871+
unsigned long vaddr, npages;
873872

874873
if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
875874
return;

0 commit comments

Comments
 (0)