From f597ad1d4677b0d6b2c34d6166f9e4c8d865d617 Mon Sep 17 00:00:00 2001 From: Pawel Wieczorkiewicz Date: Sun, 27 Aug 2023 17:12:19 +0200 Subject: [PATCH] arch,entry,usermode: fix user pagetable mappings alignment The exception handlers as well as interrupt handlers need to be properly mapped into user pagetables. Add global symbols to find their addresses and align the beginning on a page boundary. Similar entry_usermode() and syscall_handler_entry() need to be aligned and ideally share the same page. The syscall_exit() and similar routines do not need user pagetable mappings. Add also an explicit mapping for user_cr3 variable. Signed-off-by: Pawel Wieczorkiewicz --- arch/x86/entry.S | 10 +++++++++- arch/x86/pagetables.c | 2 +- common/usermode.c | 17 +++++++++++++++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/arch/x86/entry.S b/arch/x86/entry.S index 16abb335..d2593d45 100644 --- a/arch/x86/entry.S +++ b/arch/x86/entry.S @@ -107,6 +107,8 @@ ENTRY(handle_exception) IRET END_FUNC(handle_exception) +.align PAGE_SIZE +GLOBAL(exception_handlers) exception_handler DE X86_EX_DE 0 exception_handler DB X86_EX_DB 0 exception_handler NMI X86_EX_NMI 0 @@ -129,14 +131,18 @@ exception_handler MC X86_EX_MC 0 exception_handler XM X86_EX_XM 0 exception_handler VE X86_EX_VE 0 exception_handler SE X86_EX_SE 1 +GLOBAL(end_exception_handlers) +GLOBAL(interrupt_handlers) interrupt_handler timer timer_interrupt_handler interrupt_handler uart uart_interrupt_handler interrupt_handler keyboard keyboard_interrupt_handler #ifdef KTF_ACPICA interrupt_handler acpi acpi_interrupt_handler #endif +GLOBAL(end_interrupt_handlers) +.align PAGE_SIZE ENTRY(syscall_exit) POPF @@ -157,6 +163,8 @@ ENTRY(terminate_user_task) ret END_FUNC(terminate_user_task) +.align PAGE_SIZE +GLOBAL(usermode_helpers) ENTRY(enter_usermode) /* FIXME: Add 32-bit support */ @@ -184,7 +192,6 @@ ENTRY(enter_usermode) IRET END_FUNC(enter_usermode) -.align PAGE_SIZE ENTRY(syscall_handler_entry) SAVE_CALLEE_SAVED_REGS syscall_from_usermode @@ -206,6 +213,7 @@ ENTRY(syscall_handler_entry) RESTORE_CALLEE_SAVED_REGS SYSRET END_FUNC(syscall_handler_entry) +GLOBAL(end_usermode_helpers) SECTION(.text.user, "ax", 16) ENTRY(usermode_stub) diff --git a/arch/x86/pagetables.c b/arch/x86/pagetables.c index fe03ec60..289a907f 100644 --- a/arch/x86/pagetables.c +++ b/arch/x86/pagetables.c @@ -30,7 +30,7 @@ #include #include -cr3_t cr3; +cr3_t __aligned(PAGE_SIZE) cr3; cr3_t user_cr3; static inline const char *dump_pte_flags(char *buf, size_t size, pte_t pte) { diff --git a/common/usermode.c b/common/usermode.c index a214d64a..7c97937b 100644 --- a/common/usermode.c +++ b/common/usermode.c @@ -28,6 +28,10 @@ #include #include +extern char exception_handlers[], end_exception_handlers[]; +extern char interrupt_handlers[], end_interrupt_handlers[]; +extern char usermode_helpers[], end_usermode_helpers[]; + long syscall_handler(long syscall_nr, long arg1, long arg2, long arg3, long arg4, long arg5) { switch (syscall_nr) { @@ -89,8 +93,17 @@ static void init_syscall(void) { void init_usermode(percpu_t *percpu) { vmap_user_4k(&cr3, virt_to_mfn(&cr3), L1_PROT); - vmap_user_4k(&enter_usermode, virt_to_mfn(&enter_usermode), L1_PROT); - vmap_user_4k(&syscall_handler_entry, virt_to_mfn(&syscall_handler_entry), L1_PROT); + vmap_user_4k(&user_cr3, virt_to_mfn(&user_cr3), L1_PROT); + + BUG_ON(end_exception_handlers - exception_handlers > (long) PAGE_SIZE); + vmap_user_4k(exception_handlers, virt_to_mfn(exception_handlers), L1_PROT); + + BUG_ON(end_interrupt_handlers - interrupt_handlers > (long) PAGE_SIZE); + vmap_user_4k(interrupt_handlers, virt_to_mfn(interrupt_handlers), L1_PROT); + + BUG_ON(end_usermode_helpers - usermode_helpers > (long) PAGE_SIZE); + vmap_user_4k(usermode_helpers, virt_to_mfn(usermode_helpers), L1_PROT); + init_syscall(); }