Commit 7e20d344 authored by Linus Torvalds's avatar Linus Torvalds

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
parents b9ddbb0c 62d5e970
...@@ -256,7 +256,7 @@ static int __sev_cpuid_hv(u32 fn, int reg_idx, u32 *reg) ...@@ -256,7 +256,7 @@ static int __sev_cpuid_hv(u32 fn, int reg_idx, u32 *reg)
return 0; return 0;
} }
static int sev_cpuid_hv(struct cpuid_leaf *leaf) static int __sev_cpuid_hv_msr(struct cpuid_leaf *leaf)
{ {
int ret; int ret;
...@@ -279,6 +279,45 @@ static int sev_cpuid_hv(struct cpuid_leaf *leaf) ...@@ -279,6 +279,45 @@ static int sev_cpuid_hv(struct cpuid_leaf *leaf)
return ret; return ret;
} }
static int __sev_cpuid_hv_ghcb(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
{
u32 cr4 = native_read_cr4();
int ret;
ghcb_set_rax(ghcb, leaf->fn);
ghcb_set_rcx(ghcb, leaf->subfn);
if (cr4 & X86_CR4_OSXSAVE)
/* Safe to read xcr0 */
ghcb_set_xcr0(ghcb, xgetbv(XCR_XFEATURE_ENABLED_MASK));
else
/* xgetbv will cause #UD - use reset value for xcr0 */
ghcb_set_xcr0(ghcb, 1);
ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_CPUID, 0, 0);
if (ret != ES_OK)
return ret;
if (!(ghcb_rax_is_valid(ghcb) &&
ghcb_rbx_is_valid(ghcb) &&
ghcb_rcx_is_valid(ghcb) &&
ghcb_rdx_is_valid(ghcb)))
return ES_VMM_ERROR;
leaf->eax = ghcb->save.rax;
leaf->ebx = ghcb->save.rbx;
leaf->ecx = ghcb->save.rcx;
leaf->edx = ghcb->save.rdx;
return ES_OK;
}
static int sev_cpuid_hv(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
{
return ghcb ? __sev_cpuid_hv_ghcb(ghcb, ctxt, leaf)
: __sev_cpuid_hv_msr(leaf);
}
/* /*
* This may be called early while still running on the initial identity * This may be called early while still running on the initial identity
* mapping. Use RIP-relative addressing to obtain the correct address * mapping. Use RIP-relative addressing to obtain the correct address
...@@ -388,19 +427,20 @@ snp_cpuid_get_validated_func(struct cpuid_leaf *leaf) ...@@ -388,19 +427,20 @@ snp_cpuid_get_validated_func(struct cpuid_leaf *leaf)
return false; return false;
} }
static void snp_cpuid_hv(struct cpuid_leaf *leaf) static void snp_cpuid_hv(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
{ {
if (sev_cpuid_hv(leaf)) if (sev_cpuid_hv(ghcb, ctxt, leaf))
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID_HV); sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID_HV);
} }
static int snp_cpuid_postprocess(struct cpuid_leaf *leaf) static int snp_cpuid_postprocess(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
struct cpuid_leaf *leaf)
{ {
struct cpuid_leaf leaf_hv = *leaf; struct cpuid_leaf leaf_hv = *leaf;
switch (leaf->fn) { switch (leaf->fn) {
case 0x1: case 0x1:
snp_cpuid_hv(&leaf_hv); snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
/* initial APIC ID */ /* initial APIC ID */
leaf->ebx = (leaf_hv.ebx & GENMASK(31, 24)) | (leaf->ebx & GENMASK(23, 0)); 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) ...@@ -419,7 +459,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
break; break;
case 0xB: case 0xB:
leaf_hv.subfn = 0; leaf_hv.subfn = 0;
snp_cpuid_hv(&leaf_hv); snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
/* extended APIC ID */ /* extended APIC ID */
leaf->edx = leaf_hv.edx; leaf->edx = leaf_hv.edx;
...@@ -467,7 +507,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf) ...@@ -467,7 +507,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
} }
break; break;
case 0x8000001E: case 0x8000001E:
snp_cpuid_hv(&leaf_hv); snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
/* extended APIC ID */ /* extended APIC ID */
leaf->eax = leaf_hv.eax; leaf->eax = leaf_hv.eax;
...@@ -488,7 +528,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf) ...@@ -488,7 +528,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
* Returns -EOPNOTSUPP if feature not enabled. Any other non-zero return value * Returns -EOPNOTSUPP if feature not enabled. Any other non-zero return value
* should be treated as fatal by caller. * should be treated as fatal by caller.
*/ */
static int snp_cpuid(struct cpuid_leaf *leaf) static int snp_cpuid(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
{ {
const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table(); const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
...@@ -522,7 +562,7 @@ static int snp_cpuid(struct cpuid_leaf *leaf) ...@@ -522,7 +562,7 @@ static int snp_cpuid(struct cpuid_leaf *leaf)
return 0; return 0;
} }
return snp_cpuid_postprocess(leaf); return snp_cpuid_postprocess(ghcb, ctxt, leaf);
} }
/* /*
...@@ -544,14 +584,14 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code) ...@@ -544,14 +584,14 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)
leaf.fn = fn; leaf.fn = fn;
leaf.subfn = subfn; leaf.subfn = subfn;
ret = snp_cpuid(&leaf); ret = snp_cpuid(NULL, NULL, &leaf);
if (!ret) if (!ret)
goto cpuid_done; goto cpuid_done;
if (ret != -EOPNOTSUPP) if (ret != -EOPNOTSUPP)
goto fail; goto fail;
if (sev_cpuid_hv(&leaf)) if (__sev_cpuid_hv_msr(&leaf))
goto fail; goto fail;
cpuid_done: cpuid_done:
...@@ -848,14 +888,15 @@ static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt) ...@@ -848,14 +888,15 @@ static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
return ret; return ret;
} }
static int vc_handle_cpuid_snp(struct pt_regs *regs) static int vc_handle_cpuid_snp(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
{ {
struct pt_regs *regs = ctxt->regs;
struct cpuid_leaf leaf; struct cpuid_leaf leaf;
int ret; int ret;
leaf.fn = regs->ax; leaf.fn = regs->ax;
leaf.subfn = regs->cx; leaf.subfn = regs->cx;
ret = snp_cpuid(&leaf); ret = snp_cpuid(ghcb, ctxt, &leaf);
if (!ret) { if (!ret) {
regs->ax = leaf.eax; regs->ax = leaf.eax;
regs->bx = leaf.ebx; regs->bx = leaf.ebx;
...@@ -874,7 +915,7 @@ static enum es_result vc_handle_cpuid(struct ghcb *ghcb, ...@@ -874,7 +915,7 @@ static enum es_result vc_handle_cpuid(struct ghcb *ghcb,
enum es_result ret; enum es_result ret;
int snp_cpuid_ret; int snp_cpuid_ret;
snp_cpuid_ret = vc_handle_cpuid_snp(regs); snp_cpuid_ret = vc_handle_cpuid_snp(ghcb, ctxt);
if (!snp_cpuid_ret) if (!snp_cpuid_ret)
return ES_OK; return ES_OK;
if (snp_cpuid_ret != -EOPNOTSUPP) if (snp_cpuid_ret != -EOPNOTSUPP)
......
...@@ -868,8 +868,7 @@ void snp_set_memory_private(unsigned long vaddr, unsigned long npages) ...@@ -868,8 +868,7 @@ void snp_set_memory_private(unsigned long vaddr, unsigned long npages)
void snp_accept_memory(phys_addr_t start, phys_addr_t end) void snp_accept_memory(phys_addr_t start, phys_addr_t end)
{ {
unsigned long vaddr; unsigned long vaddr, npages;
unsigned int npages;
if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment