aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/Makefile14
-rw-r--r--arch/um/kernel/checksum.c36
-rw-r--r--arch/um/kernel/exec_kern.c1
-rw-r--r--arch/um/kernel/initrd.c (renamed from arch/um/kernel/initrd_kern.c)21
-rw-r--r--arch/um/kernel/initrd_user.c46
-rw-r--r--arch/um/kernel/irq.c1
-rw-r--r--arch/um/kernel/irq_user.c10
-rw-r--r--arch/um/kernel/ksyms.c4
-rw-r--r--arch/um/kernel/main.c42
-rw-r--r--arch/um/kernel/mem.c40
-rw-r--r--arch/um/kernel/process.c51
-rw-r--r--arch/um/kernel/process_kern.c56
-rw-r--r--arch/um/kernel/ptrace.c128
-rw-r--r--arch/um/kernel/sigio_user.c1
-rw-r--r--arch/um/kernel/skas/include/mode_kern-skas.h1
-rw-r--r--arch/um/kernel/skas/include/skas.h3
-rw-r--r--arch/um/kernel/skas/include/uaccess-skas.h4
-rw-r--r--arch/um/kernel/skas/process.c68
-rw-r--r--arch/um/kernel/skas/process_kern.c11
-rw-r--r--arch/um/kernel/skas/trap_user.c24
-rw-r--r--arch/um/kernel/skas/uaccess.c7
-rw-r--r--arch/um/kernel/skas/util/Makefile1
-rw-r--r--arch/um/kernel/skas/util/mk_ptregs-i386.c46
-rw-r--r--arch/um/kernel/skas/util/mk_ptregs-x86_64.c60
-rw-r--r--arch/um/kernel/syscall_kern.c1
-rw-r--r--arch/um/kernel/sysrq.c21
-rw-r--r--arch/um/kernel/time_kern.c18
-rw-r--r--arch/um/kernel/trap_kern.c64
-rw-r--r--arch/um/kernel/trap_user.c13
-rw-r--r--arch/um/kernel/tt/Makefile1
-rw-r--r--arch/um/kernel/tt/include/mode_kern-tt.h1
-rw-r--r--arch/um/kernel/tt/include/uaccess-tt.h4
-rw-r--r--arch/um/kernel/tt/ksyms.c1
-rw-r--r--arch/um/kernel/tt/mem.c8
-rw-r--r--arch/um/kernel/tt/process_kern.c26
-rw-r--r--arch/um/kernel/tt/syscall_user.c4
-rw-r--r--arch/um/kernel/tt/tracer.c8
-rw-r--r--arch/um/kernel/tt/trap_user.c6
-rw-r--r--arch/um/kernel/um_arch.c14
-rw-r--r--arch/um/kernel/uml.lds.S2
-rw-r--r--arch/um/kernel/vmlinux.lds.S6
41 files changed, 377 insertions, 497 deletions
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 246f0e7fb4cc..a8918e80df96 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -4,9 +4,9 @@
#
extra-y := vmlinux.lds
-clean-files := vmlinux.lds.S config.tmp
+clean-files :=
-obj-y = checksum.o config.o exec_kern.o exitcode.o \
+obj-y = config.o exec_kern.o exitcode.o \
helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \
physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \
sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \
@@ -14,7 +14,7 @@ obj-y = checksum.o config.o exec_kern.o exitcode.o \
tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \
user_util.o
-obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
+obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
obj-$(CONFIG_TTY_LOG) += tty_log.o
@@ -23,18 +23,14 @@ obj-$(CONFIG_SYSCALL_DEBUG) += syscall_user.o
obj-$(CONFIG_MODE_TT) += tt/
obj-$(CONFIG_MODE_SKAS) += skas/
-# This needs be compiled with frame pointers regardless of how the rest of the
-# kernel is built.
-CFLAGS_frame.o := -fno-omit-frame-pointer
-
user-objs-$(CONFIG_TTY_LOG) += tty_log.o
USER_OBJS := $(user-objs-y) config.o helper.o main.o process.o tempfile.o \
- time.o tty_log.o umid.o user_util.o frame.o
+ time.o tty_log.o umid.o user_util.o
include arch/um/scripts/Makefile.rules
-targets += config.c
+targets := config.c config.tmp
# Be careful with the below Sed code - sed is pitfall-rich!
# We use sed to lower build requirements, for "embedded" builders for instance.
diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c
deleted file mode 100644
index e69b2be951d1..000000000000
--- a/arch/um/kernel/checksum.c
+++ /dev/null
@@ -1,36 +0,0 @@
-#include "asm/uaccess.h"
-#include "linux/errno.h"
-#include "linux/module.h"
-
-unsigned int arch_csum_partial(const unsigned char *buff, int len, int sum);
-
-unsigned int csum_partial(unsigned char *buff, int len, int sum)
-{
- return arch_csum_partial(buff, len, sum);
-}
-
-EXPORT_SYMBOL(csum_partial);
-
-unsigned int csum_partial_copy_to(const unsigned char *src,
- unsigned char __user *dst, int len, int sum,
- int *err_ptr)
-{
- if(copy_to_user(dst, src, len)){
- *err_ptr = -EFAULT;
- return(-1);
- }
-
- return(arch_csum_partial(src, len, sum));
-}
-
-unsigned int csum_partial_copy_from(const unsigned char __user *src,
- unsigned char *dst, int len, int sum,
- int *err_ptr)
-{
- if(copy_from_user(dst, src, len)){
- *err_ptr = -EFAULT;
- return(-1);
- }
-
- return arch_csum_partial(dst, len, sum);
-}
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index 49ddabe69be7..efd222ffe20e 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -16,7 +16,6 @@
#include "kern.h"
#include "irq_user.h"
#include "tlb.h"
-#include "2_5compat.h"
#include "os.h"
#include "time_user.h"
#include "choose-mode.h"
diff --git a/arch/um/kernel/initrd_kern.c b/arch/um/kernel/initrd.c
index fc568af468b9..82ecf904b09c 100644
--- a/arch/um/kernel/initrd_kern.c
+++ b/arch/um/kernel/initrd.c
@@ -41,12 +41,31 @@ static int __init uml_initrd_setup(char *line, int *add)
return 0;
}
-__uml_setup("initrd=", uml_initrd_setup,
+__uml_setup("initrd=", uml_initrd_setup,
"initrd=<initrd image>\n"
" This is used to boot UML from an initrd image. The argument is the\n"
" name of the file containing the image.\n\n"
);
+int load_initrd(char *filename, void *buf, int size)
+{
+ int fd, n;
+
+ fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
+ if(fd < 0){
+ printk("Opening '%s' failed - err = %d\n", filename, -fd);
+ return(-1);
+ }
+ n = os_read_file(fd, buf, size);
+ if(n != size){
+ printk("Read of %d bytes from '%s' failed, err = %d\n", size,
+ filename, -n);
+ return(-1);
+ }
+
+ os_close_file(fd);
+ 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
diff --git a/arch/um/kernel/initrd_user.c b/arch/um/kernel/initrd_user.c
deleted file mode 100644
index cb90681e151c..000000000000
--- a/arch/um/kernel/initrd_user.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-#include "user_util.h"
-#include "kern_util.h"
-#include "user.h"
-#include "initrd.h"
-#include "os.h"
-
-int load_initrd(char *filename, void *buf, int size)
-{
- int fd, n;
-
- fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
- if(fd < 0){
- printk("Opening '%s' failed - err = %d\n", filename, -fd);
- return(-1);
- }
- n = os_read_file(fd, buf, size);
- if(n != size){
- printk("Read of %d bytes from '%s' failed, err = %d\n", size,
- filename, -n);
- return(-1);
- }
-
- os_close_file(fd);
- 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/irq.c b/arch/um/kernel/irq.c
index d71e8f00810f..d44fb5282547 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -163,7 +163,6 @@ void __init init_IRQ(void)
irq_desc[i].handler = &SIGIO_irq_type;
enable_irq(i);
}
- init_irq_signals(0);
}
/*
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index 6d6f9484b884..b3074cbaa479 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -236,9 +236,15 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
(*prev)->fd, pollfds[i].fd);
goto out;
}
- memcpy(&pollfds[i], &pollfds[i + 1],
- (pollfds_num - i - 1) * sizeof(pollfds[0]));
+
pollfds_num--;
+
+ /* This moves the *whole* array after pollfds[i] (though
+ * it doesn't spot as such)! */
+
+ memmove(&pollfds[i], &pollfds[i + 1],
+ (pollfds_num - i) * sizeof(pollfds[0]));
+
if(last_irq_ptr == &old_fd->next)
last_irq_ptr = prev;
*prev = (*prev)->next;
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index b41d3397d07b..99439fa15ef4 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -10,7 +10,6 @@
#include "linux/spinlock.h"
#include "linux/highmem.h"
#include "asm/current.h"
-#include "asm/delay.h"
#include "asm/processor.h"
#include "asm/unistd.h"
#include "asm/pgalloc.h"
@@ -28,8 +27,6 @@ EXPORT_SYMBOL(uml_physmem);
EXPORT_SYMBOL(set_signals);
EXPORT_SYMBOL(get_signals);
EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(__const_udelay);
-EXPORT_SYMBOL(__udelay);
EXPORT_SYMBOL(sys_waitpid);
EXPORT_SYMBOL(task_size);
EXPORT_SYMBOL(flush_tlb_range);
@@ -60,6 +57,7 @@ EXPORT_SYMBOL(copy_to_user_tt);
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(uml_strdup);
diff --git a/arch/um/kernel/main.c b/arch/um/kernel/main.c
index a17c49703f9b..e59f58152678 100644
--- a/arch/um/kernel/main.c
+++ b/arch/um/kernel/main.c
@@ -24,8 +24,6 @@
#include "mode.h"
#include "choose-mode.h"
#include "uml-config.h"
-#include "irq_user.h"
-#include "time_user.h"
#include "os.h"
/* Set in set_stklim, which is called from main and __wrap_malloc.
@@ -71,7 +69,7 @@ static __init void do_uml_initcalls(void)
static void last_ditch_exit(int sig)
{
- CHOOSE_MODE(kmalloc_ok = 0, (void) 0);
+ kmalloc_ok = 0;
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGHUP, SIG_DFL);
@@ -87,7 +85,7 @@ int main(int argc, char **argv, char **envp)
{
char **new_argv;
sigset_t mask;
- int ret, i;
+ int ret, i, err;
/* Enable all signals except SIGIO - in some environments, we can
* enter with some signals blocked
@@ -160,27 +158,29 @@ int main(int argc, char **argv, char **envp)
*/
change_sig(SIGPROF, 0);
- /* Reboot */
- if(ret){
- int err;
+ /* This signal stuff used to be in the reboot case. However,
+ * sometimes a SIGVTALRM can come in when we're halting (reproducably
+ * when writing out gcov information, presumably because that takes
+ * some time) and cause a segfault.
+ */
- printf("\n");
+ /* stop timers and set SIG*ALRM to be ignored */
+ disable_timer();
- /* stop timers and set SIG*ALRM to be ignored */
- disable_timer();
+ /* disable SIGIO for the fds and set SIGIO to be ignored */
+ err = deactivate_all_fds();
+ if(err)
+ printf("deactivate_all_fds failed, errno = %d\n", -err);
- /* disable SIGIO for the fds and set SIGIO to be ignored */
- err = deactivate_all_fds();
- if(err)
- printf("deactivate_all_fds failed, errno = %d\n",
- -err);
-
- /* Let any pending signals fire now. This ensures
- * that they won't be delivered after the exec, when
- * they are definitely not expected.
- */
- unblock_signals();
+ /* Let any pending signals fire now. This ensures
+ * that they won't be delivered after the exec, when
+ * they are definitely not expected.
+ */
+ unblock_signals();
+ /* Reboot */
+ if(ret){
+ printf("\n");
execvp(new_argv[0], new_argv);
perror("Failed to exec kernel");
ret = 1;
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index f156661781cb..c22825f13e40 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -100,12 +100,37 @@ void mem_init(void)
#endif
}
+/*
+ * Create a page table and place a pointer to it in a middle page
+ * directory entry.
+ */
+static void __init one_page_table_init(pmd_t *pmd)
+{
+ if (pmd_none(*pmd)) {
+ pte_t *pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pmd(pmd, __pmd(_KERNPG_TABLE +
+ (unsigned long) __pa(pte)));
+ if (pte != pte_offset_kernel(pmd, 0))
+ BUG();
+ }
+}
+
+static void __init one_md_table_init(pud_t *pud)
+{
+#ifdef CONFIG_3_LEVEL_PGTABLES
+ pmd_t *pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table)));
+ if (pmd_table != pmd_offset(pud, 0))
+ BUG();
+#endif
+}
+
static void __init fixrange_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
- pte_t *pte;
int i, j;
unsigned long vaddr;
@@ -115,15 +140,12 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
pgd = pgd_base + i;
for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
- pmd = (pmd_t *)pgd;
+ pud = pud_offset(pgd, vaddr);
+ if (pud_none(*pud))
+ one_md_table_init(pud);
+ pmd = pmd_offset(pud, vaddr);
for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
- if (pmd_none(*pmd)) {
- pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
- set_pmd(pmd, __pmd(_KERNPG_TABLE +
- (unsigned long) __pa(pte)));
- if (pte != pte_offset_kernel(pmd, 0))
- BUG();
- }
+ one_page_table_init(pmd);
vaddr += PMD_SIZE;
}
j = 0;
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index f76a2692adca..1b5ef3e96c71 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -30,7 +30,6 @@
#include "init.h"
#include "os.h"
#include "uml-config.h"
-#include "ptrace_user.h"
#include "choose-mode.h"
#include "mode.h"
#ifdef UML_CONFIG_MODE_SKAS
@@ -65,8 +64,6 @@ void init_new_thread_signals(int altstack)
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
set_handler(SIGBUS, (__sighandler_t) sig_handler, flags,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
set_handler(SIGUSR2, (__sighandler_t) sig_handler,
flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
signal(SIGHUP, SIG_IGN);
@@ -133,7 +130,7 @@ int start_fork_tramp(void *thread_arg, unsigned long temp_stack,
return(arg.pid);
}
-static int ptrace_child(void *arg)
+static int ptrace_child(void)
{
int ret;
int pid = os_getpid(), ppid = getppid();
@@ -162,20 +159,16 @@ static int ptrace_child(void *arg)
_exit(ret);
}
-static int start_ptraced_child(void **stack_out)
+static int start_ptraced_child(void)
{
- void *stack;
- unsigned long sp;
int pid, n, status;
- stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if(stack == MAP_FAILED)
- panic("check_ptrace : mmap failed, errno = %d", errno);
- sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
- pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
+ pid = fork();
+ if(pid == 0)
+ ptrace_child();
+
if(pid < 0)
- panic("check_ptrace : clone failed, errno = %d", errno);
+ panic("check_ptrace : fork failed, errno = %d", errno);
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
if(n < 0)
panic("check_ptrace : wait failed, errno = %d", errno);
@@ -183,7 +176,6 @@ static int start_ptraced_child(void **stack_out)
panic("check_ptrace : expected SIGSTOP, got status = %d",
status);
- *stack_out = stack;
return(pid);
}
@@ -191,12 +183,12 @@ static int start_ptraced_child(void **stack_out)
* just avoid using sysemu, not panic, but only if SYSEMU features are broken.
* So only for SYSEMU features we test mustpanic, while normal host features
* must work anyway!*/
-static int stop_ptraced_child(int pid, void *stack, int exitcode, int mustpanic)
+static int stop_ptraced_child(int pid, int exitcode, int mustexit)
{
int status, n, ret = 0;
if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
- panic("check_ptrace : ptrace failed, errno = %d", errno);
+ panic("stop_ptraced_child : ptrace failed, errno = %d", errno);
CATCH_EINTR(n = waitpid(pid, &status, 0));
if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) {
int exit_with = WEXITSTATUS(status);
@@ -207,15 +199,13 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode, int mustpanic)
printk("check_ptrace : child exited with exitcode %d, while "
"expecting %d; status 0x%x", exit_with,
exitcode, status);
- if (mustpanic)
+ if (mustexit)
panic("\n");
else
printk("\n");
ret = -1;
}
- if(munmap(stack, PAGE_SIZE) < 0)
- panic("check_ptrace : munmap failed, errno = %d", errno);
return ret;
}
@@ -237,12 +227,11 @@ __uml_setup("nosysemu", nosysemu_cmd_param,
static void __init check_sysemu(void)
{
- void *stack;
int pid, syscall, n, status, count=0;
printk("Checking syscall emulation patch for ptrace...");
sysemu_supported = 0;
- pid = start_ptraced_child(&stack);
+ pid = start_ptraced_child();
if(ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0)
goto fail;
@@ -260,7 +249,7 @@ static void __init check_sysemu(void)
panic("check_sysemu : failed to modify system "
"call return, errno = %d", errno);
- if (stop_ptraced_child(pid, stack, 0, 0) < 0)
+ if (stop_ptraced_child(pid, 0, 0) < 0)
goto fail_stopped;
sysemu_supported = 1;
@@ -268,7 +257,7 @@ static void __init check_sysemu(void)
set_using_sysemu(!force_sysemu_disabled);
printk("Checking advanced syscall emulation patch for ptrace...");
- pid = start_ptraced_child(&stack);
+ pid = start_ptraced_child();
while(1){
count++;
if(ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0)
@@ -293,7 +282,7 @@ static void __init check_sysemu(void)
break;
}
}
- if (stop_ptraced_child(pid, stack, 0, 0) < 0)
+ if (stop_ptraced_child(pid, 0, 0) < 0)
goto fail_stopped;
sysemu_supported = 2;
@@ -304,18 +293,17 @@ static void __init check_sysemu(void)
return;
fail:
- stop_ptraced_child(pid, stack, 1, 0);
+ stop_ptraced_child(pid, 1, 0);
fail_stopped:
printk("missing\n");
}
void __init check_ptrace(void)
{
- void *stack;
int pid, syscall, n, status;
printk("Checking that ptrace can change system call numbers...");
- pid = start_ptraced_child(&stack);
+ pid = start_ptraced_child();
if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
panic("check_ptrace: PTRACE_SETOPTIONS failed, errno = %d", errno);
@@ -342,7 +330,7 @@ void __init check_ptrace(void)
break;
}
}
- stop_ptraced_child(pid, stack, 0, 1);
+ stop_ptraced_child(pid, 0, 1);
printk("OK\n");
check_sysemu();
}
@@ -374,11 +362,10 @@ void forward_pending_sigio(int target)
static inline int check_skas3_ptrace_support(void)
{
struct ptrace_faultinfo fi;
- void *stack;
int pid, n, ret = 1;
printf("Checking for the skas3 patch in the host...");
- pid = start_ptraced_child(&stack);
+ pid = start_ptraced_child();
n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
if (n < 0) {
@@ -393,7 +380,7 @@ static inline int check_skas3_ptrace_support(void)
}
init_registers(pid);
- stop_ptraced_child(pid, stack, 1, 1);
+ stop_ptraced_child(pid, 1, 1);
return(ret);
}
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 7a943696f950..804c6bbdf67c 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -43,7 +43,6 @@
#include "tlb.h"
#include "frame_kern.h"
#include "sigcontext.h"
-#include "2_5compat.h"
#include "os.h"
#include "mode.h"
#include "mode_kern.h"
@@ -55,18 +54,6 @@
*/
struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
-struct task_struct *get_task(int pid, int require)
-{
- struct task_struct *ret;
-
- read_lock(&tasklist_lock);
- ret = find_task_by_pid(pid);
- read_unlock(&tasklist_lock);
-
- if(require && (ret == NULL)) panic("get_task couldn't find a task\n");
- return(ret);
-}
-
int external_pid(void *t)
{
struct task_struct *task = t ? t : current;
@@ -115,16 +102,6 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
return(pid);
}
-void switch_mm(struct mm_struct *prev, struct mm_struct *next,
- struct task_struct *tsk)
-{
- int cpu = smp_processor_id();
-
- if (prev != next)
- cpu_clear(cpu, prev->cpu_vm_mask);
- cpu_set(cpu, next->cpu_vm_mask);
-}
-
void set_current(void *t)
{
struct task_struct *task = t;
@@ -152,7 +129,6 @@ void release_thread(struct task_struct *task)
void exit_thread(void)
{
- CHOOSE_MODE(exit_thread_tt(), exit_thread_skas());
unprotect_stack((unsigned long) current_thread);
}
@@ -200,7 +176,6 @@ void default_idle(void)
while(1){
/* endless idle loop with no priority at all */
- SET_PRI(current);
/*
* although we are an idle CPU, we do not want to
@@ -223,11 +198,6 @@ int page_size(void)
return(PAGE_SIZE);
}
-unsigned long page_mask(void)
-{
- return(PAGE_MASK);
-}
-
void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
pte_t *pte_out)
{
@@ -360,11 +330,6 @@ char *uml_strdup(char *string)
return(new);
}
-void *get_init_task(void)
-{
- return(&init_thread_union.thread_info.task);
-}
-
int copy_to_user_proc(void __user *to, void *from, int size)
{
return(copy_to_user(to, from, size));
@@ -476,21 +441,18 @@ int singlestepping(void * t)
return 2;
}
+/*
+ * Only x86 and x86_64 have an arch_align_stack().
+ * All other arches have "#define arch_align_stack(x) (x)"
+ * in their asm/system.h
+ * As this is included in UML from asm-um/system-generic.h,
+ * we can use it to behave as the subarch does.
+ */
+#ifndef arch_align_stack
unsigned long arch_align_stack(unsigned long sp)
{
if (randomize_va_space)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
-
-
-/*
- * 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:
- */
+#endif
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index e50e60ff5d27..71af4d503899 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -19,15 +19,30 @@
#include "skas_ptrace.h"
#include "sysdep/ptrace.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;
+
+#ifdef SUBARCH_SET_SINGLESTEPPING
+ SUBARCH_SET_SINGLESTEPPING(child, on);
+#endif
+}
+
/*
* Called by kernel/ptrace.c when detaching..
*/
void ptrace_disable(struct task_struct *child)
{
- child->ptrace &= ~PT_DTRACE;
- child->thread.singlestep_syscall = 0;
+ set_singlestepping(child,0);
}
+extern int peek_user(struct task_struct * child, long addr, long data);
+extern int poke_user(struct task_struct * child, long addr, long data);
+
long sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
@@ -67,6 +82,10 @@ long sys_ptrace(long request, long pid, long addr, long data)
goto out_tsk;
}
+#ifdef SUBACH_PTRACE_SPECIAL
+ SUBARCH_PTRACE_SPECIAL(child,request,addr,data);
+#endif
+
ret = ptrace_check_attach(child, request == PTRACE_KILL);
if (ret < 0)
goto out_tsk;
@@ -87,26 +106,9 @@ long sys_ptrace(long request, long pid, long addr, long data)
}
/* read the word at location addr in the USER area. */
- case PTRACE_PEEKUSR: {
- unsigned long tmp;
-
- ret = -EIO;
- if ((addr & 3) || addr < 0)
- break;
-
- tmp = 0; /* Default return condition */
- if(addr < MAX_REG_OFFSET){
- tmp = getreg(child, addr);
- }
- else if((addr >= offsetof(struct user, u_debugreg[0])) &&
- (addr <= offsetof(struct user, u_debugreg[7]))){
- addr -= offsetof(struct user, u_debugreg[0]);
- addr = addr >> 2;
- tmp = child->thread.arch.debugregs[addr];
- }
- ret = put_user(tmp, (unsigned long __user *) 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. */
@@ -119,26 +121,8 @@ long sys_ptrace(long request, long pid, long addr, long data)
break;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
- ret = -EIO;
- if ((addr & 3) || addr < 0)
- break;
-
- if (addr < MAX_REG_OFFSET) {
- ret = putreg(child, addr, data);
- break;
- }
-#if 0 /* XXX x86_64 */
- else if((addr >= offsetof(struct user, u_debugreg[0])) &&
- (addr <= offsetof(struct user, u_debugreg[7]))){
- addr -= offsetof(struct user, u_debugreg[0]);
- addr = addr >> 2;
- if((addr == 4) || (addr == 5)) break;
- child->thread.arch.debugregs[addr] = data;
- ret = 0;
- }
-#endif
-
- break;
+ ret = poke_user(child, addr, data);
+ break;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
@@ -146,8 +130,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
if (!valid_signal(data))
break;
- child->ptrace &= ~PT_DTRACE;
- child->thread.singlestep_syscall = 0;
+ set_singlestepping(child, 0);
if (request == PTRACE_SYSCALL) {
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
}
@@ -170,8 +153,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
- child->ptrace &= ~PT_DTRACE;
- child->thread.singlestep_syscall = 0;
+ set_singlestepping(child, 0);
child->exit_code = SIGKILL;
wake_up_process(child);
break;
@@ -182,8 +164,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
if (!valid_signal(data))
break;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- child->ptrace |= PT_DTRACE;
- child->thread.singlestep_syscall = 0;
+ set_singlestepping(child, 1);
child->exit_code = data;
/* give it a chance to run. */
wake_up_process(child);
@@ -250,23 +231,19 @@ long sys_ptrace(long request, long pid, long addr, long data)
break;
#endif
case PTRACE_FAULTINFO: {
- struct ptrace_faultinfo fault;
-
- fault = ((struct ptrace_faultinfo)
- { .is_write = child->thread.err,
- .addr = child->thread.cr2 });
- ret = copy_to_user((unsigned long __user *) data, &fault,
- sizeof(fault));
+ /* Take the info from thread->arch->faultinfo,
+ * but transfer max. sizeof(struct ptrace_faultinfo).
+ * On i386, ptrace_faultinfo is smaller!
+ */
+ ret = copy_to_user((unsigned long __user *) data,
+ &child->thread.arch.faultinfo,
+ sizeof(struct ptrace_faultinfo));
if(ret)
break;
break;
}
- case PTRACE_SIGPENDING:
- ret = copy_to_user((unsigned long __user *) data,
- &child->pending.signal,
- sizeof(child->pending.signal));
- break;
+#ifdef PTRACE_LDT
case PTRACE_LDT: {
struct ptrace_ldt ldt;
@@ -282,6 +259,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
break;
}
+#endif
#ifdef CONFIG_PROC_MM
case PTRACE_SWITCH_MM: {
struct mm_struct *old = child->mm;
@@ -337,15 +315,16 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
if (unlikely(current->audit_context)) {
if (!entryexit)
- audit_syscall_entry(current,
- UPT_SYSCALL_NR(&regs->regs),
- UPT_SYSCALL_ARG1(&regs->regs),
- UPT_SYSCALL_ARG2(&regs->regs),
- UPT_SYSCALL_ARG3(&regs->regs),
- UPT_SYSCALL_ARG4(&regs->regs));
- else
- audit_syscall_exit(current,
- UPT_SYSCALL_RET(&regs->regs));
+ audit_syscall_entry(current,
+ HOST_AUDIT_ARCH,
+ UPT_SYSCALL_NR(regs),
+ UPT_SYSCALL_ARG1(regs),
+ UPT_SYSCALL_ARG2(regs),
+ UPT_SYSCALL_ARG3(regs),
+ UPT_SYSCALL_ARG4(regs));
+ else audit_syscall_exit(current,
+ AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
+ UPT_SYSCALL_RET(regs));
}
/* Fake a debug trap */
@@ -375,14 +354,3 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
current->exit_code = 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/sigio_user.c b/arch/um/kernel/sigio_user.c
index 668df13d8c9d..e89218958f38 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -182,6 +182,7 @@ static int write_sigio_thread(void *unused)
int i, n, respond_fd;
char c;
+ signal(SIGWINCH, SIG_IGN);
fds = &current_poll;
while(1){
n = poll(fds->poll, fds->used, -1);
diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/kernel/skas/include/mode_kern-skas.h
index 94c564962378..e48490028111 100644
--- a/arch/um/kernel/skas/include/mode_kern-skas.h
+++ b/arch/um/kernel/skas/include/mode_kern-skas.h
@@ -18,7 +18,6 @@ extern 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);
extern void release_thread_skas(struct task_struct *task);
-extern void exit_thread_skas(void);
extern void initial_thread_cb_skas(void (*proc)(void *), void *arg);
extern void init_idle_skas(void);
extern void flush_tlb_kernel_range_skas(unsigned long start,
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index f0702c2c7204..96b51dba3471 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -27,9 +27,10 @@ extern void map(int fd, unsigned long virt, unsigned long len, int r, int w,
extern int unmap(int fd, void *addr, unsigned long len);
extern int protect(int fd, unsigned long addr, unsigned long len,
int r, int w, int x);
-extern void user_signal(int sig, union uml_pt_regs *regs);
+extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
extern int new_mm(int from);
extern void start_userspace(int cpu);
+extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
extern long execute_syscall_skas(void *r);
#endif
diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h
index c35620385da0..cd6c280482cb 100644
--- a/arch/um/kernel/skas/include/uaccess-skas.h
+++ b/arch/um/kernel/skas/include/uaccess-skas.h
@@ -18,8 +18,8 @@
((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
((unsigned long) (addr) + (size) >= (unsigned long)(addr))))
-static inline int __deprecated verify_area_skas(int type, const void * addr,
- unsigned long size)
+static inline int verify_area_skas(int type, const void * addr,
+ unsigned long size)
{
return(access_ok_skas(type, addr, size) ? 0 : -EFAULT);
}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index b4ffaaa81241..773cd2b525fc 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -4,6 +4,7 @@
*/
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
@@ -27,27 +28,37 @@
#include "chan_user.h"
#include "signal_user.h"
#include "registers.h"
+#include "process.h"
int is_skas_winch(int pid, int fd, void *data)
{
- if(pid != os_getpid())
+ if(pid != os_getpgrp())
return(0);
register_winch_irq(-1, fd, -1, data);
return(1);
}
-static void handle_segv(int pid)
+void get_skas_faultinfo(int pid, struct faultinfo * fi)
{
- struct ptrace_faultinfo fault;
int err;
- err = ptrace(PTRACE_FAULTINFO, pid, 0, &fault);
+ err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
if(err)
- panic("handle_segv - PTRACE_FAULTINFO failed, errno = %d\n",
- errno);
+ panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
+ "errno = %d\n", errno);
+
+ /* Special handling for i386, which has different structs */
+ if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
+ memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
+ sizeof(struct faultinfo) -
+ sizeof(struct ptrace_faultinfo));
+}
- segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL);
+static void handle_segv(int pid, union uml_pt_regs * regs)
+{
+ get_skas_faultinfo(pid, &regs->skas.faultinfo);
+ segv(regs->skas.faultinfo, 0, 1, NULL);
}
/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
@@ -163,7 +174,7 @@ void userspace(union uml_pt_regs *regs)
if(WIFSTOPPED(status)){
switch(WSTOPSIG(status)){
case SIGSEGV:
- handle_segv(pid);
+ handle_segv(pid, regs);
break;
case SIGTRAP + 0x80:
handle_trap(pid, regs, local_using_sysemu);
@@ -177,7 +188,7 @@ void userspace(union uml_pt_regs *regs)
case SIGBUS:
case SIGFPE:
case SIGWINCH:
- user_signal(WSTOPSIG(status), regs);
+ user_signal(WSTOPSIG(status), regs, pid);
break;
default:
printk("userspace - child stopped with signal "
@@ -190,6 +201,11 @@ void userspace(union uml_pt_regs *regs)
}
}
}
+#define INIT_JMP_NEW_THREAD 0
+#define INIT_JMP_REMOVE_SIGSTACK 1
+#define INIT_JMP_CALLBACK 2
+#define INIT_JMP_HALT 3
+#define INIT_JMP_REBOOT 4
void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
void (*handler)(int))
@@ -225,7 +241,7 @@ void thread_wait(void *sw, void *fb)
*switch_buf = &buf;
fork_buf = fb;
if(sigsetjmp(buf, 1) == 0)
- siglongjmp(*fork_buf, 1);
+ siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
}
void switch_threads(void *me, void *next)
@@ -249,23 +265,31 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
sigjmp_buf **switch_buf = switch_buf_ptr;
int n;
+ set_handler(SIGWINCH, (__sighandler_t) sig_handler,
+ SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
+ SIGVTALRM, -1);
+
*fork_buf_ptr = &initial_jmpbuf;
n = sigsetjmp(initial_jmpbuf, 1);
- if(n == 0)
- new_thread_proc((void *) stack, new_thread_handler);
- else if(n == 1)
- remove_sigstack();
- else if(n == 2){
+ switch(n){
+ case INIT_JMP_NEW_THREAD:
+ new_thread_proc((void *) stack, new_thread_handler);
+ break;
+ case INIT_JMP_REMOVE_SIGSTACK:
+ remove_sigstack();
+ break;
+ case INIT_JMP_CALLBACK:
(*cb_proc)(cb_arg);
siglongjmp(*cb_back, 1);
- }
- else if(n == 3){
+ break;
+ case INIT_JMP_HALT:
kmalloc_ok = 0;
return(0);
- }
- else if(n == 4){
+ case INIT_JMP_REBOOT:
kmalloc_ok = 0;
return(1);
+ default:
+ panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
}
siglongjmp(**switch_buf, 1);
}
@@ -290,7 +314,7 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
block_signals();
if(sigsetjmp(here, 1) == 0)
- siglongjmp(initial_jmpbuf, 2);
+ siglongjmp(initial_jmpbuf, INIT_JMP_CALLBACK);
unblock_signals();
cb_proc = NULL;
@@ -301,13 +325,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
void halt_skas(void)
{
block_signals();
- siglongjmp(initial_jmpbuf, 3);
+ siglongjmp(initial_jmpbuf, INIT_JMP_HALT);
}
void reboot_skas(void)
{
block_signals();
- siglongjmp(initial_jmpbuf, 4);
+ siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT);
}
void switch_mm_skas(int mm_fd)
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 5d096ea63b97..fc71ef295782 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -68,8 +68,11 @@ void new_thread_handler(int sig)
* 0 if it just exits
*/
n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
- if(n == 1)
+ if(n == 1){
+ /* Handle any immediate reschedules or signals */
+ interrupt_end();
userspace(&current->thread.regs.regs);
+ }
else do_exit(0);
}
@@ -83,10 +86,6 @@ void release_thread_skas(struct task_struct *task)
{
}
-void exit_thread_skas(void)
-{
-}
-
void fork_handler(int sig)
{
change_sig(SIGUSR1, 1);
@@ -100,6 +99,8 @@ void fork_handler(int sig)
schedule_tail(current->thread.prev_sched);
current->thread.prev_sched = NULL;
+ /* Handle any immediate reschedules or signals */
+ interrupt_end();
userspace(&current->thread.regs.regs);
}
diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c
index 8e9b46d4702e..0dee1d95c806 100644
--- a/arch/um/kernel/skas/trap_user.c
+++ b/arch/um/kernel/skas/trap_user.c
@@ -5,12 +5,15 @@
#include <signal.h>
#include <errno.h>
-#include "sysdep/ptrace.h"
#include "signal_user.h"
#include "user_util.h"
#include "kern_util.h"
#include "task.h"
#include "sigcontext.h"
+#include "skas.h"
+#include "ptrace_user.h"
+#include "sysdep/ptrace.h"
+#include "sysdep/ptrace_user.h"
void sig_handler_common_skas(int sig, void *sc_ptr)
{
@@ -31,9 +34,11 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
r = &TASK_REGS(get_current())->skas;
save_user = r->is_user;
r->is_user = 0;
- r->fault_addr = SC_FAULT_ADDR(sc);
- r->fault_type = SC_FAULT_TYPE(sc);
- r->trap_type = SC_TRAP_TYPE(sc);
+ if ( sig == SIGFPE || sig == SIGSEGV ||
+ sig == SIGBUS || sig == SIGILL ||
+ sig == SIGTRAP ) {
+ GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
+ }
change_sig(SIGUSR1, 1);
info = &sig_info[sig];
@@ -45,14 +50,17 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
r->is_user = save_user;
}
-void user_signal(int sig, union uml_pt_regs *regs)
+extern int ptrace_faultinfo;
+
+void user_signal(int sig, union uml_pt_regs *regs, int pid)
{
struct signal_info *info;
+ int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
+ (sig == SIGILL) || (sig == SIGTRAP));
regs->skas.is_user = 1;
- regs->skas.fault_addr = 0;
- regs->skas.fault_type = 0;
- regs->skas.trap_type = 0;
+ if (segv)
+ get_skas_faultinfo(pid, &regs->skas.faultinfo);
info = &sig_info[sig];
(*info->handler)(sig, regs);
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index f7da9d027672..75195281081e 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -29,9 +29,12 @@ static unsigned long maybe_map(unsigned long virt, int is_write)
if(IS_ERR(phys) || (is_write && !pte_write(pte))){
err = handle_page_fault(virt, 0, is_write, 1, &dummy_code);
if(err)
- return(0);
+ return(-1UL);
phys = um_virt_to_phys(current, virt, NULL);
}
+ if(IS_ERR(phys))
+ phys = (void *) -1;
+
return((unsigned long) phys);
}
@@ -42,7 +45,7 @@ static int do_op(unsigned long addr, int len, int is_write,
int n;
addr = maybe_map(addr, is_write);
- if(addr == -1)
+ if(addr == -1UL)
return(-1);
page = phys_to_page(addr);
diff --git a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile
index 17f5909d60f7..f7b7eba83340 100644
--- a/arch/um/kernel/skas/util/Makefile
+++ b/arch/um/kernel/skas/util/Makefile
@@ -2,3 +2,4 @@ hostprogs-y := mk_ptregs
always := $(hostprogs-y)
mk_ptregs-objs := mk_ptregs-$(SUBARCH).o
+HOSTCFLAGS_mk_ptregs-$(SUBARCH).o := -I$(objtree)/arch/um
diff --git a/arch/um/kernel/skas/util/mk_ptregs-i386.c b/arch/um/kernel/skas/util/mk_ptregs-i386.c
index 0788dd05bcac..1f96e1eeb8a7 100644
--- a/arch/um/kernel/skas/util/mk_ptregs-i386.c
+++ b/arch/um/kernel/skas/util/mk_ptregs-i386.c
@@ -1,8 +1,7 @@
#include <stdio.h>
-#include <asm/ptrace.h>
-#include <asm/user.h>
+#include <user-offsets.h>
-#define PRINT_REG(name, val) printf("#define HOST_%s %d\n", (name), (val))
+#define SHOW(name) printf("#define %s %d\n", #name, name)
int main(int argc, char **argv)
{
@@ -12,28 +11,27 @@ int main(int argc, char **argv)
printf("#ifndef __SKAS_PT_REGS_\n");
printf("#define __SKAS_PT_REGS_\n");
printf("\n");
- printf("#define HOST_FRAME_SIZE %d\n", FRAME_SIZE);
- printf("#define HOST_FP_SIZE %d\n",
- sizeof(struct user_i387_struct) / sizeof(unsigned long));
- printf("#define HOST_XFP_SIZE %d\n",
- sizeof(struct user_fxsr_struct) / sizeof(unsigned long));
+ SHOW(HOST_FRAME_SIZE);
+ SHOW(HOST_FP_SIZE);
+ SHOW(HOST_XFP_SIZE);
+
+ SHOW(HOST_IP);
+ SHOW(HOST_SP);
+ SHOW(HOST_EFLAGS);
+ SHOW(HOST_EAX);
+ SHOW(HOST_EBX);
+ SHOW(HOST_ECX);
+ SHOW(HOST_EDX);
+ SHOW(HOST_ESI);
+ SHOW(HOST_EDI);
+ SHOW(HOST_EBP);
+ SHOW(HOST_CS);
+ SHOW(HOST_SS);
+ SHOW(HOST_DS);
+ SHOW(HOST_FS);
+ SHOW(HOST_ES);
+ SHOW(HOST_GS);
- PRINT_REG("IP", EIP);
- PRINT_REG("SP", UESP);
- PRINT_REG("EFLAGS", EFL);
- PRINT_REG("EAX", EAX);
- PRINT_REG("EBX", EBX);
- PRINT_REG("ECX", ECX);
- PRINT_REG("EDX", EDX);
- PRINT_REG("ESI", ESI);
- PRINT_REG("EDI", EDI);
- PRINT_REG("EBP", EBP);
- PRINT_REG("CS", CS);
- PRINT_REG("SS", SS);
- PRINT_REG("DS", DS);
- PRINT_REG("FS", FS);
- PRINT_REG("ES", ES);
- PRINT_REG("GS", GS);
printf("\n");
printf("#endif\n");
return(0);
diff --git a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c
index 67aee92a70ef..5fccbfe35f78 100644
--- a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c
+++ b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c
@@ -5,11 +5,10 @@
*/
#include <stdio.h>
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
+#include <user-offsets.h>
-#define PRINT_REG(name, val) \
- printf("#define HOST_%s (%d / sizeof(unsigned long))\n", (name), (val))
+#define SHOW(name) \
+ printf("#define %s (%d / sizeof(unsigned long))\n", #name, name)
int main(int argc, char **argv)
{
@@ -18,36 +17,35 @@ int main(int argc, char **argv)
printf("\n");
printf("#ifndef __SKAS_PT_REGS_\n");
printf("#define __SKAS_PT_REGS_\n");
- printf("#define HOST_FRAME_SIZE (%d / sizeof(unsigned long))\n",
- FRAME_SIZE);
- PRINT_REG("RBX", RBX);
- PRINT_REG("RCX", RCX);
- PRINT_REG("RDI", RDI);
- PRINT_REG("RSI", RSI);
- PRINT_REG("RDX", RDX);
- PRINT_REG("RBP", RBP);
- PRINT_REG("RAX", RAX);
- PRINT_REG("R8", R8);
- PRINT_REG("R9", R9);
- PRINT_REG("R10", R10);
- PRINT_REG("R11", R11);
- PRINT_REG("R12", R12);
- PRINT_REG("R13", R13);
- PRINT_REG("R14", R14);
- PRINT_REG("R15", R15);
- PRINT_REG("ORIG_RAX", ORIG_RAX);
- PRINT_REG("CS", CS);
- PRINT_REG("SS", SS);
- PRINT_REG("EFLAGS", EFLAGS);
+ SHOW(HOST_FRAME_SIZE);
+ SHOW(HOST_RBX);
+ SHOW(HOST_RCX);
+ SHOW(HOST_RDI);
+ SHOW(HOST_RSI);
+ SHOW(HOST_RDX);
+ SHOW(HOST_RBP);
+ SHOW(HOST_RAX);
+ SHOW(HOST_R8);
+ SHOW(HOST_R9);
+ SHOW(HOST_R10);
+ SHOW(HOST_R11);
+ SHOW(HOST_R12);
+ SHOW(HOST_R13);
+ SHOW(HOST_R14);
+ SHOW(HOST_R15);
+ SHOW(HOST_ORIG_RAX);
+ SHOW(HOST_CS);
+ SHOW(HOST_SS);
+ SHOW(HOST_EFLAGS);
#if 0
- PRINT_REG("FS", FS);
- PRINT_REG("GS", GS);
- PRINT_REG("DS", DS);
- PRINT_REG("ES", ES);
+ SHOW(HOST_FS);
+ SHOW(HOST_GS);
+ SHOW(HOST_DS);
+ SHOW(HOST_ES);
#endif
- PRINT_REG("IP", RIP);
- PRINT_REG("SP", RSP);
+ SHOW(HOST_IP);
+ SHOW(HOST_SP);
printf("#define HOST_FP_SIZE 0\n");
printf("#define HOST_XFP_SIZE 0\n");
printf("\n");
diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
index 42731e04f50f..b7a55251e897 100644
--- a/arch/um/kernel/syscall_kern.c
+++ b/arch/um/kernel/syscall_kern.c
@@ -17,7 +17,6 @@
#include "linux/utime.h"
#include "asm/mman.h"
#include "asm/uaccess.h"
-#include "asm/ipc.h"
#include "kern_util.h"
#include "user_util.h"
#include "sysdep/syscalls.h"
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index e630438f9e73..f80850091e79 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -3,6 +3,7 @@
* Licensed under the GPL
*/
+#include "linux/config.h"
#include "linux/sched.h"
#include "linux/kernel.h"
#include "linux/module.h"
@@ -12,14 +13,14 @@
#include "sysrq.h"
#include "user_util.h"
-void show_trace(unsigned long * stack)
+/* Catch non-i386 SUBARCH's. */
+#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
+void show_trace(struct task_struct *task, unsigned long * stack)
{
- /* XXX: Copy the CONFIG_FRAME_POINTER stack-walking backtrace from
- * arch/i386/kernel/traps.c, and then move this to sys-i386/sysrq.c.*/
unsigned long addr;
if (!stack) {
- stack = (unsigned long*) &stack;
+ stack = (unsigned long*) &stack;
WARN_ON(1);
}
@@ -35,6 +36,7 @@ void show_trace(unsigned long * stack)
}
printk("\n");
}
+#endif
/*
* stack dumps generator - this is used by arch-independent code.
@@ -44,7 +46,7 @@ void dump_stack(void)
{
unsigned long stack;
- show_trace(&stack);
+ show_trace(current, &stack);
}
EXPORT_SYMBOL(dump_stack);
@@ -59,7 +61,11 @@ void show_stack(struct task_struct *task, unsigned long *esp)
int i;
if (esp == NULL) {
- if (task != current) {
+ if (task != current && task != NULL) {
+ /* XXX: Isn't this bogus? I.e. isn't this the
+ * *userspace* stack of this task? If not so, use this
+ * even when task == current (as in i386).
+ */
esp = (unsigned long *) KSTK_ESP(task);
/* Which one? No actual difference - just coding style.*/
//esp = (unsigned long *) PT_REGS_IP(&task->thread.regs);
@@ -77,5 +83,6 @@ void show_stack(struct task_struct *task, unsigned long *esp)
printk("%08lx ", *stack++);
}
- show_trace(esp);
+ printk("Call Trace: \n");
+ show_trace(current, esp);
}
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 2461cd73ca87..6516fc52afe0 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -48,8 +48,6 @@ static unsigned long long prev_usecs;
static long long delta; /* Deviation per interval */
#endif
-#define MILLION 1000000
-
void timer_irq(union uml_pt_regs *regs)
{
unsigned long long ticks = 0;
@@ -136,22 +134,6 @@ long um_stime(int __user *tptr)
return 0;
}
-void __udelay(unsigned long usecs)
-{
- int i, n;
-
- n = (loops_per_jiffy * HZ * usecs) / MILLION;
- for(i=0;i<n;i++) ;
-}
-
-void __const_udelay(unsigned long usecs)
-{
- int i, n;
-
- n = (loops_per_jiffy * HZ * usecs) / MILLION;
- for(i=0;i<n;i++) ;
-}
-
void timer_handler(int sig, union uml_pt_regs *regs)
{
local_irq_disable();
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 47e766e6ba10..c20aef120598 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -23,7 +23,6 @@
#include "kern.h"
#include "chan_kern.h"
#include "mconsole_kern.h"
-#include "2_5compat.h"
#include "mem.h"
#include "mem_kern.h"
@@ -48,7 +47,7 @@ int handle_page_fault(unsigned long address, unsigned long ip,
goto good_area;
else if(!(vma->vm_flags & VM_GROWSDOWN))
goto out;
- else if(!ARCH_IS_STACKGROW(address))
+ else if(is_user && !ARCH_IS_STACKGROW(address))
goto out;
else if(expand_stack(vma, address))
goto out;
@@ -57,10 +56,11 @@ int handle_page_fault(unsigned long address, unsigned long ip,
*code_out = SEGV_ACCERR;
if(is_write && !(vma->vm_flags & VM_WRITE))
goto out;
+
+ if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ goto out;
+
page = address & PAGE_MASK;
- pgd = pgd_offset(mm, page);
- pud = pud_offset(pgd, page);
- pmd = pmd_offset(pud, page);
do {
survive:
switch (handle_mm_fault(mm, vma, address, is_write)){
@@ -106,46 +106,24 @@ out_of_memory:
goto out;
}
-LIST_HEAD(physmem_remappers);
-
-void register_remapper(struct remapper *info)
-{
- list_add(&info->list, &physmem_remappers);
-}
-
-static int check_remapped_addr(unsigned long address, int is_write)
-{
- struct remapper *remapper;
- struct list_head *ele;
- __u64 offset;
- int fd;
-
- fd = phys_mapping(__pa(address), &offset);
- if(fd == -1)
- return(0);
-
- list_for_each(ele, &physmem_remappers){
- remapper = list_entry(ele, struct remapper, list);
- if((*remapper->proc)(fd, address, is_write, offset))
- return(1);
- }
-
- return(0);
-}
-
-unsigned long segv(unsigned long address, unsigned long ip, int is_write,
- int is_user, void *sc)
+/*
+ * We give a *copy* of the faultinfo in the regs to segv.
+ * This must be done, since nesting SEGVs could overwrite
+ * the info in the regs. A pointer to the info then would
+ * give us bad data!
+ */
+unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
{
struct siginfo si;
void *catcher;
int err;
+ int is_write = FAULT_WRITE(fi);
+ unsigned long address = FAULT_ADDRESS(fi);
if(!is_user && (address >= start_vm) && (address < end_vm)){
flush_tlb_kernel_vm();
return(0);
}
- else if(check_remapped_addr(address & PAGE_MASK, is_write))
- return(0);
else if(current->mm == NULL)
panic("Segfault with no mm");
err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
@@ -159,7 +137,7 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write,
}
else if(current->thread.fault_addr != NULL)
panic("fault_addr set but no fault catcher");
- else if(arch_fixup(ip, sc))
+ else if(!is_user && arch_fixup(ip, sc))
return(0);
if(!is_user)
@@ -171,6 +149,7 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write,
si.si_errno = 0;
si.si_code = BUS_ADRERR;
si.si_addr = (void *)address;
+ current->thread.arch.faultinfo = fi;
force_sig_info(SIGBUS, &si, current);
}
else if(err == -ENOMEM){
@@ -180,22 +159,20 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write,
else {
si.si_signo = SIGSEGV;
si.si_addr = (void *) address;
- current->thread.cr2 = address;
- current->thread.err = is_write;
+ current->thread.arch.faultinfo = fi;
force_sig_info(SIGSEGV, &si, current);
}
return(0);
}
-void bad_segv(unsigned long address, unsigned long ip, int is_write)
+void bad_segv(struct faultinfo fi, unsigned long ip)
{
struct siginfo si;
si.si_signo = SIGSEGV;
si.si_code = SEGV_ACCERR;
- si.si_addr = (void *) address;
- current->thread.cr2 = address;
- current->thread.err = is_write;
+ si.si_addr = (void *) FAULT_ADDRESS(fi);
+ current->thread.arch.faultinfo = fi;
force_sig_info(SIGSEGV, &si, current);
}
@@ -204,6 +181,7 @@ void relay_signal(int sig, union uml_pt_regs *regs)
if(arch_handle_signal(sig, regs)) return;
if(!UPT_IS_USER(regs))
panic("Kernel mode signal %d", sig);
+ current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
force_sig(sig, current);
}
diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
index 50a4042a509f..f825a6eda3f5 100644
--- a/arch/um/kernel/trap_user.c
+++ b/arch/um/kernel/trap_user.c
@@ -54,23 +54,22 @@ struct {
void segv_handler(int sig, union uml_pt_regs *regs)
{
int index, max;
+ struct faultinfo * fi = UPT_FAULTINFO(regs);
- if(UPT_IS_USER(regs) && !UPT_SEGV_IS_FIXABLE(regs)){
- bad_segv(UPT_FAULT_ADDR(regs), UPT_IP(regs),
- UPT_FAULT_WRITE(regs));
+ if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
+ bad_segv(*fi, UPT_IP(regs));
return;
}
max = sizeof(segfault_record)/sizeof(segfault_record[0]);
index = next_trap_index(max);
nsegfaults++;
- segfault_record[index].address = UPT_FAULT_ADDR(regs);
+ segfault_record[index].address = FAULT_ADDRESS(*fi);
segfault_record[index].pid = os_getpid();
- segfault_record[index].is_write = UPT_FAULT_WRITE(regs);
+ segfault_record[index].is_write = FAULT_WRITE(*fi);
segfault_record[index].sp = UPT_SP(regs);
segfault_record[index].is_user = UPT_IS_USER(regs);
- segv(UPT_FAULT_ADDR(regs), UPT_IP(regs), UPT_FAULT_WRITE(regs),
- UPT_IS_USER(regs), regs);
+ segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
}
void usr2_handler(int sig, union uml_pt_regs *regs)
diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile
index 3d5177df3504..c3faea21a996 100644
--- a/arch/um/kernel/tt/Makefile
+++ b/arch/um/kernel/tt/Makefile
@@ -4,6 +4,7 @@
#
extra-y := unmap_fin.o
+targets := unmap.o
clean-files := unmap_tmp.o
obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
diff --git a/arch/um/kernel/tt/include/mode_kern-tt.h b/arch/um/kernel/tt/include/mode_kern-tt.h
index 28aaab3448fa..e0ca0e0b2516 100644
--- a/arch/um/kernel/tt/include/mode_kern-tt.h
+++ b/arch/um/kernel/tt/include/mode_kern-tt.h
@@ -19,7 +19,6 @@ extern 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);
extern void release_thread_tt(struct task_struct *task);
-extern void exit_thread_tt(void);
extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
extern void init_idle_tt(void);
extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/kernel/tt/include/uaccess-tt.h
index bb69d6b7d022..3fbb5fe26f49 100644
--- a/arch/um/kernel/tt/include/uaccess-tt.h
+++ b/arch/um/kernel/tt/include/uaccess-tt.h
@@ -33,8 +33,8 @@ extern unsigned long uml_physmem;
(((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \
(under_task_size(addr, size) || is_stack(addr, size))))
-static inline int __deprecated verify_area_tt(int type, const void * addr,
- unsigned long size)
+static inline int verify_area_tt(int type, const void * addr,
+ unsigned long size)
{
return(access_ok_tt(type, addr, size) ? 0 : -EFAULT);
}
diff --git a/arch/um/kernel/tt/ksyms.c b/arch/um/kernel/tt/ksyms.c
index 92ec85d67c7c..84a9385a8fef 100644
--- a/arch/um/kernel/tt/ksyms.c
+++ b/arch/um/kernel/tt/ksyms.c
@@ -12,6 +12,7 @@ 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);
diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c
index 74346a04a2b2..bcb8796c3cb1 100644
--- a/arch/um/kernel/tt/mem.c
+++ b/arch/um/kernel/tt/mem.c
@@ -21,14 +21,8 @@ void before_mem_tt(unsigned long brk_start)
remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1);
}
-#ifdef CONFIG_HOST_2G_2G
-#define TOP 0x80000000
-#else
-#define TOP 0xc0000000
-#endif
-
#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000)
-#define START (TOP - SIZE)
+#define START (CONFIG_TOP_ADDR - SIZE)
unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
unsigned long *task_size_out)
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index f19f7c18febe..776310fd5b8b 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -32,10 +32,6 @@ void *switch_to_tt(void *prev, void *next, void *last)
unsigned long flags;
int err, vtalrm, alrm, prof, cpu;
char c;
- /* jailing and SMP are incompatible, so this doesn't need to be
- * made per-cpu
- */
- static int reading;
from = prev;
to = next;
@@ -59,14 +55,11 @@ void *switch_to_tt(void *prev, void *next, void *last)
c = 0;
set_current(to);
- reading = 0;
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);
- reading = 1;
- if((from->exit_state == EXIT_ZOMBIE) ||
- (from->exit_state == EXIT_DEAD))
+ 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));
@@ -81,8 +74,7 @@ void *switch_to_tt(void *prev, void *next, void *last)
* in case it has not already killed itself.
*/
prev_sched = current->thread.prev_sched;
- if((prev_sched->exit_state == EXIT_ZOMBIE) ||
- (prev_sched->exit_state == EXIT_DEAD))
+ 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);
@@ -101,14 +93,18 @@ 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);
-}
-void exit_thread_tt(void)
-{
- os_close_file(current->thread.mode.tt.switch_pipe[0]);
- os_close_file(current->thread.mode.tt.switch_pipe[1]);
+ 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)
diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c
index e4e7e9c2224c..b218316cfdb2 100644
--- a/arch/um/kernel/tt/syscall_user.c
+++ b/arch/um/kernel/tt/syscall_user.c
@@ -63,6 +63,10 @@ void do_syscall(void *task, int pid, int local_using_sysemu)
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");
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
index 7b5d937e5955..d11e7399d7a1 100644
--- a/arch/um/kernel/tt/tracer.c
+++ b/arch/um/kernel/tt/tracer.c
@@ -26,6 +26,7 @@
#include "kern_util.h"
#include "chan_user.h"
#include "ptrace_user.h"
+#include "irq_user.h"
#include "mode.h"
#include "tt.h"
@@ -33,7 +34,7 @@ static int tracer_winch[2];
int is_tracer_winch(int pid, int fd, void *data)
{
- if(pid != tracing_pid)
+ if(pid != os_getpgrp())
return(0);
register_winch_irq(tracer_winch[0], fd, -1, data);
@@ -89,8 +90,10 @@ void tracer_panic(char *format, ...)
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",
- SC_FAULT_ADDR(&sc), SC_IP(&sc));
+ FAULT_ADDRESS(fi), SC_IP(&sc));
while(1)
pause();
}
@@ -117,6 +120,7 @@ static int signal_tramp(void *arg)
signal(SIGSEGV, (__sighandler_t) sig_handler);
set_cmdline("(idle thread)");
set_init_pid(os_getpid());
+ init_irq_signals(0);
proc = arg;
return((*proc)(NULL));
}
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
index 92a3820ca543..fc108615beaf 100644
--- a/arch/um/kernel/tt/trap_user.c
+++ b/arch/um/kernel/tt/trap_user.c
@@ -7,6 +7,7 @@
#include <errno.h>
#include <signal.h>
#include "sysdep/ptrace.h"
+#include "sysdep/sigcontext.h"
#include "signal_user.h"
#include "user_util.h"
#include "kern_util.h"
@@ -28,6 +29,11 @@ void sig_handler_common_tt(int sig, void *sc_ptr)
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;
is_user = user_context(SC_SP(sc));
r->sc = sc;
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 5c49d88eed3d..8736d098f0ee 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -23,9 +23,9 @@
#include "asm/ptrace.h"
#include "asm/elf.h"
#include "asm/user.h"
+#include "asm/setup.h"
#include "ubd_user.h"
#include "asm/current.h"
-#include "asm/setup.h"
#include "user_util.h"
#include "kern_util.h"
#include "kern.h"
@@ -42,9 +42,9 @@
#define DEFAULT_COMMAND_LINE "root=98:0"
/* Changed in linux_main and setup_arch, which run before SMP is started */
-char command_line[COMMAND_LINE_SIZE] = { 0 };
+static char command_line[COMMAND_LINE_SIZE] = { 0 };
-void add_arg(char *arg)
+static void add_arg(char *arg)
{
if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) {
printf("add_arg: Too many command line arguments!\n");
@@ -110,12 +110,6 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo,
};
-pte_t * __bad_pagetable(void)
-{
- panic("Someone should implement __bad_pagetable");
- return(NULL);
-}
-
/* Set in linux_main */
unsigned long host_task_size;
unsigned long task_size;
@@ -449,7 +443,7 @@ void __init setup_arch(char **cmdline_p)
{
notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
paging_init();
- strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+ strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
setup_hostinfo();
}
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index 76eadb309189..dd5355500bdc 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -73,6 +73,8 @@ SECTIONS
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
diff --git a/arch/um/kernel/vmlinux.lds.S b/arch/um/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..1660a769674b
--- /dev/null
+++ b/arch/um/kernel/vmlinux.lds.S
@@ -0,0 +1,6 @@
+#include <linux/config.h>
+#ifdef CONFIG_LD_SCRIPT_STATIC
+#include "uml.lds.S"
+#else
+#include "dyn.lds.S"
+#endif