[PATCH] qemu/bitops.h: Locate changed bits
Add inlined functions to obtain a mask of changed bits. 3 flavors are added: toggled, changed to 1, changed to 0. These newly added utilities aid common device behaviors where actions are taken only when a register's bit(s) are changed. Signed-off-by: Tong Ho --- include/qemu/bitops.h | 33 + 1 file changed, 33 insertions(+) diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h index 2c0a2fe751..7a701474ea 100644 --- a/include/qemu/bitops.h +++ b/include/qemu/bitops.h @@ -148,6 +148,39 @@ static inline int test_bit(long nr, const unsigned long *addr) return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); } +/** + * find_bits_changed - Returns a mask of bits changed. + * @ref_bits: the reference bits against which the test is made. + * @chk_bits: the bits to be checked. + */ +static inline unsigned long find_bits_changed(unsigned long ref_bits, + unsigned long chk_bits) +{ +return ref_bits ^ chk_bits; +} + +/** + * find_bits_to_1 - Returns a mask of bits changed from 0 to 1. + * @ref_bits: the reference bits against which the test is made. + * @chk_bits: the bits to be checked. + */ +static inline unsigned long find_bits_to_1(unsigned long ref_bits, + unsigned long chk_bits) +{ +return find_bits_changed(ref_bits, chk_bits) & chk_bits; +} + +/** + * find_bits_to_0 - Returns a mask of bits changed from 1 to 0. + * @ref_bits: the reference bits against which the test is made. + * @chk_bits: the bits to be checked. + */ +static inline unsigned long find_bits_to_0(unsigned long ref_bits, + unsigned long chk_bits) +{ +return find_bits_to_1(chk_bits, ref_bits); +} + /** * find_last_bit - find the last set bit in a memory region * @addr: The address to start the search at -- 2.25.1
[PATCH v2] hw/char/pl011: Add support for loopback
This patch adds loopback for sent characters, sent BREAK, and modem-control signals. Loopback of send and modem-control is often used for uart self tests in real hardware but missing from current pl011 model, resulting in self-test failures when running in QEMU. This implementation matches what is observed in real pl011 hardware placed in loopback mode: 1. Input characters and BREAK events from serial backend are ignored, but 2. Both TX characters and BREAK events are still sent to serial backend, in addition to be looped back to RX. Signed-off-by: Tong Ho Signed-off-by: Francisco Iglesias --- hw/char/pl011.c | 110 +++- 1 file changed, 108 insertions(+), 2 deletions(-) diff --git a/hw/char/pl011.c b/hw/char/pl011.c index 855cb82d08..8753b84a84 100644 --- a/hw/char/pl011.c +++ b/hw/char/pl011.c @@ -49,10 +49,14 @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr) } /* Flag Register, UARTFR */ +#define PL011_FLAG_RI 0x100 #define PL011_FLAG_TXFE 0x80 #define PL011_FLAG_RXFF 0x40 #define PL011_FLAG_TXFF 0x20 #define PL011_FLAG_RXFE 0x10 +#define PL011_FLAG_DCD 0x04 +#define PL011_FLAG_DSR 0x02 +#define PL011_FLAG_CTS 0x01 /* Data Register, UARTDR */ #define DR_BE (1 << 10) @@ -76,6 +80,13 @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr) #define LCR_FEN (1 << 4) #define LCR_BRK (1 << 0) +/* Control Register, UARTCR */ +#define CR_OUT2 (1 << 13) +#define CR_OUT1 (1 << 12) +#define CR_RTS (1 << 11) +#define CR_DTR (1 << 10) +#define CR_LBE (1 << 7) + static const unsigned char pl011_id_arm[8] = { 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }; static const unsigned char pl011_id_luminary[8] = @@ -251,6 +262,89 @@ static void pl011_trace_baudrate_change(const PL011State *s) s->ibrd, s->fbrd); } +static bool pl011_loopback_enabled(PL011State *s) +{ +return !!(s->cr & CR_LBE); +} + +static void pl011_loopback_mdmctrl(PL011State *s) +{ +uint32_t cr, fr, il; + +if (!pl011_loopback_enabled(s)) { +return; +} + +/* + * Loopback software-driven modem control outputs to modem status inputs: + * FR.RI <= CR.Out2 + * FR.DCD <= CR.Out1 + * FR.CTS <= CR.RTS + * FR.DSR <= CR.DTR + * + * The loopback happens immediately even if this call is triggered + * by setting only CR.LBE. + * + * CTS/RTS updates due to enabled hardware flow controls are not + * dealt with here. + */ +cr = s->cr; +fr = s->flags & ~(PL011_FLAG_RI | PL011_FLAG_DCD | + PL011_FLAG_DSR | PL011_FLAG_CTS); +fr |= (cr & CR_OUT2) ? PL011_FLAG_RI : 0; +fr |= (cr & CR_OUT1) ? PL011_FLAG_DCD : 0; +fr |= (cr & CR_RTS) ? PL011_FLAG_CTS : 0; +fr |= (cr & CR_DTR) ? PL011_FLAG_DSR : 0; + +/* Change interrupts based on updated FR */ +il = s->int_level & ~(INT_DSR | INT_DCD | INT_CTS | INT_RI); +il |= (fr & PL011_FLAG_DSR) ? INT_DSR : 0; +il |= (fr & PL011_FLAG_DCD) ? INT_DCD : 0; +il |= (fr & PL011_FLAG_CTS) ? INT_CTS : 0; +il |= (fr & PL011_FLAG_RI) ? INT_RI : 0; + +s->flags = fr; +s->int_level = il; +pl011_update(s); +} + +static void pl011_put_fifo(void *opaque, uint32_t value); + +static void pl011_loopback_tx(PL011State *s, uint32_t value) +{ +if (!pl011_loopback_enabled(s)) { +return; +} + +/* + * Caveat: + * + * In real hardware, TX loopback happens at the serial-bit level + * and then reassembled by the RX logics back into bytes and placed + * into the RX fifo. That is, loopback happens after TX fifo. + * + * Because the real hardware TX fifo is time-drained at the frame + * rate governed by the configured serial format, some loopback + * bytes in TX fifo may still be able to get into the RX fifo + * that could be full at times while being drained at software + * pace. + * + * In such scenario, the RX draining pace is the major factor + * deciding which loopback bytes get into the RX fifo, unless + * hardware flow-control is enabled. + * + * For simplicity, the above described is not emulated. + */ +pl011_put_fifo(s, value); +} + +static void pl011_loopback_break(PL011State *s, int brk_enable) +{ +if (brk_enable) { +pl011_loopback_tx(s, DR_BE); +} +} + static void pl011_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { @@ -266,6 +360,7 @@ static void pl011_write(void *opaque, hwaddr offset, /* XXX this blocks entire thread. Rewrite to use * qemu_chr_fe_write and background I/O callbacks */ qemu_chr_fe_write_all(>chr, , 1); +pl011_loopback_tx(s, ch); s->int_level |= INT_TX;
[PATCH] hw/char/pl011: Add support for loopback
This patch adds loopback for sent characters as well as modem-control signals. Loopback of send and modem-control is often used for uart self tests in real hardware but missing from current pl011 model, resulting in self-test failures when running in QEMU. Signed-off-by: Tong Ho Signed-off-by: Francisco Iglesias --- hw/char/pl011.c | 51 +++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/hw/char/pl011.c b/hw/char/pl011.c index 855cb82d08..3c0e07aa35 100644 --- a/hw/char/pl011.c +++ b/hw/char/pl011.c @@ -121,6 +121,51 @@ static void pl011_update(PL011State *s) } } +static void pl011_put_fifo(void *opaque, uint32_t value); + +static bool pl011_is_loopback(PL011State *s) +{ +return !!(s->cr & (1U << 7)); +} + +static void pl011_tx_loopback(PL011State *s, uint32_t value) +{ +if (pl011_is_loopback(s)) { +pl011_put_fifo(s, value); +} +} + +static uint32_t pl011_cr_loopback(PL011State *s, bool update) +{ +uint32_t cr = s->cr; +uint32_t fr = s->flags; +uint32_t ri = 1 << 8, dcd = 1 << 2, dsr = 1 << 1, cts = 0; +uint32_t out2 = 1 << 13, out1 = 1 << 12, rts = 1 << 11, dtr = 1 << 10; + +if (!pl011_is_loopback(s)) { +return fr; +} + +fr &= ~(ri | dcd | dsr | cts); +fr |= (cr & out2) ? ri : 0; /* FR.RI <= CR.Out2 */ +fr |= (cr & out1) ? dcd : 0; /* FR.DCD <= CR.Out1 */ +fr |= (cr & rts) ? cts : 0; /* FR.CTS <= CR.RTS */ +fr |= (cr & dtr) ? dsr : 0; /* FR.DSR <= CR.DTR */ + +if (!update) { +return fr; +} + +s->int_level &= ~(INT_DSR | INT_DCD | INT_CTS | INT_RI); +s->int_level |= (fr & dsr) ? INT_DSR : 0; +s->int_level |= (fr & dcd) ? INT_DCD : 0; +s->int_level |= (fr & cts) ? INT_CTS : 0; +s->int_level |= (fr & ri) ? INT_RI : 0; +pl011_update(s); + +return fr; +} + static bool pl011_is_fifo_enabled(PL011State *s) { return (s->lcr & LCR_FEN) != 0; @@ -172,7 +217,7 @@ static uint64_t pl011_read(void *opaque, hwaddr offset, r = s->rsr; break; case 6: /* UARTFR */ -r = s->flags; +r = pl011_cr_loopback(s, false); break; case 8: /* UARTILPR */ r = s->ilpr; @@ -267,6 +312,7 @@ static void pl011_write(void *opaque, hwaddr offset, * qemu_chr_fe_write and background I/O callbacks */ qemu_chr_fe_write_all(>chr, , 1); s->int_level |= INT_TX; +pl011_tx_loopback(s, ch); pl011_update(s); break; case 1: /* UARTRSR/UARTECR */ @@ -300,8 +346,9 @@ static void pl011_write(void *opaque, hwaddr offset, pl011_set_read_trigger(s); break; case 12: /* UARTCR */ -/* ??? Need to implement the enable and loopback bits. */ +/* ??? Need to implement the enable bit. */ s->cr = value; +pl011_cr_loopback(s, true); break; case 13: /* UARTIFS */ s->ifl = value; -- 2.25.1
[PATCH v5 0/3] AMD/Xilinx Versal TRNG support
This series adds support for the True Random Number Generator (TRNG) in the AMD/Xilinx Versal family of devices. The series starts by introducing a non-cryptographic grade model of the TRNG controller in the Versal family of devices, followed by instantiating the model in Xilinx Versal machine. The series ends with a q-test for sanity check of the TRNG model in the Xilinx Versal machine. V4 => V5 1) Patch #1 Use host-endian uint32 array to seed GRand to ensure consistent sequence generated in different host endian. 2) Patch #3 a) Remove incorrect time-wait for checking status register update by device-under-test. b) Use g_assert_no_error() instead of g_error() to report failed tests. c) Rename FAILED macro to TRNG_FAILED to build for Windows. V3 => V4 1) Patch #1 a) Simplify the data given to g_rand_set_seed_array() as an array of guint32. b) Use qemu_guest_getrandom_nofail() as the entropy source when the device is configured in TRNG (mode 3). c) Allow 0 and (2^32-1) as valid output of the generator d) Add output-related context to VMSTATE. 2) Patch #3 Remove test's assumption of PRNG output != TRNG output. V2 => V3 1) Patch #1 Use DEFINE_PROP to define a property with custom action on set 2) Patch #1 Remove duplicated version-check on writing to CTRL4 register 3) Patch #2 Defer adding TRNG to machine's device-tree to a future patch 4) Patch #3 Code style fix: group all local vars definitions together V1 => V2 1) Change patch #1 only 2) Use g_rand_*() PRNG from glib to replace V1's custom PRNG. 3) Implement ResettableClass for device-reset. 4) Add device-mode description to commit-message. Best regards, Tong Ho Tong Ho (3): hw/misc: Introduce AMD/Xilix Versal TRNG device hw/arm: xlnx-versal-virt: Add AMD/Xilinx TRNG device tests/qtest: Introduce tests for AMD/Xilinx Versal TRNG device hw/arm/Kconfig | 1 + hw/arm/xlnx-versal.c| 16 + hw/misc/Kconfig | 3 + hw/misc/meson.build | 3 + hw/misc/xlnx-versal-trng.c | 717 include/hw/arm/xlnx-versal.h| 5 + include/hw/misc/xlnx-versal-trng.h | 58 +++ tests/qtest/meson.build | 2 +- tests/qtest/xlnx-versal-trng-test.c | 485 +++ 9 files changed, 1289 insertions(+), 1 deletion(-) create mode 100644 hw/misc/xlnx-versal-trng.c create mode 100644 include/hw/misc/xlnx-versal-trng.h create mode 100644 tests/qtest/xlnx-versal-trng-test.c -- 2.25.1
[PATCH v5 1/3] hw/misc: Introduce AMD/Xilix Versal TRNG device
This adds a non-cryptographic grade implementation of the model for the True Random Number Generator (TRNG) component in AMD/Xilinx Versal device family. This implements all 3 modes defined by the actual hardware specs, all of which selectable by guest software at will at anytime: 1) PRNG mode, in which the generated sequence is required to be reproducible after reseeded by the same 384-bit value as supplied by guest software. 2) Test mode, in which the generated sequence is required to be reproducible ater reseeded by the same 128-bit test seed supplied by guest software. 3) TRNG mode, in which non-reproducible sequence is generated based on periodic reseed by a suitable entropy source. This model is only intended for non-real world testing of guest software, where cryptographically strong PRNG or TRNG is not needed. This model supports versions 1 & 2 of the device, with default to be version 2; the 'hw-version' uint32 property can be set to 0x0100 to override the default. Other implemented properties: - 'forced-prng', uint64 When set to non-zero, mode 3's entropy source is implemented as a deterministic sequence based on the given value and other deterministic parameters. This option allows the emulation to test guest software using mode 3 and to reproduce data-dependent defects. - 'fips-fault-events', uint32, bit-mask bit 3: Triggers the SP800-90B entropy health test fault irq bit 1: Triggers the FIPS 140-2 continuous test fault irq Signed-off-by: Tong Ho --- hw/misc/Kconfig| 3 + hw/misc/meson.build| 3 + hw/misc/xlnx-versal-trng.c | 717 + include/hw/misc/xlnx-versal-trng.h | 58 +++ 4 files changed, 781 insertions(+) create mode 100644 hw/misc/xlnx-versal-trng.c create mode 100644 include/hw/misc/xlnx-versal-trng.h diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index dba41afe67..cc8a8c1418 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -197,4 +197,7 @@ config DJMEMC config IOSB bool +config XLNX_VERSAL_TRNG +bool + source macio/Kconfig diff --git a/hw/misc/meson.build b/hw/misc/meson.build index f60de33f9a..36c20d5637 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -104,6 +104,9 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files( 'xlnx-cfi-if.c', 'xlnx-versal-cframe-reg.c', )) +system_ss.add(when: 'CONFIG_XLNX_VERSAL_TRNG', if_true: files( + 'xlnx-versal-trng.c', +)) system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c')) system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c')) system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c')) diff --git a/hw/misc/xlnx-versal-trng.c b/hw/misc/xlnx-versal-trng.c new file mode 100644 index 00..4d41c262c4 --- /dev/null +++ b/hw/misc/xlnx-versal-trng.c @@ -0,0 +1,717 @@ +/* + * Non-crypto strength model of the True Random Number Generator + * in the AMD/Xilinx Versal device family. + * + * Copyright (c) 2017-2020 Xilinx Inc. + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * + * Written by Edgar E. Iglesias + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "hw/misc/xlnx-versal-trng.h" + +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qemu/guest-random.h" +#include "qemu/timer.h" +#include "qapi/visitor.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" + +#ifndef XLNX_VERSAL_TRNG_ERR_DEBUG +#define XLNX_VERSAL_TRNG_ERR_DEBUG 0 +#endif + +REG32(INT_CTRL, 0x0) +FIELD(INT_CTRL, CERTF_RST, 5, 1) +FIELD(INT_CTRL, DTF_RST, 4, 1) +FIELD(INT_CTRL, DONE_RST, 3, 1) +FIELD(INT_CTRL, CERTF_EN, 2, 1) +FIELD(INT_CTRL, DTF_EN, 1, 1) +FIELD
[PATCH v5 3/3] tests/qtest: Introduce tests for AMD/Xilinx Versal TRNG device
Signed-off-by: Tong Ho --- tests/qtest/meson.build | 2 +- tests/qtest/xlnx-versal-trng-test.c | 485 2 files changed, 486 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/xlnx-versal-trng-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index d6022ebd64..c9945e69b1 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -216,7 +216,7 @@ qtests_aarch64 = \ (config_all.has_key('CONFIG_TCG') and config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ?\ ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) + \ (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 'fuzz-xlnx-dp-test'] : []) + \ - (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test'] : []) + \ + (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test', 'xlnx-versal-trng-test'] : []) + \ (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) + \ (config_all.has_key('CONFIG_TCG') and \ config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \ diff --git a/tests/qtest/xlnx-versal-trng-test.c b/tests/qtest/xlnx-versal-trng-test.c new file mode 100644 index 00..cef4e575bb --- /dev/null +++ b/tests/qtest/xlnx-versal-trng-test.c @@ -0,0 +1,485 @@ +/* + * QTests for the Xilinx Versal True Random Number Generator device + * + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "libqtest-single.h" + +/* Base Address */ +#define TRNG_BASEADDR (0xf123) + +/* TRNG_INT_CTRL */ +#define R_TRNG_INT_CTRL (0x) +#define TRNG_INT_CTRL_CERTF_RST_MASK (1 << 5) +#define TRNG_INT_CTRL_DTF_RST_MASK(1 << 4) +#define TRNG_INT_CTRL_DONE_RST_MASK (1 << 3) +#define TRNG_INT_CTRL_CERTF_EN_MASK (1 << 2) +#define TRNG_INT_CTRL_DTF_EN_MASK (1 << 1) +#define TRNG_INT_CTRL_DONE_EN_MASK(1) + +/* TRNG_STATUS */ +#define R_TRNG_STATUS (0x0004) +#define TRNG_STATUS_QCNT_SHIFT (9) +#define TRNG_STATUS_QCNT_MASK(7 << TRNG_STATUS_QCNT_SHIFT) +#define TRNG_STATUS_CERTF_MASK (1 << 3) +#define TRNG_STATUS_DTF_MASK (1 << 1) +#define TRNG_STATUS_DONE_MASK(1) + +/* TRNG_CTRL */ +#define R_TRNG_CTRL(0x0008) +#define TRNG_CTRL_PERSODISABLE_MASK (1 << 10) +#define TRNG_CTRL_SINGLEGENMODE_MASK (1 << 9) +#define TRNG_CTRL_PRNGMODE_MASK (1 << 7) +#define TRNG_CTRL_TSTMODE_MASK(1 << 6) +#define TRNG_CTRL_PRNGSTART_MASK (1 << 5) +#define TRNG_CTRL_PRNGXS_MASK (1 << 3) +#define TRNG_CTRL_TRSSEN_MASK (1 << 2) +#define TRNG_CTRL_QERTUEN_MASK(1 << 1) +#define TRNG_CTRL_PRNGSRST_MASK (1) + +/* TRNG_EXT_SEED_0 ... _11 */ +#define R_TRNG_EXT_SEED_0 (0x0040) +#define R_TRNG_EXT_SEED_11 (R_TRNG_EXT_SEED_0 + 4 * 11) + +/* TRNG_PER_STRNG_0 ... 11 */ +#define R_TRNG_PER_STRNG_0 (0x0080) +#define R_TRNG_PER_STRNG_11(R_TRNG_PER_STRNG_0 + 4 * 11) + +/* TRNG_CORE_OUTPUT */ +#define R_TRNG_CORE_OUTPUT (0x00c0) + +/* TRNG_RESET */ +#define R_TRNG_RESET (0x00d0) +#define TRNG_RESET_VAL_MASK (1) + +/* TRNG_OSC_EN */ +#define R_TRNG_OSC_EN (0x00d4) +#define TRNG_OSC_EN_VAL_MASK (1) + +/* TRNG_TRNG_ISR, _IMR, _IER, _IDR */ +#define R_TRNG_ISR (0x00e0) +#define R_TRNG_IMR (0x00e4) +#define R_TRNG_IER (0x00e8) +#define R_TRNG_IDR (0x00ec) +#define TRNG_IRQ_SLVERR_MASK (1 << 1) +#define TRNG_IRQ_CORE_INT_MASK (1) + +/* + * End test with a formatted error message, by embedding the message + * in a GError. + */ +#define TRNG_FAILED(FMT, ...) \ +do {\ +g_autoptr(GError) err = g_error_new(\ +g_quark_from_static_string(trng_qname), 0, \ +FMT, ## __VA_ARGS__); \ +g_assert_no_error(err); \ +} while (0) + +static const gchar trng_qname[] = "xlnx-versal-trng-test"; + +static const uint32_t prng_seed[12] = { +0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, +0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98, +}; + +static const uint32_t pers_str[12] = { +0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98, +0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, +}; + +static void trng_test_start(void) +{ +qtest_start("-machine xlnx-versal-virt"); +} + +static void trng_test_stop(vo
[PATCH v5 2/3] hw/arm: xlnx-versal-virt: Add AMD/Xilinx TRNG device
Connect the support for Versal True Random Number Generator (TRNG) device. Warning: unlike the TRNG component in a real device from the Versal device familiy, the connected TRNG model is not of cryptographic grade and is not intended for use cases when cryptograpically strong TRNG is needed. Signed-off-by: Tong Ho Reviewed-by: Francisco Iglesias Reviewed-by: Peter Maydell --- hw/arm/Kconfig | 1 + hw/arm/xlnx-versal.c | 16 include/hw/arm/xlnx-versal.h | 5 + 3 files changed, 22 insertions(+) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 7e68348440..0a3ff6748d 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -482,6 +482,7 @@ config XLNX_VERSAL select XLNX_BBRAM select XLNX_EFUSE_VERSAL select XLNX_USB_SUBSYS +select XLNX_VERSAL_TRNG config NPCM7XX bool diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index fa556d8764..4f74a64a0d 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -373,6 +373,21 @@ static void versal_create_rtc(Versal *s, qemu_irq *pic) qdev_get_gpio_in(DEVICE(>pmc.apb_irq_orgate), 0)); } +static void versal_create_trng(Versal *s, qemu_irq *pic) +{ +SysBusDevice *sbd; +MemoryRegion *mr; + +object_initialize_child(OBJECT(s), "trng", >pmc.trng, +TYPE_XLNX_VERSAL_TRNG); +sbd = SYS_BUS_DEVICE(>pmc.trng); +sysbus_realize(sbd, _fatal); + +mr = sysbus_mmio_get_region(sbd, 0); +memory_region_add_subregion(>mr_ps, MM_PMC_TRNG, mr); +sysbus_connect_irq(sbd, 0, pic[VERSAL_TRNG_IRQ]); +} + static void versal_create_xrams(Versal *s, qemu_irq *pic) { int nr_xrams = ARRAY_SIZE(s->lpd.xram.ctrl); @@ -909,6 +924,7 @@ static void versal_realize(DeviceState *dev, Error **errp) versal_create_sds(s, pic); versal_create_pmc_apb_irq_orgate(s, pic); versal_create_rtc(s, pic); +versal_create_trng(s, pic); versal_create_xrams(s, pic); versal_create_bbram(s, pic); versal_create_efuse(s, pic); diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index b710d71fb0..b24fa64557 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -30,6 +30,7 @@ #include "hw/dma/xlnx_csu_dma.h" #include "hw/misc/xlnx-versal-crl.h" #include "hw/misc/xlnx-versal-pmc-iou-slcr.h" +#include "hw/misc/xlnx-versal-trng.h" #include "hw/net/xlnx-versal-canfd.h" #include "hw/misc/xlnx-versal-cfu.h" #include "hw/misc/xlnx-versal-cframe-reg.h" @@ -115,6 +116,7 @@ struct Versal { } iou; XlnxZynqMPRTC rtc; +XlnxVersalTRng trng; XlnxBBRam bbram; XlnxEFuse efuse; XlnxVersalEFuseCtrl efuse_ctrl; @@ -159,6 +161,7 @@ struct Versal { #define VERSAL_OSPI_IRQ124 #define VERSAL_SD0_IRQ_0 126 #define VERSAL_EFUSE_IRQ 139 +#define VERSAL_TRNG_IRQ141 #define VERSAL_RTC_ALARM_IRQ 142 #define VERSAL_RTC_SECONDS_IRQ 143 @@ -328,4 +331,6 @@ struct Versal { #define MM_PMC_CRP_SIZE 0x1 #define MM_PMC_RTC 0xf12a #define MM_PMC_RTC_SIZE 0x1 +#define MM_PMC_TRNG 0xf123 +#define MM_PMC_TRNG_SIZE0x1 #endif -- 2.25.1
[PATCH v4 3/3] tests/qtest: Introduce tests for AMD/Xilinx Versal TRNG device
Signed-off-by: Tong Ho --- tests/qtest/meson.build | 2 +- tests/qtest/xlnx-versal-trng-test.c | 486 2 files changed, 487 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/xlnx-versal-trng-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 66795cfcd2..593ca6714b 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -216,7 +216,7 @@ qtests_aarch64 = \ (config_all.has_key('CONFIG_TCG') and config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ?\ ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) + \ (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 'fuzz-xlnx-dp-test'] : []) + \ - (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test'] : []) + \ + (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test', 'xlnx-versal-trng-test'] : []) + \ (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) + \ (config_all.has_key('CONFIG_TCG') and \ config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \ diff --git a/tests/qtest/xlnx-versal-trng-test.c b/tests/qtest/xlnx-versal-trng-test.c new file mode 100644 index 00..dc19c1e83b --- /dev/null +++ b/tests/qtest/xlnx-versal-trng-test.c @@ -0,0 +1,486 @@ +/* + * QTests for the Xilinx Versal True Random Number Generator device + * + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "libqtest-single.h" + +/* Base Address */ +#define TRNG_BASEADDR (0xf123) + +/* TRNG_INT_CTRL */ +#define R_TRNG_INT_CTRL (0x) +#define TRNG_INT_CTRL_CERTF_RST_MASK (1 << 5) +#define TRNG_INT_CTRL_DTF_RST_MASK(1 << 4) +#define TRNG_INT_CTRL_DONE_RST_MASK (1 << 3) +#define TRNG_INT_CTRL_CERTF_EN_MASK (1 << 2) +#define TRNG_INT_CTRL_DTF_EN_MASK (1 << 1) +#define TRNG_INT_CTRL_DONE_EN_MASK(1) + +/* TRNG_STATUS */ +#define R_TRNG_STATUS (0x0004) +#define TRNG_STATUS_QCNT_SHIFT (9) +#define TRNG_STATUS_QCNT_MASK(7 << TRNG_STATUS_QCNT_SHIFT) +#define TRNG_STATUS_CERTF_MASK (1 << 3) +#define TRNG_STATUS_DTF_MASK (1 << 1) +#define TRNG_STATUS_DONE_MASK(1) + +/* TRNG_CTRL */ +#define R_TRNG_CTRL(0x0008) +#define TRNG_CTRL_PERSODISABLE_MASK (1 << 10) +#define TRNG_CTRL_SINGLEGENMODE_MASK (1 << 9) +#define TRNG_CTRL_PRNGMODE_MASK (1 << 7) +#define TRNG_CTRL_TSTMODE_MASK(1 << 6) +#define TRNG_CTRL_PRNGSTART_MASK (1 << 5) +#define TRNG_CTRL_PRNGXS_MASK (1 << 3) +#define TRNG_CTRL_TRSSEN_MASK (1 << 2) +#define TRNG_CTRL_QERTUEN_MASK(1 << 1) +#define TRNG_CTRL_PRNGSRST_MASK (1) + +/* TRNG_EXT_SEED_0 ... _11 */ +#define R_TRNG_EXT_SEED_0 (0x0040) +#define R_TRNG_EXT_SEED_11 (R_TRNG_EXT_SEED_0 + 4 * 11) + +/* TRNG_PER_STRNG_0 ... 11 */ +#define R_TRNG_PER_STRNG_0 (0x0080) +#define R_TRNG_PER_STRNG_11(R_TRNG_PER_STRNG_0 + 4 * 11) + +/* TRNG_CORE_OUTPUT */ +#define R_TRNG_CORE_OUTPUT (0x00c0) + +/* TRNG_RESET */ +#define R_TRNG_RESET (0x00d0) +#define TRNG_RESET_VAL_MASK (1) + +/* TRNG_OSC_EN */ +#define R_TRNG_OSC_EN (0x00d4) +#define TRNG_OSC_EN_VAL_MASK (1) + +/* TRNG_TRNG_ISR, _IMR, _IER, _IDR */ +#define R_TRNG_ISR (0x00e0) +#define R_TRNG_IMR (0x00e4) +#define R_TRNG_IER (0x00e8) +#define R_TRNG_IDR (0x00ec) +#define TRNG_IRQ_SLVERR_MASK (1 << 1) +#define TRNG_IRQ_CORE_INT_MASK (1) + +#define FAILED(FMT, ...) g_error("%s(): " FMT, __func__, ## __VA_ARGS__) + +static const uint32_t prng_seed[12] = { +0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, +0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98, +}; + +static const uint32_t pers_str[12] = { +0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98, +0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, +}; + +static void trng_test_start(void) +{ +qtest_start("-machine xlnx-versal-virt"); +} + +static void trng_test_stop(void) +{ +qtest_end(); +} + +static void trng_test_set_uint_prop(const char *name, uint64_t value) +{ +const char *path = "/machine/xlnx-versal/trng"; +QDict *response; + +response = qmp("{ 'execute': 'qom-set'," +" 'arguments': {" + " 'path': %s," + " 'property': %s," + " 'value': %llu" +
[PATCH v4 0/3] AMD/Xilinx Versal TRNG support
This series adds support for the True Random Number Generator (TRNG) in the AMD/Xilinx Versal family of devices. The series starts by introducing a non-cryptographic grade model of the TRNG controller in the Versal family of devices, followed by instantiating the model in Xilinx Versal machine. The series ends with a q-test for sanity check of the TRNG model in the Xilinx Versal machine. V3 => V4 1) Patch #1 a) Simplify the data given to g_rand_set_seed_array() as an array of guint32. b) Use qemu_guest_getrandom_nofail() as the entropy source when the device is configured in TRNG (mode 3). c) Allow 0 and (2^32-1) as valid output of the generator d) Add output-related context to VMSTATE. 2) Patch #3 Remove test's assumption of PRNG output != TRNG output. V2 => V3 1) Patch #1 Use DEFINE_PROP to define a property with custom action on set 2) Patch #1 Remove duplicated version-check on writing to CTRL4 register 3) Patch #2 Defer adding TRNG to machine's device-tree to a future patch 4) Patch #3 Code style fix: group all local vars definitions together V1 => V2 1) Change patch #1 only 2) Use g_rand_*() PRNG from glib to replace V1's custom PRNG. 3) Implement ResettableClass for device-reset. 4) Add device-mode description to commit-message. Best regards, Tong Ho Tong Ho (3): hw/misc: Introduce AMD/Xilix Versal TRNG device hw/arm: xlnx-versal-virt: Add AMD/Xilinx TRNG device tests/qtest: Introduce tests for AMD/Xilinx Versal TRNG device hw/arm/Kconfig | 1 + hw/arm/xlnx-versal.c| 16 + hw/misc/Kconfig | 3 + hw/misc/meson.build | 3 + hw/misc/xlnx-versal-trng.c | 727 include/hw/arm/xlnx-versal.h| 5 + include/hw/misc/xlnx-versal-trng.h | 58 +++ tests/qtest/meson.build | 2 +- tests/qtest/xlnx-versal-trng-test.c | 486 +++ 9 files changed, 1300 insertions(+), 1 deletion(-) create mode 100644 hw/misc/xlnx-versal-trng.c create mode 100644 include/hw/misc/xlnx-versal-trng.h create mode 100644 tests/qtest/xlnx-versal-trng-test.c -- 2.25.1
[PATCH v4 1/3] hw/misc: Introduce AMD/Xilix Versal TRNG device
This adds a non-cryptographic grade implementation of the model for the True Random Number Generator (TRNG) component in AMD/Xilinx Versal device family. This implements all 3 modes defined by the actual hardware specs, all of which selectable by guest software at will at anytime: 1) PRNG mode, in which the generated sequence is required to be reproducible after reseeded by the same 384-bit value as supplied by guest software. 2) Test mode, in which the generated sequence is required to be reproducible ater reseeded by the same 128-bit test seed supplied by guest software. 3) TRNG mode, in which non-reproducible sequence is generated based on periodic reseed by a suitable entropy source. This model is only intended for non-real world testing of guest software, where cryptographically strong PRNG or TRNG is not needed. This model supports versions 1 & 2 of the device, with default to be version 2; the 'hw-version' uint32 property can be set to 0x0100 to override the default. Other implemented properties: - 'forced-prng', uint64 When set to non-zero, mode 3's entropy source is implemented as a deterministic sequence based on the given value and other deterministic parameters. This option allows the emulation to test guest software using mode 3 and to reproduce data-dependent defects. - 'fips-fault-events', uint32, bit-mask bit 3: Triggers the SP800-90B entropy health test fault irq bit 1: Triggers the FIPS 140-2 continuous test fault irq Signed-off-by: Tong Ho --- hw/misc/Kconfig| 3 + hw/misc/meson.build| 3 + hw/misc/xlnx-versal-trng.c | 727 + include/hw/misc/xlnx-versal-trng.h | 58 +++ 4 files changed, 791 insertions(+) create mode 100644 hw/misc/xlnx-versal-trng.c create mode 100644 include/hw/misc/xlnx-versal-trng.h diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index dba41afe67..cc8a8c1418 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -197,4 +197,7 @@ config DJMEMC config IOSB bool +config XLNX_VERSAL_TRNG +bool + source macio/Kconfig diff --git a/hw/misc/meson.build b/hw/misc/meson.build index f60de33f9a..36c20d5637 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -104,6 +104,9 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files( 'xlnx-cfi-if.c', 'xlnx-versal-cframe-reg.c', )) +system_ss.add(when: 'CONFIG_XLNX_VERSAL_TRNG', if_true: files( + 'xlnx-versal-trng.c', +)) system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c')) system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c')) system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c')) diff --git a/hw/misc/xlnx-versal-trng.c b/hw/misc/xlnx-versal-trng.c new file mode 100644 index 00..fb0130a6b2 --- /dev/null +++ b/hw/misc/xlnx-versal-trng.c @@ -0,0 +1,727 @@ +/* + * Non-crypto strength model of the True Random Number Generator + * in the AMD/Xilinx Versal device family. + * + * Copyright (c) 2017-2020 Xilinx Inc. + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * + * Written by Edgar E. Iglesias + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "hw/misc/xlnx-versal-trng.h" + +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qemu/guest-random.h" +#include "qemu/timer.h" +#include "qapi/visitor.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" + +#ifndef XLNX_VERSAL_TRNG_ERR_DEBUG +#define XLNX_VERSAL_TRNG_ERR_DEBUG 0 +#endif + +REG32(INT_CTRL, 0x0) +FIELD(INT_CTRL, CERTF_RST, 5, 1) +FIELD(INT_CTRL, DTF_RST, 4, 1) +FIELD(INT_CTRL, DONE_RST, 3, 1) +FIELD(INT_CTRL, CERTF_EN, 2, 1) +FIELD(INT_CTRL, DTF_EN, 1, 1) +FIELD
[PATCH v4 2/3] hw/arm: xlnx-versal-virt: Add AMD/Xilinx TRNG device
Connect the support for Versal True Random Number Generator (TRNG) device. Warning: unlike the TRNG component in a real device from the Versal device familiy, the connected TRNG model is not of cryptographic grade and is not intended for use cases when cryptograpically strong TRNG is needed. Signed-off-by: Tong Ho --- hw/arm/Kconfig | 1 + hw/arm/xlnx-versal.c | 16 include/hw/arm/xlnx-versal.h | 5 + 3 files changed, 22 insertions(+) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 7e68348440..0a3ff6748d 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -482,6 +482,7 @@ config XLNX_VERSAL select XLNX_BBRAM select XLNX_EFUSE_VERSAL select XLNX_USB_SUBSYS +select XLNX_VERSAL_TRNG config NPCM7XX bool diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index fa556d8764..4f74a64a0d 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -373,6 +373,21 @@ static void versal_create_rtc(Versal *s, qemu_irq *pic) qdev_get_gpio_in(DEVICE(>pmc.apb_irq_orgate), 0)); } +static void versal_create_trng(Versal *s, qemu_irq *pic) +{ +SysBusDevice *sbd; +MemoryRegion *mr; + +object_initialize_child(OBJECT(s), "trng", >pmc.trng, +TYPE_XLNX_VERSAL_TRNG); +sbd = SYS_BUS_DEVICE(>pmc.trng); +sysbus_realize(sbd, _fatal); + +mr = sysbus_mmio_get_region(sbd, 0); +memory_region_add_subregion(>mr_ps, MM_PMC_TRNG, mr); +sysbus_connect_irq(sbd, 0, pic[VERSAL_TRNG_IRQ]); +} + static void versal_create_xrams(Versal *s, qemu_irq *pic) { int nr_xrams = ARRAY_SIZE(s->lpd.xram.ctrl); @@ -909,6 +924,7 @@ static void versal_realize(DeviceState *dev, Error **errp) versal_create_sds(s, pic); versal_create_pmc_apb_irq_orgate(s, pic); versal_create_rtc(s, pic); +versal_create_trng(s, pic); versal_create_xrams(s, pic); versal_create_bbram(s, pic); versal_create_efuse(s, pic); diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 7b419f88c2..54f4b98d9d 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -31,6 +31,7 @@ #include "hw/dma/xlnx_csu_dma.h" #include "hw/misc/xlnx-versal-crl.h" #include "hw/misc/xlnx-versal-pmc-iou-slcr.h" +#include "hw/misc/xlnx-versal-trng.h" #include "hw/net/xlnx-versal-canfd.h" #include "hw/misc/xlnx-versal-cfu.h" #include "hw/misc/xlnx-versal-cframe-reg.h" @@ -116,6 +117,7 @@ struct Versal { } iou; XlnxZynqMPRTC rtc; +XlnxVersalTRng trng; XlnxBBRam bbram; XlnxEFuse efuse; XlnxVersalEFuseCtrl efuse_ctrl; @@ -160,6 +162,7 @@ struct Versal { #define VERSAL_OSPI_IRQ124 #define VERSAL_SD0_IRQ_0 126 #define VERSAL_EFUSE_IRQ 139 +#define VERSAL_TRNG_IRQ141 #define VERSAL_RTC_ALARM_IRQ 142 #define VERSAL_RTC_SECONDS_IRQ 143 @@ -329,4 +332,6 @@ struct Versal { #define MM_PMC_CRP_SIZE 0x1 #define MM_PMC_RTC 0xf12a #define MM_PMC_RTC_SIZE 0x1 +#define MM_PMC_TRNG 0xf123 +#define MM_PMC_TRNG_SIZE0x1 #endif -- 2.25.1
[PATCH v3 2/3] hw/arm: xlnx-versal-virt: Add AMD/Xilinx TRNG device
Connect the support for Versal True Random Number Generator (TRNG) device. Warning: unlike the TRNG component in a real device from the Versal device familiy, the connected TRNG model is not of cryptographic grade and is not intended for use cases when cryptograpically strong TRNG is needed. Signed-off-by: Tong Ho --- hw/arm/Kconfig | 1 + hw/arm/xlnx-versal.c | 16 include/hw/arm/xlnx-versal.h | 5 + 3 files changed, 22 insertions(+) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 7e68348440..0a3ff6748d 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -482,6 +482,7 @@ config XLNX_VERSAL select XLNX_BBRAM select XLNX_EFUSE_VERSAL select XLNX_USB_SUBSYS +select XLNX_VERSAL_TRNG config NPCM7XX bool diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index fa556d8764..4f74a64a0d 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -373,6 +373,21 @@ static void versal_create_rtc(Versal *s, qemu_irq *pic) qdev_get_gpio_in(DEVICE(>pmc.apb_irq_orgate), 0)); } +static void versal_create_trng(Versal *s, qemu_irq *pic) +{ +SysBusDevice *sbd; +MemoryRegion *mr; + +object_initialize_child(OBJECT(s), "trng", >pmc.trng, +TYPE_XLNX_VERSAL_TRNG); +sbd = SYS_BUS_DEVICE(>pmc.trng); +sysbus_realize(sbd, _fatal); + +mr = sysbus_mmio_get_region(sbd, 0); +memory_region_add_subregion(>mr_ps, MM_PMC_TRNG, mr); +sysbus_connect_irq(sbd, 0, pic[VERSAL_TRNG_IRQ]); +} + static void versal_create_xrams(Versal *s, qemu_irq *pic) { int nr_xrams = ARRAY_SIZE(s->lpd.xram.ctrl); @@ -909,6 +924,7 @@ static void versal_realize(DeviceState *dev, Error **errp) versal_create_sds(s, pic); versal_create_pmc_apb_irq_orgate(s, pic); versal_create_rtc(s, pic); +versal_create_trng(s, pic); versal_create_xrams(s, pic); versal_create_bbram(s, pic); versal_create_efuse(s, pic); diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 7b419f88c2..54f4b98d9d 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -31,6 +31,7 @@ #include "hw/dma/xlnx_csu_dma.h" #include "hw/misc/xlnx-versal-crl.h" #include "hw/misc/xlnx-versal-pmc-iou-slcr.h" +#include "hw/misc/xlnx-versal-trng.h" #include "hw/net/xlnx-versal-canfd.h" #include "hw/misc/xlnx-versal-cfu.h" #include "hw/misc/xlnx-versal-cframe-reg.h" @@ -116,6 +117,7 @@ struct Versal { } iou; XlnxZynqMPRTC rtc; +XlnxVersalTRng trng; XlnxBBRam bbram; XlnxEFuse efuse; XlnxVersalEFuseCtrl efuse_ctrl; @@ -160,6 +162,7 @@ struct Versal { #define VERSAL_OSPI_IRQ124 #define VERSAL_SD0_IRQ_0 126 #define VERSAL_EFUSE_IRQ 139 +#define VERSAL_TRNG_IRQ141 #define VERSAL_RTC_ALARM_IRQ 142 #define VERSAL_RTC_SECONDS_IRQ 143 @@ -329,4 +332,6 @@ struct Versal { #define MM_PMC_CRP_SIZE 0x1 #define MM_PMC_RTC 0xf12a #define MM_PMC_RTC_SIZE 0x1 +#define MM_PMC_TRNG 0xf123 +#define MM_PMC_TRNG_SIZE0x1 #endif -- 2.25.1
[PATCH v3 3/3] tests/qtest: Introduce tests for AMD/Xilinx Versal TRNG device
Signed-off-by: Tong Ho --- tests/qtest/meson.build | 2 +- tests/qtest/xlnx-versal-trng-test.c | 490 2 files changed, 491 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/xlnx-versal-trng-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 1fba07f4ed..215d20e8cf 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -216,7 +216,7 @@ qtests_aarch64 = \ (config_all.has_key('CONFIG_TCG') and config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ?\ ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) + \ (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 'fuzz-xlnx-dp-test'] : []) + \ - (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test'] : []) + \ + (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test', 'xlnx-versal-trng-test'] : []) + \ (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) + \ (config_all.has_key('CONFIG_TCG') and \ config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \ diff --git a/tests/qtest/xlnx-versal-trng-test.c b/tests/qtest/xlnx-versal-trng-test.c new file mode 100644 index 00..ddafaee72b --- /dev/null +++ b/tests/qtest/xlnx-versal-trng-test.c @@ -0,0 +1,490 @@ +/* + * QTests for the Xilinx Versal True Random Number Generator device + * + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "libqtest-single.h" + +/* Base Address */ +#define TRNG_BASEADDR (0xf123) + +/* TRNG_INT_CTRL */ +#define R_TRNG_INT_CTRL (0x) +#define TRNG_INT_CTRL_CERTF_RST_MASK (1 << 5) +#define TRNG_INT_CTRL_DTF_RST_MASK(1 << 4) +#define TRNG_INT_CTRL_DONE_RST_MASK (1 << 3) +#define TRNG_INT_CTRL_CERTF_EN_MASK (1 << 2) +#define TRNG_INT_CTRL_DTF_EN_MASK (1 << 1) +#define TRNG_INT_CTRL_DONE_EN_MASK(1) + +/* TRNG_STATUS */ +#define R_TRNG_STATUS (0x0004) +#define TRNG_STATUS_QCNT_SHIFT (9) +#define TRNG_STATUS_QCNT_MASK(7 << TRNG_STATUS_QCNT_SHIFT) +#define TRNG_STATUS_CERTF_MASK (1 << 3) +#define TRNG_STATUS_DTF_MASK (1 << 1) +#define TRNG_STATUS_DONE_MASK(1) + +/* TRNG_CTRL */ +#define R_TRNG_CTRL(0x0008) +#define TRNG_CTRL_PERSODISABLE_MASK (1 << 10) +#define TRNG_CTRL_SINGLEGENMODE_MASK (1 << 9) +#define TRNG_CTRL_PRNGMODE_MASK (1 << 7) +#define TRNG_CTRL_TSTMODE_MASK(1 << 6) +#define TRNG_CTRL_PRNGSTART_MASK (1 << 5) +#define TRNG_CTRL_PRNGXS_MASK (1 << 3) +#define TRNG_CTRL_TRSSEN_MASK (1 << 2) +#define TRNG_CTRL_QERTUEN_MASK(1 << 1) +#define TRNG_CTRL_PRNGSRST_MASK (1) + +/* TRNG_EXT_SEED_0 ... _11 */ +#define R_TRNG_EXT_SEED_0 (0x0040) +#define R_TRNG_EXT_SEED_11 (R_TRNG_EXT_SEED_0 + 4 * 11) + +/* TRNG_PER_STRNG_0 ... 11 */ +#define R_TRNG_PER_STRNG_0 (0x0080) +#define R_TRNG_PER_STRNG_11(R_TRNG_PER_STRNG_0 + 4 * 11) + +/* TRNG_CORE_OUTPUT */ +#define R_TRNG_CORE_OUTPUT (0x00c0) + +/* TRNG_RESET */ +#define R_TRNG_RESET (0x00d0) +#define TRNG_RESET_VAL_MASK (1) + +/* TRNG_OSC_EN */ +#define R_TRNG_OSC_EN (0x00d4) +#define TRNG_OSC_EN_VAL_MASK (1) + +/* TRNG_TRNG_ISR, _IMR, _IER, _IDR */ +#define R_TRNG_ISR (0x00e0) +#define R_TRNG_IMR (0x00e4) +#define R_TRNG_IER (0x00e8) +#define R_TRNG_IDR (0x00ec) +#define TRNG_IRQ_SLVERR_MASK (1 << 1) +#define TRNG_IRQ_CORE_INT_MASK (1) + +#define FAILED(FMT, ...) g_error("%s(): " FMT, __func__, ## __VA_ARGS__) + +static const uint32_t prng_seed[12] = { +0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, +0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98, +}; + +static const uint32_t pers_str[12] = { +0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98, +0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, +}; + +static void trng_test_start(void) +{ +qtest_start("-machine xlnx-versal-virt"); +} + +static void trng_test_stop(void) +{ +qtest_end(); +} + +static void trng_test_set_uint_prop(const char *name, uint64_t value) +{ +const char *path = "/machine/xlnx-versal/trng"; +QDict *response; + +response = qmp("{ 'execute': 'qom-set'," +" 'arguments': {" + " 'path': %s," + " 'property': %s," + " 'value': %llu" +
[PATCH v3 0/3] AMD/Xilinx Versal TRNG support
This series adds support for the True Random Number Generator (TRNG) in the AMD/Xilinx Versal family of devices. The series starts by introducing a non-cryptographic grade model of the TRNG controller in the Versal family of devices, followed by instantiating the model in Xilinx Versal machine. The series ends with a q-test for sanity check of the TRNG model in the Xilinx Versal machine. V2 => V3 1) Patch #1 Use DEFINE_PROP to define a property with custom action on set 2) Patch #1 Remove duplicated version-check on writing to CTRL4 register 3) Patch #2 Defer adding TRNG to machine's device-tree to a future patch 4) Patch #3 Code style fix: group all local vars definitions together V1 => V2 1) Change patch #1 only 2) Use g_rand_*() PRNG from glib to replace V1's custom PRNG. 3) Implement ResettableClass for device-reset. 4) Add device-mode description to commit-message. Best regards, Tong Ho Tong Ho (3): hw/misc: Introduce AMD/Xilix Versal TRNG device hw/arm: xlnx-versal-virt: Add AMD/Xilinx TRNG device tests/qtest: Introduce tests for AMD/Xilinx Versal TRNG device hw/arm/Kconfig | 1 + hw/arm/xlnx-versal.c| 16 + hw/misc/Kconfig | 3 + hw/misc/meson.build | 3 + hw/misc/xlnx-versal-trng.c | 732 include/hw/arm/xlnx-versal.h| 5 + include/hw/misc/xlnx-versal-trng.h | 58 +++ tests/qtest/meson.build | 2 +- tests/qtest/xlnx-versal-trng-test.c | 490 +++ 9 files changed, 1309 insertions(+), 1 deletion(-) create mode 100644 hw/misc/xlnx-versal-trng.c create mode 100644 include/hw/misc/xlnx-versal-trng.h create mode 100644 tests/qtest/xlnx-versal-trng-test.c -- 2.25.1
[PATCH v3 1/3] hw/misc: Introduce AMD/Xilix Versal TRNG device
This adds a non-cryptographic grade implementation of the model for the True Random Number Generator (TRNG) component in AMD/Xilinx Versal device family. This implements all 3 modes defined by the actual hardware specs, all of which selectable by guest software at will at anytime: 1) PRNG mode, in which the generated sequence is required to be reproducible after reseeded by the same 384-bit value as supplied by guest software. 2) Test mode, in which the generated sequence is required to be reproducible ater reseeded by the same 128-bit test seed supplied by guest software. 3) TRNG mode, in which non-reproducible sequence is generated based on periodic reseed by a suitable entropy source. This model is only intended for non-real world testing of guest software, where cryptographically strong PRNG and TRNG is not needed. This model supports versions 1 & 2 of the device, with default to be version 2; the 'hw-version' uint32 property can be set to 0x0100 to override the default. Other implemented properties: - 'forced-prng', uint64 When set to non-zero, mode 3's entropy source is implemented as a deterministic sequence based on the given value and other deterministic parameters. This option allows the emulation to test guest software using mode 3 and to reproduce data-dependent defects. - 'fips-fault-events', uint32, bit-mask bit 3: Triggers the SP800-90B entropy health test fault irq bit 1: Triggers the FIPS 140-2 continuous test fault irq Signed-off-by: Tong Ho --- hw/misc/Kconfig| 3 + hw/misc/meson.build| 3 + hw/misc/xlnx-versal-trng.c | 732 + include/hw/misc/xlnx-versal-trng.h | 58 +++ 4 files changed, 796 insertions(+) create mode 100644 hw/misc/xlnx-versal-trng.c create mode 100644 include/hw/misc/xlnx-versal-trng.h diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 6996d265e4..6b6105dcbf 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -186,4 +186,7 @@ config AXP2XX_PMU bool depends on I2C +config XLNX_VERSAL_TRNG +bool + source macio/Kconfig diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 88ecab8392..8507ec9e86 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -102,6 +102,9 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files( 'xlnx-cfi-if.c', 'xlnx-versal-cframe-reg.c', )) +system_ss.add(when: 'CONFIG_XLNX_VERSAL_TRNG', if_true: files( + 'xlnx-versal-trng.c', +)) system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c')) system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c')) system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c')) diff --git a/hw/misc/xlnx-versal-trng.c b/hw/misc/xlnx-versal-trng.c new file mode 100644 index 00..168328cf3f --- /dev/null +++ b/hw/misc/xlnx-versal-trng.c @@ -0,0 +1,732 @@ +/* + * Non-crypto strength model of the True Random Number Generator + * in the AMD/Xilinx Versal device family. + * + * Copyright (c) 2017-2020 Xilinx Inc. + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * + * Written by Edgar E. Iglesias + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "hw/misc/xlnx-versal-trng.h" + +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qemu/timer.h" +#include "qapi/visitor.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" + +#ifndef XLNX_VERSAL_TRNG_ERR_DEBUG +#define XLNX_VERSAL_TRNG_ERR_DEBUG 0 +#endif + +REG32(INT_CTRL, 0x0) +FIELD(INT_CTRL, CERTF_RST, 5, 1) +FIELD(INT_CTRL, DTF_RST, 4, 1) +FIELD(INT_CTRL, DONE_RST, 3, 1) +FIELD(INT_CTRL, CERTF_EN, 2, 1) +FIELD(INT_CTRL, DTF_EN, 1, 1) +FIELD(INT_CTRL, DONE_EN, 0, 1) +REG32(ST
[PATCH] xlnx-zynqmp-efuse: hw/nvram: Remove deprecated device reset
This change implements the ResettableClass interface for the device. Signed-off-by: Tong Ho --- hw/nvram/xlnx-zynqmp-efuse.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c index 228ba0bbfa..3db5f98ec1 100644 --- a/hw/nvram/xlnx-zynqmp-efuse.c +++ b/hw/nvram/xlnx-zynqmp-efuse.c @@ -2,6 +2,7 @@ * QEMU model of the ZynqMP eFuse * * Copyright (c) 2015 Xilinx Inc. + * Copyright (c) 2023 Advanced Micro Devices, Inc. * * Written by Edgar E. Iglesias * @@ -769,9 +770,9 @@ static void zynqmp_efuse_register_reset(RegisterInfo *reg) register_reset(reg); } -static void zynqmp_efuse_reset(DeviceState *dev) +static void zynqmp_efuse_reset_hold(Object *obj) { -XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(dev); +XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(obj); unsigned int i; for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) { @@ -837,8 +838,9 @@ static Property zynqmp_efuse_props[] = { static void zynqmp_efuse_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); +ResettableClass *rc = RESETTABLE_CLASS(klass); -dc->reset = zynqmp_efuse_reset; +rc->phases.hold = zynqmp_efuse_reset_hold; dc->realize = zynqmp_efuse_realize; dc->vmsd = _efuse; device_class_set_props(dc, zynqmp_efuse_props); -- 2.25.1
[PATCH] xlnx-versal-efuse: hw/nvram: Remove deprecated device reset
This change implements the ResettableClass interface for the device. Signed-off-by: Tong Ho --- hw/nvram/xlnx-versal-efuse-ctrl.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c b/hw/nvram/xlnx-versal-efuse-ctrl.c index b35ba65ab5..beb5661c35 100644 --- a/hw/nvram/xlnx-versal-efuse-ctrl.c +++ b/hw/nvram/xlnx-versal-efuse-ctrl.c @@ -2,6 +2,7 @@ * QEMU model of the Versal eFuse controller * * Copyright (c) 2020 Xilinx Inc. + * Copyright (c) 2023 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -657,9 +658,9 @@ static void efuse_ctrl_register_reset(RegisterInfo *reg) register_reset(reg); } -static void efuse_ctrl_reset(DeviceState *dev) +static void efuse_ctrl_reset_hold(Object *obj) { -XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(dev); +XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj); unsigned int i; for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) { @@ -749,8 +750,9 @@ static Property efuse_ctrl_props[] = { static void efuse_ctrl_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); +ResettableClass *rc = RESETTABLE_CLASS(klass); -dc->reset = efuse_ctrl_reset; +rc->phases.hold = efuse_ctrl_reset_hold; dc->realize = efuse_ctrl_realize; dc->vmsd = _efuse_ctrl; device_class_set_props(dc, efuse_ctrl_props); -- 2.25.1
[PATCH] xlnx-bbram: hw/nvram: Remove deprecated device reset
This change implements the ResettableClass interface for the device. Signed-off-by: Tong Ho --- hw/nvram/xlnx-bbram.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c index c6b484cc85..e18e7770e1 100644 --- a/hw/nvram/xlnx-bbram.c +++ b/hw/nvram/xlnx-bbram.c @@ -2,6 +2,7 @@ * QEMU model of the Xilinx BBRAM Battery Backed RAM * * Copyright (c) 2014-2021 Xilinx Inc. + * Copyright (c) 2023 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -416,9 +417,9 @@ static RegisterAccessInfo bbram_ctrl_regs_info[] = { } }; -static void bbram_ctrl_reset(DeviceState *dev) +static void bbram_ctrl_reset_hold(Object *obj) { -XlnxBBRam *s = XLNX_BBRAM(dev); +XlnxBBRam *s = XLNX_BBRAM(obj); unsigned int i; for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) { @@ -522,8 +523,9 @@ static Property bbram_ctrl_props[] = { static void bbram_ctrl_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); +ResettableClass *rc = RESETTABLE_CLASS(klass); -dc->reset = bbram_ctrl_reset; +rc->phases.hold = bbram_ctrl_reset_hold; dc->realize = bbram_ctrl_realize; dc->vmsd = _bbram_ctrl; device_class_set_props(dc, bbram_ctrl_props); -- 2.25.1
[PATCH] xlnx-bbram: hw/nvram: Use dot in device type name
This replaces the comma (,) to dot (.) in the device type name so the name can be used with the 'driver=' command line option. Signed-off-by: Tong Ho --- include/hw/nvram/xlnx-bbram.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hw/nvram/xlnx-bbram.h b/include/hw/nvram/xlnx-bbram.h index 87d59ef3c0..6fc13f8cc1 100644 --- a/include/hw/nvram/xlnx-bbram.h +++ b/include/hw/nvram/xlnx-bbram.h @@ -34,7 +34,7 @@ #define RMAX_XLNX_BBRAM ((0x4c / 4) + 1) -#define TYPE_XLNX_BBRAM "xlnx,bbram-ctrl" +#define TYPE_XLNX_BBRAM "xlnx.bbram-ctrl" OBJECT_DECLARE_SIMPLE_TYPE(XlnxBBRam, XLNX_BBRAM); struct XlnxBBRam { -- 2.25.1
[PATCH v2 3/3] tests/qtest: Introduce tests for AMD/Xilinx Versal TRNG device
Signed-off-by: Tong Ho --- tests/qtest/meson.build | 2 +- tests/qtest/xlnx-versal-trng-test.c | 490 2 files changed, 491 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/xlnx-versal-trng-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 1fba07f4ed..215d20e8cf 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -216,7 +216,7 @@ qtests_aarch64 = \ (config_all.has_key('CONFIG_TCG') and config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ?\ ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) + \ (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 'fuzz-xlnx-dp-test'] : []) + \ - (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test'] : []) + \ + (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test', 'xlnx-versal-trng-test'] : []) + \ (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) + \ (config_all.has_key('CONFIG_TCG') and \ config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \ diff --git a/tests/qtest/xlnx-versal-trng-test.c b/tests/qtest/xlnx-versal-trng-test.c new file mode 100644 index 00..6aff00c7fc --- /dev/null +++ b/tests/qtest/xlnx-versal-trng-test.c @@ -0,0 +1,490 @@ +/* + * QTests for the Xilinx Versal True Random Number Generator device + * + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * + * SPDX-License-Identifier: MIT + */ + +#include "qemu/osdep.h" +#include "libqtest-single.h" + +/* Base Address */ +#define TRNG_BASEADDR (0xf123) + +/* TRNG_INT_CTRL */ +#define R_TRNG_INT_CTRL (0x) +#define TRNG_INT_CTRL_CERTF_RST_MASK (1 << 5) +#define TRNG_INT_CTRL_DTF_RST_MASK(1 << 4) +#define TRNG_INT_CTRL_DONE_RST_MASK (1 << 3) +#define TRNG_INT_CTRL_CERTF_EN_MASK (1 << 2) +#define TRNG_INT_CTRL_DTF_EN_MASK (1 << 1) +#define TRNG_INT_CTRL_DONE_EN_MASK(1) + +/* TRNG_STATUS */ +#define R_TRNG_STATUS (0x0004) +#define TRNG_STATUS_QCNT_SHIFT (9) +#define TRNG_STATUS_QCNT_MASK(7 << TRNG_STATUS_QCNT_SHIFT) +#define TRNG_STATUS_CERTF_MASK (1 << 3) +#define TRNG_STATUS_DTF_MASK (1 << 1) +#define TRNG_STATUS_DONE_MASK(1) + +/* TRNG_CTRL */ +#define R_TRNG_CTRL(0x0008) +#define TRNG_CTRL_PERSODISABLE_MASK (1 << 10) +#define TRNG_CTRL_SINGLEGENMODE_MASK (1 << 9) +#define TRNG_CTRL_PRNGMODE_MASK (1 << 7) +#define TRNG_CTRL_TSTMODE_MASK(1 << 6) +#define TRNG_CTRL_PRNGSTART_MASK (1 << 5) +#define TRNG_CTRL_PRNGXS_MASK (1 << 3) +#define TRNG_CTRL_TRSSEN_MASK (1 << 2) +#define TRNG_CTRL_QERTUEN_MASK(1 << 1) +#define TRNG_CTRL_PRNGSRST_MASK (1) + +/* TRNG_EXT_SEED_0 ... _11 */ +#define R_TRNG_EXT_SEED_0 (0x0040) +#define R_TRNG_EXT_SEED_11 (R_TRNG_EXT_SEED_0 + 4 * 11) + +/* TRNG_PER_STRNG_0 ... 11 */ +#define R_TRNG_PER_STRNG_0 (0x0080) +#define R_TRNG_PER_STRNG_11(R_TRNG_PER_STRNG_0 + 4 * 11) + +/* TRNG_CORE_OUTPUT */ +#define R_TRNG_CORE_OUTPUT (0x00c0) + +/* TRNG_RESET */ +#define R_TRNG_RESET (0x00d0) +#define TRNG_RESET_VAL_MASK (1) + +/* TRNG_OSC_EN */ +#define R_TRNG_OSC_EN (0x00d4) +#define TRNG_OSC_EN_VAL_MASK (1) + +/* TRNG_TRNG_ISR, _IMR, _IER, _IDR */ +#define R_TRNG_ISR (0x00e0) +#define R_TRNG_IMR (0x00e4) +#define R_TRNG_IER (0x00e8) +#define R_TRNG_IDR (0x00ec) +#define TRNG_IRQ_SLVERR_MASK (1 << 1) +#define TRNG_IRQ_CORE_INT_MASK (1) + +#define FAILED(FMT, ...) g_error("%s(): " FMT, __func__, ## __VA_ARGS__) + +static const uint32_t prng_seed[12] = { +0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, +0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98, +}; + +static const uint32_t pers_str[12] = { +0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98, +0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, +}; + +static void trng_test_start(void) +{ +qtest_start("-machine xlnx-versal-virt"); +} + +static void trng_test_stop(void) +{ +qtest_end(); +} + +static void trng_test_set_uint_prop(const char *name, uint64_t value) +{ +const char *path = "/machine/xlnx-versal/trng"; +QDict *response; + +response = qmp("{ 'execute': 'qom-set'," +" 'arguments': {" + " 'path': %s," + " 'property': %s," + " 'value': %llu" +
[PATCH v2 2/3] hw/arm: xlnx-versal-virt: Add AMD/Xilinx TRNG device
Connect the support for Versal True Random Number Generator (TRNG) device. Warning: unlike the TRNG component in a real device from the Versal device familiy, the connected TRNG model is not of cryptographic grade and is not intended for use cases when cryptograpically strong TRNG is needed. Signed-off-by: Tong Ho --- hw/arm/Kconfig | 1 + hw/arm/xlnx-versal-virt.c| 20 hw/arm/xlnx-versal.c | 16 include/hw/arm/xlnx-versal.h | 5 + 4 files changed, 42 insertions(+) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 7e68348440..0a3ff6748d 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -482,6 +482,7 @@ config XLNX_VERSAL select XLNX_BBRAM select XLNX_EFUSE_VERSAL select XLNX_USB_SUBSYS +select XLNX_VERSAL_TRNG config NPCM7XX bool diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 88c561ff63..d99255ee89 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -391,6 +391,25 @@ static void fdt_add_rtc_node(VersalVirt *s) g_free(name); } +static void fdt_add_trng_node(VersalVirt *s) +{ +const char compat[] = TYPE_XLNX_VERSAL_TRNG; +const char interrupt_names[] = "trng"; +g_autofree char *name = g_strdup_printf("/trng@%x", MM_PMC_TRNG); + +qemu_fdt_add_subnode(s->fdt, name); + +qemu_fdt_setprop_cells(s->fdt, name, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, VERSAL_TRNG_IRQ, + GIC_FDT_IRQ_FLAGS_LEVEL_HI); +qemu_fdt_setprop(s->fdt, name, "interrupt-names", + interrupt_names, sizeof(interrupt_names)); +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, MM_PMC_TRNG, + 2, MM_PMC_TRNG_SIZE); +qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +} + static void fdt_add_bbram_node(VersalVirt *s) { const char compat[] = TYPE_XLNX_BBRAM; @@ -690,6 +709,7 @@ static void versal_virt_init(MachineState *machine) fdt_add_usb_xhci_nodes(s); fdt_add_sd_nodes(s); fdt_add_rtc_node(s); +fdt_add_trng_node(s); fdt_add_bbram_node(s); fdt_add_efuse_ctrl_node(s); fdt_add_efuse_cache_node(s); diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index fa556d8764..4f74a64a0d 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -373,6 +373,21 @@ static void versal_create_rtc(Versal *s, qemu_irq *pic) qdev_get_gpio_in(DEVICE(>pmc.apb_irq_orgate), 0)); } +static void versal_create_trng(Versal *s, qemu_irq *pic) +{ +SysBusDevice *sbd; +MemoryRegion *mr; + +object_initialize_child(OBJECT(s), "trng", >pmc.trng, +TYPE_XLNX_VERSAL_TRNG); +sbd = SYS_BUS_DEVICE(>pmc.trng); +sysbus_realize(sbd, _fatal); + +mr = sysbus_mmio_get_region(sbd, 0); +memory_region_add_subregion(>mr_ps, MM_PMC_TRNG, mr); +sysbus_connect_irq(sbd, 0, pic[VERSAL_TRNG_IRQ]); +} + static void versal_create_xrams(Versal *s, qemu_irq *pic) { int nr_xrams = ARRAY_SIZE(s->lpd.xram.ctrl); @@ -909,6 +924,7 @@ static void versal_realize(DeviceState *dev, Error **errp) versal_create_sds(s, pic); versal_create_pmc_apb_irq_orgate(s, pic); versal_create_rtc(s, pic); +versal_create_trng(s, pic); versal_create_xrams(s, pic); versal_create_bbram(s, pic); versal_create_efuse(s, pic); diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 7b419f88c2..54f4b98d9d 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -31,6 +31,7 @@ #include "hw/dma/xlnx_csu_dma.h" #include "hw/misc/xlnx-versal-crl.h" #include "hw/misc/xlnx-versal-pmc-iou-slcr.h" +#include "hw/misc/xlnx-versal-trng.h" #include "hw/net/xlnx-versal-canfd.h" #include "hw/misc/xlnx-versal-cfu.h" #include "hw/misc/xlnx-versal-cframe-reg.h" @@ -116,6 +117,7 @@ struct Versal { } iou; XlnxZynqMPRTC rtc; +XlnxVersalTRng trng; XlnxBBRam bbram; XlnxEFuse efuse; XlnxVersalEFuseCtrl efuse_ctrl; @@ -160,6 +162,7 @@ struct Versal { #define VERSAL_OSPI_IRQ124 #define VERSAL_SD0_IRQ_0 126 #define VERSAL_EFUSE_IRQ 139 +#define VERSAL_TRNG_IRQ141 #define VERSAL_RTC_ALARM_IRQ 142 #define VERSAL_RTC_SECONDS_IRQ 143 @@ -329,4 +332,6 @@ struct Versal { #define MM_PMC_CRP_SIZE 0x1 #define MM_PMC_RTC 0xf12a #define MM_PMC_RTC_SIZE 0x1 +#define MM_PMC_TRNG 0xf123 +#define MM_PMC_TRNG_SIZE0x1 #endif -- 2.25.1
[PATCH v2 0/3] AMD/Xilinx Versal TRNG support
This series adds support for the True Random Number Generator (TRNG) in the AMD/Xilinx Versal family of devices. The series starts by introducing a non-cryptographic grade model of the TRNG controller in the Versal family of devices, followed by instantiating the model in Xilinx Versal machine. The series ends with a q-test for sanity check of the TRNG model in the Xilinx Versal machine. V1 => V2 1) Change patch #1 only 2) Use g_rand_*() PRNG from glib to replace V1's custom PRNG. 3) Implement ResettableClass for device-reset. 4) Add device-mode description to commit-message. Best regards, Tong Ho Tong Ho (3): hw/misc: Introduce AMD/Xilix Versal TRNG device hw/arm: xlnx-versal-virt: Add AMD/Xilinx TRNG device tests/qtest: Introduce tests for AMD/Xilinx Versal TRNG device hw/arm/Kconfig | 1 + hw/arm/xlnx-versal-virt.c | 20 + hw/arm/xlnx-versal.c| 16 + hw/misc/Kconfig | 3 + hw/misc/meson.build | 3 + hw/misc/xlnx-versal-trng.c | 734 include/hw/arm/xlnx-versal.h| 5 + include/hw/misc/xlnx-versal-trng.h | 57 +++ tests/qtest/meson.build | 2 +- tests/qtest/xlnx-versal-trng-test.c | 490 +++ 10 files changed, 1330 insertions(+), 1 deletion(-) create mode 100644 hw/misc/xlnx-versal-trng.c create mode 100644 include/hw/misc/xlnx-versal-trng.h create mode 100644 tests/qtest/xlnx-versal-trng-test.c -- 2.25.1
[PATCH v2 1/3] hw/misc: Introduce AMD/Xilix Versal TRNG device
This adds a non-cryptographic grade implementation of the model for the True Random Number Generator (TRNG) component in AMD/Xilinx Versal device family. This implements all 3 modes defined by the actual hardware specs, all of which selectable by guest software at will at anytime: 1) PRNG mode, in which the generated sequence is required to be reproducible after reseeded by the same 384-bit value as supplied by guest software. 2) Test mode, in which the generated sequence is required to be reproducible ater reseeded by the same 128-bit test seed supplied by guest software. 3) TRNG mode, in which non-reproducible sequence is generated based on periodic reseed by a suitable entropy source. This model is only intended for non-real world testing of guest software, where cryptographically strong PRNG and TRNG is not needed. This model supports versions 1 & 2 of the device, with default to be version 2; the 'hw-version' uint32 property can be set to 0x0100 to override the default. Other implemented properties: - 'forced-prng', uint64 When set to non-zero, mode 3's entropy source is implemented as a deterministic sequence based on the given value and other deterministic parameters. This option allows the emulation to test guest software using mode 3 and to reproduce data-dependent defects. - 'fips-fault-events', uint32, bit-mask bit 3: Triggers the SP800-90B entropy health test fault irq bit 1: Triggers the FIPS 140-2 continuous test fault irq Signed-off-by: Tong Ho --- hw/misc/Kconfig| 3 + hw/misc/meson.build| 3 + hw/misc/xlnx-versal-trng.c | 734 + include/hw/misc/xlnx-versal-trng.h | 57 +++ 4 files changed, 797 insertions(+) create mode 100644 hw/misc/xlnx-versal-trng.c create mode 100644 include/hw/misc/xlnx-versal-trng.h diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 6996d265e4..6b6105dcbf 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -186,4 +186,7 @@ config AXP2XX_PMU bool depends on I2C +config XLNX_VERSAL_TRNG +bool + source macio/Kconfig diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 88ecab8392..8507ec9e86 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -102,6 +102,9 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files( 'xlnx-cfi-if.c', 'xlnx-versal-cframe-reg.c', )) +system_ss.add(when: 'CONFIG_XLNX_VERSAL_TRNG', if_true: files( + 'xlnx-versal-trng.c', +)) system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c')) system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c')) system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c')) diff --git a/hw/misc/xlnx-versal-trng.c b/hw/misc/xlnx-versal-trng.c new file mode 100644 index 00..6f52b0d636 --- /dev/null +++ b/hw/misc/xlnx-versal-trng.c @@ -0,0 +1,734 @@ +/* + * Non-crypto strength model of the True Random Number Generator + * in the AMD/Xilinx Versal device family. + * + * Copyright (c) 2017-2020 Xilinx Inc. + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * + * Written by Edgar E. Iglesias + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "hw/misc/xlnx-versal-trng.h" + +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qemu/timer.h" +#include "qapi/visitor.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" + +#ifndef XLNX_VERSAL_TRNG_ERR_DEBUG +#define XLNX_VERSAL_TRNG_ERR_DEBUG 0 +#endif + +REG32(INT_CTRL, 0x0) +FIELD(INT_CTRL, CERTF_RST, 5, 1) +FIELD(INT_CTRL, DTF_RST, 4, 1) +FIELD(INT_CTRL, DONE_RST, 3, 1) +FIELD(INT_CTRL, CERTF_EN, 2, 1) +FIELD(INT_CTRL, DTF_EN, 1, 1) +FIELD(INT_CTRL, DONE_EN, 0, 1) +REG32(ST
[PATCH 1/3] hw/misc: Introduce AMD/Xilix Versal TRNG device
This adds a non-cryptographic grade implementation of the model for the True Random Number Generator (TRNG) component in AMD/Xilinx Versal device family. This model is only intended for non-real world testing of guest software, where cryptographically strong TRNG is not needed. This model supports versions 1 & 2 of the Versal TRNG, with default to be version 2; the 'hw-version' uint32 property can be set to 0x0100 to override the default. Other implemented properties: - 'forced-prng', uint64 When set to non-zero, "true random reseed" is replaced by deterministic reseed based on the given value and other deterministic parameters, even when guest software has configured the TRNG as "true random reseed". This option allows guest software to reproduce data-dependent defects. - 'fips-fault-events', uint32, bit-mask bit 3: Triggers the SP800-90B entropy health test fault irq bit 1: Triggers the FIPS 140-2 continuous test fault irq Signed-off-by: Tong Ho --- hw/misc/Kconfig| 3 + hw/misc/meson.build| 3 + hw/misc/xlnx-versal-trng.c | 725 + include/hw/misc/xlnx-versal-trng.h | 58 +++ 4 files changed, 789 insertions(+) create mode 100644 hw/misc/xlnx-versal-trng.c create mode 100644 include/hw/misc/xlnx-versal-trng.h diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 6996d265e4..6b6105dcbf 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -186,4 +186,7 @@ config AXP2XX_PMU bool depends on I2C +config XLNX_VERSAL_TRNG +bool + source macio/Kconfig diff --git a/hw/misc/meson.build b/hw/misc/meson.build index d9a370c1de..2425187c51 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -99,6 +99,9 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files( 'xlnx-versal-xramc.c', 'xlnx-versal-pmc-iou-slcr.c', )) +system_ss.add(when: 'CONFIG_XLNX_VERSAL_TRNG', if_true: files( + 'xlnx-versal-trng.c', +)) system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c')) system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c')) system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c')) diff --git a/hw/misc/xlnx-versal-trng.c b/hw/misc/xlnx-versal-trng.c new file mode 100644 index 00..8835e78dda --- /dev/null +++ b/hw/misc/xlnx-versal-trng.c @@ -0,0 +1,725 @@ +/* + * Non-crypto strength model of the True Random Number Generator + * in the AMD/Xilinx Versal device family. + * + * Copyright (c) 2017-2020 Xilinx Inc. + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * + * Written by Edgar E. Iglesias + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "hw/misc/xlnx-versal-trng.h" + +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qemu/timer.h" +#include "qapi/visitor.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" + +#ifndef XLNX_VERSAL_TRNG_ERR_DEBUG +#define XLNX_VERSAL_TRNG_ERR_DEBUG 0 +#endif + +REG32(INT_CTRL, 0x0) +FIELD(INT_CTRL, CERTF_RST, 5, 1) +FIELD(INT_CTRL, DTF_RST, 4, 1) +FIELD(INT_CTRL, DONE_RST, 3, 1) +FIELD(INT_CTRL, CERTF_EN, 2, 1) +FIELD(INT_CTRL, DTF_EN, 1, 1) +FIELD(INT_CTRL, DONE_EN, 0, 1) +REG32(STATUS, 0x4) +FIELD(STATUS, QCNT, 9, 3) +FIELD(STATUS, EAT, 4, 5) +FIELD(STATUS, CERTF, 3, 1) +FIELD(STATUS, DTF, 1, 1) +FIELD(STATUS, DONE, 0, 1) +REG32(CTRL, 0x8) +FIELD(CTRL, PERSODISABLE, 10, 1) +FIELD(CTRL, SINGLEGENMODE, 9, 1) +FIELD(CTRL, EUMODE, 8, 1) +FIELD(CTRL, PRNGMODE, 7, 1) +FIELD(CTRL, TSTMODE, 6, 1) +FIELD(CTRL, PRNGSTART, 5, 1) +FIELD(CTRL, EATAU, 4, 1) +FIELD(CTRL, PRNGXS, 3, 1) +FIELD(CTRL, TRSSEN, 2, 1) +FIELD(CTRL, QERTUEN, 1, 1
[PATCH 3/3] tests/qtest: Introduce tests for AMD/Xilinx Versal TRNG device
Signed-off-by: Tong Ho --- tests/qtest/meson.build | 2 +- tests/qtest/xlnx-versal-trng-test.c | 490 2 files changed, 491 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/xlnx-versal-trng-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index b071d400b3..af060d9e5b 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -216,7 +216,7 @@ qtests_aarch64 = \ (config_all.has_key('CONFIG_TCG') and config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ?\ ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) + \ (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 'fuzz-xlnx-dp-test'] : []) + \ - (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test'] : []) + \ + (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test', 'xlnx-versal-trng-test'] : []) + \ (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) + \ (config_all.has_key('CONFIG_TCG') and \ config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \ diff --git a/tests/qtest/xlnx-versal-trng-test.c b/tests/qtest/xlnx-versal-trng-test.c new file mode 100644 index 00..6aff00c7fc --- /dev/null +++ b/tests/qtest/xlnx-versal-trng-test.c @@ -0,0 +1,490 @@ +/* + * QTests for the Xilinx Versal True Random Number Generator device + * + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * + * SPDX-License-Identifier: MIT + */ + +#include "qemu/osdep.h" +#include "libqtest-single.h" + +/* Base Address */ +#define TRNG_BASEADDR (0xf123) + +/* TRNG_INT_CTRL */ +#define R_TRNG_INT_CTRL (0x) +#define TRNG_INT_CTRL_CERTF_RST_MASK (1 << 5) +#define TRNG_INT_CTRL_DTF_RST_MASK(1 << 4) +#define TRNG_INT_CTRL_DONE_RST_MASK (1 << 3) +#define TRNG_INT_CTRL_CERTF_EN_MASK (1 << 2) +#define TRNG_INT_CTRL_DTF_EN_MASK (1 << 1) +#define TRNG_INT_CTRL_DONE_EN_MASK(1) + +/* TRNG_STATUS */ +#define R_TRNG_STATUS (0x0004) +#define TRNG_STATUS_QCNT_SHIFT (9) +#define TRNG_STATUS_QCNT_MASK(7 << TRNG_STATUS_QCNT_SHIFT) +#define TRNG_STATUS_CERTF_MASK (1 << 3) +#define TRNG_STATUS_DTF_MASK (1 << 1) +#define TRNG_STATUS_DONE_MASK(1) + +/* TRNG_CTRL */ +#define R_TRNG_CTRL(0x0008) +#define TRNG_CTRL_PERSODISABLE_MASK (1 << 10) +#define TRNG_CTRL_SINGLEGENMODE_MASK (1 << 9) +#define TRNG_CTRL_PRNGMODE_MASK (1 << 7) +#define TRNG_CTRL_TSTMODE_MASK(1 << 6) +#define TRNG_CTRL_PRNGSTART_MASK (1 << 5) +#define TRNG_CTRL_PRNGXS_MASK (1 << 3) +#define TRNG_CTRL_TRSSEN_MASK (1 << 2) +#define TRNG_CTRL_QERTUEN_MASK(1 << 1) +#define TRNG_CTRL_PRNGSRST_MASK (1) + +/* TRNG_EXT_SEED_0 ... _11 */ +#define R_TRNG_EXT_SEED_0 (0x0040) +#define R_TRNG_EXT_SEED_11 (R_TRNG_EXT_SEED_0 + 4 * 11) + +/* TRNG_PER_STRNG_0 ... 11 */ +#define R_TRNG_PER_STRNG_0 (0x0080) +#define R_TRNG_PER_STRNG_11(R_TRNG_PER_STRNG_0 + 4 * 11) + +/* TRNG_CORE_OUTPUT */ +#define R_TRNG_CORE_OUTPUT (0x00c0) + +/* TRNG_RESET */ +#define R_TRNG_RESET (0x00d0) +#define TRNG_RESET_VAL_MASK (1) + +/* TRNG_OSC_EN */ +#define R_TRNG_OSC_EN (0x00d4) +#define TRNG_OSC_EN_VAL_MASK (1) + +/* TRNG_TRNG_ISR, _IMR, _IER, _IDR */ +#define R_TRNG_ISR (0x00e0) +#define R_TRNG_IMR (0x00e4) +#define R_TRNG_IER (0x00e8) +#define R_TRNG_IDR (0x00ec) +#define TRNG_IRQ_SLVERR_MASK (1 << 1) +#define TRNG_IRQ_CORE_INT_MASK (1) + +#define FAILED(FMT, ...) g_error("%s(): " FMT, __func__, ## __VA_ARGS__) + +static const uint32_t prng_seed[12] = { +0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, +0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98, +}; + +static const uint32_t pers_str[12] = { +0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98, +0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, +}; + +static void trng_test_start(void) +{ +qtest_start("-machine xlnx-versal-virt"); +} + +static void trng_test_stop(void) +{ +qtest_end(); +} + +static void trng_test_set_uint_prop(const char *name, uint64_t value) +{ +const char *path = "/machine/xlnx-versal/trng"; +QDict *response; + +response = qmp("{ 'execute': 'qom-set'," +" 'arguments': {" + " 'path': %s," + " 'property': %s," + " 'value': %llu" +
[PATCH 0/3] AMD/Xilinx Versal TRNG support
This series adds support for the True Random Number Generator (TRNG) in the AMD/Xilinx Versal family of devices. The series starts by introducing a non-cryptographic grade model of the TRNG controller in the Versal family of devices, followed by instantiating the model in Xilinx Versal machine. The series ends with a q-test for sanity check of the TRNG model in the Xilinx Versal machine. Best regards, Tong Ho References: [1] https://docs.xilinx.com/r/en-US/am011-versal-acap-trm/True-Random-Number-Generator Tong Ho (3): hw/misc: Introduce AMD/Xilix Versal TRNG device hw/arm: xlnx-versal-virt: Add AMD/Xilinx TRNG device tests/qtest: Introduce tests for AMD/Xilinx Versal TRNG device hw/arm/Kconfig | 1 + hw/arm/xlnx-versal-virt.c | 20 + hw/arm/xlnx-versal.c| 16 + hw/misc/Kconfig | 3 + hw/misc/meson.build | 3 + hw/misc/xlnx-versal-trng.c | 725 include/hw/arm/xlnx-versal.h| 5 + include/hw/misc/xlnx-versal-trng.h | 58 +++ tests/qtest/meson.build | 2 +- tests/qtest/xlnx-versal-trng-test.c | 490 +++ 10 files changed, 1322 insertions(+), 1 deletion(-) create mode 100644 hw/misc/xlnx-versal-trng.c create mode 100644 include/hw/misc/xlnx-versal-trng.h create mode 100644 tests/qtest/xlnx-versal-trng-test.c -- 2.25.1
[PATCH 2/3] hw/arm: xlnx-versal-virt: Add AMD/Xilinx TRNG device
Connect the support for Versal True Random Number Generator (TRNG) device. Warning: unlike the TRNG component in a real device from the Versal device familiy, the connected TRNG model is not of cryptographic grade and is not intended for use cases when cryptograpically strong TRNG is needed. Signed-off-by: Tong Ho --- hw/arm/Kconfig | 1 + hw/arm/xlnx-versal-virt.c| 20 hw/arm/xlnx-versal.c | 16 include/hw/arm/xlnx-versal.h | 5 + 4 files changed, 42 insertions(+) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 7e68348440..0a3ff6748d 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -482,6 +482,7 @@ config XLNX_VERSAL select XLNX_BBRAM select XLNX_EFUSE_VERSAL select XLNX_USB_SUBSYS +select XLNX_VERSAL_TRNG config NPCM7XX bool diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 1ee2b8697f..c0704f416e 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -391,6 +391,25 @@ static void fdt_add_rtc_node(VersalVirt *s) g_free(name); } +static void fdt_add_trng_node(VersalVirt *s) +{ +const char compat[] = TYPE_XLNX_VERSAL_TRNG; +const char interrupt_names[] = "trng"; +g_autofree char *name = g_strdup_printf("/trng@%x", MM_PMC_TRNG); + +qemu_fdt_add_subnode(s->fdt, name); + +qemu_fdt_setprop_cells(s->fdt, name, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, VERSAL_TRNG_IRQ, + GIC_FDT_IRQ_FLAGS_LEVEL_HI); +qemu_fdt_setprop(s->fdt, name, "interrupt-names", + interrupt_names, sizeof(interrupt_names)); +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, MM_PMC_TRNG, + 2, MM_PMC_TRNG_SIZE); +qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +} + static void fdt_add_bbram_node(VersalVirt *s) { const char compat[] = TYPE_XLNX_BBRAM; @@ -690,6 +709,7 @@ static void versal_virt_init(MachineState *machine) fdt_add_usb_xhci_nodes(s); fdt_add_sd_nodes(s); fdt_add_rtc_node(s); +fdt_add_trng_node(s); fdt_add_bbram_node(s); fdt_add_efuse_ctrl_node(s); fdt_add_efuse_cache_node(s); diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 60bf5fe657..4fd1924cf6 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -372,6 +372,21 @@ static void versal_create_rtc(Versal *s, qemu_irq *pic) qdev_get_gpio_in(DEVICE(>pmc.apb_irq_orgate), 0)); } +static void versal_create_trng(Versal *s, qemu_irq *pic) +{ +SysBusDevice *sbd; +MemoryRegion *mr; + +object_initialize_child(OBJECT(s), "trng", >pmc.trng, +TYPE_XLNX_VERSAL_TRNG); +sbd = SYS_BUS_DEVICE(>pmc.trng); +sysbus_realize(sbd, _fatal); + +mr = sysbus_mmio_get_region(sbd, 0); +memory_region_add_subregion(>mr_ps, MM_PMC_TRNG, mr); +sysbus_connect_irq(sbd, 0, pic[VERSAL_TRNG_IRQ]); +} + static void versal_create_xrams(Versal *s, qemu_irq *pic) { int nr_xrams = ARRAY_SIZE(s->lpd.xram.ctrl); @@ -757,6 +772,7 @@ static void versal_realize(DeviceState *dev, Error **errp) versal_create_sds(s, pic); versal_create_pmc_apb_irq_orgate(s, pic); versal_create_rtc(s, pic); +versal_create_trng(s, pic); versal_create_xrams(s, pic); versal_create_bbram(s, pic); versal_create_efuse(s, pic); diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 39ee31185c..159ee26aad 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -31,6 +31,7 @@ #include "hw/dma/xlnx_csu_dma.h" #include "hw/misc/xlnx-versal-crl.h" #include "hw/misc/xlnx-versal-pmc-iou-slcr.h" +#include "hw/misc/xlnx-versal-trng.h" #include "hw/net/xlnx-versal-canfd.h" #define TYPE_XLNX_VERSAL "xlnx-versal" @@ -113,6 +114,7 @@ struct Versal { } iou; XlnxZynqMPRTC rtc; +XlnxVersalTRng trng; XlnxBBRam bbram; XlnxEFuse efuse; XlnxVersalEFuseCtrl efuse_ctrl; @@ -151,6 +153,7 @@ struct Versal { #define VERSAL_OSPI_IRQ124 #define VERSAL_SD0_IRQ_0 126 #define VERSAL_EFUSE_IRQ 139 +#define VERSAL_TRNG_IRQ141 #define VERSAL_RTC_ALARM_IRQ 142 #define VERSAL_RTC_SECONDS_IRQ 143 @@ -244,4 +247,6 @@ struct Versal { #define MM_PMC_CRP_SIZE 0x1 #define MM_PMC_RTC 0xf12a #define MM_PMC_RTC_SIZE 0x1 +#define MM_PMC_TRNG 0xf123 +#define MM_PMC_TRNG_SIZE0x1 #endif -- 2.25.1
[PATCH] hw/nvram: Avoid unnecessary Xilinx eFuse backstore write
Add a check in the bit-set operation to write the backstore only if the affected bit is 0 before. With this in place, there will be no need for callers to do the checking in order to avoid unnecessary writes. Signed-off-by: Tong Ho --- hw/nvram/xlnx-efuse.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/hw/nvram/xlnx-efuse.c b/hw/nvram/xlnx-efuse.c index fdfffaab99..655c40b8d1 100644 --- a/hw/nvram/xlnx-efuse.c +++ b/hw/nvram/xlnx-efuse.c @@ -143,6 +143,8 @@ static bool efuse_ro_bits_find(XlnxEFuse *s, uint32_t k) bool xlnx_efuse_set_bit(XlnxEFuse *s, unsigned int bit) { +uint32_t set, *row; + if (efuse_ro_bits_find(s, bit)) { g_autofree char *path = object_get_canonical_path(OBJECT(s)); @@ -152,8 +154,13 @@ bool xlnx_efuse_set_bit(XlnxEFuse *s, unsigned int bit) return false; } -s->fuse32[bit / 32] |= 1 << (bit % 32); -efuse_bdrv_sync(s, bit); +/* Avoid back-end write unless there is a real update */ +row = >fuse32[bit / 32]; +set = 1 << (bit % 32); +if (!(set & *row)) { +*row |= set; +efuse_bdrv_sync(s, bit); +} return true; } -- 2.25.1
[PATCH 1/1] xlnx-bbram: hw/nvram: Fix uninitialized Error *
This adds required initialization of Error * variable. Signed-off-by: Tong Ho --- hw/nvram/xlnx-bbram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c index b70828e5bf..6ed32adad9 100644 --- a/hw/nvram/xlnx-bbram.c +++ b/hw/nvram/xlnx-bbram.c @@ -89,7 +89,7 @@ static bool bbram_pgm_enabled(XlnxBBRam *s) static void bbram_bdrv_error(XlnxBBRam *s, int rc, gchar *detail) { -Error *errp; +Error *errp = NULL; error_setg_errno(, -rc, "%s: BBRAM backstore %s failed.", blk_name(s->blk), detail); -- 2.25.1
[PATCH 0/1] xlnx-bbram: hw/nvram: Fix Coverity CID 1487233
This patch addresses Coverity CID 1487233 by adding the required initialiation of a local variable of type Error *. Tong Ho (1): xlnx-bbram: hw/nvram: Fix uninitialized Error * hw/nvram/xlnx-bbram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -- 2.25.1
[PATCH 0/3] hw/nvram: Fix Memory Leaks in Xilinx eFUSE
This series fixes memory leaks in Xilinx eFUSE devices for the Versal and ZynqMP product families. The leaks result from failing to free memory allocated by object_get_canonical_path(). Tong Ho (3): hw/nvram: Fix Memory Leak in Xilinx eFuse QOM hw/nvram: Fix Memory Leak in Xilinx Versal eFuse device hw/nvram: Fix Memory Leak in Xilinx ZynqMP eFuse device hw/nvram/xlnx-efuse.c | 9 ++--- hw/nvram/xlnx-versal-efuse-ctrl.c | 20 +++- hw/nvram/xlnx-zynqmp-efuse.c | 18 -- 3 files changed, 33 insertions(+), 14 deletions(-) -- 2.25.1
[PATCH 1/3] hw/nvram: Fix Memory Leak in Xilinx eFuse QOM
Signed-off-by: Tong Ho --- hw/nvram/xlnx-efuse.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/nvram/xlnx-efuse.c b/hw/nvram/xlnx-efuse.c index ee1caab54c..a0fd77b586 100644 --- a/hw/nvram/xlnx-efuse.c +++ b/hw/nvram/xlnx-efuse.c @@ -144,10 +144,11 @@ static bool efuse_ro_bits_find(XlnxEFuse *s, uint32_t k) bool xlnx_efuse_set_bit(XlnxEFuse *s, unsigned int bit) { if (efuse_ro_bits_find(s, bit)) { +g_autofree char *path = object_get_canonical_path(OBJECT(s)); + qemu_log_mask(LOG_GUEST_ERROR, "%s: WARN: " "Ignored setting of readonly efuse bit<%u,%u>!\n", - object_get_canonical_path(OBJECT(s)), - (bit / 32), (bit % 32)); + path, (bit / 32), (bit % 32)); return false; } @@ -202,9 +203,11 @@ static void efuse_realize(DeviceState *dev, Error **errp) efuse_ro_bits_sort(s); if ((s->efuse_size % 32) != 0) { +g_autofree char *path = object_get_canonical_path(OBJECT(s)); + error_setg(errp, "%s.efuse-size: %u: property value not multiple of 32.", - object_get_canonical_path(OBJECT(dev)), s->efuse_size); + path, s->efuse_size); return; } -- 2.25.1
[PATCH 3/3] hw/nvram: Fix Memory Leak in Xilinx ZynqMP eFuse device
Signed-off-by: Tong Ho --- hw/nvram/xlnx-zynqmp-efuse.c | 18 -- 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c index 1f87dbf988..228ba0bbfa 100644 --- a/hw/nvram/xlnx-zynqmp-efuse.c +++ b/hw/nvram/xlnx-zynqmp-efuse.c @@ -434,11 +434,12 @@ static void zynqmp_efuse_pgm_addr_postw(RegisterInfo *reg, uint64_t val64) if (!errmsg) { ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, PGM_ERROR, 0); } else { +g_autofree char *path = object_get_canonical_path(OBJECT(s)); + ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, PGM_ERROR, 1); qemu_log_mask(LOG_GUEST_ERROR, "%s - eFuse write error: %s; addr=0x%x\n", - object_get_canonical_path(OBJECT(s)), - errmsg, (unsigned)val64); + path, errmsg, (unsigned)val64); } ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, PGM_DONE, 1); @@ -448,6 +449,7 @@ static void zynqmp_efuse_pgm_addr_postw(RegisterInfo *reg, uint64_t val64) static void zynqmp_efuse_rd_addr_postw(RegisterInfo *reg, uint64_t val64) { XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(reg->opaque); +g_autofree char *path = NULL; /* * Grant reads only to allowed bits; reference sources: @@ -538,10 +540,10 @@ static void zynqmp_efuse_rd_addr_postw(RegisterInfo *reg, uint64_t val64) return; denied: +path = object_get_canonical_path(OBJECT(s)); qemu_log_mask(LOG_GUEST_ERROR, "%s: Denied efuse read from array %u, row %u\n", - object_get_canonical_path(OBJECT(s)), - efuse_ary, efuse_row); + path, efuse_ary, efuse_row); s->regs[R_EFUSE_RD_DATA] = 0; @@ -731,9 +733,11 @@ static void zynqmp_efuse_reg_write(void *opaque, hwaddr addr, s = XLNX_ZYNQMP_EFUSE(dev); if (addr != A_WR_LOCK && s->regs[R_WR_LOCK]) { +g_autofree char *path = object_get_canonical_path(OBJECT(s)); + qemu_log_mask(LOG_GUEST_ERROR, "%s[reg_0x%02lx]: Attempt to write locked register.\n", - object_get_canonical_path(OBJECT(s)), (long)addr); + path, (long)addr); } else { register_write_memory(opaque, addr, data, size); } @@ -784,8 +788,10 @@ static void zynqmp_efuse_realize(DeviceState *dev, Error **errp) XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(dev); if (!s->efuse) { +g_autofree char *path = object_get_canonical_path(OBJECT(s)); + error_setg(errp, "%s.efuse: link property not connected to XLNX-EFUSE", - object_get_canonical_path(OBJECT(dev))); + path); return; } -- 2.25.1
[PATCH 2/3] hw/nvram: Fix Memory Leak in Xilinx Versal eFuse device
Signed-off-by: Tong Ho --- hw/nvram/xlnx-versal-efuse-ctrl.c | 20 +++- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c b/hw/nvram/xlnx-versal-efuse-ctrl.c index d362376703..b35ba65ab5 100644 --- a/hw/nvram/xlnx-versal-efuse-ctrl.c +++ b/hw/nvram/xlnx-versal-efuse-ctrl.c @@ -439,9 +439,11 @@ static void efuse_pgm_addr_postw(RegisterInfo *reg, uint64_t val64) * up to guest to do so (or by reset). */ if (efuse_pgm_locked(s, bit)) { +g_autofree char *path = object_get_canonical_path(OBJECT(s)); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Denied setting of efuse<%u, %u, %u>\n", - object_get_canonical_path(OBJECT(s)), + path, FIELD_EX32(bit, EFUSE_PGM_ADDR, PAGE), FIELD_EX32(bit, EFUSE_PGM_ADDR, ROW), FIELD_EX32(bit, EFUSE_PGM_ADDR, COLUMN)); @@ -478,9 +480,11 @@ static void efuse_rd_addr_postw(RegisterInfo *reg, uint64_t val64) s->regs[R_EFUSE_RD_DATA] = xlnx_versal_efuse_read_row(s->efuse, bit, ); if (denied) { +g_autofree char *path = object_get_canonical_path(OBJECT(s)); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Denied reading of efuse<%u, %u>\n", - object_get_canonical_path(OBJECT(s)), + path, FIELD_EX32(bit, EFUSE_RD_ADDR, PAGE), FIELD_EX32(bit, EFUSE_RD_ADDR, ROW)); @@ -625,9 +629,11 @@ static void efuse_ctrl_reg_write(void *opaque, hwaddr addr, s = XLNX_VERSAL_EFUSE_CTRL(dev); if (addr != A_WR_LOCK && s->regs[R_WR_LOCK]) { +g_autofree char *path = object_get_canonical_path(OBJECT(s)); + qemu_log_mask(LOG_GUEST_ERROR, "%s[reg_0x%02lx]: Attempt to write locked register.\n", - object_get_canonical_path(OBJECT(s)), (long)addr); + path, (long)addr); } else { register_write_memory(opaque, addr, data, size); } @@ -681,16 +687,20 @@ static void efuse_ctrl_realize(DeviceState *dev, Error **errp) const uint32_t lks_sz = sizeof(XlnxEFuseLkSpec) / 2; if (!s->efuse) { +g_autofree char *path = object_get_canonical_path(OBJECT(s)); + error_setg(errp, "%s.efuse: link property not connected to XLNX-EFUSE", - object_get_canonical_path(OBJECT(dev))); + path); return; } /* Sort property-defined pgm-locks for bsearch lookup */ if ((s->extra_pg0_lock_n16 % lks_sz) != 0) { +g_autofree char *path = object_get_canonical_path(OBJECT(s)); + error_setg(errp, "%s.pg0-lock: array property item-count not multiple of %u", - object_get_canonical_path(OBJECT(dev)), lks_sz); + path, lks_sz); return; } -- 2.25.1
RE: [PATCH v3 0/9] hw/nvram: hw/arm: Introduce Xilinx eFUSE and BBRAM
Hi Peter, I will follow up with patches to fix the memory leaks. Where can I get a copy of the Coverity reports that have the 10 issues you indicated? Thanks, Tong -Original Message- From: Peter Maydell Sent: Saturday, October 2, 2021 3:28 AM To: Tong Ho Cc: qemu-arm ; QEMU Developers ; Alistair Francis ; Edgar E. Iglesias Subject: Re: [PATCH v3 0/9] hw/nvram: hw/arm: Introduce Xilinx eFUSE and BBRAM On Fri, 17 Sept 2021 at 06:24, Tong Ho wrote: > > This series implements the Xilinx eFUSE and BBRAM devices for the > Versal and ZynqMP product families. > > Furthermore, both new devices are connected to the xlnx-versal-virt > board and the xlnx-zcu102 board. > > See changes in docs/system/arm/xlnx-versal-virt.rst for detail. Hi -- now this has landed upstream, Coverity points out a lot of memory leaks on error or logging paths, where the code does things like: *** CID 1464071: Resource leaks (RESOURCE_LEAK) /qemu/hw/nvram/xlnx-versal-efuse-ctrl.c: 628 in efuse_ctrl_reg_write() 622 dev = reg_array->mem.owner; 623 assert(dev); 624 625 s = XLNX_VERSAL_EFUSE_CTRL(dev); 626 627 if (addr != A_WR_LOCK && s->regs[R_WR_LOCK]) { >>> CID 1464071: Resource leaks (RESOURCE_LEAK) >>> Failing to save or free storage allocated by >>> "object_get_canonical_path((Object *)s)" leaks it. 628 qemu_log_mask(LOG_GUEST_ERROR, 629 "%s[reg_0x%02lx]: Attempt to write locked register.\n", 630 object_get_canonical_path(OBJECT(s)), (long)addr); 631 } else { 632 register_write_memory(opaque, addr, data, size); 633 } You need to free the memory here. A good pattern is how it's done in xlnx-zynqmp-can.c with g_autofree: if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) { g_autofree char *path = object_get_canonical_path(OBJECT(s)); qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while" " data while controller is in reset mode.\n", path); return false; } Could somebody send some followup patches that fix all of these, please? (There are 10 coverity issues, covering probably all of the places where object_get_canonical_path() is used in this series.) thanks -- PMM
[PATCH v3 3/9] hw/nvram: Introduce Xilinx ZynqMP eFuse device
This implements the Xilinx ZynqMP eFuse, an one-time field-programmable non-volatile storage device. There is only one such device in the Xilinx ZynqMP product family. Co-authored-by: Edgar E. Iglesias Co-authored-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Signed-off-by: Sai Pavan Boddu Signed-off-by: Tong Ho --- hw/nvram/Kconfig | 4 + hw/nvram/meson.build | 2 + hw/nvram/xlnx-zynqmp-efuse.c | 855 +++ include/hw/nvram/xlnx-zynqmp-efuse.h | 44 ++ 4 files changed, 905 insertions(+) create mode 100644 hw/nvram/xlnx-zynqmp-efuse.c create mode 100644 include/hw/nvram/xlnx-zynqmp-efuse.h diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig index 6c2bb5afe3..3059c5dae0 100644 --- a/hw/nvram/Kconfig +++ b/hw/nvram/Kconfig @@ -26,3 +26,7 @@ config XLNX_EFUSE config XLNX_EFUSE_VERSAL bool select XLNX_EFUSE + +config XLNX_EFUSE_ZYNQMP +bool +select XLNX_EFUSE diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index 62352ad8ec..6dc54d9873 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -14,5 +14,7 @@ softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files( 'xlnx-versal-efuse-cache.c', 'xlnx-versal-efuse-ctrl.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_ZYNQMP', if_true: files( + 'xlnx-zynqmp-efuse.c')) specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c')) diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c new file mode 100644 index 00..1f87dbf988 --- /dev/null +++ b/hw/nvram/xlnx-zynqmp-efuse.c @@ -0,0 +1,855 @@ +/* + * QEMU model of the ZynqMP eFuse + * + * Copyright (c) 2015 Xilinx Inc. + * + * Written by Edgar E. Iglesias + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/nvram/xlnx-zynqmp-efuse.h" + +#include "qemu/log.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" + +#ifndef ZYNQMP_EFUSE_ERR_DEBUG +#define ZYNQMP_EFUSE_ERR_DEBUG 0 +#endif + +REG32(WR_LOCK, 0x0) +FIELD(WR_LOCK, LOCK, 0, 16) +REG32(CFG, 0x4) +FIELD(CFG, SLVERR_ENABLE, 5, 1) +FIELD(CFG, MARGIN_RD, 2, 2) +FIELD(CFG, PGM_EN, 1, 1) +FIELD(CFG, EFUSE_CLK_SEL, 0, 1) +REG32(STATUS, 0x8) +FIELD(STATUS, AES_CRC_PASS, 7, 1) +FIELD(STATUS, AES_CRC_DONE, 6, 1) +FIELD(STATUS, CACHE_DONE, 5, 1) +FIELD(STATUS, CACHE_LOAD, 4, 1) +FIELD(STATUS, EFUSE_3_TBIT, 2, 1) +FIELD(STATUS, EFUSE_2_TBIT, 1, 1) +FIELD(STATUS, EFUSE_0_TBIT, 0, 1) +REG32(EFUSE_PGM_ADDR, 0xc) +FIELD(EFUSE_PGM_ADDR, EFUSE, 11, 2) +FIELD(EFUSE_PGM_ADDR, ROW, 5, 6) +FIELD(EFUSE_PGM_ADDR, COLUMN, 0, 5) +REG32(EFUSE_RD_ADDR, 0x10) +FIELD(EFUSE_RD_ADDR, EFUSE, 11, 2) +FIELD(EFUSE_RD_ADDR, ROW, 5, 6) +REG32(EFUSE_RD_DATA, 0x14) +REG32(TPGM, 0x18) +FIELD(TPGM, VALUE, 0, 16) +REG32(TRD, 0x1c) +FIELD(TRD, VALUE, 0, 8) +REG32(TSU_H_PS, 0x20) +FIELD(TSU_H_PS, VALUE, 0, 8) +REG32(TSU_H_PS_CS, 0x24) +FIELD(TSU_H_PS_CS, VALUE, 0, 8) +REG32(TSU_H_CS, 0x2c) +FIELD(TSU_H_CS, VALUE, 0, 4) +REG32(EFUSE_ISR, 0x30) +FIELD(EFUSE_ISR, APB_SLVERR, 31, 1) +FIELD(EFUSE_ISR, CACHE_ERROR, 4, 1) +FIELD(EFUSE_ISR, RD_ERROR, 3, 1) +FIELD(EFUSE_ISR, RD_DONE, 2, 1) +FIELD(EFUSE_ISR, PGM_ERROR, 1, 1) +FIELD(EFUSE_ISR, PGM_DONE, 0, 1) +REG32(EFUSE_IMR, 0x34) +FIELD(EFUSE_IMR, APB_SLVERR, 31, 1) +FIELD(EFUSE_IMR, CACHE_ERROR, 4, 1) +FIELD(EFUSE_IMR, RD_ERROR, 3, 1) +FIELD(EFUSE_IMR, RD_DONE, 2, 1) +FIELD(EFUSE_IMR, PGM_ERROR, 1, 1) +FIELD(EFUSE_IMR, PGM_DONE, 0, 1) +REG32(EFUSE_IER, 0x3
[PATCH v3 1/9] hw/nvram: Introduce Xilinx eFuse QOM
This introduces the QOM for Xilinx eFuse, an one-time field-programmable storage bit array. The actual mmio interface to the array varies by device families and will be provided in different change-sets. Co-authored-by: Edgar E. Iglesias Co-authored-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Signed-off-by: Sai Pavan Boddu Signed-off-by: Tong Ho --- hw/nvram/Kconfig | 7 + hw/nvram/meson.build | 2 + hw/nvram/xlnx-efuse-crc.c | 119 +++ hw/nvram/xlnx-efuse.c | 280 ++ include/hw/nvram/xlnx-efuse.h | 132 5 files changed, 540 insertions(+) create mode 100644 hw/nvram/xlnx-efuse-crc.c create mode 100644 hw/nvram/xlnx-efuse.c create mode 100644 include/hw/nvram/xlnx-efuse.h diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig index e872fcb194..252251f366 100644 --- a/hw/nvram/Kconfig +++ b/hw/nvram/Kconfig @@ -15,3 +15,10 @@ config NMC93XX_EEPROM config CHRP_NVRAM bool + +config XLNX_EFUSE_CRC +bool + +config XLNX_EFUSE +bool +select XLNX_EFUSE_CRC diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index fd2951a860..623c94efff 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -9,5 +9,7 @@ softmmu_ss.add(when: 'CONFIG_AT24C', if_true: files('eeprom_at24c.c')) softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c')) softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c')) softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_CRC', if_true: files('xlnx-efuse-crc.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c')) specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c')) diff --git a/hw/nvram/xlnx-efuse-crc.c b/hw/nvram/xlnx-efuse-crc.c new file mode 100644 index 00..5a5cc13f39 --- /dev/null +++ b/hw/nvram/xlnx-efuse-crc.c @@ -0,0 +1,119 @@ +/* + * Xilinx eFuse/bbram CRC calculator + * + * Copyright (c) 2021 Xilinx Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "hw/nvram/xlnx-efuse.h" + +static uint32_t xlnx_efuse_u37_crc(uint32_t prev_crc, uint32_t data, + uint32_t addr) +{ +/* A table for 7-bit slicing */ +static const uint32_t crc_tab[128] = { +0x, 0xe13b70f7, 0xc79a971f, 0x26a1e7e8, +0x8ad958cf, 0x6be22838, 0x4d43cfd0, 0xac78bf27, +0x105ec76f, 0xf165b798, 0xd7c45070, 0x36ff2087, +0x9a879fa0, 0x7bbcef57, 0x5d1d08bf, 0xbc267848, +0x20bd8ede, 0xc186fe29, 0xe72719c1, 0x061c6936, +0xaa64d611, 0x4b5fa6e6, 0x6dfe410e, 0x8cc531f9, +0x30e349b1, 0xd1d83946, 0xf779deae, 0x1642ae59, +0xba3a117e, 0x5b016189, 0x7da08661, 0x9c9bf696, +0x417b1dbc, 0xa0406d4b, 0x86e18aa3, 0x67dafa54, +0xcba24573, 0x2a993584, 0x0c38d26c, 0xed03a29b, +0x5125dad3, 0xb01eaa24, 0x96bf4dcc, 0x77843d3b, +0xdbfc821c, 0x3ac7f2eb, 0x1c661503, 0xfd5d65f4, +0x61c69362, 0x80fde395, 0xa65c047d, 0x4767748a, +0xeb1fcbad, 0x0a24bb5a, 0x2c855cb2, 0xcdbe2c45, +0x7198540d, 0x90a324fa, 0xb602c312, 0x5739b3e5, +0xfb410cc2, 0x1a7a7c35, 0x3cdb9bdd, 0xdde0eb2a, +0x82f63b78, 0x63cd4b8f, 0x456cac67, 0xa457dc90, +0x082f63b7, 0xe9141340, 0xcfb5f4a8, 0x2e8e845f, +0x92a8fc17, 0x73938ce0, 0x55326b08, 0xb4091bff, +0x1871a4d8, 0xf94ad42f, 0xdfeb33c7, 0x3ed04330, +0xa24bb5a6, 0x4370c551, 0x65d122b9, 0x84ea524e, +0x2892ed69, 0xc9a99d9e, 0xef087a76, 0x0e330a81, +0xb21572c9, 0x532e023e, 0x758fe5d6, 0x94b49521, +0x38cc2a06, 0xd9f75af1, 0xff56bd19, 0x1e6dcdee, +0xc38d26c4, 0x22b65633, 0x0417b1db, 0xe52cc12c, +0x49547e0b, 0xa86f0efc, 0x8ecee914, 0x6ff599e3, +0xd3d3e1ab, 0x32e8915c, 0x144976b4, 0xf5720643, +
[PATCH v3 6/9] hw/arm: xlnx-versal-virt: Add Xilinx eFUSE device
Connect the support for Versal eFUSE one-time field-programmable bit array. The command argument: -drive if=pflash,index=1,... Can be used to optionally connect the bit array to a backend storage, such that field-programmed values in one invocation can be made available to next invocation. The backend storage must be a seekable binary file, and its size must be 3072 bytes or larger. A file with all binary 0's is a 'blank'. Signed-off-by: Tong Ho --- hw/arm/Kconfig | 1 + hw/arm/xlnx-versal-virt.c| 52 hw/arm/xlnx-versal.c | 39 +++ include/hw/arm/xlnx-versal.h | 10 +++ 4 files changed, 102 insertions(+) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index f92fb9e568..9edc05782d 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -382,6 +382,7 @@ config XLNX_VERSAL select XLNX_ZYNQMP select OR_IRQ select XLNX_BBRAM +select XLNX_EFUSE_VERSAL config NPCM7XX bool diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index e1c5ead475..d2f55e29b6 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -376,6 +376,41 @@ static void fdt_add_bbram_node(VersalVirt *s) g_free(name); } +static void fdt_add_efuse_ctrl_node(VersalVirt *s) +{ +const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CTRL; +const char interrupt_names[] = "pmc_efuse"; +char *name = g_strdup_printf("/pmc_efuse@%x", MM_PMC_EFUSE_CTRL); + +qemu_fdt_add_subnode(s->fdt, name); + +qemu_fdt_setprop_cells(s->fdt, name, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, VERSAL_EFUSE_IRQ, + GIC_FDT_IRQ_FLAGS_LEVEL_HI); +qemu_fdt_setprop(s->fdt, name, "interrupt-names", + interrupt_names, sizeof(interrupt_names)); +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, MM_PMC_EFUSE_CTRL, + 2, MM_PMC_EFUSE_CTRL_SIZE); +qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +g_free(name); +} + +static void fdt_add_efuse_cache_node(VersalVirt *s) +{ +const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CACHE; +char *name = g_strdup_printf("/xlnx_pmc_efuse_cache@%x", + MM_PMC_EFUSE_CACHE); + +qemu_fdt_add_subnode(s->fdt, name); + +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, MM_PMC_EFUSE_CACHE, + 2, MM_PMC_EFUSE_CACHE_SIZE); +qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +g_free(name); +} + static void fdt_nop_memory_nodes(void *fdt, Error **errp) { Error *err = NULL; @@ -542,6 +577,18 @@ static void bbram_attach_drive(XlnxBBRam *dev) } } +static void efuse_attach_drive(XlnxEFuse *dev) +{ +DriveInfo *dinfo; +BlockBackend *blk; + +dinfo = drive_get_by_index(IF_PFLASH, 1); +blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; +if (blk) { +qdev_prop_set_drive(DEVICE(dev), "drive", blk); +} +} + static void sd_plugin_card(SDHCIState *sd, DriveInfo *di) { BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL; @@ -603,6 +650,8 @@ static void versal_virt_init(MachineState *machine) fdt_add_sd_nodes(s); fdt_add_rtc_node(s); fdt_add_bbram_node(s); +fdt_add_efuse_ctrl_node(s); +fdt_add_efuse_cache_node(s); fdt_add_cpu_nodes(s, psci_conduit); fdt_add_clk_node(s, "/clk125", 12500, s->phandle.clk_125Mhz); fdt_add_clk_node(s, "/clk25", 2500, s->phandle.clk_25Mhz); @@ -615,6 +664,9 @@ static void versal_virt_init(MachineState *machine) /* Attach bbram backend, if given */ bbram_attach_drive(>soc.pmc.bbram); +/* Attach efuse backend, if given */ +efuse_attach_drive(>soc.pmc.efuse); + /* Plugin SD cards. */ for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) { sd_plugin_card(>soc.pmc.iou.sd[i], drive_get_next(IF_SD)); diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 23451ae012..b2705b6925 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -331,6 +331,44 @@ static void versal_create_bbram(Versal *s, qemu_irq *pic) sysbus_connect_irq(sbd, 0, pic[VERSAL_BBRAM_APB_IRQ_0]); } +static void versal_realize_efuse_part(Versal *s, Object *dev, hwaddr base) +{ +SysBusDevice *part = SYS_BUS_DEVICE(dev); + +object_property_set_link(OBJECT(part), "efuse", + OBJECT(>pmc.efuse), _abort); + +sysbus_realize(part, _abort); +memory_region_add_subregion(>mr_ps, base, +sysbus_mmio_get_region(part, 0)); +} + +static void versal_create_efuse(Versal *s, qemu_irq *pic) +{ +Object *bits = OB
[PATCH v3 7/9] hw/arm: xlnx-zcu102: Add Xilinx BBRAM device
Connect the support for Xilinx ZynqMP Battery-Backed RAM (BBRAM) The command argument: -drive if=pflash,index=2,... Can be used to optionally connect the bbram to a backend storage, such that field-programmed values in one invocation can be made available to next invocation. The backend storage must be a seekable binary file, and its size must be 36 bytes or larger. A file with all binary 0's is a 'blank'. Signed-off-by: Tong Ho --- hw/Kconfig | 1 + hw/arm/xlnx-zcu102.c | 15 +++ hw/arm/xlnx-zynqmp.c | 20 include/hw/arm/xlnx-zynqmp.h | 2 ++ 4 files changed, 38 insertions(+) diff --git a/hw/Kconfig b/hw/Kconfig index 8cb7664d70..b6fb6a4507 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -81,3 +81,4 @@ config XLNX_ZYNQMP select REGISTER select CAN_BUS select PTIMER +select XLNX_BBRAM diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c index 6c6cb02e86..b247c5779b 100644 --- a/hw/arm/xlnx-zcu102.c +++ b/hw/arm/xlnx-zcu102.c @@ -98,6 +98,18 @@ static void zcu102_modify_dtb(const struct arm_boot_info *binfo, void *fdt) } } +static void bbram_attach_drive(XlnxBBRam *dev) +{ +DriveInfo *dinfo; +BlockBackend *blk; + +dinfo = drive_get_by_index(IF_PFLASH, 2); +blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; +if (blk) { +qdev_prop_set_drive(DEVICE(dev), "drive", blk); +} +} + static void xlnx_zcu102_init(MachineState *machine) { XlnxZCU102 *s = ZCU102_MACHINE(machine); @@ -136,6 +148,9 @@ static void xlnx_zcu102_init(MachineState *machine) qdev_realize(DEVICE(>soc), NULL, _fatal); +/* Attach bbram backend, if given */ +bbram_attach_drive(>soc.bbram); + /* Create and plug in the SD cards */ for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) { BusState *bus; diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 4e5a471e30..1e8e2ddcc2 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -66,6 +66,9 @@ #define RTC_ADDR0xffa6 #define RTC_IRQ 26 +#define BBRAM_ADDR 0xffcd +#define BBRAM_IRQ 11 + #define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */ static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = { @@ -226,6 +229,22 @@ static void xlnx_zynqmp_create_rpu(MachineState *ms, XlnxZynqMPState *s, qdev_realize(DEVICE(>rpu_cluster), NULL, _fatal); } +static void xlnx_zynqmp_create_bbram(XlnxZynqMPState *s, qemu_irq *gic) +{ +SysBusDevice *sbd; + +object_initialize_child_with_props(OBJECT(s), "bbram", >bbram, + sizeof(s->bbram), TYPE_XLNX_BBRAM, + _fatal, + "crc-zpads", "1", + NULL); +sbd = SYS_BUS_DEVICE(>bbram); + +sysbus_realize(sbd, _fatal); +sysbus_mmio_map(sbd, 0, BBRAM_ADDR); +sysbus_connect_irq(sbd, 0, gic[BBRAM_IRQ]); +} + static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s) { static const struct UnimpInfo { @@ -626,6 +645,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(>rtc), 0, RTC_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(>rtc), 0, gic_spi[RTC_IRQ]); +xlnx_zynqmp_create_bbram(s, gic_spi); xlnx_zynqmp_create_unimp_mmio(s); for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) { diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index c84fe15996..067e8a5238 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -36,6 +36,7 @@ #include "qom/object.h" #include "net/can_emu.h" #include "hw/dma/xlnx_csu_dma.h" +#include "hw/nvram/xlnx-bbram.h" #define TYPE_XLNX_ZYNQMP "xlnx-zynqmp" OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) @@ -100,6 +101,7 @@ struct XlnxZynqMPState { MemoryRegion *ddr_ram; MemoryRegion ddr_ram_low, ddr_ram_high; +XlnxBBRam bbram; MemoryRegion mr_unimp[XLNX_ZYNQMP_NUM_UNIMP_AREAS]; -- 2.25.1
[PATCH v3 9/9] docs/system/arm: xlnx-versal-virt: BBRAM and eFUSE Usage
Add BBRAM and eFUSE usage to the Xilinx Versal Virt board document. Signed-off-by: Tong Ho --- docs/system/arm/xlnx-versal-virt.rst | 49 1 file changed, 49 insertions(+) diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst index 27f73500d9..92ad10d2da 100644 --- a/docs/system/arm/xlnx-versal-virt.rst +++ b/docs/system/arm/xlnx-versal-virt.rst @@ -32,6 +32,8 @@ Implemented devices: - OCM (256KB of On Chip Memory) - XRAM (4MB of on chip Accelerator RAM) - DDR memory +- BBRAM (36 bytes of Battery-backed RAM) +- eFUSE (3072 bytes of one-time field-programmable bit array) QEMU does not yet model any other devices, including the PL and the AI Engine. @@ -175,3 +177,50 @@ Run the following at the U-Boot prompt: fdt set /chosen/dom0 reg <0x 0x4000 0x0 0x0310> booti 3000 - 2000 +BBRAM File Backend +"""""""""""""""""" +BBRAM can have an optional file backend, which must be a seekable +binary file with a size of 36 bytes or larger. A file with all +binary 0s is a 'blank'. + +To add a file-backend for the BBRAM: + +.. code-block:: bash + + -drive if=pflash,index=0,file=versal-bbram.bin,format=raw + +To use a different index value, N, from default of 0, add: + +.. code-block:: bash + + -global xlnx,bbram-ctrl.drive-index=N + +eFUSE File Backend +"""""""""""""""""" +eFUSE can have an optional file backend, which must be a seekable +binary file with a size of 3072 bytes or larger. A file with all +binary 0s is a 'blank'. + +To add a file-backend for the eFUSE: + +.. code-block:: bash + + -drive if=pflash,index=1,file=versal-efuse.bin,format=raw + +To use a different index value, N, from default of 1, add: + +.. code-block:: bash + + -global xlnx,efuse.drive-index=N + +.. warning:: + In actual physical Versal, BBRAM and eFUSE contain sensitive data. + The QEMU device models do **not** encrypt nor obfuscate any data + when holding them in models' memory or when writing them to their + file backends. + + Thus, a file backend should be used with caution, and 'format=luks' + is highly recommended (albeit with usage complexity). + + Better yet, do not use actual product data when running guest image + on this Xilinx Versal Virt board. -- 2.25.1
[PATCH v3 0/9] hw/nvram: hw/arm: Introduce Xilinx eFUSE and BBRAM
This series implements the Xilinx eFUSE and BBRAM devices for the Versal and ZynqMP product families. Furthermore, both new devices are connected to the xlnx-versal-virt board and the xlnx-zcu102 board. See changes in docs/system/arm/xlnx-versal-virt.rst for detail. --- Changelogs: v2->v3: * Move drive-backend attaching to board models * Use OBJECT_DECLARE_SIMPLE_TYPE instead of OBJECT_CHECK * Use reg_array->mem directly instead of an extra mr-container * Add doc comments for .h file API * Remove "qemu/osdep.h" from .h files * Remove ad-hoc endianess detection * Remove error_abort from device models * Remove empty vmstate and mininum_version_id_old * Remove unused #define macros * Remove unavailable references from comments * Kconfig & meson.build: - Add CONFIG_XLNX_EFUSE_CRC in patch 1 - Select bbram and efuse devices from boards' Kconfig - Remove 'if' from meson.build * Fix spelling and wording in comments and docs v1->v2: * Move doc change from 1st to last of this series * Remove outdated comment of 'autogenerated by xregqemu.py' from all affected files. --- Tong Ho (9): hw/nvram: Introduce Xilinx eFuse QOM hw/nvram: Introduce Xilinx Versal eFuse device hw/nvram: Introduce Xilinx ZynqMP eFuse device hw/nvram: Introduce Xilinx battery-backed ram hw/arm: xlnx-versal-virt: Add Xilinx BBRAM device hw/arm: xlnx-versal-virt: Add Xilinx eFUSE device hw/arm: xlnx-zcu102: Add Xilinx BBRAM device hw/arm: xlnx-zcu102: Add Xilinx eFUSE device docs/system/arm: xlnx-versal-virt: BBRAM and eFUSE Usage docs/system/arm/xlnx-versal-virt.rst | 49 ++ hw/Kconfig | 2 + hw/arm/Kconfig | 2 + hw/arm/xlnx-versal-virt.c| 88 +++ hw/arm/xlnx-versal.c | 57 ++ hw/arm/xlnx-zcu102.c | 30 + hw/arm/xlnx-zynqmp.c | 49 ++ hw/nvram/Kconfig | 19 + hw/nvram/meson.build | 8 + hw/nvram/xlnx-bbram.c| 545 + hw/nvram/xlnx-efuse-crc.c| 119 hw/nvram/xlnx-efuse.c| 280 + hw/nvram/xlnx-versal-efuse-cache.c | 114 hw/nvram/xlnx-versal-efuse-ctrl.c| 783 hw/nvram/xlnx-zynqmp-efuse.c | 855 +++ include/hw/arm/xlnx-versal.h | 15 + include/hw/arm/xlnx-zynqmp.h | 5 + include/hw/nvram/xlnx-bbram.h| 54 ++ include/hw/nvram/xlnx-efuse.h| 132 + include/hw/nvram/xlnx-versal-efuse.h | 68 +++ include/hw/nvram/xlnx-zynqmp-efuse.h | 44 ++ 21 files changed, 3318 insertions(+) create mode 100644 hw/nvram/xlnx-bbram.c create mode 100644 hw/nvram/xlnx-efuse-crc.c create mode 100644 hw/nvram/xlnx-efuse.c create mode 100644 hw/nvram/xlnx-versal-efuse-cache.c create mode 100644 hw/nvram/xlnx-versal-efuse-ctrl.c create mode 100644 hw/nvram/xlnx-zynqmp-efuse.c create mode 100644 include/hw/nvram/xlnx-bbram.h create mode 100644 include/hw/nvram/xlnx-efuse.h create mode 100644 include/hw/nvram/xlnx-versal-efuse.h create mode 100644 include/hw/nvram/xlnx-zynqmp-efuse.h -- 2.25.1
[PATCH v3 8/9] hw/arm: xlnx-zcu102: Add Xilinx eFUSE device
Connect the support for ZynqMP eFUSE one-time field-programmable bit array. The command argument: -drive if=pflash,index=3,... Can be used to optionally connect the bit array to a backend storage, such that field-programmed values in one invocation can be made available to next invocation. The backend storage must be a seekable binary file, and its size must be 768 bytes or larger. A file with all binary 0's is a 'blank'. Signed-off-by: Tong Ho --- hw/Kconfig | 1 + hw/arm/xlnx-zcu102.c | 15 +++ hw/arm/xlnx-zynqmp.c | 29 + include/hw/arm/xlnx-zynqmp.h | 3 +++ 4 files changed, 48 insertions(+) diff --git a/hw/Kconfig b/hw/Kconfig index b6fb6a4507..ad20cce0a9 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -82,3 +82,4 @@ config XLNX_ZYNQMP select CAN_BUS select PTIMER select XLNX_BBRAM +select XLNX_EFUSE_ZYNQMP diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c index b247c5779b..3dc2b5e8ca 100644 --- a/hw/arm/xlnx-zcu102.c +++ b/hw/arm/xlnx-zcu102.c @@ -110,6 +110,18 @@ static void bbram_attach_drive(XlnxBBRam *dev) } } +static void efuse_attach_drive(XlnxEFuse *dev) +{ +DriveInfo *dinfo; +BlockBackend *blk; + +dinfo = drive_get_by_index(IF_PFLASH, 3); +blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; +if (blk) { +qdev_prop_set_drive(DEVICE(dev), "drive", blk); +} +} + static void xlnx_zcu102_init(MachineState *machine) { XlnxZCU102 *s = ZCU102_MACHINE(machine); @@ -151,6 +163,9 @@ static void xlnx_zcu102_init(MachineState *machine) /* Attach bbram backend, if given */ bbram_attach_drive(>soc.bbram); +/* Attach efuse backend, if given */ +efuse_attach_drive(>soc.efuse); + /* Create and plug in the SD cards */ for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) { BusState *bus; diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 1e8e2ddcc2..1c52a575aa 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -69,6 +69,9 @@ #define BBRAM_ADDR 0xffcd #define BBRAM_IRQ 11 +#define EFUSE_ADDR 0xffcc +#define EFUSE_IRQ 87 + #define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */ static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = { @@ -245,6 +248,31 @@ static void xlnx_zynqmp_create_bbram(XlnxZynqMPState *s, qemu_irq *gic) sysbus_connect_irq(sbd, 0, gic[BBRAM_IRQ]); } +static void xlnx_zynqmp_create_efuse(XlnxZynqMPState *s, qemu_irq *gic) +{ +Object *bits = OBJECT(>efuse); +Object *ctrl = OBJECT(>efuse_ctrl); +SysBusDevice *sbd; + +object_initialize_child(OBJECT(s), "efuse-ctrl", >efuse_ctrl, +TYPE_XLNX_ZYNQMP_EFUSE); + +object_initialize_child_with_props(ctrl, "xlnx-efuse@0", bits, + sizeof(s->efuse), + TYPE_XLNX_EFUSE, _abort, + "efuse-nr", "3", + "efuse-size", "2048", + NULL); + +qdev_realize(DEVICE(bits), NULL, _abort); +object_property_set_link(ctrl, "efuse", bits, _abort); + +sbd = SYS_BUS_DEVICE(ctrl); +sysbus_realize(sbd, _abort); +sysbus_mmio_map(sbd, 0, EFUSE_ADDR); +sysbus_connect_irq(sbd, 0, gic[EFUSE_IRQ]); +} + static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s) { static const struct UnimpInfo { @@ -646,6 +674,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(>rtc), 0, gic_spi[RTC_IRQ]); xlnx_zynqmp_create_bbram(s, gic_spi); +xlnx_zynqmp_create_efuse(s, gic_spi); xlnx_zynqmp_create_unimp_mmio(s); for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) { diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index 067e8a5238..062e637fe4 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -37,6 +37,7 @@ #include "net/can_emu.h" #include "hw/dma/xlnx_csu_dma.h" #include "hw/nvram/xlnx-bbram.h" +#include "hw/nvram/xlnx-zynqmp-efuse.h" #define TYPE_XLNX_ZYNQMP "xlnx-zynqmp" OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) @@ -102,6 +103,8 @@ struct XlnxZynqMPState { MemoryRegion *ddr_ram; MemoryRegion ddr_ram_low, ddr_ram_high; XlnxBBRam bbram; +XlnxEFuse efuse; +XlnxZynqMPEFuse efuse_ctrl; MemoryRegion mr_unimp[XLNX_ZYNQMP_NUM_UNIMP_AREAS]; -- 2.25.1
[PATCH v3 4/9] hw/nvram: Introduce Xilinx battery-backed ram
This device is present in Versal and ZynqMP product families to store a 256-bit encryption key. Co-authored-by: Edgar E. Iglesias Co-authored-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Signed-off-by: Sai Pavan Boddu Signed-off-by: Tong Ho --- hw/nvram/Kconfig | 4 + hw/nvram/meson.build | 1 + hw/nvram/xlnx-bbram.c | 545 ++ include/hw/nvram/xlnx-bbram.h | 54 4 files changed, 604 insertions(+) create mode 100644 hw/nvram/xlnx-bbram.c create mode 100644 include/hw/nvram/xlnx-bbram.h diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig index 3059c5dae0..24cfc18f8b 100644 --- a/hw/nvram/Kconfig +++ b/hw/nvram/Kconfig @@ -30,3 +30,7 @@ config XLNX_EFUSE_VERSAL config XLNX_EFUSE_ZYNQMP bool select XLNX_EFUSE + +config XLNX_BBRAM +bool +select XLNX_EFUSE_CRC diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index 6dc54d9873..202a5466e6 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -16,5 +16,6 @@ softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files( 'xlnx-versal-efuse-ctrl.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_ZYNQMP', if_true: files( 'xlnx-zynqmp-efuse.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_BBRAM', if_true: files('xlnx-bbram.c')) specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c')) diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c new file mode 100644 index 00..b70828e5bf --- /dev/null +++ b/hw/nvram/xlnx-bbram.c @@ -0,0 +1,545 @@ +/* + * QEMU model of the Xilinx BBRAM Battery Backed RAM + * + * Copyright (c) 2014-2021 Xilinx Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/nvram/xlnx-bbram.h" + +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "sysemu/blockdev.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" +#include "hw/qdev-properties-system.h" +#include "hw/nvram/xlnx-efuse.h" + +#ifndef XLNX_BBRAM_ERR_DEBUG +#define XLNX_BBRAM_ERR_DEBUG 0 +#endif + +REG32(BBRAM_STATUS, 0x0) +FIELD(BBRAM_STATUS, AES_CRC_PASS, 9, 1) +FIELD(BBRAM_STATUS, AES_CRC_DONE, 8, 1) +FIELD(BBRAM_STATUS, BBRAM_ZEROIZED, 4, 1) +FIELD(BBRAM_STATUS, PGM_MODE, 0, 1) +REG32(BBRAM_CTRL, 0x4) +FIELD(BBRAM_CTRL, ZEROIZE, 0, 1) +REG32(PGM_MODE, 0x8) +REG32(BBRAM_AES_CRC, 0xc) +REG32(BBRAM_0, 0x10) +REG32(BBRAM_1, 0x14) +REG32(BBRAM_2, 0x18) +REG32(BBRAM_3, 0x1c) +REG32(BBRAM_4, 0x20) +REG32(BBRAM_5, 0x24) +REG32(BBRAM_6, 0x28) +REG32(BBRAM_7, 0x2c) +REG32(BBRAM_8, 0x30) +REG32(BBRAM_SLVERR, 0x34) +FIELD(BBRAM_SLVERR, ENABLE, 0, 1) +REG32(BBRAM_ISR, 0x38) +FIELD(BBRAM_ISR, APB_SLVERR, 0, 1) +REG32(BBRAM_IMR, 0x3c) +FIELD(BBRAM_IMR, APB_SLVERR, 0, 1) +REG32(BBRAM_IER, 0x40) +FIELD(BBRAM_IER, APB_SLVERR, 0, 1) +REG32(BBRAM_IDR, 0x44) +FIELD(BBRAM_IDR, APB_SLVERR, 0, 1) +REG32(BBRAM_MSW_LOCK, 0x4c) +FIELD(BBRAM_MSW_LOCK, VAL, 0, 1) + +#define R_MAX (R_BBRAM_MSW_LOCK + 1) + +#define RAM_MAX (A_BBRAM_8 + 4 - A_BBRAM_0) + +#define BBRAM_PGM_MAGIC 0x757bdf0d + +QEMU_BUILD_BUG_ON(R_MAX != ARRAY_SIZE(((XlnxBBRam *)0)->regs)); + +static bool bbram_msw_locked(XlnxBBRam *s) +{ +return ARRAY_FIELD_EX32(s->regs, BBRAM_MSW_LOCK, VAL) != 0; +} + +static bool bbram_pgm_enabled(XlnxBBRam *s) +{ +return ARRAY_FIELD_EX32(s->regs, BBRAM_STATUS, PGM_MODE) != 0; +} + +static void bbram_bdrv_error(XlnxBBRam *s, int rc, gchar *detail) +{ +Error *errp; + +error_setg_errno(, -rc, "%s: BBRAM backstore %s failed.", + blk_name(s->blk), detail); +error_report("%s", error_get_pretty(errp)); +error_free(err
[PATCH v3 2/9] hw/nvram: Introduce Xilinx Versal eFuse device
This implements the Xilinx Versal eFuse, an one-time field-programmable non-volatile storage device. There is only one such device in the Xilinx Versal product family. This device has two separate mmio interfaces, a controller and a flatten readback. The controller provides interfaces for field-programming, configuration, control, and status. The flatten readback is a cache to provide a byte-accessible read-only interface to efficiently read efuse array. Co-authored-by: Edgar E. Iglesias Co-authored-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Signed-off-by: Sai Pavan Boddu Signed-off-by: Tong Ho --- hw/nvram/Kconfig | 4 + hw/nvram/meson.build | 3 + hw/nvram/xlnx-versal-efuse-cache.c | 114 hw/nvram/xlnx-versal-efuse-ctrl.c| 783 +++ include/hw/nvram/xlnx-versal-efuse.h | 68 +++ 5 files changed, 972 insertions(+) create mode 100644 hw/nvram/xlnx-versal-efuse-cache.c create mode 100644 hw/nvram/xlnx-versal-efuse-ctrl.c create mode 100644 include/hw/nvram/xlnx-versal-efuse.h diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig index 252251f366..6c2bb5afe3 100644 --- a/hw/nvram/Kconfig +++ b/hw/nvram/Kconfig @@ -22,3 +22,7 @@ config XLNX_EFUSE_CRC config XLNX_EFUSE bool select XLNX_EFUSE_CRC + +config XLNX_EFUSE_VERSAL +bool +select XLNX_EFUSE diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index 623c94efff..62352ad8ec 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -11,5 +11,8 @@ softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c')) softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_CRC', if_true: files('xlnx-efuse-crc.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files( + 'xlnx-versal-efuse-cache.c', + 'xlnx-versal-efuse-ctrl.c')) specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c')) diff --git a/hw/nvram/xlnx-versal-efuse-cache.c b/hw/nvram/xlnx-versal-efuse-cache.c new file mode 100644 index 00..eaec64d785 --- /dev/null +++ b/hw/nvram/xlnx-versal-efuse-cache.c @@ -0,0 +1,114 @@ +/* + * QEMU model of the EFuse_Cache + * + * Copyright (c) 2017 Xilinx Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/nvram/xlnx-versal-efuse.h" + +#include "qemu/log.h" +#include "hw/qdev-properties.h" + +#define MR_SIZE 0xC00 + +static uint64_t efuse_cache_read(void *opaque, hwaddr addr, unsigned size) +{ +XlnxVersalEFuseCache *s = XLNX_VERSAL_EFUSE_CACHE(opaque); +unsigned int w0 = QEMU_ALIGN_DOWN(addr * 8, 32); +unsigned int w1 = QEMU_ALIGN_DOWN((addr + size - 1) * 8, 32); + +uint64_t ret; + +assert(w0 == w1 || (w0 + 32) == w1); + +ret = xlnx_versal_efuse_read_row(s->efuse, w1, NULL); +if (w0 < w1) { +ret <<= 32; +ret |= xlnx_versal_efuse_read_row(s->efuse, w0, NULL); +} + +/* If 'addr' unaligned, the guest is always assumed to be little-endian. */ +addr &= 3; +if (addr) { +ret >>= 8 * addr; +} + +return ret; +} + +static void efuse_cache_write(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ +/* No Register Writes allowed */ +qemu_log_mask(LOG_GUEST_ERROR, "%s: efuse cache registers are read-only", + __func__); +} + +static const MemoryRegionOps efuse_cache_ops = { +.read = efuse_cache_read, +.write = efuse_cache_write, +.endianness = DEVICE_LITTLE_ENDIAN, +.valid = { +.min_access_size = 1, +.max_access_size = 4, +}, +}; + +static v
[PATCH v3 5/9] hw/arm: xlnx-versal-virt: Add Xilinx BBRAM device
Connect the support for Versal Battery-Backed RAM (BBRAM) The command argument: -drive if=pflash,index=0,... Can be used to optionally connect the bbram to a backend storage, such that field-programmed values in one invocation can be made available to next invocation. The backend storage must be a seekable binary file, and its size must be 36 bytes or larger. A file with all binary 0's is a 'blank'. Signed-off-by: Tong Ho --- hw/arm/Kconfig | 1 + hw/arm/xlnx-versal-virt.c| 36 hw/arm/xlnx-versal.c | 18 ++ include/hw/arm/xlnx-versal.h | 5 + 4 files changed, 60 insertions(+) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 78fdd1b935..f92fb9e568 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -381,6 +381,7 @@ config XLNX_VERSAL select XLNX_ZDMA select XLNX_ZYNQMP select OR_IRQ +select XLNX_BBRAM config NPCM7XX bool diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 5bca360dce..e1c5ead475 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -356,6 +356,26 @@ static void fdt_add_rtc_node(VersalVirt *s) g_free(name); } +static void fdt_add_bbram_node(VersalVirt *s) +{ +const char compat[] = TYPE_XLNX_BBRAM; +const char interrupt_names[] = "bbram-error"; +char *name = g_strdup_printf("/bbram@%x", MM_PMC_BBRAM_CTRL); + +qemu_fdt_add_subnode(s->fdt, name); + +qemu_fdt_setprop_cells(s->fdt, name, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, VERSAL_BBRAM_APB_IRQ_0, + GIC_FDT_IRQ_FLAGS_LEVEL_HI); +qemu_fdt_setprop(s->fdt, name, "interrupt-names", + interrupt_names, sizeof(interrupt_names)); +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, MM_PMC_BBRAM_CTRL, + 2, MM_PMC_BBRAM_CTRL_SIZE); +qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +g_free(name); +} + static void fdt_nop_memory_nodes(void *fdt, Error **errp) { Error *err = NULL; @@ -510,6 +530,18 @@ static void create_virtio_regions(VersalVirt *s) } } +static void bbram_attach_drive(XlnxBBRam *dev) +{ +DriveInfo *dinfo; +BlockBackend *blk; + +dinfo = drive_get_by_index(IF_PFLASH, 0); +blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; +if (blk) { +qdev_prop_set_drive(DEVICE(dev), "drive", blk); +} +} + static void sd_plugin_card(SDHCIState *sd, DriveInfo *di) { BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL; @@ -570,6 +602,7 @@ static void versal_virt_init(MachineState *machine) fdt_add_usb_xhci_nodes(s); fdt_add_sd_nodes(s); fdt_add_rtc_node(s); +fdt_add_bbram_node(s); fdt_add_cpu_nodes(s, psci_conduit); fdt_add_clk_node(s, "/clk125", 12500, s->phandle.clk_125Mhz); fdt_add_clk_node(s, "/clk25", 2500, s->phandle.clk_25Mhz); @@ -579,6 +612,9 @@ static void versal_virt_init(MachineState *machine) memory_region_add_subregion_overlap(get_system_memory(), 0, >soc.fpd.apu.mr, 0); +/* Attach bbram backend, if given */ +bbram_attach_drive(>soc.pmc.bbram); + /* Plugin SD cards. */ for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) { sd_plugin_card(>soc.pmc.iou.sd[i], drive_get_next(IF_SD)); diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 547a26603a..23451ae012 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -314,6 +314,23 @@ static void versal_create_xrams(Versal *s, qemu_irq *pic) } } +static void versal_create_bbram(Versal *s, qemu_irq *pic) +{ +SysBusDevice *sbd; + +object_initialize_child_with_props(OBJECT(s), "bbram", >pmc.bbram, + sizeof(s->pmc.bbram), TYPE_XLNX_BBRAM, + _fatal, + "crc-zpads", "0", + NULL); +sbd = SYS_BUS_DEVICE(>pmc.bbram); + +sysbus_realize(sbd, _fatal); +memory_region_add_subregion(>mr_ps, MM_PMC_BBRAM_CTRL, +sysbus_mmio_get_region(sbd, 0)); +sysbus_connect_irq(sbd, 0, pic[VERSAL_BBRAM_APB_IRQ_0]); +} + /* This takes the board allocated linear DDR memory and creates aliases * for each split DDR range/aperture on the Versal address map. */ @@ -402,6 +419,7 @@ static void versal_realize(DeviceState *dev, Error **errp) versal_create_sds(s, pic); versal_create_rtc(s, pic); versal_create_xrams(s, pic); +versal_create_bbram(s, pic); versal_map_ddr(s); versal_unimp(s); diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 9b79051747..1
[PATCH v2 3/9] hw/nvram: Introduce Xilinx ZynqMP eFuse device
This implements the Xilinx ZynqMP eFuse, an one-time field-programmable non-volatile storage device. There is only one such device in the Xilinx ZynqMP product family. The command argument: -drive if=pflash,index=N,... Can be used to optionally connect the storage array to a backend storage, such that field-programmed values in one invocation can be made available to next invocation. The backend storage must be a seekable binary file, and its size must be 768 bytes or larger. A file with all binary 0's is a 'blank'. The drive 'index' value N has a default value of 3, but can be changed using command argument: -global xlnx,efuse.drive-index=N Co-authored-by: Edgar E. Iglesias Co-authored-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Signed-off-by: Sai Pavan Boddu Signed-off-by: Tong Ho --- hw/nvram/Kconfig | 5 + hw/nvram/meson.build | 2 + hw/nvram/xlnx-zynqmp-efuse.c | 860 +++ include/hw/nvram/xlnx-zynqmp-efuse.h | 45 ++ 4 files changed, 912 insertions(+) create mode 100644 hw/nvram/xlnx-zynqmp-efuse.c create mode 100644 include/hw/nvram/xlnx-zynqmp-efuse.h diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig index e96749ced3..cc3ed789fe 100644 --- a/hw/nvram/Kconfig +++ b/hw/nvram/Kconfig @@ -23,3 +23,8 @@ config XLNX_EFUSE_VERSAL bool default y if XLNX_VERSAL select XLNX_EFUSE + +config XLNX_EFUSE_ZYNQMP +bool +default y if XLNX_ZYNQMP +select XLNX_EFUSE diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index a432665158..f364520ad5 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -13,6 +13,8 @@ softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files( 'xlnx-versal-efuse-cache.c', 'xlnx-versal-efuse-ctrl.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_ZYNQMP', if_true: files( + 'xlnx-zynqmp-efuse.c')) if 'CONFIG_XLNX_BBRAM' in config_all or \ 'CONFIG_XLNX_EFUSE' in config_all softmmu_ss.add(files('xlnx-efuse-crc.c')) diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c new file mode 100644 index 00..a16a00aa55 --- /dev/null +++ b/hw/nvram/xlnx-zynqmp-efuse.c @@ -0,0 +1,860 @@ +/* + * QEMU model of the ZynqMP eFuse + * + * Copyright (c) 2015 Xilinx Inc. + * + * Written by Edgar E. Iglesias + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/nvram/xlnx-zynqmp-efuse.h" + +#include "qemu/log.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" + +#ifndef ZYNQMP_EFUSE_ERR_DEBUG +#define ZYNQMP_EFUSE_ERR_DEBUG 0 +#endif + +#define ZYNQMP_EFUSE(obj) \ + OBJECT_CHECK(XlnxZynqMPEFuse, (obj), TYPE_XLNX_ZYNQMP_EFUSE) + +REG32(WR_LOCK, 0x0) +FIELD(WR_LOCK, LOCK, 0, 16) +REG32(CFG, 0x4) +FIELD(CFG, SLVERR_ENABLE, 5, 1) +FIELD(CFG, MARGIN_RD, 2, 2) +FIELD(CFG, PGM_EN, 1, 1) +FIELD(CFG, EFUSE_CLK_SEL, 0, 1) +REG32(STATUS, 0x8) +FIELD(STATUS, AES_CRC_PASS, 7, 1) +FIELD(STATUS, AES_CRC_DONE, 6, 1) +FIELD(STATUS, CACHE_DONE, 5, 1) +FIELD(STATUS, CACHE_LOAD, 4, 1) +FIELD(STATUS, EFUSE_3_TBIT, 2, 1) +FIELD(STATUS, EFUSE_2_TBIT, 1, 1) +FIELD(STATUS, EFUSE_0_TBIT, 0, 1) +REG32(EFUSE_PGM_ADDR, 0xc) +FIELD(EFUSE_PGM_ADDR, EFUSE, 11, 2) +FIELD(EFUSE_PGM_ADDR, ROW, 5, 6) +FIELD(EFUSE_PGM_ADDR, COLUMN, 0, 5) +REG32(EFUSE_RD_ADDR, 0x10) +FIELD(EFUSE_RD_ADDR, EFUSE, 11, 2) +FIELD(EFUSE_RD_ADDR, ROW, 5, 6) +REG32(EFUSE_RD_DATA, 0x14) +REG32(TPGM, 0x18) +FIELD(TPGM, VALUE, 0, 16) +REG32(TRD, 0x1c) +FIELD(TRD, VALUE, 0, 8) +REG32(TSU_H_PS, 0x20) +FIELD(TSU_
[PATCH v2 9/9] docs/system/arm: xlnx-versal-virt: BBRAM and eFUSE Usage
Add BBRAM and eFUSE usage to the Xilinx Versal Virt board document. Signed-off-by: Tong Ho --- docs/system/arm/xlnx-versal-virt.rst | 49 1 file changed, 49 insertions(+) diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst index 27f73500d9..84afac3734 100644 --- a/docs/system/arm/xlnx-versal-virt.rst +++ b/docs/system/arm/xlnx-versal-virt.rst @@ -32,6 +32,8 @@ Implemented devices: - OCM (256KB of On Chip Memory) - XRAM (4MB of on chip Accelerator RAM) - DDR memory +- BBRAM (36 bytes of Battery-backed RAM) +- eFUSE (3072 bytes of one-time field-programmable bit array) QEMU does not yet model any other devices, including the PL and the AI Engine. @@ -175,3 +177,50 @@ Run the following at the U-Boot prompt: fdt set /chosen/dom0 reg <0x 0x4000 0x0 0x0310> booti 3000 - 2000 +BBRAM File Backend +"""""""""""""""""" +BBRAM can have an optional file backend, which must a seekable +binary file with a size of 36 bytes or larger. A file with all +binary 0s is a 'blank'. + +To add a file-backend for the BBRAM: + +.. code-block:: bash + + -drive if=pflash,index=0,file=versal-bbram.bin,format=raw + +To use a different index value, N, from default of 0, add: + +.. code-block:: bash + + -global xlnx,bbram-ctrl.drive-index=N + +eFUSE File Backend +"""""""""""""""""" +eFUSE can have an optional file backend, which must a seekable +binary file with a size of 3072 bytes or larger. A file with all +binary 0s is a 'blank'. + +To add a file-backend for the eFUSE: + +.. code-block:: bash + + -drive if=pflash,index=1,file=versal-efuse.bin,format=raw + +To use a different index value, N, from default of 1, add: + +.. code-block:: bash + + -global xlnx,efuse.drive-index=N + +.. warning:: + In actual physical Versal, BBRAM and eFUSE contain sensitive data. + The QEMU device models do **not** encrypt nor obfuscate any data + when holding them in models' memory or when writing them to their + file backends. + + Thus, a file backend should be used with caution, and 'format=luks' + is highly recommended (albeit with usage complexity). + + Better yet, do not use actual product data when running guest image + on this Xilinx Versal Virt board. | -- 2.25.1
[PATCH v2 6/9] hw/arm: xlnx-versal: Add Xilinx eFUSE device
Connect the support for Versal eFUSE one-time field-programmable bit array. Signed-off-by: Tong Ho --- hw/arm/xlnx-versal-virt.c| 37 ++ hw/arm/xlnx-versal.c | 39 include/hw/arm/xlnx-versal.h | 12 +++ 3 files changed, 88 insertions(+) diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index d9e2a6a853..5c72b9ba4b 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -376,6 +376,41 @@ static void fdt_add_bbram_node(VersalVirt *s) g_free(name); } +static void fdt_add_efuse_ctrl_node(VersalVirt *s) +{ +const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CTRL; +const char interrupt_names[] = "pmc_efuse"; +char *name = g_strdup_printf("/pmc_efuse@%x", MM_PMC_EFUSE_CTRL); + +qemu_fdt_add_subnode(s->fdt, name); + +qemu_fdt_setprop_cells(s->fdt, name, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, VERSAL_EFUSE_IRQ, + GIC_FDT_IRQ_FLAGS_LEVEL_HI); +qemu_fdt_setprop(s->fdt, name, "interrupt-names", + interrupt_names, sizeof(interrupt_names)); +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, MM_PMC_EFUSE_CTRL, + 2, MM_PMC_EFUSE_CTRL_SIZE); +qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +g_free(name); +} + +static void fdt_add_efuse_cache_node(VersalVirt *s) +{ +const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CACHE; +char *name = g_strdup_printf("/xlnx_pmc_efuse_cache@%x", + MM_PMC_EFUSE_CACHE); + +qemu_fdt_add_subnode(s->fdt, name); + +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, MM_PMC_EFUSE_CACHE, + 2, MM_PMC_EFUSE_CACHE_SIZE); +qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +g_free(name); +} + static void fdt_nop_memory_nodes(void *fdt, Error **errp) { Error *err = NULL; @@ -591,6 +626,8 @@ static void versal_virt_init(MachineState *machine) fdt_add_sd_nodes(s); fdt_add_rtc_node(s); fdt_add_bbram_node(s); +fdt_add_efuse_ctrl_node(s); +fdt_add_efuse_cache_node(s); fdt_add_cpu_nodes(s, psci_conduit); fdt_add_clk_node(s, "/clk125", 12500, s->phandle.clk_125Mhz); fdt_add_clk_node(s, "/clk25", 2500, s->phandle.clk_25Mhz); diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 46d7f42a6b..d278d6e0f4 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -329,6 +329,44 @@ static void versal_create_bbram(Versal *s, qemu_irq *pic) sysbus_connect_irq(sbd, 0, pic[VERSAL_BBRAM_APB_IRQ_0]); } +static void versal_realize_efuse_part(Versal *s, Object *dev, hwaddr base) +{ +SysBusDevice *part = SYS_BUS_DEVICE(dev); + +object_property_set_link(OBJECT(part), "efuse", + OBJECT(>pmc.efuse.bits), _abort); + +sysbus_realize(part, _abort); +memory_region_add_subregion(>mr_ps, base, +sysbus_mmio_get_region(part, 0)); +} + +static void versal_create_efuse(Versal *s, qemu_irq *pic) +{ +Object *bits = OBJECT(>pmc.efuse.bits); +Object *ctrl = OBJECT(>pmc.efuse.ctrl); +Object *cache = OBJECT(>pmc.efuse.cache); + +object_initialize_child(OBJECT(s), "efuse-ctrl", >pmc.efuse.ctrl, +TYPE_XLNX_VERSAL_EFUSE_CTRL); + +object_initialize_child(OBJECT(s), "efuse-cache", >pmc.efuse.cache, +TYPE_XLNX_VERSAL_EFUSE_CACHE); + +object_initialize_child_with_props(ctrl, "efuse-bits", bits, + sizeof(s->pmc.efuse.bits), + TYPE_XLNX_EFUSE, _abort, + "efuse-nr", "3", + "efuse-size", "8192", + NULL); + +qdev_realize(DEVICE(bits), NULL, _abort); +versal_realize_efuse_part(s, ctrl, MM_PMC_EFUSE_CTRL); +versal_realize_efuse_part(s, cache, MM_PMC_EFUSE_CACHE); + +sysbus_connect_irq(SYS_BUS_DEVICE(ctrl), 0, pic[VERSAL_EFUSE_IRQ]); +} + /* This takes the board allocated linear DDR memory and creates aliases * for each split DDR range/aperture on the Versal address map. */ @@ -416,6 +454,7 @@ static void versal_realize(DeviceState *dev, Error **errp) versal_create_rtc(s, pic); versal_create_xrams(s, pic); versal_create_bbram(s, pic); +versal_create_efuse(s, pic); versal_map_ddr(s); versal_unimp(s); diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 7719e8c4d2..33b89f0
[PATCH v2 1/9] hw/nvram: Introduce Xilinx eFuse QOM
This introduces the QOM for Xilinx eFuse, an one-time field-programmable storage bit array. The actual mmio interface to the array varies by device families and will be provided in different change-sets. Co-authored-by: Edgar E. Iglesias Co-authored-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Signed-off-by: Sai Pavan Boddu Signed-off-by: Tong Ho --- hw/nvram/xlnx-efuse-crc.c | 118 hw/nvram/xlnx-efuse.c | 252 ++ include/hw/nvram/xlnx-efuse.h | 80 +++ 3 files changed, 450 insertions(+) create mode 100644 hw/nvram/xlnx-efuse-crc.c create mode 100644 hw/nvram/xlnx-efuse.c create mode 100644 include/hw/nvram/xlnx-efuse.h diff --git a/hw/nvram/xlnx-efuse-crc.c b/hw/nvram/xlnx-efuse-crc.c new file mode 100644 index 00..bc12c39e00 --- /dev/null +++ b/hw/nvram/xlnx-efuse-crc.c @@ -0,0 +1,118 @@ +/* + * Xilinx eFuse/bbram CRC calculator + * + * Copyright (c) 2021 Xilinx Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "hw/nvram/xlnx-efuse.h" + +static uint32_t xlnx_efuse_u37_crc(uint32_t prev_crc, uint32_t data, + uint32_t addr) +{ +/* A table for 7-bit slicing */ +static const uint32_t crc_tab[128] = { +0x, 0xe13b70f7, 0xc79a971f, 0x26a1e7e8, +0x8ad958cf, 0x6be22838, 0x4d43cfd0, 0xac78bf27, +0x105ec76f, 0xf165b798, 0xd7c45070, 0x36ff2087, +0x9a879fa0, 0x7bbcef57, 0x5d1d08bf, 0xbc267848, +0x20bd8ede, 0xc186fe29, 0xe72719c1, 0x061c6936, +0xaa64d611, 0x4b5fa6e6, 0x6dfe410e, 0x8cc531f9, +0x30e349b1, 0xd1d83946, 0xf779deae, 0x1642ae59, +0xba3a117e, 0x5b016189, 0x7da08661, 0x9c9bf696, +0x417b1dbc, 0xa0406d4b, 0x86e18aa3, 0x67dafa54, +0xcba24573, 0x2a993584, 0x0c38d26c, 0xed03a29b, +0x5125dad3, 0xb01eaa24, 0x96bf4dcc, 0x77843d3b, +0xdbfc821c, 0x3ac7f2eb, 0x1c661503, 0xfd5d65f4, +0x61c69362, 0x80fde395, 0xa65c047d, 0x4767748a, +0xeb1fcbad, 0x0a24bb5a, 0x2c855cb2, 0xcdbe2c45, +0x7198540d, 0x90a324fa, 0xb602c312, 0x5739b3e5, +0xfb410cc2, 0x1a7a7c35, 0x3cdb9bdd, 0xdde0eb2a, +0x82f63b78, 0x63cd4b8f, 0x456cac67, 0xa457dc90, +0x082f63b7, 0xe9141340, 0xcfb5f4a8, 0x2e8e845f, +0x92a8fc17, 0x73938ce0, 0x55326b08, 0xb4091bff, +0x1871a4d8, 0xf94ad42f, 0xdfeb33c7, 0x3ed04330, +0xa24bb5a6, 0x4370c551, 0x65d122b9, 0x84ea524e, +0x2892ed69, 0xc9a99d9e, 0xef087a76, 0x0e330a81, +0xb21572c9, 0x532e023e, 0x758fe5d6, 0x94b49521, +0x38cc2a06, 0xd9f75af1, 0xff56bd19, 0x1e6dcdee, +0xc38d26c4, 0x22b65633, 0x0417b1db, 0xe52cc12c, +0x49547e0b, 0xa86f0efc, 0x8ecee914, 0x6ff599e3, +0xd3d3e1ab, 0x32e8915c, 0x144976b4, 0xf5720643, +0x590ab964, 0xb831c993, 0x9e902e7b, 0x7fab5e8c, +0xe330a81a, 0x020bd8ed, 0x24aa3f05, 0xc5914ff2, +0x69e9f0d5, 0x88d28022, 0xae7367ca, 0x4f48173d, +0xf36e6f75, 0x12551f82, 0x34f4f86a, 0xd5cf889d, +0x79b737ba, 0x988c474d, 0xbe2da0a5, 0x5f16d052 +}; + +/* + * eFuse calculation is shown here: + * https://github.com/Xilinx/embeddedsw/blob/release-2019.2/lib/sw_services/xilskey/src/xilskey_utils.c#L1496 + * + * Each u32 word is appended a 5-bit value, for a total of 37 bits; see: + * https://github.com/Xilinx/embeddedsw/blob/release-2019.2/lib/sw_services/xilskey/src/xilskey_utils.c#L1356 + */ +uint32_t crc = prev_crc; +const unsigned rshf = 7; +const uint32_t im = (1 << rshf) - 1; +const uint32_t rm = (1 << (32 - rshf)) - 1; +const uint32_t i2 = (1 << 2) - 1; +const uint32_t r2 = (1 << 30) - 1; + +unsigned j; +uint32_t i, r; +uint64_t w; + +w = (uint64_t)(addr) << 32; +w |= data; + +/* Feed 35 bits, in 5 rounds, each a slice of 7 bits */ +
[PATCH v2 7/9] hw/arm: xlnx-zynqmp: Add Xilinx BBRAM device
Connect the support for Xilinx ZynqMP Battery-Backed RAM (BBRAM) Signed-off-by: Tong Ho --- hw/arm/xlnx-zynqmp.c | 21 + include/hw/arm/xlnx-zynqmp.h | 2 ++ 2 files changed, 23 insertions(+) diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 3597e8db4d..8e39b7d6c7 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -62,6 +62,9 @@ #define RTC_ADDR0xffa6 #define RTC_IRQ 26 +#define BBRAM_ADDR 0xffcd +#define BBRAM_IRQ 11 + #define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */ static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = { @@ -222,6 +225,22 @@ static void xlnx_zynqmp_create_rpu(MachineState *ms, XlnxZynqMPState *s, qdev_realize(DEVICE(>rpu_cluster), NULL, _fatal); } +static void xlnx_zynqmp_create_bbram(XlnxZynqMPState *s, qemu_irq *gic) +{ +SysBusDevice *sbd; + +object_initialize_child_with_props(OBJECT(s), "bbram", >bbram, + sizeof(s->bbram), TYPE_XLNX_BBRAM, + _fatal, + "crc-zpads", "1", + NULL); +sbd = SYS_BUS_DEVICE(>bbram); + +sysbus_realize(sbd, _fatal); +sysbus_mmio_map(sbd, 0, BBRAM_ADDR); +sysbus_connect_irq(sbd, 0, gic[BBRAM_IRQ]); +} + static void xlnx_zynqmp_init(Object *obj) { MachineState *ms = MACHINE(qdev_get_machine()); @@ -616,6 +635,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(>rtc), 0, RTC_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(>rtc), 0, gic_spi[RTC_IRQ]); +xlnx_zynqmp_create_bbram(s, gic_spi); + for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) { if (!object_property_set_uint(OBJECT(>gdma[i]), "bus-width", 128, errp)) { diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index d3e2ef97f6..07ebcefbab 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -36,6 +36,7 @@ #include "qom/object.h" #include "net/can_emu.h" #include "hw/dma/xlnx_csu_dma.h" +#include "hw/nvram/xlnx-bbram.h" #define TYPE_XLNX_ZYNQMP "xlnx-zynqmp" OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) @@ -95,6 +96,7 @@ struct XlnxZynqMPState { MemoryRegion *ddr_ram; MemoryRegion ddr_ram_low, ddr_ram_high; +XlnxBBRam bbram; CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS]; CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS]; -- 2.25.1
[PATCH v2 5/9] hw/arm: xlnx-versal: Add Xilinx BBRAM device
Connect the support for Versal Battery-Backed RAM (BBRAM) Signed-off-by: Tong Ho --- hw/arm/xlnx-versal-virt.c| 21 + hw/arm/xlnx-versal.c | 18 ++ include/hw/arm/xlnx-versal.h | 5 + 3 files changed, 44 insertions(+) diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 5bca360dce..d9e2a6a853 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -356,6 +356,26 @@ static void fdt_add_rtc_node(VersalVirt *s) g_free(name); } +static void fdt_add_bbram_node(VersalVirt *s) +{ +const char compat[] = TYPE_XLNX_BBRAM; +const char interrupt_names[] = "bbram-error"; +char *name = g_strdup_printf("/bbram@%x", MM_PMC_BBRAM_CTRL); + +qemu_fdt_add_subnode(s->fdt, name); + +qemu_fdt_setprop_cells(s->fdt, name, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, VERSAL_BBRAM_APB_IRQ_0, + GIC_FDT_IRQ_FLAGS_LEVEL_HI); +qemu_fdt_setprop(s->fdt, name, "interrupt-names", + interrupt_names, sizeof(interrupt_names)); +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, MM_PMC_BBRAM_CTRL, + 2, MM_PMC_BBRAM_CTRL_SIZE); +qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +g_free(name); +} + static void fdt_nop_memory_nodes(void *fdt, Error **errp) { Error *err = NULL; @@ -570,6 +590,7 @@ static void versal_virt_init(MachineState *machine) fdt_add_usb_xhci_nodes(s); fdt_add_sd_nodes(s); fdt_add_rtc_node(s); +fdt_add_bbram_node(s); fdt_add_cpu_nodes(s, psci_conduit); fdt_add_clk_node(s, "/clk125", 12500, s->phandle.clk_125Mhz); fdt_add_clk_node(s, "/clk25", 2500, s->phandle.clk_25Mhz); diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index fb776834f7..46d7f42a6b 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -312,6 +312,23 @@ static void versal_create_xrams(Versal *s, qemu_irq *pic) } } +static void versal_create_bbram(Versal *s, qemu_irq *pic) +{ +SysBusDevice *sbd; + +object_initialize_child_with_props(OBJECT(s), "bbram", >pmc.bbram, + sizeof(s->pmc.bbram), TYPE_XLNX_BBRAM, + _fatal, + "crc-zpads", "0", + NULL); +sbd = SYS_BUS_DEVICE(>pmc.bbram); + +sysbus_realize(sbd, _fatal); +memory_region_add_subregion(>mr_ps, MM_PMC_BBRAM_CTRL, +sysbus_mmio_get_region(sbd, 0)); +sysbus_connect_irq(sbd, 0, pic[VERSAL_BBRAM_APB_IRQ_0]); +} + /* This takes the board allocated linear DDR memory and creates aliases * for each split DDR range/aperture on the Versal address map. */ @@ -398,6 +415,7 @@ static void versal_realize(DeviceState *dev, Error **errp) versal_create_sds(s, pic); versal_create_rtc(s, pic); versal_create_xrams(s, pic); +versal_create_bbram(s, pic); versal_map_ddr(s); versal_unimp(s); diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 22a8fa5d11..7719e8c4d2 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -24,6 +24,7 @@ #include "qom/object.h" #include "hw/usb/xlnx-usb-subsystem.h" #include "hw/misc/xlnx-versal-xramc.h" +#include "hw/nvram/xlnx-bbram.h" #define TYPE_XLNX_VERSAL "xlnx-versal" OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL) @@ -79,6 +80,7 @@ struct Versal { } iou; XlnxZynqMPRTC rtc; +XlnxBBRam bbram; } pmc; struct { @@ -105,6 +107,7 @@ struct Versal { #define VERSAL_GEM1_WAKE_IRQ_0 59 #define VERSAL_ADMA_IRQ_0 60 #define VERSAL_XRAM_IRQ_0 79 +#define VERSAL_BBRAM_APB_IRQ_0 121 #define VERSAL_RTC_APB_ERR_IRQ 121 #define VERSAL_SD0_IRQ_0 126 #define VERSAL_RTC_ALARM_IRQ 142 @@ -170,6 +173,8 @@ struct Versal { #define MM_PMC_SD0 0xf104U #define MM_PMC_SD0_SIZE 0x1 +#define MM_PMC_BBRAM_CTRL 0xf11f +#define MM_PMC_BBRAM_CTRL_SIZE 0x00050 #define MM_PMC_CRP 0xf126U #define MM_PMC_CRP_SIZE 0x1 #define MM_PMC_RTC 0xf12a -- 2.25.1
[PATCH v2 0/9] hw/nvram: hw/arm: Introduce Xilinx eFUSE and BBRAM
This series implements the Xilinx eFUSE and BBRAM devices for the Versal and ZynqMP product families. Furthermore, both new devices are connected to the xlnx-versal-virt board and the xlnx-zcu102 board. See changes in docs/system/arm/xlnx-versal-virt.rst for detail. --- Changelogs: v1->v2: * Move doc change from 1st to last of this series * Remove outdated comment of 'autogenerated by xregqemu.py' from all affected files. --- Tong Ho (9): hw/nvram: Introduce Xilinx eFuse QOM hw/nvram: Introduce Xilinx Versal eFuse device hw/nvram: Introduce Xilinx ZynqMP eFuse device hw/nvram: Introduce Xilinx battery-backed ram hw/arm: xlnx-versal: Add Xilinx BBRAM device hw/arm: xlnx-versal: Add Xilinx eFUSE device hw/arm: xlnx-zynqmp: Add Xilinx BBRAM device hw/arm: xlnx-zynqmp: Add Xilinx eFUSE device docs/system/arm: xlnx-versal-virt: BBRAM and eFUSE Usage docs/system/arm/xlnx-versal-virt.rst | 49 ++ hw/arm/xlnx-versal-virt.c| 58 ++ hw/arm/xlnx-versal.c | 57 ++ hw/arm/xlnx-zynqmp.c | 50 ++ hw/nvram/Kconfig | 17 + hw/nvram/meson.build | 11 + hw/nvram/xlnx-bbram.c| 534 + hw/nvram/xlnx-efuse-crc.c| 118 hw/nvram/xlnx-efuse.c| 252 hw/nvram/xlnx-versal-efuse-cache.c | 139 + hw/nvram/xlnx-versal-efuse-ctrl.c| 784 hw/nvram/xlnx-zynqmp-efuse.c | 860 +++ include/hw/arm/xlnx-versal.h | 17 + include/hw/arm/xlnx-zynqmp.h | 5 + include/hw/nvram/xlnx-bbram.h| 55 ++ include/hw/nvram/xlnx-efuse.h| 80 +++ include/hw/nvram/xlnx-versal-efuse.h | 62 ++ include/hw/nvram/xlnx-zynqmp-efuse.h | 45 ++ 18 files changed, 3193 insertions(+) create mode 100644 hw/nvram/xlnx-bbram.c create mode 100644 hw/nvram/xlnx-efuse-crc.c create mode 100644 hw/nvram/xlnx-efuse.c create mode 100644 hw/nvram/xlnx-versal-efuse-cache.c create mode 100644 hw/nvram/xlnx-versal-efuse-ctrl.c create mode 100644 hw/nvram/xlnx-zynqmp-efuse.c create mode 100644 include/hw/nvram/xlnx-bbram.h create mode 100644 include/hw/nvram/xlnx-efuse.h create mode 100644 include/hw/nvram/xlnx-versal-efuse.h create mode 100644 include/hw/nvram/xlnx-zynqmp-efuse.h -- 2.25.1
[PATCH v2 4/9] hw/nvram: Introduce Xilinx battery-backed ram
This device is present in Versal and ZynqMP product families to store a 256-bit encryption key. Co-authored-by: Edgar E. Iglesias Co-authored-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Signed-off-by: Sai Pavan Boddu Signed-off-by: Tong Ho --- hw/nvram/Kconfig | 4 + hw/nvram/meson.build | 1 + hw/nvram/xlnx-bbram.c | 534 ++ include/hw/nvram/xlnx-bbram.h | 55 4 files changed, 594 insertions(+) create mode 100644 hw/nvram/xlnx-bbram.c create mode 100644 include/hw/nvram/xlnx-bbram.h diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig index cc3ed789fe..a8c5e9227e 100644 --- a/hw/nvram/Kconfig +++ b/hw/nvram/Kconfig @@ -28,3 +28,7 @@ config XLNX_EFUSE_ZYNQMP bool default y if XLNX_ZYNQMP select XLNX_EFUSE + +config XLNX_BBRAM +bool +default y if (XLNX_VERSAL || XLNX_ZYNQMP) diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index f364520ad5..0a1676d37a 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -9,6 +9,7 @@ softmmu_ss.add(when: 'CONFIG_AT24C', if_true: files('eeprom_at24c.c')) softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c')) softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c')) softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_BBRAM', if_true: files('xlnx-bbram.c', 'xlnx-efuse-crc.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files( 'xlnx-versal-efuse-cache.c', diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c new file mode 100644 index 00..6da79aa383 --- /dev/null +++ b/hw/nvram/xlnx-bbram.c @@ -0,0 +1,534 @@ +/* + * QEMU model of the Xilinx BBRAM Battery Backed RAM + * + * Copyright (c) 2014-2021 Xilinx Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/nvram/xlnx-bbram.h" + +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "sysemu/blockdev.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" +#include "hw/qdev-properties-system.h" +#include "hw/nvram/xlnx-efuse.h" + +#ifndef XLNX_BBRAM_ERR_DEBUG +#define XLNX_BBRAM_ERR_DEBUG 0 +#endif + +#define XLNX_BBRAM(obj) \ + OBJECT_CHECK(XlnxBBRam, (obj), TYPE_XLNX_BBRAM) + +#define DB_PRINT_L(lvl, fmt, args...) do { \ +if (XLNX_BBRAM_ERR_DEBUG >= lvl) { \ +qemu_log("%s: " fmt, __func__, ## args); \ +} \ +} while (0) + +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) + +REG32(BBRAM_STATUS, 0x0) +FIELD(BBRAM_STATUS, AES_CRC_PASS, 9, 1) +FIELD(BBRAM_STATUS, AES_CRC_DONE, 8, 1) +FIELD(BBRAM_STATUS, BBRAM_ZEROIZED, 4, 1) +FIELD(BBRAM_STATUS, PGM_MODE, 0, 1) +REG32(BBRAM_CTRL, 0x4) +FIELD(BBRAM_CTRL, ZEROIZE, 0, 1) +REG32(PGM_MODE, 0x8) +REG32(BBRAM_AES_CRC, 0xc) +REG32(BBRAM_0, 0x10) +REG32(BBRAM_1, 0x14) +REG32(BBRAM_2, 0x18) +REG32(BBRAM_3, 0x1c) +REG32(BBRAM_4, 0x20) +REG32(BBRAM_5, 0x24) +REG32(BBRAM_6, 0x28) +REG32(BBRAM_7, 0x2c) +REG32(BBRAM_8, 0x30) +REG32(BBRAM_SLVERR, 0x34) +FIELD(BBRAM_SLVERR, ENABLE, 0, 1) +REG32(BBRAM_ISR, 0x38) +FIELD(BBRAM_ISR, APB_SLVERR, 0, 1) +REG32(BBRAM_IMR, 0x3c) +FIELD(BBRAM_IMR, APB_SLVERR, 0, 1) +REG32(BBRAM_IER, 0x40) +FIELD(BBRAM_IER, APB_SLVERR, 0, 1) +REG32(BBRAM_IDR, 0x44) +FIELD(BBRAM_IDR, APB_SLVERR, 0, 1) +REG32(BBRAM_MSW_LOCK, 0x4c) +FIELD(BBRAM_MSW_LOCK, VAL, 0, 1) + +#define R_MAX (R_BBRAM_MSW_LOCK + 1) + +#define RAM_MAX (A_BBRAM_8 + 4 - A_BBRAM_0) + +#define BBRAM_PGM_MAGIC 0x757bdf0d + +QEMU_BUILD_BUG_ON(R_MAX != ARRAY_SIZE(((XlnxBBRam *)0)->regs)); + +static bool bbram_msw_l
[PATCH v2 2/9] hw/nvram: Introduce Xilinx Versal eFuse device
This implements the Xilinx Versal eFuse, an one-time field-programmable non-volatile storage device. There is only one such device in the Xilinx Versal product family. The command argument: -drive if=pflash,index=N,... Can be used to optionally connect the storage array to a backend storage, such that field-programmed values in one invocation can be made available to next invocation. The backend storage must be a seekable binary file, and its size must be 3072 bytes or larger. A file with all binary 0's is a 'blank'. The drive 'index' value N has a default value of 1, but can be changed using command argument: -global xlnx,efuse.drive-index=N This device has two separate mmio interfaces, a controller and a flatten readback. The controller provides interfaces for field-programming, configuration, control, and status. The flatten readback is a cache to provide a byte-accessible read-only interface to efficiently read efuse array. Co-authored-by: Edgar E. Iglesias Co-authored-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Signed-off-by: Sai Pavan Boddu Signed-off-by: Tong Ho --- hw/nvram/Kconfig | 8 + hw/nvram/meson.build | 8 + hw/nvram/xlnx-versal-efuse-cache.c | 139 + hw/nvram/xlnx-versal-efuse-ctrl.c| 784 +++ include/hw/nvram/xlnx-versal-efuse.h | 62 +++ 5 files changed, 1001 insertions(+) create mode 100644 hw/nvram/xlnx-versal-efuse-cache.c create mode 100644 hw/nvram/xlnx-versal-efuse-ctrl.c create mode 100644 include/hw/nvram/xlnx-versal-efuse.h diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig index e872fcb194..e96749ced3 100644 --- a/hw/nvram/Kconfig +++ b/hw/nvram/Kconfig @@ -15,3 +15,11 @@ config NMC93XX_EEPROM config CHRP_NVRAM bool + +config XLNX_EFUSE +bool + +config XLNX_EFUSE_VERSAL +bool +default y if XLNX_VERSAL +select XLNX_EFUSE diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index fd2951a860..a432665158 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -9,5 +9,13 @@ softmmu_ss.add(when: 'CONFIG_AT24C', if_true: files('eeprom_at24c.c')) softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c')) softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c')) softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files( + 'xlnx-versal-efuse-cache.c', + 'xlnx-versal-efuse-ctrl.c')) +if 'CONFIG_XLNX_BBRAM' in config_all or \ + 'CONFIG_XLNX_EFUSE' in config_all + softmmu_ss.add(files('xlnx-efuse-crc.c')) +endif specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c')) diff --git a/hw/nvram/xlnx-versal-efuse-cache.c b/hw/nvram/xlnx-versal-efuse-cache.c new file mode 100644 index 00..8847efe55e --- /dev/null +++ b/hw/nvram/xlnx-versal-efuse-cache.c @@ -0,0 +1,139 @@ +/* + * QEMU model of the EFuse_Cache + * + * Copyright (c) 2017 Xilinx Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/nvram/xlnx-versal-efuse.h" + +#include "qemu/log.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" + +#ifndef XILINX_EFUSE_CACHE_ERR_DEBUG +#define XILINX_EFUSE_CACHE_ERR_DEBUG 0 +#endif + +#define XILINX_EFUSE_CACHE(obj) \ + OBJECT_CHECK(XlnxVersalEFuseCache, (obj), TYPE_XLNX_VERSAL_EFUSE_CACHE) + +#define DPRINT(...) \ +if (XILINX_EFUSE_CACHE_ERR_DEBUG) { \ +qemu_log(__VA_ARGS__); \ +} + +#define DPRINT_GE(args, ...) \ + qemu_log_mask(LOG_GUEST_ERROR, "%s: " args, __func__, ## __VA_ARGS__); + +#define MR_SIZE 0xC00 + +static uint64_t efuse_cach
[PATCH v2 8/9] hw/arm: xlnx-zynqmp: Add Xilinx eFUSE device
Connect the support for ZynqMP eFUSE one-time field-programmable bit array. Signed-off-by: Tong Ho --- hw/arm/xlnx-zynqmp.c | 29 + include/hw/arm/xlnx-zynqmp.h | 3 +++ 2 files changed, 32 insertions(+) diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 8e39b7d6c7..9e458ad1c0 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -65,6 +65,9 @@ #define BBRAM_ADDR 0xffcd #define BBRAM_IRQ 11 +#define EFUSE_ADDR 0xffcc +#define EFUSE_IRQ 87 + #define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */ static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = { @@ -241,6 +244,31 @@ static void xlnx_zynqmp_create_bbram(XlnxZynqMPState *s, qemu_irq *gic) sysbus_connect_irq(sbd, 0, gic[BBRAM_IRQ]); } +static void xlnx_zynqmp_create_efuse(XlnxZynqMPState *s, qemu_irq *gic) +{ +Object *bits = OBJECT(>efuse_bits); +Object *ctrl = OBJECT(>efuse); +SysBusDevice *sbd; + +object_initialize_child(OBJECT(s), "efuse", >efuse, +TYPE_XLNX_ZYNQMP_EFUSE); + +object_initialize_child_with_props(ctrl, "efuse-bits", bits, + sizeof(s->efuse_bits), + TYPE_XLNX_EFUSE, _abort, + "efuse-nr", "3", + "efuse-size", "2048", + NULL); + +qdev_realize(DEVICE(bits), NULL, _abort); +object_property_set_link(ctrl, "efuse", bits, _abort); + +sbd = SYS_BUS_DEVICE(ctrl); +sysbus_realize(sbd, _abort); +sysbus_mmio_map(sbd, 0, EFUSE_ADDR); +sysbus_connect_irq(sbd, 0, gic[EFUSE_IRQ]); +} + static void xlnx_zynqmp_init(Object *obj) { MachineState *ms = MACHINE(qdev_get_machine()); @@ -636,6 +664,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(>rtc), 0, gic_spi[RTC_IRQ]); xlnx_zynqmp_create_bbram(s, gic_spi); +xlnx_zynqmp_create_efuse(s, gic_spi); for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) { if (!object_property_set_uint(OBJECT(>gdma[i]), "bus-width", 128, diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index 07ebcefbab..876e8bf4e3 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -37,6 +37,7 @@ #include "net/can_emu.h" #include "hw/dma/xlnx_csu_dma.h" #include "hw/nvram/xlnx-bbram.h" +#include "hw/nvram/xlnx-zynqmp-efuse.h" #define TYPE_XLNX_ZYNQMP "xlnx-zynqmp" OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) @@ -97,6 +98,8 @@ struct XlnxZynqMPState { MemoryRegion *ddr_ram; MemoryRegion ddr_ram_low, ddr_ram_high; XlnxBBRam bbram; +XlnxZynqMPEFuse efuse; +XLNXEFuse efuse_bits; CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS]; CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS]; -- 2.25.1
[Patch v2 1/2] hw/arm/xlnx-versal: Add unimplemented APU mmio
Add unimplemented APU mmio region to xlnx-versal for booting bare-metal guests built with standalone bsp, which access the region from one of the following places: https://github.com/Xilinx/embeddedsw/blob/release-2020.2/lib/bsp/standalone/src/arm/ARMv8/64bit/armclang/boot.S#L139 https://github.com/Xilinx/embeddedsw/blob/release-2020.2/lib/bsp/standalone/src/arm/ARMv8/64bit/gcc/boot.S#L183 Acked-by: Alistair Francis Reviewed-by: Edgar E. Iglesias Signed-off-by: Tong Ho --- hw/arm/xlnx-versal.c | 2 ++ include/hw/arm/xlnx-versal.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index fb776834f7..cb6ec0a4a0 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -376,6 +376,8 @@ static void versal_unimp(Versal *s) MM_CRL, MM_CRL_SIZE); versal_unimp_area(s, "crf", >mr_ps, MM_FPD_CRF, MM_FPD_CRF_SIZE); +versal_unimp_area(s, "apu", >mr_ps, +MM_FPD_FPD_APU, MM_FPD_FPD_APU_SIZE); versal_unimp_area(s, "crp", >mr_ps, MM_PMC_CRP, MM_PMC_CRP_SIZE); versal_unimp_area(s, "iou-scntr", >mr_ps, diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 22a8fa5d11..9b79051747 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -167,6 +167,8 @@ struct Versal { #define MM_IOU_SCNTRS_SIZE 0x1 #define MM_FPD_CRF 0xfd1aU #define MM_FPD_CRF_SIZE 0x14 +#define MM_FPD_FPD_APU 0xfd5c +#define MM_FPD_FPD_APU_SIZE 0x100 #define MM_PMC_SD0 0xf104U #define MM_PMC_SD0_SIZE 0x1 -- 2.25.1
[Patch v2 0/2] hw/arm/xlnx-versal: hw/arm/xlnx-zynqmp: Add unimplemented mmio
This series adds the APU mmio region as an unimplemented device to each of two Xilinx SoC to support booting guests built with the standalone bsp published at: https://github.com/Xilinx/embeddedsw/tree/master/lib/bsp/standalone/src/arm/ARMv8/64bit --- Changelogs: v1->v2: * For xlnx-zynqmp.c: - Use assert to ensure UnimpInfo array initialization. - Use 'unsigned int' style. * Provide a more specific URL, in both patches' commit messages, to where the APU mmio region is accessed by standalone bsp bootstrap. --- Tong Ho (2): hw/arm/xlnx-versal: Add unimplemented APU mmio hw/arm/xlnx-zynqmp: Add unimplemented APU mmio hw/arm/xlnx-versal.c | 2 ++ hw/arm/xlnx-zynqmp.c | 32 include/hw/arm/xlnx-versal.h | 2 ++ include/hw/arm/xlnx-zynqmp.h | 7 +++ 4 files changed, 43 insertions(+) -- 2.25.1
[Patch v2 2/2] hw/arm/xlnx-zynqmp: Add unimplemented APU mmio
Add unimplemented APU mmio region to xlnx-zynqmp for booting bare-metal guests built with standalone bsp, which access the region from one of the following places: https://github.com/Xilinx/embeddedsw/blob/release-2020.2/lib/bsp/standalone/src/arm/ARMv8/64bit/armclang/boot.S#L139 https://github.com/Xilinx/embeddedsw/blob/release-2020.2/lib/bsp/standalone/src/arm/ARMv8/64bit/gcc/boot.S#L183 Acked-by: Alistair Francis Reviewed-by: Edgar E. Iglesias Signed-off-by: Tong Ho --- hw/arm/xlnx-zynqmp.c | 32 include/hw/arm/xlnx-zynqmp.h | 7 +++ 2 files changed, 39 insertions(+) diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 3597e8db4d..fb70204662 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -20,6 +20,7 @@ #include "qemu/module.h" #include "hw/arm/xlnx-zynqmp.h" #include "hw/intc/arm_gic_common.h" +#include "hw/misc/unimp.h" #include "hw/boards.h" #include "sysemu/kvm.h" #include "sysemu/sysemu.h" @@ -56,6 +57,9 @@ #define DPDMA_ADDR 0xfd4c #define DPDMA_IRQ 116 +#define APU_ADDR0xfd5c +#define APU_SIZE0x100 + #define IPI_ADDR0xFF30 #define IPI_IRQ 64 @@ -222,6 +226,32 @@ static void xlnx_zynqmp_create_rpu(MachineState *ms, XlnxZynqMPState *s, qdev_realize(DEVICE(>rpu_cluster), NULL, _fatal); } +static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s) +{ +static const struct UnimpInfo { +const char *name; +hwaddr base; +hwaddr size; +} unimp_areas[ARRAY_SIZE(s->mr_unimp)] = { +{ .name = "apu", APU_ADDR, APU_SIZE }, +}; +unsigned int nr; + +for (nr = 0; nr < ARRAY_SIZE(unimp_areas); nr++) { +const struct UnimpInfo *info = _areas[nr]; +DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE); +SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + +assert(info->name && info->base && info->size > 0); +qdev_prop_set_string(dev, "name", info->name); +qdev_prop_set_uint64(dev, "size", info->size); +object_property_add_child(OBJECT(s), info->name, OBJECT(dev)); + +sysbus_realize_and_unref(sbd, _fatal); +sysbus_mmio_map(sbd, 0, info->base); +} +} + static void xlnx_zynqmp_init(Object *obj) { MachineState *ms = MACHINE(qdev_get_machine()); @@ -616,6 +646,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(>rtc), 0, RTC_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(>rtc), 0, gic_spi[RTC_IRQ]); +xlnx_zynqmp_create_unimp_mmio(s); + for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) { if (!object_property_set_uint(OBJECT(>gdma[i]), "bus-width", 128, errp)) { diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index d3e2ef97f6..c84fe15996 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -79,6 +79,11 @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) #define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \ XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE) +/* + * Unimplemented mmio regions needed to boot some images. + */ +#define XLNX_ZYNQMP_NUM_UNIMP_AREAS 1 + struct XlnxZynqMPState { /*< private >*/ DeviceState parent_obj; @@ -96,6 +101,8 @@ struct XlnxZynqMPState { MemoryRegion *ddr_ram; MemoryRegion ddr_ram_low, ddr_ram_high; +MemoryRegion mr_unimp[XLNX_ZYNQMP_NUM_UNIMP_AREAS]; + CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS]; CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS]; XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN]; -- 2.25.1
[PATCH 4/9] hw/nvram: Introduce Xilinx ZynqMP eFuse device
This implements the Xilinx ZynqMP eFuse, an one-time field-programmable non-volatile storage device. There is only one such device in the Xilinx ZynqMP product family. The command argument: -drive if=pflash,index=N,... Can be used to optionally connect the storage array to a backend storage, such that field-programmed values in one invocation can be made available to next invocation. The backend storage must be a seekable binary file, and its size must be 768 bytes or larger. A file with all binary 0's is a 'blank'. The drive 'index' value N has a default value of 3, but can be changed using command argument: -global xlnx,efuse.drive-index=N Co-authored-by: Edgar E. Iglesias Co-authored-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Signed-off-by: Sai Pavan Boddu Signed-off-by: Tong Ho --- hw/nvram/Kconfig | 5 + hw/nvram/meson.build | 2 + hw/nvram/xlnx-zynqmp-efuse.c | 861 +++ include/hw/nvram/xlnx-zynqmp-efuse.h | 45 ++ 4 files changed, 913 insertions(+) create mode 100644 hw/nvram/xlnx-zynqmp-efuse.c create mode 100644 include/hw/nvram/xlnx-zynqmp-efuse.h diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig index e96749ced3..cc3ed789fe 100644 --- a/hw/nvram/Kconfig +++ b/hw/nvram/Kconfig @@ -23,3 +23,8 @@ config XLNX_EFUSE_VERSAL bool default y if XLNX_VERSAL select XLNX_EFUSE + +config XLNX_EFUSE_ZYNQMP +bool +default y if XLNX_ZYNQMP +select XLNX_EFUSE diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index a432665158..f364520ad5 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -13,6 +13,8 @@ softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files( 'xlnx-versal-efuse-cache.c', 'xlnx-versal-efuse-ctrl.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_ZYNQMP', if_true: files( + 'xlnx-zynqmp-efuse.c')) if 'CONFIG_XLNX_BBRAM' in config_all or \ 'CONFIG_XLNX_EFUSE' in config_all softmmu_ss.add(files('xlnx-efuse-crc.c')) diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c new file mode 100644 index 00..3591577498 --- /dev/null +++ b/hw/nvram/xlnx-zynqmp-efuse.c @@ -0,0 +1,861 @@ +/* + * QEMU model of the ZynqMP eFuse + * + * Copyright (c) 2015 Xilinx Inc. + * + * Written by Edgar E. Iglesias + * Partially autogenerated by xregqemu.py 2015-01-02. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/nvram/xlnx-zynqmp-efuse.h" + +#include "qemu/log.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" + +#ifndef ZYNQMP_EFUSE_ERR_DEBUG +#define ZYNQMP_EFUSE_ERR_DEBUG 0 +#endif + +#define ZYNQMP_EFUSE(obj) \ + OBJECT_CHECK(XlnxZynqMPEFuse, (obj), TYPE_XLNX_ZYNQMP_EFUSE) + +REG32(WR_LOCK, 0x0) +FIELD(WR_LOCK, LOCK, 0, 16) +REG32(CFG, 0x4) +FIELD(CFG, SLVERR_ENABLE, 5, 1) +FIELD(CFG, MARGIN_RD, 2, 2) +FIELD(CFG, PGM_EN, 1, 1) +FIELD(CFG, EFUSE_CLK_SEL, 0, 1) +REG32(STATUS, 0x8) +FIELD(STATUS, AES_CRC_PASS, 7, 1) +FIELD(STATUS, AES_CRC_DONE, 6, 1) +FIELD(STATUS, CACHE_DONE, 5, 1) +FIELD(STATUS, CACHE_LOAD, 4, 1) +FIELD(STATUS, EFUSE_3_TBIT, 2, 1) +FIELD(STATUS, EFUSE_2_TBIT, 1, 1) +FIELD(STATUS, EFUSE_0_TBIT, 0, 1) +REG32(EFUSE_PGM_ADDR, 0xc) +FIELD(EFUSE_PGM_ADDR, EFUSE, 11, 2) +FIELD(EFUSE_PGM_ADDR, ROW, 5, 6) +FIELD(EFUSE_PGM_ADDR, COLUMN, 0, 5) +REG32(EFUSE_RD_ADDR, 0x10) +FIELD(EFUSE_RD_ADDR, EFUSE, 11, 2) +FIELD(EFUSE_RD_ADDR, ROW, 5, 6) +REG32(EFUSE_RD_DATA, 0x14) +REG32(TPGM, 0x18) +FIELD(TPGM, VALUE, 0, 16) +REG32(TRD, 0x1c) +FIELD(T
[PATCH 0/9] hw/nvram: hw/arm: Introduce Xilinx eFUSE and BBRAM
This series implements the Xilinx eFUSE and BBRAM devices for the Versal and ZynqMP product families. Furthermore, both new devices are connected to the xlnx-versal-virt board and the xlnx-zcu102 board. See changes in docs/system/arm/xlnx-versal-virt.rst for detail. Tong Ho (9): docs/system/arm: xlnx-versal-virt: BBRAM and eFUSE Usage hw/nvram: Introduce Xilinx eFuse QOM hw/nvram: Introduce Xilinx Versal eFuse device hw/nvram: Introduce Xilinx ZynqMP eFuse device hw/nvram: Introduce Xilinx battery-backed ram hw/arm: xlnx-versal: Add Xilinx BBRAM device hw/arm: xlnx-versal: Add Xilinx eFUSE device hw/arm: xlnx-zynqmp: Add Xilinx BBRAM device hw/arm: xlnx-zynqmp: Add Xilinx eFUSE device docs/system/arm/xlnx-versal-virt.rst | 49 ++ hw/arm/xlnx-versal-virt.c| 57 ++ hw/arm/xlnx-versal.c | 57 ++ hw/arm/xlnx-zynqmp.c | 50 ++ hw/nvram/Kconfig | 17 + hw/nvram/meson.build | 11 + hw/nvram/xlnx-bbram.c| 536 + hw/nvram/xlnx-efuse-crc.c| 118 hw/nvram/xlnx-efuse.c| 253 hw/nvram/xlnx-versal-efuse-cache.c | 141 + hw/nvram/xlnx-versal-efuse-ctrl.c| 786 hw/nvram/xlnx-zynqmp-efuse.c | 861 +++ include/hw/arm/xlnx-versal.h | 17 + include/hw/arm/xlnx-zynqmp.h | 5 + include/hw/nvram/xlnx-bbram.h| 55 ++ include/hw/nvram/xlnx-efuse.h| 80 +++ include/hw/nvram/xlnx-versal-efuse.h | 62 ++ include/hw/nvram/xlnx-zynqmp-efuse.h | 45 ++ 18 files changed, 3200 insertions(+) create mode 100644 hw/nvram/xlnx-bbram.c create mode 100644 hw/nvram/xlnx-efuse-crc.c create mode 100644 hw/nvram/xlnx-efuse.c create mode 100644 hw/nvram/xlnx-versal-efuse-cache.c create mode 100644 hw/nvram/xlnx-versal-efuse-ctrl.c create mode 100644 hw/nvram/xlnx-zynqmp-efuse.c create mode 100644 include/hw/nvram/xlnx-bbram.h create mode 100644 include/hw/nvram/xlnx-efuse.h create mode 100644 include/hw/nvram/xlnx-versal-efuse.h create mode 100644 include/hw/nvram/xlnx-zynqmp-efuse.h -- 2.25.1
[PATCH 3/9] hw/nvram: Introduce Xilinx Versal eFuse device
This implements the Xilinx Versal eFuse, an one-time field-programmable non-volatile storage device. There is only one such device in the Xilinx Versal product family. The command argument: -drive if=pflash,index=N,... Can be used to optionally connect the storage array to a backend storage, such that field-programmed values in one invocation can be made available to next invocation. The backend storage must be a seekable binary file, and its size must be 3072 bytes or larger. A file with all binary 0's is a 'blank'. The drive 'index' value N has a default value of 1, but can be changed using command argument: -global xlnx,efuse.drive-index=N This device has two separate mmio interfaces, a controller and a flatten readback. The controller provides interfaces for field-programming, configuration, control, and status. The flatten readback is a cache to provide a byte-accessible read-only interface to efficiently read efuse array. Co-authored-by: Edgar E. Iglesias Co-authored-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Signed-off-by: Sai Pavan Boddu Signed-off-by: Tong Ho --- hw/nvram/Kconfig | 8 + hw/nvram/meson.build | 8 + hw/nvram/xlnx-versal-efuse-cache.c | 141 + hw/nvram/xlnx-versal-efuse-ctrl.c| 786 +++ include/hw/nvram/xlnx-versal-efuse.h | 62 +++ 5 files changed, 1005 insertions(+) create mode 100644 hw/nvram/xlnx-versal-efuse-cache.c create mode 100644 hw/nvram/xlnx-versal-efuse-ctrl.c create mode 100644 include/hw/nvram/xlnx-versal-efuse.h diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig index e872fcb194..e96749ced3 100644 --- a/hw/nvram/Kconfig +++ b/hw/nvram/Kconfig @@ -15,3 +15,11 @@ config NMC93XX_EEPROM config CHRP_NVRAM bool + +config XLNX_EFUSE +bool + +config XLNX_EFUSE_VERSAL +bool +default y if XLNX_VERSAL +select XLNX_EFUSE diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index fd2951a860..a432665158 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -9,5 +9,13 @@ softmmu_ss.add(when: 'CONFIG_AT24C', if_true: files('eeprom_at24c.c')) softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c')) softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c')) softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files( + 'xlnx-versal-efuse-cache.c', + 'xlnx-versal-efuse-ctrl.c')) +if 'CONFIG_XLNX_BBRAM' in config_all or \ + 'CONFIG_XLNX_EFUSE' in config_all + softmmu_ss.add(files('xlnx-efuse-crc.c')) +endif specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c')) diff --git a/hw/nvram/xlnx-versal-efuse-cache.c b/hw/nvram/xlnx-versal-efuse-cache.c new file mode 100644 index 00..8b4eca7a39 --- /dev/null +++ b/hw/nvram/xlnx-versal-efuse-cache.c @@ -0,0 +1,141 @@ +/* + * QEMU model of the EFuse_Cache + * + * Copyright (c) 2017 Xilinx Inc. + * + * Partially generated by xregqemu.py 2017-06-05. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/nvram/xlnx-versal-efuse.h" + +#include "qemu/log.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" + +#ifndef XILINX_EFUSE_CACHE_ERR_DEBUG +#define XILINX_EFUSE_CACHE_ERR_DEBUG 0 +#endif + +#define XILINX_EFUSE_CACHE(obj) \ + OBJECT_CHECK(XlnxVersalEFuseCache, (obj), TYPE_XLNX_VERSAL_EFUSE_CACHE) + +#define DPRINT(...) \ +if (XILINX_EFUSE_CACHE_ERR_DEBUG) { \ +qemu_log(__VA_ARGS__); \ +} + +#define DPRINT_GE(args, ...) \ + qemu_log_mask(LOG_GUEST_ERROR, "%s: " args, __func__, ## __VA_ARGS__); + +#de
[PATCH 5/9] hw/nvram: Introduce Xilinx battery-backed ram
This device is present in Versal and ZynqMP product families to store a 256-bit encryption key. Co-authored-by: Edgar E. Iglesias Co-authored-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Signed-off-by: Sai Pavan Boddu Signed-off-by: Tong Ho --- hw/nvram/Kconfig | 4 + hw/nvram/meson.build | 1 + hw/nvram/xlnx-bbram.c | 536 ++ include/hw/nvram/xlnx-bbram.h | 55 4 files changed, 596 insertions(+) create mode 100644 hw/nvram/xlnx-bbram.c create mode 100644 include/hw/nvram/xlnx-bbram.h diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig index cc3ed789fe..a8c5e9227e 100644 --- a/hw/nvram/Kconfig +++ b/hw/nvram/Kconfig @@ -28,3 +28,7 @@ config XLNX_EFUSE_ZYNQMP bool default y if XLNX_ZYNQMP select XLNX_EFUSE + +config XLNX_BBRAM +bool +default y if (XLNX_VERSAL || XLNX_ZYNQMP) diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index f364520ad5..0a1676d37a 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -9,6 +9,7 @@ softmmu_ss.add(when: 'CONFIG_AT24C', if_true: files('eeprom_at24c.c')) softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c')) softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c')) softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c')) +softmmu_ss.add(when: 'CONFIG_XLNX_BBRAM', if_true: files('xlnx-bbram.c', 'xlnx-efuse-crc.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files( 'xlnx-versal-efuse-cache.c', diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c new file mode 100644 index 00..d560dcdfa8 --- /dev/null +++ b/hw/nvram/xlnx-bbram.c @@ -0,0 +1,536 @@ +/* + * QEMU model of the Xilinx BBRAM Battery Backed RAM + * + * Copyright (c) 2014-2021 Xilinx Inc. + * + * Autogenerated by xregqemu.py 2020-02-06. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/nvram/xlnx-bbram.h" + +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "sysemu/blockdev.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" +#include "hw/qdev-properties-system.h" +#include "hw/nvram/xlnx-efuse.h" + +#ifndef XLNX_BBRAM_ERR_DEBUG +#define XLNX_BBRAM_ERR_DEBUG 0 +#endif + +#define XLNX_BBRAM(obj) \ + OBJECT_CHECK(XlnxBBRam, (obj), TYPE_XLNX_BBRAM) + +#define DB_PRINT_L(lvl, fmt, args...) do { \ +if (XLNX_BBRAM_ERR_DEBUG >= lvl) { \ +qemu_log("%s: " fmt, __func__, ## args); \ +} \ +} while (0) + +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) + +REG32(BBRAM_STATUS, 0x0) +FIELD(BBRAM_STATUS, AES_CRC_PASS, 9, 1) +FIELD(BBRAM_STATUS, AES_CRC_DONE, 8, 1) +FIELD(BBRAM_STATUS, BBRAM_ZEROIZED, 4, 1) +FIELD(BBRAM_STATUS, PGM_MODE, 0, 1) +REG32(BBRAM_CTRL, 0x4) +FIELD(BBRAM_CTRL, ZEROIZE, 0, 1) +REG32(PGM_MODE, 0x8) +REG32(BBRAM_AES_CRC, 0xc) +REG32(BBRAM_0, 0x10) +REG32(BBRAM_1, 0x14) +REG32(BBRAM_2, 0x18) +REG32(BBRAM_3, 0x1c) +REG32(BBRAM_4, 0x20) +REG32(BBRAM_5, 0x24) +REG32(BBRAM_6, 0x28) +REG32(BBRAM_7, 0x2c) +REG32(BBRAM_8, 0x30) +REG32(BBRAM_SLVERR, 0x34) +FIELD(BBRAM_SLVERR, ENABLE, 0, 1) +REG32(BBRAM_ISR, 0x38) +FIELD(BBRAM_ISR, APB_SLVERR, 0, 1) +REG32(BBRAM_IMR, 0x3c) +FIELD(BBRAM_IMR, APB_SLVERR, 0, 1) +REG32(BBRAM_IER, 0x40) +FIELD(BBRAM_IER, APB_SLVERR, 0, 1) +REG32(BBRAM_IDR, 0x44) +FIELD(BBRAM_IDR, APB_SLVERR, 0, 1) +REG32(BBRAM_MSW_LOCK, 0x4c) +FIELD(BBRAM_MSW_LOCK, VAL, 0, 1) + +#define R_MAX (R_BBRAM_MSW_LOCK + 1) + +#define RAM_MAX (A_BBRAM_8 + 4 - A_BBRAM_0) + +#define BBRAM_PGM_MAGIC 0x757bdf0d + +QEMU_BUILD_BUG_ON(R_MAX != ARRAY_SIZE(((Xln
[PATCH 1/9] docs/system/arm: xlnx-versal-virt: BBRAM and eFUSE Usage
Add BBRAM and eFUSE usage to the Xilinx Versal Virt board document. Signed-off-by: Tong Ho --- docs/system/arm/xlnx-versal-virt.rst | 49 1 file changed, 49 insertions(+) diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst index 27f73500d9..84afac3734 100644 --- a/docs/system/arm/xlnx-versal-virt.rst +++ b/docs/system/arm/xlnx-versal-virt.rst @@ -32,6 +32,8 @@ Implemented devices: - OCM (256KB of On Chip Memory) - XRAM (4MB of on chip Accelerator RAM) - DDR memory +- BBRAM (36 bytes of Battery-backed RAM) +- eFUSE (3072 bytes of one-time field-programmable bit array) QEMU does not yet model any other devices, including the PL and the AI Engine. @@ -175,3 +177,50 @@ Run the following at the U-Boot prompt: fdt set /chosen/dom0 reg <0x 0x4000 0x0 0x0310> booti 3000 - 2000 +BBRAM File Backend +"""""""""""""""""" +BBRAM can have an optional file backend, which must a seekable +binary file with a size of 36 bytes or larger. A file with all +binary 0s is a 'blank'. + +To add a file-backend for the BBRAM: + +.. code-block:: bash + + -drive if=pflash,index=0,file=versal-bbram.bin,format=raw + +To use a different index value, N, from default of 0, add: + +.. code-block:: bash + + -global xlnx,bbram-ctrl.drive-index=N + +eFUSE File Backend +"""""""""""""""""" +eFUSE can have an optional file backend, which must a seekable +binary file with a size of 3072 bytes or larger. A file with all +binary 0s is a 'blank'. + +To add a file-backend for the eFUSE: + +.. code-block:: bash + + -drive if=pflash,index=1,file=versal-efuse.bin,format=raw + +To use a different index value, N, from default of 1, add: + +.. code-block:: bash + + -global xlnx,efuse.drive-index=N + +.. warning:: + In actual physical Versal, BBRAM and eFUSE contain sensitive data. + The QEMU device models do **not** encrypt nor obfuscate any data + when holding them in models' memory or when writing them to their + file backends. + + Thus, a file backend should be used with caution, and 'format=luks' + is highly recommended (albeit with usage complexity). + + Better yet, do not use actual product data when running guest image + on this Xilinx Versal Virt board. | -- 2.25.1
[PATCH 9/9] hw/arm: xlnx-zynqmp: Add Xilinx eFUSE device
Connect the support for ZynqMP eFUSE one-time field-programmable bit array. Signed-off-by: Tong Ho --- hw/arm/xlnx-zynqmp.c | 29 + include/hw/arm/xlnx-zynqmp.h | 3 +++ 2 files changed, 32 insertions(+) diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 8e39b7d6c7..9e458ad1c0 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -65,6 +65,9 @@ #define BBRAM_ADDR 0xffcd #define BBRAM_IRQ 11 +#define EFUSE_ADDR 0xffcc +#define EFUSE_IRQ 87 + #define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */ static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = { @@ -241,6 +244,31 @@ static void xlnx_zynqmp_create_bbram(XlnxZynqMPState *s, qemu_irq *gic) sysbus_connect_irq(sbd, 0, gic[BBRAM_IRQ]); } +static void xlnx_zynqmp_create_efuse(XlnxZynqMPState *s, qemu_irq *gic) +{ +Object *bits = OBJECT(>efuse_bits); +Object *ctrl = OBJECT(>efuse); +SysBusDevice *sbd; + +object_initialize_child(OBJECT(s), "efuse", >efuse, +TYPE_XLNX_ZYNQMP_EFUSE); + +object_initialize_child_with_props(ctrl, "efuse-bits", bits, + sizeof(s->efuse_bits), + TYPE_XLNX_EFUSE, _abort, + "efuse-nr", "3", + "efuse-size", "2048", + NULL); + +qdev_realize(DEVICE(bits), NULL, _abort); +object_property_set_link(ctrl, "efuse", bits, _abort); + +sbd = SYS_BUS_DEVICE(ctrl); +sysbus_realize(sbd, _abort); +sysbus_mmio_map(sbd, 0, EFUSE_ADDR); +sysbus_connect_irq(sbd, 0, gic[EFUSE_IRQ]); +} + static void xlnx_zynqmp_init(Object *obj) { MachineState *ms = MACHINE(qdev_get_machine()); @@ -636,6 +664,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(>rtc), 0, gic_spi[RTC_IRQ]); xlnx_zynqmp_create_bbram(s, gic_spi); +xlnx_zynqmp_create_efuse(s, gic_spi); for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) { if (!object_property_set_uint(OBJECT(>gdma[i]), "bus-width", 128, diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index 07ebcefbab..876e8bf4e3 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -37,6 +37,7 @@ #include "net/can_emu.h" #include "hw/dma/xlnx_csu_dma.h" #include "hw/nvram/xlnx-bbram.h" +#include "hw/nvram/xlnx-zynqmp-efuse.h" #define TYPE_XLNX_ZYNQMP "xlnx-zynqmp" OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) @@ -97,6 +98,8 @@ struct XlnxZynqMPState { MemoryRegion *ddr_ram; MemoryRegion ddr_ram_low, ddr_ram_high; XlnxBBRam bbram; +XlnxZynqMPEFuse efuse; +XLNXEFuse efuse_bits; CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS]; CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS]; -- 2.25.1
[PATCH 7/9] hw/arm: xlnx-versal: Add Xilinx eFUSE device
Connect the support for Versal eFUSE one-time field-programmable bit array. Signed-off-by: Tong Ho --- hw/arm/xlnx-versal-virt.c| 36 + hw/arm/xlnx-versal.c | 39 include/hw/arm/xlnx-versal.h | 12 +++ 3 files changed, 87 insertions(+) diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index d9e2a6a853..04da6c4517 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -376,6 +376,40 @@ static void fdt_add_bbram_node(VersalVirt *s) g_free(name); } +static void fdt_add_efuse_ctrl_node(VersalVirt *s) +{ +const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CTRL; +const char interrupt_names[] = "pmc_efuse"; +char *name = g_strdup_printf("/pmc_efuse@%x", MM_PMC_EFUSE_CTRL); + +qemu_fdt_add_subnode(s->fdt, name); + +qemu_fdt_setprop_cells(s->fdt, name, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, VERSAL_EFUSE_IRQ, + GIC_FDT_IRQ_FLAGS_LEVEL_HI); +qemu_fdt_setprop(s->fdt, name, "interrupt-names", + interrupt_names, sizeof(interrupt_names)); +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, MM_PMC_EFUSE_CTRL, + 2, MM_PMC_EFUSE_CTRL_SIZE); +qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +g_free(name); +} + +static void fdt_add_efuse_cache_node(VersalVirt *s) +{ +const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CACHE; +char *name = g_strdup_printf("/xlnx_pmc_efuse_cache@%x", MM_PMC_EFUSE_CACHE); + +qemu_fdt_add_subnode(s->fdt, name); + +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, MM_PMC_EFUSE_CACHE, + 2, MM_PMC_EFUSE_CACHE_SIZE); +qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +g_free(name); +} + static void fdt_nop_memory_nodes(void *fdt, Error **errp) { Error *err = NULL; @@ -591,6 +625,8 @@ static void versal_virt_init(MachineState *machine) fdt_add_sd_nodes(s); fdt_add_rtc_node(s); fdt_add_bbram_node(s); +fdt_add_efuse_ctrl_node(s); +fdt_add_efuse_cache_node(s); fdt_add_cpu_nodes(s, psci_conduit); fdt_add_clk_node(s, "/clk125", 12500, s->phandle.clk_125Mhz); fdt_add_clk_node(s, "/clk25", 2500, s->phandle.clk_25Mhz); diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 46d7f42a6b..d278d6e0f4 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -329,6 +329,44 @@ static void versal_create_bbram(Versal *s, qemu_irq *pic) sysbus_connect_irq(sbd, 0, pic[VERSAL_BBRAM_APB_IRQ_0]); } +static void versal_realize_efuse_part(Versal *s, Object *dev, hwaddr base) +{ +SysBusDevice *part = SYS_BUS_DEVICE(dev); + +object_property_set_link(OBJECT(part), "efuse", + OBJECT(>pmc.efuse.bits), _abort); + +sysbus_realize(part, _abort); +memory_region_add_subregion(>mr_ps, base, +sysbus_mmio_get_region(part, 0)); +} + +static void versal_create_efuse(Versal *s, qemu_irq *pic) +{ +Object *bits = OBJECT(>pmc.efuse.bits); +Object *ctrl = OBJECT(>pmc.efuse.ctrl); +Object *cache = OBJECT(>pmc.efuse.cache); + +object_initialize_child(OBJECT(s), "efuse-ctrl", >pmc.efuse.ctrl, +TYPE_XLNX_VERSAL_EFUSE_CTRL); + +object_initialize_child(OBJECT(s), "efuse-cache", >pmc.efuse.cache, +TYPE_XLNX_VERSAL_EFUSE_CACHE); + +object_initialize_child_with_props(ctrl, "efuse-bits", bits, + sizeof(s->pmc.efuse.bits), + TYPE_XLNX_EFUSE, _abort, + "efuse-nr", "3", + "efuse-size", "8192", + NULL); + +qdev_realize(DEVICE(bits), NULL, _abort); +versal_realize_efuse_part(s, ctrl, MM_PMC_EFUSE_CTRL); +versal_realize_efuse_part(s, cache, MM_PMC_EFUSE_CACHE); + +sysbus_connect_irq(SYS_BUS_DEVICE(ctrl), 0, pic[VERSAL_EFUSE_IRQ]); +} + /* This takes the board allocated linear DDR memory and creates aliases * for each split DDR range/aperture on the Versal address map. */ @@ -416,6 +454,7 @@ static void versal_realize(DeviceState *dev, Error **errp) versal_create_rtc(s, pic); versal_create_xrams(s, pic); versal_create_bbram(s, pic); +versal_create_efuse(s, pic); versal_map_ddr(s); versal_unimp(s); diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 7719e8c4d2..33b89f00b6 100644 --- a/include/hw/arm/xlnx-
[PATCH 2/9] hw/nvram: Introduce Xilinx eFuse QOM
This introduces the QOM for Xilinx eFuse, an one-time field-programmable storage bit array. The actual mmio interface to the array varies by device families and will be provided in different change-sets. Co-authored-by: Edgar E. Iglesias Co-authored-by: Sai Pavan Boddu Signed-off-by: Edgar E. Iglesias Signed-off-by: Sai Pavan Boddu Signed-off-by: Tong Ho --- hw/nvram/xlnx-efuse-crc.c | 118 hw/nvram/xlnx-efuse.c | 253 ++ include/hw/nvram/xlnx-efuse.h | 80 +++ 3 files changed, 451 insertions(+) create mode 100644 hw/nvram/xlnx-efuse-crc.c create mode 100644 hw/nvram/xlnx-efuse.c create mode 100644 include/hw/nvram/xlnx-efuse.h diff --git a/hw/nvram/xlnx-efuse-crc.c b/hw/nvram/xlnx-efuse-crc.c new file mode 100644 index 00..bc12c39e00 --- /dev/null +++ b/hw/nvram/xlnx-efuse-crc.c @@ -0,0 +1,118 @@ +/* + * Xilinx eFuse/bbram CRC calculator + * + * Copyright (c) 2021 Xilinx Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "hw/nvram/xlnx-efuse.h" + +static uint32_t xlnx_efuse_u37_crc(uint32_t prev_crc, uint32_t data, + uint32_t addr) +{ +/* A table for 7-bit slicing */ +static const uint32_t crc_tab[128] = { +0x, 0xe13b70f7, 0xc79a971f, 0x26a1e7e8, +0x8ad958cf, 0x6be22838, 0x4d43cfd0, 0xac78bf27, +0x105ec76f, 0xf165b798, 0xd7c45070, 0x36ff2087, +0x9a879fa0, 0x7bbcef57, 0x5d1d08bf, 0xbc267848, +0x20bd8ede, 0xc186fe29, 0xe72719c1, 0x061c6936, +0xaa64d611, 0x4b5fa6e6, 0x6dfe410e, 0x8cc531f9, +0x30e349b1, 0xd1d83946, 0xf779deae, 0x1642ae59, +0xba3a117e, 0x5b016189, 0x7da08661, 0x9c9bf696, +0x417b1dbc, 0xa0406d4b, 0x86e18aa3, 0x67dafa54, +0xcba24573, 0x2a993584, 0x0c38d26c, 0xed03a29b, +0x5125dad3, 0xb01eaa24, 0x96bf4dcc, 0x77843d3b, +0xdbfc821c, 0x3ac7f2eb, 0x1c661503, 0xfd5d65f4, +0x61c69362, 0x80fde395, 0xa65c047d, 0x4767748a, +0xeb1fcbad, 0x0a24bb5a, 0x2c855cb2, 0xcdbe2c45, +0x7198540d, 0x90a324fa, 0xb602c312, 0x5739b3e5, +0xfb410cc2, 0x1a7a7c35, 0x3cdb9bdd, 0xdde0eb2a, +0x82f63b78, 0x63cd4b8f, 0x456cac67, 0xa457dc90, +0x082f63b7, 0xe9141340, 0xcfb5f4a8, 0x2e8e845f, +0x92a8fc17, 0x73938ce0, 0x55326b08, 0xb4091bff, +0x1871a4d8, 0xf94ad42f, 0xdfeb33c7, 0x3ed04330, +0xa24bb5a6, 0x4370c551, 0x65d122b9, 0x84ea524e, +0x2892ed69, 0xc9a99d9e, 0xef087a76, 0x0e330a81, +0xb21572c9, 0x532e023e, 0x758fe5d6, 0x94b49521, +0x38cc2a06, 0xd9f75af1, 0xff56bd19, 0x1e6dcdee, +0xc38d26c4, 0x22b65633, 0x0417b1db, 0xe52cc12c, +0x49547e0b, 0xa86f0efc, 0x8ecee914, 0x6ff599e3, +0xd3d3e1ab, 0x32e8915c, 0x144976b4, 0xf5720643, +0x590ab964, 0xb831c993, 0x9e902e7b, 0x7fab5e8c, +0xe330a81a, 0x020bd8ed, 0x24aa3f05, 0xc5914ff2, +0x69e9f0d5, 0x88d28022, 0xae7367ca, 0x4f48173d, +0xf36e6f75, 0x12551f82, 0x34f4f86a, 0xd5cf889d, +0x79b737ba, 0x988c474d, 0xbe2da0a5, 0x5f16d052 +}; + +/* + * eFuse calculation is shown here: + * https://github.com/Xilinx/embeddedsw/blob/release-2019.2/lib/sw_services/xilskey/src/xilskey_utils.c#L1496 + * + * Each u32 word is appended a 5-bit value, for a total of 37 bits; see: + * https://github.com/Xilinx/embeddedsw/blob/release-2019.2/lib/sw_services/xilskey/src/xilskey_utils.c#L1356 + */ +uint32_t crc = prev_crc; +const unsigned rshf = 7; +const uint32_t im = (1 << rshf) - 1; +const uint32_t rm = (1 << (32 - rshf)) - 1; +const uint32_t i2 = (1 << 2) - 1; +const uint32_t r2 = (1 << 30) - 1; + +unsigned j; +uint32_t i, r; +uint64_t w; + +w = (uint64_t)(addr) << 32; +w |= data; + +/* Feed 35 bits, in 5 rounds, each a slice of 7 bits */ +
[PATCH 6/9] hw/arm: xlnx-versal: Add Xilinx BBRAM device
Connect the support for Versal Battery-Backed RAM (BBRAM) Signed-off-by: Tong Ho --- hw/arm/xlnx-versal-virt.c| 21 + hw/arm/xlnx-versal.c | 18 ++ include/hw/arm/xlnx-versal.h | 5 + 3 files changed, 44 insertions(+) diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 5bca360dce..d9e2a6a853 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -356,6 +356,26 @@ static void fdt_add_rtc_node(VersalVirt *s) g_free(name); } +static void fdt_add_bbram_node(VersalVirt *s) +{ +const char compat[] = TYPE_XLNX_BBRAM; +const char interrupt_names[] = "bbram-error"; +char *name = g_strdup_printf("/bbram@%x", MM_PMC_BBRAM_CTRL); + +qemu_fdt_add_subnode(s->fdt, name); + +qemu_fdt_setprop_cells(s->fdt, name, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, VERSAL_BBRAM_APB_IRQ_0, + GIC_FDT_IRQ_FLAGS_LEVEL_HI); +qemu_fdt_setprop(s->fdt, name, "interrupt-names", + interrupt_names, sizeof(interrupt_names)); +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, MM_PMC_BBRAM_CTRL, + 2, MM_PMC_BBRAM_CTRL_SIZE); +qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +g_free(name); +} + static void fdt_nop_memory_nodes(void *fdt, Error **errp) { Error *err = NULL; @@ -570,6 +590,7 @@ static void versal_virt_init(MachineState *machine) fdt_add_usb_xhci_nodes(s); fdt_add_sd_nodes(s); fdt_add_rtc_node(s); +fdt_add_bbram_node(s); fdt_add_cpu_nodes(s, psci_conduit); fdt_add_clk_node(s, "/clk125", 12500, s->phandle.clk_125Mhz); fdt_add_clk_node(s, "/clk25", 2500, s->phandle.clk_25Mhz); diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index fb776834f7..46d7f42a6b 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -312,6 +312,23 @@ static void versal_create_xrams(Versal *s, qemu_irq *pic) } } +static void versal_create_bbram(Versal *s, qemu_irq *pic) +{ +SysBusDevice *sbd; + +object_initialize_child_with_props(OBJECT(s), "bbram", >pmc.bbram, + sizeof(s->pmc.bbram), TYPE_XLNX_BBRAM, + _fatal, + "crc-zpads", "0", + NULL); +sbd = SYS_BUS_DEVICE(>pmc.bbram); + +sysbus_realize(sbd, _fatal); +memory_region_add_subregion(>mr_ps, MM_PMC_BBRAM_CTRL, +sysbus_mmio_get_region(sbd, 0)); +sysbus_connect_irq(sbd, 0, pic[VERSAL_BBRAM_APB_IRQ_0]); +} + /* This takes the board allocated linear DDR memory and creates aliases * for each split DDR range/aperture on the Versal address map. */ @@ -398,6 +415,7 @@ static void versal_realize(DeviceState *dev, Error **errp) versal_create_sds(s, pic); versal_create_rtc(s, pic); versal_create_xrams(s, pic); +versal_create_bbram(s, pic); versal_map_ddr(s); versal_unimp(s); diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 22a8fa5d11..7719e8c4d2 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -24,6 +24,7 @@ #include "qom/object.h" #include "hw/usb/xlnx-usb-subsystem.h" #include "hw/misc/xlnx-versal-xramc.h" +#include "hw/nvram/xlnx-bbram.h" #define TYPE_XLNX_VERSAL "xlnx-versal" OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL) @@ -79,6 +80,7 @@ struct Versal { } iou; XlnxZynqMPRTC rtc; +XlnxBBRam bbram; } pmc; struct { @@ -105,6 +107,7 @@ struct Versal { #define VERSAL_GEM1_WAKE_IRQ_0 59 #define VERSAL_ADMA_IRQ_0 60 #define VERSAL_XRAM_IRQ_0 79 +#define VERSAL_BBRAM_APB_IRQ_0 121 #define VERSAL_RTC_APB_ERR_IRQ 121 #define VERSAL_SD0_IRQ_0 126 #define VERSAL_RTC_ALARM_IRQ 142 @@ -170,6 +173,8 @@ struct Versal { #define MM_PMC_SD0 0xf104U #define MM_PMC_SD0_SIZE 0x1 +#define MM_PMC_BBRAM_CTRL 0xf11f +#define MM_PMC_BBRAM_CTRL_SIZE 0x00050 #define MM_PMC_CRP 0xf126U #define MM_PMC_CRP_SIZE 0x1 #define MM_PMC_RTC 0xf12a -- 2.25.1
[PATCH 8/9] hw/arm: xlnx-zynqmp: Add Xilinx BBRAM device
Connect the support for Xilinx ZynqMP Battery-Backed RAM (BBRAM) Signed-off-by: Tong Ho --- hw/arm/xlnx-zynqmp.c | 21 + include/hw/arm/xlnx-zynqmp.h | 2 ++ 2 files changed, 23 insertions(+) diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 3597e8db4d..8e39b7d6c7 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -62,6 +62,9 @@ #define RTC_ADDR0xffa6 #define RTC_IRQ 26 +#define BBRAM_ADDR 0xffcd +#define BBRAM_IRQ 11 + #define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */ static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = { @@ -222,6 +225,22 @@ static void xlnx_zynqmp_create_rpu(MachineState *ms, XlnxZynqMPState *s, qdev_realize(DEVICE(>rpu_cluster), NULL, _fatal); } +static void xlnx_zynqmp_create_bbram(XlnxZynqMPState *s, qemu_irq *gic) +{ +SysBusDevice *sbd; + +object_initialize_child_with_props(OBJECT(s), "bbram", >bbram, + sizeof(s->bbram), TYPE_XLNX_BBRAM, + _fatal, + "crc-zpads", "1", + NULL); +sbd = SYS_BUS_DEVICE(>bbram); + +sysbus_realize(sbd, _fatal); +sysbus_mmio_map(sbd, 0, BBRAM_ADDR); +sysbus_connect_irq(sbd, 0, gic[BBRAM_IRQ]); +} + static void xlnx_zynqmp_init(Object *obj) { MachineState *ms = MACHINE(qdev_get_machine()); @@ -616,6 +635,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(>rtc), 0, RTC_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(>rtc), 0, gic_spi[RTC_IRQ]); +xlnx_zynqmp_create_bbram(s, gic_spi); + for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) { if (!object_property_set_uint(OBJECT(>gdma[i]), "bus-width", 128, errp)) { diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index d3e2ef97f6..07ebcefbab 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -36,6 +36,7 @@ #include "qom/object.h" #include "net/can_emu.h" #include "hw/dma/xlnx_csu_dma.h" +#include "hw/nvram/xlnx-bbram.h" #define TYPE_XLNX_ZYNQMP "xlnx-zynqmp" OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) @@ -95,6 +96,7 @@ struct XlnxZynqMPState { MemoryRegion *ddr_ram; MemoryRegion ddr_ram_low, ddr_ram_high; +XlnxBBRam bbram; CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS]; CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS]; -- 2.25.1
[Patch 2/2] hw/arm/xlnx-zynqmp: Add unimplemented APU mmio
Add unimplemented APU mmio region to xlnx-zynqmp for booting bare-metal guests built with standalone bsp published at: https://github.com/Xilinx/embeddedsw/tree/master/lib/bsp/standalone/src/arm/ARMv8/64bit Signed-off-by: Tong Ho --- hw/arm/xlnx-zynqmp.c | 32 include/hw/arm/xlnx-zynqmp.h | 7 +++ 2 files changed, 39 insertions(+) diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 3597e8db4d..790df2b6f1 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -20,6 +20,7 @@ #include "qemu/module.h" #include "hw/arm/xlnx-zynqmp.h" #include "hw/intc/arm_gic_common.h" +#include "hw/misc/unimp.h" #include "hw/boards.h" #include "sysemu/kvm.h" #include "sysemu/sysemu.h" @@ -56,6 +57,9 @@ #define DPDMA_ADDR 0xfd4c #define DPDMA_IRQ 116 +#define APU_ADDR0xfd5c +#define APU_SIZE0x100 + #define IPI_ADDR0xFF30 #define IPI_IRQ 64 @@ -222,6 +226,32 @@ static void xlnx_zynqmp_create_rpu(MachineState *ms, XlnxZynqMPState *s, qdev_realize(DEVICE(>rpu_cluster), NULL, _fatal); } +static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s) +{ +static const struct UnimpInfo { +const char *name; +hwaddr base; +hwaddr size; +} unimp_areas[ARRAY_SIZE(s->mr_unimp)] = { +{ .name = "apu", APU_ADDR, APU_SIZE }, +}; + +unsigned nr; + +for (nr = 0; nr < ARRAY_SIZE(unimp_areas); nr++) { +const struct UnimpInfo *info = _areas[nr]; +DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE); +SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + +qdev_prop_set_string(dev, "name", info->name); +qdev_prop_set_uint64(dev, "size", info->size); +object_property_add_child(OBJECT(s), info->name, OBJECT(dev)); + +sysbus_realize_and_unref(sbd, _fatal); +sysbus_mmio_map(sbd, 0, info->base); +} +} + static void xlnx_zynqmp_init(Object *obj) { MachineState *ms = MACHINE(qdev_get_machine()); @@ -616,6 +646,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(>rtc), 0, RTC_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(>rtc), 0, gic_spi[RTC_IRQ]); +xlnx_zynqmp_create_unimp_mmio(s); + for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) { if (!object_property_set_uint(OBJECT(>gdma[i]), "bus-width", 128, errp)) { diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index d3e2ef97f6..c84fe15996 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -79,6 +79,11 @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) #define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \ XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE) +/* + * Unimplemented mmio regions needed to boot some images. + */ +#define XLNX_ZYNQMP_NUM_UNIMP_AREAS 1 + struct XlnxZynqMPState { /*< private >*/ DeviceState parent_obj; @@ -96,6 +101,8 @@ struct XlnxZynqMPState { MemoryRegion *ddr_ram; MemoryRegion ddr_ram_low, ddr_ram_high; +MemoryRegion mr_unimp[XLNX_ZYNQMP_NUM_UNIMP_AREAS]; + CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS]; CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS]; XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN]; -- 2.25.1
[Patch 1/2] hw/arm/xlnx-versal: Add unimplemented APU mmio
Add unimplemented APU mmio region to xlnx-versal for booting bare-metal guests built with standalone bsp published at: https://github.com/Xilinx/embeddedsw/tree/master/lib/bsp/standalone/src/arm/ARMv8/64bit Signed-off-by: Tong Ho --- hw/arm/xlnx-versal.c | 2 ++ include/hw/arm/xlnx-versal.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index fb776834f7..cb6ec0a4a0 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -376,6 +376,8 @@ static void versal_unimp(Versal *s) MM_CRL, MM_CRL_SIZE); versal_unimp_area(s, "crf", >mr_ps, MM_FPD_CRF, MM_FPD_CRF_SIZE); +versal_unimp_area(s, "apu", >mr_ps, +MM_FPD_FPD_APU, MM_FPD_FPD_APU_SIZE); versal_unimp_area(s, "crp", >mr_ps, MM_PMC_CRP, MM_PMC_CRP_SIZE); versal_unimp_area(s, "iou-scntr", >mr_ps, diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 22a8fa5d11..9b79051747 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -167,6 +167,8 @@ struct Versal { #define MM_IOU_SCNTRS_SIZE 0x1 #define MM_FPD_CRF 0xfd1aU #define MM_FPD_CRF_SIZE 0x14 +#define MM_FPD_FPD_APU 0xfd5c +#define MM_FPD_FPD_APU_SIZE 0x100 #define MM_PMC_SD0 0xf104U #define MM_PMC_SD0_SIZE 0x1 -- 2.25.1
[Patch 0/2] hw/arm/xlnx-versal: hw/arm/xlnx-zynqmp: Add unimplemented mmio
This series adds the APU mmio region as an unimplemented device to each of two Xilinx SoC to support booting guests built with the standalone bsp published at: https://github.com/Xilinx/embeddedsw/tree/master/lib/bsp/standalone/src/arm/ARMv8/64bit Tong Ho (2): hw/arm/xlnx-versal: Add unimplemented APU mmio hw/arm/xlnx-zynqmp: Add unimplemented APU mmio hw/arm/xlnx-versal.c | 2 ++ hw/arm/xlnx-zynqmp.c | 32 include/hw/arm/xlnx-versal.h | 2 ++ include/hw/arm/xlnx-zynqmp.h | 7 +++ 4 files changed, 43 insertions(+) -- 2.25.1
[PATCH] crypto: fix getter of a QCryptoSecret's property
This fixes the condition-check done by the "loaded" property getter, such that the property returns true even when the secret is loaded by the 'file' option. Signed-off-by: Tong Ho --- Pre-existing getter returns true only when the secret is loaded by the 'data' option. crypto/secret.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crypto/secret.c b/crypto/secret.c index 1cf0ad0..5fb6bbe 100644 --- a/crypto/secret.c +++ b/crypto/secret.c @@ -221,6 +221,7 @@ qcrypto_secret_prop_set_loaded(Object *obj, secret->rawlen = inputlen; } else { g_free(secret->rawdata); +secret->rawdata = NULL; secret->rawlen = 0; } } @@ -231,7 +232,7 @@ qcrypto_secret_prop_get_loaded(Object *obj, Error **errp G_GNUC_UNUSED) { QCryptoSecret *secret = QCRYPTO_SECRET(obj); -return secret->data != NULL; +return secret->rawdata != NULL; } -- 2.7.4