ecall from U-mode has a different mcause value than ecall from M-mode
This commit is contained in:
parent
632c61daba
commit
81aec325bb
|
@ -819,7 +819,12 @@ wire [W_EXCEPT-1:0] x_except =
|
|||
x_loadstore_pmp_fail ? EXCEPT_LOAD_FAULT : d_except;
|
||||
|
||||
// If an instruction causes an exceptional condition we do not consider it to have retired.
|
||||
wire x_except_counts_as_retire = x_except == EXCEPT_EBREAK || x_except == EXCEPT_MRET || x_except == EXCEPT_ECALL;
|
||||
wire x_except_counts_as_retire =
|
||||
x_except == EXCEPT_EBREAK ||
|
||||
x_except == EXCEPT_MRET ||
|
||||
x_except == EXCEPT_ECALL_M ||
|
||||
x_except == EXCEPT_ECALL_U;
|
||||
|
||||
wire x_instr_ret = |df_cir_use && (x_except == EXCEPT_NONE || x_except_counts_as_retire);
|
||||
wire m_dphase_in_flight = xm_memop != MEMOP_NONE && xm_memop != MEMOP_AMO;
|
||||
|
||||
|
|
|
@ -292,14 +292,14 @@ always @ (*) begin
|
|||
RV_ZIP: if (EXTENSION_ZBKB) begin d_aluop = ALUOP_ZIP; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||
|
||||
RV_FENCE: begin d_rs2 = X0; end // NOP, note rs1/rd are zero in instruction
|
||||
RV_FENCE_I: if (EXTENSION_ZIFENCEI) begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_branchcond = BCOND_ALWAYS; end else begin d_invalid_32bit = 1'b1; end // note rs1/rs2/rd are zero in instruction
|
||||
RV_FENCE_I: if (EXTENSION_ZIFENCEI) begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_branchcond = BCOND_ALWAYS; end else begin d_invalid_32bit = 1'b1; end // note rs1/rs2/rd are zero in instruction
|
||||
RV_CSRRW: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = 1'b1 ; d_csr_ren = |d_rd; d_csr_wtype = CSR_WTYPE_W; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_CSRRS: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_S; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_CSRRC: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_C; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_CSRRWI: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = 1'b1 ; d_csr_ren = |d_rd; d_csr_wtype = CSR_WTYPE_W; d_csr_w_imm = 1'b1; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_CSRRSI: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_S; d_csr_w_imm = 1'b1; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_CSRRCI: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_C; d_csr_w_imm = 1'b1; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_ECALL: if (HAVE_CSR) begin d_except = EXCEPT_ECALL; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_ECALL: if (HAVE_CSR) begin d_except = m_mode || !U_MODE ? EXCEPT_ECALL_M : EXCEPT_ECALL_U; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_EBREAK: if (HAVE_CSR) begin d_except = EXCEPT_EBREAK; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_MRET: if (HAVE_CSR && m_mode) begin d_except = EXCEPT_MRET; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||
RV_WFI: if (HAVE_CSR && permit_wfi) begin d_wfi = 1'b1; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||
|
|
|
@ -103,8 +103,9 @@ localparam EXCEPT_LOAD_ALIGN = 4'h4;
|
|||
localparam EXCEPT_LOAD_FAULT = 4'h5;
|
||||
localparam EXCEPT_STORE_ALIGN = 4'h6;
|
||||
localparam EXCEPT_STORE_FAULT = 4'h7;
|
||||
localparam EXCEPT_ECALL_U = 4'h8;
|
||||
localparam EXCEPT_MRET = 4'ha; // Not really an exception, but handled like one
|
||||
localparam EXCEPT_ECALL = 4'hb;
|
||||
localparam EXCEPT_ECALL_M = 4'hb;
|
||||
|
||||
// Operations for M extension (these are just instr[14:12])
|
||||
|
||||
|
|
|
@ -15,19 +15,19 @@
|
|||
Initial
|
||||
mcause = 1
|
||||
4-byte region
|
||||
mcause = 11
|
||||
mcause = 8
|
||||
Large region
|
||||
mcause = 11
|
||||
mcause = 8
|
||||
X under !X
|
||||
mcause = 11
|
||||
mcause = 8
|
||||
!X under X
|
||||
mcause = 1
|
||||
Full match under partial match, positive overhang
|
||||
mcause = 11
|
||||
mcause = 8
|
||||
Partial match under full match, positive overhang
|
||||
mcause = 1
|
||||
Full match under partial match, negative overhang
|
||||
mcause = 11
|
||||
mcause = 8
|
||||
Partial match under full match, negative overhang
|
||||
mcause = 1
|
||||
Jump to bad jump
|
||||
|
@ -89,7 +89,7 @@ void __attribute__((naked)) do_jump() {
|
|||
}
|
||||
|
||||
#define MCAUSE_INSTR_FAULT 1
|
||||
#define MCAUSE_ECALL 11
|
||||
#define MCAUSE_ECALL_UMODE 8
|
||||
|
||||
int main() {
|
||||
// Initially, there are no permissions active in the PMP, so we should get
|
||||
|
@ -107,7 +107,7 @@ int main() {
|
|||
|
||||
enter_umode(&do_ecall);
|
||||
tb_printf("mcause = %u\n", read_csr(mcause));
|
||||
tb_assert(read_csr(mcause) == MCAUSE_ECALL, "Should successfully execute ecall\n");
|
||||
tb_assert(read_csr(mcause) == MCAUSE_ECALL_UMODE, "Should successfully execute ecall\n");
|
||||
tb_assert(read_csr(mepc) == (uint32_t)&do_ecall, "Bad mepc\n");
|
||||
|
||||
// Make the region larger (all of memory) -- should still pass.
|
||||
|
@ -117,7 +117,7 @@ int main() {
|
|||
|
||||
enter_umode(&do_ecall);
|
||||
tb_printf("mcause = %u\n", read_csr(mcause));
|
||||
tb_assert(read_csr(mcause) == MCAUSE_ECALL, "Should successfully execute ecall\n");
|
||||
tb_assert(read_csr(mcause) == MCAUSE_ECALL_UMODE, "Should successfully execute ecall\n");
|
||||
tb_assert(read_csr(mepc) == (uint32_t)&do_ecall, "Bad mepc\n");
|
||||
|
||||
// Put another region on top, with no permissions -- should still pass
|
||||
|
@ -130,7 +130,7 @@ int main() {
|
|||
|
||||
enter_umode(&do_ecall);
|
||||
tb_printf("mcause = %u\n", read_csr(mcause));
|
||||
tb_assert(read_csr(mcause) == MCAUSE_ECALL, "Should successfully execute ecall\n");
|
||||
tb_assert(read_csr(mcause) == MCAUSE_ECALL_UMODE, "Should successfully execute ecall\n");
|
||||
tb_assert(read_csr(mepc) == (uint32_t)&do_ecall, "Bad mepc\n");
|
||||
|
||||
// Swap the two regions. Should now fail, because lower-numbered region
|
||||
|
@ -159,7 +159,7 @@ int main() {
|
|||
|
||||
enter_umode(&do_nops);
|
||||
tb_printf("mcause = %u\n", read_csr(mcause));
|
||||
tb_assert(read_csr(mcause) == MCAUSE_ECALL, "Should successfully execute ecall\n");
|
||||
tb_assert(read_csr(mcause) == MCAUSE_ECALL_UMODE, "Should successfully execute ecall\n");
|
||||
tb_assert(read_csr(mepc) == (uint32_t)&do_nops + 6, "Bad mepc\n");
|
||||
|
||||
// Now swap the order of the regions. The partial match of the
|
||||
|
@ -186,7 +186,7 @@ int main() {
|
|||
|
||||
enter_umode(&do_nops);
|
||||
tb_printf("mcause = %u\n", read_csr(mcause));
|
||||
tb_assert(read_csr(mcause) == MCAUSE_ECALL, "Should successfully execute ecall\n");
|
||||
tb_assert(read_csr(mcause) == MCAUSE_ECALL_UMODE, "Should successfully execute ecall\n");
|
||||
tb_assert(read_csr(mepc) == (uint32_t)&do_nops + 6, "Bad mepc\n");
|
||||
|
||||
tb_puts("Partial match under full match, negative overhang\n");
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
/*EXPECTED-OUTPUT***************************************************************
|
||||
|
||||
Do WFI with TW=0:
|
||||
mcause = 11 // = ecall, meaning normal exit. The test also checks mepc.
|
||||
mcause = 8 // = ecall, meaning normal exit. The test also checks mepc.
|
||||
Do WFI with TW=1:
|
||||
mstatus = 00200000 // Check TW write is reflected in readback
|
||||
mcause = 2 // = illegal instruction. The test also checks mepc.
|
||||
|
|
Loading…
Reference in New Issue