[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH kernel 14/17] x86/sev: Add GHCB calls for SEV-TIO



SEV-TIO is a PSP protocol allowing PCI pass through of trusted devices
(TDI == TEE Device Interface) to an SNP VM. The VMM advertises
the support via HV_FEATURES and implements new calls:

1) TDI operation: the host executes on the guest behalf:
- TDI bind/unbind to/from the SNP VM in the PSP;
- TDI start/stop which translates to TDISP interface start/stop.

2) TIO guest request for an encrypted communication channel between
the SNP VM and the PSP, it follows the existing Extended Guest Request
pattern to read device evidence:
- get TDI status;
- validate MMIO ranges (a variant of the PVALIDATE instruction for
  MMIO RMPs);
- configure sDTE (a secure IOMMU descriptor).

Extend snp_req_data to pass more parameters.

Signed-off-by: Alexey Kardashevskiy <aik@xxxxxxx>
---
 arch/x86/include/asm/sev-common.h |  1 +
 arch/x86/include/asm/sev.h        |  5 +++
 arch/x86/include/uapi/asm/svm.h   | 40 +++++++++++++++++++
 arch/x86/coco/sev/core.c          | 42 ++++++++++++++++++++
 4 files changed, 88 insertions(+)

diff --git a/arch/x86/include/asm/sev-common.h 
b/arch/x86/include/asm/sev-common.h
index 01a6e4dbe423..ff763c3c5d63 100644
--- a/arch/x86/include/asm/sev-common.h
+++ b/arch/x86/include/asm/sev-common.h
@@ -137,6 +137,7 @@ enum psc_op {
 #define GHCB_HV_FT_SNP                 BIT_ULL(0)
 #define GHCB_HV_FT_SNP_AP_CREATION     BIT_ULL(1)
 #define GHCB_HV_FT_SNP_MULTI_VMPL      BIT_ULL(5)
+#define GHCB_HV_FT_SNP_SEV_TIO         BIT_ULL(7)
 
 /*
  * SNP Page State Change NAE event
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 9e7a077c445d..89aaccb053ba 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -149,6 +149,9 @@ struct snp_req_data {
        unsigned long resp_gpa;
        unsigned long data_gpa;
        unsigned int data_npages;
+       unsigned int guest_rid;
+       unsigned long npages;
+       unsigned long param;
 };
 
 #define MAX_AUTHTAG_LEN                32
@@ -597,6 +600,8 @@ static inline void sev_evict_cache(void *va, int npages)
        }
 }
 
+int sev_tio_op(u32 guest_rid, unsigned int op, u64 *fw_err, u64 *tdi_id);
+
 #else  /* !CONFIG_AMD_MEM_ENCRYPT */
 
 #define snp_vmpl 0
diff --git a/arch/x86/include/uapi/asm/svm.h b/arch/x86/include/uapi/asm/svm.h
index 010a45c9f614..93597ad492bf 100644
--- a/arch/x86/include/uapi/asm/svm.h
+++ b/arch/x86/include/uapi/asm/svm.h
@@ -122,6 +122,44 @@
 #define SVM_VMGEXIT_SAVIC_REGISTER_GPA         0
 #define SVM_VMGEXIT_SAVIC_UNREGISTER_GPA       1
 #define SVM_VMGEXIT_SAVIC_SELF_GPA             ~0ULL
+#define SVM_VMGEXIT_SEV_TIO_GR                 0x80000020ull
+#define SVM_VMGEXIT_SEV_TIO_GR_INFO_STATE      BIT(0)
+#define SVM_VMGEXIT_SEV_TIO_GR_INFO_CERTS      BIT(1)
+#define SVM_VMGEXIT_SEV_TIO_GR_INFO_MEAS       BIT(2)
+#define SVM_VMGEXIT_SEV_TIO_GR_INFO_REPORT     BIT(3)
+
+#define SVM_VMGEXIT_SEV_TIO_GR_SDTE_VALIDATE   BIT(0)
+#define SVM_VMGEXIT_SEV_TIO_GR_SDTE_VTOM       GENMASK_ULL(51, 21)
+
+/*
+ * TIO_GUEST_REQUEST's MMIO_VALIDATE_REQ/MMIO_CONFIG_REQ encoding for MMIO in 
RDX:
+ *
+ * T....... ....GGGG GGGGGGGG GGGGGGGG GGGGGGGG GGGGGGGG GGGG.... ........
+ * Where:
+ *     G - guest physical address
+ *     T - TEE
+ */
+#define SVM_VMGEXIT_SEV_TIO_GR_MMIO_GFN(r)      (((r) & 0x000FFFFFFFFFF000ULL) 
>> PAGE_SHIFT)
+#define SVM_VMGEXIT_SEV_TIO_GR_MMIO_RESERVED(r) ((r) & 0x7FF0000000000FFFULL)
+#define SVM_VMGEXIT_SEV_TIO_GR_MMIO_PRIVATE(r)  (!!((r) & BIT(63)))
+
+#define SVM_VMGEXIT_SEV_TIO_GR_MMIO_NUM(r)      ((uint32_t)((r) >> 32))
+#define SVM_VMGEXIT_SEV_TIO_GR_MMIO_ADDR(r)     ((uint32_t)((r) & 0xFFFFFFFF))
+
+#define SVM_VMGEXIT_SEV_TIO_GR_MMIO_MK_VALIDATE(start, private) \
+       ((SVM_VMGEXIT_SEV_TIO_GR_MMIO_GFN(start) << PAGE_SHIFT) | \
+       ((private) ? BIT(63) : 0))
+
+#define SVM_VMGEXIT_SEV_TIO_OP                 0x80000021ull
+#define SVM_VMGEXIT_SEV_TIO_GR_MMIO_MK_NUM_BDFN(n, bdfn) (((uint64_t)(n) << 
32) | (bdfn))
+
+#define SVM_VMGEXIT_SEV_TIO_OP_PARAM(guest_id, action) 
((u64)(action)<<32|(guest_id))
+#define SVM_VMGEXIT_SEV_TIO_OP_ACTION(exitinfo1)       ((exitinfo1)>>32)
+#define SVM_VMGEXIT_SEV_TIO_OP_GUEST_ID(exitinfo1)     ((exitinfo1) & 
0xFFFFFFFF)
+#define SVM_VMGEXIT_SEV_TIO_OP_BIND    0
+#define SVM_VMGEXIT_SEV_TIO_OP_UNBIND  1
+#define SVM_VMGEXIT_SEV_TIO_OP_RUN     2
+#define SVM_VMGEXIT_SEV_TIO_OP_STOP    3
 #define SVM_VMGEXIT_HV_FEATURES                        0x8000fffdull
 #define SVM_VMGEXIT_TERM_REQUEST               0x8000fffeull
 #define SVM_VMGEXIT_TERM_REASON(reason_set, reason_code)       \
@@ -245,6 +283,8 @@
        { SVM_VMGEXIT_GUEST_REQUEST,    "vmgexit_guest_request" }, \
        { SVM_VMGEXIT_EXT_GUEST_REQUEST, "vmgexit_ext_guest_request" }, \
        { SVM_VMGEXIT_AP_CREATION,      "vmgexit_ap_creation" }, \
+       { SVM_VMGEXIT_SEV_TIO_GR,       "vmgexit_sev_tio_guest_request" }, \
+       { SVM_VMGEXIT_SEV_TIO_OP,       "vmgexit_sev_tio_op" }, \
        { SVM_VMGEXIT_HV_FEATURES,      "vmgexit_hypervisor_feature" }, \
        { SVM_EXIT_ERR,         "invalid_guest_state" }
 
diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
index 5b912f42f493..ed0e4546d5e5 100644
--- a/arch/x86/coco/sev/core.c
+++ b/arch/x86/coco/sev/core.c
@@ -104,6 +104,37 @@ static unsigned long snp_tsc_freq_khz __ro_after_init;
 DEFINE_PER_CPU(struct sev_es_runtime_data*, runtime_data);
 DEFINE_PER_CPU(struct sev_es_save_area *, sev_vmsa);
 
+int sev_tio_op(u32 guest_rid, unsigned int op, u64 *fw_err, u64 *tdi_id)
+{
+       struct ghcb_state state;
+       struct es_em_ctxt ctxt;
+       struct ghcb *ghcb;
+       int ret;
+
+       /* __sev_get_ghcb() needs IRQs disabled because it uses per-CPU GHCB. */
+       guard(irqsave)();
+
+       ghcb = __sev_get_ghcb(&state);
+       if (!ghcb)
+               return -EIO;
+
+       vc_ghcb_invalidate(ghcb);
+       ret = sev_es_ghcb_hv_call(ghcb, &ctxt, SVM_VMGEXIT_SEV_TIO_OP,
+                                 SVM_VMGEXIT_SEV_TIO_OP_PARAM(guest_rid, op), 
0);
+
+       *fw_err = ghcb->save.sw_exit_info_2;
+       if (*fw_err)
+               ret = -EIO;
+
+       if (!ret && op == SVM_VMGEXIT_SEV_TIO_OP_BIND && tdi_id)
+               *tdi_id = ghcb_get_rcx(ghcb);
+
+       __sev_put_ghcb(&state);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(sev_tio_op);
+
 /*
  * SVSM related information:
  *   When running under an SVSM, the VMPL that Linux is executing at must be
@@ -1345,6 +1376,11 @@ static int snp_issue_guest_request(struct snp_guest_req 
*req)
        if (req->exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) {
                ghcb_set_rax(ghcb, input->data_gpa);
                ghcb_set_rbx(ghcb, input->data_npages);
+       } else if (req->exit_code == SVM_VMGEXIT_SEV_TIO_GR) {
+               ghcb_set_rax(ghcb, input->data_gpa);
+               ghcb_set_rbx(ghcb, input->data_npages);
+               ghcb_set_rcx(ghcb, ((uint64_t)input->npages << 32) | 
input->guest_rid);
+               ghcb_set_rdx(ghcb, input->param);
        }
 
        ret = sev_es_ghcb_hv_call(ghcb, &ctxt, req->exit_code, input->req_gpa, 
input->resp_gpa);
@@ -1354,6 +1390,8 @@ static int snp_issue_guest_request(struct snp_guest_req 
*req)
        req->exitinfo2 = ghcb->save.sw_exit_info_2;
        switch (req->exitinfo2) {
        case 0:
+               if (req->exit_code == SVM_VMGEXIT_SEV_TIO_GR)
+                       input->param = ghcb_get_rdx(ghcb);
                break;
 
        case SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_BUSY):
@@ -1366,6 +1404,10 @@ static int snp_issue_guest_request(struct snp_guest_req 
*req)
                        input->data_npages = ghcb_get_rbx(ghcb);
                        ret = -ENOSPC;
                        break;
+               } else if (req->exit_code == SVM_VMGEXIT_SEV_TIO_GR) {
+                       input->data_npages = ghcb_get_rbx(ghcb);
+                       ret = -ENOSPC;
+                       break;
                }
                fallthrough;
        default:
-- 
2.55.0




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.