diff options
Diffstat (limited to 'arch/um/kernel')
| -rw-r--r-- | arch/um/kernel/Makefile | 2 | ||||
| -rw-r--r-- | arch/um/kernel/checksum.c | 0 | ||||
| -rw-r--r-- | arch/um/kernel/initrd.c | 78 | ||||
| -rw-r--r-- | arch/um/kernel/irq_user.c | 10 | ||||
| -rw-r--r-- | arch/um/kernel/ksyms.c | 1 | ||||
| -rw-r--r-- | arch/um/kernel/mem.c | 40 | ||||
| -rw-r--r-- | arch/um/kernel/ptrace.c | 6 | ||||
| -rw-r--r-- | arch/um/kernel/trap_kern.c | 36 | ||||
| -rw-r--r-- | arch/um/kernel/tt/ksyms.c | 1 | ||||
| -rw-r--r-- | arch/um/kernel/uml.lds.S | 2 |
10 files changed, 129 insertions, 47 deletions
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 9736ca27c5f0..a8918e80df96 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile | |||
| @@ -14,7 +14,7 @@ obj-y = config.o exec_kern.o exitcode.o \ | |||
| 14 | tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \ | 14 | tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \ |
| 15 | user_util.o | 15 | user_util.o |
| 16 | 16 | ||
| 17 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o | 17 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o |
| 18 | obj-$(CONFIG_GPROF) += gprof_syms.o | 18 | obj-$(CONFIG_GPROF) += gprof_syms.o |
| 19 | obj-$(CONFIG_GCOV) += gmon_syms.o | 19 | obj-$(CONFIG_GCOV) += gmon_syms.o |
| 20 | obj-$(CONFIG_TTY_LOG) += tty_log.o | 20 | obj-$(CONFIG_TTY_LOG) += tty_log.o |
diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c deleted file mode 100644 index e69de29bb2d1..000000000000 --- a/arch/um/kernel/checksum.c +++ /dev/null | |||
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c new file mode 100644 index 000000000000..82ecf904b09c --- /dev/null +++ b/arch/um/kernel/initrd.c | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include "linux/init.h" | ||
| 7 | #include "linux/bootmem.h" | ||
| 8 | #include "linux/initrd.h" | ||
| 9 | #include "asm/types.h" | ||
| 10 | #include "user_util.h" | ||
| 11 | #include "kern_util.h" | ||
| 12 | #include "initrd.h" | ||
| 13 | #include "init.h" | ||
| 14 | #include "os.h" | ||
| 15 | |||
| 16 | /* Changed by uml_initrd_setup, which is a setup */ | ||
| 17 | static char *initrd __initdata = NULL; | ||
| 18 | |||
| 19 | static int __init read_initrd(void) | ||
| 20 | { | ||
| 21 | void *area; | ||
| 22 | long long size; | ||
| 23 | int err; | ||
| 24 | |||
| 25 | if(initrd == NULL) return 0; | ||
| 26 | err = os_file_size(initrd, &size); | ||
| 27 | if(err) return 0; | ||
| 28 | area = alloc_bootmem(size); | ||
| 29 | if(area == NULL) return 0; | ||
| 30 | if(load_initrd(initrd, area, size) == -1) return 0; | ||
| 31 | initrd_start = (unsigned long) area; | ||
| 32 | initrd_end = initrd_start + size; | ||
| 33 | return 0; | ||
| 34 | } | ||
| 35 | |||
| 36 | __uml_postsetup(read_initrd); | ||
| 37 | |||
| 38 | static int __init uml_initrd_setup(char *line, int *add) | ||
| 39 | { | ||
| 40 | initrd = line; | ||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | |||
| 44 | __uml_setup("initrd=", uml_initrd_setup, | ||
| 45 | "initrd=<initrd image>\n" | ||
| 46 | " This is used to boot UML from an initrd image. The argument is the\n" | ||
| 47 | " name of the file containing the image.\n\n" | ||
| 48 | ); | ||
| 49 | |||
| 50 | int load_initrd(char *filename, void *buf, int size) | ||
| 51 | { | ||
| 52 | int fd, n; | ||
| 53 | |||
| 54 | fd = os_open_file(filename, of_read(OPENFLAGS()), 0); | ||
| 55 | if(fd < 0){ | ||
| 56 | printk("Opening '%s' failed - err = %d\n", filename, -fd); | ||
| 57 | return(-1); | ||
| 58 | } | ||
| 59 | n = os_read_file(fd, buf, size); | ||
| 60 | if(n != size){ | ||
| 61 | printk("Read of %d bytes from '%s' failed, err = %d\n", size, | ||
| 62 | filename, -n); | ||
| 63 | return(-1); | ||
| 64 | } | ||
| 65 | |||
| 66 | os_close_file(fd); | ||
| 67 | return(0); | ||
| 68 | } | ||
| 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_user.c b/arch/um/kernel/irq_user.c index 6d6f9484b884..b3074cbaa479 100644 --- a/arch/um/kernel/irq_user.c +++ b/arch/um/kernel/irq_user.c | |||
| @@ -236,9 +236,15 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) | |||
| 236 | (*prev)->fd, pollfds[i].fd); | 236 | (*prev)->fd, pollfds[i].fd); |
| 237 | goto out; | 237 | goto out; |
| 238 | } | 238 | } |
| 239 | memcpy(&pollfds[i], &pollfds[i + 1], | 239 | |
| 240 | (pollfds_num - i - 1) * sizeof(pollfds[0])); | ||
| 241 | pollfds_num--; | 240 | pollfds_num--; |
| 241 | |||
| 242 | /* This moves the *whole* array after pollfds[i] (though | ||
| 243 | * it doesn't spot as such)! */ | ||
| 244 | |||
| 245 | memmove(&pollfds[i], &pollfds[i + 1], | ||
| 246 | (pollfds_num - i) * sizeof(pollfds[0])); | ||
| 247 | |||
| 242 | if(last_irq_ptr == &old_fd->next) | 248 | if(last_irq_ptr == &old_fd->next) |
| 243 | last_irq_ptr = prev; | 249 | last_irq_ptr = prev; |
| 244 | *prev = (*prev)->next; | 250 | *prev = (*prev)->next; |
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index 78d69dc74b26..99439fa15ef4 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c | |||
| @@ -57,6 +57,7 @@ EXPORT_SYMBOL(copy_to_user_tt); | |||
| 57 | EXPORT_SYMBOL(strncpy_from_user_skas); | 57 | EXPORT_SYMBOL(strncpy_from_user_skas); |
| 58 | EXPORT_SYMBOL(copy_to_user_skas); | 58 | EXPORT_SYMBOL(copy_to_user_skas); |
| 59 | EXPORT_SYMBOL(copy_from_user_skas); | 59 | EXPORT_SYMBOL(copy_from_user_skas); |
| 60 | EXPORT_SYMBOL(clear_user_skas); | ||
| 60 | #endif | 61 | #endif |
| 61 | EXPORT_SYMBOL(uml_strdup); | 62 | EXPORT_SYMBOL(uml_strdup); |
| 62 | 63 | ||
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index f156661781cb..c22825f13e40 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c | |||
| @@ -100,12 +100,37 @@ void mem_init(void) | |||
| 100 | #endif | 100 | #endif |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | /* | ||
| 104 | * Create a page table and place a pointer to it in a middle page | ||
| 105 | * directory entry. | ||
| 106 | */ | ||
| 107 | static void __init one_page_table_init(pmd_t *pmd) | ||
| 108 | { | ||
| 109 | if (pmd_none(*pmd)) { | ||
| 110 | pte_t *pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); | ||
| 111 | set_pmd(pmd, __pmd(_KERNPG_TABLE + | ||
| 112 | (unsigned long) __pa(pte))); | ||
| 113 | if (pte != pte_offset_kernel(pmd, 0)) | ||
| 114 | BUG(); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | static void __init one_md_table_init(pud_t *pud) | ||
| 119 | { | ||
| 120 | #ifdef CONFIG_3_LEVEL_PGTABLES | ||
| 121 | pmd_t *pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); | ||
| 122 | set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table))); | ||
| 123 | if (pmd_table != pmd_offset(pud, 0)) | ||
| 124 | BUG(); | ||
| 125 | #endif | ||
| 126 | } | ||
| 127 | |||
| 103 | static void __init fixrange_init(unsigned long start, unsigned long end, | 128 | static void __init fixrange_init(unsigned long start, unsigned long end, |
| 104 | pgd_t *pgd_base) | 129 | pgd_t *pgd_base) |
| 105 | { | 130 | { |
| 106 | pgd_t *pgd; | 131 | pgd_t *pgd; |
| 132 | pud_t *pud; | ||
| 107 | pmd_t *pmd; | 133 | pmd_t *pmd; |
| 108 | pte_t *pte; | ||
| 109 | int i, j; | 134 | int i, j; |
| 110 | unsigned long vaddr; | 135 | unsigned long vaddr; |
| 111 | 136 | ||
| @@ -115,15 +140,12 @@ static void __init fixrange_init(unsigned long start, unsigned long end, | |||
| 115 | pgd = pgd_base + i; | 140 | pgd = pgd_base + i; |
| 116 | 141 | ||
| 117 | for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) { | 142 | for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) { |
| 118 | pmd = (pmd_t *)pgd; | 143 | pud = pud_offset(pgd, vaddr); |
| 144 | if (pud_none(*pud)) | ||
| 145 | one_md_table_init(pud); | ||
| 146 | pmd = pmd_offset(pud, vaddr); | ||
| 119 | for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { | 147 | for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { |
| 120 | if (pmd_none(*pmd)) { | 148 | one_page_table_init(pmd); |
| 121 | pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); | ||
| 122 | set_pmd(pmd, __pmd(_KERNPG_TABLE + | ||
| 123 | (unsigned long) __pa(pte))); | ||
| 124 | if (pte != pte_offset_kernel(pmd, 0)) | ||
| 125 | BUG(); | ||
| 126 | } | ||
| 127 | vaddr += PMD_SIZE; | 149 | vaddr += PMD_SIZE; |
| 128 | } | 150 | } |
| 129 | j = 0; | 151 | j = 0; |
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 2b75d8d9ba73..2925e15324de 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c | |||
| @@ -28,9 +28,9 @@ static inline void set_singlestepping(struct task_struct *child, int on) | |||
| 28 | child->thread.singlestep_syscall = 0; | 28 | child->thread.singlestep_syscall = 0; |
| 29 | 29 | ||
| 30 | #ifdef SUBARCH_SET_SINGLESTEPPING | 30 | #ifdef SUBARCH_SET_SINGLESTEPPING |
| 31 | SUBARCH_SET_SINGLESTEPPING(child, on) | 31 | SUBARCH_SET_SINGLESTEPPING(child, on); |
| 32 | #endif | 32 | #endif |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | /* | 35 | /* |
| 36 | * Called by kernel/ptrace.c when detaching.. | 36 | * Called by kernel/ptrace.c when detaching.. |
| @@ -83,7 +83,7 @@ long sys_ptrace(long request, long pid, long addr, long data) | |||
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | #ifdef SUBACH_PTRACE_SPECIAL | 85 | #ifdef SUBACH_PTRACE_SPECIAL |
| 86 | SUBARCH_PTRACE_SPECIAL(child,request,addr,data) | 86 | SUBARCH_PTRACE_SPECIAL(child,request,addr,data); |
| 87 | #endif | 87 | #endif |
| 88 | 88 | ||
| 89 | ret = ptrace_check_attach(child, request == PTRACE_KILL); | 89 | ret = ptrace_check_attach(child, request == PTRACE_KILL); |
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 5fca2c61eb98..1de22d8a313a 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c | |||
| @@ -57,10 +57,11 @@ int handle_page_fault(unsigned long address, unsigned long ip, | |||
| 57 | *code_out = SEGV_ACCERR; | 57 | *code_out = SEGV_ACCERR; |
| 58 | if(is_write && !(vma->vm_flags & VM_WRITE)) | 58 | if(is_write && !(vma->vm_flags & VM_WRITE)) |
| 59 | goto out; | 59 | goto out; |
| 60 | |||
| 61 | if(!(vma->vm_flags & (VM_READ | VM_EXEC))) | ||
| 62 | goto out; | ||
| 63 | |||
| 60 | page = address & PAGE_MASK; | 64 | page = address & PAGE_MASK; |
| 61 | pgd = pgd_offset(mm, page); | ||
| 62 | pud = pud_offset(pgd, page); | ||
| 63 | pmd = pmd_offset(pud, page); | ||
| 64 | do { | 65 | do { |
| 65 | survive: | 66 | survive: |
| 66 | switch (handle_mm_fault(mm, vma, address, is_write)){ | 67 | switch (handle_mm_fault(mm, vma, address, is_write)){ |
| @@ -106,33 +107,6 @@ out_of_memory: | |||
| 106 | goto out; | 107 | goto out; |
| 107 | } | 108 | } |
| 108 | 109 | ||
| 109 | LIST_HEAD(physmem_remappers); | ||
| 110 | |||
| 111 | void register_remapper(struct remapper *info) | ||
| 112 | { | ||
| 113 | list_add(&info->list, &physmem_remappers); | ||
| 114 | } | ||
| 115 | |||
| 116 | static int check_remapped_addr(unsigned long address, int is_write) | ||
| 117 | { | ||
| 118 | struct remapper *remapper; | ||
| 119 | struct list_head *ele; | ||
| 120 | __u64 offset; | ||
| 121 | int fd; | ||
| 122 | |||
| 123 | fd = phys_mapping(__pa(address), &offset); | ||
| 124 | if(fd == -1) | ||
| 125 | return(0); | ||
| 126 | |||
| 127 | list_for_each(ele, &physmem_remappers){ | ||
| 128 | remapper = list_entry(ele, struct remapper, list); | ||
| 129 | if((*remapper->proc)(fd, address, is_write, offset)) | ||
| 130 | return(1); | ||
| 131 | } | ||
| 132 | |||
| 133 | return(0); | ||
| 134 | } | ||
| 135 | |||
| 136 | /* | 110 | /* |
| 137 | * We give a *copy* of the faultinfo in the regs to segv. | 111 | * We give a *copy* of the faultinfo in the regs to segv. |
| 138 | * This must be done, since nesting SEGVs could overwrite | 112 | * This must be done, since nesting SEGVs could overwrite |
| @@ -151,8 +125,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) | |||
| 151 | flush_tlb_kernel_vm(); | 125 | flush_tlb_kernel_vm(); |
| 152 | return(0); | 126 | return(0); |
| 153 | } | 127 | } |
| 154 | else if(check_remapped_addr(address & PAGE_MASK, is_write)) | ||
| 155 | return(0); | ||
| 156 | else if(current->mm == NULL) | 128 | else if(current->mm == NULL) |
| 157 | panic("Segfault with no mm"); | 129 | panic("Segfault with no mm"); |
| 158 | err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); | 130 | err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); |
diff --git a/arch/um/kernel/tt/ksyms.c b/arch/um/kernel/tt/ksyms.c index 92ec85d67c7c..84a9385a8fef 100644 --- a/arch/um/kernel/tt/ksyms.c +++ b/arch/um/kernel/tt/ksyms.c | |||
| @@ -12,6 +12,7 @@ EXPORT_SYMBOL(__do_copy_to_user); | |||
| 12 | EXPORT_SYMBOL(__do_strncpy_from_user); | 12 | EXPORT_SYMBOL(__do_strncpy_from_user); |
| 13 | EXPORT_SYMBOL(__do_strnlen_user); | 13 | EXPORT_SYMBOL(__do_strnlen_user); |
| 14 | EXPORT_SYMBOL(__do_clear_user); | 14 | EXPORT_SYMBOL(__do_clear_user); |
| 15 | EXPORT_SYMBOL(clear_user_tt); | ||
| 15 | 16 | ||
| 16 | EXPORT_SYMBOL(tracing_pid); | 17 | EXPORT_SYMBOL(tracing_pid); |
| 17 | EXPORT_SYMBOL(honeypot); | 18 | EXPORT_SYMBOL(honeypot); |
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index 76eadb309189..dd5355500bdc 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S | |||
| @@ -73,6 +73,8 @@ SECTIONS | |||
| 73 | 73 | ||
| 74 | .got : { *(.got.plt) *(.got) } | 74 | .got : { *(.got.plt) *(.got) } |
| 75 | .dynamic : { *(.dynamic) } | 75 | .dynamic : { *(.dynamic) } |
| 76 | .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } | ||
| 77 | .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } | ||
| 76 | /* We want the small data sections together, so single-instruction offsets | 78 | /* We want the small data sections together, so single-instruction offsets |
| 77 | can access them all, and initialized data all before uninitialized, so | 79 | can access them all, and initialized data all before uninitialized, so |
| 78 | we can shorten the on-disk segment size. */ | 80 | we can shorten the on-disk segment size. */ |
