[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] x86_64: iret in long mode resets %fs and %gs base (doesn't on real CPUs),
Vegard Nossum <=