diff options
| author | Wim Van Sebroeck <wim@iguana.be> | 2007-05-11 19:03:13 +0000 | 
|---|---|---|
| committer | Wim Van Sebroeck <wim@iguana.be> | 2007-05-11 19:03:13 +0000 | 
| commit | 5c34202b8bf942da411b6599668a76b07449bbfd (patch) | |
| tree | 5719c361321eaddc8e4f1b0c8a7994f0e9a6fdd3 /arch/um/kernel | |
| parent | 0d4804b31f91cfbcff6d62af0bc09a893a1c8ae0 (diff) | |
| parent | 1f8a6b658a943b4f04a1fc7b3a420360202c86cd (diff) | |
Merge /pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'arch/um/kernel')
38 files changed, 528 insertions, 642 deletions
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index e36f92b463c..87a4e4427d8 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S @@ -97,6 +97,8 @@ SECTIONS    .data           : {      . = ALIGN(KERNEL_STACK_SIZE);		/* init_task */      *(.data.init_task) +    . = ALIGN(KERNEL_STACK_SIZE); +    *(.data.init_irqstack)      *(.data .data.* .gnu.linkonce.d.*)      SORT(CONSTRUCTORS)    } diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index 121166400e2..356e50f5aae 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c @@ -10,8 +10,8 @@  #include "asm/pgtable.h"  #include "asm/tlbflush.h"  #include "asm/uaccess.h" -#include "user_util.h"  #include "kern_util.h" +#include "as-layout.h"  #include "mem_user.h"  #include "kern.h"  #include "irq_user.h" diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c index 8cde431348c..d4f1d1ab252 100644 --- a/arch/um/kernel/init_task.c +++ b/arch/um/kernel/init_task.c @@ -1,5 +1,5 @@ -/*  - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,intel.linux}.com)   * Licensed under the GPL   */ @@ -10,7 +10,6 @@  #include "linux/mqueue.h"  #include "asm/uaccess.h"  #include "asm/pgtable.h" -#include "user_util.h"  #include "mem_user.h"  #include "os.h" @@ -34,28 +33,20 @@ EXPORT_SYMBOL(init_task);  /*   * Initial thread structure.   * - * We need to make sure that this is 16384-byte aligned due to the + * We need to make sure that this is aligned due to the   * way process stacks are handled. This is done by having a special   * "init_task" linker map entry..   */ -union thread_union init_thread_union  -__attribute__((__section__(".data.init_task"))) =  -{ INIT_THREAD_INFO(init_task) }; +union thread_union init_thread_union +	__attribute__((__section__(".data.init_task"))) = +		{ INIT_THREAD_INFO(init_task) }; + +union thread_union cpu0_irqstack +	__attribute__((__section__(".data.init_irqstack"))) = +		{ INIT_THREAD_INFO(init_task) };  void unprotect_stack(unsigned long stack)  { -	os_protect_memory((void *) stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, -		       1, 1, 0); +	os_protect_memory((void *) stack, THREAD_SIZE, 1, 1, 0);  } - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only.  This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c index 82ecf904b09..16dc43e9d94 100644 --- a/arch/um/kernel/initrd.c +++ b/arch/um/kernel/initrd.c @@ -7,7 +7,6 @@  #include "linux/bootmem.h"  #include "linux/initrd.h"  #include "asm/types.h" -#include "user_util.h"  #include "kern_util.h"  #include "initrd.h"  #include "init.h" @@ -22,12 +21,20 @@ static int __init read_initrd(void)  	long long size;  	int err; -	if(initrd == NULL) return 0; +	if(initrd == NULL) +		return 0; +  	err = os_file_size(initrd, &size); -	if(err) return 0; +	if(err) +		return 0; +  	area = alloc_bootmem(size); -	if(area == NULL) return 0; -	if(load_initrd(initrd, area, size) == -1) return 0; +	if(area == NULL) +		return 0; + +	if(load_initrd(initrd, area, size) == -1) +		return 0; +  	initrd_start = (unsigned long) area;  	initrd_end = initrd_start + size;  	return 0; @@ -54,25 +61,15 @@ int load_initrd(char *filename, void *buf, int size)  	fd = os_open_file(filename, of_read(OPENFLAGS()), 0);  	if(fd < 0){  		printk("Opening '%s' failed - err = %d\n", filename, -fd); -		return(-1); +		return -1;  	}  	n = os_read_file(fd, buf, size);  	if(n != size){  		printk("Read of %d bytes from '%s' failed, err = %d\n", size,  		       filename, -n); -		return(-1); +		return -1;  	}  	os_close_file(fd); -	return(0); +	return 0;  } -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only.  This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index dbf2f5bc842..dba04d88b43 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -1,4 +1,4 @@ -/*  +/*   * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)   * Licensed under the GPL   * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c: @@ -25,7 +25,6 @@  #include "asm/system.h"  #include "asm/errno.h"  #include "asm/uaccess.h" -#include "user_util.h"  #include "kern_util.h"  #include "irq_user.h"  #include "irq_kern.h" @@ -33,6 +32,7 @@  #include "sigio.h"  #include "um_malloc.h"  #include "misc_constants.h" +#include "as-layout.h"  /*   * Generic, controller-independent functions: @@ -54,7 +54,7 @@ int show_interrupts(struct seq_file *p, void *v)  	if (i < NR_IRQS) {  		spin_lock_irqsave(&irq_desc[i].lock, flags);  		action = irq_desc[i].action; -		if (!action)  +		if (!action)  			goto skip;  		seq_printf(p, "%3d: ",i);  #ifndef CONFIG_SMP @@ -79,6 +79,14 @@ skip:  	return 0;  } +/* + * This list is accessed under irq_lock, except in sigio_handler, + * where it is safe from being modified.  IRQ handlers won't change it - + * if an IRQ source has vanished, it will be freed by free_irqs just + * before returning from sigio_handler.  That will process a separate + * list of irqs to free, with its own locking, coming back here to + * remove list elements, taking the irq_lock to do so. + */  static struct irq_fd *active_fds = NULL;  static struct irq_fd **last_irq_ptr = &active_fds; @@ -244,6 +252,7 @@ void free_irq_by_fd(int fd)  	free_irq_by_cb(same_fd, &fd);  } +/* Must be called with irq_lock held */  static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)  {  	struct irq_fd *irq; @@ -309,6 +318,12 @@ void deactivate_fd(int fd, int irqnum)  	ignore_sigio_fd(fd);  } +/* + * Called just before shutdown in order to provide a clean exec + * environment in case the system is rebooting.  No locking because + * that would cause a pointless shutdown hang if something hadn't + * released the lock. + */  int deactivate_all_fds(void)  {  	struct irq_fd *irq; @@ -454,3 +469,113 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler)   out:  	return err;  } + +/* + * IRQ stack entry and exit: + * + * Unlike i386, UML doesn't receive IRQs on the normal kernel stack + * and switch over to the IRQ stack after some preparation.  We use + * sigaltstack to receive signals on a separate stack from the start. + * These two functions make sure the rest of the kernel won't be too + * upset by being on a different stack.  The IRQ stack has a + * thread_info structure at the bottom so that current et al continue + * to work. + * + * to_irq_stack copies the current task's thread_info to the IRQ stack + * thread_info and sets the tasks's stack to point to the IRQ stack. + * + * from_irq_stack copies the thread_info struct back (flags may have + * been modified) and resets the task's stack pointer. + * + * Tricky bits - + * + * What happens when two signals race each other?  UML doesn't block + * signals with sigprocmask, SA_DEFER, or sa_mask, so a second signal + * could arrive while a previous one is still setting up the + * thread_info. + * + * There are three cases - + *     The first interrupt on the stack - sets up the thread_info and + * handles the interrupt + *     A nested interrupt interrupting the copying of the thread_info - + * can't handle the interrupt, as the stack is in an unknown state + *     A nested interrupt not interrupting the copying of the + * thread_info - doesn't do any setup, just handles the interrupt + * + * The first job is to figure out whether we interrupted stack setup. + * This is done by xchging the signal mask with thread_info->pending. + * If the value that comes back is zero, then there is no setup in + * progress, and the interrupt can be handled.  If the value is + * non-zero, then there is stack setup in progress.  In order to have + * the interrupt handled, we leave our signal in the mask, and it will + * be handled by the upper handler after it has set up the stack. + * + * Next is to figure out whether we are the outer handler or a nested + * one.  As part of setting up the stack, thread_info->real_thread is + * set to non-NULL (and is reset to NULL on exit).  This is the + * nesting indicator.  If it is non-NULL, then the stack is already + * set up and the handler can run. + */ + +static unsigned long pending_mask; + +unsigned long to_irq_stack(int sig, unsigned long *mask_out) +{ +	struct thread_info *ti; +	unsigned long mask, old; +	int nested; + +	mask = xchg(&pending_mask, 1 << sig); +	if(mask != 0){ +		/* If any interrupts come in at this point, we want to +		 * make sure that their bits aren't lost by our +		 * putting our bit in.  So, this loop accumulates bits +		 * until xchg returns the same value that we put in. +		 * When that happens, there were no new interrupts, +		 * and pending_mask contains a bit for each interrupt +		 * that came in. +		 */ +		old = 1 << sig; +		do { +			old |= mask; +			mask = xchg(&pending_mask, old); +		} while(mask != old); +		return 1; +	} + +	ti = current_thread_info(); +	nested = (ti->real_thread != NULL); +	if(!nested){ +		struct task_struct *task; +		struct thread_info *tti; + +		task = cpu_tasks[ti->cpu].task; +		tti = task_thread_info(task); +		*ti = *tti; +		ti->real_thread = tti; +		task->stack = ti; +	} + +	mask = xchg(&pending_mask, 0); +	*mask_out |= mask | nested; +	return 0; +} + +unsigned long from_irq_stack(int nested) +{ +	struct thread_info *ti, *to; +	unsigned long mask; + +	ti = current_thread_info(); + +	pending_mask = 1; + +	to = ti->real_thread; +	current->stack = to; +	ti->real_thread = NULL; +	*to = *ti; + +	mask = xchg(&pending_mask, 0); +	return mask & ~1; +} + diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index 0e00cf93f90..7b3e53fb807 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c @@ -16,7 +16,7 @@  #include "asm/page.h"  #include "asm/tlbflush.h"  #include "kern_util.h" -#include "user_util.h" +#include "as-layout.h"  #include "mem_user.h"  #include "os.h" diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index df7d662b98c..72ff85693a3 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -13,8 +13,8 @@  #include "asm/page.h"  #include "asm/fixmap.h"  #include "asm/pgalloc.h" -#include "user_util.h"  #include "kern_util.h" +#include "as-layout.h"  #include "kern.h"  #include "mem_user.h"  #include "uml_uaccess.h" @@ -216,7 +216,7 @@ static void __init fixaddr_user_init( void)  #endif  } -void paging_init(void) +void __init paging_init(void)  {  	unsigned long zones_size[MAX_NR_ZONES], vaddr;  	int i; diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index 638f3b5f609..3ba6e4c841d 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -13,7 +13,7 @@  #include "asm/types.h"  #include "asm/pgtable.h"  #include "kern_util.h" -#include "user_util.h" +#include "as-layout.h"  #include "mode_kern.h"  #include "mem.h"  #include "mem_user.h" @@ -21,229 +21,8 @@  #include "kern.h"  #include "init.h" -struct phys_desc { -	struct rb_node rb; -	int fd; -	__u64 offset; -	void *virt; -	unsigned long phys; -	struct list_head list; -}; - -static struct rb_root phys_mappings = RB_ROOT; - -static struct rb_node **find_rb(void *virt) -{ -	struct rb_node **n = &phys_mappings.rb_node; -	struct phys_desc *d; - -	while(*n != NULL){ -		d = rb_entry(*n, struct phys_desc, rb); -		if(d->virt == virt) -			return n; - -		if(d->virt > virt) -			n = &(*n)->rb_left; -		else -			n = &(*n)->rb_right; -	} - -	return n; -} - -static struct phys_desc *find_phys_mapping(void *virt) -{ -	struct rb_node **n = find_rb(virt); - -	if(*n == NULL) -		return NULL; - -	return rb_entry(*n, struct phys_desc, rb); -} - -static void insert_phys_mapping(struct phys_desc *desc) -{ -	struct rb_node **n = find_rb(desc->virt); - -	if(*n != NULL) -		panic("Physical remapping for %p already present", -		      desc->virt); - -	rb_link_node(&desc->rb, rb_parent(*n), n); -	rb_insert_color(&desc->rb, &phys_mappings); -} - -LIST_HEAD(descriptor_mappings); - -struct desc_mapping { -	int fd; -	struct list_head list; -	struct list_head pages; -}; - -static struct desc_mapping *find_mapping(int fd) -{ -	struct desc_mapping *desc; -	struct list_head *ele; - -	list_for_each(ele, &descriptor_mappings){ -		desc = list_entry(ele, struct desc_mapping, list); -		if(desc->fd == fd) -			return desc; -	} - -	return NULL; -} - -static struct desc_mapping *descriptor_mapping(int fd) -{ -	struct desc_mapping *desc; - -	desc = find_mapping(fd); -	if(desc != NULL) -		return desc; - -	desc = kmalloc(sizeof(*desc), GFP_ATOMIC); -	if(desc == NULL) -		return NULL; - -	*desc = ((struct desc_mapping) -		{ .fd =		fd, -		  .list =	LIST_HEAD_INIT(desc->list), -		  .pages =	LIST_HEAD_INIT(desc->pages) }); -	list_add(&desc->list, &descriptor_mappings); - -	return desc; -} - -int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w) -{ -	struct desc_mapping *fd_maps; -	struct phys_desc *desc; -	unsigned long phys; -	int err; - -	fd_maps = descriptor_mapping(fd); -	if(fd_maps == NULL) -		return -ENOMEM; - -	phys = __pa(virt); -	desc = find_phys_mapping(virt); -	if(desc != NULL) -		panic("Address 0x%p is already substituted\n", virt); - -	err = -ENOMEM; -	desc = kmalloc(sizeof(*desc), GFP_ATOMIC); -	if(desc == NULL) -		goto out; - -	*desc = ((struct phys_desc) -		{ .fd =			fd, -		  .offset =		offset, -		  .virt =		virt, -		  .phys =		__pa(virt), -		  .list = 		LIST_HEAD_INIT(desc->list) }); -	insert_phys_mapping(desc); - -	list_add(&desc->list, &fd_maps->pages); - -	virt = (void *) ((unsigned long) virt & PAGE_MASK); -	err = os_map_memory(virt, fd, offset, PAGE_SIZE, 1, w, 0); -	if(!err) -		goto out; - -	rb_erase(&desc->rb, &phys_mappings); -	kfree(desc); - out: -	return err; -} -  static int physmem_fd = -1; -static void remove_mapping(struct phys_desc *desc) -{ -	void *virt = desc->virt; -	int err; - -	rb_erase(&desc->rb, &phys_mappings); -	list_del(&desc->list); -	kfree(desc); - -	err = os_map_memory(virt, physmem_fd, __pa(virt), PAGE_SIZE, 1, 1, 0); -	if(err) -		panic("Failed to unmap block device page from physical memory, " -		      "errno = %d", -err); -} - -int physmem_remove_mapping(void *virt) -{ -	struct phys_desc *desc; - -	virt = (void *) ((unsigned long) virt & PAGE_MASK); -	desc = find_phys_mapping(virt); -	if(desc == NULL) -		return 0; - -	remove_mapping(desc); -	return 1; -} - -void physmem_forget_descriptor(int fd) -{ -	struct desc_mapping *desc; -	struct phys_desc *page; -	struct list_head *ele, *next; -	__u64 offset; -	void *addr; -	int err; - -	desc = find_mapping(fd); -	if(desc == NULL) -		return; - -	list_for_each_safe(ele, next, &desc->pages){ -		page = list_entry(ele, struct phys_desc, list); -		offset = page->offset; -		addr = page->virt; -		remove_mapping(page); -		err = os_seek_file(fd, offset); -		if(err) -			panic("physmem_forget_descriptor - failed to seek " -			      "to %lld in fd %d, error = %d\n", -			      offset, fd, -err); -		err = os_read_file(fd, addr, PAGE_SIZE); -		if(err < 0) -			panic("physmem_forget_descriptor - failed to read " -			      "from fd %d to 0x%p, error = %d\n", -			      fd, addr, -err); -	} - -	list_del(&desc->list); -	kfree(desc); -} - -EXPORT_SYMBOL(physmem_forget_descriptor); -EXPORT_SYMBOL(physmem_remove_mapping); -EXPORT_SYMBOL(physmem_subst_mapping); - -void arch_free_page(struct page *page, int order) -{ -	void *virt; -	int i; - -	for(i = 0; i < (1 << order); i++){ -		virt = __va(page_to_phys(page + i)); -		physmem_remove_mapping(virt); -	} -} - -int is_remapped(void *virt) -{ - 	struct phys_desc *desc = find_phys_mapping(virt); - -	return desc != NULL; -} -  /* Changed during early boot */  unsigned long high_physmem; @@ -350,14 +129,9 @@ void setup_physmem(unsigned long start, unsigned long reserve_end,  int phys_mapping(unsigned long phys, __u64 *offset_out)  { -	struct phys_desc *desc = find_phys_mapping(__va(phys & PAGE_MASK));  	int fd = -1; -	if(desc != NULL){ -		fd = desc->fd; -		*offset_out = desc->offset; -	} -	else if(phys < physmem_size){ +	if(phys < physmem_size){  		fd = physmem_fd;  		*offset_out = phys;  	} diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 348b272bb76..8d2c5496532 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -32,8 +32,8 @@  #include "asm/tlbflush.h"  #include "asm/uaccess.h"  #include "asm/user.h" -#include "user_util.h"  #include "kern_util.h" +#include "as-layout.h"  #include "kern.h"  #include "signal_kern.h"  #include "init.h" @@ -54,11 +54,9 @@   */  struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; -int external_pid(void *t) +static inline int external_pid(struct task_struct *task)  { -	struct task_struct *task = t ? t : current; - -	return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task)); +	return CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task);  }  int pid_to_processor_id(int pid) @@ -66,9 +64,10 @@ int pid_to_processor_id(int pid)  	int i;  	for(i = 0; i < ncpus; i++){ -		if(cpu_tasks[i].pid == pid) return(i); +		if(cpu_tasks[i].pid == pid) +			return i;  	} -	return(-1); +	return -1;  }  void free_stack(unsigned long stack, int order) @@ -85,9 +84,9 @@ unsigned long alloc_stack(int order, int atomic)  		flags = GFP_ATOMIC;  	page = __get_free_pages(flags, order);  	if(page == 0) -		return(0); +		return 0;  	stack_protections(page); -	return(page); +	return page;  }  int 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)  	current->thread.request.u.thread.arg = arg;  	pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,  		      ¤t->thread.regs, 0, NULL, NULL); -	if(pid < 0) -		panic("do_fork failed in kernel_thread, errno = %d", pid); -	return(pid); +	return pid;  } -void set_current(void *t) +static inline void set_current(struct task_struct *task)  { -	struct task_struct *task = t; -  	cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)  		{ external_pid(task), task });  } @@ -128,14 +123,16 @@ void *_switch_to(void *prev, void *next, void *last)  		prev= current;  	} while(current->thread.saved_task); -	return(current->thread.prev_sched); +	return current->thread.prev_sched;  }  void interrupt_end(void)  { -	if(need_resched()) schedule(); -	if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal(); +	if(need_resched()) +		schedule(); +	if(test_tsk_thread_flag(current, TIF_SIGPENDING)) +		do_signal();  }  void release_thread(struct task_struct *task) @@ -150,7 +147,7 @@ void exit_thread(void)  void *get_current(void)  { -	return(current); +	return current;  }  int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, @@ -188,15 +185,12 @@ void initial_thread_cb(void (*proc)(void *), void *arg)  	kmalloc_ok = save_kmalloc_ok;  } +#ifdef CONFIG_MODE_TT  unsigned long stack_sp(unsigned long page)  { -	return(page + PAGE_SIZE - sizeof(void *)); -} - -int current_pid(void) -{ -	return(current->pid); +	return page + PAGE_SIZE - sizeof(void *);  } +#endif  void default_idle(void)  { @@ -221,11 +215,6 @@ void cpu_idle(void)  	CHOOSE_MODE(init_idle_tt(), init_idle_skas());  } -int page_size(void) -{ -	return(PAGE_SIZE); -} -  void *um_virt_to_phys(struct task_struct *task, unsigned long addr,  		      pte_t *pte_out)  { @@ -236,68 +225,43 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,  	pte_t ptent;  	if(task->mm == NULL) -		return(ERR_PTR(-EINVAL)); +		return ERR_PTR(-EINVAL);  	pgd = pgd_offset(task->mm, addr);  	if(!pgd_present(*pgd)) -		return(ERR_PTR(-EINVAL)); +		return ERR_PTR(-EINVAL);  	pud = pud_offset(pgd, addr);  	if(!pud_present(*pud)) -		return(ERR_PTR(-EINVAL)); +		return ERR_PTR(-EINVAL);  	pmd = pmd_offset(pud, addr);  	if(!pmd_present(*pmd)) -		return(ERR_PTR(-EINVAL)); +		return ERR_PTR(-EINVAL);  	pte = pte_offset_kernel(pmd, addr);  	ptent = *pte;  	if(!pte_present(ptent)) -		return(ERR_PTR(-EINVAL)); +		return ERR_PTR(-EINVAL);  	if(pte_out != NULL)  		*pte_out = ptent; -	return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK)); +	return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK);  }  char *current_cmd(void)  {  #if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM) -	return("(Unknown)"); +	return "(Unknown)";  #else  	void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);  	return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);  #endif  } -void force_sigbus(void) -{ -	printk(KERN_ERR "Killing pid %d because of a lack of memory\n", -	       current->pid); -	lock_kernel(); -	sigaddset(¤t->pending.signal, SIGBUS); -	recalc_sigpending(); -	current->flags |= PF_SIGNALED; -	do_exit(SIGBUS | 0x80); -} -  void dump_thread(struct pt_regs *regs, struct user *u)  {  } -void enable_hlt(void) -{ -	panic("enable_hlt"); -} - -EXPORT_SYMBOL(enable_hlt); - -void disable_hlt(void) -{ -	panic("disable_hlt"); -} - -EXPORT_SYMBOL(disable_hlt); -  void *um_kmalloc(int size)  {  	return kmalloc(size, GFP_KERNEL); @@ -313,36 +277,17 @@ void *um_vmalloc(int size)  	return vmalloc(size);  } -void *um_vmalloc_atomic(int size) -{ -	return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL); -} -  int __cant_sleep(void) {  	return in_atomic() || irqs_disabled() || in_interrupt();  	/* Is in_interrupt() really needed? */  } -unsigned long get_fault_addr(void) -{ -	return((unsigned long) current->thread.fault_addr); -} - -EXPORT_SYMBOL(get_fault_addr); - -void not_implemented(void) -{ -	printk(KERN_DEBUG "Something isn't implemented in here\n"); -} - -EXPORT_SYMBOL(not_implemented); -  int user_context(unsigned long sp)  {  	unsigned long stack;  	stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); -	return(stack != (unsigned long) current_thread); +	return stack != (unsigned long) current_thread;  }  extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; @@ -363,22 +308,22 @@ char *uml_strdup(char *string)  int copy_to_user_proc(void __user *to, void *from, int size)  { -	return(copy_to_user(to, from, size)); +	return copy_to_user(to, from, size);  }  int copy_from_user_proc(void *to, void __user *from, int size)  { -	return(copy_from_user(to, from, size)); +	return copy_from_user(to, from, size);  }  int clear_user_proc(void __user *buf, int size)  { -	return(clear_user(buf, size)); +	return clear_user(buf, size);  }  int strlen_user_proc(char __user *str)  { -	return(strlen_user(str)); +	return strlen_user(str);  }  int smp_sigio_handler(void) @@ -387,14 +332,14 @@ int smp_sigio_handler(void)  	int cpu = current_thread->cpu;  	IPI_handler(cpu);  	if(cpu != 0) -		return(1); +		return 1;  #endif -	return(0); +	return 0;  }  int cpu(void)  { -	return(current_thread->cpu); +	return current_thread->cpu;  }  static atomic_t using_sysemu = ATOMIC_INIT(0); @@ -443,7 +388,7 @@ int __init make_proc_sysemu(void)  	if (ent == NULL)  	{  		printk(KERN_WARNING "Failed to register /proc/sysemu\n"); -		return(0); +		return 0;  	}  	ent->read_proc  = proc_read_sysemu; diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index f602623644a..7e4305a1fd3 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c @@ -6,7 +6,6 @@  #include "linux/module.h"  #include "linux/sched.h"  #include "asm/smp.h" -#include "user_util.h"  #include "kern_util.h"  #include "kern.h"  #include "os.h" diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c index 3c798cdde55..c4020c3d785 100644 --- a/arch/um/kernel/signal.c +++ b/arch/um/kernel/signal.c @@ -17,7 +17,6 @@  #include "asm/signal.h"  #include "asm/uaccess.h"  #include "asm/unistd.h" -#include "user_util.h"  #include "asm/ucontext.h"  #include "kern_util.h"  #include "signal_kern.h" diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c index 54b79595137..580eb646894 100644 --- a/arch/um/kernel/skas/exec.c +++ b/arch/um/kernel/skas/exec.c @@ -17,7 +17,17 @@  void flush_thread_skas(void)  { -	force_flush_all(); +	void *data = NULL; +	unsigned long end = proc_mm ? task_size : CONFIG_STUB_START; +	int ret; + +	ret = unmap(¤t->mm->context.skas.id, 0, end, 1, &data); +	if(ret){ +		printk("flush_thread_skas - clearing address space failed, " +		       "err = %d\n", ret); +		force_sig(SIGKILL, current); +	} +  	switch_mm_skas(¤t->mm->context.skas.id);  } diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index ae4fa71d3b8..2a69a7ce579 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -13,9 +13,9 @@  #include "asm/uaccess.h"  #include "asm/atomic.h"  #include "kern_util.h" +#include "as-layout.h"  #include "skas.h"  #include "os.h" -#include "user_util.h"  #include "tlb.h"  #include "kern.h"  #include "mode.h" @@ -163,8 +163,12 @@ static int start_kernel_proc(void *unused)  extern int userspace_pid[]; +extern char cpu0_irqstack[]; +  int start_uml_skas(void)  { +	stack_protections((unsigned long) &cpu0_irqstack); +	set_sigstack(cpu0_irqstack, THREAD_SIZE);  	if(proc_mm)  		userspace_pid[0] = start_userspace(0); @@ -178,20 +182,23 @@ int start_uml_skas(void)  int external_pid_skas(struct task_struct *task)  { -#warning Need to look up userspace_pid by cpu +	/* FIXME: Need to look up userspace_pid by cpu */  	return(userspace_pid[0]);  }  int thread_pid_skas(struct task_struct *task)  { -#warning Need to look up userspace_pid by cpu +	/* FIXME: Need to look up userspace_pid by cpu */  	return(userspace_pid[0]);  }  void kill_off_processes_skas(void)  {  	if(proc_mm) -#warning need to loop over userspace_pids in kill_off_processes_skas +		/* +		 * FIXME: need to loop over userspace_pids in +		 * kill_off_processes_skas +		 */  		os_kill_ptraced_process(userspace_pid[0], 1);  	else {  		struct task_struct *p; diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c index 27eb29ce666..c0f0693743b 100644 --- a/arch/um/kernel/skas/tlb.c +++ b/arch/um/kernel/skas/tlb.c @@ -10,7 +10,6 @@  #include "asm/page.h"  #include "asm/pgtable.h"  #include "asm/mmu.h" -#include "user_util.h"  #include "mem_user.h"  #include "mem.h"  #include "skas.h" @@ -28,19 +27,17 @@ static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last,  		switch(op->type){  		case MMAP:  			ret = map(&mmu->skas.id, op->u.mmap.addr, -				  op->u.mmap.len, op->u.mmap.r, op->u.mmap.w, -				  op->u.mmap.x, op->u.mmap.fd, -				  op->u.mmap.offset, finished, flush); +				  op->u.mmap.len, op->u.mmap.prot, +				  op->u.mmap.fd, op->u.mmap.offset, finished, +				  flush);  			break;  		case MUNMAP: -			ret = unmap(&mmu->skas.id, -				    (void *) op->u.munmap.addr, +			ret = unmap(&mmu->skas.id, op->u.munmap.addr,  				    op->u.munmap.len, finished, flush);  			break;  		case MPROTECT:  			ret = protect(&mmu->skas.id, op->u.mprotect.addr, -				      op->u.mprotect.len, op->u.mprotect.r, -				      op->u.mprotect.w, op->u.mprotect.x, +				      op->u.mprotect.len, op->u.mprotect.prot,  				      finished, flush);  			break;  		default: @@ -92,6 +89,76 @@ void flush_tlb_mm_skas(struct mm_struct *mm)  void force_flush_all_skas(void)  { -	unsigned long end = proc_mm ? task_size : CONFIG_STUB_START; -        fix_range(current->mm, 0, end, 1); +	struct mm_struct *mm = current->mm; +	struct vm_area_struct *vma = mm->mmap; + +	while(vma != NULL) { +		fix_range(mm, vma->vm_start, vma->vm_end, 1); +		vma = vma->vm_next; +	} +} + +void flush_tlb_page_skas(struct vm_area_struct *vma, unsigned long address) +{ +	pgd_t *pgd; +	pud_t *pud; +	pmd_t *pmd; +	pte_t *pte; +	struct mm_struct *mm = vma->vm_mm; +	void *flush = NULL; +	int r, w, x, prot, err = 0; +	struct mm_id *mm_id; + +	pgd = pgd_offset(mm, address); +	if(!pgd_present(*pgd)) +		goto kill; + +	pud = pud_offset(pgd, address); +	if(!pud_present(*pud)) +		goto kill; + +	pmd = pmd_offset(pud, address); +	if(!pmd_present(*pmd)) +		goto kill; + +	pte = pte_offset_kernel(pmd, address); + +	r = pte_read(*pte); +	w = pte_write(*pte); +	x = pte_exec(*pte); +	if (!pte_young(*pte)) { +		r = 0; +		w = 0; +	} else if (!pte_dirty(*pte)) { +		w = 0; +	} + +	mm_id = &mm->context.skas.id; +	prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | +		(x ? UM_PROT_EXEC : 0)); +	if(pte_newpage(*pte)){ +		if(pte_present(*pte)){ +			unsigned long long offset; +			int fd; + +			fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset); +			err = map(mm_id, address, PAGE_SIZE, prot, fd, offset, +				  1, &flush); +		} +		else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush); +	} +	else if(pte_newprot(*pte)) +		err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush); + +	if(err) +		goto kill; + +	*pte = pte_mkuptodate(*pte); + +	return; + +kill: +	printk("Failed to flush page for address 0x%lx\n", address); +	force_sig(SIGKILL, current);  } + diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index 759b0705316..e6a7778006a 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);  #include "asm/smp.h"  #include "asm/processor.h"  #include "asm/spinlock.h" -#include "user_util.h"  #include "kern_util.h"  #include "kern.h"  #include "irq_user.h" @@ -90,7 +89,7 @@ static int idle_proc(void *cpup)  	cpu_set(cpu, cpu_online_map);  	default_idle(); -	return(0); +	return 0;  }  static struct task_struct *idle_thread(int cpu) @@ -98,8 +97,8 @@ static struct task_struct *idle_thread(int cpu)  	struct task_struct *new_task;  	unsigned char c; -        current->thread.request.u.thread.proc = idle_proc; -        current->thread.request.u.thread.arg = (void *) cpu; +	current->thread.request.u.thread.proc = idle_proc; +	current->thread.request.u.thread.arg = (void *) cpu;  	new_task = fork_idle(cpu);  	if(IS_ERR(new_task))  		panic("copy_process failed in idle_thread, error = %ld", @@ -110,9 +109,9 @@ static struct task_struct *idle_thread(int cpu)  			    .task = 	new_task } );  	idle_threads[cpu] = new_task;  	CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c, -			  sizeof(c)), +				  sizeof(c)),  		    ({ panic("skas mode doesn't support SMP"); })); -	return(new_task); +	return new_task;  }  void smp_prepare_cpus(unsigned int maxcpus) @@ -163,13 +162,13 @@ int __cpu_up(unsigned int cpu)  	cpu_set(cpu, smp_commenced_mask);  	while (!cpu_isset(cpu, cpu_online_map))  		mb(); -	return(0); +	return 0;  }  int setup_profiling_timer(unsigned int multiplier)  {  	printk(KERN_INFO "setup_profiling_timer\n"); -	return(0); +	return 0;  }  void smp_call_function_slave(int cpu); @@ -205,7 +204,7 @@ void IPI_handler(int cpu)  int hard_smp_processor_id(void)  { -	return(pid_to_processor_id(os_getpid())); +	return pid_to_processor_id(os_getpid());  }  static DEFINE_SPINLOCK(call_lock); @@ -254,14 +253,3 @@ int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,  }  #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only.  This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index 2828c528322..237c4eab7cf 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -18,7 +18,6 @@  #include "asm/mman.h"  #include "asm/uaccess.h"  #include "kern_util.h" -#include "user_util.h"  #include "sysdep/syscalls.h"  #include "mode_kern.h"  #include "choose-mode.h" diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index f9e02b31a97..93263571d81 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -10,7 +10,6 @@  #include "asm/page.h"  #include "asm/processor.h"  #include "sysrq.h" -#include "user_util.h"  /* Catch non-i386 SUBARCH's. */  #if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT) diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index b1f8b075241..259c49da7ff 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -18,7 +18,6 @@  #include "asm/param.h"  #include "asm/current.h"  #include "kern_util.h" -#include "user_util.h"  #include "mode.h"  #include "os.h" @@ -35,8 +34,8 @@ unsigned long long sched_clock(void)  	return (unsigned long long)jiffies_64 * (1000000000 / HZ);  } -static unsigned long long prev_nsecs[NR_CPUS];  #ifdef CONFIG_UML_REAL_TIME_CLOCK +static unsigned long long prev_nsecs[NR_CPUS];  static long long delta[NR_CPUS];		/* Deviation per interval */  #endif @@ -95,7 +94,12 @@ irqreturn_t um_timer(int irq, void *dev)  	do_timer(1); +#ifdef CONFIG_UML_REAL_TIME_CLOCK  	nsecs = get_time(); +#else +	nsecs = (unsigned long long) xtime.tv_sec * BILLION + xtime.tv_nsec + +		BILLION / HZ; +#endif  	xtime.tv_sec = nsecs / NSEC_PER_SEC;  	xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; @@ -128,13 +132,18 @@ void time_init(void)  	nsecs = os_nsecs();  	set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION,  				-nsecs % BILLION); +	set_normalized_timespec(&xtime, nsecs / BILLION, nsecs % BILLION);  	late_time_init = register_timer;  }  void do_gettimeofday(struct timeval *tv)  { +#ifdef CONFIG_UML_REAL_TIME_CLOCK  	unsigned long long nsecs = get_time(); - +#else +	unsigned long long nsecs = (unsigned long long) xtime.tv_sec * BILLION + +		xtime.tv_nsec; +#endif  	tv->tv_sec = nsecs / NSEC_PER_SEC;  	/* Careful about calculations here - this was originally done as  	 * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC @@ -168,6 +177,8 @@ int do_settimeofday(struct timespec *tv)  void timer_handler(int sig, union uml_pt_regs *regs)  { +	if(current_thread->cpu == 0) +		timer_irq(regs);  	local_irq_disable();  	irq_enter();  	update_process_times(CHOOSE_MODE( @@ -175,6 +186,4 @@ void timer_handler(int sig, union uml_pt_regs *regs)  			     (regs)->skas.is_user));  	irq_exit();  	local_irq_enable(); -	if(current_thread->cpu == 0) -		timer_irq(regs);  } diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index 54a5ff25645..8a8d5285144 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c @@ -6,17 +6,18 @@  #include "linux/mm.h"  #include "asm/page.h"  #include "asm/pgalloc.h" +#include "asm/pgtable.h"  #include "asm/tlbflush.h"  #include "choose-mode.h"  #include "mode_kern.h" -#include "user_util.h" +#include "as-layout.h"  #include "tlb.h"  #include "mem.h"  #include "mem_user.h"  #include "os.h"  static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, -		    int r, int w, int x, struct host_vm_op *ops, int *index, +		    unsigned int prot, struct host_vm_op *ops, int *index,  		    int last_filled, union mm_context *mmu, void **flush,  		    int (*do_ops)(union mm_context *, struct host_vm_op *,  				  int, int, void **)) @@ -30,8 +31,7 @@ static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,  		last = &ops[*index];  		if((last->type == MMAP) &&  		   (last->u.mmap.addr + last->u.mmap.len == virt) && -		   (last->u.mmap.r == r) && (last->u.mmap.w == w) && -		   (last->u.mmap.x == x) && (last->u.mmap.fd == fd) && +		   (last->u.mmap.prot == prot) && (last->u.mmap.fd == fd) &&  		   (last->u.mmap.offset + last->u.mmap.len == offset)){  			last->u.mmap.len += len;  			return 0; @@ -47,9 +47,7 @@ static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,  			     			.u = { .mmap = {  						       .addr	= virt,  						       .len	= len, -						       .r	= r, -						       .w	= w, -						       .x	= x, +						       .prot	= prot,  						       .fd	= fd,  						       .offset	= offset }  			   } }); @@ -86,8 +84,8 @@ static int add_munmap(unsigned long addr, unsigned long len,  	return ret;  } -static int add_mprotect(unsigned long addr, unsigned long len, int r, int w, -			int x, struct host_vm_op *ops, int *index, +static int add_mprotect(unsigned long addr, unsigned long len, +			unsigned int prot, struct host_vm_op *ops, int *index,  			int last_filled, union mm_context *mmu, void **flush,  			int (*do_ops)(union mm_context *, struct host_vm_op *,  				      int, int, void **)) @@ -99,8 +97,7 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,  		last = &ops[*index];  		if((last->type == MPROTECT) &&  		   (last->u.mprotect.addr + last->u.mprotect.len == addr) && -		   (last->u.mprotect.r == r) && (last->u.mprotect.w == w) && -		   (last->u.mprotect.x == x)){ +		   (last->u.mprotect.prot == prot)){  			last->u.mprotect.len += len;  			return 0;  		} @@ -115,114 +112,145 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,  			     		       .u = { .mprotect = {  						       .addr	= addr,  						       .len	= len, -						       .r	= r, -						       .w	= w, -						       .x	= x } } }); +						       .prot	= prot } } });  	return ret;  }  #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) +static inline int update_pte_range(pmd_t *pmd, unsigned long addr, +				   unsigned long end, struct host_vm_op *ops, +				   int last_op, int *op_index, int force, +				   union mm_context *mmu, void **flush, +				   int (*do_ops)(union mm_context *, +						 struct host_vm_op *, int, int, +						 void **)) +{ +	pte_t *pte; +	int r, w, x, prot, ret = 0; + +	pte = pte_offset_kernel(pmd, addr); +	do { +		r = pte_read(*pte); +		w = pte_write(*pte); +		x = pte_exec(*pte); +		if (!pte_young(*pte)) { +			r = 0; +			w = 0; +		} else if (!pte_dirty(*pte)) { +			w = 0; +		} +		prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | +			(x ? UM_PROT_EXEC : 0)); +		if(force || pte_newpage(*pte)){ +			if(pte_present(*pte)) +				ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK, +					       PAGE_SIZE, prot, ops, op_index, +					       last_op, mmu, flush, do_ops); +			else ret = add_munmap(addr, PAGE_SIZE, ops, op_index, +					      last_op, mmu, flush, do_ops); +		} +		else if(pte_newprot(*pte)) +			ret = add_mprotect(addr, PAGE_SIZE, prot, ops, op_index, +					   last_op, mmu, flush, do_ops); +		*pte = pte_mkuptodate(*pte); +	} while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret)); +	return ret; +} + +static inline int update_pmd_range(pud_t *pud, unsigned long addr, +				   unsigned long end, struct host_vm_op *ops, +				   int last_op, int *op_index, int force, +				   union mm_context *mmu, void **flush, +				   int (*do_ops)(union mm_context *, +						 struct host_vm_op *, int, int, +						 void **)) +{ +	pmd_t *pmd; +	unsigned long next; +	int ret = 0; + +	pmd = pmd_offset(pud, addr); +	do { +		next = pmd_addr_end(addr, end); +		if(!pmd_present(*pmd)){ +			if(force || pmd_newpage(*pmd)){ +				ret = add_munmap(addr, next - addr, ops, +						 op_index, last_op, mmu, +						 flush, do_ops); +				pmd_mkuptodate(*pmd); +			} +		} +		else ret = update_pte_range(pmd, addr, next, ops, last_op, +					    op_index, force, mmu, flush, +					    do_ops); +	} while (pmd++, addr = next, ((addr != end) && !ret)); +	return ret; +} + +static inline int update_pud_range(pgd_t *pgd, unsigned long addr, +				   unsigned long end, struct host_vm_op *ops, +				   int last_op, int *op_index, int force, +				   union mm_context *mmu, void **flush, +				   int (*do_ops)(union mm_context *, +						 struct host_vm_op *, int, int, +						 void **)) +{ +	pud_t *pud; +	unsigned long next; +	int ret = 0; + +	pud = pud_offset(pgd, addr); +	do { +		next = pud_addr_end(addr, end); +		if(!pud_present(*pud)){ +			if(force || pud_newpage(*pud)){ +				ret = add_munmap(addr, next - addr, ops, +						 op_index, last_op, mmu, +						 flush, do_ops); +				pud_mkuptodate(*pud); +			} +		} +		else ret = update_pmd_range(pud, addr, next, ops, last_op, +					    op_index, force, mmu, flush, +					    do_ops); +	} while (pud++, addr = next, ((addr != end) && !ret)); +	return ret; +} +  void fix_range_common(struct mm_struct *mm, unsigned long start_addr,  		      unsigned long end_addr, int force,  		      int (*do_ops)(union mm_context *, struct host_vm_op *,  				    int, int, void **))  { -	pgd_t *npgd; -	pud_t *npud; -	pmd_t *npmd; -	pte_t *npte; +	pgd_t *pgd;  	union mm_context *mmu = &mm->context; -	unsigned long addr, end; -	int r, w, x;  	struct host_vm_op ops[1]; +	unsigned long addr = start_addr, next; +	int ret = 0, last_op = ARRAY_SIZE(ops) - 1, op_index = -1;  	void *flush = NULL; -	int op_index = -1, last_op = ARRAY_SIZE(ops) - 1; -	int ret = 0; - -	if(mm == NULL) -		return;  	ops[0].type = NONE; -	for(addr = start_addr; addr < end_addr && !ret;){ -		npgd = pgd_offset(mm, addr); -		if(!pgd_present(*npgd)){ -			end = ADD_ROUND(addr, PGDIR_SIZE); -			if(end > end_addr) -				end = end_addr; -			if(force || pgd_newpage(*npgd)){ -				ret = add_munmap(addr, end - addr, ops, -						 &op_index, last_op, mmu, -						 &flush, do_ops); -				pgd_mkuptodate(*npgd); -			} -			addr = end; -			continue; -		} - -		npud = pud_offset(npgd, addr); -		if(!pud_present(*npud)){ -			end = ADD_ROUND(addr, PUD_SIZE); -			if(end > end_addr) -				end = end_addr; -			if(force || pud_newpage(*npud)){ -				ret = add_munmap(addr, end - addr, ops, -						 &op_index, last_op, mmu, -						 &flush, do_ops); -				pud_mkuptodate(*npud); -			} -			addr = end; -			continue; -		} - -		npmd = pmd_offset(npud, addr); -		if(!pmd_present(*npmd)){ -			end = ADD_ROUND(addr, PMD_SIZE); -			if(end > end_addr) -				end = end_addr; -			if(force || pmd_newpage(*npmd)){ -				ret = add_munmap(addr, end - addr, ops, +	pgd = pgd_offset(mm, addr); +	do { +		next = pgd_addr_end(addr, end_addr); +		if(!pgd_present(*pgd)){ +			if (force || pgd_newpage(*pgd)){ +				ret = add_munmap(addr, next - addr, ops,  						 &op_index, last_op, mmu,  						 &flush, do_ops); -				pmd_mkuptodate(*npmd); +				pgd_mkuptodate(*pgd);  			} -			addr = end; -			continue; -		} - -		npte = pte_offset_kernel(npmd, addr); -		r = pte_read(*npte); -		w = pte_write(*npte); -		x = pte_exec(*npte); -		if (!pte_young(*npte)) { -			r = 0; -			w = 0; -		} else if (!pte_dirty(*npte)) { -			w = 0; -		} -		if(force || pte_newpage(*npte)){ -			if(pte_present(*npte)) -				ret = add_mmap(addr, -					       pte_val(*npte) & PAGE_MASK, -					       PAGE_SIZE, r, w, x, ops, -					       &op_index, last_op, mmu, -					       &flush, do_ops); -			else ret = add_munmap(addr, PAGE_SIZE, ops, -					      &op_index, last_op, mmu, -					      &flush, do_ops);  		} -		else if(pte_newprot(*npte)) -			ret = add_mprotect(addr, PAGE_SIZE, r, w, x, ops, -					   &op_index, last_op, mmu, -					   &flush, do_ops); +		else ret = update_pud_range(pgd, addr, next, ops, last_op, +					    &op_index, force, mmu, &flush, +					    do_ops); +	} while (pgd++, addr = next, ((addr != end_addr) && !ret)); -		*npte = pte_mkuptodate(*npte); -		addr += PAGE_SIZE; -	}  	if(!ret)  		ret = (*do_ops)(mmu, ops, op_index, 1, &flush); -/* This is not an else because ret is modified above */ +	/* This is not an else because ret is modified above */  	if(ret) {  		printk("fix_range_common: failed, killing current process\n");  		force_sig(SIGKILL, current); @@ -343,12 +371,6 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr)  	return(pte_offset_map(pmd, addr));  } -void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) -{ -	address &= PAGE_MASK; -	flush_tlb_range(vma, address, address + PAGE_SIZE); -} -  void flush_tlb_all(void)  {  	flush_tlb_mm(current->mm); diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 26f15c45857..abab90c3803 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c @@ -18,8 +18,9 @@  #include "asm/current.h"  #include "asm/irq.h"  #include "sysdep/sigcontext.h" -#include "user_util.h"  #include "kern_util.h" +#include "as-layout.h" +#include "arch.h"  #include "kern.h"  #include "chan_kern.h"  #include "mconsole_kern.h" @@ -71,8 +72,8 @@ good_area:  		goto out;  	/* Don't require VM_READ|VM_EXEC for write faults! */ -        if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) -                goto out; +	if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) +		goto out;  	do {  survive: @@ -156,20 +157,23 @@ static void segv_handler(int sig, union uml_pt_regs *regs)   * the info in the regs. A pointer to the info then would   * give us bad data!   */ -unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) +unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, +		   union uml_pt_regs *regs)  {  	struct siginfo si;  	void *catcher;  	int err; -        int is_write = FAULT_WRITE(fi); -        unsigned long address = FAULT_ADDRESS(fi); +	int is_write = FAULT_WRITE(fi); +	unsigned long address = FAULT_ADDRESS(fi); -        if(!is_user && (address >= start_vm) && (address < end_vm)){ -                flush_tlb_kernel_vm(); -                return(0); -        } -	else if(current->mm == NULL) -		panic("Segfault with no mm"); +	if(!is_user && (address >= start_vm) && (address < end_vm)){ +		flush_tlb_kernel_vm(); +		return 0; +	} +	else if(current->mm == NULL) { +		show_regs(container_of(regs, struct pt_regs, regs)); +  		panic("Segfault with no mm"); +	}  	if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi))  		err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); @@ -182,26 +186,28 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)  	catcher = current->thread.fault_catcher;  	if(!err) -		return(0); +		return 0;  	else if(catcher != NULL){  		current->thread.fault_addr = (void *) address;  		do_longjmp(catcher, 1);  	}  	else if(current->thread.fault_addr != NULL)  		panic("fault_addr set but no fault catcher"); -        else if(!is_user && arch_fixup(ip, sc)) -		return(0); +	else if(!is_user && arch_fixup(ip, regs)) +		return 0; - 	if(!is_user) +	if(!is_user) { +		show_regs(container_of(regs, struct pt_regs, regs));  		panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",  		      address, ip); +	}  	if (err == -EACCES) {  		si.si_signo = SIGBUS;  		si.si_errno = 0;  		si.si_code = BUS_ADRERR;  		si.si_addr = (void __user *)address; -                current->thread.arch.faultinfo = fi; +		current->thread.arch.faultinfo = fi;  		force_sig_info(SIGBUS, &si, current);  	} else if (err == -ENOMEM) {  		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)  		BUG_ON(err != -EFAULT);  		si.si_signo = SIGSEGV;  		si.si_addr = (void __user *) address; -                current->thread.arch.faultinfo = fi; +		current->thread.arch.faultinfo = fi;  		force_sig_info(SIGSEGV, &si, current);  	} -	return(0); +	return 0;  }  void relay_signal(int sig, union uml_pt_regs *regs) @@ -223,12 +229,12 @@ void relay_signal(int sig, union uml_pt_regs *regs)  	if(!UPT_IS_USER(regs)){  		if(sig == SIGBUS) -			printk("Bus error - the /dev/shm or /tmp mount likely " -			       "just ran out of space\n"); +			printk("Bus error - the host /dev/shm or /tmp mount " +			       "likely just ran out of space\n");  		panic("Kernel mode signal %d", sig);  	} -        current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); +	current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);  	force_sig(sig, current);  } diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c index ad66df17d9d..40126cb5180 100644 --- a/arch/um/kernel/tt/exec_kern.c +++ b/arch/um/kernel/tt/exec_kern.c @@ -10,7 +10,6 @@  #include "asm/uaccess.h"  #include "asm/pgalloc.h"  #include "asm/tlbflush.h" -#include "user_util.h"  #include "kern_util.h"  #include "irq_user.h"  #include "mem_user.h" @@ -58,7 +57,7 @@ void flush_thread_tt(void)  	enable_timer();  	free_page(stack);  	protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); -	task_protections((unsigned long) current_thread); +	stack_protections((unsigned long) current_thread);  	force_flush_all();  	unblock_signals();  } diff --git a/arch/um/kernel/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c index a92c02ff2ce..7b5f2181cf5 100644 --- a/arch/um/kernel/tt/exec_user.c +++ b/arch/um/kernel/tt/exec_user.c @@ -10,7 +10,6 @@  #include <errno.h>  #include <sys/wait.h>  #include <signal.h> -#include "user_util.h"  #include "kern_util.h"  #include "user.h"  #include "ptrace_user.h" diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c index 8eba8f7dca6..030e4658f36 100644 --- a/arch/um/kernel/tt/gdb.c +++ b/arch/um/kernel/tt/gdb.c @@ -17,7 +17,6 @@  #include "user.h"  #include "debug.h"  #include "kern_util.h" -#include "user_util.h"  #include "tt.h"  #include "sysdep/thread.h"  #include "os.h" @@ -115,6 +114,8 @@ struct gdb_data {  	int err;  }; +extern char *linux_prog; +  static void config_gdb_cb(void *arg)  {  	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 2a35b15c5fe..00000000000 --- a/arch/um/kernel/tt/include/mode_kern-tt.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __TT_MODE_KERN_H__ -#define __TT_MODE_KERN_H__ - -#include "linux/sched.h" -#include "asm/page.h" -#include "asm/ptrace.h" -#include "asm/uaccess.h" - -extern void switch_to_tt(void *prev, void *next); -extern void flush_thread_tt(void); -extern void start_thread_tt(struct pt_regs *regs, unsigned long eip, -			   unsigned long esp); -extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, -			  unsigned long stack_top, struct task_struct *p, -			  struct pt_regs *regs); -extern void release_thread_tt(struct task_struct *task); -extern void initial_thread_cb_tt(void (*proc)(void *), void *arg); -extern void init_idle_tt(void); -extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end); -extern void flush_tlb_kernel_vm_tt(void); -extern void __flush_tlb_one_tt(unsigned long addr); -extern void flush_tlb_range_tt(struct vm_area_struct *vma, -			       unsigned long start, unsigned long end); -extern void flush_tlb_mm_tt(struct mm_struct *mm); -extern void force_flush_all_tt(void); -extern long execute_syscall_tt(void *r); -extern void before_mem_tt(unsigned long brk_start); -extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out, -				       unsigned long *task_size_out); -extern int start_uml_tt(void); -extern int external_pid_tt(struct task_struct *task); -extern int thread_pid_tt(struct task_struct *task); - -#define kmem_end_tt (host_task_size - ABOVE_KMEM) - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only.  This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c index 4d1929dfa28..d0c3c4975f2 100644 --- a/arch/um/kernel/tt/mem.c +++ b/arch/um/kernel/tt/mem.c @@ -8,7 +8,6 @@  #include "asm/uaccess.h"  #include "mem_user.h"  #include "kern_util.h" -#include "user_util.h"  #include "kern.h"  #include "tt.h" diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c index 03e58989538..9774f6360c3 100644 --- a/arch/um/kernel/tt/mem_user.c +++ b/arch/um/kernel/tt/mem_user.c @@ -11,7 +11,6 @@  #include <sys/mman.h>  #include "tt.h"  #include "mem_user.h" -#include "user_util.h"  #include "os.h"  void 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 1e86f0bfef7..74347adf81b 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c @@ -14,7 +14,6 @@  #include "asm/tlbflush.h"  #include "irq_user.h"  #include "kern_util.h" -#include "user_util.h"  #include "os.h"  #include "kern.h"  #include "sigcontext.h" @@ -65,7 +64,8 @@ void switch_to_tt(void *prev, void *next)  	if(from->thread.mode.tt.switch_pipe[0] == -1)  		os_kill_process(os_getpid(), 0); -	err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c)); +	err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, +			     sizeof(c));  	if(err != sizeof(c))  		panic("read of switch_pipe failed, errno = %d", -err); @@ -209,7 +209,7 @@ void finish_fork_handler(int sig)  	if(current->mm != current->parent->mm)  		protect_memory(uml_reserved, high_physmem - uml_reserved, 1,   			       1, 0, 1); -	task_protections((unsigned long) current_thread); +	stack_protections((unsigned long) current_thread);  	free_page(current->thread.temp_stack);  	local_irq_disable(); diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c index 58800c50b10..420c23f311f 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  #include "sysdep.h"  #include "wait.h" -#include "user_util.h"  #include "user.h"  #include "os.h"  #include "tempfile.h" @@ -339,11 +338,12 @@ int start_debugger(char *prog, int startup, int stop, int *fd_out)  			       "err = %d\n", -fd);  			exit(1);  		} -		os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1); +		os_write_file(fd, gdb_init_string, +			      sizeof(gdb_init_string) - 1);  		if(startup){  			if(stop){  				os_write_file(fd, "b start_kernel\n", -				      strlen("b start_kernel\n")); +						strlen("b start_kernel\n"));  			}  			os_write_file(fd, "c\n", strlen("c\n"));  		} diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c index 03774427d46..4b4f6179b21 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  #include "ptproxy.h"  #include "debug.h" -#include "user_util.h"  #include "kern_util.h"  #include "ptrace_user.h"  #include "tt.h" diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c index 99f178319d0..e0e1ab0588a 100644 --- a/arch/um/kernel/tt/ptproxy/sysdep.c +++ b/arch/um/kernel/tt/ptproxy/sysdep.c @@ -13,7 +13,6 @@ terms and conditions.  #include <sys/types.h>  #include <linux/unistd.h>  #include "ptrace_user.h" -#include "user_util.h"  #include "user.h"  #include "os.h" diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c index 12f6319d8d7..bdd4af4b65f 100644 --- a/arch/um/kernel/tt/ptproxy/wait.c +++ b/arch/um/kernel/tt/ptproxy/wait.c @@ -13,7 +13,6 @@ terms and conditions.  #include "ptproxy.h"  #include "sysdep.h"  #include "wait.h" -#include "user_util.h"  #include "ptrace_user.h"  #include "sysdep/ptrace.h"  #include "sysdep/sigcontext.h" diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c index 902987bf379..f52b47aff1d 100644 --- a/arch/um/kernel/tt/syscall_user.c +++ b/arch/um/kernel/tt/syscall_user.c @@ -11,7 +11,6 @@  #include "sigcontext.h"  #include "ptrace_user.h"  #include "task.h" -#include "user_util.h"  #include "kern_util.h"  #include "syscall.h"  #include "tt.h" diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c index ae6217c8613..7caa24fe05d 100644 --- a/arch/um/kernel/tt/tlb.c +++ b/arch/um/kernel/tt/tlb.c @@ -12,7 +12,6 @@  #include "asm/pgtable.h"  #include "asm/uaccess.h"  #include "asm/tlbflush.h" -#include "user_util.h"  #include "mem_user.h"  #include "os.h"  #include "tlb.h" diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c index b9195355075..c23588393f6 100644 --- a/arch/um/kernel/tt/tracer.c +++ b/arch/um/kernel/tt/tracer.c @@ -19,7 +19,6 @@  #include "sigcontext.h"  #include "sysdep/sigcontext.h"  #include "os.h" -#include "user_util.h"  #include "mem_user.h"  #include "process.h"  #include "kern_util.h" diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c index b5d9d64d91e..3032eb5e246 100644 --- a/arch/um/kernel/tt/trap_user.c +++ b/arch/um/kernel/tt/trap_user.c @@ -8,7 +8,6 @@  #include <signal.h>  #include "sysdep/ptrace.h"  #include "sysdep/sigcontext.h" -#include "user_util.h"  #include "kern_util.h"  #include "task.h"  #include "tt.h" diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c index ed1abcf4d05..0e5c82c5e5b 100644 --- a/arch/um/kernel/tt/uaccess_user.c +++ b/arch/um/kernel/tt/uaccess_user.c @@ -5,7 +5,6 @@   */  #include <string.h> -#include "user_util.h"  #include "uml_uaccess.h"  #include "task.h"  #include "kern_util.h" diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 89c6dba731f..ecc458fe51b 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -17,6 +17,7 @@  #include "linux/seq_file.h"  #include "linux/delay.h"  #include "linux/module.h" +#include "linux/utsname.h"  #include "asm/page.h"  #include "asm/pgtable.h"  #include "asm/ptrace.h" @@ -25,8 +26,9 @@  #include "asm/setup.h"  #include "ubd_user.h"  #include "asm/current.h" -#include "user_util.h"  #include "kern_util.h" +#include "as-layout.h" +#include "arch.h"  #include "kern.h"  #include "mem_user.h"  #include "mem.h" @@ -42,7 +44,7 @@  #define DEFAULT_COMMAND_LINE "root=98:0" -/* Changed in linux_main and setup_arch, which run before SMP is started */ +/* Changed in add_arg and setup_arch, which run before SMP is started */  static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 };  static void __init add_arg(char *arg) @@ -56,17 +58,25 @@ static void __init add_arg(char *arg)  	strcat(command_line, arg);  } -struct cpuinfo_um boot_cpu_data = {  +/* + * These fields are initialized at boot time and not changed. + * XXX This structure is used only in the non-SMP case.  Maybe this + * should be moved to smp.c. + */ +struct cpuinfo_um boot_cpu_data = {  	.loops_per_jiffy	= 0,  	.ipi_pipe		= { -1, -1 }  };  unsigned long thread_saved_pc(struct task_struct *task)  { -	return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, -					      task))); +	return os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, +					      task));  } +/* Changed in setup_arch, which is called in early boot */ +static char host_info[(__NEW_UTS_LEN + 1) * 5]; +  static int show_cpuinfo(struct seq_file *m, void *v)  {  	int index = 0; @@ -86,7 +96,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)  		   loops_per_jiffy/(500000/HZ),  		   (loops_per_jiffy/(5000/HZ)) % 100); -	return(0); +	return 0;  }  static void *c_start(struct seq_file *m, loff_t *pos) @@ -114,14 +124,12 @@ const struct seq_operations cpuinfo_op = {  /* Set in linux_main */  unsigned long host_task_size;  unsigned long task_size; - -unsigned long uml_start; - -/* Set in early boot */  unsigned long uml_physmem; -unsigned long uml_reserved; +unsigned long uml_reserved; /* Also modified in mem_init */  unsigned long start_vm;  unsigned long end_vm; + +/* Set in uml_ncpus_setup */  int ncpus = 1;  #ifdef CONFIG_CMDLINE_ON_HOST @@ -135,6 +143,8 @@ static char *argv1_end = NULL;  /* Set in early boot */  static int have_root __initdata = 0; + +/* Set in uml_mem_setup and modified in linux_main */  long long physmem_size = 32 * 1024 * 1024;  void set_cmdline(char *cmd) @@ -212,12 +222,12 @@ __uml_setup("debug", no_skas_debug_setup,  #ifdef CONFIG_SMP  static int __init uml_ncpus_setup(char *line, int *add)  { -       if (!sscanf(line, "%d", &ncpus)) { -               printf("Couldn't parse [%s]\n", line); -               return -1; -       } +	if (!sscanf(line, "%d", &ncpus)) { +		printf("Couldn't parse [%s]\n", line); +		return -1; +	} -       return 0; +	return 0;  }  __uml_setup("ncpus=", uml_ncpus_setup, @@ -234,7 +244,7 @@ static int force_tt = 0;  static int __init mode_tt_setup(char *line, int *add)  {  	force_tt = 1; -	return(0); +	return 0;  }  #else @@ -245,7 +255,7 @@ static int __init mode_tt_setup(char *line, int *add)  static int __init mode_tt_setup(char *line, int *add)  {  	printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); -	return(0); +	return 0;  }  #else @@ -256,7 +266,7 @@ static int __init mode_tt_setup(char *line, int *add)  static int __init mode_tt_setup(char *line, int *add)  {  	printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); -	return(0); +	return 0;  }  #endif @@ -274,16 +284,15 @@ int mode_tt = DEFAULT_TT;  static int __init Usage(char *line, int *add)  { - 	const char **p; +	const char **p;  	printf(usage_string, init_utsname()->release); - 	p = &__uml_help_start; - 	while (p < &__uml_help_end) { - 		printf("%s", *p); - 		p++; - 	} +	p = &__uml_help_start; +	while (p < &__uml_help_end) { +		printf("%s", *p); +		p++; +	}  	exit(0); -  	return 0;  } @@ -374,13 +383,12 @@ int __init linux_main(int argc, char **argv)  	printf("UML running in %s mode\n", mode); -	uml_start = (unsigned long) &__binary_start;  	host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt,  					  set_task_sizes_skas, &task_size);  	/* - 	 * Setting up handlers to 'sig_info' struct - 	 */ +	 * Setting up handlers to 'sig_info' struct +	 */  	os_fill_handlinfo(handlinfo_kern);  	brk_start = (unsigned long) sbrk(0); @@ -396,7 +404,7 @@ int __init linux_main(int argc, char **argv)  		physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);  	} -	uml_physmem = uml_start & PAGE_MASK; +	uml_physmem = (unsigned long) &__binary_start & PAGE_MASK;  	/* Reserve up to 4M after the current brk */  	uml_reserved = ROUND_4M(brk_start) + (1 << 22); @@ -407,7 +415,7 @@ int __init linux_main(int argc, char **argv)  	argv1_begin = argv[1];  	argv1_end = &argv[1][strlen(argv[1])];  #endif -   +  	highmem = 0;  	iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;  	max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; @@ -449,12 +457,12 @@ int __init linux_main(int argc, char **argv)  		printf("Kernel virtual memory size shrunk to %lu bytes\n",  		       virtmem_size); -  	uml_postsetup(); +	uml_postsetup(); -	task_protections((unsigned long) &init_thread_info); +	stack_protections((unsigned long) &init_thread_info);  	os_flush_stdout(); -	return(CHOOSE_MODE(start_uml_tt(), start_uml_skas())); +	return CHOOSE_MODE(start_uml_tt(), start_uml_skas());  }  extern int uml_exitcode; @@ -466,8 +474,8 @@ static int panic_exit(struct notifier_block *self, unsigned long unused1,  	show_regs(&(current->thread.regs));  	bust_spinlocks(0);  	uml_exitcode = 1; -	machine_halt(); -	return(0); +	os_dump_core(); +	return 0;  }  static struct notifier_block panic_exit_notifier = { @@ -482,14 +490,14 @@ void __init setup_arch(char **cmdline_p)  			&panic_exit_notifier);  	paging_init();  	strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); - 	*cmdline_p = command_line; -	setup_hostinfo(); +	*cmdline_p = command_line; +	setup_hostinfo(host_info, sizeof host_info);  }  void __init check_bugs(void)  {  	arch_check_bugs(); - 	os_check_bugs(); +	os_check_bugs();  }  void apply_alternatives(struct alt_instr *start, struct alt_instr *end) diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index f6301274cf3..bc59f97e34d 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S @@ -59,6 +59,8 @@ SECTIONS    {      . = ALIGN(KERNEL_STACK_SIZE);		/* init_task */      *(.data.init_task) +    . = ALIGN(KERNEL_STACK_SIZE); +    *(.data.init_irqstack)      *(.data)      *(.gnu.linkonce.d*)      CONSTRUCTORS  | 
