diff options
author | Johannes Berg <johannes.berg@intel.com> | 2023-04-14 15:46:39 +0200 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2023-04-20 23:08:43 +0200 |
commit | 6032aca0deb9c138df122192f8ef02de1fdccf25 (patch) | |
tree | f9acfe2a2c09cfa1b3a86351b8bdf2ccd8fa48ef /arch | |
parent | fc54a4f15988e228cf88f888483e985c5f35031e (diff) |
um: make stub data pages size tweakable
There's a lot of code here that hard-codes that the
data is a single page, and right now that seems to
be sufficient, but to make it easier to change this
in the future, add a new STUB_DATA_PAGES constant
and use it throughout the code.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/um/include/shared/as-layout.h | 3 | ||||
-rw-r--r-- | arch/um/kernel/skas/clone.c | 5 | ||||
-rw-r--r-- | arch/um/kernel/skas/mmu.c | 6 | ||||
-rw-r--r-- | arch/um/kernel/um_arch.c | 10 | ||||
-rw-r--r-- | arch/um/os-Linux/skas/process.c | 6 | ||||
-rw-r--r-- | arch/x86/um/shared/sysdep/stub_32.h | 8 | ||||
-rw-r--r-- | arch/x86/um/shared/sysdep/stub_64.h | 8 | ||||
-rw-r--r-- | arch/x86/um/stub_segv.c | 2 |
8 files changed, 27 insertions, 21 deletions
diff --git a/arch/um/include/shared/as-layout.h b/arch/um/include/shared/as-layout.h index 9a0bd648d872..9ec3015bc5e2 100644 --- a/arch/um/include/shared/as-layout.h +++ b/arch/um/include/shared/as-layout.h @@ -23,7 +23,8 @@ #define STUB_START stub_start #define STUB_CODE STUB_START #define STUB_DATA (STUB_CODE + UM_KERN_PAGE_SIZE) -#define STUB_END (STUB_DATA + UM_KERN_PAGE_SIZE) +#define STUB_DATA_PAGES 1 /* must be a power of two */ +#define STUB_END (STUB_DATA + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE) #ifndef __ASSEMBLY__ diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c index ff5061f29167..62435187dda4 100644 --- a/arch/um/kernel/skas/clone.c +++ b/arch/um/kernel/skas/clone.c @@ -24,11 +24,12 @@ void __attribute__ ((__section__ (".__syscall_stub"))) stub_clone_handler(void) { - struct stub_data *data = get_stub_page(); + struct stub_data *data = get_stub_data(); long err; err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, - (unsigned long)data + UM_KERN_PAGE_SIZE / 2); + (unsigned long)data + + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE / 2); if (err) { data->parent_err = err; goto done; diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 125df465e8ea..656fe16c9b63 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -21,7 +21,7 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) unsigned long stack = 0; int ret = -ENOMEM; - stack = get_zeroed_page(GFP_KERNEL); + stack = __get_free_pages(GFP_KERNEL | __GFP_ZERO, ilog2(STUB_DATA_PAGES)); if (stack == 0) goto out; @@ -52,7 +52,7 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) out_free: if (to_mm->id.stack != 0) - free_page(to_mm->id.stack); + free_pages(to_mm->id.stack, ilog2(STUB_DATA_PAGES)); out: return ret; } @@ -74,6 +74,6 @@ void destroy_context(struct mm_struct *mm) } os_kill_ptraced_process(mmu->id.u.pid, 1); - free_page(mmu->id.stack); + free_pages(mmu->id.stack, ilog2(STUB_DATA_PAGES)); free_ldt(mmu); } diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 8dcda617b8bf..0a23a98d4ca0 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -326,9 +326,13 @@ int __init linux_main(int argc, char **argv) add_arg(DEFAULT_COMMAND_LINE_CONSOLE); host_task_size = os_get_top_address(); - /* reserve two pages for the stubs */ - host_task_size -= 2 * PAGE_SIZE; - stub_start = host_task_size; + /* reserve a few pages for the stubs (taking care of data alignment) */ + /* align the data portion */ + BUILD_BUG_ON(!is_power_of_2(STUB_DATA_PAGES)); + stub_start = (host_task_size - 1) & ~(STUB_DATA_PAGES * PAGE_SIZE - 1); + /* another page for the code portion */ + stub_start -= PAGE_SIZE; + host_task_size = stub_start; /* * TASK_SIZE needs to be PGDIR_SIZE aligned or else exit_mmap craps diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index b1ea53285af1..9464833e741a 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -262,7 +262,7 @@ static int userspace_tramp(void *stack) if (stack != NULL) { fd = phys_mapping(uml_to_phys(stack), &offset); addr = mmap((void *) STUB_DATA, - UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, offset); if (addr == MAP_FAILED) { printk(UM_KERN_ERR "mapping segfault stack at 0x%lx failed, errno = %d\n", @@ -277,7 +277,7 @@ static int userspace_tramp(void *stack) (unsigned long) stub_segv_handler - (unsigned long) __syscall_stub_start; - set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE); + set_sigstack((void *) STUB_DATA, STUB_DATA_PAGES * UM_KERN_PAGE_SIZE); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO; sa.sa_sigaction = (void *) v; @@ -515,7 +515,7 @@ static int __init init_thread_regs(void) thread_regs[REGS_IP_INDEX] = STUB_CODE + (unsigned long) stub_clone_handler - (unsigned long) __syscall_stub_start; - thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE - + thread_regs[REGS_SP_INDEX] = STUB_DATA + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - sizeof(void *); #ifdef __SIGNAL_FRAMESIZE thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE; diff --git a/arch/x86/um/shared/sysdep/stub_32.h b/arch/x86/um/shared/sysdep/stub_32.h index 4c6c2be0c899..38fa894b65d0 100644 --- a/arch/x86/um/shared/sysdep/stub_32.h +++ b/arch/x86/um/shared/sysdep/stub_32.h @@ -89,19 +89,19 @@ static inline void remap_stack_and_trap(void) "addl %4,%%ebx ; movl %%eax, (%%ebx) ;" "int $3" : : - "g" (~(UM_KERN_PAGE_SIZE - 1)), + "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1)), "g" (STUB_MMAP_NR), "g" (UML_STUB_FIELD_FD), "g" (UML_STUB_FIELD_OFFSET), "g" (UML_STUB_FIELD_CHILD_ERR), - "c" (UM_KERN_PAGE_SIZE), + "c" (STUB_DATA_PAGES * UM_KERN_PAGE_SIZE), "d" (PROT_READ | PROT_WRITE), "S" (MAP_FIXED | MAP_SHARED) : "memory"); } -static __always_inline void *get_stub_page(void) +static __always_inline void *get_stub_data(void) { unsigned long ret; @@ -109,7 +109,7 @@ static __always_inline void *get_stub_page(void) "movl %%esp,%0 ;" "andl %1,%0" : "=a" (ret) - : "g" (~(UM_KERN_PAGE_SIZE - 1))); + : "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1))); return (void *)ret; } diff --git a/arch/x86/um/shared/sysdep/stub_64.h b/arch/x86/um/shared/sysdep/stub_64.h index 92ea1670cf1c..2de1c8f88173 100644 --- a/arch/x86/um/shared/sysdep/stub_64.h +++ b/arch/x86/um/shared/sysdep/stub_64.h @@ -98,18 +98,18 @@ static inline void remap_stack_and_trap(void) "int3" : : "g" (STUB_MMAP_NR), - "g" (~(UM_KERN_PAGE_SIZE - 1)), + "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1)), "g" (MAP_FIXED | MAP_SHARED), "g" (UML_STUB_FIELD_FD), "g" (UML_STUB_FIELD_OFFSET), "g" (UML_STUB_FIELD_CHILD_ERR), - "S" (UM_KERN_PAGE_SIZE), + "S" (STUB_DATA_PAGES * UM_KERN_PAGE_SIZE), "d" (PROT_READ | PROT_WRITE) : __syscall_clobber, "r10", "r8", "r9"); } -static __always_inline void *get_stub_page(void) +static __always_inline void *get_stub_data(void) { unsigned long ret; @@ -117,7 +117,7 @@ static __always_inline void *get_stub_page(void) "movq %%rsp,%0 ;" "andq %1,%0" : "=a" (ret) - : "g" (~(UM_KERN_PAGE_SIZE - 1))); + : "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1))); return (void *)ret; } diff --git a/arch/x86/um/stub_segv.c b/arch/x86/um/stub_segv.c index f7eefba034f9..040668b989b5 100644 --- a/arch/x86/um/stub_segv.c +++ b/arch/x86/um/stub_segv.c @@ -11,7 +11,7 @@ void __attribute__ ((__section__ (".__syscall_stub"))) stub_segv_handler(int sig, siginfo_t *info, void *p) { - struct faultinfo *f = get_stub_page(); + struct faultinfo *f = get_stub_data(); ucontext_t *uc = p; GET_FAULTINFO_FROM_MC(*f, &uc->uc_mcontext); |