* [Qemu-devel] x86_64: iret in long mode resets %fs and %gs base (doesn't on real CPUs)
@ 2010-03-24 20:50 Vegard Nossum
0 siblings, 0 replies; only message in thread
From: Vegard Nossum @ 2010-03-24 20:50 UTC (permalink / raw)
To: qemu-devel
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
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2010-03-24 20:50 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-03-24 20:50 [Qemu-devel] x86_64: iret in long mode resets %fs and %gs base (doesn't on real CPUs) Vegard Nossum
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).