forked from Bananymous/banan-os
Kernel: rework the whole PageTable structure
We now have page table structure for kernel memory which is shared between all processes.
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
#define RSPD_SIZE 20
|
||||
#define RSPDv2_SIZE 36
|
||||
|
||||
extern uint8_t g_kernel_end[];
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
@@ -104,42 +106,73 @@ namespace Kernel
|
||||
|
||||
if (rsdp->revision >= 2)
|
||||
{
|
||||
const XSDT* xsdt = (const XSDT*)rsdp->xsdt_address;
|
||||
PageTable::kernel().identity_map_page((uintptr_t)xsdt, PageTable::Flags::Present);
|
||||
BAN::ScopeGuard _([xsdt] { PageTable::kernel().unmap_page((uintptr_t)xsdt); });
|
||||
PageTable::kernel().map_page_at(rsdp->xsdt_address & PAGE_ADDR_MASK, 0, PageTable::Flags::Present);
|
||||
const XSDT* xsdt = (const XSDT*)(rsdp->xsdt_address % PAGE_SIZE);
|
||||
BAN::ScopeGuard _([xsdt] { PageTable::kernel().unmap_page(0); });
|
||||
|
||||
if (memcmp(xsdt->signature, "XSDT", 4) != 0)
|
||||
return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid);
|
||||
if (!is_valid_std_header(xsdt))
|
||||
return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid);
|
||||
|
||||
m_header_table = (uintptr_t)xsdt->entries;
|
||||
m_header_table_paddr = (paddr_t)xsdt->entries + (rsdp->rsdt_address & PAGE_ADDR_MASK);
|
||||
m_entry_size = 8;
|
||||
m_entry_count = (xsdt->length - sizeof(SDTHeader)) / 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
const RSDT* rsdt = (const RSDT*)(uintptr_t)rsdp->rsdt_address;
|
||||
PageTable::kernel().identity_map_page((vaddr_t)rsdt, PageTable::Flags::Present);
|
||||
BAN::ScopeGuard _([rsdt] { PageTable::kernel().unmap_page((vaddr_t)rsdt); });
|
||||
PageTable::kernel().map_page_at(rsdp->rsdt_address & PAGE_ADDR_MASK, 0, PageTable::Flags::Present);
|
||||
const RSDT* rsdt = (const RSDT*)((vaddr_t)rsdp->rsdt_address % PAGE_SIZE);
|
||||
BAN::ScopeGuard _([rsdt] { PageTable::kernel().unmap_page(0); });
|
||||
|
||||
if (memcmp(rsdt->signature, "RSDT", 4) != 0)
|
||||
return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid);
|
||||
if (!is_valid_std_header(rsdt))
|
||||
return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid);
|
||||
|
||||
m_header_table = (uintptr_t)rsdt->entries;
|
||||
m_header_table_paddr = (paddr_t)rsdt->entries + (rsdp->rsdt_address & PAGE_ADDR_MASK);
|
||||
m_entry_size = 4;
|
||||
m_entry_count = (rsdt->length - sizeof(SDTHeader)) / 4;
|
||||
}
|
||||
|
||||
PageTable::kernel().identity_map_range(m_header_table, m_entry_count * m_entry_size, PageTable::Flags::Present);
|
||||
size_t needed_pages = range_page_count(m_header_table_paddr, m_entry_count * m_entry_size);
|
||||
m_header_table_vaddr = PageTable::kernel().get_free_contiguous_pages(needed_pages, (vaddr_t)g_kernel_end);
|
||||
ASSERT(m_header_table_vaddr);
|
||||
|
||||
m_header_table_vaddr += m_header_table_paddr % PAGE_SIZE;
|
||||
|
||||
PageTable::kernel().map_range_at(
|
||||
m_header_table_paddr & PAGE_ADDR_MASK,
|
||||
m_header_table_vaddr & PAGE_ADDR_MASK,
|
||||
needed_pages * PAGE_SIZE,
|
||||
PageTable::Flags::Present
|
||||
);
|
||||
|
||||
for (uint32_t i = 0; i < m_entry_count; i++)
|
||||
{
|
||||
auto* header = get_header_from_index(i);
|
||||
PageTable::kernel().identity_map_page((uintptr_t)header, PageTable::Flags::Present);
|
||||
PageTable::kernel().identity_map_range((uintptr_t)header, header->length, PageTable::Flags::Present);
|
||||
paddr_t header_paddr = (m_entry_size == 4) ?
|
||||
((uint32_t*)m_header_table_vaddr)[i] :
|
||||
((uint64_t*)m_header_table_vaddr)[i];
|
||||
|
||||
PageTable::kernel().map_page_at(header_paddr & PAGE_ADDR_MASK, 0, PageTable::Flags::Present);
|
||||
size_t header_length = ((SDTHeader*)(header_paddr % PAGE_SIZE))->length;
|
||||
PageTable::kernel().unmap_page(0);
|
||||
|
||||
size_t needed_pages = range_page_count(header_paddr, header_length);
|
||||
vaddr_t page_vaddr = PageTable::kernel().get_free_contiguous_pages(needed_pages, (vaddr_t)g_kernel_end);
|
||||
ASSERT(page_vaddr);
|
||||
|
||||
PageTable::kernel().map_range_at(
|
||||
header_paddr & PAGE_ADDR_MASK,
|
||||
page_vaddr,
|
||||
needed_pages * PAGE_SIZE,
|
||||
PageTable::Flags::Present
|
||||
);
|
||||
|
||||
MUST(m_mapped_headers.push_back({
|
||||
.paddr = header_paddr,
|
||||
.vaddr = page_vaddr + (header_paddr % PAGE_SIZE)
|
||||
}));
|
||||
}
|
||||
|
||||
return {};
|
||||
@@ -161,8 +194,15 @@ namespace Kernel
|
||||
ASSERT(index < m_entry_count);
|
||||
ASSERT(m_entry_size == 4 || m_entry_size == 8);
|
||||
|
||||
uintptr_t header_address = (m_entry_size == 4) ? ((uint32_t*)m_header_table)[index] : ((uint64_t*)m_header_table)[index];
|
||||
return (SDTHeader*)header_address;
|
||||
paddr_t header_paddr = (m_entry_size == 4) ?
|
||||
((uint32_t*)m_header_table_vaddr)[index] :
|
||||
((uint64_t*)m_header_table_vaddr)[index];
|
||||
|
||||
for (const auto& page : m_mapped_headers)
|
||||
if (page.paddr == header_paddr)
|
||||
return (SDTHeader*)page.vaddr;
|
||||
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -81,6 +81,8 @@ union RedirectionEntry
|
||||
};
|
||||
};
|
||||
|
||||
extern uint8_t g_kernel_end[];
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
APIC* APIC::create()
|
||||
@@ -101,7 +103,7 @@ APIC* APIC::create()
|
||||
}
|
||||
|
||||
APIC* apic = new APIC;
|
||||
apic->m_local_apic = madt->local_apic;
|
||||
apic->m_local_apic_paddr = madt->local_apic;
|
||||
for (uint32_t i = 0x00; i <= 0xFF; i++)
|
||||
apic->m_irq_overrides[i] = i;
|
||||
|
||||
@@ -121,7 +123,7 @@ APIC* APIC::create()
|
||||
case 1:
|
||||
IOAPIC ioapic;
|
||||
ioapic.id = entry->entry1.ioapic_id;
|
||||
ioapic.address = entry->entry1.ioapic_address;
|
||||
ioapic.paddr = entry->entry1.ioapic_address;
|
||||
ioapic.gsi_base = entry->entry1.gsi_base;
|
||||
ioapic.max_redirs = 0;
|
||||
MUST(apic->m_io_apics.push_back(ioapic));
|
||||
@@ -130,7 +132,7 @@ APIC* APIC::create()
|
||||
apic->m_irq_overrides[entry->entry2.irq_source] = entry->entry2.gsi;
|
||||
break;
|
||||
case 5:
|
||||
apic->m_local_apic = entry->entry5.address;
|
||||
apic->m_local_apic_paddr = entry->entry5.address;
|
||||
break;
|
||||
default:
|
||||
dprintln("Unhandled madt entry, type {}", entry->type);
|
||||
@@ -139,17 +141,40 @@ APIC* APIC::create()
|
||||
madt_entry_addr += entry->length;
|
||||
}
|
||||
|
||||
if (apic->m_local_apic == 0 || apic->m_io_apics.empty())
|
||||
if (apic->m_local_apic_paddr == 0 || apic->m_io_apics.empty())
|
||||
{
|
||||
dprintln("MADT did not provide necessary information");
|
||||
delete apic;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PageTable::kernel().identity_map_page(apic->m_local_apic, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
// Map the local apic to kernel memory
|
||||
{
|
||||
vaddr_t vaddr = PageTable::kernel().get_free_page((vaddr_t)g_kernel_end);
|
||||
ASSERT(vaddr);
|
||||
dprintln("lapic paddr {8H}", apic->m_local_apic_paddr);
|
||||
apic->m_local_apic_vaddr = vaddr + (apic->m_local_apic_paddr % PAGE_SIZE);
|
||||
dprintln("lapic vaddr {8H}", apic->m_local_apic_vaddr);
|
||||
PageTable::kernel().map_page_at(
|
||||
apic->m_local_apic_paddr & PAGE_ADDR_MASK,
|
||||
apic->m_local_apic_vaddr & PAGE_ADDR_MASK,
|
||||
PageTable::Flags::ReadWrite | PageTable::Flags::Present
|
||||
);
|
||||
}
|
||||
|
||||
// Map io apics to kernel memory
|
||||
for (auto& io_apic : apic->m_io_apics)
|
||||
{
|
||||
PageTable::kernel().identity_map_page(io_apic.address, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
vaddr_t vaddr = PageTable::kernel().get_free_page((vaddr_t)g_kernel_end);
|
||||
ASSERT(vaddr);
|
||||
|
||||
io_apic.vaddr = vaddr + (io_apic.paddr % PAGE_SIZE);
|
||||
|
||||
PageTable::kernel().map_page_at(
|
||||
io_apic.paddr & PAGE_ADDR_MASK,
|
||||
io_apic.vaddr & PAGE_ADDR_MASK,
|
||||
PageTable::Flags::ReadWrite | PageTable::Flags::Present
|
||||
);
|
||||
io_apic.max_redirs = io_apic.read(IOAPIC_MAX_REDIRS);
|
||||
}
|
||||
|
||||
@@ -171,24 +196,24 @@ APIC* APIC::create()
|
||||
|
||||
uint32_t APIC::read_from_local_apic(ptrdiff_t offset)
|
||||
{
|
||||
return *(uint32_t*)(m_local_apic + offset);
|
||||
return *(uint32_t*)(m_local_apic_vaddr + offset);
|
||||
}
|
||||
|
||||
void APIC::write_to_local_apic(ptrdiff_t offset, uint32_t data)
|
||||
{
|
||||
*(uint32_t*)(m_local_apic + offset) = data;
|
||||
*(uint32_t*)(m_local_apic_vaddr + offset) = data;
|
||||
}
|
||||
|
||||
uint32_t APIC::IOAPIC::read(uint8_t offset)
|
||||
{
|
||||
volatile uint32_t* ioapic = (volatile uint32_t*)address;
|
||||
volatile uint32_t* ioapic = (volatile uint32_t*)vaddr;
|
||||
ioapic[0] = offset;
|
||||
return ioapic[4];
|
||||
}
|
||||
|
||||
void APIC::IOAPIC::write(uint8_t offset, uint32_t data)
|
||||
{
|
||||
volatile uint32_t* ioapic = (volatile uint32_t*)address;
|
||||
volatile uint32_t* ioapic = (volatile uint32_t*)vaddr;
|
||||
ioapic[0] = offset;
|
||||
ioapic[4] = data;
|
||||
}
|
||||
|
||||
@@ -196,7 +196,6 @@ namespace Kernel
|
||||
|
||||
page_vaddr = m_page_table.get_free_page();
|
||||
m_page_table.map_page_at(page_paddr, page_vaddr, PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
m_page_table.invalidate(page_vaddr);
|
||||
}
|
||||
|
||||
bool FixedWidthAllocator::allocate_page_if_needed(vaddr_t vaddr, uint8_t flags)
|
||||
@@ -251,7 +250,6 @@ namespace Kernel
|
||||
{
|
||||
paddr_t paddr = new_page_table.physical_address_of(page_begin);
|
||||
m_page_table.map_page_at(paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
m_page_table.invalidate(0);
|
||||
memcpy((void*)0, (void*)page_begin, PAGE_SIZE);
|
||||
}
|
||||
|
||||
@@ -261,7 +259,6 @@ namespace Kernel
|
||||
}
|
||||
|
||||
m_page_table.unmap_page(0);
|
||||
m_page_table.invalidate(0);
|
||||
|
||||
m_page_table.unlock();
|
||||
|
||||
|
||||
@@ -109,14 +109,12 @@ namespace Kernel
|
||||
new_page_table.map_page_at(paddr, vaddr, flags);
|
||||
|
||||
m_page_table.map_page_at(paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
m_page_table.invalidate(0);
|
||||
memcpy((void*)0, (void*)vaddr, PAGE_SIZE);
|
||||
}
|
||||
|
||||
MUST(allocator->m_allocations.push_back(BAN::move(new_allocation)));
|
||||
}
|
||||
m_page_table.unmap_page(0);
|
||||
m_page_table.invalidate(0);
|
||||
|
||||
m_page_table.unlock();
|
||||
|
||||
|
||||
@@ -85,11 +85,9 @@ namespace Kernel
|
||||
for (size_t i = 0; i < result->m_physical_pages.size(); i++)
|
||||
{
|
||||
m_page_table.map_page_at(result->m_physical_pages[i], 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
m_page_table.invalidate(0);
|
||||
memcpy((void*)0, (void*)(vaddr() + i * PAGE_SIZE), PAGE_SIZE);
|
||||
}
|
||||
m_page_table.unmap_page(0);
|
||||
m_page_table.invalidate(0);
|
||||
|
||||
m_page_table.unlock();
|
||||
|
||||
@@ -112,11 +110,9 @@ namespace Kernel
|
||||
for (size_t i = 0; i < m_physical_pages.size(); i++)
|
||||
{
|
||||
page_table.map_page_at(m_physical_pages[i], 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
page_table.invalidate(0);
|
||||
memset((void*)0, 0, PAGE_SIZE);
|
||||
}
|
||||
page_table.unmap_page(0);
|
||||
page_table.invalidate(0);
|
||||
|
||||
page_table.unlock();
|
||||
}
|
||||
@@ -147,7 +143,6 @@ namespace Kernel
|
||||
|
||||
// NOTE: we map the first page separately since it needs extra calculations
|
||||
page_table.map_page_at(m_physical_pages[i], 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
page_table.invalidate(0);
|
||||
|
||||
memcpy((void*)off, buffer, PAGE_SIZE - off);
|
||||
|
||||
@@ -160,7 +155,6 @@ namespace Kernel
|
||||
size_t len = BAN::Math::min<size_t>(PAGE_SIZE, bytes);
|
||||
|
||||
page_table.map_page_at(m_physical_pages[i], 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
page_table.invalidate(0);
|
||||
|
||||
memcpy((void*)0, buffer, len);
|
||||
|
||||
@@ -169,7 +163,6 @@ namespace Kernel
|
||||
i++;
|
||||
}
|
||||
page_table.unmap_page(0);
|
||||
page_table.invalidate(0);
|
||||
|
||||
page_table.unlock();
|
||||
}
|
||||
|
||||
@@ -265,8 +265,6 @@ namespace Kernel
|
||||
io_write(ATA_PORT_LBA2, (uint8_t)(lba >> 16));
|
||||
io_write(ATA_PORT_COMMAND, ATA_COMMAND_READ_SECTORS);
|
||||
|
||||
PIT::sleep(1);
|
||||
|
||||
for (uint32_t sector = 0; sector < sector_count; sector++)
|
||||
{
|
||||
block_until_irq();
|
||||
|
||||
@@ -178,7 +178,6 @@ namespace Kernel
|
||||
ASSERT(page_table.is_page_free(0));
|
||||
|
||||
page_table.map_page_at(this->paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
page_table.invalidate(0);
|
||||
|
||||
for (size_t i = 0; i < PAGE_SIZE / device.sector_size(); i++)
|
||||
{
|
||||
@@ -188,7 +187,6 @@ namespace Kernel
|
||||
}
|
||||
|
||||
page_table.unmap_page(0);
|
||||
page_table.invalidate(0);
|
||||
|
||||
page_table.unlock();
|
||||
|
||||
@@ -210,7 +208,6 @@ namespace Kernel
|
||||
ASSERT(page_table.is_page_free(0));
|
||||
|
||||
page_table.map_page_at(this->paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
page_table.invalidate(0);
|
||||
|
||||
// Sector not yet cached
|
||||
if (!(this->sector_mask & (1 << sector_offset)))
|
||||
@@ -222,7 +219,6 @@ namespace Kernel
|
||||
memcpy(buffer, (const void*)(sector_offset * device.sector_size()), device.sector_size());
|
||||
|
||||
page_table.unmap_page(0);
|
||||
page_table.invalidate(0);
|
||||
|
||||
page_table.unlock();
|
||||
|
||||
@@ -244,14 +240,12 @@ namespace Kernel
|
||||
ASSERT(page_table.is_page_free(0));
|
||||
|
||||
page_table.map_page_at(this->paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
page_table.invalidate(0);
|
||||
|
||||
memcpy((void*)(sector_offset * device.sector_size()), buffer, device.sector_size());
|
||||
this->sector_mask |= 1 << sector_offset;
|
||||
this->dirty_mask |= 1 << sector_offset;
|
||||
|
||||
page_table.unmap_page(0);
|
||||
page_table.invalidate(0);
|
||||
|
||||
page_table.unlock();
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
extern uint8_t g_kernel_end[];
|
||||
|
||||
VesaTerminalDriver* VesaTerminalDriver::create()
|
||||
{
|
||||
if (!(g_multiboot_info->flags & MULTIBOOT_FLAGS_FRAMEBUFFER))
|
||||
@@ -36,14 +38,21 @@ VesaTerminalDriver* VesaTerminalDriver::create()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PageTable::kernel().identity_map_range(framebuffer.addr, framebuffer.pitch * framebuffer.height, PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
uint64_t first_page = framebuffer.addr / PAGE_SIZE;
|
||||
uint64_t last_page = BAN::Math::div_round_up<uint64_t>(framebuffer.addr + framebuffer.pitch * framebuffer.height, PAGE_SIZE);
|
||||
uint64_t needed_pages = last_page - first_page + 1;
|
||||
|
||||
vaddr_t vaddr = PageTable::kernel().get_free_contiguous_pages(needed_pages, (vaddr_t)g_kernel_end);
|
||||
ASSERT(vaddr);
|
||||
|
||||
PageTable::kernel().map_range_at(framebuffer.addr, vaddr, needed_pages * PAGE_SIZE, PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||
|
||||
auto* driver = new VesaTerminalDriver(
|
||||
framebuffer.width,
|
||||
framebuffer.height,
|
||||
framebuffer.pitch,
|
||||
framebuffer.bpp,
|
||||
framebuffer.addr
|
||||
vaddr
|
||||
);
|
||||
driver->set_cursor_position(0, 0);
|
||||
driver->clear(TerminalColor::BLACK);
|
||||
|
||||
Reference in New Issue
Block a user