[amd64] Fixed problem with invalid upper mapping
This commit is contained in:
@@ -1,16 +1,20 @@
|
||||
/* vim: set ft=cpp.doxygen : */
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "sys/amd64/loader/data.h"
|
||||
|
||||
/// The place where the kernel pages are virtually mapped to
|
||||
#define KERNEL_VIRT_BASE 0xFFFFFF0000000000
|
||||
|
||||
/// amd64 standard states that addresses' upper bits are copies of the 47th bit, so these need to be
|
||||
/// stripped down to only 48 bits
|
||||
#define AMD64_MM_MASK(a) ((uintptr_t) (a) & 0xFFFFFFFFFFFF)
|
||||
#define AMD64_MM_STRIPSX(a) ((uintptr_t) (a) & 0xFFFFFFFFFFFF)
|
||||
#define AMD64_MM_ADDRSX(a) (((uintptr_t) (a) & (1ULL << 47)) ? \
|
||||
(0xFFFFFF0000000000 | ((uintptr_t) (a))) : \
|
||||
((uintptr_t) (a)))
|
||||
|
||||
#define MM_VIRTUALIZE(a) ((uintptr_t) (a) + 0xFFFFFF0000000000)
|
||||
#define MM_PHYS(a) ((uintptr_t) (a) - 0xFFFFFF0000000000)
|
||||
#define MM_VIRTUALIZE(a) ((uintptr_t) (a) + 0xFFFFFF0000000000)
|
||||
#define MM_PHYS(a) ((uintptr_t) (a) - 0xFFFFFF0000000000)
|
||||
|
||||
/// Page map level 4
|
||||
typedef uint64_t *mm_pml4_t;
|
||||
@@ -27,4 +31,4 @@ typedef mm_pml4_t mm_space_t;
|
||||
/// Kernel memory space
|
||||
extern mm_space_t mm_kernel;
|
||||
|
||||
void amd64_mm_init(void);
|
||||
void amd64_mm_init(struct amd64_loader_data *data);
|
||||
|
||||
@@ -62,9 +62,8 @@ int acpi_hpet_init(void) {
|
||||
if (!hpet_base) {
|
||||
return -1;
|
||||
}
|
||||
uint64_t addr = 0x7FFFFFFFF000ULL;
|
||||
hpet = (struct hpet *) addr;
|
||||
mm_map_pages_contiguous(mm_kernel, addr, hpet_base, 1, 0);
|
||||
hpet = (struct hpet *) MM_VIRTUALIZE(hpet_base);
|
||||
kdebug("HPET = %p\n", hpet);
|
||||
|
||||
uint64_t hpet_clk = (hpet->caps >> 32) & 0xFFFFFFFF;
|
||||
assert(hpet_clk != 0, "HPET does not work correctly\n");
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ void kernel_main(uintptr_t loader_info_phys_ptr) {
|
||||
// Memory management
|
||||
kernel_startup_section("Memory management");
|
||||
amd64_phys_memory_map((multiboot_memory_map_t *) MM_VIRTUALIZE(multiboot_info->mmap_addr), multiboot_info->mmap_length);
|
||||
amd64_mm_init();
|
||||
amd64_mm_init(loader_data);
|
||||
|
||||
kernel_startup_section("Basic hardware");
|
||||
amd64_gdt_init();
|
||||
|
||||
+5
-1
@@ -6,7 +6,7 @@
|
||||
ENTRY(_start)
|
||||
|
||||
_kernel_base = 0xFFFFFF0000000000;
|
||||
_kernel_base_phys = 0x200000;
|
||||
_kernel_base_phys = 0x4000000;
|
||||
|
||||
SECTIONS {
|
||||
. = _kernel_base + _kernel_base_phys;
|
||||
@@ -29,5 +29,9 @@ SECTIONS {
|
||||
*(COMMON)
|
||||
*(.bss)
|
||||
}
|
||||
|
||||
. = ALIGN(4K);
|
||||
_kernel_end = .;
|
||||
_kernel_end_phys = . - _kernel_base;
|
||||
}
|
||||
|
||||
|
||||
+68
-99
@@ -7,6 +7,7 @@
|
||||
#include "sys/amd64/mm/pool.h"
|
||||
|
||||
uintptr_t amd64_map_get(const mm_space_t pml4, uintptr_t vaddr, uint64_t *flags) {
|
||||
vaddr = AMD64_MM_STRIPSX(vaddr);
|
||||
size_t pml4i = (vaddr >> 39) & 0x1FF;
|
||||
size_t pdpti = (vaddr >> 30) & 0x1FF;
|
||||
size_t pdi = (vaddr >> 21) & 0x1FF;
|
||||
@@ -64,6 +65,7 @@ uintptr_t amd64_map_get(const mm_space_t pml4, uintptr_t vaddr, uint64_t *flags)
|
||||
}
|
||||
|
||||
uintptr_t amd64_map_umap(mm_space_t pml4, uintptr_t vaddr, uint32_t size) {
|
||||
vaddr = AMD64_MM_STRIPSX(vaddr);
|
||||
// TODO: support page sizes other than 4KiB
|
||||
// (Though I can't think of any reason to use it)
|
||||
size_t pml4i = (vaddr >> 39) & 0x1FF;
|
||||
@@ -116,6 +118,7 @@ uintptr_t amd64_map_umap(mm_space_t pml4, uintptr_t vaddr, uint32_t size) {
|
||||
}
|
||||
|
||||
int amd64_map_single(mm_space_t pml4, uintptr_t virt_addr, uintptr_t phys, uint32_t flags) {
|
||||
virt_addr = AMD64_MM_STRIPSX(virt_addr);
|
||||
// TODO: support page sizes other than 4KiB
|
||||
// (Though I can't think of any reason to use it)
|
||||
size_t pml4i = (virt_addr >> 39) & 0x1FF;
|
||||
@@ -200,6 +203,69 @@ int mm_space_clone(mm_space_t dst_pml4, const mm_space_t src_pml4, uint32_t flag
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amd64_mm_describe_range(const mm_space_t pml4, uintptr_t start_addr, uintptr_t end_addr) {
|
||||
uintptr_t addr = AMD64_MM_STRIPSX(start_addr);
|
||||
|
||||
size_t range_length = 0;
|
||||
uintptr_t virt_range_begin = MM_NADDR;
|
||||
uint32_t range_flags = 0;
|
||||
|
||||
mm_pdpt_t pdpt;
|
||||
|
||||
while (addr < AMD64_MM_STRIPSX(end_addr)) {
|
||||
size_t pml4i = (addr >> 39) & 0x1FF;
|
||||
size_t pdpti = (addr >> 30) & 0x1FF;
|
||||
size_t pdi = (addr >> 21) & 0x1FF;
|
||||
size_t pti = (addr >> 12) & 0x1FF;
|
||||
size_t page_size = 1ULL << 39;
|
||||
|
||||
if (pml4[pml4i] & 1) {
|
||||
if (pml4[pml4i] & (1 << 7)) {
|
||||
panic("Found a huge page in PML4 (shouldn't be possible): %p\n", AMD64_MM_ADDRSX(addr));
|
||||
}
|
||||
|
||||
page_size = 1ULL << 30;
|
||||
pdpt = (mm_pdpt_t) MM_VIRTUALIZE(pml4[pml4i] & ~0xFFF);
|
||||
|
||||
if (pdpt[pdpti] & 1) {
|
||||
if (pdpt[pdpti] & (1 << 7)) {
|
||||
if (virt_range_begin == MM_NADDR) {
|
||||
virt_range_begin = addr;
|
||||
range_length = 0;
|
||||
range_flags = pdpt[pdpti] & 5;
|
||||
}
|
||||
|
||||
goto found;
|
||||
}
|
||||
|
||||
panic("TODO: implement smaller page description\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (virt_range_begin != MM_NADDR) {
|
||||
kdebug("Range %p .. %p (%c%c) %S\n",
|
||||
virt_range_begin,
|
||||
virt_range_begin + range_length,
|
||||
(range_flags & (1 << 2) ? 'u' : '-'),
|
||||
(range_flags & (1 << 1) ? 'w' : '-'),
|
||||
range_length);
|
||||
}
|
||||
|
||||
found:
|
||||
addr += page_size;
|
||||
range_length += page_size;
|
||||
}
|
||||
|
||||
if (virt_range_begin != MM_NADDR) {
|
||||
kdebug("Range %p .. %p (%c%c) %S\n",
|
||||
virt_range_begin,
|
||||
virt_range_begin + range_length,
|
||||
(range_flags & (1 << 2) ? 'u' : '-'),
|
||||
(range_flags & (1 << 1) ? 'w' : '-'),
|
||||
range_length);
|
||||
}
|
||||
}
|
||||
|
||||
void mm_describe(const mm_space_t pml4) {
|
||||
kdebug("Memory space V:%p:\n", pml4);
|
||||
|
||||
@@ -209,104 +275,7 @@ void mm_describe(const mm_space_t pml4) {
|
||||
|
||||
// Dump everything except kernel-space mappings
|
||||
kdebug("- Userspace:\n");
|
||||
for (size_t pml4i = 0; pml4i < 255; ++pml4i) {
|
||||
if (!(pml4[pml4i] & 1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pml4[pml4i] & (1 << 7)) {
|
||||
kdebug("`- PHYS %p\n", pml4[pml4i] & ~0xFFF);
|
||||
continue;
|
||||
}
|
||||
|
||||
pdpt = (mm_pdpt_t) MM_VIRTUALIZE(pml4[pml4i] & ~0xFFF);
|
||||
kdebug("`- PDPT %p\n", pdpt);
|
||||
|
||||
for (size_t pdpti = 0; pdpti < 512; ++pdpti) {
|
||||
if (!(pdpt[pdpti] & 1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pdpt[pdpti] & (1 << 7)) {
|
||||
kdebug("`- PHYS %p\n", pdpt[pdpti] & ~0xFFF);
|
||||
continue;
|
||||
}
|
||||
|
||||
pd = (mm_pagedir_t) MM_VIRTUALIZE(pdpt[pdpti] & ~0xFFF);
|
||||
kdebug(" `- PDIR %p\n", pd);
|
||||
|
||||
for (size_t pdi = 0; pdi < 512; ++pdi) {
|
||||
if (!(pd[pdi] & 1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pd[pdi] & (1 << 7)) {
|
||||
kdebug("`- PHYS %p\n", pdpt[pdpti] & ~0xFFF);
|
||||
continue;
|
||||
}
|
||||
|
||||
pt = (mm_pagetab_t) MM_VIRTUALIZE(pd[pdi] & ~0xFFF);
|
||||
kdebug(" `- PTAB %p\n", pt);
|
||||
|
||||
for (size_t pti = 0; pti < 512; ++pti) {
|
||||
if (!(pt[pti] & 1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
kdebug(" `- %p - %p (4KiB)\n", (pml4i << 39) | (pdpti << 30) | (pdi << 21) | (pti << 12), pt[pti] & ~0xFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
amd64_mm_describe_range(pml4, 0, 0xFFFFFF0000000000);
|
||||
kdebug("- Kernelspace:\n");
|
||||
for (size_t pml4i = 255; pml4i < 510; ++pml4i) {
|
||||
if (!(pml4[pml4i] & 1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pml4[pml4i] & (1 << 7)) {
|
||||
kdebug("`- PHYS %p\n", pml4[pml4i] & ~0xFFF);
|
||||
continue;
|
||||
}
|
||||
|
||||
pdpt = (mm_pdpt_t) MM_VIRTUALIZE(pml4[pml4i] & ~0xFFF);
|
||||
kdebug("`- PDPT %p\n", pdpt);
|
||||
|
||||
for (size_t pdpti = 0; pdpti < 512; ++pdpti) {
|
||||
if (!(pdpt[pdpti] & 1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pdpt[pdpti] & (1 << 7)) {
|
||||
kdebug("`- PHYS %p\n", pdpt[pdpti] & ~0xFFF);
|
||||
continue;
|
||||
}
|
||||
|
||||
pd = (mm_pagedir_t) MM_VIRTUALIZE(pdpt[pdpti] & ~0xFFF);
|
||||
kdebug(" `- PDIR %p\n", pd);
|
||||
|
||||
for (size_t pdi = 0; pdi < 512; ++pdi) {
|
||||
if (!(pd[pdi] & 1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pd[pdi] & (1 << 7)) {
|
||||
kdebug("`- PHYS %p\n", pdpt[pdpti] & ~0xFFF);
|
||||
continue;
|
||||
}
|
||||
|
||||
pt = (mm_pagetab_t) MM_VIRTUALIZE(pd[pdi] & ~0xFFF);
|
||||
kdebug(" `- PTAB %p\n", pt);
|
||||
|
||||
for (size_t pti = 0; pti < 512; ++pti) {
|
||||
if (!(pt[pti] & 1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
kdebug(" `- %p - %p (4KiB)\n", (pml4i << 39) | (pdpti << 30) | (pdi << 21) | (pti << 12), pt[pti] & ~0xFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
amd64_mm_describe_range(pml4, 0xFFFFFF0000000000, 0xFFFFFF00FFFFFFFF);
|
||||
}
|
||||
|
||||
+8
-5
@@ -10,7 +10,9 @@
|
||||
|
||||
mm_space_t mm_kernel;
|
||||
|
||||
void amd64_mm_init(void) {
|
||||
extern int _kernel_end;
|
||||
|
||||
void amd64_mm_init(struct amd64_loader_data *data) {
|
||||
kdebug("Memory manager init\n");
|
||||
|
||||
// Physical memory at this point:
|
||||
@@ -26,16 +28,17 @@ void amd64_mm_init(void) {
|
||||
memset((void *) (0x200000 - 2 * 0x1000), 0, 0x1000 * 2);
|
||||
|
||||
// 0xFFFFFF0000000000 -> 0 (512GiB) mapping
|
||||
pml4[AMD64_MM_MASK(KERNEL_VIRT_BASE) >> 39] = (uint64_t) pdpt | 1 | 2 | 4;
|
||||
for (int i = 0; i < 512; ++i) {
|
||||
pdpt[(AMD64_MM_MASK((KERNEL_VIRT_BASE) >> 30) + i) & 0x1FF] = 1 | 2 | 4 | (1 << 7);
|
||||
pml4[AMD64_MM_STRIPSX(KERNEL_VIRT_BASE) >> 39] = ((uintptr_t) pdpt) | 1 | 2 | 4;
|
||||
for (uint64_t i = 0; i < 4; ++i) {
|
||||
kdebug("Mapping %p -> %p\n", KERNEL_VIRT_BASE | (i << 30), i << 30);
|
||||
pdpt[((AMD64_MM_STRIPSX(KERNEL_VIRT_BASE) >> 30) + i) & 0x1FF] = (i << 30) | 1 | 2 | 4 | (1 << 7);
|
||||
}
|
||||
|
||||
// Load the new table
|
||||
asm volatile ("mov %0, %%cr3"::"a"(pml4):"memory");
|
||||
|
||||
// Create a pool located right after kernel image
|
||||
amd64_mm_pool_init(MM_VIRTUALIZE(0x400000), MM_POOL_SIZE);
|
||||
amd64_mm_pool_init((uintptr_t) &_kernel_end, MM_POOL_SIZE);
|
||||
|
||||
mm_kernel = (mm_space_t) (MM_VIRTUALIZE(pml4));
|
||||
|
||||
|
||||
+2
-1
@@ -6,9 +6,10 @@
|
||||
#include "sys/mem.h"
|
||||
#include "sys/mm.h"
|
||||
|
||||
extern int _kernel_end_phys;
|
||||
// Roughly 36MiB of lower memory is occupied by kernel so far:
|
||||
// The rest is available for both kernel and user allocation
|
||||
#define PHYS_ALLOWED_BEGIN (((/* Kernel image end */ 0x400000 + MM_POOL_SIZE) + 0xFFF) & ~0xFFF)
|
||||
#define PHYS_ALLOWED_BEGIN ((((uintptr_t) &_kernel_end_phys + MM_POOL_SIZE) + 0xFFF) & ~0xFFF)
|
||||
|
||||
// TODO: move to sys/util.h
|
||||
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
||||
|
||||
Reference in New Issue
Block a user