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, faulted; pte = maybe_map(addr, is_write); if (pte == NULL) return -1; page = pte_page(*pte); addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + (addr & ~PAGE_MASK); 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; }
int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr) { jmp_buf buf; int n; *jmp_ptr = &buf; n = UML_SETJMP(&buf); if (n != 0) return n; (*fn)(arg); return 0; }
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; }
int __do_strnlen_user(const char *str, unsigned long n, void **fault_addr, void **fault_catcher) { struct tt_regs save = TASK_REGS(get_current())->tt; int ret; unsigned long *faddrp = (unsigned long *)fault_addr; jmp_buf jbuf; *fault_catcher = &jbuf; if(UML_SETJMP(&jbuf) == 0) ret = strlen(str) + 1; else ret = *faddrp - (unsigned long) str; *fault_addr = NULL; *fault_catcher = NULL; TASK_REGS(get_current())->tt = save; return ret; }
unsigned long __do_user_copy(void *to, const void *from, int n, void **fault_addr, jmp_buf **fault_catcher, void (*op)(void *to, const void *from, int n), int *faulted_out) { unsigned long *faddrp = (unsigned long *) fault_addr, ret; jmp_buf jbuf; *fault_catcher = &jbuf; if (UML_SETJMP(&jbuf) == 0) { (*op)(to, from, n); ret = 0; *faulted_out = 0; } else { ret = *faddrp; *faulted_out = 1; } *fault_addr = NULL; *fault_catcher = NULL; return ret; }