aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/exec.c2
-rw-r--r--arch/um/kernel/init_task.c1
-rw-r--r--arch/um/kernel/initrd.c33
-rw-r--r--arch/um/kernel/irq.c16
-rw-r--r--arch/um/kernel/ksyms.c2
-rw-r--r--arch/um/kernel/mem.c4
-rw-r--r--arch/um/kernel/physmem.c230
-rw-r--r--arch/um/kernel/process.c125
-rw-r--r--arch/um/kernel/reboot.c1
-rw-r--r--arch/um/kernel/signal.c1
-rw-r--r--arch/um/kernel/skas/exec.c12
-rw-r--r--arch/um/kernel/skas/process.c2
-rw-r--r--arch/um/kernel/skas/tlb.c87
-rw-r--r--arch/um/kernel/smp.c28
-rw-r--r--arch/um/kernel/syscall.c1
-rw-r--r--arch/um/kernel/sysrq.c1
-rw-r--r--arch/um/kernel/time.c15
-rw-r--r--arch/um/kernel/tlb.c226
-rw-r--r--arch/um/kernel/trap.c50
-rw-r--r--arch/um/kernel/tt/exec_kern.c1
-rw-r--r--arch/um/kernel/tt/exec_user.c1
-rw-r--r--arch/um/kernel/tt/gdb.c3
-rw-r--r--arch/um/kernel/tt/include/mode_kern-tt.h52
-rw-r--r--arch/um/kernel/tt/mem.c1
-rw-r--r--arch/um/kernel/tt/mem_user.c1
-rw-r--r--arch/um/kernel/tt/process_kern.c4
-rw-r--r--arch/um/kernel/tt/ptproxy/proxy.c6
-rw-r--r--arch/um/kernel/tt/ptproxy/ptrace.c1
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.c1
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.c1
-rw-r--r--arch/um/kernel/tt/syscall_user.c1
-rw-r--r--arch/um/kernel/tt/tlb.c1
-rw-r--r--arch/um/kernel/tt/tracer.c1
-rw-r--r--arch/um/kernel/tt/trap_user.c1
-rw-r--r--arch/um/kernel/tt/uaccess_user.c1
-rw-r--r--arch/um/kernel/um_arch.c84
36 files changed, 385 insertions, 613 deletions
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 121166400e25..356e50f5aaed 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -10,8 +10,8 @@
10#include "asm/pgtable.h" 10#include "asm/pgtable.h"
11#include "asm/tlbflush.h" 11#include "asm/tlbflush.h"
12#include "asm/uaccess.h" 12#include "asm/uaccess.h"
13#include "user_util.h"
14#include "kern_util.h" 13#include "kern_util.h"
14#include "as-layout.h"
15#include "mem_user.h" 15#include "mem_user.h"
16#include "kern.h" 16#include "kern.h"
17#include "irq_user.h" 17#include "irq_user.h"
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
index 8cde431348cc..cda91aa8e703 100644
--- a/arch/um/kernel/init_task.c
+++ b/arch/um/kernel/init_task.c
@@ -10,7 +10,6 @@
10#include "linux/mqueue.h" 10#include "linux/mqueue.h"
11#include "asm/uaccess.h" 11#include "asm/uaccess.h"
12#include "asm/pgtable.h" 12#include "asm/pgtable.h"
13#include "user_util.h"
14#include "mem_user.h" 13#include "mem_user.h"
15#include "os.h" 14#include "os.h"
16 15
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
index 82ecf904b09c..16dc43e9d940 100644
--- a/arch/um/kernel/initrd.c
+++ b/arch/um/kernel/initrd.c
@@ -7,7 +7,6 @@
7#include "linux/bootmem.h" 7#include "linux/bootmem.h"
8#include "linux/initrd.h" 8#include "linux/initrd.h"
9#include "asm/types.h" 9#include "asm/types.h"
10#include "user_util.h"
11#include "kern_util.h" 10#include "kern_util.h"
12#include "initrd.h" 11#include "initrd.h"
13#include "init.h" 12#include "init.h"
@@ -22,12 +21,20 @@ static int __init read_initrd(void)
22 long long size; 21 long long size;
23 int err; 22 int err;
24 23
25 if(initrd == NULL) return 0; 24 if(initrd == NULL)
25 return 0;
26
26 err = os_file_size(initrd, &size); 27 err = os_file_size(initrd, &size);
27 if(err) return 0; 28 if(err)
29 return 0;
30
28 area = alloc_bootmem(size); 31 area = alloc_bootmem(size);
29 if(area == NULL) return 0; 32 if(area == NULL)
30 if(load_initrd(initrd, area, size) == -1) return 0; 33 return 0;
34
35 if(load_initrd(initrd, area, size) == -1)
36 return 0;
37
31 initrd_start = (unsigned long) area; 38 initrd_start = (unsigned long) area;
32 initrd_end = initrd_start + size; 39 initrd_end = initrd_start + size;
33 return 0; 40 return 0;
@@ -54,25 +61,15 @@ int load_initrd(char *filename, void *buf, int size)
54 fd = os_open_file(filename, of_read(OPENFLAGS()), 0); 61 fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
55 if(fd < 0){ 62 if(fd < 0){
56 printk("Opening '%s' failed - err = %d\n", filename, -fd); 63 printk("Opening '%s' failed - err = %d\n", filename, -fd);
57 return(-1); 64 return -1;
58 } 65 }
59 n = os_read_file(fd, buf, size); 66 n = os_read_file(fd, buf, size);
60 if(n != size){ 67 if(n != size){
61 printk("Read of %d bytes from '%s' failed, err = %d\n", size, 68 printk("Read of %d bytes from '%s' failed, err = %d\n", size,
62 filename, -n); 69 filename, -n);
63 return(-1); 70 return -1;
64 } 71 }
65 72
66 os_close_file(fd); 73 os_close_file(fd);
67 return(0); 74 return 0;
68} 75}
69/*
70 * Overrides for Emacs so that we follow Linus's tabbing style.
71 * Emacs will notice this stuff at the end of the file and automatically
72 * adjust the settings for this buffer only. This must remain at the end
73 * of the file.
74 * ---------------------------------------------------------------------------
75 * Local variables:
76 * c-file-style: "linux"
77 * End:
78 */
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index dbf2f5bc842f..8f2ed3690315 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -25,7 +25,6 @@
25#include "asm/system.h" 25#include "asm/system.h"
26#include "asm/errno.h" 26#include "asm/errno.h"
27#include "asm/uaccess.h" 27#include "asm/uaccess.h"
28#include "user_util.h"
29#include "kern_util.h" 28#include "kern_util.h"
30#include "irq_user.h" 29#include "irq_user.h"
31#include "irq_kern.h" 30#include "irq_kern.h"
@@ -79,6 +78,14 @@ skip:
79 return 0; 78 return 0;
80} 79}
81 80
81/*
82 * This list is accessed under irq_lock, except in sigio_handler,
83 * where it is safe from being modified. IRQ handlers won't change it -
84 * if an IRQ source has vanished, it will be freed by free_irqs just
85 * before returning from sigio_handler. That will process a separate
86 * list of irqs to free, with its own locking, coming back here to
87 * remove list elements, taking the irq_lock to do so.
88 */
82static struct irq_fd *active_fds = NULL; 89static struct irq_fd *active_fds = NULL;
83static struct irq_fd **last_irq_ptr = &active_fds; 90static struct irq_fd **last_irq_ptr = &active_fds;
84 91
@@ -244,6 +251,7 @@ void free_irq_by_fd(int fd)
244 free_irq_by_cb(same_fd, &fd); 251 free_irq_by_cb(same_fd, &fd);
245} 252}
246 253
254/* Must be called with irq_lock held */
247static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) 255static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
248{ 256{
249 struct irq_fd *irq; 257 struct irq_fd *irq;
@@ -309,6 +317,12 @@ void deactivate_fd(int fd, int irqnum)
309 ignore_sigio_fd(fd); 317 ignore_sigio_fd(fd);
310} 318}
311 319
320/*
321 * Called just before shutdown in order to provide a clean exec
322 * environment in case the system is rebooting. No locking because
323 * that would cause a pointless shutdown hang if something hadn't
324 * released the lock.
325 */
312int deactivate_all_fds(void) 326int deactivate_all_fds(void)
313{ 327{
314 struct irq_fd *irq; 328 struct irq_fd *irq;
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 0e00cf93f900..7b3e53fb8070 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -16,7 +16,7 @@
16#include "asm/page.h" 16#include "asm/page.h"
17#include "asm/tlbflush.h" 17#include "asm/tlbflush.h"
18#include "kern_util.h" 18#include "kern_util.h"
19#include "user_util.h" 19#include "as-layout.h"
20#include "mem_user.h" 20#include "mem_user.h"
21#include "os.h" 21#include "os.h"
22 22
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index df7d662b98ce..72ff85693a39 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -13,8 +13,8 @@
13#include "asm/page.h" 13#include "asm/page.h"
14#include "asm/fixmap.h" 14#include "asm/fixmap.h"
15#include "asm/pgalloc.h" 15#include "asm/pgalloc.h"
16#include "user_util.h"
17#include "kern_util.h" 16#include "kern_util.h"
17#include "as-layout.h"
18#include "kern.h" 18#include "kern.h"
19#include "mem_user.h" 19#include "mem_user.h"
20#include "uml_uaccess.h" 20#include "uml_uaccess.h"
@@ -216,7 +216,7 @@ static void __init fixaddr_user_init( void)
216#endif 216#endif
217} 217}
218 218
219void paging_init(void) 219void __init paging_init(void)
220{ 220{
221 unsigned long zones_size[MAX_NR_ZONES], vaddr; 221 unsigned long zones_size[MAX_NR_ZONES], vaddr;
222 int i; 222 int i;
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index 638f3b5f6094..3ba6e4c841da 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -13,7 +13,7 @@
13#include "asm/types.h" 13#include "asm/types.h"
14#include "asm/pgtable.h" 14#include "asm/pgtable.h"
15#include "kern_util.h" 15#include "kern_util.h"
16#include "user_util.h" 16#include "as-layout.h"
17#include "mode_kern.h" 17#include "mode_kern.h"
18#include "mem.h" 18#include "mem.h"
19#include "mem_user.h" 19#include "mem_user.h"
@@ -21,229 +21,8 @@
21#include "kern.h" 21#include "kern.h"
22#include "init.h" 22#include "init.h"
23 23
24struct phys_desc {
25 struct rb_node rb;
26 int fd;
27 __u64 offset;
28 void *virt;
29 unsigned long phys;
30 struct list_head list;
31};
32
33static struct rb_root phys_mappings = RB_ROOT;
34
35static struct rb_node **find_rb(void *virt)
36{
37 struct rb_node **n = &phys_mappings.rb_node;
38 struct phys_desc *d;
39
40 while(*n != NULL){
41 d = rb_entry(*n, struct phys_desc, rb);
42 if(d->virt == virt)
43 return n;
44
45 if(d->virt > virt)
46 n = &(*n)->rb_left;
47 else
48 n = &(*n)->rb_right;
49 }
50
51 return n;
52}
53
54static struct phys_desc *find_phys_mapping(void *virt)
55{
56 struct rb_node **n = find_rb(virt);
57
58 if(*n == NULL)
59 return NULL;
60
61 return rb_entry(*n, struct phys_desc, rb);
62}
63
64static void insert_phys_mapping(struct phys_desc *desc)
65{
66 struct rb_node **n = find_rb(desc->virt);
67
68 if(*n != NULL)
69 panic("Physical remapping for %p already present",
70 desc->virt);
71
72 rb_link_node(&desc->rb, rb_parent(*n), n);
73 rb_insert_color(&desc->rb, &phys_mappings);
74}
75
76LIST_HEAD(descriptor_mappings);
77
78struct desc_mapping {
79 int fd;
80 struct list_head list;
81 struct list_head pages;
82};
83
84static struct desc_mapping *find_mapping(int fd)
85{
86 struct desc_mapping *desc;
87 struct list_head *ele;
88
89 list_for_each(ele, &descriptor_mappings){
90 desc = list_entry(ele, struct desc_mapping, list);
91 if(desc->fd == fd)
92 return desc;
93 }
94
95 return NULL;
96}
97
98static struct desc_mapping *descriptor_mapping(int fd)
99{
100 struct desc_mapping *desc;
101
102 desc = find_mapping(fd);
103 if(desc != NULL)
104 return desc;
105
106 desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
107 if(desc == NULL)
108 return NULL;
109
110 *desc = ((struct desc_mapping)
111 { .fd = fd,
112 .list = LIST_HEAD_INIT(desc->list),
113 .pages = LIST_HEAD_INIT(desc->pages) });
114 list_add(&desc->list, &descriptor_mappings);
115
116 return desc;
117}
118
119int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
120{
121 struct desc_mapping *fd_maps;
122 struct phys_desc *desc;
123 unsigned long phys;
124 int err;
125
126 fd_maps = descriptor_mapping(fd);
127 if(fd_maps == NULL)
128 return -ENOMEM;
129
130 phys = __pa(virt);
131 desc = find_phys_mapping(virt);
132 if(desc != NULL)
133 panic("Address 0x%p is already substituted\n", virt);
134
135 err = -ENOMEM;
136 desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
137 if(desc == NULL)
138 goto out;
139
140 *desc = ((struct phys_desc)
141 { .fd = fd,
142 .offset = offset,
143 .virt = virt,
144 .phys = __pa(virt),
145 .list = LIST_HEAD_INIT(desc->list) });
146 insert_phys_mapping(desc);
147
148 list_add(&desc->list, &fd_maps->pages);
149
150 virt = (void *) ((unsigned long) virt & PAGE_MASK);
151 err = os_map_memory(virt, fd, offset, PAGE_SIZE, 1, w, 0);
152 if(!err)
153 goto out;
154
155 rb_erase(&desc->rb, &phys_mappings);
156 kfree(desc);
157 out:
158 return err;
159}
160
161static int physmem_fd = -1; 24static int physmem_fd = -1;
162 25
163static void remove_mapping(struct phys_desc *desc)
164{
165 void *virt = desc->virt;
166 int err;
167
168 rb_erase(&desc->rb, &phys_mappings);
169 list_del(&desc->list);
170 kfree(desc);
171
172 err = os_map_memory(virt, physmem_fd, __pa(virt), PAGE_SIZE, 1, 1, 0);
173 if(err)
174 panic("Failed to unmap block device page from physical memory, "
175 "errno = %d", -err);
176}
177
178int physmem_remove_mapping(void *virt)
179{
180 struct phys_desc *desc;
181
182 virt = (void *) ((unsigned long) virt & PAGE_MASK);
183 desc = find_phys_mapping(virt);
184 if(desc == NULL)
185 return 0;
186
187 remove_mapping(desc);
188 return 1;
189}
190
191void physmem_forget_descriptor(int fd)
192{
193 struct desc_mapping *desc;
194 struct phys_desc *page;
195 struct list_head *ele, *next;
196 __u64 offset;
197 void *addr;
198 int err;
199
200 desc = find_mapping(fd);
201 if(desc == NULL)
202 return;
203
204 list_for_each_safe(ele, next, &desc->pages){
205 page = list_entry(ele, struct phys_desc, list);
206 offset = page->offset;
207 addr = page->virt;
208 remove_mapping(page);
209 err = os_seek_file(fd, offset);
210 if(err)
211 panic("physmem_forget_descriptor - failed to seek "
212 "to %lld in fd %d, error = %d\n",
213 offset, fd, -err);
214 err = os_read_file(fd, addr, PAGE_SIZE);
215 if(err < 0)
216 panic("physmem_forget_descriptor - failed to read "
217 "from fd %d to 0x%p, error = %d\n",
218 fd, addr, -err);
219 }
220
221 list_del(&desc->list);
222 kfree(desc);
223}
224
225EXPORT_SYMBOL(physmem_forget_descriptor);
226EXPORT_SYMBOL(physmem_remove_mapping);
227EXPORT_SYMBOL(physmem_subst_mapping);
228
229void arch_free_page(struct page *page, int order)
230{
231 void *virt;
232 int i;
233
234 for(i = 0; i < (1 << order); i++){
235 virt = __va(page_to_phys(page + i));
236 physmem_remove_mapping(virt);
237 }
238}
239
240int is_remapped(void *virt)
241{
242 struct phys_desc *desc = find_phys_mapping(virt);
243
244 return desc != NULL;
245}
246
247/* Changed during early boot */ 26/* Changed during early boot */
248unsigned long high_physmem; 27unsigned long high_physmem;
249 28
@@ -350,14 +129,9 @@ void setup_physmem(unsigned long start, unsigned long reserve_end,
350 129
351int phys_mapping(unsigned long phys, __u64 *offset_out) 130int phys_mapping(unsigned long phys, __u64 *offset_out)
352{ 131{
353 struct phys_desc *desc = find_phys_mapping(__va(phys & PAGE_MASK));
354 int fd = -1; 132 int fd = -1;
355 133
356 if(desc != NULL){ 134 if(phys < physmem_size){
357 fd = desc->fd;
358 *offset_out = desc->offset;
359 }
360 else if(phys < physmem_size){
361 fd = physmem_fd; 135 fd = physmem_fd;
362 *offset_out = phys; 136 *offset_out = phys;
363 } 137 }
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 348b272bb766..8d2c5496532b 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -32,8 +32,8 @@
32#include "asm/tlbflush.h" 32#include "asm/tlbflush.h"
33#include "asm/uaccess.h" 33#include "asm/uaccess.h"
34#include "asm/user.h" 34#include "asm/user.h"
35#include "user_util.h"
36#include "kern_util.h" 35#include "kern_util.h"
36#include "as-layout.h"
37#include "kern.h" 37#include "kern.h"
38#include "signal_kern.h" 38#include "signal_kern.h"
39#include "init.h" 39#include "init.h"
@@ -54,11 +54,9 @@
54 */ 54 */
55struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; 55struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
56 56
57int external_pid(void *t) 57static inline int external_pid(struct task_struct *task)
58{ 58{
59 struct task_struct *task = t ? t : current; 59 return CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task);
60
61 return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task));
62} 60}
63 61
64int pid_to_processor_id(int pid) 62int pid_to_processor_id(int pid)
@@ -66,9 +64,10 @@ int pid_to_processor_id(int pid)
66 int i; 64 int i;
67 65
68 for(i = 0; i < ncpus; i++){ 66 for(i = 0; i < ncpus; i++){
69 if(cpu_tasks[i].pid == pid) return(i); 67 if(cpu_tasks[i].pid == pid)
68 return i;
70 } 69 }
71 return(-1); 70 return -1;
72} 71}
73 72
74void free_stack(unsigned long stack, int order) 73void free_stack(unsigned long stack, int order)
@@ -85,9 +84,9 @@ unsigned long alloc_stack(int order, int atomic)
85 flags = GFP_ATOMIC; 84 flags = GFP_ATOMIC;
86 page = __get_free_pages(flags, order); 85 page = __get_free_pages(flags, order);
87 if(page == 0) 86 if(page == 0)
88 return(0); 87 return 0;
89 stack_protections(page); 88 stack_protections(page);
90 return(page); 89 return page;
91} 90}
92 91
93int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 92int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
@@ -98,15 +97,11 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
98 current->thread.request.u.thread.arg = arg; 97 current->thread.request.u.thread.arg = arg;
99 pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, 98 pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
100 &current->thread.regs, 0, NULL, NULL); 99 &current->thread.regs, 0, NULL, NULL);
101 if(pid < 0) 100 return pid;
102 panic("do_fork failed in kernel_thread, errno = %d", pid);
103 return(pid);
104} 101}
105 102
106void set_current(void *t) 103static inline void set_current(struct task_struct *task)
107{ 104{
108 struct task_struct *task = t;
109
110 cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) 105 cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
111 { external_pid(task), task }); 106 { external_pid(task), task });
112} 107}
@@ -128,14 +123,16 @@ void *_switch_to(void *prev, void *next, void *last)
128 prev= current; 123 prev= current;
129 } while(current->thread.saved_task); 124 } while(current->thread.saved_task);
130 125
131 return(current->thread.prev_sched); 126 return current->thread.prev_sched;
132 127
133} 128}
134 129
135void interrupt_end(void) 130void interrupt_end(void)
136{ 131{
137 if(need_resched()) schedule(); 132 if(need_resched())
138 if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal(); 133 schedule();
134 if(test_tsk_thread_flag(current, TIF_SIGPENDING))
135 do_signal();
139} 136}
140 137
141void release_thread(struct task_struct *task) 138void release_thread(struct task_struct *task)
@@ -150,7 +147,7 @@ void exit_thread(void)
150 147
151void *get_current(void) 148void *get_current(void)
152{ 149{
153 return(current); 150 return current;
154} 151}
155 152
156int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, 153int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
@@ -188,15 +185,12 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
188 kmalloc_ok = save_kmalloc_ok; 185 kmalloc_ok = save_kmalloc_ok;
189} 186}
190 187
188#ifdef CONFIG_MODE_TT
191unsigned long stack_sp(unsigned long page) 189unsigned long stack_sp(unsigned long page)
192{ 190{
193 return(page + PAGE_SIZE - sizeof(void *)); 191 return page + PAGE_SIZE - sizeof(void *);
194}
195
196int current_pid(void)
197{
198 return(current->pid);
199} 192}
193#endif
200 194
201void default_idle(void) 195void default_idle(void)
202{ 196{
@@ -221,11 +215,6 @@ void cpu_idle(void)
221 CHOOSE_MODE(init_idle_tt(), init_idle_skas()); 215 CHOOSE_MODE(init_idle_tt(), init_idle_skas());
222} 216}
223 217
224int page_size(void)
225{
226 return(PAGE_SIZE);
227}
228
229void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 218void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
230 pte_t *pte_out) 219 pte_t *pte_out)
231{ 220{
@@ -236,68 +225,43 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
236 pte_t ptent; 225 pte_t ptent;
237 226
238 if(task->mm == NULL) 227 if(task->mm == NULL)
239 return(ERR_PTR(-EINVAL)); 228 return ERR_PTR(-EINVAL);
240 pgd = pgd_offset(task->mm, addr); 229 pgd = pgd_offset(task->mm, addr);
241 if(!pgd_present(*pgd)) 230 if(!pgd_present(*pgd))
242 return(ERR_PTR(-EINVAL)); 231 return ERR_PTR(-EINVAL);
243 232
244 pud = pud_offset(pgd, addr); 233 pud = pud_offset(pgd, addr);
245 if(!pud_present(*pud)) 234 if(!pud_present(*pud))
246 return(ERR_PTR(-EINVAL)); 235 return ERR_PTR(-EINVAL);
247 236
248 pmd = pmd_offset(pud, addr); 237 pmd = pmd_offset(pud, addr);
249 if(!pmd_present(*pmd)) 238 if(!pmd_present(*pmd))
250 return(ERR_PTR(-EINVAL)); 239 return ERR_PTR(-EINVAL);
251 240
252 pte = pte_offset_kernel(pmd, addr); 241 pte = pte_offset_kernel(pmd, addr);
253 ptent = *pte; 242 ptent = *pte;
254 if(!pte_present(ptent)) 243 if(!pte_present(ptent))
255 return(ERR_PTR(-EINVAL)); 244 return ERR_PTR(-EINVAL);
256 245
257 if(pte_out != NULL) 246 if(pte_out != NULL)
258 *pte_out = ptent; 247 *pte_out = ptent;
259 return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK)); 248 return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK);
260} 249}
261 250
262char *current_cmd(void) 251char *current_cmd(void)
263{ 252{
264#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM) 253#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
265 return("(Unknown)"); 254 return "(Unknown)";
266#else 255#else
267 void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL); 256 void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
268 return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr); 257 return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
269#endif 258#endif
270} 259}
271 260
272void force_sigbus(void)
273{
274 printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
275 current->pid);
276 lock_kernel();
277 sigaddset(&current->pending.signal, SIGBUS);
278 recalc_sigpending();
279 current->flags |= PF_SIGNALED;
280 do_exit(SIGBUS | 0x80);
281}
282
283void dump_thread(struct pt_regs *regs, struct user *u) 261void dump_thread(struct pt_regs *regs, struct user *u)
284{ 262{
285} 263}
286 264
287void enable_hlt(void)
288{
289 panic("enable_hlt");
290}
291
292EXPORT_SYMBOL(enable_hlt);
293
294void disable_hlt(void)
295{
296 panic("disable_hlt");
297}
298
299EXPORT_SYMBOL(disable_hlt);
300
301void *um_kmalloc(int size) 265void *um_kmalloc(int size)
302{ 266{
303 return kmalloc(size, GFP_KERNEL); 267 return kmalloc(size, GFP_KERNEL);
@@ -313,36 +277,17 @@ void *um_vmalloc(int size)
313 return vmalloc(size); 277 return vmalloc(size);
314} 278}
315 279
316void *um_vmalloc_atomic(int size)
317{
318 return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
319}
320
321int __cant_sleep(void) { 280int __cant_sleep(void) {
322 return in_atomic() || irqs_disabled() || in_interrupt(); 281 return in_atomic() || irqs_disabled() || in_interrupt();
323 /* Is in_interrupt() really needed? */ 282 /* Is in_interrupt() really needed? */
324} 283}
325 284
326unsigned long get_fault_addr(void)
327{
328 return((unsigned long) current->thread.fault_addr);
329}
330
331EXPORT_SYMBOL(get_fault_addr);
332
333void not_implemented(void)
334{
335 printk(KERN_DEBUG "Something isn't implemented in here\n");
336}
337
338EXPORT_SYMBOL(not_implemented);
339
340int user_context(unsigned long sp) 285int user_context(unsigned long sp)
341{ 286{
342 unsigned long stack; 287 unsigned long stack;
343 288
344 stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); 289 stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
345 return(stack != (unsigned long) current_thread); 290 return stack != (unsigned long) current_thread;
346} 291}
347 292
348extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; 293extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
@@ -363,22 +308,22 @@ char *uml_strdup(char *string)
363 308
364int copy_to_user_proc(void __user *to, void *from, int size) 309int copy_to_user_proc(void __user *to, void *from, int size)
365{ 310{
366 return(copy_to_user(to, from, size)); 311 return copy_to_user(to, from, size);
367} 312}
368 313
369int copy_from_user_proc(void *to, void __user *from, int size) 314int copy_from_user_proc(void *to, void __user *from, int size)
370{ 315{
371 return(copy_from_user(to, from, size)); 316 return copy_from_user(to, from, size);
372} 317}
373 318
374int clear_user_proc(void __user *buf, int size) 319int clear_user_proc(void __user *buf, int size)
375{ 320{
376 return(clear_user(buf, size)); 321 return clear_user(buf, size);
377} 322}
378 323
379int strlen_user_proc(char __user *str) 324int strlen_user_proc(char __user *str)
380{ 325{
381 return(strlen_user(str)); 326 return strlen_user(str);
382} 327}
383 328
384int smp_sigio_handler(void) 329int smp_sigio_handler(void)
@@ -387,14 +332,14 @@ int smp_sigio_handler(void)
387 int cpu = current_thread->cpu; 332 int cpu = current_thread->cpu;
388 IPI_handler(cpu); 333 IPI_handler(cpu);
389 if(cpu != 0) 334 if(cpu != 0)
390 return(1); 335 return 1;
391#endif 336#endif
392 return(0); 337 return 0;
393} 338}
394 339
395int cpu(void) 340int cpu(void)
396{ 341{
397 return(current_thread->cpu); 342 return current_thread->cpu;
398} 343}
399 344
400static atomic_t using_sysemu = ATOMIC_INIT(0); 345static atomic_t using_sysemu = ATOMIC_INIT(0);
@@ -443,7 +388,7 @@ int __init make_proc_sysemu(void)
443 if (ent == NULL) 388 if (ent == NULL)
444 { 389 {
445 printk(KERN_WARNING "Failed to register /proc/sysemu\n"); 390 printk(KERN_WARNING "Failed to register /proc/sysemu\n");
446 return(0); 391 return 0;
447 } 392 }
448 393
449 ent->read_proc = proc_read_sysemu; 394 ent->read_proc = proc_read_sysemu;
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index f602623644aa..7e4305a1fd3c 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -6,7 +6,6 @@
6#include "linux/module.h" 6#include "linux/module.h"
7#include "linux/sched.h" 7#include "linux/sched.h"
8#include "asm/smp.h" 8#include "asm/smp.h"
9#include "user_util.h"
10#include "kern_util.h" 9#include "kern_util.h"
11#include "kern.h" 10#include "kern.h"
12#include "os.h" 11#include "os.h"
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index 3c798cdde550..c4020c3d7857 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -17,7 +17,6 @@
17#include "asm/signal.h" 17#include "asm/signal.h"
18#include "asm/uaccess.h" 18#include "asm/uaccess.h"
19#include "asm/unistd.h" 19#include "asm/unistd.h"
20#include "user_util.h"
21#include "asm/ucontext.h" 20#include "asm/ucontext.h"
22#include "kern_util.h" 21#include "kern_util.h"
23#include "signal_kern.h" 22#include "signal_kern.h"
diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c
index 54b795951372..580eb6468949 100644
--- a/arch/um/kernel/skas/exec.c
+++ b/arch/um/kernel/skas/exec.c
@@ -17,7 +17,17 @@
17 17
18void flush_thread_skas(void) 18void flush_thread_skas(void)
19{ 19{
20 force_flush_all(); 20 void *data = NULL;
21 unsigned long end = proc_mm ? task_size : CONFIG_STUB_START;
22 int ret;
23
24 ret = unmap(&current->mm->context.skas.id, 0, end, 1, &data);
25 if(ret){
26 printk("flush_thread_skas - clearing address space failed, "
27 "err = %d\n", ret);
28 force_sig(SIGKILL, current);
29 }
30
21 switch_mm_skas(&current->mm->context.skas.id); 31 switch_mm_skas(&current->mm->context.skas.id);
22} 32}
23 33
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index ae4fa71d3b8b..ef36facd8fe9 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -13,9 +13,9 @@
13#include "asm/uaccess.h" 13#include "asm/uaccess.h"
14#include "asm/atomic.h" 14#include "asm/atomic.h"
15#include "kern_util.h" 15#include "kern_util.h"
16#include "as-layout.h"
16#include "skas.h" 17#include "skas.h"
17#include "os.h" 18#include "os.h"
18#include "user_util.h"
19#include "tlb.h" 19#include "tlb.h"
20#include "kern.h" 20#include "kern.h"
21#include "mode.h" 21#include "mode.h"
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c
index 27eb29ce666b..c0f0693743ba 100644
--- a/arch/um/kernel/skas/tlb.c
+++ b/arch/um/kernel/skas/tlb.c
@@ -10,7 +10,6 @@
10#include "asm/page.h" 10#include "asm/page.h"
11#include "asm/pgtable.h" 11#include "asm/pgtable.h"
12#include "asm/mmu.h" 12#include "asm/mmu.h"
13#include "user_util.h"
14#include "mem_user.h" 13#include "mem_user.h"
15#include "mem.h" 14#include "mem.h"
16#include "skas.h" 15#include "skas.h"
@@ -28,19 +27,17 @@ static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last,
28 switch(op->type){ 27 switch(op->type){
29 case MMAP: 28 case MMAP:
30 ret = map(&mmu->skas.id, op->u.mmap.addr, 29 ret = map(&mmu->skas.id, op->u.mmap.addr,
31 op->u.mmap.len, op->u.mmap.r, op->u.mmap.w, 30 op->u.mmap.len, op->u.mmap.prot,
32 op->u.mmap.x, op->u.mmap.fd, 31 op->u.mmap.fd, op->u.mmap.offset, finished,
33 op->u.mmap.offset, finished, flush); 32 flush);
34 break; 33 break;
35 case MUNMAP: 34 case MUNMAP:
36 ret = unmap(&mmu->skas.id, 35 ret = unmap(&mmu->skas.id, op->u.munmap.addr,
37 (void *) op->u.munmap.addr,
38 op->u.munmap.len, finished, flush); 36 op->u.munmap.len, finished, flush);
39 break; 37 break;
40 case MPROTECT: 38 case MPROTECT:
41 ret = protect(&mmu->skas.id, op->u.mprotect.addr, 39 ret = protect(&mmu->skas.id, op->u.mprotect.addr,
42 op->u.mprotect.len, op->u.mprotect.r, 40 op->u.mprotect.len, op->u.mprotect.prot,
43 op->u.mprotect.w, op->u.mprotect.x,
44 finished, flush); 41 finished, flush);
45 break; 42 break;
46 default: 43 default:
@@ -92,6 +89,76 @@ void flush_tlb_mm_skas(struct mm_struct *mm)
92 89
93void force_flush_all_skas(void) 90void force_flush_all_skas(void)
94{ 91{
95 unsigned long end = proc_mm ? task_size : CONFIG_STUB_START; 92 struct mm_struct *mm = current->mm;
96 fix_range(current->mm, 0, end, 1); 93 struct vm_area_struct *vma = mm->mmap;
94
95 while(vma != NULL) {
96 fix_range(mm, vma->vm_start, vma->vm_end, 1);
97 vma = vma->vm_next;
98 }
99}
100
101void flush_tlb_page_skas(struct vm_area_struct *vma, unsigned long address)
102{
103 pgd_t *pgd;
104 pud_t *pud;
105 pmd_t *pmd;
106 pte_t *pte;
107 struct mm_struct *mm = vma->vm_mm;
108 void *flush = NULL;
109 int r, w, x, prot, err = 0;
110 struct mm_id *mm_id;
111
112 pgd = pgd_offset(mm, address);
113 if(!pgd_present(*pgd))
114 goto kill;
115
116 pud = pud_offset(pgd, address);
117 if(!pud_present(*pud))
118 goto kill;
119
120 pmd = pmd_offset(pud, address);
121 if(!pmd_present(*pmd))
122 goto kill;
123
124 pte = pte_offset_kernel(pmd, address);
125
126 r = pte_read(*pte);
127 w = pte_write(*pte);
128 x = pte_exec(*pte);
129 if (!pte_young(*pte)) {
130 r = 0;
131 w = 0;
132 } else if (!pte_dirty(*pte)) {
133 w = 0;
134 }
135
136 mm_id = &mm->context.skas.id;
137 prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
138 (x ? UM_PROT_EXEC : 0));
139 if(pte_newpage(*pte)){
140 if(pte_present(*pte)){
141 unsigned long long offset;
142 int fd;
143
144 fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset);
145 err = map(mm_id, address, PAGE_SIZE, prot, fd, offset,
146 1, &flush);
147 }
148 else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush);
149 }
150 else if(pte_newprot(*pte))
151 err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush);
152
153 if(err)
154 goto kill;
155
156 *pte = pte_mkuptodate(*pte);
157
158 return;
159
160kill:
161 printk("Failed to flush page for address 0x%lx\n", address);
162 force_sig(SIGKILL, current);
97} 163}
164
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index 759b07053160..e6a7778006ad 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -21,7 +21,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
21#include "asm/smp.h" 21#include "asm/smp.h"
22#include "asm/processor.h" 22#include "asm/processor.h"
23#include "asm/spinlock.h" 23#include "asm/spinlock.h"
24#include "user_util.h"
25#include "kern_util.h" 24#include "kern_util.h"
26#include "kern.h" 25#include "kern.h"
27#include "irq_user.h" 26#include "irq_user.h"
@@ -90,7 +89,7 @@ static int idle_proc(void *cpup)
90 89
91 cpu_set(cpu, cpu_online_map); 90 cpu_set(cpu, cpu_online_map);
92 default_idle(); 91 default_idle();
93 return(0); 92 return 0;
94} 93}
95 94
96static struct task_struct *idle_thread(int cpu) 95static struct task_struct *idle_thread(int cpu)
@@ -98,8 +97,8 @@ static struct task_struct *idle_thread(int cpu)
98 struct task_struct *new_task; 97 struct task_struct *new_task;
99 unsigned char c; 98 unsigned char c;
100 99
101 current->thread.request.u.thread.proc = idle_proc; 100 current->thread.request.u.thread.proc = idle_proc;
102 current->thread.request.u.thread.arg = (void *) cpu; 101 current->thread.request.u.thread.arg = (void *) cpu;
103 new_task = fork_idle(cpu); 102 new_task = fork_idle(cpu);
104 if(IS_ERR(new_task)) 103 if(IS_ERR(new_task))
105 panic("copy_process failed in idle_thread, error = %ld", 104 panic("copy_process failed in idle_thread, error = %ld",
@@ -110,9 +109,9 @@ static struct task_struct *idle_thread(int cpu)
110 .task = new_task } ); 109 .task = new_task } );
111 idle_threads[cpu] = new_task; 110 idle_threads[cpu] = new_task;
112 CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c, 111 CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c,
113 sizeof(c)), 112 sizeof(c)),
114 ({ panic("skas mode doesn't support SMP"); })); 113 ({ panic("skas mode doesn't support SMP"); }));
115 return(new_task); 114 return new_task;
116} 115}
117 116
118void smp_prepare_cpus(unsigned int maxcpus) 117void smp_prepare_cpus(unsigned int maxcpus)
@@ -163,13 +162,13 @@ int __cpu_up(unsigned int cpu)
163 cpu_set(cpu, smp_commenced_mask); 162 cpu_set(cpu, smp_commenced_mask);
164 while (!cpu_isset(cpu, cpu_online_map)) 163 while (!cpu_isset(cpu, cpu_online_map))
165 mb(); 164 mb();
166 return(0); 165 return 0;
167} 166}
168 167
169int setup_profiling_timer(unsigned int multiplier) 168int setup_profiling_timer(unsigned int multiplier)
170{ 169{
171 printk(KERN_INFO "setup_profiling_timer\n"); 170 printk(KERN_INFO "setup_profiling_timer\n");
172 return(0); 171 return 0;
173} 172}
174 173
175void smp_call_function_slave(int cpu); 174void smp_call_function_slave(int cpu);
@@ -205,7 +204,7 @@ void IPI_handler(int cpu)
205 204
206int hard_smp_processor_id(void) 205int hard_smp_processor_id(void)
207{ 206{
208 return(pid_to_processor_id(os_getpid())); 207 return pid_to_processor_id(os_getpid());
209} 208}
210 209
211static DEFINE_SPINLOCK(call_lock); 210static DEFINE_SPINLOCK(call_lock);
@@ -254,14 +253,3 @@ int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
254} 253}
255 254
256#endif 255#endif
257
258/*
259 * Overrides for Emacs so that we follow Linus's tabbing style.
260 * Emacs will notice this stuff at the end of the file and automatically
261 * adjust the settings for this buffer only. This must remain at the end
262 * of the file.
263 * ---------------------------------------------------------------------------
264 * Local variables:
265 * c-file-style: "linux"
266 * End:
267 */
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index 2828c5283227..237c4eab7cfd 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -18,7 +18,6 @@
18#include "asm/mman.h" 18#include "asm/mman.h"
19#include "asm/uaccess.h" 19#include "asm/uaccess.h"
20#include "kern_util.h" 20#include "kern_util.h"
21#include "user_util.h"
22#include "sysdep/syscalls.h" 21#include "sysdep/syscalls.h"
23#include "mode_kern.h" 22#include "mode_kern.h"
24#include "choose-mode.h" 23#include "choose-mode.h"
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index f9e02b31a97a..93263571d813 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -10,7 +10,6 @@
10#include "asm/page.h" 10#include "asm/page.h"
11#include "asm/processor.h" 11#include "asm/processor.h"
12#include "sysrq.h" 12#include "sysrq.h"
13#include "user_util.h"
14 13
15/* Catch non-i386 SUBARCH's. */ 14/* Catch non-i386 SUBARCH's. */
16#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT) 15#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index b1f8b0752419..cd7349de8ca6 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -18,7 +18,6 @@
18#include "asm/param.h" 18#include "asm/param.h"
19#include "asm/current.h" 19#include "asm/current.h"
20#include "kern_util.h" 20#include "kern_util.h"
21#include "user_util.h"
22#include "mode.h" 21#include "mode.h"
23#include "os.h" 22#include "os.h"
24 23
@@ -35,8 +34,8 @@ unsigned long long sched_clock(void)
35 return (unsigned long long)jiffies_64 * (1000000000 / HZ); 34 return (unsigned long long)jiffies_64 * (1000000000 / HZ);
36} 35}
37 36
38static unsigned long long prev_nsecs[NR_CPUS];
39#ifdef CONFIG_UML_REAL_TIME_CLOCK 37#ifdef CONFIG_UML_REAL_TIME_CLOCK
38static unsigned long long prev_nsecs[NR_CPUS];
40static long long delta[NR_CPUS]; /* Deviation per interval */ 39static long long delta[NR_CPUS]; /* Deviation per interval */
41#endif 40#endif
42 41
@@ -95,7 +94,12 @@ irqreturn_t um_timer(int irq, void *dev)
95 94
96 do_timer(1); 95 do_timer(1);
97 96
97#ifdef CONFIG_UML_REAL_TIME_CLOCK
98 nsecs = get_time(); 98 nsecs = get_time();
99#else
100 nsecs = (unsigned long long) xtime.tv_sec * BILLION + xtime.tv_nsec +
101 BILLION / HZ;
102#endif
99 xtime.tv_sec = nsecs / NSEC_PER_SEC; 103 xtime.tv_sec = nsecs / NSEC_PER_SEC;
100 xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; 104 xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
101 105
@@ -128,13 +132,18 @@ void time_init(void)
128 nsecs = os_nsecs(); 132 nsecs = os_nsecs();
129 set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, 133 set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION,
130 -nsecs % BILLION); 134 -nsecs % BILLION);
135 set_normalized_timespec(&xtime, nsecs / BILLION, nsecs % BILLION);
131 late_time_init = register_timer; 136 late_time_init = register_timer;
132} 137}
133 138
134void do_gettimeofday(struct timeval *tv) 139void do_gettimeofday(struct timeval *tv)
135{ 140{
141#ifdef CONFIG_UML_REAL_TIME_CLOCK
136 unsigned long long nsecs = get_time(); 142 unsigned long long nsecs = get_time();
137 143#else
144 unsigned long long nsecs = (unsigned long long) xtime.tv_sec * BILLION +
145 xtime.tv_nsec;
146#endif
138 tv->tv_sec = nsecs / NSEC_PER_SEC; 147 tv->tv_sec = nsecs / NSEC_PER_SEC;
139 /* Careful about calculations here - this was originally done as 148 /* Careful about calculations here - this was originally done as
140 * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC 149 * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 54a5ff25645a..8a8d52851443 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -6,17 +6,18 @@
6#include "linux/mm.h" 6#include "linux/mm.h"
7#include "asm/page.h" 7#include "asm/page.h"
8#include "asm/pgalloc.h" 8#include "asm/pgalloc.h"
9#include "asm/pgtable.h"
9#include "asm/tlbflush.h" 10#include "asm/tlbflush.h"
10#include "choose-mode.h" 11#include "choose-mode.h"
11#include "mode_kern.h" 12#include "mode_kern.h"
12#include "user_util.h" 13#include "as-layout.h"
13#include "tlb.h" 14#include "tlb.h"
14#include "mem.h" 15#include "mem.h"
15#include "mem_user.h" 16#include "mem_user.h"
16#include "os.h" 17#include "os.h"
17 18
18static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, 19static 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, 20 unsigned int prot, struct host_vm_op *ops, int *index,
20 int last_filled, union mm_context *mmu, void **flush, 21 int last_filled, union mm_context *mmu, void **flush,
21 int (*do_ops)(union mm_context *, struct host_vm_op *, 22 int (*do_ops)(union mm_context *, struct host_vm_op *,
22 int, int, void **)) 23 int, int, void **))
@@ -30,8 +31,7 @@ static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
30 last = &ops[*index]; 31 last = &ops[*index];
31 if((last->type == MMAP) && 32 if((last->type == MMAP) &&
32 (last->u.mmap.addr + last->u.mmap.len == virt) && 33 (last->u.mmap.addr + last->u.mmap.len == virt) &&
33 (last->u.mmap.r == r) && (last->u.mmap.w == w) && 34 (last->u.mmap.prot == prot) && (last->u.mmap.fd == fd) &&
34 (last->u.mmap.x == x) && (last->u.mmap.fd == fd) &&
35 (last->u.mmap.offset + last->u.mmap.len == offset)){ 35 (last->u.mmap.offset + last->u.mmap.len == offset)){
36 last->u.mmap.len += len; 36 last->u.mmap.len += len;
37 return 0; 37 return 0;
@@ -47,9 +47,7 @@ static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
47 .u = { .mmap = { 47 .u = { .mmap = {
48 .addr = virt, 48 .addr = virt,
49 .len = len, 49 .len = len,
50 .r = r, 50 .prot = prot,
51 .w = w,
52 .x = x,
53 .fd = fd, 51 .fd = fd,
54 .offset = offset } 52 .offset = offset }
55 } }); 53 } });
@@ -86,8 +84,8 @@ static int add_munmap(unsigned long addr, unsigned long len,
86 return ret; 84 return ret;
87} 85}
88 86
89static int add_mprotect(unsigned long addr, unsigned long len, int r, int w, 87static int add_mprotect(unsigned long addr, unsigned long len,
90 int x, struct host_vm_op *ops, int *index, 88 unsigned int prot, struct host_vm_op *ops, int *index,
91 int last_filled, union mm_context *mmu, void **flush, 89 int last_filled, union mm_context *mmu, void **flush,
92 int (*do_ops)(union mm_context *, struct host_vm_op *, 90 int (*do_ops)(union mm_context *, struct host_vm_op *,
93 int, int, void **)) 91 int, int, void **))
@@ -99,8 +97,7 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
99 last = &ops[*index]; 97 last = &ops[*index];
100 if((last->type == MPROTECT) && 98 if((last->type == MPROTECT) &&
101 (last->u.mprotect.addr + last->u.mprotect.len == addr) && 99 (last->u.mprotect.addr + last->u.mprotect.len == addr) &&
102 (last->u.mprotect.r == r) && (last->u.mprotect.w == w) && 100 (last->u.mprotect.prot == prot)){
103 (last->u.mprotect.x == x)){
104 last->u.mprotect.len += len; 101 last->u.mprotect.len += len;
105 return 0; 102 return 0;
106 } 103 }
@@ -115,114 +112,145 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
115 .u = { .mprotect = { 112 .u = { .mprotect = {
116 .addr = addr, 113 .addr = addr,
117 .len = len, 114 .len = len,
118 .r = r, 115 .prot = prot } } });
119 .w = w,
120 .x = x } } });
121 return ret; 116 return ret;
122} 117}
123 118
124#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) 119#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
125 120
121static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
122 unsigned long end, struct host_vm_op *ops,
123 int last_op, int *op_index, int force,
124 union mm_context *mmu, void **flush,
125 int (*do_ops)(union mm_context *,
126 struct host_vm_op *, int, int,
127 void **))
128{
129 pte_t *pte;
130 int r, w, x, prot, ret = 0;
131
132 pte = pte_offset_kernel(pmd, addr);
133 do {
134 r = pte_read(*pte);
135 w = pte_write(*pte);
136 x = pte_exec(*pte);
137 if (!pte_young(*pte)) {
138 r = 0;
139 w = 0;
140 } else if (!pte_dirty(*pte)) {
141 w = 0;
142 }
143 prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
144 (x ? UM_PROT_EXEC : 0));
145 if(force || pte_newpage(*pte)){
146 if(pte_present(*pte))
147 ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
148 PAGE_SIZE, prot, ops, op_index,
149 last_op, mmu, flush, do_ops);
150 else ret = add_munmap(addr, PAGE_SIZE, ops, op_index,
151 last_op, mmu, flush, do_ops);
152 }
153 else if(pte_newprot(*pte))
154 ret = add_mprotect(addr, PAGE_SIZE, prot, ops, op_index,
155 last_op, mmu, flush, do_ops);
156 *pte = pte_mkuptodate(*pte);
157 } while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret));
158 return ret;
159}
160
161static inline int update_pmd_range(pud_t *pud, unsigned long addr,
162 unsigned long end, struct host_vm_op *ops,
163 int last_op, int *op_index, int force,
164 union mm_context *mmu, void **flush,
165 int (*do_ops)(union mm_context *,
166 struct host_vm_op *, int, int,
167 void **))
168{
169 pmd_t *pmd;
170 unsigned long next;
171 int ret = 0;
172
173 pmd = pmd_offset(pud, addr);
174 do {
175 next = pmd_addr_end(addr, end);
176 if(!pmd_present(*pmd)){
177 if(force || pmd_newpage(*pmd)){
178 ret = add_munmap(addr, next - addr, ops,
179 op_index, last_op, mmu,
180 flush, do_ops);
181 pmd_mkuptodate(*pmd);
182 }
183 }
184 else ret = update_pte_range(pmd, addr, next, ops, last_op,
185 op_index, force, mmu, flush,
186 do_ops);
187 } while (pmd++, addr = next, ((addr != end) && !ret));
188 return ret;
189}
190
191static inline int update_pud_range(pgd_t *pgd, unsigned long addr,
192 unsigned long end, struct host_vm_op *ops,
193 int last_op, int *op_index, int force,
194 union mm_context *mmu, void **flush,
195 int (*do_ops)(union mm_context *,
196 struct host_vm_op *, int, int,
197 void **))
198{
199 pud_t *pud;
200 unsigned long next;
201 int ret = 0;
202
203 pud = pud_offset(pgd, addr);
204 do {
205 next = pud_addr_end(addr, end);
206 if(!pud_present(*pud)){
207 if(force || pud_newpage(*pud)){
208 ret = add_munmap(addr, next - addr, ops,
209 op_index, last_op, mmu,
210 flush, do_ops);
211 pud_mkuptodate(*pud);
212 }
213 }
214 else ret = update_pmd_range(pud, addr, next, ops, last_op,
215 op_index, force, mmu, flush,
216 do_ops);
217 } while (pud++, addr = next, ((addr != end) && !ret));
218 return ret;
219}
220
126void fix_range_common(struct mm_struct *mm, unsigned long start_addr, 221void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
127 unsigned long end_addr, int force, 222 unsigned long end_addr, int force,
128 int (*do_ops)(union mm_context *, struct host_vm_op *, 223 int (*do_ops)(union mm_context *, struct host_vm_op *,
129 int, int, void **)) 224 int, int, void **))
130{ 225{
131 pgd_t *npgd; 226 pgd_t *pgd;
132 pud_t *npud;
133 pmd_t *npmd;
134 pte_t *npte;
135 union mm_context *mmu = &mm->context; 227 union mm_context *mmu = &mm->context;
136 unsigned long addr, end;
137 int r, w, x;
138 struct host_vm_op ops[1]; 228 struct host_vm_op ops[1];
229 unsigned long addr = start_addr, next;
230 int ret = 0, last_op = ARRAY_SIZE(ops) - 1, op_index = -1;
139 void *flush = NULL; 231 void *flush = NULL;
140 int op_index = -1, last_op = ARRAY_SIZE(ops) - 1;
141 int ret = 0;
142
143 if(mm == NULL)
144 return;
145 232
146 ops[0].type = NONE; 233 ops[0].type = NONE;
147 for(addr = start_addr; addr < end_addr && !ret;){ 234 pgd = pgd_offset(mm, addr);
148 npgd = pgd_offset(mm, addr); 235 do {
149 if(!pgd_present(*npgd)){ 236 next = pgd_addr_end(addr, end_addr);
150 end = ADD_ROUND(addr, PGDIR_SIZE); 237 if(!pgd_present(*pgd)){
151 if(end > end_addr) 238 if (force || pgd_newpage(*pgd)){
152 end = end_addr; 239 ret = add_munmap(addr, next - addr, ops,
153 if(force || pgd_newpage(*npgd)){
154 ret = add_munmap(addr, end - addr, ops,
155 &op_index, last_op, mmu,
156 &flush, do_ops);
157 pgd_mkuptodate(*npgd);
158 }
159 addr = end;
160 continue;
161 }
162
163 npud = pud_offset(npgd, addr);
164 if(!pud_present(*npud)){
165 end = ADD_ROUND(addr, PUD_SIZE);
166 if(end > end_addr)
167 end = end_addr;
168 if(force || pud_newpage(*npud)){
169 ret = add_munmap(addr, end - addr, ops,
170 &op_index, last_op, mmu,
171 &flush, do_ops);
172 pud_mkuptodate(*npud);
173 }
174 addr = end;
175 continue;
176 }
177
178 npmd = pmd_offset(npud, addr);
179 if(!pmd_present(*npmd)){
180 end = ADD_ROUND(addr, PMD_SIZE);
181 if(end > end_addr)
182 end = end_addr;
183 if(force || pmd_newpage(*npmd)){
184 ret = add_munmap(addr, end - addr, ops,
185 &op_index, last_op, mmu, 240 &op_index, last_op, mmu,
186 &flush, do_ops); 241 &flush, do_ops);
187 pmd_mkuptodate(*npmd); 242 pgd_mkuptodate(*pgd);
188 } 243 }
189 addr = end;
190 continue;
191 }
192
193 npte = pte_offset_kernel(npmd, addr);
194 r = pte_read(*npte);
195 w = pte_write(*npte);
196 x = pte_exec(*npte);
197 if (!pte_young(*npte)) {
198 r = 0;
199 w = 0;
200 } else if (!pte_dirty(*npte)) {
201 w = 0;
202 }
203 if(force || pte_newpage(*npte)){
204 if(pte_present(*npte))
205 ret = add_mmap(addr,
206 pte_val(*npte) & PAGE_MASK,
207 PAGE_SIZE, r, w, x, ops,
208 &op_index, last_op, mmu,
209 &flush, do_ops);
210 else ret = add_munmap(addr, PAGE_SIZE, ops,
211 &op_index, last_op, mmu,
212 &flush, do_ops);
213 } 244 }
214 else if(pte_newprot(*npte)) 245 else ret = update_pud_range(pgd, addr, next, ops, last_op,
215 ret = add_mprotect(addr, PAGE_SIZE, r, w, x, ops, 246 &op_index, force, mmu, &flush,
216 &op_index, last_op, mmu, 247 do_ops);
217 &flush, do_ops); 248 } while (pgd++, addr = next, ((addr != end_addr) && !ret));
218 249
219 *npte = pte_mkuptodate(*npte);
220 addr += PAGE_SIZE;
221 }
222 if(!ret) 250 if(!ret)
223 ret = (*do_ops)(mmu, ops, op_index, 1, &flush); 251 ret = (*do_ops)(mmu, ops, op_index, 1, &flush);
224 252
225/* This is not an else because ret is modified above */ 253 /* This is not an else because ret is modified above */
226 if(ret) { 254 if(ret) {
227 printk("fix_range_common: failed, killing current process\n"); 255 printk("fix_range_common: failed, killing current process\n");
228 force_sig(SIGKILL, current); 256 force_sig(SIGKILL, current);
@@ -343,12 +371,6 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr)
343 return(pte_offset_map(pmd, addr)); 371 return(pte_offset_map(pmd, addr));
344} 372}
345 373
346void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
347{
348 address &= PAGE_MASK;
349 flush_tlb_range(vma, address, address + PAGE_SIZE);
350}
351
352void flush_tlb_all(void) 374void flush_tlb_all(void)
353{ 375{
354 flush_tlb_mm(current->mm); 376 flush_tlb_mm(current->mm);
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 26f15c458574..abab90c3803f 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -18,8 +18,9 @@
18#include "asm/current.h" 18#include "asm/current.h"
19#include "asm/irq.h" 19#include "asm/irq.h"
20#include "sysdep/sigcontext.h" 20#include "sysdep/sigcontext.h"
21#include "user_util.h"
22#include "kern_util.h" 21#include "kern_util.h"
22#include "as-layout.h"
23#include "arch.h"
23#include "kern.h" 24#include "kern.h"
24#include "chan_kern.h" 25#include "chan_kern.h"
25#include "mconsole_kern.h" 26#include "mconsole_kern.h"
@@ -71,8 +72,8 @@ good_area:
71 goto out; 72 goto out;
72 73
73 /* Don't require VM_READ|VM_EXEC for write faults! */ 74 /* Don't require VM_READ|VM_EXEC for write faults! */
74 if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) 75 if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC)))
75 goto out; 76 goto out;
76 77
77 do { 78 do {
78survive: 79survive:
@@ -156,20 +157,23 @@ static void segv_handler(int sig, union uml_pt_regs *regs)
156 * the info in the regs. A pointer to the info then would 157 * the info in the regs. A pointer to the info then would
157 * give us bad data! 158 * give us bad data!
158 */ 159 */
159unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) 160unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
161 union uml_pt_regs *regs)
160{ 162{
161 struct siginfo si; 163 struct siginfo si;
162 void *catcher; 164 void *catcher;
163 int err; 165 int err;
164 int is_write = FAULT_WRITE(fi); 166 int is_write = FAULT_WRITE(fi);
165 unsigned long address = FAULT_ADDRESS(fi); 167 unsigned long address = FAULT_ADDRESS(fi);
166 168
167 if(!is_user && (address >= start_vm) && (address < end_vm)){ 169 if(!is_user && (address >= start_vm) && (address < end_vm)){
168 flush_tlb_kernel_vm(); 170 flush_tlb_kernel_vm();
169 return(0); 171 return 0;
170 } 172 }
171 else if(current->mm == NULL) 173 else if(current->mm == NULL) {
172 panic("Segfault with no mm"); 174 show_regs(container_of(regs, struct pt_regs, regs));
175 panic("Segfault with no mm");
176 }
173 177
174 if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi)) 178 if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi))
175 err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); 179 err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
@@ -182,26 +186,28 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
182 186
183 catcher = current->thread.fault_catcher; 187 catcher = current->thread.fault_catcher;
184 if(!err) 188 if(!err)
185 return(0); 189 return 0;
186 else if(catcher != NULL){ 190 else if(catcher != NULL){
187 current->thread.fault_addr = (void *) address; 191 current->thread.fault_addr = (void *) address;
188 do_longjmp(catcher, 1); 192 do_longjmp(catcher, 1);
189 } 193 }
190 else if(current->thread.fault_addr != NULL) 194 else if(current->thread.fault_addr != NULL)
191 panic("fault_addr set but no fault catcher"); 195 panic("fault_addr set but no fault catcher");
192 else if(!is_user && arch_fixup(ip, sc)) 196 else if(!is_user && arch_fixup(ip, regs))
193 return(0); 197 return 0;
194 198
195 if(!is_user) 199 if(!is_user) {
200 show_regs(container_of(regs, struct pt_regs, regs));
196 panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", 201 panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
197 address, ip); 202 address, ip);
203 }
198 204
199 if (err == -EACCES) { 205 if (err == -EACCES) {
200 si.si_signo = SIGBUS; 206 si.si_signo = SIGBUS;
201 si.si_errno = 0; 207 si.si_errno = 0;
202 si.si_code = BUS_ADRERR; 208 si.si_code = BUS_ADRERR;
203 si.si_addr = (void __user *)address; 209 si.si_addr = (void __user *)address;
204 current->thread.arch.faultinfo = fi; 210 current->thread.arch.faultinfo = fi;
205 force_sig_info(SIGBUS, &si, current); 211 force_sig_info(SIGBUS, &si, current);
206 } else if (err == -ENOMEM) { 212 } else if (err == -ENOMEM) {
207 printk("VM: killing process %s\n", current->comm); 213 printk("VM: killing process %s\n", current->comm);
@@ -210,10 +216,10 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
210 BUG_ON(err != -EFAULT); 216 BUG_ON(err != -EFAULT);
211 si.si_signo = SIGSEGV; 217 si.si_signo = SIGSEGV;
212 si.si_addr = (void __user *) address; 218 si.si_addr = (void __user *) address;
213 current->thread.arch.faultinfo = fi; 219 current->thread.arch.faultinfo = fi;
214 force_sig_info(SIGSEGV, &si, current); 220 force_sig_info(SIGSEGV, &si, current);
215 } 221 }
216 return(0); 222 return 0;
217} 223}
218 224
219void relay_signal(int sig, union uml_pt_regs *regs) 225void relay_signal(int sig, union uml_pt_regs *regs)
@@ -223,12 +229,12 @@ void relay_signal(int sig, union uml_pt_regs *regs)
223 229
224 if(!UPT_IS_USER(regs)){ 230 if(!UPT_IS_USER(regs)){
225 if(sig == SIGBUS) 231 if(sig == SIGBUS)
226 printk("Bus error - the /dev/shm or /tmp mount likely " 232 printk("Bus error - the host /dev/shm or /tmp mount "
227 "just ran out of space\n"); 233 "likely just ran out of space\n");
228 panic("Kernel mode signal %d", sig); 234 panic("Kernel mode signal %d", sig);
229 } 235 }
230 236
231 current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); 237 current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
232 force_sig(sig, current); 238 force_sig(sig, current);
233} 239}
234 240
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
index ad66df17d9d7..98e21743e604 100644
--- a/arch/um/kernel/tt/exec_kern.c
+++ b/arch/um/kernel/tt/exec_kern.c
@@ -10,7 +10,6 @@
10#include "asm/uaccess.h" 10#include "asm/uaccess.h"
11#include "asm/pgalloc.h" 11#include "asm/pgalloc.h"
12#include "asm/tlbflush.h" 12#include "asm/tlbflush.h"
13#include "user_util.h"
14#include "kern_util.h" 13#include "kern_util.h"
15#include "irq_user.h" 14#include "irq_user.h"
16#include "mem_user.h" 15#include "mem_user.h"
diff --git a/arch/um/kernel/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c
index a92c02ff2ce3..7b5f2181cf51 100644
--- a/arch/um/kernel/tt/exec_user.c
+++ b/arch/um/kernel/tt/exec_user.c
@@ -10,7 +10,6 @@
10#include <errno.h> 10#include <errno.h>
11#include <sys/wait.h> 11#include <sys/wait.h>
12#include <signal.h> 12#include <signal.h>
13#include "user_util.h"
14#include "kern_util.h" 13#include "kern_util.h"
15#include "user.h" 14#include "user.h"
16#include "ptrace_user.h" 15#include "ptrace_user.h"
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 8eba8f7dca68..030e4658f36b 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -17,7 +17,6 @@
17#include "user.h" 17#include "user.h"
18#include "debug.h" 18#include "debug.h"
19#include "kern_util.h" 19#include "kern_util.h"
20#include "user_util.h"
21#include "tt.h" 20#include "tt.h"
22#include "sysdep/thread.h" 21#include "sysdep/thread.h"
23#include "os.h" 22#include "os.h"
@@ -115,6 +114,8 @@ struct gdb_data {
115 int err; 114 int err;
116}; 115};
117 116
117extern char *linux_prog;
118
118static void config_gdb_cb(void *arg) 119static void config_gdb_cb(void *arg)
119{ 120{
120 struct gdb_data *data = arg; 121 struct gdb_data *data = arg;
diff --git a/arch/um/kernel/tt/include/mode_kern-tt.h b/arch/um/kernel/tt/include/mode_kern-tt.h
deleted file mode 100644
index 2a35b15c5fef..000000000000
--- a/arch/um/kernel/tt/include/mode_kern-tt.h
+++ /dev/null
@@ -1,52 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __TT_MODE_KERN_H__
7#define __TT_MODE_KERN_H__
8
9#include "linux/sched.h"
10#include "asm/page.h"
11#include "asm/ptrace.h"
12#include "asm/uaccess.h"
13
14extern void switch_to_tt(void *prev, void *next);
15extern void flush_thread_tt(void);
16extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
17 unsigned long esp);
18extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
19 unsigned long stack_top, struct task_struct *p,
20 struct pt_regs *regs);
21extern void release_thread_tt(struct task_struct *task);
22extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
23extern void init_idle_tt(void);
24extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
25extern void flush_tlb_kernel_vm_tt(void);
26extern void __flush_tlb_one_tt(unsigned long addr);
27extern void flush_tlb_range_tt(struct vm_area_struct *vma,
28 unsigned long start, unsigned long end);
29extern void flush_tlb_mm_tt(struct mm_struct *mm);
30extern void force_flush_all_tt(void);
31extern long execute_syscall_tt(void *r);
32extern void before_mem_tt(unsigned long brk_start);
33extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
34 unsigned long *task_size_out);
35extern int start_uml_tt(void);
36extern int external_pid_tt(struct task_struct *task);
37extern int thread_pid_tt(struct task_struct *task);
38
39#define kmem_end_tt (host_task_size - ABOVE_KMEM)
40
41#endif
42
43/*
44 * Overrides for Emacs so that we follow Linus's tabbing style.
45 * Emacs will notice this stuff at the end of the file and automatically
46 * adjust the settings for this buffer only. This must remain at the end
47 * of the file.
48 * ---------------------------------------------------------------------------
49 * Local variables:
50 * c-file-style: "linux"
51 * End:
52 */
diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c
index 4d1929dfa285..d0c3c4975f28 100644
--- a/arch/um/kernel/tt/mem.c
+++ b/arch/um/kernel/tt/mem.c
@@ -8,7 +8,6 @@
8#include "asm/uaccess.h" 8#include "asm/uaccess.h"
9#include "mem_user.h" 9#include "mem_user.h"
10#include "kern_util.h" 10#include "kern_util.h"
11#include "user_util.h"
12#include "kern.h" 11#include "kern.h"
13#include "tt.h" 12#include "tt.h"
14 13
diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c
index 03e589895388..9774f6360c32 100644
--- a/arch/um/kernel/tt/mem_user.c
+++ b/arch/um/kernel/tt/mem_user.c
@@ -11,7 +11,6 @@
11#include <sys/mman.h> 11#include <sys/mman.h>
12#include "tt.h" 12#include "tt.h"
13#include "mem_user.h" 13#include "mem_user.h"
14#include "user_util.h"
15#include "os.h" 14#include "os.h"
16 15
17void remap_data(void *segment_start, void *segment_end, int w) 16void remap_data(void *segment_start, void *segment_end, int w)
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index 1e86f0bfef72..c631303cb800 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -14,7 +14,6 @@
14#include "asm/tlbflush.h" 14#include "asm/tlbflush.h"
15#include "irq_user.h" 15#include "irq_user.h"
16#include "kern_util.h" 16#include "kern_util.h"
17#include "user_util.h"
18#include "os.h" 17#include "os.h"
19#include "kern.h" 18#include "kern.h"
20#include "sigcontext.h" 19#include "sigcontext.h"
@@ -65,7 +64,8 @@ void switch_to_tt(void *prev, void *next)
65 if(from->thread.mode.tt.switch_pipe[0] == -1) 64 if(from->thread.mode.tt.switch_pipe[0] == -1)
66 os_kill_process(os_getpid(), 0); 65 os_kill_process(os_getpid(), 0);
67 66
68 err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c)); 67 err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c,
68 sizeof(c));
69 if(err != sizeof(c)) 69 if(err != sizeof(c))
70 panic("read of switch_pipe failed, errno = %d", -err); 70 panic("read of switch_pipe failed, errno = %d", -err);
71 71
diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c
index 58800c50b10e..420c23f311f3 100644
--- a/arch/um/kernel/tt/ptproxy/proxy.c
+++ b/arch/um/kernel/tt/ptproxy/proxy.c
@@ -26,7 +26,6 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml
26#include "sysdep.h" 26#include "sysdep.h"
27#include "wait.h" 27#include "wait.h"
28 28
29#include "user_util.h"
30#include "user.h" 29#include "user.h"
31#include "os.h" 30#include "os.h"
32#include "tempfile.h" 31#include "tempfile.h"
@@ -339,11 +338,12 @@ int start_debugger(char *prog, int startup, int stop, int *fd_out)
339 "err = %d\n", -fd); 338 "err = %d\n", -fd);
340 exit(1); 339 exit(1);
341 } 340 }
342 os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1); 341 os_write_file(fd, gdb_init_string,
342 sizeof(gdb_init_string) - 1);
343 if(startup){ 343 if(startup){
344 if(stop){ 344 if(stop){
345 os_write_file(fd, "b start_kernel\n", 345 os_write_file(fd, "b start_kernel\n",
346 strlen("b start_kernel\n")); 346 strlen("b start_kernel\n"));
347 } 347 }
348 os_write_file(fd, "c\n", strlen("c\n")); 348 os_write_file(fd, "c\n", strlen("c\n"));
349 } 349 }
diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c
index 03774427d468..4b4f6179b212 100644
--- a/arch/um/kernel/tt/ptproxy/ptrace.c
+++ b/arch/um/kernel/tt/ptproxy/ptrace.c
@@ -16,7 +16,6 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml
16 16
17#include "ptproxy.h" 17#include "ptproxy.h"
18#include "debug.h" 18#include "debug.h"
19#include "user_util.h"
20#include "kern_util.h" 19#include "kern_util.h"
21#include "ptrace_user.h" 20#include "ptrace_user.h"
22#include "tt.h" 21#include "tt.h"
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
index 99f178319d03..e0e1ab0588ad 100644
--- a/arch/um/kernel/tt/ptproxy/sysdep.c
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c
@@ -13,7 +13,6 @@ terms and conditions.
13#include <sys/types.h> 13#include <sys/types.h>
14#include <linux/unistd.h> 14#include <linux/unistd.h>
15#include "ptrace_user.h" 15#include "ptrace_user.h"
16#include "user_util.h"
17#include "user.h" 16#include "user.h"
18#include "os.h" 17#include "os.h"
19 18
diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c
index 12f6319d8d76..bdd4af4b65fc 100644
--- a/arch/um/kernel/tt/ptproxy/wait.c
+++ b/arch/um/kernel/tt/ptproxy/wait.c
@@ -13,7 +13,6 @@ terms and conditions.
13#include "ptproxy.h" 13#include "ptproxy.h"
14#include "sysdep.h" 14#include "sysdep.h"
15#include "wait.h" 15#include "wait.h"
16#include "user_util.h"
17#include "ptrace_user.h" 16#include "ptrace_user.h"
18#include "sysdep/ptrace.h" 17#include "sysdep/ptrace.h"
19#include "sysdep/sigcontext.h" 18#include "sysdep/sigcontext.h"
diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c
index 902987bf379b..f52b47aff1d2 100644
--- a/arch/um/kernel/tt/syscall_user.c
+++ b/arch/um/kernel/tt/syscall_user.c
@@ -11,7 +11,6 @@
11#include "sigcontext.h" 11#include "sigcontext.h"
12#include "ptrace_user.h" 12#include "ptrace_user.h"
13#include "task.h" 13#include "task.h"
14#include "user_util.h"
15#include "kern_util.h" 14#include "kern_util.h"
16#include "syscall.h" 15#include "syscall.h"
17#include "tt.h" 16#include "tt.h"
diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c
index ae6217c86135..7caa24fe05df 100644
--- a/arch/um/kernel/tt/tlb.c
+++ b/arch/um/kernel/tt/tlb.c
@@ -12,7 +12,6 @@
12#include "asm/pgtable.h" 12#include "asm/pgtable.h"
13#include "asm/uaccess.h" 13#include "asm/uaccess.h"
14#include "asm/tlbflush.h" 14#include "asm/tlbflush.h"
15#include "user_util.h"
16#include "mem_user.h" 15#include "mem_user.h"
17#include "os.h" 16#include "os.h"
18#include "tlb.h" 17#include "tlb.h"
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
index b9195355075a..c23588393f6e 100644
--- a/arch/um/kernel/tt/tracer.c
+++ b/arch/um/kernel/tt/tracer.c
@@ -19,7 +19,6 @@
19#include "sigcontext.h" 19#include "sigcontext.h"
20#include "sysdep/sigcontext.h" 20#include "sysdep/sigcontext.h"
21#include "os.h" 21#include "os.h"
22#include "user_util.h"
23#include "mem_user.h" 22#include "mem_user.h"
24#include "process.h" 23#include "process.h"
25#include "kern_util.h" 24#include "kern_util.h"
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
index b5d9d64d91e4..3032eb5e2467 100644
--- a/arch/um/kernel/tt/trap_user.c
+++ b/arch/um/kernel/tt/trap_user.c
@@ -8,7 +8,6 @@
8#include <signal.h> 8#include <signal.h>
9#include "sysdep/ptrace.h" 9#include "sysdep/ptrace.h"
10#include "sysdep/sigcontext.h" 10#include "sysdep/sigcontext.h"
11#include "user_util.h"
12#include "kern_util.h" 11#include "kern_util.h"
13#include "task.h" 12#include "task.h"
14#include "tt.h" 13#include "tt.h"
diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c
index ed1abcf4d057..0e5c82c5e5b7 100644
--- a/arch/um/kernel/tt/uaccess_user.c
+++ b/arch/um/kernel/tt/uaccess_user.c
@@ -5,7 +5,6 @@
5 */ 5 */
6 6
7#include <string.h> 7#include <string.h>
8#include "user_util.h"
9#include "uml_uaccess.h" 8#include "uml_uaccess.h"
10#include "task.h" 9#include "task.h"
11#include "kern_util.h" 10#include "kern_util.h"
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 89c6dba731f8..1cf954a47fd7 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -17,6 +17,7 @@
17#include "linux/seq_file.h" 17#include "linux/seq_file.h"
18#include "linux/delay.h" 18#include "linux/delay.h"
19#include "linux/module.h" 19#include "linux/module.h"
20#include "linux/utsname.h"
20#include "asm/page.h" 21#include "asm/page.h"
21#include "asm/pgtable.h" 22#include "asm/pgtable.h"
22#include "asm/ptrace.h" 23#include "asm/ptrace.h"
@@ -25,8 +26,9 @@
25#include "asm/setup.h" 26#include "asm/setup.h"
26#include "ubd_user.h" 27#include "ubd_user.h"
27#include "asm/current.h" 28#include "asm/current.h"
28#include "user_util.h"
29#include "kern_util.h" 29#include "kern_util.h"
30#include "as-layout.h"
31#include "arch.h"
30#include "kern.h" 32#include "kern.h"
31#include "mem_user.h" 33#include "mem_user.h"
32#include "mem.h" 34#include "mem.h"
@@ -42,7 +44,7 @@
42 44
43#define DEFAULT_COMMAND_LINE "root=98:0" 45#define DEFAULT_COMMAND_LINE "root=98:0"
44 46
45/* Changed in linux_main and setup_arch, which run before SMP is started */ 47/* Changed in add_arg and setup_arch, which run before SMP is started */
46static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 }; 48static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 };
47 49
48static void __init add_arg(char *arg) 50static void __init add_arg(char *arg)
@@ -56,17 +58,25 @@ static void __init add_arg(char *arg)
56 strcat(command_line, arg); 58 strcat(command_line, arg);
57} 59}
58 60
59struct cpuinfo_um boot_cpu_data = { 61/*
62 * These fields are initialized at boot time and not changed.
63 * XXX This structure is used only in the non-SMP case. Maybe this
64 * should be moved to smp.c.
65 */
66struct cpuinfo_um boot_cpu_data = {
60 .loops_per_jiffy = 0, 67 .loops_per_jiffy = 0,
61 .ipi_pipe = { -1, -1 } 68 .ipi_pipe = { -1, -1 }
62}; 69};
63 70
64unsigned long thread_saved_pc(struct task_struct *task) 71unsigned long thread_saved_pc(struct task_struct *task)
65{ 72{
66 return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, 73 return os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
67 task))); 74 task));
68} 75}
69 76
77/* Changed in setup_arch, which is called in early boot */
78static char host_info[(__NEW_UTS_LEN + 1) * 5];
79
70static int show_cpuinfo(struct seq_file *m, void *v) 80static int show_cpuinfo(struct seq_file *m, void *v)
71{ 81{
72 int index = 0; 82 int index = 0;
@@ -86,7 +96,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
86 loops_per_jiffy/(500000/HZ), 96 loops_per_jiffy/(500000/HZ),
87 (loops_per_jiffy/(5000/HZ)) % 100); 97 (loops_per_jiffy/(5000/HZ)) % 100);
88 98
89 return(0); 99 return 0;
90} 100}
91 101
92static void *c_start(struct seq_file *m, loff_t *pos) 102static void *c_start(struct seq_file *m, loff_t *pos)
@@ -114,14 +124,12 @@ const struct seq_operations cpuinfo_op = {
114/* Set in linux_main */ 124/* Set in linux_main */
115unsigned long host_task_size; 125unsigned long host_task_size;
116unsigned long task_size; 126unsigned long task_size;
117
118unsigned long uml_start;
119
120/* Set in early boot */
121unsigned long uml_physmem; 127unsigned long uml_physmem;
122unsigned long uml_reserved; 128unsigned long uml_reserved; /* Also modified in mem_init */
123unsigned long start_vm; 129unsigned long start_vm;
124unsigned long end_vm; 130unsigned long end_vm;
131
132/* Set in uml_ncpus_setup */
125int ncpus = 1; 133int ncpus = 1;
126 134
127#ifdef CONFIG_CMDLINE_ON_HOST 135#ifdef CONFIG_CMDLINE_ON_HOST
@@ -135,6 +143,8 @@ static char *argv1_end = NULL;
135 143
136/* Set in early boot */ 144/* Set in early boot */
137static int have_root __initdata = 0; 145static int have_root __initdata = 0;
146
147/* Set in uml_mem_setup and modified in linux_main */
138long long physmem_size = 32 * 1024 * 1024; 148long long physmem_size = 32 * 1024 * 1024;
139 149
140void set_cmdline(char *cmd) 150void set_cmdline(char *cmd)
@@ -212,12 +222,12 @@ __uml_setup("debug", no_skas_debug_setup,
212#ifdef CONFIG_SMP 222#ifdef CONFIG_SMP
213static int __init uml_ncpus_setup(char *line, int *add) 223static int __init uml_ncpus_setup(char *line, int *add)
214{ 224{
215 if (!sscanf(line, "%d", &ncpus)) { 225 if (!sscanf(line, "%d", &ncpus)) {
216 printf("Couldn't parse [%s]\n", line); 226 printf("Couldn't parse [%s]\n", line);
217 return -1; 227 return -1;
218 } 228 }
219 229
220 return 0; 230 return 0;
221} 231}
222 232
223__uml_setup("ncpus=", uml_ncpus_setup, 233__uml_setup("ncpus=", uml_ncpus_setup,
@@ -234,7 +244,7 @@ static int force_tt = 0;
234static int __init mode_tt_setup(char *line, int *add) 244static int __init mode_tt_setup(char *line, int *add)
235{ 245{
236 force_tt = 1; 246 force_tt = 1;
237 return(0); 247 return 0;
238} 248}
239 249
240#else 250#else
@@ -245,7 +255,7 @@ static int __init mode_tt_setup(char *line, int *add)
245static int __init mode_tt_setup(char *line, int *add) 255static int __init mode_tt_setup(char *line, int *add)
246{ 256{
247 printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); 257 printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
248 return(0); 258 return 0;
249} 259}
250 260
251#else 261#else
@@ -256,7 +266,7 @@ static int __init mode_tt_setup(char *line, int *add)
256static int __init mode_tt_setup(char *line, int *add) 266static int __init mode_tt_setup(char *line, int *add)
257{ 267{
258 printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); 268 printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
259 return(0); 269 return 0;
260} 270}
261 271
262#endif 272#endif
@@ -274,16 +284,15 @@ int mode_tt = DEFAULT_TT;
274 284
275static int __init Usage(char *line, int *add) 285static int __init Usage(char *line, int *add)
276{ 286{
277 const char **p; 287 const char **p;
278 288
279 printf(usage_string, init_utsname()->release); 289 printf(usage_string, init_utsname()->release);
280 p = &__uml_help_start; 290 p = &__uml_help_start;
281 while (p < &__uml_help_end) { 291 while (p < &__uml_help_end) {
282 printf("%s", *p); 292 printf("%s", *p);
283 p++; 293 p++;
284 } 294 }
285 exit(0); 295 exit(0);
286
287 return 0; 296 return 0;
288} 297}
289 298
@@ -374,13 +383,12 @@ int __init linux_main(int argc, char **argv)
374 383
375 printf("UML running in %s mode\n", mode); 384 printf("UML running in %s mode\n", mode);
376 385
377 uml_start = (unsigned long) &__binary_start;
378 host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt, 386 host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt,
379 set_task_sizes_skas, &task_size); 387 set_task_sizes_skas, &task_size);
380 388
381 /* 389 /*
382 * Setting up handlers to 'sig_info' struct 390 * Setting up handlers to 'sig_info' struct
383 */ 391 */
384 os_fill_handlinfo(handlinfo_kern); 392 os_fill_handlinfo(handlinfo_kern);
385 393
386 brk_start = (unsigned long) sbrk(0); 394 brk_start = (unsigned long) sbrk(0);
@@ -396,7 +404,7 @@ int __init linux_main(int argc, char **argv)
396 physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); 404 physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
397 } 405 }
398 406
399 uml_physmem = uml_start & PAGE_MASK; 407 uml_physmem = (unsigned long) &__binary_start & PAGE_MASK;
400 408
401 /* Reserve up to 4M after the current brk */ 409 /* Reserve up to 4M after the current brk */
402 uml_reserved = ROUND_4M(brk_start) + (1 << 22); 410 uml_reserved = ROUND_4M(brk_start) + (1 << 22);
@@ -407,7 +415,7 @@ int __init linux_main(int argc, char **argv)
407 argv1_begin = argv[1]; 415 argv1_begin = argv[1];
408 argv1_end = &argv[1][strlen(argv[1])]; 416 argv1_end = &argv[1][strlen(argv[1])];
409#endif 417#endif
410 418
411 highmem = 0; 419 highmem = 0;
412 iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; 420 iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
413 max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; 421 max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
@@ -449,12 +457,12 @@ int __init linux_main(int argc, char **argv)
449 printf("Kernel virtual memory size shrunk to %lu bytes\n", 457 printf("Kernel virtual memory size shrunk to %lu bytes\n",
450 virtmem_size); 458 virtmem_size);
451 459
452 uml_postsetup(); 460 uml_postsetup();
453 461
454 task_protections((unsigned long) &init_thread_info); 462 task_protections((unsigned long) &init_thread_info);
455 os_flush_stdout(); 463 os_flush_stdout();
456 464
457 return(CHOOSE_MODE(start_uml_tt(), start_uml_skas())); 465 return CHOOSE_MODE(start_uml_tt(), start_uml_skas());
458} 466}
459 467
460extern int uml_exitcode; 468extern int uml_exitcode;
@@ -466,8 +474,8 @@ static int panic_exit(struct notifier_block *self, unsigned long unused1,
466 show_regs(&(current->thread.regs)); 474 show_regs(&(current->thread.regs));
467 bust_spinlocks(0); 475 bust_spinlocks(0);
468 uml_exitcode = 1; 476 uml_exitcode = 1;
469 machine_halt(); 477 os_dump_core();
470 return(0); 478 return 0;
471} 479}
472 480
473static struct notifier_block panic_exit_notifier = { 481static struct notifier_block panic_exit_notifier = {
@@ -482,14 +490,14 @@ void __init setup_arch(char **cmdline_p)
482 &panic_exit_notifier); 490 &panic_exit_notifier);
483 paging_init(); 491 paging_init();
484 strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); 492 strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
485 *cmdline_p = command_line; 493 *cmdline_p = command_line;
486 setup_hostinfo(); 494 setup_hostinfo(host_info, sizeof host_info);
487} 495}
488 496
489void __init check_bugs(void) 497void __init check_bugs(void)
490{ 498{
491 arch_check_bugs(); 499 arch_check_bugs();
492 os_check_bugs(); 500 os_check_bugs();
493} 501}
494 502
495void apply_alternatives(struct alt_instr *start, struct alt_instr *end) 503void apply_alternatives(struct alt_instr *start, struct alt_instr *end)