From c56004901fa5dcf55f92318f192ab3c0e87db2d1 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 3 Sep 2005 15:57:36 -0700 Subject: [PATCH] uml: TLB operation batching This adds VM op batching to skas0. Rather than having a context switch to and from the userspace stub for each address space change, we write a number of operations to the stub data page and invoke a different stub which loops over them and executes them all in one go. The operations are stored as [ system call number, arg1, arg2, ... ] tuples. The set is terminated by a system call number of 0. Single operations, i.e. page faults, are handled in the old way, since that is slightly more efficient. For a kernel build, a minority (~1/4) of the operations are part of a set. These sets averaged ~100 in length, so for this quarter, the context switching overhead is greatly reduced. Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/skas/tlb.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'arch/um/kernel/skas/tlb.c') diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c index 6230999c672..4b5fd204954 100644 --- a/arch/um/kernel/skas/tlb.c +++ b/arch/um/kernel/skas/tlb.c @@ -18,7 +18,8 @@ #include "os.h" #include "tlb.h" -static void do_ops(union mm_context *mmu, struct host_vm_op *ops, int last) +static void *do_ops(union mm_context *mmu, struct host_vm_op *ops, int last, + int finished, void *flush) { struct host_vm_op *op; int i; @@ -27,24 +28,28 @@ static void do_ops(union mm_context *mmu, struct host_vm_op *ops, int last) op = &ops[i]; switch(op->type){ case MMAP: - map(&mmu->skas.id, op->u.mmap.addr, op->u.mmap.len, - op->u.mmap.r, op->u.mmap.w, op->u.mmap.x, - op->u.mmap.fd, op->u.mmap.offset); + flush = map(&mmu->skas.id, op->u.mmap.addr, + op->u.mmap.len, op->u.mmap.r, op->u.mmap.w, + op->u.mmap.x, op->u.mmap.fd, + op->u.mmap.offset, finished, flush); break; case MUNMAP: - unmap(&mmu->skas.id, (void *) op->u.munmap.addr, - op->u.munmap.len); + flush = unmap(&mmu->skas.id, (void *) op->u.munmap.addr, + op->u.munmap.len, finished, flush); break; case MPROTECT: - protect(&mmu->skas.id, op->u.mprotect.addr, - op->u.mprotect.len, op->u.mprotect.r, - op->u.mprotect.w, op->u.mprotect.x); + flush = protect(&mmu->skas.id, op->u.mprotect.addr, + op->u.mprotect.len, op->u.mprotect.r, + op->u.mprotect.w, op->u.mprotect.x, + finished, flush); break; default: printk("Unknown op type %d in do_ops\n", op->type); break; } } + + return flush; } extern int proc_mm; -- cgit v1.2.3 From 07bf731e4b95d7c9ea9dbacd1fc4a041120dfffb Mon Sep 17 00:00:00 2001 From: Bodo Stroesser Date: Sat, 3 Sep 2005 15:57:50 -0700 Subject: [PATCH] uml: skas0 stubs now check system call return values Change syscall-stub's data to include a "expected retval". Stub now checks syscalls retval and aborts execution of syscall list, if retval != expected retval. run_syscall_stub prints the data of the failed syscall, using the data pointer and retval written by the stub to the beginning of the stack. one_syscall_stub is removed, to simplify code, because only some instructions are saved by one_syscall_stub, no host-syscall. Using the stub with additional data (modify_ldt via stub) is prepared also. Signed-off-by: Bodo Stroesser Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/skas/tlb.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'arch/um/kernel/skas/tlb.c') diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c index 4b5fd204954..6e84963dfc2 100644 --- a/arch/um/kernel/skas/tlb.c +++ b/arch/um/kernel/skas/tlb.c @@ -18,30 +18,31 @@ #include "os.h" #include "tlb.h" -static void *do_ops(union mm_context *mmu, struct host_vm_op *ops, int last, - int finished, void *flush) +static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last, + int finished, void **flush) { struct host_vm_op *op; - int i; + int i, ret = 0; - for(i = 0; i <= last; i++){ + for(i = 0; i <= last && !ret; i++){ op = &ops[i]; switch(op->type){ case MMAP: - flush = map(&mmu->skas.id, op->u.mmap.addr, - op->u.mmap.len, op->u.mmap.r, op->u.mmap.w, - op->u.mmap.x, op->u.mmap.fd, - op->u.mmap.offset, finished, flush); + ret = map(&mmu->skas.id, op->u.mmap.addr, + op->u.mmap.len, op->u.mmap.r, op->u.mmap.w, + op->u.mmap.x, op->u.mmap.fd, + op->u.mmap.offset, finished, flush); break; case MUNMAP: - flush = unmap(&mmu->skas.id, (void *) op->u.munmap.addr, - op->u.munmap.len, finished, flush); + ret = unmap(&mmu->skas.id, + (void *) op->u.munmap.addr, + op->u.munmap.len, finished, flush); break; case MPROTECT: - flush = protect(&mmu->skas.id, op->u.mprotect.addr, - op->u.mprotect.len, op->u.mprotect.r, - op->u.mprotect.w, op->u.mprotect.x, - finished, flush); + ret = protect(&mmu->skas.id, op->u.mprotect.addr, + op->u.mprotect.len, op->u.mprotect.r, + op->u.mprotect.w, op->u.mprotect.x, + finished, flush); break; default: printk("Unknown op type %d in do_ops\n", op->type); @@ -49,7 +50,7 @@ static void *do_ops(union mm_context *mmu, struct host_vm_op *ops, int last, } } - return flush; + return ret; } extern int proc_mm; -- cgit v1.2.3