[sw] proof of concept of address translation idea
- Move all linked flash code to a virtual address that does not exist
- Translate back to physical address in boot_rom for both ibus and dbus
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/meson.build b/meson.build
index 10c966c..eee3ef0 100644
--- a/meson.build
+++ b/meson.build
@@ -230,6 +230,7 @@
hw_ip_usbdev_reg_h = gen_hw_hdr.process('hw/ip/usbdev/data/usbdev.hjson')
hw_ip_pwrmgr_reg_h = gen_hw_hdr.process('hw/' + TOPNAME + '/ip/pwrmgr/data/autogen/pwrmgr.hjson')
hw_ip_rstmgr_reg_h = gen_hw_hdr.process('hw/' + TOPNAME + '/ip/rstmgr/data/autogen/rstmgr.hjson')
+hw_ip_ibex_reg_h = gen_hw_hdr.process('hw//ip/rv_core_ibex_peri/data/rv_core_ibex_peri.hjson')
hw_top_earlgrey_pinmux_reg_h = gen_hw_hdr.process('hw/' + TOPNAME + '/ip/pinmux/data/autogen/pinmux.hjson')
hw_top_earlgrey_rv_plic_reg_h = gen_hw_hdr.process('hw/' + TOPNAME + '/ip/rv_plic/data/autogen/rv_plic.hjson')
diff --git a/sw/device/boot_rom/boot_rom.c b/sw/device/boot_rom/boot_rom.c
index c4f4eea..53d4eb6 100644
--- a/sw/device/boot_rom/boot_rom.c
+++ b/sw/device/boot_rom/boot_rom.c
@@ -9,6 +9,7 @@
#include "sw/device/lib/dif/dif_gpio.h"
#include "sw/device/lib/dif/dif_uart.h"
#include "sw/device/lib/flash_ctrl.h"
+#include "sw/device/lib/ibex_peri.h"
#include "sw/device/lib/pinmux.h"
#include "sw/device/lib/runtime/hart.h"
#include "sw/device/lib/runtime/log.h"
@@ -27,6 +28,8 @@
* for that.
*/
extern struct { void (*entry)(void); } _flash_header;
+extern uint32_t _vflash_size;
+extern uint32_t _flash_start;
static dif_uart_t uart0;
@@ -63,6 +66,13 @@
test_status_set(kTestStatusFailed);
}
+ // Simple transalation on flash
+ uint32_t src_addr = (uint32_t)&_flash_header;
+ uint32_t size = (uint32_t)&_vflash_size;
+ uint32_t dst_addr = (uint32_t)&_flash_start;
+
+ init_translation(src_addr, size, dst_addr);
+
LOG_INFO("Boot ROM initialisation has completed, jump into flash!");
// Jump into flash. At this point, the contents of the flash binary have been
diff --git a/sw/device/boot_rom/meson.build b/sw/device/boot_rom/meson.build
index f2db021..ccf1c3f 100644
--- a/sw/device/boot_rom/meson.build
+++ b/sw/device/boot_rom/meson.build
@@ -53,6 +53,7 @@
sw_lib_runtime_hart,
sw_lib_runtime_print,
sw_lib_flash_ctrl,
+ sw_lib_ibex,
sw_lib_pinmux,
sw_lib_dif_gpio,
sw_lib_dif_spi_device,
diff --git a/sw/device/boot_rom/rom_link.ld b/sw/device/boot_rom/rom_link.ld
index 6dc74e4..aa41408 100644
--- a/sw/device/boot_rom/rom_link.ld
+++ b/sw/device/boot_rom/rom_link.ld
@@ -28,6 +28,8 @@
_stack_size = LENGTH(ram_main) - _heap_size;
_stack_end = ORIGIN(ram_main) + LENGTH(ram_main);
_stack_start = _stack_end - _stack_size;
+_vflash_start = ORIGIN(eflash_virtual);
+_vflash_size = LENGTH(eflash_virtual);
_flash_start = ORIGIN(eflash);
/**
@@ -37,7 +39,7 @@
* See sw/device/lib/ext/common/flash_link.ld, under the .flash_header section,
* which populates it.
*/
-_flash_header = _flash_start;
+_flash_header = _vflash_start;
_rom_digest_size = 32;
_chip_info_size = 128;
diff --git a/sw/device/exts/common/flash_link.ld b/sw/device/exts/common/flash_link.ld
index 0917419..f90bf1a 100644
--- a/sw/device/exts/common/flash_link.ld
+++ b/sw/device/exts/common/flash_link.ld
@@ -45,9 +45,9 @@
* The flash header. This will eventually contain other stuff, like a
* signature, but for now it's just the entry point at offset zero.
*/
- .flash_header ORIGIN(eflash) : ALIGN(4) {
+ .flash_header ORIGIN(eflash_virtual) : ALIGN(4) {
KEEP(*(.flash_header))
- } > eflash
+ } > eflash_virtual
/**
* C runtime (CRT) section, containing program initialization code.
@@ -57,7 +57,7 @@
*/
.crt : ALIGN(4) {
KEEP(*(.crt))
- } > eflash
+ } > eflash_virtual
/**
* Ibex interrupt vectors. See 'ibex_interrupt_vectors.S' for more
@@ -65,7 +65,7 @@
*/
.vectors : {
*(.vectors)
- } > eflash
+ } > eflash_virtual
/**
* For LLVM profiling. This contains a pointer to the runtime initialization
@@ -79,7 +79,7 @@
*(.init_array.*)
. = ALIGN(4);
_init_array_end = .;
- } > eflash
+ } > eflash_virtual
/**
* Standard text section, containing program code.
@@ -87,7 +87,7 @@
.text : ALIGN(4) {
*(.text)
*(.text.*)
- } > eflash
+ } > eflash_virtual
/**
* Read-only data section, containing all large compile-time constants, like
@@ -105,7 +105,7 @@
KEEP(*(__llvm_covfun))
KEEP(*(__llvm_covmap))
KEEP(*(__llvm_prf_names))
- } > eflash
+ } > eflash_virtual
/**
* "Intitial data" section, the initial values of the mutable data section
@@ -113,7 +113,7 @@
*/
.idata : ALIGN(4) {
_data_init_start = .;
- } > eflash
+ } > eflash_virtual
/**
* Standard mutable data section, at the bottom of RAM. This will be
diff --git a/sw/device/lib/ibex_peri.c b/sw/device/lib/ibex_peri.c
new file mode 100644
index 0000000..96fcb9f
--- /dev/null
+++ b/sw/device/lib/ibex_peri.c
@@ -0,0 +1,31 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "sw/device/lib/ibex_peri.h"
+
+#include "sw/device/lib/base/mmio.h"
+
+#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
+#include "rv_core_ibex_peri_regs.h"
+
+void init_translation(uint32_t src_addr, uint32_t size, uint32_t dst_addr) {
+ mmio_region_t ibex_base =
+ mmio_region_from_addr(TOP_EARLGREY_RV_CORE_IBEX_PERI_BASE_ADDR);
+
+ uint32_t mask = src_addr | ((size - 1) >> 1);
+ mmio_region_write32(ibex_base,
+ RV_CORE_IBEX_PERI_IBUS_ADDR_MATCHING_0_REG_OFFSET, mask);
+ mmio_region_write32(ibex_base,
+ RV_CORE_IBEX_PERI_DBUS_ADDR_MATCHING_0_REG_OFFSET, mask);
+
+ mmio_region_write32(ibex_base, RV_CORE_IBEX_PERI_IBUS_REMAP_ADDR_0_REG_OFFSET,
+ dst_addr);
+ mmio_region_write32(ibex_base, RV_CORE_IBEX_PERI_DBUS_REMAP_ADDR_0_REG_OFFSET,
+ dst_addr);
+
+ mmio_region_write32(ibex_base, RV_CORE_IBEX_PERI_IBUS_ADDR_EN_0_REG_OFFSET,
+ 1);
+ mmio_region_write32(ibex_base, RV_CORE_IBEX_PERI_DBUS_ADDR_EN_0_REG_OFFSET,
+ 1);
+}
diff --git a/sw/device/lib/ibex_peri.h b/sw/device/lib/ibex_peri.h
new file mode 100644
index 0000000..ec96df6
--- /dev/null
+++ b/sw/device/lib/ibex_peri.h
@@ -0,0 +1,18 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef OPENTITAN_SW_DEVICE_LIB_IBEX_PERI_H_
+#define OPENTITAN_SW_DEVICE_LIB_IBEX_PERI_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/**
+ * @src_addr The source base address of the translate region
+ * @size The size of the target translate block
+ * @dst_addr The destination address after translation
+ */
+void init_translation(uint32_t src_addr, uint32_t size, uint32_t dst_addr);
+
+#endif // OPENTITAN_SW_DEVICE_LIB_IBEX_PERI_H_
diff --git a/sw/device/lib/meson.build b/sw/device/lib/meson.build
index 4e27959..f223c4e 100644
--- a/sw/device/lib/meson.build
+++ b/sw/device/lib/meson.build
@@ -23,6 +23,20 @@
)
)
+# Temp ibex peri library (sw_lib_ibex)
+sw_lib_ibex = declare_dependency(
+ link_with: static_library(
+ 'ibex_ot',
+ sources: [
+ hw_ip_ibex_reg_h,
+ 'ibex_peri.c',
+ ],
+ dependencies: [
+ top_earlgrey,
+ ]
+ )
+)
+
# PINMUX library (sw_lib_pinmux)
sw_lib_pinmux = declare_dependency(
link_with: static_library(
diff --git a/util/topgen/templates/toplevel.sv.tpl b/util/topgen/templates/toplevel.sv.tpl
index 9a7d1a7..5fd06e3 100644
--- a/util/topgen/templates/toplevel.sv.tpl
+++ b/util/topgen/templates/toplevel.sv.tpl
@@ -334,7 +334,9 @@
.fatal_intg_event_o (rv_core_ibex_fatal_intg_event),
.fatal_core_event_o (rv_core_ibex_fatal_core_event),
.recov_core_event_o (rv_core_ibex_recov_core_event),
-
+ // address translation configuration
+ .ibus_region_cfg_i (rv_core_ibex_peri_ibus_region_cfg),
+ .dbus_region_cfg_i (rv_core_ibex_peri_dbus_region_cfg),
// dft bypass
.scan_rst_ni,
.scanmode_i
diff --git a/util/topgen/templates/toplevel_memory.ld.tpl b/util/topgen/templates/toplevel_memory.ld.tpl
index 42c4198..3bb6271 100644
--- a/util/topgen/templates/toplevel_memory.ld.tpl
+++ b/util/topgen/templates/toplevel_memory.ld.tpl
@@ -21,10 +21,13 @@
/**
* Partial linker script for chip memory configuration.
+ * eflash virtual is a fixed address that does not physically exist but is used as the
+ * translation base
*/
MEMORY {
rom(rx) : ORIGIN = 0x00008000, LENGTH = 0x4000
% for m in top["memory"]:
${m["name"]}(${memory_to_flags(m)}) : ORIGIN = ${m["base_addr"]}, LENGTH = ${m["size"]}
% endfor
+ eflash_virtual(rx) : ORIGIN = 0x80000000, LENGTH = 0x100000
}