mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-21 10:36:04 +08:00
add ls2k mmu
This commit is contained in:
@@ -24,6 +24,41 @@ rt_ubase_t rt_interrupt_from_thread;
|
||||
rt_ubase_t rt_interrupt_to_thread;
|
||||
rt_ubase_t rt_thread_switch_interrupt_flag;
|
||||
|
||||
const char *exception_name[] = {
|
||||
"Interrupt",
|
||||
"(X)TLB Modify Exception",
|
||||
"(X)TLB Read/Fetch Exception",
|
||||
"(X)TLB Write Exception",
|
||||
"Address Read/Fetch Exception",
|
||||
"Address Write Exception",
|
||||
"",
|
||||
"",
|
||||
"Syscall",
|
||||
"Breakpoint",
|
||||
"Reversed Instruction Exception",
|
||||
"Coprocessor Unit Invalid",
|
||||
"Overflow",
|
||||
"Trap",
|
||||
"FPU Exception in Vector Instruction",
|
||||
"FPU Exception",
|
||||
"Loongson Custom Exception",
|
||||
"",
|
||||
"",
|
||||
"(X)TLB Read Denied Exception",
|
||||
"(X)TLB Execute Denied Exception",
|
||||
"Vector Module Disabled Exception",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"Cache Error Exception",
|
||||
""
|
||||
};
|
||||
|
||||
rt_base_t rt_hw_interrupt_disable(void)
|
||||
{
|
||||
rt_base_t status = read_c0_status();
|
||||
@@ -87,10 +122,11 @@ void cache_error_handler(void)
|
||||
|
||||
static void unhandled_exception_handle(struct pt_regs *regs)
|
||||
{
|
||||
rt_kprintf("Unknown Exception, EPC: 0x%08x, CAUSE: 0x%08x\n", read_c0_epc(),
|
||||
read_c0_cause());
|
||||
rt_kprintf("ST0: 0x%08x ", regs->cp0_status);
|
||||
rt_kprintf("ErrorPC: 0x%08x\n", read_c0_errorepc());
|
||||
rt_kprintf("Unknown Exception, EPC: 0x%p, CAUSE: 0x%08x\n", read_c0_epc(), read_c0_cause());
|
||||
rt_kprintf("Exception Name:%s\n",exception_name[(read_c0_cause() >> 2) & 0x1f]);
|
||||
rt_kprintf("ExeCode = 0x%08x,BadAddr = 0x%p\n",(read_c0_cause() >> 2) & 0x1f,mmu_tlb_get_bad_vaddr());
|
||||
rt_kprintf("ST0: 0x%08x ",regs->cp0_status);
|
||||
rt_kprintf("ErrorPC: 0x%p\n",read_c0_errorepc());
|
||||
mips_dump_regs(regs);
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2020, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-03-29 quanzhao the first version
|
||||
* 2020-07-26 lizhirui porting to ls2k
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtdef.h>
|
||||
|
||||
rt_inline rt_uint64_t rt_cpu_icache_line_size(void)
|
||||
{
|
||||
rt_uint64_t ctr;
|
||||
return 4 << (ctr & 0xF);
|
||||
}
|
||||
|
||||
rt_inline rt_uint64_t rt_cpu_dcache_line_size(void)
|
||||
{
|
||||
rt_uint64_t ctr;
|
||||
return 4 << ((ctr >> 16) & 0xF);
|
||||
}
|
||||
|
||||
void rt_hw_cpu_icache_invalidate(void *addr, int size)
|
||||
{
|
||||
rt_uint64_t line_size = rt_cpu_icache_line_size();
|
||||
rt_uint64_t start_addr = (rt_uint64_t)addr;
|
||||
rt_uint64_t end_addr = (rt_uint64_t) addr + size + line_size - 1;
|
||||
}
|
||||
|
||||
void rt_hw_cpu_dcache_invalidate(void *addr, int size)
|
||||
{
|
||||
rt_uint64_t line_size = rt_cpu_dcache_line_size();
|
||||
rt_uint64_t start_addr = (rt_uint64_t)addr;
|
||||
rt_uint64_t end_addr = (rt_uint64_t) addr + size + line_size - 1;
|
||||
}
|
||||
|
||||
void rt_hw_cpu_dcache_clean(void *addr, int size)
|
||||
{
|
||||
rt_uint64_t line_size = rt_cpu_dcache_line_size();
|
||||
rt_uint64_t start_addr = (rt_uint64_t)addr;
|
||||
rt_uint64_t end_addr = (rt_uint64_t) addr + size + line_size - 1;
|
||||
}
|
||||
|
||||
void rt_hw_cpu_icache_ops(int ops, void *addr, int size)
|
||||
{
|
||||
if (ops == RT_HW_CACHE_INVALIDATE)
|
||||
rt_hw_cpu_icache_invalidate(addr, size);
|
||||
}
|
||||
|
||||
void rt_hw_cpu_dcache_ops(int ops, void *addr, int size)
|
||||
{
|
||||
if (ops == RT_HW_CACHE_FLUSH)
|
||||
rt_hw_cpu_dcache_clean(addr, size);
|
||||
else if (ops == RT_HW_CACHE_INVALIDATE)
|
||||
rt_hw_cpu_dcache_invalidate(addr, size);
|
||||
}
|
||||
|
||||
rt_base_t rt_hw_cpu_icache_status(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
rt_base_t rt_hw_cpu_dcache_status(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-03-25 quanzhao the first version
|
||||
*/
|
||||
#ifndef __CACHE_H__
|
||||
#define __CACHE_H__
|
||||
|
||||
unsigned long rt_cpu_get_smp_id(void);
|
||||
|
||||
void rt_cpu_mmu_disable(void);
|
||||
void rt_cpu_mmu_enable(void);
|
||||
void rt_cpu_tlb_set(volatile unsigned long*);
|
||||
|
||||
void rt_cpu_dcache_clean_flush(void);
|
||||
void rt_cpu_icache_flush(void);
|
||||
|
||||
void rt_cpu_vector_set_base(unsigned int addr);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2020, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2020-07-26 lizhirui the first version
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mips.h"
|
||||
#include "mips_mmu.h"
|
||||
|
||||
void mmu_init()
|
||||
{
|
||||
uint32_t status = read_c0_status();
|
||||
status |= 0x07 << 5;//ux = 1,sx = 1,kx = 1
|
||||
write_c0_status(status);
|
||||
|
||||
mmu_clear_tlb();
|
||||
mmu_clear_itlb();
|
||||
}
|
||||
|
||||
void mmu_set_cpu_mode(cpu_mode_t cpu_mode)
|
||||
{
|
||||
uint32_t status = read_c0_status();
|
||||
status &= ~(0x03 << 3);
|
||||
status |= ((uint32_t)cpu_mode & 0x03) << 3;
|
||||
write_c0_status(status);
|
||||
}
|
||||
|
||||
cpu_mode_t mmu_get_cpu_mode()
|
||||
{
|
||||
uint32_t status = read_c0_status();
|
||||
return (cpu_mode_t)((status >> 3) & 0x03);
|
||||
}
|
||||
|
||||
void mmu_clear_tlb()
|
||||
{
|
||||
uint32_t max_tlb_index = mmu_get_max_tlb_index();
|
||||
uint64_t va = KSEG0BASE;
|
||||
uint32_t entry;
|
||||
tlb_item_t tlb_item;
|
||||
|
||||
for(entry = 0;entry <= max_tlb_index;entry++)
|
||||
{
|
||||
mmu_tlb_item_init(&tlb_item);
|
||||
mmu_tlb_write_indexed(entry,&tlb_item);
|
||||
}
|
||||
}
|
||||
|
||||
void mmu_clear_itlb()
|
||||
{
|
||||
uint32_t diag = read_c0_diag();
|
||||
write_c0_diag(diag | (0x01 << 2));//write ITLB bit
|
||||
read_c0_entrylo0();
|
||||
}
|
||||
|
||||
uint32_t mmu_get_max_tlb_index()
|
||||
{
|
||||
uint32_t config1 = read_c0_config1();
|
||||
return ((config1 >> 25) & 0x3F);
|
||||
}
|
||||
|
||||
void mmu_tlb_write_indexed(uint32_t index,tlb_item_t *tlb_item)
|
||||
{
|
||||
tlb_item -> entry_lo[0].g |= tlb_item -> entry_lo[1].g;
|
||||
tlb_item -> entry_lo[1].g |= tlb_item -> entry_lo[0].g;
|
||||
mmu_tlb_set_index(index);
|
||||
write_c0_entrylo0(reg_type_convert(tlb_item -> entry_lo[0],uint64_t));
|
||||
write_c0_entrylo1(reg_type_convert(tlb_item -> entry_lo[1],uint64_t));
|
||||
write_c0_entryhi(reg_type_convert(tlb_item -> entry_hi,uint64_t));
|
||||
write_c0_pagemask(reg_type_convert(tlb_item -> page_mask,uint64_t));
|
||||
tlb_write_indexed();
|
||||
read_c0_entrylo0();
|
||||
}
|
||||
|
||||
void mmu_tlb_write_random(tlb_item_t *tlb_item)
|
||||
{
|
||||
tlb_item -> entry_lo[0].g |= tlb_item -> entry_lo[1].g;
|
||||
tlb_item -> entry_lo[1].g |= tlb_item -> entry_lo[0].g;
|
||||
write_c0_entrylo0(reg_type_convert(tlb_item -> entry_lo[0],uint64_t));
|
||||
write_c0_entrylo1(reg_type_convert(tlb_item -> entry_lo[1],uint64_t));
|
||||
write_c0_entryhi(reg_type_convert(tlb_item -> entry_hi,uint64_t));
|
||||
write_c0_pagemask(reg_type_convert(tlb_item -> page_mask,uint64_t));
|
||||
tlb_write_random();
|
||||
read_c0_entrylo0();
|
||||
}
|
||||
|
||||
void mmu_tlb_read(uint32_t index,tlb_item_t *tlb_item)
|
||||
{
|
||||
mmu_tlb_set_index(index);
|
||||
tlb_read();
|
||||
uint64_t entrylo[2];
|
||||
uint64_t entryhi;
|
||||
uint64_t page_mask;
|
||||
entrylo[0] = read_c0_entrylo0();
|
||||
entrylo[1] = read_c0_entrylo1();
|
||||
entryhi = read_c0_entryhi();
|
||||
page_mask = read_c0_pagemask();
|
||||
tlb_item -> entry_lo[0] = reg_type_convert(entrylo[0],entry_lo_t);
|
||||
tlb_item -> entry_lo[1] = reg_type_convert(entrylo[1],entry_lo_t);
|
||||
tlb_item -> entry_hi = reg_type_convert(entryhi,entry_hi_t);
|
||||
tlb_item -> page_mask = reg_type_convert(page_mask,page_mask_t);
|
||||
}
|
||||
|
||||
uint32_t mmu_tlb_find(uint64_t vpn,uint32_t asid,uint32_t *index)
|
||||
{
|
||||
entry_hi_t entry_hi;
|
||||
entry_hi.r = (vpn >> 62) & 0x03;
|
||||
entry_hi.vpn2 = (vpn >> 13) & 0x7FFFFFFU;
|
||||
entry_hi.asid = asid & 0xFFU;
|
||||
tlb_item_t tlb_item;
|
||||
//mmu_tlb_read(6,&tlb_item);
|
||||
//tlb_dump();
|
||||
mmu_tlb_item_init(&tlb_item);
|
||||
tlb_item.entry_lo[0].g = tlb_item.entry_lo[1].g = 1;
|
||||
read_c0_entrylo0();//i don't know why,but if i don't read any register of mmu,tplb will be failed in qemu.
|
||||
write_c0_entrylo0(reg_type_convert(tlb_item.entry_lo[0],uint64_t));
|
||||
write_c0_entrylo1(reg_type_convert(tlb_item.entry_lo[1],uint64_t));
|
||||
write_c0_entryhi(reg_type_convert(entry_hi,uint64_t));
|
||||
//__asm__ __volatile__("ehb");
|
||||
//read_c0_entryhi();
|
||||
//rt_kprintf("entry_hi = %p\n",read_c0_entryhi());
|
||||
tlb_probe();
|
||||
*index = mmu_tlb_get_index();
|
||||
return mmu_tlb_is_matched();
|
||||
}
|
||||
|
||||
void mmu_tlb_item_init(tlb_item_t *tlb_item)
|
||||
{
|
||||
memset(tlb_item,0,sizeof(tlb_item_t));
|
||||
tlb_item -> entry_lo[0].c = 0x03;
|
||||
tlb_item -> entry_lo[1].c = 0x03;
|
||||
}
|
||||
|
||||
void mmu_set_map(uint64_t vpn,uint64_t ppn,page_mask_enum_t page_mask,uint32_t asid,uint32_t global)
|
||||
{
|
||||
uint64_t page_mask_v = (uint64_t)page_mask;
|
||||
|
||||
/*if(page_mask_v & (1 << 13))
|
||||
{
|
||||
page_mask_v |= (1 << 12);
|
||||
}*/
|
||||
|
||||
uint64_t lb = lowbit((~(page_mask_v)) << 12);
|
||||
uint64_t pn_remained = ((~(page_mask_v)) << 12) | lb;
|
||||
vpn &= pn_remained;
|
||||
ppn &= pn_remained;
|
||||
uint64_t odd_vpn = vpn | lb;
|
||||
uint64_t even_vpn = vpn & (~lb);
|
||||
uint32_t index;
|
||||
tlb_item_t tlb_item,tlb2_item;
|
||||
|
||||
mmu_tlb_item_init(&tlb_item);
|
||||
mmu_tlb_item_init(&tlb2_item);
|
||||
tlb_item.page_mask.mask = page_mask;
|
||||
|
||||
if(mmu_tlb_find(vpn & (~lb),asid,&index))
|
||||
{
|
||||
mmu_tlb_read(index,&tlb_item);
|
||||
mmu_tlb_write_indexed(index,&tlb2_item);
|
||||
}
|
||||
|
||||
entry_lo_t *entry_lo = &tlb_item.entry_lo[vpn == even_vpn ? 0 : 1];
|
||||
tlb_item.entry_lo[0].g = tlb_item.entry_lo[1].g = global;
|
||||
entry_lo -> d = 1;
|
||||
entry_lo -> ri = 0;
|
||||
entry_lo -> xi = 0;
|
||||
entry_lo -> v = 1;
|
||||
entry_lo -> pfn = ppn >> 12;
|
||||
tlb_item.entry_hi.r = (vpn >> 62) & 0x03;
|
||||
tlb_item.entry_hi.vpn2 = (vpn >> 13) & 0x7FFFFFFU;
|
||||
tlb_item.entry_hi.asid = asid & 0xFFU;
|
||||
mmu_tlb_write_random(&tlb_item);
|
||||
}
|
||||
|
||||
uint32_t mmu_tlb_get_random()
|
||||
{
|
||||
return read_c0_random();
|
||||
}
|
||||
|
||||
uint32_t mmu_tlb_get_index()
|
||||
{
|
||||
return read_c0_index() & 0x3F;
|
||||
}
|
||||
|
||||
void mmu_tlb_set_index(uint32_t index)
|
||||
{
|
||||
write_c0_index(index & 0x3F);
|
||||
}
|
||||
|
||||
uint32_t mmu_tlb_is_matched()
|
||||
{
|
||||
return (read_c0_index() & 0x80000000) == 0;
|
||||
}
|
||||
|
||||
uint64_t mmu_tlb_get_bad_vaddr()
|
||||
{
|
||||
return read_c0_badvaddr();
|
||||
}
|
||||
|
||||
void tlb_dump()
|
||||
{
|
||||
uint32_t max_index = mmu_get_max_tlb_index();
|
||||
//uint32_t max_index = 10;
|
||||
uint32_t entry;
|
||||
tlb_item_t tlb_item;
|
||||
|
||||
for(entry = 0;entry <= max_index;entry++)
|
||||
{
|
||||
mmu_tlb_read(entry,&tlb_item);
|
||||
//mmu_tlb_write_indexed(entry,&tlb_item);
|
||||
//mmu_tlb_read(entry,&tlb_item);
|
||||
rt_kprintf("vpn = 0x%p,ppn0 = 0x%p,ppn1 = 0x%p\n",(uint64_t)tlb_item.entry_hi.vpn2 << 13 | (uint64_t)tlb_item.entry_hi.asid << 62,(uint64_t)tlb_item.entry_lo[0].pfn << 12,(uint64_t)tlb_item.entry_lo[1].pfn << 12);
|
||||
rt_kprintf("v = %d,d = %d,g = %d,ri = %d,xi = %d,c = %d\n",tlb_item.entry_lo[0].v,tlb_item.entry_lo[0].d,tlb_item.entry_lo[0].g,tlb_item.entry_lo[0].ri,tlb_item.entry_lo[0].xi,tlb_item.entry_lo[0].c);
|
||||
rt_kprintf("v = %d,d = %d,g = %d,ri = %d,xi = %d,c = %d\n",tlb_item.entry_lo[1].v,tlb_item.entry_lo[1].d,tlb_item.entry_lo[1].g,tlb_item.entry_lo[1].ri,tlb_item.entry_lo[1].xi,tlb_item.entry_lo[1].c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2020, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2020-07-26 lizhirui the first version
|
||||
*/
|
||||
|
||||
#ifndef __MIPS_MMU_H__
|
||||
#define __MIPS_MMU_H__
|
||||
|
||||
typedef enum cpu_mode_t
|
||||
{
|
||||
CPU_MODE_KERNEL = 0x00,
|
||||
CPU_MODE_SUPERVISOR = 0x01,
|
||||
CPU_MODE_USER = 0x02
|
||||
}cpu_mode_t;
|
||||
|
||||
typedef enum page_mask_enum_t
|
||||
{
|
||||
PAGE_MASK_4KB = 0x00,
|
||||
PAGE_MASK_16KB = 0x03,
|
||||
PAGE_MASK_64KB = 0x0F,
|
||||
PAGE_MASK_256KB = 0x3F,
|
||||
PAGE_MASK_1MB = 0xFF,
|
||||
PAGE_MASK_4MB = 0x3FF,
|
||||
PAGE_MASK_16MB = 0xFFF,
|
||||
PAGE_MASK_64MB = 0x3FFF,
|
||||
PAGE_MASK_256MB = 0xFFFF,
|
||||
PAGE_MASK_1GB = 0x3FFFF
|
||||
}page_mask_enum_t;
|
||||
|
||||
typedef struct page_mask_t
|
||||
{
|
||||
uint64_t : 11;
|
||||
uint64_t : 2;
|
||||
uint64_t mask : 18;
|
||||
uint64_t : 33;
|
||||
}page_mask_t;
|
||||
|
||||
typedef struct entry_lo_t
|
||||
{
|
||||
uint64_t g : 1;
|
||||
uint64_t v : 1;
|
||||
uint64_t d : 1;
|
||||
uint64_t c : 3;
|
||||
uint64_t pfn : 24;
|
||||
uint64_t pfnx : 3;
|
||||
uint64_t : 29;
|
||||
uint64_t xi : 1;
|
||||
uint64_t ri : 1;
|
||||
}entry_lo_t;
|
||||
|
||||
typedef struct entry_hi_t
|
||||
{
|
||||
uint64_t asid : 8;
|
||||
uint64_t : 5;
|
||||
uint64_t vpn2 : 27;
|
||||
uint64_t : 22;
|
||||
uint64_t r : 2;
|
||||
}entry_hi_t;
|
||||
|
||||
typedef struct tlb_item_t
|
||||
{
|
||||
entry_lo_t entry_lo[2];
|
||||
entry_hi_t entry_hi;
|
||||
page_mask_t page_mask;
|
||||
}tlb_item_t;
|
||||
|
||||
#define read_c0_diag() __read_32bit_c0_register($22, 0)
|
||||
#define write_c0_diag(val) __write_32bit_c0_register($22, 0, val)
|
||||
#define read_c0_badvaddr() __read_64bit_c0_register($8, 0)
|
||||
#define read_c0_random() __read_32bit_c0_register($1, 0)
|
||||
|
||||
#define reg_type_convert(variable,new_type) *((new_type *)(&variable))
|
||||
#define lowbit(x) ((x) & (-(x)))
|
||||
|
||||
void mmu_init();
|
||||
void mmu_set_cpu_mode(cpu_mode_t cpu_mode);
|
||||
cpu_mode_t mmu_get_cpu_mode();
|
||||
void mmu_clear_tlb();
|
||||
void mmu_clear_itlb();
|
||||
uint32_t mmu_get_max_tlb_index();
|
||||
void mmu_tlb_write_indexed(uint32_t index,tlb_item_t *tlb_item);
|
||||
void mmu_tlb_write_random(tlb_item_t *tlb_item);
|
||||
void mmu_tlb_read(uint32_t index,tlb_item_t *tlb_item);
|
||||
uint32_t mmu_tlb_find(uint64_t vpn,uint32_t asid,uint32_t *index);
|
||||
void mmu_tlb_item_init(tlb_item_t *tlb_item);
|
||||
void mmu_set_map(uint64_t vpn,uint64_t ppn,page_mask_enum_t page_mask,uint32_t asid,uint32_t global);
|
||||
uint32_t mmu_tlb_get_random();
|
||||
uint32_t mmu_tlb_get_index();
|
||||
void mmu_tlb_set_index(uint32_t index);
|
||||
uint32_t mmu_tlb_is_matched();
|
||||
uint64_t mmu_tlb_get_bad_vaddr();
|
||||
|
||||
void tlb_dump();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2020, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2020-07-28 lizhirui first version
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
#include <mips.h>
|
||||
|
||||
mips32_core_cfg_t g_mips_core =
|
||||
{
|
||||
64, /* icache_line_size */
|
||||
128, /* icache_lines_per_way */
|
||||
4, /* icache_ways */
|
||||
32768,
|
||||
64, /* dcache_line_size */
|
||||
128, /* dcache_lines_per_way */
|
||||
4, /* dcache_ways */
|
||||
32768,
|
||||
64, /* max_tlb_entries */
|
||||
};
|
||||
|
||||
static rt_uint16_t m_pow(rt_uint16_t b, rt_uint16_t n)
|
||||
{
|
||||
rt_uint16_t rets = 1;
|
||||
|
||||
while (n--)
|
||||
rets *= b;
|
||||
|
||||
return rets;
|
||||
}
|
||||
|
||||
static rt_uint16_t m_log2(rt_uint16_t b)
|
||||
{
|
||||
rt_uint16_t rets = 0;
|
||||
|
||||
while (b != 1)
|
||||
{
|
||||
b /= 2;
|
||||
rets++;
|
||||
}
|
||||
|
||||
return rets;
|
||||
}
|
||||
|
||||
/**
|
||||
* read core attribute
|
||||
*/
|
||||
void mips32_cfg_init(void)
|
||||
{
|
||||
rt_uint16_t val;
|
||||
rt_uint32_t cp0_config1;
|
||||
|
||||
cp0_config1 = read_c0_config();
|
||||
if (cp0_config1 & 0x80000000)
|
||||
{
|
||||
cp0_config1 = read_c0_config1();
|
||||
|
||||
val = (cp0_config1 & (7<<22))>>22;
|
||||
g_mips_core.icache_lines_per_way = 64 * m_pow(2, val);
|
||||
val = (cp0_config1 & (7<<19))>>19;
|
||||
g_mips_core.icache_line_size = 2 * m_pow(2, val);
|
||||
val = (cp0_config1 & (7<<16))>>16;
|
||||
g_mips_core.icache_ways = val + 1;
|
||||
|
||||
val = (cp0_config1 & (7<<13))>>13;
|
||||
g_mips_core.dcache_lines_per_way = 64 * m_pow(2, val);
|
||||
val = (cp0_config1 & (7<<10))>>10;
|
||||
g_mips_core.dcache_line_size = 2 * m_pow(2, val);
|
||||
val = (cp0_config1 & (7<<7))>>7;
|
||||
g_mips_core.dcache_ways = val + 1;
|
||||
|
||||
val = (cp0_config1 & (0x3F<<25))>>25;
|
||||
g_mips_core.max_tlb_entries = val + 1;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-03-25 quanzhao the first version
|
||||
* 2020-07-26 lizhirui porting to ls2k
|
||||
*/
|
||||
#ifndef __MMU_H_
|
||||
#define __MMU_H_
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#define DESC_SEC (0x2)
|
||||
#define MEMWBWA ((1<<12)|(3<<2)) /* write back, write allocate */
|
||||
#define MEMWB (3<<2) /* write back, no write allocate */
|
||||
#define MEMWT (2<<2) /* write through, no write allocate */
|
||||
#define SHAREDEVICE (1<<2) /* shared device */
|
||||
#define STRONGORDER (0<<2) /* strong ordered */
|
||||
#define XN (1<<4) /* eXecute Never */
|
||||
#ifdef RT_USING_USERSPACE
|
||||
#define AP_RW (1<<10) /* supervisor=RW, user=No */
|
||||
#define AP_RO ((1<<10) |(1 << 15)) /* supervisor=RW, user=No */
|
||||
#else
|
||||
#define AP_RW (3<<10) /* supervisor=RW, user=RW */
|
||||
#define AP_RO ((2<<10) /* supervisor=RW, user=RO */
|
||||
#endif
|
||||
|
||||
#define SHARED (1<<16) /* shareable */
|
||||
|
||||
#define DOMAIN_FAULT (0x0)
|
||||
#define DOMAIN_CHK (0x1)
|
||||
#define DOMAIN_NOTCHK (0x3)
|
||||
#define DOMAIN0 (0x0<<5)
|
||||
#define DOMAIN1 (0x1<<5)
|
||||
|
||||
#define DOMAIN0_ATTR (DOMAIN_CHK<<0)
|
||||
#define DOMAIN1_ATTR (DOMAIN_FAULT<<2)
|
||||
|
||||
/* device mapping type */
|
||||
#define DEVICE_MEM (SHARED|AP_RW|DOMAIN0|SHAREDEVICE|DESC_SEC|XN)
|
||||
/* normal memory mapping type */
|
||||
#define NORMAL_MEM (SHARED|AP_RW|DOMAIN0|MEMWBWA|DESC_SEC)
|
||||
|
||||
#define STRONG_ORDER_MEM (SHARED|AP_RO|XN|DESC_SEC)
|
||||
|
||||
struct mem_desc
|
||||
{
|
||||
rt_uint32_t vaddr_start;
|
||||
rt_uint32_t vaddr_end;
|
||||
rt_uint32_t paddr_start;
|
||||
rt_uint32_t attr;
|
||||
};
|
||||
|
||||
#define MMU_MAP_MTBL_XN (1<<0)
|
||||
#define MMU_MAP_MTBL_A (1<<1)
|
||||
#define MMU_MAP_MTBL_B (1<<2)
|
||||
#define MMU_MAP_MTBL_C (1<<3)
|
||||
#define MMU_MAP_MTBL_AP01(x) (x<<4)
|
||||
#define MMU_MAP_MTBL_TEX(x) (x<<6)
|
||||
#define MMU_MAP_MTBL_AP2(x) (x<<9)
|
||||
#define MMU_MAP_MTBL_SHARE (1<<10)
|
||||
|
||||
#define MMU_MAP_K_RO (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(1)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE)
|
||||
#define MMU_MAP_K_RWCB (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE)
|
||||
#define MMU_MAP_K_RW (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_SHARE)
|
||||
#define MMU_MAP_K_DEVICE (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_SHARE)
|
||||
#define MMU_MAP_U_RO (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(1)|MMU_MAP_MTBL_AP01(2)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE)
|
||||
#define MMU_MAP_U_RWCB (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE)
|
||||
#define MMU_MAP_U_RW (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_SHARE)
|
||||
#define MMU_MAP_U_DEVICE (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_SHARE)
|
||||
|
||||
#define ARCH_SECTION_SHIFT 20
|
||||
#define ARCH_SECTION_SIZE (1 << ARCH_SECTION_SHIFT)
|
||||
#define ARCH_SECTION_MASK (ARCH_SECTION_SIZE - 1)
|
||||
#define ARCH_PAGE_SHIFT 14
|
||||
#define ARCH_PAGE_SIZE (1 << ARCH_PAGE_SHIFT)
|
||||
#define ARCH_PAGE_MASK (ARCH_PAGE_SIZE - 1)
|
||||
#define ARCH_PAGE_TBL_SHIFT 10
|
||||
#define ARCH_PAGE_TBL_SIZE (1 << ARCH_PAGE_TBL_SHIFT)
|
||||
#define ARCH_PAGE_TBL_MASK (ARCH_PAGE_TBL_SIZE - 1)
|
||||
|
||||
#define ARCH_MMU_USED_MASK 3
|
||||
|
||||
#define ARCH_TYPE_SUPERSECTION (1 << 18)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t *vtable;
|
||||
size_t vstart;
|
||||
size_t vend;
|
||||
size_t pv_off;
|
||||
} rt_mmu_info;
|
||||
|
||||
void *mmu_table_get();
|
||||
void switch_mmu(void *mmu_table);
|
||||
|
||||
int rt_hw_mmu_map_init(rt_mmu_info *mmu_info, void* v_address, size_t size, size_t *vtable, size_t pv_off);
|
||||
#ifdef RT_USING_USERSPACE
|
||||
void *rt_hw_mmu_map(rt_mmu_info *mmu_info, void *v_addr, void* p_addr, size_t size, size_t attr);
|
||||
void *rt_hw_mmu_map_auto(rt_mmu_info *mmu_info, void *v_addr, size_t size, size_t attr);
|
||||
#else
|
||||
void *rt_hw_mmu_map(rt_mmu_info *mmu_info, void* p_addr, size_t size, size_t attr);
|
||||
#endif
|
||||
void rt_hw_mmu_unmap(rt_mmu_info *mmu_info, void* v_addr, size_t size);
|
||||
void *rt_hw_mmu_v2p(rt_mmu_info *mmu_info, void* v_addr);
|
||||
|
||||
void *rt_hw_kernel_phys_to_virt(void *p_addr, size_t size);
|
||||
void *rt_hw_kernel_virt_to_phys(void *v_addr, size_t size);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user