On Fri, 23 Aug 2024 23:21:31 +1000 Alexey Kardashevskiy <aik@xxxxxxx> wrote: > Define tsm_ops for the guest and forward the ops calls to the HV via > SVM_VMGEXIT_SEV_TIO_GUEST_REQUEST. > Do the attestation report examination and enable MMIO. > > Signed-off-by: Alexey Kardashevskiy <aik@xxxxxxx> More trivial stuff. > diff --git a/drivers/virt/coco/sev-guest/sev_guest_tio.c b/drivers/virt/coco/sev-guest/sev_guest_tio.c > new file mode 100644 > index 000000000000..33a082e7f039 > --- /dev/null > +++ b/drivers/virt/coco/sev-guest/sev_guest_tio.c > @@ -0,0 +1,513 @@ > +static int tio_tdi_sdte_write(struct tsm_tdi *tdi, struct snp_guest_dev *snp_dev, bool invalidate) > +{ > + struct snp_guest_crypto *crypto = snp_dev->crypto; > + size_t resp_len = sizeof(struct tio_msg_sdte_write_rsp) + crypto->a_len; > + struct tio_msg_sdte_write_rsp *rsp = kzalloc(resp_len, GFP_KERNEL); > + struct tio_msg_sdte_write_req req = { > + .guest_device_id = pci_dev_id(tdi->pdev), > + .sdte.vmpl = 0, > + .sdte.vtom = tsm_vtom, > + .sdte.vtom_en = 1, > + .sdte.iw = 1, > + .sdte.ir = 1, > + .sdte.v = 1, > + }; > + u64 fw_err = 0; > + u64 bdfn = pci_dev_id(tdi->pdev); > + int rc; > + > + BUILD_BUG_ON(sizeof(struct sdte) * 8 != 512); > + > + if (invalidate) > + memset(&req, 0, sizeof(req)); Little odd to fill it then zero it. Maybe just fill it if !invalidate > + > + pci_notice(tdi->pdev, "SDTE write vTOM=%lx", (unsigned long) req.sdte.vtom << 21); > + > + if (!rsp) I'd allocate rsp down here as then obvious what is going on. > + return -ENOMEM; > + > + rc = handle_tio_guest_request(snp_dev, TIO_MSG_SDTE_WRITE_REQ, > + &req, sizeof(req), rsp, resp_len, > + NULL, NULL, &bdfn, NULL, &fw_err); > + if (rc) { > + pci_err(tdi->pdev, "SDTE write failed with 0x%llx\n", fw_err); > + goto free_exit; > + } > + > +free_exit: > + /* The response buffer contains the sensitive data, explicitly clear it. */ > + memzero_explicit(&rsp, sizeof(resp_len)); > + kfree(rsp); kfree_sensitive() perhaps? > + return rc; > +} > +static int sev_guest_tdi_validate(struct tsm_tdi *tdi, bool invalidate, void *private_data) > +{ > + struct snp_guest_dev *snp_dev = private_data; > + struct tsm_tdi_status ts = { 0 }; > + int ret; > + > + if (!tdi->report) { > + ret = tio_tdi_status(tdi, snp_dev, &ts); > + > + if (ret || !tdi->report) { > + pci_err(tdi->pdev, "No report available, ret=%d", ret); > + if (!ret && tdi->report) > + ret = -EIO; > + return ret; I'd split the error paths to simplify the logic. if (ret) { pci_err(tdi->pdev, "No report available, ret=%d", ret); return ret; } if (!tdi->report) { pci_err(... some more meaningful message) return -EIO; > + } > + > + if (ts.state != TDISP_STATE_RUN) { > + pci_err(tdi->pdev, "Not in RUN state, state=%d instead", ts.state); > + return -EIO; > + } > + } > + > + ret = tio_tdi_sdte_write(tdi, snp_dev, invalidate); > + if (ret) > + return ret; > + > + ret = tio_tdi_mmio_validate(tdi, snp_dev, invalidate); return tio_tdi_mmio_validate(); > + if (ret) > + return ret; > + > + return 0; > +}