From patchwork Thu Mar 3 01:09:31 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Feiner X-Patchwork-Id: 8487031 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id E02699F96D for ; Thu, 3 Mar 2016 01:09:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D22BE201FE for ; Thu, 3 Mar 2016 01:09:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id ADD0C2034A for ; Thu, 3 Mar 2016 01:09:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752989AbcCCBJu (ORCPT ); Wed, 2 Mar 2016 20:09:50 -0500 Received: from mail-pf0-f171.google.com ([209.85.192.171]:36534 "EHLO mail-pf0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751243AbcCCBJt (ORCPT ); Wed, 2 Mar 2016 20:09:49 -0500 Received: by mail-pf0-f171.google.com with SMTP id 63so4165898pfe.3 for ; Wed, 02 Mar 2016 17:09:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=yr88sXTC7FjsemTepPMxbzjRDLEG6/GJ/3NpxM/6auc=; b=YUEeTBbAtVAg+N+YITj/ZTjudfdepYk7V8OpIyUl9I8KySQUHB+OgfaecrYb7hYbhS sMVaeRoYeBbu18XLMo4PMLE7m4ZB4K5XtBBjShajhWcTZNIwo16rEmm45Tfsne5/izSe OL30s4f5Rv/1ksNkbTf0uLD04DptIc0deVIMvFf9S5QBnx+8L79KXB2qMub7wxf4waDN Ih64wifS4wmJL4HREx5JR5ZW1Ln6Sf83ouH0oc/QOLMl0OSnItp+0LflzvIlkqpP7ths IQLPVlD1H1xrBFJMEszTcG0Aqi4z8e3oJIDSW4mySlPje3p402PUjE5WC1FNdoHnlVTL SxKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=yr88sXTC7FjsemTepPMxbzjRDLEG6/GJ/3NpxM/6auc=; b=OkpbSOjfhtpPvM4qoIZJGqMkDQKFf30bTFeFM2jQbXeGRP0vnNuK9jCVFVb4rN8+pC BisaioZxIMJrls2z121hrNIa72FZ81q+PgDVjqQSchJ1OshKlPcUJbplAuRKy5atsxRT nfSNTiKt35eMPn7qeJ9R9XZn1sr3gFW/w4zgFc3IMOnywo5ZoJudPGZp0cWdC7GyWpI9 8rX1/4BTAHnMmMjaR6fpMEMOAWHT0RGApmJgxKcUSFVOq8woXM16xrdwGwotq1wGtU00 hYUZDDn0uttkryO4t4Yzq44hGPWu3n0TFa2PFjJCSGCpMxKijlteUexiBWlCqpjyFolw gs4w== X-Gm-Message-State: AD7BkJJzIFvNi6q+ELw6GS9RjR8uRavVz/Q+DoeN4VECtGXW9gMBOBqXfL6cQJJYr+T/Rx0I X-Received: by 10.98.67.67 with SMTP id q64mr43784902pfa.44.1456967388237; Wed, 02 Mar 2016 17:09:48 -0800 (PST) Received: from localhost ([2620:0:1009:3:10b2:1b3a:febc:1b15]) by smtp.gmail.com with ESMTPSA id v9sm11342825pfi.50.2016.03.02.17.09.47 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Wed, 02 Mar 2016 17:09:47 -0800 (PST) From: Peter Feiner To: kvm@vger.kernel.org, drjones@redhat.com, pbonzini@redhat.com Cc: pfeiner@google.com Subject: [kvm-unit-tests v2 1/8] x86: emulator: asm fixes Date: Wed, 2 Mar 2016 17:09:31 -0800 Message-Id: <1456967378-6367-2-git-send-email-pfeiner@google.com> X-Mailer: git-send-email 2.7.0.rc3.207.g0ac5344 In-Reply-To: <1456967378-6367-1-git-send-email-pfeiner@google.com> References: <1456867658-10937-1-git-send-email-pfeiner@google.com> <1456967378-6367-1-git-send-email-pfeiner@google.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Found several problems in the emulator test when trying to compile with various combinations of -fno-omit-frame-pointer and -O{0,1}. Fixed register clobbering in several tests. It's not good enough to save & restore a register with I/O operands because the compiler can use the register to effect the I/O! Fixing %rbp was tricky because it can't be listed in the clobber list when -fno-omit-frame-pointer is in effect; thus %rbp has to be saved manually using a scratch register that's declared as clobbered. The length of the jmp instruction in test_jmp_noncanonical was 2, not 3. This patch makes the exception handler more robust by using the computed instruction length. Signed-off-by: Peter Feiner --- x86/emulator.c | 60 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/x86/emulator.c b/x86/emulator.c index e5c1c6b..d990961 100644 --- a/x86/emulator.c +++ b/x86/emulator.c @@ -260,24 +260,30 @@ void test_pop(void *mem) report("ret", 1); stack_top[-1] = 0x778899; - asm volatile("mov %%rsp, %[tmp] \n\t" - "mov %%rbp, %[tmp3] \n\t" - "mov %[stack_top], %%rbp \n\t" + asm volatile("mov %[stack_top], %%r8 \n\t" + "mov %%rsp, %%r9 \n\t" + "xchg %%rbp, %%r8 \n\t" "leave \n\t" - "xchg %%rsp, %[tmp] \n\t" - "xchg %%rbp, %[tmp3]" + "xchg %%rsp, %%r9 \n\t" + "xchg %%rbp, %%r8 \n\t" + "mov %%r9, %[tmp] \n\t" + "mov %%r8, %[tmp3]" : [tmp]"=&r"(tmp), [tmp3]"=&r"(tmp3) : [stack_top]"r"(stack_top-1) - : "memory"); + : "memory", "r8", "r9"); report("leave", tmp == (ulong)stack_top && tmp3 == 0x778899); rbp = 0xaa55aa55bb66bb66ULL; rsp = (unsigned long)stack_top; - asm volatile("xchg %%rsp, %[rsp] \n\t" - "xchg %%rbp, %[rbp] \n\t" + asm volatile("mov %[rsp], %%r8 \n\t" + "mov %[rbp], %%r9 \n\t" + "xchg %%rsp, %%r8 \n\t" + "xchg %%rbp, %%r9 \n\t" "enter $0x1238, $0 \n\t" - "xchg %%rsp, %[rsp] \n\t" - "xchg %%rbp, %[rbp]" - : [rsp]"+a"(rsp), [rbp]"+b"(rbp) : : "memory"); + "xchg %%rsp, %%r8 \n\t" + "xchg %%rbp, %%r9 \n\t" + "xchg %%r8, %[rsp] \n\t" + "xchg %%r9, %[rbp]" + : [rsp]"+a"(rsp), [rbp]"+b"(rbp) : : "memory", "r8", "r9"); report("enter", rsp == (unsigned long)stack_top - 8 - 0x1238 && rbp == (unsigned long)stack_top - 8 @@ -405,7 +411,7 @@ void test_xchg(void *mem) "mov %%rax, %[rax]\n\t" : [rax]"=r"(rax) : [memq]"r"(memq) - : "memory"); + : "memory", "rax"); report("xchg reg, r/m (1)", rax == 0xfedcba98765432ef && *memq == 0x123456789abcd10); @@ -416,7 +422,7 @@ void test_xchg(void *mem) "mov %%rax, %[rax]\n\t" : [rax]"=r"(rax) : [memq]"r"(memq) - : "memory"); + : "memory", "rax"); report("xchg reg, r/m (2)", rax == 0xfedcba987654cdef && *memq == 0x123456789ab3210); @@ -427,7 +433,7 @@ void test_xchg(void *mem) "mov %%rax, %[rax]\n\t" : [rax]"=r"(rax) : [memq]"r"(memq) - : "memory"); + : "memory", "rax"); report("xchg reg, r/m (3)", rax == 0x89abcdef && *memq == 0x123456776543210); @@ -438,7 +444,7 @@ void test_xchg(void *mem) "mov %%rax, %[rax]\n\t" : [rax]"=r"(rax) : [memq]"r"(memq) - : "memory"); + : "memory", "rax"); report("xchg reg, r/m (4)", rax == 0x123456789abcdef && *memq == 0xfedcba9876543210); } @@ -455,7 +461,7 @@ void test_xadd(void *mem) "mov %%rax, %[rax]\n\t" : [rax]"=r"(rax) : [memq]"r"(memq) - : "memory"); + : "memory", "rax"); report("xadd reg, r/m (1)", rax == 0xfedcba98765432ef && *memq == 0x123456789abcdff); @@ -466,7 +472,7 @@ void test_xadd(void *mem) "mov %%rax, %[rax]\n\t" : [rax]"=r"(rax) : [memq]"r"(memq) - : "memory"); + : "memory", "rax"); report("xadd reg, r/m (2)", rax == 0xfedcba987654cdef && *memq == 0x123456789abffff); @@ -477,7 +483,7 @@ void test_xadd(void *mem) "mov %%rax, %[rax]\n\t" : [rax]"=r"(rax) : [memq]"r"(memq) - : "memory"); + : "memory", "rax"); report("xadd reg, r/m (3)", rax == 0x89abcdef && *memq == 0x1234567ffffffff); @@ -488,7 +494,7 @@ void test_xadd(void *mem) "mov %%rax, %[rax]\n\t" : [rax]"=r"(rax) : [memq]"r"(memq) - : "memory"); + : "memory", "rax"); report("xadd reg, r/m (4)", rax == 0x123456789abcdef && *memq == 0xffffffffffffffff); } @@ -804,10 +810,12 @@ static void trap_emulator(uint64_t *mem, void *alt_insn_page, outregs = save; } -static void advance_rip_by_3_and_note_exception(struct ex_regs *regs) +static unsigned long rip_advance; + +static void advance_rip_and_note_exception(struct ex_regs *regs) { ++exceptions; - regs->rip += 3; + regs->rip += rip_advance; } static void test_mmx_movq_mf(uint64_t *mem, uint8_t *insn_page, @@ -819,11 +827,12 @@ static void test_mmx_movq_mf(uint64_t *mem, uint8_t *insn_page, write_cr0(read_cr0() & ~6); /* TS, EM */ exceptions = 0; - handle_exception(MF_VECTOR, advance_rip_by_3_and_note_exception); + handle_exception(MF_VECTOR, advance_rip_and_note_exception); asm volatile("fninit; fldcw %0" : : "m"(fcw)); asm volatile("fldz; fldz; fdivp"); /* generate exception */ MK_INSN(mmx_movq_mf, "movq %mm0, (%rax) \n\t"); + rip_advance = insn_mmx_movq_mf.len; inregs = (struct regs){ .rsp=(u64)stack+1024 }; trap_emulator(mem, alt_insn_page, &insn_mmx_movq_mf); /* exit MMX mode */ @@ -834,11 +843,14 @@ static void test_mmx_movq_mf(uint64_t *mem, uint8_t *insn_page, static void test_jmp_noncanonical(uint64_t *mem) { + extern char nc_jmp_start, nc_jmp_end; + *mem = 0x1111111111111111ul; exceptions = 0; - handle_exception(GP_VECTOR, advance_rip_by_3_and_note_exception); - asm volatile ("jmp *%0" : : "m"(*mem)); + rip_advance = &nc_jmp_end - &nc_jmp_start; + handle_exception(GP_VECTOR, advance_rip_and_note_exception); + asm volatile ("nc_jmp_start: jmp *%0; nc_jmp_end:" : : "m"(*mem)); report("jump to non-canonical address", exceptions == 1); handle_exception(GP_VECTOR, 0); }