xlnx-bbram.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. /*
  2. * QEMU model of the Xilinx BBRAM Battery Backed RAM
  3. *
  4. * Copyright (c) 2014-2021 Xilinx Inc.
  5. * Copyright (c) 2023 Advanced Micro Devices, Inc.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. #include "qemu/osdep.h"
  26. #include "hw/nvram/xlnx-bbram.h"
  27. #include "qemu/error-report.h"
  28. #include "qemu/log.h"
  29. #include "qapi/error.h"
  30. #include "system/blockdev.h"
  31. #include "migration/vmstate.h"
  32. #include "hw/qdev-properties.h"
  33. #include "hw/qdev-properties-system.h"
  34. #include "hw/nvram/xlnx-efuse.h"
  35. #ifndef XLNX_BBRAM_ERR_DEBUG
  36. #define XLNX_BBRAM_ERR_DEBUG 0
  37. #endif
  38. REG32(BBRAM_STATUS, 0x0)
  39. FIELD(BBRAM_STATUS, AES_CRC_PASS, 9, 1)
  40. FIELD(BBRAM_STATUS, AES_CRC_DONE, 8, 1)
  41. FIELD(BBRAM_STATUS, BBRAM_ZEROIZED, 4, 1)
  42. FIELD(BBRAM_STATUS, PGM_MODE, 0, 1)
  43. REG32(BBRAM_CTRL, 0x4)
  44. FIELD(BBRAM_CTRL, ZEROIZE, 0, 1)
  45. REG32(PGM_MODE, 0x8)
  46. REG32(BBRAM_AES_CRC, 0xc)
  47. REG32(BBRAM_0, 0x10)
  48. REG32(BBRAM_1, 0x14)
  49. REG32(BBRAM_2, 0x18)
  50. REG32(BBRAM_3, 0x1c)
  51. REG32(BBRAM_4, 0x20)
  52. REG32(BBRAM_5, 0x24)
  53. REG32(BBRAM_6, 0x28)
  54. REG32(BBRAM_7, 0x2c)
  55. REG32(BBRAM_8, 0x30)
  56. REG32(BBRAM_SLVERR, 0x34)
  57. FIELD(BBRAM_SLVERR, ENABLE, 0, 1)
  58. REG32(BBRAM_ISR, 0x38)
  59. FIELD(BBRAM_ISR, APB_SLVERR, 0, 1)
  60. REG32(BBRAM_IMR, 0x3c)
  61. FIELD(BBRAM_IMR, APB_SLVERR, 0, 1)
  62. REG32(BBRAM_IER, 0x40)
  63. FIELD(BBRAM_IER, APB_SLVERR, 0, 1)
  64. REG32(BBRAM_IDR, 0x44)
  65. FIELD(BBRAM_IDR, APB_SLVERR, 0, 1)
  66. REG32(BBRAM_MSW_LOCK, 0x4c)
  67. FIELD(BBRAM_MSW_LOCK, VAL, 0, 1)
  68. #define R_MAX (R_BBRAM_MSW_LOCK + 1)
  69. #define RAM_MAX (A_BBRAM_8 + 4 - A_BBRAM_0)
  70. #define BBRAM_PGM_MAGIC 0x757bdf0d
  71. QEMU_BUILD_BUG_ON(R_MAX != ARRAY_SIZE(((XlnxBBRam *)0)->regs));
  72. static bool bbram_msw_locked(XlnxBBRam *s)
  73. {
  74. return ARRAY_FIELD_EX32(s->regs, BBRAM_MSW_LOCK, VAL) != 0;
  75. }
  76. static bool bbram_pgm_enabled(XlnxBBRam *s)
  77. {
  78. return ARRAY_FIELD_EX32(s->regs, BBRAM_STATUS, PGM_MODE) != 0;
  79. }
  80. static void bbram_bdrv_error(XlnxBBRam *s, int rc, gchar *detail)
  81. {
  82. Error *errp = NULL;
  83. error_setg_errno(&errp, -rc, "%s: BBRAM backstore %s failed.",
  84. blk_name(s->blk), detail);
  85. error_report("%s", error_get_pretty(errp));
  86. error_free(errp);
  87. g_free(detail);
  88. }
  89. static void bbram_bdrv_read(XlnxBBRam *s, Error **errp)
  90. {
  91. uint32_t *ram = &s->regs[R_BBRAM_0];
  92. int nr = RAM_MAX;
  93. if (!s->blk) {
  94. return;
  95. }
  96. s->blk_ro = !blk_supports_write_perm(s->blk);
  97. if (!s->blk_ro) {
  98. int rc;
  99. rc = blk_set_perm(s->blk,
  100. (BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE),
  101. BLK_PERM_ALL, NULL);
  102. if (rc) {
  103. s->blk_ro = true;
  104. }
  105. }
  106. if (s->blk_ro) {
  107. warn_report("%s: Skip saving updates to read-only BBRAM backstore.",
  108. blk_name(s->blk));
  109. }
  110. if (blk_pread(s->blk, 0, nr, ram, 0) < 0) {
  111. error_setg(errp,
  112. "%s: Failed to read %u bytes from BBRAM backstore.",
  113. blk_name(s->blk), nr);
  114. return;
  115. }
  116. /* Convert from little-endian backstore for each 32-bit word */
  117. nr /= 4;
  118. while (nr--) {
  119. ram[nr] = le32_to_cpu(ram[nr]);
  120. }
  121. }
  122. static void bbram_bdrv_sync(XlnxBBRam *s, uint64_t hwaddr)
  123. {
  124. uint32_t le32;
  125. unsigned offset;
  126. int rc;
  127. assert(A_BBRAM_0 <= hwaddr && hwaddr <= A_BBRAM_8);
  128. /* Backstore is always in little-endian */
  129. le32 = cpu_to_le32(s->regs[hwaddr / 4]);
  130. /* Update zeroized flag */
  131. if (le32 && (hwaddr != A_BBRAM_8 || s->bbram8_wo)) {
  132. ARRAY_FIELD_DP32(s->regs, BBRAM_STATUS, BBRAM_ZEROIZED, 0);
  133. }
  134. if (!s->blk || s->blk_ro) {
  135. return;
  136. }
  137. offset = hwaddr - A_BBRAM_0;
  138. rc = blk_pwrite(s->blk, offset, 4, &le32, 0);
  139. if (rc < 0) {
  140. bbram_bdrv_error(s, rc, g_strdup_printf("write to offset %u", offset));
  141. }
  142. }
  143. static void bbram_bdrv_zero(XlnxBBRam *s)
  144. {
  145. int rc;
  146. ARRAY_FIELD_DP32(s->regs, BBRAM_STATUS, BBRAM_ZEROIZED, 1);
  147. if (!s->blk || s->blk_ro) {
  148. return;
  149. }
  150. rc = blk_make_zero(s->blk, 0);
  151. if (rc < 0) {
  152. bbram_bdrv_error(s, rc, g_strdup("zeroizing"));
  153. }
  154. /* Restore bbram8 if it is non-zero */
  155. if (s->regs[R_BBRAM_8]) {
  156. bbram_bdrv_sync(s, A_BBRAM_8);
  157. }
  158. }
  159. static void bbram_zeroize(XlnxBBRam *s)
  160. {
  161. int nr = RAM_MAX - (s->bbram8_wo ? 0 : 4); /* only wo bbram8 is cleared */
  162. memset(&s->regs[R_BBRAM_0], 0, nr);
  163. bbram_bdrv_zero(s);
  164. }
  165. static void bbram_update_irq(XlnxBBRam *s)
  166. {
  167. bool pending = s->regs[R_BBRAM_ISR] & ~s->regs[R_BBRAM_IMR];
  168. qemu_set_irq(s->irq_bbram, pending);
  169. }
  170. static void bbram_ctrl_postw(RegisterInfo *reg, uint64_t val64)
  171. {
  172. XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
  173. uint32_t val = val64;
  174. if (val & R_BBRAM_CTRL_ZEROIZE_MASK) {
  175. bbram_zeroize(s);
  176. /* The bit is self clearing */
  177. s->regs[R_BBRAM_CTRL] &= ~R_BBRAM_CTRL_ZEROIZE_MASK;
  178. }
  179. }
  180. static void bbram_pgm_mode_postw(RegisterInfo *reg, uint64_t val64)
  181. {
  182. XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
  183. uint32_t val = val64;
  184. if (val == BBRAM_PGM_MAGIC) {
  185. bbram_zeroize(s);
  186. /* The status bit is cleared only by POR */
  187. ARRAY_FIELD_DP32(s->regs, BBRAM_STATUS, PGM_MODE, 1);
  188. }
  189. }
  190. static void bbram_aes_crc_postw(RegisterInfo *reg, uint64_t val64)
  191. {
  192. XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
  193. uint32_t calc_crc;
  194. if (!bbram_pgm_enabled(s)) {
  195. /* We are not in programming mode, don't do anything */
  196. return;
  197. }
  198. /* Perform the AES integrity check */
  199. s->regs[R_BBRAM_STATUS] |= R_BBRAM_STATUS_AES_CRC_DONE_MASK;
  200. /*
  201. * Set check status.
  202. *
  203. * ZynqMP BBRAM check has a zero-u32 prepended; see:
  204. * https://github.com/Xilinx/embeddedsw/blob/release-2019.2/lib/sw_services/xilskey/src/xilskey_bbramps_zynqmp.c#L311
  205. */
  206. calc_crc = xlnx_efuse_calc_crc(&s->regs[R_BBRAM_0],
  207. (R_BBRAM_8 - R_BBRAM_0), s->crc_zpads);
  208. ARRAY_FIELD_DP32(s->regs, BBRAM_STATUS, AES_CRC_PASS,
  209. (s->regs[R_BBRAM_AES_CRC] == calc_crc));
  210. }
  211. static uint64_t bbram_key_prew(RegisterInfo *reg, uint64_t val64)
  212. {
  213. XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
  214. uint32_t original_data = *(uint32_t *) reg->data;
  215. if (bbram_pgm_enabled(s)) {
  216. return val64;
  217. } else {
  218. /* We are not in programming mode, don't do anything */
  219. qemu_log_mask(LOG_GUEST_ERROR,
  220. "Not in programming mode, dropping the write\n");
  221. return original_data;
  222. }
  223. }
  224. static void bbram_key_postw(RegisterInfo *reg, uint64_t val64)
  225. {
  226. XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
  227. bbram_bdrv_sync(s, reg->access->addr);
  228. }
  229. static uint64_t bbram_wo_postr(RegisterInfo *reg, uint64_t val)
  230. {
  231. return 0;
  232. }
  233. static uint64_t bbram_r8_postr(RegisterInfo *reg, uint64_t val)
  234. {
  235. XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
  236. return s->bbram8_wo ? bbram_wo_postr(reg, val) : val;
  237. }
  238. static bool bbram_r8_readonly(XlnxBBRam *s)
  239. {
  240. return !bbram_pgm_enabled(s) || bbram_msw_locked(s);
  241. }
  242. static uint64_t bbram_r8_prew(RegisterInfo *reg, uint64_t val64)
  243. {
  244. XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
  245. if (bbram_r8_readonly(s)) {
  246. val64 = *(uint32_t *)reg->data;
  247. }
  248. return val64;
  249. }
  250. static void bbram_r8_postw(RegisterInfo *reg, uint64_t val64)
  251. {
  252. XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
  253. if (!bbram_r8_readonly(s)) {
  254. bbram_bdrv_sync(s, A_BBRAM_8);
  255. }
  256. }
  257. static uint64_t bbram_msw_lock_prew(RegisterInfo *reg, uint64_t val64)
  258. {
  259. XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
  260. /* Never lock if bbram8 is wo; and, only POR can clear the lock */
  261. if (s->bbram8_wo) {
  262. val64 = 0;
  263. } else {
  264. val64 |= s->regs[R_BBRAM_MSW_LOCK];
  265. }
  266. return val64;
  267. }
  268. static void bbram_isr_postw(RegisterInfo *reg, uint64_t val64)
  269. {
  270. XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
  271. bbram_update_irq(s);
  272. }
  273. static uint64_t bbram_ier_prew(RegisterInfo *reg, uint64_t val64)
  274. {
  275. XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
  276. uint32_t val = val64;
  277. s->regs[R_BBRAM_IMR] &= ~val;
  278. bbram_update_irq(s);
  279. return 0;
  280. }
  281. static uint64_t bbram_idr_prew(RegisterInfo *reg, uint64_t val64)
  282. {
  283. XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
  284. uint32_t val = val64;
  285. s->regs[R_BBRAM_IMR] |= val;
  286. bbram_update_irq(s);
  287. return 0;
  288. }
  289. static RegisterAccessInfo bbram_ctrl_regs_info[] = {
  290. { .name = "BBRAM_STATUS", .addr = A_BBRAM_STATUS,
  291. .rsvd = 0xee,
  292. .ro = 0x3ff,
  293. },{ .name = "BBRAM_CTRL", .addr = A_BBRAM_CTRL,
  294. .post_write = bbram_ctrl_postw,
  295. },{ .name = "PGM_MODE", .addr = A_PGM_MODE,
  296. .post_write = bbram_pgm_mode_postw,
  297. },{ .name = "BBRAM_AES_CRC", .addr = A_BBRAM_AES_CRC,
  298. .post_write = bbram_aes_crc_postw,
  299. .post_read = bbram_wo_postr,
  300. },{ .name = "BBRAM_0", .addr = A_BBRAM_0,
  301. .pre_write = bbram_key_prew,
  302. .post_write = bbram_key_postw,
  303. .post_read = bbram_wo_postr,
  304. },{ .name = "BBRAM_1", .addr = A_BBRAM_1,
  305. .pre_write = bbram_key_prew,
  306. .post_write = bbram_key_postw,
  307. .post_read = bbram_wo_postr,
  308. },{ .name = "BBRAM_2", .addr = A_BBRAM_2,
  309. .pre_write = bbram_key_prew,
  310. .post_write = bbram_key_postw,
  311. .post_read = bbram_wo_postr,
  312. },{ .name = "BBRAM_3", .addr = A_BBRAM_3,
  313. .pre_write = bbram_key_prew,
  314. .post_write = bbram_key_postw,
  315. .post_read = bbram_wo_postr,
  316. },{ .name = "BBRAM_4", .addr = A_BBRAM_4,
  317. .pre_write = bbram_key_prew,
  318. .post_write = bbram_key_postw,
  319. .post_read = bbram_wo_postr,
  320. },{ .name = "BBRAM_5", .addr = A_BBRAM_5,
  321. .pre_write = bbram_key_prew,
  322. .post_write = bbram_key_postw,
  323. .post_read = bbram_wo_postr,
  324. },{ .name = "BBRAM_6", .addr = A_BBRAM_6,
  325. .pre_write = bbram_key_prew,
  326. .post_write = bbram_key_postw,
  327. .post_read = bbram_wo_postr,
  328. },{ .name = "BBRAM_7", .addr = A_BBRAM_7,
  329. .pre_write = bbram_key_prew,
  330. .post_write = bbram_key_postw,
  331. .post_read = bbram_wo_postr,
  332. },{ .name = "BBRAM_8", .addr = A_BBRAM_8,
  333. .pre_write = bbram_r8_prew,
  334. .post_write = bbram_r8_postw,
  335. .post_read = bbram_r8_postr,
  336. },{ .name = "BBRAM_SLVERR", .addr = A_BBRAM_SLVERR,
  337. .rsvd = ~1,
  338. },{ .name = "BBRAM_ISR", .addr = A_BBRAM_ISR,
  339. .w1c = 0x1,
  340. .post_write = bbram_isr_postw,
  341. },{ .name = "BBRAM_IMR", .addr = A_BBRAM_IMR,
  342. .ro = 0x1,
  343. },{ .name = "BBRAM_IER", .addr = A_BBRAM_IER,
  344. .pre_write = bbram_ier_prew,
  345. },{ .name = "BBRAM_IDR", .addr = A_BBRAM_IDR,
  346. .pre_write = bbram_idr_prew,
  347. },{ .name = "BBRAM_MSW_LOCK", .addr = A_BBRAM_MSW_LOCK,
  348. .pre_write = bbram_msw_lock_prew,
  349. .ro = ~R_BBRAM_MSW_LOCK_VAL_MASK,
  350. }
  351. };
  352. static void bbram_ctrl_reset_hold(Object *obj, ResetType type)
  353. {
  354. XlnxBBRam *s = XLNX_BBRAM(obj);
  355. unsigned int i;
  356. for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
  357. if (i < R_BBRAM_0 || i > R_BBRAM_8) {
  358. register_reset(&s->regs_info[i]);
  359. }
  360. }
  361. bbram_update_irq(s);
  362. }
  363. static const MemoryRegionOps bbram_ctrl_ops = {
  364. .read = register_read_memory,
  365. .write = register_write_memory,
  366. .endianness = DEVICE_LITTLE_ENDIAN,
  367. .valid = {
  368. .min_access_size = 4,
  369. .max_access_size = 4,
  370. },
  371. };
  372. static void bbram_ctrl_realize(DeviceState *dev, Error **errp)
  373. {
  374. XlnxBBRam *s = XLNX_BBRAM(dev);
  375. if (s->crc_zpads) {
  376. s->bbram8_wo = true;
  377. }
  378. bbram_bdrv_read(s, errp);
  379. }
  380. static void bbram_ctrl_init(Object *obj)
  381. {
  382. XlnxBBRam *s = XLNX_BBRAM(obj);
  383. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  384. s->reg_array =
  385. register_init_block32(DEVICE(obj), bbram_ctrl_regs_info,
  386. ARRAY_SIZE(bbram_ctrl_regs_info),
  387. s->regs_info, s->regs,
  388. &bbram_ctrl_ops,
  389. XLNX_BBRAM_ERR_DEBUG,
  390. R_MAX * 4);
  391. sysbus_init_mmio(sbd, &s->reg_array->mem);
  392. sysbus_init_irq(sbd, &s->irq_bbram);
  393. }
  394. static void bbram_ctrl_finalize(Object *obj)
  395. {
  396. XlnxBBRam *s = XLNX_BBRAM(obj);
  397. register_finalize_block(s->reg_array);
  398. }
  399. static void bbram_prop_set_drive(Object *obj, Visitor *v, const char *name,
  400. void *opaque, Error **errp)
  401. {
  402. DeviceState *dev = DEVICE(obj);
  403. qdev_prop_drive.set(obj, v, name, opaque, errp);
  404. /* Fill initial data if backend is attached after realized */
  405. if (dev->realized) {
  406. bbram_bdrv_read(XLNX_BBRAM(obj), errp);
  407. }
  408. }
  409. static void bbram_prop_get_drive(Object *obj, Visitor *v, const char *name,
  410. void *opaque, Error **errp)
  411. {
  412. qdev_prop_drive.get(obj, v, name, opaque, errp);
  413. }
  414. static void bbram_prop_release_drive(Object *obj, const char *name,
  415. void *opaque)
  416. {
  417. qdev_prop_drive.release(obj, name, opaque);
  418. }
  419. static const PropertyInfo bbram_prop_drive = {
  420. .type = "str",
  421. .description = "Node name or ID of a block device to use as BBRAM backend",
  422. .realized_set_allowed = true,
  423. .get = bbram_prop_get_drive,
  424. .set = bbram_prop_set_drive,
  425. .release = bbram_prop_release_drive,
  426. };
  427. static const VMStateDescription vmstate_bbram_ctrl = {
  428. .name = TYPE_XLNX_BBRAM,
  429. .version_id = 1,
  430. .minimum_version_id = 1,
  431. .fields = (const VMStateField[]) {
  432. VMSTATE_UINT32_ARRAY(regs, XlnxBBRam, R_MAX),
  433. VMSTATE_END_OF_LIST(),
  434. }
  435. };
  436. static const Property bbram_ctrl_props[] = {
  437. DEFINE_PROP("drive", XlnxBBRam, blk, bbram_prop_drive, BlockBackend *),
  438. DEFINE_PROP_UINT32("crc-zpads", XlnxBBRam, crc_zpads, 1),
  439. };
  440. static void bbram_ctrl_class_init(ObjectClass *klass, void *data)
  441. {
  442. DeviceClass *dc = DEVICE_CLASS(klass);
  443. ResettableClass *rc = RESETTABLE_CLASS(klass);
  444. rc->phases.hold = bbram_ctrl_reset_hold;
  445. dc->realize = bbram_ctrl_realize;
  446. dc->vmsd = &vmstate_bbram_ctrl;
  447. device_class_set_props(dc, bbram_ctrl_props);
  448. }
  449. static const TypeInfo bbram_ctrl_info = {
  450. .name = TYPE_XLNX_BBRAM,
  451. .parent = TYPE_SYS_BUS_DEVICE,
  452. .instance_size = sizeof(XlnxBBRam),
  453. .class_init = bbram_ctrl_class_init,
  454. .instance_init = bbram_ctrl_init,
  455. .instance_finalize = bbram_ctrl_finalize,
  456. };
  457. static void bbram_ctrl_register_types(void)
  458. {
  459. type_register_static(&bbram_ctrl_info);
  460. }
  461. type_init(bbram_ctrl_register_types)