diff -Naur linux-2.4.17-orig/arch/ia64/ia32/sys_ia32.c linux-2.4.17/arch/ia64/ia32/sys_ia32.c --- linux-2.4.17-orig/arch/ia64/ia32/sys_ia32.c Thu Feb 7 20:53:36 2002 +++ linux-2.4.17/arch/ia64/ia32/sys_ia32.c Tue Feb 26 23:09:16 2002 @@ -324,14 +324,72 @@ return ret; } +static void +ia32_set_range(struct mmap_range *rp, unsigned int start) +{ + struct mmap_range *rg; + + if ((rg = kmalloc(sizeof(*rg), GFP_KERNEL)) == (struct mmap_range *)0) + return; + rg->base = start; + rg->next = rp->next; + rp->next = rg; + return; +} + +static int +ia32_in_range(struct mmap_range *rp, unsigned int start) +{ + struct mmap_range *rg; + + while ((rg = rp->next)) + if (rg->base == start) { + rp->next = rg->next; + kfree(rg); + return(1); + } else + rp = rg; + return(0); +} + +void +ia32_delete_range(struct mmap_range *rp) +{ + struct mmap_range *rg; + + while ((rg = rp)) { + rp = rp->next; + kfree(rg); + } + return; +} + +void +ia32_copy_range(struct mmap_range *rp) +{ + struct mmap_range *rg, *cg; + + rp->next = (struct mmap_range *)0; + cg = (struct mmap_range *)¤t->thread.mmap_range; + while ((cg = cg->next)) { + if ((rg = kmalloc(sizeof(*rg), GFP_KERNEL)) == (struct mmap_range *)0) + return; + rg->base = cg->base; + rg->next = rp->next; + rp->next = rg; + } + return; +} + static unsigned long emulate_mmap (struct file *file, unsigned long start, unsigned long len, int prot, int flags, loff_t off) { - unsigned long tmp, end, pend, pstart, ret, is_congruent, fudge = 0; + unsigned long tmp, end, orig, pend, pstart, ret, is_congruent, fudge = 0; struct inode *inode; loff_t poff; + orig = start; end = start + len; pstart = PAGE_START(start); pend = PAGE_ALIGN(end); @@ -415,6 +473,8 @@ if (!(prot & PROT_WRITE) && sys_mprotect(pstart, pend - pstart, prot) < 0) return EINVAL; } + if (orig == 0) + ia32_set_range((struct mmap_range *)¤t->thread.mmap_range, (unsigned int)start); return start; } @@ -550,8 +610,11 @@ if (start > end) return -EINVAL; + if (ia32_in_range((struct mmap_range *)¤t->thread.mmap_range, start)) + end = PAGE_ALIGN(end); + else + end = PAGE_START(end); start = PAGE_ALIGN(start); - end = PAGE_START(end); if (start >= end) return 0; diff -Naur linux-2.4.17-orig/arch/ia64/kernel/process.c linux-2.4.17/arch/ia64/kernel/process.c --- linux-2.4.17-orig/arch/ia64/kernel/process.c Mon Feb 11 21:33:55 2002 +++ linux-2.4.17/arch/ia64/kernel/process.c Tue Feb 26 22:41:36 2002 @@ -308,8 +308,13 @@ * If we're cloning an IA32 task then save the IA32 extra * state from the current task to the new task */ - if (IS_IA32_PROCESS(ia64_task_regs(current))) + if (IS_IA32_PROCESS(ia64_task_regs(current))) { ia32_save_state(p); + /* + * Copy mmap ranges that might be needed for munmap calls + */ + ia32_copy_range((struct mmap_range *)&p->thread.mmap_range); + } #endif #ifdef CONFIG_PERFMON if (p->thread.pfm_context) @@ -516,6 +521,10 @@ */ current->thread.flags &= ~IA64_THREAD_PM_VALID; } +#endif +#ifdef CONFIG_IA32_SUPPORT + if (IS_IA32_PROCESS(ia64_task_regs(current))) + ia32_delete_range(current->thread.mmap_range); #endif } diff -Naur linux-2.4.17-orig/include/asm-ia64/processor.h linux-2.4.17/include/asm-ia64/processor.h --- linux-2.4.17-orig/include/asm-ia64/processor.h Thu Feb 7 21:15:44 2002 +++ linux-2.4.17/include/asm-ia64/processor.h Tue Feb 26 22:42:20 2002 @@ -348,6 +348,14 @@ struct siginfo; +struct mmap_range { + struct mmap_range *next; + unsigned int base; +}; + +void ia32_copy_range(struct mmap_range *); +void ia32_delet_range(struct mmap_range *); + struct thread_struct { __u64 ksp; /* kernel stack pointer */ unsigned long flags; /* various flags */ @@ -365,7 +373,8 @@ __u64 ssd; /* IA32 stack selector descriptor */ __u64 old_k1; /* old value of ar.k1 */ __u64 old_iob; /* old IOBase value */ -# define INIT_THREAD_IA32 0, 0, 0x17800000037fULL, 0, 0, 0, 0, 0, 0, + struct mmap_range *mmap_range; /* mmap ranges */ +# define INIT_THREAD_IA32 0, 0, 0x17800000037fULL, 0, 0, 0, 0, 0, 0, 0, #else # define INIT_THREAD_IA32 #endif /* CONFIG_IA32_SUPPORT */