[kernel] Remove 'allowed' page table flag

The allowed flag was janky and easy to get lost when doing page table
manipulation. All allocation goes throug vm_area now, so 'allowed' can
be dropped.
This commit is contained in:
2020-09-27 16:06:25 -07:00
parent f7f8bb3f45
commit 2d44e8112b
5 changed files with 8 additions and 83 deletions

View File

@@ -91,7 +91,6 @@ vm_area_shared::commit(uintptr_t phys, uintptr_t offset, size_t count)
.phys = phys}); .phys = phys});
n = 1; n = 1;
// Try to expand to abutting similar areas // Try to expand to abutting similar areas
if (o > 0 && if (o > 0 &&
m_mappings[o-1].end() == offset && m_mappings[o-1].end() == offset &&

View File

@@ -100,27 +100,6 @@ page_table::iterator::next(level l)
} }
} }
bool
page_table::iterator::allowed() const
{
level d = depth();
while (true) {
if (entry(d) & flag::allowed) return true;
else if (d == level::pml4) return false;
--d;
}
}
void
page_table::iterator::allow(level at, bool allowed)
{
for (level l = level::pdp; l <= at; ++l)
ensure_table(l);
if (allowed) entry(at) |= flag::allowed;
else entry(at) &= ~flag::allowed;
}
bool bool
page_table::iterator::operator!=(const iterator &o) const page_table::iterator::operator!=(const iterator &o) const
{ {
@@ -159,7 +138,7 @@ page_table::iterator::ensure_table(level l)
uintptr_t phys = reinterpret_cast<uintptr_t>(table) & ~page_offset; uintptr_t phys = reinterpret_cast<uintptr_t>(table) & ~page_offset;
uint64_t &parent = entry(l - 1); uint64_t &parent = entry(l - 1);
flag flags = table_flags | (parent & flag::allowed); flag flags = table_flags;
if (m_index[0] < memory::pml4e_kernel) if (m_index[0] < memory::pml4e_kernel)
flags |= flag::user; flags |= flag::user;
@@ -185,7 +164,6 @@ page_table::get(int i, uint16_t *flags) const
void void
page_table::set(int i, page_table *p, uint16_t flags) page_table::set(int i, page_table *p, uint16_t flags)
{ {
if (entries[i] & flag::allowed) flags |= flag::allowed;
entries[i] = entries[i] =
(reinterpret_cast<uint64_t>(p) - page_offset) | (reinterpret_cast<uint64_t>(p) - page_offset) |
(flags & 0xfff); (flags & 0xfff);

View File

@@ -28,10 +28,7 @@ struct page_table
page = 0x0080, /// Entry is a large page page = 0x0080, /// Entry is a large page
pte_mtrr2 = 0x0080, /// MTRR selector bit 2 on PT entries pte_mtrr2 = 0x0080, /// MTRR selector bit 2 on PT entries
global = 0x0100, /// Entry is not PCID-specific global = 0x0100, /// Entry is not PCID-specific
mtrr2 = 0x1000, /// MTRR selector bit 2 on PD and PDP entries mtrr2 = 0x1000 /// MTRR selector bit 2 on PD and PDP entries
// jsix-defined
allowed = 0x0800 /// Allocation here is allowed
}; };
/// Helper for getting the next level value /// Helper for getting the next level value
@@ -103,12 +100,6 @@ struct page_table
/// Increment iteration to the next entry aligned to the given level /// Increment iteration to the next entry aligned to the given level
void next(level l); void next(level l);
/// Check if allocation is allowed at the current location
bool allowed() const;
/// Mark allocation allowed at the given depth for the current location
void allow(level at, bool allowed);
/// Increment iteration to the next entry at the deepest level /// Increment iteration to the next entry at the deepest level
inline void increment() { next(level::page); } inline void increment() { next(level::page); }

View File

@@ -197,7 +197,6 @@ vm_space::clear(const vm_area &vma, uintptr_t offset, size_t count, bool free)
while (count--) { while (count--) {
uint64_t &e = it.entry(page_table::level::pt); uint64_t &e = it.entry(page_table::level::pt);
bool allowed = (e & page_table::flag::allowed);
uintptr_t phys = e & ~0xfffull; uintptr_t phys = e & ~0xfffull;
if (e & page_table::flag::present) { if (e & page_table::flag::present) {
@@ -212,7 +211,7 @@ vm_space::clear(const vm_area &vma, uintptr_t offset, size_t count, bool free)
fa.free(e & ~0xfffull, 1); fa.free(e & ~0xfffull, 1);
} }
e = 0 | (allowed ? page_table::flag::allowed : page_table::flag::none); e = 0;
++it; ++it;
} }
@@ -229,24 +228,6 @@ vm_space::lookup(const vm_area &vma, uintptr_t offset)
return base + offset; return base + offset;
} }
void
vm_space::allow(uintptr_t start, size_t length, bool allow)
{
using level = page_table::level;
kassert((start & 0xfff) == 0, "non-page-aligned address");
kassert((length & 0xfff) == 0, "non-page-aligned length");
const uintptr_t end = start + length;
page_table::iterator it {start, m_pml4};
while (it.vaddress() < end) {
level d = it.align();
while (it.end(d) > end) ++d;
it.allow(d-1, allow);
it.next(d);
}
}
bool bool
vm_space::active() const vm_space::active() const
{ {
@@ -276,8 +257,6 @@ vm_space::handle_fault(uintptr_t addr, fault_type fault)
{ {
uintptr_t page = addr & ~0xfffull; uintptr_t page = addr & ~0xfffull;
page_table::iterator it {addr, m_pml4};
// TODO: Handle more fult types // TODO: Handle more fult types
if (fault && fault_type::present) if (fault && fault_type::present)
return false; return false;
@@ -285,24 +264,13 @@ vm_space::handle_fault(uintptr_t addr, fault_type fault)
uintptr_t base = 0; uintptr_t base = 0;
vm_area *area = get(addr, &base); vm_area *area = get(addr, &base);
if ((!area || !area->allowed(page-base)) && !it.allowed()) if (!area || !area->allowed(page-base))
return false; return false;
uintptr_t phys = 0; uintptr_t phys = 0;
size_t n = frame_allocator::get().allocate(1, &phys); size_t n = frame_allocator::get().allocate(1, &phys);
kassert(n, "Failed to allocate a new page during page fault"); kassert(n, "Failed to allocate a new page during page fault");
page_table::flag flags =
page_table::flag::present |
page_table::flag::write |
(area
? page_table::flag::none
: page_table::flag::allowed) |
(is_kernel()
? page_table::flag::global
: page_table::flag::user);
if (area) {
if (area->flags() && vm_flags::zero) if (area->flags() && vm_flags::zero)
kutil::memset(memory::to_virtual<void>(phys), 0, memory::frame_size); kutil::memset(memory::to_virtual<void>(phys), 0, memory::frame_size);
@@ -311,10 +279,6 @@ vm_space::handle_fault(uintptr_t addr, fault_type fault)
return true; return true;
} }
it.entry(page_table::level::pt) = phys | flags;
return true;
}
size_t size_t
vm_space::copy(vm_space &source, vm_space &dest, void *from, void *to, size_t length) vm_space::copy(vm_space &source, vm_space &dest, void *from, void *to, size_t length)
{ {

View File

@@ -64,13 +64,6 @@ public:
/// Look up the address of a given VMA's offset /// Look up the address of a given VMA's offset
uintptr_t lookup(const vm_area &vma, uintptr_t offset); uintptr_t lookup(const vm_area &vma, uintptr_t offset);
/// Mark whether allocation is allowed or not in a range of
/// virtual memory.
/// \arg start The starting virtual address of the area
/// \arg length The length in bytes of the area
/// \arg allow True if allocation should be allowed
void allow(uintptr_t start, size_t length, bool allow);
/// Check if this space is the current active space /// Check if this space is the current active space
bool active() const; bool active() const;