diff --git a/.gitattributes b/.gitattributes index 10347def7..93ffa03a6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,3 +7,4 @@ doc/img/memmap.svg linguist-generated=true doc/img/mocha.svg linguist-generated=true hw/top_chip/ip/xbar_peri/*/autogen/* linguist-generated=true hw/top_chip/ip_autogen/* linguist-generated=true +sw/device/devicetree/mocha.S linguist-generated=true diff --git a/flake.nix b/flake.nix index 057e8c649..cd2766af6 100644 --- a/flake.nix +++ b/flake.nix @@ -87,6 +87,7 @@ verible srecord d2 + dtc ]; in { formatter = pkgs.alejandra; diff --git a/sw/CMakeLists.txt b/sw/CMakeLists.txt index 7803f6d82..4896fc9a9 100644 --- a/sw/CMakeLists.txt +++ b/sw/CMakeLists.txt @@ -15,4 +15,8 @@ enable_testing() set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +include(ExternalProject) + add_subdirectory(device) + +include(cmake/opensbi.cmake) diff --git a/sw/cheri_toolchain.cmake b/sw/cheri_toolchain.cmake index 54d0d7448..097799d71 100644 --- a/sw/cheri_toolchain.cmake +++ b/sw/cheri_toolchain.cmake @@ -46,7 +46,11 @@ string(CONCAT CMAKE_C_FLAGS_INIT " -Wall -Wextra" ) -set(CMAKE_ASM_FLAGS_INIT "") +set(CMAKE_ASM_FLAGS_INIT + # Workaround: Our current build of the LLVM toolchain crashes + # when trying to erroneously relax the devicetree assembly file. + "-mno-relax" +) set(CMAKE_EXE_LINKER_FLAGS_INIT "-nodefaultlibs" diff --git a/sw/cmake/opensbi.cmake b/sw/cmake/opensbi.cmake new file mode 100644 index 000000000..895d71f00 --- /dev/null +++ b/sw/cmake/opensbi.cmake @@ -0,0 +1,80 @@ +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +# Function that builds OpenSBI with a specific payload for Mocha. +function(mocha_opensbi_with_payload PAYLOAD_TARGET) + # find the target payload file. + set(PAYLOAD "$.bin") + # name of the target OpenSBI build. + set(NAME opensbi_with_${PAYLOAD_TARGET}) + + # OpenSBI repository and tag to use. + set(OPENSBI_REPOSITORY https://github.com/lowrisc/opensbi) + set(OPENSBI_TAG mocha-devel) + + # build command - run make with build options. + set(BUILD_COMMAND + make + # Use CHERI LLVM. + LLVM=1 + # ISA options. + PLATFORM_RISCV_XLEN=64 + PLATFORM_RISCV_ISA=rv64imac_zcherihybrid + PLATFORM_RISCV_ABI=l64pc128 + # Build for the 'generic' platform, which uses devicetree data. + PLATFORM=generic + # Use the Mocha defconfig file. + PLATFORM_DEFCONFIG=mocha_defconfig + # Build a 'payload' firmware. + FW_PAYLOAD=y + FW_JUMP=n + # Build with the given payload. + FW_PAYLOAD_PATH=${PAYLOAD} + # Disable position-independent code and link to DRAM base, + # as loading position-independent executables is not supported by + # our Verilator ELF loader. + FW_PIC=n + FW_TEXT_START=0x80000000 + # 0x2 bit = build with runtime debug printing. + FW_OPTIONS=0x2 + ) + + # Built firmware binaries to copy into the root of the external project directory. + # These consist of OpenSBI + the provided payload for the next stage. + set(FIRMWARES + build/platform/generic/firmware/fw_payload.elf + build/platform/generic/firmware/fw_payload.bin + ) + + # install command - copy the firmware binaries to the root of the external project directory. + set(INSTALL_COMMAND + cp ${FIRMWARES} + ) + + ExternalProject_Add( + ${NAME} PREFIX ${NAME} + GIT_REPOSITORY ${OPENSBI_REPOSITORY} + GIT_TAG ${OPENSBI_TAG} + # OpenSBI builds in its own 'build' sub-directory. + BUILD_IN_SOURCE true + # make is job server aware. + BUILD_JOB_SERVER_AWARE true + CONFIGURE_COMMAND "" # no configure step needed, do nothing here. + BUILD_COMMAND ${BUILD_COMMAND} + INSTALL_COMMAND ${INSTALL_COMMAND} + # depend on the given payload target. + DEPENDS ${PAYLOAD_TARGET} + # suppress output from stdout. + LOG_DOWNLOAD true + LOG_UPDATE true + LOG_PATCH true + LOG_CONFIGURE true + LOG_BUILD true + LOG_INSTALL true + LOG_MERGED_STDOUTERR true + LOG_OUTPUT_ON_FAILURE true + ) +endfunction() + +mocha_opensbi_with_payload(opensbi_test_payload) diff --git a/sw/cmake/tests.cmake b/sw/cmake/tests.cmake index 59cd60b6a..1d2a12c9d 100644 --- a/sw/cmake/tests.cmake +++ b/sw/cmake/tests.cmake @@ -49,7 +49,7 @@ macro(mocha_add_fpga_test NAME) endmacro() set(BOOT_CFG rom bare ) # Config Name -set(BOOT_CFG_OFFSET 0x4000 0x00 ) # Offset +set(BOOT_CFG_OFFSET 0x8000 0x00 ) # Offset set(BOOT_CFG_FPGA YES NO ) # Fpga supported? set(BOOT_CFG_VERILATOR NO YES ) # Verilator supported? diff --git a/sw/device/bootrom/CMakeLists.txt b/sw/device/bootrom/CMakeLists.txt index 33e406b6f..4cea241b7 100644 --- a/sw/device/bootrom/CMakeLists.txt +++ b/sw/device/bootrom/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 set(NAME bootrom) -add_executable(${NAME} bootrom.c) +add_executable(${NAME} bootrom.c ../devicetree/mocha.S) target_link_libraries(${NAME} hal_vanilla runtime_vanilla startup_vanilla) target_compile_options(${NAME} PUBLIC ${VANILLA_FLAGS}) target_link_options(${NAME} PUBLIC diff --git a/sw/device/bootrom/bootrom.c b/sw/device/bootrom/bootrom.c index 144eb4236..b4843e9f0 100644 --- a/sw/device/bootrom/bootrom.c +++ b/sw/device/bootrom/bootrom.c @@ -6,6 +6,7 @@ #include "builtin.h" #include "constants.h" #include "hal/gpio.h" +#include "hal/hart.h" #include "hal/mocha.h" #include "hal/spi_device.h" #include "hal/uart.h" @@ -17,7 +18,7 @@ #define MINOR "01" #define PATCH "00" -const uintptr_t boot_slots[] = { 0x10004000, 0x80000000 }; +const uintptr_t boot_slots[] = { 0x10008000, 0x80000000 }; struct boot_context { uart_t console; gpio_t gpio; @@ -28,6 +29,9 @@ struct boot_context { extern uint8_t _program_start[]; extern uint8_t _program_end[]; +// Pointer to devicetree blob, defined in devicetree/mocha.S +extern char dt_blob_start[]; + static bool spi_boot_strap(struct boot_context *ctx); static void page_program(uart_t console, spi_device_t spid, uint32_t offset, uint32_t bytes); static void boot(uintptr_t addr); @@ -57,11 +61,10 @@ int main(void) spi_boot_strap(&boot_ctx); } - uint32_t boot_addr = 0; - while (!get_boot_addr(&boot_addr)) { - uprintf(boot_ctx.console, "Entering SPI bootstrap\n"); - // Spin polling the spi_dev and processing incoming data until a reset command is received. - spi_boot_strap(&boot_ctx); + uint32_t boot_addr; + if (!get_boot_addr(&boot_addr)) { + uprintf(boot_ctx.console, "No valid slot found, default to DRAM\n"); + boot_addr = dram_base; } uprintf(boot_ctx.console, "\nJumping to: 0x%x\n", boot_addr); @@ -72,9 +75,12 @@ int main(void) void boot(uintptr_t addr) { - typedef void (*reset_handler_t)(void); - reset_handler_t reset = (reset_handler_t)addr; - reset(); + /* next boot stages (OpenSBI, Linux, etc..) expect: + * - hart's hartid stored in the a0 register. + * - pointer to devicetree blob in the a1 register. */ + unsigned long hartid = hart_hartid_get(); + void (*next_stage)(unsigned long hartid, char *dtb) = (void *)addr; + next_stage(hartid, dt_blob_start); } bool get_boot_addr(uint32_t *addr) diff --git a/sw/device/devicetree/REUSE.toml b/sw/device/devicetree/REUSE.toml new file mode 100644 index 000000000..bd1f16093 --- /dev/null +++ b/sw/device/devicetree/REUSE.toml @@ -0,0 +1,6 @@ +version = 1 + +[[annotations]] +path = ["mocha.S"] +SPDX-FileCopyrightText = "lowRISC Contributors (COSMIC project)." +SPDX-License-Identifier = "Apache-2.0" diff --git a/sw/device/devicetree/mocha.S b/sw/device/devicetree/mocha.S new file mode 100644 index 000000000..f31857074 --- /dev/null +++ b/sw/device/devicetree/mocha.S @@ -0,0 +1,1301 @@ +/* autogenerated by dtc, do not edit */ + + .globl dt_blob_start +dt_blob_start: +_dt_blob_start: + .globl dt_header +dt_header: +_dt_header: + /* magic */ + .byte 0xd0 + .byte 0x0d + .byte 0xfe + .byte 0xed + /* totalsize */ + .byte ((_dt_blob_abs_end - _dt_blob_start) >> 24) & 0xff + .byte ((_dt_blob_abs_end - _dt_blob_start) >> 16) & 0xff + .byte ((_dt_blob_abs_end - _dt_blob_start) >> 8) & 0xff + .byte (_dt_blob_abs_end - _dt_blob_start) & 0xff + /* off_dt_struct */ + .byte ((_dt_struct_start - _dt_blob_start) >> 24) & 0xff + .byte ((_dt_struct_start - _dt_blob_start) >> 16) & 0xff + .byte ((_dt_struct_start - _dt_blob_start) >> 8) & 0xff + .byte (_dt_struct_start - _dt_blob_start) & 0xff + /* off_dt_strings */ + .byte ((_dt_strings_start - _dt_blob_start) >> 24) & 0xff + .byte ((_dt_strings_start - _dt_blob_start) >> 16) & 0xff + .byte ((_dt_strings_start - _dt_blob_start) >> 8) & 0xff + .byte (_dt_strings_start - _dt_blob_start) & 0xff + /* off_mem_rsvmap */ + .byte ((_dt_reserve_map - _dt_blob_start) >> 24) & 0xff + .byte ((_dt_reserve_map - _dt_blob_start) >> 16) & 0xff + .byte ((_dt_reserve_map - _dt_blob_start) >> 8) & 0xff + .byte (_dt_reserve_map - _dt_blob_start) & 0xff + /* version */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x11 + /* last_comp_version */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x10 + /* boot_cpuid_phys */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + /* size_dt_strings */ + .byte ((_dt_strings_end - _dt_strings_start) >> 24) & 0xff + .byte ((_dt_strings_end - _dt_strings_start) >> 16) & 0xff + .byte ((_dt_strings_end - _dt_strings_start) >> 8) & 0xff + .byte (_dt_strings_end - _dt_strings_start) & 0xff + /* size_dt_struct */ + .byte ((_dt_struct_end - _dt_struct_start) >> 24) & 0xff + .byte ((_dt_struct_end - _dt_struct_start) >> 16) & 0xff + .byte ((_dt_struct_end - _dt_struct_start) >> 8) & 0xff + .byte (_dt_struct_end - _dt_struct_start) & 0xff + .balign 8, 0 + .globl dt_reserve_map +dt_reserve_map: +_dt_reserve_map: +/* Memory reserve map from source file */ + .long 0, 0 + .long 0, 0 + .globl dt_struct_start +dt_struct_start: +_dt_struct_start: + /* FDT_BEGIN_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .asciz "" + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x0f + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x0e + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x1b + .byte 0x6c + .byte 0x6f + .byte 0x77 + .byte 0x72 + .byte 0x69 + .byte 0x73 + .byte 0x63 + .byte 0x2c + .byte 0x6d + .byte 0x6f + .byte 0x63 + .byte 0x68 + .byte 0x61 + .byte 0x0 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x0e + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x26 + .byte 0x6c + .byte 0x6f + .byte 0x77 + .byte 0x72 + .byte 0x69 + .byte 0x73 + .byte 0x63 + .byte 0x2c + .byte 0x6d + .byte 0x6f + .byte 0x63 + .byte 0x68 + .byte 0x61 + .byte 0x0 + .balign 4, 0 + /* FDT_BEGIN_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .asciz "memory@80000000" + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x07 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x2c + .byte 0x6d + .byte 0x65 + .byte 0x6d + .byte 0x6f + .byte 0x72 + .byte 0x79 + .byte 0x0 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x10 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x38 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x80 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x3f + .byte 0x80 + .byte 0x00 + .byte 0x00 + .balign 4, 0 + /* FDT_END_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + /* FDT_BEGIN_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .asciz "cpus" + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x0f + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x3c + .byte 0x02 + .byte 0xfa + .byte 0xf0 + .byte 0x80 + .balign 4, 0 + /* FDT_BEGIN_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .asciz "cpu@0" + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x06 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x1b + .byte 0x72 + .byte 0x69 + .byte 0x73 + .byte 0x63 + .byte 0x76 + .byte 0x0 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x2c + .byte 0x63 + .byte 0x70 + .byte 0x75 + .byte 0x00 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x38 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x33 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x4f + .byte 0x72 + .byte 0x76 + .byte 0x36 + .byte 0x34 + .byte 0x69 + .byte 0x6d + .byte 0x61 + .byte 0x63 + .byte 0x5f + .byte 0x7a + .byte 0x63 + .byte 0x68 + .byte 0x65 + .byte 0x72 + .byte 0x69 + .byte 0x70 + .byte 0x75 + .byte 0x72 + .byte 0x65 + .byte 0x63 + .byte 0x61 + .byte 0x70 + .byte 0x5f + .byte 0x7a + .byte 0x63 + .byte 0x68 + .byte 0x65 + .byte 0x72 + .byte 0x69 + .byte 0x68 + .byte 0x79 + .byte 0x62 + .byte 0x72 + .byte 0x69 + .byte 0x64 + .byte 0x5f + .byte 0x7a + .byte 0x69 + .byte 0x63 + .byte 0x73 + .byte 0x72 + .byte 0x5f + .byte 0x7a + .byte 0x69 + .byte 0x66 + .byte 0x65 + .byte 0x6e + .byte 0x63 + .byte 0x65 + .byte 0x69 + .byte 0x0 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x0b + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x59 + .byte 0x72 + .byte 0x69 + .byte 0x73 + .byte 0x63 + .byte 0x76 + .byte 0x2c + .byte 0x73 + .byte 0x76 + .byte 0x33 + .byte 0x39 + .byte 0x0 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x05 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x62 + .byte 0x6f + .byte 0x6b + .byte 0x61 + .byte 0x79 + .byte 0x0 + .balign 4, 0 + .globl cpu0intc +cpu0intc: + /* FDT_BEGIN_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .asciz "interrupt-controller" + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x69 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x7e + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x0f + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x1b + .byte 0x72 + .byte 0x69 + .byte 0x73 + .byte 0x63 + .byte 0x76 + .byte 0x2c + .byte 0x63 + .byte 0x70 + .byte 0x75 + .byte 0x2d + .byte 0x69 + .byte 0x6e + .byte 0x74 + .byte 0x63 + .byte 0x0 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x8f + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + .balign 4, 0 + /* FDT_END_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + .globl cpu0intc_end +cpu0intc_end: + /* FDT_END_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + /* FDT_END_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + /* FDT_BEGIN_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .asciz "soc" + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x0f + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x0b + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x1b + .byte 0x73 + .byte 0x69 + .byte 0x6d + .byte 0x70 + .byte 0x6c + .byte 0x65 + .byte 0x2d + .byte 0x62 + .byte 0x75 + .byte 0x73 + .byte 0x0 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x97 + .balign 4, 0 + /* FDT_BEGIN_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .asciz "serial@41000000" + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x1d + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x1b + .byte 0x6c + .byte 0x6f + .byte 0x77 + .byte 0x72 + .byte 0x69 + .byte 0x73 + .byte 0x63 + .byte 0x2c + .byte 0x6f + .byte 0x70 + .byte 0x65 + .byte 0x6e + .byte 0x74 + .byte 0x69 + .byte 0x74 + .byte 0x61 + .byte 0x6e + .byte 0x2d + .byte 0x75 + .byte 0x61 + .byte 0x72 + .byte 0x74 + .byte 0x2d + .byte 0x31 + .byte 0x2e + .byte 0x30 + .byte 0x2e + .byte 0x30 + .byte 0x0 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x10 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x38 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x41 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x30 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x08 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x9e + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x08 + .balign 4, 0 + /* FDT_END_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + /* FDT_BEGIN_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .asciz "timer@44000000" + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x21 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x1b + .byte 0x6c + .byte 0x6f + .byte 0x77 + .byte 0x72 + .byte 0x69 + .byte 0x73 + .byte 0x63 + .byte 0x2c + .byte 0x6f + .byte 0x70 + .byte 0x65 + .byte 0x6e + .byte 0x74 + .byte 0x69 + .byte 0x74 + .byte 0x61 + .byte 0x6e + .byte 0x2d + .byte 0x72 + .byte 0x76 + .byte 0x2d + .byte 0x74 + .byte 0x69 + .byte 0x6d + .byte 0x65 + .byte 0x72 + .byte 0x2d + .byte 0x31 + .byte 0x2e + .byte 0x30 + .byte 0x2e + .byte 0x30 + .byte 0x0 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x10 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x38 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x44 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .byte 0x20 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x08 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x9e + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x07 + .balign 4, 0 + /* FDT_END_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + .globl plic +plic: + /* FDT_BEGIN_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .asciz "interrupt-controller@48000000" + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x2f + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x1b + .byte 0x6c + .byte 0x6f + .byte 0x77 + .byte 0x72 + .byte 0x69 + .byte 0x73 + .byte 0x63 + .byte 0x2c + .byte 0x6f + .byte 0x70 + .byte 0x65 + .byte 0x6e + .byte 0x74 + .byte 0x69 + .byte 0x74 + .byte 0x61 + .byte 0x6e + .byte 0x2d + .byte 0x70 + .byte 0x6c + .byte 0x69 + .byte 0x63 + .byte 0x2d + .byte 0x31 + .byte 0x2e + .byte 0x30 + .byte 0x2e + .byte 0x30 + .byte 0x00 + .byte 0x73 + .byte 0x69 + .byte 0x66 + .byte 0x69 + .byte 0x76 + .byte 0x65 + .byte 0x2c + .byte 0x70 + .byte 0x6c + .byte 0x69 + .byte 0x63 + .byte 0x2d + .byte 0x31 + .byte 0x2e + .byte 0x30 + .byte 0x2e + .byte 0x30 + .byte 0x0 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x69 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x7e + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x10 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x38 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x48 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x10 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x9e + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x09 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x0b + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0xb2 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x20 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x8f + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .balign 4, 0 + /* FDT_END_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + .globl plic_end +plic_end: + .globl plicsw +plicsw: + /* FDT_BEGIN_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .asciz "interrupt-controller@4c000000" + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x1f + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x1b + .byte 0x6c + .byte 0x6f + .byte 0x77 + .byte 0x72 + .byte 0x69 + .byte 0x73 + .byte 0x63 + .byte 0x2c + .byte 0x6f + .byte 0x70 + .byte 0x65 + .byte 0x6e + .byte 0x74 + .byte 0x69 + .byte 0x74 + .byte 0x61 + .byte 0x6e + .byte 0x2d + .byte 0x70 + .byte 0x6c + .byte 0x69 + .byte 0x63 + .byte 0x73 + .byte 0x77 + .byte 0x2d + .byte 0x31 + .byte 0x2e + .byte 0x30 + .byte 0x2e + .byte 0x30 + .byte 0x0 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x69 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x04 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x7e + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x01 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x10 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x38 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x4c + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x40 + .byte 0x00 + .balign 4, 0 + /* FDT_PROP */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x08 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x9e + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x03 + .balign 4, 0 + /* FDT_END_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + .globl plicsw_end +plicsw_end: + /* FDT_END_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + /* FDT_END_NODE */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x02 + /* FDT_END */ + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x09 + .globl dt_struct_end +dt_struct_end: +_dt_struct_end: + .globl dt_strings_start +dt_strings_start: +_dt_strings_start: + .asciz "#address-cells" + .asciz "#size-cells" + .asciz "compatible" + .asciz "model" + .asciz "device_type" + .asciz "reg" + .asciz "timebase-frequency" + .asciz "riscv,isa" + .asciz "mmu-type" + .asciz "status" + .asciz "interrupt-controller" + .asciz "#interrupt-cells" + .asciz "phandle" + .asciz "ranges" + .asciz "interrupts-extended" + .asciz "riscv,ndev" + .globl dt_strings_end +dt_strings_end: +_dt_strings_end: + .globl dt_blob_end +dt_blob_end: +_dt_blob_end: + .balign 64, 0 + .globl dt_blob_abs_end +dt_blob_abs_end: +_dt_blob_abs_end: diff --git a/sw/device/devicetree/mocha.dts b/sw/device/devicetree/mocha.dts new file mode 100644 index 000000000..1ed0d65e9 --- /dev/null +++ b/sw/device/devicetree/mocha.dts @@ -0,0 +1,80 @@ +// Copyright lowRISC contributors (COSMIC project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +/dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <2>; + compatible = "lowrisc,mocha"; + model = "lowrisc,mocha"; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x0 0x3f800000>; // (1 GiB - 8 MiB) + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <50000000>; // 50 MHz + + cpu@0 { + compatible = "riscv"; + device_type = "cpu"; + reg = <0>; + riscv,isa = "rv64imac_zcheripurecap_zcherihybrid_zicsr_zifencei"; + mmu-type = "riscv,sv39"; + status = "okay"; + + cpu0intc: interrupt-controller { + interrupt-controller; + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + }; + }; + }; + + soc { + #address-cells = <2>; + #size-cells = <2>; + compatible = "simple-bus"; + ranges; + + serial@41000000 { + compatible = "lowrisc,opentitan-uart-1.0.0"; + reg = <0x0 0x41000000 0x0 0x30>; + interrupts-extended = <&plic 8>; // UART is PLIC interrupt source 8 + }; + + timer@44000000 { + compatible = "lowrisc,opentitan-rv-timer-1.0.0"; + reg = <0x0 0x44000000 0x0 0x120>; + interrupts-extended = <&cpu0intc 7>; // M-mode timer interrupt + }; + + plic: interrupt-controller@48000000 { + compatible = "lowrisc,opentitan-plic-1.0.0", + "sifive,plic-1.0.0"; // Compatible with the SiFive PLIC memory layout + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = <0x0 0x48000000 0x0 0x4000000>; + interrupts-extended = <&cpu0intc 9>, // S-mode external interrupt + <&cpu0intc 11>; // M-mode external interrupt + riscv,ndev = <32>; + }; + + // End of PLIC memory region is for software interrupts, + // model this as another interrupt controller that delivers the software interrupts + plicsw: interrupt-controller@4c000000 { + compatible = "lowrisc,opentitan-plicsw-1.0.0"; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = <0x0 0x4c000000 0x0 0x4000>; + interrupts-extended = <&cpu0intc 3>; // M-mode software interrupt + }; + }; +}; diff --git a/sw/device/lib/hal/hart.h b/sw/device/lib/hal/hart.h index fcfe877d9..7a6c3ccbb 100644 --- a/sw/device/lib/hal/hart.h +++ b/sw/device/lib/hal/hart.h @@ -39,6 +39,8 @@ static inline bool hart_interrupt_any_pending(enum interrupt interrupts); /* cycle counter */ static inline uint64_t hart_cycle_get(void); +/* hartid */ +static inline unsigned long hart_hartid_get(void); static inline bool hart_global_interrupt_enable_set(bool enable) { @@ -91,6 +93,13 @@ static inline uint64_t hart_cycle_get(void) return cycle; } +static inline unsigned long hart_hartid_get(void) +{ + unsigned long hartid; + asm volatile("csrr %0, mhartid" : "=r"(hartid)::); + return hartid; +} + /* wait for a condition to be true, allowing preemption by interrupts */ #define WAIT_FOR_CONDITION_PREEMPTABLE(volatile_condition) \ do { \ diff --git a/sw/device/tests/CMakeLists.txt b/sw/device/tests/CMakeLists.txt index 01b43671b..412c270e9 100644 --- a/sw/device/tests/CMakeLists.txt +++ b/sw/device/tests/CMakeLists.txt @@ -26,4 +26,5 @@ mocha_add_test(NAME timer_smoketest SOURCES timer/smoketest.c LIBRARIES ${LIBS} mocha_add_test(NAME timer_interrupt_test SOURCES timer/interrupt.c LIBRARIES ${LIBS}) mocha_add_test(NAME uart_smoketest SOURCES uart/smoketest.c LIBRARIES ${LIBS}) +add_subdirectory(opensbi) add_subdirectory(dram) diff --git a/sw/device/tests/opensbi/CMakeLists.txt b/sw/device/tests/opensbi/CMakeLists.txt new file mode 100644 index 000000000..cdf5d3005 --- /dev/null +++ b/sw/device/tests/opensbi/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright lowRISC contributors (COSMIC project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +set(NAME opensbi_test_payload) +add_executable(${NAME} test_payload.S) +target_compile_options(${NAME} PUBLIC ${VANILLA_FLAGS}) +# The link address 0x80200000 is the address that OpenSBI will +# load the payload into and jump to it. This specific choice +# of offset (0x200000 = 2 MiB) is so that the load address is +# aligned to the size of a second-layer page (2 MiB on RV64), +# so that S-mode software can map itself into virtual memory +# using just a few large pages. This is a requirement for Linux too, +# see https://docs.kernel.org/arch/riscv/boot.html#kernel-location. +target_link_options(${NAME} PUBLIC "-Wl,--Ttext=0x80200000") +mocha_add_executable_artefacts(${NAME}) diff --git a/sw/device/tests/opensbi/test_payload.S b/sw/device/tests/opensbi/test_payload.S new file mode 100644 index 000000000..938120a18 --- /dev/null +++ b/sw/device/tests/opensbi/test_payload.S @@ -0,0 +1,56 @@ +/* Copyright lowRISC contributors. */ +/* Licensed under the Apache License, Version 2.0, see LICENSE for details. */ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* A simple test payload to use with OpenSBI. */ +/* This performs an SBI call to print the success string and */ +/* writes to the DV Test Status register to indicate success. */ + +#define SBI_DEBUG_CONSOLE 0x4442434e +#define SBI_DEBUG_CONSOLE_WRITE 0 + +#define DV_TEST_STATUS 0x20020000 +#define DV_TEST_STATUS_IN_TEST 0x4354 +#define DV_TEST_STATUS_PASSED 0x900d + +.section .text + +.globl _start +_start: + /* Perform an SBI call to print test_status_string. */ + li a7, SBI_DEBUG_CONSOLE + li a6, SBI_DEBUG_CONSOLE_WRITE + la a0, test_status_string_len + lw a0, 0(a0) + la a1, test_status_string + li a2, 0 + li a3, 0 + li a4, 0 + li a5, 0 + ecall + + /* Write to DV Test Status */ + /* We need to put this after the string is printed as + * the FPGA run should have been terminated by then. + * Also we must write the in test status first as it is + * an error to transition straight to test passing. */ + la a0, DV_TEST_STATUS + li a1, DV_TEST_STATUS_IN_TEST + sw a1, 0(a0) + + la a0, DV_TEST_STATUS + li a1, DV_TEST_STATUS_PASSED + sw a1, 0(a0) + +loop: + wfi + j loop + +.section .data + +test_status_string: + .string "TEST RESULT: PASSED\n" +test_status_string_len: + .word . - test_status_string + /* Padding is required for vmem */ + .align 3 diff --git a/util/artefacts.py b/util/artefacts.py index f3714ab58..758e04c7e 100755 --- a/util/artefacts.py +++ b/util/artefacts.py @@ -132,6 +132,19 @@ "build/rdl/rdl.json", "doc/img/memmap.svg", ], + # generate devicetree + [ + "dtc", + "-I", + "dts", + "sw/device/devicetree/mocha.dts", + "-O", + "asm", + "-o", + "sw/device/devicetree/mocha.S", + "--align", + "64", + ], # documentation ["d2", "doc/img/mocha.d2"], ]