- Small cleanups and improvements
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEzv7L6UO9uDPlPSfHEsHwGGHeVUoFAmZCcL8ACgkQEsHwGGHe VUo1NxAAuKdh6dT2I2qMEsrYcG505DNI13AZ8Zp9w+3f7ehVzi5EAETx0c9JCh6i brTlkAerydTGIErCE/agNvbDHPxJDUjMPvOsUHCiuvcChbJSEsZ5KpmbHX2rLQCq znRS+51PmoRg9EmscqW898qi7jWklgy2ZaeFyZGNx7stlcjc/C4pgfMPt6UJqIiO WeqSTSGeAKq/wsSpx0Fm3Ize6HZGAGTlkHSKE1XllvuDigDhPnBa8O1g0iyoyFHl YHOMHSUZ5G/hqtOzCPMnAvLPEta8EcJZrhGYhQguDNk02a3LHfkitVPC2FeJk/Zy jp2KESkHjWiEvkw3myazpONYY8Z6Fw5GZWvR5EBBhgv285viNUQBRoch4xdKjHCb 230LVVvdzZ8iOUx0Im6f9Ec6oYB9hXxdFr7YnkPPBPf3VU22H3i1meE294pkZUbq 2wFAWlIi8CbbAPNEqmPjVEyxGqsc+ZJt7/yge3iiJqcQdubMVCX8drfAhcI84QjO mmcwcQ3BT3ugsKaKSQuUFUdqBrHKgcQ2aMOeyMUkBs1UANZlOBbRaTdTubPzL5cj G4pJcH/dRHSktWTn01SHDpxIhbSDdG7c4jHOzIio86vn0ahbrCSAzp6Y9nP4YkZm jdHZAI6yZSA3FF3vtBpkTatPOYRb9lgFMNDoxTVr62F7UfgkBS8= =Z3p4 -----END PGP SIGNATURE----- Merge tag 'x86_sev_for_v6.10_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull x86 SEV updates from Borislav Petkov: - Small cleanups and improvements * tag 'x86_sev_for_v6.10_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/sev: Make the VMPL0 checking more straight forward x86/sev: Rename snp_init() in boot/compressed/sev.c x86/sev: Shorten struct name snp_secrets_page_layout to snp_secrets_page
This commit is contained in:
commit
964bbdfdf0
@ -335,26 +335,6 @@ finish:
|
||||
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
|
||||
}
|
||||
|
||||
static void enforce_vmpl0(void)
|
||||
{
|
||||
u64 attrs;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* RMPADJUST modifies RMP permissions of a lesser-privileged (numerically
|
||||
* higher) privilege level. Here, clear the VMPL1 permission mask of the
|
||||
* GHCB page. If the guest is not running at VMPL0, this will fail.
|
||||
*
|
||||
* If the guest is running at VMPL0, it will succeed. Even if that operation
|
||||
* modifies permission bits, it is still ok to do so currently because Linux
|
||||
* SNP guests are supported only on VMPL0 so VMPL1 or higher permission masks
|
||||
* changing is a don't-care.
|
||||
*/
|
||||
attrs = 1;
|
||||
if (rmpadjust((unsigned long)&boot_ghcb_page, RMP_PG_SIZE_4K, attrs))
|
||||
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_NOT_VMPL0);
|
||||
}
|
||||
|
||||
/*
|
||||
* SNP_FEATURES_IMPL_REQ is the mask of SNP features that will need
|
||||
* guest side implementation for proper functioning of the guest. If any
|
||||
@ -413,6 +393,85 @@ void snp_check_features(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Search for Confidential Computing blob in the EFI config table. */
|
||||
static struct cc_blob_sev_info *find_cc_blob_efi(struct boot_params *bp)
|
||||
{
|
||||
unsigned long cfg_table_pa;
|
||||
unsigned int cfg_table_len;
|
||||
int ret;
|
||||
|
||||
ret = efi_get_conf_table(bp, &cfg_table_pa, &cfg_table_len);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
return (struct cc_blob_sev_info *)efi_find_vendor_table(bp, cfg_table_pa,
|
||||
cfg_table_len,
|
||||
EFI_CC_BLOB_GUID);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initial set up of SNP relies on information provided by the
|
||||
* Confidential Computing blob, which can be passed to the boot kernel
|
||||
* by firmware/bootloader in the following ways:
|
||||
*
|
||||
* - via an entry in the EFI config table
|
||||
* - via a setup_data structure, as defined by the Linux Boot Protocol
|
||||
*
|
||||
* Scan for the blob in that order.
|
||||
*/
|
||||
static struct cc_blob_sev_info *find_cc_blob(struct boot_params *bp)
|
||||
{
|
||||
struct cc_blob_sev_info *cc_info;
|
||||
|
||||
cc_info = find_cc_blob_efi(bp);
|
||||
if (cc_info)
|
||||
goto found_cc_info;
|
||||
|
||||
cc_info = find_cc_blob_setup_data(bp);
|
||||
if (!cc_info)
|
||||
return NULL;
|
||||
|
||||
found_cc_info:
|
||||
if (cc_info->magic != CC_BLOB_SEV_HDR_MAGIC)
|
||||
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
|
||||
|
||||
return cc_info;
|
||||
}
|
||||
|
||||
/*
|
||||
* Indicate SNP based on presence of SNP-specific CC blob. Subsequent checks
|
||||
* will verify the SNP CPUID/MSR bits.
|
||||
*/
|
||||
static bool early_snp_init(struct boot_params *bp)
|
||||
{
|
||||
struct cc_blob_sev_info *cc_info;
|
||||
|
||||
if (!bp)
|
||||
return false;
|
||||
|
||||
cc_info = find_cc_blob(bp);
|
||||
if (!cc_info)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If a SNP-specific Confidential Computing blob is present, then
|
||||
* firmware/bootloader have indicated SNP support. Verifying this
|
||||
* involves CPUID checks which will be more reliable if the SNP
|
||||
* CPUID table is used. See comments over snp_setup_cpuid_table() for
|
||||
* more details.
|
||||
*/
|
||||
setup_cpuid_table(cc_info);
|
||||
|
||||
/*
|
||||
* Pass run-time kernel a pointer to CC info via boot_params so EFI
|
||||
* config table doesn't need to be searched again during early startup
|
||||
* phase.
|
||||
*/
|
||||
bp->cc_blob_address = (u32)(unsigned long)cc_info;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* sev_check_cpu_support - Check for SEV support in the CPU capabilities
|
||||
*
|
||||
@ -463,7 +522,7 @@ void sev_enable(struct boot_params *bp)
|
||||
bp->cc_blob_address = 0;
|
||||
|
||||
/*
|
||||
* Do an initial SEV capability check before snp_init() which
|
||||
* Do an initial SEV capability check before early_snp_init() which
|
||||
* loads the CPUID page and the same checks afterwards are done
|
||||
* without the hypervisor and are trustworthy.
|
||||
*
|
||||
@ -478,7 +537,7 @@ void sev_enable(struct boot_params *bp)
|
||||
* Setup/preliminary detection of SNP. This will be sanity-checked
|
||||
* against CPUID/MSR values later.
|
||||
*/
|
||||
snp = snp_init(bp);
|
||||
snp = early_snp_init(bp);
|
||||
|
||||
/* Now repeat the checks with the SNP CPUID table. */
|
||||
|
||||
@ -509,7 +568,20 @@ void sev_enable(struct boot_params *bp)
|
||||
if (!(get_hv_features() & GHCB_HV_FT_SNP))
|
||||
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
|
||||
|
||||
enforce_vmpl0();
|
||||
/*
|
||||
* Enforce running at VMPL0.
|
||||
*
|
||||
* RMPADJUST modifies RMP permissions of a lesser-privileged (numerically
|
||||
* higher) privilege level. Here, clear the VMPL1 permission mask of the
|
||||
* GHCB page. If the guest is not running at VMPL0, this will fail.
|
||||
*
|
||||
* If the guest is running at VMPL0, it will succeed. Even if that operation
|
||||
* modifies permission bits, it is still ok to do so currently because Linux
|
||||
* SNP guests running at VMPL0 only run at VMPL0, so VMPL1 or higher
|
||||
* permission mask changes are a don't-care.
|
||||
*/
|
||||
if (rmpadjust((unsigned long)&boot_ghcb_page, RMP_PG_SIZE_4K, 1))
|
||||
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_NOT_VMPL0);
|
||||
}
|
||||
|
||||
if (snp && !(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
|
||||
@ -535,85 +607,6 @@ u64 sev_get_status(void)
|
||||
return m.q;
|
||||
}
|
||||
|
||||
/* Search for Confidential Computing blob in the EFI config table. */
|
||||
static struct cc_blob_sev_info *find_cc_blob_efi(struct boot_params *bp)
|
||||
{
|
||||
unsigned long cfg_table_pa;
|
||||
unsigned int cfg_table_len;
|
||||
int ret;
|
||||
|
||||
ret = efi_get_conf_table(bp, &cfg_table_pa, &cfg_table_len);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
return (struct cc_blob_sev_info *)efi_find_vendor_table(bp, cfg_table_pa,
|
||||
cfg_table_len,
|
||||
EFI_CC_BLOB_GUID);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initial set up of SNP relies on information provided by the
|
||||
* Confidential Computing blob, which can be passed to the boot kernel
|
||||
* by firmware/bootloader in the following ways:
|
||||
*
|
||||
* - via an entry in the EFI config table
|
||||
* - via a setup_data structure, as defined by the Linux Boot Protocol
|
||||
*
|
||||
* Scan for the blob in that order.
|
||||
*/
|
||||
static struct cc_blob_sev_info *find_cc_blob(struct boot_params *bp)
|
||||
{
|
||||
struct cc_blob_sev_info *cc_info;
|
||||
|
||||
cc_info = find_cc_blob_efi(bp);
|
||||
if (cc_info)
|
||||
goto found_cc_info;
|
||||
|
||||
cc_info = find_cc_blob_setup_data(bp);
|
||||
if (!cc_info)
|
||||
return NULL;
|
||||
|
||||
found_cc_info:
|
||||
if (cc_info->magic != CC_BLOB_SEV_HDR_MAGIC)
|
||||
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
|
||||
|
||||
return cc_info;
|
||||
}
|
||||
|
||||
/*
|
||||
* Indicate SNP based on presence of SNP-specific CC blob. Subsequent checks
|
||||
* will verify the SNP CPUID/MSR bits.
|
||||
*/
|
||||
bool snp_init(struct boot_params *bp)
|
||||
{
|
||||
struct cc_blob_sev_info *cc_info;
|
||||
|
||||
if (!bp)
|
||||
return false;
|
||||
|
||||
cc_info = find_cc_blob(bp);
|
||||
if (!cc_info)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If a SNP-specific Confidential Computing blob is present, then
|
||||
* firmware/bootloader have indicated SNP support. Verifying this
|
||||
* involves CPUID checks which will be more reliable if the SNP
|
||||
* CPUID table is used. See comments over snp_setup_cpuid_table() for
|
||||
* more details.
|
||||
*/
|
||||
setup_cpuid_table(cc_info);
|
||||
|
||||
/*
|
||||
* Pass run-time kernel a pointer to CC info via boot_params so EFI
|
||||
* config table doesn't need to be searched again during early startup
|
||||
* phase.
|
||||
*/
|
||||
bp->cc_blob_address = (u32)(unsigned long)cc_info;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void sev_prep_identity_maps(unsigned long top_level_pgt)
|
||||
{
|
||||
/*
|
||||
|
@ -140,7 +140,7 @@ struct secrets_os_area {
|
||||
#define VMPCK_KEY_LEN 32
|
||||
|
||||
/* See the SNP spec version 0.9 for secrets page format */
|
||||
struct snp_secrets_page_layout {
|
||||
struct snp_secrets_page {
|
||||
u32 version;
|
||||
u32 imien : 1,
|
||||
rsvd1 : 31;
|
||||
|
@ -648,7 +648,7 @@ static u64 __init get_secrets_page(void)
|
||||
|
||||
static u64 __init get_snp_jump_table_addr(void)
|
||||
{
|
||||
struct snp_secrets_page_layout *layout;
|
||||
struct snp_secrets_page *secrets;
|
||||
void __iomem *mem;
|
||||
u64 pa, addr;
|
||||
|
||||
@ -662,9 +662,9 @@ static u64 __init get_snp_jump_table_addr(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
layout = (__force struct snp_secrets_page_layout *)mem;
|
||||
secrets = (__force struct snp_secrets_page *)mem;
|
||||
|
||||
addr = layout->os_area.ap_jump_table_pa;
|
||||
addr = secrets->os_area.ap_jump_table_pa;
|
||||
iounmap(mem);
|
||||
|
||||
return addr;
|
||||
|
@ -59,7 +59,7 @@ struct snp_guest_dev {
|
||||
*/
|
||||
struct snp_guest_msg secret_request, secret_response;
|
||||
|
||||
struct snp_secrets_page_layout *layout;
|
||||
struct snp_secrets_page *secrets;
|
||||
struct snp_req_data input;
|
||||
union {
|
||||
struct snp_report_req report;
|
||||
@ -743,26 +743,26 @@ static const struct file_operations snp_guest_fops = {
|
||||
.unlocked_ioctl = snp_guest_ioctl,
|
||||
};
|
||||
|
||||
static u8 *get_vmpck(int id, struct snp_secrets_page_layout *layout, u32 **seqno)
|
||||
static u8 *get_vmpck(int id, struct snp_secrets_page *secrets, u32 **seqno)
|
||||
{
|
||||
u8 *key = NULL;
|
||||
|
||||
switch (id) {
|
||||
case 0:
|
||||
*seqno = &layout->os_area.msg_seqno_0;
|
||||
key = layout->vmpck0;
|
||||
*seqno = &secrets->os_area.msg_seqno_0;
|
||||
key = secrets->vmpck0;
|
||||
break;
|
||||
case 1:
|
||||
*seqno = &layout->os_area.msg_seqno_1;
|
||||
key = layout->vmpck1;
|
||||
*seqno = &secrets->os_area.msg_seqno_1;
|
||||
key = secrets->vmpck1;
|
||||
break;
|
||||
case 2:
|
||||
*seqno = &layout->os_area.msg_seqno_2;
|
||||
key = layout->vmpck2;
|
||||
*seqno = &secrets->os_area.msg_seqno_2;
|
||||
key = secrets->vmpck2;
|
||||
break;
|
||||
case 3:
|
||||
*seqno = &layout->os_area.msg_seqno_3;
|
||||
key = layout->vmpck3;
|
||||
*seqno = &secrets->os_area.msg_seqno_3;
|
||||
key = secrets->vmpck3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -897,8 +897,8 @@ static void unregister_sev_tsm(void *data)
|
||||
|
||||
static int __init sev_guest_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snp_secrets_page_layout *layout;
|
||||
struct sev_guest_platform_data *data;
|
||||
struct snp_secrets_page *secrets;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct snp_guest_dev *snp_dev;
|
||||
struct miscdevice *misc;
|
||||
@ -916,7 +916,7 @@ static int __init sev_guest_probe(struct platform_device *pdev)
|
||||
if (!mapping)
|
||||
return -ENODEV;
|
||||
|
||||
layout = (__force void *)mapping;
|
||||
secrets = (__force void *)mapping;
|
||||
|
||||
ret = -ENOMEM;
|
||||
snp_dev = devm_kzalloc(&pdev->dev, sizeof(struct snp_guest_dev), GFP_KERNEL);
|
||||
@ -924,7 +924,7 @@ static int __init sev_guest_probe(struct platform_device *pdev)
|
||||
goto e_unmap;
|
||||
|
||||
ret = -EINVAL;
|
||||
snp_dev->vmpck = get_vmpck(vmpck_id, layout, &snp_dev->os_area_msg_seqno);
|
||||
snp_dev->vmpck = get_vmpck(vmpck_id, secrets, &snp_dev->os_area_msg_seqno);
|
||||
if (!snp_dev->vmpck) {
|
||||
dev_err(dev, "invalid vmpck id %d\n", vmpck_id);
|
||||
goto e_unmap;
|
||||
@ -938,7 +938,7 @@ static int __init sev_guest_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, snp_dev);
|
||||
snp_dev->dev = dev;
|
||||
snp_dev->layout = layout;
|
||||
snp_dev->secrets = secrets;
|
||||
|
||||
/* Allocate the shared page used for the request and response message. */
|
||||
snp_dev->request = alloc_shared_pages(dev, sizeof(struct snp_guest_msg));
|
||||
|
Loading…
Reference in New Issue
Block a user