Commit d491878d authored by Jonathan Currier's avatar Jonathan Currier
Browse files

Introduce SPR_KAIVB for interrupt vector table relocation.

The PowerPC ISA allows for some amount of interrupt vector table
relocation, but it is defined in the context of a hypervisor.

Kestrel/microwatt does not implement hypervisor, and so lacks the
associated registers and logic.

Introduce a simple register to set the interrupt vector table base.
Kestrel arch interrupt vector base: KAIVB.

Provides mapping of 48 bits (bits 14:61) of a 16KiB aligned table.
parent a4367ece
1 merge request!1Dormito/interrupt remap v2
...@@ -43,6 +43,7 @@ package common is ...@@ -43,6 +43,7 @@ package common is
constant SPR_HSPRG1 : spr_num_t := 305; constant SPR_HSPRG1 : spr_num_t := 305;
constant SPR_PID : spr_num_t := 48; constant SPR_PID : spr_num_t := 48;
constant SPR_PRTBL : spr_num_t := 720; constant SPR_PRTBL : spr_num_t := 720;
constant SPR_KAIVB : spr_num_t := 850;
-- GPR indices in the register file (GPR only) -- GPR indices in the register file (GPR only)
subtype gpr_index_t is std_ulogic_vector(4 downto 0); subtype gpr_index_t is std_ulogic_vector(4 downto 0);
...@@ -96,6 +97,8 @@ package common is ...@@ -96,6 +97,8 @@ package common is
dec: std_ulogic_vector(63 downto 0); dec: std_ulogic_vector(63 downto 0);
msr: std_ulogic_vector(63 downto 0); msr: std_ulogic_vector(63 downto 0);
cfar: std_ulogic_vector(63 downto 0); cfar: std_ulogic_vector(63 downto 0);
-- Kestrel arch interrupt vector base: location of the interrupt vector table for kestrel
kaivb: std_ulogic_vector(61 downto 13);
irq_state : irq_state_t; irq_state : irq_state_t;
srr1: std_ulogic_vector(63 downto 0); srr1: std_ulogic_vector(63 downto 0);
end record; end record;
......
...@@ -437,11 +437,11 @@ begin ...@@ -437,11 +437,11 @@ begin
irq_valid := '0'; irq_valid := '0';
if ctrl.msr(MSR_EE) = '1' then if ctrl.msr(MSR_EE) = '1' then
if ctrl.dec(63) = '1' then if ctrl.dec(63) = '1' then
v.f.redirect_nia := std_logic_vector(to_unsigned(16#900#, 64)); v.f.redirect_nia := (61 downto 13 => ctrl.kaivb(61 downto 13), 11 downto 0 => x"900", others => '0');
report "IRQ valid: DEC"; report "IRQ valid: DEC";
irq_valid := '1'; irq_valid := '1';
elsif ext_irq_in = '1' then elsif ext_irq_in = '1' then
v.f.redirect_nia := std_logic_vector(to_unsigned(16#500#, 64)); v.f.redirect_nia := (61 downto 13 => ctrl.kaivb(61 downto 13), 11 downto 0 => x"500", others => '0');
report "IRQ valid: External"; report "IRQ valid: External";
irq_valid := '1'; irq_valid := '1';
end if; end if;
...@@ -500,7 +500,7 @@ begin ...@@ -500,7 +500,7 @@ begin
instr_is_privileged(e_in.insn_type, e_in.insn) then instr_is_privileged(e_in.insn_type, e_in.insn) then
-- generate a program interrupt -- generate a program interrupt
exception := '1'; exception := '1';
v.f.redirect_nia := std_logic_vector(to_unsigned(16#700#, 64)); v.f.redirect_nia := (61 downto 13 => ctrl.kaivb(61 downto 13), 11 downto 0 => x"700", others => '0');
-- set bit 45 to indicate privileged instruction type interrupt -- set bit 45 to indicate privileged instruction type interrupt
ctrl_tmp.srr1(63 - 45) <= '1'; ctrl_tmp.srr1(63 - 45) <= '1';
report "privileged instruction"; report "privileged instruction";
...@@ -530,7 +530,7 @@ begin ...@@ -530,7 +530,7 @@ begin
if e_in.insn(1) = '1' then if e_in.insn(1) = '1' then
exception := '1'; exception := '1';
exception_nextpc := '1'; exception_nextpc := '1';
v.f.redirect_nia := std_logic_vector(to_unsigned(16#C00#, 64)); v.f.redirect_nia := (61 downto 13 => ctrl.kaivb(61 downto 13), 11 downto 0 => x"C00", others => '0');
report "sc"; report "sc";
else else
illegal := '1'; illegal := '1';
...@@ -622,7 +622,7 @@ begin ...@@ -622,7 +622,7 @@ begin
if or (trapval and insn_to(e_in.insn)) = '1' then if or (trapval and insn_to(e_in.insn)) = '1' then
-- generate trap-type program interrupt -- generate trap-type program interrupt
exception := '1'; exception := '1';
v.f.redirect_nia := std_logic_vector(to_unsigned(16#700#, 64)); v.f.redirect_nia := (61 downto 13 => ctrl.kaivb(61 downto 13), 11 downto 0 => x"700", others => '0');
-- set bit 46 to say trap occurred -- set bit 46 to say trap occurred
ctrl_tmp.srr1(63 - 46) <= '1'; ctrl_tmp.srr1(63 - 46) <= '1';
report "trap"; report "trap";
...@@ -762,6 +762,12 @@ begin ...@@ -762,6 +762,12 @@ begin
when SPR_TBU => when SPR_TBU =>
spr_val(63 downto 32) := (others => '0'); spr_val(63 downto 32) := (others => '0');
spr_val(31 downto 0) := ctrl.tb(63 downto 32); spr_val(31 downto 0) := ctrl.tb(63 downto 32);
when SPR_KAIVB =>
if ctrl.msr(MSR_PR) = '1' then
illegal := '1';
else
spr_val(61 downto 0) := (61 downto 13 => ctrl.kaivb(61 downto 13), others => '0');
end if;
when SPR_DEC => when SPR_DEC =>
spr_val := ctrl.dec; spr_val := ctrl.dec;
when SPR_CFAR => when SPR_CFAR =>
...@@ -846,6 +852,12 @@ begin ...@@ -846,6 +852,12 @@ begin
ctrl_tmp.dec <= c_in; ctrl_tmp.dec <= c_in;
when 724 => -- LOG_ADDR SPR when 724 => -- LOG_ADDR SPR
v.log_addr_spr := c_in(31 downto 0); v.log_addr_spr := c_in(31 downto 0);
when SPR_KAIVB =>
if ctrl.msr(MSR_PR) = '1' then
illegal := '1';
else
ctrl_tmp.kaivb <= c_in(61 downto 13);
end if;
when others => when others =>
-- 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 for user mode
...@@ -989,7 +1001,7 @@ begin ...@@ -989,7 +1001,7 @@ begin
if illegal = '1' then if illegal = '1' then
exception := '1'; exception := '1';
v.f.redirect_nia := std_logic_vector(to_unsigned(16#700#, 64)); v.f.redirect_nia := (61 downto 13 => ctrl.kaivb(61 downto 13), 11 downto 0 => x"700", others => '0');
-- Since we aren't doing Hypervisor emulation assist (0xe40) we -- Since we aren't doing Hypervisor emulation assist (0xe40) we
-- set bit 44 to indicate we have an illegal -- set bit 44 to indicate we have an illegal
ctrl_tmp.srr1(63 - 44) <= '1'; ctrl_tmp.srr1(63 - 44) <= '1';
...@@ -1010,9 +1022,9 @@ begin ...@@ -1010,9 +1022,9 @@ begin
if l_in.exception = '1' then if l_in.exception = '1' then
if l_in.instr_fault = '0' then if l_in.instr_fault = '0' then
if l_in.segment_fault = '0' then if l_in.segment_fault = '0' then
v.f.redirect_nia := std_logic_vector(to_unsigned(16#300#, 64)); v.f.redirect_nia := (61 downto 13 => ctrl.kaivb(61 downto 13), 11 downto 0 => x"300", others => '0');
else else
v.f.redirect_nia := std_logic_vector(to_unsigned(16#380#, 64)); v.f.redirect_nia := (61 downto 13 => ctrl.kaivb(61 downto 13), 11 downto 0 => x"380", others => '0');
end if; end if;
else else
if l_in.segment_fault = '0' then if l_in.segment_fault = '0' then
...@@ -1020,9 +1032,9 @@ begin ...@@ -1020,9 +1032,9 @@ begin
ctrl_tmp.srr1(63 - 35) <= l_in.perm_error; -- noexec fault ctrl_tmp.srr1(63 - 35) <= l_in.perm_error; -- noexec fault
ctrl_tmp.srr1(63 - 44) <= l_in.badtree; ctrl_tmp.srr1(63 - 44) <= l_in.badtree;
ctrl_tmp.srr1(63 - 45) <= l_in.rc_error; ctrl_tmp.srr1(63 - 45) <= l_in.rc_error;
v.f.redirect_nia := std_logic_vector(to_unsigned(16#400#, 64)); v.f.redirect_nia := (61 downto 13 => ctrl.kaivb(61 downto 13), 11 downto 0 => x"400", others => '0');
else else
v.f.redirect_nia := std_logic_vector(to_unsigned(16#480#, 64)); v.f.redirect_nia := (61 downto 13 => ctrl.kaivb(61 downto 13), 11 downto 0 => x"480", others => '0');
end if; end if;
end if; end if;
v.e.exc_write_enable := '1'; v.e.exc_write_enable := '1';
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment