tpm_tis.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. /*
  2. * tpm_tis.c - QEMU's TPM TIS interface emulator
  3. *
  4. * Copyright (C) 2006,2010-2013 IBM Corporation
  5. *
  6. * Authors:
  7. * Stefan Berger <stefanb@us.ibm.com>
  8. * David Safford <safford@us.ibm.com>
  9. *
  10. * Xen 4 support: Andrease Niederl <andreas.niederl@iaik.tugraz.at>
  11. *
  12. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  13. * See the COPYING file in the top-level directory.
  14. *
  15. * Implementation of the TIS interface according to specs found at
  16. * http://www.trustedcomputinggroup.org. This implementation currently
  17. * supports version 1.3, 21 March 2013
  18. * In the developers menu choose the PC Client section then find the TIS
  19. * specification.
  20. *
  21. * TPM TIS for TPM 2 implementation following TCG PC Client Platform
  22. * TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43
  23. */
  24. #include "qemu/osdep.h"
  25. #include "hw/irq.h"
  26. #include "hw/isa/isa.h"
  27. #include "qapi/error.h"
  28. #include "qemu/module.h"
  29. #include "hw/acpi/tpm.h"
  30. #include "hw/pci/pci_ids.h"
  31. #include "hw/qdev-properties.h"
  32. #include "migration/vmstate.h"
  33. #include "sysemu/tpm_backend.h"
  34. #include "tpm_int.h"
  35. #include "tpm_util.h"
  36. #include "tpm_ppi.h"
  37. #include "trace.h"
  38. #define TPM_TIS_NUM_LOCALITIES 5 /* per spec */
  39. #define TPM_TIS_LOCALITY_SHIFT 12
  40. #define TPM_TIS_NO_LOCALITY 0xff
  41. #define TPM_TIS_IS_VALID_LOCTY(x) ((x) < TPM_TIS_NUM_LOCALITIES)
  42. #define TPM_TIS_BUFFER_MAX 4096
  43. typedef enum {
  44. TPM_TIS_STATE_IDLE = 0,
  45. TPM_TIS_STATE_READY,
  46. TPM_TIS_STATE_COMPLETION,
  47. TPM_TIS_STATE_EXECUTION,
  48. TPM_TIS_STATE_RECEPTION,
  49. } TPMTISState;
  50. /* locality data -- all fields are persisted */
  51. typedef struct TPMLocality {
  52. TPMTISState state;
  53. uint8_t access;
  54. uint32_t sts;
  55. uint32_t iface_id;
  56. uint32_t inte;
  57. uint32_t ints;
  58. } TPMLocality;
  59. typedef struct TPMState {
  60. ISADevice busdev;
  61. MemoryRegion mmio;
  62. unsigned char buffer[TPM_TIS_BUFFER_MAX];
  63. uint16_t rw_offset;
  64. uint8_t active_locty;
  65. uint8_t aborting_locty;
  66. uint8_t next_locty;
  67. TPMLocality loc[TPM_TIS_NUM_LOCALITIES];
  68. qemu_irq irq;
  69. uint32_t irq_num;
  70. TPMBackendCmd cmd;
  71. TPMBackend *be_driver;
  72. TPMVersion be_tpm_version;
  73. size_t be_buffer_size;
  74. bool ppi_enabled;
  75. TPMPPI ppi;
  76. } TPMState;
  77. #define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS)
  78. #define DEBUG_TIS 0
  79. /* local prototypes */
  80. static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
  81. unsigned size);
  82. /* utility functions */
  83. static uint8_t tpm_tis_locality_from_addr(hwaddr addr)
  84. {
  85. return (uint8_t)((addr >> TPM_TIS_LOCALITY_SHIFT) & 0x7);
  86. }
  87. static void tpm_tis_show_buffer(const unsigned char *buffer,
  88. size_t buffer_size, const char *string)
  89. {
  90. size_t len, i;
  91. char *line_buffer, *p;
  92. len = MIN(tpm_cmd_get_size(buffer), buffer_size);
  93. /*
  94. * allocate enough room for 3 chars per buffer entry plus a
  95. * newline after every 16 chars and a final null terminator.
  96. */
  97. line_buffer = g_malloc(len * 3 + (len / 16) + 1);
  98. for (i = 0, p = line_buffer; i < len; i++) {
  99. if (i && !(i % 16)) {
  100. p += sprintf(p, "\n");
  101. }
  102. p += sprintf(p, "%.2X ", buffer[i]);
  103. }
  104. trace_tpm_tis_show_buffer(string, len, line_buffer);
  105. g_free(line_buffer);
  106. }
  107. /*
  108. * Set the given flags in the STS register by clearing the register but
  109. * preserving the SELFTEST_DONE and TPM_FAMILY_MASK flags and then setting
  110. * the new flags.
  111. *
  112. * The SELFTEST_DONE flag is acquired from the backend that determines it by
  113. * peeking into TPM commands.
  114. *
  115. * A VM suspend/resume will preserve the flag by storing it into the VM
  116. * device state, but the backend will not remember it when QEMU is started
  117. * again. Therefore, we cache the flag here. Once set, it will not be unset
  118. * except by a reset.
  119. */
  120. static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags)
  121. {
  122. l->sts &= TPM_TIS_STS_SELFTEST_DONE | TPM_TIS_STS_TPM_FAMILY_MASK;
  123. l->sts |= flags;
  124. }
  125. /*
  126. * Send a request to the TPM.
  127. */
  128. static void tpm_tis_tpm_send(TPMState *s, uint8_t locty)
  129. {
  130. if (trace_event_get_state_backends(TRACE_TPM_TIS_SHOW_BUFFER)) {
  131. tpm_tis_show_buffer(s->buffer, s->be_buffer_size, "To TPM");
  132. }
  133. /*
  134. * rw_offset serves as length indicator for length of data;
  135. * it's reset when the response comes back
  136. */
  137. s->loc[locty].state = TPM_TIS_STATE_EXECUTION;
  138. s->cmd = (TPMBackendCmd) {
  139. .locty = locty,
  140. .in = s->buffer,
  141. .in_len = s->rw_offset,
  142. .out = s->buffer,
  143. .out_len = s->be_buffer_size,
  144. };
  145. tpm_backend_deliver_request(s->be_driver, &s->cmd);
  146. }
  147. /* raise an interrupt if allowed */
  148. static void tpm_tis_raise_irq(TPMState *s, uint8_t locty, uint32_t irqmask)
  149. {
  150. if (!TPM_TIS_IS_VALID_LOCTY(locty)) {
  151. return;
  152. }
  153. if ((s->loc[locty].inte & TPM_TIS_INT_ENABLED) &&
  154. (s->loc[locty].inte & irqmask)) {
  155. trace_tpm_tis_raise_irq(irqmask);
  156. qemu_irq_raise(s->irq);
  157. s->loc[locty].ints |= irqmask;
  158. }
  159. }
  160. static uint32_t tpm_tis_check_request_use_except(TPMState *s, uint8_t locty)
  161. {
  162. uint8_t l;
  163. for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
  164. if (l == locty) {
  165. continue;
  166. }
  167. if ((s->loc[l].access & TPM_TIS_ACCESS_REQUEST_USE)) {
  168. return 1;
  169. }
  170. }
  171. return 0;
  172. }
  173. static void tpm_tis_new_active_locality(TPMState *s, uint8_t new_active_locty)
  174. {
  175. bool change = (s->active_locty != new_active_locty);
  176. bool is_seize;
  177. uint8_t mask;
  178. if (change && TPM_TIS_IS_VALID_LOCTY(s->active_locty)) {
  179. is_seize = TPM_TIS_IS_VALID_LOCTY(new_active_locty) &&
  180. s->loc[new_active_locty].access & TPM_TIS_ACCESS_SEIZE;
  181. if (is_seize) {
  182. mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY);
  183. } else {
  184. mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY|
  185. TPM_TIS_ACCESS_REQUEST_USE);
  186. }
  187. /* reset flags on the old active locality */
  188. s->loc[s->active_locty].access &= mask;
  189. if (is_seize) {
  190. s->loc[s->active_locty].access |= TPM_TIS_ACCESS_BEEN_SEIZED;
  191. }
  192. }
  193. s->active_locty = new_active_locty;
  194. trace_tpm_tis_new_active_locality(s->active_locty);
  195. if (TPM_TIS_IS_VALID_LOCTY(new_active_locty)) {
  196. /* set flags on the new active locality */
  197. s->loc[new_active_locty].access |= TPM_TIS_ACCESS_ACTIVE_LOCALITY;
  198. s->loc[new_active_locty].access &= ~(TPM_TIS_ACCESS_REQUEST_USE |
  199. TPM_TIS_ACCESS_SEIZE);
  200. }
  201. if (change) {
  202. tpm_tis_raise_irq(s, s->active_locty, TPM_TIS_INT_LOCALITY_CHANGED);
  203. }
  204. }
  205. /* abort -- this function switches the locality */
  206. static void tpm_tis_abort(TPMState *s)
  207. {
  208. s->rw_offset = 0;
  209. trace_tpm_tis_abort(s->next_locty);
  210. /*
  211. * Need to react differently depending on who's aborting now and
  212. * which locality will become active afterwards.
  213. */
  214. if (s->aborting_locty == s->next_locty) {
  215. s->loc[s->aborting_locty].state = TPM_TIS_STATE_READY;
  216. tpm_tis_sts_set(&s->loc[s->aborting_locty],
  217. TPM_TIS_STS_COMMAND_READY);
  218. tpm_tis_raise_irq(s, s->aborting_locty, TPM_TIS_INT_COMMAND_READY);
  219. }
  220. /* locality after abort is another one than the current one */
  221. tpm_tis_new_active_locality(s, s->next_locty);
  222. s->next_locty = TPM_TIS_NO_LOCALITY;
  223. /* nobody's aborting a command anymore */
  224. s->aborting_locty = TPM_TIS_NO_LOCALITY;
  225. }
  226. /* prepare aborting current command */
  227. static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty)
  228. {
  229. uint8_t busy_locty;
  230. assert(TPM_TIS_IS_VALID_LOCTY(newlocty));
  231. s->aborting_locty = locty; /* may also be TPM_TIS_NO_LOCALITY */
  232. s->next_locty = newlocty; /* locality after successful abort */
  233. /*
  234. * only abort a command using an interrupt if currently executing
  235. * a command AND if there's a valid connection to the vTPM.
  236. */
  237. for (busy_locty = 0; busy_locty < TPM_TIS_NUM_LOCALITIES; busy_locty++) {
  238. if (s->loc[busy_locty].state == TPM_TIS_STATE_EXECUTION) {
  239. /*
  240. * request the backend to cancel. Some backends may not
  241. * support it
  242. */
  243. tpm_backend_cancel_cmd(s->be_driver);
  244. return;
  245. }
  246. }
  247. tpm_tis_abort(s);
  248. }
  249. /*
  250. * Callback from the TPM to indicate that the response was received.
  251. */
  252. static void tpm_tis_request_completed(TPMIf *ti, int ret)
  253. {
  254. TPMState *s = TPM(ti);
  255. uint8_t locty = s->cmd.locty;
  256. uint8_t l;
  257. assert(TPM_TIS_IS_VALID_LOCTY(locty));
  258. if (s->cmd.selftest_done) {
  259. for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
  260. s->loc[l].sts |= TPM_TIS_STS_SELFTEST_DONE;
  261. }
  262. }
  263. /* FIXME: report error if ret != 0 */
  264. tpm_tis_sts_set(&s->loc[locty],
  265. TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE);
  266. s->loc[locty].state = TPM_TIS_STATE_COMPLETION;
  267. s->rw_offset = 0;
  268. if (trace_event_get_state_backends(TRACE_TPM_TIS_SHOW_BUFFER)) {
  269. tpm_tis_show_buffer(s->buffer, s->be_buffer_size, "From TPM");
  270. }
  271. if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) {
  272. tpm_tis_abort(s);
  273. }
  274. tpm_tis_raise_irq(s, locty,
  275. TPM_TIS_INT_DATA_AVAILABLE | TPM_TIS_INT_STS_VALID);
  276. }
  277. /*
  278. * Read a byte of response data
  279. */
  280. static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty)
  281. {
  282. uint32_t ret = TPM_TIS_NO_DATA_BYTE;
  283. uint16_t len;
  284. if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
  285. len = MIN(tpm_cmd_get_size(&s->buffer),
  286. s->be_buffer_size);
  287. ret = s->buffer[s->rw_offset++];
  288. if (s->rw_offset >= len) {
  289. /* got last byte */
  290. tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID);
  291. tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID);
  292. }
  293. trace_tpm_tis_data_read(ret, s->rw_offset - 1);
  294. }
  295. return ret;
  296. }
  297. #ifdef DEBUG_TIS
  298. static void tpm_tis_dump_state(void *opaque, hwaddr addr)
  299. {
  300. static const unsigned regs[] = {
  301. TPM_TIS_REG_ACCESS,
  302. TPM_TIS_REG_INT_ENABLE,
  303. TPM_TIS_REG_INT_VECTOR,
  304. TPM_TIS_REG_INT_STATUS,
  305. TPM_TIS_REG_INTF_CAPABILITY,
  306. TPM_TIS_REG_STS,
  307. TPM_TIS_REG_DID_VID,
  308. TPM_TIS_REG_RID,
  309. 0xfff};
  310. int idx;
  311. uint8_t locty = tpm_tis_locality_from_addr(addr);
  312. hwaddr base = addr & ~0xfff;
  313. TPMState *s = opaque;
  314. printf("tpm_tis: active locality : %d\n"
  315. "tpm_tis: state of locality %d : %d\n"
  316. "tpm_tis: register dump:\n",
  317. s->active_locty,
  318. locty, s->loc[locty].state);
  319. for (idx = 0; regs[idx] != 0xfff; idx++) {
  320. printf("tpm_tis: 0x%04x : 0x%08x\n", regs[idx],
  321. (int)tpm_tis_mmio_read(opaque, base + regs[idx], 4));
  322. }
  323. printf("tpm_tis: r/w offset : %d\n"
  324. "tpm_tis: result buffer : ",
  325. s->rw_offset);
  326. for (idx = 0;
  327. idx < MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size);
  328. idx++) {
  329. printf("%c%02x%s",
  330. s->rw_offset == idx ? '>' : ' ',
  331. s->buffer[idx],
  332. ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : "");
  333. }
  334. printf("\n");
  335. }
  336. #endif
  337. /*
  338. * Read a register of the TIS interface
  339. * See specs pages 33-63 for description of the registers
  340. */
  341. static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
  342. unsigned size)
  343. {
  344. TPMState *s = opaque;
  345. uint16_t offset = addr & 0xffc;
  346. uint8_t shift = (addr & 0x3) * 8;
  347. uint32_t val = 0xffffffff;
  348. uint8_t locty = tpm_tis_locality_from_addr(addr);
  349. uint32_t avail;
  350. uint8_t v;
  351. if (tpm_backend_had_startup_error(s->be_driver)) {
  352. return 0;
  353. }
  354. switch (offset) {
  355. case TPM_TIS_REG_ACCESS:
  356. /* never show the SEIZE flag even though we use it internally */
  357. val = s->loc[locty].access & ~TPM_TIS_ACCESS_SEIZE;
  358. /* the pending flag is always calculated */
  359. if (tpm_tis_check_request_use_except(s, locty)) {
  360. val |= TPM_TIS_ACCESS_PENDING_REQUEST;
  361. }
  362. val |= !tpm_backend_get_tpm_established_flag(s->be_driver);
  363. break;
  364. case TPM_TIS_REG_INT_ENABLE:
  365. val = s->loc[locty].inte;
  366. break;
  367. case TPM_TIS_REG_INT_VECTOR:
  368. val = s->irq_num;
  369. break;
  370. case TPM_TIS_REG_INT_STATUS:
  371. val = s->loc[locty].ints;
  372. break;
  373. case TPM_TIS_REG_INTF_CAPABILITY:
  374. switch (s->be_tpm_version) {
  375. case TPM_VERSION_UNSPEC:
  376. val = 0;
  377. break;
  378. case TPM_VERSION_1_2:
  379. val = TPM_TIS_CAPABILITIES_SUPPORTED1_3;
  380. break;
  381. case TPM_VERSION_2_0:
  382. val = TPM_TIS_CAPABILITIES_SUPPORTED2_0;
  383. break;
  384. }
  385. break;
  386. case TPM_TIS_REG_STS:
  387. if (s->active_locty == locty) {
  388. if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
  389. val = TPM_TIS_BURST_COUNT(
  390. MIN(tpm_cmd_get_size(&s->buffer),
  391. s->be_buffer_size)
  392. - s->rw_offset) | s->loc[locty].sts;
  393. } else {
  394. avail = s->be_buffer_size - s->rw_offset;
  395. /*
  396. * byte-sized reads should not return 0x00 for 0x100
  397. * available bytes.
  398. */
  399. if (size == 1 && avail > 0xff) {
  400. avail = 0xff;
  401. }
  402. val = TPM_TIS_BURST_COUNT(avail) | s->loc[locty].sts;
  403. }
  404. }
  405. break;
  406. case TPM_TIS_REG_DATA_FIFO:
  407. case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END:
  408. if (s->active_locty == locty) {
  409. if (size > 4 - (addr & 0x3)) {
  410. /* prevent access beyond FIFO */
  411. size = 4 - (addr & 0x3);
  412. }
  413. val = 0;
  414. shift = 0;
  415. while (size > 0) {
  416. switch (s->loc[locty].state) {
  417. case TPM_TIS_STATE_COMPLETION:
  418. v = tpm_tis_data_read(s, locty);
  419. break;
  420. default:
  421. v = TPM_TIS_NO_DATA_BYTE;
  422. break;
  423. }
  424. val |= (v << shift);
  425. shift += 8;
  426. size--;
  427. }
  428. shift = 0; /* no more adjustments */
  429. }
  430. break;
  431. case TPM_TIS_REG_INTERFACE_ID:
  432. val = s->loc[locty].iface_id;
  433. break;
  434. case TPM_TIS_REG_DID_VID:
  435. val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID;
  436. break;
  437. case TPM_TIS_REG_RID:
  438. val = TPM_TIS_TPM_RID;
  439. break;
  440. #ifdef DEBUG_TIS
  441. case TPM_TIS_REG_DEBUG:
  442. tpm_tis_dump_state(opaque, addr);
  443. break;
  444. #endif
  445. }
  446. if (shift) {
  447. val >>= shift;
  448. }
  449. trace_tpm_tis_mmio_read(size, addr, val);
  450. return val;
  451. }
  452. /*
  453. * Write a value to a register of the TIS interface
  454. * See specs pages 33-63 for description of the registers
  455. */
  456. static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
  457. uint64_t val, unsigned size)
  458. {
  459. TPMState *s = opaque;
  460. uint16_t off = addr & 0xffc;
  461. uint8_t shift = (addr & 0x3) * 8;
  462. uint8_t locty = tpm_tis_locality_from_addr(addr);
  463. uint8_t active_locty, l;
  464. int c, set_new_locty = 1;
  465. uint16_t len;
  466. uint32_t mask = (size == 1) ? 0xff : ((size == 2) ? 0xffff : ~0);
  467. trace_tpm_tis_mmio_write(size, addr, val);
  468. if (locty == 4) {
  469. trace_tpm_tis_mmio_write_locty4();
  470. return;
  471. }
  472. if (tpm_backend_had_startup_error(s->be_driver)) {
  473. return;
  474. }
  475. val &= mask;
  476. if (shift) {
  477. val <<= shift;
  478. mask <<= shift;
  479. }
  480. mask ^= 0xffffffff;
  481. switch (off) {
  482. case TPM_TIS_REG_ACCESS:
  483. if ((val & TPM_TIS_ACCESS_SEIZE)) {
  484. val &= ~(TPM_TIS_ACCESS_REQUEST_USE |
  485. TPM_TIS_ACCESS_ACTIVE_LOCALITY);
  486. }
  487. active_locty = s->active_locty;
  488. if ((val & TPM_TIS_ACCESS_ACTIVE_LOCALITY)) {
  489. /* give up locality if currently owned */
  490. if (s->active_locty == locty) {
  491. trace_tpm_tis_mmio_write_release_locty(locty);
  492. uint8_t newlocty = TPM_TIS_NO_LOCALITY;
  493. /* anybody wants the locality ? */
  494. for (c = TPM_TIS_NUM_LOCALITIES - 1; c >= 0; c--) {
  495. if ((s->loc[c].access & TPM_TIS_ACCESS_REQUEST_USE)) {
  496. trace_tpm_tis_mmio_write_locty_req_use(c);
  497. newlocty = c;
  498. break;
  499. }
  500. }
  501. trace_tpm_tis_mmio_write_next_locty(newlocty);
  502. if (TPM_TIS_IS_VALID_LOCTY(newlocty)) {
  503. set_new_locty = 0;
  504. tpm_tis_prep_abort(s, locty, newlocty);
  505. } else {
  506. active_locty = TPM_TIS_NO_LOCALITY;
  507. }
  508. } else {
  509. /* not currently the owner; clear a pending request */
  510. s->loc[locty].access &= ~TPM_TIS_ACCESS_REQUEST_USE;
  511. }
  512. }
  513. if ((val & TPM_TIS_ACCESS_BEEN_SEIZED)) {
  514. s->loc[locty].access &= ~TPM_TIS_ACCESS_BEEN_SEIZED;
  515. }
  516. if ((val & TPM_TIS_ACCESS_SEIZE)) {
  517. /*
  518. * allow seize if a locality is active and the requesting
  519. * locality is higher than the one that's active
  520. * OR
  521. * allow seize for requesting locality if no locality is
  522. * active
  523. */
  524. while ((TPM_TIS_IS_VALID_LOCTY(s->active_locty) &&
  525. locty > s->active_locty) ||
  526. !TPM_TIS_IS_VALID_LOCTY(s->active_locty)) {
  527. bool higher_seize = FALSE;
  528. /* already a pending SEIZE ? */
  529. if ((s->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) {
  530. break;
  531. }
  532. /* check for ongoing seize by a higher locality */
  533. for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) {
  534. if ((s->loc[l].access & TPM_TIS_ACCESS_SEIZE)) {
  535. higher_seize = TRUE;
  536. break;
  537. }
  538. }
  539. if (higher_seize) {
  540. break;
  541. }
  542. /* cancel any seize by a lower locality */
  543. for (l = 0; l < locty; l++) {
  544. s->loc[l].access &= ~TPM_TIS_ACCESS_SEIZE;
  545. }
  546. s->loc[locty].access |= TPM_TIS_ACCESS_SEIZE;
  547. trace_tpm_tis_mmio_write_locty_seized(locty, s->active_locty);
  548. trace_tpm_tis_mmio_write_init_abort();
  549. set_new_locty = 0;
  550. tpm_tis_prep_abort(s, s->active_locty, locty);
  551. break;
  552. }
  553. }
  554. if ((val & TPM_TIS_ACCESS_REQUEST_USE)) {
  555. if (s->active_locty != locty) {
  556. if (TPM_TIS_IS_VALID_LOCTY(s->active_locty)) {
  557. s->loc[locty].access |= TPM_TIS_ACCESS_REQUEST_USE;
  558. } else {
  559. /* no locality active -> make this one active now */
  560. active_locty = locty;
  561. }
  562. }
  563. }
  564. if (set_new_locty) {
  565. tpm_tis_new_active_locality(s, active_locty);
  566. }
  567. break;
  568. case TPM_TIS_REG_INT_ENABLE:
  569. if (s->active_locty != locty) {
  570. break;
  571. }
  572. s->loc[locty].inte &= mask;
  573. s->loc[locty].inte |= (val & (TPM_TIS_INT_ENABLED |
  574. TPM_TIS_INT_POLARITY_MASK |
  575. TPM_TIS_INTERRUPTS_SUPPORTED));
  576. break;
  577. case TPM_TIS_REG_INT_VECTOR:
  578. /* hard wired -- ignore */
  579. break;
  580. case TPM_TIS_REG_INT_STATUS:
  581. if (s->active_locty != locty) {
  582. break;
  583. }
  584. /* clearing of interrupt flags */
  585. if (((val & TPM_TIS_INTERRUPTS_SUPPORTED)) &&
  586. (s->loc[locty].ints & TPM_TIS_INTERRUPTS_SUPPORTED)) {
  587. s->loc[locty].ints &= ~val;
  588. if (s->loc[locty].ints == 0) {
  589. qemu_irq_lower(s->irq);
  590. trace_tpm_tis_mmio_write_lowering_irq();
  591. }
  592. }
  593. s->loc[locty].ints &= ~(val & TPM_TIS_INTERRUPTS_SUPPORTED);
  594. break;
  595. case TPM_TIS_REG_STS:
  596. if (s->active_locty != locty) {
  597. break;
  598. }
  599. if (s->be_tpm_version == TPM_VERSION_2_0) {
  600. /* some flags that are only supported for TPM 2 */
  601. if (val & TPM_TIS_STS_COMMAND_CANCEL) {
  602. if (s->loc[locty].state == TPM_TIS_STATE_EXECUTION) {
  603. /*
  604. * request the backend to cancel. Some backends may not
  605. * support it
  606. */
  607. tpm_backend_cancel_cmd(s->be_driver);
  608. }
  609. }
  610. if (val & TPM_TIS_STS_RESET_ESTABLISHMENT_BIT) {
  611. if (locty == 3 || locty == 4) {
  612. tpm_backend_reset_tpm_established_flag(s->be_driver, locty);
  613. }
  614. }
  615. }
  616. val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO |
  617. TPM_TIS_STS_RESPONSE_RETRY);
  618. if (val == TPM_TIS_STS_COMMAND_READY) {
  619. switch (s->loc[locty].state) {
  620. case TPM_TIS_STATE_READY:
  621. s->rw_offset = 0;
  622. break;
  623. case TPM_TIS_STATE_IDLE:
  624. tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_COMMAND_READY);
  625. s->loc[locty].state = TPM_TIS_STATE_READY;
  626. tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY);
  627. break;
  628. case TPM_TIS_STATE_EXECUTION:
  629. case TPM_TIS_STATE_RECEPTION:
  630. /* abort currently running command */
  631. trace_tpm_tis_mmio_write_init_abort();
  632. tpm_tis_prep_abort(s, locty, locty);
  633. break;
  634. case TPM_TIS_STATE_COMPLETION:
  635. s->rw_offset = 0;
  636. /* shortcut to ready state with C/R set */
  637. s->loc[locty].state = TPM_TIS_STATE_READY;
  638. if (!(s->loc[locty].sts & TPM_TIS_STS_COMMAND_READY)) {
  639. tpm_tis_sts_set(&s->loc[locty],
  640. TPM_TIS_STS_COMMAND_READY);
  641. tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY);
  642. }
  643. s->loc[locty].sts &= ~(TPM_TIS_STS_DATA_AVAILABLE);
  644. break;
  645. }
  646. } else if (val == TPM_TIS_STS_TPM_GO) {
  647. switch (s->loc[locty].state) {
  648. case TPM_TIS_STATE_RECEPTION:
  649. if ((s->loc[locty].sts & TPM_TIS_STS_EXPECT) == 0) {
  650. tpm_tis_tpm_send(s, locty);
  651. }
  652. break;
  653. default:
  654. /* ignore */
  655. break;
  656. }
  657. } else if (val == TPM_TIS_STS_RESPONSE_RETRY) {
  658. switch (s->loc[locty].state) {
  659. case TPM_TIS_STATE_COMPLETION:
  660. s->rw_offset = 0;
  661. tpm_tis_sts_set(&s->loc[locty],
  662. TPM_TIS_STS_VALID|
  663. TPM_TIS_STS_DATA_AVAILABLE);
  664. break;
  665. default:
  666. /* ignore */
  667. break;
  668. }
  669. }
  670. break;
  671. case TPM_TIS_REG_DATA_FIFO:
  672. case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END:
  673. /* data fifo */
  674. if (s->active_locty != locty) {
  675. break;
  676. }
  677. if (s->loc[locty].state == TPM_TIS_STATE_IDLE ||
  678. s->loc[locty].state == TPM_TIS_STATE_EXECUTION ||
  679. s->loc[locty].state == TPM_TIS_STATE_COMPLETION) {
  680. /* drop the byte */
  681. } else {
  682. trace_tpm_tis_mmio_write_data2send(val, size);
  683. if (s->loc[locty].state == TPM_TIS_STATE_READY) {
  684. s->loc[locty].state = TPM_TIS_STATE_RECEPTION;
  685. tpm_tis_sts_set(&s->loc[locty],
  686. TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);
  687. }
  688. val >>= shift;
  689. if (size > 4 - (addr & 0x3)) {
  690. /* prevent access beyond FIFO */
  691. size = 4 - (addr & 0x3);
  692. }
  693. while ((s->loc[locty].sts & TPM_TIS_STS_EXPECT) && size > 0) {
  694. if (s->rw_offset < s->be_buffer_size) {
  695. s->buffer[s->rw_offset++] =
  696. (uint8_t)val;
  697. val >>= 8;
  698. size--;
  699. } else {
  700. tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID);
  701. }
  702. }
  703. /* check for complete packet */
  704. if (s->rw_offset > 5 &&
  705. (s->loc[locty].sts & TPM_TIS_STS_EXPECT)) {
  706. /* we have a packet length - see if we have all of it */
  707. bool need_irq = !(s->loc[locty].sts & TPM_TIS_STS_VALID);
  708. len = tpm_cmd_get_size(&s->buffer);
  709. if (len > s->rw_offset) {
  710. tpm_tis_sts_set(&s->loc[locty],
  711. TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);
  712. } else {
  713. /* packet complete */
  714. tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID);
  715. }
  716. if (need_irq) {
  717. tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID);
  718. }
  719. }
  720. }
  721. break;
  722. case TPM_TIS_REG_INTERFACE_ID:
  723. if (val & TPM_TIS_IFACE_ID_INT_SEL_LOCK) {
  724. for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
  725. s->loc[l].iface_id |= TPM_TIS_IFACE_ID_INT_SEL_LOCK;
  726. }
  727. }
  728. break;
  729. }
  730. }
  731. static const MemoryRegionOps tpm_tis_memory_ops = {
  732. .read = tpm_tis_mmio_read,
  733. .write = tpm_tis_mmio_write,
  734. .endianness = DEVICE_LITTLE_ENDIAN,
  735. .valid = {
  736. .min_access_size = 1,
  737. .max_access_size = 4,
  738. },
  739. };
  740. /*
  741. * Get the TPMVersion of the backend device being used
  742. */
  743. static enum TPMVersion tpm_tis_get_tpm_version(TPMIf *ti)
  744. {
  745. TPMState *s = TPM(ti);
  746. if (tpm_backend_had_startup_error(s->be_driver)) {
  747. return TPM_VERSION_UNSPEC;
  748. }
  749. return tpm_backend_get_tpm_version(s->be_driver);
  750. }
  751. /*
  752. * This function is called when the machine starts, resets or due to
  753. * S3 resume.
  754. */
  755. static void tpm_tis_reset(DeviceState *dev)
  756. {
  757. TPMState *s = TPM(dev);
  758. int c;
  759. s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);
  760. s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver),
  761. TPM_TIS_BUFFER_MAX);
  762. if (s->ppi_enabled) {
  763. tpm_ppi_reset(&s->ppi);
  764. }
  765. tpm_backend_reset(s->be_driver);
  766. s->active_locty = TPM_TIS_NO_LOCALITY;
  767. s->next_locty = TPM_TIS_NO_LOCALITY;
  768. s->aborting_locty = TPM_TIS_NO_LOCALITY;
  769. for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) {
  770. s->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS;
  771. switch (s->be_tpm_version) {
  772. case TPM_VERSION_UNSPEC:
  773. break;
  774. case TPM_VERSION_1_2:
  775. s->loc[c].sts = TPM_TIS_STS_TPM_FAMILY1_2;
  776. s->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3;
  777. break;
  778. case TPM_VERSION_2_0:
  779. s->loc[c].sts = TPM_TIS_STS_TPM_FAMILY2_0;
  780. s->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0;
  781. break;
  782. }
  783. s->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL;
  784. s->loc[c].ints = 0;
  785. s->loc[c].state = TPM_TIS_STATE_IDLE;
  786. s->rw_offset = 0;
  787. }
  788. if (tpm_backend_startup_tpm(s->be_driver, s->be_buffer_size) < 0) {
  789. exit(1);
  790. }
  791. }
  792. /* persistent state handling */
  793. static int tpm_tis_pre_save(void *opaque)
  794. {
  795. TPMState *s = opaque;
  796. uint8_t locty = s->active_locty;
  797. trace_tpm_tis_pre_save(locty, s->rw_offset);
  798. if (DEBUG_TIS) {
  799. tpm_tis_dump_state(opaque, 0);
  800. }
  801. /*
  802. * Synchronize with backend completion.
  803. */
  804. tpm_backend_finish_sync(s->be_driver);
  805. return 0;
  806. }
  807. static const VMStateDescription vmstate_locty = {
  808. .name = "tpm-tis/locty",
  809. .version_id = 0,
  810. .fields = (VMStateField[]) {
  811. VMSTATE_UINT32(state, TPMLocality),
  812. VMSTATE_UINT32(inte, TPMLocality),
  813. VMSTATE_UINT32(ints, TPMLocality),
  814. VMSTATE_UINT8(access, TPMLocality),
  815. VMSTATE_UINT32(sts, TPMLocality),
  816. VMSTATE_UINT32(iface_id, TPMLocality),
  817. VMSTATE_END_OF_LIST(),
  818. }
  819. };
  820. static const VMStateDescription vmstate_tpm_tis = {
  821. .name = "tpm-tis",
  822. .version_id = 0,
  823. .pre_save = tpm_tis_pre_save,
  824. .fields = (VMStateField[]) {
  825. VMSTATE_BUFFER(buffer, TPMState),
  826. VMSTATE_UINT16(rw_offset, TPMState),
  827. VMSTATE_UINT8(active_locty, TPMState),
  828. VMSTATE_UINT8(aborting_locty, TPMState),
  829. VMSTATE_UINT8(next_locty, TPMState),
  830. VMSTATE_STRUCT_ARRAY(loc, TPMState, TPM_TIS_NUM_LOCALITIES, 0,
  831. vmstate_locty, TPMLocality),
  832. VMSTATE_END_OF_LIST()
  833. }
  834. };
  835. static Property tpm_tis_properties[] = {
  836. DEFINE_PROP_UINT32("irq", TPMState, irq_num, TPM_TIS_IRQ),
  837. DEFINE_PROP_TPMBE("tpmdev", TPMState, be_driver),
  838. DEFINE_PROP_BOOL("ppi", TPMState, ppi_enabled, true),
  839. DEFINE_PROP_END_OF_LIST(),
  840. };
  841. static void tpm_tis_realizefn(DeviceState *dev, Error **errp)
  842. {
  843. TPMState *s = TPM(dev);
  844. if (!tpm_find()) {
  845. error_setg(errp, "at most one TPM device is permitted");
  846. return;
  847. }
  848. if (!s->be_driver) {
  849. error_setg(errp, "'tpmdev' property is required");
  850. return;
  851. }
  852. if (s->irq_num > 15) {
  853. error_setg(errp, "IRQ %d is outside valid range of 0 to 15",
  854. s->irq_num);
  855. return;
  856. }
  857. isa_init_irq(&s->busdev, &s->irq, s->irq_num);
  858. memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
  859. TPM_TIS_ADDR_BASE, &s->mmio);
  860. if (s->ppi_enabled) {
  861. tpm_ppi_init(&s->ppi, isa_address_space(ISA_DEVICE(dev)),
  862. TPM_PPI_ADDR_BASE, OBJECT(s));
  863. }
  864. }
  865. static void tpm_tis_initfn(Object *obj)
  866. {
  867. TPMState *s = TPM(obj);
  868. memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops,
  869. s, "tpm-tis-mmio",
  870. TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT);
  871. }
  872. static void tpm_tis_class_init(ObjectClass *klass, void *data)
  873. {
  874. DeviceClass *dc = DEVICE_CLASS(klass);
  875. TPMIfClass *tc = TPM_IF_CLASS(klass);
  876. dc->realize = tpm_tis_realizefn;
  877. dc->props = tpm_tis_properties;
  878. dc->reset = tpm_tis_reset;
  879. dc->vmsd = &vmstate_tpm_tis;
  880. tc->model = TPM_MODEL_TPM_TIS;
  881. tc->get_version = tpm_tis_get_tpm_version;
  882. tc->request_completed = tpm_tis_request_completed;
  883. }
  884. static const TypeInfo tpm_tis_info = {
  885. .name = TYPE_TPM_TIS,
  886. .parent = TYPE_ISA_DEVICE,
  887. .instance_size = sizeof(TPMState),
  888. .instance_init = tpm_tis_initfn,
  889. .class_init = tpm_tis_class_init,
  890. .interfaces = (InterfaceInfo[]) {
  891. { TYPE_TPM_IF },
  892. { }
  893. }
  894. };
  895. static void tpm_tis_register(void)
  896. {
  897. type_register_static(&tpm_tis_info);
  898. }
  899. type_init(tpm_tis_register)