Remove FIXME about considering concurrent load/store and debug entry
in calculating the privilege of load/stores. This is safe because it is only the *current* debug mode state which affects load/stores, and some new properties have been added to ensure load/stores can not be in aphase at the point debug mode is entered/exited (which is achieved by delaying the trap). Therefore there is no way for debug entry to inadvertently boost the privilege of an executing U-mode load/store. Also rename a confusingly-named signal for an unsquashable bus transfer in stage 2 that delays IRQ entry.
This commit is contained in:
		
							parent
							
								
									97bf2d06f6
								
							
						
					
					
						commit
						c81666177e
					
				| 
						 | 
				
			
			@ -324,7 +324,7 @@ reg  [W_EXCEPT-1:0]  xm_except;
 | 
			
		|||
reg                  xm_except_to_d_mode;
 | 
			
		||||
reg                  xm_sleep_wfi;
 | 
			
		||||
reg                  xm_sleep_block;
 | 
			
		||||
reg                  xm_delay_irq_entry_on_ls_dphase;
 | 
			
		||||
reg                  xm_delay_irq_entry_on_ls_stagex;
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// Stall logic
 | 
			
		||||
| 
						 | 
				
			
			@ -893,7 +893,7 @@ reg prev_instr_was_32_bit;
 | 
			
		|||
 | 
			
		||||
always @ (posedge clk or negedge rst_n) begin
 | 
			
		||||
	if (!rst_n) begin
 | 
			
		||||
		xm_delay_irq_entry_on_ls_dphase <= 1'b0;
 | 
			
		||||
		xm_delay_irq_entry_on_ls_stagex <= 1'b0;
 | 
			
		||||
		prev_instr_was_32_bit <= 1'b0;
 | 
			
		||||
	end else begin
 | 
			
		||||
		// Must hold off IRQ if we are in the second cycle of an address phase or
 | 
			
		||||
| 
						 | 
				
			
			@ -905,7 +905,7 @@ always @ (posedge clk or negedge rst_n) begin
 | 
			
		|||
		// Also hold off on AMOs, unless the AMO is transitioning to an address
 | 
			
		||||
		// phase or completing. ("completing" excludes transitions to error phase.)
 | 
			
		||||
 | 
			
		||||
		xm_delay_irq_entry_on_ls_dphase <= bus_aph_req_d && !bus_aph_ready_d ||
 | 
			
		||||
		xm_delay_irq_entry_on_ls_stagex <= bus_aph_req_d && !bus_aph_ready_d ||
 | 
			
		||||
			d_memop_is_amo && !(
 | 
			
		||||
				x_amo_phase == 3'h3 && bus_dph_ready_d && !bus_dph_err_d ||
 | 
			
		||||
				// Read reservation failure failure also generates error
 | 
			
		||||
| 
						 | 
				
			
			@ -944,7 +944,7 @@ wire m_dphase_in_flight = xm_memop != MEMOP_NONE && xm_memop != MEMOP_AMO;
 | 
			
		|||
 | 
			
		||||
// Need to delay IRQ entry on sleep exit because, for deep sleep states, we
 | 
			
		||||
// can't access the bus until the power handshake has completed.
 | 
			
		||||
wire m_delay_irq_entry = xm_delay_irq_entry_on_ls_dphase ||
 | 
			
		||||
wire m_delay_irq_entry = xm_delay_irq_entry_on_ls_stagex ||
 | 
			
		||||
	((xm_sleep_wfi || xm_sleep_block) && !m_sleep_stall_release);
 | 
			
		||||
 | 
			
		||||
wire m_pwr_allow_sleep;
 | 
			
		||||
| 
						 | 
				
			
			@ -999,6 +999,7 @@ hazard3_csr #(
 | 
			
		|||
	.trap_enter_vld             (m_trap_enter_vld),
 | 
			
		||||
	.trap_enter_rdy             (m_trap_enter_rdy),
 | 
			
		||||
	.loadstore_dphase_pending   (m_dphase_in_flight),
 | 
			
		||||
	.delay_irq_entry            (m_delay_irq_entry),
 | 
			
		||||
	.mepc_in                    (m_exception_return_addr),
 | 
			
		||||
 | 
			
		||||
	.pwr_allow_sleep            (m_pwr_allow_sleep),
 | 
			
		||||
| 
						 | 
				
			
			@ -1011,7 +1012,6 @@ hazard3_csr #(
 | 
			
		|||
	.m_mode_trap_entry          (m_mmode_trap_entry),
 | 
			
		||||
 | 
			
		||||
	// IRQ and exception requests
 | 
			
		||||
	.delay_irq_entry            (m_delay_irq_entry),
 | 
			
		||||
	.irq                        (irq),
 | 
			
		||||
	.irq_software               (soft_irq),
 | 
			
		||||
	.irq_timer                  (timer_irq),
 | 
			
		||||
| 
						 | 
				
			
			@ -1085,6 +1085,14 @@ always @ (posedge clk or negedge rst_n) begin
 | 
			
		|||
			xm_sleep_wfi <= 1'b0; // TODO needed?
 | 
			
		||||
			xm_sleep_block <= 1'b0;
 | 
			
		||||
		end
 | 
			
		||||
`ifdef HAZARD3_ASSERTIONS
 | 
			
		||||
		// Some of the exception->ls paths are cut as they are supposed to be
 | 
			
		||||
		// impossible -- make sure there is no way to have a load/store that
 | 
			
		||||
		// is not squashed. (This includes debug entry!)
 | 
			
		||||
		if (m_trap_enter_vld) begin
 | 
			
		||||
			assert(!bus_aph_req_d);
 | 
			
		||||
		end
 | 
			
		||||
`endif
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,9 +79,12 @@ module hazard3_csr #(
 | 
			
		|||
	// addresses.
 | 
			
		||||
	output wire                trap_enter_soon,
 | 
			
		||||
	// We need to know about load/stores in data phase because their exception
 | 
			
		||||
	// status is still unknown, so we fence off on them before entering debug
 | 
			
		||||
	// mode.
 | 
			
		||||
	// status is still unknown, so fence them off before entering debug mode.
 | 
			
		||||
	input  wire                loadstore_dphase_pending,
 | 
			
		||||
	// Asserted when the instruction in stage 2 can't be squashed (e.g. to
 | 
			
		||||
	// keep an AHB address phase stable), or instruction fetch request can't
 | 
			
		||||
	// be issued (e.g. waiting for wake from wfi state).
 | 
			
		||||
	input  wire                delay_irq_entry,
 | 
			
		||||
	input  wire [XLEN-1:0]     mepc_in,
 | 
			
		||||
 | 
			
		||||
	// Power control signalling
 | 
			
		||||
| 
						 | 
				
			
			@ -100,7 +103,6 @@ module hazard3_csr #(
 | 
			
		|||
	input  wire                except_to_d_mode,
 | 
			
		||||
 | 
			
		||||
	// Level-sensitive interrupt sources
 | 
			
		||||
	input  wire                delay_irq_entry,
 | 
			
		||||
	input  wire [NUM_IRQS-1:0] irq,
 | 
			
		||||
	input  wire                irq_software,
 | 
			
		||||
	input  wire                irq_timer,
 | 
			
		||||
| 
						 | 
				
			
			@ -1197,7 +1199,7 @@ wire want_halt_except = DEBUG_SUPPORT && !debug_mode && (
 | 
			
		|||
//
 | 
			
		||||
// We must mask halt_req with delay_irq_entry (true on cycle 2 and beyond of
 | 
			
		||||
// load/store address phase) because at that point we can't suppress the bus
 | 
			
		||||
// access..
 | 
			
		||||
// access. Others are fine because they are never mid-instruction in stage 2.
 | 
			
		||||
wire want_halt_irq_if_no_exception = DEBUG_SUPPORT && !debug_mode && !want_halt_except && (
 | 
			
		||||
	(dbg_req_halt_prev && !delay_irq_entry) ||
 | 
			
		||||
	(dbg_req_halt_on_reset && have_just_reset) ||
 | 
			
		||||
| 
						 | 
				
			
			@ -1299,7 +1301,6 @@ assign trap_is_irq = DEBUG_SUPPORT && (want_halt_except || want_halt_irq) ?
 | 
			
		|||
// in progress, because that dphase could subsequently except, and sample the
 | 
			
		||||
// IRQ vector PC instead of the load/store instruction PC.
 | 
			
		||||
 | 
			
		||||
// delay_irq_entry also applies to IRQ-like debug entries.
 | 
			
		||||
assign trap_enter_vld =
 | 
			
		||||
	CSR_M_TRAP && (exception_req_any ||
 | 
			
		||||
		!delay_irq_entry && !debug_mode && irq_active && !loadstore_dphase_pending) ||
 | 
			
		||||
| 
						 | 
				
			
			@ -1343,7 +1344,7 @@ assign m_mode_trap_entry = !U_MODE || (
 | 
			
		|||
// - Privilege level of load/stores on the bus
 | 
			
		||||
// - Checking load/stores against PMP read/write permission
 | 
			
		||||
 | 
			
		||||
assign m_mode_loadstore = !U_MODE || debug_mode || ( // FIXME how does this interact with load/store racing against debug entry?
 | 
			
		||||
assign m_mode_loadstore = !U_MODE || debug_mode || (
 | 
			
		||||
	mstatus_mprv ? mstatus_mpp : m_mode
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1435,6 +1436,18 @@ always @ (posedge clk) begin
 | 
			
		|||
		assert(except == EXCEPT_EBREAK);
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	// Exceptions should squash load/stores before they reach dphase.
 | 
			
		||||
	if (except != EXCEPT_NONE && !(except == EXCEPT_LOAD_FAULT || except == EXCEPT_STORE_FAULT)) begin
 | 
			
		||||
		assert(!loadstore_dphase_pending);
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	// Debug entries are trap entries! (we should also assert in core.v that
 | 
			
		||||
	// trap entries are never coincident with active load/store address
 | 
			
		||||
	// phases, which gives some confidence that debug entry does not gobble
 | 
			
		||||
	// load/stores.)
 | 
			
		||||
	if (enter_debug_mode) begin
 | 
			
		||||
		assert(trap_enter_vld);
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
`endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue