blob: 40c31e1dd3ebd6d45c7c9445b4d59ff8a5f32bfb [file] [log] [blame]
// Copyright 2023 Google LLC
// Copyright lowRISC contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "hw/top_matcha/sw/autogen/top_matcha_memory.h"
#include "sw/device/lib/base/macros.h"
#include "sw/device/lib/base/multibits_asm.h"
#include "ast_regs.h"
#include "csrng_regs.h"
#include "edn_regs.h"
#include "entropy_src_regs.h"
#include "otp_ctrl_regs.h"
#include "sensor_ctrl_regs.h"
#include "sram_ctrl_regs.h"
/**
* Test ROM interrupt vectors.
*
* After reset all interrupts are disabled. Only exceptions (interrupt 0) and
* non-maskable interrupts (interrupt 31) are possible. For simplicity however
* we just set all interrupt handlers in the Test ROM to use the same handler,
* which loops forever.
*
* Interrupt vectors in Ibex have 32 entries for 32 possible interrupts. The
* vector must be 256-byte aligned, as Ibex's vectoring mechanism requires that.
*
* Note that the Ibex reset handler (entry point) immediately follows this
* interrupt vector and can be thought of as an extra entry.
*
* More information about Ibex's interrupts can be found here:
* https://ibex-core.readthedocs.io/en/latest/03_reference/exception_interrupts.html
*/
// Push Test ROM interrupt vector options.
.option push
// Disable RISC-V instruction compression: we need all instructions to
// be exactly word wide in the interrupt vector.
.option norvc
// Disable RISC-V linker relaxation, as it can compress instructions at
// link-time, which we also really don't want.
.option norelax
// NOTE: The "ax" flag below is necessary to ensure that this section
// is allocated executable space in ROM by the linker.
.section .vectors, "ax"
#ifdef PUPPETEER_ROM
bootrom_vector_table:
j default_irq_handler // Exception 0, Reserved
j default_irq_handler // Exception 1, Supervisor software interrupt
j default_irq_handler // Exception 2, Reserved
j default_irq_handler // Exception 3, Machine software interrupt
j default_irq_handler // Exception 4, Reserved
j default_irq_handler // Exception 5, Supervisor software interrupt
j default_irq_handler // Exception 6, Reserved
j default_irq_handler // Exception 7, Machine timer interrupt
j default_irq_handler // Exception 8, Reserved
j default_irq_handler // Exception 9, Supervisor external interrupt
j default_irq_handler // Exception 10, Reserved
j default_irq_handler // Exception 11, Machine external interrupt
j default_irq_handler // Exception 12, Reserved
j default_irq_handler // Exception 13, Reserved
j default_irq_handler // Exception 14, Reserved
j default_irq_handler // Exception 15, Reserved
j default_irq_handler // Exception 16, Ibex fast interrupt handler 0
j default_irq_handler // Exception 17, Ibex fast interrupt handler 1
j default_irq_handler // Exception 18, Ibex fast interrupt handler 2
j default_irq_handler // Exception 19, Ibex fast interrupt handler 3
j default_irq_handler // Exception 20, Ibex fast interrupt handler 4
j default_irq_handler // Exception 21, Ibex fast interrupt handler 5
j default_irq_handler // Exception 22, Ibex fast interrupt handler 6
j default_irq_handler // Exception 23, Ibex fast interrupt handler 7
j default_irq_handler // Exception 24, Ibex fast interrupt handler 8
j default_irq_handler // Exception 25, Ibex fast interrupt handler 9
j default_irq_handler // Exception 26, Ibex fast interrupt handler 10
j default_irq_handler // Exception 27, Ibex fast interrupt handler 11
j default_irq_handler // Exception 28, Ibex fast interrupt handler 12
j default_irq_handler // Exception 29, Ibex fast interrupt handler 13
j default_irq_handler // Exception 30, Ibex fast interrupt handler 14
j default_irq_handler // Exception 31, Ibex NMI handler
j _reset_start // Ibex reset vector @ 0x8080
#else
.balign 256
.global _test_rom_interrupt_vector
.type _test_rom_interrupt_vector, @function
_test_rom_interrupt_vector:
// Each jump instruction must be exactly 4 bytes in order to ensure that the
// entries are properly located.
.rept 32
j _test_rom_irq_handler
.endr
// Ibex reset vector, the initial entry point after reset. (This falls at IRQ
// handler 0x80.)
j _reset_start
// Set size so this vector can be disassembled.
.size _test_rom_interrupt_vector, .-_test_rom_interrupt_vector
// Pop ROM interrupt vector options.
//
// Re-enable compressed instructions, linker relaxation.
#endif
.option pop
// -----------------------------------------------------------------------------
#ifdef PUPPETEER_ROM
// The default interrupt handler during the first stage boot does nothing
// useful and just spins in a wfi loop.
.section .crt, "ax"
default_irq_handler:
wfi
j default_irq_handler
//------------------------------------------------------------------------------
// Bare-metal entry point for Shodan's first-stage bootloader, stored in the
// on-die boot rom.
.section .crt, "ax"
.global _reset_start
#else
/**
* Test ROM runtime initialization code.
*/
// NOTE: The "ax" flag below is necessary to ensure that this section
// is allocated executable space in ROM by the linker.
.section .crt, "ax"
/**
* Entry point after reset. This symbol is jumped to from the handler
* for IRQ 0x80.
*/
.balign 4
.global _reset_start
.type _reset_start, @function
#endif
_reset_start:
// Set up the global pointer. This requires that we disable linker relaxations
// (or it will be relaxed to `mv gp, gp`).
.option push
.option norelax
la gp, __global_pointer$
.option pop
// Clobber all writeable registers.
li x1, 0x0
li x2, 0x0
li x4, 0x0
li x5, 0x0
li x6, 0x0
li x7, 0x0
li x8, 0x0
li x9, 0x0
li x10, 0x0
li x11, 0x0
li x12, 0x0
li x13, 0x0
li x14, 0x0
li x15, 0x0
li x16, 0x0
li x17, 0x0
li x18, 0x0
li x19, 0x0
li x20, 0x0
li x21, 0x0
li x22, 0x0
li x23, 0x0
li x24, 0x0
li x25, 0x0
li x26, 0x0
li x27, 0x0
li x28, 0x0
li x29, 0x0
li x30, 0x0
li x31, 0x0
#ifdef PUPPETEER_ROM
// Set up the stack
la sp, _stack_end
// With GP and SP set we can now technically run C code, but we need some
// additional configuration work to enable Ibex's security systems. Those are
// handled by _start below.
j _start
//------------------------------------------------------------------------------
// C-callable entry point for the first stage bootloader. Initializes AST,
// entropy sources, SRAM scrambling, and then clears RAM and jumps to
// _boot_start.
.section .crt, "ax"
.global _start
#else
// Set up the stack.
la sp, _stack_end
// Explicit fall-through to `_start`.
.size _reset_start, .-_reset_start
// -----------------------------------------------------------------------------
/**
* Callable entry point for the boot rom.
*
* Currently, this zeroes the `.bss` section, copies initial data to
* `.data`, and then jumps to the program entry point.
*/
.balign 4
.global _start
.type _start, @function
#endif
_start:
#if !OT_IS_ENGLISH_BREAKFAST
#if !OTP_IS_RAM
// Check if AST initialization should be skipped.
li a0, (TOP_MATCHA_OTP_CTRL_CORE_BASE_ADDR + \
OTP_CTRL_SW_CFG_WINDOW_REG_OFFSET)
lw t0, OTP_CTRL_PARAM_CREATOR_SW_CFG_AST_INIT_EN_OFFSET(a0)
li t1, MULTIBIT_ASM_BOOL4_TRUE
bne t0, t1, .L_ast_init_skip
// Copy the AST configuration from OTP.
li a0, (TOP_MATCHA_AST_BASE_ADDR)
li a1, (TOP_MATCHA_AST_BASE_ADDR + AST_REGAL_REG_OFFSET + 4)
li a2, (TOP_MATCHA_OTP_CTRL_CORE_BASE_ADDR + \
OTP_CTRL_SW_CFG_WINDOW_REG_OFFSET + \
OTP_CTRL_PARAM_CREATOR_SW_CFG_AST_CFG_OFFSET)
call crt_section_copy
#else
j .L_ast_init_skip
#endif
// Wait for AST initialization to complete.
li a0, TOP_MATCHA_SENSOR_CTRL_BASE_ADDR
.L_ast_done_loop:
lw t0, SENSOR_CTRL_STATUS_REG_OFFSET(a0)
srli t0, t0, SENSOR_CTRL_STATUS_AST_INIT_DONE_BIT // no-op as bit index is currently 0
andi t0, t0, 0x1
beqz t0, .L_ast_done_loop
.L_ast_init_skip:
// The following sequence enables the minimum level of entropy required to
// initialize memory scrambling, as well as the entropy distribution network.
li a0, TOP_MATCHA_ENTROPY_SRC_BASE_ADDR
// Note for BOOT_ROM initialization the FIPS_ENABLE bit is set to kMultiBitBool4False
// to prevent the release of FIPS entropy until all the thresholds are set
li t0, (MULTIBIT_ASM_BOOL4_FALSE << ENTROPY_SRC_CONF_FIPS_ENABLE_OFFSET) | \
(MULTIBIT_ASM_BOOL4_FALSE << ENTROPY_SRC_CONF_ENTROPY_DATA_REG_ENABLE_OFFSET) | \
(MULTIBIT_ASM_BOOL4_FALSE << ENTROPY_SRC_CONF_THRESHOLD_SCOPE_OFFSET) | \
(MULTIBIT_ASM_BOOL4_FALSE << ENTROPY_SRC_CONF_RNG_BIT_ENABLE_OFFSET)
sw t0, ENTROPY_SRC_CONF_REG_OFFSET(a0)
li t0, (MULTIBIT_ASM_BOOL4_TRUE << ENTROPY_SRC_MODULE_ENABLE_MODULE_ENABLE_OFFSET)
sw t0, ENTROPY_SRC_MODULE_ENABLE_REG_OFFSET(a0)
li a0, TOP_MATCHA_CSRNG_BASE_ADDR
li t0, (MULTIBIT_ASM_BOOL4_TRUE << CSRNG_CTRL_ENABLE_OFFSET) | \
(MULTIBIT_ASM_BOOL4_TRUE << CSRNG_CTRL_SW_APP_ENABLE_OFFSET) | \
(MULTIBIT_ASM_BOOL4_TRUE << CSRNG_CTRL_READ_INT_STATE_OFFSET)
sw t0, CSRNG_CTRL_REG_OFFSET(a0)
li a0, TOP_MATCHA_EDN0_BASE_ADDR
li t0, (MULTIBIT_ASM_BOOL4_TRUE << EDN_CTRL_EDN_ENABLE_OFFSET) | \
(MULTIBIT_ASM_BOOL4_TRUE << EDN_CTRL_BOOT_REQ_MODE_OFFSET) | \
(MULTIBIT_ASM_BOOL4_FALSE << EDN_CTRL_AUTO_REQ_MODE_OFFSET) | \
(MULTIBIT_ASM_BOOL4_FALSE << EDN_CTRL_CMD_FIFO_RST_OFFSET)
sw t0, EDN_CTRL_REG_OFFSET(a0)
// Remove address space protections by configuring entry 15 as
// read-write-execute for the entire address space and then clearing
// all other entries.
// NOTE: This should happen before attemting to access any address outside
// the initial ePMP RX region at reset, e.g. `kDeviceType` which is in
// .rodata.
li t0, (0x9f << 24) // Locked NAPOT read-write-execute.
csrw pmpcfg3, t0
li t0, 0x7fffffff // NAPOT encoded region covering entire 34-bit address space.
csrw pmpaddr15, t0
csrw pmpcfg0, zero
csrw pmpcfg1, zero
csrw pmpcfg2, zero
#endif
// Scramble and initialize main memory (main SRAM).
// Memory accesses will stall until initialization is complete.
#ifndef PUPPETEER_ROM
// Skip SRAM initialization for DV sim device type, as the testbench handles
// this to optimize test run times.
lw t0, kDeviceType
beqz t0, .L_sram_init_skip
#endif
li a0, TOP_MATCHA_SRAM_CTRL_MAIN_REGS_BASE_ADDR
li t0, (1 << SRAM_CTRL_CTRL_INIT_BIT)
sw t0, SRAM_CTRL_CTRL_REG_OFFSET(a0)
#ifndef PUPPETEER_ROM
.L_sram_init_skip:
#endif
// Zero out the `.bss` segment.
la a0, _bss_start
la a1, _bss_end
#ifdef PUPPETEER_ROM
call crt_section_clear
// Zero out the stack
la a0, _stack_start
la a1, _stack_end
#endif
call crt_section_clear
// Initialize the `.data` segment from the `.idata` segment.
la a0, _data_start
la a1, _data_end
la a2, _data_init_start
call crt_section_copy
// Clobber all temporary registers.
li t0, 0x0
li t1, 0x0
li t2, 0x0
li t3, 0x0
li t4, 0x0
li t5, 0x0
li t6, 0x0
// Clobber all argument registers.
li a0, 0x0
li a1, 0x0
li a2, 0x0
li a3, 0x0
li a4, 0x0
li a5, 0x0
li a6, 0x0
li a7, 0x0
// Jump into the C program entry point.
call _boot_start
// Enter a wait for interrupt loop, the device should reset shortly.
.L_wfi_loop:
wfi
j .L_wfi_loop
#ifndef PUPPETEER_ROM
.size _start, .-_start
// -----------------------------------------------------------------------------
/**
* Test ROM IRQ/exception handler; loops forever.
*/
.balign 4
.section .text
.global _test_rom_irq_handler
.type _test_rom_irq_handler, @function
_test_rom_irq_handler:
wfi
j _test_rom_irq_handler
.size _test_rom_irq_handler, .-_test_rom_irq_handler
#endif