AMD introduced the next generation of SEV called SEV-SNP (Secure Nested
Paging). SEV-SNP builds upon existing SEV and SEV-ES functionality
while adding new hardware security protection.

Define the commands and structures used to communicate with the AMD-SP
when creating and managing the SEV-SNP guests. The SEV-SNP firmware spec
is available at developer.amd.com/sev.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Borislav Petkov <b...@alien8.de>
Cc: Joerg Roedel <jroe...@suse.de>
Cc: "H. Peter Anvin" <h...@zytor.com>
Cc: Tony Luck <tony.l...@intel.com>
Cc: Dave Hansen <dave.han...@intel.com>
Cc: "Peter Zijlstra (Intel)" <pet...@infradead.org>
Cc: Paolo Bonzini <pbonz...@redhat.com>
Cc: Tom Lendacky <thomas.lenda...@amd.com>
Cc: David Rientjes <rient...@google.com>
Cc: Sean Christopherson <sea...@google.com>
Cc: x...@kernel.org
Cc: k...@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.si...@amd.com>
---
 drivers/crypto/ccp/sev-dev.c |  11 ++
 include/linux/psp-sev.h      | 210 +++++++++++++++++++++++++++++++++++
 include/uapi/linux/psp-sev.h |  27 +++++
 3 files changed, 248 insertions(+)

diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index 476113e12489..8a9fd843ad9e 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -128,6 +128,17 @@ static int sev_cmd_buffer_len(int cmd)
        case SEV_CMD_LAUNCH_UPDATE_SECRET:      return sizeof(struct 
sev_data_launch_secret);
        case SEV_CMD_DOWNLOAD_FIRMWARE:         return sizeof(struct 
sev_data_download_firmware);
        case SEV_CMD_GET_ID:                    return sizeof(struct 
sev_data_get_id);
+       case SEV_CMD_SNP_GCTX_CREATE:           return sizeof(struct 
sev_data_snp_gctx_create);
+       case SEV_CMD_SNP_LAUNCH_START:          return sizeof(struct 
sev_data_snp_launch_start);
+       case SEV_CMD_SNP_LAUNCH_UPDATE:         return sizeof(struct 
sev_data_snp_launch_update);
+       case SEV_CMD_SNP_ACTIVATE:              return sizeof(struct 
sev_data_snp_activate);
+       case SEV_CMD_SNP_DECOMMISSION:          return sizeof(struct 
sev_data_snp_decommission);
+       case SEV_CMD_SNP_PAGE_RECLAIM:          return sizeof(struct 
sev_data_snp_page_reclaim);
+       case SEV_CMD_SNP_GUEST_STATUS:          return sizeof(struct 
sev_data_snp_guest_status);
+       case SEV_CMD_SNP_LAUNCH_FINISH:         return sizeof(struct 
sev_data_snp_launch_finish);
+       case SEV_CMD_SNP_PAGE_UNSMASH:          return sizeof(struct 
sev_data_snp_page_unsmash);
+       case SEV_CMD_SNP_PLATFORM_STATUS:       return sizeof(struct 
sev_data_snp_platform_status_buf);
+       case SEV_CMD_SNP_GUEST_REQUEST:         return sizeof(struct 
sev_data_snp_guest_request);
        default:                                return 0;
        }
 
diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h
index 49d155cd2dfe..df89f0207099 100644
--- a/include/linux/psp-sev.h
+++ b/include/linux/psp-sev.h
@@ -83,6 +83,34 @@ enum sev_cmd {
        SEV_CMD_DBG_DECRYPT             = 0x060,
        SEV_CMD_DBG_ENCRYPT             = 0x061,
 
+       /* SNP specific commands */
+       SEV_CMD_SNP_INIT                = 0x81,
+       SEV_CMD_SNP_SHUTDOWN            = 0x82,
+       SEV_CMD_SNP_PLATFORM_STATUS     = 0x83,
+       SEV_CMD_SNP_DF_FLUSH            = 0x84,
+       SEV_CMD_SNP_DOWNLOAD_FIRMWARE   = 0x85,
+       SEV_CMD_SNP_GET_ID              = 0x86,
+       SEV_CMD_SNP_DECOMMISSION        = 0x90,
+       SEV_CMD_SNP_ACTIVATE            = 0x91,
+       SEV_CMD_SNP_GUEST_STATUS        = 0x92,
+       SEV_CMD_SNP_GCTX_CREATE         = 0x93,
+       SEV_CMD_SNP_GUEST_REQUEST       = 0x94,
+       SEV_CMD_SNP_ACTIVATE_EX         = 0x95,
+       SEV_CMD_SNP_LAUNCH_START        = 0xA0,
+       SEV_CMD_SNP_LAUNCH_UPDATE       = 0xA1,
+       SEV_CMD_SNP_LAUNCH_FINISH       = 0xA2,
+       SEV_CMD_SNP_DBG_DECRYPT         = 0xB0,
+       SEV_CMD_SNP_DBG_ENCRYT          = 0xB1,
+       SEV_CMD_SNP_PAGE_SWAP_OUT       = 0xC0,
+       SEV_CMD_SNP_PAGE_SWAP_IN        = 0xC1,
+       SEV_CMD_SNP_PAGE_MOVE           = 0xC2,
+       SEV_CMD_SNP_PAGE_MD_INIT        = 0xC3,
+       SEV_CMD_SNP_PAGE_MD_RECLAIM     = 0xC4,
+       SEV_CMD_SNP_PAGE_RO_RECLAIM     = 0xC5,
+       SEV_CMD_SNP_PAGE_RO_RESTORE     = 0xC6,
+       SEV_CMD_SNP_PAGE_RECLAIM        = 0xC7,
+       SEV_CMD_SNP_PAGE_UNSMASH        = 0xC8,
+
        SEV_CMD_MAX,
 };
 
@@ -483,6 +511,188 @@ struct sev_data_dbg {
        u32 len;                                /* In */
 } __packed;
 
+/**
+ * struct sev_data_snp_platform_status_buf - SNP_PLATFORM_STATUS command params
+ *
+ * @address: physical address where the status should be copied
+ */
+struct sev_data_snp_platform_status_buf {
+       u64 status_paddr;                       /* In */
+} __packed;
+
+/**
+ * struct sev_data_snp_download_firmware - SNP_DOWNLOAD_FIRMWARE command params
+ *
+ * @address: physical address of firmware image
+ * @len: len of the firmware image
+ */
+struct sev_data_snp_download_firmware {
+       u64 address;                            /* In */
+       u32 len;                                /* In */
+} __packed;
+
+/**
+ * struct sev_data_snp_gctx_create - SNP_GCTX_CREATE command params
+ *
+ * @gctx_paddr: system physical address of the page donated to firmware by
+ *             the hypervisor to contain the guest context.
+ */
+struct sev_data_snp_gctx_create {
+       u64 gctx_paddr;                         /* In */
+} __packed;
+
+/**
+ * struct sev_data_snp_activate - SNP_ACTIVATE command params
+ *
+ * @gctx_paddr: system physical address guest context page
+ * @asid: ASID to bind to the guest
+ */
+struct sev_data_snp_activate {
+       u64 gctx_paddr;                         /* In */
+       u32 asid;                               /* In */
+} __packed;
+
+/**
+ * struct sev_data_snp_decommission - SNP_DECOMMISSION command params
+ *
+ * @address: system physical address guest context page
+ */
+struct sev_data_snp_decommission {
+       u64 gctx_paddr;                         /* In */
+} __packed;
+
+/**
+ * struct sev_data_snp_launch_start - SNP_LAUNCH_START command params
+ *
+ * @gctx_addr: system physical address of guest context page
+ * @policy: guest policy
+ * @ma_gctx_addr: system physical address of migration agent
+ * @imi_en: launch flow is launching an IMI for the purpose of
+ *   guest-assisted migration.
+ * @ma_en: the guest is associated with a migration agent
+ */
+struct sev_data_snp_launch_start {
+       u64 gctx_paddr;                         /* In */
+       u64 policy;                             /* In */
+       u64 ma_gctx_paddr;                      /* In */
+       u32 ma_en:1;                            /* In */
+       u32 imi_en:1;                           /* In */
+       u32 rsvd:30;
+} __packed;
+
+/* SNP support page type */
+enum {
+       SNP_PAGE_TYPE_NORMAL            = 0x1,
+       SNP_PAGE_TYPE_VMSA              = 0x2,
+       SNP_PAGE_TYPE_ZERO              = 0x3,
+       SNP_PAGE_TYPE_UNMEASURED        = 0x4,
+       SNP_PAGE_TYPE_SECRET            = 0x5,
+       SNP_PAGE_TYPE_CPUID             = 0x6,
+
+       SNP_PAGE_TYPE_MAX
+};
+
+/**
+ * struct sev_data_snp_launch_update - SNP_LAUNCH_UPDATE command params
+ *
+ * @gctx_addr: system physical address of guest context page
+ * @imi_page: indicates that this page is part of the IMI of the guest
+ * @page_type: encoded page type
+ * @page_size: page size 0 indicates 4K and 1 indicates 2MB page
+ * @address: system physical address of destination page to encrypt
+ * @vmpl3_perms: VMPL permission mask for VMPL3
+ * @vmpl2_perms: VMPL permission mask for VMPL2
+ * @vmpl1_perms: VMPL permission mask for VMPL1
+ */
+struct sev_data_snp_launch_update {
+       u64 gctx_paddr;                         /* In */
+       u32 page_size:1;                        /* In */
+       u32 page_type:3;                        /* In */
+       u32 imi_page:1;                         /* In */
+       u32 rsvd:27;
+       u32 rsvd2;
+       u64 address;                            /* In */
+       u32 rsvd3:8;
+       u32 vmpl3_perms:8;                      /* In */
+       u32 vmpl2_perms:8;                      /* In */
+       u32 vmpl1_perms:8;                      /* In */
+       u32 rsvd4;
+} __packed;
+
+/**
+ * struct sev_data_snp_launch_finish - SNP_LAUNCH_FINISH command params
+ *
+ * @gctx_addr: system pphysical address of guest context page
+ */
+struct sev_data_snp_launch_finish {
+       u64 gctx_paddr;
+       u64 id_block_paddr;
+       u64 id_auth_paddr;
+       u8 id_block_en:1;
+       u8 auth_key_en:1;
+       u64 rsvd:62;
+       u8 host_data[32];
+} __packed;
+
+/**
+ * struct sev_data_snp_guest_status - SNP_GUEST_STATUS command params
+ *
+ * @gctx_paddr: system physical address of guest context page
+ * @address: system physical address of guest status page
+ */
+struct sev_data_snp_guest_status {
+       u64 gctx_paddr;
+       u64 address;
+} __packed;
+
+/**
+ * struct sev_data_snp_page_reclaim - SNP_PAGE_RECLAIM command params
+ *
+ * @paddr: system physical address of page to be claimed. The BIT0 indicate
+ *     the page size. 0h indicates 4 kB and 1h indicates 2 MB page.
+ */
+struct sev_data_snp_page_reclaim {
+       u64 paddr;
+} __packed;
+
+/**
+ * struct sev_data_snp_page_unsmash - SNP_PAGE_UNMASH command params
+ *
+ * @paddr: system physical address of page to be unmashed. The BIT0 indicate
+ *     the page size. 0h indicates 4 kB and 1h indicates 2 MB page.
+ */
+struct sev_data_snp_page_unsmash {
+       u64 paddr;
+} __packed;
+
+/**
+ * struct sev_data_dbg - DBG_ENCRYPT/DBG_DECRYPT command parameters
+ *
+ * @handle: handle of the VM to perform debug operation
+ * @src_addr: source address of data to operate on
+ * @dst_addr: destination address of data to operate on
+ * @len: len of data to operate on
+ */
+struct sev_data_snp_dbg {
+       u64 gctx_paddr;                         /* In */
+       u64 src_addr;                           /* In */
+       u64 dst_addr;                           /* In */
+       u32 len;                                /* In */
+} __packed;
+
+/**
+ * struct sev_snp_guest_request - SNP_GUEST_REQUEST command params
+ *
+ * @gctx_paddr: system physical address of guest context page
+ * @req_paddr: system physical address of request page
+ * @res_paddr: system physical address of response page
+ */
+struct sev_data_snp_guest_request {
+       u64 gctx_paddr;                         /* In */
+       u64 req_paddr;                          /* In */
+       u64 res_paddr;                          /* In */
+} __packed;
+
 #ifdef CONFIG_CRYPTO_DEV_SP_PSP
 
 /**
diff --git a/include/uapi/linux/psp-sev.h b/include/uapi/linux/psp-sev.h
index 91b4c63d5cbf..9bc63b026091 100644
--- a/include/uapi/linux/psp-sev.h
+++ b/include/uapi/linux/psp-sev.h
@@ -61,6 +61,11 @@ typedef enum {
        SEV_RET_INVALID_PARAM,
        SEV_RET_RESOURCE_LIMIT,
        SEV_RET_SECURE_DATA_INVALID,
+       SEV_RET_INVALID_PAGE_SIZE,
+       SEV_RET_INVALID_PAGE_STATE,
+       SEV_RET_INVALID_MDATA_ENTRY,
+       SEV_RET_INVALID_PAGE_OWNER,
+       SEV_RET_INVALID_PAGE_AEAD_OFLOW,
        SEV_RET_MAX,
 } sev_ret_code;
 
@@ -147,6 +152,28 @@ struct sev_user_data_get_id2 {
        __u32 length;                           /* In/Out */
 } __packed;
 
+/**
+ * struct sev_data_snp_platform_status - Platform status
+ *
+ * @major: API major version
+ * @minor: API minor version
+ * @state: current platform state
+ * @build: firmware build id for the API version
+ * @guest_count: the number of guest currently managed by the firmware
+ * @tcb_version: current TCB version
+ */
+struct sev_user_snp_status {
+       __u8 api_major;         /* Out */
+       __u8 api_minor;         /* Out */
+       __u8 state;             /* Out */
+       __u8 rsvd;
+       __u32 build_id;         /* Out */
+       __u32 rsvd1;
+       __u32 guest_count;      /* Out */
+       __u64 tcb_version;      /* Out */
+       __u64 rsvd2;
+} __packed;
+
 /**
  * struct sev_issue_cmd - SEV ioctl parameters
  *
-- 
2.17.1

Reply via email to