All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Radim Krčmář" <rkrcmar@redhat.com>
To: kvm@vger.kernel.org
Cc: Paolo Bonzini <pbonzini@redhat.com>, P J P <ppandit@redhat.com>
Subject: [kvm-unit-tests PATCH 2/2] x86: add testcase for syscall/sysret TF handling
Date: Thu, 22 Jun 2017 17:27:07 +0200	[thread overview]
Message-ID: <20170622152707.18399-3-rkrcmar@redhat.com> (raw)
In-Reply-To: <20170622152707.18399-1-rkrcmar@redhat.com>

From: Paolo Bonzini <pbonzini@redhat.com>

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
---
 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
-- 
2.13.1

  parent reply	other threads:[~2017-06-22 15:27 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-22 15:27 [kvm-unit-tests PATCH 0/2] x86: Testcase for wrong TF handling in syscall/sysret Radim Krčmář
2017-06-22 15:27 ` [kvm-unit-tests PATCH 1/2] x86: move syscall MSR testcase to separate test Radim Krčmář
2017-06-22 15:27 ` Radim Krčmář [this message]
2017-07-27 12:05 ` [kvm-unit-tests PATCH 0/2] x86: Testcase for wrong TF handling in syscall/sysret Wanpeng Li
2017-07-27 13:09   ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170622152707.18399-3-rkrcmar@redhat.com \
    --to=rkrcmar@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=ppandit@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.