PMU: Fix setting of SIAR and SDAR on trace interrupt

This arranges for SIAR and SDAR to be set when a trace interrupt
is triggered by a non-zero setting of the MSR[TE] field.  According to
the ISA, SIAR should be set to the address of the instruction and SDAR
should be set to the effective address of its storage operand if any.
This also fixes setting of SDAR by the PMU when an alert occurs;
previously it was always just set to zero.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/435/head
Paul Mackerras 5 days ago
parent 23b183fb16
commit ff00dc1505

@ -529,6 +529,7 @@ package common is
nia : std_ulogic_vector(63 downto 0);
addr : std_ulogic_vector(63 downto 0);
addr_v : std_ulogic;
trace : std_ulogic;
occur : PMUEventType;
end record;

@ -601,6 +602,8 @@ package common is
type Loadstore1ToExecute1Type is record
busy : std_ulogic;
l2stall : std_ulogic;
ea_for_pmu : std_ulogic_vector(63 downto 0);
ea_valid : std_ulogic;
end record;

type Loadstore1ToDcacheType is record

@ -254,6 +254,7 @@ architecture behaviour of execute1 is
-- PMU signals
signal x_to_pmu : Execute1ToPMUType;
signal pmu_to_x : PMUToExecute1Type;
signal pmu_trace : std_ulogic;

-- signals for logging
signal exception_log : std_ulogic;
@ -560,11 +561,12 @@ begin
br_mispredict => ex2.br_mispredict,
others => '0');
x_to_pmu.nia <= e_in.nia;
x_to_pmu.addr <= (others => '0');
x_to_pmu.addr_v <= '0';
x_to_pmu.addr <= l_in.ea_for_pmu;
x_to_pmu.addr_v <= l_in.ea_valid;
x_to_pmu.spr_num <= ex1.pmu_spr_num;
x_to_pmu.spr_val <= ex1.e.write_data;
x_to_pmu.run <= ctrl.run;
x_to_pmu.trace <= pmu_trace;

-- XER forwarding. The CA and CA32 bits are only modified by instructions
-- that are handled here, so for them we can just use the result most
@ -1163,7 +1165,6 @@ begin
-- see if we have a CIABR map
if ctrl.ciabr(0) = '1' and ctrl.ciabr(1) = not ex1.msr(MSR_PR) and
ctrl.ciabr(63 downto 2) = e_in.nia(63 downto 2) then
v.do_trace := '1';
v.ciabr_trace := '1';
end if;

@ -1707,7 +1708,7 @@ begin
v.e.valid := actions.complete;
bypass_valid := actions.bypass_valid;
v.taken_branch_event := actions.take_branch;
v.trace_next := actions.do_trace;
v.trace_next := actions.do_trace or actions.ciabr_trace;
v.trace_ciabr := actions.ciabr_trace;
v.fp_exception_next := actions.fp_intr;
v.res2_sel := actions.res2_sel;
@ -1740,6 +1741,7 @@ begin
end if;
is_scv := go and actions.se.scv_trap;
bsort_start <= go and actions.start_bsort;
pmu_trace <= go and actions.do_trace;

if not HAS_FPU and ex1.div_in_progress = '1' then
v.div_in_progress := not divider_to_x.valid;

@ -102,6 +102,7 @@ architecture behave of loadstore1 is
dword_index : std_ulogic;
two_dwords : std_ulogic;
incomplete : std_ulogic;
ea_valid : std_ulogic;
end record;
constant request_init : request_t := (valid => '0', dc_req => '0', load => '0', store => '0',
flush => '0', touch => '0', sync => '0', tlbie => '0',
@ -119,7 +120,8 @@ architecture behave of loadstore1 is
rc => '0', nc => '0',
virt_mode => '0', priv_mode => '0', load_sp => '0',
sprsel => "00", ric => "00", is_slbia => '0', align_intr => '0',
dword_index => '0', two_dwords => '0', incomplete => '0');
dword_index => '0', two_dwords => '0', incomplete => '0',
ea_valid => '0');

type reg_stage1_t is record
req : request_t;
@ -464,6 +466,7 @@ begin
addr(63 downto 32) := (others => '0');
end if;
v.addr := addr;
v.ea_valid := l_in.valid;

-- XXX Temporary hack. Mark the op as non-cachable if the address
-- is the form 0xc------- for a real-mode access.
@ -509,6 +512,7 @@ begin
case l_in.op is
when OP_SYNC =>
v.sync := '1';
v.ea_valid := '0';
when OP_STORE =>
v.store := '1';
if l_in.length = "0000" then
@ -536,14 +540,15 @@ begin
v.align_intr := v.nc;
when OP_TLBIE =>
v.tlbie := '1';
v.addr := l_in.addr2; -- address from RB for tlbie
v.is_slbia := l_in.insn(7);
v.mmu_op := '1';
when OP_MFSPR =>
v.read_spr := '1';
v.ea_valid := '0';
when OP_MTSPR =>
v.write_spr := '1';
v.mmu_op := not sprn(1);
v.ea_valid := '0';
when OP_FETCH_FAILED =>
-- send it to the MMU to do the radix walk
v.instr_fault := '1';
@ -1067,6 +1072,9 @@ begin
e_out.busy <= busy;
e_out.l2stall <= dc_stall or d_in.error or r2.busy;

e_out.ea_for_pmu <= req_in.addr;
e_out.ea_valid <= req_in.ea_valid;

events <= r3.events;

flush <= exception;

@ -183,12 +183,12 @@ begin
end if;
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "1100" then
siar <= p_in.spr_val;
elsif doalert = '1' then
elsif doalert = '1' or p_in.trace = '1' then
siar <= p_in.nia;
end if;
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "1101" then
sdar <= p_in.spr_val;
elsif doalert = '1' then
elsif doalert = '1' or p_in.trace = '1' then
sdar <= p_in.addr;
end if;
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "0000" then

Loading…
Cancel
Save