From patchwork Thu Feb 10 08:46:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hou Wenlong X-Patchwork-Id: 12741565 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 09535C433F5 for ; Thu, 10 Feb 2022 08:47:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237875AbiBJIrA (ORCPT ); Thu, 10 Feb 2022 03:47:00 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:45340 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237870AbiBJIq7 (ORCPT ); Thu, 10 Feb 2022 03:46:59 -0500 Received: from out0-145.mail.aliyun.com (out0-145.mail.aliyun.com [140.205.0.145]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B072F1E7 for ; Thu, 10 Feb 2022 00:46:59 -0800 (PST) X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R141e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=ay29a033018047205;MF=houwenlong.hwl@antgroup.com;NM=1;PH=DS;RN=4;SR=0;TI=SMTPD_---.MntXQUp_1644482816; Received: from localhost(mailfrom:houwenlong.hwl@antgroup.com fp:SMTPD_---.MntXQUp_1644482816) by smtp.aliyun-inc.com(127.0.0.1); Thu, 10 Feb 2022 16:46:56 +0800 From: "Hou Wenlong" To: kvm@vger.kernel.org Cc: "Sean Christopherson" , "Hou Wenlong" , "Paolo Bonzini" Subject: [kvm-unit-tests PATCH v3 1/3] x86/emulator: Add some tests for far ret instruction emulation Date: Thu, 10 Feb 2022 16:46:33 +0800 Message-Id: <5e4eab590cb46108d2b007a117edf1b9f566446d.1644481282.git.houwenlong.hwl@antgroup.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Per Intel's SDM on the "Instruction Set Reference", when loading segment descriptor for far return, not-present segment check should be after all type and privilege checks. However, __load_segment_descriptor() in x86's emulator does not-present segment check first, so it would trigger #NP instead of #GP if type or privilege checks fail and the segment is not present. And if RPL < CPL, it should trigger #GP, but the check is missing in emulator. So add some tests for far ret instruction, and it will test those tests on hardware and emulator. Enable kvm.force_emulation_prefix when try to test them on emulator. Signed-off-by: Hou Wenlong --- x86/emulator.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/x86/emulator.c b/x86/emulator.c index cd78e3cbbcd7..c56b32be8baa 100644 --- a/x86/emulator.c +++ b/x86/emulator.c @@ -21,6 +21,60 @@ static int exceptions; #define KVM_FEP "ud2; .byte 'k', 'v', 'm';" #define KVM_FEP_LENGTH 5 static int fep_available = 1; +static int far_xfer_vector = -1; +static unsigned int far_xfer_error_code = -1; + +struct far_xfer_test_case { + uint16_t rpl; + uint16_t type; + uint16_t dpl; + uint16_t p; + bool usermode; + int vector; + const char *msg; +}; + +enum far_xfer_insn { + FAR_XFER_RET, +}; + +struct far_xfer_test { + enum far_xfer_insn insn; + const char *insn_name; + struct far_xfer_test_case *testcases; + unsigned int nr_testcases; +}; + +#define NON_CONFORM_CS_TYPE 0xb +#define CONFORM_CS_TYPE 0xf +#define DS_TYPE 0x3 + +static struct far_xfer_test_case far_ret_testcases[] = { + {0, DS_TYPE, 0, 0, false, GP_VECTOR, "desc.type!=code && desc.p=0"}, + {0, NON_CONFORM_CS_TYPE, 3, 0, false, GP_VECTOR, "non-conforming && dpl!=rpl && desc.p=0"}, + {0, CONFORM_CS_TYPE, 3, 0, false, GP_VECTOR, "conforming && dpl>rpl && desc.p=0"}, + {0, NON_CONFORM_CS_TYPE, 0, 0, false, NP_VECTOR, "desc.p=0"}, + {0, NON_CONFORM_CS_TYPE, 3, 1, true, GP_VECTOR, "rplvector; + far_xfer_error_code = regs->error_code; + regs->rip = regs->rax; +} + +static void __test_far_xfer(enum far_xfer_insn insn, uint16_t seg, + bool force_emulation) +{ + switch (insn) { + case FAR_XFER_RET: + if (force_emulation) + TEST_FAR_RET_ASM(seg, KVM_FEP); + else + TEST_FAR_RET_ASM(seg, ""); + break; + default: + report_fail("Unexpected insn enum = %d\n", insn); + break; + } +} + +static void test_far_xfer(bool force_emulation, struct far_xfer_test *test) +{ + struct far_xfer_test_case *t; + uint16_t seg; + bool ign; + int i; + + handle_exception(GP_VECTOR, far_xfer_exception_handler); + handle_exception(NP_VECTOR, far_xfer_exception_handler); + + for (i = 0; i < test->nr_testcases; i++) { + t = &test->testcases[i]; + + seg = FIRST_SPARE_SEL | t->rpl; + gdt[seg / 8] = gdt[(t->usermode ? USER_CS64 : KERNEL_CS) / 8]; + gdt[seg / 8].type = t->type; + gdt[seg / 8].dpl = t->dpl; + gdt[seg / 8].p = t->p; + + far_xfer_vector = -1; + far_xfer_error_code = -1; + + if (t->usermode) + run_in_user((usermode_func)__test_far_xfer, UD_VECTOR, + test->insn, seg, force_emulation, 0, &ign); + else + __test_far_xfer(test->insn, seg, force_emulation); + + report(far_xfer_vector == t->vector && + (far_xfer_vector < 0 || far_xfer_error_code == FIRST_SPARE_SEL), + "%s on %s, %s: wanted %d (%d), got %d (%d)", + test->insn_name, force_emulation ? "emulator" : "hardware", t->msg, + t->vector, t->vector < 0 ? -1 : FIRST_SPARE_SEL, + far_xfer_vector, far_xfer_error_code); + } + + handle_exception(GP_VECTOR, 0); + handle_exception(NP_VECTOR, 0); +} + +static void test_far_ret(uint64_t *mem) +{ + test_far_xfer(false, &far_ret_test); +} + +static void test_em_far_ret(uint64_t *mem) +{ + test_far_xfer(true, &far_ret_test); +} + static void test_push16(uint64_t *mem) { uint64_t rsp1, rsp2; @@ -1169,6 +1296,7 @@ int main(void) test_smsw(mem); test_lmsw(); test_ljmp(mem); + test_far_ret(mem); test_stringio(); test_incdecnotneg(mem); test_btc(mem); @@ -1193,6 +1321,7 @@ int main(void) test_smsw_reg(mem); test_nop(mem); test_mov_dr(mem); + test_em_far_ret(mem); } else { report_skip("skipping register-only tests, " "use kvm.force_emulation_prefix=1 to enable"); From patchwork Thu Feb 10 08:46:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hou Wenlong X-Patchwork-Id: 12741566 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4D562C433EF for ; Thu, 10 Feb 2022 08:47:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237921AbiBJIrP (ORCPT ); Thu, 10 Feb 2022 03:47:15 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:45472 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237870AbiBJIrJ (ORCPT ); Thu, 10 Feb 2022 03:47:09 -0500 Received: from out0-146.mail.aliyun.com (out0-146.mail.aliyun.com [140.205.0.146]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 70D881E7 for ; Thu, 10 Feb 2022 00:47:10 -0800 (PST) X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R591e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=ay29a033018047190;MF=houwenlong.hwl@antgroup.com;NM=1;PH=DS;RN=4;SR=0;TI=SMTPD_---.MntXQXa_1644482825; Received: from localhost(mailfrom:houwenlong.hwl@antgroup.com fp:SMTPD_---.MntXQXa_1644482825) by smtp.aliyun-inc.com(127.0.0.1); Thu, 10 Feb 2022 16:47:05 +0800 From: "Hou Wenlong" To: kvm@vger.kernel.org Cc: "Sean Christopherson" , "Hou Wenlong" , "Paolo Bonzini" Subject: [kvm-unit-tests PATCH v3 2/3] x86/emulator: Rename test_ljmp() as test_far_jmp() Date: Thu, 10 Feb 2022 16:46:34 +0800 Message-Id: <8d712b48c0b5c2f0e4c3a0126321a083d850591e.1644481282.git.houwenlong.hwl@antgroup.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Rename test_ljmp() as test_far_jmp() to better match the SDM. Also change the output of test to explain what it is doing. Suggested-by: Sean Christopherson Signed-off-by: Hou Wenlong --- x86/emulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x86/emulator.c b/x86/emulator.c index c56b32be8baa..45972c2fe940 100644 --- a/x86/emulator.c +++ b/x86/emulator.c @@ -358,7 +358,7 @@ static void test_pop(void *mem) "enter"); } -static void test_ljmp(void *mem) +static void test_far_jmp(void *mem) { unsigned char *m = mem; volatile int res = 1; @@ -368,7 +368,7 @@ static void test_ljmp(void *mem) asm volatile ("rex64 ljmp *%0"::"m"(*m)); res = 0; jmpf: - report(res, "ljmp"); + report(res, "far jmp, via emulated MMIO"); } static void test_incdecnotneg(void *mem) @@ -1295,7 +1295,7 @@ int main(void) test_smsw(mem); test_lmsw(); - test_ljmp(mem); + test_far_jmp(mem); test_far_ret(mem); test_stringio(); test_incdecnotneg(mem); From patchwork Thu Feb 10 08:46:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hou Wenlong X-Patchwork-Id: 12741567 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EFE86C433EF for ; Thu, 10 Feb 2022 08:47:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237917AbiBJIrY (ORCPT ); Thu, 10 Feb 2022 03:47:24 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:45596 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237934AbiBJIrN (ORCPT ); Thu, 10 Feb 2022 03:47:13 -0500 Received: from out0-143.mail.aliyun.com (out0-143.mail.aliyun.com [140.205.0.143]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7482B10E2 for ; Thu, 10 Feb 2022 00:47:13 -0800 (PST) X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R151e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=ay29a033018047187;MF=houwenlong.hwl@antgroup.com;NM=1;PH=DS;RN=4;SR=0;TI=SMTPD_---.MnuUIKp_1644482830; Received: from localhost(mailfrom:houwenlong.hwl@antgroup.com fp:SMTPD_---.MnuUIKp_1644482830) by smtp.aliyun-inc.com(127.0.0.1); Thu, 10 Feb 2022 16:47:10 +0800 From: "Hou Wenlong" To: kvm@vger.kernel.org Cc: "Sean Christopherson" , "Hou Wenlong" , "Paolo Bonzini" Subject: [kvm-unit-tests PATCH v3 3/3] x86/emulator: Add some tests for far jmp instruction emulation Date: Thu, 10 Feb 2022 16:46:35 +0800 Message-Id: <9c1d2125cb8680aff8a69e04461c4d84edb85760.1644481282.git.houwenlong.hwl@antgroup.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Per Intel's SDM on the "Instruction Set Reference", when loading segment descriptor for far jmp, not-present segment check should be after all type and privilege checks. However, __load_segment_descriptor() in x86's emulator does not-present segment check first, so it would trigger #NP instead of #GP if type or privilege checks fail and the segment is not present. So add some tests for far jmp instruction, and it will test those tests on hardware and emulator. Enable kvm.force_emulation_prefix when try to test them on emulator. Signed-off-by: Hou Wenlong --- x86/emulator.c | 71 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/x86/emulator.c b/x86/emulator.c index 45972c2fe940..7e98bacd714a 100644 --- a/x86/emulator.c +++ b/x86/emulator.c @@ -36,6 +36,7 @@ struct far_xfer_test_case { enum far_xfer_insn { FAR_XFER_RET, + FAR_XFER_JMP, }; struct far_xfer_test { @@ -64,6 +65,25 @@ static struct far_xfer_test far_ret_test = { .nr_testcases = sizeof(far_ret_testcases) / sizeof(struct far_xfer_test_case), }; +static struct far_xfer_test_case far_jmp_testcases[] = { + {0, DS_TYPE, 0, 0, false, GP_VECTOR, "desc.type!=code && desc.p=0"}, + {0, NON_CONFORM_CS_TYPE, 3, 0, false, GP_VECTOR, "non-conforming && dpl!=cpl && desc.p=0"}, + {3, NON_CONFORM_CS_TYPE, 0, 0, false, GP_VECTOR, "conforming && rpl>cpl && desc.p=0"}, + {0, CONFORM_CS_TYPE, 3, 0, false, GP_VECTOR, "conforming && dpl>cpl && desc.p=0"}, + {0, NON_CONFORM_CS_TYPE, 0, 0, false, NP_VECTOR, "desc.p=0"}, + {3, CONFORM_CS_TYPE, 0, 1, true, -1, "dpl