Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752995AbbBMNZn (ORCPT ); Fri, 13 Feb 2015 08:25:43 -0500 Received: from mail-qg0-f45.google.com ([209.85.192.45]:63165 "EHLO mail-qg0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752520AbbBMNZl convert rfc822-to-8bit (ORCPT ); Fri, 13 Feb 2015 08:25:41 -0500 MIME-Version: 1.0 In-Reply-To: <20150213120121.GC3712@pd.tnic> References: <1423768017-31766-1-git-send-email-dvlasenk@redhat.com> <20150213120121.GC3712@pd.tnic> From: Denys Vlasenko Date: Fri, 13 Feb 2015 14:25:20 +0100 Message-ID: Subject: Re: [PATCH] x86: x86-opcode-map.txt: explain CALLW discrepancy between Intel and AMD To: Borislav Petkov Cc: Denys Vlasenko , Masami Hiramatsu , Ingo Molnar , Oleg Nesterov , Linux Kernel Mailing List Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8BIT Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2666 Lines: 83 On Fri, Feb 13, 2015 at 1:01 PM, Borislav Petkov wrote: > On Thu, Feb 12, 2015 at 08:06:57PM +0100, Denys Vlasenko wrote: >> In 64-bit mode, AMD and Intel CPUs treat 0x66 prefix before branch >> insns differently. For near branches, it affects decode too since >> immediate offset's width is different. >> >> Signed-off-by: Denys Vlasenko >> CC: Masami Hiramatsu >> CC: Ingo Molnar >> CC: Oleg Nesterov >> CC: linux-kernel@vger.kernel.org >> --- >> arch/x86/lib/x86-opcode-map.txt | 9 +++++++++ >> 1 file changed, 9 insertions(+) >> >> diff --git a/arch/x86/lib/x86-opcode-map.txt b/arch/x86/lib/x86-opcode-map.txt >> index 1a2be7c..816488c 100644 >> --- a/arch/x86/lib/x86-opcode-map.txt >> +++ b/arch/x86/lib/x86-opcode-map.txt >> @@ -273,6 +273,9 @@ dd: ESC >> de: ESC >> df: ESC >> # 0xe0 - 0xef >> +# Note: "forced64" is Intel CPU behavior: they ignore 0x66 prefix >> +# in 64-bit mode. AMD CPUs accept 0x66 prefix, it causes RIP truncation >> +# to 16 bits. In 32-bit mode, 0x66 is accepted by both Intel and AMD. > > Well, according to the SDM, Intel truncates too, see the LOOP/LOOPcc > Operation section: > > ... > IF BranchCond = 1 > THEN > IF OperandSize = 32 > THEN EIP ← EIP + SignExtend(DEST); > ELSE IF OperandSize = 64 > THEN RIP ← RIP + SignExtend(DEST); > FI; > ELSE IF OperandSize = 16 > THEN EIP ← EIP AND 0000FFFFH; <--- > > and text talks about 0x67 but that's address size and it is used to size > the rCX register. > > So something must be setting the OperandSize and text doesn't mention > anywhere about 0x66 being ignored. > > Or have you been doing some empirical experiments? :-) Yes, I did. 32-bit case: Intel CPU truncates EIP to 16 bits: $ cat t.S _start: .globl _start 1: .byte 0x66 loop 1b $ gcc -nostartfiles -nostdlib -m32 t.S $ objdump -dr a.out a.out: file format elf32-i386 Disassembly of section .text: 08048098 <_start>: 8048098: 66 data16 8048099: e2 fd loop 8048098 <_start> $ gdb ./a.out (gdb) run Program received signal SIGSEGV, Segmentation fault. 0x00008098 in ?? () Now let's try 64-bit version - compiling without -m32: $ gcc -nostartfiles -nostdlib t.S $ ./a.out (runs without SEGV) -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/