@@ -367,20 +367,25 @@ static void enforce_vmpl0(void)
367
367
*/
368
368
#define SNP_FEATURES_PRESENT (0)
369
369
370
+ u64 snp_get_unsupported_features (u64 status )
371
+ {
372
+ if (!(status & MSR_AMD64_SEV_SNP_ENABLED ))
373
+ return 0 ;
374
+
375
+ return status & SNP_FEATURES_IMPL_REQ & ~SNP_FEATURES_PRESENT ;
376
+ }
377
+
370
378
void snp_check_features (void )
371
379
{
372
380
u64 unsupported ;
373
381
374
- if (!(sev_status & MSR_AMD64_SEV_SNP_ENABLED ))
375
- return ;
376
-
377
382
/*
378
383
* Terminate the boot if hypervisor has enabled any feature lacking
379
384
* guest side implementation. Pass on the unsupported features mask through
380
385
* EXIT_INFO_2 of the GHCB protocol so that those features can be reported
381
386
* as part of the guest boot failure.
382
387
*/
383
- unsupported = sev_status & SNP_FEATURES_IMPL_REQ & ~ SNP_FEATURES_PRESENT ;
388
+ unsupported = snp_get_unsupported_features ( sev_status ) ;
384
389
if (unsupported ) {
385
390
if (ghcb_version < 2 || (!boot_ghcb && !early_setup_ghcb ()))
386
391
sev_es_terminate (SEV_TERM_SET_GEN , GHCB_SNP_UNSUPPORTED );
@@ -390,35 +395,22 @@ void snp_check_features(void)
390
395
}
391
396
}
392
397
393
- void sev_enable (struct boot_params * bp )
398
+ /*
399
+ * sev_check_cpu_support - Check for SEV support in the CPU capabilities
400
+ *
401
+ * Returns < 0 if SEV is not supported, otherwise the position of the
402
+ * encryption bit in the page table descriptors.
403
+ */
404
+ static int sev_check_cpu_support (void )
394
405
{
395
406
unsigned int eax , ebx , ecx , edx ;
396
- struct msr m ;
397
- bool snp ;
398
-
399
- /*
400
- * bp->cc_blob_address should only be set by boot/compressed kernel.
401
- * Initialize it to 0 to ensure that uninitialized values from
402
- * buggy bootloaders aren't propagated.
403
- */
404
- if (bp )
405
- bp -> cc_blob_address = 0 ;
406
-
407
- /*
408
- * Do an initial SEV capability check before snp_init() which
409
- * loads the CPUID page and the same checks afterwards are done
410
- * without the hypervisor and are trustworthy.
411
- *
412
- * If the HV fakes SEV support, the guest will crash'n'burn
413
- * which is good enough.
414
- */
415
407
416
408
/* Check for the SME/SEV support leaf */
417
409
eax = 0x80000000 ;
418
410
ecx = 0 ;
419
411
native_cpuid (& eax , & ebx , & ecx , & edx );
420
412
if (eax < 0x8000001f )
421
- return ;
413
+ return - ENODEV ;
422
414
423
415
/*
424
416
* Check for the SME/SEV feature:
@@ -433,6 +425,35 @@ void sev_enable(struct boot_params *bp)
433
425
native_cpuid (& eax , & ebx , & ecx , & edx );
434
426
/* Check whether SEV is supported */
435
427
if (!(eax & BIT (1 )))
428
+ return - ENODEV ;
429
+
430
+ return ebx & 0x3f ;
431
+ }
432
+
433
+ void sev_enable (struct boot_params * bp )
434
+ {
435
+ struct msr m ;
436
+ int bitpos ;
437
+ bool snp ;
438
+
439
+ /*
440
+ * bp->cc_blob_address should only be set by boot/compressed kernel.
441
+ * Initialize it to 0 to ensure that uninitialized values from
442
+ * buggy bootloaders aren't propagated.
443
+ */
444
+ if (bp )
445
+ bp -> cc_blob_address = 0 ;
446
+
447
+ /*
448
+ * Do an initial SEV capability check before snp_init() which
449
+ * loads the CPUID page and the same checks afterwards are done
450
+ * without the hypervisor and are trustworthy.
451
+ *
452
+ * If the HV fakes SEV support, the guest will crash'n'burn
453
+ * which is good enough.
454
+ */
455
+
456
+ if (sev_check_cpu_support () < 0 )
436
457
return ;
437
458
438
459
/*
@@ -443,26 +464,8 @@ void sev_enable(struct boot_params *bp)
443
464
444
465
/* Now repeat the checks with the SNP CPUID table. */
445
466
446
- /* Recheck the SME/SEV support leaf */
447
- eax = 0x80000000 ;
448
- ecx = 0 ;
449
- native_cpuid (& eax , & ebx , & ecx , & edx );
450
- if (eax < 0x8000001f )
451
- return ;
452
-
453
- /*
454
- * Recheck for the SME/SEV feature:
455
- * CPUID Fn8000_001F[EAX]
456
- * - Bit 0 - Secure Memory Encryption support
457
- * - Bit 1 - Secure Encrypted Virtualization support
458
- * CPUID Fn8000_001F[EBX]
459
- * - Bits 5:0 - Pagetable bit position used to indicate encryption
460
- */
461
- eax = 0x8000001f ;
462
- ecx = 0 ;
463
- native_cpuid (& eax , & ebx , & ecx , & edx );
464
- /* Check whether SEV is supported */
465
- if (!(eax & BIT (1 ))) {
467
+ bitpos = sev_check_cpu_support ();
468
+ if (bitpos < 0 ) {
466
469
if (snp )
467
470
error ("SEV-SNP support indicated by CC blob, but not CPUID." );
468
471
return ;
@@ -494,7 +497,24 @@ void sev_enable(struct boot_params *bp)
494
497
if (snp && !(sev_status & MSR_AMD64_SEV_SNP_ENABLED ))
495
498
error ("SEV-SNP supported indicated by CC blob, but not SEV status MSR." );
496
499
497
- sme_me_mask = BIT_ULL (ebx & 0x3f );
500
+ sme_me_mask = BIT_ULL (bitpos );
501
+ }
502
+
503
+ /*
504
+ * sev_get_status - Retrieve the SEV status mask
505
+ *
506
+ * Returns 0 if the CPU is not SEV capable, otherwise the value of the
507
+ * AMD64_SEV MSR.
508
+ */
509
+ u64 sev_get_status (void )
510
+ {
511
+ struct msr m ;
512
+
513
+ if (sev_check_cpu_support () < 0 )
514
+ return 0 ;
515
+
516
+ boot_rdmsr (MSR_AMD64_SEV , & m );
517
+ return m .q ;
498
518
}
499
519
500
520
/* Search for Confidential Computing blob in the EFI config table. */
0 commit comments