diff options
| author | Steven Whitehouse <swhiteho@redhat.com> | 2006-09-28 08:29:59 -0400 |
|---|---|---|
| committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-09-28 08:29:59 -0400 |
| commit | 185a257f2f73bcd89050ad02da5bedbc28fc43fa (patch) | |
| tree | 5e32586114534ed3f2165614cba3d578f5d87307 /arch/um/kernel | |
| parent | 3f1a9aaeffd8d1cbc5ab9776c45cbd66af1c9699 (diff) | |
| parent | a77c64c1a641950626181b4857abb701d8f38ccc (diff) | |
Merge branch 'master' into gfs2
Diffstat (limited to 'arch/um/kernel')
| -rw-r--r-- | arch/um/kernel/Makefile | 2 | ||||
| -rw-r--r-- | arch/um/kernel/exec.c | 4 | ||||
| -rw-r--r-- | arch/um/kernel/gmon_syms.c | 13 | ||||
| -rw-r--r-- | arch/um/kernel/irq.c | 34 | ||||
| -rw-r--r-- | arch/um/kernel/ksyms.c | 3 | ||||
| -rw-r--r-- | arch/um/kernel/mem.c | 10 | ||||
| -rw-r--r-- | arch/um/kernel/process.c (renamed from arch/um/kernel/process_kern.c) | 36 | ||||
| -rw-r--r-- | arch/um/kernel/reboot.c | 13 | ||||
| -rw-r--r-- | arch/um/kernel/skas/Makefile | 3 | ||||
| -rw-r--r-- | arch/um/kernel/skas/exec.c | 30 | ||||
| -rw-r--r-- | arch/um/kernel/skas/exec_kern.c | 41 | ||||
| -rw-r--r-- | arch/um/kernel/skas/mmu.c | 2 | ||||
| -rw-r--r-- | arch/um/kernel/skas/process.c | 217 | ||||
| -rw-r--r-- | arch/um/kernel/skas/process_kern.c | 533 | ||||
| -rw-r--r-- | arch/um/kernel/time.c | 14 | ||||
| -rw-r--r-- | arch/um/kernel/tlb.c | 370 | ||||
| -rw-r--r-- | arch/um/kernel/trap.c | 28 | ||||
| -rw-r--r-- | arch/um/kernel/um_arch.c | 2 |
18 files changed, 898 insertions, 457 deletions
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index a2d93065b2d0..6fa63a2a89e3 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile | |||
| @@ -7,7 +7,7 @@ extra-y := vmlinux.lds | |||
| 7 | clean-files := | 7 | clean-files := |
| 8 | 8 | ||
| 9 | obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ | 9 | obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ |
| 10 | physmem.o process_kern.o ptrace.o reboot.o resource.o sigio.o \ | 10 | physmem.o process.o ptrace.o reboot.o resource.o sigio.o \ |
| 11 | signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \ | 11 | signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \ |
| 12 | um_arch.o umid.o | 12 | um_arch.o umid.o |
| 13 | 13 | ||
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index fc38a6d5906d..0561c43b4685 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c | |||
| @@ -41,9 +41,11 @@ static long execve1(char *file, char __user * __user *argv, | |||
| 41 | long error; | 41 | long error; |
| 42 | 42 | ||
| 43 | #ifdef CONFIG_TTY_LOG | 43 | #ifdef CONFIG_TTY_LOG |
| 44 | task_lock(current); | 44 | mutex_lock(&tty_mutex); |
| 45 | task_lock(current); /* FIXME: is this needed ? */ | ||
| 45 | log_exec(argv, current->signal->tty); | 46 | log_exec(argv, current->signal->tty); |
| 46 | task_unlock(current); | 47 | task_unlock(current); |
| 48 | mutex_unlock(&tty_mutex); | ||
| 47 | #endif | 49 | #endif |
| 48 | error = do_execve(file, argv, env, ¤t->thread.regs); | 50 | error = do_execve(file, argv, env, ¤t->thread.regs); |
| 49 | if (error == 0){ | 51 | if (error == 0){ |
diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c index 2c86e7fdb014..13aa115cd1b4 100644 --- a/arch/um/kernel/gmon_syms.c +++ b/arch/um/kernel/gmon_syms.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include "linux/module.h" | 6 | #include "linux/module.h" |
| 7 | 7 | ||
| 8 | extern void __bb_init_func(void *); | 8 | extern void __bb_init_func(void *) __attribute__((weak)); |
| 9 | EXPORT_SYMBOL(__bb_init_func); | 9 | EXPORT_SYMBOL(__bb_init_func); |
| 10 | 10 | ||
| 11 | /* This is defined (and referred to in profiling stub code) only by some GCC | 11 | /* This is defined (and referred to in profiling stub code) only by some GCC |
| @@ -21,14 +21,3 @@ EXPORT_SYMBOL(__gcov_init); | |||
| 21 | 21 | ||
| 22 | extern void __gcov_merge_add(void *) __attribute__((weak)); | 22 | extern void __gcov_merge_add(void *) __attribute__((weak)); |
| 23 | EXPORT_SYMBOL(__gcov_merge_add); | 23 | EXPORT_SYMBOL(__gcov_merge_add); |
| 24 | |||
| 25 | /* | ||
| 26 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
| 27 | * Emacs will notice this stuff at the end of the file and automatically | ||
| 28 | * adjust the settings for this buffer only. This must remain at the end | ||
| 29 | * of the file. | ||
| 30 | * --------------------------------------------------------------------------- | ||
| 31 | * Local variables: | ||
| 32 | * c-file-style: "linux" | ||
| 33 | * End: | ||
| 34 | */ | ||
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 589c69a75043..ce7f233fc490 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c | |||
| @@ -142,19 +142,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
| 142 | .events = events, | 142 | .events = events, |
| 143 | .current_events = 0 } ); | 143 | .current_events = 0 } ); |
| 144 | 144 | ||
| 145 | /* Critical section - locked by a spinlock because this stuff can | ||
| 146 | * be changed from interrupt handlers. The stuff above is done | ||
| 147 | * outside the lock because it allocates memory. | ||
| 148 | */ | ||
| 149 | |||
| 150 | /* Actually, it only looks like it can be called from interrupt | ||
| 151 | * context. The culprit is reactivate_fd, which calls | ||
| 152 | * maybe_sigio_broken, which calls write_sigio_workaround, | ||
| 153 | * which calls activate_fd. However, write_sigio_workaround should | ||
| 154 | * only be called once, at boot time. That would make it clear that | ||
| 155 | * this is called only from process context, and can be locked with | ||
| 156 | * a semaphore. | ||
| 157 | */ | ||
| 158 | spin_lock_irqsave(&irq_lock, flags); | 145 | spin_lock_irqsave(&irq_lock, flags); |
| 159 | for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { | 146 | for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { |
| 160 | if ((irq_fd->fd == fd) && (irq_fd->type == type)) { | 147 | if ((irq_fd->fd == fd) && (irq_fd->type == type)) { |
| @@ -165,7 +152,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
| 165 | } | 152 | } |
| 166 | } | 153 | } |
| 167 | 154 | ||
| 168 | /*-------------*/ | ||
| 169 | if (type == IRQ_WRITE) | 155 | if (type == IRQ_WRITE) |
| 170 | fd = -1; | 156 | fd = -1; |
| 171 | 157 | ||
| @@ -198,7 +184,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
| 198 | 184 | ||
| 199 | spin_lock_irqsave(&irq_lock, flags); | 185 | spin_lock_irqsave(&irq_lock, flags); |
| 200 | } | 186 | } |
| 201 | /*-------------*/ | ||
| 202 | 187 | ||
| 203 | *last_irq_ptr = new_fd; | 188 | *last_irq_ptr = new_fd; |
| 204 | last_irq_ptr = &new_fd->next; | 189 | last_irq_ptr = &new_fd->next; |
| @@ -210,14 +195,14 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
| 210 | */ | 195 | */ |
| 211 | maybe_sigio_broken(fd, (type == IRQ_READ)); | 196 | maybe_sigio_broken(fd, (type == IRQ_READ)); |
| 212 | 197 | ||
| 213 | return(0); | 198 | return 0; |
| 214 | 199 | ||
| 215 | out_unlock: | 200 | out_unlock: |
| 216 | spin_unlock_irqrestore(&irq_lock, flags); | 201 | spin_unlock_irqrestore(&irq_lock, flags); |
| 217 | out_kfree: | 202 | out_kfree: |
| 218 | kfree(new_fd); | 203 | kfree(new_fd); |
| 219 | out: | 204 | out: |
| 220 | return(err); | 205 | return err; |
| 221 | } | 206 | } |
| 222 | 207 | ||
| 223 | static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) | 208 | static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) |
| @@ -302,10 +287,7 @@ void reactivate_fd(int fd, int irqnum) | |||
| 302 | os_set_pollfd(i, irq->fd); | 287 | os_set_pollfd(i, irq->fd); |
| 303 | spin_unlock_irqrestore(&irq_lock, flags); | 288 | spin_unlock_irqrestore(&irq_lock, flags); |
| 304 | 289 | ||
| 305 | /* This calls activate_fd, so it has to be outside the critical | 290 | add_sigio_fd(fd); |
| 306 | * section. | ||
| 307 | */ | ||
| 308 | maybe_sigio_broken(fd, (irq->type == IRQ_READ)); | ||
| 309 | } | 291 | } |
| 310 | 292 | ||
| 311 | void deactivate_fd(int fd, int irqnum) | 293 | void deactivate_fd(int fd, int irqnum) |
| @@ -316,11 +298,15 @@ void deactivate_fd(int fd, int irqnum) | |||
| 316 | 298 | ||
| 317 | spin_lock_irqsave(&irq_lock, flags); | 299 | spin_lock_irqsave(&irq_lock, flags); |
| 318 | irq = find_irq_by_fd(fd, irqnum, &i); | 300 | irq = find_irq_by_fd(fd, irqnum, &i); |
| 319 | if (irq == NULL) | 301 | if(irq == NULL){ |
| 320 | goto out; | 302 | spin_unlock_irqrestore(&irq_lock, flags); |
| 303 | return; | ||
| 304 | } | ||
| 305 | |||
| 321 | os_set_pollfd(i, -1); | 306 | os_set_pollfd(i, -1); |
| 322 | out: | ||
| 323 | spin_unlock_irqrestore(&irq_lock, flags); | 307 | spin_unlock_irqrestore(&irq_lock, flags); |
| 308 | |||
| 309 | ignore_sigio_fd(fd); | ||
| 324 | } | 310 | } |
| 325 | 311 | ||
| 326 | int deactivate_all_fds(void) | 312 | int deactivate_all_fds(void) |
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index c97045d6d89f..f030e44262ba 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | #include "mem_user.h" | 21 | #include "mem_user.h" |
| 22 | #include "os.h" | 22 | #include "os.h" |
| 23 | 23 | ||
| 24 | EXPORT_SYMBOL(stop); | ||
| 25 | EXPORT_SYMBOL(uml_physmem); | 24 | EXPORT_SYMBOL(uml_physmem); |
| 26 | EXPORT_SYMBOL(set_signals); | 25 | EXPORT_SYMBOL(set_signals); |
| 27 | EXPORT_SYMBOL(get_signals); | 26 | EXPORT_SYMBOL(get_signals); |
| @@ -41,12 +40,14 @@ EXPORT_SYMBOL(handle_page_fault); | |||
| 41 | EXPORT_SYMBOL(find_iomem); | 40 | EXPORT_SYMBOL(find_iomem); |
| 42 | 41 | ||
| 43 | #ifdef CONFIG_MODE_TT | 42 | #ifdef CONFIG_MODE_TT |
| 43 | EXPORT_SYMBOL(stop); | ||
| 44 | EXPORT_SYMBOL(strncpy_from_user_tt); | 44 | EXPORT_SYMBOL(strncpy_from_user_tt); |
| 45 | EXPORT_SYMBOL(copy_from_user_tt); | 45 | EXPORT_SYMBOL(copy_from_user_tt); |
| 46 | EXPORT_SYMBOL(copy_to_user_tt); | 46 | EXPORT_SYMBOL(copy_to_user_tt); |
| 47 | #endif | 47 | #endif |
| 48 | 48 | ||
| 49 | #ifdef CONFIG_MODE_SKAS | 49 | #ifdef CONFIG_MODE_SKAS |
| 50 | EXPORT_SYMBOL(strnlen_user_skas); | ||
| 50 | EXPORT_SYMBOL(strncpy_from_user_skas); | 51 | EXPORT_SYMBOL(strncpy_from_user_skas); |
| 51 | EXPORT_SYMBOL(copy_to_user_skas); | 52 | EXPORT_SYMBOL(copy_to_user_skas); |
| 52 | EXPORT_SYMBOL(copy_from_user_skas); | 53 | EXPORT_SYMBOL(copy_from_user_skas); |
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 61280167c560..c95855ba6ab5 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c | |||
| @@ -79,8 +79,10 @@ void mem_init(void) | |||
| 79 | 79 | ||
| 80 | /* this will put all low memory onto the freelists */ | 80 | /* this will put all low memory onto the freelists */ |
| 81 | totalram_pages = free_all_bootmem(); | 81 | totalram_pages = free_all_bootmem(); |
| 82 | #ifdef CONFIG_HIGHMEM | ||
| 82 | totalhigh_pages = highmem >> PAGE_SHIFT; | 83 | totalhigh_pages = highmem >> PAGE_SHIFT; |
| 83 | totalram_pages += totalhigh_pages; | 84 | totalram_pages += totalhigh_pages; |
| 85 | #endif | ||
| 84 | num_physpages = totalram_pages; | 86 | num_physpages = totalram_pages; |
| 85 | max_pfn = totalram_pages; | 87 | max_pfn = totalram_pages; |
| 86 | printk(KERN_INFO "Memory: %luk available\n", | 88 | printk(KERN_INFO "Memory: %luk available\n", |
| @@ -221,10 +223,14 @@ void paging_init(void) | |||
| 221 | 223 | ||
| 222 | empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); | 224 | empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); |
| 223 | empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); | 225 | empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); |
| 224 | for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++) | 226 | for(i = 0; i < ARRAY_SIZE(zones_size); i++) |
| 225 | zones_size[i] = 0; | 227 | zones_size[i] = 0; |
| 226 | zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); | 228 | |
| 229 | zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) - | ||
| 230 | (uml_physmem >> PAGE_SHIFT); | ||
| 231 | #ifdef CONFIG_HIGHMEM | ||
| 227 | zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT; | 232 | zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT; |
| 233 | #endif | ||
| 228 | free_area_init(zones_size); | 234 | free_area_init(zones_size); |
| 229 | 235 | ||
| 230 | /* | 236 | /* |
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process.c index f6a5a502120b..fe6c64abda5b 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process.c | |||
| @@ -1,10 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) |
| 3 | * Copyright 2003 PathScale, Inc. | 3 | * Copyright 2003 PathScale, Inc. |
| 4 | * Licensed under the GPL | 4 | * Licensed under the GPL |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include "linux/config.h" | ||
| 8 | #include "linux/kernel.h" | 7 | #include "linux/kernel.h" |
| 9 | #include "linux/sched.h" | 8 | #include "linux/sched.h" |
| 10 | #include "linux/interrupt.h" | 9 | #include "linux/interrupt.h" |
| @@ -23,6 +22,7 @@ | |||
| 23 | #include "linux/proc_fs.h" | 22 | #include "linux/proc_fs.h" |
| 24 | #include "linux/ptrace.h" | 23 | #include "linux/ptrace.h" |
| 25 | #include "linux/random.h" | 24 | #include "linux/random.h" |
| 25 | #include "linux/personality.h" | ||
| 26 | #include "asm/unistd.h" | 26 | #include "asm/unistd.h" |
| 27 | #include "asm/mman.h" | 27 | #include "asm/mman.h" |
| 28 | #include "asm/segment.h" | 28 | #include "asm/segment.h" |
| @@ -112,11 +112,11 @@ void set_current(void *t) | |||
| 112 | 112 | ||
| 113 | void *_switch_to(void *prev, void *next, void *last) | 113 | void *_switch_to(void *prev, void *next, void *last) |
| 114 | { | 114 | { |
| 115 | struct task_struct *from = prev; | 115 | struct task_struct *from = prev; |
| 116 | struct task_struct *to= next; | 116 | struct task_struct *to= next; |
| 117 | 117 | ||
| 118 | to->thread.prev_sched = from; | 118 | to->thread.prev_sched = from; |
| 119 | set_current(to); | 119 | set_current(to); |
| 120 | 120 | ||
| 121 | do { | 121 | do { |
| 122 | current->thread.saved_task = NULL ; | 122 | current->thread.saved_task = NULL ; |
| @@ -127,7 +127,7 @@ void *_switch_to(void *prev, void *next, void *last) | |||
| 127 | prev= current; | 127 | prev= current; |
| 128 | } while(current->thread.saved_task); | 128 | } while(current->thread.saved_task); |
| 129 | 129 | ||
| 130 | return(current->thread.prev_sched); | 130 | return(current->thread.prev_sched); |
| 131 | 131 | ||
| 132 | } | 132 | } |
| 133 | 133 | ||
| @@ -141,19 +141,19 @@ void release_thread(struct task_struct *task) | |||
| 141 | { | 141 | { |
| 142 | CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); | 142 | CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | void exit_thread(void) | 145 | void exit_thread(void) |
| 146 | { | 146 | { |
| 147 | unprotect_stack((unsigned long) current_thread); | 147 | unprotect_stack((unsigned long) current_thread); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | void *get_current(void) | 150 | void *get_current(void) |
| 151 | { | 151 | { |
| 152 | return(current); | 152 | return(current); |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, | 155 | int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, |
| 156 | unsigned long stack_top, struct task_struct * p, | 156 | unsigned long stack_top, struct task_struct * p, |
| 157 | struct pt_regs *regs) | 157 | struct pt_regs *regs) |
| 158 | { | 158 | { |
| 159 | int ret; | 159 | int ret; |
| @@ -182,11 +182,11 @@ void initial_thread_cb(void (*proc)(void *), void *arg) | |||
| 182 | int save_kmalloc_ok = kmalloc_ok; | 182 | int save_kmalloc_ok = kmalloc_ok; |
| 183 | 183 | ||
| 184 | kmalloc_ok = 0; | 184 | kmalloc_ok = 0; |
| 185 | CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, | 185 | CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, |
| 186 | arg); | 186 | arg); |
| 187 | kmalloc_ok = save_kmalloc_ok; | 187 | kmalloc_ok = save_kmalloc_ok; |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | unsigned long stack_sp(unsigned long page) | 190 | unsigned long stack_sp(unsigned long page) |
| 191 | { | 191 | { |
| 192 | return(page + PAGE_SIZE - sizeof(void *)); | 192 | return(page + PAGE_SIZE - sizeof(void *)); |
| @@ -210,7 +210,7 @@ void default_idle(void) | |||
| 210 | */ | 210 | */ |
| 211 | if(need_resched()) | 211 | if(need_resched()) |
| 212 | schedule(); | 212 | schedule(); |
| 213 | 213 | ||
| 214 | idle_sleep(10); | 214 | idle_sleep(10); |
| 215 | } | 215 | } |
| 216 | } | 216 | } |
| @@ -225,7 +225,7 @@ int page_size(void) | |||
| 225 | return(PAGE_SIZE); | 225 | return(PAGE_SIZE); |
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | void *um_virt_to_phys(struct task_struct *task, unsigned long addr, | 228 | void *um_virt_to_phys(struct task_struct *task, unsigned long addr, |
| 229 | pte_t *pte_out) | 229 | pte_t *pte_out) |
| 230 | { | 230 | { |
| 231 | pgd_t *pgd; | 231 | pgd_t *pgd; |
| @@ -234,7 +234,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr, | |||
| 234 | pte_t *pte; | 234 | pte_t *pte; |
| 235 | pte_t ptent; | 235 | pte_t ptent; |
| 236 | 236 | ||
| 237 | if(task->mm == NULL) | 237 | if(task->mm == NULL) |
| 238 | return(ERR_PTR(-EINVAL)); | 238 | return(ERR_PTR(-EINVAL)); |
| 239 | pgd = pgd_offset(task->mm, addr); | 239 | pgd = pgd_offset(task->mm, addr); |
| 240 | if(!pgd_present(*pgd)) | 240 | if(!pgd_present(*pgd)) |
| @@ -245,7 +245,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr, | |||
| 245 | return(ERR_PTR(-EINVAL)); | 245 | return(ERR_PTR(-EINVAL)); |
| 246 | 246 | ||
| 247 | pmd = pmd_offset(pud, addr); | 247 | pmd = pmd_offset(pud, addr); |
| 248 | if(!pmd_present(*pmd)) | 248 | if(!pmd_present(*pmd)) |
| 249 | return(ERR_PTR(-EINVAL)); | 249 | return(ERR_PTR(-EINVAL)); |
| 250 | 250 | ||
| 251 | pte = pte_offset_kernel(pmd, addr); | 251 | pte = pte_offset_kernel(pmd, addr); |
| @@ -270,7 +270,7 @@ char *current_cmd(void) | |||
| 270 | 270 | ||
| 271 | void force_sigbus(void) | 271 | void force_sigbus(void) |
| 272 | { | 272 | { |
| 273 | printk(KERN_ERR "Killing pid %d because of a lack of memory\n", | 273 | printk(KERN_ERR "Killing pid %d because of a lack of memory\n", |
| 274 | current->pid); | 274 | current->pid); |
| 275 | lock_kernel(); | 275 | lock_kernel(); |
| 276 | sigaddset(¤t->pending.signal, SIGBUS); | 276 | sigaddset(¤t->pending.signal, SIGBUS); |
| @@ -476,7 +476,7 @@ int singlestepping(void * t) | |||
| 476 | #ifndef arch_align_stack | 476 | #ifndef arch_align_stack |
| 477 | unsigned long arch_align_stack(unsigned long sp) | 477 | unsigned long arch_align_stack(unsigned long sp) |
| 478 | { | 478 | { |
| 479 | if (randomize_va_space) | 479 | if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) |
| 480 | sp -= get_random_int() % 8192; | 480 | sp -= get_random_int() % 8192; |
| 481 | return sp & ~0xf; | 481 | return sp & ~0xf; |
| 482 | } | 482 | } |
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 3ef73bf2e781..f602623644aa 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c | |||
| @@ -22,7 +22,7 @@ static void kill_idlers(int me) | |||
| 22 | struct task_struct *p; | 22 | struct task_struct *p; |
| 23 | int i; | 23 | int i; |
| 24 | 24 | ||
| 25 | for(i = 0; i < sizeof(idle_threads)/sizeof(idle_threads[0]); i++){ | 25 | for(i = 0; i < ARRAY_SIZE(idle_threads); i++){ |
| 26 | p = idle_threads[i]; | 26 | p = idle_threads[i]; |
| 27 | if((p != NULL) && (p->thread.mode.tt.extern_pid != me)) | 27 | if((p != NULL) && (p->thread.mode.tt.extern_pid != me)) |
| 28 | os_kill_process(p->thread.mode.tt.extern_pid, 0); | 28 | os_kill_process(p->thread.mode.tt.extern_pid, 0); |
| @@ -62,14 +62,3 @@ void machine_halt(void) | |||
| 62 | { | 62 | { |
| 63 | machine_power_off(); | 63 | machine_power_off(); |
| 64 | } | 64 | } |
| 65 | |||
| 66 | /* | ||
| 67 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
| 68 | * Emacs will notice this stuff at the end of the file and automatically | ||
| 69 | * adjust the settings for this buffer only. This must remain at the end | ||
| 70 | * of the file. | ||
| 71 | * --------------------------------------------------------------------------- | ||
| 72 | * Local variables: | ||
| 73 | * c-file-style: "linux" | ||
| 74 | * End: | ||
| 75 | */ | ||
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile index ea3a8e409a6e..3e3fa7e7e3cf 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile | |||
| @@ -3,8 +3,7 @@ | |||
| 3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \ | 6 | obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o |
| 7 | syscall.o tlb.o uaccess.o | ||
| 8 | 7 | ||
| 9 | # clone.o is in the stub, so it can't be built with profiling | 8 | # clone.o is in the stub, so it can't be built with profiling |
| 10 | # GCC hardened also auto-enables -fpic, but we need %ebx so it can't work -> | 9 | # GCC hardened also auto-enables -fpic, but we need %ebx so it can't work -> |
diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c new file mode 100644 index 000000000000..54b795951372 --- /dev/null +++ b/arch/um/kernel/skas/exec.c | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include "linux/kernel.h" | ||
| 7 | #include "asm/current.h" | ||
| 8 | #include "asm/page.h" | ||
| 9 | #include "asm/signal.h" | ||
| 10 | #include "asm/ptrace.h" | ||
| 11 | #include "asm/uaccess.h" | ||
| 12 | #include "asm/mmu_context.h" | ||
| 13 | #include "tlb.h" | ||
| 14 | #include "skas.h" | ||
| 15 | #include "um_mmu.h" | ||
| 16 | #include "os.h" | ||
| 17 | |||
| 18 | void flush_thread_skas(void) | ||
| 19 | { | ||
| 20 | force_flush_all(); | ||
| 21 | switch_mm_skas(¤t->mm->context.skas.id); | ||
| 22 | } | ||
| 23 | |||
| 24 | void start_thread_skas(struct pt_regs *regs, unsigned long eip, | ||
| 25 | unsigned long esp) | ||
| 26 | { | ||
| 27 | set_fs(USER_DS); | ||
| 28 | PT_REGS_IP(regs) = eip; | ||
| 29 | PT_REGS_SP(regs) = esp; | ||
| 30 | } | ||
diff --git a/arch/um/kernel/skas/exec_kern.c b/arch/um/kernel/skas/exec_kern.c deleted file mode 100644 index 77ed7bbab219..000000000000 --- a/arch/um/kernel/skas/exec_kern.c +++ /dev/null | |||
| @@ -1,41 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include "linux/kernel.h" | ||
| 7 | #include "asm/current.h" | ||
| 8 | #include "asm/page.h" | ||
| 9 | #include "asm/signal.h" | ||
| 10 | #include "asm/ptrace.h" | ||
| 11 | #include "asm/uaccess.h" | ||
| 12 | #include "asm/mmu_context.h" | ||
| 13 | #include "tlb.h" | ||
| 14 | #include "skas.h" | ||
| 15 | #include "um_mmu.h" | ||
| 16 | #include "os.h" | ||
| 17 | |||
| 18 | void flush_thread_skas(void) | ||
| 19 | { | ||
| 20 | force_flush_all(); | ||
| 21 | switch_mm_skas(¤t->mm->context.skas.id); | ||
| 22 | } | ||
| 23 | |||
| 24 | void start_thread_skas(struct pt_regs *regs, unsigned long eip, | ||
| 25 | unsigned long esp) | ||
| 26 | { | ||
| 27 | set_fs(USER_DS); | ||
| 28 | PT_REGS_IP(regs) = eip; | ||
| 29 | PT_REGS_SP(regs) = esp; | ||
| 30 | } | ||
| 31 | |||
| 32 | /* | ||
| 33 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
| 34 | * Emacs will notice this stuff at the end of the file and automatically | ||
| 35 | * adjust the settings for this buffer only. This must remain at the end | ||
| 36 | * of the file. | ||
| 37 | * --------------------------------------------------------------------------- | ||
| 38 | * Local variables: | ||
| 39 | * c-file-style: "linux" | ||
| 40 | * End: | ||
| 41 | */ | ||
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 624ca238d1fd..79c22707a637 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c | |||
| @@ -55,7 +55,7 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, | |||
| 55 | * destroy_context_skas. | 55 | * destroy_context_skas. |
| 56 | */ | 56 | */ |
| 57 | 57 | ||
| 58 | mm->context.skas.last_page_table = pmd_page_kernel(*pmd); | 58 | mm->context.skas.last_page_table = pmd_page_vaddr(*pmd); |
| 59 | #ifdef CONFIG_3_LEVEL_PGTABLES | 59 | #ifdef CONFIG_3_LEVEL_PGTABLES |
| 60 | mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud)); | 60 | mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud)); |
| 61 | #endif | 61 | #endif |
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c new file mode 100644 index 000000000000..ae4fa71d3b8b --- /dev/null +++ b/arch/um/kernel/skas/process.c | |||
| @@ -0,0 +1,217 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include "linux/sched.h" | ||
| 7 | #include "linux/slab.h" | ||
| 8 | #include "linux/ptrace.h" | ||
| 9 | #include "linux/proc_fs.h" | ||
| 10 | #include "linux/file.h" | ||
| 11 | #include "linux/errno.h" | ||
| 12 | #include "linux/init.h" | ||
| 13 | #include "asm/uaccess.h" | ||
| 14 | #include "asm/atomic.h" | ||
| 15 | #include "kern_util.h" | ||
| 16 | #include "skas.h" | ||
| 17 | #include "os.h" | ||
| 18 | #include "user_util.h" | ||
| 19 | #include "tlb.h" | ||
| 20 | #include "kern.h" | ||
| 21 | #include "mode.h" | ||
| 22 | #include "registers.h" | ||
| 23 | |||
| 24 | void switch_to_skas(void *prev, void *next) | ||
| 25 | { | ||
| 26 | struct task_struct *from, *to; | ||
| 27 | |||
| 28 | from = prev; | ||
| 29 | to = next; | ||
| 30 | |||
| 31 | /* XXX need to check runqueues[cpu].idle */ | ||
| 32 | if(current->pid == 0) | ||
| 33 | switch_timers(0); | ||
| 34 | |||
| 35 | switch_threads(&from->thread.mode.skas.switch_buf, | ||
| 36 | &to->thread.mode.skas.switch_buf); | ||
| 37 | |||
| 38 | arch_switch_to_skas(current->thread.prev_sched, current); | ||
| 39 | |||
| 40 | if(current->pid == 0) | ||
| 41 | switch_timers(1); | ||
| 42 | } | ||
| 43 | |||
| 44 | extern void schedule_tail(struct task_struct *prev); | ||
| 45 | |||
| 46 | /* This is called magically, by its address being stuffed in a jmp_buf | ||
| 47 | * and being longjmp-d to. | ||
| 48 | */ | ||
| 49 | void new_thread_handler(void) | ||
| 50 | { | ||
| 51 | int (*fn)(void *), n; | ||
| 52 | void *arg; | ||
| 53 | |||
| 54 | if(current->thread.prev_sched != NULL) | ||
| 55 | schedule_tail(current->thread.prev_sched); | ||
| 56 | current->thread.prev_sched = NULL; | ||
| 57 | |||
| 58 | fn = current->thread.request.u.thread.proc; | ||
| 59 | arg = current->thread.request.u.thread.arg; | ||
| 60 | |||
| 61 | /* The return value is 1 if the kernel thread execs a process, | ||
| 62 | * 0 if it just exits | ||
| 63 | */ | ||
| 64 | n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); | ||
| 65 | if(n == 1){ | ||
| 66 | /* Handle any immediate reschedules or signals */ | ||
| 67 | interrupt_end(); | ||
| 68 | userspace(¤t->thread.regs.regs); | ||
| 69 | } | ||
| 70 | else do_exit(0); | ||
| 71 | } | ||
| 72 | |||
| 73 | void release_thread_skas(struct task_struct *task) | ||
| 74 | { | ||
| 75 | } | ||
| 76 | |||
| 77 | /* Called magically, see new_thread_handler above */ | ||
| 78 | void fork_handler(void) | ||
| 79 | { | ||
| 80 | force_flush_all(); | ||
| 81 | if(current->thread.prev_sched == NULL) | ||
| 82 | panic("blech"); | ||
| 83 | |||
| 84 | schedule_tail(current->thread.prev_sched); | ||
| 85 | |||
| 86 | /* XXX: if interrupt_end() calls schedule, this call to | ||
| 87 | * arch_switch_to_skas isn't needed. We could want to apply this to | ||
| 88 | * improve performance. -bb */ | ||
| 89 | arch_switch_to_skas(current->thread.prev_sched, current); | ||
| 90 | |||
| 91 | current->thread.prev_sched = NULL; | ||
| 92 | |||
| 93 | /* Handle any immediate reschedules or signals */ | ||
| 94 | interrupt_end(); | ||
| 95 | |||
| 96 | userspace(¤t->thread.regs.regs); | ||
| 97 | } | ||
| 98 | |||
| 99 | int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, | ||
| 100 | unsigned long stack_top, struct task_struct * p, | ||
| 101 | struct pt_regs *regs) | ||
| 102 | { | ||
| 103 | void (*handler)(void); | ||
| 104 | |||
| 105 | if(current->thread.forking){ | ||
| 106 | memcpy(&p->thread.regs.regs.skas, ®s->regs.skas, | ||
| 107 | sizeof(p->thread.regs.regs.skas)); | ||
| 108 | REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0); | ||
| 109 | if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; | ||
| 110 | |||
| 111 | handler = fork_handler; | ||
| 112 | |||
| 113 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); | ||
| 114 | } | ||
| 115 | else { | ||
| 116 | init_thread_registers(&p->thread.regs.regs); | ||
| 117 | p->thread.request.u.thread = current->thread.request.u.thread; | ||
| 118 | handler = new_thread_handler; | ||
| 119 | } | ||
| 120 | |||
| 121 | new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf, | ||
| 122 | handler); | ||
| 123 | return(0); | ||
| 124 | } | ||
| 125 | |||
| 126 | int new_mm(unsigned long stack) | ||
| 127 | { | ||
| 128 | int fd; | ||
| 129 | |||
| 130 | fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); | ||
| 131 | if(fd < 0) | ||
| 132 | return(fd); | ||
| 133 | |||
| 134 | if(skas_needs_stub) | ||
| 135 | map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); | ||
| 136 | |||
| 137 | return(fd); | ||
| 138 | } | ||
| 139 | |||
| 140 | void init_idle_skas(void) | ||
| 141 | { | ||
| 142 | cpu_tasks[current_thread->cpu].pid = os_getpid(); | ||
| 143 | default_idle(); | ||
| 144 | } | ||
| 145 | |||
| 146 | extern void start_kernel(void); | ||
| 147 | |||
| 148 | static int start_kernel_proc(void *unused) | ||
| 149 | { | ||
| 150 | int pid; | ||
| 151 | |||
| 152 | block_signals(); | ||
| 153 | pid = os_getpid(); | ||
| 154 | |||
| 155 | cpu_tasks[0].pid = pid; | ||
| 156 | cpu_tasks[0].task = current; | ||
| 157 | #ifdef CONFIG_SMP | ||
| 158 | cpu_online_map = cpumask_of_cpu(0); | ||
| 159 | #endif | ||
| 160 | start_kernel(); | ||
| 161 | return(0); | ||
| 162 | } | ||
| 163 | |||
| 164 | extern int userspace_pid[]; | ||
| 165 | |||
| 166 | int start_uml_skas(void) | ||
| 167 | { | ||
| 168 | if(proc_mm) | ||
| 169 | userspace_pid[0] = start_userspace(0); | ||
| 170 | |||
| 171 | init_new_thread_signals(); | ||
| 172 | |||
| 173 | init_task.thread.request.u.thread.proc = start_kernel_proc; | ||
| 174 | init_task.thread.request.u.thread.arg = NULL; | ||
| 175 | return(start_idle_thread(task_stack_page(&init_task), | ||
| 176 | &init_task.thread.mode.skas.switch_buf)); | ||
| 177 | } | ||
| 178 | |||
| 179 | int external_pid_skas(struct task_struct *task) | ||
| 180 | { | ||
| 181 | #warning Need to look up userspace_pid by cpu | ||
| 182 | return(userspace_pid[0]); | ||
| 183 | } | ||
| 184 | |||
| 185 | int thread_pid_skas(struct task_struct *task) | ||
| 186 | { | ||
| 187 | #warning Need to look up userspace_pid by cpu | ||
| 188 | return(userspace_pid[0]); | ||
| 189 | } | ||
| 190 | |||
| 191 | void kill_off_processes_skas(void) | ||
| 192 | { | ||
| 193 | if(proc_mm) | ||
| 194 | #warning need to loop over userspace_pids in kill_off_processes_skas | ||
| 195 | os_kill_ptraced_process(userspace_pid[0], 1); | ||
| 196 | else { | ||
| 197 | struct task_struct *p; | ||
| 198 | int pid, me; | ||
| 199 | |||
| 200 | me = os_getpid(); | ||
| 201 | for_each_process(p){ | ||
| 202 | if(p->mm == NULL) | ||
| 203 | continue; | ||
| 204 | |||
| 205 | pid = p->mm->context.skas.id.u.pid; | ||
| 206 | os_kill_ptraced_process(pid, 1); | ||
| 207 | } | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 211 | unsigned long current_stub_stack(void) | ||
| 212 | { | ||
| 213 | if(current->mm == NULL) | ||
| 214 | return(0); | ||
| 215 | |||
| 216 | return(current->mm->context.skas.id.stack); | ||
| 217 | } | ||
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 55caeec8b257..0f3d5d084dc7 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c | |||
| @@ -1,227 +1,484 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) |
| 3 | * Copyright 2003 PathScale, Inc. | ||
| 3 | * Licensed under the GPL | 4 | * Licensed under the GPL |
| 4 | */ | 5 | */ |
| 5 | 6 | ||
| 7 | #include "linux/config.h" | ||
| 8 | #include "linux/kernel.h" | ||
| 6 | #include "linux/sched.h" | 9 | #include "linux/sched.h" |
| 10 | #include "linux/interrupt.h" | ||
| 11 | #include "linux/string.h" | ||
| 12 | #include "linux/mm.h" | ||
| 7 | #include "linux/slab.h" | 13 | #include "linux/slab.h" |
| 8 | #include "linux/ptrace.h" | 14 | #include "linux/utsname.h" |
| 9 | #include "linux/proc_fs.h" | 15 | #include "linux/fs.h" |
| 10 | #include "linux/file.h" | 16 | #include "linux/utime.h" |
| 11 | #include "linux/errno.h" | 17 | #include "linux/smp_lock.h" |
| 18 | #include "linux/module.h" | ||
| 12 | #include "linux/init.h" | 19 | #include "linux/init.h" |
| 20 | #include "linux/capability.h" | ||
| 21 | #include "linux/vmalloc.h" | ||
| 22 | #include "linux/spinlock.h" | ||
| 23 | #include "linux/proc_fs.h" | ||
| 24 | #include "linux/ptrace.h" | ||
| 25 | #include "linux/random.h" | ||
| 26 | #include "linux/personality.h" | ||
| 27 | #include "asm/unistd.h" | ||
| 28 | #include "asm/mman.h" | ||
| 29 | #include "asm/segment.h" | ||
| 30 | #include "asm/stat.h" | ||
| 31 | #include "asm/pgtable.h" | ||
| 32 | #include "asm/processor.h" | ||
| 33 | #include "asm/tlbflush.h" | ||
| 13 | #include "asm/uaccess.h" | 34 | #include "asm/uaccess.h" |
| 14 | #include "asm/atomic.h" | 35 | #include "asm/user.h" |
| 15 | #include "kern_util.h" | ||
| 16 | #include "skas.h" | ||
| 17 | #include "os.h" | ||
| 18 | #include "user_util.h" | 36 | #include "user_util.h" |
| 19 | #include "tlb.h" | 37 | #include "kern_util.h" |
| 20 | #include "kern.h" | 38 | #include "kern.h" |
| 39 | #include "signal_kern.h" | ||
| 40 | #include "init.h" | ||
| 41 | #include "irq_user.h" | ||
| 42 | #include "mem_user.h" | ||
| 43 | #include "tlb.h" | ||
| 44 | #include "frame_kern.h" | ||
| 45 | #include "sigcontext.h" | ||
| 46 | #include "os.h" | ||
| 21 | #include "mode.h" | 47 | #include "mode.h" |
| 22 | #include "registers.h" | 48 | #include "mode_kern.h" |
| 49 | #include "choose-mode.h" | ||
| 50 | |||
| 51 | /* This is a per-cpu array. A processor only modifies its entry and it only | ||
| 52 | * cares about its entry, so it's OK if another processor is modifying its | ||
| 53 | * entry. | ||
| 54 | */ | ||
| 55 | struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; | ||
| 56 | |||
| 57 | int external_pid(void *t) | ||
| 58 | { | ||
| 59 | struct task_struct *task = t ? t : current; | ||
| 60 | |||
| 61 | return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task)); | ||
| 62 | } | ||
| 63 | |||
| 64 | int pid_to_processor_id(int pid) | ||
| 65 | { | ||
| 66 | int i; | ||
| 67 | |||
| 68 | for(i = 0; i < ncpus; i++){ | ||
| 69 | if(cpu_tasks[i].pid == pid) return(i); | ||
| 70 | } | ||
| 71 | return(-1); | ||
| 72 | } | ||
| 73 | |||
| 74 | void free_stack(unsigned long stack, int order) | ||
| 75 | { | ||
| 76 | free_pages(stack, order); | ||
| 77 | } | ||
| 78 | |||
| 79 | unsigned long alloc_stack(int order, int atomic) | ||
| 80 | { | ||
| 81 | unsigned long page; | ||
| 82 | gfp_t flags = GFP_KERNEL; | ||
| 83 | |||
| 84 | if (atomic) | ||
| 85 | flags = GFP_ATOMIC; | ||
| 86 | page = __get_free_pages(flags, order); | ||
| 87 | if(page == 0) | ||
| 88 | return(0); | ||
| 89 | stack_protections(page); | ||
| 90 | return(page); | ||
| 91 | } | ||
| 92 | |||
| 93 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
| 94 | { | ||
| 95 | int pid; | ||
| 96 | |||
| 97 | current->thread.request.u.thread.proc = fn; | ||
| 98 | current->thread.request.u.thread.arg = arg; | ||
| 99 | pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, | ||
| 100 | ¤t->thread.regs, 0, NULL, NULL); | ||
| 101 | if(pid < 0) | ||
| 102 | panic("do_fork failed in kernel_thread, errno = %d", pid); | ||
| 103 | return(pid); | ||
| 104 | } | ||
| 23 | 105 | ||
| 24 | void switch_to_skas(void *prev, void *next) | 106 | void set_current(void *t) |
| 25 | { | 107 | { |
| 26 | struct task_struct *from, *to; | 108 | struct task_struct *task = t; |
| 27 | 109 | ||
| 28 | from = prev; | 110 | cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) |
| 29 | to = next; | 111 | { external_pid(task), task }); |
| 112 | } | ||
| 30 | 113 | ||
| 31 | /* XXX need to check runqueues[cpu].idle */ | 114 | void *_switch_to(void *prev, void *next, void *last) |
| 32 | if(current->pid == 0) | 115 | { |
| 33 | switch_timers(0); | 116 | struct task_struct *from = prev; |
| 117 | struct task_struct *to= next; | ||
| 34 | 118 | ||
| 35 | switch_threads(&from->thread.mode.skas.switch_buf, | 119 | to->thread.prev_sched = from; |
| 36 | to->thread.mode.skas.switch_buf); | 120 | set_current(to); |
| 37 | 121 | ||
| 38 | arch_switch_to_skas(current->thread.prev_sched, current); | 122 | do { |
| 123 | current->thread.saved_task = NULL ; | ||
| 124 | CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next); | ||
| 125 | if(current->thread.saved_task) | ||
| 126 | show_regs(&(current->thread.regs)); | ||
| 127 | next= current->thread.saved_task; | ||
| 128 | prev= current; | ||
| 129 | } while(current->thread.saved_task); | ||
| 130 | |||
| 131 | return(current->thread.prev_sched); | ||
| 39 | 132 | ||
| 40 | if(current->pid == 0) | ||
| 41 | switch_timers(1); | ||
| 42 | } | 133 | } |
| 43 | 134 | ||
| 44 | extern void schedule_tail(struct task_struct *prev); | 135 | void interrupt_end(void) |
| 136 | { | ||
| 137 | if(need_resched()) schedule(); | ||
| 138 | if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal(); | ||
| 139 | } | ||
| 45 | 140 | ||
| 46 | void new_thread_handler(int sig) | 141 | void release_thread(struct task_struct *task) |
| 47 | { | 142 | { |
| 48 | int (*fn)(void *), n; | 143 | CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); |
| 49 | void *arg; | 144 | } |
| 50 | 145 | ||
| 51 | fn = current->thread.request.u.thread.proc; | 146 | void exit_thread(void) |
| 52 | arg = current->thread.request.u.thread.arg; | 147 | { |
| 53 | os_usr1_signal(1); | 148 | unprotect_stack((unsigned long) current_thread); |
| 54 | thread_wait(¤t->thread.mode.skas.switch_buf, | 149 | } |
| 55 | current->thread.mode.skas.fork_buf); | ||
| 56 | 150 | ||
| 57 | if(current->thread.prev_sched != NULL) | 151 | void *get_current(void) |
| 58 | schedule_tail(current->thread.prev_sched); | 152 | { |
| 59 | current->thread.prev_sched = NULL; | 153 | return(current); |
| 154 | } | ||
| 155 | |||
| 156 | int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, | ||
| 157 | unsigned long stack_top, struct task_struct * p, | ||
| 158 | struct pt_regs *regs) | ||
| 159 | { | ||
| 160 | int ret; | ||
| 60 | 161 | ||
| 61 | /* The return value is 1 if the kernel thread execs a process, | 162 | p->thread = (struct thread_struct) INIT_THREAD; |
| 62 | * 0 if it just exits | 163 | ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, |
| 164 | clone_flags, sp, stack_top, p, regs); | ||
| 165 | |||
| 166 | if (ret || !current->thread.forking) | ||
| 167 | goto out; | ||
| 168 | |||
| 169 | clear_flushed_tls(p); | ||
| 170 | |||
| 171 | /* | ||
| 172 | * Set a new TLS for the child thread? | ||
| 63 | */ | 173 | */ |
| 64 | n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); | 174 | if (clone_flags & CLONE_SETTLS) |
| 65 | if(n == 1){ | 175 | ret = arch_copy_tls(p); |
| 66 | /* Handle any immediate reschedules or signals */ | 176 | |
| 67 | interrupt_end(); | 177 | out: |
| 68 | userspace(¤t->thread.regs.regs); | 178 | return ret; |
| 179 | } | ||
| 180 | |||
| 181 | void initial_thread_cb(void (*proc)(void *), void *arg) | ||
| 182 | { | ||
| 183 | int save_kmalloc_ok = kmalloc_ok; | ||
| 184 | |||
| 185 | kmalloc_ok = 0; | ||
| 186 | CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, | ||
| 187 | arg); | ||
| 188 | kmalloc_ok = save_kmalloc_ok; | ||
| 189 | } | ||
| 190 | |||
| 191 | unsigned long stack_sp(unsigned long page) | ||
| 192 | { | ||
| 193 | return(page + PAGE_SIZE - sizeof(void *)); | ||
| 194 | } | ||
| 195 | |||
| 196 | int current_pid(void) | ||
| 197 | { | ||
| 198 | return(current->pid); | ||
| 199 | } | ||
| 200 | |||
| 201 | void default_idle(void) | ||
| 202 | { | ||
| 203 | CHOOSE_MODE(uml_idle_timer(), (void) 0); | ||
| 204 | |||
| 205 | while(1){ | ||
| 206 | /* endless idle loop with no priority at all */ | ||
| 207 | |||
| 208 | /* | ||
| 209 | * although we are an idle CPU, we do not want to | ||
| 210 | * get into the scheduler unnecessarily. | ||
| 211 | */ | ||
| 212 | if(need_resched()) | ||
| 213 | schedule(); | ||
| 214 | |||
| 215 | idle_sleep(10); | ||
| 69 | } | 216 | } |
| 70 | else do_exit(0); | ||
| 71 | } | 217 | } |
| 72 | 218 | ||
| 73 | void new_thread_proc(void *stack, void (*handler)(int sig)) | 219 | void cpu_idle(void) |
| 74 | { | 220 | { |
| 75 | init_new_thread_stack(stack, handler); | 221 | CHOOSE_MODE(init_idle_tt(), init_idle_skas()); |
| 76 | os_usr1_process(os_getpid()); | ||
| 77 | } | 222 | } |
| 78 | 223 | ||
| 79 | void release_thread_skas(struct task_struct *task) | 224 | int page_size(void) |
| 80 | { | 225 | { |
| 226 | return(PAGE_SIZE); | ||
| 81 | } | 227 | } |
| 82 | 228 | ||
| 83 | void fork_handler(int sig) | 229 | void *um_virt_to_phys(struct task_struct *task, unsigned long addr, |
| 230 | pte_t *pte_out) | ||
| 84 | { | 231 | { |
| 85 | os_usr1_signal(1); | 232 | pgd_t *pgd; |
| 86 | thread_wait(¤t->thread.mode.skas.switch_buf, | 233 | pud_t *pud; |
| 87 | current->thread.mode.skas.fork_buf); | 234 | pmd_t *pmd; |
| 88 | 235 | pte_t *pte; | |
| 89 | force_flush_all(); | 236 | pte_t ptent; |
| 90 | if(current->thread.prev_sched == NULL) | 237 | |
| 91 | panic("blech"); | 238 | if(task->mm == NULL) |
| 239 | return(ERR_PTR(-EINVAL)); | ||
| 240 | pgd = pgd_offset(task->mm, addr); | ||
| 241 | if(!pgd_present(*pgd)) | ||
| 242 | return(ERR_PTR(-EINVAL)); | ||
| 243 | |||
| 244 | pud = pud_offset(pgd, addr); | ||
| 245 | if(!pud_present(*pud)) | ||
| 246 | return(ERR_PTR(-EINVAL)); | ||
| 247 | |||
| 248 | pmd = pmd_offset(pud, addr); | ||
| 249 | if(!pmd_present(*pmd)) | ||
| 250 | return(ERR_PTR(-EINVAL)); | ||
| 251 | |||
| 252 | pte = pte_offset_kernel(pmd, addr); | ||
| 253 | ptent = *pte; | ||
| 254 | if(!pte_present(ptent)) | ||
| 255 | return(ERR_PTR(-EINVAL)); | ||
| 256 | |||
| 257 | if(pte_out != NULL) | ||
| 258 | *pte_out = ptent; | ||
| 259 | return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK)); | ||
| 260 | } | ||
| 92 | 261 | ||
| 93 | schedule_tail(current->thread.prev_sched); | 262 | char *current_cmd(void) |
| 263 | { | ||
| 264 | #if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM) | ||
| 265 | return("(Unknown)"); | ||
| 266 | #else | ||
| 267 | void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL); | ||
| 268 | return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr); | ||
| 269 | #endif | ||
| 270 | } | ||
| 94 | 271 | ||
| 95 | /* XXX: if interrupt_end() calls schedule, this call to | 272 | void force_sigbus(void) |
| 96 | * arch_switch_to_skas isn't needed. We could want to apply this to | 273 | { |
| 97 | * improve performance. -bb */ | 274 | printk(KERN_ERR "Killing pid %d because of a lack of memory\n", |
| 98 | arch_switch_to_skas(current->thread.prev_sched, current); | 275 | current->pid); |
| 276 | lock_kernel(); | ||
| 277 | sigaddset(¤t->pending.signal, SIGBUS); | ||
| 278 | recalc_sigpending(); | ||
| 279 | current->flags |= PF_SIGNALED; | ||
| 280 | do_exit(SIGBUS | 0x80); | ||
| 281 | } | ||
| 99 | 282 | ||
| 100 | current->thread.prev_sched = NULL; | 283 | void dump_thread(struct pt_regs *regs, struct user *u) |
| 284 | { | ||
| 285 | } | ||
| 101 | 286 | ||
| 102 | /* Handle any immediate reschedules or signals */ | 287 | void enable_hlt(void) |
| 103 | interrupt_end(); | 288 | { |
| 289 | panic("enable_hlt"); | ||
| 290 | } | ||
| 291 | |||
| 292 | EXPORT_SYMBOL(enable_hlt); | ||
| 104 | 293 | ||
| 105 | userspace(¤t->thread.regs.regs); | 294 | void disable_hlt(void) |
| 295 | { | ||
| 296 | panic("disable_hlt"); | ||
| 106 | } | 297 | } |
| 107 | 298 | ||
| 108 | int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, | 299 | EXPORT_SYMBOL(disable_hlt); |
| 109 | unsigned long stack_top, struct task_struct * p, | 300 | |
| 110 | struct pt_regs *regs) | 301 | void *um_kmalloc(int size) |
| 111 | { | 302 | { |
| 112 | void (*handler)(int); | 303 | return kmalloc(size, GFP_KERNEL); |
| 304 | } | ||
| 113 | 305 | ||
| 114 | if(current->thread.forking){ | 306 | void *um_kmalloc_atomic(int size) |
| 115 | memcpy(&p->thread.regs.regs.skas, ®s->regs.skas, | 307 | { |
| 116 | sizeof(p->thread.regs.regs.skas)); | 308 | return kmalloc(size, GFP_ATOMIC); |
| 117 | REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0); | 309 | } |
| 118 | if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; | ||
| 119 | 310 | ||
| 120 | handler = fork_handler; | 311 | void *um_vmalloc(int size) |
| 312 | { | ||
| 313 | return vmalloc(size); | ||
| 314 | } | ||
| 121 | 315 | ||
| 122 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); | 316 | void *um_vmalloc_atomic(int size) |
| 123 | } | 317 | { |
| 124 | else { | 318 | return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL); |
| 125 | init_thread_registers(&p->thread.regs.regs); | 319 | } |
| 126 | p->thread.request.u.thread = current->thread.request.u.thread; | ||
| 127 | handler = new_thread_handler; | ||
| 128 | } | ||
| 129 | 320 | ||
| 130 | new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf, | 321 | int __cant_sleep(void) { |
| 131 | &p->thread.mode.skas.fork_buf, handler); | 322 | return in_atomic() || irqs_disabled() || in_interrupt(); |
| 132 | return(0); | 323 | /* Is in_interrupt() really needed? */ |
| 324 | } | ||
| 325 | |||
| 326 | unsigned long get_fault_addr(void) | ||
| 327 | { | ||
| 328 | return((unsigned long) current->thread.fault_addr); | ||
| 133 | } | 329 | } |
| 134 | 330 | ||
| 135 | int new_mm(unsigned long stack) | 331 | EXPORT_SYMBOL(get_fault_addr); |
| 332 | |||
| 333 | void not_implemented(void) | ||
| 136 | { | 334 | { |
| 137 | int fd; | 335 | printk(KERN_DEBUG "Something isn't implemented in here\n"); |
| 336 | } | ||
| 138 | 337 | ||
| 139 | fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); | 338 | EXPORT_SYMBOL(not_implemented); |
| 140 | if(fd < 0) | ||
| 141 | return(fd); | ||
| 142 | 339 | ||
| 143 | if(skas_needs_stub) | 340 | int user_context(unsigned long sp) |
| 144 | map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); | 341 | { |
| 342 | unsigned long stack; | ||
| 145 | 343 | ||
| 146 | return(fd); | 344 | stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); |
| 345 | return(stack != (unsigned long) current_thread); | ||
| 147 | } | 346 | } |
| 148 | 347 | ||
| 149 | void init_idle_skas(void) | 348 | extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; |
| 349 | |||
| 350 | void do_uml_exitcalls(void) | ||
| 150 | { | 351 | { |
| 151 | cpu_tasks[current_thread->cpu].pid = os_getpid(); | 352 | exitcall_t *call; |
| 152 | default_idle(); | 353 | |
| 354 | call = &__uml_exitcall_end; | ||
| 355 | while (--call >= &__uml_exitcall_begin) | ||
| 356 | (*call)(); | ||
| 153 | } | 357 | } |
| 154 | 358 | ||
| 155 | extern void start_kernel(void); | 359 | char *uml_strdup(char *string) |
| 360 | { | ||
| 361 | return kstrdup(string, GFP_KERNEL); | ||
| 362 | } | ||
| 156 | 363 | ||
| 157 | static int start_kernel_proc(void *unused) | 364 | int copy_to_user_proc(void __user *to, void *from, int size) |
| 158 | { | 365 | { |
| 159 | int pid; | 366 | return(copy_to_user(to, from, size)); |
| 367 | } | ||
| 368 | |||
| 369 | int copy_from_user_proc(void *to, void __user *from, int size) | ||
| 370 | { | ||
| 371 | return(copy_from_user(to, from, size)); | ||
| 372 | } | ||
| 373 | |||
| 374 | int clear_user_proc(void __user *buf, int size) | ||
| 375 | { | ||
| 376 | return(clear_user(buf, size)); | ||
| 377 | } | ||
| 160 | 378 | ||
| 161 | block_signals(); | 379 | int strlen_user_proc(char __user *str) |
| 162 | pid = os_getpid(); | 380 | { |
| 381 | return(strlen_user(str)); | ||
| 382 | } | ||
| 163 | 383 | ||
| 164 | cpu_tasks[0].pid = pid; | 384 | int smp_sigio_handler(void) |
| 165 | cpu_tasks[0].task = current; | 385 | { |
| 166 | #ifdef CONFIG_SMP | 386 | #ifdef CONFIG_SMP |
| 167 | cpu_online_map = cpumask_of_cpu(0); | 387 | int cpu = current_thread->cpu; |
| 388 | IPI_handler(cpu); | ||
| 389 | if(cpu != 0) | ||
| 390 | return(1); | ||
| 168 | #endif | 391 | #endif |
| 169 | start_kernel(); | ||
| 170 | return(0); | 392 | return(0); |
| 171 | } | 393 | } |
| 172 | 394 | ||
| 173 | extern int userspace_pid[]; | 395 | int cpu(void) |
| 174 | |||
| 175 | int start_uml_skas(void) | ||
| 176 | { | 396 | { |
| 177 | if(proc_mm) | 397 | return(current_thread->cpu); |
| 178 | userspace_pid[0] = start_userspace(0); | 398 | } |
| 399 | |||
| 400 | static atomic_t using_sysemu = ATOMIC_INIT(0); | ||
| 401 | int sysemu_supported; | ||
| 179 | 402 | ||
| 180 | init_new_thread_signals(); | 403 | void set_using_sysemu(int value) |
| 404 | { | ||
| 405 | if (value > sysemu_supported) | ||
| 406 | return; | ||
| 407 | atomic_set(&using_sysemu, value); | ||
| 408 | } | ||
| 181 | 409 | ||
| 182 | init_task.thread.request.u.thread.proc = start_kernel_proc; | 410 | int get_using_sysemu(void) |
| 183 | init_task.thread.request.u.thread.arg = NULL; | 411 | { |
| 184 | return(start_idle_thread(task_stack_page(&init_task), | 412 | return atomic_read(&using_sysemu); |
| 185 | &init_task.thread.mode.skas.switch_buf, | ||
| 186 | &init_task.thread.mode.skas.fork_buf)); | ||
| 187 | } | 413 | } |
| 188 | 414 | ||
| 189 | int external_pid_skas(struct task_struct *task) | 415 | static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data) |
| 190 | { | 416 | { |
| 191 | #warning Need to look up userspace_pid by cpu | 417 | if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/ |
| 192 | return(userspace_pid[0]); | 418 | *eof = 1; |
| 419 | |||
| 420 | return strlen(buf); | ||
| 193 | } | 421 | } |
| 194 | 422 | ||
| 195 | int thread_pid_skas(struct task_struct *task) | 423 | static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data) |
| 196 | { | 424 | { |
| 197 | #warning Need to look up userspace_pid by cpu | 425 | char tmp[2]; |
| 198 | return(userspace_pid[0]); | 426 | |
| 427 | if (copy_from_user(tmp, buf, 1)) | ||
| 428 | return -EFAULT; | ||
| 429 | |||
| 430 | if (tmp[0] >= '0' && tmp[0] <= '2') | ||
| 431 | set_using_sysemu(tmp[0] - '0'); | ||
| 432 | return count; /*We use the first char, but pretend to write everything*/ | ||
| 199 | } | 433 | } |
| 200 | 434 | ||
| 201 | void kill_off_processes_skas(void) | 435 | int __init make_proc_sysemu(void) |
| 202 | { | 436 | { |
| 203 | if(proc_mm) | 437 | struct proc_dir_entry *ent; |
| 204 | #warning need to loop over userspace_pids in kill_off_processes_skas | 438 | if (!sysemu_supported) |
| 205 | os_kill_ptraced_process(userspace_pid[0], 1); | 439 | return 0; |
| 206 | else { | ||
| 207 | struct task_struct *p; | ||
| 208 | int pid, me; | ||
| 209 | 440 | ||
| 210 | me = os_getpid(); | 441 | ent = create_proc_entry("sysemu", 0600, &proc_root); |
| 211 | for_each_process(p){ | ||
| 212 | if(p->mm == NULL) | ||
| 213 | continue; | ||
| 214 | 442 | ||
| 215 | pid = p->mm->context.skas.id.u.pid; | 443 | if (ent == NULL) |
| 216 | os_kill_ptraced_process(pid, 1); | 444 | { |
| 217 | } | 445 | printk(KERN_WARNING "Failed to register /proc/sysemu\n"); |
| 446 | return(0); | ||
| 218 | } | 447 | } |
| 448 | |||
| 449 | ent->read_proc = proc_read_sysemu; | ||
| 450 | ent->write_proc = proc_write_sysemu; | ||
| 451 | |||
| 452 | return 0; | ||
| 219 | } | 453 | } |
| 220 | 454 | ||
| 221 | unsigned long current_stub_stack(void) | 455 | late_initcall(make_proc_sysemu); |
| 456 | |||
| 457 | int singlestepping(void * t) | ||
| 222 | { | 458 | { |
| 223 | if(current->mm == NULL) | 459 | struct task_struct *task = t ? t : current; |
| 460 | |||
| 461 | if ( ! (task->ptrace & PT_DTRACE) ) | ||
| 224 | return(0); | 462 | return(0); |
| 225 | 463 | ||
| 226 | return(current->mm->context.skas.id.stack); | 464 | if (task->thread.singlestep_syscall) |
| 465 | return(1); | ||
| 466 | |||
| 467 | return 2; | ||
| 468 | } | ||
| 469 | |||
| 470 | /* | ||
| 471 | * Only x86 and x86_64 have an arch_align_stack(). | ||
| 472 | * All other arches have "#define arch_align_stack(x) (x)" | ||
| 473 | * in their asm/system.h | ||
| 474 | * As this is included in UML from asm-um/system-generic.h, | ||
| 475 | * we can use it to behave as the subarch does. | ||
| 476 | */ | ||
| 477 | #ifndef arch_align_stack | ||
| 478 | unsigned long arch_align_stack(unsigned long sp) | ||
| 479 | { | ||
| 480 | if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) | ||
| 481 | sp -= get_random_int() % 8192; | ||
| 482 | return sp & ~0xf; | ||
| 227 | } | 483 | } |
| 484 | #endif | ||
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 552ca1cb9847..820affbf3e16 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c | |||
| @@ -35,9 +35,6 @@ unsigned long long sched_clock(void) | |||
| 35 | return (unsigned long long)jiffies_64 * (1000000000 / HZ); | 35 | return (unsigned long long)jiffies_64 * (1000000000 / HZ); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | /* Changed at early boot */ | ||
| 39 | int timer_irq_inited = 0; | ||
| 40 | |||
| 41 | static unsigned long long prev_nsecs; | 38 | static unsigned long long prev_nsecs; |
| 42 | #ifdef CONFIG_UML_REAL_TIME_CLOCK | 39 | #ifdef CONFIG_UML_REAL_TIME_CLOCK |
| 43 | static long long delta; /* Deviation per interval */ | 40 | static long long delta; /* Deviation per interval */ |
| @@ -98,7 +95,7 @@ irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) | |||
| 98 | 95 | ||
| 99 | do_timer(regs); | 96 | do_timer(regs); |
| 100 | 97 | ||
| 101 | nsecs = get_time() + local_offset; | 98 | nsecs = get_time(); |
| 102 | xtime.tv_sec = nsecs / NSEC_PER_SEC; | 99 | xtime.tv_sec = nsecs / NSEC_PER_SEC; |
| 103 | xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; | 100 | xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; |
| 104 | 101 | ||
| @@ -113,12 +110,13 @@ static void register_timer(void) | |||
| 113 | 110 | ||
| 114 | err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); | 111 | err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); |
| 115 | if(err != 0) | 112 | if(err != 0) |
| 116 | printk(KERN_ERR "timer_init : request_irq failed - " | 113 | printk(KERN_ERR "register_timer : request_irq failed - " |
| 117 | "errno = %d\n", -err); | 114 | "errno = %d\n", -err); |
| 118 | 115 | ||
| 119 | timer_irq_inited = 1; | 116 | err = set_interval(1); |
| 120 | 117 | if(err != 0) | |
| 121 | user_time_init(); | 118 | printk(KERN_ERR "register_timer : set_interval failed - " |
| 119 | "errno = %d\n", -err); | ||
| 122 | } | 120 | } |
| 123 | 121 | ||
| 124 | extern void (*late_time_init)(void); | 122 | extern void (*late_time_init)(void); |
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index f5b0636f9ad7..54a5ff25645a 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) |
| 3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
| 4 | */ | 4 | */ |
| @@ -16,12 +16,12 @@ | |||
| 16 | #include "os.h" | 16 | #include "os.h" |
| 17 | 17 | ||
| 18 | static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, | 18 | static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, |
| 19 | int r, int w, int x, struct host_vm_op *ops, int *index, | 19 | int r, int w, int x, struct host_vm_op *ops, int *index, |
| 20 | int last_filled, union mm_context *mmu, void **flush, | 20 | int last_filled, union mm_context *mmu, void **flush, |
| 21 | int (*do_ops)(union mm_context *, struct host_vm_op *, | 21 | int (*do_ops)(union mm_context *, struct host_vm_op *, |
| 22 | int, int, void **)) | 22 | int, int, void **)) |
| 23 | { | 23 | { |
| 24 | __u64 offset; | 24 | __u64 offset; |
| 25 | struct host_vm_op *last; | 25 | struct host_vm_op *last; |
| 26 | int fd, ret = 0; | 26 | int fd, ret = 0; |
| 27 | 27 | ||
| @@ -89,7 +89,7 @@ static int add_munmap(unsigned long addr, unsigned long len, | |||
| 89 | static int add_mprotect(unsigned long addr, unsigned long len, int r, int w, | 89 | static int add_mprotect(unsigned long addr, unsigned long len, int r, int w, |
| 90 | int x, struct host_vm_op *ops, int *index, | 90 | int x, struct host_vm_op *ops, int *index, |
| 91 | int last_filled, union mm_context *mmu, void **flush, | 91 | int last_filled, union mm_context *mmu, void **flush, |
| 92 | int (*do_ops)(union mm_context *, struct host_vm_op *, | 92 | int (*do_ops)(union mm_context *, struct host_vm_op *, |
| 93 | int, int, void **)) | 93 | int, int, void **)) |
| 94 | { | 94 | { |
| 95 | struct host_vm_op *last; | 95 | struct host_vm_op *last; |
| @@ -124,105 +124,105 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w, | |||
| 124 | #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) | 124 | #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) |
| 125 | 125 | ||
| 126 | void fix_range_common(struct mm_struct *mm, unsigned long start_addr, | 126 | void fix_range_common(struct mm_struct *mm, unsigned long start_addr, |
| 127 | unsigned long end_addr, int force, | 127 | unsigned long end_addr, int force, |
| 128 | int (*do_ops)(union mm_context *, struct host_vm_op *, | 128 | int (*do_ops)(union mm_context *, struct host_vm_op *, |
| 129 | int, int, void **)) | 129 | int, int, void **)) |
| 130 | { | 130 | { |
| 131 | pgd_t *npgd; | 131 | pgd_t *npgd; |
| 132 | pud_t *npud; | 132 | pud_t *npud; |
| 133 | pmd_t *npmd; | 133 | pmd_t *npmd; |
| 134 | pte_t *npte; | 134 | pte_t *npte; |
| 135 | union mm_context *mmu = &mm->context; | 135 | union mm_context *mmu = &mm->context; |
| 136 | unsigned long addr, end; | 136 | unsigned long addr, end; |
| 137 | int r, w, x; | 137 | int r, w, x; |
| 138 | struct host_vm_op ops[1]; | 138 | struct host_vm_op ops[1]; |
| 139 | void *flush = NULL; | 139 | void *flush = NULL; |
| 140 | int op_index = -1, last_op = sizeof(ops) / sizeof(ops[0]) - 1; | 140 | int op_index = -1, last_op = ARRAY_SIZE(ops) - 1; |
| 141 | int ret = 0; | 141 | int ret = 0; |
| 142 | 142 | ||
| 143 | if(mm == NULL) return; | 143 | if(mm == NULL) |
| 144 | 144 | return; | |
| 145 | ops[0].type = NONE; | 145 | |
| 146 | for(addr = start_addr; addr < end_addr && !ret;){ | 146 | ops[0].type = NONE; |
| 147 | npgd = pgd_offset(mm, addr); | 147 | for(addr = start_addr; addr < end_addr && !ret;){ |
| 148 | if(!pgd_present(*npgd)){ | 148 | npgd = pgd_offset(mm, addr); |
| 149 | end = ADD_ROUND(addr, PGDIR_SIZE); | 149 | if(!pgd_present(*npgd)){ |
| 150 | if(end > end_addr) | 150 | end = ADD_ROUND(addr, PGDIR_SIZE); |
| 151 | end = end_addr; | 151 | if(end > end_addr) |
| 152 | if(force || pgd_newpage(*npgd)){ | 152 | end = end_addr; |
| 153 | ret = add_munmap(addr, end - addr, ops, | 153 | if(force || pgd_newpage(*npgd)){ |
| 154 | &op_index, last_op, mmu, | 154 | ret = add_munmap(addr, end - addr, ops, |
| 155 | &flush, do_ops); | 155 | &op_index, last_op, mmu, |
| 156 | pgd_mkuptodate(*npgd); | 156 | &flush, do_ops); |
| 157 | } | 157 | pgd_mkuptodate(*npgd); |
| 158 | addr = end; | 158 | } |
| 159 | continue; | 159 | addr = end; |
| 160 | } | 160 | continue; |
| 161 | 161 | } | |
| 162 | npud = pud_offset(npgd, addr); | 162 | |
| 163 | if(!pud_present(*npud)){ | 163 | npud = pud_offset(npgd, addr); |
| 164 | end = ADD_ROUND(addr, PUD_SIZE); | 164 | if(!pud_present(*npud)){ |
| 165 | if(end > end_addr) | 165 | end = ADD_ROUND(addr, PUD_SIZE); |
| 166 | end = end_addr; | 166 | if(end > end_addr) |
| 167 | if(force || pud_newpage(*npud)){ | 167 | end = end_addr; |
| 168 | ret = add_munmap(addr, end - addr, ops, | 168 | if(force || pud_newpage(*npud)){ |
| 169 | &op_index, last_op, mmu, | 169 | ret = add_munmap(addr, end - addr, ops, |
| 170 | &flush, do_ops); | 170 | &op_index, last_op, mmu, |
| 171 | pud_mkuptodate(*npud); | 171 | &flush, do_ops); |
| 172 | } | 172 | pud_mkuptodate(*npud); |
| 173 | addr = end; | 173 | } |
| 174 | continue; | 174 | addr = end; |
| 175 | } | 175 | continue; |
| 176 | 176 | } | |
| 177 | npmd = pmd_offset(npud, addr); | 177 | |
| 178 | if(!pmd_present(*npmd)){ | 178 | npmd = pmd_offset(npud, addr); |
| 179 | end = ADD_ROUND(addr, PMD_SIZE); | 179 | if(!pmd_present(*npmd)){ |
| 180 | if(end > end_addr) | 180 | end = ADD_ROUND(addr, PMD_SIZE); |
| 181 | end = end_addr; | 181 | if(end > end_addr) |
| 182 | if(force || pmd_newpage(*npmd)){ | 182 | end = end_addr; |
| 183 | ret = add_munmap(addr, end - addr, ops, | 183 | if(force || pmd_newpage(*npmd)){ |
| 184 | &op_index, last_op, mmu, | 184 | ret = add_munmap(addr, end - addr, ops, |
| 185 | &flush, do_ops); | 185 | &op_index, last_op, mmu, |
| 186 | pmd_mkuptodate(*npmd); | 186 | &flush, do_ops); |
| 187 | } | 187 | pmd_mkuptodate(*npmd); |
| 188 | addr = end; | 188 | } |
| 189 | continue; | 189 | addr = end; |
| 190 | } | 190 | continue; |
| 191 | 191 | } | |
| 192 | npte = pte_offset_kernel(npmd, addr); | 192 | |
| 193 | r = pte_read(*npte); | 193 | npte = pte_offset_kernel(npmd, addr); |
| 194 | w = pte_write(*npte); | 194 | r = pte_read(*npte); |
| 195 | x = pte_exec(*npte); | 195 | w = pte_write(*npte); |
| 196 | x = pte_exec(*npte); | ||
| 196 | if (!pte_young(*npte)) { | 197 | if (!pte_young(*npte)) { |
| 197 | r = 0; | 198 | r = 0; |
| 198 | w = 0; | 199 | w = 0; |
| 199 | } else if (!pte_dirty(*npte)) { | 200 | } else if (!pte_dirty(*npte)) { |
| 200 | w = 0; | 201 | w = 0; |
| 201 | } | 202 | } |
| 202 | if(force || pte_newpage(*npte)){ | 203 | if(force || pte_newpage(*npte)){ |
| 203 | if(pte_present(*npte)) | 204 | if(pte_present(*npte)) |
| 204 | ret = add_mmap(addr, | 205 | ret = add_mmap(addr, |
| 205 | pte_val(*npte) & PAGE_MASK, | 206 | pte_val(*npte) & PAGE_MASK, |
| 206 | PAGE_SIZE, r, w, x, ops, | 207 | PAGE_SIZE, r, w, x, ops, |
| 207 | &op_index, last_op, mmu, | 208 | &op_index, last_op, mmu, |
| 208 | &flush, do_ops); | 209 | &flush, do_ops); |
| 209 | else ret = add_munmap(addr, PAGE_SIZE, ops, | 210 | else ret = add_munmap(addr, PAGE_SIZE, ops, |
| 210 | &op_index, last_op, mmu, | 211 | &op_index, last_op, mmu, |
| 211 | &flush, do_ops); | 212 | &flush, do_ops); |
| 212 | } | 213 | } |
| 213 | else if(pte_newprot(*npte)) | 214 | else if(pte_newprot(*npte)) |
| 214 | ret = add_mprotect(addr, PAGE_SIZE, r, w, x, ops, | 215 | ret = add_mprotect(addr, PAGE_SIZE, r, w, x, ops, |
| 215 | &op_index, last_op, mmu, | 216 | &op_index, last_op, mmu, |
| 216 | &flush, do_ops); | 217 | &flush, do_ops); |
| 217 | 218 | ||
| 218 | *npte = pte_mkuptodate(*npte); | 219 | *npte = pte_mkuptodate(*npte); |
| 219 | addr += PAGE_SIZE; | 220 | addr += PAGE_SIZE; |
| 220 | } | 221 | } |
| 221 | |||
| 222 | if(!ret) | 222 | if(!ret) |
| 223 | ret = (*do_ops)(mmu, ops, op_index, 1, &flush); | 223 | ret = (*do_ops)(mmu, ops, op_index, 1, &flush); |
| 224 | 224 | ||
| 225 | /* This is not an else because ret is modified above */ | 225 | /* This is not an else because ret is modified above */ |
| 226 | if(ret) { | 226 | if(ret) { |
| 227 | printk("fix_range_common: failed, killing current process\n"); | 227 | printk("fix_range_common: failed, killing current process\n"); |
| 228 | force_sig(SIGKILL, current); | 228 | force_sig(SIGKILL, current); |
| @@ -231,160 +231,160 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr, | |||
| 231 | 231 | ||
| 232 | int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) | 232 | int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) |
| 233 | { | 233 | { |
| 234 | struct mm_struct *mm; | 234 | struct mm_struct *mm; |
| 235 | pgd_t *pgd; | 235 | pgd_t *pgd; |
| 236 | pud_t *pud; | 236 | pud_t *pud; |
| 237 | pmd_t *pmd; | 237 | pmd_t *pmd; |
| 238 | pte_t *pte; | 238 | pte_t *pte; |
| 239 | unsigned long addr, last; | 239 | unsigned long addr, last; |
| 240 | int updated = 0, err; | 240 | int updated = 0, err; |
| 241 | 241 | ||
| 242 | mm = &init_mm; | 242 | mm = &init_mm; |
| 243 | for(addr = start; addr < end;){ | 243 | for(addr = start; addr < end;){ |
| 244 | pgd = pgd_offset(mm, addr); | 244 | pgd = pgd_offset(mm, addr); |
| 245 | if(!pgd_present(*pgd)){ | 245 | if(!pgd_present(*pgd)){ |
| 246 | last = ADD_ROUND(addr, PGDIR_SIZE); | 246 | last = ADD_ROUND(addr, PGDIR_SIZE); |
| 247 | if(last > end) | 247 | if(last > end) |
| 248 | last = end; | 248 | last = end; |
| 249 | if(pgd_newpage(*pgd)){ | 249 | if(pgd_newpage(*pgd)){ |
| 250 | updated = 1; | 250 | updated = 1; |
| 251 | err = os_unmap_memory((void *) addr, | 251 | err = os_unmap_memory((void *) addr, |
| 252 | last - addr); | 252 | last - addr); |
| 253 | if(err < 0) | 253 | if(err < 0) |
| 254 | panic("munmap failed, errno = %d\n", | 254 | panic("munmap failed, errno = %d\n", |
| 255 | -err); | 255 | -err); |
| 256 | } | 256 | } |
| 257 | addr = last; | 257 | addr = last; |
| 258 | continue; | 258 | continue; |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | pud = pud_offset(pgd, addr); | 261 | pud = pud_offset(pgd, addr); |
| 262 | if(!pud_present(*pud)){ | 262 | if(!pud_present(*pud)){ |
| 263 | last = ADD_ROUND(addr, PUD_SIZE); | 263 | last = ADD_ROUND(addr, PUD_SIZE); |
| 264 | if(last > end) | 264 | if(last > end) |
| 265 | last = end; | 265 | last = end; |
| 266 | if(pud_newpage(*pud)){ | 266 | if(pud_newpage(*pud)){ |
| 267 | updated = 1; | 267 | updated = 1; |
| 268 | err = os_unmap_memory((void *) addr, | 268 | err = os_unmap_memory((void *) addr, |
| 269 | last - addr); | 269 | last - addr); |
| 270 | if(err < 0) | 270 | if(err < 0) |
| 271 | panic("munmap failed, errno = %d\n", | 271 | panic("munmap failed, errno = %d\n", |
| 272 | -err); | 272 | -err); |
| 273 | } | 273 | } |
| 274 | addr = last; | 274 | addr = last; |
| 275 | continue; | 275 | continue; |
| 276 | } | 276 | } |
| 277 | 277 | ||
| 278 | pmd = pmd_offset(pud, addr); | 278 | pmd = pmd_offset(pud, addr); |
| 279 | if(!pmd_present(*pmd)){ | 279 | if(!pmd_present(*pmd)){ |
| 280 | last = ADD_ROUND(addr, PMD_SIZE); | 280 | last = ADD_ROUND(addr, PMD_SIZE); |
| 281 | if(last > end) | 281 | if(last > end) |
| 282 | last = end; | 282 | last = end; |
| 283 | if(pmd_newpage(*pmd)){ | 283 | if(pmd_newpage(*pmd)){ |
| 284 | updated = 1; | 284 | updated = 1; |
| 285 | err = os_unmap_memory((void *) addr, | 285 | err = os_unmap_memory((void *) addr, |
| 286 | last - addr); | 286 | last - addr); |
| 287 | if(err < 0) | 287 | if(err < 0) |
| 288 | panic("munmap failed, errno = %d\n", | 288 | panic("munmap failed, errno = %d\n", |
| 289 | -err); | 289 | -err); |
| 290 | } | 290 | } |
| 291 | addr = last; | 291 | addr = last; |
| 292 | continue; | 292 | continue; |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | pte = pte_offset_kernel(pmd, addr); | 295 | pte = pte_offset_kernel(pmd, addr); |
| 296 | if(!pte_present(*pte) || pte_newpage(*pte)){ | 296 | if(!pte_present(*pte) || pte_newpage(*pte)){ |
| 297 | updated = 1; | 297 | updated = 1; |
| 298 | err = os_unmap_memory((void *) addr, | 298 | err = os_unmap_memory((void *) addr, |
| 299 | PAGE_SIZE); | 299 | PAGE_SIZE); |
| 300 | if(err < 0) | 300 | if(err < 0) |
| 301 | panic("munmap failed, errno = %d\n", | 301 | panic("munmap failed, errno = %d\n", |
| 302 | -err); | 302 | -err); |
| 303 | if(pte_present(*pte)) | 303 | if(pte_present(*pte)) |
| 304 | map_memory(addr, | 304 | map_memory(addr, |
| 305 | pte_val(*pte) & PAGE_MASK, | 305 | pte_val(*pte) & PAGE_MASK, |
| 306 | PAGE_SIZE, 1, 1, 1); | 306 | PAGE_SIZE, 1, 1, 1); |
| 307 | } | 307 | } |
| 308 | else if(pte_newprot(*pte)){ | 308 | else if(pte_newprot(*pte)){ |
| 309 | updated = 1; | 309 | updated = 1; |
| 310 | os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1); | 310 | os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1); |
| 311 | } | 311 | } |
| 312 | addr += PAGE_SIZE; | 312 | addr += PAGE_SIZE; |
| 313 | } | 313 | } |
| 314 | return(updated); | 314 | return(updated); |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) | 317 | pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) |
| 318 | { | 318 | { |
| 319 | return(pgd_offset(mm, address)); | 319 | return(pgd_offset(mm, address)); |
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address) | 322 | pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address) |
| 323 | { | 323 | { |
| 324 | return(pud_offset(pgd, address)); | 324 | return(pud_offset(pgd, address)); |
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address) | 327 | pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address) |
| 328 | { | 328 | { |
| 329 | return(pmd_offset(pud, address)); | 329 | return(pmd_offset(pud, address)); |
| 330 | } | 330 | } |
| 331 | 331 | ||
| 332 | pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) | 332 | pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) |
| 333 | { | 333 | { |
| 334 | return(pte_offset_kernel(pmd, address)); | 334 | return(pte_offset_kernel(pmd, address)); |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | pte_t *addr_pte(struct task_struct *task, unsigned long addr) | 337 | pte_t *addr_pte(struct task_struct *task, unsigned long addr) |
| 338 | { | 338 | { |
| 339 | pgd_t *pgd = pgd_offset(task->mm, addr); | 339 | pgd_t *pgd = pgd_offset(task->mm, addr); |
| 340 | pud_t *pud = pud_offset(pgd, addr); | 340 | pud_t *pud = pud_offset(pgd, addr); |
| 341 | pmd_t *pmd = pmd_offset(pud, addr); | 341 | pmd_t *pmd = pmd_offset(pud, addr); |
| 342 | 342 | ||
| 343 | return(pte_offset_map(pmd, addr)); | 343 | return(pte_offset_map(pmd, addr)); |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) | 346 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) |
| 347 | { | 347 | { |
| 348 | address &= PAGE_MASK; | 348 | address &= PAGE_MASK; |
| 349 | flush_tlb_range(vma, address, address + PAGE_SIZE); | 349 | flush_tlb_range(vma, address, address + PAGE_SIZE); |
| 350 | } | 350 | } |
| 351 | 351 | ||
| 352 | void flush_tlb_all(void) | 352 | void flush_tlb_all(void) |
| 353 | { | 353 | { |
| 354 | flush_tlb_mm(current->mm); | 354 | flush_tlb_mm(current->mm); |
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | void flush_tlb_kernel_range(unsigned long start, unsigned long end) | 357 | void flush_tlb_kernel_range(unsigned long start, unsigned long end) |
| 358 | { | 358 | { |
| 359 | CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt, | 359 | CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt, |
| 360 | flush_tlb_kernel_range_common, start, end); | 360 | flush_tlb_kernel_range_common, start, end); |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | void flush_tlb_kernel_vm(void) | 363 | void flush_tlb_kernel_vm(void) |
| 364 | { | 364 | { |
| 365 | CHOOSE_MODE(flush_tlb_kernel_vm_tt(), | 365 | CHOOSE_MODE(flush_tlb_kernel_vm_tt(), |
| 366 | flush_tlb_kernel_range_common(start_vm, end_vm)); | 366 | flush_tlb_kernel_range_common(start_vm, end_vm)); |
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | void __flush_tlb_one(unsigned long addr) | 369 | void __flush_tlb_one(unsigned long addr) |
| 370 | { | 370 | { |
| 371 | CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr); | 371 | CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr); |
| 372 | } | 372 | } |
| 373 | 373 | ||
| 374 | void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | 374 | void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, |
| 375 | unsigned long end) | 375 | unsigned long end) |
| 376 | { | 376 | { |
| 377 | CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start, | 377 | CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start, |
| 378 | end); | 378 | end); |
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | void flush_tlb_mm(struct mm_struct *mm) | 381 | void flush_tlb_mm(struct mm_struct *mm) |
| 382 | { | 382 | { |
| 383 | CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm); | 383 | CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm); |
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | void force_flush_all(void) | 386 | void force_flush_all(void) |
| 387 | { | 387 | { |
| 388 | CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas()); | 388 | CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas()); |
| 389 | } | 389 | } |
| 390 | 390 | ||
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index ac70fa5a2e2a..61a23fff4395 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c | |||
| @@ -140,14 +140,6 @@ void segv_handler(int sig, union uml_pt_regs *regs) | |||
| 140 | segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs); | 140 | segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | struct kern_handlers handlinfo_kern = { | ||
| 144 | .relay_signal = relay_signal, | ||
| 145 | .winch = winch, | ||
| 146 | .bus_handler = relay_signal, | ||
| 147 | .page_fault = segv_handler, | ||
| 148 | .sigio_handler = sigio_handler, | ||
| 149 | .timer_handler = timer_handler | ||
| 150 | }; | ||
| 151 | /* | 143 | /* |
| 152 | * We give a *copy* of the faultinfo in the regs to segv. | 144 | * We give a *copy* of the faultinfo in the regs to segv. |
| 153 | * This must be done, since nesting SEGVs could overwrite | 145 | * This must be done, since nesting SEGVs could overwrite |
| @@ -227,9 +219,16 @@ void bad_segv(struct faultinfo fi, unsigned long ip) | |||
| 227 | 219 | ||
| 228 | void relay_signal(int sig, union uml_pt_regs *regs) | 220 | void relay_signal(int sig, union uml_pt_regs *regs) |
| 229 | { | 221 | { |
| 230 | if(arch_handle_signal(sig, regs)) return; | 222 | if(arch_handle_signal(sig, regs)) |
| 231 | if(!UPT_IS_USER(regs)) | 223 | return; |
| 224 | |||
| 225 | if(!UPT_IS_USER(regs)){ | ||
| 226 | if(sig == SIGBUS) | ||
| 227 | printk("Bus error - the /dev/shm or /tmp mount likely " | ||
| 228 | "just ran out of space\n"); | ||
| 232 | panic("Kernel mode signal %d", sig); | 229 | panic("Kernel mode signal %d", sig); |
| 230 | } | ||
| 231 | |||
| 233 | current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); | 232 | current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); |
| 234 | force_sig(sig, current); | 233 | force_sig(sig, current); |
| 235 | } | 234 | } |
| @@ -246,6 +245,15 @@ void winch(int sig, union uml_pt_regs *regs) | |||
| 246 | do_IRQ(WINCH_IRQ, regs); | 245 | do_IRQ(WINCH_IRQ, regs); |
| 247 | } | 246 | } |
| 248 | 247 | ||
| 248 | const struct kern_handlers handlinfo_kern = { | ||
| 249 | .relay_signal = relay_signal, | ||
| 250 | .winch = winch, | ||
| 251 | .bus_handler = bus_handler, | ||
| 252 | .page_fault = segv_handler, | ||
| 253 | .sigio_handler = sigio_handler, | ||
| 254 | .timer_handler = timer_handler | ||
| 255 | }; | ||
| 256 | |||
| 249 | void trap_init(void) | 257 | void trap_init(void) |
| 250 | { | 258 | { |
| 251 | } | 259 | } |
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 7896cf98232d..55005710dcbb 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c | |||
| @@ -106,7 +106,7 @@ static void c_stop(struct seq_file *m, void *v) | |||
| 106 | { | 106 | { |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | struct seq_operations cpuinfo_op = { | 109 | const struct seq_operations cpuinfo_op = { |
| 110 | .start = c_start, | 110 | .start = c_start, |
| 111 | .next = c_next, | 111 | .next = c_next, |
| 112 | .stop = c_stop, | 112 | .stop = c_stop, |
