From patchwork Fri Feb 25 09:49:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hou Wenlong X-Patchwork-Id: 12759996 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 3832CC433F5 for ; Fri, 25 Feb 2022 09:49:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239245AbiBYJuV (ORCPT ); Fri, 25 Feb 2022 04:50:21 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40730 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239248AbiBYJuV (ORCPT ); Fri, 25 Feb 2022 04:50:21 -0500 Received: from out0-156.mail.aliyun.com (out0-156.mail.aliyun.com [140.205.0.156]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D78FB24FB80 for ; Fri, 25 Feb 2022 01:49:48 -0800 (PST) X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R121e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=ay29a033018047188;MF=houwenlong.hwl@antgroup.com;NM=1;PH=DS;RN=4;SR=0;TI=SMTPD_---.Mvtm13J_1645782586; Received: from localhost(mailfrom:houwenlong.hwl@antgroup.com fp:SMTPD_---.Mvtm13J_1645782586) by smtp.aliyun-inc.com(127.0.0.1); Fri, 25 Feb 2022 17:49:46 +0800 From: "Hou Wenlong" To: kvm@vger.kernel.org Cc: "Paolo Bonzini" , "Sean Christopherson" , "Hou Wenlong" Subject: [kvm-unit-tests PATCH v4 1/3] x86/emulator: Add some tests for far ret instruction emulation Date: Fri, 25 Feb 2022 17:49:25 +0800 Message-Id: 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 Reviewed-and-tested-by: Sean Christopherson --- x86/emulator.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/x86/emulator.c b/x86/emulator.c index cd78e3cbbcd7..c62dcedac991 100644 --- a/x86/emulator.c +++ b/x86/emulator.c @@ -21,6 +21,61 @@ 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 +1297,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 +1322,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 Fri Feb 25 09:49:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hou Wenlong X-Patchwork-Id: 12759997 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 4DD7FC433EF for ; Fri, 25 Feb 2022 09:49:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239251AbiBYJuX (ORCPT ); Fri, 25 Feb 2022 04:50:23 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40752 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236996AbiBYJuW (ORCPT ); Fri, 25 Feb 2022 04:50:22 -0500 Received: from out0-142.mail.aliyun.com (out0-142.mail.aliyun.com [140.205.0.142]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 812BD24FA2C for ; Fri, 25 Feb 2022 01:49:50 -0800 (PST) X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R331e4;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_---.Mvv.A6N_1645782587; Received: from localhost(mailfrom:houwenlong.hwl@antgroup.com fp:SMTPD_---.Mvv.A6N_1645782587) by smtp.aliyun-inc.com(127.0.0.1); Fri, 25 Feb 2022 17:49:48 +0800 From: "Hou Wenlong" To: kvm@vger.kernel.org Cc: "Paolo Bonzini" , "Sean Christopherson" , "Hou Wenlong" Subject: [kvm-unit-tests PATCH v4 2/3] x86/emulator: Rename test_ljmp() as test_far_jmp() Date: Fri, 25 Feb 2022 17:49:26 +0800 Message-Id: <6b975c25ce066a9c344b1fedca3bc4826b1878c3.1645672780.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 Reviewed-and-tested-by: Sean Christopherson --- x86/emulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x86/emulator.c b/x86/emulator.c index c62dcedac991..7925ad48c36d 100644 --- a/x86/emulator.c +++ b/x86/emulator.c @@ -359,7 +359,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; @@ -369,7 +369,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) @@ -1296,7 +1296,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 Fri Feb 25 09:49:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hou Wenlong X-Patchwork-Id: 12759998 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 2ABC4C433F5 for ; Fri, 25 Feb 2022 09:49:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239253AbiBYJuZ (ORCPT ); Fri, 25 Feb 2022 04:50:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40760 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239250AbiBYJuX (ORCPT ); Fri, 25 Feb 2022 04:50:23 -0500 Received: from out0-136.mail.aliyun.com (out0-136.mail.aliyun.com [140.205.0.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CD52A24FA10 for ; Fri, 25 Feb 2022 01:49:51 -0800 (PST) X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R331e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=ay29a033018047203;MF=houwenlong.hwl@antgroup.com;NM=1;PH=DS;RN=4;SR=0;TI=SMTPD_---.Mvuq7w7_1645782589; Received: from localhost(mailfrom:houwenlong.hwl@antgroup.com fp:SMTPD_---.Mvuq7w7_1645782589) by smtp.aliyun-inc.com(127.0.0.1); Fri, 25 Feb 2022 17:49:49 +0800 From: "Hou Wenlong" To: kvm@vger.kernel.org Cc: "Paolo Bonzini" , "Sean Christopherson" , "Hou Wenlong" Subject: [kvm-unit-tests PATCH v4 3/3] x86/emulator: Add some tests for far jmp instruction emulation Date: Fri, 25 Feb 2022 17:49:27 +0800 Message-Id: <62121e1866da786aac864b76091b8bfba21e0dcd.1645672780.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 Reviewed-and-tested-by: Sean Christopherson --- x86/emulator.c | 71 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/x86/emulator.c b/x86/emulator.c index 7925ad48c36d..76f3c3ce8eb4 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