@@ -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
557597cpuid_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 )
0 commit comments