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 {
46
#define SPAPR_VTPM_VALID_INIT_CRQ_COMMAND 0xC0
47
#define SPAPR_VTPM_VALID_COMMAND 0x80
48
#define SPAPR_VTPM_MSG_RESULT 0x80
51
#define SPAPR_VTPM_INIT_CRQ_RESULT 0x1
52
#define SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT 0x2
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
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
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;
85
TPMBackend *be_driver;
86
TPMVersion be_tpm_version;
88
size_t be_buffer_size;
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)
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");
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;
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:
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:
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;
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);
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);
326
static int tpm_spapr_pre_save(void *opaque)
328
SpaprTpmState *s = opaque;
330
tpm_backend_finish_sync(s->be_driver);
338
static int tpm_spapr_post_load(void *opaque, int version_id)
340
SpaprTpmState *s = opaque;
343
trace_tpm_spapr_post_load();
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 = (const 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),
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)