From patchwork Thu Jun 22 15:27:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?UmFkaW0gS3LEjW3DocWZ?= X-Patchwork-Id: 9804705 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2D46060386 for ; Thu, 22 Jun 2017 15:27:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1D76928696 for ; Thu, 22 Jun 2017 15:27:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 124A0286A3; Thu, 22 Jun 2017 15:27:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 84DEC28696 for ; Thu, 22 Jun 2017 15:27:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752424AbdFVP13 (ORCPT ); Thu, 22 Jun 2017 11:27:29 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50150 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751224AbdFVP12 (ORCPT ); Thu, 22 Jun 2017 11:27:28 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4F775120E8 for ; Thu, 22 Jun 2017 15:27:28 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 4F775120E8 Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=rkrcmar@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 4F775120E8 Received: from potion (unknown [10.43.2.65]) by smtp.corp.redhat.com (Postfix) with SMTP id 8EE7960608; Thu, 22 Jun 2017 15:27:26 +0000 (UTC) Received: by potion (sSMTP sendmail emulation); Thu, 22 Jun 2017 17:27:25 +0200 From: =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= To: kvm@vger.kernel.org Cc: Paolo Bonzini , P J P Subject: [kvm-unit-tests PATCH 2/2] x86: add testcase for syscall/sysret TF handling Date: Thu, 22 Jun 2017 17:27:07 +0200 Message-Id: <20170622152707.18399-3-rkrcmar@redhat.com> In-Reply-To: <20170622152707.18399-1-rkrcmar@redhat.com> References: <20170622152707.18399-1-rkrcmar@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Thu, 22 Jun 2017 15:27:28 +0000 (UTC) Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Paolo Bonzini Signed-off-by: Paolo Bonzini Signed-off-by: Radim Krčmář --- lib/x86/processor.h | 4 +++ x86/syscall.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++ x86/unittests.cfg | 1 + 3 files changed, 85 insertions(+) diff --git a/lib/x86/processor.h b/lib/x86/processor.h index 895d992a6943..3e1a853b392b 100644 --- a/lib/x86/processor.h +++ b/lib/x86/processor.h @@ -35,7 +35,11 @@ #define X86_EFLAGS_AF 0x00000010 #define X86_EFLAGS_ZF 0x00000040 #define X86_EFLAGS_SF 0x00000080 +#define X86_EFLAGS_TF 0x00000100 +#define X86_EFLAGS_IF 0x00000200 +#define X86_EFLAGS_DF 0x00000400 #define X86_EFLAGS_OF 0x00000800 +#define X86_EFLAGS_NT 0x00004000 #define X86_EFLAGS_AC 0x00040000 #define X86_IA32_EFER 0xc0000080 diff --git a/x86/syscall.c b/x86/syscall.c index d791edd6155d..8c3992d39b76 100644 --- a/x86/syscall.c +++ b/x86/syscall.c @@ -20,9 +20,89 @@ static void test_syscall_lazy_load(void) report("MSR_*STAR eager loading", true); } +/* + * test handling of TF in syscall/sysret: #DB is raised if TF + * is 1 at the *end* of syscall/sysret. + * + * This uses 32-bit syscall/sysret because KVM emulates it on Intel processors. + * However, the same bug happens with 64-bit syscall/sysret if two vCPUs + * "race" to force the emulation of syscall/sysret. + */ + +static uint16_t code_segment_upon_db; +static void handle_db(struct ex_regs *regs) +{ + code_segment_upon_db = regs->cs; + regs->rflags &= ~(1 << 8); +} + +/* expects desired ring 3 flags in rax */ +asm("syscall32_target:\n" + " cmp $0, code_segment_upon_db(%rip)\n" + " jne back_to_test\n" + " mov %eax,%r11d\n" + " sysretl\n"); + +/* 32-bit, ring-3 part of test_syscall_tf */ +asm(" .code32\n" + "syscall_tf_user32:\n" + " pushf\n" + " pop %eax\n" + " or $(1<<8),%eax\n" + " push %eax\n" + " popf\n" + " syscall\n" /* singlestep trap taken after syscall */ + " syscall\n" /* jumps back to test_syscall_tf's body */ + " .code64\n"); + +static void test_syscall_tf(void) +{ + extern void syscall32_target(); + extern void syscall_tf_user32(); + ulong rcx; + + wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_SCE); + wrmsr(MSR_CSTAR, (ulong)syscall32_target); + wrmsr(MSR_STAR, ((uint64_t)USER_CS32 << 48) | ((uint64_t)KERNEL_CS64 << 32)); + wrmsr(MSR_SYSCALL_MASK, X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_NT); + handle_exception(DB_VECTOR, handle_db); + + /* good: + * sysret to syscall_tf_user32 + * popf sets TF (singlestep starts on the next instruction) + * syscall to syscall32_target -> TF cleared and no singlestep + * sysretl sets TF + * handle_db sets code_segment_upon_db to USER_CS32 and clears TF + * syscall to syscall32_target + * syscall32_target jumps to back_to_test + * + * bad: + * sysret to syscall_tf_user32 + * popf sets TF (singlestep starts on the next instruction) + * syscall to syscall32_target, TF cleared and wrong singlestep exception + * handle_db sets code_segment_upon_db to KERNEL_CS64 + * syscall32_target jumps to back_to_test + */ + rcx = (ulong)syscall_tf_user32; + asm volatile(" push %%rbp\n" + " pushf; pop %%rax\n" // expected by syscall32_target + " sysret\n" + "back_to_test:\n" + " pop %%rbp" + : "+c"(rcx) : + : "rax", "rbx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15"); + if (code_segment_upon_db != USER_CS32) { + printf("wrong CS (%#04x)!\n", code_segment_upon_db); + } + report("syscall TF handling", code_segment_upon_db == USER_CS32); +} + int main(int ac, char **av) { + setup_idt(); test_syscall_lazy_load(); + test_syscall_tf(); return report_summary(); } diff --git a/x86/unittests.cfg b/x86/unittests.cfg index 2575ae6b3d5b..6455ee50f27f 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -153,6 +153,7 @@ file = sieve.flat [syscall] file = syscall.flat +extra_params = -cpu Opteron_G1,vendor=AuthenticAMD [tsc] file = tsc.flat