@@ -256,7 +256,7 @@ static int __sev_cpuid_hv(u32 fn, int reg_idx, u32 *reg)
256
256
return 0 ;
257
257
}
258
258
259
- static int sev_cpuid_hv (struct cpuid_leaf * leaf )
259
+ static int __sev_cpuid_hv_msr (struct cpuid_leaf * leaf )
260
260
{
261
261
int ret ;
262
262
@@ -279,6 +279,45 @@ static int sev_cpuid_hv(struct cpuid_leaf *leaf)
279
279
return ret ;
280
280
}
281
281
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
+
282
321
/*
283
322
* This may be called early while still running on the initial identity
284
323
* mapping. Use RIP-relative addressing to obtain the correct address
@@ -388,19 +427,20 @@ snp_cpuid_get_validated_func(struct cpuid_leaf *leaf)
388
427
return false;
389
428
}
390
429
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 )
392
431
{
393
- if (sev_cpuid_hv (leaf ))
432
+ if (sev_cpuid_hv (ghcb , ctxt , leaf ))
394
433
sev_es_terminate (SEV_TERM_SET_LINUX , GHCB_TERM_CPUID_HV );
395
434
}
396
435
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 )
398
438
{
399
439
struct cpuid_leaf leaf_hv = * leaf ;
400
440
401
441
switch (leaf -> fn ) {
402
442
case 0x1 :
403
- snp_cpuid_hv (& leaf_hv );
443
+ snp_cpuid_hv (ghcb , ctxt , & leaf_hv );
404
444
405
445
/* initial APIC ID */
406
446
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
459
break ;
420
460
case 0xB :
421
461
leaf_hv .subfn = 0 ;
422
- snp_cpuid_hv (& leaf_hv );
462
+ snp_cpuid_hv (ghcb , ctxt , & leaf_hv );
423
463
424
464
/* extended APIC ID */
425
465
leaf -> edx = leaf_hv .edx ;
@@ -467,7 +507,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
467
507
}
468
508
break ;
469
509
case 0x8000001E :
470
- snp_cpuid_hv (& leaf_hv );
510
+ snp_cpuid_hv (ghcb , ctxt , & leaf_hv );
471
511
472
512
/* extended APIC ID */
473
513
leaf -> eax = leaf_hv .eax ;
@@ -488,7 +528,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
488
528
* Returns -EOPNOTSUPP if feature not enabled. Any other non-zero return value
489
529
* should be treated as fatal by caller.
490
530
*/
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 )
492
532
{
493
533
const struct snp_cpuid_table * cpuid_table = snp_cpuid_get_table ();
494
534
@@ -522,7 +562,7 @@ static int snp_cpuid(struct cpuid_leaf *leaf)
522
562
return 0 ;
523
563
}
524
564
525
- return snp_cpuid_postprocess (leaf );
565
+ return snp_cpuid_postprocess (ghcb , ctxt , leaf );
526
566
}
527
567
528
568
/*
@@ -544,14 +584,14 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)
544
584
leaf .fn = fn ;
545
585
leaf .subfn = subfn ;
546
586
547
- ret = snp_cpuid (& leaf );
587
+ ret = snp_cpuid (NULL , NULL , & leaf );
548
588
if (!ret )
549
589
goto cpuid_done ;
550
590
551
591
if (ret != - EOPNOTSUPP )
552
592
goto fail ;
553
593
554
- if (sev_cpuid_hv (& leaf ))
594
+ if (__sev_cpuid_hv_msr (& leaf ))
555
595
goto fail ;
556
596
557
597
cpuid_done :
@@ -848,14 +888,15 @@ static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
848
888
return ret ;
849
889
}
850
890
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 )
852
892
{
893
+ struct pt_regs * regs = ctxt -> regs ;
853
894
struct cpuid_leaf leaf ;
854
895
int ret ;
855
896
856
897
leaf .fn = regs -> ax ;
857
898
leaf .subfn = regs -> cx ;
858
- ret = snp_cpuid (& leaf );
899
+ ret = snp_cpuid (ghcb , ctxt , & leaf );
859
900
if (!ret ) {
860
901
regs -> ax = leaf .eax ;
861
902
regs -> bx = leaf .ebx ;
@@ -874,7 +915,7 @@ static enum es_result vc_handle_cpuid(struct ghcb *ghcb,
874
915
enum es_result ret ;
875
916
int snp_cpuid_ret ;
876
917
877
- snp_cpuid_ret = vc_handle_cpuid_snp (regs );
918
+ snp_cpuid_ret = vc_handle_cpuid_snp (ghcb , ctxt );
878
919
if (!snp_cpuid_ret )
879
920
return ES_OK ;
880
921
if (snp_cpuid_ret != - EOPNOTSUPP )
0 commit comments