-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mmu2 #4
base: pre_mmu2
Are you sure you want to change the base?
Mmu2 #4
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,41 @@ | |
#include "cp15_cacheops.h" | ||
#include "mmu.h" | ||
|
||
#ifdef CONFIG_APP_BINARY_SEPARATION | ||
#include <tinyara/mm/mm.h> | ||
#endif | ||
/**************************************************************************** | ||
* Private Functions | ||
****************************************************************************/ | ||
static void mmu_set_flags(uint32_t *val, bool ro, bool exec, uint8_t isL1, uint8_t isGlobal) | ||
{ | ||
if (isL1) { | ||
if (ro && exec) { | ||
*val |= MMU_APP_L1_ROX; | ||
} else if (ro) { | ||
*val |= MMU_APP_L1_RO; | ||
} else { | ||
*val |= MMU_APP_L1_RW; | ||
} | ||
|
||
if (!isGlobal) { | ||
*val |= PMD_SECT_NG; | ||
} | ||
} else { | ||
if (ro && exec) { | ||
*val |= MMU_APP_L2_ROX; | ||
} else if (ro) { | ||
*val |= MMU_APP_L2_RO; | ||
} else { | ||
*val |= MMU_APP_L2_RW; | ||
} | ||
|
||
if (!isGlobal) { | ||
*val |= PTE_NG; | ||
} | ||
} | ||
} | ||
|
||
/**************************************************************************** | ||
* Public Functions | ||
****************************************************************************/ | ||
|
@@ -254,3 +289,264 @@ void mmu_invalidate_region(uint32_t vstart, size_t size) | |
} | ||
} | ||
#endif | ||
|
||
#ifdef CONFIG_APP_BINARY_SEPARATION | ||
/**************************************************************************** | ||
* Name: mmu_get_os_l1_pgtbl | ||
* | ||
* Description: | ||
* Returns the virtual address of the kernel L1 page table. | ||
* | ||
* Input Parameters: | ||
* | ||
* Returned Value: | ||
* Page table address | ||
****************************************************************************/ | ||
uint32_t *mmu_get_os_l1_pgtbl(void) | ||
{ | ||
return (uint32_t *)PGTABLE_BASE_VADDR; | ||
} | ||
|
||
/**************************************************************************** | ||
* Name: mmu_allocate_app_l1_pgtbl | ||
* | ||
* Description: | ||
* Allocate space for L1 page table of application, in accordance with | ||
* the requirements of the arch specific mmu. | ||
* | ||
* Input Parameters: | ||
* | ||
* Returned Value: | ||
* L1 Page table address | ||
****************************************************************************/ | ||
uint32_t *mmu_allocate_app_l1_pgtbl(int app_id) | ||
{ | ||
uint32_t *addr = (uint32_t *)(PGTABLE_BASE_VADDR + (app_id * 16384)); | ||
// uint32_t *addr = (uint32_t *)kmm_memalign(L1_PGTBL_ALIGNMENT, L1_PGTBL_SIZE); | ||
// ASSERT(addr); | ||
// memset(addr, 0, L1_PGTBL_SIZE); | ||
return addr; | ||
} | ||
|
||
/**************************************************************************** | ||
* Name: mmu_allocate_app_l2_pgtbl | ||
* | ||
* Description: | ||
* Allocate space for L2 page table of application, in accordance with | ||
* the requirements of the arch specific mmu. | ||
* | ||
* Input Parameters: | ||
* | ||
* Returned Value: | ||
* L2 Page table address | ||
****************************************************************************/ | ||
uint32_t *mmu_allocate_app_l2_pgtbl(int app_id, int l2_idx) | ||
{ | ||
app_id--; | ||
uint32_t *addr = (uint32_t *)(PGTABLE_BASE_VADDR + (2 * 16384) + (app_id * l2_idx * 1024)); | ||
// uint32_t *addr = (uint32_t *)kmm_memalign(L2_PGTBL_ALIGNMENT, L2_PGTBL_SIZE); | ||
// ASSERT(addr); | ||
// memset(addr, 0, L2_PGTBL_SIZE); | ||
return addr; | ||
} | ||
|
||
/**************************************************************************** | ||
* Name: mmu_update_app_l1_pgtbl_ospgtbl | ||
* | ||
* Description: | ||
* Loop through the L1 page table. | ||
* Copy kernel L1 page table to app page table. | ||
* If the entry is pointing to a L2 page table | ||
* Allocate L2 page table for app. | ||
* Copy entries from kernel to app L2 table. | ||
* Update the L2 page table address in L1 table. | ||
* | ||
* Input Parameters: | ||
* app_pgtbl: Pointer to L1 page table of app | ||
* | ||
****************************************************************************/ | ||
void mmu_update_app_l1_pgtbl_ospgtbl(uint32_t *app_l1_pgtbl) | ||
{ | ||
uint32_t *os_l1_pgtbl = (uint32_t *)PGTABLE_BASE_VADDR; | ||
|
||
memcpy((void *)app_l1_pgtbl, (void *)os_l1_pgtbl, L1_PGTBL_SIZE); | ||
cp15_flush_dcache((uintptr_t)app_l1_pgtbl, (uintptr_t)app_l1_pgtbl + L1_PGTBL_SIZE); | ||
|
||
#ifdef CONFIG_SUPPORT_COMMON_BINARY | ||
for (int i = 0; i < L1_PGTBL_NENTRIES; i++) { | ||
if ((os_l1_pgtbl[i] & PMD_TYPE_MASK) == PMD_TYPE_PTE) { | ||
//Found a L2 page table. | ||
uint32_t *os_l2_pgtbl = (uint32_t *)(os_l1_pgtbl[i] & PMD_PTE_PADDR_MASK); | ||
uint32_t *app_l2_pgtbl = mmu_allocate_app_l2_pgtbl(); | ||
memcpy(app_l2_pgtbl, os_l2_pgtbl, L2_PGTBL_SIZE); | ||
app_l1_pgtbl[i] &= ~PMD_PTE_PADDR_MASK; | ||
app_l1_pgtbl[i] |= (uint32_t)app_l2_pgtbl & PMD_PTE_PADDR_MASK; | ||
} | ||
} | ||
#endif | ||
} | ||
|
||
/**************************************************************************** | ||
* Name: mmu_map_app_region | ||
* | ||
* Description | ||
* | ||
* Input Parameters: | ||
* | ||
* Returned Value: | ||
****************************************************************************/ | ||
void mmu_map_app_region(int app_id, uint32_t *l1_pgtbl, uint32_t start, uint32_t size, bool ro, bool exec, bool global) | ||
{ | ||
uint32_t idx; | ||
uint32_t val; | ||
uint32_t end = start + size; | ||
irqstate_t flags; | ||
|
||
lldbg("start = 0x%08x end = 0x%08x size = %x\n", start, end, size); | ||
|
||
// Run a loop until the entire region is mapped. | ||
while (start < end) { | ||
// Check if this address can be mapped to a section. | ||
if (!(start & SECTION_MASK) && !(size & SECTION_MASK)) { | ||
// Yes. Update the section entry in the the L1 page table. | ||
idx = start >> 20; | ||
val = start & PMD_PTE_PADDR_MASK; | ||
mmu_set_flags(&val, ro, exec, true, global); | ||
|
||
lldbg("Add section for addr 0x%08x idx = %d\n", start, idx); | ||
|
||
if (global) { | ||
// If this update is for the common binary, then it is done | ||
// in the kernel page tables and so the cache and tlbs need | ||
// to be flushed and invalidated. | ||
flags = enter_critical_section(); | ||
l1_pgtbl[idx] = val; | ||
cp15_clean_dcache_bymva((uint32_t)&l1_pgtbl[idx]); | ||
mmu_invalidate_region(start, SECTION_SIZE); | ||
leave_critical_section(flags); | ||
} else { | ||
l1_pgtbl[idx] = val; | ||
cp15_clean_dcache_bymva((uint32_t)&l1_pgtbl[idx]); | ||
} | ||
|
||
// Advance the memory region address. | ||
start += SECTION_SIZE; | ||
} else { // Check if this address can be mapped to a small page. | ||
|
||
// Check if L2 page table is not created. | ||
idx = (start & 0xfff00000) >> 20; | ||
int l2_idx = 0; | ||
uint32_t *l2_pgtbl = (uint32_t *)(l1_pgtbl[idx] & PMD_PTE_PADDR_MASK); | ||
if ((l1_pgtbl[idx] & PMD_TYPE_MASK) != PMD_TYPE_PTE) { | ||
// Yes. Allocate L2 page table for app. | ||
l2_pgtbl = mmu_allocate_app_l2_pgtbl(app_id, l2_idx++); | ||
|
||
lldbg("Allocated L2 pgtbl at 0x%08x\n", l2_pgtbl); | ||
if (global) { | ||
// If this update is for the common binary, then it is done | ||
// in the kernel page tables and so the cache and tlbs need | ||
// to be flushed and invalidated. | ||
|
||
flags = enter_critical_section(); | ||
|
||
// Fill default entries into L2 page table. | ||
uint32_t tmp = start; | ||
for (idx = 0; idx < L2_PGTBL_NENTRIES; idx++) { | ||
val = tmp & PTE_SMALL_PADDR_MASK; | ||
val |= MMU_MEMFLAGS; | ||
l2_pgtbl[idx] = val; | ||
cp15_clean_dcache_bymva((uint32_t)&l2_pgtbl[idx]); | ||
tmp += 4096; | ||
} | ||
|
||
// Update L2 page table address in L1 page table. | ||
val = (uint32_t)l2_pgtbl & PMD_PTE_PADDR_MASK; | ||
val |= MMU_L1_DATAFLAGS; | ||
l1_pgtbl[idx] = val; | ||
|
||
cp15_clean_dcache_bymva((uint32_t)&l1_pgtbl[idx]); | ||
cp15_invalidate_tlb_bymva(start); | ||
leave_critical_section(flags); | ||
} else { | ||
// Update L2 page table address in L1 page table. | ||
val = (uint32_t)l2_pgtbl & PMD_PTE_PADDR_MASK; | ||
val |= MMU_L1_PGTABFLAGS; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this looks wrong, it has some flags that are not needed.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. Will look into it. But changing it is not fixing the issue. |
||
l1_pgtbl[idx] = val; | ||
// dbg("Set l1 pte at 0x%08x = 0x%08x\n", &l1_pgtbl[idx], val); | ||
cp15_clean_dcache_bymva((uint32_t)&l1_pgtbl[idx]); | ||
} | ||
} | ||
|
||
// Update the L2 page table entry. | ||
idx = (start & 0x000ff000) >> 12; | ||
val = start & PTE_SMALL_PADDR_MASK; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we are filling the addresses from only the start in the page table, it will miss some entries before start and after end. I think it might not be right?? (May cause prefetch abort when fetching the address that does not have an entry in secondary page table?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. I will change it. But it will not affect our current issue. |
||
mmu_set_flags(&val, ro, exec, false, global); | ||
|
||
if (global) { | ||
flags = enter_critical_section(); | ||
l2_pgtbl[idx] = val; | ||
// If this update is for the common binary, then it is done | ||
// in the kernel page tables and so the cache and tlbs need | ||
// to be flushed and invalidated. | ||
cp15_clean_dcache_bymva((uint32_t)&l2_pgtbl[idx]); | ||
cp15_invalidate_tlb_bymva(start); | ||
leave_critical_section(flags); | ||
} else { | ||
l2_pgtbl[idx] = val; | ||
// dbg("Set l2 pte at 0x%08x = 0x%08x\n", &l2_pgtbl[idx], val); | ||
cp15_clean_dcache_bymva((uint32_t)&l2_pgtbl[idx]); | ||
} | ||
|
||
// Advance the memory region address. | ||
start += SMALL_PAGE_SIZE; | ||
} | ||
} | ||
} | ||
|
||
#endif // CONFIG_APP_BINARY_SEPARATION | ||
|
||
|
||
void mmu_dump_pgtbl(void) | ||
{ | ||
struct tcb_s *rtcb = sched_self(); | ||
if (rtcb->app_id < 1) { | ||
return; | ||
} | ||
|
||
uint32_t *l1tbl = mmu_l1_pgtable(); | ||
|
||
lldbg("L1 page table base addr = 0x%08x\n", l1tbl); | ||
|
||
lldbg("================================================\n"); | ||
lldbg("ENTRY TYPE OUT NG AP XN\n"); | ||
lldbg("ADDR ADDR \n"); | ||
lldbg("================================================\n"); | ||
for (int i = 0; i < L1_PGTBL_NENTRIES; i++) { | ||
bool ng = (l1tbl[i] & PMD_SECT_NG) ? 1 : 0; | ||
if (ng && (l1tbl[i] & PMD_TYPE_MASK) == PMD_TYPE_SECT) { | ||
lldbg("0x%08x SECT 0x%08x %d %1x%1x %d\n", | ||
&l1tbl[i], | ||
l1tbl[i] & PMD_SECT_PADDR_MASK, | ||
(l1tbl[i] & PMD_SECT_NG) ? 1 : 0, | ||
(l1tbl[i] & PMD_SECT_AP2) ? 1 : 0, | ||
(l1tbl[i] & PMD_SECT_AP_MASK) >> PMD_SECT_AP_SHIFT, | ||
(l1tbl[i] & PMD_SECT_XN) ? 1 : 0); | ||
} else if((l1tbl[i] & PMD_TYPE_MASK) == PMD_TYPE_PTE) { | ||
lldbg("0x%08x L1PTE 0x%08x\n", &l1tbl[i], l1tbl[i] & PMD_PTE_PADDR_MASK); | ||
uint32_t *l2tbl = (uint32_t)l1tbl[i] & PMD_PTE_PADDR_MASK; | ||
for (int j = 0; j < L2_PGTBL_NENTRIES; j++) { | ||
bool ng = (l2tbl[j] & PTE_NG) ? 1 : 0; | ||
if (ng && ((l2tbl[j] & PTE_TYPE_MASK) != PTE_TYPE_FAULT)) { | ||
lldbg("0x%08x PAGE 0x%08x %d %1x%1x %d\n", | ||
&l2tbl[j], | ||
l2tbl[j] & PTE_SMALL_PADDR_MASK, | ||
(l2tbl[j] & PTE_NG) ? 1 : 0, | ||
(l2tbl[j] & PTE_AP2) ? 1 : 0, | ||
(l2tbl[j] & PTE_AP_MASK) >> PTE_AP_SHIFT, | ||
(l2tbl[j] & PTE_SMALL_XN) ? 1 : 0); | ||
} | ||
} | ||
} | ||
} | ||
lldbg("=============================================\n"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not required at present, but may be needed to change the mask to section instead of PTE