execute1: Generate privileged instruction interrupts when MSR[PR] = 1
authorPaul Mackerras <paulus@ozlabs.org>
Tue, 28 Apr 2020 09:38:58 +0000 (19:38 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Tue, 28 Apr 2020 21:48:40 +0000 (07:48 +1000)
This adds logic to execute1 to check, when MSR[PR] = 1, whether each
instruction arriving to be executed is a privileged instruction.
If it is, a privileged-instruction type program interrupt is generated.
For the mtspr and mfspr instructions, we need to look at bit 20 of the
instruction (bit 4 of the SPR number) to determine if the SPR is
privileged.

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

index 0f4eea938274e7e83738a00298828ae9e8380a00..9153b378e58c5ee5d8b8860201abadd592eb21da 100644 (file)
@@ -76,6 +76,28 @@ architecture behaviour of execute1 is
     signal x_to_divider: Execute1ToDividerType;
     signal divider_to_x: DividerToExecute1Type;
 
+    type privilege_level is (USER, SUPER);
+    type op_privilege_array is array(insn_type_t) of privilege_level;
+    constant op_privilege: op_privilege_array := (
+        OP_ATTN => SUPER,
+        OP_MFMSR => SUPER,
+        OP_MTMSRD => SUPER,
+        OP_RFID => SUPER,
+        others => USER
+        );
+
+    function instr_is_privileged(op: insn_type_t; insn: std_ulogic_vector(31 downto 0))
+        return boolean is
+    begin
+        if op_privilege(op) = SUPER then
+            return true;
+        elsif op = OP_MFSPR or op = OP_MTSPR then
+            return insn(20) = '1';
+        else
+            return false;
+        end if;
+    end;
+
     procedure set_carry(e: inout Execute1ToWritebackType;
                        carry32 : in std_ulogic;
                        carry : in std_ulogic) is
@@ -432,6 +454,16 @@ begin
            ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#900#, 64));
            ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
 
+        elsif e_in.valid = '1' and ctrl.msr(MSR_PR) = '1' and
+            instr_is_privileged(e_in.insn_type, e_in.insn) then
+            -- generate a program interrupt
+            exception := '1';
+            ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#700#, 64));
+            ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
+            -- set bit 45 to indicate privileged instruction type interrupt
+            ctrl_tmp.srr1(63 - 45) <= '1';
+            report "privileged instruction";
+            
        elsif e_in.valid = '1' then
 
            v.e.valid := '1';