Misc fixes:

- Fix SEV-SNP guest crashes that may happen on NMIs
 
  - Fix a potential SEV platform memory setup overflow
 
 Signed-off-by: Ingo Molnar <mingo@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmUieNgRHG1pbmdvQGtl
 cm5lbC5vcmcACgkQEnMQ0APhK1jDAQ//YtM2ZOS/vdgBM0CccGvyDjgkKbl8Agrc
 IBGN9amWupkJHQR8DPasnQGQpJ1xoppnM7mDToJQjmr7kfKlna6Wa6BFeGB50oqI
 RMzKc+RVr3614LBULrVFy6gkS+1pNkyGdw1tGybjwlTtzxefwfXrswRewOCWZ0K8
 jzkEjhSSgNB6XQ8lal1Iv6fNqVb/8QtfU27Juv6aZzsMllBvZZU2VQbrrKYLQbF3
 TEkL62pi0qV8PtiqkTLqAwbBBbBfEi0vKY5QVedcB6c+ge/onMptI0ai3/MNxP4e
 Lrb7JrsbpRJ9Py3rGKEx33xSh2LBBVG3V8I6VmIHq4ZH+8Lret8K/NgWzeKm8eP/
 GmvpIhR88ehIKNJe9a7qBMpDJsP0jI7c+lD1j4gZaBv7IrHDqBS6rx9U6imwGzzm
 lHrxDk/jCdLGYoIL4FckgluTmEnG8Y0XD8kG4BmR7sKFwuVSGa6OQlkt7Yo/JJNI
 qP8rgZvwLiQmwNxEG7X1QUWXnsnR661AxHxpBjjNV1kzLIzPFMRlB9QGBGfP5Z9M
 zw5Ijl3R5gbEElVd7b6CXzYJYHEoakj10EUYwJJ/TYhN26jbmPqWc7qGWo4tRFoX
 veaj1CJ0d8L9N1qJ85gJLY542zRFwHD8O8x0T4IAJrh6ZIVxZRQYPIWqRC36A7FA
 W43aGtFoyRg=
 =1LPl
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2023-10-08 09:27:20 -07:00
commit 7e20d344b5
2 changed files with 56 additions and 16 deletions

View File

@ -256,7 +256,7 @@ static int __sev_cpuid_hv(u32 fn, int reg_idx, u32 *reg)
return 0;
}
static int sev_cpuid_hv(struct cpuid_leaf *leaf)
static int __sev_cpuid_hv_msr(struct cpuid_leaf *leaf)
{
int ret;
@ -279,6 +279,45 @@ static int sev_cpuid_hv(struct cpuid_leaf *leaf)
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
* mapping. Use RIP-relative addressing to obtain the correct address
@ -388,19 +427,20 @@ snp_cpuid_get_validated_func(struct cpuid_leaf *leaf)
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);
}
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;
switch (leaf->fn) {
case 0x1:
snp_cpuid_hv(&leaf_hv);
snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
/* initial APIC ID */
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)
break;
case 0xB:
leaf_hv.subfn = 0;
snp_cpuid_hv(&leaf_hv);
snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
/* extended APIC ID */
leaf->edx = leaf_hv.edx;
@ -467,7 +507,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
}
break;
case 0x8000001E:
snp_cpuid_hv(&leaf_hv);
snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
/* extended APIC ID */
leaf->eax = leaf_hv.eax;
@ -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
* 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();
@ -522,7 +562,7 @@ static int snp_cpuid(struct cpuid_leaf *leaf)
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)
leaf.fn = fn;
leaf.subfn = subfn;
ret = snp_cpuid(&leaf);
ret = snp_cpuid(NULL, NULL, &leaf);
if (!ret)
goto cpuid_done;
if (ret != -EOPNOTSUPP)
goto fail;
if (sev_cpuid_hv(&leaf))
if (__sev_cpuid_hv_msr(&leaf))
goto fail;
cpuid_done:
@ -848,14 +888,15 @@ static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
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;
int ret;
leaf.fn = regs->ax;
leaf.subfn = regs->cx;
ret = snp_cpuid(&leaf);
ret = snp_cpuid(ghcb, ctxt, &leaf);
if (!ret) {
regs->ax = leaf.eax;
regs->bx = leaf.ebx;
@ -874,7 +915,7 @@ static enum es_result vc_handle_cpuid(struct ghcb *ghcb,
enum es_result 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)
return ES_OK;
if (snp_cpuid_ret != -EOPNOTSUPP)

View File

@ -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)
{
unsigned long vaddr;
unsigned int npages;
unsigned long vaddr, npages;
if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
return;