From: Emmanuel Blot <[email protected]>

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 <[email protected]>
Signed-off-by: Loïc Lefort <[email protected]>
---
 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


Reply via email to