@@ -335,26 +335,6 @@ void do_boot_stage2_vc(struct pt_regs *regs, unsigned long exit_code)
335335 sev_es_terminate (SEV_TERM_SET_GEN , GHCB_SEV_ES_GEN_REQ );
336336}
337337
338- static void enforce_vmpl0 (void )
339- {
340- u64 attrs ;
341- int err ;
342-
343- /*
344- * RMPADJUST modifies RMP permissions of a lesser-privileged (numerically
345- * higher) privilege level. Here, clear the VMPL1 permission mask of the
346- * GHCB page. If the guest is not running at VMPL0, this will fail.
347- *
348- * If the guest is running at VMPL0, it will succeed. Even if that operation
349- * modifies permission bits, it is still ok to do so currently because Linux
350- * SNP guests are supported only on VMPL0 so VMPL1 or higher permission masks
351- * changing is a don't-care.
352- */
353- attrs = 1 ;
354- if (rmpadjust ((unsigned long )& boot_ghcb_page , RMP_PG_SIZE_4K , attrs ))
355- sev_es_terminate (SEV_TERM_SET_LINUX , GHCB_TERM_NOT_VMPL0 );
356- }
357-
358338/*
359339 * SNP_FEATURES_IMPL_REQ is the mask of SNP features that will need
360340 * guest side implementation for proper functioning of the guest. If any
@@ -413,6 +393,85 @@ void snp_check_features(void)
413393 }
414394}
415395
396+ /* Search for Confidential Computing blob in the EFI config table. */
397+ static struct cc_blob_sev_info * find_cc_blob_efi (struct boot_params * bp )
398+ {
399+ unsigned long cfg_table_pa ;
400+ unsigned int cfg_table_len ;
401+ int ret ;
402+
403+ ret = efi_get_conf_table (bp , & cfg_table_pa , & cfg_table_len );
404+ if (ret )
405+ return NULL ;
406+
407+ return (struct cc_blob_sev_info * )efi_find_vendor_table (bp , cfg_table_pa ,
408+ cfg_table_len ,
409+ EFI_CC_BLOB_GUID );
410+ }
411+
412+ /*
413+ * Initial set up of SNP relies on information provided by the
414+ * Confidential Computing blob, which can be passed to the boot kernel
415+ * by firmware/bootloader in the following ways:
416+ *
417+ * - via an entry in the EFI config table
418+ * - via a setup_data structure, as defined by the Linux Boot Protocol
419+ *
420+ * Scan for the blob in that order.
421+ */
422+ static struct cc_blob_sev_info * find_cc_blob (struct boot_params * bp )
423+ {
424+ struct cc_blob_sev_info * cc_info ;
425+
426+ cc_info = find_cc_blob_efi (bp );
427+ if (cc_info )
428+ goto found_cc_info ;
429+
430+ cc_info = find_cc_blob_setup_data (bp );
431+ if (!cc_info )
432+ return NULL ;
433+
434+ found_cc_info :
435+ if (cc_info -> magic != CC_BLOB_SEV_HDR_MAGIC )
436+ sev_es_terminate (SEV_TERM_SET_GEN , GHCB_SNP_UNSUPPORTED );
437+
438+ return cc_info ;
439+ }
440+
441+ /*
442+ * Indicate SNP based on presence of SNP-specific CC blob. Subsequent checks
443+ * will verify the SNP CPUID/MSR bits.
444+ */
445+ static bool early_snp_init (struct boot_params * bp )
446+ {
447+ struct cc_blob_sev_info * cc_info ;
448+
449+ if (!bp )
450+ return false;
451+
452+ cc_info = find_cc_blob (bp );
453+ if (!cc_info )
454+ return false;
455+
456+ /*
457+ * If a SNP-specific Confidential Computing blob is present, then
458+ * firmware/bootloader have indicated SNP support. Verifying this
459+ * involves CPUID checks which will be more reliable if the SNP
460+ * CPUID table is used. See comments over snp_setup_cpuid_table() for
461+ * more details.
462+ */
463+ setup_cpuid_table (cc_info );
464+
465+ /*
466+ * Pass run-time kernel a pointer to CC info via boot_params so EFI
467+ * config table doesn't need to be searched again during early startup
468+ * phase.
469+ */
470+ bp -> cc_blob_address = (u32 )(unsigned long )cc_info ;
471+
472+ return true;
473+ }
474+
416475/*
417476 * sev_check_cpu_support - Check for SEV support in the CPU capabilities
418477 *
@@ -463,7 +522,7 @@ void sev_enable(struct boot_params *bp)
463522 bp -> cc_blob_address = 0 ;
464523
465524 /*
466- * Do an initial SEV capability check before snp_init () which
525+ * Do an initial SEV capability check before early_snp_init () which
467526 * loads the CPUID page and the same checks afterwards are done
468527 * without the hypervisor and are trustworthy.
469528 *
@@ -478,7 +537,7 @@ void sev_enable(struct boot_params *bp)
478537 * Setup/preliminary detection of SNP. This will be sanity-checked
479538 * against CPUID/MSR values later.
480539 */
481- snp = snp_init (bp );
540+ snp = early_snp_init (bp );
482541
483542 /* Now repeat the checks with the SNP CPUID table. */
484543
@@ -509,7 +568,20 @@ void sev_enable(struct boot_params *bp)
509568 if (!(get_hv_features () & GHCB_HV_FT_SNP ))
510569 sev_es_terminate (SEV_TERM_SET_GEN , GHCB_SNP_UNSUPPORTED );
511570
512- enforce_vmpl0 ();
571+ /*
572+ * Enforce running at VMPL0.
573+ *
574+ * RMPADJUST modifies RMP permissions of a lesser-privileged (numerically
575+ * higher) privilege level. Here, clear the VMPL1 permission mask of the
576+ * GHCB page. If the guest is not running at VMPL0, this will fail.
577+ *
578+ * If the guest is running at VMPL0, it will succeed. Even if that operation
579+ * modifies permission bits, it is still ok to do so currently because Linux
580+ * SNP guests running at VMPL0 only run at VMPL0, so VMPL1 or higher
581+ * permission mask changes are a don't-care.
582+ */
583+ if (rmpadjust ((unsigned long )& boot_ghcb_page , RMP_PG_SIZE_4K , 1 ))
584+ sev_es_terminate (SEV_TERM_SET_LINUX , GHCB_TERM_NOT_VMPL0 );
513585 }
514586
515587 if (snp && !(sev_status & MSR_AMD64_SEV_SNP_ENABLED ))
@@ -535,85 +607,6 @@ u64 sev_get_status(void)
535607 return m .q ;
536608}
537609
538- /* Search for Confidential Computing blob in the EFI config table. */
539- static struct cc_blob_sev_info * find_cc_blob_efi (struct boot_params * bp )
540- {
541- unsigned long cfg_table_pa ;
542- unsigned int cfg_table_len ;
543- int ret ;
544-
545- ret = efi_get_conf_table (bp , & cfg_table_pa , & cfg_table_len );
546- if (ret )
547- return NULL ;
548-
549- return (struct cc_blob_sev_info * )efi_find_vendor_table (bp , cfg_table_pa ,
550- cfg_table_len ,
551- EFI_CC_BLOB_GUID );
552- }
553-
554- /*
555- * Initial set up of SNP relies on information provided by the
556- * Confidential Computing blob, which can be passed to the boot kernel
557- * by firmware/bootloader in the following ways:
558- *
559- * - via an entry in the EFI config table
560- * - via a setup_data structure, as defined by the Linux Boot Protocol
561- *
562- * Scan for the blob in that order.
563- */
564- static struct cc_blob_sev_info * find_cc_blob (struct boot_params * bp )
565- {
566- struct cc_blob_sev_info * cc_info ;
567-
568- cc_info = find_cc_blob_efi (bp );
569- if (cc_info )
570- goto found_cc_info ;
571-
572- cc_info = find_cc_blob_setup_data (bp );
573- if (!cc_info )
574- return NULL ;
575-
576- found_cc_info :
577- if (cc_info -> magic != CC_BLOB_SEV_HDR_MAGIC )
578- sev_es_terminate (SEV_TERM_SET_GEN , GHCB_SNP_UNSUPPORTED );
579-
580- return cc_info ;
581- }
582-
583- /*
584- * Indicate SNP based on presence of SNP-specific CC blob. Subsequent checks
585- * will verify the SNP CPUID/MSR bits.
586- */
587- bool snp_init (struct boot_params * bp )
588- {
589- struct cc_blob_sev_info * cc_info ;
590-
591- if (!bp )
592- return false;
593-
594- cc_info = find_cc_blob (bp );
595- if (!cc_info )
596- return false;
597-
598- /*
599- * If a SNP-specific Confidential Computing blob is present, then
600- * firmware/bootloader have indicated SNP support. Verifying this
601- * involves CPUID checks which will be more reliable if the SNP
602- * CPUID table is used. See comments over snp_setup_cpuid_table() for
603- * more details.
604- */
605- setup_cpuid_table (cc_info );
606-
607- /*
608- * Pass run-time kernel a pointer to CC info via boot_params so EFI
609- * config table doesn't need to be searched again during early startup
610- * phase.
611- */
612- bp -> cc_blob_address = (u32 )(unsigned long )cc_info ;
613-
614- return true;
615- }
616-
617610void sev_prep_identity_maps (unsigned long top_level_pgt )
618611{
619612 /*
0 commit comments