mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-11 23:43:15 +00:00
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>
This commit is contained in:
parent
23b183fb16
commit
ff00dc1505
@ -529,6 +529,7 @@ package common is
|
|||||||
nia : std_ulogic_vector(63 downto 0);
|
nia : std_ulogic_vector(63 downto 0);
|
||||||
addr : std_ulogic_vector(63 downto 0);
|
addr : std_ulogic_vector(63 downto 0);
|
||||||
addr_v : std_ulogic;
|
addr_v : std_ulogic;
|
||||||
|
trace : std_ulogic;
|
||||||
occur : PMUEventType;
|
occur : PMUEventType;
|
||||||
end record;
|
end record;
|
||||||
|
|
||||||
@ -601,6 +602,8 @@ package common is
|
|||||||
type Loadstore1ToExecute1Type is record
|
type Loadstore1ToExecute1Type is record
|
||||||
busy : std_ulogic;
|
busy : std_ulogic;
|
||||||
l2stall : std_ulogic;
|
l2stall : std_ulogic;
|
||||||
|
ea_for_pmu : std_ulogic_vector(63 downto 0);
|
||||||
|
ea_valid : std_ulogic;
|
||||||
end record;
|
end record;
|
||||||
|
|
||||||
type Loadstore1ToDcacheType is record
|
type Loadstore1ToDcacheType is record
|
||||||
|
|||||||
@ -254,6 +254,7 @@ architecture behaviour of execute1 is
|
|||||||
-- PMU signals
|
-- PMU signals
|
||||||
signal x_to_pmu : Execute1ToPMUType;
|
signal x_to_pmu : Execute1ToPMUType;
|
||||||
signal pmu_to_x : PMUToExecute1Type;
|
signal pmu_to_x : PMUToExecute1Type;
|
||||||
|
signal pmu_trace : std_ulogic;
|
||||||
|
|
||||||
-- signals for logging
|
-- signals for logging
|
||||||
signal exception_log : std_ulogic;
|
signal exception_log : std_ulogic;
|
||||||
@ -560,11 +561,12 @@ begin
|
|||||||
br_mispredict => ex2.br_mispredict,
|
br_mispredict => ex2.br_mispredict,
|
||||||
others => '0');
|
others => '0');
|
||||||
x_to_pmu.nia <= e_in.nia;
|
x_to_pmu.nia <= e_in.nia;
|
||||||
x_to_pmu.addr <= (others => '0');
|
x_to_pmu.addr <= l_in.ea_for_pmu;
|
||||||
x_to_pmu.addr_v <= '0';
|
x_to_pmu.addr_v <= l_in.ea_valid;
|
||||||
x_to_pmu.spr_num <= ex1.pmu_spr_num;
|
x_to_pmu.spr_num <= ex1.pmu_spr_num;
|
||||||
x_to_pmu.spr_val <= ex1.e.write_data;
|
x_to_pmu.spr_val <= ex1.e.write_data;
|
||||||
x_to_pmu.run <= ctrl.run;
|
x_to_pmu.run <= ctrl.run;
|
||||||
|
x_to_pmu.trace <= pmu_trace;
|
||||||
|
|
||||||
-- XER forwarding. The CA and CA32 bits are only modified by instructions
|
-- 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
|
-- 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
|
-- see if we have a CIABR map
|
||||||
if ctrl.ciabr(0) = '1' and ctrl.ciabr(1) = not ex1.msr(MSR_PR) and
|
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
|
ctrl.ciabr(63 downto 2) = e_in.nia(63 downto 2) then
|
||||||
v.do_trace := '1';
|
|
||||||
v.ciabr_trace := '1';
|
v.ciabr_trace := '1';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
@ -1707,7 +1708,7 @@ begin
|
|||||||
v.e.valid := actions.complete;
|
v.e.valid := actions.complete;
|
||||||
bypass_valid := actions.bypass_valid;
|
bypass_valid := actions.bypass_valid;
|
||||||
v.taken_branch_event := actions.take_branch;
|
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.trace_ciabr := actions.ciabr_trace;
|
||||||
v.fp_exception_next := actions.fp_intr;
|
v.fp_exception_next := actions.fp_intr;
|
||||||
v.res2_sel := actions.res2_sel;
|
v.res2_sel := actions.res2_sel;
|
||||||
@ -1740,6 +1741,7 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
is_scv := go and actions.se.scv_trap;
|
is_scv := go and actions.se.scv_trap;
|
||||||
bsort_start <= go and actions.start_bsort;
|
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
|
if not HAS_FPU and ex1.div_in_progress = '1' then
|
||||||
v.div_in_progress := not divider_to_x.valid;
|
v.div_in_progress := not divider_to_x.valid;
|
||||||
|
|||||||
@ -102,6 +102,7 @@ architecture behave of loadstore1 is
|
|||||||
dword_index : std_ulogic;
|
dword_index : std_ulogic;
|
||||||
two_dwords : std_ulogic;
|
two_dwords : std_ulogic;
|
||||||
incomplete : std_ulogic;
|
incomplete : std_ulogic;
|
||||||
|
ea_valid : std_ulogic;
|
||||||
end record;
|
end record;
|
||||||
constant request_init : request_t := (valid => '0', dc_req => '0', load => '0', store => '0',
|
constant request_init : request_t := (valid => '0', dc_req => '0', load => '0', store => '0',
|
||||||
flush => '0', touch => '0', sync => '0', tlbie => '0',
|
flush => '0', touch => '0', sync => '0', tlbie => '0',
|
||||||
@ -119,7 +120,8 @@ architecture behave of loadstore1 is
|
|||||||
rc => '0', nc => '0',
|
rc => '0', nc => '0',
|
||||||
virt_mode => '0', priv_mode => '0', load_sp => '0',
|
virt_mode => '0', priv_mode => '0', load_sp => '0',
|
||||||
sprsel => "00", ric => "00", is_slbia => '0', align_intr => '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
|
type reg_stage1_t is record
|
||||||
req : request_t;
|
req : request_t;
|
||||||
@ -464,6 +466,7 @@ begin
|
|||||||
addr(63 downto 32) := (others => '0');
|
addr(63 downto 32) := (others => '0');
|
||||||
end if;
|
end if;
|
||||||
v.addr := addr;
|
v.addr := addr;
|
||||||
|
v.ea_valid := l_in.valid;
|
||||||
|
|
||||||
-- XXX Temporary hack. Mark the op as non-cachable if the address
|
-- XXX Temporary hack. Mark the op as non-cachable if the address
|
||||||
-- is the form 0xc------- for a real-mode access.
|
-- is the form 0xc------- for a real-mode access.
|
||||||
@ -509,6 +512,7 @@ begin
|
|||||||
case l_in.op is
|
case l_in.op is
|
||||||
when OP_SYNC =>
|
when OP_SYNC =>
|
||||||
v.sync := '1';
|
v.sync := '1';
|
||||||
|
v.ea_valid := '0';
|
||||||
when OP_STORE =>
|
when OP_STORE =>
|
||||||
v.store := '1';
|
v.store := '1';
|
||||||
if l_in.length = "0000" then
|
if l_in.length = "0000" then
|
||||||
@ -536,14 +540,15 @@ begin
|
|||||||
v.align_intr := v.nc;
|
v.align_intr := v.nc;
|
||||||
when OP_TLBIE =>
|
when OP_TLBIE =>
|
||||||
v.tlbie := '1';
|
v.tlbie := '1';
|
||||||
v.addr := l_in.addr2; -- address from RB for tlbie
|
|
||||||
v.is_slbia := l_in.insn(7);
|
v.is_slbia := l_in.insn(7);
|
||||||
v.mmu_op := '1';
|
v.mmu_op := '1';
|
||||||
when OP_MFSPR =>
|
when OP_MFSPR =>
|
||||||
v.read_spr := '1';
|
v.read_spr := '1';
|
||||||
|
v.ea_valid := '0';
|
||||||
when OP_MTSPR =>
|
when OP_MTSPR =>
|
||||||
v.write_spr := '1';
|
v.write_spr := '1';
|
||||||
v.mmu_op := not sprn(1);
|
v.mmu_op := not sprn(1);
|
||||||
|
v.ea_valid := '0';
|
||||||
when OP_FETCH_FAILED =>
|
when OP_FETCH_FAILED =>
|
||||||
-- send it to the MMU to do the radix walk
|
-- send it to the MMU to do the radix walk
|
||||||
v.instr_fault := '1';
|
v.instr_fault := '1';
|
||||||
@ -1067,6 +1072,9 @@ begin
|
|||||||
e_out.busy <= busy;
|
e_out.busy <= busy;
|
||||||
e_out.l2stall <= dc_stall or d_in.error or r2.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;
|
events <= r3.events;
|
||||||
|
|
||||||
flush <= exception;
|
flush <= exception;
|
||||||
|
|||||||
4
pmu.vhdl
4
pmu.vhdl
@ -183,12 +183,12 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "1100" then
|
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "1100" then
|
||||||
siar <= p_in.spr_val;
|
siar <= p_in.spr_val;
|
||||||
elsif doalert = '1' then
|
elsif doalert = '1' or p_in.trace = '1' then
|
||||||
siar <= p_in.nia;
|
siar <= p_in.nia;
|
||||||
end if;
|
end if;
|
||||||
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "1101" then
|
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "1101" then
|
||||||
sdar <= p_in.spr_val;
|
sdar <= p_in.spr_val;
|
||||||
elsif doalert = '1' then
|
elsif doalert = '1' or p_in.trace = '1' then
|
||||||
sdar <= p_in.addr;
|
sdar <= p_in.addr;
|
||||||
end if;
|
end if;
|
||||||
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "0000" then
|
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "0000" then
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user