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 <paulus@ozlabs.org>
pull/434/head
Paul Mackerras 1 year ago
parent e3f4ccedec
commit d2777dd1dd

@ -57,6 +57,7 @@ package common is
constant SPR_PVR : spr_num_t := 287; constant SPR_PVR : spr_num_t := 287;
constant SPR_FSCR : spr_num_t := 153; constant SPR_FSCR : spr_num_t := 153;
constant SPR_HFSCR : spr_num_t := 190; constant SPR_HFSCR : spr_num_t := 190;
constant SPR_HEIR : spr_num_t := 339;


-- PMU registers -- PMU registers
constant SPR_UPMC1 : spr_num_t := 771; constant SPR_UPMC1 : spr_num_t := 771;
@ -159,6 +160,7 @@ package common is
constant SPRSEL_CFAR : spr_selector := 4x"6"; constant SPRSEL_CFAR : spr_selector := 4x"6";
constant SPRSEL_FSCR : spr_selector := 4x"7"; constant SPRSEL_FSCR : spr_selector := 4x"7";
constant SPRSEL_HFSCR : spr_selector := 4x"8"; constant SPRSEL_HFSCR : spr_selector := 4x"8";
constant SPRSEL_HEIR : spr_selector := 4x"9";
constant SPRSEL_XER : spr_selector := 4x"f"; constant SPRSEL_XER : spr_selector := 4x"f";


-- FSCR and HFSCR bit numbers -- FSCR and HFSCR bit numbers
@ -253,6 +255,7 @@ package common is
hfscr_pref: std_ulogic; hfscr_pref: std_ulogic;
hfscr_tar: std_ulogic; hfscr_tar: std_ulogic;
hfscr_fp: std_ulogic; hfscr_fp: std_ulogic;
heir: std_ulogic_vector(63 downto 0);
end record; end record;
constant ctrl_t_init : ctrl_t := constant ctrl_t_init : ctrl_t :=
(xer_low => 18x"0", (xer_low => 18x"0",
@ -401,6 +404,7 @@ package common is
dbg_spr_access : std_ulogic; dbg_spr_access : std_ulogic;
dec_ctr : std_ulogic; dec_ctr : std_ulogic;
prefixed : std_ulogic; prefixed : std_ulogic;
prefix : std_ulogic_vector(25 downto 0);
illegal_suffix : std_ulogic; illegal_suffix : std_ulogic;
misaligned_prefix : std_ulogic; misaligned_prefix : std_ulogic;
uses_tar : 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', ramspr_wraddr => (others => '0'), ramspr_write_even => '0', ramspr_write_odd => '0',
dbg_spr_access => '0', dbg_spr_access => '0',
dec_ctr => '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')); others => (others => '0'));


type MultiplyInputType is record type MultiplyInputType is record

@ -330,6 +330,9 @@ begin
when 5x"0f" => when 5x"0f" =>
isram := '0'; isram := '0';
sel := SPRSEL_HFSCR; sel := SPRSEL_HFSCR;
when 5x"10" =>
isram := '0';
sel := SPRSEL_HEIR;
when others => when others =>
valid := '0'; valid := '0';
end case; end case;

@ -456,6 +456,8 @@ architecture behaviour of decode1 is
i.sel := SPRSEL_FSCR; i.sel := SPRSEL_FSCR;
when SPR_HFSCR => when SPR_HFSCR =>
i.sel := SPRSEL_HFSCR; i.sel := SPRSEL_HFSCR;
when SPR_HEIR =>
i.sel := SPRSEL_HEIR;
when others => when others =>
i.valid := '0'; i.valid := '0';
end case; end case;

@ -609,6 +609,7 @@ begin
end if; end if;
end if; end if;
v.e.prefixed := d_in.prefixed; v.e.prefixed := d_in.prefixed;
v.e.prefix := d_in.prefix;
v.e.illegal_suffix := d_in.illegal_suffix; v.e.illegal_suffix := d_in.illegal_suffix;
v.e.misaligned_prefix := d_in.misaligned_prefix; v.e.misaligned_prefix := d_in.misaligned_prefix;



@ -89,6 +89,8 @@ architecture behaviour of execute1 is
write_ic : std_ulogic; write_ic : std_ulogic;
write_hfscr : std_ulogic; write_hfscr : std_ulogic;
write_hic : std_ulogic; write_hic : std_ulogic;
write_heir : std_ulogic;
set_heir : std_ulogic;
end record; end record;
constant side_effect_init : side_effect_type := (others => '0'); constant side_effect_init : side_effect_type := (others => '0');


@ -147,6 +149,9 @@ architecture behaviour of execute1 is
ramspr_wraddr : ramspr_index; ramspr_wraddr : ramspr_index;
ramspr_odd_data : std_ulogic_vector(63 downto 0); ramspr_odd_data : std_ulogic_vector(63 downto 0);
ic : std_ulogic_vector(3 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; end record;
constant reg_stage1_type_init : reg_stage1_type := constant reg_stage1_type_init : reg_stage1_type :=
(e => Execute1ToWritebackInit, se => side_effect_init, (e => Execute1ToWritebackInit, se => side_effect_init,
@ -162,7 +167,8 @@ architecture behaviour of execute1 is
msr => 64x"0", msr => 64x"0",
xerc => xerc_init, xerc_valid => '0', xerc => xerc_init, xerc_valid => '0',
ramspr_wraddr => (others => '0'), ramspr_odd_data => 64x"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 type reg_stage2_type is record
e : Execute1ToWritebackType; e : Execute1ToWritebackType;
@ -679,6 +685,8 @@ begin
dbg_spr_data <= assemble_fscr(ctrl); dbg_spr_data <= assemble_fscr(ctrl);
when SPRSEL_HFSCR => when SPRSEL_HFSCR =>
dbg_spr_data <= assemble_hfscr(ctrl); dbg_spr_data <= assemble_hfscr(ctrl);
when SPRSEL_HEIR =>
dbg_spr_data <= ctrl.heir;
when others => when others =>
dbg_spr_data <= assemble_xer(xerc_in, ctrl.xer_low); dbg_spr_data <= assemble_xer(xerc_in, ctrl.xer_low);
end case; end case;
@ -1319,6 +1327,8 @@ begin
v.se.write_fscr := '1'; v.se.write_fscr := '1';
when SPRSEL_HFSCR => when SPRSEL_HFSCR =>
v.se.write_hfscr := '1'; v.se.write_hfscr := '1';
when SPRSEL_HEIR =>
v.se.write_heir := '1';
when others => when others =>
end case; end case;
end if; end if;
@ -1421,11 +1431,13 @@ begin
end if; end if;


elsif illegal = '1' then elsif illegal = '1' then
-- generate hypervisor emulation assistance interrupt (HEAI)
-- and write the offending instruction into HEIR
v.exception := '1'; v.exception := '1';
v.e.srr1(47 - 34) := e_in.prefixed; v.e.srr1(47 - 34) := e_in.prefixed;
-- Since we aren't doing Hypervisor emulation assist (0xe40) we v.e.intr_vec := 16#e40#;
-- set bit 44 to indicate we have an illegal v.e.hv_intr := '1';
v.e.srr1(47 - 44) := '1'; v.se.set_heir := '1';
if e_in.valid = '1' then if e_in.valid = '1' then
report "illegal instruction"; report "illegal instruction";
end if; end if;
@ -1495,6 +1507,9 @@ begin
v.lr_from_next := e_in.lr; v.lr_from_next := e_in.lr;
v.ramspr_odd_data := actions.ramspr_odd_data; v.ramspr_odd_data := actions.ramspr_odd_data;
v.ic := actions.ic; v.ic := actions.ic;
v.prefixed := e_in.prefixed;
v.insn := e_in.insn;
v.prefix := e_in.prefix;
end if; end if;


lv := Execute1ToLoadstore1Init; lv := Execute1ToLoadstore1Init;
@ -1752,6 +1767,7 @@ begin
ctrl.cfar when SPRSEL_CFAR, ctrl.cfar when SPRSEL_CFAR,
assemble_fscr(ctrl) when SPRSEL_FSCR, assemble_fscr(ctrl) when SPRSEL_FSCR,
assemble_hfscr(ctrl) when SPRSEL_HFSCR, assemble_hfscr(ctrl) when SPRSEL_HFSCR,
ctrl.heir when SPRSEL_HEIR,
assemble_xer(ex1.e.xerc, ctrl.xer_low) when others; assemble_xer(ex1.e.xerc, ctrl.xer_low) when others;


stage2_stall <= l_in.l2stall or fp_in.f2stall; stage2_stall <= l_in.l2stall or fp_in.f2stall;
@ -1909,6 +1925,17 @@ begin
elsif ex1.se.write_ic = '1' then elsif ex1.se.write_ic = '1' then
ctrl_tmp.fscr_ic <= ex1.ic; ctrl_tmp.fscr_ic <= ex1.ic;
end if; 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; end if;


if interrupt_in.intr = '1' then if interrupt_in.intr = '1' then

@ -550,7 +550,7 @@ static const char *fast_spr_names[] =
"lr", "ctr", "srr0", "srr1", "hsrr0", "hsrr1", "lr", "ctr", "srr0", "srr1", "hsrr0", "hsrr1",
"sprg0", "sprg1", "sprg2", "sprg3", "sprg0", "sprg1", "sprg2", "sprg3",
"hsprg0", "hsprg1", "xer", "tar", "hsprg0", "hsprg1", "xer", "tar",
"fscr", "hfscr", "fscr", "hfscr", "heir",
}; };


static const char *ldst_spr_names[] = { static const char *ldst_spr_names[] = {

@ -74,25 +74,15 @@ ill_test_1:
EXCEPTION(0x500) EXCEPTION(0x500)
EXCEPTION(0x600) EXCEPTION(0x600)


// We shouldn't get a Program interrupt at 700, so fail
. = 0x700 . = 0x700
mtsprg0 %r3 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 mfsrr0 %r3
add %r3, %r3, %r4 // skip some instructions addi %r3, %r3, 4 // skip one instruction, causing a fail
mtsrr0 %r3 mtsrr0 %r3


mfsprg0 %r3 mfsprg0 %r3
mfsprg1 %r4
rfid rfid


EXCEPTION(0x800) EXCEPTION(0x800)
@ -104,7 +94,18 @@ ill_test_1:
EXCEPTION(0xd00) EXCEPTION(0xd00)
EXCEPTION(0xe00) EXCEPTION(0xe00)
EXCEPTION(0xe20) 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(0xe60)
EXCEPTION(0xe80) EXCEPTION(0xe80)
EXCEPTION(0xf00) EXCEPTION(0xf00)

Binary file not shown.
Loading…
Cancel
Save