]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
um: make stub data pages size tweakable
authorJohannes Berg <johannes.berg@intel.com>
Fri, 14 Apr 2023 13:46:39 +0000 (15:46 +0200)
committerRichard Weinberger <richard@nod.at>
Thu, 20 Apr 2023 21:08:43 +0000 (23:08 +0200)
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>
arch/um/include/shared/as-layout.h
arch/um/kernel/skas/clone.c
arch/um/kernel/skas/mmu.c
arch/um/kernel/um_arch.c
arch/um/os-Linux/skas/process.c
arch/x86/um/shared/sysdep/stub_32.h
arch/x86/um/shared/sysdep/stub_64.h
arch/x86/um/stub_segv.c

index 9a0bd648d8723588d6aa21323f4f815d4e480726..9ec3015bc5e2e2c74dfcf7f615bcd37c4cc5e47b 100644 (file)
@@ -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__
 
index ff5061f291674913e08c100fb21d31cd2d8bcd0a..62435187dda4840183f5e6bc42277340ba3afd30 100644 (file)
 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;
index 125df465e8ea4feb89c730b4f80e768c2f9d0fb7..656fe16c9b6338c46afda6e5a45da2865c2661af 100644 (file)
@@ -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);
 }
index 8dcda617b8bf6d4734f3bbf0a6a1009aaaf896ee..0a23a98d4ca0a74fc5825f68df9a2cea1510fe00 100644 (file)
@@ -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
index b1ea53285af1ba9f80d5dd95d568c9b35d3a7f50..9464833e741af3370d6d8910071e1b7e0905c8ac 100644 (file)
@@ -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;
index 4c6c2be0c899775b6480deb641ac01faf18d94f9..38fa894b65d088970f99a9ca7ad6bfeb7895462c 100644 (file)
@@ -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;
 }
index 92ea1670cf1c8b1df7dc0ff0cfe77886cb2759db..2de1c8f8817341f7447ed72ccc5010f5faed5686 100644 (file)
@@ -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;
 }
index f7eefba034f96bf1e1379742ad0bf504dd0e88cb..040668b989b5c519e68dc21afcf9d4ae59466933 100644 (file)
@@ -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);