diff --git a/common.vhdl b/common.vhdl index eefa2fd..64fb755 100644 --- a/common.vhdl +++ b/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 diff --git a/decode2.vhdl b/decode2.vhdl index a68bc8b..74809f5 100644 --- a/decode2.vhdl +++ b/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; diff --git a/execute1.vhdl b/execute1.vhdl index cf73de5..34be583 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -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'; diff --git a/predecode.vhdl b/predecode.vhdl index d3ca015..858910c 100644 --- a/predecode.vhdl +++ b/predecode.vhdl @@ -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) diff --git a/tests/mmu/mmu.c b/tests/mmu/mmu.c index 64afa44..ff6a582 100644 --- a/tests/mmu/mmu.c +++ b/tests/mmu/mmu.c @@ -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; } diff --git a/tests/prefix/prefix.c b/tests/prefix/prefix.c index 94ac500..d594037 100644 --- a/tests/prefix/prefix.c +++ b/tests/prefix/prefix.c @@ -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; } diff --git a/tests/test_mmu.bin b/tests/test_mmu.bin index 1ade44e..6e352a7 100755 Binary files a/tests/test_mmu.bin and b/tests/test_mmu.bin differ diff --git a/tests/test_prefix.bin b/tests/test_prefix.bin index a5f9ff7..8690be7 100755 Binary files a/tests/test_prefix.bin and b/tests/test_prefix.bin differ diff --git a/tests/test_xics.bin b/tests/test_xics.bin index 80d1508..41876c8 100755 Binary files a/tests/test_xics.bin and b/tests/test_xics.bin differ diff --git a/tests/xics/head.S b/tests/xics/head.S index c513a02..4de3e29 100644 --- a/tests/xics/head.S +++ b/tests/xics/head.S @@ -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) diff --git a/writeback.vhdl b/writeback.vhdl index 6a86fb7..c479c20 100644 --- a/writeback.vhdl +++ b/writeback.vhdl @@ -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