execute1: Implement LPCR[EVIRT] bit

This implements the EVIRT bit in the LPCR register.  When set to 1,
EVIRT causes mfspr and mtspr to an undefined SPR number in privileged
mode (i.e. hypervisor mode) to cause a hypervisor emulation assistance
interrupt.  When set to 0, such instructions are executed as no-ops.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/452/head
Paul Mackerras 3 weeks ago
parent 1d758f1d74
commit 9c40ddffd2

@ -249,6 +249,7 @@ package common is
-- LPCR bit numbers -- LPCR bit numbers
constant LPCR_HAIL : integer := 63 - 37; constant LPCR_HAIL : integer := 63 - 37;
constant LPCR_UPRT : integer := 63 - 41; constant LPCR_UPRT : integer := 63 - 41;
constant LPCR_EVIRT : integer := 63 - 42;
constant LPCR_HR : integer := 63 - 43; constant LPCR_HR : integer := 63 - 43;
constant LPCR_LD : integer := 63 - 46; constant LPCR_LD : integer := 63 - 46;
constant LPCR_HEIC : integer := 63 - 59; constant LPCR_HEIC : integer := 63 - 59;
@ -322,6 +323,7 @@ package common is
hdexcr_hyp: aspect_bits_t; hdexcr_hyp: aspect_bits_t;
hdexcr_enf: aspect_bits_t; hdexcr_enf: aspect_bits_t;
lpcr_hail: std_ulogic; lpcr_hail: std_ulogic;
lpcr_evirt: std_ulogic;
lpcr_ld: std_ulogic; lpcr_ld: std_ulogic;
lpcr_heic: std_ulogic; lpcr_heic: std_ulogic;
lpcr_lpes: std_ulogic; lpcr_lpes: std_ulogic;
@ -333,7 +335,7 @@ package common is
dscr => (others => '0'), dscr => (others => '0'),
dexcr_pnh => aspect_bits_init, dexcr_pro => aspect_bits_init, dexcr_pnh => aspect_bits_init, dexcr_pro => aspect_bits_init,
hdexcr_hyp => aspect_bits_init, hdexcr_enf => aspect_bits_init, hdexcr_hyp => aspect_bits_init, hdexcr_enf => aspect_bits_init,
lpcr_hail => '0', lpcr_ld => '1', lpcr_heic => '0', lpcr_hail => '0', lpcr_evirt => '0', lpcr_ld => '1', lpcr_heic => '0',
lpcr_lpes => '0', lpcr_hvice => '0', lpcr_lpes => '0', lpcr_hvice => '0',
others => (others => '0')); others => (others => '0'));



@ -425,6 +425,7 @@ architecture behaviour of execute1 is
begin begin
ret := (others => '0'); ret := (others => '0');
ret(LPCR_HAIL) := c.lpcr_hail; ret(LPCR_HAIL) := c.lpcr_hail;
ret(LPCR_EVIRT) := c.lpcr_evirt;
ret(LPCR_UPRT) := '1'; ret(LPCR_UPRT) := '1';
ret(LPCR_HR) := '1'; ret(LPCR_HR) := '1';
ret(LPCR_LD) := c.lpcr_ld; ret(LPCR_LD) := c.lpcr_ld;
@ -1450,14 +1451,15 @@ begin
end if; end if;
else else
-- mfspr from unimplemented SPRs should be a nop in -- mfspr from unimplemented SPRs should be a nop in
-- supervisor mode and a program interrupt for user mode -- supervisor mode and a program or HEAI interrupt for user mode
-- LPCR[EVIRT] = 1 makes it HEAI in privileged mode
if e_in.valid = '1' and not is_X(e_in.insn) then if e_in.valid = '1' and not is_X(e_in.insn) then
report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) & report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
" invalid"; " invalid";
end if; end if;
slow_op := '1'; slow_op := '1';
v.e.write_enable := '0'; v.e.write_enable := '0';
if ex1.msr(MSR_PR) = '1' then if ex1.msr(MSR_PR) = '1' or ctrl.lpcr_evirt = '1' then
illegal := '1'; illegal := '1';
end if; end if;
end if; end if;
@ -1544,8 +1546,9 @@ begin
end if; end if;
if e_in.spr_select.valid = '0' and e_in.spr_is_ram = '0' then if e_in.spr_select.valid = '0' and e_in.spr_is_ram = '0' then
-- mtspr to unimplemented SPRs should be a nop in -- mtspr to unimplemented SPRs should be a nop in
-- supervisor mode and a program interrupt for user mode -- supervisor mode and a program interrupt or HEAI for user mode
if ex1.msr(MSR_PR) = '1' then -- LPCR[EVIRT] = 1 makes it HEAI in privileged mode
if ex1.msr(MSR_PR) = '1' or ctrl.lpcr_evirt = '1' then
illegal := '1'; illegal := '1';
end if; end if;
end if; end if;
@ -2185,6 +2188,7 @@ begin
end if; end if;
if ex1.se.write_lpcr = '1' then if ex1.se.write_lpcr = '1' then
ctrl_tmp.lpcr_hail <= ex1.spr_write_data(LPCR_HAIL); ctrl_tmp.lpcr_hail <= ex1.spr_write_data(LPCR_HAIL);
ctrl_tmp.lpcr_evirt <= ex1.spr_write_data(LPCR_EVIRT);
ctrl_tmp.lpcr_ld <= ex1.spr_write_data(LPCR_LD); ctrl_tmp.lpcr_ld <= ex1.spr_write_data(LPCR_LD);
ctrl_tmp.lpcr_heic <= ex1.spr_write_data(LPCR_HEIC); ctrl_tmp.lpcr_heic <= ex1.spr_write_data(LPCR_HEIC);
ctrl_tmp.lpcr_lpes <= ex1.spr_write_data(LPCR_LPES); ctrl_tmp.lpcr_lpes <= ex1.spr_write_data(LPCR_LPES);

Loading…
Cancel
Save