qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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


From: Edgar E. Iglesias
Subject: Re: [Qemu-devel] [PATCH] User mode: Handle x86_64 vsyscall
Date: Sat, 17 Oct 2009 21:57:26 +0200
User-agent: Mutt/1.5.20 (2009-06-14)

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 <address@hidden>


> #include <stdio.h>
> #include <stdint.h>
> #include <time.h>
> #include <unistd.h>
> #include <sys/time.h>
> 
> 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;
> }





reply via email to

[Prev in Thread] Current Thread [Next in Thread]