Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Johannes Berg and committed by
Richard Weinberger
6032aca0 fc54a4f1

+27 -21
+2 -1
arch/um/include/shared/as-layout.h
··· 23 23 #define STUB_START stub_start 24 24 #define STUB_CODE STUB_START 25 25 #define STUB_DATA (STUB_CODE + UM_KERN_PAGE_SIZE) 26 - #define STUB_END (STUB_DATA + UM_KERN_PAGE_SIZE) 26 + #define STUB_DATA_PAGES 1 /* must be a power of two */ 27 + #define STUB_END (STUB_DATA + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE) 27 28 28 29 #ifndef __ASSEMBLY__ 29 30
+3 -2
arch/um/kernel/skas/clone.c
··· 24 24 void __attribute__ ((__section__ (".__syscall_stub"))) 25 25 stub_clone_handler(void) 26 26 { 27 - struct stub_data *data = get_stub_page(); 27 + struct stub_data *data = get_stub_data(); 28 28 long err; 29 29 30 30 err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, 31 - (unsigned long)data + UM_KERN_PAGE_SIZE / 2); 31 + (unsigned long)data + 32 + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE / 2); 32 33 if (err) { 33 34 data->parent_err = err; 34 35 goto done;
+3 -3
arch/um/kernel/skas/mmu.c
··· 21 21 unsigned long stack = 0; 22 22 int ret = -ENOMEM; 23 23 24 - stack = get_zeroed_page(GFP_KERNEL); 24 + stack = __get_free_pages(GFP_KERNEL | __GFP_ZERO, ilog2(STUB_DATA_PAGES)); 25 25 if (stack == 0) 26 26 goto out; 27 27 ··· 52 52 53 53 out_free: 54 54 if (to_mm->id.stack != 0) 55 - free_page(to_mm->id.stack); 55 + free_pages(to_mm->id.stack, ilog2(STUB_DATA_PAGES)); 56 56 out: 57 57 return ret; 58 58 } ··· 74 74 } 75 75 os_kill_ptraced_process(mmu->id.u.pid, 1); 76 76 77 - free_page(mmu->id.stack); 77 + free_pages(mmu->id.stack, ilog2(STUB_DATA_PAGES)); 78 78 free_ldt(mmu); 79 79 }
+7 -3
arch/um/kernel/um_arch.c
··· 326 326 add_arg(DEFAULT_COMMAND_LINE_CONSOLE); 327 327 328 328 host_task_size = os_get_top_address(); 329 - /* reserve two pages for the stubs */ 330 - host_task_size -= 2 * PAGE_SIZE; 331 - stub_start = host_task_size; 329 + /* reserve a few pages for the stubs (taking care of data alignment) */ 330 + /* align the data portion */ 331 + BUILD_BUG_ON(!is_power_of_2(STUB_DATA_PAGES)); 332 + stub_start = (host_task_size - 1) & ~(STUB_DATA_PAGES * PAGE_SIZE - 1); 333 + /* another page for the code portion */ 334 + stub_start -= PAGE_SIZE; 335 + host_task_size = stub_start; 332 336 333 337 /* 334 338 * TASK_SIZE needs to be PGDIR_SIZE aligned or else exit_mmap craps
+3 -3
arch/um/os-Linux/skas/process.c
··· 262 262 if (stack != NULL) { 263 263 fd = phys_mapping(uml_to_phys(stack), &offset); 264 264 addr = mmap((void *) STUB_DATA, 265 - UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, 265 + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, 266 266 MAP_FIXED | MAP_SHARED, fd, offset); 267 267 if (addr == MAP_FAILED) { 268 268 printk(UM_KERN_ERR "mapping segfault stack at 0x%lx failed, errno = %d\n", ··· 277 277 (unsigned long) stub_segv_handler - 278 278 (unsigned long) __syscall_stub_start; 279 279 280 - set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE); 280 + set_sigstack((void *) STUB_DATA, STUB_DATA_PAGES * UM_KERN_PAGE_SIZE); 281 281 sigemptyset(&sa.sa_mask); 282 282 sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO; 283 283 sa.sa_sigaction = (void *) v; ··· 515 515 thread_regs[REGS_IP_INDEX] = STUB_CODE + 516 516 (unsigned long) stub_clone_handler - 517 517 (unsigned long) __syscall_stub_start; 518 - thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE - 518 + thread_regs[REGS_SP_INDEX] = STUB_DATA + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 519 519 sizeof(void *); 520 520 #ifdef __SIGNAL_FRAMESIZE 521 521 thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
+4 -4
arch/x86/um/shared/sysdep/stub_32.h
··· 89 89 "addl %4,%%ebx ; movl %%eax, (%%ebx) ;" 90 90 "int $3" 91 91 : : 92 - "g" (~(UM_KERN_PAGE_SIZE - 1)), 92 + "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1)), 93 93 "g" (STUB_MMAP_NR), 94 94 "g" (UML_STUB_FIELD_FD), 95 95 "g" (UML_STUB_FIELD_OFFSET), 96 96 "g" (UML_STUB_FIELD_CHILD_ERR), 97 - "c" (UM_KERN_PAGE_SIZE), 97 + "c" (STUB_DATA_PAGES * UM_KERN_PAGE_SIZE), 98 98 "d" (PROT_READ | PROT_WRITE), 99 99 "S" (MAP_FIXED | MAP_SHARED) 100 100 : 101 101 "memory"); 102 102 } 103 103 104 - static __always_inline void *get_stub_page(void) 104 + static __always_inline void *get_stub_data(void) 105 105 { 106 106 unsigned long ret; 107 107 ··· 109 109 "movl %%esp,%0 ;" 110 110 "andl %1,%0" 111 111 : "=a" (ret) 112 - : "g" (~(UM_KERN_PAGE_SIZE - 1))); 112 + : "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1))); 113 113 114 114 return (void *)ret; 115 115 }
+4 -4
arch/x86/um/shared/sysdep/stub_64.h
··· 98 98 "int3" 99 99 : : 100 100 "g" (STUB_MMAP_NR), 101 - "g" (~(UM_KERN_PAGE_SIZE - 1)), 101 + "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1)), 102 102 "g" (MAP_FIXED | MAP_SHARED), 103 103 "g" (UML_STUB_FIELD_FD), 104 104 "g" (UML_STUB_FIELD_OFFSET), 105 105 "g" (UML_STUB_FIELD_CHILD_ERR), 106 - "S" (UM_KERN_PAGE_SIZE), 106 + "S" (STUB_DATA_PAGES * UM_KERN_PAGE_SIZE), 107 107 "d" (PROT_READ | PROT_WRITE) 108 108 : 109 109 __syscall_clobber, "r10", "r8", "r9"); 110 110 } 111 111 112 - static __always_inline void *get_stub_page(void) 112 + static __always_inline void *get_stub_data(void) 113 113 { 114 114 unsigned long ret; 115 115 ··· 117 117 "movq %%rsp,%0 ;" 118 118 "andq %1,%0" 119 119 : "=a" (ret) 120 - : "g" (~(UM_KERN_PAGE_SIZE - 1))); 120 + : "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1))); 121 121 122 122 return (void *)ret; 123 123 }
+1 -1
arch/x86/um/stub_segv.c
··· 11 11 void __attribute__ ((__section__ (".__syscall_stub"))) 12 12 stub_segv_handler(int sig, siginfo_t *info, void *p) 13 13 { 14 - struct faultinfo *f = get_stub_page(); 14 + struct faultinfo *f = get_stub_data(); 15 15 ucontext_t *uc = p; 16 16 17 17 GET_FAULTINFO_FROM_MC(*f, &uc->uc_mcontext);