aboutsummaryrefslogtreecommitdiff
path: root/arch/um/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/Makefile7
-rw-r--r--arch/um/kernel/dyn.lds.S2
-rw-r--r--arch/um/kernel/exec.c58
-rw-r--r--arch/um/kernel/init_task.c13
-rw-r--r--arch/um/kernel/irq.c113
-rw-r--r--arch/um/kernel/ksyms.c41
-rw-r--r--arch/um/kernel/mem.c2
-rw-r--r--arch/um/kernel/physmem.c69
-rw-r--r--arch/um/kernel/process.c226
-rw-r--r--arch/um/kernel/ptrace.c141
-rw-r--r--arch/um/kernel/reboot.c57
-rw-r--r--arch/um/kernel/signal.c59
-rw-r--r--arch/um/kernel/skas/Makefile4
-rw-r--r--arch/um/kernel/skas/clone.c6
-rw-r--r--arch/um/kernel/skas/exec.c40
-rw-r--r--arch/um/kernel/skas/mem.c22
-rw-r--r--arch/um/kernel/skas/mmu.c81
-rw-r--r--arch/um/kernel/skas/process.c187
-rw-r--r--arch/um/kernel/skas/syscall.c21
-rw-r--r--arch/um/kernel/skas/tlb.c164
-rw-r--r--arch/um/kernel/skas/uaccess.c146
-rw-r--r--arch/um/kernel/smp.c36
-rw-r--r--arch/um/kernel/syscall.c40
-rw-r--r--arch/um/kernel/time.c223
-rw-r--r--arch/um/kernel/tlb.c418
-rw-r--r--arch/um/kernel/trap.c129
-rw-r--r--arch/um/kernel/tt/Makefile14
-rw-r--r--arch/um/kernel/tt/exec_kern.c84
-rw-r--r--arch/um/kernel/tt/exec_user.c56
-rw-r--r--arch/um/kernel/tt/gdb.c280
-rw-r--r--arch/um/kernel/tt/gdb_kern.c40
-rw-r--r--arch/um/kernel/tt/include/mode-tt.h34
-rw-r--r--arch/um/kernel/tt/ksyms.c29
-rw-r--r--arch/um/kernel/tt/mem.c34
-rw-r--r--arch/um/kernel/tt/mem_user.c49
-rw-r--r--arch/um/kernel/tt/process_kern.c461
-rw-r--r--arch/um/kernel/tt/ptproxy/Makefile10
-rw-r--r--arch/um/kernel/tt/ptproxy/proxy.c377
-rw-r--r--arch/um/kernel/tt/ptproxy/ptproxy.h61
-rw-r--r--arch/um/kernel/tt/ptproxy/ptrace.c237
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.c70
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.h25
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.c85
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.h15
-rw-r--r--arch/um/kernel/tt/syscall_kern.c46
-rw-r--r--arch/um/kernel/tt/syscall_user.c60
-rw-r--r--arch/um/kernel/tt/tlb.c120
-rw-r--r--arch/um/kernel/tt/tracer.c461
-rw-r--r--arch/um/kernel/tt/trap_user.c70
-rw-r--r--arch/um/kernel/tt/uaccess.c73
-rw-r--r--arch/um/kernel/tt/uaccess_user.c105
-rw-r--r--arch/um/kernel/uaccess.c2
-rw-r--r--arch/um/kernel/um_arch.c217
-rw-r--r--arch/um/kernel/uml.lds.S7
54 files changed, 1000 insertions, 4427 deletions
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index c5cf4a0827b..499e5e95e60 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux,intel}.com)
# Licensed under the GPL
#
@@ -9,15 +9,12 @@ clean-files :=
obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
physmem.o process.o ptrace.o reboot.o sigio.o \
signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
- um_arch.o umid.o
+ um_arch.o umid.o skas/
obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
-obj-$(CONFIG_MODE_TT) += tt/
-obj-$(CONFIG_MODE_SKAS) += skas/
-
USER_OBJS := config.o
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 41850906116..3866f4960f0 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -10,8 +10,6 @@ SECTIONS
PROVIDE (__executable_start = START);
. = START + SIZEOF_HEADERS;
.interp : { *(.interp) }
- /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start
- * is remapped.*/
__binary_start = .;
. = ALIGN(4096); /* Init code and data */
_text = .;
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index ce6828fd396..8196450451c 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -1,35 +1,44 @@
/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/slab.h"
+#include "linux/stddef.h"
+#include "linux/fs.h"
#include "linux/smp_lock.h"
#include "linux/ptrace.h"
-#include "linux/fs.h"
-#include "asm/ptrace.h"
-#include "asm/pgtable.h"
-#include "asm/tlbflush.h"
+#include "linux/sched.h"
+#include "asm/current.h"
+#include "asm/processor.h"
#include "asm/uaccess.h"
-#include "kern_util.h"
#include "as-layout.h"
#include "mem_user.h"
-#include "kern.h"
-#include "irq_user.h"
-#include "tlb.h"
+#include "skas.h"
#include "os.h"
-#include "choose-mode.h"
-#include "mode_kern.h"
void flush_thread(void)
{
+ void *data = NULL;
+ unsigned long end = proc_mm ? task_size : STUB_START;
+ int ret;
+
arch_flush_thread(&current->thread.arch);
- CHOOSE_MODE(flush_thread_tt(), flush_thread_skas());
+
+ ret = unmap(&current->mm->context.id, 0, end, 1, &data);
+ if (ret) {
+ printk(KERN_ERR "flush_thread - clearing address space failed, "
+ "err = %d\n", ret);
+ force_sig(SIGKILL, current);
+ }
+
+ __switch_mm(&current->mm->context.id);
}
void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
{
- CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp);
+ set_fs(USER_DS);
+ PT_REGS_IP(regs) = eip;
+ PT_REGS_SP(regs) = esp;
}
#ifdef CONFIG_TTY_LOG
@@ -39,7 +48,7 @@ extern void log_exec(char **argv, void *tty);
static long execve1(char *file, char __user * __user *argv,
char __user *__user *env)
{
- long error;
+ long error;
#ifdef CONFIG_TTY_LOG
struct tty_struct *tty;
@@ -49,17 +58,16 @@ static long execve1(char *file, char __user * __user *argv,
log_exec(argv, tty);
mutex_unlock(&tty_mutex);
#endif
- error = do_execve(file, argv, env, &current->thread.regs);
- if (error == 0){
+ error = do_execve(file, argv, env, &current->thread.regs);
+ if (error == 0) {
task_lock(current);
- current->ptrace &= ~PT_DTRACE;
+ current->ptrace &= ~PT_DTRACE;
#ifdef SUBARCH_EXECVE1
SUBARCH_EXECVE1(&current->thread.regs.regs);
#endif
task_unlock(current);
- set_cmdline(current_cmd());
- }
- return(error);
+ }
+ return error;
}
long um_execve(char *file, char __user *__user *argv, char __user *__user *env)
@@ -67,9 +75,9 @@ long um_execve(char *file, char __user *__user *argv, char __user *__user *env)
long err;
err = execve1(file, argv, env);
- if(!err)
- do_longjmp(current->thread.exec_buf, 1);
- return(err);
+ if (!err)
+ UML_LONGJMP(current->thread.exec_buf, 1);
+ return err;
}
long sys_execve(char __user *file, char __user *__user *argv,
@@ -86,5 +94,5 @@ long sys_execve(char __user *file, char __user *__user *argv,
putname(filename);
out:
unlock_kernel();
- return(error);
+ return error;
}
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
index cba516e6c99..dcfceca9505 100644
--- a/arch/um/kernel/init_task.c
+++ b/arch/um/kernel/init_task.c
@@ -3,16 +3,12 @@
* Licensed under the GPL
*/
-#include "linux/mm.h"
-#include "linux/fs.h"
-#include "linux/module.h"
#include "linux/sched.h"
#include "linux/init_task.h"
+#include "linux/fs.h"
+#include "linux/module.h"
#include "linux/mqueue.h"
#include "asm/uaccess.h"
-#include "asm/pgtable.h"
-#include "mem_user.h"
-#include "os.h"
static struct fs_struct init_fs = INIT_FS;
struct mm_struct init_mm = INIT_MM(init_mm);
@@ -46,8 +42,3 @@ union thread_union init_thread_union
union thread_union cpu0_irqstack
__attribute__((__section__(".data.init_irqstack"))) =
{ INIT_THREAD_INFO(init_task) };
-
-void unprotect_stack(unsigned long stack)
-{
- os_protect_memory((void *) stack, THREAD_SIZE, 1, 1, 0);
-}
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index cf0dd9cf8c4..277fce17b08 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -1,37 +1,19 @@
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
* Derived (i.e. mostly copied) from arch/i386/kernel/irq.c:
* Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
*/
-#include "linux/kernel.h"
-#include "linux/module.h"
-#include "linux/smp.h"
-#include "linux/kernel_stat.h"
+#include "linux/cpumask.h"
+#include "linux/hardirq.h"
#include "linux/interrupt.h"
-#include "linux/random.h"
-#include "linux/slab.h"
-#include "linux/file.h"
-#include "linux/proc_fs.h"
-#include "linux/init.h"
+#include "linux/kernel_stat.h"
+#include "linux/module.h"
#include "linux/seq_file.h"
-#include "linux/profile.h"
-#include "linux/hardirq.h"
-#include "asm/irq.h"
-#include "asm/hw_irq.h"
-#include "asm/atomic.h"
-#include "asm/signal.h"
-#include "asm/system.h"
-#include "asm/errno.h"
-#include "asm/uaccess.h"
+#include "as-layout.h"
#include "kern_util.h"
-#include "irq_user.h"
-#include "irq_kern.h"
#include "os.h"
-#include "sigio.h"
-#include "misc_constants.h"
-#include "as-layout.h"
/*
* Generic, controller-independent functions:
@@ -71,9 +53,8 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
skip:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
- } else if (i == NR_IRQS) {
+ } else if (i == NR_IRQS)
seq_putc(p, '\n');
- }
return 0;
}
@@ -91,7 +72,7 @@ static struct irq_fd **last_irq_ptr = &active_fds;
extern void free_irqs(void);
-void sigio_handler(int sig, union uml_pt_regs *regs)
+void sigio_handler(int sig, struct uml_pt_regs *regs)
{
struct irq_fd *irq_fd;
int n;
@@ -102,11 +83,13 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
while (1) {
n = os_waiting_for_events(active_fds);
if (n <= 0) {
- if(n == -EINTR) continue;
+ if (n == -EINTR)
+ continue;
else break;
}
- for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
+ for (irq_fd = active_fds; irq_fd != NULL;
+ irq_fd = irq_fd->next) {
if (irq_fd->current_events != 0) {
irq_fd->current_events = 0;
do_IRQ(irq_fd->irq, regs);
@@ -138,8 +121,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
if (type == IRQ_READ)
events = UM_POLLIN | UM_POLLPRI;
- else
- events = UM_POLLOUT;
+ else events = UM_POLLOUT;
*new_fd = ((struct irq_fd) { .next = NULL,
.id = dev_id,
.fd = fd,
@@ -153,9 +135,10 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
spin_lock_irqsave(&irq_lock, flags);
for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
if ((irq_fd->fd == fd) && (irq_fd->type == type)) {
- printk("Registering fd %d twice\n", fd);
- printk("Irqs : %d, %d\n", irq_fd->irq, irq);
- printk("Ids : 0x%p, 0x%p\n", irq_fd->id, dev_id);
+ printk(KERN_ERR "Registering fd %d twice\n", fd);
+ printk(KERN_ERR "Irqs : %d, %d\n", irq_fd->irq, irq);
+ printk(KERN_ERR "Ids : 0x%p, 0x%p\n", irq_fd->id,
+ dev_id);
goto out_unlock;
}
}
@@ -171,7 +154,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
if (n == 0)
break;
- /* n > 0
+ /*
+ * n > 0
* It means we couldn't put new pollfd to current pollfds
* and tmp_fds is NULL or too small for new pollfds array.
* Needed size is equal to n as minimum.
@@ -197,7 +181,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
spin_unlock_irqrestore(&irq_lock, flags);
- /* This calls activate_fd, so it has to be outside the critical
+ /*
+ * This calls activate_fd, so it has to be outside the critical
* section.
*/
maybe_sigio_broken(fd, (type == IRQ_READ));
@@ -264,13 +249,14 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
i++;
}
if (irq == NULL) {
- printk("find_irq_by_fd doesn't have descriptor %d\n", fd);
+ printk(KERN_ERR "find_irq_by_fd doesn't have descriptor %d\n",
+ fd);
goto out;
}
fdi = os_get_pollfd(i);
if ((fdi != -1) && (fdi != fd)) {
- printk("find_irq_by_fd - mismatch between active_fds and "
- "pollfds, fd %d vs %d, need %d\n", irq->fd,
+ printk(KERN_ERR "find_irq_by_fd - mismatch between active_fds "
+ "and pollfds, fd %d vs %d, need %d\n", irq->fd,
fdi, fd);
irq = NULL;
goto out;
@@ -306,7 +292,7 @@ void deactivate_fd(int fd, int irqnum)
spin_lock_irqsave(&irq_lock, flags);
irq = find_irq_by_fd(fd, irqnum, &i);
- if(irq == NULL){
+ if (irq == NULL) {
spin_unlock_irqrestore(&irq_lock, flags);
return;
}
@@ -339,36 +325,12 @@ int deactivate_all_fds(void)
return 0;
}
-#ifdef CONFIG_MODE_TT
-void forward_interrupts(int pid)
-{
- struct irq_fd *irq;
- unsigned long flags;
- int err;
-
- spin_lock_irqsave(&irq_lock, flags);
- for (irq = active_fds; irq != NULL; irq = irq->next) {
- err = os_set_owner(irq->fd, pid);
- if (err < 0) {
- /* XXX Just remove the irq rather than
- * print out an infinite stream of these
- */
- printk("Failed to forward %d to pid %d, err = %d\n",
- irq->fd, pid, -err);
- }
-
- irq->pid = pid;
- }
- spin_unlock_irqrestore(&irq_lock, flags);
-}
-#endif
-
/*
* do_IRQ handles all normal device IRQ's (the special
* SMP cross-CPU interrupts have their own specific
* handlers).
*/
-unsigned int do_IRQ(int irq, union uml_pt_regs *regs)
+unsigned int do_IRQ(int irq, struct uml_pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs);
irq_enter();
@@ -396,8 +358,10 @@ int um_request_irq(unsigned int irq, int fd, int type,
EXPORT_SYMBOL(um_request_irq);
EXPORT_SYMBOL(reactivate_fd);
-/* hw_interrupt_type must define (startup || enable) &&
- * (shutdown || disable) && end */
+/*
+ * hw_interrupt_type must define (startup || enable) &&
+ * (shutdown || disable) && end
+ */
static void dummy(unsigned int irq)
{
}
@@ -446,7 +410,8 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler)
err = os_pipe(fds, 1, 1);
if (err) {
- printk("init_aio_irq - os_pipe failed, err = %d\n", -err);
+ printk(KERN_ERR "init_aio_irq - os_pipe failed, err = %d\n",
+ -err);
goto out;
}
@@ -454,7 +419,8 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler)
IRQF_DISABLED | IRQF_SAMPLE_RANDOM, name,
(void *) (long) fds[0]);
if (err) {
- printk("init_aio_irq - : um_request_irq failed, err = %d\n",
+ printk(KERN_ERR "init_aio_irq - : um_request_irq failed, "
+ "err = %d\n",
err);
goto out_close;
}
@@ -525,8 +491,9 @@ unsigned long to_irq_stack(unsigned long *mask_out)
int nested;
mask = xchg(&pending_mask, *mask_out);
- if(mask != 0){
- /* If any interrupts come in at this point, we want to
+ if (mask != 0) {
+ /*
+ * If any interrupts come in at this point, we want to
* make sure that their bits aren't lost by our
* putting our bit in. So, this loop accumulates bits
* until xchg returns the same value that we put in.
@@ -538,13 +505,13 @@ unsigned long to_irq_stack(unsigned long *mask_out)
do {
old |= mask;
mask = xchg(&pending_mask, old);
- } while(mask != old);
+ } while (mask != old);
return 1;
}
ti = current_thread_info();
nested = (ti->real_thread != NULL);
- if(!nested){
+ if (!nested) {
struct task_struct *task;
struct thread_info *tti;
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 7b3e53fb807..1b388b41d95 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -1,22 +1,15 @@
/*
- * Copyright (C) 2001 - 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include "linux/module.h"
-#include "linux/string.h"
-#include "linux/smp_lock.h"
-#include "linux/spinlock.h"
-#include "linux/highmem.h"
-#include "asm/current.h"
-#include "asm/processor.h"
-#include "asm/unistd.h"
-#include "asm/pgalloc.h"
-#include "asm/pgtable.h"
-#include "asm/page.h"
+#include "linux/syscalls.h"
+#include "asm/a.out.h"
#include "asm/tlbflush.h"
-#include "kern_util.h"
+#include "asm/uaccess.h"
#include "as-layout.h"
+#include "kern_util.h"
#include "mem_user.h"
#include "os.h"
@@ -34,30 +27,19 @@ EXPORT_SYMBOL(get_kmem_end);
EXPORT_SYMBOL(high_physmem);
EXPORT_SYMBOL(empty_zero_page);
EXPORT_SYMBOL(um_virt_to_phys);
-EXPORT_SYMBOL(mode_tt);
EXPORT_SYMBOL(handle_page_fault);
EXPORT_SYMBOL(find_iomem);
-#ifdef CONFIG_MODE_TT
-EXPORT_SYMBOL(stop);
-EXPORT_SYMBOL(strncpy_from_user_tt);
-EXPORT_SYMBOL(copy_from_user_tt);
-EXPORT_SYMBOL(copy_to_user_tt);
-#endif
-
-#ifdef CONFIG_MODE_SKAS
-EXPORT_SYMBOL(strnlen_user_skas);
-EXPORT_SYMBOL(strncpy_from_user_skas);
-EXPORT_SYMBOL(copy_to_user_skas);
-EXPORT_SYMBOL(copy_from_user_skas);
-EXPORT_SYMBOL(clear_user_skas);
-#endif
+EXPORT_SYMBOL(strnlen_user);
+EXPORT_SYMBOL(strncpy_from_user);
+EXPORT_SYMBOL(copy_to_user);
+EXPORT_SYMBOL(copy_from_user);
+EXPORT_SYMBOL(clear_user);
EXPORT_SYMBOL(uml_strdup);
EXPORT_SYMBOL(os_stat_fd);
EXPORT_SYMBOL(os_stat_file);
EXPORT_SYMBOL(os_access);
-EXPORT_SYMBOL(os_print_error);
EXPORT_SYMBOL(os_get_exec_close);
EXPORT_SYMBOL(os_set_exec_close);
EXPORT_SYMBOL(os_getpid);
@@ -85,9 +67,6 @@ EXPORT_SYMBOL(run_helper);
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(dump_thread);
-EXPORT_SYMBOL(do_gettimeofday);
-EXPORT_SYMBOL(do_settimeofday);
-
#ifdef CONFIG_SMP
/* required for SMP */
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index d2b11f24269..8456397f5f4 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -17,7 +17,7 @@
#include "as-layout.h"
#include "kern.h"
#include "mem_user.h"
-#include "uml_uaccess.h"
+#include "um_uaccess.h"
#include "os.h"
#include "linux/types.h"
#include "linux/string.h"
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index 5ee7e851bbc..e66432f4248 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -1,25 +1,17 @@
/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/mm.h"
-#include "linux/rbtree.h"
-#include "linux/slab.h"
-#include "linux/vmalloc.h"
#include "linux/bootmem.h"
-#include "linux/module.h"
+#include "linux/mm.h"
#include "linux/pfn.h"
-#include "asm/types.h"
-#include "asm/pgtable.h"
-#include "kern_util.h"
+#include "asm/page.h"
#include "as-layout.h"
-#include "mode_kern.h"
-#include "mem.h"
+#include "init.h"
+#include "kern.h"
#include "mem_user.h"
#include "os.h"
-#include "kern.h"
-#include "init.h"
static int physmem_fd = -1;
@@ -49,10 +41,10 @@ int __init init_maps(unsigned long physmem, unsigned long iomem,
total_len = phys_len + iomem_len + highmem_len;
map = alloc_bootmem_low_pages(total_len);
- if(map == NULL)
+ if (map == NULL)
return -ENOMEM;
- for(i = 0; i < total_pages; i++){
+ for (i = 0; i < total_pages; i++) {
p = &map[i];
memset(p, 0, sizeof(struct page));
SetPageReserved(p);
@@ -68,8 +60,8 @@ static unsigned long kmem_top = 0;
unsigned long get_kmem_end(void)
{
- if(kmem_top == 0)
- kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
+ if (kmem_top == 0)
+ kmem_top = host_task_size - 1024 * 1024;
return kmem_top;
}
@@ -81,9 +73,9 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
fd = phys_mapping(phys, &offset);
err = os_map_memory((void *) virt, fd, offset, len, r, w, x);
- if(err) {
- if(err == -ENOMEM)
- printk("try increasing the host's "
+ if (err) {
+ if (err == -ENOMEM)
+ printk(KERN_ERR "try increasing the host's "
"/proc/sys/vm/max_map_count to <physical "
"memory size>/4096\n");
panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, "
@@ -105,13 +97,16 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end,
offset = uml_reserved - uml_physmem;
err = os_map_memory((void *) uml_reserved, physmem_fd, offset,
- len - offset, 1, 1, 0);
- if(err < 0){
- os_print_error(err, "Mapping memory");
+ len - offset, 1, 1, 1);
+ if (err < 0) {
+ printf("setup_physmem - mapping %ld bytes of memory at 0x%p "
+ "failed - errno = %d\n", len - offset,
+ (void *) uml_reserved, err);
exit(1);
}
- /* Special kludge - This page will be mapped in to userspace processes
+ /*
+ * Special kludge - This page will be mapped in to userspace processes
* from physmem_fd, so it needs to be written out there.
*/
os_seek_file(physmem_fd, __pa(&__syscall_stub_start));
@@ -122,20 +117,20 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end,
len - bootmap_size - reserve);
}
-int phys_mapping(unsigned long phys, __u64 *offset_out)
+int phys_mapping(unsigned long phys, unsigned long long *offset_out)
{
int fd = -1;
- if(phys < physmem_size){
+ if (phys < physmem_size) {
fd = physmem_fd;
*offset_out = phys;
}
- else if(phys < __pa(end_iomem)){
+ else if (phys < __pa(end_iomem)) {
struct iomem_region *region = iomem_regions;
- while(region != NULL){
- if((phys >= region->phys) &&
- (phys < region->phys + region->size)){
+ while (region != NULL) {
+ if ((phys >= region->phys) &&
+ (phys < region->phys + region->size)) {
fd = region->fd;
*offset_out = phys - region->phys;
break;
@@ -143,7 +138,7 @@ int phys_mapping(unsigned long phys, __u64 *offset_out)
region = region->next;
}
}
- else if(phys < __pa(end_iomem) + highmem){
+ else if (phys < __pa(end_iomem) + highmem) {
fd = physmem_fd;
*offset_out = phys - iomem_size;
}
@@ -188,8 +183,8 @@ unsigned long find_iomem(char *driver, unsigned long *len_out)
{
struct iomem_region *region = iomem_regions;
- while(region != NULL){
- if(!strcmp(region->driver, driver)){
+ while (region != NULL) {
+ if (!strcmp(region->driver, driver)) {
*len_out = region->size;
return region->virt;
}
@@ -206,12 +201,12 @@ int setup_iomem(void)
unsigned long iomem_start = high_physmem + PAGE_SIZE;
int err;
- while(region != NULL){
+ while (region != NULL) {
err = os_map_memory((void *) iomem_start, region->fd, 0,
region->size, 1, 1, 0);
- if(err)
- printk("Mapping iomem region for driver '%s' failed, "
- "errno = %d\n", region->driver, -err);
+ if (err)
+ printk(KERN_ERR "Mapping iomem region for driver '%s' "
+ "failed, errno = %d\n", region->driver, -err);
else {
region->virt = iomem_start;
region->phys = __pa(region->virt);
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index bfa52f206bb..0eae00b3e58 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -1,53 +1,30 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Copyright 2003 PathScale, Inc.
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/sched.h"
-#include "linux/interrupt.h"
-#include "linux/string.h"
+#include "linux/stddef.h"
+#include "linux/err.h"
+#include "linux/hardirq.h"
#include "linux/mm.h"
-#include "linux/slab.h"
-#include "linux/utsname.h"
-#include "linux/fs.h"
-#include "linux/utime.h"
-#include "linux/smp_lock.h"
-#include "linux/module.h"
-#include "linux/init.h"
-#include "linux/capability.h"
-#include "linux/vmalloc.h"
-#include "linux/spinlock.h"
+#include "linux/personality.h"
#include "linux/proc_fs.h"
#include "linux/ptrace.h"
#include "linux/random.h"
-#include "linux/personality.h"
-#include "asm/unistd.h"
-#include "asm/mman.h"
-#include "asm/segment.h"
-#include "asm/stat.h"
+#include "linux/sched.h"
+#include "linux/tick.h"
+#include "linux/threads.h"
#include "asm/pgtable.h"
-#include "asm/processor.h"
-#include "asm/tlbflush.h"
#include "asm/uaccess.h"
-#include "asm/user.h"
-#include "kern_util.h"
#include "as-layout.h"
-#include "kern.h"
-#include "signal_kern.h"
-#include "init.h"
-#include "irq_user.h"
-#include "mem_user.h"
-#include "tlb.h"
-#include "frame_kern.h"
-#include "sigcontext.h"
+#include "kern_util.h"
#include "os.h"
-#include "mode.h"
-#include "mode_kern.h"
-#include "choose-mode.h"
+#include "skas.h"
+#include "tlb.h"
-/* This is a per-cpu array. A processor only modifies its entry and it only
+/*
+ * This is a per-cpu array. A processor only modifies its entry and it only
* cares about its entry, so it's OK if another processor is modifying its
* entry.
*/
@@ -55,15 +32,16 @@ struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
static inline int external_pid(struct task_struct *task)
{
- return CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task);
+ /* FIXME: Need to look up userspace_pid by cpu */
+ return userspace_pid[0];
}
int pid_to_processor_id(int pid)
{
int i;
- for(i = 0; i < ncpus; i++){
- if(cpu_tasks[i].pid == pid)
+ for(i = 0; i < ncpus; i++) {
+ if (cpu_tasks[i].pid == pid)
return i;
}
return -1;
@@ -82,9 +60,9 @@ unsigned long alloc_stack(int order, int atomic)
if (atomic)
flags = GFP_ATOMIC;
page = __get_free_pages(flags, order);
- if(page == 0)
+ if (page == 0)
return 0;
- stack_protections(page);
+
return page;
}
@@ -105,6 +83,8 @@ static inline void set_current(struct task_struct *task)
{ external_pid(task), task });
}
+extern void arch_switch_to(struct task_struct *from, struct task_struct *to);
+
void *_switch_to(void *prev, void *next, void *last)
{
struct task_struct *from = prev;
@@ -114,9 +94,14 @@ void *_switch_to(void *prev, void *next, void *last)
set_current(to);
do {
- current->thread.saved_task = NULL ;
- CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next);
- if(current->thread.saved_task)
+ current->thread.saved_task = NULL;
+
+ switch_threads(&from->thread.switch_buf,
+ &to->thread.switch_buf);
+
+ arch_switch_to(current->thread.prev_sched, current);
+
+ if (current->thread.saved_task)
show_regs(&(current->thread.regs));
next= current->thread.saved_task;
prev= current;
@@ -128,20 +113,14 @@ void *_switch_to(void *prev, void *next, void *last)
void interrupt_end(void)
{
- if(need_resched())
+ if (need_resched())
schedule();
- if(test_tsk_thread_flag(current, TIF_SIGPENDING))
+ if (test_tsk_thread_flag(current, TIF_SIGPENDING))
do_signal();
}
-void release_thread(struct task_struct *task)
-{
- CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
-}
-
void exit_thread(void)
{
- unprotect_stack((unsigned long) current_thread);
}
void *get_current(void)
@@ -149,28 +128,99 @@ void *get_current(void)
return current;
}
+extern void schedule_tail(struct task_struct *prev);
+
+/*
+ * This is called magically, by its address being stuffed in a jmp_buf
+ * and being longjmp-d to.
+ */
+void new_thread_handler(void)
+{
+ int (*fn)(void *), n;
+ void *arg;
+
+ if (current->thread.prev_sched != NULL)
+ schedule_tail(current->thread.prev_sched);
+ current->thread.prev_sched = NULL;
+
+ fn = current->thread.request.u.thread.proc;
+ arg = current->thread.request.u.thread.arg;
+
+ /*
+ * The return value is 1 if the kernel thread execs a process,
+ * 0 if it just exits
+ */
+ n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
+ if (n == 1) {
+ /* Handle any immediate reschedules or signals */
+ interrupt_end();
+ userspace(&current->thread.regs.regs);
+ }
+ else do_exit(0);
+}
+
+/* Called magically, see new_thread_handler above */
+void fork_handler(void)
+{
+ force_flush_all();
+ if (current->thread.prev_sched == NULL)
+ panic("blech");
+
+ schedule_tail(current->thread.prev_sched);
+
+ /*
+ * XXX: if interrupt_end() calls schedule, this call to
+ * arch_switch_to isn't needed. We could want to apply this to
+ * improve performance. -bb
+ */
+ arch_switch_to(current->thread.prev_sched, current);
+
+ current->thread.prev_sched = NULL;
+
+ /* Handle any immediate reschedules or signals */
+ interrupt_end();
+
+ userspace(&current->thread.regs.regs);
+}
+
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
unsigned long stack_top, struct task_struct * p,
struct pt_regs *regs)
{
- int ret;
+ void (*handler)(void);
+ int ret = 0;
p->thread = (struct thread_struct) INIT_THREAD;
- ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
- clone_flags, sp, stack_top, p, regs);
- if (ret || !current->thread.forking)
- goto out;
+ if (current->thread.forking) {
+ memcpy(&p->thread.regs.regs, &regs->regs,
+ sizeof(p->thread.regs.regs));
+ REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.gp, 0);
+ if (sp != 0)
+ REGS_SP(p->thread.regs.regs.gp) = sp;
- clear_flushed_tls(p);
+ handler = fork_handler;
- /*
- * Set a new TLS for the child thread?
- */
- if (clone_flags & CLONE_SETTLS)
- ret = arch_copy_tls(p);
+ arch_copy_thread(&current->thread.arch, &p->thread.arch);
+ }
+ else {
+ init_thread_registers(&p->thread.regs.regs);
+ p->thread.request.u.thread = current->thread.request.u.thread;
+ handler = new_thread_handler;
+ }
+
+ new_thread(task_stack_page(p), &p->thread.switch_buf, handler);
+
+ if (current->thread.forking) {
+ clear_flushed_tls(p);
+
+ /*
+ * Set a new TLS for the child thread?
+ */
+ if (clone_flags & CLONE_SETTLS)
+ ret = arch_copy_tls(p);
+ }
-out:
return ret;
}
@@ -179,39 +229,35 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
int save_kmalloc_ok = kmalloc_ok;
kmalloc_ok = 0;
- CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
- arg);
+ initial_thread_cb_skas(proc, arg);
kmalloc_ok = save_kmalloc_ok;
}
-#ifdef CONFIG_MODE_TT
-unsigned long stack_sp(unsigned long page)
-{
- return page + PAGE_SIZE - sizeof(void *);
-}
-#endif
-
void default_idle(void)
{
- CHOOSE_MODE(uml_idle_timer(), (void) 0);
+ unsigned long long nsecs;
- while(1){
+ while(1) {
/* endless idle loop with no priority at all */
/*
* although we are an idle CPU, we do not want to
* get into the scheduler unnecessarily.
*/
- if(need_resched())
+ if (need_resched())
schedule();
- idle_sleep(10);
+ tick_nohz_stop_sched_tick();
+ nsecs = disable_timer();
+ idle_sleep(nsecs);
+ tick_nohz_restart_sched_tick();
}
}
void cpu_idle(void)
{
- CHOOSE_MODE(init_idle_tt(), init_idle_skas());
+ cpu_tasks[current_thread->cpu].pid = os_getpid();
+ default_idle();
}
void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
@@ -223,26 +269,26 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
pte_t *pte;
pte_t ptent;
- if(task->mm == NULL)
+ if (task->mm == NULL)
return ERR_PTR(-EINVAL);
pgd = pgd_offset(task->mm, addr);
- if(!pgd_present(*pgd))
+ if (!pgd_present(*pgd))
return ERR_PTR(-EINVAL);
pud = pud_offset(pgd, addr);
- if(!pud_present(*pud))
+ if (!pud_present(*pud))
return ERR_PTR(-EINVAL);
pmd = pmd_offset(pud, addr);
- if(!pmd_present(*pmd))
+ if (!pmd_present(*pmd))
return ERR_PTR(-EINVAL);
pte = pte_offset_kernel(pmd, addr);
ptent = *pte;
- if(!pte_present(ptent))
+ if (!pte_present(ptent))
return ERR_PTR(-EINVAL);
- if(pte_out != NULL)
+ if (pte_out != NULL)
*pte_out = ptent;
return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK);
}
@@ -315,7 +361,7 @@ int smp_sigio_handler(void)
#ifdef CONFIG_SMP
int cpu = current_thread->cpu;
IPI_handler(cpu);
- if(cpu != 0)
+ if (cpu != 0)
return 1;
#endif
return 0;
@@ -343,7 +389,8 @@ int get_using_sysemu(void)
static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
{
- if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
+ if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size)
+ /* No overflow */
*eof = 1;
return strlen(buf);
@@ -358,7 +405,8 @@ static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned
if (tmp[0] >= '0' && tmp[0] <= '2')
set_using_sysemu(tmp[0] - '0');
- return count; /*We use the first char, but pretend to write everything*/
+ /* We use the first char, but pretend to write everything */
+ return count;
}
int __init make_proc_sysemu(void)
@@ -388,10 +436,10 @@ int singlestepping(void * t)
struct task_struct *task = t ? t : current;
if ( ! (task->ptrace & PT_DTRACE) )
- return(0);
+ return 0;
if (task->thread.singlestep_syscall)
- return(1);
+ return 1;
return 2;
}
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 6916c8888db..a0eba083306 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -1,35 +1,27 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/sched.h"
-#include "linux/mm.h"
-#include "linux/errno.h"
-#include "linux/smp_lock.h"
-#include "linux/security.h"
-#include "linux/ptrace.h"
#include "linux/audit.h"
+#include "linux/ptrace.h"
+#include "linux/sched.h"
+#include "asm/uaccess.h"
#ifdef CONFIG_PROC_MM
-#include "linux/proc_mm.h"
+#include "proc_mm.h"
#endif
-#include "asm/ptrace.h"
-#include "asm/uaccess.h"
-#include "kern_util.h"
#include "skas_ptrace.h"
-#include "sysdep/ptrace.h"
-#include "os.h"
static inline void set_singlestepping(struct task_struct *child, int on)
{
- if (on)
- child->ptrace |= PT_DTRACE;
- else
- child->ptrace &= ~PT_DTRACE;
- child->thread.singlestep_syscall = 0;
+ if (on)
+ child->ptrace |= PT_DTRACE;
+ else
+ child->ptrace &= ~PT_DTRACE;
+ child->thread.singlestep_syscall = 0;
#ifdef SUBARCH_SET_SINGLESTEPPING
- SUBARCH_SET_SINGLESTEPPING(child, on);
+ SUBARCH_SET_SINGLESTEPPING(child, on);
#endif
}
@@ -37,8 +29,8 @@ static inline void set_singlestepping(struct task_struct *child, int on)
* Called by kernel/ptrace.c when detaching..
*/
void ptrace_disable(struct task_struct *child)
-{
- set_singlestepping(child,0);
+{
+ set_singlestepping(child,0);
}
extern int peek_user(struct task_struct * child, long addr, long data);
@@ -50,40 +42,40 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
unsigned long __user *p = (void __user *)(unsigned long)data;
switch (request) {
- /* when I and D space are separate, these will need to be fixed. */
- case PTRACE_PEEKTEXT: /* read word at location addr. */
+ /* read word at location addr. */
+ case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
ret = generic_ptrace_peekdata(child, addr, data);
break;
/* read the word at location addr in the USER area. */
- case PTRACE_PEEKUSR:
- ret = peek_user(child, addr, data);
- break;
+ case PTRACE_PEEKUSR:
+ ret = peek_user(child, addr, data);
+ break;
- /* when I and D space are separate, this will have to be fixed. */
- case PTRACE_POKETEXT: /* write the word at location addr. */
+ /* write the word at location addr. */
+ case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
ret = generic_ptrace_pokedata(child, addr, data);
break;
- case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
- ret = poke_user(child, addr, data);
- break;
+ /* write the word at location addr in the USER area */
+ case PTRACE_POKEUSR:
+ ret = poke_user(child, addr, data);
+ break;
- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
- case PTRACE_CONT: { /* restart after signal. */
+ /* continue and stop at next (return from) syscall */
+ case PTRACE_SYSCALL:
+ /* restart after signal. */
+ case PTRACE_CONT: {
ret = -EIO;
if (!valid_signal(data))
break;
- set_singlestepping(child, 0);
- if (request == PTRACE_SYSCALL) {
+ set_singlestepping(child, 0);
+ if (request == PTRACE_SYSCALL)
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- }
- else {
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- }
+ else clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data;
wake_up_process(child);
ret = 0;
@@ -91,8 +83,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
/*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
+ * make the child exit. Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
* exit.
*/
case PTRACE_KILL: {
@@ -100,7 +92,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
- set_singlestepping(child, 0);
+ set_singlestepping(child, 0);
child->exit_code = SIGKILL;
wake_up_process(child);
break;
@@ -111,7 +103,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
if (!valid_signal(data))
break;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- set_singlestepping(child, 1);
+ set_singlestepping(child, 1);
child->exit_code = data;
/* give it a chance to run. */
wake_up_process(child);
@@ -119,11 +111,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
- case PTRACE_DETACH:
- /* detach a process that was attached. */
- ret = ptrace_detach(child, data);
- break;
-
#ifdef PTRACE_GETREGS
case PTRACE_GETREGS: { /* Get all gp regs from the child. */
if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) {
@@ -156,22 +143,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#endif
#ifdef PTRACE_GETFPREGS
case PTRACE_GETFPREGS: /* Get the child FPU state. */
- ret = get_fpregs(data, child);
+ ret = get_fpregs((struct user_i387_struct __user *) data,
+ child);
break;
#endif
#ifdef PTRACE_SETFPREGS
case PTRACE_SETFPREGS: /* Set the child FPU state. */
- ret = set_fpregs(data, child);
- break;
-#endif
-#ifdef PTRACE_GETFPXREGS
- case PTRACE_GETFPXREGS: /* Get the child FPU state. */
- ret = get_fpxregs(data, child);
- break;
-#endif
-#ifdef PTRACE_SETFPXREGS
- case PTRACE_SETFPXREGS: /* Set the child FPU state. */
- ret = set_fpxregs(data, child);
+ ret = set_fpregs((struct user_i387_struct __user *) data,
+ child);
break;
#endif
case PTRACE_GET_THREAD_AREA:
@@ -185,14 +164,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
case PTRACE_FAULTINFO: {
- /* Take the info from thread->arch->faultinfo,
+ /*
+ * Take the info from thread->arch->faultinfo,
* but transfer max. sizeof(struct ptrace_faultinfo).
* On i386, ptrace_faultinfo is smaller!
*/
ret = copy_to_user(p, &child->thread.arch.faultinfo,
sizeof(struct ptrace_faultinfo));
- if(ret)
- break;
break;
}
@@ -200,12 +178,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_LDT: {
struct ptrace_ldt ldt;
- if(copy_from_user(&ldt, p, sizeof(ldt))){
+ if (copy_from_user(&ldt, p, sizeof(ldt))) {
ret = -EIO;
break;
}
- /* This one is confusing, so just punt and return -EIO for
+ /*
+ * This one is confusing, so just punt and return -EIO for
* now
*/
ret = -EIO;
@@ -217,7 +196,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
struct mm_struct *old = child->mm;
struct mm_struct *new = proc_mm_get_mm(data);
- if(IS_ERR(new)){
+ if (IS_ERR(new)) {
ret = PTR_ERR(new);
break;
}
@@ -231,20 +210,22 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
#endif
#ifdef PTRACE_ARCH_PRCTL
- case PTRACE_ARCH_PRCTL:
- /* XXX Calls ptrace on the host - needs some SMP thinking */
- ret = arch_prctl_skas(child, data, (void *) addr);
- break;
+ case PTRACE_ARCH_PRCTL:
+ /* XXX Calls ptrace on the host - needs some SMP thinking */
+ ret = arch_prctl(child, data, (void *) addr);
+ break;
#endif
default:
ret = ptrace_request(child, request, addr, data);
+ if (ret == -EIO)
+ ret = subarch_ptrace(child, request, addr, data);
break;
}
return ret;
}
-void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs,
+void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs,
int error_code)
{
struct siginfo info;
@@ -260,10 +241,11 @@ void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs,
force_sig_info(SIGTRAP, &info, tsk);
}
-/* XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and
+/*
+ * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and
* PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check
*/
-void syscall_trace(union uml_pt_regs *regs, int entryexit)
+void syscall_trace(struct uml_pt_regs *regs, int entryexit)
{
int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit;
int tracesysgood;
@@ -277,7 +259,7 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
UPT_SYSCALL_ARG3(regs),
UPT_SYSCALL_ARG4(regs));
else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
- UPT_SYSCALL_RET(regs));
+ UPT_SYSCALL_RET(regs));
}
/* Fake a debug trap */
@@ -290,15 +272,18 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
if (!(current->ptrace & PT_PTRACED))
return;
- /* the 0x80 provides a way for the tracing parent to distinguish
- between a syscall stop and SIGTRAP delivery */
+ /*
+ * the 0x80 provides a way for the tracing parent to distinguish
+ * between a syscall stop and SIGTRAP delivery
+ */
tracesysgood = (current->ptrace & PT_TRACESYSGOOD);
ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0));
if (entryexit) /* force do_signal() --> is_syscall() */
set_thread_flag(TIF_SIGPENDING);
- /* this isn't the same as continuing with a signal, but it will do
+ /*
+ * this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 7e4305a1fd3..04cebcf0679 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -1,60 +1,53 @@
/*
- * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/module.h"
#include "linux/sched.h"
-#include "asm/smp.h"
-#include "kern_util.h"
-#include "kern.h"
#include "os.h"
-#include "mode.h"
-#include "choose-mode.h"
+#include "skas.h"
void (*pm_power_off)(void);
-#ifdef CONFIG_SMP
-static void kill_idlers(int me)
-{
-#ifdef CONFIG_MODE_TT
- struct task_struct *p;
- int i;
-
- for(i = 0; i < ARRAY_SIZE(idle_threads); i++){
- p = idle_threads[i];
- if((p != NULL) && (p->thread.mode.tt.extern_pid != me))
- os_kill_process(p->thread.mode.tt.extern_pid, 0);
- }
-#endif
-}
-#endif
-
static void kill_off_processes(void)
{
- CHOOSE_MODE(kill_off_processes_tt(), kill_off_processes_skas());
-#ifdef CONFIG_SMP
- kill_idlers(os_getpid());
-#endif
+ if(proc_mm)
+ /*
+ * FIXME: need to loop over userspace_pids
+ */
+ os_kill_ptraced_process(userspace_pid[0], 1);
+ else {
+ struct task_struct *p;
+ int pid, me;
+
+ me = os_getpid();
+ for_each_process(p){
+ if(p->mm == NULL)
+ continue;
+
+ pid = p->mm->context.id.u.pid;
+ os_kill_ptraced_process(pid, 1);
+ }
+ }
}
void uml_cleanup(void)
{
- kmalloc_ok = 0;
+ kmalloc_ok = 0;
do_uml_exitcalls();
kill_off_processes();
}
void machine_restart(char * __unused)
{
- uml_cleanup();
- CHOOSE_MODE(reboot_tt(), reboot_skas());
+ uml_cleanup();
+ reboot_skas();
}
void machine_power_off(void)
{
- uml_cleanup();
- CHOOSE_MODE(halt_tt(), halt_skas());
+ uml_cleanup();
+ halt_skas();
}
void machine_halt(void)
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index c4020c3d785..19cb9773393 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -1,29 +1,17 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/stddef.h"
-#include "linux/sys.h"
-#include "linux/sched.h"
-#include "linux/wait.h"
-#include "linux/kernel.h"
-#include "linux/smp_lock.h"
#include "linux/module.h"
-#include "linux/slab.h"
-#include "linux/tty.h"
-#include "linux/binfmts.h"
#include "linux/ptrace.h"
+#include "linux/sched.h"
+#include "asm/siginfo.h"
#include "asm/signal.h"
-#include "asm/uaccess.h"
#include "asm/unistd.h"
-#include "asm/ucontext.h"
-#include "kern_util.h"
-#include "signal_kern.h"
-#include "kern.h"
#include "frame_kern.h"
+#include "kern_util.h"
#include "sigcontext.h"
-#include "mode.h"
EXPORT_SYMBOL(block_signals);
EXPORT_SYMBOL(unblock_signals);
@@ -46,9 +34,9 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
current_thread_info()->restart_block.fn = do_no_restart_syscall;
/* Did we come from a system call? */
- if(PT_REGS_SYSCALL_NR(regs) >= 0){
+ if (PT_REGS_SYSCALL_NR(regs) >= 0) {
/* If so, check system call restarting.. */
- switch(PT_REGS_SYSCALL_RET(regs)){
+ switch(PT_REGS_SYSCALL_RET(regs)) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
PT_REGS_SYSCALL_RET(regs) = -EINTR;
@@ -68,17 +56,17 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
}
sp = PT_REGS_SP(regs);
- if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
+ if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
sp = current->sas_ss_sp + current->sas_ss_size;
#ifdef CONFIG_ARCH_HAS_SC_SIGNALS
- if(!(ka->sa.sa_flags & SA_SIGINFO))
+ if (!(ka->sa.sa_flags & SA_SIGINFO))
err = setup_signal_stack_sc(sp, signr, ka, regs, oldset);
else
#endif
err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);
- if(err){
+ if (err) {
spin_lock_irq(&current->sighand->siglock);
current->blocked = *oldset;
recalc_sigpending();
@@ -88,7 +76,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked,
&ka->sa.sa_mask);
- if(!(ka->sa.sa_flags & SA_NODEFER))
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, signr);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
@@ -109,14 +97,16 @@ static int kern_do_signal(struct pt_regs *regs)
else
oldset = &current->blocked;
- while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){
+ while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) {
handled_sig = 1;
/* Whee! Actually deliver the signal. */
- if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){
- /* a signal was successfully delivered; the saved
+ if (!handle_signal(regs, sig, &ka_copy, &info, oldset)) {
+ /*
+ * a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
- * clear the TIF_RESTORE_SIGMASK flag */
+ * clear the TIF_RESTORE_SIGMASK flag
+ */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
break;
@@ -124,9 +114,9 @@ static int kern_do_signal(struct pt_regs *regs)
}
/* Did we come from a system call? */
- if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){
+ if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) {
/* Restart the system call - no handlers present */
- switch(PT_REGS_SYSCALL_RET(regs)){
+ switch(PT_REGS_SYSCALL_RET(regs)) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
@@ -137,22 +127,25 @@ static int kern_do_signal(struct pt_regs *regs)
PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall;
PT_REGS_RESTART_SYSCALL(regs);
break;
- }
+ }
}
- /* This closes a way to execute a system call on the host. If
+ /*
+ * This closes a way to execute a system call on the host. If
* you set a breakpoint on a system call instruction and singlestep
* from it, the tracing thread used to PTRACE_SINGLESTEP the process
* rather than PTRACE_SYSCALL it, allowing the system call to execute
* on the host. The tracing thread will check this flag and
* PTRACE_SYSCALL if necessary.
*/
- if(current->ptrace & PT_DTRACE)
+ if (current->ptrace & PT_DTRACE)
current->thread.singlestep_syscall =
is_syscall(PT_REGS_IP(&current->thread.regs));
- /* if there's no signal to deliver, we just put the saved sigmask
- * back */
+ /*
+ * if there's no signal to deliver, we just put the saved sigmask
+ * back
+ */
if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 3e3fa7e7e3c..0b76d8869c9 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -1,9 +1,9 @@
#
-# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
+# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
# Licensed under the GPL
#
-obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o
+obj-y := clone.o mmu.o process.o syscall.o uaccess.o
# clone.o is in the stub, so it can't be built with profiling
# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
index 47b812b3bca..d119f4f7d89 100644
--- a/arch/um/kernel/skas/clone.c
+++ b/arch/um/kernel/skas/clone.c
@@ -4,6 +4,7 @@
#include <sys/time.h>
#include <asm/unistd.h>
#include <asm/page.h>
+#include "as-layout.h"
#include "ptrace_user.h"
#include "skas.h"
#include "stub-data.h"
@@ -21,12 +22,11 @@
void __attribute__ ((__section__ (".__syscall_stub")))
stub_clone_handler(void)
{
- struct stub_data *data = (struct stub_data *) UML_CONFIG_STUB_DATA;
+ struct stub_data *data = (struct stub_data *) STUB_DATA;
long err;
err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
- UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE / 2 -
- sizeof(void *));
+ STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *));
if(err != 0)
goto out;
diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c
deleted file mode 100644
index 580eb646894..00000000000
--- a/arch/um/kernel/skas/exec.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/kernel.h"
-#include "asm/current.h"
-#include "asm/page.h"
-#include "asm/signal.h"
-#include "asm/ptrace.h"
-#include "asm/uaccess.h"
-#include "asm/mmu_context.h"
-#include "tlb.h"
-#include "skas.h"
-#include "um_mmu.h"
-#include "os.h"
-
-void flush_thread_skas(void)
-{
- void *data = NULL;
- unsigned long end = proc_mm ? task_size : CONFIG_STUB_START;
- int ret;
-
- ret = unmap(&current->mm->context.skas.id, 0, end, 1, &data);
- if(ret){
- printk("flush_thread_skas - clearing address space failed, "
- "err = %d\n", ret);
- force_sig(SIGKILL, current);
- }
-
- switch_mm_skas(&current->mm->context.skas.id);
-}
-
-void start_thread_skas(struct pt_regs *regs, unsigned long eip,
- unsigned long esp)
-{
- set_fs(USER_DS);
- PT_REGS_IP(regs) = eip;
- PT_REGS_SP(regs) = esp;
-}
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
deleted file mode 100644
index 7c18dfcd7d8..00000000000
--- a/arch/um/kernel/skas/mem.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/mm.h"
-#include "asm/pgtable.h"
-#include "mem_user.h"
-#include "skas.h"
-
-unsigned long set_task_sizes_skas(unsigned long *task_size_out)
-{
- /* Round up to the nearest 4M */
- unsigned long host_task_size = ROUND_4M((unsigned long)
- &host_task_size);
-
- if (!skas_needs_stub)
- *task_size_out = host_task_size;
- else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
-
- return host_task_size;
-}
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 2c6d090a2e8..f859ec306cd 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -1,20 +1,13 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/sched.h"
-#include "linux/list.h"
-#include "linux/spinlock.h"
-#include "linux/slab.h"
-#include "linux/errno.h"
#include "linux/mm.h"
-#include "asm/current.h"
-#include "asm/segment.h"
-#include "asm/mmu.h"
+#include "linux/sched.h"
#include "asm/pgalloc.h"
#include "asm/pgtable.h"
-#include "asm/ldt.h"
+#include "as-layout.h"
#include "os.h"
#include "skas.h"
@@ -41,10 +34,11 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
if (!pte)
goto out_pte;
- /* There's an interaction between the skas0 stub pages, stack
+ /*
+ * There's an interaction between the skas0 stub pages, stack
* randomization, and the BUG at the end of exit_mmap. exit_mmap
- * checks that the number of page tables freed is the same as had
- * been allocated. If the stack is on the last page table page,
+ * checks that the number of page tables freed is the same as had
+ * been allocated. If the stack is on the last page table page,
* then the stack pte page will be freed, and if not, it won't. To
* avoid having to know where the stack is, or if the process mapped
* something at the top of its address space for some other reason,
@@ -54,76 +48,77 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
* destroy_context_skas.
*/
- mm->context.skas.last_page_table = pmd_page_vaddr(*pmd);
+ mm->context.last_page_table = pmd_page_vaddr(*pmd);
#ifdef CONFIG_3_LEVEL_PGTABLES
- mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud));
+ mm->context.last_pmd = (unsigned long) __va(pud_val(*pud));
#endif
*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
*pte = pte_mkread(*pte);
- return(0);
+ return 0;
out_pmd:
pud_free(pud);
out_pte:
pmd_free(pmd);
out:
- return(-ENOMEM);
+ return -ENOMEM;
}
-int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
+int init_new_context(struct task_struct *task, struct mm_struct *mm)
{
- struct mmu_context_skas *from_mm = NULL;
- struct mmu_context_skas *to_mm = &mm->context.skas;
+ struct mm_context *from_mm = NULL;
+ struct mm_context *to_mm = &mm->context;
unsigned long stack = 0;
int ret = -ENOMEM;
- if(skas_needs_stub){
+ if (skas_needs_stub) {
stack = get_zeroed_page(GFP_KERNEL);
- if(stack == 0)
+ if (stack == 0)
goto out;
- /* This zeros the entry that pgd_alloc didn't, needed since
+ /*
+ * This zeros the entry that pgd_alloc didn't, needed since
* we are about to reinitialize it, and want mm.nr_ptes to
* be accurate.
*/
mm->pgd[USER_PTRS_PER_PGD] = __pgd(0);
- ret = init_stub_pte(mm, CONFIG_STUB_CODE,
+ ret = init_stub_pte(mm, STUB_CODE,
(unsigned long) &__syscall_stub_start);
- if(ret)
+ if (ret)
goto out_free;
- ret = init_stub_pte(mm, CONFIG_STUB_DATA, stack);
- if(ret)
+ ret = init_stub_pte(mm, STUB_DATA, stack);
+ if (ret)
goto out_free;
mm->nr_ptes--;
}
to_mm->id.stack = stack;
- if(current->mm != NULL && current->mm != &init_mm)
- from_mm = &current->mm->context.skas;
+ if (current->mm != NULL && current->mm != &init_mm)
+ from_mm = &current->mm->context;
- if(proc_mm){
+ if (proc_mm) {
ret = new_mm(stack);
- if(ret < 0){
- printk("init_new_context_skas - new_mm failed, "
- "errno = %d\n", ret);
+ if (ret < 0) {
+ printk(KERN_ERR "init_new_context_skas - "
+ "new_mm failed, errno = %d\n", ret);
goto out_free;
}
to_mm->id.u.mm_fd = ret;
}
else {
- if(from_mm)
+ 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"
+ if (ret < 0) {
+ printk(KERN_ERR "init_new_context_skas - init_ldt"
" failed, errno = %d\n", ret);
goto out_free;
}
@@ -131,22 +126,22 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
return 0;
out_free:
- if(to_mm->id.stack != 0)
+ if (to_mm->id.stack != 0)
free_page(to_mm->id.stack);
out:
return ret;
}
-void destroy_context_skas(struct mm_struct *mm)
+void destroy_context(struct mm_struct *mm)
{
- struct mmu_context_skas *mmu = &mm->context.skas;
+ struct mm_context *mmu = &mm->context;
- if(proc_mm)
+ if (proc_mm)
os_close_file(mmu->id.u.mm_fd);
else
os_kill_ptraced_process(mmu->id.u.pid, 1);
- if(!proc_mm || !ptrace_faultinfo){
+ 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);
@@ -155,4 +150,6 @@ void destroy_context_skas(struct mm_struct *mm)
pmd_free((pmd_t *) mmu->last_pmd);
#endif
}
+
+ free_ldt(mmu);
}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 48051a98525..fce389c2342 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -1,146 +1,26 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/sched.h"
-#include "linux/slab.h"
-#include "linux/ptrace.h"
-#include "linux/proc_fs.h"
-#include "linux/file.h"
-#include "linux/errno.h"
#include "linux/init.h"
-#include "asm/uaccess.h"
-#include "asm/atomic.h"
-#include "kern_util.h"
+#include "linux/sched.h"
#include "as-layout.h"
-#include "skas.h"
#include "os.h"
-#include "tlb.h"
-#include "kern.h"
-#include "mode.h"
-#include "registers.h"
-
-void switch_to_skas(void *prev, void *next)
-{
- struct task_struct *from, *to;
-
- from = prev;
- to = next;
-
- /* XXX need to check runqueues[cpu].idle */
- if(current->pid == 0)
- switch_timers(0);
-
- switch_threads(&from->thread.mode.skas.switch_buf,
- &to->thread.mode.skas.switch_buf);
-
- arch_switch_to_skas(current->thread.prev_sched, current);
-
- if(current->pid == 0)
- switch_timers(1);
-}
-
-extern void schedule_tail(struct task_struct *prev);
-
-/* This is called magically, by its address being stuffed in a jmp_buf
- * and being longjmp-d to.
- */
-void new_thread_handler(void)
-{
- int (*fn)(void *), n;
- void *arg;
-
- if(current->thread.prev_sched != NULL)
- schedule_tail(current->thread.prev_sched);
- current->thread.prev_sched = NULL;
-
- fn = current->thread.request.u.thread.proc;
- arg = current->thread.request.u.thread.arg;
-
- /* The return value is 1 if the kernel thread execs a process,
- * 0 if it just exits
- */
- n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
- if(n == 1){
- /* Handle any immediate reschedules or signals */
- interrupt_end();
- userspace(&current->thread.regs.regs);
- }
- else do_exit(0);
-}
-
-void release_thread_skas(struct task_struct *task)
-{
-}
-
-/* Called magically, see new_thread_handler above */
-void fork_handler(void)
-{
- force_flush_all();
- if(current->thread.prev_sched == NULL)
- panic("blech");
-
- schedule_tail(current->thread.prev_sched);
-
- /* XXX: if interrupt_end() calls schedule, this call to
- * arch_switch_to_skas isn't needed. We could want to apply this to
- * improve performance. -bb */
- arch_switch_to_skas(current->thread.prev_sched, current);
-
- current->thread.prev_sched = NULL;
-
-/* Handle any immediate reschedules or signals */
- interrupt_end();
-
- userspace(&current->thread.regs.regs);
-}
-
-int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
- unsigned long stack_top, struct task_struct * p,
- struct pt_regs *regs)
-{
- void (*handler)(void);
-
- if(current->thread.forking){
- memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
- sizeof(p->thread.regs.regs.skas));
- REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
- if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
-
- handler = fork_handler;
-
- arch_copy_thread(&current->thread.arch, &p->thread.arch);
- }
- else {
- init_thread_registers(&p->thread.regs.regs);
- p->thread.request.u.thread = current->thread.request.u.thread;
- handler = new_thread_handler;
- }
-
- new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
- handler);
- return(0);
-}
+#include "skas.h"
int new_mm(unsigned long stack)
{
int fd;
fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
- if(fd < 0)
- return(fd);
+ if (fd < 0)
+ return fd;
- if(skas_needs_stub)
- map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
+ if (skas_needs_stub)
+ map_stub_pages(fd, STUB_CODE, STUB_DATA, stack);
- return(fd);
-}
-
-void init_idle_skas(void)
-{
- cpu_tasks[current_thread->cpu].pid = os_getpid();
- default_idle();
+ return fd;
}
extern void start_kernel(void);
@@ -158,67 +38,32 @@ static int __init start_kernel_proc(void *unused)
cpu_online_map = cpumask_of_cpu(0);
#endif
start_kernel();
- return(0);
+ return 0;
}
extern int userspace_pid[];
extern char cpu0_irqstack[];
-int __init start_uml_skas(void)
+int __init start_uml(void)
{
stack_protections((unsigned long) &cpu0_irqstack);
set_sigstack(cpu0_irqstack, THREAD_SIZE);
- if(proc_mm)
+ if (proc_mm)
userspace_pid[0] = start_userspace(0);
init_new_thread_signals();
init_task.thread.request.u.thread.proc = start_kernel_proc;
init_task.thread.request.u.thread.arg = NULL;
- return(start_idle_thread(task_stack_page(&init_task),
- &init_task.thread.mode.skas.switch_buf));
-}
-
-int external_pid_skas(struct task_struct *task)
-{
- /* FIXME: Need to look up userspace_pid by cpu */
- return(userspace_pid[0]);
-}
-
-int thread_pid_skas(struct task_struct *task)
-{
- /* FIXME: Need to look up userspace_pid by cpu */
- return(userspace_pid[0]);
-}
-
-void kill_off_processes_skas(void)
-{
- if(proc_mm)
- /*
- * FIXME: need to loop over userspace_pids in
- * kill_off_processes_skas
- */
- os_kill_ptraced_process(userspace_pid[0], 1);
- else {
- struct task_struct *p;
- int pid, me;
-
- me = os_getpid();
- for_each_process(p){
- if(p->mm == NULL)
- continue;
-
- pid = p->mm->context.skas.id.u.pid;
- os_kill_ptraced_process(pid, 1);
- }
- }
+ return start_idle_thread(task_stack_page(&init_task),
+ &init_task.thread.switch_buf);
}
unsigned long current_stub_stack(void)
{
- if(current->mm == NULL)
- return(0);
+ if (current->mm == NULL)
+ return 0;
- return(current->mm->context.skas.id.stack);
+ return current->mm->context.id.stack;
}
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c
index 0ae4eea21be..50b476f2b38 100644
--- a/arch/um/kernel/skas/syscall.c
+++ b/arch/um/kernel/skas/syscall.c
@@ -1,19 +1,15 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/sys.h"
+#include "linux/kernel.h"
#include "linux/ptrace.h"
-#include "asm/errno.h"
-#include "asm/unistd.h"
-#include "asm/ptrace.h"
-#include "asm/current.h"
-#include "sysdep/syscalls.h"
#include "kern_util.h"
-#include "syscall.h"
+#include "sysdep/ptrace.h"
+#include "sysdep/syscalls.h"
-void handle_syscall(union uml_pt_regs *r)
+void handle_syscall(struct uml_pt_regs *r)
{
struct pt_regs *regs = container_of(r, struct pt_regs, regs);
long result;
@@ -24,7 +20,8 @@ void handle_syscall(union uml_pt_regs *r)
current->thread.nsyscalls++;
nsyscalls++;
- /* This should go in the declaration of syscall, but when I do that,
+ /*
+ * This should go in the declaration of syscall, but when I do that,
* strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing
* children at all, sometimes hanging when bash doesn't see the first
* ls exit.
@@ -33,11 +30,11 @@ void handle_syscall(union uml_pt_regs *r)
* in case it's a compiler bug.
*/
syscall = UPT_SYSCALL_NR(r);
- if((syscall >= NR_syscalls) || (syscall < 0))
+ if ((syscall >= NR_syscalls) || (syscall < 0))
result = -ENOSYS;
else result = EXECUTE_SYSCALL(syscall, regs);
- REGS_SET_SYSCALL_RETURN(r->skas.regs, result);
+ REGS_SET_SYSCALL_RETURN(r->gp, result);
syscall_trace(r, 1);
}
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c
deleted file mode 100644
index c0f0693743b..00000000000
--- a/arch/um/kernel/skas/tlb.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Copyright 2003 PathScale, Inc.
- * Licensed under the GPL
- */
-
-#include "linux/stddef.h"
-#include "linux/sched.h"
-#include "linux/mm.h"
-#include "asm/page.h"
-#include "asm/pgtable.h"
-#include "asm/mmu.h"
-#include "mem_user.h"
-#include "mem.h"
-#include "skas.h"
-#include "os.h"
-#include "tlb.h"
-
-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, ret = 0;
-
- for(i = 0; i <= last && !ret; i++){
- op = &ops[i];
- switch(op->type){
- case MMAP:
- ret = map(&mmu->skas.id, op->u.mmap.addr,
- op->u.mmap.len, op->u.mmap.prot,
- op->u.mmap.fd, op->u.mmap.offset, finished,
- flush);
- break;
- case MUNMAP:
- ret = unmap(&mmu->skas.id, op->u.munmap.addr,
- op->u.munmap.len, finished, flush);
- break;
- case MPROTECT:
- ret = protect(&mmu->skas.id, op->u.mprotect.addr,
- op->u.mprotect.len, op->u.mprotect.prot,
- finished, flush);
- break;
- default:
- printk("Unknown op type %d in do_ops\n", op->type);
- break;
- }
- }
-
- return ret;
-}
-
-extern int proc_mm;
-
-static void fix_range(struct mm_struct *mm, unsigned long start_addr,
- unsigned long end_addr, int force)
-{
- if(!proc_mm && (end_addr > CONFIG_STUB_START))
- end_addr = CONFIG_STUB_START;
-
- fix_range_common(mm, start_addr, end_addr, force, do_ops);
-}
-
-void __flush_tlb_one_skas(unsigned long addr)
-{
- flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE);
-}
-
-void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
-{
- if(vma->vm_mm == NULL)
- flush_tlb_kernel_range_common(start, end);
- else fix_range(vma->vm_mm, start, end, 0);
-}
-
-void flush_tlb_mm_skas(struct mm_struct *mm)
-{
- unsigned long end;
-
- /* Don't bother flushing if this address space is about to be
- * destroyed.
- */
- if(atomic_read(&mm->mm_users) == 0)
- return;
-
- end = proc_mm ? task_size : CONFIG_STUB_START;
- fix_range(mm, 0, end, 0);
-}
-
-void force_flush_all_skas(void)
-{
- struct mm_struct *mm = current->mm;
- struct vm_area_struct *vma = mm->mmap;
-
- while(vma != NULL) {
- fix_range(mm, vma->vm_start, vma->vm_end, 1);
- vma = vma->vm_next;
- }
-}
-
-void flush_tlb_page_skas(struct vm_area_struct *vma, unsigned long address)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- struct mm_struct *mm = vma->vm_mm;
- void *flush = NULL;
- int r, w, x, prot, err = 0;
- struct mm_id *mm_id;
-
- pgd = pgd_offset(mm, address);
- if(!pgd_present(*pgd))
- goto kill;
-
- pud = pud_offset(pgd, address);
- if(!pud_present(*pud))
- goto kill;
-
- pmd = pmd_offset(pud, address);
- if(!pmd_present(*pmd))
- goto kill;
-
- pte = pte_offset_kernel(pmd, address);
-
- r = pte_read(*pte);
- w = pte_write(*pte);
- x = pte_exec(*pte);
- if (!pte_young(*pte)) {
- r = 0;
- w = 0;
- } else if (!pte_dirty(*pte)) {
- w = 0;
- }
-
- mm_id = &mm->context.skas.id;
- prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
- (x ? UM_PROT_EXEC : 0));
- if(pte_newpage(*pte)){
- if(pte_present(*pte)){
- unsigned long long offset;
- int fd;
-
- fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset);
- err = map(mm_id, address, PAGE_SIZE, prot, fd, offset,
- 1, &flush);
- }
- else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush);
- }
- else if(pte_newprot(*pte))
- err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush);
-
- if(err)
- goto kill;
-
- *pte = pte_mkuptodate(*pte);
-
- return;
-
-kill:
- printk("Failed to flush page for address 0x%lx\n", address);
- force_sig(SIGKILL, current);
-}
-
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 8912cec0fe4..1d8b119f2d0 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -1,18 +1,14 @@
/*
- * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/compiler.h"
-#include "linux/stddef.h"
-#include "linux/kernel.h"
-#include "linux/string.h"
-#include "linux/fs.h"
-#include "linux/hardirq.h"
+#include "linux/err.h"
#include "linux/highmem.h"
+#include "linux/mm.h"
+#include "asm/current.h"
#include "asm/page.h"
#include "asm/pgtable.h"
-#include "asm/uaccess.h"
#include "kern_util.h"
#include "os.h"
@@ -27,16 +23,16 @@ static unsigned long maybe_map(unsigned long virt, int is_write)
void *phys = um_virt_to_phys(current, virt, &pte);
int dummy_code;
- if(IS_ERR(phys) || (is_write && !pte_write(pte))){
+ if (IS_ERR(phys) || (is_write && !pte_write(pte))) {
err = handle_page_fault(virt, 0, is_write, 1, &dummy_code);
- if(err)
- return(-1UL);
+ if (err)
+ return -1UL;
phys = um_virt_to_phys(current, virt, NULL);
}
- if(IS_ERR(phys))
- phys = (void *) -1;
+ if (IS_ERR(phys))
+ phys = (void *) -1;
- return((unsigned long) phys);
+ return (unsigned long) phys;
}
static int do_op_one_page(unsigned long addr, int len, int is_write,
@@ -46,17 +42,18 @@ static int do_op_one_page(unsigned long addr, int len, int is_write,
int n;
addr = maybe_map(addr, is_write);
- if(addr == -1UL)
- return(-1);
+ if (addr == -1UL)
+ return -1;
page = phys_to_page(addr);
- addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + (addr & ~PAGE_MASK);
+ addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) +
+ (addr & ~PAGE_MASK);
n = (*op)(addr, len, arg);
kunmap_atomic(page, KM_UML_USERCOPY);
- return(n);
+ return n;
}
static void do_buffer_op(void *jmpbuf, void *arg_ptr)
@@ -81,21 +78,21 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr)
current->thread.fault_catcher = jmpbuf;
n = do_op_one_page(addr, size, is_write, op, arg);
- if(n != 0){
+ if (n != 0) {
*res = (n < 0 ? remain : 0);
goto out;
}
addr += size;
remain -= size;
- if(remain == 0){
+ if (remain == 0) {
*res = 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){
+ if (n != 0) {
*res = (n < 0 ? remain : 0);
goto out;
}
@@ -103,13 +100,13 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr)
addr += PAGE_SIZE;
remain -= PAGE_SIZE;
}
- if(remain == 0){
+ if (remain == 0) {
*res = 0;
goto out;
}
n = do_op_one_page(addr, remain, is_write, op, arg);
- if(n != 0)
+ if (n != 0)
*res = (n < 0 ? remain : 0);
else *res = 0;
out:
@@ -124,10 +121,10 @@ static int buffer_op(unsigned long addr, int len, int is_write,
faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg,
&res);
- if(!faulted)
- return(res);
+ if (!faulted)
+ return res;
- return(addr + len - (unsigned long) current->thread.fault_addr);
+ return addr + len - (unsigned long) current->thread.fault_addr;
}
static int copy_chunk_from_user(unsigned long from, int len, void *arg)
@@ -136,19 +133,19 @@ static int copy_chunk_from_user(unsigned long from, int len, void *arg)
memcpy((void *) to, (void *) from, len);
*to_ptr += len;
- return(0);
+ return 0;
}
-int copy_from_user_skas(void *to, const void __user *from, int n)
+int copy_from_user(void *to, const void __user *from, int n)
{
- if(segment_eq(get_fs(), KERNEL_DS)){
+ if (segment_eq(get_fs(), KERNEL_DS)) {
memcpy(to, (__force void*)from, n);
- return(0);
+ return 0;
}
- return(access_ok(VERIFY_READ, from, n) ?
+ return access_ok(VERIFY_READ, from, n) ?
buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to):
- n);
+ n;
}
static int copy_chunk_to_user(unsigned long to, int len, void *arg)
@@ -157,19 +154,19 @@ static int copy_chunk_to_user(unsigned long to, int len, void *arg)
memcpy((void *) to, (void *) from, len);
*from_ptr += len;
- return(0);
+ return 0;
}
-int copy_to_user_skas(void __user *to, const void *from, int n)
+int copy_to_user(void __user *to, const void *from, int n)
{
- if(segment_eq(get_fs(), KERNEL_DS)){
- memcpy((__force void*)to, from, n);
- return(0);
+ if (segment_eq(get_fs(), KERNEL_DS)) {
+ memcpy((__force void *) to, from, n);
+ return 0;
}
- return(access_ok(VERIFY_WRITE, to, n) ?
+ return access_ok(VERIFY_WRITE, to, n) ?
buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) :
- n);
+ n;
}
static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
@@ -181,51 +178,51 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
n = strnlen(to, len);
*to_ptr += n;
- if(n < len)
- return(1);
- return(0);
+ if (n < len)
+ return 1;
+ return 0;
}
-int strncpy_from_user_skas(char *dst, const char __user *src, int count)
+int strncpy_from_user(char *dst, const char __user *src, int count)
{
int n;
char *ptr = dst;
- if(segment_eq(get_fs(), KERNEL_DS)){
- strncpy(dst, (__force void*)src, count);
- return(strnlen(dst, count));
+ if (segment_eq(get_fs(), KERNEL_DS)) {
+ strncpy(dst, (__force void *) src, count);
+ return strnlen(dst, count);
}
- if(!access_ok(VERIFY_READ, src, 1))
- return(-EFAULT);
+ if (!access_ok(VERIFY_READ, src, 1))
+ return -EFAULT;
n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user,
&ptr);
- if(n != 0)
- return(-EFAULT);
- return(strnlen(dst, count));
+ if (n != 0)
+ return -EFAULT;
+ return strnlen(dst, count);
}
static int clear_chunk(unsigned long addr, int len, void *unused)
{
memset((void *) addr, 0, len);
- return(0);
+ return 0;
}
-int __clear_user_skas(void __user *mem, int len)
+int __clear_user(void __user *mem, int len)
{
- return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL));
+ return buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL);
}
-int clear_user_skas(void __user *mem, int len)
+int clear_user(void __user *mem, int len)
{
- if(segment_eq(get_fs(), KERNEL_DS)){
+ if (segment_eq(get_fs(), KERNEL_DS)) {
memset((__force void*)mem, 0, len);
- return(0);
+ return 0;
}
- return(access_ok(VERIFY_WRITE, mem, len) ?
- buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len);
+ return access_ok(VERIFY_WRITE, mem, len) ?
+ buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len;
}
static int strnlen_chunk(unsigned long str, int len, void *arg)
@@ -235,31 +232,20 @@ static int strnlen_chunk(unsigned long str, int len, void *arg)
n = strnlen((void *) str, len);
*len_ptr += n;
- if(n < len)
- return(1);
- return(0);
+ if (n < len)
+ return 1;
+ return 0;
}
-int strnlen_user_skas(const void __user *str, int len)
+int strnlen_user(const void __user *str, int len)
{
int count = 0, n;
- if(segment_eq(get_fs(), KERNEL_DS))
- return(strnlen((__force char*)str, len) + 1);
+ if (segment_eq(get_fs(), KERNEL_DS))
+ return strnlen((__force char*)str, len) + 1;
n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count);
- if(n == 0)
- return(count + 1);
- return(-EFAULT);
+ if (n == 0)
+ return count + 1;
+ return -EFAULT;
}
-
-/*
- * 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/smp.c b/arch/um/kernel/smp.c
index e6a7778006a..36d89cf8d20 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -56,12 +56,12 @@ void smp_send_stop(void)
int i;
printk(KERN_INFO "Stopping all CPUs...");
- for(i = 0; i < num_online_cpus(); i++){
- if(i == current_thread->cpu)
+ for (i = 0; i < num_online_cpus(); i++) {
+ if (i == current_thread->cpu)
continue;
os_write_file(cpu_data[i].ipi_pipe[1], "S", 1);
}
- printk("done\n");
+ printk(KERN_INFO "done\n");
}
static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
@@ -72,7 +72,7 @@ static int idle_proc(void *cpup)
int cpu = (int) cpup, err;
err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1);
- if(err < 0)
+ if (err < 0)
panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
os_set_fd_async(cpu_data[cpu].ipi_pipe[0],
@@ -80,7 +80,7 @@ static int idle_proc(void *cpup)
wmb();
if (cpu_test_and_set(cpu, cpu_callin_map)) {
- printk("huh, CPU#%d already present??\n", cpu);
+ printk(KERN_ERR "huh, CPU#%d already present??\n", cpu);
BUG();
}
@@ -95,12 +95,11 @@ static int idle_proc(void *cpup)
static struct task_struct *idle_thread(int cpu)
{
struct task_struct *new_task;
- unsigned char c;
current->thread.request.u.thread.proc = idle_proc;
current->thread.request.u.thread.arg = (void *) cpu;
new_task = fork_idle(cpu);
- if(IS_ERR(new_task))
+ if (IS_ERR(new_task))
panic("copy_process failed in idle_thread, error = %ld",
PTR_ERR(new_task));
@@ -108,9 +107,7 @@ static struct task_struct *idle_thread(int cpu)
{ .pid = new_task->thread.mode.tt.extern_pid,
.task = new_task } );
idle_threads[cpu] = new_task;
- CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c,
- sizeof(c)),
- ({ panic("skas mode doesn't support SMP"); }));
+ panic("skas mode doesn't support SMP");
return new_task;
}
@@ -129,14 +126,14 @@ void smp_prepare_cpus(unsigned int maxcpus)
cpu_set(me, cpu_callin_map);
err = os_pipe(cpu_data[me].ipi_pipe, 1, 1);
- if(err < 0)
+ if (err < 0)
panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
os_set_fd_async(cpu_data[me].ipi_pipe[0],
current->thread.mode.tt.extern_pid);
- for(cpu = 1; cpu < ncpus; cpu++){
- printk("Booting processor %d...\n", cpu);
+ for (cpu = 1; cpu < ncpus; cpu++) {
+ printk(KERN_INFO "Booting processor %d...\n", cpu);
idle = idle_thread(cpu);
@@ -147,8 +144,8 @@ void smp_prepare_cpus(unsigned int maxcpus)
cpu_relax();
if (cpu_isset(cpu, cpu_callin_map))
- printk("done\n");
- else printk("failed\n");
+ printk(KERN_INFO "done\n");
+ else printk(KERN_INFO "failed\n");
}
}
@@ -190,13 +187,14 @@ void IPI_handler(int cpu)
break;
case 'S':
- printk("CPU#%d stopping\n", cpu);
- while(1)
+ printk(KERN_INFO "CPU#%d stopping\n", cpu);
+ while (1)
pause();
break;
default:
- printk("CPU#%d received unknown IPI [%c]!\n", cpu, c);
+ printk(KERN_ERR "CPU#%d received unknown IPI [%c]!\n",
+ cpu, c);
break;
}
}
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index 7b3b67333ff..b9d92b2089a 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -1,27 +1,17 @@
/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/sched.h"
#include "linux/file.h"
-#include "linux/smp_lock.h"
-#include "linux/mm.h"
#include "linux/fs.h"
+#include "linux/mm.h"
+#include "linux/sched.h"
#include "linux/utsname.h"
-#include "linux/msg.h"
-#include "linux/shm.h"
-#include "linux/sys.h"
-#include "linux/syscalls.h"
-#include "linux/unistd.h"
-#include "linux/slab.h"
-#include "linux/utime.h"
+#include "asm/current.h"
#include "asm/mman.h"
#include "asm/uaccess.h"
-#include "kern_util.h"
-#include "sysdep/syscalls.h"
-#include "mode_kern.h"
-#include "choose-mode.h"
+#include "asm/unistd.h"
/* Unlocked, I don't care if this is a bit off */
int nsyscalls = 0;
@@ -34,7 +24,7 @@ long sys_fork(void)
ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
&current->thread.regs, 0, NULL, NULL);
current->thread.forking = 0;
- return(ret);
+ return ret;
}
long sys_vfork(void)
@@ -46,7 +36,7 @@ long sys_vfork(void)
UPT_SP(&current->thread.regs.regs),
&current->thread.regs, 0, NULL, NULL);
current->thread.forking = 0;
- return(ret);
+ return ret;
}
/* common code for old and new mmaps */
@@ -92,15 +82,15 @@ long old_mmap(unsigned long addr, unsigned long len,
*/
long sys_pipe(unsigned long __user * fildes)
{
- int fd[2];
- long error;
+ int fd[2];
+ long error;
- error = do_pipe(fd);
- if (!error) {
+ error = do_pipe(fd);
+ if (!error) {
if (copy_to_user(fildes, fd, sizeof(fd)))
- error = -EFAULT;
- }
- return error;
+ error = -EFAULT;
+ }
+ return error;
}
@@ -124,7 +114,7 @@ long sys_olduname(struct oldold_utsname __user * name)
if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
return -EFAULT;
- down_read(&uts_sem);
+ down_read(&uts_sem);
error = __copy_to_user(&name->sysname, &utsname()->sysname,
__OLD_UTS_LEN);
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 259c49da7ff..1ac746a9eae 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -1,189 +1,126 @@
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/module.h"
-#include "linux/unistd.h"
-#include "linux/stddef.h"
-#include "linux/spinlock.h"
-#include "linux/time.h"
-#include "linux/sched.h"
+#include "linux/clockchips.h"
#include "linux/interrupt.h"
-#include "linux/init.h"
-#include "linux/delay.h"
-#include "linux/hrtimer.h"
+#include "linux/jiffies.h"
+#include "linux/threads.h"
#include "asm/irq.h"
#include "asm/param.h"
-#include "asm/current.h"
#include "kern_util.h"
-#include "mode.h"
#include "os.h"
-int hz(void)
-{
- return(HZ);
-}
-
/*
* Scheduler clock - returns current time in nanosec units.
*/
unsigned long long sched_clock(void)
{
- return (unsigned long long)jiffies_64 * (1000000000 / HZ);
+ return (unsigned long long)jiffies_64 * (NSEC_PER_SEC / HZ);
}
-#ifdef CONFIG_UML_REAL_TIME_CLOCK
-static unsigned long long prev_nsecs[NR_CPUS];
-static long long delta[NR_CPUS]; /* Deviation per interval */
-#endif
+void timer_handler(int sig, struct uml_pt_regs *regs)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ do_IRQ(TIMER_IRQ, regs);
+ local_irq_restore(flags);
+}
-void timer_irq(union uml_pt_regs *regs)
+static void itimer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
{
- unsigned long long ticks = 0;
-#ifdef CONFIG_UML_REAL_TIME_CLOCK
- int c = cpu();
- if(prev_nsecs[c]){
- /* We've had 1 tick */
- unsigned long long nsecs = os_nsecs();
-
- delta[c] += nsecs - prev_nsecs[c];
- prev_nsecs[c] = nsecs;
-
- /* Protect against the host clock being set backwards */
- if(delta[c] < 0)
- delta[c] = 0;
-
- ticks += (delta[c] * HZ) / BILLION;
- delta[c] -= (ticks * BILLION) / HZ;
- }
- else prev_nsecs[c] = os_nsecs();
-#else
- ticks = 1;
-#endif
- while(ticks > 0){
- do_IRQ(TIMER_IRQ, regs);
- ticks--;
+ switch(mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ set_interval();
+ break;
+
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_ONESHOT:
+ disable_timer();
+ break;
+
+ case CLOCK_EVT_MODE_RESUME:
+ break;
}
}
-/* Protects local_offset */
-static DEFINE_SPINLOCK(timer_spinlock);
-static unsigned long long local_offset = 0;
-
-static inline unsigned long long get_time(void)
+static int itimer_next_event(unsigned long delta,
+ struct clock_event_device *evt)
{
- unsigned long long nsecs;
- unsigned long flags;
-
- spin_lock_irqsave(&timer_spinlock, flags);
- nsecs = os_nsecs();
- nsecs += local_offset;
- spin_unlock_irqrestore(&timer_spinlock, flags);
-
- return nsecs;
+ return timer_one_shot(delta + 1);
}
-irqreturn_t um_timer(int irq, void *dev)
+static struct clock_event_device itimer_clockevent = {
+ .name = "itimer",
+ .rating = 250,
+ .cpumask = CPU_MASK_ALL,
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_mode = itimer_set_mode,
+ .set_next_event = itimer_next_event,
+ .shift = 32,
+ .irq = 0,
+};
+
+static irqreturn_t um_timer(int irq, void *dev)
{
- unsigned long long nsecs;
- unsigned long flags;
-
- write_seqlock_irqsave(&xtime_lock, flags);
-
- do_timer(1);
-
-#ifdef CONFIG_UML_REAL_TIME_CLOCK
- nsecs = get_time();
-#else
- nsecs = (unsigned long long) xtime.tv_sec * BILLION + xtime.tv_nsec +
- BILLION / HZ;
-#endif
- xtime.tv_sec = nsecs / NSEC_PER_SEC;
- xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
-
- write_sequnlock_irqrestore(&xtime_lock, flags);
+ (*itimer_clockevent.event_handler)(&itimer_clockevent);
return IRQ_HANDLED;
}
-static void register_timer(void)
+static cycle_t itimer_read(void)
+{
+ return os_nsecs();
+}
+
+static struct clocksource itimer_clocksource = {
+ .name = "itimer",
+ .rating = 300,
+ .read = itimer_read,
+ .mask = CLOCKSOURCE_MASK(64),
+ .mult = 1,
+ .shift = 0,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init setup_itimer(void)
{
int err;
err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL);
- if(err != 0)
+ if (err != 0)
printk(KERN_ERR "register_timer : request_irq failed - "
"errno = %d\n", -err);
- err = set_interval(1);
- if(err != 0)
- printk(KERN_ERR "register_timer : set_interval failed - "
- "errno = %d\n", -err);
+ itimer_clockevent.mult = div_sc(HZ, NSEC_PER_SEC, 32);
+ itimer_clockevent.max_delta_ns =
+ clockevent_delta2ns(60 * HZ, &itimer_clockevent);
+ itimer_clockevent.min_delta_ns =
+ clockevent_delta2ns(1, &itimer_clockevent);
+ err = clocksource_register(&itimer_clocksource);
+ if (err) {
+ printk(KERN_ERR "clocksource_register returned %d\n", err);
+ return;
+ }
+ clockevents_register_device(&itimer_clockevent);
}
extern void (*late_time_init)(void);
-void time_init(void)
+void __init time_init(void)
{
long long nsecs;
- nsecs = os_nsecs();
- set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION,
- -nsecs % BILLION);
- set_normalized_timespec(&xtime, nsecs / BILLION, nsecs % BILLION);
- late_time_init = register_timer;
-}
-
-void do_gettimeofday(struct timeval *tv)
-{
-#ifdef CONFIG_UML_REAL_TIME_CLOCK
- unsigned long long nsecs = get_time();
-#else
- unsigned long long nsecs = (unsigned long long) xtime.tv_sec * BILLION +
- xtime.tv_nsec;
-#endif
- tv->tv_sec = nsecs / NSEC_PER_SEC;
- /* Careful about calculations here - this was originally done as
- * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
- * which gave bogus (> 1000000) values. Dunno why, suspect gcc
- * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion
- * problem that I missed.
- */
- nsecs -= tv->tv_sec * NSEC_PER_SEC;
- tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC;
-}
-
-static inline void set_time(unsigned long long nsecs)
-{
- unsigned long long now;
- unsigned long flags;
-
- spin_lock_irqsave(&timer_spinlock, flags);
- now = os_nsecs();
- local_offset = nsecs - now;
- spin_unlock_irqrestore(&timer_spinlock, flags);
-
- clock_was_set();
-}
-
-int do_settimeofday(struct timespec *tv)
-{
- set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec);
-
- return 0;
-}
+ timer_init();
-void timer_handler(int sig, union uml_pt_regs *regs)
-{
- if(current_thread->cpu == 0)
- timer_irq(regs);
- local_irq_disable();
- irq_enter();
- update_process_times(CHOOSE_MODE(
- (UPT_SC(regs) && user_context(UPT_SP(regs))),
- (regs)->skas.is_user));
- irq_exit();
- local_irq_enable();
+ nsecs = os_nsecs();
+ set_normalized_timespec(&wall_to_monotonic, -nsecs / NSEC_PER_SEC,
+ -nsecs % NSEC_PER_SEC);
+ set_normalized_timespec(&xtime, nsecs / NSEC_PER_SEC,
+ nsecs % NSEC_PER_SEC);
+ late_time_init = setup_itimer;
}
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 8a8d5285144..f4a0e407eee 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -1,130 +1,182 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include "linux/mm.h"
-#include "asm/page.h"
-#include "asm/pgalloc.h"
#include "asm/pgtable.h"
#include "asm/tlbflush.h"
-#include "choose-mode.h"
-#include "mode_kern.h"
#include "as-layout.h"
-#include "tlb.h"
-#include "mem.h"
#include "mem_user.h"
#include "os.h"
+#include "skas.h"
+#include "tlb.h"
+
+struct host_vm_change {
+ struct host_vm_op {
+ enum { NONE, MMAP, MUNMAP, MPROTECT } type;
+ union {
+ struct {
+ unsigned long addr;
+ unsigned long len;
+ unsigned int prot;
+ int fd;
+ __u64 offset;
+ } mmap;
+ struct {
+ unsigned long addr;
+ unsigned long len;
+ } munmap;
+ struct {
+ unsigned long addr;
+ unsigned long len;
+ unsigned int prot;
+ } mprotect;
+ } u;
+ } ops[1];
+ int index;
+ struct mm_id *id;
+ void *data;
+ int force;
+};
+
+#define INIT_HVC(mm, force) \
+ ((struct host_vm_change) \
+ { .ops = { { .type = NONE } }, \
+ .id = &mm->context.id, \
+ .data = NULL, \
+ .index = 0, \
+ .force = force })
+
+static int do_ops(struct host_vm_change *hvc, int end,
+ int finished)
+{
+ struct host_vm_op *op;
+ int i, ret = 0;
+
+ for (i = 0; i < end && !ret; i++) {
+ op = &hvc->ops[i];
+ switch(op->type) {
+ case MMAP:
+ ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len,
+ op->u.mmap.prot, op->u.mmap.fd,
+ op->u.mmap.offset, finished, &hvc->data);
+ break;
+ case MUNMAP:
+ ret = unmap(hvc->id, op->u.munmap.addr,
+ op->u.munmap.len, finished, &hvc->data);
+ break;
+ case MPROTECT:
+ ret = protect(hvc->id, op->u.mprotect.addr,
+ op->u.mprotect.len, op->u.mprotect.prot,
+ finished, &hvc->data);
+ break;
+ default:
+ printk(KERN_ERR "Unknown op type %d in do_ops\n",
+ op->type);
+ break;
+ }
+ }
+
+ return ret;
+}
static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
- unsigned int prot, struct host_vm_op *ops, int *index,
- int last_filled, union mm_context *mmu, void **flush,
- int (*do_ops)(union mm_context *, struct host_vm_op *,
- int, int, void **))
+ unsigned int prot, struct host_vm_change *hvc)
{
__u64 offset;
struct host_vm_op *last;
int fd, ret = 0;
fd = phys_mapping(phys, &offset);
- if(*index != -1){
- last = &ops[*index];
- if((last->type == MMAP) &&
+ if (hvc->index != 0) {
+ last = &hvc->ops[hvc->index - 1];
+ if ((last->type == MMAP) &&
(last->u.mmap.addr + last->u.mmap.len == virt) &&
(last->u.mmap.prot == prot) && (last->u.mmap.fd == fd) &&
- (last->u.mmap.offset + last->u.mmap.len == offset)){
+ (last->u.mmap.offset + last->u.mmap.len == offset)) {
last->u.mmap.len += len;
return 0;
}
}
- if(*index == last_filled){
- ret = (*do_ops)(mmu, ops, last_filled, 0, flush);
- *index = -1;
+ if (hvc->index == ARRAY_SIZE(hvc->ops)) {
+ ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0);
+ hvc->index = 0;
}
- ops[++*index] = ((struct host_vm_op) { .type = MMAP,
- .u = { .mmap = {
- .addr = virt,
- .len = len,
- .prot = prot,
- .fd = fd,
- .offset = offset }
+ hvc->ops[hvc->index++] = ((struct host_vm_op)
+ { .type = MMAP,
+ .u = { .mmap = { .addr = virt,
+ .len = len,
+ .prot = prot,
+ .fd = fd,
+ .offset = offset }
} });
return ret;
}
static int add_munmap(unsigned long addr, unsigned long len,
- struct host_vm_op *ops, int *index, int last_filled,
- union mm_context *mmu, void **flush,
- int (*do_ops)(union mm_context *, struct host_vm_op *,
- int, int, void **))
+ struct host_vm_change *hvc)
{
struct host_vm_op *last;
int ret = 0;
- if(*index != -1){
- last = &ops[*index];
- if((last->type == MUNMAP) &&
- (last->u.munmap.addr + last->u.mmap.len == addr)){
+ if (hvc->index != 0) {
+ last = &hvc->ops[hvc->index - 1];
+ if ((last->type == MUNMAP) &&
+ (last->u.munmap.addr + last->u.mmap.len == addr)) {
last->u.munmap.len += len;
return 0;
}
}
- if(*index == last_filled){
- ret = (*do_ops)(mmu, ops, last_filled, 0, flush);
- *index = -1;
+ if (hvc->index == ARRAY_SIZE(hvc->ops)) {
+ ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0);
+ hvc->index = 0;
}
- ops[++*index] = ((struct host_vm_op) { .type = MUNMAP,
- .u = { .munmap = {
- .addr = addr,
- .len = len } } });
+ hvc->ops[hvc->index++] = ((struct host_vm_op)
+ { .type = MUNMAP,
+ .u = { .munmap = { .addr = addr,
+ .len = len } } });
return ret;
}
static int add_mprotect(unsigned long addr, unsigned long len,
- unsigned int prot, struct host_vm_op *ops, int *index,
- int last_filled, union mm_context *mmu, void **flush,
- int (*do_ops)(union mm_context *, struct host_vm_op *,
- int, int, void **))
+ unsigned int prot, struct host_vm_change *hvc)
{
struct host_vm_op *last;
int ret = 0;
- if(*index != -1){
- last = &ops[*index];
- if((last->type == MPROTECT) &&
+ if (hvc->index != 0) {
+ last = &hvc->ops[hvc->index - 1];
+ if ((last->type == MPROTECT) &&
(last->u.mprotect.addr + last->u.mprotect.len == addr) &&
- (last->u.mprotect.prot == prot)){
+ (last->u.mprotect.prot == prot)) {
last->u.mprotect.len += len;
return 0;
}
}
- if(*index == last_filled){
- ret = (*do_ops)(mmu, ops, last_filled, 0, flush);
- *index = -1;
+ if (hvc->index == ARRAY_SIZE(hvc->ops)) {
+ ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0);
+ hvc->index = 0;
}
- ops[++*index] = ((struct host_vm_op) { .type = MPROTECT,
- .u = { .mprotect = {
- .addr = addr,
- .len = len,
- .prot = prot } } });
+ hvc->ops[hvc->index++] = ((struct host_vm_op)
+ { .type = MPROTECT,
+ .u = { .mprotect = { .addr = addr,
+ .len = len,
+ .prot = prot } } });
return ret;
}
#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
- unsigned long end, struct host_vm_op *ops,
- int last_op, int *op_index, int force,
- union mm_context *mmu, void **flush,
- int (*do_ops)(union mm_context *,
- struct host_vm_op *, int, int,
- void **))
+ unsigned long end,
+ struct host_vm_change *hvc)
{
pte_t *pte;
int r, w, x, prot, ret = 0;
@@ -142,29 +194,22 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
}
prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
(x ? UM_PROT_EXEC : 0));
- if(force || pte_newpage(*pte)){
- if(pte_present(*pte))
+ if (hvc->force || pte_newpage(*pte)) {
+ if (pte_present(*pte))
ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
- PAGE_SIZE, prot, ops, op_index,
- last_op, mmu, flush, do_ops);
- else ret = add_munmap(addr, PAGE_SIZE, ops, op_index,
- last_op, mmu, flush, do_ops);
+ PAGE_SIZE, prot, hvc);
+ else ret = add_munmap(addr, PAGE_SIZE, hvc);
}
- else if(pte_newprot(*pte))
- ret = add_mprotect(addr, PAGE_SIZE, prot, ops, op_index,
- last_op, mmu, flush, do_ops);
+ else if (pte_newprot(*pte))
+ ret = add_mprotect(addr, PAGE_SIZE, prot, hvc);
*pte = pte_mkuptodate(*pte);
} while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret));
return ret;
}
static inline int update_pmd_range(pud_t *pud, unsigned long addr,
- unsigned long end, struct host_vm_op *ops,
- int last_op, int *op_index, int force,
- union mm_context *mmu, void **flush,
- int (*do_ops)(union mm_context *,
- struct host_vm_op *, int, int,
- void **))
+ unsigned long end,
+ struct host_vm_change *hvc)
{
pmd_t *pmd;
unsigned long next;
@@ -173,28 +218,20 @@ static inline int update_pmd_range(pud_t *pud, unsigned long addr,
pmd = pmd_offset(pud, addr);
do {
next = pmd_addr_end(addr, end);
- if(!pmd_present(*pmd)){
- if(force || pmd_newpage(*pmd)){
- ret = add_munmap(addr, next - addr, ops,
- op_index, last_op, mmu,
- flush, do_ops);
+ if (!pmd_present(*pmd)) {
+ if (hvc->force || pmd_newpage(*pmd)) {
+ ret = add_munmap(addr, next - addr, hvc);
pmd_mkuptodate(*pmd);
}
}
- else ret = update_pte_range(pmd, addr, next, ops, last_op,
- op_index, force, mmu, flush,
- do_ops);
+ else ret = update_pte_range(pmd, addr, next, hvc);
} while (pmd++, addr = next, ((addr != end) && !ret));
return ret;
}
static inline int update_pud_range(pgd_t *pgd, unsigned long addr,
- unsigned long end, struct host_vm_op *ops,
- int last_op, int *op_index, int force,
- union mm_context *mmu, void **flush,
- int (*do_ops)(union mm_context *,
- struct host_vm_op *, int, int,
- void **))
+ unsigned long end,
+ struct host_vm_change *hvc)
{
pud_t *pud;
unsigned long next;
@@ -203,56 +240,45 @@ static inline int update_pud_range(pgd_t *pgd, unsigned long addr,
pud = pud_offset(pgd, addr);
do {
next = pud_addr_end(addr, end);
- if(!pud_present(*pud)){
- if(force || pud_newpage(*pud)){
- ret = add_munmap(addr, next - addr, ops,
- op_index, last_op, mmu,
- flush, do_ops);
+ if (!pud_present(*pud)) {
+ if (hvc->force || pud_newpage(*pud)) {
+ ret = add_munmap(addr, next - addr, hvc);
pud_mkuptodate(*pud);
}
}
- else ret = update_pmd_range(pud, addr, next, ops, last_op,
- op_index, force, mmu, flush,
- do_ops);
+ else ret = update_pmd_range(pud, addr, next, hvc);
} while (pud++, addr = next, ((addr != end) && !ret));
return ret;
}
void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
- unsigned long end_addr, int force,
- int (*do_ops)(union mm_context *, struct host_vm_op *,
- int, int, void **))
+ unsigned long end_addr, int force)
{
pgd_t *pgd;
- union mm_context *mmu = &mm->context;
- struct host_vm_op ops[1];
+ struct host_vm_change hvc;
unsigned long addr = start_addr, next;
- int ret = 0, last_op = ARRAY_SIZE(ops) - 1, op_index = -1;
- void *flush = NULL;
+ int ret = 0;
- ops[0].type = NONE;
+ hvc = INIT_HVC(mm, force);
pgd = pgd_offset(mm, addr);
do {
next = pgd_addr_end(addr, end_addr);
- if(!pgd_present(*pgd)){
- if (force || pgd_newpage(*pgd)){
- ret = add_munmap(addr, next - addr, ops,
- &op_index, last_op, mmu,
- &flush, do_ops);
+ if (!pgd_present(*pgd)) {
+ if (force || pgd_newpage(*pgd)) {
+ ret = add_munmap(addr, next - addr, &hvc);
pgd_mkuptodate(*pgd);
}
}
- else ret = update_pud_range(pgd, addr, next, ops, last_op,
- &op_index, force, mmu, &flush,
- do_ops);
+ else ret = update_pud_range(pgd, addr, next, &hvc);
} while (pgd++, addr = next, ((addr != end_addr) && !ret));
- if(!ret)
- ret = (*do_ops)(mmu, ops, op_index, 1, &flush);
+ if (!ret)
+ ret = do_ops(&hvc, hvc.index, 1);
/* This is not an else because ret is modified above */
- if(ret) {
- printk("fix_range_common: failed, killing current process\n");
+ if (ret) {
+ printk(KERN_ERR "fix_range_common: failed, killing current "
+ "process\n");
force_sig(SIGKILL, current);
}
}
@@ -268,17 +294,17 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
int updated = 0, err;
mm = &init_mm;
- for(addr = start; addr < end;){
+ for (addr = start; addr < end;) {
pgd = pgd_offset(mm, addr);
- if(!pgd_present(*pgd)){
+ if (!pgd_present(*pgd)) {
last = ADD_ROUND(addr, PGDIR_SIZE);
- if(last > end)
+ if (last > end)
last = end;
- if(pgd_newpage(*pgd)){
+ if (pgd_newpage(*pgd)) {
updated = 1;
err = os_unmap_memory((void *) addr,
last - addr);
- if(err < 0)
+ if (err < 0)
panic("munmap failed, errno = %d\n",
-err);
}
@@ -287,15 +313,15 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
}
pud = pud_offset(pgd, addr);
- if(!pud_present(*pud)){
+ if (!pud_present(*pud)) {
last = ADD_ROUND(addr, PUD_SIZE);
- if(last > end)
+ if (last > end)
last = end;
- if(pud_newpage(*pud)){
+ if (pud_newpage(*pud)) {
updated = 1;
err = os_unmap_memory((void *) addr,
last - addr);
- if(err < 0)
+ if (err < 0)
panic("munmap failed, errno = %d\n",
-err);
}
@@ -304,15 +330,15 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
}
pmd = pmd_offset(pud, addr);
- if(!pmd_present(*pmd)){
+ if (!pmd_present(*pmd)) {
last = ADD_ROUND(addr, PMD_SIZE);
- if(last > end)
+ if (last > end)
last = end;
- if(pmd_newpage(*pmd)){
+ if (pmd_newpage(*pmd)) {
updated = 1;
err = os_unmap_memory((void *) addr,
last - addr);
- if(err < 0)
+ if (err < 0)
panic("munmap failed, errno = %d\n",
-err);
}
@@ -321,45 +347,110 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
}
pte = pte_offset_kernel(pmd, addr);
- if(!pte_present(*pte) || pte_newpage(*pte)){
+ if (!pte_present(*pte) || pte_newpage(*pte)) {
updated = 1;
err = os_unmap_memory((void *) addr,
PAGE_SIZE);
- if(err < 0)
+ if (err < 0)
panic("munmap failed, errno = %d\n",
-err);
- if(pte_present(*pte))
+ if (pte_present(*pte))
map_memory(addr,
pte_val(*pte) & PAGE_MASK,
PAGE_SIZE, 1, 1, 1);
}
- else if(pte_newprot(*pte)){
+ else if (pte_newprot(*pte)) {
updated = 1;
os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1);
}
addr += PAGE_SIZE;
}
- return(updated);
+ return updated;
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ struct mm_struct *mm = vma->vm_mm;
+ void *flush = NULL;
+ int r, w, x, prot, err = 0;
+ struct mm_id *mm_id;
+
+ address &= PAGE_MASK;
+ pgd = pgd_offset(mm, address);
+ if (!pgd_present(*pgd))
+ goto kill;
+
+ pud = pud_offset(pgd, address);
+ if (!pud_present(*pud))
+ goto kill;
+
+ pmd = pmd_offset(pud, address);
+ if (!pmd_present(*pmd))
+ goto kill;
+
+ pte = pte_offset_kernel(pmd, address);
+
+ r = pte_read(*pte);
+ w = pte_write(*pte);
+ x = pte_exec(*pte);
+ if (!pte_young(*pte)) {
+ r = 0;
+ w = 0;
+ } else if (!pte_dirty(*pte)) {
+ w = 0;
+ }
+
+ mm_id = &mm->context.id;
+ prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
+ (x ? UM_PROT_EXEC : 0));
+ if (pte_newpage(*pte)) {
+ if (pte_present(*pte)) {
+ unsigned long long offset;
+ int fd;
+
+ fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset);
+ err = map(mm_id, address, PAGE_SIZE, prot, fd, offset,
+ 1, &flush);
+ }
+ else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush);
+ }
+ else if (pte_newprot(*pte))
+ err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush);
+
+ if (err)
+ goto kill;
+
+ *pte = pte_mkuptodate(*pte);
+
+ return;
+
+kill:
+ printk(KERN_ERR "Failed to flush page for address 0x%lx\n", address);
+ force_sig(SIGKILL, current);
}
pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
{
- return(pgd_offset(mm, address));
+ return pgd_offset(mm, address);
}
pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address)
{
- return(pud_offset(pgd, address));
+ return pud_offset(pgd, address);
}
pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address)
{
- return(pmd_offset(pud, address));
+ return pmd_offset(pud, address);
}
pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
{
- return(pte_offset_kernel(pmd, address));
+ return pte_offset_kernel(pmd, address);
}
pte_t *addr_pte(struct task_struct *task, unsigned long addr)
@@ -368,7 +459,7 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr)
pud_t *pud = pud_offset(pgd, addr);
pmd_t *pmd = pmd_offset(pud, addr);
- return(pte_offset_map(pmd, addr));
+ return pte_offset_map(pmd, addr);
}
void flush_tlb_all(void)
@@ -378,35 +469,58 @@ void flush_tlb_all(void)
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
- CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
- flush_tlb_kernel_range_common, start, end);
+ flush_tlb_kernel_range_common(start, end);
}
void flush_tlb_kernel_vm(void)
{
- CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
- flush_tlb_kernel_range_common(start_vm, end_vm));
+ flush_tlb_kernel_range_common(start_vm, end_vm);
}
void __flush_tlb_one(unsigned long addr)
{
- CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
+ flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE);
+}
+
+static void fix_range(struct mm_struct *mm, unsigned long start_addr,
+ unsigned long end_addr, int force)
+{
+ if (!proc_mm && (end_addr > STUB_START))
+ end_addr = STUB_START;
+
+ fix_range_common(mm, start_addr, end_addr, force);
}
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end)
{
- CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
- end);
+ if (vma->vm_mm == NULL)
+ flush_tlb_kernel_range_common(start, end);
+ else fix_range(vma->vm_mm, start, end, 0);
}
void flush_tlb_mm(struct mm_struct *mm)
{
- CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
+ unsigned long end;
+
+ /*
+ * Don't bother flushing if this address space is about to be
+ * destroyed.
+ */
+ if (atomic_read(&mm->mm_users) == 0)
+ return;
+
+ end = proc_mm ? task_size : STUB_START;
+ fix_range(mm, 0, end, 0);
}
void force_flush_all(void)
{
- CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
-}
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma = mm->mmap;
+ while (vma != NULL) {
+ fix_range(mm, vma->vm_start, vma->vm_end, 1);
+ vma = vma->vm_next;
+ }
+}
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 3850d53f79f..bd060551e61 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -1,40 +1,24 @@
/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "asm/errno.h"
-#include "linux/sched.h"
-#include "linux/mm.h"
-#include "linux/spinlock.h"
-#include "linux/init.h"
-#include "linux/ptrace.h"
-#include "asm/semaphore.h"
-#include "asm/pgtable.h"
-#include "asm/pgalloc.h"
-#include "asm/tlbflush.h"
-#include "asm/a.out.h"
-#include "asm/current.h"
-#include "asm/irq.h"
-#include "sysdep/sigcontext.h"
-#include "kern_util.h"
-#include "as-layout.h"
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/hardirq.h>
+#include <asm/current.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
#include "arch.h"
-#include "kern.h"
-#include "chan_kern.h"
-#include "mconsole_kern.h"
-#include "mem.h"
-#include "mem_kern.h"
-#include "sysdep/sigcontext.h"
-#include "sysdep/ptrace.h"
-#include "os.h"
-#ifdef CONFIG_MODE_SKAS
-#include "skas.h"
-#endif
+#include "as-layout.h"
+#include "kern_util.h"
#include "os.h"
+#include "sysdep/sigcontext.h"
-/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */
+/*
+ * Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by
+ * segv().
+ */
int handle_page_fault(unsigned long address, unsigned long ip,
int is_write, int is_user, int *code_out)
{
@@ -48,31 +32,33 @@ int handle_page_fault(unsigned long address, unsigned long ip,
*code_out = SEGV_MAPERR;
- /* If the fault was during atomic operation, don't take the fault, just
- * fail. */
+ /*
+ * If the fault was during atomic operation, don't take the fault, just
+ * fail.
+ */
if (in_atomic())
goto out_nosemaphore;
down_read(&mm->mmap_sem);
vma = find_vma(mm, address);
- if(!vma)
+ if (!vma)
goto out;
- else if(vma->vm_start <= address)
+ else if (vma->vm_start <= address)
goto good_area;
- else if(!(vma->vm_flags & VM_GROWSDOWN))
+ else if (!(vma->vm_flags & VM_GROWSDOWN))
goto out;
- else if(is_user && !ARCH_IS_STACKGROW(address))
+ else if (is_user && !ARCH_IS_STACKGROW(address))
goto out;
- else if(expand_stack(vma, address))
+ else if (expand_stack(vma, address))
goto out;
good_area:
*code_out = SEGV_ACCERR;
- if(is_write && !(vma->vm_flags & VM_WRITE))
+ if (is_write && !(vma->vm_flags & VM_WRITE))
goto out;
/* Don't require VM_READ|VM_EXEC for write faults! */
- if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC)))
+ if (!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC)))
goto out;
do {
@@ -98,9 +84,10 @@ survive:
pud = pud_offset(pgd, address);
pmd = pmd_offset(pud, address);
pte = pte_offset_kernel(pmd, address);
- } while(!pte_present(*pte));
+ } while (!pte_present(*pte));
err = 0;
- /* The below warning was added in place of
+ /*
+ * The below warning was added in place of
* pte_mkyoung(); if (is_write) pte_mkdirty();
* If it's triggered, we'd see normally a hang here (a clean pte is
* marked read-only to emulate the dirty bit).
@@ -114,7 +101,7 @@ survive:
out:
up_read(&mm->mmap_sem);
out_nosemaphore:
- return(err);
+ return err;
/*
* We ran out of memory, or some other thing happened to us that made
@@ -141,11 +128,11 @@ static void bad_segv(struct faultinfo fi, unsigned long ip)
force_sig_info(SIGSEGV, &si, current);
}
-static void segv_handler(int sig, union uml_pt_regs *regs)
+static void segv_handler(int sig, struct uml_pt_regs *regs)
{
struct faultinfo * fi = UPT_FAULTINFO(regs);
- if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
+ if (UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)) {
bad_segv(*fi, UPT_IP(regs));
return;
}
@@ -159,45 +146,49 @@ static void segv_handler(int sig, union uml_pt_regs *regs)
* give us bad data!
*/
unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
- union uml_pt_regs *regs)
+ struct uml_pt_regs *regs)
{
struct siginfo si;
- void *catcher;
+ jmp_buf *catcher;
int err;
int is_write = FAULT_WRITE(fi);
unsigned long address = FAULT_ADDRESS(fi);
- if(!is_user && (address >= start_vm) && (address < end_vm)){
+ if (!is_user && (address >= start_vm) && (address < end_vm)) {
flush_tlb_kernel_vm();
return 0;
}
- else if(current->mm == NULL) {
+ else if (current->mm == NULL) {
show_regs(container_of(regs, struct pt_regs, regs));
- panic("Segfault with no mm");
+ panic("Segfault with no mm");
}
if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi))
- err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
+ err = handle_page_fault(address, ip, is_write, is_user,
+ &si.si_code);
else {
err = -EFAULT;
- /* A thread accessed NULL, we get a fault, but CR2 is invalid.
- * This code is used in __do_copy_from_user() of TT mode. */
+ /*
+ * A thread accessed NULL, we get a fault, but CR2 is invalid.
+ * This code is used in __do_copy_from_user() of TT mode.
+ * XXX tt mode is gone, so maybe this isn't needed any more
+ */
address = 0;
}
catcher = current->thread.fault_catcher;
- if(!err)
+ if (!err)
return 0;
- else if(catcher != NULL){
+ else if (catcher != NULL) {
current->thread.fault_addr = (void *) address;
- do_longjmp(catcher, 1);
+ UML_LONGJMP(catcher, 1);
}
- else if(current->thread.fault_addr != NULL)
+ else if (current->thread.fault_addr != NULL)
panic("fault_addr set but no fault catcher");
- else if(!is_user && arch_fixup(ip, regs))
+ else if (!is_user && arch_fixup(ip, regs))
return 0;
- if(!is_user) {
+ if (!is_user) {
show_regs(container_of(regs, struct pt_regs, regs));
panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
address, ip);
@@ -211,7 +202,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
current->thread.arch.faultinfo = fi;
force_sig_info(SIGBUS, &si, current);
} else if (err == -ENOMEM) {
- printk("VM: killing process %s\n", current->comm);
+ printk(KERN_INFO "VM: killing process %s\n", current->comm);
do_exit(SIGKILL);
} else {
BUG_ON(err != -EFAULT);
@@ -223,15 +214,15 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
return 0;
}
-void relay_signal(int sig, union uml_pt_regs *regs)
+void relay_signal(int sig, struct uml_pt_regs *regs)
{
- if(arch_handle_signal(sig, regs))
+ if (arch_handle_signal(sig, regs))
return;
- if(!UPT_IS_USER(regs)){
- if(sig == SIGBUS)
- printk("Bus error - the host /dev/shm or /tmp mount "
- "likely just ran out of space\n");
+ if (!UPT_IS_USER(regs)) {
+ if (sig == SIGBUS)
+ printk(KERN_ERR "Bus error - the host /dev/shm or /tmp "
+ "mount likely just ran out of space\n");
panic("Kernel mode signal %d", sig);
}
@@ -239,14 +230,14 @@ void relay_signal(int sig, union uml_pt_regs *regs)
force_sig(sig, current);
}
-static void bus_handler(int sig, union uml_pt_regs *regs)
+static void bus_handler(int sig, struct uml_pt_regs *regs)
{
- if(current->thread.fault_catcher != NULL)
- do_longjmp(current->thread.fault_catcher, 1);
+ if (current->thread.fault_catcher != NULL)
+ UML_LONGJMP(current->thread.fault_catcher, 1);
else relay_signal(sig, regs);
}
-static void winch(int sig, union uml_pt_regs *regs)
+static void winch(int sig, struct uml_pt_regs *regs)
{
do_IRQ(WINCH_IRQ, regs);
}
diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile
deleted file mode 100644
index 6939e5af847..00000000000
--- a/arch/um/kernel/tt/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
-# Licensed under the GPL
-#
-
-obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
- syscall_kern.o syscall_user.o tlb.o tracer.o trap_user.o \
- uaccess.o uaccess_user.o
-
-obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
-
-USER_OBJS := gdb.o tracer.o
-
-include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
deleted file mode 100644
index 40126cb5180..00000000000
--- a/arch/um/kernel/tt/exec_kern.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/kernel.h"
-#include "linux/mm.h"
-#include "asm/signal.h"
-#include "asm/ptrace.h"
-#include "asm/uaccess.h"
-#include "asm/pgalloc.h"
-#include "asm/tlbflush.h"
-#include "kern_util.h"
-#include "irq_user.h"
-#include "mem_user.h"
-#include "os.h"
-#include "tlb.h"
-#include "mode.h"
-
-static int exec_tramp(void *sig_stack)
-{
- init_new_thread_stack(sig_stack, NULL);
- init_new_thread_signals();
- os_stop_process(os_getpid());
- return(0);
-}
-
-void flush_thread_tt(void)
-{
- unsigned long stack;
- int new_pid;
-
- stack = alloc_stack(0, 0);
- if(stack == 0){
- printk(KERN_ERR
- "flush_thread : failed to allocate temporary stack\n");
- do_exit(SIGKILL);
- }
-
- new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp);
- if(new_pid < 0){
- printk(KERN_ERR
- "flush_thread : new thread failed, errno = %d\n",
- -new_pid);
- do_exit(SIGKILL);
- }
-
- if(current_thread->cpu == 0)
- forward_interrupts(new_pid);
- current->thread.request.op = OP_EXEC;
- current->thread.request.u.exec.pid = new_pid;
- unprotect_stack((unsigned long) current_thread);
- os_usr1_process(os_getpid());
- change_sig(SIGUSR1, 1);
-
- change_sig(SIGUSR1, 0);
- enable_timer();
- free_page(stack);
- protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
- stack_protections((unsigned long) current_thread);
- force_flush_all();
- unblock_signals();
-}
-
-void start_thread_tt(struct pt_regs *regs, unsigned long eip,
- unsigned long esp)
-{
- set_fs(USER_DS);
- flush_tlb_mm(current->mm);
- PT_REGS_IP(regs) = eip;
- PT_REGS_SP(regs) = esp;
- PT_FIX_EXEC_STACK(esp);
-}
-
-/*
- * 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/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c
deleted file mode 100644
index 7b5f2181cf5..00000000000
--- a/arch/um/kernel/tt/exec_user.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sched.h>
-#include <errno.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include "kern_util.h"
-#include "user.h"
-#include "ptrace_user.h"
-#include "os.h"
-
-void do_exec(int old_pid, int new_pid)
-{
- unsigned long regs[FRAME_SIZE];
- int err;
-
- if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) ||
- (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0))
- tracer_panic("do_exec failed to attach proc - errno = %d",
- errno);
-
- CATCH_EINTR(err = waitpid(new_pid, 0, WUNTRACED));
- if (err < 0)
- tracer_panic("do_exec failed to attach proc in waitpid - errno = %d",
- errno);
-
- if(ptrace_getregs(old_pid, regs) < 0)
- tracer_panic("do_exec failed to get registers - errno = %d",
- errno);
-
- os_kill_ptraced_process(old_pid, 0);
-
- if (ptrace(PTRACE_OLDSETOPTIONS, new_pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
- tracer_panic("do_exec: PTRACE_SETOPTIONS failed, errno = %d", errno);
-
- if(ptrace_setregs(new_pid, regs) < 0)
- tracer_panic("do_exec failed to start new proc - errno = %d",
- errno);
-}
-
-/*
- * 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/tt/gdb.c b/arch/um/kernel/tt/gdb.c
deleted file mode 100644
index 030e4658f36..00000000000
--- a/arch/um/kernel/tt/gdb.c
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/types.h>
-#include "ptrace_user.h"
-#include "uml-config.h"
-#include "kern_constants.h"
-#include "chan_user.h"
-#include "init.h"
-#include "user.h"
-#include "debug.h"
-#include "kern_util.h"
-#include "tt.h"
-#include "sysdep/thread.h"
-#include "os.h"
-
-extern int debugger_pid;
-extern int debugger_fd;
-extern int debugger_parent;
-
-int detach(int pid, int sig)
-{
- return(ptrace(PTRACE_DETACH, pid, 0, sig));
-}
-
-int attach(int pid)
-{
- int err;
-
- err = ptrace(PTRACE_ATTACH, pid, 0, 0);
- if(err < 0) return(-errno);
- else return(err);
-}
-
-int cont(int pid)
-{
- return(ptrace(PTRACE_CONT, pid, 0, 0));
-}
-
-#ifdef UML_CONFIG_PT_PROXY
-
-int debugger_signal(int status, pid_t pid)
-{
- return(debugger_proxy(status, pid));
-}
-
-void child_signal(pid_t pid, int status)
-{
- child_proxy(pid, status);
-}
-
-static void gdb_announce(char *dev_name, int dev)
-{
- printf("gdb assigned device '%s'\n", dev_name);
-}
-
-static struct chan_opts opts = {
- .announce = gdb_announce,
- .xterm_title = "UML kernel debugger",
- .raw = 0,
- .tramp_stack = 0,
- .in_kernel = 0,
-};
-
-/* Accessed by the tracing thread, which automatically serializes access */
-static void *xterm_data;
-static int xterm_fd;
-
-extern void *xterm_init(char *, int, struct chan_opts *);
-extern int xterm_open(int, int, int, void *, char **);
-extern void xterm_close(int, void *);
-
-int open_gdb_chan(void)
-{
- char stack[UM_KERN_PAGE_SIZE], *dummy;
-
- opts.tramp_stack = (unsigned long) stack;
- xterm_data = xterm_init("", 0, &opts);
- xterm_fd = xterm_open(1, 1, 1, xterm_data, &dummy);
- return(xterm_fd);
-}
-
-static void exit_debugger_cb(void *unused)
-{
- if(debugger_pid != -1){
- if(gdb_pid != -1){
- fake_child_exit();
- gdb_pid = -1;
- }
- else kill_child_dead(debugger_pid);
- debugger_pid = -1;
- if(debugger_parent != -1)
- detach(debugger_parent, SIGINT);
- }
- if(xterm_data != NULL) xterm_close(xterm_fd, xterm_data);
-}
-
-static void exit_debugger(void)
-{
- initial_thread_cb(exit_debugger_cb, NULL);
-}
-
-__uml_exitcall(exit_debugger);
-
-struct gdb_data {
- char *str;
- int err;
-};
-
-extern char *linux_prog;
-
-static void config_gdb_cb(void *arg)
-{
- struct gdb_data *data = arg;
- void *task;
- int pid;
-
- data->err = -1;
- if(debugger_pid != -1) exit_debugger_cb(NULL);
- if(!strncmp(data->str, "pid,", strlen("pid,"))){
- data->str += strlen("pid,");
- pid = strtoul(data->str, NULL, 0);
- task = cpu_tasks[0].task;
- debugger_pid = attach_debugger(TASK_EXTERN_PID(task), pid, 0);
- if(debugger_pid != -1){
- data->err = 0;
- gdb_pid = pid;
- }
- return;
- }
- data->err = 0;
- debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
- init_proxy(debugger_pid, 0, 0);
-}
-
-int gdb_config(char *str, char **error_out)
-{
- struct gdb_data data;
-
- if(*str++ != '=') return(-1);
- data.str = str;
- initial_thread_cb(config_gdb_cb, &data);
- return(data.err);
-}
-
-void remove_gdb_cb(void *unused)
-{
- exit_debugger_cb(NULL);
-}
-
-int gdb_remove(int unused, char **error_out)
-{
- initial_thread_cb(remove_gdb_cb, NULL);
- return 0;
-}
-
-void signal_usr1(int sig)
-{
- if(debugger_pid != -1){
- printf("The debugger is already running\n");
- return;
- }
- debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
- init_proxy(debugger_pid, 0, 0);
-}
-
-int init_ptrace_proxy(int idle_pid, int startup, int stop)
-{
- int pid, status;
-
- pid = start_debugger(linux_prog, startup, stop, &debugger_fd);
- status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL);
- if(pid < 0){
- cont(idle_pid);
- return(-1);
- }
- init_proxy(pid, 1, status);
- return(pid);
-}
-
-int attach_debugger(int idle_pid, int pid, int stop)
-{
- int status = 0, err;
-
- err = attach(pid);
- if(err < 0){
- printf("Failed to attach pid %d, errno = %d\n", pid, -err);
- return(-1);
- }
- if(stop) status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL);
- init_proxy(pid, 1, status);
- return(pid);
-}
-
-#ifdef notdef /* Put this back in when it does something useful */
-static int __init uml_gdb_init_setup(char *line, int *add)
-{
- gdb_init = uml_strdup(line);
- return 0;
-}
-
-__uml_setup("gdb=", uml_gdb_init_setup,
-"gdb=<channel description>\n\n"
-);
-#endif
-
-static int __init uml_gdb_pid_setup(char *line, int *add)
-{
- gdb_pid = strtoul(line, NULL, 0);
- *add = 0;
- return 0;
-}
-
-__uml_setup("gdb-pid=", uml_gdb_pid_setup,
-"gdb-pid=<pid>\n"
-" gdb-pid is used to attach an external debugger to UML. This may be\n"
-" an already-running gdb or a debugger-like process like strace.\n\n"
-);
-
-#else
-
-int debugger_signal(int status, pid_t pid){ return(0); }
-void child_signal(pid_t pid, int status){ }
-int init_ptrace_proxy(int idle_pid, int startup, int stop)
-{
- printf("debug requested when CONFIG_PT_PROXY is off\n");
- kill_child_dead(idle_pid);
- exit(1);
-}
-
-void signal_usr1(int sig)
-{
- printf("debug requested when CONFIG_PT_PROXY is off\n");
-}
-
-int attach_debugger(int idle_pid, int pid, int stop)
-{
- printf("attach_debugger called when CONFIG_PT_PROXY "
- "is off\n");
- return(-1);
-}
-
-int config_gdb(char *str)
-{
- return(-1);
-}
-
-int remove_gdb(void)
-{
- return(-1);
-}
-
-int init_parent_proxy(int pid)
-{
- return(-1);
-}
-
-void debugger_parent_signal(int status, int pid)
-{
-}
-
-#endif
-
-/*
- * 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/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c
deleted file mode 100644
index 03b06bc0077..00000000000
--- a/arch/um/kernel/tt/gdb_kern.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/init.h"
-#include "mconsole_kern.h"
-
-#ifdef CONFIG_MCONSOLE
-
-extern int gdb_config(char *str, char **error_out);
-extern int gdb_remove(int n, char **error_out);
-
-static struct mc_device gdb_mc = {
- .list = INIT_LIST_HEAD(gdb_mc.list),
- .name = "gdb",
- .config = gdb_config,
- .remove = gdb_remove,
-};
-
-int gdb_mc_init(void)
-{
- mconsole_register_dev(&gdb_mc);
- return(0);
-}
-
-__initcall(gdb_mc_init);
-
-#endif
-
-/*
- * 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/tt/include/mode-tt.h b/arch/um/kernel/tt/include/mode-tt.h
deleted file mode 100644
index e171e15fead..00000000000
--- a/arch/um/kernel/tt/include/mode-tt.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __MODE_TT_H__
-#define __MODE_TT_H__
-
-#include "sysdep/ptrace.h"
-
-enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
-
-extern int tracing_pid;
-
-extern int tracer(int (*init_proc)(void *), void *sp);
-extern void sig_handler_common_tt(int sig, void *sc);
-extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
-extern void reboot_tt(void);
-extern void halt_tt(void);
-extern int is_tracer_winch(int pid, int fd, void *data);
-extern void kill_off_processes_tt(void);
-
-#endif
-
-/*
- * 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/tt/ksyms.c b/arch/um/kernel/tt/ksyms.c
deleted file mode 100644
index 84a9385a8fe..00000000000
--- a/arch/um/kernel/tt/ksyms.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/module.h"
-#include "asm/uaccess.h"
-#include "mode.h"
-
-EXPORT_SYMBOL(__do_copy_from_user);
-EXPORT_SYMBOL(__do_copy_to_user);
-EXPORT_SYMBOL(__do_strncpy_from_user);
-EXPORT_SYMBOL(__do_strnlen_user);
-EXPORT_SYMBOL(__do_clear_user);
-EXPORT_SYMBOL(clear_user_tt);
-
-EXPORT_SYMBOL(tracing_pid);
-EXPORT_SYMBOL(honeypot);
-
-/*
- * 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/tt/mem.c b/arch/um/kernel/tt/mem.c
deleted file mode 100644
index d0c3c4975f2..00000000000
--- a/arch/um/kernel/tt/mem.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/stddef.h"
-#include "linux/mm.h"
-#include "asm/uaccess.h"
-#include "mem_user.h"
-#include "kern_util.h"
-#include "kern.h"
-#include "tt.h"
-
-void before_mem_tt(unsigned long brk_start)
-{
- if(debug)
- remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1);
- remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1);
- remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1);
-}
-
-#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000)
-#define START (CONFIG_TOP_ADDR - SIZE)
-
-unsigned long set_task_sizes_tt(unsigned long *task_size_out)
-{
- unsigned long host_task_size;
-
- /* Round up to the nearest 4M */
- host_task_size = ROUND_4M((unsigned long) &host_task_size);
- *task_size_out = START;
-
- return host_task_size;
-}
diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c
deleted file mode 100644
index 9774f6360c3..00000000000
--- a/arch/um/kernel/tt/mem_user.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/mman.h>
-#include "tt.h"
-#include "mem_user.h"
-#include "os.h"
-
-void remap_data(void *segment_start, void *segment_end, int w)
-{
- void *addr;
- unsigned long size;
- int data, prot;
-
- if(w) prot = PROT_WRITE;
- else prot = 0;
- prot |= PROT_READ | PROT_EXEC;
- size = (unsigned long) segment_end -
- (unsigned long) segment_start;
- data = create_mem_file(size);
- addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0);
- if(addr == MAP_FAILED){
- perror("mapping new data segment");
- exit(1);
- }
- memcpy(addr, segment_start, size);
- if(switcheroo(data, prot, addr, segment_start, size) < 0){
- printf("switcheroo failed\n");
- exit(1);
- }
-}
-
-/*
- * 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/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
deleted file mode 100644
index 74347adf81b..00000000000
--- a/arch/um/kernel/tt/process_kern.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/sched.h"
-#include "linux/signal.h"
-#include "linux/kernel.h"
-#include "linux/interrupt.h"
-#include "linux/ptrace.h"
-#include "asm/system.h"
-#include "asm/pgalloc.h"
-#include "asm/ptrace.h"
-#include "asm/tlbflush.h"
-#include "irq_user.h"
-#include "kern_util.h"
-#include "os.h"
-#include "kern.h"
-#include "sigcontext.h"
-#include "mem_user.h"
-#include "tlb.h"
-#include "mode.h"
-#include "mode_kern.h"
-#include "init.h"
-#include "tt.h"
-
-void switch_to_tt(void *prev, void *next)
-{
- struct task_struct *from, *to, *prev_sched;
- unsigned long flags;
- int err, vtalrm, alrm, prof, cpu;
- char c;
-
- from = prev;
- to = next;
-
- cpu = task_thread_info(from)->cpu;
- if(cpu == 0)
- forward_interrupts(to->thread.mode.tt.extern_pid);
-#ifdef CONFIG_SMP
- forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid);
-#endif
- local_irq_save(flags);
-
- vtalrm = change_sig(SIGVTALRM, 0);
- alrm = change_sig(SIGALRM, 0);
- prof = change_sig(SIGPROF, 0);
-
- forward_pending_sigio(to->thread.mode.tt.extern_pid);
-
- c = 0;
-
- /* Notice that here we "up" the semaphore on which "to" is waiting, and
- * below (the read) we wait on this semaphore (which is implemented by
- * switch_pipe) and go sleeping. Thus, after that, we have resumed in
- * "to", and can't use any more the value of "from" (which is outdated),
- * nor the value in "to" (since it was the task which stole us the CPU,
- * which we don't care about). */
-
- err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
- if(err != sizeof(c))
- panic("write of switch_pipe failed, err = %d", -err);
-
- if(from->thread.mode.tt.switch_pipe[0] == -1)
- os_kill_process(os_getpid(), 0);
-
- err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c,
- sizeof(c));
- if(err != sizeof(c))
- panic("read of switch_pipe failed, errno = %d", -err);
-
- /* If the process that we have just scheduled away from has exited,
- * then it needs to be killed here. The reason is that, even though
- * it will kill itself when it next runs, that may be too late. Its
- * stack will be freed, possibly before then, and if that happens,
- * we have a use-after-free situation. So, it gets killed here
- * in case it has not already killed itself.
- */
- prev_sched = current->thread.prev_sched;
- if(prev_sched->thread.mode.tt.switch_pipe[0] == -1)
- os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1);
-
- change_sig(SIGVTALRM, vtalrm);
- change_sig(SIGALRM, alrm);
- change_sig(SIGPROF, prof);
-
- arch_switch_to_tt(prev_sched, current);
-
- flush_tlb_all();
- local_irq_restore(flags);
-}
-
-void release_thread_tt(struct task_struct *task)
-{
- int pid = task->thread.mode.tt.extern_pid;
-
- /*
- * We first have to kill the other process, before
- * closing its switch_pipe. Else it might wake up
- * and receive "EOF" before we could kill it.
- */
- if(os_getpid() != pid)
- os_kill_process(pid, 0);
-
- os_close_file(task->thread.mode.tt.switch_pipe[0]);
- os_close_file(task->thread.mode.tt.switch_pipe[1]);
- /* use switch_pipe as flag: thread is released */
- task->thread.mode.tt.switch_pipe[0] = -1;
-}
-
-void suspend_new_thread(int fd)
-{
- int err;
- char c;
-
- os_stop_process(os_getpid());
- err = os_read_file(fd, &c, sizeof(c));
- if(err != sizeof(c))
- panic("read failed in suspend_new_thread, err = %d", -err);
-}
-
-void schedule_tail(struct task_struct *prev);
-
-static void new_thread_handler(int sig)
-{
- unsigned long disable;
- int (*fn)(void *);
- void *arg;
-
- fn = current->thread.request.u.thread.proc;
- arg = current->thread.request.u.thread.arg;
-
- UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
- disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) |
- (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1));
- SC_SIGMASK(UPT_SC(&current->thread.regs.regs)) &= ~disable;
-
- suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
-
- force_flush_all();
- if(current->thread.prev_sched != NULL)
- schedule_tail(current->thread.prev_sched);
- current->thread.prev_sched = NULL;
-
- init_new_thread_signals();
- enable_timer();
- free_page(current->thread.temp_stack);
- set_cmdline("(kernel thread)");
-
- change_sig(SIGUSR1, 1);
- change_sig(SIGPROF, 1);
- local_irq_enable();
- if(!run_kernel_thread(fn, arg, &current->thread.exec_buf))
- do_exit(0);
-
- /* XXX No set_user_mode here because a newly execed process will
- * immediately segfault on its non-existent IP, coming straight back
- * to the signal handler, which will call set_user_mode on its way
- * out. This should probably change since it's confusing.
- */
-}
-
-static int new_thread_proc(void *stack)
-{
- /* local_irq_disable is needed to block out signals until this thread is
- * properly scheduled. Otherwise, the tracing thread will get mighty
- * upset about any signals that arrive before that.
- * This has the complication that it sets the saved signal mask in
- * the sigcontext to block signals. This gets restored when this
- * thread (or a descendant, since they get a copy of this sigcontext)
- * returns to userspace.
- * So, this is compensated for elsewhere.
- * XXX There is still a small window until local_irq_disable() actually
- * finishes where signals are possible - shouldn't be a problem in
- * practice since SIGIO hasn't been forwarded here yet, and the
- * local_irq_disable should finish before a SIGVTALRM has time to be
- * delivered.
- */
-
- local_irq_disable();
- init_new_thread_stack(stack, new_thread_handler);
- os_usr1_process(os_getpid());
- change_sig(SIGUSR1, 1);
- return(0);
-}
-
-/* Signal masking - signals are blocked at the start of fork_tramp. They
- * are re-enabled when finish_fork_handler is entered by fork_tramp hitting
- * itself with a SIGUSR1. set_user_mode has to be run with SIGUSR1 off,
- * so it is blocked before it's called. They are re-enabled on sigreturn
- * despite the fact that they were blocked when the SIGUSR1 was issued because
- * copy_thread copies the parent's sigcontext, including the signal mask
- * onto the signal frame.
- */
-
-void finish_fork_handler(int sig)
-{
- UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
- suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
-
- force_flush_all();
- if(current->thread.prev_sched != NULL)
- schedule_tail(current->thread.prev_sched);
- current->thread.prev_sched = NULL;
-
- enable_timer();
- change_sig(SIGVTALRM, 1);
- local_irq_enable();
- if(current->mm != current->parent->mm)
- protect_memory(uml_reserved, high_physmem - uml_reserved, 1,
- 1, 0, 1);
- stack_protections((unsigned long) current_thread);
-
- free_page(current->thread.temp_stack);
- local_irq_disable();
- change_sig(SIGUSR1, 0);
- set_user_mode(current);
-}
-
-int fork_tramp(void *stack)
-{
- local_irq_disable();
- arch_init_thread();
- init_new_thread_stack(stack, finish_fork_handler);
-
- os_usr1_process(os_getpid());
- change_sig(SIGUSR1, 1);
- return(0);
-}
-
-int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
- unsigned long stack_top, struct task_struct * p,
- struct pt_regs *regs)
-{
- int (*tramp)(void *);
- int new_pid, err;
- unsigned long stack;
-
- if(current->thread.forking)
- tramp = fork_tramp;
- else {
- tramp = new_thread_proc;
- p->thread.request.u.thread = current->thread.request.u.thread;
- }
-
- err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1);
- if(err < 0){
- printk("copy_thread : pipe failed, err = %d\n", -err);
- return(err);
- }
-
- stack = alloc_stack(0, 0);
- if(stack == 0){
- printk(KERN_ERR "copy_thread : failed to allocate "
- "temporary stack\n");
- return(-ENOMEM);
- }
-
- clone_flags &= CLONE_VM;
- p->thread.temp_stack = stack;
- new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp);
- if(new_pid < 0){
- printk(KERN_ERR "copy_thread : clone failed - errno = %d\n",
- -new_pid);
- return(new_pid);
- }
-
- if(current->thread.forking){
- sc_to_sc(UPT_SC(&p->thread.regs.regs), UPT_SC(&regs->regs));
- SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0);
- if(sp != 0)
- SC_SP(UPT_SC(&p->thread.regs.regs)) = sp;
- }
- p->thread.mode.tt.extern_pid = new_pid;
-
- current->thread.request.op = OP_FORK;
- current->thread.request.u.fork.pid = new_pid;
- os_usr1_process(os_getpid());
-
- /* Enable the signal and then disable it to ensure that it is handled
- * here, and nowhere else.
- */
- change_sig(SIGUSR1, 1);
-
- change_sig(SIGUSR1, 0);
- err = 0;
- return(err);
-}
-
-void reboot_tt(void)
-{
- current->thread.request.op = OP_REBOOT;
- os_usr1_process(os_getpid());
- change_sig(SIGUSR1, 1);
-}
-
-void halt_tt(void)
-{
- current->thread.request.op = OP_HALT;
- os_usr1_process(os_getpid());
- change_sig(SIGUSR1, 1);
-}
-
-void kill_off_processes_tt(void)
-{
- struct task_struct *p;
- int me;
-
- me = os_getpid();
- for_each_process(p){
- if(p->thread.mode.tt.extern_pid != me)
- os_kill_process(p->thread.mode.tt.extern_pid, 0);
- }
- if(init_task.thread.mode.tt.extern_pid != me)
- os_kill_process(init_task.thread.mode.tt.extern_pid, 0);
-}
-
-void initial_thread_cb_tt(void (*proc)(void *), void *arg)
-{
- if(os_getpid() == tracing_pid){
- (*proc)(arg);
- }
- else {
- current->thread.request.op = OP_CB;
- current->thread.request.u.cb.proc = proc;
- current->thread.request.u.cb.arg = arg;
- os_usr1_process(os_getpid());
- change_sig(SIGUSR1, 1);
-
- change_sig(SIGUSR1, 0);
- }
-}
-
-int do_proc_op(void *t, int proc_id)
-{
- struct task_struct *task;
- struct thread_struct *thread;
- int op, pid;
-
- task = t;
- thread = &task->thread;
- op = thread->request.op;
- switch(op){
- case OP_NONE:
- case OP_TRACE_ON:
- break;
- case OP_EXEC:
- pid = thread->request.u.exec.pid;
- do_exec(thread->mode.tt.extern_pid, pid);
- thread->mode.tt.extern_pid = pid;
- cpu_tasks[task_thread_info(task)->cpu].pid = pid;
- break;
- case OP_FORK:
- attach_process(thread->request.u.fork.pid);
- break;
- case OP_CB:
- (*thread->request.u.cb.proc)(thread->request.u.cb.arg);
- break;
- case OP_REBOOT:
- case OP_HALT:
- break;
- default:
- tracer_panic("Bad op in do_proc_op");
- break;
- }
- thread->request.op = OP_NONE;
- return(op);
-}
-
-void init_idle_tt(void)
-{
- default_idle();
-}
-
-extern void start_kernel(void);
-
-static int start_kernel_proc(void *unused)
-{
- int pid;
-
- block_signals();
- pid = os_getpid();
-
- cpu_tasks[0].pid = pid;
- cpu_tasks[0].task = current;
-#ifdef CONFIG_SMP
- cpu_online_map = cpumask_of_cpu(0);
-#endif
- if(debug) os_stop_process(pid);
- start_kernel();
- return(0);
-}
-
-void set_tracing(void *task, int tracing)
-{
- ((struct task_struct *) task)->thread.mode.tt.tracing = tracing;
-}
-
-int is_tracing(void *t)
-{
- return (((struct task_struct *) t)->thread.mode.tt.tracing);
-}
-
-int set_user_mode(void *t)
-{
- struct task_struct *task;
-
- task = t ? t : current;
- if(task->thread.mode.tt.tracing)
- return(1);
- task->thread.request.op = OP_TRACE_ON;
- os_usr1_process(os_getpid());
- return(0);
-}
-
-void set_init_pid(int pid)
-{
- int err;
-
- init_task.thread.mode.tt.extern_pid = pid;
- err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1);
- if(err)
- panic("Can't create switch pipe for init_task, errno = %d",
- -err);
-}
-
-int start_uml_tt(void)
-{
- void *sp;
- int pages;
-
- pages = (1 << CONFIG_KERNEL_STACK_ORDER);
- sp = task_stack_page(&init_task) +
- pages * PAGE_SIZE - sizeof(unsigned long);
- return(tracer(start_kernel_proc, sp));
-}
-
-int external_pid_tt(struct task_struct *task)
-{
- return(task->thread.mode.tt.extern_pid);
-}
-
-int thread_pid_tt(struct task_struct *task)
-{
- return(task->thread.mode.tt.extern_pid);
-}
-
-int is_valid_pid(int pid)
-{
- struct task_struct *task;
-
- read_lock(&tasklist_lock);
- for_each_process(task){
- if(task->thread.mode.tt.extern_pid == pid){
- read_unlock(&tasklist_lock);
- return(1);
- }
- }
- read_unlock(&tasklist_lock);
- return(0);
-}
diff --git a/arch/um/kernel/tt/ptproxy/Makefile b/arch/um/kernel/tt/ptproxy/Makefile
deleted file mode 100644
index 3ad5b774de5..00000000000
--- a/arch/um/kernel/tt/ptproxy/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-# Licensed under the GPL
-#
-
-obj-y = proxy.o ptrace.o sysdep.o wait.o
-
-USER_OBJS := $(obj-y)
-
-include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c
deleted file mode 100644
index 420c23f311f..00000000000
--- a/arch/um/kernel/tt/ptproxy/proxy.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/**********************************************************************
-proxy.c
-
-Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-terms and conditions.
-
-Jeff Dike (jdike@karaya.com) : Modified for integration into uml
-**********************************************************************/
-
-/* XXX This file shouldn't refer to CONFIG_* */
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-#include <termios.h>
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <asm/unistd.h>
-#include "ptrace_user.h"
-
-#include "ptproxy.h"
-#include "sysdep.h"
-#include "wait.h"
-
-#include "user.h"
-#include "os.h"
-#include "tempfile.h"
-
-static int debugger_wait(debugger_state *debugger, int *status, int options,
- int (*syscall)(debugger_state *debugger, pid_t child),
- int (*normal_return)(debugger_state *debugger,
- pid_t unused),
- int (*wait_return)(debugger_state *debugger,
- pid_t unused))
-{
- if(debugger->real_wait){
- debugger->handle_trace = normal_return;
- syscall_continue(debugger->pid);
- debugger->real_wait = 0;
- return(1);
- }
- debugger->wait_status_ptr = status;
- debugger->wait_options = options;
- if((debugger->debugee != NULL) && debugger->debugee->event){
- syscall_continue(debugger->pid);
- wait_for_stop(debugger->pid, SIGTRAP, PTRACE_SYSCALL,
- NULL);
- (*wait_return)(debugger, -1);
- return(0);
- }
- else if(debugger->wait_options & WNOHANG){
- syscall_cancel(debugger->pid, 0);
- debugger->handle_trace = syscall;
- return(0);
- }
- else {
- syscall_pause(debugger->pid);
- debugger->handle_trace = wait_return;
- debugger->waiting = 1;
- }
- return(1);
-}
-
-/*
- * Handle debugger trap, i.e. syscall.
- */
-
-int debugger_syscall(debugger_state *debugger, pid_t child)
-{
- long arg1, arg2, arg3, arg4, arg5, result;
- int syscall, ret = 0;
-
- syscall = get_syscall(debugger->pid, &arg1, &arg2, &arg3, &arg4,
- &arg5);
-
- switch(syscall){
- case __NR_execve:
- /* execve never returns */
- debugger->handle_trace = debugger_syscall;
- break;
-
- case __NR_ptrace:
- if(debugger->debugee->pid != 0) arg2 = debugger->debugee->pid;
- if(!debugger->debugee->in_context)
- child = debugger->debugee->pid;
- result = proxy_ptrace(debugger, arg1, arg2, arg3, arg4, child,
- &ret);
- syscall_cancel(debugger->pid, result);
- debugger->handle_trace = debugger_syscall;
- return(ret);
-
-#ifdef __NR_waitpid
- case __NR_waitpid:
-#endif
- case __NR_wait4:
- if(!debugger_wait(debugger, (int *) arg2, arg3,
- debugger_syscall, debugger_normal_return,
- proxy_wait_return))
- return(0);
- break;
-
- case __NR_kill:
- if(!debugger->debugee->in_context)
- child = debugger->debugee->pid;
- if(arg1 == debugger->debugee->pid){
- result = kill(child, arg2);
- syscall_cancel(debugger->pid, result);
- debugger->handle_trace = debugger_syscall;
- return(0);
- }
- else debugger->handle_trace = debugger_normal_return;
- break;
-
- default:
- debugger->handle_trace = debugger_normal_return;
- }
-
- syscall_continue(debugger->pid);
- return(0);
-}
-
-/* Used by the tracing thread */
-static debugger_state parent;
-static int parent_syscall(debugger_state *debugger, int pid);
-
-int init_parent_proxy(int pid)
-{
- parent = ((debugger_state) { .pid = pid,
- .wait_options = 0,
- .wait_status_ptr = NULL,
- .waiting = 0,
- .real_wait = 0,
- .expecting_child = 0,
- .handle_trace = parent_syscall,
- .debugee = NULL } );
- return(0);
-}
-
-int parent_normal_return(debugger_state *debugger, pid_t unused)
-{
- debugger->handle_trace = parent_syscall;
- syscall_continue(debugger->pid);
- return(0);
-}
-
-static int parent_syscall(debugger_state *debugger, int pid)
-{
- long arg1, arg2, arg3, arg4, arg5;
- int syscall;
-
- syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5);
-
- if((syscall == __NR_wait4)
-#ifdef __NR_waitpid
- || (syscall == __NR_waitpid)
-#endif
- ){
- debugger_wait(&parent, (int *) arg2, arg3, parent_syscall,
- parent_normal_return, parent_wait_return);
- }
- else ptrace(PTRACE_SYSCALL, pid, 0, 0);
- return(0);
-}
-
-int debugger_normal_return(debugger_state *debugger, pid_t unused)
-{
- debugger->handle_trace = debugger_syscall;
- syscall_continue(debugger->pid);
- return(0);
-}
-
-void debugger_cancelled_return(debugger_state *debugger, int result)
-{
- debugger->handle_trace = debugger_syscall;
- syscall_set_result(debugger->pid, result);
- syscall_continue(debugger->pid);
-}
-
-/* Used by the tracing thread */
-static debugger_state debugger;
-static debugee_state debugee;
-
-void init_proxy (pid_t debugger_pid, int stopped, int status)
-{
- debugger.pid = debugger_pid;
- debugger.handle_trace = debugger_syscall;
- debugger.debugee = &debugee;
- debugger.waiting = 0;
- debugger.real_wait = 0;
- debugger.expecting_child = 0;
-
- debugee.pid = 0;
- debugee.traced = 0;
- debugee.stopped = stopped;
- debugee.event = 0;
- debugee.zombie = 0;
- debugee.died = 0;
- debugee.wait_status = status;
- debugee.in_context = 1;
-}
-
-int debugger_proxy(int status, int pid)
-{
- int ret = 0, sig;
-
- if(WIFSTOPPED(status)){
- sig = WSTOPSIG(status);
- if (sig == SIGTRAP)
- ret = (*debugger.handle_trace)(&debugger, pid);
-
- else if(sig == SIGCHLD){
- if(debugger.expecting_child){
- ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
- debugger.expecting_child = 0;
- }
- else if(debugger.waiting)
- real_wait_return(&debugger);
- else {
- ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
- debugger.real_wait = 1;
- }
- }
- else ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
- }
- else if(WIFEXITED(status)){
- tracer_panic("debugger (pid %d) exited with status %d",
- debugger.pid, WEXITSTATUS(status));
- }
- else if(WIFSIGNALED(status)){
- tracer_panic("debugger (pid %d) exited with signal %d",
- debugger.pid, WTERMSIG(status));
- }
- else {
- tracer_panic("proxy got unknown status (0x%x) on debugger "
- "(pid %d)", status, debugger.pid);
- }
- return(ret);
-}
-
-void child_proxy(pid_t pid, int status)
-{
- debugee.event = 1;
- debugee.wait_status = status;
-
- if(WIFSTOPPED(status)){
- debugee.stopped = 1;
- debugger.expecting_child = 1;
- kill(debugger.pid, SIGCHLD);
- }
- else if(WIFEXITED(status) || WIFSIGNALED(status)){
- debugee.zombie = 1;
- debugger.expecting_child = 1;
- kill(debugger.pid, SIGCHLD);
- }
- else panic("proxy got unknown status (0x%x) on child (pid %d)",
- status, pid);
-}
-
-void debugger_parent_signal(int status, int pid)
-{
- int sig;
-
- if(WIFSTOPPED(status)){
- sig = WSTOPSIG(status);
- if(sig == SIGTRAP) (*parent.handle_trace)(&parent, pid);
- else ptrace(PTRACE_SYSCALL, pid, 0, sig);
- }
-}
-
-void fake_child_exit(void)
-{
- int status, pid;
-
- child_proxy(1, W_EXITCODE(0, 0));
- while(debugger.waiting == 1){
- CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED));
- if(pid != debugger.pid){
- printk("fake_child_exit - waitpid failed, "
- "errno = %d\n", errno);
- return;
- }
- debugger_proxy(status, debugger.pid);
- }
- CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED));
- if(pid != debugger.pid){
- printk("fake_child_exit - waitpid failed, "
- "errno = %d\n", errno);
- return;
- }
- if(ptrace(PTRACE_DETACH, debugger.pid, 0, SIGCONT) < 0)
- printk("fake_child_exit - PTRACE_DETACH failed, errno = %d\n",
- errno);
-}
-
-char gdb_init_string[] =
-"att 1 \n\
-b panic \n\
-b stop \n\
-handle SIGWINCH nostop noprint pass \n\
-";
-
-int start_debugger(char *prog, int startup, int stop, int *fd_out)
-{
- int slave, child;
-
- slave = open_gdb_chan();
- child = fork();
- if(child == 0){
- char *tempname = NULL;
- int fd;
-
- if(setsid() < 0) perror("setsid");
- if((dup2(slave, 0) < 0) || (dup2(slave, 1) < 0) ||
- (dup2(slave, 2) < 0)){
- printk("start_debugger : dup2 failed, errno = %d\n",
- errno);
- exit(1);
- }
- if(ioctl(0, TIOCSCTTY, 0) < 0){
- printk("start_debugger : TIOCSCTTY failed, "
- "errno = %d\n", errno);
- exit(1);
- }
- if(tcsetpgrp (1, os_getpid()) < 0){
- printk("start_debugger : tcsetpgrp failed, "
- "errno = %d\n", errno);
-#ifdef notdef
- exit(1);
-#endif
- }
- fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0);
- if(fd < 0){
- printk("start_debugger : make_tempfile failed,"
- "err = %d\n", -fd);
- exit(1);
- }
- os_write_file(fd, gdb_init_string,
- sizeof(gdb_init_string) - 1);
- if(startup){
- if(stop){
- os_write_file(fd, "b start_kernel\n",
- strlen("b start_kernel\n"));
- }
- os_write_file(fd, "c\n", strlen("c\n"));
- }
- if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
- printk("start_debugger : PTRACE_TRACEME failed, "
- "errno = %d\n", errno);
- exit(1);
- }
- execlp("gdb", "gdb", "--command", tempname, prog, NULL);
- printk("start_debugger : exec of gdb failed, errno = %d\n",
- errno);
- }
- if(child < 0){
- printk("start_debugger : fork for gdb failed, errno = %d\n",
- errno);
- return(-1);
- }
- *fd_out = slave;
- return(child);
-}
-
-/*
- * 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/tt/ptproxy/ptproxy.h b/arch/um/kernel/tt/ptproxy/ptproxy.h
deleted file mode 100644
index 5eb0285b196..00000000000
--- a/arch/um/kernel/tt/ptproxy/ptproxy.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/**********************************************************************
-ptproxy.h
-
-Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-terms and conditions.
-**********************************************************************/
-
-#ifndef __PTPROXY_H
-#define __PTPROXY_H
-
-#include <sys/types.h>
-
-typedef struct debugger debugger_state;
-typedef struct debugee debugee_state;
-
-struct debugger
-{
- pid_t pid;
- int wait_options;
- int *wait_status_ptr;
- unsigned int waiting : 1;
- unsigned int real_wait : 1;
- unsigned int expecting_child : 1;
- int (*handle_trace) (debugger_state *, pid_t);
-
- debugee_state *debugee;
-};
-
-struct debugee
-{
- pid_t pid;
- int wait_status;
- unsigned int died : 1;
- unsigned int event : 1;
- unsigned int stopped : 1;
- unsigned int trace_singlestep : 1;
- unsigned int trace_syscall : 1;
- unsigned int traced : 1;
- unsigned int zombie : 1;
- unsigned int in_context : 1;
-};
-
-extern int debugger_syscall(debugger_state *debugger, pid_t pid);
-extern int debugger_normal_return (debugger_state *debugger, pid_t unused);
-
-extern long proxy_ptrace (struct debugger *, int, pid_t, long, long, pid_t,
- int *strace_out);
-extern void debugger_cancelled_return(debugger_state *debugger, int result);
-
-#endif
-
-/*
- * 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/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c
deleted file mode 100644
index 4b4f6179b21..00000000000
--- a/arch/um/kernel/tt/ptproxy/ptrace.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/**********************************************************************
-ptrace.c
-
-Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-terms and conditions.
-
-Jeff Dike (jdike@karaya.com) : Modified for integration into uml
-**********************************************************************/
-
-#include <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-
-#include "ptproxy.h"
-#include "debug.h"
-#include "kern_util.h"
-#include "ptrace_user.h"
-#include "tt.h"
-#include "os.h"
-
-long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
- long arg3, long arg4, pid_t child, int *ret)
-{
- sigset_t relay;
- long result;
- int status;
-
- *ret = 0;
- if(debugger->debugee->died) return(-ESRCH);
-
- switch(arg1){
- case PTRACE_ATTACH:
- if(debugger->debugee->traced) return(-EPERM);
-
- debugger->debugee->pid = arg2;
- debugger->debugee->traced = 1;
-
- if(is_valid_pid(arg2) && (arg2 != child)){
- debugger->debugee->in_context = 0;
- kill(arg2, SIGSTOP);
- debugger->debugee->event = 1;
- debugger->debugee->wait_status = W_STOPCODE(SIGSTOP);
- }
- else {
- debugger->debugee->in_context = 1;
- if(debugger->debugee->stopped)
- child_proxy(child, W_STOPCODE(SIGSTOP));
- else kill(child, SIGSTOP);
- }
-
- return(0);
-
- case PTRACE_DETACH:
- if(!debugger->debugee->traced) return(-EPERM);
-
- debugger->debugee->traced = 0;
- debugger->debugee->pid = 0;
- if(!debugger->debugee->in_context)
- kill(child, SIGCONT);
-
- return(0);
-
- case PTRACE_CONT:
- if(!debugger->debugee->in_context) return(-EPERM);
- *ret = PTRACE_CONT;
- return(ptrace(PTRACE_CONT, child, arg3, arg4));
-
-#ifdef UM_HAVE_GETFPREGS
- case PTRACE_GETFPREGS:
- {
- long regs[FP_FRAME_SIZE];
- int i, result;
-
- result = ptrace(PTRACE_GETFPREGS, child, 0, regs);
- if(result == -1) return(-errno);
-
- for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
- ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i,
- regs[i]);
- return(result);
- }
-#endif
-
-#ifdef UM_HAVE_GETFPXREGS
- case PTRACE_GETFPXREGS:
- {
- long regs[FPX_FRAME_SIZE];
- int i, result;
-
- result = ptrace(PTRACE_GETFPXREGS, child, 0, regs);
- if(result == -1) return(-errno);
-
- for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
- ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i,
- regs[i]);
- return(result);
- }
-#endif
-
-#ifdef UM_HAVE_GETREGS
- case PTRACE_GETREGS:
- {
- long regs[FRAME_SIZE];
- int i, result;
-
- result = ptrace(PTRACE_GETREGS, child, 0, regs);
- if(result == -1) return(-errno);
-
- for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
- ptrace (PTRACE_POKEDATA, debugger->pid,
- arg4 + 4 * i, regs[i]);
- return(result);
- }
- break;
-#endif
-
- case PTRACE_KILL:
- result = ptrace(PTRACE_KILL, child, arg3, arg4);
- if(result == -1) return(-errno);
-
- return(result);
-
- case PTRACE_PEEKDATA:
- case PTRACE_PEEKTEXT:
- case PTRACE_PEEKUSR:
- /* The value being read out could be -1, so we have to
- * check errno to see if there's an error, and zero it
- * beforehand so we're not faked out by an old error
- */
-
- errno = 0;
- result = ptrace(arg1, child, arg3, 0);
- if((result == -1) && (errno != 0)) return(-errno);
-
- result = ptrace(PTRACE_POKEDATA, debugger->pid, arg4, result);
- if(result == -1) return(-errno);
-
- return(result);
-
- case PTRACE_POKEDATA:
- case PTRACE_POKETEXT:
- case PTRACE_POKEUSR:
- result = ptrace(arg1, child, arg3, arg4);
- if(result == -1) return(-errno);
-
- if(arg1 == PTRACE_POKEUSR) ptrace_pokeuser(arg3, arg4);
- return(result);
-
-#ifdef UM_HAVE_SETFPREGS
- case PTRACE_SETFPREGS:
- {
- long regs[FP_FRAME_SIZE];
- int i;
-
- for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
- regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid,
- arg4 + 4 * i, 0);
- result = ptrace(PTRACE_SETFPREGS, child, 0, regs);
- if(result == -1) return(-errno);
-
- return(result);
- }
-#endif
-
-#ifdef UM_HAVE_SETFPXREGS
- case PTRACE_SETFPXREGS:
- {
- long regs[FPX_FRAME_SIZE];
- int i;
-
- for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
- regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid,
- arg4 + 4 * i, 0);
- result = ptrace(PTRACE_SETFPXREGS, child, 0, regs);
- if(result == -1) return(-errno);
-
- return(result);
- }
-#endif
-
-#ifdef UM_HAVE_SETREGS
- case PTRACE_SETREGS:
- {
- long regs[FRAME_SIZE];
- int i;
-
- for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
- regs[i] = ptrace(PTRACE_PEEKDATA, debugger->pid,
- arg4 + 4 * i, 0);
- result = ptrace(PTRACE_SETREGS, child, 0, regs);
- if(result == -1) return(-errno);
-
- return(result);
- }
-#endif
-
- case PTRACE_SINGLESTEP:
- if(!debugger->debugee->in_context) return(-EPERM);
- sigemptyset(&relay);
- sigaddset(&relay, SIGSEGV);
- sigaddset(&relay, SIGILL);
- sigaddset(&relay, SIGBUS);
- result = ptrace(PTRACE_SINGLESTEP, child, arg3, arg4);
- if(result == -1) return(-errno);
-
- status = wait_for_stop(child, SIGTRAP, PTRACE_SINGLESTEP,
- &relay);
- child_proxy(child, status);
- return(result);
-
- case PTRACE_SYSCALL:
- if(!debugger->debugee->in_context) return(-EPERM);
- result = ptrace(PTRACE_SYSCALL, child, arg3, arg4);
- if(result == -1) return(-errno);
-
- *ret = PTRACE_SYSCALL;
- return(result);
-
- case PTRACE_TRACEME:
- default:
- return(-EINVAL);
- }
-}
-
-/*
- * 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/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
deleted file mode 100644
index e0e1ab0588a..00000000000
--- a/arch/um/kernel/tt/ptproxy/sysdep.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/**********************************************************************
-sysdep.c
-
-Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-terms and conditions.
-**********************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <linux/unistd.h>
-#include "ptrace_user.h"
-#include "user.h"
-#include "os.h"
-
-int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4,
- long *arg5)
-{
- *arg1 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG1_OFFSET, 0);
- *arg2 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG2_OFFSET, 0);
- *arg3 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG3_OFFSET, 0);
- *arg4 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG4_OFFSET, 0);
- *arg5 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG5_OFFSET, 0);
- return(ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 0));
-}
-
-void syscall_cancel(pid_t pid, int result)
-{
- if((ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
- __NR_getpid) < 0) ||
- (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) ||
- (wait_for_stop(pid, SIGTRAP, PTRACE_SYSCALL, NULL) < 0) ||
- (ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result) < 0) ||
- (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0))
- printk("ptproxy: couldn't cancel syscall: errno = %d\n",
- errno);
-}
-
-void syscall_set_result(pid_t pid, long result)
-{
- ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result);
-}
-
-void syscall_continue(pid_t pid)
-{
- ptrace(PTRACE_SYSCALL, pid, 0, 0);
-}
-
-int syscall_pause(pid_t pid)
-{
- if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){
- printk("syscall_change - ptrace failed, errno = %d\n", errno);
- return(-1);
- }
- 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/tt/ptproxy/sysdep.h b/arch/um/kernel/tt/ptproxy/sysdep.h
deleted file mode 100644
index 735f488049a..00000000000
--- a/arch/um/kernel/tt/ptproxy/sysdep.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/**********************************************************************
-sysdep.h
-
-Copyright (C) 1999 Lars Brinkhoff.
-Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-See the file COPYING for licensing terms and conditions.
-**********************************************************************/
-
-extern int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3,
- long *arg4, long *arg5);
-extern void syscall_cancel (pid_t pid, long result);
-extern void syscall_set_result (pid_t pid, long result);
-extern void syscall_continue (pid_t pid);
-extern int syscall_pause(pid_t pid);
-
-/*
- * 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/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c
deleted file mode 100644
index bdd4af4b65f..00000000000
--- a/arch/um/kernel/tt/ptproxy/wait.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/**********************************************************************
-wait.c
-
-Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-terms and conditions.
-
-**********************************************************************/
-
-#include <errno.h>
-#include <signal.h>
-#include <sys/wait.h>
-
-#include "ptproxy.h"
-#include "sysdep.h"
-#include "wait.h"
-#include "ptrace_user.h"
-#include "sysdep/ptrace.h"
-#include "sysdep/sigcontext.h"
-
-int proxy_wait_return(struct debugger *debugger, pid_t unused)
-{
- debugger->waiting = 0;
-
- if(debugger->debugee->died || (debugger->wait_options & __WCLONE)){
- debugger_cancelled_return(debugger, -ECHILD);
- return(0);
- }
-
- if(debugger->debugee->zombie && debugger->debugee->event)
- debugger->debugee->died = 1;
-
- if(debugger->debugee->event){
- debugger->debugee->event = 0;
- ptrace(PTRACE_POKEDATA, debugger->pid,
- debugger->wait_status_ptr,
- debugger->debugee->wait_status);
- /* if (wait4)
- ptrace (PTRACE_POKEDATA, pid, rusage_ptr, ...); */
- debugger_cancelled_return(debugger, debugger->debugee->pid);
- return(0);
- }
-
- /* pause will return -EINTR, which happens to be right for wait */
- debugger_normal_return(debugger, -1);
- return(0);
-}
-
-int parent_wait_return(struct debugger *debugger, pid_t unused)
-{
- return(debugger_normal_return(debugger, -1));
-}
-
-int real_wait_return(struct debugger *debugger)
-{
- unsigned long ip;
- int pid;
-
- pid = debugger->pid;
-
- ip = ptrace(PTRACE_PEEKUSR, pid, PT_IP_OFFSET, 0);
- IP_RESTART_SYSCALL(ip);
-
- if(ptrace(PTRACE_POKEUSR, pid, PT_IP_OFFSET, ip) < 0)
- tracer_panic("real_wait_return : Failed to restart system "
- "call, errno = %d\n", errno);
-
- if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) ||
- (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
- (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
- debugger_normal_return(debugger, -1))
- tracer_panic("real_wait_return : gdb failed to wait, "
- "errno = %d\n", errno);
- 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/tt/ptproxy/wait.h b/arch/um/kernel/tt/ptproxy/wait.h
deleted file mode 100644
index 542e73ee2ce..00000000000
--- a/arch/um/kernel/tt/ptproxy/wait.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/**********************************************************************
-wait.h
-
-Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-terms and conditions.
-**********************************************************************/
-
-#ifndef __PTPROXY_WAIT_H
-#define __PTPROXY_WAIT_H
-
-extern int proxy_wait_return(struct debugger *debugger, pid_t unused);
-extern int real_wait_return(struct debugger *debugger);
-extern int parent_wait_return(struct debugger *debugger, pid_t unused);
-
-#endif
diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c
deleted file mode 100644
index 293caa6d0c2..00000000000
--- a/arch/um/kernel/tt/syscall_kern.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include "linux/types.h"
-#include "linux/utime.h"
-#include "linux/sys.h"
-#include "linux/ptrace.h"
-#include "asm/unistd.h"
-#include "asm/ptrace.h"
-#include "asm/uaccess.h"
-#include "asm/stat.h"
-#include "sysdep/syscalls.h"
-#include "sysdep/sigcontext.h"
-#include "kern_util.h"
-#include "syscall.h"
-
-void syscall_handler_tt(int sig, struct pt_regs *regs)
-{
- void *sc;
- long result;
- int syscall;
-
- sc = UPT_SC(&regs->regs);
- SC_START_SYSCALL(sc);
-
- syscall = UPT_SYSCALL_NR(&regs->regs);
- syscall_trace(&regs->regs, 0);
-
- current->thread.nsyscalls++;
- nsyscalls++;
-
- if((syscall >= NR_syscalls) || (syscall < 0))
- result = -ENOSYS;
- else result = EXECUTE_SYSCALL(syscall, regs);
-
- /* regs->sc may have changed while the system call ran (there may
- * have been an interrupt or segfault), so it needs to be refreshed.
- */
- UPT_SC(&regs->regs) = sc;
-
- SC_SET_SYSCALL_RETURN(sc, result);
-
- syscall_trace(&regs->regs, 1);
-}
diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c
deleted file mode 100644
index f52b47aff1d..00000000000
--- a/arch/um/kernel/tt/syscall_user.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <unistd.h>
-#include <signal.h>
-#include <errno.h>
-#include <asm/unistd.h>
-#include "sysdep/ptrace.h"
-#include "sigcontext.h"
-#include "ptrace_user.h"
-#include "task.h"
-#include "kern_util.h"
-#include "syscall.h"
-#include "tt.h"
-
-void do_sigtrap(void *task)
-{
- UPT_SYSCALL_NR(TASK_REGS(task)) = -1;
-}
-
-void do_syscall(void *task, int pid, int local_using_sysemu)
-{
- unsigned long proc_regs[FRAME_SIZE];
-
- if(ptrace_getregs(pid, proc_regs) < 0)
- tracer_panic("Couldn't read registers");
-
- UPT_SYSCALL_NR(TASK_REGS(task)) = PT_SYSCALL_NR(proc_regs);
-
-#ifdef UPT_ORIGGPR2
- UPT_ORIGGPR2(TASK_REGS(task)) = REGS_ORIGGPR2(proc_regs);
-#endif
-
- if(((unsigned long *) PT_IP(proc_regs) >= &_stext) &&
- ((unsigned long *) PT_IP(proc_regs) <= &_etext))
- tracer_panic("I'm tracing myself and I can't get out");
-
- /* advanced sysemu mode set syscall number to -1 automatically */
- if (local_using_sysemu==2)
- return;
-
- /* syscall number -1 in sysemu skips syscall restarting in host */
- if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
- local_using_sysemu ? -1 : __NR_getpid) < 0)
- tracer_panic("do_syscall : Nullifying syscall failed, "
- "errno = %d", errno);
-}
-
-/*
- * 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/tt/tlb.c b/arch/um/kernel/tt/tlb.c
deleted file mode 100644
index 7caa24fe05d..00000000000
--- a/arch/um/kernel/tt/tlb.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Copyright 2003 PathScale, Inc.
- * Licensed under the GPL
- */
-
-#include "linux/stddef.h"
-#include "linux/kernel.h"
-#include "linux/sched.h"
-#include "linux/mm.h"
-#include "asm/page.h"
-#include "asm/pgtable.h"
-#include "asm/uaccess.h"
-#include "asm/tlbflush.h"
-#include "mem_user.h"
-#include "os.h"
-#include "tlb.h"
-
-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, ret=0;
-
- for(i = 0; i <= last && !ret; i++){
- op = &ops[i];
- switch(op->type){
- case MMAP:
- ret = os_map_memory((void *) op->u.mmap.addr,
- op->u.mmap.fd, op->u.mmap.offset,
- op->u.mmap.len, op->u.mmap.r,
- op->u.mmap.w, op->u.mmap.x);
- break;
- case MUNMAP:
- ret = os_unmap_memory((void *) op->u.munmap.addr,
- op->u.munmap.len);
- break;
- case MPROTECT:
- ret = protect_memory(op->u.mprotect.addr,
- op->u.munmap.len,
- op->u.mprotect.r,
- op->u.mprotect.w,
- op->u.mprotect.x, 1);
- protect_memory(op->u.mprotect.addr, op->u.munmap.len,
- op->u.mprotect.r, op->u.mprotect.w,
- op->u.mprotect.x, 1);
- break;
- default:
- printk("Unknown op type %d in do_ops\n", op->type);
- break;
- }
- }
-
- return ret;
-}
-
-static void fix_range(struct mm_struct *mm, unsigned long start_addr,
- unsigned long end_addr, int force)
-{
- if((current->thread.mode.tt.extern_pid != -1) &&
- (current->thread.mode.tt.extern_pid != os_getpid()))
- panic("fix_range fixing wrong address space, current = 0x%p",
- current);
-
- fix_range_common(mm, start_addr, end_addr, force, do_ops);
-}
-
-atomic_t vmchange_seq = ATOMIC_INIT(1);
-
-void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end)
-{
- if(flush_tlb_kernel_range_common(start, end))
- atomic_inc(&vmchange_seq);
-}
-
-void flush_tlb_kernel_vm_tt(void)
-{
- flush_tlb_kernel_range(start_vm, end_vm);
-}
-
-void __flush_tlb_one_tt(unsigned long addr)
-{
- flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
-}
-
-void flush_tlb_range_tt(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
-{
- if(vma->vm_mm != current->mm) return;
-
- /* Assumes that the range start ... end is entirely within
- * either process memory or kernel vm
- */
- if((start >= start_vm) && (start < end_vm)){
- if(flush_tlb_kernel_range_common(start, end))
- atomic_inc(&vmchange_seq);
- }
- else fix_range(vma->vm_mm, start, end, 0);
-}
-
-void flush_tlb_mm_tt(struct mm_struct *mm)
-{
- unsigned long seq;
-
- if(mm != current->mm) return;
-
- fix_range(mm, 0, STACK_TOP, 0);
-
- seq = atomic_read(&vmchange_seq);
- if(current->thread.mode.tt.vm_seq == seq)
- return;
- current->thread.mode.tt.vm_seq = seq;
- flush_tlb_kernel_range_common(start_vm, end_vm);
-}
-
-void force_flush_all_tt(void)
-{
- fix_range(current->mm, 0, STACK_TOP, 1);
- flush_tlb_kernel_range_common(start_vm, end_vm);
-}
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
deleted file mode 100644
index c23588393f6..00000000000
--- a/arch/um/kernel/tt/tracer.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <signal.h>
-#include <errno.h>
-#include <sched.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include "user.h"
-#include "sysdep/ptrace.h"
-#include "sigcontext.h"
-#include "sysdep/sigcontext.h"
-#include "os.h"
-#include "mem_user.h"
-#include "process.h"
-#include "kern_util.h"
-#include "chan_user.h"
-#include "ptrace_user.h"
-#include "irq_user.h"
-#include "mode.h"
-#include "tt.h"
-
-static int tracer_winch[2];
-
-int is_tracer_winch(int pid, int fd, void *data)
-{
- if(pid != os_getpgrp())
- return(0);
-
- register_winch_irq(tracer_winch[0], fd, -1, data);
- return(1);
-}
-
-static void tracer_winch_handler(int sig)
-{
- int n;
- char c = 1;
-
- n = os_write_file(tracer_winch[1], &c, sizeof(c));
- if(n != sizeof(c))
- printk("tracer_winch_handler - write failed, err = %d\n", -n);
-}
-
-/* Called only by the tracing thread during initialization */
-
-static void setup_tracer_winch(void)
-{
- int err;
-
- err = os_pipe(tracer_winch, 1, 1);
- if(err < 0){
- printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err);
- return;
- }
- signal(SIGWINCH, tracer_winch_handler);
-}
-
-void attach_process(int pid)
-{
- if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) ||
- (ptrace(PTRACE_CONT, pid, 0, 0) < 0))
- tracer_panic("OP_FORK failed to attach pid");
- wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
- if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
- tracer_panic("OP_FORK: PTRACE_SETOPTIONS failed, errno = %d", errno);
- if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
- tracer_panic("OP_FORK failed to continue process");
-}
-
-void tracer_panic(char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- vprintf(format, ap);
- va_end(ap);
- printf("\n");
- while(1) pause();
-}
-
-static void tracer_segv(int sig, struct sigcontext sc)
-{
- struct faultinfo fi;
- GET_FAULTINFO_FROM_SC(fi, &sc);
- printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n",
- FAULT_ADDRESS(fi), SC_IP(&sc));
- while(1)
- pause();
-}
-
-/* Changed early in boot, and then only read */
-int debug = 0;
-int debug_stop = 1;
-int debug_parent = 0;
-int honeypot = 0;
-
-static int signal_tramp(void *arg)
-{
- int (*proc)(void *);
-
- if(honeypot && munmap((void *) (host_task_size - 0x10000000),
- 0x10000000))
- panic("Unmapping stack failed");
- if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
- panic("ptrace PTRACE_TRACEME failed");
- os_stop_process(os_getpid());
- change_sig(SIGWINCH, 0);
- signal(SIGUSR1, SIG_IGN);
- change_sig(SIGCHLD, 0);
- signal(SIGSEGV, (__sighandler_t) sig_handler);
- set_cmdline("(idle thread)");
- set_init_pid(os_getpid());
- init_irq_signals(0);
- proc = arg;
- return((*proc)(NULL));
-}
-
-static void sleeping_process_signal(int pid, int sig)
-{
- switch(sig){
- /* These two result from UML being ^Z-ed and bg-ed. PTRACE_CONT is
- * right because the process must be in the kernel already.
- */
- case SIGCONT:
- case SIGTSTP:
- if(ptrace(PTRACE_CONT, pid, 0, sig) < 0)
- tracer_panic("sleeping_process_signal : Failed to "
- "continue pid %d, signal = %d, "
- "errno = %d\n", pid, sig, errno);
- break;
-
- /* This happens when the debugger (e.g. strace) is doing system call
- * tracing on the kernel. During a context switch, the current task
- * will be set to the incoming process and the outgoing process will
- * hop into write and then read. Since it's not the current process
- * any more, the trace of those will land here. So, we need to just
- * PTRACE_SYSCALL it.
- */
- case (SIGTRAP + 0x80):
- if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
- tracer_panic("sleeping_process_signal : Failed to "
- "PTRACE_SYSCALL pid %d, errno = %d\n",
- pid, errno);
- break;
- case SIGSTOP:
- break;
- default:
- tracer_panic("sleeping process %d got unexpected "
- "signal : %d\n", pid, sig);
- break;
- }
-}
-
-/* Accessed only by the tracing thread */
-int debugger_pid = -1;
-int debugger_parent = -1;
-int debugger_fd = -1;
-int gdb_pid = -1;
-
-struct {
- int pid;
- int signal;
- unsigned long addr;
- struct timeval time;
-} signal_record[1024][32];
-
-int signal_index[32];
-int nsignals = 0;
-int debug_trace = 0;
-
-extern void signal_usr1(int sig);
-
-int tracing_pid = -1;
-
-int tracer(int (*init_proc)(void *), void *sp)
-{
- void *task = NULL;
- int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0;
- int proc_id = 0, n, err, old_tracing = 0, strace = 0;
- int local_using_sysemu = 0;
-
- signal(SIGPIPE, SIG_IGN);
- setup_tracer_winch();
- tracing_pid = os_getpid();
- printf("tracing thread pid = %d\n", tracing_pid);
-
- pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc);
- CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
- if(n < 0){
- printf("waitpid on idle thread failed, errno = %d\n", errno);
- exit(1);
- }
- if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) {
- printf("Failed to PTRACE_SETOPTIONS for idle thread, errno = %d\n", errno);
- exit(1);
- }
- if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){
- printf("Failed to continue idle thread, errno = %d\n", errno);
- exit(1);
- }
-
- signal(SIGSEGV, (sighandler_t) tracer_segv);
- signal(SIGUSR1, signal_usr1);
- if(debug_trace){
- printf("Tracing thread pausing to be attached\n");
- stop();
- }
- if(debug){
- if(gdb_pid != -1)
- debugger_pid = attach_debugger(pid, gdb_pid, 1);
- else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop);
- if(debug_parent){
- debugger_parent = os_process_parent(debugger_pid);
- init_parent_proxy(debugger_parent);
- err = attach(debugger_parent);
- if(err){
- printf("Failed to attach debugger parent %d, "
- "errno = %d\n", debugger_parent, -err);
- debugger_parent = -1;
- }
- else {
- if(ptrace(PTRACE_SYSCALL, debugger_parent,
- 0, 0) < 0){
- printf("Failed to continue debugger "
- "parent, errno = %d\n", errno);
- debugger_parent = -1;
- }
- }
- }
- }
- set_cmdline("(tracing thread)");
- while(1){
- CATCH_EINTR(pid = waitpid(-1, &status, WUNTRACED));
- if(pid <= 0){
- if(errno != ECHILD){
- printf("wait failed - errno = %d\n", errno);
- }
- continue;
- }
- if(pid == debugger_pid){
- int cont = 0;
-
- if(WIFEXITED(status) || WIFSIGNALED(status))
- debugger_pid = -1;
- /* XXX Figure out how to deal with gdb and SMP */
- else cont = debugger_signal(status, cpu_tasks[0].pid);
- if(cont == PTRACE_SYSCALL) strace = 1;
- continue;
- }
- else if(pid == debugger_parent){
- debugger_parent_signal(status, pid);
- continue;
- }
- nsignals++;
- if(WIFEXITED(status)) ;
-#ifdef notdef
- {
- printf("Child %d exited with status %d\n", pid,
- WEXITSTATUS(status));
- }
-#endif
- else if(WIFSIGNALED(status)){
- sig = WTERMSIG(status);
- if(sig != 9){
- printf("Child %d exited with signal %d\n", pid,
- sig);
- }
- }
- else if(WIFSTOPPED(status)){
- proc_id = pid_to_processor_id(pid);
- sig = WSTOPSIG(status);
- if(proc_id == -1){
- sleeping_process_signal(pid, sig);
- continue;
- }
-
- task = cpu_tasks[proc_id].task;
- tracing = is_tracing(task);
- old_tracing = tracing;
-
- /* Assume: no syscall, when coming from user */
- if ( tracing )
- do_sigtrap(task);
-
- switch(sig){
- case SIGUSR1:
- sig = 0;
- op = do_proc_op(task, proc_id);
- switch(op){
- /*
- * This is called when entering user mode; after
- * this, we start intercepting syscalls.
- *
- * In fact, a process is started in kernel mode,
- * so with is_tracing() == 0 (and that is reset
- * when executing syscalls, since UML kernel has
- * the right to do syscalls);
- */
- case OP_TRACE_ON:
- arch_leave_kernel(task, pid);
- tracing = 1;
- break;
- case OP_REBOOT:
- case OP_HALT:
- unmap_physmem();
- kmalloc_ok = 0;
- os_kill_ptraced_process(pid, 0);
- /* Now let's reap remaining zombies */
- errno = 0;
- do {
- waitpid(-1, &status,
- WUNTRACED);
- } while (errno != ECHILD);
- return(op == OP_REBOOT);
- case OP_NONE:
- printf("Detaching pid %d\n", pid);
- detach(pid, SIGSTOP);
- continue;
- default:
- break;
- }
- /* OP_EXEC switches host processes on us,
- * we want to continue the new one.
- */
- pid = cpu_tasks[proc_id].pid;
- break;
- case (SIGTRAP + 0x80):
- if(!tracing && (debugger_pid != -1)){
- child_signal(pid, status & 0x7fff);
- continue;
- }
- tracing = 0;
- /* local_using_sysemu has been already set
- * below, since if we are here, is_tracing() on
- * the traced task was 1, i.e. the process had
- * already run through one iteration of the
- * loop which executed a OP_TRACE_ON request.*/
- do_syscall(task, pid, local_using_sysemu);
- sig = SIGUSR2;
- break;
- case SIGTRAP:
- if(!tracing && (debugger_pid != -1)){
- child_signal(pid, status);
- continue;
- }
- tracing = 0;
- break;
- case SIGPROF:
- if(tracing) sig = 0;
- break;
- case SIGCHLD:
- case SIGHUP:
- sig = 0;
- break;
- case SIGSEGV:
- case SIGIO:
- case SIGALRM:
- case SIGVTALRM:
- case SIGFPE:
- case SIGBUS:
- case SIGILL:
- case SIGWINCH:
-
- default:
- tracing = 0;
- break;
- }
- set_tracing(task, tracing);
-
- if(!tracing && old_tracing)
- arch_enter_kernel(task, pid);
-
- if(!tracing && (debugger_pid != -1) && (sig != 0) &&
- (sig != SIGALRM) && (sig != SIGVTALRM) &&
- (sig != SIGSEGV) && (sig != SIGTRAP) &&
- (sig != SIGUSR2) && (sig != SIGIO) &&
- (sig != SIGFPE)){
- child_signal(pid, status);
- continue;
- }
-
- local_using_sysemu = get_using_sysemu();
-
- if(tracing)
- cont_type = SELECT_PTRACE_OPERATION(local_using_sysemu,
- singlestepping(task));
- else if((debugger_pid != -1) && strace)
- cont_type = PTRACE_SYSCALL;
- else
- cont_type = PTRACE_CONT;
-
- if(ptrace(cont_type, pid, 0, sig) != 0){
- tracer_panic("ptrace failed to continue "
- "process - errno = %d\n",
- errno);
- }
- }
- }
- return(0);
-}
-
-static int __init uml_debug_setup(char *line, int *add)
-{
- char *next;
-
- debug = 1;
- *add = 0;
- if(*line != '=') return(0);
- line++;
-
- while(line != NULL){
- next = strchr(line, ',');
- if(next) *next++ = '\0';
-
- if(!strcmp(line, "go")) debug_stop = 0;
- else if(!strcmp(line, "parent")) debug_parent = 1;
- else printf("Unknown debug option : '%s'\n", line);
-
- line = next;
- }
- return(0);
-}
-
-__uml_setup("debug", uml_debug_setup,
-"debug\n"
-" Starts up the kernel under the control of gdb. See the \n"
-" kernel debugging tutorial and the debugging session pages\n"
-" at http://user-mode-linux.sourceforge.net/ for more information.\n\n"
-);
-
-static int __init uml_debugtrace_setup(char *line, int *add)
-{
- debug_trace = 1;
- return 0;
-}
-__uml_setup("debugtrace", uml_debugtrace_setup,
-"debugtrace\n"
-" Causes the tracing thread to pause until it is attached by a\n"
-" debugger and continued. This is mostly for debugging crashes\n"
-" early during boot, and should be pretty much obsoleted by\n"
-" the debug switch.\n\n"
-);
-
-/*
- * 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/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
deleted file mode 100644
index 3032eb5e246..00000000000
--- a/arch/um/kernel/tt/trap_user.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <signal.h>
-#include "sysdep/ptrace.h"
-#include "sysdep/sigcontext.h"
-#include "kern_util.h"
-#include "task.h"
-#include "tt.h"
-#include "os.h"
-
-void sig_handler_common_tt(int sig, void *sc_ptr)
-{
- struct sigcontext *sc = sc_ptr;
- struct tt_regs save_regs, *r;
- int save_errno = errno, is_user = 0;
- void (*handler)(int, union uml_pt_regs *);
-
- /* This is done because to allow SIGSEGV to be delivered inside a SEGV
- * handler. This can happen in copy_user, and if SEGV is disabled,
- * the process will die.
- */
- if(sig == SIGSEGV)
- change_sig(SIGSEGV, 1);
-
- r = &TASK_REGS(get_current())->tt;
- if ( sig == SIGFPE || sig == SIGSEGV ||
- sig == SIGBUS || sig == SIGILL ||
- sig == SIGTRAP ) {
- GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
- }
- save_regs = *r;
- if (sc)
- is_user = user_context(SC_SP(sc));
- r->sc = sc;
- if(sig != SIGUSR2)
- r->syscall = -1;
-
- handler = sig_info[sig];
-
- /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */
- if (sig != SIGIO && sig != SIGWINCH &&
- sig != SIGVTALRM && sig != SIGALRM)
- unblock_signals();
-
- handler(sig, (union uml_pt_regs *) r);
-
- if(is_user){
- interrupt_end();
- block_signals();
- set_user_mode(NULL);
- }
- *r = save_regs;
- errno = save_errno;
-}
-
-/*
- * 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/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c
deleted file mode 100644
index 1cb60726567..00000000000
--- a/arch/um/kernel/tt/uaccess.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include "linux/sched.h"
-#include "asm/uaccess.h"
-
-int copy_from_user_tt(void *to, const void __user *from, int n)
-{
- if(!access_ok(VERIFY_READ, from, n))
- return(n);
-
- return(__do_copy_from_user(to, from, n, &current->thread.fault_addr,
- &current->thread.fault_catcher));
-}
-
-int copy_to_user_tt(void __user *to, const void *from, int n)
-{
- if(!access_ok(VERIFY_WRITE, to, n))
- return(n);
-
- return(__do_copy_to_user(to, from, n, &current->thread.fault_addr,
- &current->thread.fault_catcher));
-}
-
-int strncpy_from_user_tt(char *dst, const char __user *src, int count)
-{
- int n;
-
- if(!access_ok(VERIFY_READ, src, 1))
- return(-EFAULT);
-
- n = __do_strncpy_from_user(dst, src, count,
- &current->thread.fault_addr,
- &current->thread.fault_catcher);
- if(n < 0) return(-EFAULT);
- return(n);
-}
-
-int __clear_user_tt(void __user *mem, int len)
-{
- return(__do_clear_user(mem, len,
- &current->thread.fault_addr,
- &current->thread.fault_catcher));
-}
-
-int clear_user_tt(void __user *mem, int len)
-{
- if(!access_ok(VERIFY_WRITE, mem, len))
- return(len);
-
- return(__do_clear_user(mem, len, &current->thread.fault_addr,
- &current->thread.fault_catcher));
-}
-
-int strnlen_user_tt(const void __user *str, int len)
-{
- return(__do_strnlen_user(str, len,
- &current->thread.fault_addr,
- &current->thread.fault_catcher));
-}
-
-/*
- * 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/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c
deleted file mode 100644
index 0e5c82c5e5b..00000000000
--- a/arch/um/kernel/tt/uaccess_user.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <string.h>
-#include "uml_uaccess.h"
-#include "task.h"
-#include "kern_util.h"
-#include "os.h"
-#include "longjmp.h"
-
-int __do_copy_from_user(void *to, const void *from, int n,
- void **fault_addr, void **fault_catcher)
-{
- struct tt_regs save = TASK_REGS(get_current())->tt;
- unsigned long fault;
- int faulted;
-
- fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
- __do_copy, &faulted);
- TASK_REGS(get_current())->tt = save;
-
- if(!faulted)
- return 0;
- else if (fault)
- return n - (fault - (unsigned long) from);
- else
- /* In case of a general protection fault, we don't have the
- * fault address, so NULL is used instead. Pretend we didn't
- * copy anything. */
- return n;
-}
-
-static void __do_strncpy(void *dst, const void *src, int count)
-{
- strncpy(dst, src, count);
-}
-
-int __do_strncpy_from_user(char *dst, const char *src, unsigned long count,
- void **fault_addr, void **fault_catcher)
-{
- struct tt_regs save = TASK_REGS(get_current())->tt;
- unsigned long fault;
- int faulted;
-
- fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher,
- __do_strncpy, &faulted);
- TASK_REGS(get_current())->tt = save;
-
- if(!faulted) return(strlen(dst));
- else return(-1);
-}
-
-static void __do_clear(void *to, const void *from, int n)
-{
- memset(to, 0, n);
-}
-
-int __do_clear_user(void *mem, unsigned long len,
- void **fault_addr, void **fault_catcher)
-{
- struct tt_regs save = TASK_REGS(get_current())->tt;
- unsigned long fault;
- int faulted;
-
- fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher,
- __do_clear, &faulted);
- TASK_REGS(get_current())->tt = save;
-
- if(!faulted) return(0);
- else return(len - (fault - (unsigned long) mem));
-}
-
-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;
-}
-
-/*
- * 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/uaccess.c b/arch/um/kernel/uaccess.c
index 054e3de0784..d7436aacd26 100644
--- a/arch/um/kernel/uaccess.c
+++ b/arch/um/kernel/uaccess.c
@@ -18,7 +18,7 @@ void __do_copy(void *to, const void *from, int n)
int __do_copy_to_user(void *to, const void *from, int n,
- void **fault_addr, void **fault_catcher)
+ void **fault_addr, jmp_buf **fault_catcher)
{
unsigned long fault;
int faulted;
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index ecc458fe51b..f1c71393f57 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -1,46 +1,24 @@
/*
- * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/sched.h"
-#include "linux/notifier.h"
-#include "linux/mm.h"
-#include "linux/types.h"
-#include "linux/tty.h"
-#include "linux/init.h"
-#include "linux/bootmem.h"
-#include "linux/spinlock.h"
-#include "linux/utsname.h"
-#include "linux/sysrq.h"
-#include "linux/seq_file.h"
#include "linux/delay.h"
+#include "linux/mm.h"
#include "linux/module.h"
+#include "linux/seq_file.h"
+#include "linux/string.h"
#include "linux/utsname.h"
-#include "asm/page.h"
#include "asm/pgtable.h"
-#include "asm/ptrace.h"
-#include "asm/elf.h"
-#include "asm/user.h"
+#include "asm/processor.h"
#include "asm/setup.h"
-#include "ubd_user.h"
-#include "asm/current.h"
-#include "kern_util.h"
-#include "as-layout.h"
#include "arch.h"
+#include "as-layout.h"
+#include "init.h"
#include "kern.h"
#include "mem_user.h"
-#include "mem.h"
-#include "initrd.h"
-#include "init.h"
#include "os.h"
-#include "choose-mode.h"
-#include "mode_kern.h"
-#include "mode.h"
-#ifdef UML_CONFIG_MODE_SKAS
#include "skas.h"
-#endif
#define DEFAULT_COMMAND_LINE "root=98:0"
@@ -53,7 +31,7 @@ static void __init add_arg(char *arg)
printf("add_arg: Too many command line arguments!\n");
exit(1);
}
- if(strlen(command_line) > 0)
+ if (strlen(command_line) > 0)
strcat(command_line, " ");
strcat(command_line, arg);
}
@@ -70,8 +48,8 @@ struct cpuinfo_um boot_cpu_data = {
unsigned long thread_saved_pc(struct task_struct *task)
{
- return os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
- task));
+ /* FIXME: Need to look up userspace_pid by cpu */
+ return os_process_pc(userspace_pid[0]);
}
/* Changed in setup_arch, which is called in early boot */
@@ -90,7 +68,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "processor\t: %d\n", index);
seq_printf(m, "vendor_id\t: User Mode Linux\n");
seq_printf(m, "model name\t: UML\n");
- seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas"));
+ seq_printf(m, "mode\t\t: skas\n");
seq_printf(m, "host\t\t: %s\n", host_info);
seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
loops_per_jiffy/(500000/HZ),
@@ -132,44 +110,13 @@ unsigned long end_vm;
/* Set in uml_ncpus_setup */
int ncpus = 1;
-#ifdef CONFIG_CMDLINE_ON_HOST
-/* Pointer set in linux_main, the array itself is private to each thread,
- * and changed at address space creation time so this poses no concurrency
- * problems.
- */
-static char *argv1_begin = NULL;
-static char *argv1_end = NULL;
-#endif
-
/* Set in early boot */
static int have_root __initdata = 0;
/* Set in uml_mem_setup and modified in linux_main */
long long physmem_size = 32 * 1024 * 1024;
-void set_cmdline(char *cmd)
-{
-#ifdef CONFIG_CMDLINE_ON_HOST
- char *umid, *ptr;
-
- if(CHOOSE_MODE(honeypot, 0)) return;
-
- umid = get_umid();
- if(*umid != '\0'){
- snprintf(argv1_begin,
- (argv1_end - argv1_begin) * sizeof(*ptr),
- "(%s) ", umid);
- ptr = &argv1_begin[strlen(argv1_begin)];
- }
- else ptr = argv1_begin;
-
- snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd);
- memset(argv1_begin + strlen(argv1_begin), '\0',
- argv1_end - argv1_begin - strlen(argv1_begin));
-#endif
-}
-
-static char *usage_string =
+static char *usage_string =
"User Mode Linux v%s\n"
" available at http://user-mode-linux.sourceforge.net/\n\n";
@@ -201,13 +148,10 @@ __uml_setup("root=", uml_root_setup,
" root=/dev/ubd5\n\n"
);
-#ifndef CONFIG_MODE_TT
-
static int __init no_skas_debug_setup(char *line, int *add)
{
printf("'debug' is not necessary to gdb UML in skas mode - run \n");
- printf("'gdb linux' and disable CONFIG_CMDLINE_ON_HOST if gdb \n");
- printf("doesn't work as expected\n");
+ printf("'gdb linux'");
return 0;
}
@@ -217,8 +161,6 @@ __uml_setup("debug", no_skas_debug_setup,
" this flag is not needed to run gdb on UML in skas mode\n\n"
);
-#endif
-
#ifdef CONFIG_SMP
static int __init uml_ncpus_setup(char *line, int *add)
{
@@ -232,56 +174,10 @@ static int __init uml_ncpus_setup(char *line, int *add)
__uml_setup("ncpus=", uml_ncpus_setup,
"ncpus=<# of desired CPUs>\n"
-" This tells an SMP kernel how many virtual processors to start.\n\n"
+" This tells an SMP kernel how many virtual processors to start.\n\n"
);
#endif
-static int force_tt = 0;
-
-#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS)
-#define DEFAULT_TT 0
-
-static int __init mode_tt_setup(char *line, int *add)
-{
- force_tt = 1;
- return 0;
-}
-
-#else
-#ifdef CONFIG_MODE_SKAS
-
-#define DEFAULT_TT 0
-
-static int __init mode_tt_setup(char *line, int *add)
-{
- printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
- return 0;
-}
-
-#else
-#ifdef CONFIG_MODE_TT
-
-#define DEFAULT_TT 1
-
-static int __init mode_tt_setup(char *line, int *add)
-{
- printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
- return 0;
-}
-
-#endif
-#endif
-#endif
-
-__uml_setup("mode=tt", mode_tt_setup,
-"mode=tt\n"
-" When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n"
-" forces UML to run in tt (tracing thread) mode. It is not the default\n"
-" because it's slower and less secure than skas mode.\n\n"
-);
-
-int mode_tt = DEFAULT_TT;
-
static int __init Usage(char *line, int *add)
{
const char **p;
@@ -310,9 +206,8 @@ static int __init uml_checksetup(char *line, int *add)
int n;
n = strlen(p->str);
- if(!strncmp(line, p->str, n)){
- if (p->setup_func(line + n, add)) return 1;
- }
+ if (!strncmp(line, p->str, n) && p->setup_func(line + n, add))
+ return 1;
p++;
}
return 0;
@@ -323,7 +218,7 @@ static void __init uml_postsetup(void)
initcall_t *p;
p = &__uml_postsetup_start;
- while(p < &__uml_postsetup_end){
+ while(p < &__uml_postsetup_end) {
(*p)();
p++;
}
@@ -339,6 +234,20 @@ EXPORT_SYMBOL(end_iomem);
extern char __binary_start;
+static unsigned long set_task_sizes_skas(unsigned long *task_size_out)
+{
+ /* Round up to the nearest 4M */
+ unsigned long host_task_size = ROUND_4M((unsigned long)
+ &host_task_size);
+
+ if (!skas_needs_stub)
+ *task_size_out = host_task_size;
+ else
+ *task_size_out = STUB_START & PGDIR_MASK;
+
+ return host_task_size;
+}
+
int __init linux_main(int argc, char **argv)
{
unsigned long avail, diff;
@@ -346,45 +255,30 @@ int __init linux_main(int argc, char **argv)
unsigned int i, add;
char * mode;
- for (i = 1; i < argc; i++){
- if((i == 1) && (argv[i][0] == ' ')) continue;
+ for (i = 1; i < argc; i++) {
+ if ((i == 1) && (argv[i][0] == ' '))
+ continue;
add = 1;
uml_checksetup(argv[i], &add);
if (add)
add_arg(argv[i]);
}
- if(have_root == 0)
+ if (have_root == 0)
add_arg(DEFAULT_COMMAND_LINE);
+ /* OS sanity checks that need to happen before the kernel runs */
os_early_checks();
- if (force_tt)
- clear_can_do_skas();
- mode_tt = force_tt ? 1 : !can_do_skas();
-#ifndef CONFIG_MODE_TT
- if (mode_tt) {
- /*Since CONFIG_MODE_TT is #undef'ed, force_tt cannot be 1. So,
- * can_do_skas() returned 0, and the message is correct. */
- printf("Support for TT mode is disabled, and no SKAS support is present on the host.\n");
- exit(1);
- }
-#endif
-#ifndef CONFIG_MODE_SKAS
- mode = "TT";
-#else
- /* Show to the user the result of selection */
- if (mode_tt)
- mode = "TT";
- else if (proc_mm && ptrace_faultinfo)
+ can_do_skas();
+
+ if (proc_mm && ptrace_faultinfo)
mode = "SKAS3";
else
mode = "SKAS0";
-#endif
printf("UML running in %s mode\n", mode);
- host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt,
- set_task_sizes_skas, &task_size);
+ host_task_size = set_task_sizes_skas(&task_size);
/*
* Setting up handlers to 'sig_info' struct
@@ -392,13 +286,15 @@ int __init linux_main(int argc, char **argv)
os_fill_handlinfo(handlinfo_kern);
brk_start = (unsigned long) sbrk(0);
- CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
- /* Increase physical memory size for exec-shield users
- so they actually get what they asked for. This should
- add zero for non-exec shield users */
+
+ /*
+ * Increase physical memory size for exec-shield users
+ * so they actually get what they asked for. This should
+ * add zero for non-exec shield users
+ */
diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
- if(diff > 1024 * 1024){
+ if (diff > 1024 * 1024) {
printf("Adding %ld bytes to physical memory to account for "
"exec-shield gap\n", diff);
physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
@@ -411,20 +307,16 @@ int __init linux_main(int argc, char **argv)
setup_machinename(init_utsname()->machine);
-#ifdef CONFIG_CMDLINE_ON_HOST
- argv1_begin = argv[1];
- argv1_end = &argv[1][strlen(argv[1])];
-#endif
-
highmem = 0;
iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
- /* Zones have to begin on a 1 << MAX_ORDER page boundary,
+ /*
+ * Zones have to begin on a 1 << MAX_ORDER page boundary,
* so this makes sure that's true for highmem
*/
max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1);
- if(physmem_size + iomem_size > max_physmem){
+ if (physmem_size + iomem_size > max_physmem) {
highmem = physmem_size + iomem_size - max_physmem;
physmem_size -= highmem;
#ifndef CONFIG_HIGHMEM
@@ -441,7 +333,7 @@ int __init linux_main(int argc, char **argv)
start_vm = VMALLOC_START;
setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
- if(init_maps(physmem_size, iomem_size, highmem)){
+ if (init_maps(physmem_size, iomem_size, highmem)) {
printf("Failed to allocate mem_map for %Lu bytes of physical "
"memory and %Lu bytes of highmem\n", physmem_size,
highmem);
@@ -450,10 +342,11 @@ int __init linux_main(int argc, char **argv)
virtmem_size = physmem_size;
avail = get_kmem_end() - start_vm;
- if(physmem_size > avail) virtmem_size = avail;
+ if (physmem_size > avail)
+ virtmem_size = avail;
end_vm = start_vm + virtmem_size;
- if(virtmem_size < physmem_size)
+ if (virtmem_size < physmem_size)
printf("Kernel virtual memory size shrunk to %lu bytes\n",
virtmem_size);
@@ -462,7 +355,7 @@ int __init linux_main(int argc, char **argv)
stack_protections((unsigned long) &init_thread_info);
os_flush_stdout();
- return CHOOSE_MODE(start_uml_tt(), start_uml_skas());
+ return start_uml();
}
extern int uml_exitcode;
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index 81acdc24348..13df191e2b4 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -18,13 +18,6 @@ SECTIONS
. = START + SIZEOF_HEADERS;
-#ifdef MODE_TT
- .remap_data : { UNMAP_PATH (.data .bss) }
- .remap : { UNMAP_PATH (.text) }
-
- . = ALIGN(4096); /* Init code and data */
-#endif
-
_text = .;
_stext = .;
__init_begin = .;