Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2010-02-08 Thread Vince Weaver
On Sun, 7 Feb 2010, Richard Henderson wrote:
> 
> I imagine that QEMU's VDSO would not have the complicated bits that the
> kernel's version does, where it arranges to read the clock without going into
> kernel space.  I imagine QEMU would simply stuff a normal syscall sequence in
> there, which would automatically be emulated in the normal way.

For what it's worth, this is how various other systems I'm aware of handle 
x86_64 VDSOs (both Valgrind and the m5 simulator do it this way).

Vince




Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2010-02-07 Thread Richard Henderson

On 02/06/2010 03:50 PM, Laurent Desnogues wrote:

* target-i386 code should not have to know about
  linux vsyscall


Given that we have to workaround 64-bit virtual
address limitations (cf. Richard mail and previous
discussions on the list), doing otherwise looks
difficult.


Actually, it should be easy for QEMU to handle this.

The application is given the address of the VDSO in the AT_SYSINFO and 
AT_SYSINFO_EHDR entries of the auxvec (on the stack above argv and 
environ).  We can place this anywhere we like; the fact that the kernel 
puts it in high memory is merely a convenience to the kernel.


There *is* a legacy vsyscall address in high memory, from before the 
whole VDSO arrangement was worked out, but we could probably get away 
with ignoring that.  Certainly well behaved applications will be 
honoring the VDSO when it is given.



* it is not possible to step into vsyscall code
  using a debugger


How would you achieve that?  Your guest OS
doesn't necessarily have the code mapped.  I
think this has to be considered as other syscalls,
though slightly different.


If QEMU implements the VDSO, the page *will* be mapped, and the debugger 
will Just Work.


I imagine that QEMU's VDSO would not have the complicated bits that the 
kernel's version does, where it arranges to read the clock without going 
into kernel space.  I imagine QEMU would simply stuff a normal syscall 
sequence in there, which would automatically be emulated in the normal way.


Have a stare at the linux/arch/x86/vdso directory to see how things work.


r~




Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2010-02-07 Thread Laurent Desnogues
On Sun, Feb 7, 2010 at 1:22 AM, Jamie Lokier  wrote:
[...]
>>
>> How would you achieve that?  Your guest OS
>> doesn't necessarily have the code mapped.  I
>> think this has to be considered as other syscalls,
>> though slightly different.
>
> There is no guest OS when doing -user emulation.
> Only qemu.

I meant that the vsyscall page doesn't exist on
other guest systems but x86_64 running Linux.
So if one wants to have it somehow mapped
then it would have to be installed by QEMU,
and QEMU can't install such a page due to
limitations in the way it handles virtual
addresses.

>> > My favorite solution would be a vsyscall page mapped
>> > to the correct fixed address and filled with QEMU
>> > generated specific code, for example code which calls the
>> > normal syscalls to do the work. This would only
>> > need modifications for linux-user code.
>>
>> You mean you'd explicitly put somewhere x86_64
>> code that simulates the behaviour of vsyscall?
>
> That seems like a good idea to me.

Why not indeed.  But someone will first have
to fix virtual memory management.


Laurent




Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2010-02-06 Thread malc
On Sun, 7 Feb 2010, Jamie Lokier wrote:

> Laurent Desnogues wrote:
> > On Sat, Feb 6, 2010 at 8:49 AM, Stefan Weil  wrote:
> > [...]
> > > I tested two different hosts with x86_64-linux-user:
> > >
> > > * 32 bit Intel (i386) - does not work with your patch
> > 
> > For me x86_64 on i386 has always failed without
> > even calling vsyscall :-)
> > 
> > > * 64 bit AMD (x86_64)  - works with your patch
> 
> It's a bit worrying that it depends on the host architecture at all.
> 
> How well does x86_64-linux-user emulation work on non-x86 hosts?

x64user$ uname -a   
Linux linmac 2.6.32.3 #4 Sun Jan 31 09:52:58 MSK 2010 ppc 7447A, altivec 
supported PowerMac10,2 GNU/Linux
x64user$ x86_64-linux-user/qemu-x86_64 -L ~/x/lut/gnemul/qemu-x86_64/ 
~/x/lut/x86_64/uname -a
Linux linmac 2.6.32.3 #4 Sun Jan 31 09:52:58 MSK 2010 x86-64 unknown

[..snip..]

-- 
mailto:av1...@comtv.ru

Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2010-02-06 Thread Jamie Lokier
Laurent Desnogues wrote:
> On Sat, Feb 6, 2010 at 8:49 AM, Stefan Weil  wrote:
> [...]
> > I tested two different hosts with x86_64-linux-user:
> >
> > * 32 bit Intel (i386) - does not work with your patch
> 
> For me x86_64 on i386 has always failed without
> even calling vsyscall :-)
> 
> > * 64 bit AMD (x86_64)  - works with your patch

It's a bit worrying that it depends on the host architecture at all.

How well does x86_64-linux-user emulation work on non-x86 hosts?

Does the vsyscall emulation depend only on the hosts's address sixe,
or does it have to be an x86 host to work?

> > * it is not possible to step into vsyscall code
> >  using a debugger
> 
> How would you achieve that?  Your guest OS
> doesn't necessarily have the code mapped.  I
> think this has to be considered as other syscalls,
> though slightly different.

There is no guest OS when doing -user emulation.
Only qemu.

> > My favorite solution would be a vsyscall page mapped
> > to the correct fixed address and filled with QEMU
> > generated specific code, for example code which calls the
> > normal syscalls to do the work. This would only
> > need modifications for linux-user code.
> 
> You mean you'd explicitly put somewhere x86_64
> code that simulates the behaviour of vsyscall?

That seems like a good idea to me.

-- Jamie




Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2010-02-06 Thread Laurent Desnogues
On Sat, Feb 6, 2010 at 8:49 AM, Stefan Weil  wrote:
[...]
> I tested two different hosts with x86_64-linux-user:
>
> * 32 bit Intel (i386) - does not work with your patch

For me x86_64 on i386 has always failed without
even calling vsyscall :-)

> * 64 bit AMD (x86_64)  - works with your patch
>
> Your patch improves the emulation for 64 bit hosts.
> Nevertheless, it has some open points:
>
> * target-i386 code should not have to know about
>  linux vsyscall

Given that we have to workaround 64-bit virtual
address limitations (cf. Richard mail and previous
discussions on the list), doing otherwise looks
difficult.

> * there is no vsyscall page in memory,
>  but very special programs might expect to see one
>  (it is even worse: the target sees the memory page
>  of the host)
>
> * it is not possible to step into vsyscall code
>  using a debugger

How would you achieve that?  Your guest OS
doesn't necessarily have the code mapped.  I
think this has to be considered as other syscalls,
though slightly different.

> My favorite solution would be a vsyscall page mapped
> to the correct fixed address and filled with QEMU
> generated specific code, for example code which calls the
> normal syscalls to do the work. This would only
> need modifications for linux-user code.

You mean you'd explicitly put somewhere x86_64
code that simulates the behaviour of vsyscall?


Laurent




Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2010-02-06 Thread Richard Henderson

On 02/05/2010 02:57 PM, Stefan Weil wrote:

I tried to modify x86_64-linux-user to set up a vsyscall page in high
memory, but this seems to be difficult (at least with 32 bit host).


A 64-bit userland guest can only use the low 32-bits of its address 
space with a 32-bit host at the moment.  If you can set up the vsyscall 
page in low memory, then you may be able to get this to work.


Otherwise you'll have to wait for someone to re-write the userland 
memory management in qemu.



r~




Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2010-02-05 Thread Stefan Weil
Laurent Desnogues schrieb:
> On Fri, Feb 5, 2010 at 11:57 PM, Stefan Weil  wrote:
>> Laurent Desnogues schrieb:
> [...]
>> I'm still struggling with bntest and other x86_64-linux-user software
>> calling any of the vsyscall functions.
>>
>> Laurent, your vsyscall patch only works on x86_64 hosts.
>>
>> A lot of software calls time() which uses vsyscall on x86_64 which
>> does not work with x86_64-linux-user mode.
>
> I'm not sure I understand what you mean. Did you try
> on some other host and it failed? Was your host
> 32-bit? If so, I'm afraid user-mode will fail for more
> reasons than vsyscall.
>
>> So the status of x86_64-linux-user is not more than experimental :-(
>>
>> I tried to modify x86_64-linux-user to set up a vsyscall page in high
>> memory,
>> but this seems to be difficult (at least with 32 bit host).
>>
>> Any hints how this should be done are welcome.
>
> My patch explicitly prevents the linking of the vsyscall
> page.
>
> Could you provide more info about your host?
>
>
> Laurent
>


I tested two different hosts with x86_64-linux-user:

* 32 bit Intel (i386) - does not work with your patch
* 64 bit AMD (x86_64)  - works with your patch

Your patch improves the emulation for 64 bit hosts.
Nevertheless, it has some open points:

* target-i386 code should not have to know about
  linux vsyscall

* there is no vsyscall page in memory,
  but very special programs might expect to see one
  (it is even worse: the target sees the memory page
  of the host)

* it is not possible to step into vsyscall code
  using a debugger

My favorite solution would be a vsyscall page mapped
to the correct fixed address and filled with QEMU
generated specific code, for example code which calls the
normal syscalls to do the work. This would only
need modifications for linux-user code.

Regards
Stefan





Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2010-02-05 Thread Laurent Desnogues
On Fri, Feb 5, 2010 at 11:57 PM, Stefan Weil  wrote:
> Laurent Desnogues schrieb:
[...]
>
> I'm still struggling with bntest and other x86_64-linux-user software
> calling any of the vsyscall functions.
>
> Laurent, your vsyscall patch only works on x86_64 hosts.
>
> A lot of software calls time() which uses vsyscall on x86_64 which
> does not work with x86_64-linux-user mode.

I'm not sure I understand what you mean.  Did you try
on some other host and it failed?  Was your host
32-bit?  If so, I'm afraid user-mode will fail for more
reasons than vsyscall.

> So the status of x86_64-linux-user is not more than experimental :-(
>
> I tried to modify x86_64-linux-user to set up a vsyscall page in high
> memory,
> but this seems to be difficult (at least with 32 bit host).
>
> Any hints how this should be done are welcome.

My patch explicitly prevents the linking of the vsyscall
page.

Could you provide more info about your host?


Laurent




Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2010-02-05 Thread Stefan Weil
Laurent Desnogues schrieb:
> On Sun, Oct 18, 2009 at 5:09 AM, Jamie Lokier  wrote:
> [...]
>> Please don't do that.  Some code traces instructions through the
>> vsyscall/vdso page, and will be surprised if a syscall instruction
>> does not do what's expected based on the registers at that point.
>>
>> Also I don't know if anyone's done this, but I have played with the
>> idea of an optimising x86->x86 JIT translator (similar to valgrind or
>> qemu's TCG) which would include the vdso instruction sequence in it's
>> traces, just because it didn't treat that any differently from other
>> userspace code.  Making the syscall instruction behave differently due
>> to EIP would break that sort of thing.
>>
>> There's no performance penalty in setting a few registers prior to
>> using the syscall instruction normally, so please do that.
>
> My proposed patch intercepts vsyscall as soon as the PC is
> in the [VSYSCALL_START, VSYSCALL_END[ range, so all
> instructions in that range won't be translated. Doing it
> differently will cause problems due to the virtual address.
>
>> On x86_64, the vsyscall page has fixed address (see
>> linux/arch/x86/kernel/vsyscall_64.c), but the vdso usually has
>> variable address.
>>
>> On x86_32, the vdso has randomised address unless configurd to be a
>> fixed address.  On older kernels it was a fixed address and some
>> binary programs assume they can call that.
>
> So QEMU can't do things properly and some binaries will
> fail, right?
>
>
> Laurent


I'm still struggling with bntest and other x86_64-linux-user software
calling any of the vsyscall functions.

Laurent, your vsyscall patch only works on x86_64 hosts.

A lot of software calls time() which uses vsyscall on x86_64 which
does not work with x86_64-linux-user mode.

So the status of x86_64-linux-user is not more than experimental :-(

I tried to modify x86_64-linux-user to set up a vsyscall page in high
memory,
but this seems to be difficult (at least with 32 bit host).

Any hints how this should be done are welcome.

Stefan





Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2010-02-04 Thread Stefan Weil
Laurent Desnogues schrieb:
> On Sun, Oct 18, 2009 at 5:09 AM, Jamie Lokier  wrote:
> [...]
>> Please don't do that.  Some code traces instructions through the
>> vsyscall/vdso page, and will be surprised if a syscall instruction
>> does not do what's expected based on the registers at that point.
>>
>> Also I don't know if anyone's done this, but I have played with the
>> idea of an optimising x86->x86 JIT translator (similar to valgrind or
>> qemu's TCG) which would include the vdso instruction sequence in it's
>> traces, just because it didn't treat that any differently from other
>> userspace code.  Making the syscall instruction behave differently due
>> to EIP would break that sort of thing.
>>
>> There's no performance penalty in setting a few registers prior to
>> using the syscall instruction normally, so please do that.
>
> My proposed patch intercepts vsyscall as soon as the PC is
> in the [VSYSCALL_START, VSYSCALL_END[ range, so all
> instructions in that range won't be translated. Doing it
> differently will cause problems due to the virtual address.
>
>> On x86_64, the vsyscall page has fixed address (see
>> linux/arch/x86/kernel/vsyscall_64.c), but the vdso usually has
>> variable address.
>>
>> On x86_32, the vdso has randomised address unless configurd to be a
>> fixed address.  On older kernels it was a fixed address and some
>> binary programs assume they can call that.
>
> So QEMU can't do things properly and some binaries will
> fail, right?
>
>
> Laurent

I can confirm that some binaries fail:

x86_64-linux-user/qemu-x86_64 ./bntest

with bntest from openssl creates a core dump.

Will Laurent's patch be applied, or is there a
better way to fix the problem?

Stefan






Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2009-10-18 Thread Laurent Desnogues
On Sun, Oct 18, 2009 at 5:09 AM, Jamie Lokier  wrote:
[...]
>
> Please don't do that.  Some code traces instructions through the
> vsyscall/vdso page, and will be surprised if a syscall instruction
> does not do what's expected based on the registers at that point.
>
> Also I don't know if anyone's done this, but I have played with the
> idea of an optimising x86->x86 JIT translator (similar to valgrind or
> qemu's TCG) which would include the vdso instruction sequence in it's
> traces, just because it didn't treat that any differently from other
> userspace code.  Making the syscall instruction behave differently due
> to EIP would break that sort of thing.
>
> There's no performance penalty in setting a few registers prior to
> using the syscall instruction normally, so please do that.

My proposed patch intercepts vsyscall as soon as the PC is
in the [VSYSCALL_START, VSYSCALL_END[ range, so all
instructions in that range won't be translated.  Doing it
differently will cause problems due to the virtual address.

> On x86_64, the vsyscall page has fixed address (see
> linux/arch/x86/kernel/vsyscall_64.c), but the vdso usually has
> variable address.
>
> On x86_32, the vdso has randomised address unless configurd to be a
> fixed address.  On older kernels it was a fixed address and some
> binary programs assume they can call that.

So QEMU can't do things properly and some binaries will
fail, right?


Laurent




Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2009-10-18 Thread Laurent Desnogues
On Sun, Oct 18, 2009 at 4:47 AM, Jamie Lokier  wrote:
> Laurent Desnogues wrote:
>> A recent compiler (gcc 4.4.0) produces this code for a statically
>> compiled program:
>>
>> 005779e0 :
>>   5779e0:     48 83 ec 08             sub    $0x8,%rsp
>>   5779e4:     48 c7 c0 00 04 60 ff    mov    $0xff600400,%rax
>>   5779eb:     ff d0                   callq  *%rax
>>   5779ed:     48 83 c4 08             add    $0x8,%rsp
>>   5779f1:     c3                      retq
>
> Yes.  It's a fixed address.  See the kernel at
> linux/arch/x86/kernel/vsyscall_64.c.  There are only 3 vsyscall
> functions defined: vgettimeofday, vtime and vgetcpu.

My proposed patch already implements vgettimeofday and
vtime. vgetcpu is TBD.

> Even though it's a statically linked program, I'm not sure if the
> above code will work on really old kernels.

All I can say is that it's what my toolchain generates.

Interestingly, dynamically shared programs don't run with
QEMU on my machine.  It looks like the PC is completely
wrong.

> The vsyscall page is different from the vdso, which has variable
> address, and the address is supplied to Glibc.  vdso provides nearly
> the same functions in a different way.

I don't understand how vdso and vsyscall interact (or don't
interact):  as I showed above, a statically linked program will
use vsyscall.  For dynamically linked program, I can't say,
given what I said above;  there might be a loader issue here.


Laurent




Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2009-10-18 Thread Edgar E. Iglesias
On Sun, Oct 18, 2009 at 04:09:44AM +0100, Jamie Lokier wrote:
> Edgar E. Iglesias wrote:
> > Did you consider having the linux-user loader pass a qemu version of the
> > x86_64 vdso to the guest through the auxvector? That version could probably
> > implement the vsyscalls by translating them into syscalls with x86_64 code.
> 
> That seems like a good idea.
> 
> Note that on x86_64, there is _both_ a vsyscall page at a fixed
> address, and a vdso page at a randomised address with different
> contents.  Binary programs can call either or both.
> 
> On x86_32, there is only a vdso page.  It can be a variable or fixed
> address.  To run old binaries (but not so old they don't know about
> vsyscall), it needs to be mapped at a fixed address.  Modern kernels
> have it mapped at a randomised address, and therefore won't work with
> those binaries.

Thanks for clarifiying.

If I understand correctly, my suggestion won't work for vsyscalls because
the specific fixed address might be unavailable or already used by the
host...

Cheers




Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2009-10-17 Thread Jamie Lokier
Edgar E. Iglesias wrote:
> Did you consider having the linux-user loader pass a qemu version of the
> x86_64 vdso to the guest through the auxvector? That version could probably
> implement the vsyscalls by translating them into syscalls with x86_64 code.

That seems like a good idea.

Note that on x86_64, there is _both_ a vsyscall page at a fixed
address, and a vdso page at a randomised address with different
contents.  Binary programs can call either or both.

On x86_32, there is only a vdso page.  It can be a variable or fixed
address.  To run old binaries (but not so old they don't know about
vsyscall), it needs to be mapped at a fixed address.  Modern kernels
have it mapped at a randomised address, and therefore won't work with
those binaries.

> It probably doesn't even need to do that btw, just make sure to fill it
> with syscall insns to raise exceptions and then have the linux-user/ code
> treat syscalls with eip from vdso page differently. That way the CPU model
> doesn't need to know about vdso and you can implement vsyscalls that may
> need magic interactions with qemu.
> 
> Or does that not work for some reason?

Please don't do that.  Some code traces instructions through the
vsyscall/vdso page, and will be surprised if a syscall instruction
does not do what's expected based on the registers at that point.

Also I don't know if anyone's done this, but I have played with the
idea of an optimising x86->x86 JIT translator (similar to valgrind or
qemu's TCG) which would include the vdso instruction sequence in it's
traces, just because it didn't treat that any differently from other
userspace code.  Making the syscall instruction behave differently due
to EIP would break that sort of thing.

There's no performance penalty in setting a few registers prior to
using the syscall instruction normally, so please do that.

> Performance?

syscall insns (sysenter/syscall/int $0x80/vsyscall/vdso) could be
translated to helpers for the exact type of system call if the system
call number is known, saving a little overhead.

> Are there maybe old binaries that don't look in the auxvector and
> just assume a fixed address for the vdso?

On x86_64, the vsyscall page has fixed address (see
linux/arch/x86/kernel/vsyscall_64.c), but the vdso usually has
variable address.

On x86_32, the vdso has randomised address unless configurd to be a
fixed address.  On older kernels it was a fixed address and some
binary programs assume they can call that.

-- Jamie




Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2009-10-17 Thread Jamie Lokier
Laurent Desnogues wrote:
> A recent compiler (gcc 4.4.0) produces this code for a statically
> compiled program:
> 
> 005779e0 :
>   5779e0: 48 83 ec 08 sub$0x8,%rsp
>   5779e4: 48 c7 c0 00 04 60 ffmov$0xff600400,%rax
>   5779eb: ff d0   callq  *%rax
>   5779ed: 48 83 c4 08 add$0x8,%rsp
>   5779f1: c3  retq

Yes.  It's a fixed address.  See the kernel at
linux/arch/x86/kernel/vsyscall_64.c.  There are only 3 vsyscall
functions defined: vgettimeofday, vtime and vgetcpu.

Even though it's a statically linked program, I'm not sure if the
above code will work on really old kernels.

The vsyscall page is different from the vdso, which has variable
address, and the address is supplied to Glibc.  vdso provides nearly
the same functions in a different way.

-- Jamie




Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2009-10-17 Thread Laurent Desnogues
Hi Edgar,

On Sat, Oct 17, 2009 at 9:57 PM, Edgar E. Iglesias
 wrote:
>
> It feels a bit strange to have the CPU model know about linux vsyscalls.
> Did you consider having the linux-user loader pass a qemu version of the
> x86_64 vdso to the guest through the auxvector? That version could probably
> implement the vsyscalls by translating them into syscalls with x86_64 code.
> It probably doesn't even need to do that btw, just make sure to fill it
> with syscall insns to raise exceptions and then have the linux-user/ code
> treat syscalls with eip from vdso page differently. That way the CPU model
> doesn't need to know about vdso and you can implement vsyscalls that may
> need magic interactions with qemu.
>
> Or does that not work for some reason? Performance?
> Are there maybe old binaries that don't look in the auxvector and just assume
> a fixed address for the vdso?

A recent compiler (gcc 4.4.0) produces this code for a statically
compiled program:

005779e0 :
  5779e0:   48 83 ec 08 sub$0x8,%rsp
  5779e4:   48 c7 c0 00 04 60 ffmov$0xff600400,%rax
  5779eb:   ff d0   callq  *%rax
  5779ed:   48 83 c4 08 add$0x8,%rsp
  5779f1:   c3  retq

I never heard of "auxvector" before.  Is this related to what is
discussed here?

http://manugarg.googlepages.com/aboutelfauxiliaryvectors

I dumped 4KB mapped at AT_SYSINFO_EHDR and processed
it through readelf. Nothing matches the address above:

 0:  0 NOTYPE  LOCAL  DEFAULT  UND
 1: ff70030c 0 SECTION LOCAL  DEFAULT7
 2: ff70080074 FUNCWEAK   DEFAULT   12
clock_gettime@@LINUX_2.6
 3:  0 OBJECT  GLOBAL DEFAULT  ABS LINUX_2.6
 4: ff7006c0   137 FUNCGLOBAL DEFAULT   12
__vdso_gettimeofday@@LINUX_2.6
 5: ff70085061 FUNCGLOBAL DEFAULT   12
__vdso_getcpu@@LINUX_2.6
 6: ff7006c0   137 FUNCWEAK   DEFAULT   12
gettimeofday@@LINUX_2.6
 7: ff70085061 FUNCWEAK   DEFAULT   12 getcpu@@LINUX_2.6
 8: ff70080074 FUNCGLOBAL DEFAULT   12
__vdso_clock_gettime@@LINUX_2.6

I probably missed your point :-)

Thanks,

Laurent




Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall

2009-10-17 Thread Edgar E. Iglesias
On Sat, Jul 11, 2009 at 05:14:47PM +0200, Laurent Desnogues wrote:
> Hello,
> 
> the attached patch implements two of the three x86_64 vsyscall's.
> Also attached is a test that demonstrates the issue and hopefully
> the fix.
> 
> Note there is a trick in there:  since vsyscall functions are in high
> memory, page_l1_map will return NULL resulting in an abort when
> calling tb_link_phys in tb_gen_code.  Also perhaps not very nice
> is the way a ret is simulated in cpu_loop.
> 
> I didn't implement vgetcpu.


Hello Laurent,

It feels a bit strange to have the CPU model know about linux vsyscalls.
Did you consider having the linux-user loader pass a qemu version of the
x86_64 vdso to the guest through the auxvector? That version could probably
implement the vsyscalls by translating them into syscalls with x86_64 code.
It probably doesn't even need to do that btw, just make sure to fill it
with syscall insns to raise exceptions and then have the linux-user/ code
treat syscalls with eip from vdso page differently. That way the CPU model
doesn't need to know about vdso and you can implement vsyscalls that may
need magic interactions with qemu.

Or does that not work for some reason? Performance?
Are there maybe old binaries that don't look in the auxvector and just assume
a fixed address for the vdso?


@@ -327,6 +330,9 @@ void cpu_loop(CPUX86State *env)
 int trapnr;
 abi_ulong pc;
 target_siginfo_t info;
+#ifdef TARGET_X86_64
+int syscall_num;
+#endif

 for(;;) {
 trapnr = cpu_x86_exec(env);
@@ -356,6 +362,37 @@ void cpu_loop(CPUX86State *env)
 env->eip = env->exception_next_eip;
 break;
 #endif
+#ifdef TARGET_X86_64
+case EXCP_VSYSCALL:

if you open up a new block here, the declaration of syscall_num can
be moved here (eliminating one #ifdef).

You could maybe also do the syscall mapping in the vsyscall.h file.
Something like this:

  env->regs[R_EAX] = do_syscall(env,
x86_64_vdsoaddr2syscall(env->eip),
env->regs[R_EDI],
env->regs[R_ESI],

Cheers




> 
> 
> Laurent
> 
> Signed-off-by: Laurent Desnogues 


> #include 
> #include 
> #include 
> #include 
> #include 
> 
> static void print_tod(const struct timeval *tv, const struct timezone *tz)
> {
>   if (tv)
> printf(" tv=%10ld.%06ld us",
>  tv->tv_sec, tv->tv_usec);
>   else
> fputs(" (tv null)", stdout);
>   if (tz)
> printf(" tz=%d/%d",
>  tz->tz_minuteswest, tz->tz_dsttime);
>   else
> fputs(" (tz null)", stdout);
>   fputc('\n', stdout);
> }
> 
> static time_t t1, t2;
> static struct timeval tv1, tv2;
> static struct timezone tz1, tz2;
> 
> int main(void)
> {
>   int ret;
> 
>   fputs("Checking vtime with NULL param\n", stdout);
>   t1 = time(NULL);
>   printf("  %ld\n", t1);
>   sleep(1);
>   t2 = time(NULL);
>   printf("  %ld (should be t1 + 1)\n", t2);
> 
>   fputs("Checking vtime with non NULL param\n", stdout);
>   time(&t1);
>   printf("  %ld\n", t1);
>   sleep(1);
>   time(&t2);
>   printf("  %ld (should be t1 + 1)\n", t2);
>   fputc('\n', stdout);
> 
> 
>   fputs("Checking gettimeofday\n", stdout);
>   ret = gettimeofday(&tv1, &tz1);
>   printf("  ret=%d", ret);
>   print_tod(&tv1, &tz1);
>   sleep(1);
>   ret = gettimeofday(&tv2, &tz2);
>   printf("  ret=%d", ret);
>   print_tod(&tv2, &tz2);
> 
>   fputs("Checking gettimeofday (tv NULL)\n", stdout);
>   ret = gettimeofday(NULL, &tz1);
>   printf("  ret=%d", ret);
>   print_tod(NULL, &tz1);
>   sleep(1);
>   ret = gettimeofday(NULL, &tz2);
>   printf("  ret=%d", ret);
>   print_tod(NULL, &tz2);
> 
>   fputs("Checking gettimeofday (tz NULL)\n", stdout);
>   ret = gettimeofday(&tv1, NULL);
>   printf("  ret=%d", ret);
>   print_tod(&tv1, NULL);
>   sleep(1);
>   ret = gettimeofday(&tv2, NULL);
>   printf("  ret=%d", ret);
>   print_tod(&tv2, NULL);
> 
>   fputs("Checking gettimeofday (tv and tz NULL)\n", stdout);
>   ret = gettimeofday(NULL, NULL);
>   printf("  ret=%d", ret);
>   print_tod(NULL, NULL);
>   sleep(1);
>   ret = gettimeofday(NULL, NULL);
>   printf("  ret=%d", ret);
>   print_tod(NULL, NULL);
> 
>   return 0;
> }