2001-10-26 08:30:58

by Richard Henderson

[permalink] [raw]
Subject: alpha 2.4.13: fix taso osf emulation

Required to get a dynamicly linked osf taso application working.
Like netscape. Which unfortunately still works better than mozilla
for many things.

Thoughts on changing all ports such that a mmap with a non-zero,
non-MAP_FIXED address starts the vma search at that address,
rather than looking for that exact address then checking the
regular unmapped base?



r~



diff -rup linux/fs/binfmt_aout.c 2.4.13/fs/binfmt_aout.c
--- linux/fs/binfmt_aout.c Sun Sep 30 12:26:08 2001
+++ 2.4.13/fs/binfmt_aout.c Thu Oct 25 09:58:03 2001
@@ -285,13 +285,15 @@ static int load_aout_binary(struct linux
return retval;

/* OK, This is the point of no return */
-#if !defined(__sparc__)
- set_personality(PER_LINUX);
-#else
+#if defined(__alpha__)
+ SET_AOUT_PERSONALITY(bprm, ex);
+#elif defined(__sparc__)
set_personality(PER_SUNOS);
#if !defined(__sparc_v9__)
memcpy(&current->thread.core_exec, &ex, sizeof(struct exec));
#endif
+#else
+ set_personality(PER_LINUX);
#endif

current->mm->end_code = ex.a_text +
diff -rup linux/fs/exec.c 2.4.13/fs/exec.c
--- linux/fs/exec.c Tue Sep 18 13:39:32 2001
+++ 2.4.13/fs/exec.c Thu Oct 25 11:36:53 2001
@@ -770,7 +770,6 @@ int search_binary_handler(struct linux_b
if (!bprm->loader && eh->fh.f_magic == 0x183 &&
(eh->fh.f_flags & 0x3000) == 0x3000)
{
- char * dynloader[] = { "/sbin/loader" };
struct file * file;
unsigned long loader;

@@ -780,10 +779,14 @@ int search_binary_handler(struct linux_b

loader = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);

- file = open_exec(dynloader[0]);
+ file = open_exec("/sbin/loader");
retval = PTR_ERR(file);
if (IS_ERR(file))
return retval;
+
+ /* Remember if the application is TASO. */
+ bprm->sh_bang = eh->ah.entry < 0x100000000;
+
bprm->file = file;
bprm->loader = loader;
retval = prepare_binprm(bprm);
diff -rup linux/arch/alpha/kernel/osf_sys.c 2.4.13/arch/alpha/kernel/osf_sys.c
--- linux/arch/alpha/kernel/osf_sys.c Fri Oct 26 01:17:08 2001
+++ 2.4.13/arch/alpha/kernel/osf_sys.c Thu Oct 25 12:10:52 2001
@@ -1357,14 +1357,19 @@ arch_get_unmapped_area(struct file *filp
if (len > limit)
return -ENOMEM;

- /* First, see if the given suggestion fits. */
- if (addr) {
- struct vm_area_struct *vma;
+ /* First, see if the given suggestion fits.
+
+ The OSF/1 loader (/sbin/loader) relies on us returning an
+ address larger than the requested if one exists, which is
+ a terribly broken way to program.

- addr = PAGE_ALIGN(addr);
- vma = find_vma(current->mm, addr);
- if (limit - len >= addr &&
- (!vma || addr + len <= vma->vm_start))
+ That said, I can see the use in being able to suggest not
+ merely specific addresses, but regions of memory -- perhaps
+ this feature should be incorporated into all ports? */
+
+ if (addr) {
+ addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit);
+ if (addr != -ENOMEM)
return addr;
}

diff -rup linux/include/asm-alpha/a.out.h 2.4.13/include/asm-alpha/a.out.h
--- linux/include/asm-alpha/a.out.h Fri Feb 6 10:06:55 1998
+++ 2.4.13/include/asm-alpha/a.out.h Fri Oct 26 01:24:47 2001
@@ -90,8 +90,16 @@ struct exec

#ifdef __KERNEL__

+/* Assume that start addresses below 4G belong to a TASO application.
+ Unfortunately, there is no proper bit in the exec header to check.
+ Worse, we have to notice the start address before swapping to use
+ /sbin/loader, which of course is _not_ a TASO application. */
+#define SET_AOUT_PERSONALITY(BFPM, EX) \
+ set_personality (BFPM->sh_bang || EX.ah.entry < 0x100000000 \
+ ? PER_LINUX_32BIT : PER_LINUX)
+
#define STACK_TOP \
- ((current->personality==PER_LINUX_32BIT) ? (0x80000000) : (0x00120000000UL))
+ (current->personality & ADDR_LIMIT_32BIT ? 0x80000000 : 0x00120000000UL)

#endif


2001-10-26 10:04:41

by Maciej W. Rozycki

[permalink] [raw]
Subject: Re: alpha 2.4.13: fix taso osf emulation

On Fri, 26 Oct 2001, Richard Henderson wrote:

> Required to get a dynamicly linked osf taso application working.
> Like netscape. Which unfortunately still works better than mozilla
> for many things.

The following trivial patch reportedly fixes OSF/1 programs using 31-bit
addressing. It's already present in the -ac tree; I guess it just got
lost during a merge. It applies fine to 2.4.13.

> Thoughts on changing all ports such that a mmap with a non-zero,
> non-MAP_FIXED address starts the vma search at that address,
> rather than looking for that exact address then checking the
> regular unmapped base?

It used to do so. It breaks things such as dynamic linking of shared
objects linked at high load address. It breaks mmap() in principle, as it
shouldn't fail when invoked with a non-zero, non-MAP_FIXED, invalid
address if there is still address space available elsewhere.

The following patch approximates the idea with no negative impact.

I cannot run an Alpha/Linux system anymore thus I can't immediately see
if a patch gets missed, sorry.

--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: [email protected], PGP key available +

diff -up --recursive --new-file linux-2.4.5-ac8.macro/arch/ia64/kernel/sys_ia64.c linux-2.4.5-ac8/arch/ia64/kernel/sys_ia64.c
--- linux-2.4.5-ac8.macro/arch/ia64/kernel/sys_ia64.c Tue Jun 5 14:22:10 2001
+++ linux-2.4.5-ac8/arch/ia64/kernel/sys_ia64.c Tue Jun 5 14:46:14 2001
@@ -39,11 +39,15 @@ arch_get_unmapped_area (struct file *fil
rgn_offset(addr) + len <= RGN_MAP_LIMIT) &&
(!vmm || addr + len <= vmm->vm_start))
return addr;
+ if (addr > TASK_UNMAPPED_BASE)
+ addr = 0;
+ }
+ if (!addr) {
+ if (flags & MAP_SHARED)
+ addr = COLOR_ALIGN(TASK_UNMAPPED_BASE);
+ else
+ addr = PAGE_ALIGN(TASK_UNMAPPED_BASE);
}
- if (flags & MAP_SHARED)
- addr = COLOR_ALIGN(TASK_UNMAPPED_BASE);
- else
- addr = PAGE_ALIGN(TASK_UNMAPPED_BASE);

for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
/* At this point: (!vmm || addr < vmm->vm_end). */
diff -up --recursive --new-file linux-2.4.5-ac8.macro/arch/sparc/kernel/sys_sparc.c linux-2.4.5-ac8/arch/sparc/kernel/sys_sparc.c
--- linux-2.4.5-ac8.macro/arch/sparc/kernel/sys_sparc.c Tue Jun 5 14:22:10 2001
+++ linux-2.4.5-ac8/arch/sparc/kernel/sys_sparc.c Tue Jun 5 14:39:49 2001
@@ -69,11 +69,15 @@ unsigned long arch_get_unmapped_area(str
if (TASK_SIZE - PAGE_SIZE - len >= addr &&
(!vmm || addr + len <= vmm->vm_start))
return addr;
+ if (addr > TASK_UNMAPPED_BASE)
+ addr = 0;
+ }
+ if (!addr) {
+ if (flags & MAP_SHARED)
+ addr = COLOUR_ALIGN(TASK_UNMAPPED_BASE);
+ else
+ addr = PAGE_ALIGN(TASK_UNMAPPED_BASE);
}
- if (flags & MAP_SHARED)
- addr = COLOUR_ALIGN(TASK_UNMAPPED_BASE);
- else
- addr = PAGE_ALIGN(TASK_UNMAPPED_BASE);

for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
/* At this point: (!vmm || addr < vmm->vm_end). */
diff -up --recursive --new-file linux-2.4.5-ac8.macro/arch/sparc64/kernel/sys_sparc.c linux-2.4.5-ac8/arch/sparc64/kernel/sys_sparc.c
--- linux-2.4.5-ac8.macro/arch/sparc64/kernel/sys_sparc.c Tue Jun 5 14:22:10 2001
+++ linux-2.4.5-ac8/arch/sparc64/kernel/sys_sparc.c Tue Jun 5 14:44:19 2001
@@ -76,11 +76,15 @@ unsigned long arch_get_unmapped_area(str
if (task_size >= addr &&
(!vmm || addr + len <= vmm->vm_start))
return addr;
+ if (addr > TASK_UNMAPPED_BASE)
+ addr = 0;
+ }
+ if (!addr) {
+ if (flags & MAP_SHARED)
+ addr = COLOUR_ALIGN(TASK_UNMAPPED_BASE);
+ else
+ addr = PAGE_ALIGN(TASK_UNMAPPED_BASE);
}
- if (flags & MAP_SHARED)
- addr = COLOUR_ALIGN(TASK_UNMAPPED_BASE);
- else
- addr = PAGE_ALIGN(TASK_UNMAPPED_BASE);

for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
/* At this point: (!vmm || addr < vmm->vm_end). */
diff -up --recursive --new-file linux-2.4.5-ac8.macro/mm/mmap.c linux-2.4.5-ac8/mm/mmap.c
--- linux-2.4.5-ac8.macro/mm/mmap.c Tue Jun 5 14:22:29 2001
+++ linux-2.4.5-ac8/mm/mmap.c Tue Jun 5 14:45:57 2001
@@ -408,8 +408,11 @@ static inline unsigned long arch_get_unm
if (TASK_SIZE - len >= addr &&
(!vma || addr + len <= vma->vm_start))
return addr;
+ if (addr > TASK_UNMAPPED_BASE)
+ addr = 0;
}
- addr = PAGE_ALIGN(TASK_UNMAPPED_BASE);
+ if (!addr)
+ addr = PAGE_ALIGN(TASK_UNMAPPED_BASE);

for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
/* At this point: (!vma || addr < vma->vm_end). */

2001-10-26 10:45:49

by Ivan Kokshaysky

[permalink] [raw]
Subject: Re: alpha 2.4.13: fix taso osf emulation

On Fri, Oct 26, 2001 at 12:01:10PM +0200, Maciej W. Rozycki wrote:
> On Fri, 26 Oct 2001, Richard Henderson wrote:
> > Thoughts on changing all ports such that a mmap with a non-zero,
> > non-MAP_FIXED address starts the vma search at that address,
> > rather than looking for that exact address then checking the
> > regular unmapped base?
>
> It used to do so. It breaks things such as dynamic linking of shared
> objects linked at high load address. It breaks mmap() in principle, as it
> shouldn't fail when invoked with a non-zero, non-MAP_FIXED, invalid
> address if there is still address space available elsewhere.

Maciej and I discussed all this a while back, and I had a patch
which did exactly that that Richard suggested, plus:
as far as I can tell, it conforms to any existing mmap(2) documentation;
is more effective than current implementation, as I call the second
find_vma() only after VM wraparound, which is extremely rare;
keeps osf /sbin/loader happy, so no need for alpha-specific routine.
Patch appended, comments?

Ivan.

P.S. Just noticed missing closing brace in the patch from my previous post...
Sorry.

--- 2.4.13/mm/mmap.c Sun Sep 30 22:05:40 2001
+++ linux/mm/mmap.c Fri Oct 26 13:36:47 2001
@@ -590,27 +590,38 @@ free_vma:
static inline unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
{
struct vm_area_struct *vma;
+ unsigned long addr_limit = TASK_SIZE - len;
+ unsigned long addr1 = 0;

if (len > TASK_SIZE)
return -ENOMEM;

if (addr) {
addr = PAGE_ALIGN(addr);
- vma = find_vma(current->mm, addr);
- if (TASK_SIZE - len >= addr &&
- (!vma || addr + len <= vma->vm_start))
- return addr;
+ if (addr > TASK_UNMAPPED_BASE)
+ addr1 = addr;
+ goto find_free_area;
}
+
+default_area:
addr = PAGE_ALIGN(TASK_UNMAPPED_BASE);

+find_free_area:
for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
/* At this point: (!vma || addr < vma->vm_end). */
- if (TASK_SIZE - len < addr)
- return -ENOMEM;
+ if (addr_limit < addr)
+ break;
if (!vma || addr + len <= vma->vm_start)
return addr;
addr = vma->vm_end;
}
+ if (addr1) {
+ /* No unmapped areas above addr; try below it */
+ addr_limit = addr1;
+ addr1 = 0;
+ goto default_area;
+ }
+ return -ENOMEM;
}
#else
extern unsigned long arch_get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);

2001-10-26 18:25:51

by Maciej W. Rozycki

[permalink] [raw]
Subject: Re: alpha 2.4.13: fix taso osf emulation

On Fri, 26 Oct 2001, Richard Henderson wrote:

> > The following trivial patch reportedly fixes OSF/1 programs using 31-bit
> > addressing. It's already present in the -ac tree; I guess it just got
> > lost during a merge. It applies fine to 2.4.13.
>
> This is the patch that Jay Estabrook forwarded me that I rejected
> in favour of writing a special arch_get_unmapped_area.

Ah, that is a fine approach as well; I just considered the change small
enough it's not worth making it arch-specific. Besides, my patch alsoo
has a small advantage of keeping the search algorithm the same across all
the archs.

> > It used to do so. It breaks things such as dynamic linking of shared
> > objects linked at high load address.
>
> Err, how?

I mean, the original algorithm as implemented in 2.4.9. If you had asked
e.g. for memory above TASK_SIZE you would have got an error no matter how
much address space was still available below.

> > It breaks mmap() in principle, as it shouldn't fail when invoked with
> > a non-zero, non-MAP_FIXED, invalid address if there is still address
> > space available elsewhere.
>
> No, it doesn't. Or rather, it only does if you only bothered
> to search once. IMO one should search thrice: once at addr,
> once at TASK_UNMAPPED_BASE, and once at PAGE_SIZE.

OK, but I'd prefer to avoid searching overlapping areas over and over
again for performance's sake. My solution does a single lookup and a
single search, effectively covering at least the whole space that would be
used if no address preference was specified; more if a program asked for
space below TASK_UNMAPPED_BASE (= "yes, I know what I'm doing, I want to
limit my brk() space").

--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: [email protected], PGP key available +

2001-10-26 17:12:40

by Richard Henderson

[permalink] [raw]
Subject: Re: alpha 2.4.13: fix taso osf emulation

On Fri, Oct 26, 2001 at 02:45:22PM +0400, Ivan Kokshaysky wrote:
> find_vma() only after VM wraparound, which is extremely rare;
> keeps osf /sbin/loader happy, so no need for alpha-specific routine.

Yes there is, since TASO applications need to wrap at 1<<31,
not TASK_SIZE. Note that TASK_SIZE should _not_ be changed
for TASO applications, since they can explicitly map memory
above 4G. An example here is em86, in which the low 4G is
reserved for the emulated program, and the emulator lives in
high memory.

> Patch appended, comments?

I think you're working too hard to make this "efficient", and
in the process making the code hard to read. A subroutine
containing a simple search-forward loop is just as effective.


r~

2001-10-26 17:04:56

by Richard Henderson

[permalink] [raw]
Subject: Re: alpha 2.4.13: fix taso osf emulation

On Fri, Oct 26, 2001 at 12:01:10PM +0200, Maciej W. Rozycki wrote:
> The following trivial patch reportedly fixes OSF/1 programs using 31-bit
> addressing. It's already present in the -ac tree; I guess it just got
> lost during a merge. It applies fine to 2.4.13.

This is the patch that Jay Estabrook forwarded me that I rejected
in favour of writing a special arch_get_unmapped_area.

> It used to do so. It breaks things such as dynamic linking of shared
> objects linked at high load address.

Err, how?

> It breaks mmap() in principle, as it shouldn't fail when invoked with
> a non-zero, non-MAP_FIXED, invalid address if there is still address
> space available elsewhere.

No, it doesn't. Or rather, it only does if you only bothered
to search once. IMO one should search thrice: once at addr,
once at TASK_UNMAPPED_BASE, and once at PAGE_SIZE.



r~

2001-10-28 09:43:46

by Anand Ashok Kulkarni

[permalink] [raw]
Subject: Module loading and Kernel crash

I have written a module which takes the packet from the kernel, stores some
number of packets and then sends all if them out. But some how the kernel
crashes after working for some time. how can i take care of that. the
enqueing and dequeing functions take action on the same piece of memory.
will using task queues for both of them work ?
I have tried doin it...but even then the kernel konks.:-(




----- Original Message -----
From: "Richard Henderson" <[email protected]>
To: "Maciej W. Rozycki" <[email protected]>
Cc: <[email protected]>; <[email protected]>;
<[email protected]>
Sent: Friday, October 26, 2001 10:33 PM
Subject: Re: alpha 2.4.13: fix taso osf emulation


> On Fri, Oct 26, 2001 at 12:01:10PM +0200, Maciej W. Rozycki wrote:
> > The following trivial patch reportedly fixes OSF/1 programs using
31-bit
> > addressing. It's already present in the -ac tree; I guess it just got
> > lost during a merge. It applies fine to 2.4.13.
>
> This is the patch that Jay Estabrook forwarded me that I rejected
> in favour of writing a special arch_get_unmapped_area.
>
> > It used to do so. It breaks things such as dynamic linking of shared
> > objects linked at high load address.
>
> Err, how?
>
> > It breaks mmap() in principle, as it shouldn't fail when invoked with
> > a non-zero, non-MAP_FIXED, invalid address if there is still address
> > space available elsewhere.
>
> No, it doesn't. Or rather, it only does if you only bothered
> to search once. IMO one should search thrice: once at addr,
> once at TASK_UNMAPPED_BASE, and once at PAGE_SIZE.
>
>
>
> r~
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/


Attachments:
Wipro_Disclaimer.txt (855.00 B)

2001-10-29 16:36:02

by Ivan Kokshaysky

[permalink] [raw]
Subject: Re: alpha 2.4.13: fix taso osf emulation

On Fri, Oct 26, 2001 at 10:11:45AM -0700, Richard Henderson wrote:
> Yes there is, since TASO applications need to wrap at 1<<31,
> not TASK_SIZE. Note that TASK_SIZE should _not_ be changed
> for TASO applications, since they can explicitly map memory
> above 4G. An example here is em86, in which the low 4G is
> reserved for the emulated program, and the emulator lives in
> high memory.

I see. I was confused by the fact that netscape did work with
kernels < 2.4.9. Which only means that netscape never calls
mmap() with zero address...

> I think you're working too hard to make this "efficient", and
> in the process making the code hard to read. A subroutine
> containing a simple search-forward loop is just as effective.

Ok. After converting that from assembly to C I've got your
version of arch_get_unmapped_area :-) with small changes
(to avoid searching the same areas 2 or 3 times).

Ivan.

--- linux/arch/alpha/kernel/osf_sys.c.rth Mon Oct 29 17:43:53 2001
+++ linux/arch/alpha/kernel/osf_sys.c Mon Oct 29 18:14:46 2001
@@ -1342,11 +1342,11 @@ arch_get_unmapped_area_1(unsigned long a
}

unsigned long
-arch_get_unmapped_area(struct file *filp, unsigned long addr,
+arch_get_unmapped_area(struct file *filp, unsigned long start,
unsigned long len, unsigned long pgoff,
unsigned long flags)
{
- unsigned long limit;
+ unsigned long limit, addr;

/* "32 bit" actually means 31 bit, since pointers sign extend. */
if (current->personality & ADDR_LIMIT_32BIT)
@@ -1367,10 +1367,12 @@ arch_get_unmapped_area(struct file *filp
merely specific addresses, but regions of memory -- perhaps
this feature should be incorporated into all ports? */

- if (addr) {
- addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit);
+ if (start) {
+ start = PAGE_ALIGN(start);
+ addr = arch_get_unmapped_area_1 (start, len, limit);
if (addr != -ENOMEM)
return addr;
+ limit = start;
}

/* Next, try allocating at TASK_UNMAPPED_BASE. */
@@ -1378,6 +1380,8 @@ arch_get_unmapped_area(struct file *filp
len, limit);
if (addr != -ENOMEM)
return addr;
+
+ limit = PAGE_ALIGN(TASK_UNMAPPED_BASE);

/* Finally, try allocating in low memory. */
addr = arch_get_unmapped_area_1 (PAGE_SIZE, len, limit);

2001-10-29 17:22:52

by Richard Henderson

[permalink] [raw]
Subject: Re: alpha 2.4.13: fix taso osf emulation

On Mon, Oct 29, 2001 at 07:35:00PM +0300, Ivan Kokshaysky wrote:
> Ok. After converting that from assembly to C I've got your
> version of arch_get_unmapped_area :-) with small changes
> (to avoid searching the same areas 2 or 3 times).

This looks much better, thanks.


r~