Introduce new bit to mark ROM as non-executable

This is dynamically set by hw in system_mode_ctrl. ROM will reset to
executable, but will be marked as non-executable as soon as we are no
longer executing in ROM, like system_mode.

ROM will be marked as executable again, if function calls are made to
either `syscall_addr_reg` or `blake2s_addr_reg`. Set reset value of
`blake2s_addr_reg` to an illegal address, halting the CPU if it is
called unset.

The blake2s function is 4-byte aligned, to ensure the cpu_addr is is
aligned with the address in the register.

Co-authored-by: Mikael Ågren <mikael@tillitis.se>
This commit is contained in:
Daniel Jobson 2024-11-15 09:28:01 +01:00
parent 9062b49804
commit 690bb53267
No known key found for this signature in database
GPG key ID: 3707A9DBF4BB8F1A
2 changed files with 81 additions and 38 deletions

View file

@ -117,13 +117,17 @@ module tk1 #(
//---------------------------------------------------------------- //----------------------------------------------------------------
// Registers including update variables and write enable. // Registers including update variables and write enable.
//---------------------------------------------------------------- //----------------------------------------------------------------
reg [31 : 0] cdi_mem [0 : 7]; reg [31 : 0] cdi_mem [0 : 7];
reg cdi_mem_we; reg cdi_mem_we;
reg system_mode_reg; reg system_mode_reg;
reg system_mode_new; reg system_mode_new;
reg system_mode_we; reg system_mode_we;
reg rom_executable_reg;
reg rom_executable_new;
reg rom_executable_we;
reg [ 2 : 0] led_reg; reg [ 2 : 0] led_reg;
reg led_we; reg led_we;
@ -260,33 +264,34 @@ module tk1 #(
//---------------------------------------------------------------- //----------------------------------------------------------------
always @(posedge clk) begin : reg_update always @(posedge clk) begin : reg_update
if (!reset_n) begin if (!reset_n) begin
system_mode_reg <= 1'h0; system_mode_reg <= 1'h0;
led_reg <= 3'h6; rom_executable_reg <= 1'h1;
gpio1_reg <= 2'h0; led_reg <= 3'h6;
gpio2_reg <= 2'h0; gpio1_reg <= 2'h0;
gpio3_reg <= 1'h0; gpio2_reg <= 2'h0;
gpio4_reg <= 1'h0; gpio3_reg <= 1'h0;
app_start_reg <= 32'h0; gpio4_reg <= 1'h0;
app_size_reg <= APP_SIZE; app_start_reg <= 32'h0;
blake2s_addr_reg <= 32'h0; app_size_reg <= APP_SIZE;
syscall_addr_reg <= ILLEGAL_ADDR; blake2s_addr_reg <= ILLEGAL_ADDR;
cdi_mem[0] <= 32'h0; syscall_addr_reg <= ILLEGAL_ADDR;
cdi_mem[1] <= 32'h0; cdi_mem[0] <= 32'h0;
cdi_mem[2] <= 32'h0; cdi_mem[1] <= 32'h0;
cdi_mem[3] <= 32'h0; cdi_mem[2] <= 32'h0;
cdi_mem[4] <= 32'h0; cdi_mem[3] <= 32'h0;
cdi_mem[5] <= 32'h0; cdi_mem[4] <= 32'h0;
cdi_mem[6] <= 32'h0; cdi_mem[5] <= 32'h0;
cdi_mem[7] <= 32'h0; cdi_mem[6] <= 32'h0;
cpu_trap_ctr_reg <= 24'h0; cdi_mem[7] <= 32'h0;
cpu_trap_led_reg <= 3'h0; cpu_trap_ctr_reg <= 24'h0;
cpu_mon_en_reg <= 1'h0; cpu_trap_led_reg <= 3'h0;
cpu_mon_first_reg <= 32'h0; cpu_mon_en_reg <= 1'h0;
cpu_mon_last_reg <= 32'h0; cpu_mon_first_reg <= 32'h0;
ram_addr_rand_reg <= 15'h0; cpu_mon_last_reg <= 32'h0;
ram_data_rand_reg <= 32'h0; ram_addr_rand_reg <= 15'h0;
force_trap_reg <= 1'h0; ram_data_rand_reg <= 32'h0;
system_reset_reg <= 1'h0; force_trap_reg <= 1'h0;
system_reset_reg <= 1'h0;
end end
else begin else begin
@ -304,6 +309,10 @@ module tk1 #(
system_mode_reg <= system_mode_new; system_mode_reg <= system_mode_new;
end end
if (rom_executable_we) begin
rom_executable_reg <= rom_executable_new;
end
if (led_we) begin if (led_we) begin
led_reg <= write_data[2 : 0]; led_reg <= write_data[2 : 0];
end end
@ -400,6 +409,13 @@ module tk1 #(
// //
// Trying to execute instructions in FW-RAM. // Trying to execute instructions in FW-RAM.
// //
// Executing instructions in ROM, while ROM is marked as not
// executable. Note that there is an exception, if the cpu_addr is
// the first instruction in either functions set in syscall_addr_reg
// or blake2s_addr_reg, it is allowed. For the next instruction ROM
// will be marked as executable.
// Note that the address to the functions needs to be 4-bytes aligned.
//
// Trying to execute code in mem area set to be data access only. // Trying to execute code in mem area set to be data access only.
// This requires execution monitor to have been setup and // This requires execution monitor to have been setup and
// enabled. // enabled.
@ -417,6 +433,14 @@ module tk1 #(
force_trap_set = 1'h1; force_trap_set = 1'h1;
end end
if (!rom_executable_reg) begin
if ((cpu_addr != syscall_addr_reg) && (cpu_addr != blake2s_addr_reg)) begin
if (cpu_addr <= FW_ROM_LAST) begin // Only valid as long as ROM starts at address 0x00.
force_trap_set = 1'h1;
end
end
end
if (cpu_mon_en_reg) begin if (cpu_mon_en_reg) begin
if ((cpu_addr >= cpu_mon_first_reg) && (cpu_addr <= cpu_mon_last_reg)) begin if ((cpu_addr >= cpu_mon_first_reg) && (cpu_addr <= cpu_mon_last_reg)) begin
force_trap_set = 1'h1; force_trap_set = 1'h1;
@ -427,24 +451,43 @@ module tk1 #(
end end
//---------------------------------------------------------------- //----------------------------------------------------------------
// system_mode_ctrl will raise the privilege when the function in // system_mode_ctrl dynamically sets the system mode and if ROM is
// `syscall_addr_reg` is called. // executable depending on where we are currently executing.
// //
// Automatically lowers the privilege when executing above ROM // If the function in `syscall_addr_reg` is called system_mode will
// be set to firmware mode, and ROM will be marked as executable.
//
// If the function in `blake2s_addr_reg` is called only ROM will be
// marked as executable.
//
// Automatically lowers the privilege and removes ROM execution when
// executing above ROM.
//
// Note that the address to the functions needs to be 4-bytes aligned.
// ---------------------------------------------------------------- // ----------------------------------------------------------------
always @* begin : system_mode_ctrl always @* begin : system_mode_ctrl
system_mode_new = 1'h0; system_mode_new = 1'h0;
system_mode_we = 1'h0; system_mode_we = 1'h0;
rom_executable_new = 1'h0;
rom_executable_we = 1'h0;
if (cpu_valid & cpu_instr) begin if (cpu_valid & cpu_instr) begin
if (cpu_addr == syscall_addr_reg) begin if (cpu_addr == syscall_addr_reg) begin
system_mode_new = 1'h0; system_mode_new = 1'h0;
system_mode_we = 1'h1; system_mode_we = 1'h1;
rom_executable_new = 1'h1;
rom_executable_we = 1'h1;
end
if (cpu_addr == blake2s_addr_reg) begin
rom_executable_new = 1'h1;
rom_executable_we = 1'h1;
end end
if (cpu_addr > FW_ROM_LAST) begin if (cpu_addr > FW_ROM_LAST) begin
system_mode_new = 1'h1; system_mode_new = 1'h1;
system_mode_we = 1'h1; system_mode_we = 1'h1;
rom_executable_new = 1'h0;
rom_executable_we = 1'h1;
end end
end end
end end

View file

@ -332,7 +332,7 @@ void blake2s_final(blake2s_ctx *ctx, void *out)
//------------------------------------------------------------------ //------------------------------------------------------------------
// Convenience function for all-in-one computation. // Convenience function for all-in-one computation.
//------------------------------------------------------------------ //------------------------------------------------------------------
int blake2s(void *out, size_t outlen, int __attribute__((aligned(4))) blake2s(void *out, size_t outlen,
const void *key, size_t keylen, const void *key, size_t keylen,
const void *in, size_t inlen, const void *in, size_t inlen,
blake2s_ctx *ctx) blake2s_ctx *ctx)