1 /* 2 * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator 3 * 4 * PAPR Virtual TPM 5 * 6 * Copyright (c) 2015, 2017, 2019 IBM Corporation. 7 * 8 * Authors: 9 * Stefan Berger <stefanb@linux.vnet.ibm.com> 10 * 11 * This code is licensed under the GPL version 2 or later. See the 12 * COPYING file in the top-level directory. 13 * 14 */ 15 16 #include "qemu/osdep.h" 17 #include "qemu/error-report.h" 18 #include "qapi/error.h" 19 #include "hw/qdev-properties.h" 20 #include "migration/vmstate.h" 21 22 #include "sysemu/tpm_backend.h" 23 #include "tpm_int.h" 24 #include "tpm_util.h" 25 26 #include "hw/ppc/spapr.h" 27 #include "hw/ppc/spapr_vio.h" 28 #include "trace.h" 29 30 #define DEBUG_SPAPR 0 31 32 #define VIO_SPAPR_VTPM(obj) \ 33 OBJECT_CHECK(SpaprTpmState, (obj), TYPE_TPM_SPAPR) 34 35 typedef struct TpmCrq { 36 uint8_t valid; /* 0x80: cmd; 0xc0: init crq */ 37 /* 0x81-0x83: CRQ message response */ 38 uint8_t msg; /* see below */ 39 uint16_t len; /* len of TPM request; len of TPM response */ 40 uint32_t data; /* rtce_dma_handle when sending TPM request */ 41 uint64_t reserved; 42 } TpmCrq; 43 44 #define SPAPR_VTPM_VALID_INIT_CRQ_COMMAND 0xC0 45 #define SPAPR_VTPM_VALID_COMMAND 0x80 46 #define SPAPR_VTPM_MSG_RESULT 0x80 47 48 /* msg types for valid = SPAPR_VTPM_VALID_INIT_CRQ */ 49 #define SPAPR_VTPM_INIT_CRQ_RESULT 0x1 50 #define SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT 0x2 51 52 /* msg types for valid = SPAPR_VTPM_VALID_CMD */ 53 #define SPAPR_VTPM_GET_VERSION 0x1 54 #define SPAPR_VTPM_TPM_COMMAND 0x2 55 #define SPAPR_VTPM_GET_RTCE_BUFFER_SIZE 0x3 56 #define SPAPR_VTPM_PREPARE_TO_SUSPEND 0x4 57 58 /* response error messages */ 59 #define SPAPR_VTPM_VTPM_ERROR 0xff 60 61 /* error codes */ 62 #define SPAPR_VTPM_ERR_COPY_IN_FAILED 0x3 63 #define SPAPR_VTPM_ERR_COPY_OUT_FAILED 0x4 64 65 #define TPM_SPAPR_BUFFER_MAX 4096 66 67 typedef struct { 68 SpaprVioDevice vdev; 69 70 TpmCrq crq; /* track single TPM command */ 71 72 uint8_t state; 73 #define SPAPR_VTPM_STATE_NONE 0 74 #define SPAPR_VTPM_STATE_EXECUTION 1 75 #define SPAPR_VTPM_STATE_COMPLETION 2 76 77 unsigned char *buffer; 78 79 TPMBackendCmd cmd; 80 81 TPMBackend *be_driver; 82 TPMVersion be_tpm_version; 83 84 size_t be_buffer_size; 85 } SpaprTpmState; 86 87 /* 88 * Send a request to the TPM. 89 */ 90 static void tpm_spapr_tpm_send(SpaprTpmState *s) 91 { 92 if (trace_event_get_state_backends(TRACE_TPM_SPAPR_SHOW_BUFFER)) { 93 tpm_util_show_buffer(s->buffer, s->be_buffer_size, "To TPM"); 94 } 95 96 s->state = SPAPR_VTPM_STATE_EXECUTION; 97 s->cmd = (TPMBackendCmd) { 98 .locty = 0, 99 .in = s->buffer, 100 .in_len = MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size), 101 .out = s->buffer, 102 .out_len = s->be_buffer_size, 103 }; 104 105 tpm_backend_deliver_request(s->be_driver, &s->cmd); 106 } 107 108 static int tpm_spapr_process_cmd(SpaprTpmState *s, uint64_t dataptr) 109 { 110 long rc; 111 112 /* a max. of be_buffer_size bytes can be transported */ 113 rc = spapr_vio_dma_read(&s->vdev, dataptr, 114 s->buffer, s->be_buffer_size); 115 if (rc) { 116 error_report("tpm_spapr_got_payload: DMA read failure"); 117 } 118 /* let vTPM handle any malformed request */ 119 tpm_spapr_tpm_send(s); 120 121 return rc; 122 } 123 124 static inline int spapr_tpm_send_crq(struct SpaprVioDevice *dev, TpmCrq *crq) 125 { 126 return spapr_vio_send_crq(dev, (uint8_t *)crq); 127 } 128 129 static int tpm_spapr_do_crq(struct SpaprVioDevice *dev, uint8_t *crq_data) 130 { 131 SpaprTpmState *s = VIO_SPAPR_VTPM(dev); 132 TpmCrq local_crq; 133 TpmCrq *crq = &s->crq; /* requests only */ 134 int rc; 135 uint8_t valid = crq_data[0]; 136 uint8_t msg = crq_data[1]; 137 138 trace_tpm_spapr_do_crq(valid, msg); 139 140 switch (valid) { 141 case SPAPR_VTPM_VALID_INIT_CRQ_COMMAND: /* Init command/response */ 142 143 /* Respond to initialization request */ 144 switch (msg) { 145 case SPAPR_VTPM_INIT_CRQ_RESULT: 146 trace_tpm_spapr_do_crq_crq_result(); 147 memset(&local_crq, 0, sizeof(local_crq)); 148 local_crq.valid = SPAPR_VTPM_VALID_INIT_CRQ_COMMAND; 149 local_crq.msg = SPAPR_VTPM_INIT_CRQ_RESULT; 150 spapr_tpm_send_crq(dev, &local_crq); 151 break; 152 153 case SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT: 154 trace_tpm_spapr_do_crq_crq_complete_result(); 155 memset(&local_crq, 0, sizeof(local_crq)); 156 local_crq.valid = SPAPR_VTPM_VALID_INIT_CRQ_COMMAND; 157 local_crq.msg = SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT; 158 spapr_tpm_send_crq(dev, &local_crq); 159 break; 160 } 161 162 break; 163 case SPAPR_VTPM_VALID_COMMAND: /* Payloads */ 164 switch (msg) { 165 case SPAPR_VTPM_TPM_COMMAND: 166 trace_tpm_spapr_do_crq_tpm_command(); 167 if (s->state == SPAPR_VTPM_STATE_EXECUTION) { 168 return H_BUSY; 169 } 170 memcpy(crq, crq_data, sizeof(*crq)); 171 172 rc = tpm_spapr_process_cmd(s, be32_to_cpu(crq->data)); 173 174 if (rc == H_SUCCESS) { 175 crq->valid = be16_to_cpu(0); 176 } else { 177 local_crq.valid = SPAPR_VTPM_MSG_RESULT; 178 local_crq.msg = SPAPR_VTPM_VTPM_ERROR; 179 local_crq.len = cpu_to_be16(0); 180 local_crq.data = cpu_to_be32(SPAPR_VTPM_ERR_COPY_IN_FAILED); 181 spapr_tpm_send_crq(dev, &local_crq); 182 } 183 break; 184 185 case SPAPR_VTPM_GET_RTCE_BUFFER_SIZE: 186 trace_tpm_spapr_do_crq_tpm_get_rtce_buffer_size(s->be_buffer_size); 187 local_crq.valid = SPAPR_VTPM_VALID_COMMAND; 188 local_crq.msg = SPAPR_VTPM_GET_RTCE_BUFFER_SIZE | 189 SPAPR_VTPM_MSG_RESULT; 190 local_crq.len = cpu_to_be16(s->be_buffer_size); 191 spapr_tpm_send_crq(dev, &local_crq); 192 break; 193 194 case SPAPR_VTPM_GET_VERSION: 195 local_crq.valid = SPAPR_VTPM_VALID_COMMAND; 196 local_crq.msg = SPAPR_VTPM_GET_VERSION | SPAPR_VTPM_MSG_RESULT; 197 local_crq.len = cpu_to_be16(0); 198 switch (s->be_tpm_version) { 199 case TPM_VERSION_1_2: 200 local_crq.data = cpu_to_be32(1); 201 break; 202 case TPM_VERSION_2_0: 203 local_crq.data = cpu_to_be32(2); 204 break; 205 default: 206 g_assert_not_reached(); 207 break; 208 } 209 trace_tpm_spapr_do_crq_get_version(be32_to_cpu(local_crq.data)); 210 spapr_tpm_send_crq(dev, &local_crq); 211 break; 212 213 case SPAPR_VTPM_PREPARE_TO_SUSPEND: 214 trace_tpm_spapr_do_crq_prepare_to_suspend(); 215 local_crq.valid = SPAPR_VTPM_VALID_COMMAND; 216 local_crq.msg = SPAPR_VTPM_PREPARE_TO_SUSPEND | 217 SPAPR_VTPM_MSG_RESULT; 218 spapr_tpm_send_crq(dev, &local_crq); 219 break; 220 221 default: 222 trace_tpm_spapr_do_crq_unknown_msg_type(crq->msg); 223 } 224 break; 225 default: 226 trace_tpm_spapr_do_crq_unknown_crq(valid, msg); 227 }; 228 229 return H_SUCCESS; 230 } 231 232 static void tpm_spapr_request_completed(TPMIf *ti, int ret) 233 { 234 SpaprTpmState *s = VIO_SPAPR_VTPM(ti); 235 TpmCrq *crq = &s->crq; 236 uint32_t len; 237 int rc; 238 239 s->state = SPAPR_VTPM_STATE_COMPLETION; 240 241 /* a max. of be_buffer_size bytes can be transported */ 242 len = MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size); 243 rc = spapr_vio_dma_write(&s->vdev, be32_to_cpu(crq->data), 244 s->buffer, len); 245 246 if (trace_event_get_state_backends(TRACE_TPM_SPAPR_SHOW_BUFFER)) { 247 tpm_util_show_buffer(s->buffer, len, "From TPM"); 248 } 249 250 crq->valid = SPAPR_VTPM_MSG_RESULT; 251 if (rc == H_SUCCESS) { 252 crq->msg = SPAPR_VTPM_TPM_COMMAND | SPAPR_VTPM_MSG_RESULT; 253 crq->len = cpu_to_be16(len); 254 } else { 255 error_report("%s: DMA write failure", __func__); 256 crq->msg = SPAPR_VTPM_VTPM_ERROR; 257 crq->len = cpu_to_be16(0); 258 crq->data = cpu_to_be32(SPAPR_VTPM_ERR_COPY_OUT_FAILED); 259 } 260 261 rc = spapr_tpm_send_crq(&s->vdev, crq); 262 if (rc) { 263 error_report("%s: Error sending response", __func__); 264 } 265 } 266 267 static int tpm_spapr_do_startup_tpm(SpaprTpmState *s, size_t buffersize) 268 { 269 return tpm_backend_startup_tpm(s->be_driver, buffersize); 270 } 271 272 static const char *tpm_spapr_get_dt_compatible(SpaprVioDevice *dev) 273 { 274 SpaprTpmState *s = VIO_SPAPR_VTPM(dev); 275 276 switch (s->be_tpm_version) { 277 case TPM_VERSION_1_2: 278 return "IBM,vtpm"; 279 case TPM_VERSION_2_0: 280 return "IBM,vtpm20"; 281 default: 282 g_assert_not_reached(); 283 } 284 } 285 286 static void tpm_spapr_reset(SpaprVioDevice *dev) 287 { 288 SpaprTpmState *s = VIO_SPAPR_VTPM(dev); 289 290 s->state = SPAPR_VTPM_STATE_NONE; 291 292 s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver); 293 294 s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver), 295 TPM_SPAPR_BUFFER_MAX); 296 297 tpm_backend_reset(s->be_driver); 298 tpm_spapr_do_startup_tpm(s, s->be_buffer_size); 299 } 300 301 static enum TPMVersion tpm_spapr_get_version(TPMIf *ti) 302 { 303 SpaprTpmState *s = VIO_SPAPR_VTPM(ti); 304 305 if (tpm_backend_had_startup_error(s->be_driver)) { 306 return TPM_VERSION_UNSPEC; 307 } 308 309 return tpm_backend_get_tpm_version(s->be_driver); 310 } 311 312 static const VMStateDescription vmstate_spapr_vtpm = { 313 .name = "tpm-spapr", 314 .unmigratable = 1, 315 }; 316 317 static Property tpm_spapr_properties[] = { 318 DEFINE_SPAPR_PROPERTIES(SpaprTpmState, vdev), 319 DEFINE_PROP_TPMBE("tpmdev", SpaprTpmState, be_driver), 320 DEFINE_PROP_END_OF_LIST(), 321 }; 322 323 static void tpm_spapr_realizefn(SpaprVioDevice *dev, Error **errp) 324 { 325 SpaprTpmState *s = VIO_SPAPR_VTPM(dev); 326 327 if (!tpm_find()) { 328 error_setg(errp, "at most one TPM device is permitted"); 329 return; 330 } 331 332 dev->crq.SendFunc = tpm_spapr_do_crq; 333 334 if (!s->be_driver) { 335 error_setg(errp, "'tpmdev' property is required"); 336 return; 337 } 338 s->buffer = g_malloc(TPM_SPAPR_BUFFER_MAX); 339 } 340 341 static void tpm_spapr_class_init(ObjectClass *klass, void *data) 342 { 343 DeviceClass *dc = DEVICE_CLASS(klass); 344 SpaprVioDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass); 345 TPMIfClass *tc = TPM_IF_CLASS(klass); 346 347 k->realize = tpm_spapr_realizefn; 348 k->reset = tpm_spapr_reset; 349 k->dt_name = "vtpm"; 350 k->dt_type = "IBM,vtpm"; 351 k->get_dt_compatible = tpm_spapr_get_dt_compatible; 352 k->signal_mask = 0x00000001; 353 set_bit(DEVICE_CATEGORY_MISC, dc->categories); 354 device_class_set_props(dc, tpm_spapr_properties); 355 k->rtce_window_size = 0x10000000; 356 dc->vmsd = &vmstate_spapr_vtpm; 357 358 tc->model = TPM_MODEL_TPM_SPAPR; 359 tc->get_version = tpm_spapr_get_version; 360 tc->request_completed = tpm_spapr_request_completed; 361 } 362 363 static const TypeInfo tpm_spapr_info = { 364 .name = TYPE_TPM_SPAPR, 365 .parent = TYPE_VIO_SPAPR_DEVICE, 366 .instance_size = sizeof(SpaprTpmState), 367 .class_init = tpm_spapr_class_init, 368 .interfaces = (InterfaceInfo[]) { 369 { TYPE_TPM_IF }, 370 { } 371 } 372 }; 373 374 static void tpm_spapr_register_types(void) 375 { 376 type_register_static(&tpm_spapr_info); 377 } 378 379 type_init(tpm_spapr_register_types) 380