Merge pull request #298 from paulusmack/master

MMU: Implement a vestigial partition table
remove-potato-uart
Michael Neuling 3 years ago committed by GitHub
commit 9e3c756234
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -51,7 +51,7 @@ package common is
constant SPR_HSPRG0 : spr_num_t := 304; constant SPR_HSPRG0 : spr_num_t := 304;
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_PTCR : spr_num_t := 464;
constant SPR_PVR : spr_num_t := 287; constant SPR_PVR : spr_num_t := 287;


-- GPR indices in the register file (GPR only) -- GPR indices in the register file (GPR only)

@ -609,7 +609,7 @@ begin
vi.force_single := '1'; vi.force_single := '1';
-- send MMU-related SPRs to loadstore1 -- send MMU-related SPRs to loadstore1
case sprn is 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_decode.unit := LDST;
vi.override_unit := '1'; vi.override_unit := '1';
when others => when others =>

@ -477,7 +477,7 @@ begin
v.read_spr := '1'; v.read_spr := '1';
when OP_MTSPR => when OP_MTSPR =>
v.write_spr := '1'; v.write_spr := '1';
v.mmu_op := sprn(9) or sprn(5); v.mmu_op := sprn(8) or sprn(5);
when OP_FETCH_FAILED => when OP_FETCH_FAILED =>
-- send it to the MMU to do the radix walk -- send it to the MMU to do the radix walk
v.instr_fault := '1'; v.instr_fault := '1';
@ -732,7 +732,7 @@ begin
write_enable := '1'; write_enable := '1';
-- partial decode on SPR number should be adequate given -- partial decode on SPR number should be adequate given
-- the restricted set that get sent down this path -- 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 if r2.req.sprn(0) = '0' then
sprval := x"00000000" & r3.dsisr; sprval := x"00000000" & r3.dsisr;
else else

@ -29,6 +29,9 @@ architecture behave of mmu is
type state_t is (IDLE, type state_t is (IDLE,
DO_TLBIE, DO_TLBIE,
TLB_WAIT, TLB_WAIT,
PART_TBL_READ,
PART_TBL_WAIT,
PART_TBL_DONE,
PROC_TBL_READ, PROC_TBL_READ,
PROC_TBL_WAIT, PROC_TBL_WAIT,
SEGMENT_CHECK, SEGMENT_CHECK,
@ -47,12 +50,14 @@ architecture behave of mmu is
addr : std_ulogic_vector(63 downto 0); addr : std_ulogic_vector(63 downto 0);
inval_all : std_ulogic; inval_all : std_ulogic;
-- config SPRs -- config SPRs
prtbl : std_ulogic_vector(63 downto 0); ptcr : std_ulogic_vector(63 downto 0);
pid : std_ulogic_vector(31 downto 0); pid : std_ulogic_vector(31 downto 0);
-- internal state -- internal state
state : state_t; state : state_t;
done : std_ulogic; done : std_ulogic;
err : std_ulogic; err : std_ulogic;
prtbl : std_ulogic_vector(63 downto 0);
ptb_valid : std_ulogic;
pgtbl0 : std_ulogic_vector(63 downto 0); pgtbl0 : std_ulogic_vector(63 downto 0);
pt0_valid : std_ulogic; pt0_valid : std_ulogic;
pgtbl3 : std_ulogic_vector(63 downto 0); pgtbl3 : std_ulogic_vector(63 downto 0);
@ -77,7 +82,7 @@ architecture behave of mmu is
begin begin
-- Multiplex internal SPR values back to loadstore1, selected -- Multiplex internal SPR values back to loadstore1, selected
-- by l_in.sprn. -- 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) mmu_0: process(clk)
begin begin
@ -85,9 +90,10 @@ begin
if rst = '1' then if rst = '1' then
r.state <= IDLE; r.state <= IDLE;
r.valid <= '0'; r.valid <= '0';
r.ptb_valid <= '0';
r.pt0_valid <= '0'; r.pt0_valid <= '0';
r.pt3_valid <= '0'; r.pt3_valid <= '0';
r.prtbl <= (others => '0'); r.ptcr <= (others => '0');
r.pid <= (others => '0'); r.pid <= (others => '0');
else else
if rin.valid = '1' then if rin.valid = '1' then
@ -185,6 +191,7 @@ begin
variable tlb_load : std_ulogic; variable tlb_load : std_ulogic;
variable itlb_load : std_ulogic; variable itlb_load : std_ulogic;
variable tlbie_req : std_ulogic; variable tlbie_req : std_ulogic;
variable ptbl_rd : std_ulogic;
variable prtbl_rd : std_ulogic; variable prtbl_rd : std_ulogic;
variable pt_valid : std_ulogic; variable pt_valid : std_ulogic;
variable effpid : std_ulogic_vector(31 downto 0); variable effpid : std_ulogic_vector(31 downto 0);
@ -215,6 +222,7 @@ begin
itlb_load := '0'; itlb_load := '0';
tlbie_req := '0'; tlbie_req := '0';
v.inval_all := '0'; v.inval_all := '0';
ptbl_rd := '0';
prtbl_rd := '0'; prtbl_rd := '0';


-- Radix tree data structures in memory are big-endian, -- Radix tree data structures in memory are big-endian,
@ -256,11 +264,15 @@ begin
if l_in.sprn(3) = '1' then if l_in.sprn(3) = '1' then
v.pt0_valid := '0'; v.pt0_valid := '0';
v.pt3_valid := '0'; v.pt3_valid := '0';
v.ptb_valid := '0';
end if; end if;
v.state := DO_TLBIE; v.state := DO_TLBIE;
else else
v.valid := '1'; 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 -- need to fetch process table entry
-- set v.shift so we can use finalmask for generating -- set v.shift so we can use finalmask for generating
-- the process table entry address -- the process table entry address
@ -277,13 +289,14 @@ begin
end if; end if;
if l_in.mtspr = '1' then if l_in.mtspr = '1' then
-- Move to PID needs to invalidate L1 TLBs and cached -- Move to PID needs to invalidate L1 TLBs and cached
-- pgtbl0 value. Move to PRTBL does that plus -- pgtbl0 value. Move to PTCR does that plus
-- invalidating the cached pgtbl3 value as well. -- invalidating the cached pgtbl3 and prtbl values as well.
if l_in.sprn(9) = '0' then if l_in.sprn(8) = '0' then
v.pid := l_in.rs(31 downto 0); v.pid := l_in.rs(31 downto 0);
else else
v.prtbl := l_in.rs; v.ptcr := l_in.rs;
v.pt3_valid := '0'; v.pt3_valid := '0';
v.ptb_valid := '0';
end if; end if;
v.pt0_valid := '0'; v.pt0_valid := '0';
v.inval_all := '1'; v.inval_all := '1';
@ -300,6 +313,22 @@ begin
v.state := RADIX_FINISH; v.state := RADIX_FINISH;
end if; 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 => when PROC_TBL_READ =>
dcreq := '1'; dcreq := '1';
prtbl_rd := '1'; prtbl_rd := '1';
@ -449,6 +478,9 @@ begin
elsif tlb_load = '1' then elsif tlb_load = '1' then
addr := r.addr(63 downto 12) & x"000"; addr := r.addr(63 downto 12) & x"000";
tlb_data := pte; 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 elsif prtbl_rd = '1' then
addr := prtable_addr; addr := prtable_addr;
tlb_data := (others => '0'); tlb_data := (others => '0');

@ -24,7 +24,7 @@ static inline void do_tlbie(unsigned long rb, unsigned long rs)
#define SRR0 26 #define SRR0 26
#define SRR1 27 #define SRR1 27
#define PID 48 #define PID 48
#define PRTBL 720 #define PTCR 464


static inline unsigned long mfspr(int sprnum) 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 *pgdir = (unsigned long *) 0x10000;
unsigned long *proc_tbl = (unsigned long *) 0x12000; 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]; void *eas_mapped[4];
int neas_mapped; int neas_mapped;


void init_mmu(void) void init_mmu(void)
{ {
/* set up partition table */
store_pte(&part_tbl[1], (unsigned long)proc_tbl);
/* set up process table */ /* set up process table */
zero_memory(proc_tbl, 512 * sizeof(unsigned long)); zero_memory(proc_tbl, 512 * sizeof(unsigned long));
mtspr(PRTBL, (unsigned long)proc_tbl); mtspr(PTCR, (unsigned long)part_tbl);
mtspr(PID, 1); mtspr(PID, 1);
zero_memory(pgdir, 1024 * sizeof(unsigned long)); zero_memory(pgdir, 1024 * sizeof(unsigned long));
/* RTS = 0 (2GB address space), RPDS = 10 (1024-entry top level) */ /* RTS = 0 (2GB address space), RPDS = 10 (1024-entry top level) */

@ -33,7 +33,7 @@ static inline void do_tlbie(unsigned long rb, unsigned long rs)
#define SPRG0 272 #define SPRG0 272
#define SPRG1 273 #define SPRG1 273
#define SPRG3 275 #define SPRG3 275
#define PRTBL 720 #define PTCR 464


static inline unsigned long mfspr(int sprnum) 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. * 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. * We use 3 levels, mapping 512GB, with 4kB PGD/PMD/PTE pages.
*/ */
unsigned long *proc_tbl = (unsigned long *) 0x10000; unsigned long *part_tbl = (unsigned long *) 0x10000;
unsigned long *pgdir = (unsigned long *) 0x11000; unsigned long *proc_tbl = (unsigned long *) 0x11000;
unsigned long free_ptr = 0x12000; unsigned long *pgdir = (unsigned long *) 0x12000;
unsigned long free_ptr = 0x13000;


void init_mmu(void) void init_mmu(void)
{ {
/* set up partition table */
store_pte(&part_tbl[1], (unsigned long)proc_tbl);
/* set up process table */ /* set up process table */
zero_memory(proc_tbl, 512 * sizeof(unsigned long)); zero_memory(proc_tbl, 512 * sizeof(unsigned long));
mtspr(PRTBL, (unsigned long)proc_tbl); mtspr(PTCR, (unsigned long)part_tbl);
mtspr(PID, 1); mtspr(PID, 1);
zero_memory(pgdir, 512 * sizeof(unsigned long)); zero_memory(pgdir, 512 * sizeof(unsigned long));
/* RTS = 8 (512GB address space), RPDS = 9 (512-entry top level) */ /* RTS = 8 (512GB address space), RPDS = 9 (512-entry top level) */

@ -14,7 +14,7 @@ extern int call_with_msr(unsigned long arg, int (*fn)(unsigned long), unsigned l
#define SRR0 26 #define SRR0 26
#define SRR1 27 #define SRR1 27
#define PID 48 #define PID 48
#define PRTBL 720 #define PTCR 464
#define PVR 287 #define PVR 287


static inline unsigned long mfspr(int sprnum) 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 *pgdir = (unsigned long *) 0x10000;
unsigned long *proc_tbl = (unsigned long *) 0x12000; 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) void init_mmu(void)
{ {
/* set up partition table */
store_pte(&part_tbl[1], (unsigned long)proc_tbl);
/* set up process table */ /* set up process table */
zero_memory(proc_tbl, 512 * sizeof(unsigned long)); zero_memory(proc_tbl, 512 * sizeof(unsigned long));
/* RTS = 0 (2GB address space), RPDS = 10 (1024-entry top level) */ /* RTS = 0 (2GB address space), RPDS = 10 (1024-entry top level) */
store_pte(&proc_tbl[2 * 1], (unsigned long) pgdir | 10); 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); mtspr(PID, 1);
zero_memory(pgdir, 1024 * sizeof(unsigned long)); zero_memory(pgdir, 1024 * sizeof(unsigned long));
} }

@ -18,7 +18,6 @@ extern unsigned long do_stqcx(unsigned long dst, unsigned long regs);
#define PID 48 #define PID 48
#define SPRG0 272 #define SPRG0 272
#define SPRG1 273 #define SPRG1 273
#define PRTBL 720


static inline unsigned long mfspr(int sprnum) static inline unsigned long mfspr(int sprnum)
{ {

@ -38,7 +38,7 @@ void print_test(char *str)
#define SPR_HSPRG0 304 #define SPR_HSPRG0 304
#define SPR_HSPRG1 305 #define SPR_HSPRG1 305
#define SPR_PID 48 #define SPR_PID 48
#define SPR_PRTBL 720 #define SPR_PTCR 464
#define SPR_PVR 287 #define SPR_PVR 287


#define __stringify_1(x...) #x #define __stringify_1(x...) #x
@ -83,7 +83,7 @@ int main(void)
DO_ONE(SPR_HSPRG0); DO_ONE(SPR_HSPRG0);
DO_ONE(SPR_HSPRG1); DO_ONE(SPR_HSPRG1);
DO_ONE(SPR_PID); DO_ONE(SPR_PID);
DO_ONE(SPR_PRTBL); DO_ONE(SPR_PTCR);
DO_ONE(SPR_PVR); DO_ONE(SPR_PVR);


puts(PASS); puts(PASS);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -20,6 +20,6 @@ Test SPR_SPRG3U:PASS
Test SPR_HSPRG0:PASS Test SPR_HSPRG0:PASS
Test SPR_HSPRG1:PASS Test SPR_HSPRG1:PASS
Test SPR_PID:PASS Test SPR_PID:PASS
Test SPR_PRTBL:PASS Test SPR_PTCR:PASS
Test SPR_PVR:PASS Test SPR_PVR:PASS
PASS PASS

Loading…
Cancel
Save