Message ID | 20210820155918.7518-17-brijesh.singh@amd.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Add AMD Secure Nested Paging (SEV-SNP) Hypervisor Support | expand |
On Fri, Aug 20, 2021 at 9:00 AM Brijesh Singh <brijesh.singh@amd.com> wrote: > > The command can be used by the userspace to query the SNP platform status > report. See the SEV-SNP spec for more details. > > Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> > --- > Documentation/virt/coco/sevguest.rst | 27 +++++++++++++++++ > drivers/crypto/ccp/sev-dev.c | 45 ++++++++++++++++++++++++++++ > include/uapi/linux/psp-sev.h | 1 + > 3 files changed, 73 insertions(+) > > diff --git a/Documentation/virt/coco/sevguest.rst b/Documentation/virt/coco/sevguest.rst > index 7acb8696fca4..7c51da010039 100644 > --- a/Documentation/virt/coco/sevguest.rst > +++ b/Documentation/virt/coco/sevguest.rst > @@ -52,6 +52,22 @@ to execute due to the firmware error, then fw_err code will be set. > __u64 fw_err; > }; > > +The host ioctl should be called to /dev/sev device. The ioctl accepts command > +id and command input structure. > + > +:: > + struct sev_issue_cmd { > + /* Command ID */ > + __u32 cmd; > + > + /* Command request structure */ > + __u64 data; > + > + /* firmware error code on failure (see psp-sev.h) */ > + __u32 error; > + }; > + > + > 2.1 SNP_GET_REPORT > ------------------ > > @@ -107,3 +123,14 @@ length of the blob is lesser than expected then snp_ext_report_req.certs_len wil > be updated with the expected value. > > See GHCB specification for further detail on how to parse the certificate blob. > + > +2.3 SNP_PLATFORM_STATUS > +----------------------- > +:Technology: sev-snp > +:Type: hypervisor ioctl cmd > +:Parameters (in): struct sev_data_snp_platform_status > +:Returns (out): 0 on success, -negative on error > + > +The SNP_PLATFORM_STATUS command is used to query the SNP platform status. The > +status includes API major, minor version and more. See the SEV-SNP > +specification for further details. > diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c > index 4cd7d803a624..16c6df5d412c 100644 > --- a/drivers/crypto/ccp/sev-dev.c > +++ b/drivers/crypto/ccp/sev-dev.c > @@ -1394,6 +1394,48 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable) > return ret; > } > > +static int sev_ioctl_snp_platform_status(struct sev_issue_cmd *argp) > +{ > + struct sev_device *sev = psp_master->sev_data; > + struct sev_data_snp_platform_status_buf buf; > + struct page *status_page; > + void *data; > + int ret; > + > + if (!sev->snp_inited || !argp->data) > + return -EINVAL; > + > + status_page = alloc_page(GFP_KERNEL_ACCOUNT); > + if (!status_page) > + return -ENOMEM; > + > + data = page_address(status_page); > + if (snp_set_rmp_state(__pa(data), 1, true, true, false)) { > + __free_pages(status_page, 0); > + return -EFAULT; > + } > + > + buf.status_paddr = __psp_pa(data); > + ret = __sev_do_cmd_locked(SEV_CMD_SNP_PLATFORM_STATUS, &buf, &argp->error); > + > + /* Change the page state before accessing it */ > + if (snp_set_rmp_state(__pa(data), 1, false, true, true)) { > + snp_leak_pages(__pa(data) >> PAGE_SHIFT, 1); Calling `snp_leak_pages()` here seems wrong, because `snp_set_rmp_state()` calls `snp_leak_pages()` when it returns an error. > + return -EFAULT; > + } > + > + if (ret) > + goto cleanup; > + > + if (copy_to_user((void __user *)argp->data, data, > + sizeof(struct sev_user_data_snp_status))) > + ret = -EFAULT; > + > +cleanup: > + __free_pages(status_page, 0); > + return ret; > +} > + > static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) > { > void __user *argp = (void __user *)arg; > @@ -1445,6 +1487,9 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) > case SEV_GET_ID2: > ret = sev_ioctl_do_get_id2(&input); > break; > + case SNP_PLATFORM_STATUS: > + ret = sev_ioctl_snp_platform_status(&input); > + break; > default: > ret = -EINVAL; > goto out; > diff --git a/include/uapi/linux/psp-sev.h b/include/uapi/linux/psp-sev.h > index bed65a891223..ffd60e8b0a31 100644 > --- a/include/uapi/linux/psp-sev.h > +++ b/include/uapi/linux/psp-sev.h > @@ -28,6 +28,7 @@ enum { > SEV_PEK_CERT_IMPORT, > SEV_GET_ID, /* This command is deprecated, use SEV_GET_ID2 */ > SEV_GET_ID2, > + SNP_PLATFORM_STATUS, > > SEV_MAX, > }; > -- > 2.17.1 > >
On 9/9/21 10:18 PM, Marc Orr wrote: > On Fri, Aug 20, 2021 at 9:00 AM Brijesh Singh <brijesh.singh@amd.com> wrote: >> The command can be used by the userspace to query the SNP platform status >> report. See the SEV-SNP spec for more details. >> >> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> >> --- >> Documentation/virt/coco/sevguest.rst | 27 +++++++++++++++++ >> drivers/crypto/ccp/sev-dev.c | 45 ++++++++++++++++++++++++++++ >> include/uapi/linux/psp-sev.h | 1 + >> 3 files changed, 73 insertions(+) >> >> diff --git a/Documentation/virt/coco/sevguest.rst b/Documentation/virt/coco/sevguest.rst >> index 7acb8696fca4..7c51da010039 100644 >> --- a/Documentation/virt/coco/sevguest.rst >> +++ b/Documentation/virt/coco/sevguest.rst >> @@ -52,6 +52,22 @@ to execute due to the firmware error, then fw_err code will be set. >> __u64 fw_err; >> }; >> >> +The host ioctl should be called to /dev/sev device. The ioctl accepts command >> +id and command input structure. >> + >> +:: >> + struct sev_issue_cmd { >> + /* Command ID */ >> + __u32 cmd; >> + >> + /* Command request structure */ >> + __u64 data; >> + >> + /* firmware error code on failure (see psp-sev.h) */ >> + __u32 error; >> + }; >> + >> + >> 2.1 SNP_GET_REPORT >> ------------------ >> >> @@ -107,3 +123,14 @@ length of the blob is lesser than expected then snp_ext_report_req.certs_len wil >> be updated with the expected value. >> >> See GHCB specification for further detail on how to parse the certificate blob. >> + >> +2.3 SNP_PLATFORM_STATUS >> +----------------------- >> +:Technology: sev-snp >> +:Type: hypervisor ioctl cmd >> +:Parameters (in): struct sev_data_snp_platform_status >> +:Returns (out): 0 on success, -negative on error >> + >> +The SNP_PLATFORM_STATUS command is used to query the SNP platform status. The >> +status includes API major, minor version and more. See the SEV-SNP >> +specification for further details. >> diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c >> index 4cd7d803a624..16c6df5d412c 100644 >> --- a/drivers/crypto/ccp/sev-dev.c >> +++ b/drivers/crypto/ccp/sev-dev.c >> @@ -1394,6 +1394,48 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable) >> return ret; >> } >> >> +static int sev_ioctl_snp_platform_status(struct sev_issue_cmd *argp) >> +{ >> + struct sev_device *sev = psp_master->sev_data; >> + struct sev_data_snp_platform_status_buf buf; >> + struct page *status_page; >> + void *data; >> + int ret; >> + >> + if (!sev->snp_inited || !argp->data) >> + return -EINVAL; >> + >> + status_page = alloc_page(GFP_KERNEL_ACCOUNT); >> + if (!status_page) >> + return -ENOMEM; >> + >> + data = page_address(status_page); >> + if (snp_set_rmp_state(__pa(data), 1, true, true, false)) { >> + __free_pages(status_page, 0); >> + return -EFAULT; >> + } >> + >> + buf.status_paddr = __psp_pa(data); >> + ret = __sev_do_cmd_locked(SEV_CMD_SNP_PLATFORM_STATUS, &buf, &argp->error); >> + >> + /* Change the page state before accessing it */ >> + if (snp_set_rmp_state(__pa(data), 1, false, true, true)) { >> + snp_leak_pages(__pa(data) >> PAGE_SHIFT, 1); > Calling `snp_leak_pages()` here seems wrong, because > `snp_set_rmp_state()` calls `snp_leak_pages()` when it returns an > error. Agreed, i will fix in next rev. > >> + return -EFAULT; >> + } >> + >> + if (ret) >> + goto cleanup; >> + >> + if (copy_to_user((void __user *)argp->data, data, >> + sizeof(struct sev_user_data_snp_status))) >> + ret = -EFAULT; >> + >> +cleanup: >> + __free_pages(status_page, 0); >> + return ret; >> +} >> + >> static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) >> { >> void __user *argp = (void __user *)arg; >> @@ -1445,6 +1487,9 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) >> case SEV_GET_ID2: >> ret = sev_ioctl_do_get_id2(&input); >> break; >> + case SNP_PLATFORM_STATUS: >> + ret = sev_ioctl_snp_platform_status(&input); >> + break; >> default: >> ret = -EINVAL; >> goto out; >> diff --git a/include/uapi/linux/psp-sev.h b/include/uapi/linux/psp-sev.h >> index bed65a891223..ffd60e8b0a31 100644 >> --- a/include/uapi/linux/psp-sev.h >> +++ b/include/uapi/linux/psp-sev.h >> @@ -28,6 +28,7 @@ enum { >> SEV_PEK_CERT_IMPORT, >> SEV_GET_ID, /* This command is deprecated, use SEV_GET_ID2 */ >> SEV_GET_ID2, >> + SNP_PLATFORM_STATUS, >> >> SEV_MAX, >> }; >> -- >> 2.17.1 >> >>
* Brijesh Singh (brijesh.singh@amd.com) wrote: > The command can be used by the userspace to query the SNP platform status > report. See the SEV-SNP spec for more details. > > Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> > --- > Documentation/virt/coco/sevguest.rst | 27 +++++++++++++++++ > drivers/crypto/ccp/sev-dev.c | 45 ++++++++++++++++++++++++++++ > include/uapi/linux/psp-sev.h | 1 + > 3 files changed, 73 insertions(+) > > diff --git a/Documentation/virt/coco/sevguest.rst b/Documentation/virt/coco/sevguest.rst > index 7acb8696fca4..7c51da010039 100644 > --- a/Documentation/virt/coco/sevguest.rst > +++ b/Documentation/virt/coco/sevguest.rst > @@ -52,6 +52,22 @@ to execute due to the firmware error, then fw_err code will be set. > __u64 fw_err; > }; > > +The host ioctl should be called to /dev/sev device. The ioctl accepts command > +id and command input structure. > + > +:: > + struct sev_issue_cmd { > + /* Command ID */ > + __u32 cmd; > + > + /* Command request structure */ > + __u64 data; > + > + /* firmware error code on failure (see psp-sev.h) */ > + __u32 error; > + }; > + > + > 2.1 SNP_GET_REPORT > ------------------ > > @@ -107,3 +123,14 @@ length of the blob is lesser than expected then snp_ext_report_req.certs_len wil > be updated with the expected value. > > See GHCB specification for further detail on how to parse the certificate blob. > + > +2.3 SNP_PLATFORM_STATUS > +----------------------- > +:Technology: sev-snp > +:Type: hypervisor ioctl cmd > +:Parameters (in): struct sev_data_snp_platform_status > +:Returns (out): 0 on success, -negative on error > + > +The SNP_PLATFORM_STATUS command is used to query the SNP platform status. The > +status includes API major, minor version and more. See the SEV-SNP > +specification for further details. > diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c > index 4cd7d803a624..16c6df5d412c 100644 > --- a/drivers/crypto/ccp/sev-dev.c > +++ b/drivers/crypto/ccp/sev-dev.c > @@ -1394,6 +1394,48 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable) > return ret; > } > > +static int sev_ioctl_snp_platform_status(struct sev_issue_cmd *argp) > +{ > + struct sev_device *sev = psp_master->sev_data; > + struct sev_data_snp_platform_status_buf buf; > + struct page *status_page; > + void *data; > + int ret; > + > + if (!sev->snp_inited || !argp->data) > + return -EINVAL; > + > + status_page = alloc_page(GFP_KERNEL_ACCOUNT); > + if (!status_page) > + return -ENOMEM; > + > + data = page_address(status_page); > + if (snp_set_rmp_state(__pa(data), 1, true, true, false)) { > + __free_pages(status_page, 0); > + return -EFAULT; > + } > + > + buf.status_paddr = __psp_pa(data); > + ret = __sev_do_cmd_locked(SEV_CMD_SNP_PLATFORM_STATUS, &buf, &argp->error); > + > + /* Change the page state before accessing it */ > + if (snp_set_rmp_state(__pa(data), 1, false, true, true)) { > + snp_leak_pages(__pa(data) >> PAGE_SHIFT, 1); > + return -EFAULT; > + } Could we find a way of returning some of these errors into the output, rather than interepreting them from errno values? Dave > + if (ret) > + goto cleanup; > + > + if (copy_to_user((void __user *)argp->data, data, > + sizeof(struct sev_user_data_snp_status))) > + ret = -EFAULT; > + > +cleanup: > + __free_pages(status_page, 0); > + return ret; > +} > + > static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) > { > void __user *argp = (void __user *)arg; > @@ -1445,6 +1487,9 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) > case SEV_GET_ID2: > ret = sev_ioctl_do_get_id2(&input); > break; > + case SNP_PLATFORM_STATUS: > + ret = sev_ioctl_snp_platform_status(&input); > + break; > default: > ret = -EINVAL; > goto out; > diff --git a/include/uapi/linux/psp-sev.h b/include/uapi/linux/psp-sev.h > index bed65a891223..ffd60e8b0a31 100644 > --- a/include/uapi/linux/psp-sev.h > +++ b/include/uapi/linux/psp-sev.h > @@ -28,6 +28,7 @@ enum { > SEV_PEK_CERT_IMPORT, > SEV_GET_ID, /* This command is deprecated, use SEV_GET_ID2 */ > SEV_GET_ID2, > + SNP_PLATFORM_STATUS, > > SEV_MAX, > }; > -- > 2.17.1 > >
On 9/22/21 12:35 PM, Dr. David Alan Gilbert wrote: > * Brijesh Singh (brijesh.singh@amd.com) wrote: >> The command can be used by the userspace to query the SNP platform status >> report. See the SEV-SNP spec for more details. >> >> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> >> --- >> Documentation/virt/coco/sevguest.rst | 27 +++++++++++++++++ >> drivers/crypto/ccp/sev-dev.c | 45 ++++++++++++++++++++++++++++ >> include/uapi/linux/psp-sev.h | 1 + >> 3 files changed, 73 insertions(+) >> >> diff --git a/Documentation/virt/coco/sevguest.rst b/Documentation/virt/coco/sevguest.rst >> index 7acb8696fca4..7c51da010039 100644 >> --- a/Documentation/virt/coco/sevguest.rst >> +++ b/Documentation/virt/coco/sevguest.rst >> @@ -52,6 +52,22 @@ to execute due to the firmware error, then fw_err code will be set. >> __u64 fw_err; >> }; >> >> +The host ioctl should be called to /dev/sev device. The ioctl accepts command >> +id and command input structure. >> + >> +:: >> + struct sev_issue_cmd { >> + /* Command ID */ >> + __u32 cmd; >> + >> + /* Command request structure */ >> + __u64 data; >> + >> + /* firmware error code on failure (see psp-sev.h) */ >> + __u32 error; >> + }; >> + >> + >> 2.1 SNP_GET_REPORT >> ------------------ >> >> @@ -107,3 +123,14 @@ length of the blob is lesser than expected then snp_ext_report_req.certs_len wil >> be updated with the expected value. >> >> See GHCB specification for further detail on how to parse the certificate blob. >> + >> +2.3 SNP_PLATFORM_STATUS >> +----------------------- >> +:Technology: sev-snp >> +:Type: hypervisor ioctl cmd >> +:Parameters (in): struct sev_data_snp_platform_status >> +:Returns (out): 0 on success, -negative on error >> + >> +The SNP_PLATFORM_STATUS command is used to query the SNP platform status. The >> +status includes API major, minor version and more. See the SEV-SNP >> +specification for further details. >> diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c >> index 4cd7d803a624..16c6df5d412c 100644 >> --- a/drivers/crypto/ccp/sev-dev.c >> +++ b/drivers/crypto/ccp/sev-dev.c >> @@ -1394,6 +1394,48 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable) >> return ret; >> } >> >> +static int sev_ioctl_snp_platform_status(struct sev_issue_cmd *argp) >> +{ >> + struct sev_device *sev = psp_master->sev_data; >> + struct sev_data_snp_platform_status_buf buf; >> + struct page *status_page; >> + void *data; >> + int ret; >> + >> + if (!sev->snp_inited || !argp->data) >> + return -EINVAL; >> + >> + status_page = alloc_page(GFP_KERNEL_ACCOUNT); >> + if (!status_page) >> + return -ENOMEM; >> + >> + data = page_address(status_page); >> + if (snp_set_rmp_state(__pa(data), 1, true, true, false)) { >> + __free_pages(status_page, 0); >> + return -EFAULT; >> + } >> + >> + buf.status_paddr = __psp_pa(data); >> + ret = __sev_do_cmd_locked(SEV_CMD_SNP_PLATFORM_STATUS, &buf, &argp->error); >> + >> + /* Change the page state before accessing it */ >> + if (snp_set_rmp_state(__pa(data), 1, false, true, true)) { >> + snp_leak_pages(__pa(data) >> PAGE_SHIFT, 1); >> + return -EFAULT; >> + } > Could we find a way of returning some of these errors into the output, > rather than interepreting them from errno values? I can try to find a corresponding fw error code and use it where applicable. e.g in this case I can use the SEV_RET_INVALID_PAGE_STATE. thanks
diff --git a/Documentation/virt/coco/sevguest.rst b/Documentation/virt/coco/sevguest.rst index 7acb8696fca4..7c51da010039 100644 --- a/Documentation/virt/coco/sevguest.rst +++ b/Documentation/virt/coco/sevguest.rst @@ -52,6 +52,22 @@ to execute due to the firmware error, then fw_err code will be set. __u64 fw_err; }; +The host ioctl should be called to /dev/sev device. The ioctl accepts command +id and command input structure. + +:: + struct sev_issue_cmd { + /* Command ID */ + __u32 cmd; + + /* Command request structure */ + __u64 data; + + /* firmware error code on failure (see psp-sev.h) */ + __u32 error; + }; + + 2.1 SNP_GET_REPORT ------------------ @@ -107,3 +123,14 @@ length of the blob is lesser than expected then snp_ext_report_req.certs_len wil be updated with the expected value. See GHCB specification for further detail on how to parse the certificate blob. + +2.3 SNP_PLATFORM_STATUS +----------------------- +:Technology: sev-snp +:Type: hypervisor ioctl cmd +:Parameters (in): struct sev_data_snp_platform_status +:Returns (out): 0 on success, -negative on error + +The SNP_PLATFORM_STATUS command is used to query the SNP platform status. The +status includes API major, minor version and more. See the SEV-SNP +specification for further details. diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 4cd7d803a624..16c6df5d412c 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -1394,6 +1394,48 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable) return ret; } +static int sev_ioctl_snp_platform_status(struct sev_issue_cmd *argp) +{ + struct sev_device *sev = psp_master->sev_data; + struct sev_data_snp_platform_status_buf buf; + struct page *status_page; + void *data; + int ret; + + if (!sev->snp_inited || !argp->data) + return -EINVAL; + + status_page = alloc_page(GFP_KERNEL_ACCOUNT); + if (!status_page) + return -ENOMEM; + + data = page_address(status_page); + if (snp_set_rmp_state(__pa(data), 1, true, true, false)) { + __free_pages(status_page, 0); + return -EFAULT; + } + + buf.status_paddr = __psp_pa(data); + ret = __sev_do_cmd_locked(SEV_CMD_SNP_PLATFORM_STATUS, &buf, &argp->error); + + /* Change the page state before accessing it */ + if (snp_set_rmp_state(__pa(data), 1, false, true, true)) { + snp_leak_pages(__pa(data) >> PAGE_SHIFT, 1); + return -EFAULT; + } + + if (ret) + goto cleanup; + + if (copy_to_user((void __user *)argp->data, data, + sizeof(struct sev_user_data_snp_status))) + ret = -EFAULT; + +cleanup: + __free_pages(status_page, 0); + return ret; +} + static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) { void __user *argp = (void __user *)arg; @@ -1445,6 +1487,9 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) case SEV_GET_ID2: ret = sev_ioctl_do_get_id2(&input); break; + case SNP_PLATFORM_STATUS: + ret = sev_ioctl_snp_platform_status(&input); + break; default: ret = -EINVAL; goto out; diff --git a/include/uapi/linux/psp-sev.h b/include/uapi/linux/psp-sev.h index bed65a891223..ffd60e8b0a31 100644 --- a/include/uapi/linux/psp-sev.h +++ b/include/uapi/linux/psp-sev.h @@ -28,6 +28,7 @@ enum { SEV_PEK_CERT_IMPORT, SEV_GET_ID, /* This command is deprecated, use SEV_GET_ID2 */ SEV_GET_ID2, + SNP_PLATFORM_STATUS, SEV_MAX, };
The command can be used by the userspace to query the SNP platform status report. See the SEV-SNP spec for more details. Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> --- Documentation/virt/coco/sevguest.rst | 27 +++++++++++++++++ drivers/crypto/ccp/sev-dev.c | 45 ++++++++++++++++++++++++++++ include/uapi/linux/psp-sev.h | 1 + 3 files changed, 73 insertions(+)