@@ -2026,11 +2026,173 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
2026
2026
return klass -> build_kernel_loader_hashes (sev_common , area , ctx , errp );
2027
2027
}
2028
2028
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
+
2029
2048
static int kvm_handle_vmgexit_tio_req (SevCommonState * sev_common , struct kvm_user_vmgexit * ex )
2030
2049
{
2050
+ PCIDevice * pdev = NULL ;
2051
+ VFIOPCIDevice * vdev ;
2052
+ PCIETIOIfClass * tiok ;
2053
+ Object * tioko , * vdevko ;
2031
2054
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
+
2032
2121
ex -> tio_req .fw_err = fw_err ;
2033
2122
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 );
2034
2196
return ret ;
2035
2197
}
2036
2198
0 commit comments