From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NuXX5-0007Fl-QU for qemu-devel@nongnu.org; Wed, 24 Mar 2010 16:50:31 -0400 Received: from [140.186.70.92] (port=36042 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NuXX4-0007F1-Az for qemu-devel@nongnu.org; Wed, 24 Mar 2010 16:50:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1NuXX2-0001Uk-MW for qemu-devel@nongnu.org; Wed, 24 Mar 2010 16:50:30 -0400 Received: from fg-out-1718.google.com ([72.14.220.156]:42411) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1NuXX2-0001UQ-HE for qemu-devel@nongnu.org; Wed, 24 Mar 2010 16:50:28 -0400 Received: by fg-out-1718.google.com with SMTP id d23so1509089fga.10 for ; Wed, 24 Mar 2010 13:50:26 -0700 (PDT) MIME-Version: 1.0 Date: Wed, 24 Mar 2010 21:50:26 +0100 Message-ID: <19f34abd1003241350k3b831e62gc60307b0bc164617@mail.gmail.com> From: Vegard Nossum Content-Type: text/plain; charset=UTF-8 Subject: [Qemu-devel] x86_64: iret in long mode resets %fs and %gs base (doesn't on real CPUs) List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org 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