[PATCH] qemu/bitops.h: Locate changed bits

2024-05-28 Thread Tong Ho
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

2024-02-26 Thread Tong Ho
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

2024-02-06 Thread Tong Ho
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

2023-10-31 Thread Tong Ho
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

2023-10-31 Thread Tong Ho
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

2023-10-31 Thread Tong Ho
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

2023-10-31 Thread Tong Ho
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

2023-10-17 Thread Tong Ho
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

2023-10-17 Thread Tong Ho
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

2023-10-17 Thread Tong Ho
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

2023-10-17 Thread Tong Ho
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

2023-10-04 Thread Tong Ho
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

2023-10-04 Thread Tong Ho
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

2023-10-04 Thread Tong Ho
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

2023-10-04 Thread Tong Ho
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

2023-10-03 Thread Tong Ho
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

2023-10-03 Thread Tong Ho
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

2023-10-02 Thread Tong Ho
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

2023-10-02 Thread Tong Ho
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

2023-09-22 Thread Tong Ho
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

2023-09-22 Thread Tong Ho
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

2023-09-22 Thread Tong Ho
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

2023-09-22 Thread Tong Ho
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

2023-08-31 Thread Tong Ho
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

2023-08-31 Thread Tong Ho
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

2023-08-31 Thread Tong Ho
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

2023-08-31 Thread Tong Ho
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

2023-04-26 Thread Tong Ho
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 *

2022-04-01 Thread Tong Ho
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

2022-04-01 Thread Tong Ho
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

2021-10-15 Thread Tong Ho
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

2021-10-15 Thread Tong Ho
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

2021-10-15 Thread Tong Ho
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

2021-10-15 Thread Tong Ho
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

2021-10-04 Thread Tong Ho
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

2021-09-16 Thread Tong Ho
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

2021-09-16 Thread Tong Ho
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

2021-09-16 Thread Tong Ho
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

2021-09-16 Thread Tong Ho
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

2021-09-16 Thread Tong Ho
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

2021-09-16 Thread Tong Ho
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

2021-09-16 Thread Tong Ho
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

2021-09-16 Thread Tong Ho
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

2021-09-16 Thread Tong Ho
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

2021-09-16 Thread Tong Ho
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

2021-08-23 Thread Tong Ho
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

2021-08-23 Thread Tong Ho
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

2021-08-23 Thread Tong Ho
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

2021-08-23 Thread Tong Ho
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

2021-08-23 Thread Tong Ho
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

2021-08-23 Thread Tong Ho
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

2021-08-23 Thread Tong Ho
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

2021-08-23 Thread Tong Ho
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

2021-08-23 Thread Tong Ho
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

2021-08-23 Thread Tong Ho
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

2021-08-23 Thread Tong Ho
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

2021-08-23 Thread Tong Ho
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

2021-08-23 Thread Tong Ho
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

2021-08-18 Thread Tong Ho
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

2021-08-18 Thread Tong Ho
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

2021-08-18 Thread Tong Ho
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

2021-08-18 Thread Tong Ho
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

2021-08-18 Thread Tong Ho
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

2021-08-18 Thread Tong Ho
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

2021-08-18 Thread Tong Ho
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

2021-08-18 Thread Tong Ho
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

2021-08-18 Thread Tong Ho
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

2021-08-18 Thread Tong Ho
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

2021-08-18 Thread Tong Ho
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

2021-08-18 Thread Tong Ho
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

2021-08-18 Thread Tong Ho
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

2020-01-09 Thread Tong Ho
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