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)
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 =>
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';
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
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,
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);
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
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
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);
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,
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
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';
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';
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');
#define SRR0 26
#define SRR1 27
#define PID 48
-#define PRTBL 720
+#define PTCR 464
static inline unsigned long mfspr(int sprnum)
{
*/
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) */
#define SPRG0 272
#define SPRG1 273
#define SPRG3 275
-#define PRTBL 720
+#define PTCR 464
static inline unsigned long mfspr(int sprnum)
{
* 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) */
#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)
*/
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));
}
#define PID 48
#define SPRG0 272
#define SPRG1 273
-#define PRTBL 720
static inline unsigned long mfspr(int sprnum)
{
#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
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);
Test SPR_HSPRG0:PASS\r
Test SPR_HSPRG1:PASS\r
Test SPR_PID:PASS\r
-Test SPR_PRTBL:PASS\r
+Test SPR_PTCR:PASS\r
Test SPR_PVR:PASS\r
PASS\r