summaryrefslogtreecommitdiffstats
path: root/arch/um/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/Makefile8
-rw-r--r--arch/um/kernel/checksum.c0
-rw-r--r--arch/um/kernel/initrd.c78
-rw-r--r--arch/um/kernel/irq_user.c10
-rw-r--r--arch/um/kernel/ksyms.c1
-rw-r--r--arch/um/kernel/mem.c40
-rw-r--r--arch/um/kernel/process_kern.c20
-rw-r--r--arch/um/kernel/ptrace.c79
-rw-r--r--arch/um/kernel/skas/include/mode_kern-skas.h1
-rw-r--r--arch/um/kernel/skas/include/uaccess-skas.h4
-rw-r--r--arch/um/kernel/skas/process.c35
-rw-r--r--arch/um/kernel/skas/process_kern.c4
-rw-r--r--arch/um/kernel/skas/uaccess.c7
-rw-r--r--arch/um/kernel/syscall_kern.c1
-rw-r--r--arch/um/kernel/trap_kern.c38
-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.c20
-rw-r--r--arch/um/kernel/tt/syscall_user.c4
-rw-r--r--arch/um/kernel/um_arch.c7
-rw-r--r--arch/um/kernel/uml.lds.S2
23 files changed, 217 insertions, 156 deletions
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index dca65426385..a8918e80df9 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -14,7 +14,7 @@ obj-y = 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,14 +23,10 @@ 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
diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/arch/um/kernel/checksum.c
+++ /dev/null
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
new file mode 100644
index 00000000000..82ecf904b09
--- /dev/null
+++ b/arch/um/kernel/initrd.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/init.h"
+#include "linux/bootmem.h"
+#include "linux/initrd.h"
+#include "asm/types.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "initrd.h"
+#include "init.h"
+#include "os.h"
+
+/* Changed by uml_initrd_setup, which is a setup */
+static char *initrd __initdata = NULL;
+
+static int __init read_initrd(void)
+{
+ void *area;
+ long long size;
+ int err;
+
+ if(initrd == NULL) return 0;
+ err = os_file_size(initrd, &size);
+ if(err) return 0;
+ area = alloc_bootmem(size);
+ if(area == NULL) return 0;
+ if(load_initrd(initrd, area, size) == -1) return 0;
+ initrd_start = (unsigned long) area;
+ initrd_end = initrd_start + size;
+ return 0;
+}
+
+__uml_postsetup(read_initrd);
+
+static int __init uml_initrd_setup(char *line, int *add)
+{
+ initrd = line;
+ return 0;
+}
+
+__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
+ * 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_user.c b/arch/um/kernel/irq_user.c
index 6d6f9484b88..b3074cbaa47 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 78d69dc74b2..99439fa15ef 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -57,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/mem.c b/arch/um/kernel/mem.c
index f156661781c..c22825f13e4 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_kern.c b/arch/um/kernel/process_kern.c
index 7a943696f95..c1adf7ba3fd 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -115,16 +115,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 +142,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);
}
@@ -476,12 +465,21 @@ 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;
}
+#endif
/*
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 3efa59a941a..2925e15324d 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,28 +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);
- }
-#if defined(CONFIG_UML_X86) && !defined(CONFIG_64BIT)
- 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];
- }
-#endif
- 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. */
@@ -121,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 defined(CONFIG_UML_X86) && !defined(CONFIG_64BIT)
- 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. */
@@ -148,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);
}
@@ -172,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;
@@ -184,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);
diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/kernel/skas/include/mode_kern-skas.h
index 94c56496237..e4849002811 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/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h
index c35620385da..cd6c280482c 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 4dc13bc8cfd..773cd2b525f 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -201,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))
@@ -236,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)
@@ -266,21 +271,25 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
*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);
}
@@ -305,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;
@@ -316,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 5d096ea63b9..ab5d3271da0 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -83,10 +83,6 @@ void release_thread_skas(struct task_struct *task)
{
}
-void exit_thread_skas(void)
-{
-}
-
void fork_handler(int sig)
{
change_sig(SIGUSR1, 1);
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index f7da9d02767..75195281081 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/syscall_kern.c b/arch/um/kernel/syscall_kern.c
index 42731e04f50..b7a55251e89 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/trap_kern.c b/arch/um/kernel/trap_kern.c
index 54e2ec33a43..1de22d8a313 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -48,7 +48,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 +57,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,33 +107,6 @@ 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);
-}
-
/*
* We give a *copy* of the faultinfo in the regs to segv.
* This must be done, since nesting SEGVs could overwrite
@@ -151,8 +125,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
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);
diff --git a/arch/um/kernel/tt/include/mode_kern-tt.h b/arch/um/kernel/tt/include/mode_kern-tt.h
index 28aaab3448f..e0ca0e0b251 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 bb69d6b7d02..3fbb5fe26f4 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 92ec85d67c7..84a9385a8fe 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 74346a04a2b..bcb8796c3cb 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 f19f7c18feb..df810ca8fc1 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -65,8 +65,7 @@ void *switch_to_tt(void *prev, void *next, void *last)
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 +80,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 +99,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 e4e7e9c2224..b218316cfdb 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/um_arch.c b/arch/um/kernel/um_arch.c
index 5c49d88eed3..4d10ec372a6 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -23,6 +23,7 @@
#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"
@@ -42,9 +43,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");
@@ -449,7 +450,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 76eadb30918..dd5355500bd 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. */