loadstore1: Fix reading of PIDR and PTCR via debug interface

Commit 0a11e8455f ("core: Implement hashst and hashchk
instructions", 2025-01-23) expanded the SPR selector used in
loadstore1 from 3 to 4 bits because the addition of the hash key SPR
took the number of SPRs to be addressed from 8 to 9.  In the process,
PTCR and PIDR moved from 0/1 to 8/9, but the assignment of sprsel from
dbg_spr_addr in the loadstore1_2 process wasn't updated to reflect
this.  As it happened, the hash key SPRs were subsequently moved into
the SPR RAM, reducing the number of SPRs in loadstore1 back to 8.
Also, the SPR select bit sent to the MMU never depended on dbg_spr_addr,
meaning that reading PTCR and PIDR via the debug interface would have
randomly supplied one or the other.

To fix this, revert the part of commit 0a11e8455f which expanded
the sprsel fields and variables, reducing them back to 3 bits and
restoring PTCR/PIDR to the 0/1 encodings.  Also make the SPR read
address sent to the MMU come from dbg_spr_addr when we are not
executing an mfspr in loadstore1.  With this, PTCR and PIDR can be
read correctly via the debug interface.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/462/head
Paul Mackerras 1 month ago
parent efd0571b5f
commit 969c6c335f

@ -99,7 +99,7 @@ architecture behave of loadstore1 is
virt_mode : std_ulogic; virt_mode : std_ulogic;
priv_mode : std_ulogic; priv_mode : std_ulogic;
load_sp : std_ulogic; load_sp : std_ulogic;
sprsel : std_ulogic_vector(3 downto 0); sprsel : std_ulogic_vector(2 downto 0);
ric : std_ulogic_vector(1 downto 0); ric : std_ulogic_vector(1 downto 0);
is_slbia : std_ulogic; is_slbia : std_ulogic;
align_intr : std_ulogic; align_intr : std_ulogic;
@ -116,7 +116,7 @@ architecture behave of loadstore1 is
write_reg => 6x"00", length => x"0", write_reg => 6x"00", length => x"0",
elt_length => x"0", brev_mask => "000", elt_length => x"0", brev_mask => "000",
xerc => xerc_init, xerc => xerc_init,
sprsel => "0000", ric => "00", sprsel => "000", ric => "00",
hash_addr => 64x"0", hash_addr => 64x"0",
others => '0'); others => '0');


@ -140,7 +140,7 @@ architecture behave of loadstore1 is
one_cycle : std_ulogic; one_cycle : std_ulogic;
wr_sel : std_ulogic_vector(1 downto 0); wr_sel : std_ulogic_vector(1 downto 0);
addr0 : std_ulogic_vector(63 downto 0); addr0 : std_ulogic_vector(63 downto 0);
sprsel : std_ulogic_vector(3 downto 0); sprsel : std_ulogic_vector(2 downto 0);
dbg_spr : std_ulogic_vector(63 downto 0); dbg_spr : std_ulogic_vector(63 downto 0);
dbg_spr_ack: std_ulogic; dbg_spr_ack: std_ulogic;
end record; end record;
@ -351,7 +351,7 @@ begin
r1.req.instr_fault <= '0'; r1.req.instr_fault <= '0';
r1.req.load <= '0'; r1.req.load <= '0';
r1.req.priv_mode <= '0'; r1.req.priv_mode <= '0';
r1.req.sprsel <= "0000"; r1.req.sprsel <= "000";
r1.req.ric <= "00"; r1.req.ric <= "00";
r1.req.xerc <= xerc_init; r1.req.xerc <= xerc_init;
r1.dawr_ll <= (others => '0'); r1.dawr_ll <= (others => '0');
@ -365,7 +365,7 @@ begin
r2.req.instr_fault <= '0'; r2.req.instr_fault <= '0';
r2.req.load <= '0'; r2.req.load <= '0';
r2.req.priv_mode <= '0'; r2.req.priv_mode <= '0';
r2.req.sprsel <= "0000"; r2.req.sprsel <= "000";
r2.req.ric <= "00"; r2.req.ric <= "00";
r2.req.xerc <= xerc_init; r2.req.xerc <= xerc_init;


@ -592,13 +592,13 @@ begin
v.ric := l_in.insn(19 downto 18); v.ric := l_in.insn(19 downto 18);
if sprn(8 downto 7) = "01" then if sprn(8 downto 7) = "01" then
-- debug registers DAWR[X][01] -- debug registers DAWR[X][01]
v.sprsel := "01" & sprn(3) & sprn(0); v.sprsel := "1" & sprn(3) & sprn(0);
elsif sprn(1) = '1' then elsif sprn(1) = '1' then
-- DSISR and DAR -- DSISR and DAR
v.sprsel := "001" & sprn(0); v.sprsel := "01" & sprn(0);
else else
-- PID and PTCR -- PID and PTCR
v.sprsel := "100" & sprn(8); v.sprsel := "00" & sprn(8);
end if; end if;


disp := l_in.addr2; disp := l_in.addr2;
@ -861,7 +861,7 @@ begin
variable byte_offset : unsigned(2 downto 0); variable byte_offset : unsigned(2 downto 0);
variable interrupt : std_ulogic; variable interrupt : std_ulogic;
variable dbg_spr_rd : std_ulogic; variable dbg_spr_rd : std_ulogic;
variable sprsel : std_ulogic_vector(3 downto 0); variable sprsel : std_ulogic_vector(2 downto 0);
variable sprval : std_ulogic_vector(63 downto 0); variable sprval : std_ulogic_vector(63 downto 0);
variable dawr_match : std_ulogic; variable dawr_match : std_ulogic;
begin begin
@ -896,28 +896,24 @@ begin
if dbg_spr_rd = '0' then if dbg_spr_rd = '0' then
sprsel := r1.req.sprsel; sprsel := r1.req.sprsel;
else else
sprsel := "00" & dbg_spr_addr; sprsel := "0" & dbg_spr_addr;
end if;
if sprsel(3) = '1' then
sprval := m_in.sprval; -- MMU regs
else
case sprsel(2 downto 0) is
when "100" =>
sprval := r3.dawr(0) & "000";
when "101" =>
sprval := r3.dawr(1) & "000";
when "110" =>
sprval := 48x"0" & r3.dawrx(0);
when "111" =>
sprval := 48x"0" & r3.dawrx(1);
when "010" =>
sprval := x"00000000" & r3.dsisr;
when "011" =>
sprval := r3.dar;
when others =>
sprval := (others => '0');
end case;
end if; end if;
case sprsel is
when "100" =>
sprval := r3.dawr(0) & "000";
when "101" =>
sprval := r3.dawr(1) & "000";
when "110" =>
sprval := 48x"0" & r3.dawrx(0);
when "111" =>
sprval := 48x"0" & r3.dawrx(1);
when "010" =>
sprval := x"00000000" & r3.dsisr;
when "011" =>
sprval := r3.dar;
when others =>
sprval := m_in.sprval; -- MMU regs
end case;
if dbg_spr_req = '0' then if dbg_spr_req = '0' then
v.dbg_spr_ack := '0'; v.dbg_spr_ack := '0';
elsif dbg_spr_rd = '1' and r2.dbg_spr_ack = '0' then elsif dbg_spr_rd = '1' and r2.dbg_spr_ack = '0' then
@ -1143,21 +1139,21 @@ begin
write_enable := '1'; write_enable := '1';
end if; end if;
if r2.req.write_spr = '1' then if r2.req.write_spr = '1' then
if r2.req.sprsel(3 downto 2) = "01" then if r2.req.sprsel(2) = '1' then
v.dawr_upd := '1'; v.dawr_upd := '1';
end if; end if;
case r2.req.sprsel is case r2.req.sprsel is
when "0100" => when "100" =>
v.dawr(0) := r2.req.store_data(63 downto 3); v.dawr(0) := r2.req.store_data(63 downto 3);
when "0101" => when "101" =>
v.dawr(1) := r2.req.store_data(63 downto 3); v.dawr(1) := r2.req.store_data(63 downto 3);
when "0110" => when "110" =>
v.dawrx(0) := r2.req.store_data(15 downto 0); v.dawrx(0) := r2.req.store_data(15 downto 0);
when "0111" => when "111" =>
v.dawrx(1) := r2.req.store_data(15 downto 0); v.dawrx(1) := r2.req.store_data(15 downto 0);
when "0010" => when "010" =>
v.dsisr := r2.req.store_data(31 downto 0); v.dsisr := r2.req.store_data(31 downto 0);
when "0011" => when "011" =>
v.dar := r2.req.store_data; v.dar := r2.req.store_data;
when others => when others =>
end case; end case;
@ -1327,11 +1323,15 @@ begin
m_out.tlbie <= r2.req.tlbie; m_out.tlbie <= r2.req.tlbie;
m_out.ric <= r2.req.ric; m_out.ric <= r2.req.ric;
m_out.mtspr <= mmu_mtspr; m_out.mtspr <= mmu_mtspr;
m_out.sprnf <= r1.req.sprsel(0);
m_out.sprnt <= r2.req.sprsel(0); m_out.sprnt <= r2.req.sprsel(0);
m_out.addr <= r2.req.addr; m_out.addr <= r2.req.addr;
m_out.slbia <= r2.req.is_slbia; m_out.slbia <= r2.req.is_slbia;
m_out.rs <= r2.req.store_data; m_out.rs <= r2.req.store_data;
if r1.req.valid = '1' and r1.req.read_spr = '1' then
m_out.sprnf <= r1.req.sprsel(0);
else
m_out.sprnf <= dbg_spr_addr(0);
end if;


-- Update outputs to writeback -- Update outputs to writeback
l_out.valid <= complete; l_out.valid <= complete;

Loading…
Cancel
Save