qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] x86_64: iret in long mode resets %fs and %gs base (doesn't


From: Vegard Nossum
Subject: [Qemu-devel] x86_64: iret in long mode resets %fs and %gs base (doesn't on real CPUs)
Date: Wed, 24 Mar 2010 21:50:26 +0100

Hi,

I've been investigating why some of my code failed on qemu, but
succeeded in bochs and on real hardware. In particular, it turns out
that qemu would reset the FS/GS_BASE_MSR whenever I did iret from ring
0 to 3.

I traced it down to this bit of code (in target-i386/op_helper.c):

static inline void validate_seg(int seg_reg, int cpl)
{
    int dpl;
    uint32_t e2;

    /* XXX: on x86_64, we do not want to nullify FS and GS because
       they may still contain a valid base. I would be interested to
       know how a real x86_64 CPU behaves */
    if ((seg_reg == R_FS || seg_reg == R_GS) &&
        (env->segs[seg_reg].selector & 0xfffc) == 0)
        return;

So the reason why this didn't work in qemu for me was that I was
loading the selector as 8 -- which fails the above test and
validate_seg() proceeds to clear the segment base value. Changing my
own code to only load 0 into %gs from the start fixed the problem for
me.

However, qemu is clearly doing something differently from the real
hardware. I tested both versions (loading 0 or 8 into %gs) on my Intel
P4, and GS_BASE_MSR is preserved in both cases. Perhaps the condition
on the selector value should be removed? (Or perhaps the calls to
validate_seg() for R_FS/R_GS should be removed from
helper_ret_protected()?)

Just a heads up.


Vegard




reply via email to

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