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
......@@ -43,6 +43,7 @@ package common is
constant SPR_HSPRG1 : spr_num_t := 305;
constant SPR_PID : spr_num_t := 48;
constant SPR_PRTBL : spr_num_t := 720;
constant SPR_KAIVB : spr_num_t := 850;
-- GPR indices in the register file (GPR only)
subtype gpr_index_t is std_ulogic_vector(4 downto 0);
......@@ -96,6 +97,8 @@ package common is
dec: std_ulogic_vector(63 downto 0);
msr: 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;
srr1: std_ulogic_vector(63 downto 0);
end record;
......
......@@ -437,11 +437,11 @@ begin
irq_valid := '0';
if ctrl.msr(MSR_EE) = '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";
irq_valid := '1';
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";
irq_valid := '1';
end if;
......@@ -500,7 +500,7 @@ begin
instr_is_privileged(e_in.insn_type, e_in.insn) then
-- generate a program interrupt
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
ctrl_tmp.srr1(63 - 45) <= '1';
report "privileged instruction";
......@@ -530,7 +530,7 @@ begin
if e_in.insn(1) = '1' then
exception := '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";
else
illegal := '1';
......@@ -622,7 +622,7 @@ begin
if or (trapval and insn_to(e_in.insn)) = '1' then
-- generate trap-type program interrupt
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
ctrl_tmp.srr1(63 - 46) <= '1';
report "trap";
......@@ -762,6 +762,12 @@ begin
when SPR_TBU =>
spr_val(63 downto 32) := (others => '0');
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 =>
spr_val := ctrl.dec;
when SPR_CFAR =>
......@@ -846,6 +852,12 @@ begin
ctrl_tmp.dec <= c_in;
when 724 => -- LOG_ADDR SPR
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 =>
-- mtspr to unimplemented SPRs should be a nop in
-- supervisor mode and a program interrupt for user mode
......@@ -989,7 +1001,7 @@ begin
if illegal = '1' then
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
-- set bit 44 to indicate we have an illegal
ctrl_tmp.srr1(63 - 44) <= '1';
......@@ -1010,9 +1022,9 @@ begin
if l_in.exception = '1' then
if l_in.instr_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
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;
else
if l_in.segment_fault = '0' then
......@@ -1020,9 +1032,9 @@ begin
ctrl_tmp.srr1(63 - 35) <= l_in.perm_error; -- noexec fault
ctrl_tmp.srr1(63 - 44) <= l_in.badtree;
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
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;
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