uml: eliminate setjmp_wrapper
authorJeff Dike <jdike@addtoit.com>
Tue, 5 Feb 2008 06:31:07 +0000 (22:31 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 5 Feb 2008 17:44:29 +0000 (09:44 -0800)
setjmp_wrapper existed to provide setjmp to kernel code when UML used libc's
setjmp and longjmp.  Now that UML has its own implementation, this isn't
needed and kernel code can invoke setjmp directly.

do_buffer_op is massively cleaned up since it is no longer a callback from
setjmp_wrapper and given a va_list from which it must extract its arguments.

The actual setjmp is moved from buffer_op to do_op_one_page because the copy
operation is inside an atomic section (kmap_atomic to kunmap_atomic) and it
shouldn't be longjmp-ed out of.

Signed-off-by: Jeff Dike <jdike@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/um/include/os.h
arch/um/kernel/skas/uaccess.c
arch/um/os-Linux/util.c

index daaafc8824b08078f451a23ee13464b1e17e8fad..c8684b678eebf52a8a65f77f7d9afe0abf41dbe3 100644 (file)
@@ -235,7 +235,6 @@ extern void stack_protections(unsigned long address);
 extern int raw(int fd);
 extern void setup_machinename(char *machine_out);
 extern void setup_hostinfo(char *buf, int len);
-extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
 extern void os_dump_core(void) __attribute__ ((noreturn));
 
 /* time.c */
index 05b41dbc1dd98620292912689cddbce551cb492b..e22c96993db3b07545e107adb57f2ef1d8ddb608 100644 (file)
@@ -58,9 +58,10 @@ static pte_t *maybe_map(unsigned long virt, int is_write)
 static int do_op_one_page(unsigned long addr, int len, int is_write,
                 int (*op)(unsigned long addr, int len, void *arg), void *arg)
 {
+       jmp_buf buf;
        struct page *page;
        pte_t *pte;
-       int n;
+       int n, faulted;
 
        pte = maybe_map(addr, is_write);
        if (pte == NULL)
@@ -70,82 +71,62 @@ static int do_op_one_page(unsigned long addr, int len, int is_write,
        addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) +
                (addr & ~PAGE_MASK);
 
-       n = (*op)(addr, len, arg);
+       current->thread.fault_catcher = &buf;
+
+       faulted = UML_SETJMP(&buf);
+       if (faulted == 0)
+               n = (*op)(addr, len, arg);
+       else
+               n = -1;
+
+       current->thread.fault_catcher = NULL;
 
        kunmap_atomic(page, KM_UML_USERCOPY);
 
        return n;
 }
 
-static void do_buffer_op(void *jmpbuf, void *arg_ptr)
+static int buffer_op(unsigned long addr, int len, int is_write,
+                    int (*op)(unsigned long, int, void *), void *arg)
 {
-       va_list args;
-       unsigned long addr;
-       int len, is_write, size, remain, n;
-       int (*op)(unsigned long, int, void *);
-       void *arg;
-       int *res;
-
-       va_copy(args, *(va_list *)arg_ptr);
-       addr = va_arg(args, unsigned long);
-       len = va_arg(args, int);
-       is_write = va_arg(args, int);
-       op = va_arg(args, void *);
-       arg = va_arg(args, void *);
-       res = va_arg(args, int *);
-       va_end(args);
+       int size, remain, n;
+
        size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
        remain = len;
 
-       current->thread.fault_catcher = jmpbuf;
        n = do_op_one_page(addr, size, is_write, op, arg);
        if (n != 0) {
-               *res = (n < 0 ? remain : 0);
+               remain = (n < 0 ? remain : 0);
                goto out;
        }
 
        addr += size;
        remain -= size;
-       if (remain == 0) {
-               *res = 0;
+       if (remain == 0)
                goto out;
-       }
 
-       while(addr < ((addr + remain) & PAGE_MASK)) {
+       while (addr < ((addr + remain) & PAGE_MASK)) {
                n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg);
                if (n != 0) {
-                       *res = (n < 0 ? remain : 0);
+                       remain = (n < 0 ? remain : 0);
                        goto out;
                }
 
                addr += PAGE_SIZE;
                remain -= PAGE_SIZE;
        }
-       if (remain == 0) {
-               *res = 0;
+       if (remain == 0)
                goto out;
-       }
 
        n = do_op_one_page(addr, remain, is_write, op, arg);
-       if (n != 0)
-               *res = (n < 0 ? remain : 0);
-       else *res = 0;
- out:
-       current->thread.fault_catcher = NULL;
-}
-
-static int buffer_op(unsigned long addr, int len, int is_write,
-                    int (*op)(unsigned long addr, int len, void *arg),
-                    void *arg)
-{
-       int faulted, res;
-
-       faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg,
-                                &res);
-       if (!faulted)
-               return res;
+       if (n != 0) {
+               remain = (n < 0 ? remain : 0);
+               goto out;
+       }
 
-       return addr + len - (unsigned long) current->thread.fault_addr;
+       return 0;
+ out:
+       return remain;
 }
 
 static int copy_chunk_from_user(unsigned long from, int len, void *arg)
index 3e058ce9ffb6cd044a8fbf5ff33883b46b649348..a6f31d476993cd0314c8c6adbf9dad0c7c796f15 100644 (file)
@@ -88,21 +88,6 @@ void setup_hostinfo(char *buf, int len)
                 host.release, host.version, host.machine);
 }
 
-int setjmp_wrapper(void (*proc)(void *, void *), ...)
-{
-       va_list args;
-       jmp_buf buf;
-       int n;
-
-       n = UML_SETJMP(&buf);
-       if(n == 0){
-               va_start(args, proc);
-               (*proc)(&buf, &args);
-       }
-       va_end(args);
-       return n;
-}
-
 void os_dump_core(void)
 {
        int pid;