Skip to content

Commit f804b65

Browse files
committed
sev: Glue KVM to IOMMUFD/vIOMMU
Handle guest exits and call SEV or IOMMUFD in the right order. Read certificates/measurements/report for the VM from sysfs. Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
1 parent fb31c96 commit f804b65

File tree

4 files changed

+170
-0
lines changed

4 files changed

+170
-0
lines changed

accel/kvm/kvm-all.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3195,6 +3195,11 @@ int kvm_ioctl(KVMState *s, int type, ...)
31953195
return ret;
31963196
}
31973197

3198+
int kvm_vmfd(KVMState *s)
3199+
{
3200+
return s->vmfd;
3201+
}
3202+
31983203
int kvm_vm_ioctl(KVMState *s, int type, ...)
31993204
{
32003205
int ret;

include/sysemu/kvm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ static inline int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_t
235235

236236
/* internal API */
237237

238+
int kvm_vmfd(KVMState *s);
239+
238240
int kvm_ioctl(KVMState *s, int type, ...);
239241

240242
int kvm_vm_ioctl(KVMState *s, int type, ...);

target/i386/sev.c

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2026,11 +2026,173 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
20262026
return klass->build_kernel_loader_hashes(sev_common, area, ctx, errp);
20272027
}
20282028

2029+
static ssize_t read_full(const char *fn, uint8_t *buf, ssize_t len)
2030+
{
2031+
int fd;
2032+
ssize_t rb;
2033+
2034+
if (len <= 0) {
2035+
return 0;
2036+
}
2037+
fd = open(fn, O_RDONLY);
2038+
if (fd < 0) {
2039+
return 0;
2040+
}
2041+
rb = read(fd, buf, len);
2042+
close(fd);
2043+
trace_sev_read_file(fn, rb);
2044+
2045+
return rb;
2046+
}
2047+
20292048
static int kvm_handle_vmgexit_tio_req(SevCommonState *sev_common, struct kvm_user_vmgexit *ex)
20302049
{
2050+
PCIDevice *pdev = NULL;
2051+
VFIOPCIDevice *vdev;
2052+
PCIETIOIfClass *tiok;
2053+
Object *tioko, *vdevko;
20312054
int ret, fw_err = 0;
2055+
char fn[128];
2056+
2057+
ret = pci_qdev_find_device_by_pciid(0 /* Domain */, PCI_BUS_NUM(ex->tio_req.guest_rid),
2058+
PCI_BDF_TO_DEVFN(ex->tio_req.guest_rid), &pdev);
2059+
if (ret) {
2060+
return ret;
2061+
}
2062+
2063+
tioko = object_dynamic_cast(OBJECT(pdev), INTERFACE_PCIE_TIO_DEVICE);
2064+
vdevko = object_dynamic_cast(OBJECT(pdev), TYPE_VFIO_PCI);
2065+
if (!tioko || !vdevko) {
2066+
return -EPERM;
2067+
}
2068+
tiok = PCIE_TIO_DEVICE_GET_CLASS(tioko);
2069+
2070+
ret = tiok->tio_bind(pdev, kvm_vmfd(kvm_state));
2071+
if (ret) {
2072+
return ret;
2073+
}
2074+
2075+
vdev = VFIO_PCI(pdev);
2076+
#define MMIO_VALIDATE_GPA(r) ((r) & 0x000FFFFFFFFFF000ULL)
2077+
#define MMIO_VALIDATE_LEN(r) (1ULL << (12 + (((r) >> 4) & 0xFF)))
2078+
#define MMIO_VALIDATE_RANGEID(r) ((r) & 0x7)
2079+
#define MMIO_VALIDATE_RESERVED(r) ((r) & 0xFFF0000000000008ULL)
2080+
if (ex->tio_req.flags & KVM_USER_VMGEXIT_TIO_REQ_FLAG_MMIO_CONFIG) {
2081+
printf("+++Q+++ (%u) %s %u: TODO FIXME MMIO_CONFIG\n", getpid(), __func__, __LINE__);
2082+
return -EINVAL;
2083+
}
2084+
2085+
if (ex->tio_req.flags & KVM_USER_VMGEXIT_TIO_REQ_FLAG_MMIO_VALIDATE) {
2086+
uint64_t mmio_gpa = MMIO_VALIDATE_GPA(ex->tio_req.mmio_gpa);
2087+
uint64_t mmio_size = MMIO_VALIDATE_LEN(ex->tio_req.mmio_gpa);
2088+
unsigned int rangeid = MMIO_VALIDATE_RANGEID(ex->tio_req.mmio_gpa);
2089+
int error = 0;
2090+
2091+
ret = kvm_set_memory_attributes_private(mmio_gpa, mmio_size);
2092+
2093+
struct kvm_sev_snp_rmp_update params = {
2094+
.flags = KVM_SEV_SNP_RMP_FLAG_PRIVATE,
2095+
.useraddr = (uint64_t) vdev->bars[rangeid].region.mmaps[0].mmap,
2096+
.gpa = mmio_gpa,
2097+
.size = mmio_size,
2098+
};
2099+
2100+
ret = sev_ioctl(sev_common->sev_fd, KVM_SEV_SNP_MMIO_RMP_UPDATE,
2101+
&params, &error);
2102+
if (ret) {
2103+
return ret;
2104+
}
2105+
trace_sev_snp_make_private(mmio_gpa, mmio_size);
2106+
}
2107+
2108+
/* Guest requests use 1 page for request and 1 page for response */
2109+
hwaddr req_len = 4096, rsp_len = 4096;
2110+
MemTxAttrs attrs = { 0 };
2111+
void *req = address_space_map(&address_space_memory, ex->tio_req.req_spa,
2112+
&req_len, false, attrs);
2113+
void *rsp = address_space_map(&address_space_memory, ex->tio_req.rsp_spa,
2114+
&rsp_len, true, attrs);
2115+
2116+
ret = tiok->tio_guest_request(pdev, req, 4096, rsp, 4096, &fw_err);
2117+
if (ret) {
2118+
return ret;
2119+
}
2120+
20322121
ex->tio_req.fw_err = fw_err;
20332122

2123+
if (ex->tio_req.data_npages) {
2124+
hwaddr data_len = ex->tio_req.data_npages << 12;
2125+
uint8_t *data = address_space_map(&address_space_memory, ex->tio_req.data_gpa,
2126+
&data_len, true, attrs);
2127+
struct tio_blob_table_entry {
2128+
QemuUUID guid;
2129+
uint32_t offset;
2130+
uint32_t length;
2131+
} QEMU_PACKED *t = (struct tio_blob_table_entry *) data;
2132+
ssize_t off = sizeof(*t) * 4, len = data_len - off;
2133+
QemuUUID certuuid = { .data =
2134+
UUID_LE(0x078ccb75, 0x2644, 0x49e8, 0xaf, 0xe7, 0x56, 0x86, 0xc5, 0xcf, 0x72, 0xf1)
2135+
};
2136+
QemuUUID measuuid = { .data =
2137+
UUID_LE(0x5caa80c6, 0x12ef, 0x401a, 0xb3, 0x64, 0xec, 0x59, 0xa9, 0x3a, 0xbe, 0x3f)
2138+
};
2139+
QemuUUID repouuid = { .data =
2140+
UUID_LE(0x70dc5b0e, 0x0cc0, 0x4cd5, 0x97, 0xbb, 0xff, 0x0b, 0xa2, 0x5b, 0xf3, 0x20)
2141+
};
2142+
2143+
snprintf(fn, sizeof(fn) - 1,
2144+
"/sys/bus/pci/devices/%04x:%02x:%02x.%01x/tsm_dev/tsm_certs",
2145+
vdev->host.domain, vdev->host.bus,
2146+
vdev->host.slot, vdev->host.function);
2147+
t[0].guid = certuuid;
2148+
t[0].offset = off;
2149+
t[0].length = read_full(fn, data + off, len);
2150+
off += t[0].length;
2151+
len -= t[0].length;
2152+
2153+
snprintf(fn, sizeof(fn) - 1,
2154+
"/sys/bus/pci/devices/%04x:%02x:%02x.%01x/tsm_dev/tsm_meas",
2155+
vdev->host.domain, vdev->host.bus,
2156+
vdev->host.slot, vdev->host.function);
2157+
t[1].guid = measuuid;
2158+
t[1].offset = off;
2159+
t[1].length = read_full(fn, data + off, len);
2160+
off += t[1].length;
2161+
len -= t[1].length;
2162+
2163+
snprintf(fn, sizeof(fn) - 1,
2164+
"/sys/bus/pci/devices/%04x:%02x:%02x.%01x/tsm-tdi/tdi:%04x:%02x:%02x.%01x/tsm_report",
2165+
vdev->host.domain, vdev->host.bus,
2166+
vdev->host.slot, vdev->host.function,
2167+
vdev->host.domain, vdev->host.bus,
2168+
vdev->host.slot, vdev->host.function);
2169+
2170+
t[2].guid = repouuid;
2171+
t[2].offset = off;
2172+
t[2].length = read_full(fn, data + off, len);
2173+
2174+
memset(&t[3], 0, sizeof(*t));
2175+
2176+
address_space_unmap(&address_space_memory, data, data_len, true, data_len);
2177+
}
2178+
2179+
if (ex->tio_req.flags & KVM_USER_VMGEXIT_TIO_REQ_FLAG_STATUS) {
2180+
snprintf(fn, sizeof(fn) - 1,
2181+
"/sys/bus/pci/devices/%04x:%02x:%02x.%01x/tsm-tdi/tdi:%04x:%02x:%02x.%01x/tsm_tdi_status",
2182+
vdev->host.domain, vdev->host.bus,
2183+
vdev->host.slot, vdev->host.function,
2184+
vdev->host.domain, vdev->host.bus,
2185+
vdev->host.slot, vdev->host.function);
2186+
2187+
if (sizeof(ex->tio_req.tdi_status) !=
2188+
read_full(fn, &ex->tio_req.tdi_status, sizeof(ex->tio_req.tdi_status))) {
2189+
ex->tio_req.tdi_status = 0;
2190+
}
2191+
trace_sev_snp_tdi_status(vdev->vbasedev.name, ex->tio_req.tdi_status);
2192+
}
2193+
2194+
address_space_unmap(&address_space_memory, req, req_len, false, req_len);
2195+
address_space_unmap(&address_space_memory, rsp, rsp_len, true, rsp_len);
20342196
return ret;
20352197
}
20362198

target/i386/trace-events

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ kvm_sev_snp_launch_start(uint64_t policy, char *gosvw) "policy 0x%" PRIx64 " gos
1515
kvm_sev_snp_launch_update(uint64_t src, uint64_t gpa, uint64_t len, const char *type) "src 0x%" PRIx64 " gpa 0x%" PRIx64 " len 0x%" PRIx64 " (%s page)"
1616
kvm_sev_snp_launch_finish(char *id_block, char *id_auth, char *host_data) "id_block %s id_auth %s host_data %s"
1717
sev_platform_ioctl(int fd, int cmd, int ret, int psperror) "fd=%d cmd=0x%x ret=%d psp=%d"
18+
sev_read_file(const char *fn, ssize_t rb) "Read %s => %ld bytes"
1819
sev_snp_make_private(uint64_t addr, uint64_t size) "addr=0x%" PRIx64 " size=0x%" PRIx64
1920
sev_snp_tdi_status(const char *dev, unsigned status) "%s TDI status is %d"

0 commit comments

Comments
 (0)