update main #1

Merged
Sinipelto merged 240 commits from Bananymous/banan-os:main into main 2023-11-20 13:20:51 +02:00
9 changed files with 193 additions and 134 deletions
Showing only changes of commit 3bac19e518 - Show all commits

View File

@ -1,4 +1,5 @@
#include <BAN/ScopeGuard.h> #include <BAN/ScopeGuard.h>
#include <kernel/CriticalScope.h>
#include <kernel/Memory/Heap.h> #include <kernel/Memory/Heap.h>
#include <kernel/LockGuard.h> #include <kernel/LockGuard.h>
#include <LibELF/LoadableELF.h> #include <LibELF/LoadableELF.h>
@ -306,9 +307,12 @@ namespace LibELF
if (paddr == 0) if (paddr == 0)
return BAN::Error::from_errno(ENOMEM); return BAN::Error::from_errno(ENOMEM);
m_page_table.map_page_at(paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present); {
memcpy((void*)0, (void*)(start + i * PAGE_SIZE), PAGE_SIZE); CriticalScope _;
m_page_table.unmap_page(0); PageTable::map_fast_page(paddr);
memcpy(PageTable::fast_page_as_ptr(), (void*)(start + i * PAGE_SIZE), PAGE_SIZE);
PageTable::unmap_fast_page();
}
new_page_table.map_page_at(paddr, start + i * PAGE_SIZE, flags); new_page_table.map_page_at(paddr, start + i * PAGE_SIZE, flags);
elf->m_physical_page_count++; elf->m_physical_page_count++;

View File

@ -1,6 +1,6 @@
#include <BAN/Errors.h>
#include <kernel/Arch.h> #include <kernel/Arch.h>
#include <kernel/CPUID.h> #include <kernel/CPUID.h>
#include <kernel/InterruptController.h>
#include <kernel/LockGuard.h> #include <kernel/LockGuard.h>
#include <kernel/Memory/kmalloc.h> #include <kernel/Memory/kmalloc.h>
#include <kernel/Memory/PageTable.h> #include <kernel/Memory/PageTable.h>
@ -143,6 +143,8 @@ namespace Kernel
uint64_t* pml4 = (uint64_t*)P2V(m_highest_paging_struct); uint64_t* pml4 = (uint64_t*)P2V(m_highest_paging_struct);
pml4[511] = s_global_pml4e; pml4[511] = s_global_pml4e;
prepare_fast_page();
// Map (phys_kernel_start -> phys_kernel_end) to (virt_kernel_start -> virt_kernel_end) // Map (phys_kernel_start -> phys_kernel_end) to (virt_kernel_start -> virt_kernel_end)
ASSERT((vaddr_t)g_kernel_start % PAGE_SIZE == 0); ASSERT((vaddr_t)g_kernel_start % PAGE_SIZE == 0);
map_range_at( map_range_at(
@ -185,6 +187,76 @@ namespace Kernel
g_multiboot2_info = (multiboot2_info_t*)(multiboot2_vaddr + ((vaddr_t)g_multiboot2_info % PAGE_SIZE)); g_multiboot2_info = (multiboot2_info_t*)(multiboot2_vaddr + ((vaddr_t)g_multiboot2_info % PAGE_SIZE));
} }
void PageTable::prepare_fast_page()
{
constexpr vaddr_t uc_vaddr = uncanonicalize(fast_page());
constexpr uint64_t pml4e = (uc_vaddr >> 39) & 0x1FF;
constexpr uint64_t pdpte = (uc_vaddr >> 30) & 0x1FF;
constexpr uint64_t pde = (uc_vaddr >> 21) & 0x1FF;
constexpr uint64_t pte = (uc_vaddr >> 12) & 0x1FF;
uint64_t* pml4 = (uint64_t*)P2V(m_highest_paging_struct);
ASSERT(!(pml4[pml4e] & Flags::Present));
pml4[pml4e] = V2P(allocate_zeroed_page_aligned_page()) | Flags::ReadWrite | Flags::Present;
uint64_t* pdpt = (uint64_t*)P2V(pml4[pml4e] & PAGE_ADDR_MASK);
ASSERT(!(pdpt[pdpte] & Flags::Present));
pdpt[pdpte] = V2P(allocate_zeroed_page_aligned_page()) | Flags::ReadWrite | Flags::Present;
uint64_t* pd = (uint64_t*)P2V(pdpt[pdpte] & PAGE_ADDR_MASK);
ASSERT(!(pd[pde] & Flags::Present));
pd[pde] = V2P(allocate_zeroed_page_aligned_page()) | Flags::ReadWrite | Flags::Present;
uint64_t* pt = (uint64_t*)P2V(pd[pde] & PAGE_ADDR_MASK);
ASSERT(!(pt[pte] & Flags::Present));
pt[pte] = V2P(allocate_zeroed_page_aligned_page());
}
void PageTable::map_fast_page(paddr_t paddr)
{
ASSERT(s_kernel);
ASSERT_GE(paddr, 0);
ASSERT(!interrupts_enabled());
constexpr vaddr_t uc_vaddr = uncanonicalize(fast_page());
constexpr uint64_t pml4e = (uc_vaddr >> 39) & 0x1FF;
constexpr uint64_t pdpte = (uc_vaddr >> 30) & 0x1FF;
constexpr uint64_t pde = (uc_vaddr >> 21) & 0x1FF;
constexpr uint64_t pte = (uc_vaddr >> 12) & 0x1FF;
uint64_t* pml4 = (uint64_t*)P2V(s_kernel->m_highest_paging_struct);
uint64_t* pdpt = (uint64_t*)P2V(pml4[pml4e] & PAGE_ADDR_MASK);
uint64_t* pd = (uint64_t*)P2V(pdpt[pdpte] & PAGE_ADDR_MASK);
uint64_t* pt = (uint64_t*)P2V(pd[pde] & PAGE_ADDR_MASK);
ASSERT(!(pt[pte] & Flags::Present));
pt[pte] = paddr | Flags::ReadWrite | Flags::Present;
invalidate(fast_page());
}
void PageTable::unmap_fast_page()
{
ASSERT(s_kernel);
ASSERT(!interrupts_enabled());
constexpr vaddr_t uc_vaddr = uncanonicalize(fast_page());
constexpr uint64_t pml4e = (uc_vaddr >> 39) & 0x1FF;
constexpr uint64_t pdpte = (uc_vaddr >> 30) & 0x1FF;
constexpr uint64_t pde = (uc_vaddr >> 21) & 0x1FF;
constexpr uint64_t pte = (uc_vaddr >> 12) & 0x1FF;
uint64_t* pml4 = (uint64_t*)P2V(s_kernel->m_highest_paging_struct);
uint64_t* pdpt = (uint64_t*)P2V(pml4[pml4e] & PAGE_ADDR_MASK);
uint64_t* pd = (uint64_t*)P2V(pdpt[pdpte] & PAGE_ADDR_MASK);
uint64_t* pt = (uint64_t*)P2V(pd[pde] & PAGE_ADDR_MASK);
ASSERT(pt[pte] & Flags::Present);
pt[pte] = 0;
invalidate(fast_page());
}
BAN::ErrorOr<PageTable*> PageTable::create_userspace() BAN::ErrorOr<PageTable*> PageTable::create_userspace()
{ {
LockGuard _(s_kernel->m_lock); LockGuard _(s_kernel->m_lock);
@ -246,13 +318,16 @@ namespace Kernel
void PageTable::invalidate(vaddr_t vaddr) void PageTable::invalidate(vaddr_t vaddr)
{ {
ASSERT(vaddr % PAGE_SIZE == 0); ASSERT(vaddr % PAGE_SIZE == 0);
if (this == s_current) asm volatile("invlpg (%0)" :: "r"(vaddr) : "memory");
asm volatile("invlpg (%0)" :: "r"(vaddr) : "memory");
} }
void PageTable::unmap_page(vaddr_t vaddr) void PageTable::unmap_page(vaddr_t vaddr)
{ {
if (vaddr && (vaddr >= KERNEL_OFFSET) != (this == s_kernel)) ASSERT(vaddr);
ASSERT(vaddr != fast_page());
if (vaddr >= KERNEL_OFFSET)
ASSERT_GE(vaddr, (vaddr_t)g_kernel_start);
if ((vaddr >= KERNEL_OFFSET) != (this == s_kernel))
Kernel::panic("unmapping {8H}, kernel: {}", vaddr, this == s_kernel); Kernel::panic("unmapping {8H}, kernel: {}", vaddr, this == s_kernel);
ASSERT(is_canonical(vaddr)); ASSERT(is_canonical(vaddr));
@ -294,7 +369,11 @@ namespace Kernel
void PageTable::map_page_at(paddr_t paddr, vaddr_t vaddr, flags_t flags) void PageTable::map_page_at(paddr_t paddr, vaddr_t vaddr, flags_t flags)
{ {
if (vaddr && (vaddr >= KERNEL_OFFSET) != (this == s_kernel)) ASSERT(vaddr);
ASSERT(vaddr != fast_page());
if (vaddr >= KERNEL_OFFSET)
ASSERT_GE(vaddr, (vaddr_t)g_kernel_start);
if ((vaddr >= KERNEL_OFFSET) != (this == s_kernel))
Kernel::panic("mapping {8H} to {8H}, kernel: {}", paddr, vaddr, this == s_kernel); Kernel::panic("mapping {8H} to {8H}, kernel: {}", paddr, vaddr, this == s_kernel);
ASSERT(is_canonical(vaddr)); ASSERT(is_canonical(vaddr));
@ -361,12 +440,11 @@ namespace Kernel
{ {
ASSERT(is_canonical(vaddr)); ASSERT(is_canonical(vaddr));
ASSERT(vaddr);
ASSERT(paddr % PAGE_SIZE == 0); ASSERT(paddr % PAGE_SIZE == 0);
ASSERT(vaddr % PAGE_SIZE == 0); ASSERT(vaddr % PAGE_SIZE == 0);
size_t first_page = vaddr / PAGE_SIZE; size_t page_count = range_page_count(vaddr, size);
size_t last_page = (vaddr + size - 1) / PAGE_SIZE;
size_t page_count = last_page - first_page + 1;
LockGuard _(m_lock); LockGuard _(m_lock);
for (size_t page = 0; page < page_count; page++) for (size_t page = 0; page < page_count; page++)
@ -527,6 +605,8 @@ namespace Kernel
vaddr_t PageTable::reserve_free_contiguous_pages(size_t page_count, vaddr_t first_address, vaddr_t last_address) vaddr_t PageTable::reserve_free_contiguous_pages(size_t page_count, vaddr_t first_address, vaddr_t last_address)
{ {
if (first_address >= KERNEL_OFFSET && first_address < (vaddr_t)g_kernel_start)
first_address = (vaddr_t)g_kernel_start;
if (size_t rem = first_address % PAGE_SIZE) if (size_t rem = first_address % PAGE_SIZE)
first_address += PAGE_SIZE - rem; first_address += PAGE_SIZE - rem;
if (size_t rem = last_address % PAGE_SIZE) if (size_t rem = last_address % PAGE_SIZE)

View File

@ -38,6 +38,7 @@ namespace Kernel
BAN::RefPtr<Inode> m_inode; BAN::RefPtr<Inode> m_inode;
const off_t m_offset; const off_t m_offset;
// FIXME: is this even synchronized?
BAN::RefPtr<SharedFileData> m_shared_data; BAN::RefPtr<SharedFileData> m_shared_data;
}; };

View File

@ -29,6 +29,24 @@ namespace Kernel
static PageTable& kernel(); static PageTable& kernel();
static PageTable& current(); static PageTable& current();
static void map_fast_page(paddr_t);
static void unmap_fast_page();
static constexpr vaddr_t fast_page() { return KERNEL_OFFSET; }
// FIXME: implement sized checks, return span, etc
static void* fast_page_as_ptr(size_t offset = 0)
{
ASSERT(offset <= PAGE_SIZE);
return reinterpret_cast<void*>(fast_page() + offset);
}
template<typename T>
static T& fast_page_as(size_t offset = 0)
{
ASSERT(offset + sizeof(T) <= PAGE_SIZE);
return *reinterpret_cast<T*>(fast_page() + offset);
}
static bool is_valid_pointer(uintptr_t); static bool is_valid_pointer(uintptr_t);
static BAN::ErrorOr<PageTable*> create_userspace(); static BAN::ErrorOr<PageTable*> create_userspace();
@ -64,7 +82,8 @@ namespace Kernel
uint64_t get_page_data(vaddr_t) const; uint64_t get_page_data(vaddr_t) const;
void initialize_kernel(); void initialize_kernel();
void map_kernel_memory(); void map_kernel_memory();
void invalidate(vaddr_t); void prepare_fast_page();
static void invalidate(vaddr_t);
private: private:
paddr_t m_highest_paging_struct { 0 }; paddr_t m_highest_paging_struct { 0 };

View File

@ -117,33 +117,33 @@ namespace Kernel
if (rsdp->revision >= 2) if (rsdp->revision >= 2)
{ {
PageTable::kernel().map_page_at(rsdp->xsdt_address & PAGE_ADDR_MASK, 0, PageTable::Flags::Present); PageTable::map_fast_page(rsdp->xsdt_address & PAGE_ADDR_MASK);
const XSDT* xsdt = (const XSDT*)(rsdp->xsdt_address % PAGE_SIZE); auto& xsdt = PageTable::fast_page_as<const XSDT>(rsdp->xsdt_address % PAGE_SIZE);
BAN::ScopeGuard _([xsdt] { PageTable::kernel().unmap_page(0); }); BAN::ScopeGuard _([] { PageTable::unmap_fast_page(); });
if (memcmp(xsdt->signature, "XSDT", 4) != 0) if (memcmp(xsdt.signature, "XSDT", 4) != 0)
return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid); return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid);
if (!is_valid_std_header(xsdt)) if (!is_valid_std_header(&xsdt))
return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid); return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid);
m_header_table_paddr = (paddr_t)xsdt->entries + (rsdp->rsdt_address & PAGE_ADDR_MASK); m_header_table_paddr = rsdp->xsdt_address + offsetof(XSDT, entries);
m_entry_size = 8; m_entry_size = 8;
root_entry_count = (xsdt->length - sizeof(SDTHeader)) / 8; root_entry_count = (xsdt.length - sizeof(SDTHeader)) / 8;
} }
else else
{ {
PageTable::kernel().map_page_at(rsdp->rsdt_address & PAGE_ADDR_MASK, 0, PageTable::Flags::Present); PageTable::map_fast_page(rsdp->rsdt_address & PAGE_ADDR_MASK);
const RSDT* rsdt = (const RSDT*)((vaddr_t)rsdp->rsdt_address % PAGE_SIZE); auto& rsdt = PageTable::fast_page_as<const RSDT>(rsdp->rsdt_address % PAGE_SIZE);
BAN::ScopeGuard _([rsdt] { PageTable::kernel().unmap_page(0); }); BAN::ScopeGuard _([] { PageTable::unmap_fast_page(); });
if (memcmp(rsdt->signature, "RSDT", 4) != 0) if (memcmp(rsdt.signature, "RSDT", 4) != 0)
return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid); return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid);
if (!is_valid_std_header(rsdt)) if (!is_valid_std_header(&rsdt))
return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid); return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid);
m_header_table_paddr = (paddr_t)rsdt->entries + (rsdp->rsdt_address & PAGE_ADDR_MASK); m_header_table_paddr = rsdp->rsdt_address + offsetof(RSDT, entries);
m_entry_size = 4; m_entry_size = 4;
root_entry_count = (rsdt->length - sizeof(SDTHeader)) / 4; root_entry_count = (rsdt.length - sizeof(SDTHeader)) / 4;
} }
size_t needed_pages = range_page_count(m_header_table_paddr, root_entry_count * m_entry_size); size_t needed_pages = range_page_count(m_header_table_paddr, root_entry_count * m_entry_size);
@ -162,9 +162,9 @@ namespace Kernel
auto map_header = auto map_header =
[](paddr_t header_paddr) -> vaddr_t [](paddr_t header_paddr) -> vaddr_t
{ {
PageTable::kernel().map_page_at(header_paddr & PAGE_ADDR_MASK, 0, PageTable::Flags::Present); PageTable::map_fast_page(header_paddr & PAGE_ADDR_MASK);
size_t header_length = ((SDTHeader*)(header_paddr % PAGE_SIZE))->length; size_t header_length = PageTable::fast_page_as<SDTHeader>(header_paddr % PAGE_SIZE).length;
PageTable::kernel().unmap_page(0); PageTable::unmap_fast_page();
size_t needed_pages = range_page_count(header_paddr, header_length); size_t needed_pages = range_page_count(header_paddr, header_length);
vaddr_t page_vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET); vaddr_t page_vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET);

View File

@ -1,3 +1,4 @@
#include <kernel/CriticalScope.h>
#include <kernel/LockGuard.h> #include <kernel/LockGuard.h>
#include <kernel/Memory/FileBackedRegion.h> #include <kernel/Memory/FileBackedRegion.h>
#include <kernel/Memory/Heap.h> #include <kernel/Memory/Heap.h>
@ -71,13 +72,10 @@ namespace Kernel
continue; continue;
{ {
auto& page_table = PageTable::current(); CriticalScope _;
LockGuard _(page_table); PageTable::map_fast_page(pages[i]);
ASSERT(page_table.is_page_free(0)); memcpy(page_buffer, PageTable::fast_page_as_ptr(), PAGE_SIZE);
PageTable::unmap_fast_page();
page_table.map_page_at(pages[i], 0, PageTable::Flags::Present);
memcpy(page_buffer, (void*)0, PAGE_SIZE);
page_table.unmap_page(0);
} }
if (auto ret = inode->write(i * PAGE_SIZE, BAN::ConstByteSpan::from(page_buffer)); ret.is_error()) if (auto ret = inode->write(i * PAGE_SIZE, BAN::ConstByteSpan::from(page_buffer)); ret.is_error())
@ -105,23 +103,8 @@ namespace Kernel
size_t file_offset = m_offset + (vaddr - m_vaddr); size_t file_offset = m_offset + (vaddr - m_vaddr);
size_t bytes = BAN::Math::min<size_t>(m_size - file_offset, PAGE_SIZE); size_t bytes = BAN::Math::min<size_t>(m_size - file_offset, PAGE_SIZE);
BAN::ErrorOr<size_t> read_ret = 0; ASSERT_EQ(&PageTable::current(), &m_page_table);
auto read_ret = m_inode->read(file_offset, BAN::ByteSpan((uint8_t*)vaddr, bytes));
// Zero out the new page
if (&PageTable::current() == &m_page_table)
read_ret = m_inode->read(file_offset, BAN::ByteSpan((uint8_t*)vaddr, bytes));
else
{
auto& page_table = PageTable::current();
LockGuard _(page_table);
ASSERT(page_table.is_page_free(0));
page_table.map_page_at(paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
read_ret = m_inode->read(file_offset, BAN::ByteSpan((uint8_t*)0, bytes));
memset((void*)0, 0x00, PAGE_SIZE);
page_table.unmap_page(0);
}
if (read_ret.is_error()) if (read_ret.is_error())
{ {
@ -158,15 +141,10 @@ namespace Kernel
TRY(m_inode->read(offset, BAN::ByteSpan(m_shared_data->page_buffer, bytes))); TRY(m_inode->read(offset, BAN::ByteSpan(m_shared_data->page_buffer, bytes)));
auto& page_table = PageTable::current(); CriticalScope _;
PageTable::map_fast_page(pages[page_index]);
// TODO: check if this can cause deadlock? memcpy(PageTable::fast_page_as_ptr(), m_shared_data->page_buffer, PAGE_SIZE);
LockGuard page_table_lock(page_table); PageTable::unmap_fast_page();
ASSERT(page_table.is_page_free(0));
page_table.map_page_at(pages[page_index], 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)0, m_shared_data->page_buffer, PAGE_SIZE);
page_table.unmap_page(0);
} }
paddr_t paddr = pages[page_index]; paddr_t paddr = pages[page_index];

View File

@ -1,3 +1,4 @@
#include <kernel/CriticalScope.h>
#include <kernel/LockGuard.h> #include <kernel/LockGuard.h>
#include <kernel/Memory/Heap.h> #include <kernel/Memory/Heap.h>
#include <kernel/Memory/MemoryBackedRegion.h> #include <kernel/Memory/MemoryBackedRegion.h>
@ -60,12 +61,10 @@ namespace Kernel
memset((void*)vaddr, 0x00, PAGE_SIZE); memset((void*)vaddr, 0x00, PAGE_SIZE);
else else
{ {
LockGuard _(PageTable::current()); CriticalScope _;
ASSERT(PageTable::current().is_page_free(0)); PageTable::map_fast_page(paddr);
memset(PageTable::fast_page_as_ptr(), 0x00, PAGE_SIZE);
PageTable::current().map_page_at(paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present); PageTable::unmap_fast_page();
memset((void*)0, 0x00, PAGE_SIZE);
PageTable::current().unmap_page(0);
} }
return true; return true;
@ -105,15 +104,10 @@ namespace Kernel
memcpy((void*)write_vaddr, (void*)(buffer + written), bytes); memcpy((void*)write_vaddr, (void*)(buffer + written), bytes);
else else
{ {
paddr_t paddr = m_page_table.physical_address_of(write_vaddr & PAGE_ADDR_MASK); CriticalScope _;
ASSERT(paddr); PageTable::map_fast_page(m_page_table.physical_address_of(write_vaddr & PAGE_ADDR_MASK));
memcpy(PageTable::fast_page_as_ptr(page_offset), (void*)(buffer + written), bytes);
LockGuard _(PageTable::current()); PageTable::unmap_fast_page();
ASSERT(PageTable::current().is_page_free(0));
PageTable::current().map_page_at(paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)page_offset, (void*)(buffer + written), bytes);
PageTable::current().unmap_page(0);
} }
written += bytes; written += bytes;

View File

@ -1,3 +1,4 @@
#include <kernel/CriticalScope.h>
#include <kernel/LockGuard.h> #include <kernel/LockGuard.h>
#include <kernel/Memory/Heap.h> #include <kernel/Memory/Heap.h>
#include <kernel/Memory/VirtualRange.h> #include <kernel/Memory/VirtualRange.h>
@ -124,7 +125,6 @@ namespace Kernel
auto result = TRY(create_to_vaddr(page_table, vaddr(), size(), flags(), m_preallocated)); auto result = TRY(create_to_vaddr(page_table, vaddr(), size(), flags(), m_preallocated));
LockGuard _(m_page_table); LockGuard _(m_page_table);
ASSERT(m_page_table.is_page_free(0));
for (size_t offset = 0; offset < size(); offset += PAGE_SIZE) for (size_t offset = 0; offset < size(); offset += PAGE_SIZE)
{ {
if (!m_preallocated && m_page_table.physical_address_of(vaddr() + offset)) if (!m_preallocated && m_page_table.physical_address_of(vaddr() + offset))
@ -134,10 +134,12 @@ namespace Kernel
return BAN::Error::from_errno(ENOMEM); return BAN::Error::from_errno(ENOMEM);
result->m_page_table.map_page_at(paddr, vaddr() + offset, m_flags); result->m_page_table.map_page_at(paddr, vaddr() + offset, m_flags);
} }
m_page_table.map_page_at(result->m_page_table.physical_address_of(vaddr() + offset), 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)0, (void*)(vaddr() + offset), PAGE_SIZE); CriticalScope _;
PageTable::map_fast_page(result->m_page_table.physical_address_of(vaddr() + offset));
memcpy(PageTable::fast_page_as_ptr(), (void*)(vaddr() + offset), PAGE_SIZE);
PageTable::unmap_fast_page();
} }
m_page_table.unmap_page(0);
return result; return result;
} }
@ -172,14 +174,13 @@ namespace Kernel
return; return;
} }
LockGuard _(page_table);
ASSERT(page_table.is_page_free(0));
for (size_t offset = 0; offset < size(); offset += PAGE_SIZE) for (size_t offset = 0; offset < size(); offset += PAGE_SIZE)
{ {
page_table.map_page_at(m_page_table.physical_address_of(vaddr() + offset), 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present); CriticalScope _;
memset((void*)0, 0, PAGE_SIZE); PageTable::map_fast_page(m_page_table.physical_address_of(vaddr() + offset));
memset(PageTable::fast_page_as_ptr(), 0x00, PAGE_SIZE);
PageTable::unmap_fast_page();
} }
page_table.unmap_page(0);
} }
void VirtualRange::copy_from(size_t offset, const uint8_t* buffer, size_t bytes) void VirtualRange::copy_from(size_t offset, const uint8_t* buffer, size_t bytes)
@ -187,47 +188,34 @@ namespace Kernel
if (bytes == 0) if (bytes == 0)
return; return;
// NOTE: Handling overflow // Verify no overflow
ASSERT(offset <= size()); ASSERT_LE(bytes, size());
ASSERT(bytes <= size()); ASSERT_LE(offset, size());
ASSERT(offset + bytes <= size()); ASSERT_LE(offset, size() - bytes);
PageTable& page_table = PageTable::current(); if (m_kmalloc || &PageTable::current() == &m_page_table)
if (m_kmalloc || &page_table == &m_page_table)
{ {
memcpy((void*)(vaddr() + offset), buffer, bytes); memcpy((void*)(vaddr() + offset), buffer, bytes);
return; return;
} }
LockGuard _(page_table); size_t page_offset = offset % PAGE_SIZE;
ASSERT(page_table.is_page_free(0)); size_t page_index = offset / PAGE_SIZE;
size_t off = offset % PAGE_SIZE;
size_t i = offset / PAGE_SIZE;
// NOTE: we map the first page separately since it needs extra calculations
page_table.map_page_at(m_page_table.physical_address_of(vaddr() + i * PAGE_SIZE), 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)off, buffer, PAGE_SIZE - off);
buffer += PAGE_SIZE - off;
bytes -= PAGE_SIZE - off;
i++;
while (bytes > 0) while (bytes > 0)
{ {
size_t len = BAN::Math::min<size_t>(PAGE_SIZE, bytes); {
CriticalScope _;
PageTable::map_fast_page(m_page_table.physical_address_of(vaddr() + page_index * PAGE_SIZE));
memcpy(PageTable::fast_page_as_ptr(page_offset), buffer, PAGE_SIZE - page_offset);
PageTable::unmap_fast_page();
}
page_table.map_page_at(m_page_table.physical_address_of(vaddr() + i * PAGE_SIZE), 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present); buffer += PAGE_SIZE - page_offset;
bytes -= PAGE_SIZE - page_offset;
memcpy((void*)0, buffer, len); page_offset = 0;
page_index++;
buffer += len;
bytes -= len;
i++;
} }
page_table.unmap_page(0);
} }
} }

View File

@ -47,9 +47,9 @@ namespace Kernel
continue; continue;
CriticalScope _; CriticalScope _;
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present); PageTable::map_fast_page(cache.paddr);
memcpy(buffer.data(), (void*)(page_cache_offset * m_sector_size), m_sector_size); memcpy(buffer.data(), PageTable::fast_page_as_ptr(page_cache_offset * m_sector_size), m_sector_size);
page_table.unmap_page(0); PageTable::unmap_fast_page();
return true; return true;
} }
@ -82,9 +82,9 @@ namespace Kernel
{ {
CriticalScope _; CriticalScope _;
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present); PageTable::map_fast_page(cache.paddr);
memcpy((void*)(page_cache_offset * m_sector_size), buffer.data(), m_sector_size); memcpy(PageTable::fast_page_as_ptr(page_cache_offset * m_sector_size), buffer.data(), m_sector_size);
page_table.unmap_page(0); PageTable::unmap_fast_page();
} }
cache.sector_mask |= 1 << page_cache_offset; cache.sector_mask |= 1 << page_cache_offset;
@ -113,9 +113,9 @@ namespace Kernel
{ {
CriticalScope _; CriticalScope _;
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present); PageTable::map_fast_page(cache.paddr);
memcpy((void*)(page_cache_offset * m_sector_size), buffer.data(), m_sector_size); memcpy(PageTable::fast_page_as_ptr(page_cache_offset * m_sector_size), buffer.data(), m_sector_size);
page_table.unmap_page(0); PageTable::unmap_fast_page();
} }
return {}; return {};
@ -123,21 +123,16 @@ namespace Kernel
BAN::ErrorOr<void> DiskCache::sync() BAN::ErrorOr<void> DiskCache::sync()
{ {
ASSERT(&PageTable::current() == &PageTable::kernel());
auto& page_table = PageTable::kernel();
for (auto& cache : m_cache) for (auto& cache : m_cache)
{ {
if (cache.dirty_mask == 0) if (cache.dirty_mask == 0)
continue; continue;
{ {
LockGuard _(page_table); CriticalScope _;
ASSERT(page_table.is_page_free(0)); PageTable::map_fast_page(cache.paddr);
memcpy(m_sync_cache.data(), PageTable::fast_page_as_ptr(), PAGE_SIZE);
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present); PageTable::unmap_fast_page();
memcpy(m_sync_cache.data(), (void*)0, PAGE_SIZE);
page_table.unmap_page(0);
} }
uint8_t sector_start = 0; uint8_t sector_start = 0;