On Fri, Aug 20, 2021 at 10:19:31AM -0500, Brijesh Singh wrote: > +=================================================================== > +The Definitive SEV Guest API Documentation > +=================================================================== > + > +1. General description > +====================== > + > +The SEV API is a set of ioctls that are issued to by the guest or issued to by? Issued by the guest or hypervisor, you mean.. > +hypervisor to get or set certain aspect of the SEV virtual machine. > +The ioctls belong to the following classes: > + > + - Hypervisor ioctls: These query and set global attributes which affect the > + whole SEV firmware. These ioctl is used by platform provision tools. "These ioctls are used ... " > + > + - Guest ioctls: These query and set attribute of the SEV virtual machine. "... attributes... " > + > +2. API description > +================== > + > +This section describes ioctls that can be used to query or set SEV guests. > +For each ioctl, the following information is provided along with a > +description: > + > + Technology: > + which SEV techology provides this ioctl. sev, sev-es, sev-snp or all. > + > + Type: > + hypervisor or guest. The ioctl can be used inside the guest or the > + hypervisor. > + > + Parameters: > + what parameters are accepted by the ioctl. > + > + Returns: > + the return value. General error numbers (ENOMEM, EINVAL) > + are not detailed, but errors with specific meanings are. > + > +The guest ioctl should be called to /dev/sev-guest device. The ioctl accepts s/called to/issued on a file descriptor of the/ > +struct snp_user_guest_request. The input and output structure is specified > +through the req_data and resp_data field respectively. If the ioctl fails > +to execute due to the firmware error, then fw_err code will be set. "... due to a ... " > + > +:: > + struct snp_user_guest_request { So you said earlier: > I followed the naming convension you recommended during the initial SEV driver > developement. IIRC, the main reason for us having to add "user" in it because > we wanted to distinguious that this structure is not exactly same as the what > is defined in the SEV-SNP firmware spec. but looking at the current variant in the code, the structure in the SNP spec is Table 91. Layout of the CMDBUF_SNP_GUEST_REQUEST Structure which corresponds to struct snp_guest_request_data so you can call this one: struct snp_guest_request_ioctl and then it is perfectly clear what is what. > + /* Request and response structure address */ > + __u64 req_data; > + __u64 resp_data; > + > + /* firmware error code on failure (see psp-sev.h) */ > + __u64 fw_err; > + }; > + > +2.1 SNP_GET_REPORT > +------------------ > + > +:Technology: sev-snp > +:Type: guest ioctl > +:Parameters (in): struct snp_report_req > +:Returns (out): struct snp_report_resp on success, -negative on error > + > +The SNP_GET_REPORT ioctl can be used to query the attestation report from the > +SEV-SNP firmware. The ioctl uses the SNP_GUEST_REQUEST (MSG_REPORT_REQ) command > +provided by the SEV-SNP firmware to query the attestation report. > + > +On success, the snp_report_resp.data will contains the report. The report "... will contain... " > +format is described in the SEV-SNP specification. See the SEV-SNP specification > +for further details. "... which can be found at https://developer.amd.com/sev/." assuming that URL will keep its validity in the foreseeable future. > +static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) > +{ > + struct snp_guest_dev *snp_dev = to_snp_dev(file); > + void __user *argp = (void __user *)arg; > + struct snp_user_guest_request input; > + int ret = -ENOTTY; > + > + if (copy_from_user(&input, argp, sizeof(input))) > + return -EFAULT; > + > + mutex_lock(&snp_cmd_mutex); > + > + switch (ioctl) { > + case SNP_GET_REPORT: { > + ret = get_report(snp_dev, &input); > + break; > + } No need for those {} brackets around the case. > + default: > + break; > + } > + > + mutex_unlock(&snp_cmd_mutex); > + > + if (copy_to_user(argp, &input, sizeof(input))) > + return -EFAULT; > + > + return ret; > +} > + > +static void free_shared_pages(void *buf, size_t sz) > +{ > + unsigned int npages = PAGE_ALIGN(sz) >> PAGE_SHIFT; > + > + /* If fail to restore the encryption mask then leak it. */ > + if (set_memory_encrypted((unsigned long)buf, npages)) Hmm, this sounds like an abnormal condition about which we should at least warn... > + return; > + > + __free_pages(virt_to_page(buf), get_order(sz)); > +} > + > +static void *alloc_shared_pages(size_t sz) > +{ > + unsigned int npages = PAGE_ALIGN(sz) >> PAGE_SHIFT; > + struct page *page; > + int ret; > + > + page = alloc_pages(GFP_KERNEL_ACCOUNT, get_order(sz)); > + if (IS_ERR(page)) > + return NULL; > + > + ret = set_memory_decrypted((unsigned long)page_address(page), npages); > + if (ret) { > + __free_pages(page, get_order(sz)); > + return NULL; > + } > + > + return page_address(page); > +} > + > +static const struct file_operations snp_guest_fops = { > + .owner = THIS_MODULE, > + .unlocked_ioctl = snp_guest_ioctl, > +}; > + > +static int __init snp_guest_probe(struct platform_device *pdev) > +{ > + struct snp_guest_platform_data *data; > + struct device *dev = &pdev->dev; > + struct snp_guest_dev *snp_dev; > + struct miscdevice *misc; > + int ret; > + > + if (!dev->platform_data) > + return -ENODEV; > + > + data = (struct snp_guest_platform_data *)dev->platform_data; > + vmpck_id = data->vmpck_id; > + > + snp_dev = devm_kzalloc(&pdev->dev, sizeof(struct snp_guest_dev), GFP_KERNEL); > + if (!snp_dev) > + return -ENOMEM; > + > + platform_set_drvdata(pdev, snp_dev); > + snp_dev->dev = dev; > + > + snp_dev->crypto = init_crypto(snp_dev, data->vmpck, sizeof(data->vmpck)); > + if (!snp_dev->crypto) > + return -EIO; I guess you should put the crypto init... > + > + /* Allocate the shared page used for the request and response message. */ > + snp_dev->request = alloc_shared_pages(sizeof(struct snp_guest_msg)); > + if (IS_ERR(snp_dev->request)) { > + ret = PTR_ERR(snp_dev->request); > + goto e_free_crypto; > + } > + > + snp_dev->response = alloc_shared_pages(sizeof(struct snp_guest_msg)); > + if (IS_ERR(snp_dev->response)) { > + ret = PTR_ERR(snp_dev->response); > + goto e_free_req; > + } ... here, after the page allocation to save yourself all the setup work if the shared pages allocation fails. > + > + misc = &snp_dev->misc; > + misc->minor = MISC_DYNAMIC_MINOR; > + misc->name = DEVICE_NAME; > + misc->fops = &snp_guest_fops; > + > + return misc_register(misc); > + > +e_free_req: > + free_shared_pages(snp_dev->request, sizeof(struct snp_guest_msg)); > + > +e_free_crypto: > + deinit_crypto(snp_dev->crypto); > + > + return ret; > +} -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette