mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-11 23:43:15 +00:00
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>
This commit is contained in:
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…
x
Reference in New Issue
Block a user