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