added page_iterate(): a recursive page tree walker
This commit is contained in:
parent
4514080014
commit
8fe165c162
2 changed files with 82 additions and 2 deletions
|
@ -40,15 +40,19 @@
|
|||
#define PAGE_MAP_LEVELS 2
|
||||
/// Page map bits
|
||||
#define PAGE_MAP_SHIFT 10
|
||||
/// Total operand width in bits
|
||||
#define BITS 32
|
||||
/// Linear/virtual address width
|
||||
#define VIRT_BITS 32
|
||||
#define VIRT_BITS BITS
|
||||
/// Physical address width (we dont support PAE)
|
||||
#define PHYS_BITS 32
|
||||
#define PHYS_BITS BITS
|
||||
#elif defined(CONFIG_X86_64)
|
||||
/// Number of page map indirections
|
||||
#define PAGE_MAP_LEVELS 4
|
||||
/// Page map bits
|
||||
#define PAGE_MAP_SHIFT 9
|
||||
/// Total operand width in bits
|
||||
#define BITS 64
|
||||
/// Linear/virtual address width
|
||||
#define VIRT_BITS 48
|
||||
/// Physical address width (maximum value)
|
||||
|
@ -133,6 +137,15 @@ typedef struct page_map {
|
|||
page_entry_t entries[PAGE_MAP_ENTRIES];
|
||||
} __attribute__ ((aligned (PAGE_SIZE))) page_map_t;
|
||||
|
||||
/** @brief A callback type for the page map iterator
|
||||
*
|
||||
* @param entry A pointer to the current page map entry
|
||||
* @return
|
||||
* - 0 if we want to skip underlying page tables
|
||||
* - >0 if want to recurse into underlying page tables
|
||||
*/
|
||||
typedef int (*page_cb_t)(page_entry_t* entry, int level);
|
||||
|
||||
/** @brief Converts a virtual address to a physical
|
||||
*
|
||||
* @param viraddr Virtual address to convert
|
||||
|
|
|
@ -91,6 +91,73 @@ static int entry_to_level(page_entry_t* entry) {
|
|||
|
||||
return level;
|
||||
}
|
||||
|
||||
/** @brief Recursive traversal through the page map tree
|
||||
*
|
||||
* @param start The first address whose page map entry we will call on
|
||||
* @param end The exclusive end address whose page map entry we will call on
|
||||
* @param pre Callback which is called for every page map entry (pre-order traversal)
|
||||
* @param post Callback which is called for every page map entry (post-order traversal)
|
||||
*/
|
||||
int page_iterate(size_t start, size_t end, page_cb_t pre, page_cb_t post)
|
||||
{
|
||||
page_entry_t* entry[PAGE_MAP_LEVELS];
|
||||
page_entry_t* last[PAGE_MAP_LEVELS];
|
||||
|
||||
// setup subtree boundaries
|
||||
int i;
|
||||
for (i=0; i<PAGE_MAP_LEVELS; i++) {
|
||||
entry[i] = virt_to_entry(start, i);
|
||||
// this last addresses are exclusive!
|
||||
// for end == 0 we take the whole address space (overflow => 0)
|
||||
last[i] = (end) ? virt_to_entry(end - PAGE_SIZE, i) + 1 : 0;
|
||||
}
|
||||
|
||||
// nested iterator function (sees the scope of parent)
|
||||
int iterate(int level) {
|
||||
int ret;
|
||||
while (entry[level] != last[level]) {
|
||||
//if (*entry[level] && level) kprintf("page_iterate: level=%u, entry[level]=%p, last[level]=%p\n", level, entry[level], last[level]);
|
||||
|
||||
// pre-order callback
|
||||
if (pre)
|
||||
ret = pre(entry[level], level);
|
||||
|
||||
if (BUILTIN_EXPECT(ret < 0, 0))
|
||||
return ret;
|
||||
|
||||
// recurse if
|
||||
// - we are not in the PGT
|
||||
// - and the inferior page table is present
|
||||
// - and the current entry is no huge page
|
||||
if (level && (*entry[level] & PG_PRESENT) && !(*entry[level] & PG_PSE))
|
||||
iterate(level-1);
|
||||
// or skip the entries we've omit...
|
||||
else {
|
||||
size_t next = (size_t) (entry[level]+1);
|
||||
for (i=0; i<level; i++)
|
||||
entry[i] = (page_entry_t*) (next << (PAGE_MAP_SHIFT*(level-i)));
|
||||
}
|
||||
|
||||
// post-order callback
|
||||
if (post)
|
||||
ret = post(entry[level], level);
|
||||
|
||||
if (BUILTIN_EXPECT(ret < 0, 0))
|
||||
return ret;
|
||||
|
||||
// return if
|
||||
// - we are not at the root table
|
||||
// - and we've reached the end of the current table
|
||||
entry[level]++;
|
||||
if (((size_t) entry[level] & ~PAGE_MASK) == 0x000)
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iterate(PAGE_MAP_LEVELS-1);
|
||||
}
|
||||
/** @brief Copy a single page frame
|
||||
*
|
||||
* @param src virtual address of source page frame
|
||||
|
|
Loading…
Add table
Reference in a new issue