From: Brijesh Singh <brijesh.singh@xxxxxxx> Add support to decrypt guest encrypted memory. These API interfaces can be used for example to dump VMCBs on SNP guest exit. Signed-off-by: Brijesh Singh <brijesh.singh@xxxxxxx> Signed-off-by: Ashish Kalra <ashish.kalra@xxxxxxx> [mdr: minor commit fixups] Signed-off-by: Michael Roth <michael.roth@xxxxxxx> --- drivers/crypto/ccp/sev-dev.c | 32 ++++++++++++++++++++++++++++++++ include/linux/psp-sev.h | 19 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 096ba15d0740..3c8cd2d20016 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -2061,6 +2061,38 @@ int sev_guest_df_flush(int *error) } EXPORT_SYMBOL_GPL(sev_guest_df_flush); +int snp_guest_dbg_decrypt_page(u64 gctx_pfn, u64 src_pfn, u64 dst_pfn, int *error) +{ + struct sev_data_snp_dbg data = {0}; + struct sev_device *sev; + int ret; + + if (!psp_master || !psp_master->sev_data) + return -ENODEV; + + sev = psp_master->sev_data; + + if (!sev->snp_initialized) + return -EINVAL; + + data.gctx_paddr = sme_me_mask | (gctx_pfn << PAGE_SHIFT); + data.src_addr = sme_me_mask | (src_pfn << PAGE_SHIFT); + data.dst_addr = sme_me_mask | (dst_pfn << PAGE_SHIFT); + + /* The destination page must be in the firmware state. */ + if (rmp_mark_pages_firmware(data.dst_addr, 1, false)) + return -EIO; + + ret = sev_do_cmd(SEV_CMD_SNP_DBG_DECRYPT, &data, error); + + /* Restore the page state */ + if (snp_reclaim_pages(data.dst_addr, 1, false)) + ret = -EIO; + + return ret; +} +EXPORT_SYMBOL_GPL(snp_guest_dbg_decrypt_page); + static void sev_snp_certs_release(struct kref *kref) { struct sev_snp_certs *certs = container_of(kref, struct sev_snp_certs, kref); diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h index 1235eb3110cb..55f6dfc2580d 100644 --- a/include/linux/psp-sev.h +++ b/include/linux/psp-sev.h @@ -916,6 +916,20 @@ int sev_guest_decommission(struct sev_data_decommission *data, int *error); */ int sev_do_cmd(int cmd, void *data, int *psp_ret); +/** + * snp_guest_dbg_decrypt_page - perform SEV SNP_DBG_DECRYPT command + * + * @sev_ret: sev command return code + * + * Returns: + * 0 if the SEV successfully processed the command + * -%ENODEV if the SEV device is not available + * -%ENOTSUPP if the SEV does not support SEV + * -%ETIMEDOUT if the SEV command timed out + * -%EIO if the SEV returned a non-zero return code + */ +int snp_guest_dbg_decrypt_page(u64 gctx_pfn, u64 src_pfn, u64 dst_pfn, int *error); + void *psp_copy_user_blob(u64 uaddr, u32 len); void *snp_alloc_firmware_page(gfp_t mask); void snp_free_firmware_page(void *addr); @@ -946,6 +960,11 @@ sev_issue_cmd_external_user(struct file *filep, unsigned int id, void *data, int static inline void *psp_copy_user_blob(u64 __user uaddr, u32 len) { return ERR_PTR(-EINVAL); } +static inline int snp_guest_dbg_decrypt_page(u64 gctx_pfn, u64 src_pfn, u64 dst_pfn, int *error) +{ + return -ENODEV; +} + static inline void *snp_alloc_firmware_page(gfp_t mask) { return NULL; -- 2.25.1