From 9bc1abceff7d4d6b51bdb3cc5ea4b7b20b9fe83c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Tue, 20 Feb 2018 21:58:14 +0100 Subject: [PATCH] VMM -- Touch and set page in one operation --- src/kernel/include/memory.h | 2 +- src/kernel/memory/memory.c | 3 +-- src/kernel/memory/vmm.c | 16 +++++++++++++--- src/kernel/memory/vmm.tt | 28 +++++++++++++++++++++++----- 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index ffaccb8..4915980 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -41,7 +41,7 @@ uint64_t pmm_calloc(); 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 vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags, int touch); int touch_page(uint64_t P4, uint64_t addr, uint16_t flags); void free_page(uint64_t P4, uint64_t addr, int free); diff --git a/src/kernel/memory/memory.c b/src/kernel/memory/memory.c index 3d8ff36..56d62ba 100644 --- a/src/kernel/memory/memory.c +++ b/src/kernel/memory/memory.c @@ -25,8 +25,7 @@ void memory_init() if(!PAGE_EXIST(page) || !(page & PAGE_PRESENT)) { uint16_t flags = PAGE_GLOBAL | PAGE_HUGE | PAGE_WRITE; - touch_page(kernel_P4, addr, flags); - vmm_set_page(kernel_P4, addr, p, flags | PAGE_PRESENT); + vmm_set_page(kernel_P4, addr, p, flags | PAGE_PRESENT, 1); } if(type == MMAP_FREE) diff --git a/src/kernel/memory/vmm.c b/src/kernel/memory/vmm.c index 754ae1e..859eb42 100644 --- a/src/kernel/memory/vmm.c +++ b/src/kernel/memory/vmm.c @@ -47,7 +47,7 @@ uint64_t vmm_get_page(uint64_t P4, uint64_t addr) return -1; } -int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags) +int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags, int touch) { if(flags & PAGE_HUGE) { @@ -55,7 +55,12 @@ int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags) && P4e(P4, addr).present && P3e(P4, addr).present )) - return -1; + { + if(touch) + touch_page(P4, addr, flags); + else + return -1; + } if(P2e(P4, addr).present && !P2e(P4,addr).huge) return -1; P2e(P4, addr).value = page | flags; @@ -63,7 +68,12 @@ int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags) } if(!page_exists(P4, addr)) - return -1; + { + if(touch) + touch_page(P4, addr, flags); + else + return -1; + } P1e(P4, addr).value = page | flags; return 0; diff --git a/src/kernel/memory/vmm.tt b/src/kernel/memory/vmm.tt index 272234d..57c25f0 100644 --- a/src/kernel/memory/vmm.tt +++ b/src/kernel/memory/vmm.tt @@ -82,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, 0); ASSERT_EQ_PTR(p1[0], 0x1234567890ABC000 | PAGE_PRESENT); } @@ -90,7 +90,7 @@ 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, 0); ASSERT_EQ_INT(retval, 0); } @@ -99,16 +99,34 @@ TEST(set_page_fails_if_PT_missing) BUILD_PT(0,0,0); 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, 0); ASSERT_NEQ_INT(retval, 0); } +TEST(set_page_does_not_fail_if_PT_missing_but_touch_flag_is_set) +{ + BUILD_PT(0,0,0); + p3[0] = (uint64_t)p2; + + int retval = vmm_set_page(P4, 0, 0x1234567890ABC000, PAGE_PRESENT, 1); + + ASSERT_EQ_INT(retval, 0); +} +TEST(set_page_makes_P3_if_PT_missing_but_touch_flag_is_set) +{ + BUILD_PT(0,0,0); + p3[0] = (uint64_t)p2; + + vmm_set_page(P4, 0, 0x1234567890ABC000, PAGE_PRESENT, 1); + + ASSERT_EQ_INT(p3[0] & PAGE_PRESENT, PAGE_PRESENT); +} TEST(set_page_sets_2mb_pages) { 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, 0); ASSERT_EQ_PTR(p2[3], 0x1234567890A00000 | PAGE_HUGE | PAGE_PRESENT); } @@ -116,7 +134,7 @@ 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, 0); ASSERT_NEQ_INT(retval, 0); }