xref: /openbmc/qemu/hw/tpm/tpm_spapr.c (revision eabfeb0c)
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 "sysemu/tpm_util.h"
24 #include "tpm_prop.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     uint32_t numbytes; /* number of bytes to deliver on resume */
80 
81     TPMBackendCmd cmd;
82 
83     TPMBackend *be_driver;
84     TPMVersion be_tpm_version;
85 
86     size_t be_buffer_size;
87 } SpaprTpmState;
88 
89 /*
90  * Send a request to the TPM.
91  */
92 static void tpm_spapr_tpm_send(SpaprTpmState *s)
93 {
94     if (trace_event_get_state_backends(TRACE_TPM_SPAPR_SHOW_BUFFER)) {
95         tpm_util_show_buffer(s->buffer, s->be_buffer_size, "To TPM");
96     }
97 
98     s->state = SPAPR_VTPM_STATE_EXECUTION;
99     s->cmd = (TPMBackendCmd) {
100         .locty = 0,
101         .in = s->buffer,
102         .in_len = MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size),
103         .out = s->buffer,
104         .out_len = s->be_buffer_size,
105     };
106 
107     tpm_backend_deliver_request(s->be_driver, &s->cmd);
108 }
109 
110 static int tpm_spapr_process_cmd(SpaprTpmState *s, uint64_t dataptr)
111 {
112     long rc;
113 
114     /* a max. of be_buffer_size bytes can be transported */
115     rc = spapr_vio_dma_read(&s->vdev, dataptr,
116                             s->buffer, s->be_buffer_size);
117     if (rc) {
118         error_report("tpm_spapr_got_payload: DMA read failure");
119     }
120     /* let vTPM handle any malformed request */
121     tpm_spapr_tpm_send(s);
122 
123     return rc;
124 }
125 
126 static inline int spapr_tpm_send_crq(struct SpaprVioDevice *dev, TpmCrq *crq)
127 {
128     return spapr_vio_send_crq(dev, (uint8_t *)crq);
129 }
130 
131 static int tpm_spapr_do_crq(struct SpaprVioDevice *dev, uint8_t *crq_data)
132 {
133     SpaprTpmState *s = VIO_SPAPR_VTPM(dev);
134     TpmCrq local_crq;
135     TpmCrq *crq = &s->crq; /* requests only */
136     int rc;
137     uint8_t valid = crq_data[0];
138     uint8_t msg = crq_data[1];
139 
140     trace_tpm_spapr_do_crq(valid, msg);
141 
142     switch (valid) {
143     case SPAPR_VTPM_VALID_INIT_CRQ_COMMAND: /* Init command/response */
144 
145         /* Respond to initialization request */
146         switch (msg) {
147         case SPAPR_VTPM_INIT_CRQ_RESULT:
148             trace_tpm_spapr_do_crq_crq_result();
149             memset(&local_crq, 0, sizeof(local_crq));
150             local_crq.valid = SPAPR_VTPM_VALID_INIT_CRQ_COMMAND;
151             local_crq.msg = SPAPR_VTPM_INIT_CRQ_RESULT;
152             spapr_tpm_send_crq(dev, &local_crq);
153             break;
154 
155         case SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT:
156             trace_tpm_spapr_do_crq_crq_complete_result();
157             memset(&local_crq, 0, sizeof(local_crq));
158             local_crq.valid = SPAPR_VTPM_VALID_INIT_CRQ_COMMAND;
159             local_crq.msg = SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT;
160             spapr_tpm_send_crq(dev, &local_crq);
161             break;
162         }
163 
164         break;
165     case SPAPR_VTPM_VALID_COMMAND: /* Payloads */
166         switch (msg) {
167         case SPAPR_VTPM_TPM_COMMAND:
168             trace_tpm_spapr_do_crq_tpm_command();
169             if (s->state == SPAPR_VTPM_STATE_EXECUTION) {
170                 return H_BUSY;
171             }
172             memcpy(crq, crq_data, sizeof(*crq));
173 
174             rc = tpm_spapr_process_cmd(s, be32_to_cpu(crq->data));
175 
176             if (rc == H_SUCCESS) {
177                 crq->valid = be16_to_cpu(0);
178             } else {
179                 local_crq.valid = SPAPR_VTPM_MSG_RESULT;
180                 local_crq.msg = SPAPR_VTPM_VTPM_ERROR;
181                 local_crq.len = cpu_to_be16(0);
182                 local_crq.data = cpu_to_be32(SPAPR_VTPM_ERR_COPY_IN_FAILED);
183                 spapr_tpm_send_crq(dev, &local_crq);
184             }
185             break;
186 
187         case SPAPR_VTPM_GET_RTCE_BUFFER_SIZE:
188             trace_tpm_spapr_do_crq_tpm_get_rtce_buffer_size(s->be_buffer_size);
189             local_crq.valid = SPAPR_VTPM_VALID_COMMAND;
190             local_crq.msg = SPAPR_VTPM_GET_RTCE_BUFFER_SIZE |
191                             SPAPR_VTPM_MSG_RESULT;
192             local_crq.len = cpu_to_be16(s->be_buffer_size);
193             spapr_tpm_send_crq(dev, &local_crq);
194             break;
195 
196         case SPAPR_VTPM_GET_VERSION:
197             local_crq.valid = SPAPR_VTPM_VALID_COMMAND;
198             local_crq.msg = SPAPR_VTPM_GET_VERSION | SPAPR_VTPM_MSG_RESULT;
199             local_crq.len = cpu_to_be16(0);
200             switch (s->be_tpm_version) {
201             case TPM_VERSION_1_2:
202                 local_crq.data = cpu_to_be32(1);
203                 break;
204             case TPM_VERSION_2_0:
205                 local_crq.data = cpu_to_be32(2);
206                 break;
207             default:
208                 g_assert_not_reached();
209                 break;
210             }
211             trace_tpm_spapr_do_crq_get_version(be32_to_cpu(local_crq.data));
212             spapr_tpm_send_crq(dev, &local_crq);
213             break;
214 
215         case SPAPR_VTPM_PREPARE_TO_SUSPEND:
216             trace_tpm_spapr_do_crq_prepare_to_suspend();
217             local_crq.valid = SPAPR_VTPM_VALID_COMMAND;
218             local_crq.msg = SPAPR_VTPM_PREPARE_TO_SUSPEND |
219                             SPAPR_VTPM_MSG_RESULT;
220             spapr_tpm_send_crq(dev, &local_crq);
221             break;
222 
223         default:
224             trace_tpm_spapr_do_crq_unknown_msg_type(crq->msg);
225         }
226         break;
227     default:
228         trace_tpm_spapr_do_crq_unknown_crq(valid, msg);
229     };
230 
231     return H_SUCCESS;
232 }
233 
234 static void tpm_spapr_request_completed(TPMIf *ti, int ret)
235 {
236     SpaprTpmState *s = VIO_SPAPR_VTPM(ti);
237     TpmCrq *crq = &s->crq;
238     uint32_t len;
239     int rc;
240 
241     s->state = SPAPR_VTPM_STATE_COMPLETION;
242 
243     /* a max. of be_buffer_size bytes can be transported */
244     len = MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size);
245 
246     if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
247         trace_tpm_spapr_caught_response(len);
248         /* defer delivery of response until .post_load */
249         s->numbytes = len;
250         return;
251     }
252 
253     rc = spapr_vio_dma_write(&s->vdev, be32_to_cpu(crq->data),
254                              s->buffer, len);
255 
256     if (trace_event_get_state_backends(TRACE_TPM_SPAPR_SHOW_BUFFER)) {
257         tpm_util_show_buffer(s->buffer, len, "From TPM");
258     }
259 
260     crq->valid = SPAPR_VTPM_MSG_RESULT;
261     if (rc == H_SUCCESS) {
262         crq->msg = SPAPR_VTPM_TPM_COMMAND | SPAPR_VTPM_MSG_RESULT;
263         crq->len = cpu_to_be16(len);
264     } else {
265         error_report("%s: DMA write failure", __func__);
266         crq->msg = SPAPR_VTPM_VTPM_ERROR;
267         crq->len = cpu_to_be16(0);
268         crq->data = cpu_to_be32(SPAPR_VTPM_ERR_COPY_OUT_FAILED);
269     }
270 
271     rc = spapr_tpm_send_crq(&s->vdev, crq);
272     if (rc) {
273         error_report("%s: Error sending response", __func__);
274     }
275 }
276 
277 static int tpm_spapr_do_startup_tpm(SpaprTpmState *s, size_t buffersize)
278 {
279     return tpm_backend_startup_tpm(s->be_driver, buffersize);
280 }
281 
282 static const char *tpm_spapr_get_dt_compatible(SpaprVioDevice *dev)
283 {
284     SpaprTpmState *s = VIO_SPAPR_VTPM(dev);
285 
286     switch (s->be_tpm_version) {
287     case TPM_VERSION_1_2:
288         return "IBM,vtpm";
289     case TPM_VERSION_2_0:
290         return "IBM,vtpm20";
291     default:
292         g_assert_not_reached();
293     }
294 }
295 
296 static void tpm_spapr_reset(SpaprVioDevice *dev)
297 {
298     SpaprTpmState *s = VIO_SPAPR_VTPM(dev);
299 
300     s->state = SPAPR_VTPM_STATE_NONE;
301     s->numbytes = 0;
302 
303     s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);
304 
305     s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver),
306                             TPM_SPAPR_BUFFER_MAX);
307 
308     tpm_backend_reset(s->be_driver);
309 
310     if (tpm_spapr_do_startup_tpm(s, s->be_buffer_size) < 0) {
311         exit(1);
312     }
313 }
314 
315 static enum TPMVersion tpm_spapr_get_version(TPMIf *ti)
316 {
317     SpaprTpmState *s = VIO_SPAPR_VTPM(ti);
318 
319     if (tpm_backend_had_startup_error(s->be_driver)) {
320         return TPM_VERSION_UNSPEC;
321     }
322 
323     return tpm_backend_get_tpm_version(s->be_driver);
324 }
325 
326 /* persistent state handling */
327 
328 static int tpm_spapr_pre_save(void *opaque)
329 {
330     SpaprTpmState *s = opaque;
331 
332     tpm_backend_finish_sync(s->be_driver);
333     /*
334      * we cannot deliver the results to the VM since DMA would touch VM memory
335      */
336 
337     return 0;
338 }
339 
340 static int tpm_spapr_post_load(void *opaque, int version_id)
341 {
342     SpaprTpmState *s = opaque;
343 
344     if (s->numbytes) {
345         trace_tpm_spapr_post_load();
346         /* deliver the results to the VM via DMA */
347         tpm_spapr_request_completed(TPM_IF(s), 0);
348         s->numbytes = 0;
349     }
350 
351     return 0;
352 }
353 
354 static const VMStateDescription vmstate_spapr_vtpm = {
355     .name = "tpm-spapr",
356     .pre_save = tpm_spapr_pre_save,
357     .post_load = tpm_spapr_post_load,
358     .fields = (VMStateField[]) {
359         VMSTATE_SPAPR_VIO(vdev, SpaprTpmState),
360 
361         VMSTATE_UINT8(state, SpaprTpmState),
362         VMSTATE_UINT32(numbytes, SpaprTpmState),
363         VMSTATE_VBUFFER_UINT32(buffer, SpaprTpmState, 0, NULL, numbytes),
364         /* remember DMA address */
365         VMSTATE_UINT32(crq.data, SpaprTpmState),
366         VMSTATE_END_OF_LIST(),
367     }
368 };
369 
370 static Property tpm_spapr_properties[] = {
371     DEFINE_SPAPR_PROPERTIES(SpaprTpmState, vdev),
372     DEFINE_PROP_TPMBE("tpmdev", SpaprTpmState, be_driver),
373     DEFINE_PROP_END_OF_LIST(),
374 };
375 
376 static void tpm_spapr_realizefn(SpaprVioDevice *dev, Error **errp)
377 {
378     SpaprTpmState *s = VIO_SPAPR_VTPM(dev);
379 
380     if (!tpm_find()) {
381         error_setg(errp, "at most one TPM device is permitted");
382         return;
383     }
384 
385     dev->crq.SendFunc = tpm_spapr_do_crq;
386 
387     if (!s->be_driver) {
388         error_setg(errp, "'tpmdev' property is required");
389         return;
390     }
391     s->buffer = g_malloc(TPM_SPAPR_BUFFER_MAX);
392 }
393 
394 static void tpm_spapr_class_init(ObjectClass *klass, void *data)
395 {
396     DeviceClass *dc = DEVICE_CLASS(klass);
397     SpaprVioDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
398     TPMIfClass *tc = TPM_IF_CLASS(klass);
399 
400     k->realize = tpm_spapr_realizefn;
401     k->reset = tpm_spapr_reset;
402     k->dt_name = "vtpm";
403     k->dt_type = "IBM,vtpm";
404     k->get_dt_compatible = tpm_spapr_get_dt_compatible;
405     k->signal_mask = 0x00000001;
406     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
407     device_class_set_props(dc, tpm_spapr_properties);
408     k->rtce_window_size = 0x10000000;
409     dc->vmsd = &vmstate_spapr_vtpm;
410 
411     tc->model = TPM_MODEL_TPM_SPAPR;
412     tc->get_version = tpm_spapr_get_version;
413     tc->request_completed = tpm_spapr_request_completed;
414 }
415 
416 static const TypeInfo tpm_spapr_info = {
417     .name          = TYPE_TPM_SPAPR,
418     .parent        = TYPE_VIO_SPAPR_DEVICE,
419     .instance_size = sizeof(SpaprTpmState),
420     .class_init    = tpm_spapr_class_init,
421     .interfaces = (InterfaceInfo[]) {
422         { TYPE_TPM_IF },
423         { }
424     }
425 };
426 
427 static void tpm_spapr_register_types(void)
428 {
429     type_register_static(&tpm_spapr_info);
430 }
431 
432 type_init(tpm_spapr_register_types)
433