From: Emmanuel Blot <eblot@rivosinc.com>
also adds property no_epmp_cfg on EarlGrey machine to disable
default ePMP configuration.
Usage:
qemu-system-riscv32 -M ot-earlgrey,no-epmp-cfg=true [...]
Signed-off-by: Emmanuel Blot <eblot@rivosinc.com>
Signed-off-by: Loïc Lefort <loic@rivosinc.com>
---
hw/riscv/ot_earlgrey.c | 116 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 114 insertions(+), 2 deletions(-)
diff --git a/hw/riscv/ot_earlgrey.c b/hw/riscv/ot_earlgrey.c
index 760a8d2c2e..77fb1b207c 100644
--- a/hw/riscv/ot_earlgrey.c
+++ b/hw/riscv/ot_earlgrey.c
@@ -18,6 +18,7 @@
#include "qemu/cutils.h"
#include "qemu/units.h"
#include "qapi/error.h"
+#include "qobject/qlist.h"
#include "cpu.h"
#include "system/address-spaces.h"
#include "hw/core/boards.h"
@@ -28,6 +29,13 @@
#include "hw/riscv/ot_earlgrey.h"
#include "system/system.h"
+/* ------------------------------------------------------------------------ */
+/* Forward Declarations */
+/* ------------------------------------------------------------------------ */
+
+static void ot_earlgrey_soc_hart_configure(
+ DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent);
+
/* ------------------------------------------------------------------------ */
/* Constants */
/* ------------------------------------------------------------------------ */
@@ -116,6 +124,7 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = {
/* clang-format off */
[OT_EARLGREY_SOC_DEV_HART] = {
.type = TYPE_RISCV_CPU_LOWRISC_OPENTITAN,
+ .cfg = &ot_earlgrey_soc_hart_configure,
.prop = IBEXDEVICEPROPDEFS(
IBEX_DEV_BOOL_PROP("zba", true),
IBEX_DEV_BOOL_PROP("zbb", true),
@@ -529,6 +538,60 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = {
/* clang-format on */
};
+#define PMP_CFG(_l_, _a_, _x_, _w_, _r_) \
+ ((uint8_t)(((_l_) << 7u) | ((_a_) << 3u) | ((_x_) << 2u) | ((_w_) << 1u) | \
+ ((_r_))))
+#define PMP_ADDR(_a_) ((_a_) >> 2u)
+
+#define MSECCFG(_rlb_, _mmwp_, _mml_) \
+ (((_rlb_) << 2u) | ((_mmwp_) << 1u) | ((_mml_)))
+
+enum { PMP_MODE_OFF, PMP_MODE_TOR, PMP_MODE_NA4, PMP_MODE_NAPOT };
+
+static const uint8_t ot_earlgrey_pmp_cfgs[] = {
+ /* clang-format off */
+ PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0),
+ PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0),
+ PMP_CFG(1, PMP_MODE_NAPOT, 1, 0, 1), /* rgn 2 [ROM: LRX] */
+ PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0),
+ PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0),
+ PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0),
+ PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0),
+ PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0),
+ PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0),
+ PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0),
+ PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0),
+ PMP_CFG(1, PMP_MODE_TOR, 0, 1, 1), /* rgn 11 [MMIO: LRW] */
+ PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0),
+ PMP_CFG(1, PMP_MODE_NAPOT, 1, 1, 1), /* rgn 13 [DV_ROM: LRWX] */
+ PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0),
+ PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0)
+ /* clang-format on */
+};
+
+static const uint32_t ot_earlgrey_pmp_addrs[] = {
+ /* clang-format off */
+ PMP_ADDR(0x00000000),
+ PMP_ADDR(0x00000000),
+ PMP_ADDR(0x000083fc), /* rgn 2 [ROM: base=0x0000_8000 size (2KiB)] */
+ PMP_ADDR(0x00000000),
+ PMP_ADDR(0x00000000),
+ PMP_ADDR(0x00000000),
+ PMP_ADDR(0x00000000),
+ PMP_ADDR(0x00000000),
+ PMP_ADDR(0x00000000),
+ PMP_ADDR(0x00000000),
+ PMP_ADDR(0x40000000), /* rgn 10 [MMIO: lo=0x4000_0000] */
+ PMP_ADDR(0x42010000), /* rgn 11 [MMIO: hi=0x4201_0000] */
+ PMP_ADDR(0x00000000),
+ PMP_ADDR(0x000107fc), /* rgn 13 [DV_ROM: base=0x0001_0000 size (4KiB)] */
+ PMP_ADDR(0x00000000),
+ PMP_ADDR(0x00000000)
+ /* clang-format on */
+};
+
+#define OT_EARLGREY_MSECCFG MSECCFG(1, 1, 0)
+
enum OtEarlgreyBoardDevice {
OT_EARLGREY_BOARD_DEV_SOC,
_OT_EARLGREY_BOARD_DEV_COUNT,
@@ -553,8 +616,38 @@ struct OtEarlGreyBoardState {
struct OtEarlGreyMachineState {
MachineState parent_obj;
+
+ bool no_epmp_cfg;
};
+/* ------------------------------------------------------------------------ */
+/* Device Configuration */
+/* ------------------------------------------------------------------------ */
+
+static void ot_earlgrey_soc_hart_configure(
+ DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent)
+{
+ OtEarlGreyMachineState *ms = RISCV_OT_EARLGREY_MACHINE(qdev_get_machine());
+ if (ms->no_epmp_cfg) {
+ /* skip default PMP config */
+ return;
+ }
+
+ QList *pmp_cfgs = qlist_new();
+ QList *pmp_addrs = qlist_new();
+
+ for (unsigned ix = 0; ix < ARRAY_SIZE(ot_earlgrey_pmp_cfgs); ix++) {
+ qlist_append_int(pmp_cfgs, (uint64_t)ot_earlgrey_pmp_cfgs[ix]);
+ }
+ for (unsigned ix = 0; ix < ARRAY_SIZE(ot_earlgrey_pmp_addrs); ix++) {
+ qlist_append_int(pmp_addrs, (uint64_t)ot_earlgrey_pmp_addrs[ix]);
+ }
+
+ qdev_prop_set_array(dev, "pmp_cfg", pmp_cfgs);
+ qdev_prop_set_array(dev, "pmp_addr", pmp_addrs);
+ qdev_prop_set_uint64(dev, "mseccfg", (uint64_t)OT_EARLGREY_MSECCFG);
+}
+
/* ------------------------------------------------------------------------ */
/* SoC */
/* ------------------------------------------------------------------------ */
@@ -688,12 +781,31 @@ type_init(ot_earlgrey_board_register_types);
/* Machine */
/* ------------------------------------------------------------------------ */
+static bool ot_earlgrey_machine_get_no_epmp_cfg(Object *obj, Error **errp)
+{
+ OtEarlGreyMachineState *s = RISCV_OT_EARLGREY_MACHINE(obj);
+
+ return s->no_epmp_cfg;
+}
+
+static void
+ot_earlgrey_machine_set_no_epmp_cfg(Object *obj, bool value, Error **errp)
+{
+ OtEarlGreyMachineState *s = RISCV_OT_EARLGREY_MACHINE(obj);
+
+ s->no_epmp_cfg = value;
+}
+
static void ot_earlgrey_machine_instance_init(Object *obj)
{
OtEarlGreyMachineState *s = RISCV_OT_EARLGREY_MACHINE(obj);
- /* nothing here */
- (void)s;
+ s->no_epmp_cfg = false;
+ object_property_add_bool(obj, "no-epmp-cfg",
+ &ot_earlgrey_machine_get_no_epmp_cfg,
+ &ot_earlgrey_machine_set_no_epmp_cfg);
+ object_property_set_description(obj, "no-epmp-cfg",
+ "Skip default ePMP configuration");
}
static void ot_earlgrey_machine_init(MachineState *state)
--
2.49.1