From patchwork Mon Mar 9 22:48:01 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bill Paul X-Patchwork-Id: 448288 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id F1C1B14007F for ; Tue, 10 Mar 2015 09:51:15 +1100 (AEDT) Received: from localhost ([::1]:45637 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YV6W2-0004Ki-13 for incoming@patchwork.ozlabs.org; Mon, 09 Mar 2015 18:51:14 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36081) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YV6Vm-0003dH-Ty for qemu-devel@nongnu.org; Mon, 09 Mar 2015 18:50:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YV6Vh-0005sc-Tl for qemu-devel@nongnu.org; Mon, 09 Mar 2015 18:50:58 -0400 Received: from mail.windriver.com ([147.11.1.11]:36428) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YV6Vh-0005sW-Jw for qemu-devel@nongnu.org; Mon, 09 Mar 2015 18:50:53 -0400 Received: from huisne.wrs.com (huisne.wrs.com [147.11.217.26]) by mail.windriver.com (8.14.9/8.14.5) with ESMTP id t29MoqNf022377 for ; Mon, 9 Mar 2015 15:50:52 -0700 (PDT) Received: from ala-wpaul-lx1.wrs.com (ala-wpaul-lx1.corp.ad.wrs.com [147.11.157.242]) by huisne.wrs.com (8.9.1/8.9.1) with ESMTP id PAA08045 for ; Mon, 9 Mar 2015 15:50:52 -0700 (PDT) From: Bill Paul Organization: Wind River Systems To: "qemu-devel" Date: Mon, 9 Mar 2015 15:48:01 -0700 User-Agent: KMail/1.13.5 (Linux/2.6.32-28-generic; KDE/4.4.5; x86_64; ; ) MIME-Version: 1.0 Message-Id: <201503091548.01462.wpaul@windriver.com> X-detected-operating-system: by eggs.gnu.org: Windows NT kernel [generic] [fuzzy] X-Received-From: 147.11.1.11 Subject: [Qemu-devel] Fix for incorrect SYSRET instruction implementation -- anyone looked at this yet? X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org I'm certain I'm sending this in plain text mode this time. According to my reading of the Intel documentation, the SYSRET instruction is supposed to force the RPL bits of the %ss register to 3 when returning to user mode. The actual sequence is: SS.Selector <-- (IA32_STAR[63:48]+8) OR 3; (* RPL forced to 3 *) However, the code in helper_sysret() leaves them at 0 (in other words, the "OR 3" part of the above sequence is missing). It does set the privilege level bits of %cs correctly though. This has caused me trouble with some of my VxWorks development: code that runs okay on real hardware will crash on QEMU, unless I apply the patch below. Can someone confirm that this is in fact a real bug? The Intel architecture manual seems quite clear about the SYSRET behavior. The bug seems to have been around as far back as QEMU 0.10.5. I am using QEMU 2.2.0 on FreeBSD/amd64 9.1-RELEASE. -Bill Signed-off-by: Bill Paul Reviewed-by: Fam Zheng --- target-i386/seg_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c index fa374d0..2bc757a 100644 --- a/target-i386/seg_helper.c +++ b/target-i386/seg_helper.c @@ -1043,7 +1043,7 @@ void helper_sysret(CPUX86State *env, int dflag) DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); env->eip = (uint32_t)env->regs[R_ECX]; } - cpu_x86_load_seg_cache(env, R_SS, selector + 8, + cpu_x86_load_seg_cache(env, R_SS, (selector + 8) | 3, 0, 0xffffffff, DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | (3 << DESC_DPL_SHIFT) | @@ -1056,7 +1056,7 @@ void helper_sysret(CPUX86State *env, int dflag) DESC_S_MASK | (3 << DESC_DPL_SHIFT) | DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); env->eip = (uint32_t)env->regs[R_ECX]; - cpu_x86_load_seg_cache(env, R_SS, selector + 8, + cpu_x86_load_seg_cache(env, R_SS, (selector + 8) | 3, 0, 0xffffffff, DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | (3 << DESC_DPL_SHIFT) |