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"
26 #include "hw/ppc/spapr.h"
27 #include "hw/ppc/spapr_vio.h"
32 #define VIO_SPAPR_VTPM(obj) \
33 OBJECT_CHECK(SpaprTpmState, (obj), TYPE_TPM_SPAPR)
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 */
44 #define SPAPR_VTPM_VALID_INIT_CRQ_COMMAND 0xC0
45 #define SPAPR_VTPM_VALID_COMMAND 0x80
46 #define SPAPR_VTPM_MSG_RESULT 0x80
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
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
58 /* response error messages */
59 #define SPAPR_VTPM_VTPM_ERROR 0xff
62 #define SPAPR_VTPM_ERR_COPY_IN_FAILED 0x3
63 #define SPAPR_VTPM_ERR_COPY_OUT_FAILED 0x4
65 #define TPM_SPAPR_BUFFER_MAX 4096
70 TpmCrq crq
; /* track single TPM command */
73 #define SPAPR_VTPM_STATE_NONE 0
74 #define SPAPR_VTPM_STATE_EXECUTION 1
75 #define SPAPR_VTPM_STATE_COMPLETION 2
77 unsigned char *buffer
;
79 uint32_t numbytes
; /* number of bytes to deliver on resume */
83 TPMBackend
*be_driver
;
84 TPMVersion be_tpm_version
;
86 size_t be_buffer_size
;
90 * Send a request to the TPM.
92 static void tpm_spapr_tpm_send(SpaprTpmState
*s
)
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");
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 if (trace_event_get_state_backends(TRACE_TPM_SPAPR_SHOW_BUFFER
)) {
257 tpm_util_show_buffer(s
->buffer
, len
, "From TPM");
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
);
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
);
271 rc
= spapr_tpm_send_crq(&s
->vdev
, crq
);
273 error_report("%s: Error sending response", __func__
);
277 static int tpm_spapr_do_startup_tpm(SpaprTpmState
*s
, size_t buffersize
)
279 return tpm_backend_startup_tpm(s
->be_driver
, buffersize
);
282 static const char *tpm_spapr_get_dt_compatible(SpaprVioDevice
*dev
)
284 SpaprTpmState
*s
= VIO_SPAPR_VTPM(dev
);
286 switch (s
->be_tpm_version
) {
287 case TPM_VERSION_1_2
:
289 case TPM_VERSION_2_0
:
292 g_assert_not_reached();
296 static void tpm_spapr_reset(SpaprVioDevice
*dev
)
298 SpaprTpmState
*s
= VIO_SPAPR_VTPM(dev
);
300 s
->state
= SPAPR_VTPM_STATE_NONE
;
303 s
->be_tpm_version
= tpm_backend_get_tpm_version(s
->be_driver
);
305 s
->be_buffer_size
= MIN(tpm_backend_get_buffer_size(s
->be_driver
),
306 TPM_SPAPR_BUFFER_MAX
);
308 tpm_backend_reset(s
->be_driver
);
309 tpm_spapr_do_startup_tpm(s
, s
->be_buffer_size
);
312 static enum TPMVersion
tpm_spapr_get_version(TPMIf
*ti
)
314 SpaprTpmState
*s
= VIO_SPAPR_VTPM(ti
);
316 if (tpm_backend_had_startup_error(s
->be_driver
)) {
317 return TPM_VERSION_UNSPEC
;
320 return tpm_backend_get_tpm_version(s
->be_driver
);
323 /* persistent state handling */
325 static int tpm_spapr_pre_save(void *opaque
)
327 SpaprTpmState
*s
= opaque
;
329 tpm_backend_finish_sync(s
->be_driver
);
331 * we cannot deliver the results to the VM since DMA would touch VM memory
337 static int tpm_spapr_post_load(void *opaque
, int version_id
)
339 SpaprTpmState
*s
= opaque
;
342 trace_tpm_spapr_post_load();
343 /* deliver the results to the VM via DMA */
344 tpm_spapr_request_completed(TPM_IF(s
), 0);
351 static const VMStateDescription vmstate_spapr_vtpm
= {
353 .pre_save
= tpm_spapr_pre_save
,
354 .post_load
= tpm_spapr_post_load
,
355 .fields
= (VMStateField
[]) {
356 VMSTATE_SPAPR_VIO(vdev
, SpaprTpmState
),
358 VMSTATE_UINT8(state
, SpaprTpmState
),
359 VMSTATE_UINT32(numbytes
, SpaprTpmState
),
360 VMSTATE_VBUFFER_UINT32(buffer
, SpaprTpmState
, 0, NULL
, numbytes
),
361 /* remember DMA address */
362 VMSTATE_UINT32(crq
.data
, SpaprTpmState
),
363 VMSTATE_END_OF_LIST(),
367 static Property tpm_spapr_properties
[] = {
368 DEFINE_SPAPR_PROPERTIES(SpaprTpmState
, vdev
),
369 DEFINE_PROP_TPMBE("tpmdev", SpaprTpmState
, be_driver
),
370 DEFINE_PROP_END_OF_LIST(),
373 static void tpm_spapr_realizefn(SpaprVioDevice
*dev
, Error
**errp
)
375 SpaprTpmState
*s
= VIO_SPAPR_VTPM(dev
);
378 error_setg(errp
, "at most one TPM device is permitted");
382 dev
->crq
.SendFunc
= tpm_spapr_do_crq
;
385 error_setg(errp
, "'tpmdev' property is required");
388 s
->buffer
= g_malloc(TPM_SPAPR_BUFFER_MAX
);
391 static void tpm_spapr_class_init(ObjectClass
*klass
, void *data
)
393 DeviceClass
*dc
= DEVICE_CLASS(klass
);
394 SpaprVioDeviceClass
*k
= VIO_SPAPR_DEVICE_CLASS(klass
);
395 TPMIfClass
*tc
= TPM_IF_CLASS(klass
);
397 k
->realize
= tpm_spapr_realizefn
;
398 k
->reset
= tpm_spapr_reset
;
400 k
->dt_type
= "IBM,vtpm";
401 k
->get_dt_compatible
= tpm_spapr_get_dt_compatible
;
402 k
->signal_mask
= 0x00000001;
403 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
404 device_class_set_props(dc
, tpm_spapr_properties
);
405 k
->rtce_window_size
= 0x10000000;
406 dc
->vmsd
= &vmstate_spapr_vtpm
;
408 tc
->model
= TPM_MODEL_TPM_SPAPR
;
409 tc
->get_version
= tpm_spapr_get_version
;
410 tc
->request_completed
= tpm_spapr_request_completed
;
413 static const TypeInfo tpm_spapr_info
= {
414 .name
= TYPE_TPM_SPAPR
,
415 .parent
= TYPE_VIO_SPAPR_DEVICE
,
416 .instance_size
= sizeof(SpaprTpmState
),
417 .class_init
= tpm_spapr_class_init
,
418 .interfaces
= (InterfaceInfo
[]) {
424 static void tpm_spapr_register_types(void)
426 type_register_static(&tpm_spapr_info
);
429 type_init(tpm_spapr_register_types
)