summaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/skas
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel/skas')
-rw-r--r--arch/um/kernel/skas/Makefile2
-rw-r--r--arch/um/kernel/skas/clone.c21
-rw-r--r--arch/um/kernel/skas/include/mmu-skas.h2
-rw-r--r--arch/um/kernel/skas/include/skas.h3
-rw-r--r--arch/um/kernel/skas/include/uaccess-skas.h10
-rw-r--r--arch/um/kernel/skas/mem.c2
-rw-r--r--arch/um/kernel/skas/mmu.c48
-rw-r--r--arch/um/kernel/skas/process.c17
-rw-r--r--arch/um/kernel/skas/process_kern.c2
-rw-r--r--arch/um/kernel/skas/uaccess.c8
-rw-r--r--arch/um/kernel/skas/util/Makefile5
-rw-r--r--arch/um/kernel/skas/util/mk_ptregs-i386.c49
-rw-r--r--arch/um/kernel/skas/util/mk_ptregs-x86_64.c66
13 files changed, 68 insertions, 167 deletions
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index db36c7c9594..8de471b59c1 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -6,8 +6,6 @@
obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
syscall.o tlb.o trap_user.o uaccess.o
-subdir- := util
-
USER_OBJS := process.o clone.o
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
index 4dc55f10cd1..cb37ce9124a 100644
--- a/arch/um/kernel/skas/clone.c
+++ b/arch/um/kernel/skas/clone.c
@@ -9,18 +9,24 @@
#include "stub-data.h"
#include "uml-config.h"
#include "sysdep/stub.h"
+#include "kern_constants.h"
/* This is in a separate file because it needs to be compiled with any
* extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled
+ *
+ * Use UM_KERN_PAGE_SIZE instead of PAGE_SIZE because that calls getpagesize
+ * on some systems.
*/
+
+#define STUB_DATA(field) (((struct stub_data *) UML_CONFIG_STUB_DATA)->field)
+
void __attribute__ ((__section__ (".__syscall_stub")))
stub_clone_handler(void)
{
long err;
- struct stub_data *from = (struct stub_data *) UML_CONFIG_STUB_DATA;
err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
- UML_CONFIG_STUB_DATA + PAGE_SIZE / 2 -
+ UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE / 2 -
sizeof(void *));
if(err != 0)
goto out;
@@ -30,15 +36,16 @@ stub_clone_handler(void)
goto out;
err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
- (long) &from->timer, 0);
+ (long) &STUB_DATA(timer), 0);
if(err)
goto out;
- err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, PAGE_SIZE,
- PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED,
- from->fd, from->offset);
+ err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA,
+ UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_SHARED, STUB_DATA(fd),
+ STUB_DATA(offset));
out:
/* save current result. Parent: pid; child: retcode of mmap */
- from->err = err;
+ STUB_DATA(err) = err;
trap_myself();
}
diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h
index 09536f81ee4..44110c521e4 100644
--- a/arch/um/kernel/skas/include/mmu-skas.h
+++ b/arch/um/kernel/skas/include/mmu-skas.h
@@ -8,6 +8,7 @@
#include "linux/config.h"
#include "mm_id.h"
+#include "asm/ldt.h"
struct mmu_context_skas {
struct mm_id id;
@@ -15,6 +16,7 @@ struct mmu_context_skas {
#ifdef CONFIG_3_LEVEL_PGTABLES
unsigned long last_pmd;
#endif
+ uml_ldt_t ldt;
};
extern void switch_mm_skas(struct mm_id * mm_idp);
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index 060934740f9..daa2f85b684 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -10,7 +10,8 @@
#include "sysdep/ptrace.h"
extern int userspace_pid[];
-extern int proc_mm, ptrace_faultinfo;
+extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
+extern int skas_needs_stub;
extern void switch_threads(void *me, void *next);
extern void thread_wait(void *sw, void *fb);
diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h
index 7da0c2def0e..f611f83ad4f 100644
--- a/arch/um/kernel/skas/include/uaccess-skas.h
+++ b/arch/um/kernel/skas/include/uaccess-skas.h
@@ -9,14 +9,8 @@
#include "asm/errno.h"
#include "asm/fixmap.h"
-#define access_ok_skas(type, addr, size) \
- ((segment_eq(get_fs(), KERNEL_DS)) || \
- (((unsigned long) (addr) < TASK_SIZE) && \
- ((unsigned long) (addr) + (size) <= TASK_SIZE)) || \
- ((type == VERIFY_READ ) && \
- ((unsigned long) (addr) >= FIXADDR_USER_START) && \
- ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
- ((unsigned long) (addr) + (size) >= (unsigned long)(addr))))
+/* No SKAS-specific checking. */
+#define access_ok_skas(type, addr, size) 0
extern int copy_from_user_skas(void *to, const void __user *from, int n);
extern int copy_to_user_skas(void __user *to, const void *from, int n);
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
index 147466d7ff4..88ab96c609c 100644
--- a/arch/um/kernel/skas/mem.c
+++ b/arch/um/kernel/skas/mem.c
@@ -20,7 +20,7 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
*task_size_out = CONFIG_HOST_TASK_SIZE;
#else
*host_size_out = top;
- if (proc_mm && ptrace_faultinfo)
+ if (!skas_needs_stub)
*task_size_out = top;
else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
#endif
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 240143b616a..677871f1b37 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -15,6 +15,7 @@
#include "asm/mmu.h"
#include "asm/pgalloc.h"
#include "asm/pgtable.h"
+#include "asm/ldt.h"
#include "os.h"
#include "skas.h"
@@ -28,7 +29,6 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
pmd_t *pmd;
pte_t *pte;
- spin_lock(&mm->page_table_lock);
pgd = pgd_offset(mm, proc);
pud = pud_alloc(mm, pgd, proc);
if (!pud)
@@ -63,7 +63,6 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
*pte = pte_mkexec(*pte);
*pte = pte_wrprotect(*pte);
- spin_unlock(&mm->page_table_lock);
return(0);
out_pmd:
@@ -71,19 +70,17 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
out_pte:
pmd_free(pmd);
out:
- spin_unlock(&mm->page_table_lock);
return(-ENOMEM);
}
int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
{
- struct mm_struct *cur_mm = current->mm;
- struct mm_id *cur_mm_id = &cur_mm->context.skas.id;
- struct mm_id *mm_id = &mm->context.skas.id;
+ struct mmu_context_skas *from_mm = NULL;
+ struct mmu_context_skas *to_mm = &mm->context.skas;
unsigned long stack = 0;
- int from, ret = -ENOMEM;
+ int from_fd, ret = -ENOMEM;
- if(!proc_mm || !ptrace_faultinfo){
+ if(skas_needs_stub){
stack = get_zeroed_page(GFP_KERNEL);
if(stack == 0)
goto out;
@@ -105,33 +102,43 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
mm->nr_ptes--;
}
- mm_id->stack = stack;
+
+ to_mm->id.stack = stack;
+ if(current->mm != NULL && current->mm != &init_mm)
+ from_mm = &current->mm->context.skas;
if(proc_mm){
- if((cur_mm != NULL) && (cur_mm != &init_mm))
- from = cur_mm_id->u.mm_fd;
- else from = -1;
+ if(from_mm)
+ from_fd = from_mm->id.u.mm_fd;
+ else from_fd = -1;
- ret = new_mm(from, stack);
+ ret = new_mm(from_fd, stack);
if(ret < 0){
printk("init_new_context_skas - new_mm failed, "
"errno = %d\n", ret);
goto out_free;
}
- mm_id->u.mm_fd = ret;
+ to_mm->id.u.mm_fd = ret;
}
else {
- if((cur_mm != NULL) && (cur_mm != &init_mm))
- mm_id->u.pid = copy_context_skas0(stack,
- cur_mm_id->u.pid);
- else mm_id->u.pid = start_userspace(stack);
+ if(from_mm)
+ to_mm->id.u.pid = copy_context_skas0(stack,
+ from_mm->id.u.pid);
+ else to_mm->id.u.pid = start_userspace(stack);
+ }
+
+ ret = init_new_ldt(to_mm, from_mm);
+ if(ret < 0){
+ printk("init_new_context_skas - init_ldt"
+ " failed, errno = %d\n", ret);
+ goto out_free;
}
return 0;
out_free:
- if(mm_id->stack != 0)
- free_page(mm_id->stack);
+ if(to_mm->id.stack != 0)
+ free_page(to_mm->id.stack);
out:
return ret;
}
@@ -147,6 +154,7 @@ void destroy_context_skas(struct mm_struct *mm)
if(!proc_mm || !ptrace_faultinfo){
free_page(mmu->id.stack);
+ pte_lock_deinit(virt_to_page(mmu->last_page_table));
pte_free_kernel((pte_t *) mmu->last_page_table);
dec_page_state(nr_page_table_pages);
#ifdef CONFIG_3_LEVEL_PGTABLES
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 5cd0e992978..599d679bd4f 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -69,6 +69,17 @@ void wait_stub_done(int pid, int sig, char * fname)
if((n < 0) || !WIFSTOPPED(status) ||
(WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
+ unsigned long regs[FRAME_SIZE];
+ if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+ printk("Failed to get registers from stub, "
+ "errno = %d\n", errno);
+ else {
+ int i;
+
+ printk("Stub registers -\n");
+ for(i = 0; i < FRAME_SIZE; i++)
+ printk("\t%d - %lx\n", i, regs[i]);
+ }
panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
"pid = %d, n = %d, errno = %d, status = 0x%x\n",
fname, pid, n, errno, status);
@@ -370,9 +381,9 @@ int copy_context_skas0(unsigned long new_stack, int pid)
}
/*
- * This is used only, if proc_mm is available, while PTRACE_FAULTINFO
- * isn't. Opening /proc/mm creates a new mm_context, which lacks the stub-pages
- * Thus, we map them using /proc/mm-fd
+ * This is used only, if stub pages are needed, while proc_mm is
+ * availabl. Opening /proc/mm creates a new mm_context, which lacks
+ * the stub-pages. Thus, we map them using /proc/mm-fd
*/
void map_stub_pages(int fd, unsigned long code,
unsigned long data, unsigned long stack)
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index efe92e8aa2a..9c990253966 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -145,7 +145,7 @@ int new_mm(int from, unsigned long stack)
"err = %d\n", -n);
}
- if(!ptrace_faultinfo)
+ if(skas_needs_stub)
map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
return(fd);
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 75195281081..a5a47528dec 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -143,7 +143,7 @@ int copy_from_user_skas(void *to, const void __user *from, int n)
return(0);
}
- return(access_ok_skas(VERIFY_READ, from, n) ?
+ return(access_ok(VERIFY_READ, from, n) ?
buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to):
n);
}
@@ -164,7 +164,7 @@ int copy_to_user_skas(void __user *to, const void *from, int n)
return(0);
}
- return(access_ok_skas(VERIFY_WRITE, to, n) ?
+ return(access_ok(VERIFY_WRITE, to, n) ?
buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) :
n);
}
@@ -193,7 +193,7 @@ int strncpy_from_user_skas(char *dst, const char __user *src, int count)
return(strnlen(dst, count));
}
- if(!access_ok_skas(VERIFY_READ, src, 1))
+ if(!access_ok(VERIFY_READ, src, 1))
return(-EFAULT);
n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user,
@@ -221,7 +221,7 @@ int clear_user_skas(void __user *mem, int len)
return(0);
}
- return(access_ok_skas(VERIFY_WRITE, mem, len) ?
+ return(access_ok(VERIFY_WRITE, mem, len) ?
buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len);
}
diff --git a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile
deleted file mode 100644
index f7b7eba8334..00000000000
--- a/arch/um/kernel/skas/util/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-hostprogs-y := mk_ptregs
-always := $(hostprogs-y)
-
-mk_ptregs-objs := mk_ptregs-$(SUBARCH).o
-HOSTCFLAGS_mk_ptregs-$(SUBARCH).o := -I$(objtree)/arch/um
diff --git a/arch/um/kernel/skas/util/mk_ptregs-i386.c b/arch/um/kernel/skas/util/mk_ptregs-i386.c
deleted file mode 100644
index 1f96e1eeb8a..00000000000
--- a/arch/um/kernel/skas/util/mk_ptregs-i386.c
+++ /dev/null
@@ -1,49 +0,0 @@
-#include <stdio.h>
-#include <user-offsets.h>
-
-#define SHOW(name) printf("#define %s %d\n", #name, name)
-
-int main(int argc, char **argv)
-{
- printf("/* Automatically generated by "
- "arch/um/kernel/skas/util/mk_ptregs */\n");
- printf("\n");
- printf("#ifndef __SKAS_PT_REGS_\n");
- printf("#define __SKAS_PT_REGS_\n");
- printf("\n");
- SHOW(HOST_FRAME_SIZE);
- SHOW(HOST_FP_SIZE);
- SHOW(HOST_XFP_SIZE);
-
- SHOW(HOST_IP);
- SHOW(HOST_SP);
- SHOW(HOST_EFLAGS);
- SHOW(HOST_EAX);
- SHOW(HOST_EBX);
- SHOW(HOST_ECX);
- SHOW(HOST_EDX);
- SHOW(HOST_ESI);
- SHOW(HOST_EDI);
- SHOW(HOST_EBP);
- SHOW(HOST_CS);
- SHOW(HOST_SS);
- SHOW(HOST_DS);
- SHOW(HOST_FS);
- SHOW(HOST_ES);
- SHOW(HOST_GS);
-
- printf("\n");
- printf("#endif\n");
- return(0);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c
deleted file mode 100644
index 5fccbfe35f7..00000000000
--- a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <user-offsets.h>
-
-#define SHOW(name) \
- printf("#define %s (%d / sizeof(unsigned long))\n", #name, name)
-
-int main(int argc, char **argv)
-{
- printf("/* Automatically generated by "
- "arch/um/kernel/skas/util/mk_ptregs */\n");
- printf("\n");
- printf("#ifndef __SKAS_PT_REGS_\n");
- printf("#define __SKAS_PT_REGS_\n");
- SHOW(HOST_FRAME_SIZE);
- SHOW(HOST_RBX);
- SHOW(HOST_RCX);
- SHOW(HOST_RDI);
- SHOW(HOST_RSI);
- SHOW(HOST_RDX);
- SHOW(HOST_RBP);
- SHOW(HOST_RAX);
- SHOW(HOST_R8);
- SHOW(HOST_R9);
- SHOW(HOST_R10);
- SHOW(HOST_R11);
- SHOW(HOST_R12);
- SHOW(HOST_R13);
- SHOW(HOST_R14);
- SHOW(HOST_R15);
- SHOW(HOST_ORIG_RAX);
- SHOW(HOST_CS);
- SHOW(HOST_SS);
- SHOW(HOST_EFLAGS);
-#if 0
- SHOW(HOST_FS);
- SHOW(HOST_GS);
- SHOW(HOST_DS);
- SHOW(HOST_ES);
-#endif
-
- SHOW(HOST_IP);
- SHOW(HOST_SP);
- printf("#define HOST_FP_SIZE 0\n");
- printf("#define HOST_XFP_SIZE 0\n");
- printf("\n");
- printf("\n");
- printf("#endif\n");
- return(0);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */