From f9dc3ecdc811dcc8b55ba3915b23c36b9e3d6052 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 20 Dec 2025 17:29:45 +1100 Subject: [PATCH 1/5] execute1: Correct FSCR[IC] value for prefix unavailable interrupt FSCR[IC] should be set to 13 for a prefix unavailable interrupt, not 11. To avoid this type of mistake, use the same symbols for setting IC as for the bit numbers in the rest of FSCR. Signed-off-by: Paul Mackerras --- execute1.vhdl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/execute1.vhdl b/execute1.vhdl index 15d5333..03f0ce3 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -1624,7 +1624,7 @@ begin -- misaligned prefixed instructions, which has higher priority than -- other facility unavailable interrupts. v.exception := '1'; - v.ic := x"b"; + v.ic := std_ulogic_vector(to_unsigned(FSCR_PREFIX, 4)); v.e.intr_vec := 16#f60#; v.se.write_ic := '1'; @@ -1666,7 +1666,7 @@ begin ctrl.fscr_scv = '0' then -- Facility unavailable for scv instruction v.exception := '1'; - v.ic := x"c"; + v.ic := std_ulogic_vector(to_unsigned(FSCR_SCV, 4)); v.e.intr_vec := 16#f60#; v.se.write_ic := '1'; @@ -1674,7 +1674,7 @@ begin ctrl.fscr_tar = '0' then -- Facility unavailable for TAR access v.exception := '1'; - v.ic := x"8"; + v.ic := std_ulogic_vector(to_unsigned(FSCR_TAR, 4)); v.e.intr_vec := 16#f60#; v.se.write_ic := '1'; @@ -1682,7 +1682,7 @@ begin ctrl.fscr_dscr = '0' then -- Facility unavailable for DSCR access v.exception := '1'; - v.ic := x"2"; + v.ic := std_ulogic_vector(to_unsigned(FSCR_DSCR, 4)); v.e.intr_vec := 16#f60#; v.se.write_ic := '1'; From c78d9b32efbfe392ac4a2b615ea575a59ab71163 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 23 Dec 2025 12:07:02 +1100 Subject: [PATCH 2/5] loadstore1: Ensure tlbie instructions get completed Since commit c938246cc8f3 ("dcache: Simplify addressing of the dcache TLB", 2025-04-05), tlbie instructions have been sent down the loadstore pipe with both req.dc_req and req.mmu_op set, so that the tlbie gets sent both to the data cache and the MMU. This is so that the relevant TLB hit signals are set correctly in the dcache for a single-page invalidation. However, this means that loadstore1 was not sending a completion to writeback for the tlbie. Normally this doesn't cause a problem, but if the tlbie is followed by an instruction that is marked 'single-pipe' in the decode1 tables, such as sync (any variant), decode2 will then stall forever waiting for the tlbie to complete before issuing the following instruction. To fix this, clear req.dc_req in the second loadstore stage for a tlbie (actually for any MMU operation, but tlbie is the only instruction that would have dc_req set). Fixes: c938246cc8f3 ("dcache: Simplify addressing of the dcache TLB", 2025-04-05) Signed-off-by: Paul Mackerras --- loadstore1.vhdl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/loadstore1.vhdl b/loadstore1.vhdl index c32781b..b280e6e 100644 --- a/loadstore1.vhdl +++ b/loadstore1.vhdl @@ -951,6 +951,13 @@ begin if r1.req.read_spr = '1' then v.addr0 := sprval; end if; + -- tlbie has req.dc_req set in order to send the TLB probe to + -- the dcache, but since there is no acknowledgement to wait for, + -- clear req.dc_req so that loadstore1_3 completes when the MMU + -- is finished. + if r1.req.mmu_op = '1' then + v.req.dc_req := '0'; + end if; -- Work out load formatter controls for next cycle for i in 0 to 7 loop From a7420c2a4d69cc2a57625fad9b96105d14a08e3d Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 27 Dec 2025 15:22:09 +1100 Subject: [PATCH 3/5] dcache: Fix bug causing load to return incorrect data If a touch is immediately followed by a load to a different address which has the same index as the touch address, and both are cache misses, it is possible for the load to be treated as if it is to the same cache line as the touch, and thus return data from the line being touched rather than the line being loaded from. For example, if the touch is to 0x1c20 and the load is to 0x2c20, and the state left in r1.store_ways by an earlier operation happens to match the PLRU victim way, the load will return data from 0x1c20. This happens because the touch completes immediately, meaning that the load gets processed before r1.store_ways and the cache tag for the line being touched have been set correctly, leading to a chance that the load can match when it shouldn't (or not match when it should). To fix this, complete the touch after one cycle, in RELOAD_WAIT_ACK state, rather than immediately. Also, for touches, consider hit_reload = 1 equivalent to a cache hit. If the line is being reloaded then the touch doesn't need to do anything. Signed-off-by: Paul Mackerras --- dcache.vhdl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/dcache.vhdl b/dcache.vhdl index a0fec63..58c464b 100644 --- a/dcache.vhdl +++ b/dcache.vhdl @@ -1121,9 +1121,9 @@ begin if r0.req.sync = '1' then req_op_sync <= '1'; elsif r0.req.touch = '1' then - if access_ok = '1' and is_hit = '0' and nc = '0' then + if access_ok = '1' and (is_hit or hit_reload) = '0' and nc = '0' then req_op_load_miss <= '1'; - elsif access_ok = '1' and is_hit = '1' and nc = '0' then + elsif access_ok = '1' and (is_hit or hit_reload) = '1' and nc = '0' then -- Make this OP_LOAD_HIT so the PLRU gets updated req_op_load_hit <= '1'; else @@ -1632,13 +1632,6 @@ begin r1.reloading <= '1'; r1.write_tag <= '1'; ev.load_miss <= '1'; - - -- If this is a touch, complete the instruction - if req.touch = '1' then - r1.full <= '0'; - r1.slow_valid <= '1'; - r1.ls_valid <= '1'; - end if; else r1.state <= NC_LOAD_WAIT_ACK; end if; @@ -1710,6 +1703,13 @@ begin r1.wb.adr <= next_row_wb_addr(r1.wb.adr); end if; + -- If this is a touch, complete the instruction + if r1.full = '1' and r1.req.touch = '1' then + r1.full <= '0'; + r1.slow_valid <= '1'; + r1.ls_valid <= '1'; + end if; + -- Incoming acks processing if wishbone_in.ack = '1' then r1.rows_valid(to_integer(r1.store_row(ROW_LINEBITS-1 downto 0))) <= '1'; From aadd22267f96b434ab67e96c440f29c30b0cc4f4 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 2 Jan 2026 17:25:27 +1100 Subject: [PATCH 4/5] execute1: Don't increment the LOG_ADDR SPR after reading it Reading the LOG_DATA SPR is supposed to increment the log address, and reading LOG_ADDR is not supposed to, but currently this is the wrong way around. Fix it. Also add a related comment. Fixes: 8f7326a8246e ("core: Implement various SPRs which read zero and ignore writes", 2025-04-10) Signed-off-by: Paul Mackerras --- execute1.vhdl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/execute1.vhdl b/execute1.vhdl index 03f0ce3..e8355b9 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -1442,8 +1442,8 @@ begin if e_in.spr_select.ispmu = '0' then case e_in.spr_select.sel is when SPRSEL_LOGR => - if e_in.insn(16) = '0' then - v.se.inc_loga := '1'; + if e_in.insn(16) = '1' then + v.se.inc_loga := '1'; -- reading LOG_DATA end if; when others => end case; @@ -1525,6 +1525,7 @@ begin when SPRSEL_DEC => v.se.write_dec := '1'; when SPRSEL_LOGR => + -- must be writing LOG_ADDR; LOG_DATA is readonly v.se.write_loga := '1'; when SPRSEL_CFAR => v.se.write_cfar := '1'; From 84eebf5c7caa180d9e3a9f58a85f73a20ca3e69f Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 2 Jan 2026 17:29:33 +1100 Subject: [PATCH 5/5] execute1: Fix bug causing SRR0 to be set to 4 more than the correct value If an scv (or sc) instruction is executed and an asynchronous interrupt occurs on the following instruction (e.g. the first instruction of the scv handler), the address written to SRR0 will be the address of that following instruction + 4. The reason is that ex1.advance_nia will still be set from the execution of the sc[v]. Fix this by clearing v.advance_nia in execute1_1. (This only shows up for asynchronous interrupts with scv, not sc, because sc clears MSR[EE]. It should show up for synchronous interrupts with both sc and scv, but that has not been demonstrated.) Signed-off-by: Paul Mackerras --- execute1.vhdl | 1 + 1 file changed, 1 insertion(+) diff --git a/execute1.vhdl b/execute1.vhdl index e8355b9..a751523 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -1734,6 +1734,7 @@ begin v.prefixed := e_in.prefixed; v.insn := e_in.insn; v.prefix := e_in.prefix; + v.advance_nia := '0'; end if; lv := Execute1ToLoadstore1Init;