From: "Tycho Andersen (AMD)" From the PLATYPUS [1] attack paper: We exploit unprivileged access to the Intel Running Average Power Limit (RAPL) interface that exposes values directly correlated with power consumption, forming a low-resolution side channel. The SEV firmware offers a mechanism to freeze RAPL counters across all cores during SNP initialization via the RAPL_DIS bit in SNP_INIT_EX. The counters remain frozen while SNP is initialized, and resume after an SNP shutdown. The SEV firmware also has a RAPL_DIS policy bit, allowing guests to enforce that RAPL is disabled on a system before running. Since the kernel had no way to set the RAPL_DIS bit during SNP init, trying to set the policy bit would always result in a failed launch. Allow setting the RAPL_DIS bit during SNP_INIT_EX via struct sev_platform_init_args. If the hardware does not support RAPL_DIS, set the rapl_disable parameter to false so that consumers can detect when it was not actually initialized. [1]: https://platypusattack.com/platypus.pdf Signed-off-by: Tycho Andersen (AMD) --- drivers/crypto/ccp/sev-dev.c | 14 +++++++++++++- include/linux/psp-sev.h | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index bf54a3fadb28..6223d63e676e 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -1365,8 +1365,11 @@ static int __sev_snp_init_locked(struct sev_platform_init_args *args) sev = psp->sev_data; - if (sev->snp_initialized) + if (sev->snp_initialized) { + if (args->rapl_disable && !sev->snp_plat_status.rapl_dis) + args->rapl_disable = false; return 0; + } if (!sev_version_greater_or_equal(SNP_MIN_API_MAJOR, SNP_MIN_API_MINOR)) { dev_dbg(sev->dev, "SEV-SNP support requires firmware version >= %d:%d\n", @@ -1376,6 +1379,12 @@ static int __sev_snp_init_locked(struct sev_platform_init_args *args) snp_prepare(); + if (args->rapl_disable && !(sev->snp_feat_info_0.ecx & SNP_RAPL_DISABLE_SUPPORTED)) { + dev_info(sev->dev, + "SEV: RAPL_DIS requested, but not supported\n"); + args->rapl_disable = false; + } + /* * Starting in SNP firmware v1.52, the SNP_INIT_EX command takes a list * of system physical address ranges to convert into HV-fixed page @@ -1426,6 +1435,9 @@ static int __sev_snp_init_locked(struct sev_platform_init_args *args) data.max_snp_asid = args->max_snp_asid; } + if (args->rapl_disable) + data.rapl_dis = 1; + data.init_rmp = 1; data.list_paddr_en = 1; data.list_paddr = __psp_pa(snp_range_list); diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h index d5099a2baca5..55ffc098d573 100644 --- a/include/linux/psp-sev.h +++ b/include/linux/psp-sev.h @@ -848,11 +848,13 @@ struct sev_data_snp_shutdown_ex { * unless psp_init_on_probe module param is set * @max_snp_asid: When non-zero, enable ciphertext hiding and specify the * maximum ASID that can be used for an SEV-SNP guest. + * @rapl_disable: Whether or not to set the RAPL_DIS bit during SNP_INIT_EX. */ struct sev_platform_init_args { int error; bool probe; unsigned int max_snp_asid; + bool rapl_disable; }; /** -- 2.53.0