diff -Naur -X exclude-files ac_cur/arch/um/Makefile ac/arch/um/Makefile --- ac_cur/arch/um/Makefile Fri Oct 5 14:16:42 2001 +++ ac/arch/um/Makefile Fri Oct 5 14:43:33 2001 @@ -45,9 +45,9 @@ LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc $(ARCH_DIR)/link.ld: - m4 -DSTART=$(shell echo $$((($(NESTING) + 1) * $(START_ADDR)))) \ - -DSUBARCH=$(SUBARCH) -DELF_SUBARCH=$(ELF_SUBARCH) \ - $(ARCH_DIR)/link.ld.in > $(ARCH_DIR)/link.ld + m4 -DSTART=$(START_ADDR) -DSUBARCH=$(SUBARCH) \ + -DELF_SUBARCH=$(ELF_SUBARCH) \ + $(ARCH_DIR)/link.ld.in > $(ARCH_DIR)/link.ld SYMLINK_HEADERS = include/asm-um/archparam.h include/asm-um/system.h \ include/asm-um/sigcontext.h include/asm-um/processor.h diff -Naur -X exclude-files ac_cur/arch/um/Makefile-i386 ac/arch/um/Makefile-i386 --- ac_cur/arch/um/Makefile-i386 Fri Oct 5 14:15:35 2001 +++ ac/arch/um/Makefile-i386 Fri Oct 5 14:43:33 2001 @@ -1,3 +1,8 @@ -START_ADDR = 0x10000000 +ifeq ($(CONFIG_HOST_2G_2G), y) +START_ADDR = 0x60000000 +else +START_ADDR = 0xa0000000 +endif + ARCH_CFLAGS = -U__$(SUBARCH)__ -U$(SUBARCH) -DUM_FASTCALL ELF_SUBARCH = $(SUBARCH) diff -Naur -X exclude-files ac_cur/arch/um/config.in ac/arch/um/config.in --- ac_cur/arch/um/config.in Fri Oct 5 14:16:42 2001 +++ ac/arch/um/config.in Fri Oct 5 14:43:33 2001 @@ -33,6 +33,7 @@ tristate 'Host filesystem' CONFIG_HOSTFS bool 'Management console' CONFIG_MCONSOLE dep_bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ $CONFIG_MCONSOLE +bool '2G/2G host address space split' CONFIG_HOST_2G_2G endmenu mainmenu_option next_comment diff -Naur -X exclude-files ac_cur/arch/um/defconfig ac/arch/um/defconfig --- ac_cur/arch/um/defconfig Fri Oct 5 14:15:35 2001 +++ ac/arch/um/defconfig Fri Oct 5 14:43:33 2001 @@ -30,6 +30,7 @@ CONFIG_HOSTFS=m CONFIG_MCONSOLE=y CONFIG_MAGIC_SYSRQ=y +# CONFIG_HOST_2G_2G is not set # # Loadable module support diff -Naur -X exclude-files ac_cur/arch/um/include/kern_util.h ac/arch/um/include/kern_util.h --- ac_cur/arch/um/include/kern_util.h Fri Oct 5 14:16:42 2001 +++ ac/arch/um/include/kern_util.h Fri Oct 5 14:43:33 2001 @@ -39,8 +39,6 @@ extern int is_tracing(void *task); extern int segv_syscall(void); extern void ret_from_sys_call(void *t); -extern void add_perm_vma(unsigned long start, unsigned long end, char rperm, - char wperm, char xperm, char private); extern void kern_finish_exec(void *task, int new_pid, unsigned long stack); extern int page_size(void); extern int page_mask(void); @@ -91,7 +89,6 @@ extern void debugger_signal(int status, int pid); extern void child_signal(int pid, int status); extern int init_ptrace_proxy(int idle_pid, int startup, int stop); -extern void add_process_vmas(void); extern void check_stack_overflow(void *ptr); extern void relay_signal(int sig, void *sc, int usermode); extern int singlestepping(void *t); @@ -120,6 +117,8 @@ extern char *uml_strdup(char *string); extern void unprotect_kernel_mem(void); extern void protect_kernel_mem(void); +extern unsigned long get_kmem_end(void); +extern void set_kmem_end(unsigned long); #endif /* diff -Naur -X exclude-files ac_cur/arch/um/include/mem_user.h ac/arch/um/include/mem_user.h --- ac_cur/arch/um/include/mem_user.h Fri Oct 5 14:15:35 2001 +++ ac/arch/um/include/mem_user.h Fri Oct 5 14:43:33 2001 @@ -32,6 +32,11 @@ #ifndef _MEM_USER_H #define _MEM_USER_H +#define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1)) + +extern unsigned long host_task_size; +extern unsigned long task_size; + extern int create_mem_file(unsigned long len); extern void setup_range(int fd, char *driver, unsigned long start, unsigned long usable, unsigned long total); diff -Naur -X exclude-files ac_cur/arch/um/include/user_util.h ac/arch/um/include/user_util.h --- ac_cur/arch/um/include/user_util.h Fri Oct 5 14:16:42 2001 +++ ac/arch/um/include/user_util.h Fri Oct 5 14:43:33 2001 @@ -76,8 +76,6 @@ extern int start_fork_tramp(unsigned long sig_stack, unsigned long temp_stack, int clone_vm, int (*tramp)(void *)); extern void trace_myself(void); -extern void block_shlib_mem(void); -extern void unblock_shlib_mem(void); extern void timer(void); extern void get_profile_timer(void); extern void disable_profile_timer(void); @@ -129,7 +127,6 @@ extern char *get_umid(void); extern void ptrace_cont_pid(int pid); extern void create_pid_file(char *name); -extern void remap_profiling_buffers(void); extern int load_initrd(char *filename, void *buf, int size); extern int ptrace_getregs(long pid, struct sys_pt_regs *regs_out); extern int ptrace_setregs(long pid, struct sys_pt_regs *regs_in); diff -Naur -X exclude-files ac_cur/arch/um/kernel/exec_kern.c ac/arch/um/kernel/exec_kern.c --- ac_cur/arch/um/kernel/exec_kern.c Fri Oct 5 14:16:42 2001 +++ ac/arch/um/kernel/exec_kern.c Fri Oct 5 14:43:33 2001 @@ -8,35 +8,11 @@ #include "asm/ptrace.h" #include "asm/pgtable.h" #include "asm/pgalloc.h" +#include "asm/uaccess.h" #include "user_util.h" #include "kern_util.h" #include "kern.h" -extern struct mm_struct kernel_maps; - -static void add_kernel_vma(struct task_struct *task) -{ - struct vm_area_struct *vma, *new; - - if(task->mm != init_task.mm){ - for(vma = kernel_maps.mmap;vma != NULL;vma = vma->vm_next){ - new = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); - if(!new) panic("No memory in add_kernel_vma"); - *new = *vma; - new->vm_next = NULL; - new->vm_flags |= VM_LOCKED; - new->vm_avl_height = 0; - new->vm_avl_left = NULL; - new->vm_avl_right = NULL; - new->vm_next_share = NULL; - new->vm_pprev_share = NULL; - if(new->vm_file != NULL) - atomic_inc(&new->vm_file->f_count); - insert_vm_struct(task->mm, new); - } - } -} - static void check_vma(unsigned long addr) { struct vm_area_struct *vma; @@ -93,8 +69,7 @@ { check_vma(current->mm->brk - 1); check_vma(eip); - current->addr_limit.seg = STACK_TOP; - add_kernel_vma(current); + set_fs(USER_DS); flush_tlb_mm(current->mm); if(UM_SP(¤t->thread.process_regs) == 0) current->thread.process_regs = current->thread.syscall_regs; diff -Naur -X exclude-files ac_cur/arch/um/kernel/mem.c ac/arch/um/kernel/mem.c --- ac_cur/arch/um/kernel/mem.c Fri Oct 5 14:15:35 2001 +++ ac/arch/um/kernel/mem.c Fri Oct 5 14:43:33 2001 @@ -14,8 +14,10 @@ #include "asm/pgtable.h" #include "asm/pgalloc.h" #include "asm/bitops.h" +#include "asm/uaccess.h" #include "user_util.h" #include "kern_util.h" +#include "mem_user.h" #include "kern.h" unsigned long high_physmem; @@ -177,6 +179,19 @@ printk("%d pages swap cached\n",cached); printk("%ld pages in page table cache\n",pgtable_cache_size); show_buffers(); +} + +unsigned long kmem_top = 0; + +unsigned long get_kmem_end(void) +{ + if(kmem_top == 0) kmem_top = host_task_size - ABOVE_KMEM; + return(kmem_top); +} + +void set_kmem_end(unsigned long new) +{ + kmem_top = new; } /* diff -Naur -X exclude-files ac_cur/arch/um/kernel/process.c ac/arch/um/kernel/process.c --- ac_cur/arch/um/kernel/process.c Fri Oct 5 14:15:35 2001 +++ ac/arch/um/kernel/process.c Fri Oct 5 14:43:33 2001 @@ -318,30 +318,6 @@ while(1) sleep(10); } -#ifdef PROFILING -void remap_profiling_buffers(void) -{ - unsigned long low = 1 << 31, high = 0; - - if((unsigned long) _gmonparam.kcount < low) - low = (unsigned long) _gmonparam.kcount; - if((unsigned long) _gmonparam.froms < low) - low = (unsigned long) _gmonparam.froms; - if((unsigned long) _gmonparam.tos < low) - low = (unsigned long) _gmonparam.tos; - - if((unsigned long) _gmonparam.kcount + _gmonparam.kcountsize > high) - high = (unsigned long) _gmonparam.kcount + - _gmonparam.kcountsize; - if((unsigned long) _gmonparam.froms + _gmonparam.fromssize > high) - high = (unsigned long) _gmonparam.froms + _gmonparam.fromssize; - if((unsigned long) _gmonparam.tos + _gmonparam.tossize > high) - high = (unsigned long) _gmonparam.tos + _gmonparam.tossize; - - remap_data((void *) round_down(low), (void *) round_up(high)); -} -#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 diff -Naur -X exclude-files ac_cur/arch/um/kernel/process_kern.c ac/arch/um/kernel/process_kern.c --- ac_cur/arch/um/kernel/process_kern.c Fri Oct 5 14:16:42 2001 +++ ac/arch/um/kernel/process_kern.c Fri Oct 5 14:43:33 2001 @@ -111,7 +111,7 @@ task->thread.extern_pid = pid; stop_pid(pid); set_cmdline("(kernel thread)"); - init_flush_vm(); + flush_tlb_all(); if(current->thread.request.u.cswitch.from != NULL) schedule_tail(current->thread.request.u.cswitch.from); (*fn)(arg); @@ -211,7 +211,7 @@ forward_interrupts(to->thread.extern_pid); block_signals(); usr1_pid(getpid()); - flush_tlb_kernel_vm(); + flush_tlb_all(); unblock_signals(); return(current->thread.request.u.cswitch.from); } @@ -502,8 +502,7 @@ void finish_fork_handler(int sig) { - init_flush_vm(); - flush_tlb_kernel_vm(); + force_flush_all(); if(current->mm != current->p_pptr->mm) protect(physmem, high_physmem - physmem, 1, 1, 0); task_protections((unsigned long) current); diff -Naur -X exclude-files ac_cur/arch/um/kernel/ptrace.c ac/arch/um/kernel/ptrace.c --- ac_cur/arch/um/kernel/ptrace.c Fri Oct 5 14:39:03 2001 +++ ac/arch/um/kernel/ptrace.c Fri Oct 5 14:43:33 2001 @@ -68,7 +68,6 @@ int copied; ret = -EIO; - if(overlaps_kernel(addr, sizeof(tmp))) break; copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); if (copied != sizeof(tmp)) break; diff -Naur -X exclude-files ac_cur/arch/um/kernel/syscall_kern.c ac/arch/um/kernel/syscall_kern.c --- ac_cur/arch/um/kernel/syscall_kern.c Fri Oct 5 14:15:35 2001 +++ ac/arch/um/kernel/syscall_kern.c Fri Oct 5 14:43:33 2001 @@ -329,7 +329,9 @@ panic("syscall thread activated without a system call"); if((syscall >= NR_syscalls) || (syscall < 0)) return(-ENOSYS); + set_fs(KERNEL_DS); res = EXECUTE_SYSCALL(syscall, regs); + set_fs(USER_DS); return(res); } diff -Naur -X exclude-files ac_cur/arch/um/kernel/tlb.c ac/arch/um/kernel/tlb.c --- ac_cur/arch/um/kernel/tlb.c Fri Oct 5 14:15:35 2001 +++ ac/arch/um/kernel/tlb.c Fri Oct 5 14:43:33 2001 @@ -11,16 +11,14 @@ #include "asm/a.out.h" #include "asm/processor.h" #include "asm/mmu_context.h" +#include "asm/uaccess.h" #include "user_util.h" #include "kern_util.h" #include "kern.h" -struct mm_struct kernel_maps = EMPTY_MM; - -static void fix_range(struct mm_struct *proc_mm, unsigned long start_addr, +static void fix_range(struct mm_struct *mm, unsigned long start_addr, unsigned long end_addr, int force) { - struct mm_struct *mm; pgd_t *npgd; pmd_t *npmd; pte_t *npte; @@ -30,30 +28,19 @@ if((current->thread.extern_pid != -1) && (current->thread.extern_pid != getpid())) panic("fix_range fixing wrong address space"); - mm = proc_mm; - if(mm == NULL){ - start_addr = start_vm; - end_addr = end_vm; - } + if(mm == NULL) return; for(addr=start_addr;addrvm_start <= addr)){ - addr = vma->vm_end; - continue; - } - } - - if((addr >= start_vm) && (addr < end_vm)) mm = &init_mm; - else mm = proc_mm; + if(addr == TASK_SIZE){ + /* Skip over kernel text, kernel data, and physical + * memory, which don't have ptes, plus kernel virtual + * memory, which is flushed separately, and remap + * the process stack. The only way to get here is + * if (end_addr == STACK_TOP) > TASK_SIZE, which is + * only true in the honeypot case. + */ + addr = STACK_TOP - ABOVE_KMEM; + continue; + } npgd = pgd_offset(mm, addr); npmd = pmd_offset(npgd, addr); if(pmd_present(*npmd)){ @@ -66,24 +53,6 @@ r = 0; w = 0; } - if(mm == &init_mm){ - unsigned long mask; - - mask = PAGE_MASK | _PAGE_NEWPAGE | - _PAGE_NEWPROT; - if((pte_val(*npte) & ~mask) == - pgprot_val(PAGE_KERNEL)){ - r = 1; - w = 1; - x = 1; - } - else if((pte_val(*npte) & ~mask) == - pgprot_val(PAGE_KERNEL_RO)){ - r = 1; - w = 0; - x = 1; - } - } if(force || !pte_present(*npte) || pte_newpage(*npte)){ if(munmap((void *) addr, PAGE_SIZE) < 0) panic("munmap failed, errno = %d\n", @@ -94,166 +63,108 @@ } else if(pte_newprot(*npte)) protect(addr, PAGE_SIZE, r, w, x); - if(mm == proc_mm) *npte = pte_mkuptodate(*npte); + *npte = pte_mkuptodate(*npte); addr += PAGE_SIZE; } else { - unsigned long end, len; - - end = (addr + PMD_SIZE) & PMD_MASK; - len = end - addr; if(force || pmd_newpage(*npmd)){ - if(munmap((void *) addr, len) < 0) + if(munmap((void *) addr, PMD_SIZE) < 0) panic("munmap failed, errno = %d\n", errno); - if(mm == proc_mm) pmd_mkuptodate(*npmd); } - addr += len; + addr += PMD_SIZE; } } } -void init_flush_vm(void) +void flush_tlb_kernel_vm(void) { + struct mm_struct *mm; pgd_t *npgd; pmd_t *npmd; pte_t *npte; unsigned long addr; int r, w, x; - - for(addr=start_vm;addrmm) fix_range(mm, start, end, 0); -} + if(mm != current->mm) return; -void flush_tlb_mm(struct mm_struct *mm) -{ - flush_tlb_range(mm, 0, STACK_TOP); + /* Assumes that the range start ... end is entirely within + * either process memory or kernel vm + */ + if((start >= start_vm) && (start < end_vm)) flush_tlb_kernel_vm(); + else fix_range(mm, start, end, 0); } -void flush_tlb_kernel_vm(void) +void flush_tlb_mm(struct mm_struct *mm) { - if(current->mm != NULL) fix_range(current->mm, 0, STACK_TOP, 0); - else fix_range(NULL, start_vm, end_vm, 0); + if(mm != current->mm) return; + fix_range(mm, 0, STACK_TOP, 0); + flush_tlb_kernel_vm(); } void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) { address &= PAGE_MASK; - if(vma->vm_mm == current->mm) - fix_range(current->mm, address, address + PAGE_SIZE, 0); + flush_tlb_range(vma->vm_mm, address, address + PAGE_SIZE); } void flush_tlb_all(void) { - flush_tlb_range(current->mm, 0, STACK_TOP); + flush_tlb_mm(current->mm); } void force_flush_all(void) { fix_range(current->mm, 0, STACK_TOP, 1); -} - -static pgprot_t vm_prot(char r, char w, char x, char p) -{ - if((r == '-') && (w == '-') && (x == '-')) return(PAGE_NONE); - else if(w == '-') return(PAGE_READONLY); - else if(p == 'p') return(PAGE_COPY); - else return(PAGE_SHARED); -} - -static unsigned short vm_flags(char r, char w, char x, char p) -{ - unsigned short flags; - - flags = 0; - if(r == 'r') flags |= VM_READ; - if(w == 'w') flags |= VM_WRITE; - if(x == 'x') flags |= VM_EXEC; - if(p == '-') flags |= VM_SHARED; - return(flags); -} - -extern int honeypot; - -static struct vm_area_struct *process_vmas; -static int num_process_vmas = 0; - -void add_perm_vma(unsigned long start, unsigned long end, char rperm, - char wperm, char xperm, char private) -{ - struct vm_area_struct *vma; - - if(honeypot && (end == TASK_SIZE)) return; - vma = &process_vmas[num_process_vmas++]; - *vma = ((struct vm_area_struct) { - &kernel_maps, start, end, NULL, - vm_prot(rperm, wperm, xperm, private), - vm_flags(rperm, wperm, xperm, private), 0, NULL, NULL, NULL, - NULL, NULL, 0, NULL, 0 - }); - insert_vm_struct(&kernel_maps, vma); -} - -void add_process_vmas(void) -{ - unsigned long start, end; - void *maps; - char rperm, wperm, xperm, private; - - if(process_vmas == NULL){ - int count = 0; - - maps = open_maps(); - while(read_map(maps, NULL, NULL, NULL, NULL, NULL, NULL)) - count++; - close_maps(maps); - process_vmas = malloc((count + 1) * sizeof(*process_vmas)); - if(process_vmas == NULL) - panic("Couldn't allocate process_vmas"); - } - maps = open_maps(); - while(read_map(maps, &start, &end, &rperm, &wperm, &xperm, &private)){ - if(start == 0x40000000) continue; - add_perm_vma(start, end, rperm, wperm, xperm, private); - } - close_maps(maps); + flush_tlb_kernel_vm(); } pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) diff -Naur -X exclude-files ac_cur/arch/um/kernel/trap_kern.c ac/arch/um/kernel/trap_kern.c --- ac_cur/arch/um/kernel/trap_kern.c Fri Oct 5 14:15:35 2001 +++ ac/arch/um/kernel/trap_kern.c Fri Oct 5 14:43:33 2001 @@ -34,6 +34,10 @@ unsigned long page; int ok; + if((address >= start_vm) && (address < end_vm)){ + flush_tlb_kernel_vm(); + return(0); + } if(mm == NULL) panic("Segfault with no mm"); down_read(&mm->mmap_sem); vma = find_vma(mm, address); @@ -85,6 +89,7 @@ pgd = pgd_offset(mm, page); pmd = pmd_offset(pgd, page); do { + survive: switch (handle_mm_fault(mm, vma, address, is_write)) { case 1: current->min_flt++; @@ -92,11 +97,14 @@ case 2: current->maj_flt++; break; - case 0: - up_read(&mm->mmap_sem); - force_sigbus(); - return(0); default: + if (current->pid == 1) { + current->policy |= SCHED_YIELD; + schedule(); + goto survive; + } + /* Fall through to bad area case */ + case 0: up_read(&mm->mmap_sem); force_sig(SIGBUS, current); return(0); diff -Naur -X exclude-files ac_cur/arch/um/kernel/trap_user.c ac/arch/um/kernel/trap_user.c --- ac_cur/arch/um/kernel/trap_user.c Fri Oct 5 14:15:35 2001 +++ ac/arch/um/kernel/trap_user.c Fri Oct 5 14:51:24 2001 @@ -21,6 +21,7 @@ #include #include "user_util.h" #include "kern_util.h" +#include "mem_user.h" #include "user.h" #include "process.h" #include "sysdep/sigcontext.h" @@ -45,7 +46,8 @@ { int (*proc)(void *); - if(honeypot && munmap((void *) 0xb0000000, 0x10000000)) + if(honeypot && munmap((void *) (host_task_size - 0x10000000), + 0x10000000)) panic("Unmapping stack failed"); if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) panic("ptrace PTRACE_TRACEME failed"); diff -Naur -X exclude-files ac_cur/arch/um/kernel/um_arch.c ac/arch/um/kernel/um_arch.c --- ac_cur/arch/um/kernel/um_arch.c Fri Oct 5 14:15:35 2001 +++ ac/arch/um/kernel/um_arch.c Fri Oct 5 14:43:33 2001 @@ -105,7 +105,13 @@ extern unsigned long high_physmem; -unsigned long physmem = 0x50000000 + NESTING * 0x10000000; +#ifdef CONFIG_HOST_2G_2G +#define START 0x60000000 +#else +#define START 0xa0000000 +#endif + +unsigned long physmem; unsigned long start_vm; unsigned long end_vm; @@ -206,8 +212,6 @@ extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end; extern int debug_trace; -unsigned long task_size; - int linux_main(int argc, char **argv) { unsigned long start_pfn, end_pfn, bootmap_size; @@ -224,16 +228,13 @@ remap_data(ROUND_DOWN(&_sdata), ROUND_UP(&_edata)); brk_start = sbrk(0); remap_data(ROUND_DOWN(&__bss_start), ROUND_UP(brk_start)); -#ifdef CONFIG_GPROF - remap_profiling_buffers(); -#endif - /* Round up to the nearest 4M */ - task_size = ((((unsigned long) &argc) + (1 << 22)) & ~((1 << 22) - 1)); + /* Start physical memory at least 4M after the current brk */ + physmem = ROUND_4M(brk_start) + (1 << 22); /* Create fake command line from argv[]. */ have_root = 0; - physmem_size = 16 * 1024 * 1024; + physmem_size = 32 * 1024 * 1024; virtmem_size = physmem_size; for (i = 1; i < argc; i++){ if((i == 1) && (argv[i][0] == ' ')) continue; @@ -291,15 +292,28 @@ argv1_begin = argv[1]; argv1_end = &argv[1][strlen(argv[1])]; - add_process_vmas(); - unblock_shlib_mem(); + /* Kernel vm starts after physical memory and is either the size + * of physical memory or the remaining space left in the kernel + * area of the address space, whichever is smaller. + */ + start_vm = physmem + physmem_size + VMALLOC_OFFSET; + if(start_vm >= get_kmem_end()) + panic("Physical memory too large to allow any kernel " + "virtual memory"); + + virtmem_size = physmem_size; + if(physmem_size > get_kmem_end() - start_vm) + virtmem_size = get_kmem_end() - start_vm; + end_vm = start_vm + virtmem_size; + + if(virtmem_size < physmem_size) + printk(KERN_INFO "Kernel virtual memory size shrunk to %ld " + "bytes\n", virtmem_size); + setup_range(-1, NULL, physmem, physmem_size, physmem_size + VMALLOC_OFFSET + virtmem_size); setup_memory(); high_physmem = physmem + physmem_size; - start_vm = physmem + physmem_size + VMALLOC_OFFSET; - end_vm = start_vm + virtmem_size; - add_perm_vma(physmem, end_vm, 'r', 'w', 'x', '-'); start_pfn = PFN_UP(__pa(physmem)); end_pfn = PFN_DOWN(__pa(high_physmem)); diff -Naur -X exclude-files ac_cur/arch/um/kernel/user_util.c ac/arch/um/kernel/user_util.c --- ac_cur/arch/um/kernel/user_util.c Fri Oct 5 14:16:42 2001 +++ ac/arch/um/kernel/user_util.c Fri Oct 5 14:43:33 2001 @@ -237,28 +237,6 @@ } } -static int mem_blocked = 0; - -void block_shlib_mem(void) -{ - if(mem_blocked || (NESTING > 0)) return; - mem_blocked = 1; - if(mmap((void *) 0x40000000, 0x20000000, PROT_NONE, - MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, -1, - 0) != (void *) 0x40000000){ - printf("mmap failed in linux_main\n"); - exit(1); - } -} - -void unblock_shlib_mem(void) -{ - if(NESTING == 0){ - mem_blocked = 0; - munmap((void *) 0x40000000, 0x20000000); - } -} - int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags) { int pid; diff -Naur -X exclude-files ac_cur/arch/um/main.c ac/arch/um/main.c --- ac_cur/arch/um/main.c Fri Oct 5 14:15:35 2001 +++ ac/arch/um/main.c Fri Oct 5 14:43:33 2001 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -10,8 +10,11 @@ #include #include #include +#include +#include #include "user_util.h" #include "kern_util.h" +#include "mem_user.h" #include "user.h" unsigned long stacksizelim; @@ -24,10 +27,37 @@ char padding[THREAD_NAME_LEN] = { [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' }; +static void set_stklim(void) +{ + struct rlimit lim; + + if(getrlimit(RLIMIT_STACK, &lim) < 0){ + perror("getrlimit"); + exit(1); + } + if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){ + lim.rlim_cur = STACKSIZE; + if(setrlimit(RLIMIT_STACK, &lim) < 0){ + perror("setrlimit"); + exit(1); + } + } + stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1); +} + +unsigned long host_task_size; +unsigned long task_size; + +static void set_task_sizes(int arg) +{ + /* Round up to the nearest 4M */ + host_task_size = ROUND_4M((unsigned long) &arg); + task_size = host_task_size - 0x20000000; +} + int main(int argc, char **argv, char **envp) { struct termios tt; - struct rlimit lim; int ret, i; char **new_argv; @@ -55,19 +85,10 @@ } linux_prog = argv[0]; - block_shlib_mem(); - if(getrlimit(RLIMIT_STACK, &lim) < 0){ - perror("getrlimit"); - exit(1); - } - if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){ - lim.rlim_cur = STACKSIZE; - if(setrlimit(RLIMIT_STACK, &lim) < 0){ - perror("setrlimit"); - exit(1); - } - } - stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1); + + set_stklim(); + set_task_sizes(0); + if(isatty(0)) tcgetattr(0, &tt); else if(isatty(1)) tcgetattr(1, &tt); else tcgetattr(2, &tt); @@ -101,21 +122,51 @@ return(ret); } +int allocating_monbuf = 0; + #ifdef PROFILING extern void __real___monstartup (unsigned long, unsigned long); void __wrap___monstartup (unsigned long lowpc, unsigned long highpc) { - block_shlib_mem(); + allocating_monbuf = 1; __real___monstartup(lowpc, highpc); + allocating_monbuf = 0; get_profile_timer(); } #endif extern void *__real_malloc(int); +extern unsigned long host_task_size; + +static void *gmon_buf = NULL; void *__wrap_malloc(int size) { + if(allocating_monbuf){ + unsigned long start, end; + int fd = create_mem_file(size); + + /* Calculate this here because linux_main hasn't run yet + * and host_task_size figures in STACK_TOP, which figures + * in kmem_end. + */ + set_task_sizes(0); + + /* Same with stacksizelim */ + set_stklim(); + + end = get_kmem_end(); + start = (end - size) & PAGE_MASK; + gmon_buf = mmap((void *) start, size, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_FIXED, fd, 0); + if(gmon_buf != (void *) start){ + perror("Creating gprof buffer"); + exit(1); + } + set_kmem_end(start); + return(gmon_buf); + } if(kmalloc_ok) return(um_kmalloc(size)); else return(__real_malloc(size)); } @@ -133,6 +184,10 @@ void __wrap_free(void *ptr) { + /* Could maybe unmap the gmon buffer, but we're just about to + * exit anyway + */ + if(ptr == gmon_buf) return; if(kmalloc_ok) kfree(ptr); else __real_free(ptr); } diff -Naur -X exclude-files ac_cur/include/asm-um/a.out.h ac/include/asm-um/a.out.h --- ac_cur/include/asm-um/a.out.h Fri Oct 5 14:15:51 2001 +++ ac/include/asm-um/a.out.h Fri Oct 5 14:43:33 2001 @@ -7,10 +7,12 @@ extern unsigned long stacksizelim; +extern unsigned long host_task_size; + extern int honeypot; -#define STACK_ROOM (honeypot ? (0) : (stacksizelim * (NESTING + 1))) +#define STACK_ROOM (stacksizelim) -#define STACK_TOP (TASK_SIZE - STACK_ROOM) +#define STACK_TOP (honeypot ? host_task_size : task_size) #endif diff -Naur -X exclude-files ac_cur/include/asm-um/pgalloc.h ac/include/asm-um/pgalloc.h --- ac_cur/include/asm-um/pgalloc.h Fri Oct 5 14:18:40 2001 +++ ac/include/asm-um/pgalloc.h Fri Oct 5 14:45:10 2001 @@ -114,16 +114,17 @@ * - flush_tlb_all() flushes all processes TLBs * - flush_tlb_mm(mm) flushes the specified mm context TLB's * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_kernel_vm() flushes the kernel vm area * - flush_tlb_range(mm, start, end) flushes a range of pages * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables */ extern void flush_tlb_all(void); extern void flush_tlb_mm(struct mm_struct *mm); -extern void flush_tlb_kernel_vm(void); extern void flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end); extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); +extern void flush_tlb_kernel_vm(void); static inline void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end) diff -Naur -X exclude-files ac_cur/include/asm-um/processor-generic.h ac/include/asm-um/processor-generic.h --- ac_cur/include/asm-um/processor-generic.h Fri Oct 5 14:18:38 2001 +++ ac/include/asm-um/processor-generic.h Fri Oct 5 14:45:08 2001 @@ -81,37 +81,6 @@ } request; }; -#define EMPTY_MM \ -{ \ - mmap: NULL, \ - mmap_avl: NULL, \ - mmap_cache: NULL, \ - pgd: NULL, \ - mm_users: { 0 }, \ - mm_count: { 0 }, \ - map_count: 0, \ - page_table_lock:{ }, \ - mmlist: { }, \ - start_code: 0, \ - end_code: 0, \ - start_data: 0, \ - end_data: 0, \ - start_brk: 0, \ - brk: 0, \ - start_stack: 0, \ - arg_start: 0, \ - arg_end: 0, \ - env_start: 0, \ - env_end: 0, \ - rss: 0, \ - total_vm: 0, \ - locked_vm: 0, \ - def_flags: 0, \ - cpu_vm_mask: 0, \ - swap_address: 0, \ - context: { NULL } \ -} - #define INIT_MMAP \ { \ vm_mm: &init_mm, \ diff -Naur -X exclude-files ac_cur/include/asm-um/uaccess.h ac/include/asm-um/uaccess.h --- ac_cur/include/asm-um/uaccess.h Fri Oct 5 14:18:38 2001 +++ ac/include/asm-um/uaccess.h Fri Oct 5 14:45:08 2001 @@ -25,9 +25,10 @@ #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) +#define ABOVE_KMEM (16 * 1024 * 1024) #define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) -#define USER_DS MAKE_MM_SEG(PAGE_OFFSET) +#define USER_DS MAKE_MM_SEG(TASK_SIZE) #define get_ds() (KERNEL_DS) #define get_fs() (current->addr_limit) @@ -36,21 +37,26 @@ extern unsigned long end_vm; extern unsigned long physmem; -#define overlaps_kernel(addr, size) \ - ((((addr) <= physmem) && ((addr) + (size) > physmem)) || \ - ((physmem <= (addr)) && (end_vm > (addr)))) +#define under_task_size(addr, size) \ + (((unsigned long) (addr) < TASK_SIZE) && \ + (((unsigned long) (addr) + (size)) < TASK_SIZE)) + +#define is_stack(addr, size) \ + (((unsigned long) (addr) < STACK_TOP) && \ + ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ + (((unsigned long) (addr) + (size)) <= STACK_TOP)) + +#define segment_eq(a, b) ((a).seg == (b).seg) #define access_ok(type, addr, size) \ - (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ - ((unsigned long) (addr) < TASK_SIZE) && \ - (((unsigned long) (addr) + (size)) < TASK_SIZE)) + ((type == VERIFY_READ) || (segment_eq(get_ds(), KERNEL_DS)) || \ + (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ + (under_task_size(addr, size) || is_stack(addr, size)))) static inline int verify_area(int type, const void * addr, unsigned long size) { return(access_ok(type, addr, size) ? 0 : -EFAULT); } - -#define segment_eq(a, b) (1) extern unsigned long get_fault_addr(void);