Fix bad mepc reported after branching to a branch in a no-X address range
This commit is contained in:
		
							parent
							
								
									cd3125b6e5
								
							
						
					
					
						commit
						f2876eb51f
					
				| 
						 | 
					@ -712,13 +712,13 @@ end
 | 
				
			||||||
endgenerate
 | 
					endgenerate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Be careful not to take branches whose comparisons depend on a load result
 | 
					// Be careful not to take branches whose comparisons depend on a load result
 | 
				
			||||||
wire x_jump_req_if_aligned = !x_stall_on_raw && (
 | 
					wire x_jump_req_unchecked = !x_stall_on_raw && (
 | 
				
			||||||
	d_branchcond == BCOND_ALWAYS ||
 | 
						d_branchcond == BCOND_ALWAYS ||
 | 
				
			||||||
	d_branchcond == BCOND_ZERO && !x_branch_cmp ||
 | 
						d_branchcond == BCOND_ZERO && !x_branch_cmp ||
 | 
				
			||||||
	d_branchcond == BCOND_NZERO && x_branch_cmp
 | 
						d_branchcond == BCOND_NZERO && x_branch_cmp
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
assign x_jump_req = x_jump_req_if_aligned && !x_jump_misaligned;
 | 
					assign x_jump_req = x_jump_req_unchecked && !x_jump_misaligned && !x_exec_pmp_fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Memory protection
 | 
					// Memory protection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -807,8 +807,8 @@ end
 | 
				
			||||||
wire [W_ADDR-1:0] m_exception_return_addr;
 | 
					wire [W_ADDR-1:0] m_exception_return_addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
wire [W_EXCEPT-1:0] x_except =
 | 
					wire [W_EXCEPT-1:0] x_except =
 | 
				
			||||||
	x_jump_req_if_aligned && x_jump_misaligned               ? EXCEPT_INSTR_MISALIGN :
 | 
					 | 
				
			||||||
	x_exec_pmp_fail                                          ? EXCEPT_INSTR_FAULT    :
 | 
						x_exec_pmp_fail                                          ? EXCEPT_INSTR_FAULT    :
 | 
				
			||||||
 | 
						x_jump_req_unchecked && x_jump_misaligned                ? EXCEPT_INSTR_MISALIGN :
 | 
				
			||||||
	x_csr_illegal_access                                     ? EXCEPT_INSTR_ILLEGAL  :
 | 
						x_csr_illegal_access                                     ? EXCEPT_INSTR_ILLEGAL  :
 | 
				
			||||||
	|EXTENSION_A && x_unaligned_addr &&  d_memop_is_amo      ? EXCEPT_STORE_ALIGN    :
 | 
						|EXTENSION_A && x_unaligned_addr &&  d_memop_is_amo      ? EXCEPT_STORE_ALIGN    :
 | 
				
			||||||
	|EXTENSION_A && x_amo_phase == 3'h4 && x_unaligned_addr  ? EXCEPT_STORE_ALIGN    :
 | 
						|EXTENSION_A && x_amo_phase == 3'h4 && x_unaligned_addr  ? EXCEPT_STORE_ALIGN    :
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,9 @@
 | 
				
			||||||
// the lowest-numbered matching region. Check that partial region matches
 | 
					// the lowest-numbered matching region. Check that partial region matches
 | 
				
			||||||
// cause failure no matter the permission, unless there is a lower-numbered
 | 
					// cause failure no matter the permission, unless there is a lower-numbered
 | 
				
			||||||
// fully matching region.
 | 
					// fully matching region.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Check that jumping to a branch in non-X-permitted memory points mepc at the
 | 
				
			||||||
 | 
					// branch, not its target (known corner case)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*EXPECTED-OUTPUT***************************************************************
 | 
					/*EXPECTED-OUTPUT***************************************************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,6 +30,8 @@ Full match under partial match, negative overhang
 | 
				
			||||||
mcause = 11
 | 
					mcause = 11
 | 
				
			||||||
Partial match under full match, negative overhang
 | 
					Partial match under full match, negative overhang
 | 
				
			||||||
mcause = 1
 | 
					mcause = 1
 | 
				
			||||||
 | 
					Jump to bad jump
 | 
				
			||||||
 | 
					OK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
*******************************************************************************/
 | 
					*******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,6 +68,26 @@ void __attribute__((aligned(4), naked)) do_nops() {
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void __attribute__((naked)) do_jump() {
 | 
				
			||||||
 | 
						asm (
 | 
				
			||||||
 | 
							"j 1f\n"
 | 
				
			||||||
 | 
							"nop\n"
 | 
				
			||||||
 | 
							"nop\n"
 | 
				
			||||||
 | 
							"nop\n"
 | 
				
			||||||
 | 
							"nop\n"
 | 
				
			||||||
 | 
							"nop\n"
 | 
				
			||||||
 | 
							"nop\n"
 | 
				
			||||||
 | 
							"nop\n"
 | 
				
			||||||
 | 
							"nop\n"
 | 
				
			||||||
 | 
							"nop\n"
 | 
				
			||||||
 | 
							"nop\n"
 | 
				
			||||||
 | 
							"nop\n"
 | 
				
			||||||
 | 
							"nop\n"
 | 
				
			||||||
 | 
							"1:\n"
 | 
				
			||||||
 | 
							"ret\n"
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MCAUSE_INSTR_FAULT 1
 | 
					#define MCAUSE_INSTR_FAULT 1
 | 
				
			||||||
#define MCAUSE_ECALL 11
 | 
					#define MCAUSE_ECALL 11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -175,5 +200,12 @@ int main() {
 | 
				
			||||||
	tb_assert(read_csr(mcause) == MCAUSE_INSTR_FAULT, "Should get instruction fault on partial match\n");
 | 
						tb_assert(read_csr(mcause) == MCAUSE_INSTR_FAULT, "Should get instruction fault on partial match\n");
 | 
				
			||||||
	tb_assert(read_csr(mepc) == (uint32_t)&do_nops + 2, "Bad mepc\n");
 | 
						tb_assert(read_csr(mepc) == (uint32_t)&do_nops + 2, "Bad mepc\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tb_puts("Jump to bad jump\n");
 | 
				
			||||||
 | 
						write_pmpcfg(0, 0);
 | 
				
			||||||
 | 
						write_pmpcfg(1, 0);
 | 
				
			||||||
 | 
						enter_umode(&do_jump);
 | 
				
			||||||
 | 
						tb_assert(read_csr(mepc) == (uint32_t)&do_jump, "Bad mepc\n");
 | 
				
			||||||
 | 
						tb_puts("OK\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue