2 * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
6 * Copyright (c) 2015, 2017, 2019 IBM Corporation.
9 * Stefan Berger <stefanb@linux.vnet.ibm.com>
11 * This code is licensed under the GPL version 2 or later. See the
12 * COPYING file in the top-level directory.
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"
22 #include "sysemu/tpm_backend.h"
23 #include "sysemu/tpm_util.h"
26 #include "hw/ppc/spapr.h"
27 #include "hw/ppc/spapr_vio.h"
29 #include "qom/object.h"
33 typedef struct SpaprTpmState SpaprTpmState
;
34 DECLARE_INSTANCE_CHECKER(SpaprTpmState
, VIO_SPAPR_VTPM
,
37 typedef struct TpmCrq
{
38 uint8_t valid
; /* 0x80: cmd; 0xc0: init crq */
39 /* 0x81-0x83: CRQ message response */
40 uint8_t msg
; /* see below */
41 uint16_t len
; /* len of TPM request; len of TPM response */
42 uint32_t data
; /* rtce_dma_handle when sending TPM request */
46 #define SPAPR_VTPM_VALID_INIT_CRQ_COMMAND 0xC0
47 #define SPAPR_VTPM_VALID_COMMAND 0x80
48 #define SPAPR_VTPM_MSG_RESULT 0x80
50 /* msg types for valid = SPAPR_VTPM_VALID_INIT_CRQ */
51 #define SPAPR_VTPM_INIT_CRQ_RESULT 0x1
52 #define SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT 0x2
54 /* msg types for valid = SPAPR_VTPM_VALID_CMD */
55 #define SPAPR_VTPM_GET_VERSION 0x1
56 #define SPAPR_VTPM_TPM_COMMAND 0x2
57 #define SPAPR_VTPM_GET_RTCE_BUFFER_SIZE 0x3
58 #define SPAPR_VTPM_PREPARE_TO_SUSPEND 0x4
60 /* response error messages */
61 #define SPAPR_VTPM_VTPM_ERROR 0xff
64 #define SPAPR_VTPM_ERR_COPY_IN_FAILED 0x3
65 #define SPAPR_VTPM_ERR_COPY_OUT_FAILED 0x4
67 #define TPM_SPAPR_BUFFER_MAX 4096
69 struct SpaprTpmState
{
72 TpmCrq crq
; /* track single TPM command */
75 #define SPAPR_VTPM_STATE_NONE 0
76 #define SPAPR_VTPM_STATE_EXECUTION 1
77 #define SPAPR_VTPM_STATE_COMPLETION 2
79 unsigned char *buffer
;
81 uint32_t numbytes
; /* number of bytes to deliver on resume */
85 TPMBackend
*be_driver
;
86 TPMVersion be_tpm_version
;
88 size_t be_buffer_size
;
92 * Send a request to the TPM.
94 static void tpm_spapr_tpm_send(SpaprTpmState
*s
)
96 tpm_util_show_buffer(s
->buffer
, s
->be_buffer_size
, "To TPM");
98 s
->state
= SPAPR_VTPM_STATE_EXECUTION
;
99 s
->cmd
= (TPMBackendCmd
) {
102 .in_len
= MIN(tpm_cmd_get_size(s
->buffer
), s
->be_buffer_size
),
104 .out_len
= s
->be_buffer_size
,
107 tpm_backend_deliver_request(s
->be_driver
, &s
->cmd
);
110 static int tpm_spapr_process_cmd(SpaprTpmState
*s
, uint64_t dataptr
)
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
);
118 error_report("tpm_spapr_got_payload: DMA read failure");
120 /* let vTPM handle any malformed request */
121 tpm_spapr_tpm_send(s
);
126 static inline int spapr_tpm_send_crq(struct SpaprVioDevice
*dev
, TpmCrq
*crq
)
128 return spapr_vio_send_crq(dev
, (uint8_t *)crq
);
131 static int tpm_spapr_do_crq(struct SpaprVioDevice
*dev
, uint8_t *crq_data
)
133 SpaprTpmState
*s
= VIO_SPAPR_VTPM(dev
);
135 TpmCrq
*crq
= &s
->crq
; /* requests only */
137 uint8_t valid
= crq_data
[0];
138 uint8_t msg
= crq_data
[1];
140 trace_tpm_spapr_do_crq(valid
, msg
);
143 case SPAPR_VTPM_VALID_INIT_CRQ_COMMAND
: /* Init command/response */
145 /* Respond to initialization request */
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
);
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
);
165 case SPAPR_VTPM_VALID_COMMAND
: /* Payloads */
167 case SPAPR_VTPM_TPM_COMMAND
:
168 trace_tpm_spapr_do_crq_tpm_command();
169 if (s
->state
== SPAPR_VTPM_STATE_EXECUTION
) {
172 memcpy(crq
, crq_data
, sizeof(*crq
));
174 rc
= tpm_spapr_process_cmd(s
, be32_to_cpu(crq
->data
));
176 if (rc
== H_SUCCESS
) {
177 crq
->valid
= be16_to_cpu(0);
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
);
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
);
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);
204 case TPM_VERSION_2_0
:
205 local_crq
.data
= cpu_to_be32(2);
208 g_assert_not_reached();
211 trace_tpm_spapr_do_crq_get_version(be32_to_cpu(local_crq
.data
));
212 spapr_tpm_send_crq(dev
, &local_crq
);
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
);
224 trace_tpm_spapr_do_crq_unknown_msg_type(crq
->msg
);
228 trace_tpm_spapr_do_crq_unknown_crq(valid
, msg
);
234 static void tpm_spapr_request_completed(TPMIf
*ti
, int ret
)
236 SpaprTpmState
*s
= VIO_SPAPR_VTPM(ti
);
237 TpmCrq
*crq
= &s
->crq
;
241 s
->state
= SPAPR_VTPM_STATE_COMPLETION
;
243 /* a max. of be_buffer_size bytes can be transported */
244 len
= MIN(tpm_cmd_get_size(s
->buffer
), s
->be_buffer_size
);
246 if (runstate_check(RUN_STATE_FINISH_MIGRATE
)) {
247 trace_tpm_spapr_caught_response(len
);
248 /* defer delivery of response until .post_load */
253 rc
= spapr_vio_dma_write(&s
->vdev
, be32_to_cpu(crq
->data
),
256 tpm_util_show_buffer(s
->buffer
, len
, "From TPM");
258 crq
->valid
= SPAPR_VTPM_MSG_RESULT
;
259 if (rc
== H_SUCCESS
) {
260 crq
->msg
= SPAPR_VTPM_TPM_COMMAND
| SPAPR_VTPM_MSG_RESULT
;
261 crq
->len
= cpu_to_be16(len
);
263 error_report("%s: DMA write failure", __func__
);
264 crq
->msg
= SPAPR_VTPM_VTPM_ERROR
;
265 crq
->len
= cpu_to_be16(0);
266 crq
->data
= cpu_to_be32(SPAPR_VTPM_ERR_COPY_OUT_FAILED
);
269 rc
= spapr_tpm_send_crq(&s
->vdev
, crq
);
271 error_report("%s: Error sending response", __func__
);
275 static int tpm_spapr_do_startup_tpm(SpaprTpmState
*s
, size_t buffersize
)
277 return tpm_backend_startup_tpm(s
->be_driver
, buffersize
);
280 static const char *tpm_spapr_get_dt_compatible(SpaprVioDevice
*dev
)
282 SpaprTpmState
*s
= VIO_SPAPR_VTPM(dev
);
284 switch (s
->be_tpm_version
) {
285 case TPM_VERSION_1_2
:
287 case TPM_VERSION_2_0
:
290 g_assert_not_reached();
294 static void tpm_spapr_reset(SpaprVioDevice
*dev
)
296 SpaprTpmState
*s
= VIO_SPAPR_VTPM(dev
);
298 s
->state
= SPAPR_VTPM_STATE_NONE
;
301 s
->be_tpm_version
= tpm_backend_get_tpm_version(s
->be_driver
);
303 s
->be_buffer_size
= MIN(tpm_backend_get_buffer_size(s
->be_driver
),
304 TPM_SPAPR_BUFFER_MAX
);
306 tpm_backend_reset(s
->be_driver
);
308 if (tpm_spapr_do_startup_tpm(s
, s
->be_buffer_size
) < 0) {
313 static enum TPMVersion
tpm_spapr_get_version(TPMIf
*ti
)
315 SpaprTpmState
*s
= VIO_SPAPR_VTPM(ti
);
317 if (tpm_backend_had_startup_error(s
->be_driver
)) {
318 return TPM_VERSION_UNSPEC
;
321 return tpm_backend_get_tpm_version(s
->be_driver
);
324 /* persistent state handling */
326 static int tpm_spapr_pre_save(void *opaque
)
328 SpaprTpmState
*s
= opaque
;
330 tpm_backend_finish_sync(s
->be_driver
);
332 * we cannot deliver the results to the VM since DMA would touch VM memory
338 static int tpm_spapr_post_load(void *opaque
, int version_id
)
340 SpaprTpmState
*s
= opaque
;
343 trace_tpm_spapr_post_load();
344 /* deliver the results to the VM via DMA */
345 tpm_spapr_request_completed(TPM_IF(s
), 0);
352 static const VMStateDescription vmstate_spapr_vtpm
= {
354 .pre_save
= tpm_spapr_pre_save
,
355 .post_load
= tpm_spapr_post_load
,
356 .fields
= (VMStateField
[]) {
357 VMSTATE_SPAPR_VIO(vdev
, SpaprTpmState
),
359 VMSTATE_UINT8(state
, SpaprTpmState
),
360 VMSTATE_UINT32(numbytes
, SpaprTpmState
),
361 VMSTATE_VBUFFER_UINT32(buffer
, SpaprTpmState
, 0, NULL
, numbytes
),
362 /* remember DMA address */
363 VMSTATE_UINT32(crq
.data
, SpaprTpmState
),
364 VMSTATE_END_OF_LIST(),
368 static Property tpm_spapr_properties
[] = {
369 DEFINE_SPAPR_PROPERTIES(SpaprTpmState
, vdev
),
370 DEFINE_PROP_TPMBE("tpmdev", SpaprTpmState
, be_driver
),
371 DEFINE_PROP_END_OF_LIST(),
374 static void tpm_spapr_realizefn(SpaprVioDevice
*dev
, Error
**errp
)
376 SpaprTpmState
*s
= VIO_SPAPR_VTPM(dev
);
379 error_setg(errp
, "at most one TPM device is permitted");
383 dev
->crq
.SendFunc
= tpm_spapr_do_crq
;
386 error_setg(errp
, "'tpmdev' property is required");
389 s
->buffer
= g_malloc(TPM_SPAPR_BUFFER_MAX
);
392 static void tpm_spapr_class_init(ObjectClass
*klass
, void *data
)
394 DeviceClass
*dc
= DEVICE_CLASS(klass
);
395 SpaprVioDeviceClass
*k
= VIO_SPAPR_DEVICE_CLASS(klass
);
396 TPMIfClass
*tc
= TPM_IF_CLASS(klass
);
398 k
->realize
= tpm_spapr_realizefn
;
399 k
->reset
= tpm_spapr_reset
;
401 k
->dt_type
= "IBM,vtpm";
402 k
->get_dt_compatible
= tpm_spapr_get_dt_compatible
;
403 k
->signal_mask
= 0x00000001;
404 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
405 device_class_set_props(dc
, tpm_spapr_properties
);
406 k
->rtce_window_size
= 0x10000000;
407 dc
->vmsd
= &vmstate_spapr_vtpm
;
409 tc
->model
= TPM_MODEL_TPM_SPAPR
;
410 tc
->get_version
= tpm_spapr_get_version
;
411 tc
->request_completed
= tpm_spapr_request_completed
;
414 static const TypeInfo tpm_spapr_info
= {
415 .name
= TYPE_TPM_SPAPR
,
416 .parent
= TYPE_VIO_SPAPR_DEVICE
,
417 .instance_size
= sizeof(SpaprTpmState
),
418 .class_init
= tpm_spapr_class_init
,
419 .interfaces
= (InterfaceInfo
[]) {
425 static void tpm_spapr_register_types(void)
427 type_register_static(&tpm_spapr_info
);
430 type_init(tpm_spapr_register_types
)