From: Paul Mackerras Date: Thu, 17 Jun 2021 10:01:32 +0000 (+1000) Subject: MMU: Implement a vestigial partition table X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=18120f153d138f733fa7e8a89c3456bb93683f96;p=microwatt.git MMU: Implement a vestigial partition table This implements a 1-entry partition table, so that instead of getting the process table base address from the PRTBL SPR, the MMU now reads the doubleword pointed to by the PTCR register plus 8 to get the process table base address. The partition table entry is cached. Having the PTCR and the vestigial partition table reduces the amount of software change required in Linux for Microwatt support. Signed-off-by: Paul Mackerras --- diff --git a/common.vhdl b/common.vhdl index 69dde30..b18a271 100644 --- a/common.vhdl +++ b/common.vhdl @@ -51,7 +51,7 @@ package common is constant SPR_HSPRG0 : spr_num_t := 304; constant SPR_HSPRG1 : spr_num_t := 305; constant SPR_PID : spr_num_t := 48; - constant SPR_PRTBL : spr_num_t := 720; + constant SPR_PTCR : spr_num_t := 464; constant SPR_PVR : spr_num_t := 287; -- GPR indices in the register file (GPR only) diff --git a/decode1.vhdl b/decode1.vhdl index 2869c39..5d0bdcb 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -609,7 +609,7 @@ begin vi.force_single := '1'; -- send MMU-related SPRs to loadstore1 case sprn is - when SPR_DAR | SPR_DSISR | SPR_PID | SPR_PRTBL => + when SPR_DAR | SPR_DSISR | SPR_PID | SPR_PTCR => vi.override_decode.unit := LDST; vi.override_unit := '1'; when others => diff --git a/loadstore1.vhdl b/loadstore1.vhdl index 3328617..822cc19 100644 --- a/loadstore1.vhdl +++ b/loadstore1.vhdl @@ -477,7 +477,7 @@ begin v.read_spr := '1'; when OP_MTSPR => v.write_spr := '1'; - v.mmu_op := sprn(9) or sprn(5); + v.mmu_op := sprn(8) or sprn(5); when OP_FETCH_FAILED => -- send it to the MMU to do the radix walk v.instr_fault := '1'; @@ -732,7 +732,7 @@ begin write_enable := '1'; -- partial decode on SPR number should be adequate given -- the restricted set that get sent down this path - if r2.req.sprn(9) = '0' and r2.req.sprn(5) = '0' then + if r2.req.sprn(8) = '0' and r2.req.sprn(5) = '0' then if r2.req.sprn(0) = '0' then sprval := x"00000000" & r3.dsisr; else diff --git a/mmu.vhdl b/mmu.vhdl index 623c2c9..d80caf4 100644 --- a/mmu.vhdl +++ b/mmu.vhdl @@ -29,6 +29,9 @@ architecture behave of mmu is type state_t is (IDLE, DO_TLBIE, TLB_WAIT, + PART_TBL_READ, + PART_TBL_WAIT, + PART_TBL_DONE, PROC_TBL_READ, PROC_TBL_WAIT, SEGMENT_CHECK, @@ -47,12 +50,14 @@ architecture behave of mmu is addr : std_ulogic_vector(63 downto 0); inval_all : std_ulogic; -- config SPRs - prtbl : std_ulogic_vector(63 downto 0); + ptcr : std_ulogic_vector(63 downto 0); pid : std_ulogic_vector(31 downto 0); -- internal state state : state_t; done : std_ulogic; err : std_ulogic; + prtbl : std_ulogic_vector(63 downto 0); + ptb_valid : std_ulogic; pgtbl0 : std_ulogic_vector(63 downto 0); pt0_valid : std_ulogic; pgtbl3 : std_ulogic_vector(63 downto 0); @@ -77,7 +82,7 @@ architecture behave of mmu is begin -- Multiplex internal SPR values back to loadstore1, selected -- by l_in.sprn. - l_out.sprval <= r.prtbl when l_in.sprn(9) = '1' else x"00000000" & r.pid; + l_out.sprval <= r.ptcr when l_in.sprn(8) = '1' else x"00000000" & r.pid; mmu_0: process(clk) begin @@ -85,9 +90,10 @@ begin if rst = '1' then r.state <= IDLE; r.valid <= '0'; + r.ptb_valid <= '0'; r.pt0_valid <= '0'; r.pt3_valid <= '0'; - r.prtbl <= (others => '0'); + r.ptcr <= (others => '0'); r.pid <= (others => '0'); else if rin.valid = '1' then @@ -185,6 +191,7 @@ begin variable tlb_load : std_ulogic; variable itlb_load : std_ulogic; variable tlbie_req : std_ulogic; + variable ptbl_rd : std_ulogic; variable prtbl_rd : std_ulogic; variable pt_valid : std_ulogic; variable effpid : std_ulogic_vector(31 downto 0); @@ -215,6 +222,7 @@ begin itlb_load := '0'; tlbie_req := '0'; v.inval_all := '0'; + ptbl_rd := '0'; prtbl_rd := '0'; -- Radix tree data structures in memory are big-endian, @@ -256,11 +264,15 @@ begin if l_in.sprn(3) = '1' then v.pt0_valid := '0'; v.pt3_valid := '0'; + v.ptb_valid := '0'; end if; v.state := DO_TLBIE; else v.valid := '1'; - if pt_valid = '0' then + if r.ptb_valid = '0' then + -- need to fetch process table base from partition table + v.state := PART_TBL_READ; + elsif pt_valid = '0' then -- need to fetch process table entry -- set v.shift so we can use finalmask for generating -- the process table entry address @@ -277,13 +289,14 @@ begin end if; if l_in.mtspr = '1' then -- Move to PID needs to invalidate L1 TLBs and cached - -- pgtbl0 value. Move to PRTBL does that plus - -- invalidating the cached pgtbl3 value as well. - if l_in.sprn(9) = '0' then + -- pgtbl0 value. Move to PTCR does that plus + -- invalidating the cached pgtbl3 and prtbl values as well. + if l_in.sprn(8) = '0' then v.pid := l_in.rs(31 downto 0); else - v.prtbl := l_in.rs; + v.ptcr := l_in.rs; v.pt3_valid := '0'; + v.ptb_valid := '0'; end if; v.pt0_valid := '0'; v.inval_all := '1'; @@ -300,6 +313,22 @@ begin v.state := RADIX_FINISH; end if; + when PART_TBL_READ => + dcreq := '1'; + ptbl_rd := '1'; + v.state := PART_TBL_WAIT; + + when PART_TBL_WAIT => + if d_in.done = '1' then + v.prtbl := data; + v.ptb_valid := '1'; + v.state := PART_TBL_DONE; + end if; + + when PART_TBL_DONE => + v.shift := unsigned('0' & r.prtbl(4 downto 0)); + v.state := PROC_TBL_READ; + when PROC_TBL_READ => dcreq := '1'; prtbl_rd := '1'; @@ -449,6 +478,9 @@ begin elsif tlb_load = '1' then addr := r.addr(63 downto 12) & x"000"; tlb_data := pte; + elsif ptbl_rd = '1' then + addr := x"00" & r.ptcr(55 downto 12) & x"008"; + tlb_data := (others => '0'); elsif prtbl_rd = '1' then addr := prtable_addr; tlb_data := (others => '0'); diff --git a/tests/mmu/mmu.c b/tests/mmu/mmu.c index ef00824..64afa44 100644 --- a/tests/mmu/mmu.c +++ b/tests/mmu/mmu.c @@ -24,7 +24,7 @@ static inline void do_tlbie(unsigned long rb, unsigned long rs) #define SRR0 26 #define SRR1 27 #define PID 48 -#define PRTBL 720 +#define PTCR 464 static inline unsigned long mfspr(int sprnum) { @@ -115,15 +115,18 @@ void zero_memory(void *ptr, unsigned long nbytes) */ unsigned long *pgdir = (unsigned long *) 0x10000; unsigned long *proc_tbl = (unsigned long *) 0x12000; -unsigned long free_ptr = 0x13000; +unsigned long *part_tbl = (unsigned long *) 0x13000; +unsigned long free_ptr = 0x14000; void *eas_mapped[4]; int neas_mapped; void init_mmu(void) { + /* set up partition table */ + store_pte(&part_tbl[1], (unsigned long)proc_tbl); /* set up process table */ zero_memory(proc_tbl, 512 * sizeof(unsigned long)); - mtspr(PRTBL, (unsigned long)proc_tbl); + mtspr(PTCR, (unsigned long)part_tbl); mtspr(PID, 1); zero_memory(pgdir, 1024 * sizeof(unsigned long)); /* RTS = 0 (2GB address space), RPDS = 10 (1024-entry top level) */ diff --git a/tests/modes/modes.c b/tests/modes/modes.c index c8ec9ce..b94bb47 100644 --- a/tests/modes/modes.c +++ b/tests/modes/modes.c @@ -33,7 +33,7 @@ static inline void do_tlbie(unsigned long rb, unsigned long rs) #define SPRG0 272 #define SPRG1 273 #define SPRG3 275 -#define PRTBL 720 +#define PTCR 464 static inline unsigned long mfspr(int sprnum) { @@ -121,15 +121,18 @@ void zero_memory(void *ptr, unsigned long nbytes) * Set up an MMU translation tree using memory starting at the 64k point. * We use 3 levels, mapping 512GB, with 4kB PGD/PMD/PTE pages. */ -unsigned long *proc_tbl = (unsigned long *) 0x10000; -unsigned long *pgdir = (unsigned long *) 0x11000; -unsigned long free_ptr = 0x12000; +unsigned long *part_tbl = (unsigned long *) 0x10000; +unsigned long *proc_tbl = (unsigned long *) 0x11000; +unsigned long *pgdir = (unsigned long *) 0x12000; +unsigned long free_ptr = 0x13000; void init_mmu(void) { + /* set up partition table */ + store_pte(&part_tbl[1], (unsigned long)proc_tbl); /* set up process table */ zero_memory(proc_tbl, 512 * sizeof(unsigned long)); - mtspr(PRTBL, (unsigned long)proc_tbl); + mtspr(PTCR, (unsigned long)part_tbl); mtspr(PID, 1); zero_memory(pgdir, 512 * sizeof(unsigned long)); /* RTS = 8 (512GB address space), RPDS = 9 (512-entry top level) */ diff --git a/tests/privileged/privileged.c b/tests/privileged/privileged.c index 68e30bc..fc6b23d 100644 --- a/tests/privileged/privileged.c +++ b/tests/privileged/privileged.c @@ -14,7 +14,7 @@ extern int call_with_msr(unsigned long arg, int (*fn)(unsigned long), unsigned l #define SRR0 26 #define SRR1 27 #define PID 48 -#define PRTBL 720 +#define PTCR 464 #define PVR 287 static inline unsigned long mfspr(int sprnum) @@ -106,15 +106,18 @@ void zero_memory(void *ptr, unsigned long nbytes) */ unsigned long *pgdir = (unsigned long *) 0x10000; unsigned long *proc_tbl = (unsigned long *) 0x12000; -unsigned long free_ptr = 0x13000; +unsigned long *part_tbl = (unsigned long *) 0x13000; +unsigned long free_ptr = 0x14000; void init_mmu(void) { + /* set up partition table */ + store_pte(&part_tbl[1], (unsigned long)proc_tbl); /* set up process table */ zero_memory(proc_tbl, 512 * sizeof(unsigned long)); /* RTS = 0 (2GB address space), RPDS = 10 (1024-entry top level) */ store_pte(&proc_tbl[2 * 1], (unsigned long) pgdir | 10); - mtspr(PRTBL, (unsigned long)proc_tbl); + mtspr(PTCR, (unsigned long)part_tbl); mtspr(PID, 1); zero_memory(pgdir, 1024 * sizeof(unsigned long)); } diff --git a/tests/reservation/reservation.c b/tests/reservation/reservation.c index 4df4511..a3d5a7a 100644 --- a/tests/reservation/reservation.c +++ b/tests/reservation/reservation.c @@ -18,7 +18,6 @@ extern unsigned long do_stqcx(unsigned long dst, unsigned long regs); #define PID 48 #define SPRG0 272 #define SPRG1 273 -#define PRTBL 720 static inline unsigned long mfspr(int sprnum) { diff --git a/tests/spr_read/spr_read.c b/tests/spr_read/spr_read.c index fa41154..6d2859e 100644 --- a/tests/spr_read/spr_read.c +++ b/tests/spr_read/spr_read.c @@ -38,7 +38,7 @@ void print_test(char *str) #define SPR_HSPRG0 304 #define SPR_HSPRG1 305 #define SPR_PID 48 -#define SPR_PRTBL 720 +#define SPR_PTCR 464 #define SPR_PVR 287 #define __stringify_1(x...) #x @@ -83,7 +83,7 @@ int main(void) DO_ONE(SPR_HSPRG0); DO_ONE(SPR_HSPRG1); DO_ONE(SPR_PID); - DO_ONE(SPR_PRTBL); + DO_ONE(SPR_PTCR); DO_ONE(SPR_PVR); puts(PASS); diff --git a/tests/test_mmu.bin b/tests/test_mmu.bin index 7f87578..1ade44e 100755 Binary files a/tests/test_mmu.bin and b/tests/test_mmu.bin differ diff --git a/tests/test_modes.bin b/tests/test_modes.bin index edbe0c8..7e6b8f5 100755 Binary files a/tests/test_modes.bin and b/tests/test_modes.bin differ diff --git a/tests/test_privileged.bin b/tests/test_privileged.bin index d89b34d..cd7f383 100755 Binary files a/tests/test_privileged.bin and b/tests/test_privileged.bin differ diff --git a/tests/test_spr_read.bin b/tests/test_spr_read.bin index 66a546a..68f6cd8 100755 Binary files a/tests/test_spr_read.bin and b/tests/test_spr_read.bin differ diff --git a/tests/test_spr_read.console_out b/tests/test_spr_read.console_out index 1ccac56..8a032d4 100644 --- a/tests/test_spr_read.console_out +++ b/tests/test_spr_read.console_out @@ -20,6 +20,6 @@ Test SPR_SPRG3U:PASS Test SPR_HSPRG0:PASS Test SPR_HSPRG1:PASS Test SPR_PID:PASS -Test SPR_PRTBL:PASS +Test SPR_PTCR:PASS Test SPR_PVR:PASS PASS