/kernel/trunk/doc/TODO |
---|
4,13 → 4,12 |
+ [ia32] use int 0x15 ax=0xe820 to get memory map and memory size [DONE] |
+ [mips] use some heuristics to get memory map and memory size |
+ reimplement heap so that it can allocate/deallocate |
itself frames as necessary |
itself frames as necessary [DONE] |
+ provide native four-level portable page table interface [DONE] |
+ every architecture uses its native page table format |
+ kernel provides unified four-level page table interface |
for all architectures |
+ track usage of frames containing middle-level page tables |
(frame leak) |
or page hash table interface to architectures |
+ deallocation of memory of empty page tables [DONE] |
+ get user mode support for all architectures |
/kernel/trunk/genarch/include/mm/page_pt.h |
---|
40,6 → 40,14 |
#include <mm/page.h> |
/* |
* Number of entries in each level. |
*/ |
#define PTL0_ENTRIES PTL0_ENTRIES_ARCH |
#define PTL1_ENTRIES PTL1_ENTRIES_ARCH |
#define PTL2_ENTRIES PTL2_ENTRIES_ARCH |
#define PTL3_ENTRIES PTL3_ENTRIES_ARCH |
/* |
* These macros process vaddr and extract those portions |
* of it that function as indices to respective page tables. |
*/ |
84,6 → 92,11 |
#define SET_PTL3_FLAGS(ptl2, i, x) SET_PTL3_FLAGS_ARCH(ptl2, i, x) |
#define SET_FRAME_FLAGS(ptl3, i, x) SET_FRAME_FLAGS_ARCH(ptl3, i, x) |
/* |
* Determine whether the mapping is valid. |
*/ |
#define PTE_VALID(p) PTE_VALID_ARCH((p)) |
extern page_mapping_operations_t pt_mapping_operations; |
extern void page_mapping_insert_pt(as_t *as, __address page, __address frame, int flags); |
/kernel/trunk/genarch/src/mm/page_pt.c |
---|
103,6 → 103,8 |
* TLB shootdown should follow in order to make effects of |
* this call visible. |
* |
* Empty page tables except PTL0 are freed. |
* |
* The address space must be locked and interrupts must be disabled. |
* |
* @param as Address space to wich page belongs. |
111,7 → 113,13 |
void pt_mapping_remove(as_t *as, __address page) |
{ |
pte_t *ptl0, *ptl1, *ptl2, *ptl3; |
bool empty = true; |
int i; |
/* |
* First, remove the mapping, if it exists. |
*/ |
ptl0 = (pte_t *) PA2KA((__address) as->page_table); |
if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) |
131,6 → 139,86 |
/* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */ |
memsetb((__address) &ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0); |
/* |
* Second, free all empty tables along the way from PTL3 down to PTL0. |
*/ |
/* check PTL3 */ |
for (i = 0; i < PTL3_ENTRIES; i++) { |
if (PTE_VALID(&ptl3[i])) { |
empty = false; |
break; |
} |
} |
if (empty) { |
/* |
* PTL3 is empty. |
* Release the frame and remove PTL3 pointer from preceding table. |
*/ |
frame_free(ADDR2PFN(KA2PA((__address) ptl3))); |
if (PTL2_ENTRIES) |
memsetb((__address) &ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0); |
else if (PTL1_ENTRIES) |
memsetb((__address) &ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0); |
else |
memsetb((__address) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
} else { |
/* |
* PTL3 is not empty. |
* Therefore, there must be a path from PTL0 to PTL3 and |
* thus nothing to free in higher levels. |
*/ |
return; |
} |
/* check PTL2, empty is still true */ |
if (PTL2_ENTRIES) { |
for (i = 0; i < PTL2_ENTRIES; i++) { |
if (PTE_VALID(&ptl2[i])) { |
empty = false; |
break; |
} |
} |
if (empty) { |
/* |
* PTL2 is empty. |
* Release the frame and remove PTL2 pointer from preceding table. |
*/ |
frame_free(ADDR2PFN(KA2PA((__address) ptl2))); |
if (PTL1_ENTRIES) |
memsetb((__address) &ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0); |
else |
memsetb((__address) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
} |
else { |
/* |
* PTL2 is not empty. |
* Therefore, there must be a path from PTL0 to PTL2 and |
* thus nothing to free in higher levels. |
*/ |
return; |
} |
} |
/* check PTL1, empty is still true */ |
if (PTL1_ENTRIES) { |
for (i = 0; i < PTL1_ENTRIES; i++) { |
if (PTE_VALID(&ptl1[i])) { |
empty = false; |
break; |
} |
} |
if (empty) { |
/* |
* PTL1 is empty. |
* Release the frame and remove PTL1 pointer from preceding table. |
*/ |
frame_free(ADDR2PFN(KA2PA((__address) ptl1))); |
memsetb((__address) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0); |
} |
} |
} |
/** Find mapping for virtual page in hierarchical page tables. |
/kernel/trunk/arch/amd64/include/mm/page.h |
---|
47,6 → 47,11 |
# define PA2KA(x) ((x) + 0xffffffff80000000) |
#endif |
#define PTL0_ENTRIES_ARCH 512 |
#define PTL1_ENTRIES_ARCH 512 |
#define PTL2_ENTRIES_ARCH 512 |
#define PTL3_ENTRIES_ARCH 512 |
#define PTL0_INDEX_ARCH(vaddr) (((vaddr)>>39)&0x1ff) |
#define PTL1_INDEX_ARCH(vaddr) (((vaddr)>>30)&0x1ff) |
#define PTL2_INDEX_ARCH(vaddr) (((vaddr)>>21)&0x1ff) |
73,6 → 78,8 |
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x) set_pt_flags((pte_t *)(ptl2), (index_t)(i), (x)) |
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) set_pt_flags((pte_t *)(ptl3), (index_t)(i), (x)) |
#define PTE_VALID_ARCH(p) (*((__u64 *) (p)) != 0) |
#ifndef __ASM__ |
/** Page Table Entry. */ |
/kernel/trunk/arch/mips32/include/mm/page.h |
---|
58,6 → 58,11 |
* - PTL3 has 4096 entries (12 bits) |
*/ |
#define PTL0_ENTRIES_ARCH 64 |
#define PTL1_ENTRIES_ARCH 0 |
#define PTL2_ENTRIES_ARCH 0 |
#define PTL3_ENTRIES_ARCH 4096 |
#define PTL0_INDEX_ARCH(vaddr) ((vaddr)>>26) |
#define PTL1_INDEX_ARCH(vaddr) 0 |
#define PTL2_INDEX_ARCH(vaddr) 0 |
85,6 → 90,8 |
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x) |
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) set_pt_flags((pte_t *)(ptl3), (index_t)(i), (x)) |
#define PTE_VALID_ARCH(p) (*((__u32 *) (p)) != 0) |
#ifndef __ASM__ |
#include <arch/mm/tlb.h> |
/kernel/trunk/arch/ia32/include/mm/page.h |
---|
44,6 → 44,11 |
* Implementation of generic 4-level page table interface. |
* IA-32 has 2-level page tables, so PTL1 and PTL2 are left out. |
*/ |
#define PTL0_ENTRIES_ARCH 1024 |
#define PTL1_ENTRIES_ARCH 0 |
#define PTL2_ENTRIES_ARCH 0 |
#define PTL3_ENTRIES_ARCH 1024 |
#define PTL0_INDEX_ARCH(vaddr) (((vaddr)>>22)&0x3ff) |
#define PTL1_INDEX_ARCH(vaddr) 0 |
#define PTL2_INDEX_ARCH(vaddr) 0 |
70,6 → 75,8 |
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x) |
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) set_pt_flags((pte_t *)(ptl3), (index_t)(i), (x)) |
#define PTE_VALID_ARCH(p) (*((__u32 *) (p)) != 0) |
#ifndef __ASM__ |
#include <mm/page.h> |