Use a direct address for P4 rather than a pointer

This commit is contained in:
Thomas Lovén 2018-02-20 14:02:47 +01:00
parent 8711fee390
commit 36c517dd82
6 changed files with 97 additions and 87 deletions

View File

@ -26,20 +26,24 @@
#ifndef __ASSEMBLER__
#include <stddef.h>
extern uint64_t kernel_P4;
void *memcpy(void *dst, const void *src, size_t n);
void *memset(void *s, int c, size_t n);
void *memmove(void *dest, const void *src, size_t n);
int memcmp(const void *s1, const void *s2, size_t n);
size_t strlen(const char *s);
void pmm_free(uintptr_t page);
uintptr_t pmm_alloc();
uintptr_t pmm_calloc();
void pmm_free(uint64_t page);
uint64_t pmm_alloc();
uint64_t pmm_calloc();
uintptr_t vmm_get_page(void *P4, uintptr_t addr);
int vmm_set_page(void *P4, uintptr_t addr, uintptr_t page, uint16_t flags);
int touch_page(void *P4, uintptr_t addr, uint16_t flags);
void free_page(void *P4, uintptr_t addr, int free);
uint64_t vmm_get_page(uint64_t P4, uint64_t addr);
#define PAGE_EXIST(p) ((p) != (uint64_t)-1)
int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags);
int touch_page(uint64_t P4, uint64_t addr, uint16_t flags);
void free_page(uint64_t P4, uint64_t addr, int free);
extern union PTE BootP4;
extern int kernel_start, kernel_end;

View File

@ -2,25 +2,29 @@
#include <multiboot.h>
#include <debug.h>
uint64_t kernel_P4;
void memory_init()
{
uintptr_t start, end;
kernel_P4 = (uint64_t)&BootP4;
uint64_t start, end;
uint32_t type, i = 0;
debug_info("Parsing memory map\n");
while(!multiboot_get_memory_area(i++, &start, &end, &type))
{
debug("0x%016x-0x%016x (%d)\n", start, end, type);
for(uintptr_t p = start; p < end; p += PAGE_SIZE)
for(uint64_t p = start; p < end; p += PAGE_SIZE)
{
if(p >= V2P(&kernel_start) && p < V2P(&kernel_end))
continue;
uintptr_t page = vmm_get_page(&BootP4, (uintptr_t)P2V(p));
if(page == (uintptr_t)-1 || !(page & PAGE_PRESENT))
uint64_t addr = (uint64_t)P2V(p);
uint64_t page = vmm_get_page(kernel_P4, addr);
if(!PAGE_EXIST(page) || !(page & PAGE_PRESENT))
{
uint16_t flags = PAGE_GLOBAL | PAGE_HUGE | PAGE_WRITE;
touch_page(&BootP4, (uintptr_t)P2V(p), flags);
vmm_set_page(&BootP4, (uintptr_t)P2V(p), p, flags | PAGE_PRESENT);
touch_page(kernel_P4, addr, flags);
vmm_set_page(kernel_P4, addr, p, flags | PAGE_PRESENT);
}
if(type == MMAP_FREE)

View File

@ -1,25 +1,25 @@
#include <memory.h>
uintptr_t first = 0;
uint64_t first = 0;
void pmm_free(uintptr_t page)
void pmm_free(uint64_t page)
{
page = (uintptr_t)P2V(page);
*(uintptr_t *)page = first;
page = (uint64_t)P2V(page);
*(uint64_t *)page = first;
first = page;
}
uintptr_t pmm_alloc()
uint64_t pmm_alloc()
{
uintptr_t page = first;
first = page?*(uintptr_t *)page:0;
page = (uintptr_t)(page?V2P(page):0);
uint64_t page = first;
first = page?*(uint64_t *)page:0;
page = (uint64_t)(page?V2P(page):0);
return page;
}
uintptr_t pmm_calloc()
uint64_t pmm_calloc()
{
uintptr_t page = pmm_alloc();
uint64_t page = pmm_alloc();
memset(P2V(page), 0, 0x1000);
return page;
}

View File

@ -15,19 +15,19 @@ struct {
TEST(alloc_returns_freed_page)
{
pmm_free(V2P(&mem[0]));
uintptr_t a = pmm_alloc();
uint64_t a = pmm_alloc();
ASSERT_EQ_PTR(a, V2P(&mem[0]));
}
TEST(alloc_returns_0_if_no_free_pages)
{
uintptr_t a = pmm_alloc();
uint64_t a = pmm_alloc();
ASSERT_EQ_PTR(a, 0);
}
TEST(alloc_zero_after_all_free_pages)
{
pmm_free(V2P(&mem[0]));
pmm_alloc();
uintptr_t a = pmm_alloc();
uint64_t a = pmm_alloc();
ASSERT_EQ_PTR(a, 0);
}
@ -35,7 +35,7 @@ TEST(alloc_two_pages___first_page_is_not_zero)
{
pmm_free(V2P(&mem[0]));
pmm_free(V2P(&mem[1]));
uintptr_t a = pmm_alloc();
uint64_t a = pmm_alloc();
pmm_alloc();
ASSERT_NEQ_PTR(a, 0);
}
@ -44,14 +44,14 @@ TEST(alloc_two_pages___second_page_is_not_zero)
pmm_free(V2P(&mem[0]));
pmm_free(V2P(&mem[1]));
pmm_alloc();
uintptr_t a = pmm_alloc();
uint64_t a = pmm_alloc();
ASSERT_NEQ_PTR(a, 0);
}
TEST(alloc_two_pages___doesnt_return_same_page_twice)
{
pmm_free(V2P(&mem[0]));
pmm_free(V2P(&mem[1]));
uintptr_t a = pmm_alloc();
uintptr_t b = pmm_alloc();
uint64_t a = pmm_alloc();
uint64_t b = pmm_alloc();
ASSERT_NEQ_PTR(a, b);
}

View File

@ -1,21 +1,21 @@
#include <memory.h>
#define FLAGS_MASK (PAGE_SIZE-1)
#define MASK_FLAGS(addr) ((uintptr_t)addr & ~FLAGS_MASK)
#define MASK_FLAGS(addr) ((uint64_t)addr & ~FLAGS_MASK)
union PTE {
uint64_t value;
struct {
uintptr_t present:1;
uintptr_t write:1;
uintptr_t user:1;
uintptr_t write_through:1;
uintptr_t nocache:1;
uintptr_t accessed:1;
uintptr_t dirty:1;
uintptr_t huge:1;
uintptr_t global:1;
uintptr_t flags:3;
uint64_t present:1;
uint64_t write:1;
uint64_t user:1;
uint64_t write_through:1;
uint64_t nocache:1;
uint64_t accessed:1;
uint64_t dirty:1;
uint64_t huge:1;
uint64_t global:1;
uint64_t flags:3;
};
};
@ -25,7 +25,7 @@ union PTE {
#define P2e(pt, addr) PT(P3e(pt, addr).value)[P2_OFFSET(addr)]
#define P1e(pt, addr) PT(P2e(pt, addr).value)[P1_OFFSET(addr)]
int page_exists(void *P4, uintptr_t addr)
static int page_exists(uint64_t P4, uint64_t addr)
{
if(P4
&& P4e(P4, addr).present
@ -36,7 +36,7 @@ int page_exists(void *P4, uintptr_t addr)
return 0;
}
uintptr_t vmm_get_page(void *P4, uintptr_t addr)
uint64_t vmm_get_page(uint64_t P4, uint64_t addr)
{
if(page_exists(P4, addr))
if(P2e(P4, addr).huge)
@ -47,7 +47,7 @@ uintptr_t vmm_get_page(void *P4, uintptr_t addr)
return -1;
}
int vmm_set_page(void *P4, uintptr_t addr, uintptr_t page, uint16_t flags)
int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags)
{
if(flags & PAGE_HUGE)
{
@ -69,7 +69,7 @@ int vmm_set_page(void *P4, uintptr_t addr, uintptr_t page, uint16_t flags)
return 0;
}
int touch_page(void *P4, uintptr_t addr, uint16_t flags)
int touch_page(uint64_t P4, uint64_t addr, uint16_t flags)
{
if(!P4) return -1;
@ -96,7 +96,7 @@ int touch_page(void *P4, uintptr_t addr, uint16_t flags)
return 0;
}
void free_page(void *P4, uintptr_t addr, int free)
void free_page(uint64_t P4, uint64_t addr, int free)
{
if(!page_exists(P4, addr))
return;

View File

@ -8,13 +8,14 @@
#include "vmm.c"
void *data;
uintptr_t *p4, *p3, *p2, *p1;
uint64_t *p4, *p3, *p2, *p1;
uint64_t P4;
#define ADDR1234 ((1UL<<39) + (2UL<<30) + (3UL<<21) + (4UL<<12))
#define BUILD_PT(o4, o3, o2) \
p4[(o4)] = (uintptr_t)p3; p4[(o4)] |= PAGE_PRESENT; \
p3[(o3)] = (uintptr_t)p2; p3[(o3)] |= PAGE_PRESENT; \
p2[(o2)] = (uintptr_t)p1; p2[(o2)] |= PAGE_PRESENT;
p4[(o4)] = (uint64_t)p3; p4[(o4)] |= PAGE_PRESENT; \
p3[(o3)] = (uint64_t)p2; p3[(o3)] |= PAGE_PRESENT; \
p2[(o2)] = (uint64_t)p1; p2[(o2)] |= PAGE_PRESENT;
BEFORE()
{
@ -23,6 +24,7 @@ BEFORE()
p3 = &p4[512];
p2 = &p4[1024];
p1 = &p4[1536];
P4 = (uint64_t)p4;
}
AFTER()
{
@ -34,7 +36,7 @@ TEST(get_page_returns_correct_address)
BUILD_PT(0,0,0);
p1[0] = 0x1234567890ABC000 | PAGE_PRESENT;
uintptr_t ret = vmm_get_page(p4, 0);
uint64_t ret = vmm_get_page(P4, 0);
ASSERT_EQ_PTR(ret, 0x1234567890ABC000 | PAGE_PRESENT);
}
@ -43,7 +45,7 @@ TEST(get_page_ignores_flags)
BUILD_PT(0,0,0);
p1[0] = 0x1234567890ABC000 | PAGE_PRESENT;
uintptr_t ret = vmm_get_page(p4, 0);
uint64_t ret = vmm_get_page(P4, 0);
ASSERT_EQ_PTR(ret, 0x1234567890ABC000 | PAGE_PRESENT);
}
@ -52,27 +54,27 @@ TEST(get_page_works_for_different_address)
BUILD_PT(1,2,3)
p1[4] = 0x34567890ABCDE000 | PAGE_PRESENT;
uintptr_t ret = vmm_get_page(p4, ADDR1234);
uint64_t ret = vmm_get_page(P4, ADDR1234);
ASSERT_EQ_PTR(ret, 0x34567890ABCDE000 | PAGE_PRESENT);
}
TEST(get_page_fails_if_PTE_not_present)
{
BUILD_PT(0,0,0);
p2[0] = (uintptr_t)p1;
p2[0] = (uint64_t)p1;
p1[0] = 0x1234567890ABC000 | PAGE_PRESENT;
uintptr_t ret = vmm_get_page(p4, 0);
uint64_t ret = vmm_get_page(P4, 0);
ASSERT_EQ_PTR(ret, -1);
}
TEST(get_page_gets_2mb_pages)
{
p4[1] = (uintptr_t)p3; p4[1] |= PAGE_PRESENT;
p3[2] = (uintptr_t)p2; p3[2] |= PAGE_PRESENT;
p4[1] = (uint64_t)p3; p4[1] |= PAGE_PRESENT;
p3[2] = (uint64_t)p2; p3[2] |= PAGE_PRESENT;
p2[3] = 0x1234567890A00000 | PAGE_HUGE | PAGE_PRESENT;
uintptr_t ret = vmm_get_page(p4, ADDR1234);
uint64_t ret = vmm_get_page(P4, ADDR1234);
ASSERT_EQ_PTR(ret, 0x1234567890A00000 | PAGE_HUGE | PAGE_PRESENT);
}
@ -80,7 +82,7 @@ TEST(set_page_sets_page)
{
BUILD_PT(0,0,0);
vmm_set_page(p4, 0, 0x1234567890ABC000, PAGE_PRESENT);
vmm_set_page(P4, 0, 0x1234567890ABC000, PAGE_PRESENT);
ASSERT_EQ_PTR(p1[0], 0x1234567890ABC000 | PAGE_PRESENT);
}
@ -88,25 +90,25 @@ TEST(set_page_returns_success_if_working)
{
BUILD_PT(0,0,0);
int retval = vmm_set_page(p4, 0, 0x1234567890ABC000, PAGE_PRESENT);
int retval = vmm_set_page(P4, 0, 0x1234567890ABC000, PAGE_PRESENT);
ASSERT_EQ_INT(retval, 0);
}
TEST(set_page_fails_if_PT_missing)
{
BUILD_PT(0,0,0);
p3[0] = (uintptr_t)p2;
p3[0] = (uint64_t)p2;
int retval = vmm_set_page(p4, 0, 0x1234567890ABC000, PAGE_PRESENT);
int retval = vmm_set_page(P4, 0, 0x1234567890ABC000, PAGE_PRESENT);
ASSERT_NEQ_INT(retval, 0);
}
TEST(set_page_sets_2mb_pages)
{
p4[1] = (uintptr_t)p3; p4[1] |= PAGE_PRESENT;
p3[2] = (uintptr_t)p2; p3[2] |= PAGE_PRESENT;
p4[1] = (uint64_t)p3; p4[1] |= PAGE_PRESENT;
p3[2] = (uint64_t)p2; p3[2] |= PAGE_PRESENT;
vmm_set_page(p4, (1UL<<39)+(2UL<<30)+(3UL<<21), 0x1234567890A00000, PAGE_HUGE | PAGE_PRESENT);
vmm_set_page(P4, (1UL<<39)+(2UL<<30)+(3UL<<21), 0x1234567890A00000, PAGE_HUGE | PAGE_PRESENT);
ASSERT_EQ_PTR(p2[3], 0x1234567890A00000 | PAGE_HUGE | PAGE_PRESENT);
}
@ -114,52 +116,52 @@ TEST(set_page_does_not_overwrite_4kb_pages_with_2mb)
{
BUILD_PT(0,0,0);
int retval = vmm_set_page(p4, 0, 0, PAGE_HUGE | PAGE_PRESENT);
int retval = vmm_set_page(P4, 0, 0, PAGE_HUGE | PAGE_PRESENT);
ASSERT_NEQ_INT(retval, 0);
}
uintptr_t pmm_calloc()
uint64_t pmm_calloc()
{
uintptr_t *pages[] = {p3, p2, p1};
uint64_t *pages[] = {p3, p2, p1};
static int counter=0;
if(counter >= 3) return 0;
return (uintptr_t)pages[counter++];
return (uint64_t)pages[counter++];
}
TEST(touch_page_adds_P3)
{
touch_page(p4, ADDR1234, 0);
touch_page(P4, ADDR1234, 0);
ASSERT_EQ_PTR(p4[1], (uintptr_t)p3 | PAGE_PRESENT);
ASSERT_EQ_PTR(p4[1], (uint64_t)p3 | PAGE_PRESENT);
}
TEST(touch_page_adds_P2)
{
touch_page(p4, ADDR1234, 0);
touch_page(P4, ADDR1234, 0);
ASSERT_EQ_PTR(p3[2], (uintptr_t)p2 | PAGE_PRESENT);
ASSERT_EQ_PTR(p3[2], (uint64_t)p2 | PAGE_PRESENT);
}
TEST(touch_page_adds_P1)
{
touch_page(p4, ADDR1234, 0);
touch_page(P4, ADDR1234, 0);
ASSERT_EQ_PTR(p2[3], (uintptr_t)p1 | PAGE_PRESENT);
ASSERT_EQ_PTR(p2[3], (uint64_t)p1 | PAGE_PRESENT);
}
TEST(touch_page_sets_flags)
{
touch_page(p4, 0, PAGE_WRITE);
touch_page(P4, 0, PAGE_WRITE);
ASSERT_EQ_PTR(p2[0], (uintptr_t)p1 | PAGE_WRITE | PAGE_PRESENT);
ASSERT_EQ_PTR(p2[0], (uint64_t)p1 | PAGE_WRITE | PAGE_PRESENT);
}
TEST(touch_page_fails_if_out_of_pages)
{
pmm_calloc();
int retval = touch_page(p4, 0, 0);
int retval = touch_page(P4, 0, 0);
ASSERT_NEQ_INT(retval, 0);
}
TEST(touch_page_stops_at_P2_for_huge_pages)
{
touch_page(p4, 0, PAGE_HUGE);
touch_page(P4, 0, PAGE_HUGE);
ASSERT_EQ_PTR(p2[0], 0);
}
@ -168,7 +170,7 @@ TEST(free_page_unsets_page)
BUILD_PT(1,2,3);
p1[4] = PAGE_PRESENT;
free_page(p4, ADDR1234, 0);
free_page(P4, ADDR1234, 0);
ASSERT_EQ_PTR(p1[4], 0);
}
@ -177,7 +179,7 @@ TEST(free_page_unsets_P2_entry_if_P1_is_empty)
BUILD_PT(1,2,3);
p1[4] = PAGE_PRESENT;
free_page(p4, ADDR1234, 1);
free_page(P4, ADDR1234, 1);
ASSERT_EQ_PTR(p2[3], 0);
}
@ -186,7 +188,7 @@ TEST(free_page_does_not_unset_P2_entry_if_not_asked_to)
BUILD_PT(1,2,3);
p1[4] = PAGE_PRESENT;
free_page(p4, ADDR1234, 0);
free_page(P4, ADDR1234, 0);
ASSERT_NEQ_PTR(p2[3], 0);
}
@ -196,7 +198,7 @@ TEST(free_page_does_not_unset_P2_entry_if_P1_is_not_empty)
p1[4] = PAGE_PRESENT;
p1[0] = PAGE_PRESENT;
free_page(p4, ADDR1234, 1);
free_page(P4, ADDR1234, 1);
ASSERT_NEQ_PTR(p2[3], 0);
}
@ -207,13 +209,13 @@ TEST(free_page_does_not_stop_if_P2_pointed_page_is_not_empty)
p1[4] = PAGE_PRESENT;
p1[0] = PAGE_PRESENT;
free_page(p4, ADDR1234, 1);
free_page(P4, ADDR1234, 1);
ASSERT_EQ_PTR(p2[3], 0);
}
uintptr_t freed[] = {0,0,0,0,0};
void pmm_free(uintptr_t page)
uint64_t freed[] = {0,0,0,0,0};
void pmm_free(uint64_t page)
{
static int counter = 0;
freed[counter++] = page;
@ -223,7 +225,7 @@ TEST(free_page_returns_P1_to_PMM_if_empty)
BUILD_PT(1,2,3);
p1[4] = PAGE_PRESENT;
free_page(p4, ADDR1234, 1);
free_page(P4, ADDR1234, 1);
ASSERT_EQ_PTR(freed[0], p1);
}