execute1: Implement trace interrupts
authorPaul Mackerras <paulus@ozlabs.org>
Fri, 28 Aug 2020 10:34:09 +0000 (20:34 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Sat, 29 Aug 2020 07:18:42 +0000 (17:18 +1000)
Trace interrupts occur when the MSR[TE] field is non-zero and an
instruction other than rfid has been successfully completed.  A trace
interrupt occurs before the next instruction is executed or any
asynchronous interrupt is taken.

Since the trace interrupt is defined to set SRR1 bits depending on
whether the traced instruction is a load or an instruction treated as
a load, or a store or an instruction treated as a store, we need to
make sure the treated-as-a-load instructions (icbi, icbt, dcbt, dcbst,
dcbf) and the treated-as-a-store instructions (dcbtst, dcbz) have the
correct opcodes in decode1.  Several of them were previously marked as
OP_NOP.

We don't yet implement the SIAR or SDAR registers, which should be set
by trace interrupts.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
common.vhdl
decode1.vhdl
execute1.vhdl

index 03211cea5807e8a2a53f0f2dd44c1d6738c567c5..1ca11785e6906a17627373cfeb14ab0b0fb7c2b4 100644 (file)
@@ -13,6 +13,8 @@ package common is
     constant MSR_SF  : integer := (63 - 0);     -- Sixty-Four bit mode
     constant MSR_EE  : integer := (63 - 48);    -- External interrupt Enable
     constant MSR_PR  : integer := (63 - 49);    -- PRoblem state
+    constant MSR_SE  : integer := (63 - 53);    -- Single-step bit of TE field
+    constant MSR_BE  : integer := (63 - 54);    -- Branch trace bit of TE field
     constant MSR_IR  : integer := (63 - 58);    -- Instruction Relocation
     constant MSR_DR  : integer := (63 - 59);    -- Data Relocation
     constant MSR_RI  : integer := (63 - 62);    -- Recoverable Interrupt
index 95446370dc1298afb90f2888bb66c93568f7da79..a7d59106fdee01929a3fad67f8f0f1db88dc1316 100644 (file)
@@ -201,10 +201,10 @@ architecture behaviour of decode1 is
         2#1000111010#  =>       (ALU,    OP_CNTZ,      NONE,       NONE,        RS,   RA,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- cnttzd
         2#1000011010#  =>       (ALU,    OP_CNTZ,      NONE,       NONE,        RS,   RA,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC,   '0', '0'), -- cnttzw
         2#1011110011#  =>       (ALU,    OP_DARN,      NONE,       NONE,        NONE, RT,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- darn
-        2#0001010110#  =>       (ALU,    OP_NOP,       NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbf
-        2#0000110110#  =>       (ALU,    OP_NOP,       NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbst
-        2#0100010110#  =>       (ALU,    OP_NOP,       NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbt
-        2#0011110110#  =>       (ALU,    OP_NOP,       NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbtst
+        2#0001010110#  =>       (ALU,    OP_DCBF,      NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbf
+        2#0000110110#  =>       (ALU,    OP_DCBST,     NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbst
+        2#0100010110#  =>       (ALU,    OP_DCBT,      NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbt
+        2#0011110110#  =>       (ALU,    OP_DCBTST,    NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbtst
         2#1111110110#  =>       (LDST,   OP_DCBZ,      RA_OR_ZERO, RB,          NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- dcbz
         2#0110001001#  =>       (ALU,    OP_DIVE,      RA,         RB,          NONE, RT,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- divdeu
         2#1110001001#  =>       (ALU,    OP_DIVE,      RA,         RB,          NONE, RT,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- divdeuo
@@ -230,7 +230,7 @@ architecture behaviour of decode1 is
         2#1101111010#  =>       (ALU,    OP_EXTSWSLI,  NONE,       CONST_SH,    RS,   RA,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- extswsli
         2#1101111011#  =>       (ALU,    OP_EXTSWSLI,  NONE,       CONST_SH,    RS,   RA,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- extswsli
         2#1111010110#  =>       (ALU,    OP_ICBI,      NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- icbi
-        2#0000010110#  =>       (ALU,    OP_NOP,       NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- icbt
+        2#0000010110#  =>       (ALU,    OP_ICBT,      NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- icbt
         2#0000001111#  =>       (ALU,    OP_ISEL,      RA_OR_ZERO, RB,          NONE, RT,   '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel
         2#0000101111#  =>       (ALU,    OP_ISEL,      RA_OR_ZERO, RB,          NONE, RT,   '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- isel
         2#0001001111#  =>       (ALU,    OP_ISEL,      RA_OR_ZERO, RB,          NONE, RT,   '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- isel
index 076c4ae45cf80068e90f7ac7fd00ad6884b1d3fd..04cc97022af0d6e0336a3d37a3921e1a2c2272c5 100644 (file)
@@ -53,6 +53,8 @@ architecture behaviour of execute1 is
         f : Execute1ToFetch1Type;
         busy: std_ulogic;
         terminate: std_ulogic;
+        trace_next : std_ulogic;
+        prev_op : insn_type_t;
        lr_update : std_ulogic;
        next_lr : std_ulogic_vector(63 downto 0);
        mul_in_progress : std_ulogic;
@@ -69,7 +71,7 @@ architecture behaviour of execute1 is
     end record;
     constant reg_type_init : reg_type :=
         (e => Execute1ToWritebackInit, f => Execute1ToFetch1Init,
-         busy => '0', lr_update => '0', terminate => '0',
+         busy => '0', lr_update => '0', terminate => '0', trace_next => '0', prev_op => OP_ILLEGAL,
          mul_in_progress => '0', mul_finish => '0', div_in_progress => '0', cntz_in_progress => '0',
          slow_op_insn => OP_ILLEGAL, slow_op_rc => '0', slow_op_oe => '0', slow_op_xerc => xerc_init,
          next_lr => (others => '0'), last_nia => (others => '0'), others => (others => '0'));
@@ -330,6 +332,7 @@ begin
         variable abs_branch : std_ulogic;
         variable spr_val : std_ulogic_vector(63 downto 0);
         variable addend : std_ulogic_vector(127 downto 0);
+        variable do_trace : std_ulogic;
     begin
        result := (others => '0');
        sum_with_carry := (others => '0');
@@ -525,6 +528,11 @@ begin
 
         v.e.mode_32bit := not ctrl.msr(MSR_SF);
 
+        do_trace := valid_in and ctrl.msr(MSR_SE);
+        if valid_in = '1' then
+            v.prev_op := e_in.insn_type;
+        end if;
+
        if ctrl.irq_state = WRITE_SRR1 then
            v.e.exc_write_reg := fast_spr_num(SPR_SRR1);
            v.e.exc_write_data := ctrl.srr1;
@@ -532,13 +540,29 @@ begin
             ctrl_tmp.msr(MSR_SF) <= '1';
             ctrl_tmp.msr(MSR_EE) <= '0';
             ctrl_tmp.msr(MSR_PR) <= '0';
+            ctrl_tmp.msr(MSR_SE) <= '0';
+            ctrl_tmp.msr(MSR_BE) <= '0';
             ctrl_tmp.msr(MSR_IR) <= '0';
             ctrl_tmp.msr(MSR_DR) <= '0';
             ctrl_tmp.msr(MSR_RI) <= '0';
             ctrl_tmp.msr(MSR_LE) <= '1';
             v.e.valid := '1';
+            v.trace_next := '0';
            report "Writing SRR1: " & to_hstring(ctrl.srr1);
 
+        elsif r.trace_next = '1' and valid_in = '1' then
+            -- Generate a trace interrupt rather than executing the next instruction
+            -- or taking any asynchronous interrupt
+            v.f.redirect_nia := std_logic_vector(to_unsigned(16#d00#, 64));
+            ctrl_tmp.srr1(63 - 33) <= '1';
+            if r.prev_op = OP_LOAD or r.prev_op = OP_ICBI or r.prev_op = OP_ICBT or
+                r.prev_op = OP_DCBT or r.prev_op = OP_DCBST or r.prev_op = OP_DCBF then
+                ctrl_tmp.srr1(63 - 35) <= '1';
+            elsif r.prev_op = OP_STORE or r.prev_op = OP_DCBZ or r.prev_op = OP_DCBTST then
+                ctrl_tmp.srr1(63 - 36) <= '1';
+            end if;
+            exception := '1';
+
        elsif irq_valid = '1' and valid_in = '1' then
            -- we need two cycles to write srr0 and 1
            -- will need more when we have to write HEIR
@@ -594,7 +618,7 @@ begin
                 else
                     illegal := '1';
                 end if;
-           when OP_NOP =>
+           when OP_NOP | OP_DCBF | OP_DCBST | OP_DCBT | OP_DCBTST | OP_ICBT =>
                -- Do nothing
            when OP_ADD | OP_CMP | OP_TRAP =>
                result := sum_with_carry(63 downto 0);
@@ -715,6 +739,9 @@ begin
                 is_branch := '1';
                 taken_branch := '1';
                 abs_branch := insn_aa(e_in.insn);
+                if ctrl.msr(MSR_BE) = '1' then
+                    do_trace := '1';
+                end if;
            when OP_BC =>
                -- read_data1 is CTR
                bo := insn_bo(e_in.insn);
@@ -727,6 +754,9 @@ begin
                 is_branch := '1';
                taken_branch := ppc_bc_taken(bo, bi, cr_in, a_in);
                 abs_branch := insn_aa(e_in.insn);
+                if ctrl.msr(MSR_BE) = '1' then
+                    do_trace := '1';
+                end if;
            when OP_BCREG =>
                -- read_data1 is CTR
                -- read_data2 is target register (CTR, LR or TAR)
@@ -740,6 +770,9 @@ begin
                 is_branch := '1';
                taken_branch := ppc_bc_taken(bo, bi, cr_in, a_in);
                 abs_branch := '1';
+                if ctrl.msr(MSR_BE) = '1' then
+                    do_trace := '1';
+                end if;
 
            when OP_RFID =>
                 v.f.virt_mode := a_in(MSR_IR) or a_in(MSR_PR);
@@ -760,6 +793,7 @@ begin
                 is_branch := '1';
                 taken_branch := '1';
                 abs_branch := '1';
+                do_trace := '0';
 
             when OP_CNTZ =>
                 v.e.valid := '0';
@@ -1135,6 +1169,10 @@ begin
             end if;
        end if;
 
+        if do_trace = '1' then
+            v.trace_next := '1';
+        end if;
+
        v.e.write_data := result;
        v.e.write_enable := result_en and not exception;