mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
[kernel] Add add_existing() to page_tree
This ended up being unused, but still probably useful: Refactor out the "find" logic of page_tree::find_or_add (note that this is different than the "find" logic of page_tree::find, as it potentially modifies the tree to add a location to accommodate the page being searched for) into a new page_tree::get_entry method. That was then used to add an add_existing method for inserting pages into the page_tree.
This commit is contained in:
@@ -58,30 +58,8 @@ page_tree::contains(uint64_t offset, uint8_t &index) const
|
|||||||
return (offset & level_mask(m_level)) == m_base;
|
return (offset & level_mask(m_level)) == m_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
uintptr_t &
|
||||||
page_tree::find(const page_tree *root, uint64_t offset, uintptr_t &page)
|
page_tree::get_entry(page_tree * &root, uint64_t offset)
|
||||||
{
|
|
||||||
page_tree const *node = root;
|
|
||||||
while (node) {
|
|
||||||
uint8_t level = node->m_level;
|
|
||||||
uint8_t index = 0;
|
|
||||||
if (!node->contains(offset, index))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!level) {
|
|
||||||
uintptr_t entry = node->m_entries[index].entry;
|
|
||||||
page = entry & ~0xfffull;
|
|
||||||
return (entry & 1); // bit 0 marks 'present'
|
|
||||||
}
|
|
||||||
|
|
||||||
node = node->m_entries[index].child;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
page_tree::find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page)
|
|
||||||
{
|
{
|
||||||
page_tree *level0 = nullptr;
|
page_tree *level0 = nullptr;
|
||||||
|
|
||||||
@@ -125,7 +103,7 @@ page_tree::find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page)
|
|||||||
node = *parent;
|
node = *parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
kassert( node || parent, "Both node and parent were null in find_or_add");
|
kassert( node || parent, "Both node and parent were null in page_tree::get_entry");
|
||||||
|
|
||||||
if (!node) {
|
if (!node) {
|
||||||
// We found a parent with an empty spot where this node should
|
// We found a parent with an empty spot where this node should
|
||||||
@@ -135,9 +113,39 @@ page_tree::find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kassert(level0, "Got through find_or_add without a level0");
|
kassert(level0, "Got through page_tree::get_entry without a level0");
|
||||||
|
|
||||||
uint8_t index = index_for(offset, 0);
|
uint8_t index = index_for(offset, 0);
|
||||||
uint64_t &ent = level0->m_entries[index].entry;
|
return level0->m_entries[index].entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
page_tree::find(const page_tree *root, uint64_t offset, uintptr_t &page)
|
||||||
|
{
|
||||||
|
page_tree const *node = root;
|
||||||
|
while (node) {
|
||||||
|
uint8_t level = node->m_level;
|
||||||
|
uint8_t index = 0;
|
||||||
|
if (!node->contains(offset, index))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!level) {
|
||||||
|
uintptr_t entry = node->m_entries[index].entry;
|
||||||
|
page = entry & ~0xfffull;
|
||||||
|
return (entry & 1); // bit 0 marks 'present'
|
||||||
|
}
|
||||||
|
|
||||||
|
node = node->m_entries[index].child;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
page_tree::find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page)
|
||||||
|
{
|
||||||
|
uint64_t &ent = get_entry(root, offset);
|
||||||
|
|
||||||
if (!(ent & 1)) {
|
if (!(ent & 1)) {
|
||||||
// No entry for this page exists, so make one
|
// No entry for this page exists, so make one
|
||||||
if (!frame_allocator::get().allocate(1, &ent))
|
if (!frame_allocator::get().allocate(1, &ent))
|
||||||
@@ -148,3 +156,12 @@ page_tree::find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page)
|
|||||||
page = ent & ~0xfffull;
|
page = ent & ~0xfffull;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
page_tree::add_existing(page_tree * &root, uint64_t offset, uintptr_t page)
|
||||||
|
{
|
||||||
|
uint64_t &ent = get_entry(root, offset);
|
||||||
|
kassert(!(ent & 1), "Replacing existing mapping in page_tree::add_existing");
|
||||||
|
|
||||||
|
ent = page | 1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ public:
|
|||||||
/// \returns True if a page was found
|
/// \returns True if a page was found
|
||||||
static bool find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page);
|
static bool find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page);
|
||||||
|
|
||||||
|
/// Add an existing mapping not allocated via find_or_add.
|
||||||
|
/// \arg root [inout] The root node of the tree. This pointer may be updated.
|
||||||
|
/// \arg offset Offset into the VMA, in bytes
|
||||||
|
/// \arg page The mapped page physical address
|
||||||
|
static void add_existing(page_tree * &root, uint64_t offset, uintptr_t page);
|
||||||
|
|
||||||
~page_tree();
|
~page_tree();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -34,6 +40,9 @@ private:
|
|||||||
/// \returns True if the address is contained
|
/// \returns True if the address is contained
|
||||||
bool contains(uintptr_t offset, uint8_t &index) const;
|
bool contains(uintptr_t offset, uint8_t &index) const;
|
||||||
|
|
||||||
|
/// Get a (writable) reference to a page in the tree
|
||||||
|
static uintptr_t & get_entry(page_tree * &root, uint64_t offset);
|
||||||
|
|
||||||
/// Stores the page offset of the start of this node's pages virtual addresses
|
/// Stores the page offset of the start of this node's pages virtual addresses
|
||||||
uint64_t m_base;
|
uint64_t m_base;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user