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_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

@ -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;

@ -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;

@ -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;


@ -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

@ -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[] = {

@ -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)

Binary file not shown.
Loading…
Cancel
Save