From d2777dd1dd84a33750c934b3e8c68a9f7a58f9ae Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 15 Sep 2023 20:18:14 +1000 Subject: [PATCH] Generate Hypervisor Emulation Assistance Interrupt for illegal instructions This implements the HEIR register (Hypervisor Emulation Instruction Register) and arranges for an illegal instruction to cause a Hypervisor Emulation Assistance Interrupt (HEAI) at vector 0xE40, and set HEIR to the illegal instruction. Signed-off-by: Paul Mackerras --- common.vhdl | 7 ++++++- core_debug.vhdl | 3 +++ decode1.vhdl | 2 ++ decode2.vhdl | 1 + execute1.vhdl | 35 +++++++++++++++++++++++++++++++---- scripts/mw_debug/mw_debug.c | 2 +- tests/illegal/head.S | 29 +++++++++++++++-------------- tests/test_illegal.bin | Bin 5224 -> 5500 bytes 8 files changed, 59 insertions(+), 20 deletions(-) diff --git a/common.vhdl b/common.vhdl index 6759f8f..fa6df86 100644 --- a/common.vhdl +++ b/common.vhdl @@ -57,6 +57,7 @@ package common is constant SPR_PVR : spr_num_t := 287; constant SPR_FSCR : spr_num_t := 153; constant SPR_HFSCR : spr_num_t := 190; + constant SPR_HEIR : spr_num_t := 339; -- PMU registers constant SPR_UPMC1 : spr_num_t := 771; @@ -159,6 +160,7 @@ package common is constant SPRSEL_CFAR : spr_selector := 4x"6"; constant SPRSEL_FSCR : spr_selector := 4x"7"; constant SPRSEL_HFSCR : spr_selector := 4x"8"; + constant SPRSEL_HEIR : spr_selector := 4x"9"; constant SPRSEL_XER : spr_selector := 4x"f"; -- FSCR and HFSCR bit numbers @@ -253,6 +255,7 @@ package common is hfscr_pref: std_ulogic; hfscr_tar: std_ulogic; hfscr_fp: std_ulogic; + heir: std_ulogic_vector(63 downto 0); end record; constant ctrl_t_init : ctrl_t := (xer_low => 18x"0", @@ -401,6 +404,7 @@ package common is dbg_spr_access : std_ulogic; dec_ctr : std_ulogic; prefixed : std_ulogic; + prefix : std_ulogic_vector(25 downto 0); illegal_suffix : std_ulogic; misaligned_prefix : std_ulogic; uses_tar : std_ulogic; @@ -423,7 +427,8 @@ package common is ramspr_wraddr => (others => '0'), ramspr_write_even => '0', ramspr_write_odd => '0', dbg_spr_access => '0', dec_ctr => '0', - prefixed => '0', illegal_suffix => '0', misaligned_prefix => '0', uses_tar => '0', + prefixed => '0', prefix => (others => '0'), illegal_suffix => '0', + misaligned_prefix => '0', uses_tar => '0', others => (others => '0')); type MultiplyInputType is record diff --git a/core_debug.vhdl b/core_debug.vhdl index 8e06127..6997477 100644 --- a/core_debug.vhdl +++ b/core_debug.vhdl @@ -330,6 +330,9 @@ begin when 5x"0f" => isram := '0'; sel := SPRSEL_HFSCR; + when 5x"10" => + isram := '0'; + sel := SPRSEL_HEIR; when others => valid := '0'; end case; diff --git a/decode1.vhdl b/decode1.vhdl index fd20810..a4e4908 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -456,6 +456,8 @@ architecture behaviour of decode1 is i.sel := SPRSEL_FSCR; when SPR_HFSCR => i.sel := SPRSEL_HFSCR; + when SPR_HEIR => + i.sel := SPRSEL_HEIR; when others => i.valid := '0'; end case; diff --git a/decode2.vhdl b/decode2.vhdl index 31a4909..e7c73fa 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -609,6 +609,7 @@ begin end if; end if; v.e.prefixed := d_in.prefixed; + v.e.prefix := d_in.prefix; v.e.illegal_suffix := d_in.illegal_suffix; v.e.misaligned_prefix := d_in.misaligned_prefix; diff --git a/execute1.vhdl b/execute1.vhdl index c6c0960..b71842d 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -89,6 +89,8 @@ architecture behaviour of execute1 is write_ic : std_ulogic; write_hfscr : std_ulogic; write_hic : std_ulogic; + write_heir : std_ulogic; + set_heir : std_ulogic; end record; constant side_effect_init : side_effect_type := (others => '0'); @@ -147,6 +149,9 @@ architecture behaviour of execute1 is ramspr_wraddr : ramspr_index; ramspr_odd_data : std_ulogic_vector(63 downto 0); ic : std_ulogic_vector(3 downto 0); + prefixed : std_ulogic; + insn : std_ulogic_vector(31 downto 0); + prefix : std_ulogic_vector(25 downto 0); end record; constant reg_stage1_type_init : reg_stage1_type := (e => Execute1ToWritebackInit, se => side_effect_init, @@ -162,7 +167,8 @@ architecture behaviour of execute1 is msr => 64x"0", xerc => xerc_init, xerc_valid => '0', ramspr_wraddr => (others => '0'), ramspr_odd_data => 64x"0", - ic => x"0"); + ic => x"0", + prefixed => '0', insn => 32x"0", prefix => 26x"0"); type reg_stage2_type is record e : Execute1ToWritebackType; @@ -679,6 +685,8 @@ begin dbg_spr_data <= assemble_fscr(ctrl); when SPRSEL_HFSCR => dbg_spr_data <= assemble_hfscr(ctrl); + when SPRSEL_HEIR => + dbg_spr_data <= ctrl.heir; when others => dbg_spr_data <= assemble_xer(xerc_in, ctrl.xer_low); end case; @@ -1319,6 +1327,8 @@ begin v.se.write_fscr := '1'; when SPRSEL_HFSCR => v.se.write_hfscr := '1'; + when SPRSEL_HEIR => + v.se.write_heir := '1'; when others => end case; end if; @@ -1421,11 +1431,13 @@ begin end if; elsif illegal = '1' then + -- generate hypervisor emulation assistance interrupt (HEAI) + -- and write the offending instruction into HEIR v.exception := '1'; v.e.srr1(47 - 34) := e_in.prefixed; - -- Since we aren't doing Hypervisor emulation assist (0xe40) we - -- set bit 44 to indicate we have an illegal - v.e.srr1(47 - 44) := '1'; + v.e.intr_vec := 16#e40#; + v.e.hv_intr := '1'; + v.se.set_heir := '1'; if e_in.valid = '1' then report "illegal instruction"; end if; @@ -1495,6 +1507,9 @@ begin v.lr_from_next := e_in.lr; v.ramspr_odd_data := actions.ramspr_odd_data; v.ic := actions.ic; + v.prefixed := e_in.prefixed; + v.insn := e_in.insn; + v.prefix := e_in.prefix; end if; lv := Execute1ToLoadstore1Init; @@ -1752,6 +1767,7 @@ begin ctrl.cfar when SPRSEL_CFAR, assemble_fscr(ctrl) when SPRSEL_FSCR, assemble_hfscr(ctrl) when SPRSEL_HFSCR, + ctrl.heir when SPRSEL_HEIR, assemble_xer(ex1.e.xerc, ctrl.xer_low) when others; stage2_stall <= l_in.l2stall or fp_in.f2stall; @@ -1909,6 +1925,17 @@ begin elsif ex1.se.write_ic = '1' then ctrl_tmp.fscr_ic <= ex1.ic; end if; + if ex1.se.write_heir = '1' then + ctrl_tmp.heir <= ex1.e.write_data; + elsif ex1.se.set_heir = '1' then + ctrl_tmp.heir(31 downto 0) <= ex1.insn; + if ex1.prefixed = '1' then + ctrl_tmp.heir(63 downto 58) <= 6x"01"; + ctrl_tmp.heir(57 downto 32) <= ex1.prefix; + else + ctrl_tmp.heir(63 downto 32) <= (others => '0'); + end if; + end if; end if; if interrupt_in.intr = '1' then diff --git a/scripts/mw_debug/mw_debug.c b/scripts/mw_debug/mw_debug.c index 4cb2beb..13b5788 100644 --- a/scripts/mw_debug/mw_debug.c +++ b/scripts/mw_debug/mw_debug.c @@ -550,7 +550,7 @@ static const char *fast_spr_names[] = "lr", "ctr", "srr0", "srr1", "hsrr0", "hsrr1", "sprg0", "sprg1", "sprg2", "sprg3", "hsprg0", "hsprg1", "xer", "tar", - "fscr", "hfscr", + "fscr", "hfscr", "heir", }; static const char *ldst_spr_names[] = { diff --git a/tests/illegal/head.S b/tests/illegal/head.S index 5446d68..2f7e3d2 100644 --- a/tests/illegal/head.S +++ b/tests/illegal/head.S @@ -74,25 +74,15 @@ ill_test_1: EXCEPTION(0x500) EXCEPTION(0x600) + // We shouldn't get a Program interrupt at 700, so fail . = 0x700 mtsprg0 %r3 - mtsprg1 %r4 - - // test for bit 44 being set for ILL - mfsrr1 %r3 - li %r4, 1 - sldi %r4, %r4, (63-44) - and. %r4, %r4, %r3 - li %r4, 8 // PASS so skip 2 instructions - bne 1f - li %r4, 4 // FAIL so only skip 1 instruction. Return will catch -1: + mfsrr0 %r3 - add %r3, %r3, %r4 // skip some instructions + addi %r3, %r3, 4 // skip one instruction, causing a fail mtsrr0 %r3 mfsprg0 %r3 - mfsprg1 %r4 rfid EXCEPTION(0x800) @@ -104,7 +94,18 @@ ill_test_1: EXCEPTION(0xd00) EXCEPTION(0xe00) EXCEPTION(0xe20) - EXCEPTION(0xe40) + + // We now expect a HEAI at e40 for illegal instructions + . = 0xe40 + mthsprg0 %r3 + + mfhsrr0 %r3 + addi %r3, %r3, 8 // skip one instruction, causing success + mthsrr0 %r3 + + mfhsprg0 %r3 + hrfid + EXCEPTION(0xe60) EXCEPTION(0xe80) EXCEPTION(0xf00) diff --git a/tests/test_illegal.bin b/tests/test_illegal.bin index 727876cf46da68ffefca3b1659275b558a4f8dd1..22bbbc1190e4f44b761fcbb1a8fd791badee4350 100755 GIT binary patch literal 5500 zcmeHLzi$&)9RI$vWnWwq8L300L~srn2=ZWtO6L-zJJSZ@&;X59)a{HLsYo3XmBEhA z_=q|b6sc9k01IJ29wO8!e?VF!#MmxXr-mvE2}p!3Re;Cm`|cb&C^Z9vk?gPZ{GPu* zKi?ncCtsN843RNLlyn|OlV$AR(BY&*2|G(WDqq{k?uIVo1 zJCN;^2d}zPUK)$h;}g!6k_nsbKV@?Jg;4!-{@Qt6OH<8^kvzN-Ex8v0{`sw%o5pM~ zFB|Ya#e0F{!8uJy6OJbXh{D6W1wqaD9J>+gfab^I_X;zxx%OPyIYgn<2rbx*PXOPy z!1r~F|CQ)^Z3z11!J5ip7V=CWf7}{dG-CsgqkF^Gc_%NIA?iz+h(UC0<6|1l+z*qx zJY`e`jm|xj%xAqzPZa-<}~oKkxIuvXD!DPRR_PZvhYaef^KfLT|a(x!Xeod+7W! zJ*s>S1o~3?{obw1DrGIwiw5a_jB%>2NA*g>XVcF_^=>d5f{YC2={CVOZs!;jW#Qtc1{~VM3551J~XSM?|j|*@MydRkXI*Mgs#a~J3U{^Sn#2xLF niu0L@0w4&Z?7zcqL6_~A*r$h80M8OQfS7j^%X=*)>odIppCp}O delta 798 zcmZ`$O-vI(6#k~IFd=ALAfZVKE)^0BYHK{WD`K{g@Y51$0#T3E#tSEj9J;v8Zh#A3 zOr3;;nBYOvgYhqss{!TU$pkN61?5mYajdB_zS%HoDL~7ioZqN`9qyu!NSpYxG_UH;O-#B_!6*` zNMcna!qHRHm6rk7FFJGfwTAqZ$b~zD(-ls36#SFmEm8W9#5s~!4@X(A_!jPCX%TGc zarWhhT2=1Uq}=QefmOfAt}4U9BVaud!m6pvk`sOHkIXdTX;4^?} zL}-oJFb7PeiBH%08)gw3)JN95<9^qn)%&^Y`_%#BD1ST@F9xck)@G1fF6l7RQ+>_E z0V6Bwe{NQqhPTrZvq&4?^X@k_@9z5;w*pAlc@K;2`AMXiM)B$