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