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
