loadstore1: Fix reading of PIDR and PTCR via debug interface (#462)

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>
master
Paul Mackerras 3 days ago committed by GitHub
parent efd0571b5f
commit 6081646638
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -99,7 +99,7 @@ architecture behave of loadstore1 is
virt_mode : std_ulogic;
priv_mode : 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);
is_slbia : std_ulogic;
align_intr : std_ulogic;
@ -116,7 +116,7 @@ architecture behave of loadstore1 is
write_reg => 6x"00", length => x"0",
elt_length => x"0", brev_mask => "000",
xerc => xerc_init,
sprsel => "0000", ric => "00",
sprsel => "000", ric => "00",
hash_addr => 64x"0",
others => '0');

@ -140,7 +140,7 @@ architecture behave of loadstore1 is
one_cycle : std_ulogic;
wr_sel : std_ulogic_vector(1 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_ack: std_ulogic;
end record;
@ -351,7 +351,7 @@ begin
r1.req.instr_fault <= '0';
r1.req.load <= '0';
r1.req.priv_mode <= '0';
r1.req.sprsel <= "0000";
r1.req.sprsel <= "000";
r1.req.ric <= "00";
r1.req.xerc <= xerc_init;
r1.dawr_ll <= (others => '0');
@ -365,7 +365,7 @@ begin
r2.req.instr_fault <= '0';
r2.req.load <= '0';
r2.req.priv_mode <= '0';
r2.req.sprsel <= "0000";
r2.req.sprsel <= "000";
r2.req.ric <= "00";
r2.req.xerc <= xerc_init;

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

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

Loading…
Cancel
Save