mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-03-10 12:28:45 +00:00
Implement hrfid and make MSR[HV] always 1
Implementations without hypervisor/LPAR support are permitted by the architecture, but should have MSR[HV] forced to be 1 at all times, not 0, and should implement various instructions and registers that are only accessible in hypervisor mode. This commit implements MSR[HV] as a constant 1 bit and adds the hrfid instruction, which behaves exactly the same as rfid except that it reads HSRR0/1 instead of SRR0/1. We already have HSRR0/1 and HSPRG0/1 implemented. When HV=1, Linux expects external interrupts to arrive as hypervisor interrupts, so this adds support for hypervisor interrupts (i.e., those that set HSRR0/1) and makes the external interrupt be a hypervisor interrupt. (If we had an LPCR register, the LPES bit would control this, but we don't.) The xics test is updated to read HSRR0/1 after an external interrupt. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
10
common.vhdl
10
common.vhdl
@@ -12,6 +12,7 @@ package common is
|
||||
|
||||
-- MSR bit numbers
|
||||
constant MSR_SF : integer := (63 - 0); -- Sixty-Four bit mode
|
||||
constant MSR_HV : integer := (63 - 3); -- Hypervisor mode (always 1)
|
||||
constant MSR_EE : integer := (63 - 48); -- External interrupt Enable
|
||||
constant MSR_PR : integer := (63 - 49); -- PRoblem state
|
||||
constant MSR_FP : integer := (63 - 50); -- Floating Point available
|
||||
@@ -662,6 +663,7 @@ package common is
|
||||
write_xerc_enable : std_ulogic;
|
||||
xerc : xer_common_t;
|
||||
interrupt : std_ulogic;
|
||||
hv_intr : std_ulogic;
|
||||
intr_vec : intr_vector_t;
|
||||
redirect: std_ulogic;
|
||||
redir_mode: std_ulogic_vector(3 downto 0);
|
||||
@@ -678,7 +680,8 @@ package common is
|
||||
write_xerc_enable => '0', xerc => xerc_init,
|
||||
write_data => (others => '0'), write_cr_mask => (others => '0'),
|
||||
write_cr_data => (others => '0'), write_reg => (others => '0'),
|
||||
interrupt => '0', intr_vec => 0, redirect => '0', redir_mode => "0000",
|
||||
interrupt => '0', hv_intr => '0', intr_vec => 0,
|
||||
redirect => '0', redir_mode => "0000",
|
||||
last_nia => (others => '0'),
|
||||
br_last => '0', br_taken => '0', abs_br => '0',
|
||||
srr1 => (others => '0'), msr => (others => '0'));
|
||||
@@ -795,8 +798,9 @@ package common is
|
||||
write_cr_data => (others => '0'));
|
||||
|
||||
type WritebackToExecute1Type is record
|
||||
intr : std_ulogic;
|
||||
srr1 : std_ulogic_vector(15 downto 0);
|
||||
intr : std_ulogic;
|
||||
hv_intr : std_ulogic;
|
||||
srr1 : std_ulogic_vector(15 downto 0);
|
||||
end record;
|
||||
|
||||
type WritebackEventType is record
|
||||
|
||||
11
decode2.vhdl
11
decode2.vhdl
@@ -539,8 +539,15 @@ begin
|
||||
v.e.ramspr_write_odd := d_in.ram_spr.valid and d_in.ram_spr.isodd;
|
||||
v.e.spr_is_ram := d_in.ram_spr.valid;
|
||||
when OP_RFID =>
|
||||
v.e.ramspr_even_rdaddr := RAMSPR_SRR0;
|
||||
v.e.ramspr_odd_rdaddr := RAMSPR_SRR1;
|
||||
if d_in.insn(9) = '0' then
|
||||
-- rfid
|
||||
v.e.ramspr_even_rdaddr := RAMSPR_SRR0;
|
||||
v.e.ramspr_odd_rdaddr := RAMSPR_SRR1;
|
||||
else
|
||||
-- hrfid
|
||||
v.e.ramspr_even_rdaddr := RAMSPR_HSRR0;
|
||||
v.e.ramspr_odd_rdaddr := RAMSPR_HSRR1;
|
||||
end if;
|
||||
sprs_busy := '1';
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
@@ -322,6 +322,7 @@ architecture behaviour of execute1 is
|
||||
-- 48:63, and partial function MSR bits lie in the range
|
||||
-- 33:36 and 42:47. (Note this is IBM bit numbering).
|
||||
msr_out := (others => '0');
|
||||
msr_out(MSR_HV) := '1'; -- HV is always set
|
||||
msr_out(63 downto 31) := msr(63 downto 31);
|
||||
msr_out(26 downto 22) := msr(26 downto 22);
|
||||
msr_out(15 downto 0) := msr(15 downto 0);
|
||||
@@ -332,6 +333,9 @@ architecture behaviour of execute1 is
|
||||
return std_ulogic_vector is
|
||||
variable srr1: std_ulogic_vector(63 downto 0);
|
||||
begin
|
||||
srr1(63 downto 61) := msr(63 downto 61);
|
||||
srr1(MSR_HV) := '1';
|
||||
srr1(59 downto 31) := msr(59 downto 31);
|
||||
srr1(63 downto 31) := msr(63 downto 31);
|
||||
srr1(30 downto 27) := flags(14 downto 11);
|
||||
srr1(26 downto 22) := msr(26 downto 22);
|
||||
@@ -533,7 +537,11 @@ begin
|
||||
even_wr_enab := (ex1.se.ramspr_write_even and doit) or interrupt_in.intr;
|
||||
odd_wr_enab := (ex1.se.ramspr_write_odd and doit) or interrupt_in.intr;
|
||||
if interrupt_in.intr = '1' then
|
||||
wr_addr := RAMSPR_SRR0;
|
||||
if interrupt_in.hv_intr = '0' then
|
||||
wr_addr := RAMSPR_SRR0;
|
||||
else
|
||||
wr_addr := RAMSPR_HSRR0;
|
||||
end if;
|
||||
else
|
||||
wr_addr := ex1.ramspr_wraddr;
|
||||
end if;
|
||||
@@ -610,8 +618,8 @@ begin
|
||||
ex1 <= reg_stage1_type_init;
|
||||
ex2 <= reg_stage2_type_init;
|
||||
ctrl <= ctrl_t_init;
|
||||
ctrl.msr <= (MSR_SF => '1', MSR_LE => '1', others => '0');
|
||||
ex1.msr <= (MSR_SF => '1', MSR_LE => '1', others => '0');
|
||||
ctrl.msr <= (MSR_SF => '1', MSR_HV => '1', MSR_LE => '1', others => '0');
|
||||
ex1.msr <= (MSR_SF => '1', MSR_HV => '1', MSR_LE => '1', others => '0');
|
||||
else
|
||||
ex1 <= ex1in;
|
||||
ex2 <= ex2in;
|
||||
@@ -1166,7 +1174,9 @@ begin
|
||||
not srr1(MSR_LE) & not srr1(MSR_SF);
|
||||
-- Can't use msr_copy here because the partial function MSR
|
||||
-- bits should be left unchanged, not zeroed.
|
||||
v.new_msr(63 downto 31) := srr1(63 downto 31);
|
||||
v.new_msr(63 downto 61) := srr1(63 downto 61);
|
||||
v.new_msr(MSR_HV) := '1';
|
||||
v.new_msr(59 downto 31) := srr1(59 downto 31);
|
||||
v.new_msr(26 downto 22) := srr1(26 downto 22);
|
||||
v.new_msr(15 downto 0) := srr1(15 downto 0);
|
||||
if srr1(MSR_PR) = '1' then
|
||||
@@ -1474,6 +1484,7 @@ begin
|
||||
v.e.intr_vec := 16#500#;
|
||||
report "IRQ valid: External";
|
||||
v.ext_interrupt := '1';
|
||||
v.e.hv_intr := '1';
|
||||
end if;
|
||||
v.e.srr1 := (others => '0');
|
||||
exception := '1';
|
||||
|
||||
@@ -447,6 +447,7 @@ architecture behaviour of predecoder is
|
||||
2#1_00100_11110# => INSN_isync,
|
||||
2#1_00000_10000# => INSN_mcrf,
|
||||
2#1_00000_11010# => INSN_rfid,
|
||||
2#1_01000_11010# => INSN_rfid, -- hrfid
|
||||
|
||||
-- Major opcode 59
|
||||
-- Address bits are 1, insn(10..6), 1, 0, insn(3..1)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define MSR_LE 0x1
|
||||
#define MSR_DR 0x10
|
||||
#define MSR_IR 0x20
|
||||
#define MSR_HV 0x1000000000000000ul
|
||||
#define MSR_SF 0x8000000000000000ul
|
||||
|
||||
extern int test_read(long *addr, long *ret, long init);
|
||||
@@ -450,11 +451,11 @@ int mmu_test_11(void)
|
||||
unsigned long ptr = 0x523000;
|
||||
|
||||
/* this should fail */
|
||||
if (test_exec(0, ptr, MSR_SF | MSR_IR | MSR_LE))
|
||||
if (test_exec(0, ptr, MSR_SF | MSR_HV | MSR_IR | MSR_LE))
|
||||
return 1;
|
||||
/* SRR0 and SRR1 should be set correctly */
|
||||
if (mfspr(SRR0) != (long) ptr ||
|
||||
mfspr(SRR1) != (MSR_SF | 0x40000000 | MSR_IR | MSR_LE))
|
||||
mfspr(SRR1) != (MSR_SF | MSR_HV | 0x40000000 | MSR_IR | MSR_LE))
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
@@ -468,12 +469,12 @@ int mmu_test_12(void)
|
||||
/* create PTE */
|
||||
map((void *)ptr, (void *)mem, PERM_EX | REF);
|
||||
/* this should succeed and be a cache miss */
|
||||
if (!test_exec(0, ptr, MSR_SF | MSR_IR | MSR_LE))
|
||||
if (!test_exec(0, ptr, MSR_SF | MSR_HV | MSR_IR | MSR_LE))
|
||||
return 1;
|
||||
/* create a second PTE */
|
||||
map((void *)ptr2, (void *)mem, PERM_EX | REF);
|
||||
/* this should succeed and be a cache hit */
|
||||
if (!test_exec(0, ptr2, MSR_SF | MSR_IR | MSR_LE))
|
||||
if (!test_exec(0, ptr2, MSR_SF | MSR_HV | MSR_IR | MSR_LE))
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
@@ -487,18 +488,18 @@ int mmu_test_13(void)
|
||||
/* create a PTE */
|
||||
map((void *)ptr, (void *)mem, PERM_EX | REF);
|
||||
/* this should succeed */
|
||||
if (!test_exec(1, ptr, MSR_SF | MSR_IR | MSR_LE))
|
||||
if (!test_exec(1, ptr, MSR_SF | MSR_HV | MSR_IR | MSR_LE))
|
||||
return 1;
|
||||
/* invalidate the PTE */
|
||||
unmap((void *)ptr);
|
||||
/* install a second PTE */
|
||||
map((void *)ptr2, (void *)mem, PERM_EX | REF);
|
||||
/* this should fail */
|
||||
if (test_exec(1, ptr, MSR_SF | MSR_IR | MSR_LE))
|
||||
if (test_exec(1, ptr, MSR_SF | MSR_HV | MSR_IR | MSR_LE))
|
||||
return 2;
|
||||
/* SRR0 and SRR1 should be set correctly */
|
||||
if (mfspr(SRR0) != (long) ptr ||
|
||||
mfspr(SRR1) != (MSR_SF | 0x40000000 | MSR_IR | MSR_LE))
|
||||
mfspr(SRR1) != (MSR_SF | MSR_HV | 0x40000000 | MSR_IR | MSR_LE))
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
@@ -513,16 +514,16 @@ int mmu_test_14(void)
|
||||
/* create a PTE */
|
||||
map((void *)ptr, (void *)mem, PERM_EX | REF);
|
||||
/* this should fail due to second page not being mapped */
|
||||
if (test_exec(2, ptr, MSR_SF | MSR_IR | MSR_LE))
|
||||
if (test_exec(2, ptr, MSR_SF | MSR_HV | MSR_IR | MSR_LE))
|
||||
return 1;
|
||||
/* SRR0 and SRR1 should be set correctly */
|
||||
if (mfspr(SRR0) != ptr2 ||
|
||||
mfspr(SRR1) != (MSR_SF | 0x40000000 | MSR_IR | MSR_LE))
|
||||
mfspr(SRR1) != (MSR_SF | MSR_HV | 0x40000000 | MSR_IR | MSR_LE))
|
||||
return 2;
|
||||
/* create a PTE for the second page */
|
||||
map((void *)ptr2, (void *)mem2, PERM_EX | REF);
|
||||
/* this should succeed */
|
||||
if (!test_exec(2, ptr, MSR_SF | MSR_IR | MSR_LE))
|
||||
if (!test_exec(2, ptr, MSR_SF | MSR_HV | MSR_IR | MSR_LE))
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
@@ -535,11 +536,11 @@ int mmu_test_15(void)
|
||||
/* create a PTE without execute permission */
|
||||
map((void *)ptr, (void *)mem, DFLT_PERM);
|
||||
/* this should fail */
|
||||
if (test_exec(0, ptr, MSR_SF | MSR_IR | MSR_LE))
|
||||
if (test_exec(0, ptr, MSR_SF | MSR_HV | MSR_IR | MSR_LE))
|
||||
return 1;
|
||||
/* SRR0 and SRR1 should be set correctly */
|
||||
if (mfspr(SRR0) != ptr ||
|
||||
mfspr(SRR1) != (MSR_SF | 0x10000000 | MSR_IR | MSR_LE))
|
||||
mfspr(SRR1) != (MSR_SF | MSR_HV | 0x10000000 | MSR_IR | MSR_LE))
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
@@ -556,16 +557,16 @@ int mmu_test_16(void)
|
||||
/* create a PTE for the second page without execute permission */
|
||||
map((void *)ptr2, (void *)mem2, PERM_RD | REF);
|
||||
/* this should fail due to second page being no-execute */
|
||||
if (test_exec(2, ptr, MSR_SF | MSR_IR | MSR_LE))
|
||||
if (test_exec(2, ptr, MSR_SF | MSR_HV | MSR_IR | MSR_LE))
|
||||
return 1;
|
||||
/* SRR0 and SRR1 should be set correctly */
|
||||
if (mfspr(SRR0) != ptr2 ||
|
||||
mfspr(SRR1) != (MSR_SF | 0x10000000 | MSR_IR | MSR_LE))
|
||||
mfspr(SRR1) != (MSR_SF | MSR_HV | 0x10000000 | MSR_IR | MSR_LE))
|
||||
return 2;
|
||||
/* create a PTE for the second page with execute permission */
|
||||
map((void *)ptr2, (void *)mem2, PERM_RD | PERM_EX | REF);
|
||||
/* this should succeed */
|
||||
if (!test_exec(2, ptr, MSR_SF | MSR_IR | MSR_LE))
|
||||
if (!test_exec(2, ptr, MSR_SF | MSR_HV | MSR_IR | MSR_LE))
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
@@ -578,22 +579,22 @@ int mmu_test_17(void)
|
||||
/* create a PTE without the ref bit set */
|
||||
map((void *)ptr, (void *)mem, PERM_EX);
|
||||
/* this should fail */
|
||||
if (test_exec(2, ptr, MSR_SF | MSR_IR | MSR_LE))
|
||||
if (test_exec(2, ptr, MSR_SF | MSR_HV | MSR_IR | MSR_LE))
|
||||
return 1;
|
||||
/* SRR0 and SRR1 should be set correctly */
|
||||
if (mfspr(SRR0) != (long) ptr ||
|
||||
mfspr(SRR1) != (MSR_SF | 0x00040000 | MSR_IR | MSR_LE))
|
||||
mfspr(SRR1) != (MSR_SF | MSR_HV | 0x00040000 | MSR_IR | MSR_LE))
|
||||
return 2;
|
||||
/* create a PTE without ref or execute permission */
|
||||
unmap((void *)ptr);
|
||||
map((void *)ptr, (void *)mem, 0);
|
||||
/* this should fail */
|
||||
if (test_exec(2, ptr, MSR_SF | MSR_IR | MSR_LE))
|
||||
if (test_exec(2, ptr, MSR_SF | MSR_HV | MSR_IR | MSR_LE))
|
||||
return 1;
|
||||
/* SRR0 and SRR1 should be set correctly */
|
||||
/* RC update fail bit should not be set */
|
||||
if (mfspr(SRR0) != (long) ptr ||
|
||||
mfspr(SRR1) != (MSR_SF | 0x10000000 | MSR_IR | MSR_LE))
|
||||
mfspr(SRR1) != (MSR_SF | MSR_HV | 0x10000000 | MSR_IR | MSR_LE))
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define MSR_LE 0x1
|
||||
#define MSR_DR 0x10
|
||||
#define MSR_IR 0x20
|
||||
#define MSR_HV 0x1000000000000000ul
|
||||
#define MSR_SF 0x8000000000000000ul
|
||||
|
||||
#define DSISR 18
|
||||
@@ -103,7 +104,7 @@ long int prefix_test_2(void)
|
||||
return 1;
|
||||
if (mfspr(SRR0) != (unsigned long)&test_paddi_mis + 8)
|
||||
return 2;
|
||||
if (mfspr(SRR1) != (MSR_SF | MSR_LE | (1ul << (63 - 35)) | (1ul << (63 - 34))))
|
||||
if (mfspr(SRR1) != (MSR_SF | MSR_HV | MSR_LE | (1ul << (63 - 35)) | (1ul << (63 - 34))))
|
||||
return 3;
|
||||
|
||||
ret = trapit((long)&x, test_plfd);
|
||||
@@ -111,7 +112,7 @@ long int prefix_test_2(void)
|
||||
return ret;
|
||||
if (mfspr(SRR0) != (unsigned long)&test_plfd + 8)
|
||||
return 6;
|
||||
if (mfspr(SRR1) != (MSR_SF | MSR_LE | (1ul << (63 - 34))))
|
||||
if (mfspr(SRR1) != (MSR_SF | MSR_HV | MSR_LE | (1ul << (63 - 34))))
|
||||
return 7;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -115,7 +115,7 @@ __isr:
|
||||
std %r29, 29*8(%r1)
|
||||
std %r30, 30*8(%r1)
|
||||
std %r31, 31*8(%r1)
|
||||
mfsrr0 %r0
|
||||
mfhsrr0 %r0
|
||||
std %r0, SAVE_NIA*8(%r1)
|
||||
mflr %r0
|
||||
std %r0, SAVE_LR*8(%r1)
|
||||
@@ -123,7 +123,7 @@ __isr:
|
||||
std %r0, SAVE_CTR*8(%r1)
|
||||
mfcr %r0
|
||||
std %r0, SAVE_CR*8(%r1)
|
||||
mfsrr1 %r0
|
||||
mfhsrr1 %r0
|
||||
std %r0, SAVE_SRR1*8(%r1)
|
||||
|
||||
stdu %r1,-STACK_FRAME_C_MINIMAL(%r1)
|
||||
|
||||
@@ -72,11 +72,13 @@ begin
|
||||
variable vec : integer range 0 to 16#fff#;
|
||||
variable srr1 : std_ulogic_vector(15 downto 0);
|
||||
variable intr : std_ulogic;
|
||||
variable hvi : std_ulogic;
|
||||
begin
|
||||
w_out <= WritebackToRegisterFileInit;
|
||||
c_out <= WritebackToCrFileInit;
|
||||
f := WritebackToFetch1Init;
|
||||
vec := 0;
|
||||
hvi := '0';
|
||||
|
||||
complete_out <= instr_tag_init;
|
||||
if e_in.valid = '1' then
|
||||
@@ -96,6 +98,7 @@ begin
|
||||
if e_in.interrupt = '1' then
|
||||
vec := e_in.intr_vec;
|
||||
srr1 := e_in.srr1;
|
||||
hvi := e_in.hv_intr;
|
||||
elsif l_in.interrupt = '1' then
|
||||
vec := l_in.intr_vec;
|
||||
srr1 := l_in.srr1;
|
||||
@@ -103,6 +106,7 @@ begin
|
||||
vec := fp_in.intr_vec;
|
||||
srr1 := fp_in.srr1;
|
||||
end if;
|
||||
interrupt_out.hv_intr <= hvi;
|
||||
interrupt_out.srr1 <= srr1;
|
||||
|
||||
if intr = '0' then
|
||||
|
||||
Reference in New Issue
Block a user