Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 27 May 2012 17:45:13 +1000 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        src-committers@FreeBSD.org, svn-src-all@FreeBSD.org, Ed Schouten <ed@FreeBSD.org>, svn-src-head@FreeBSD.org, rwatson@FreeBSD.org, Konstantin Belousov <kostikbel@gmail.com>, jonathan@FreeBSD.org
Subject:   Re: svn commit: r236026 - in head/sys: amd64/linux32 compat/freebsd32 kern
Message-ID:  <20120527172204.G989@besplex.bde.org>
In-Reply-To: <20120527043827.W3357@besplex.bde.org>
References:  <201205252150.q4PLomFk035064@svn.freebsd.org> <20120526173233.A885@besplex.bde.org> <20120526164927.GU2358@deviant.kiev.zoral.com.ua> <20120527043827.W3357@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 27 May 2012, Bruce Evans wrote:

> On Sat, 26 May 2012, Konstantin Belousov wrote:
>
>> On Sat, May 26, 2012 at 10:21:25PM +1000, Bruce Evans wrote:
>>>...
>>> All the non-indirect "char *"s for pathnames and other things seem to be
>>> completely wrong on amd64 too.  These pointers start as 32 bits, and it
>>> takes more than a bad type pun to turn then into kernel 64-bit pointers.
>>> The magic for this seems to be:
>>> - all args are converted to 64 bits (by zero-extension?) at a low level
>>> ...
>> The 'low level' AKA magic happens in several *_fetch_syscall_args()
>> functions. For both linux32 and freebsd32, the magic code automatically
>> zero-extends the arguments into 64bit entities. Linux passes args in
>> registers, while FreeBSD uses words on stack.
>
> Actually, the amd64 linux_fetch32_fetch_syscall_args() just copies from
> 64-bit registers frame->tf_r* to 64-bit sa->args[*].  I can't see how
> this gives anything except garbage in the top bits.  Is there magic in
> the switch to 64-bit mode that sets the top bits?  Anyway, sign extension
> would give garbage for unsigned args, and zero-extension would give
> garbage for negative signed args.

I checked what actually happens.  There is no magic.  The registers
just have garbage in the top bits.  Mostly this is 0.  Sometimes it
is all top bits 1.  Sometimes it is some top bits 1 (starting at the
top).  I traced a bit of the execution of ld-linux.so...  The first
syscall was an linux_mmap.  It had all top bits 1 in tf_rbx, then some
top bits 1 in a later register, and all top bits 0 in 4 registers.
Then there were several syscalls with all top bits in all 6 syscall
arg registers 0.  Then there was a linux_write syscall with 1's back
in some top bits.  Then there were many syscalls with all top bits in
all arg registers 0.

This behaviour is probably due to the initial state being more random
(but why doesn't exec clear all top bits?).  Then normal activity
like xorl %ebx,%ebx tends to clear top bits (does this xorl clear top
bits even in 32-bit mode?).  Then something occasionally sets top bits
to 1.

> The amd64 ia32_fetch_syscall_args() is quite different.  Now the args
> ...

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120527172204.G989>