From 74db0710678d4871843a783edfa602ed621c91d1 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 28 Apr 2020 19:38:58 +1000 Subject: [PATCH] execute1: Generate privileged instruction interrupts when MSR[PR] = 1 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 --- execute1.vhdl | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/execute1.vhdl b/execute1.vhdl index 0f4eea9..9153b37 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -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';