Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pagetables: allow user and kernel maps in same pgd #296

Merged
merged 1 commit into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions arch/x86/pagetables.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,26 @@ static mfn_t get_cr3_mfn(cr3_t *cr3_entry) {
return cr3_entry->mfn;
}

static inline void pgentry_fixup_flags(pgentry_t *entry, unsigned long flags) {
/* Our new flags may take precedence over previous ones if the new ones are more
* permissive. */
unsigned long entry_new = *entry;
entry_new |= flags & _PAGE_USER; /* USER may result in crash if we enabled SMAP */
entry_new |= flags & _PAGE_RW;
entry_new &= ~(flags & _PAGE_NX);
if (unlikely(*entry != entry_new)) {
char flags_str_old[16];
char flags_str_new[16];
printk("WARNING: Already-present PTE protection flags conflicts with our.\n"
" Updating present flags: %s -> %s\n",
dump_pte_flags(flags_str_old, 16, (pte_t) *entry),
dump_pte_flags(flags_str_new, 16, (pte_t) entry_new));
*entry = entry_new;
barrier();
flush_tlb();
}
}

static mfn_t get_pgentry_mfn(mfn_t tab_mfn, pt_index_t index, unsigned long flags) {
pgentry_t *tab, *entry;
mfn_t mfn;
Expand All @@ -147,6 +167,10 @@ static mfn_t get_pgentry_mfn(mfn_t tab_mfn, pt_index_t index, unsigned long flag
tab = init_map_mfn(mfn);
memset(tab, 0, PAGE_SIZE);
}
else {
sktt marked this conversation as resolved.
Show resolved Hide resolved
sktt marked this conversation as resolved.
Show resolved Hide resolved
/* Page table already exists but its flags may conflict with our. Maybe fixup */
pgentry_fixup_flags(entry, flags);
}

return mfn;
}
Expand Down
18 changes: 17 additions & 1 deletion tests/unittests.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <test.h>
#include <usermode.h>

#include <mm/pmm.h>
#include <smp/smp.h>

static char opt_string[4];
Expand Down Expand Up @@ -109,6 +110,12 @@ static unsigned long __user_text test_user_task_func3(void *arg) {
return -16;
}

#define HIGH_USER_PTR _ptr(0xffffffff80222000)
static unsigned long __user_text test_user_task_func4(void *arg) {
printf(USTR("access: %lx\n"), _ul(HIGH_USER_PTR));
return *(unsigned long *) HIGH_USER_PTR;
}

int unit_tests(void *_unused) {
printk("\nLet the UNITTESTs begin\n");
printk("Commandline parsing: %s\n", kernel_cmdline);
Expand Down Expand Up @@ -178,7 +185,7 @@ int unit_tests(void *_unused) {
cpu_freq_expect("Prototyp Amazing Foo Two @ 1.00GHz", 1000000000);

task_t *task1, *task2, *task_user1, *task_user1_se, *task_user1_int80, *task_user2,
*task_user3;
*task_user3, *task_user4;

task1 = new_kernel_task("test1", test_kernel_task_func, _ptr(98));
task2 = new_kernel_task("test2", test_kernel_task_func, _ptr(-99));
Expand All @@ -189,6 +196,14 @@ int unit_tests(void *_unused) {
new_user_task("test1 user int80", test_user_task_func1_int80, NULL);
task_user2 = new_user_task("test2 user", test_user_task_func2, NULL);
task_user3 = new_user_task("test3 user", test_user_task_func3, NULL);
task_user4 = new_user_task("test4 user", test_user_task_func4, NULL);

vmap_4k(HIGH_USER_PTR + 0x1000, get_free_frame()->mfn, L1_PROT);
memset(HIGH_USER_PTR + 0x1000, 0, 0x1000);
vmap_user_4k(HIGH_USER_PTR, get_free_frame()->mfn, L1_PROT_USER);
sktt marked this conversation as resolved.
Show resolved Hide resolved

/* Be sure that we can still touch this vmap despite the user vmap. */
BUG_ON(*(unsigned long *) (HIGH_USER_PTR + 0x1000) != 0);

set_task_repeat(task1, 10);
schedule_task(task1, get_bsp_cpu());
Expand All @@ -198,6 +213,7 @@ int unit_tests(void *_unused) {
schedule_task(task_user1_int80, get_bsp_cpu());
schedule_task(task_user2, get_cpu(1));
schedule_task(task_user3, get_bsp_cpu());
schedule_task(task_user4, get_cpu(1));

printk("Long mode to real mode transition:\n");
long_to_real();
Expand Down