From patchwork Thu Apr 18 21:39:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Krish Sadhukhan X-Patchwork-Id: 10908097 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 928F614DB for ; Thu, 18 Apr 2019 22:05:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7ABCD28A44 for ; Thu, 18 Apr 2019 22:05:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6C93728A5D; Thu, 18 Apr 2019 22:05:36 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY 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 E61F628A44 for ; Thu, 18 Apr 2019 22:05:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726069AbfDRWFe (ORCPT ); Thu, 18 Apr 2019 18:05:34 -0400 Received: from aserp2130.oracle.com ([141.146.126.79]:39758 "EHLO aserp2130.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725948AbfDRWFe (ORCPT ); Thu, 18 Apr 2019 18:05:34 -0400 Received: from pps.filterd (aserp2130.oracle.com [127.0.0.1]) by aserp2130.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x3ILswHJ076931; Thu, 18 Apr 2019 22:05:27 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references; s=corp-2018-07-02; bh=2mpKrZPYOzAAVJqMO+ZPNHhFM+bwKiZrqkvBjuL5Hkw=; b=PvfbjzODMeyy1ScknJbT9d0Av7FanL6P6SiLoYxDW3GKFVx+Vbu0YUfe/PyR06pWGzZ5 BdgXxEXrg7pNTJ2jGzvQln7AosUfwrJEIYQF1Cn+8BPc0KgJW3QO/dKoI8a959tUgLUA IYrEvwKW8Td03QSCNQD8B4OsuR1wULgeh+DuqEYwQMYru3EHaZhEWLaOck0Nfp14elxr QTnJc4OeNAOlPL0MQVaJZf50Y0i57OhUwHAISavZCT2Hq/C0m8lCvDCVczSZTxqdTUBI n6Vehg9T6w8iCBYJLa5fDUW8Co9QiMIsMH8mkssQ3eJyXEvAtUXoblJvEnlktob/KmSN 4w== Received: from aserp3020.oracle.com (aserp3020.oracle.com [141.146.126.70]) by aserp2130.oracle.com with ESMTP id 2ru59dkaqe-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 18 Apr 2019 22:05:27 +0000 Received: from pps.filterd (aserp3020.oracle.com [127.0.0.1]) by aserp3020.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x3IM4E9A095054; Thu, 18 Apr 2019 22:05:26 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserp3020.oracle.com with ESMTP id 2rv2tw7a71-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 18 Apr 2019 22:05:26 +0000 Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id x3IM5Q0S024823; Thu, 18 Apr 2019 22:05:26 GMT Received: from ban25x6uut29.us.oracle.com (/10.153.73.29) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 18 Apr 2019 15:05:26 -0700 From: Krish Sadhukhan To: kvm@vger.kernel.org Cc: rkrcmar@redhat.com, pbonzini@redhat.com, jmattson@google.com Subject: [PATCH 1/2][kvm-unit-test nVMX]: Move the functionality of enter_guest() to __enter_guest() and make the former a wrapper of the latter Date: Thu, 18 Apr 2019 17:39:40 -0400 Message-Id: <20190418213941.20977-2-krish.sadhukhan@oracle.com> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20190418213941.20977-1-krish.sadhukhan@oracle.com> References: <20190418213941.20977-1-krish.sadhukhan@oracle.com> X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=9231 signatures=668685 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=1 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1904180128 X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=9231 signatures=668685 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1904180128 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently enter_guest() aborts on any type of vmentry failures (early failures or invalid guest state). But the vmentry tests that want to validate the guest state need to continue running in spite of vmentry failures arising out of an invalid guest state. This patch moves the functionality of enter_guest() to __enter_guest() which accepts a parameter to conditionally abort the test as opposed to the behavior of enter_guest(). enter_guest() now calls __enter_guest() and preserves compatibility of existing callers which expect the test to be aborted on any type of vmentry failures. Signed-off-by: Krish Sadhukhan Suggested-by: Jim Mattson Reviewed-by: Karl Heubaum --- x86/vmx.c | 27 ++++++++++++++++++--------- x86/vmx.h | 4 ++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/x86/vmx.c b/x86/vmx.c index 6ba56bc..d29d21a 100644 --- a/x86/vmx.c +++ b/x86/vmx.c @@ -1583,10 +1583,10 @@ entry_failure_handler(struct vmentry_failure *failure) } /* - * Tries to enter the guest. Returns true iff entry succeeded. Otherwise, + * Tries to enter the guest. Returns true if entry succeeded. Otherwise, * populates @failure. */ -static bool vmx_enter_guest(struct vmentry_failure *failure) +static void vmx_enter_guest(struct vmentry_failure *failure) { failure->early = 0; @@ -1620,8 +1620,6 @@ static bool vmx_enter_guest(struct vmentry_failure *failure) failure->vmlaunch = !launched; failure->instr = launched ? "vmresume" : "vmlaunch"; - - return !failure->early && !(vmcs_read(EXI_REASON) & VMX_ENTRY_FAILURE); } static int vmx_run(void) @@ -1631,7 +1629,9 @@ static int vmx_run(void) bool entered; struct vmentry_failure failure; - entered = vmx_enter_guest(&failure); + vmx_enter_guest(&failure); + entered = !failure.early && + !(vmcs_read(EXI_REASON) & VMX_ENTRY_FAILURE); if (entered) { /* @@ -1765,10 +1765,9 @@ void test_set_guest(test_guest_func func) /* * Enters the guest (or launches it for the first time). Error to call once the - * guest has returned (i.e., run past the end of its guest() function). Also - * aborts if guest entry fails. + * guest has returned (i.e., run past the end of its guest() function). */ -void enter_guest(void) +void __enter_guest(u8 abort_flag) { struct vmentry_failure failure; @@ -1778,7 +1777,11 @@ void enter_guest(void) TEST_ASSERT_MSG(!guest_finished, "Called enter_guest() after guest returned."); - if (!vmx_enter_guest(&failure)) { + vmx_enter_guest(&failure); + if ((abort_flag & ABORT_ON_EARLY_VMENTRY_FAIL && failure.early) || + (abort_flag & ABORT_ON_INVALID_GUEST_STATE && + vmcs_read(EXI_REASON) & VMX_ENTRY_FAILURE)) { + print_vmentry_failure_info(&failure); abort(); } @@ -1807,6 +1810,12 @@ void enter_guest(void) } } +void enter_guest(void) +{ + __enter_guest(ABORT_ON_EARLY_VMENTRY_FAIL | + ABORT_ON_INVALID_GUEST_STATE); +} + extern struct vmx_test vmx_tests[]; static bool diff --git a/x86/vmx.h b/x86/vmx.h index 8a00f73..eefd5dc 100644 --- a/x86/vmx.h +++ b/x86/vmx.h @@ -645,6 +645,9 @@ enum vm_instruction_error_number { #define VMCS_FIELD_RESERVED_SHIFT (15) #define VMCS_FIELD_BIT_SIZE (BITS_PER_LONG) +#define ABORT_ON_EARLY_VMENTRY_FAIL 0x1 +#define ABORT_ON_INVALID_GUEST_STATE 0x2 + extern struct regs regs; extern union vmx_basic basic; @@ -830,6 +833,7 @@ bool ept_execute_only_supported(void); bool ept_ad_bits_supported(void); void enter_guest(void); +void __enter_guest(u8); typedef void (*test_guest_func)(void); typedef void (*test_teardown_func)(void *data); From patchwork Thu Apr 18 21:39:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Krish Sadhukhan X-Patchwork-Id: 10908099 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 000C91515 for ; Thu, 18 Apr 2019 22:05:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DE72728A45 for ; Thu, 18 Apr 2019 22:05:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D307728D84; Thu, 18 Apr 2019 22:05:46 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY 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 4383728A45 for ; Thu, 18 Apr 2019 22:05:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726260AbfDRWFp (ORCPT ); Thu, 18 Apr 2019 18:05:45 -0400 Received: from userp2130.oracle.com ([156.151.31.86]:42770 "EHLO userp2130.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725875AbfDRWFp (ORCPT ); Thu, 18 Apr 2019 18:05:45 -0400 Received: from pps.filterd (userp2130.oracle.com [127.0.0.1]) by userp2130.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x3ILswNQ069872; Thu, 18 Apr 2019 22:05:28 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references; s=corp-2018-07-02; bh=0h5TF87hazUE2JYeKkExM5pEv4Ic03pVXfJ6DikYKLU=; b=tI0x33SoXI3oyiXCfhFouHud1dhJGZiTVW+Sx3jQQrgP4rnmwLMJOMqGWUMciFXyScwy JasLpbuv42bCCQLzxVg4k9hAXOyk7MQAmqjLvDjiA0tfWZxkVD9QzQabVCUALK9S8uhl jDy8xDmkYU0IyXJBs6+B4I/A4FQHV+XA7wZzdT2PFDl+bPI6neOCGu/Fd8RAdJJKtnJ9 Jm09AyvzCBjCpM7OxUsNLPUDNbtMnr2KePF06Dr2lsal2fCx6a8G9rznHzcMRPqu9VNx jATUIRE7V/jHc8ZECMs2cikrhr0FC+c65EdexaPPb50d0Ehe4ozDx47HwaFVYenCYRr4 JQ== Received: from userp3020.oracle.com (userp3020.oracle.com [156.151.31.79]) by userp2130.oracle.com with ESMTP id 2rvwk43cm6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 18 Apr 2019 22:05:27 +0000 Received: from pps.filterd (userp3020.oracle.com [127.0.0.1]) by userp3020.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x3IM4VQY017324; Thu, 18 Apr 2019 22:05:27 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userp3020.oracle.com with ESMTP id 2rubq7sc8f-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 18 Apr 2019 22:05:27 +0000 Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0121.oracle.com (8.14.4/8.13.8) with ESMTP id x3IM5Qdj022898; Thu, 18 Apr 2019 22:05:26 GMT Received: from ban25x6uut29.us.oracle.com (/10.153.73.29) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 18 Apr 2019 15:05:26 -0700 From: Krish Sadhukhan To: kvm@vger.kernel.org Cc: rkrcmar@redhat.com, pbonzini@redhat.com, jmattson@google.com Subject: [PATCH 2/2][kvm-unit-test nVMX]: Check "load IA32_PAT" VM-entry control on vmentry of nested guests Date: Thu, 18 Apr 2019 17:39:41 -0400 Message-Id: <20190418213941.20977-3-krish.sadhukhan@oracle.com> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20190418213941.20977-1-krish.sadhukhan@oracle.com> References: <20190418213941.20977-1-krish.sadhukhan@oracle.com> X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=9231 signatures=668685 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=1 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1904180128 X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=9231 signatures=668685 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1904180128 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP ..to verify KVM performs the appropriate consistency checks for loading IA32_PAT as part of running a nested guest. According to section "Checking and Loading Guest State" in Intel SDM vol 3C, the following check is performed on vmentry: If the "load IA32_PAT" VM-entry control is 1, the value of the field for the IA32_PAT MSR must be one that could be written by WRMSR without fault at CPL 0. Specifically, each of the 8 bytes in the field must have one of the values 0 (UC), 1 (WC), 4 (WT), 5 (WP), 6 (WB), or 7 (UC-). Signed-off-by: Krish Sadhukhan Reviewed-by: Karl Heubaum --- x86/vmx_tests.c | 140 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 121 insertions(+), 19 deletions(-) diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 04b1aee..8186b4f 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -4995,10 +4995,37 @@ static void test_sysenter_field(u32 field, const char *name) vmcs_write(field, addr_saved); } +static void guest_pat_main(void) +{ + while (1) { + if (vmx_get_test_stage() != 2) + vmcall(); + else + break; + } + + asm volatile("fnop"); +} + +static void report_guest_pat_test(const char *test, u32 xreason, u64 guest_pat) +{ + u32 reason = vmcs_read(EXI_REASON); + u64 guest_rip; + u32 insn_len; + + report("%s, GUEST_PAT %lx", reason == xreason, test, guest_pat); + + guest_rip = vmcs_read(GUEST_RIP); + insn_len = vmcs_read(EXI_INST_LEN); + if (! (reason & 0x80000021)) + vmcs_write(GUEST_RIP, guest_rip + insn_len); +} + /* - * Since a PAT value higher than 8 will yield the same test result as that - * of 8, we want to confine our tests only up to 8 in order to reduce - * redundancy of tests and to avoid too many vmentries. + * PAT values higher than 8 are uninteresting since they're likely lumped + * in with "8". We only test values above 8 one bit at a time, + * in order to reduce the number of VM-Entries and keep the runtime + * reasonable. */ #define PAT_VAL_LIMIT 8 @@ -5010,34 +5037,77 @@ static void test_pat(u32 fld, const char * fld_name, u32 ctrl_fld, u64 ctrl_bit) u32 j; int error; - vmcs_write(ctrl_fld, ctrl_saved & ~ctrl_bit); - for (i = 0; i <= PAT_VAL_LIMIT; i++) { + vmcs_clear_bits(ctrl_fld, ctrl_bit); + if (fld == GUEST_PAT) { + vmx_set_test_stage(1); + test_set_guest(guest_pat_main); + } + + for (i = 0; i < 256; i = (i < PAT_VAL_LIMIT) ? i + 1 : i * 2) { /* Test PAT0..PAT7 fields */ - for (j = 0; j < 8; j++) { + for (j = 0; j < (i ? 8 : 1); j++) { val = i << j * 8; vmcs_write(fld, val); - report_prefix_pushf("%s %lx", fld_name, val); - test_vmx_vmlaunch(0, false); - report_prefix_pop(); + if (fld == HOST_PAT) { + report_prefix_pushf("%s %lx", fld_name, val); + test_vmx_vmlaunch(0, false); + report_prefix_pop(); + + } else { // GUEST_PAT + __enter_guest(ABORT_ON_EARLY_VMENTRY_FAIL); + report_guest_pat_test("ENT_LOAD_PAT enabled", + VMX_VMCALL, val); + } } } - vmcs_write(ctrl_fld, ctrl_saved | ctrl_bit); - for (i = 0; i <= PAT_VAL_LIMIT; i++) { + vmcs_set_bits(ctrl_fld, ctrl_bit); + for (i = 0; i < 256; i = (i < PAT_VAL_LIMIT) ? i + 1 : i * 2) { /* Test PAT0..PAT7 fields */ - for (j = 0; j < 8; j++) { + for (j = 0; j < (i ? 8 : 1); j++) { val = i << j * 8; vmcs_write(fld, val); - report_prefix_pushf("%s %lx", fld_name, val); - if (i == 0x2 || i == 0x3 || i >= 0x8) - error = VMXERR_ENTRY_INVALID_HOST_STATE_FIELD; - else - error = 0; - test_vmx_vmlaunch(error, false); - report_prefix_pop(); + + if (fld == HOST_PAT) { + report_prefix_pushf("%s %lx", fld_name, val); + if (i == 0x2 || i == 0x3 || i == 0x8) + error = + VMXERR_ENTRY_INVALID_HOST_STATE_FIELD; + else + error = 0; + + test_vmx_vmlaunch(error, false); + report_prefix_pop(); + + } else { // GUEST_PAT + if (i == 0x2 || i == 0x3 || i == 0x8) { + __enter_guest(ABORT_ON_EARLY_VMENTRY_FAIL); + report_guest_pat_test("ENT_LOAD_PAT " + "enabled", + VMX_FAIL_STATE | + VMX_ENTRY_FAILURE, + val); + } else { + __enter_guest(ABORT_ON_EARLY_VMENTRY_FAIL); + report_guest_pat_test("ENT_LOAD_PAT " + "enabled", + VMX_VMCALL, + val); + } + } + } } + if (fld == GUEST_PAT) { + /* + * Let the guest finish execution + */ + vmx_set_test_stage(2); + vmcs_write(fld, pat_saved); + __enter_guest(ABORT_ON_EARLY_VMENTRY_FAIL); + } + vmcs_write(ctrl_fld, ctrl_saved); vmcs_write(fld, pat_saved); } @@ -5083,6 +5153,37 @@ static void vmx_host_state_area_test(void) test_load_host_pat(); } +/* + * If the "load IA32_PAT" VM-entry control is 1, the value of the field + * for the IA32_PAT MSR must be one that could be written by WRMSR + * without fault at CPL 0. Specifically, each of the 8 bytes in the + * field must have one of the values 0 (UC), 1 (WC), 4 (WT), 5 (WP), + * 6 (WB), or 7 (UC-). + * + * [Intel SDM] + */ +static void test_load_guest_pat(void) +{ + /* + * "load IA32_PAT" VM-entry control + */ + if (!(ctrl_exit_rev.clr & ENT_LOAD_PAT)) { + printf("\"Load-IA32-PAT\" entry control not supported\n"); + return; + } + + test_pat(GUEST_PAT, "GUEST_PAT", ENT_CONTROLS, ENT_LOAD_PAT); +} + +/* + * Check that the virtual CPU checks the VMX Guest State Area as + * documented in the Intel SDM. + */ +static void vmx_guest_state_area_test(void) +{ + test_load_guest_pat(); +} + static bool valid_vmcs_for_vmentry(void) { struct vmcs *current_vmcs = NULL; @@ -6505,6 +6606,7 @@ struct vmx_test vmx_tests[] = { /* VM-entry tests */ TEST(vmx_controls_test), TEST(vmx_host_state_area_test), + TEST(vmx_guest_state_area_test), TEST(vmentry_movss_shadow_test), /* APICv tests */ TEST(vmx_eoi_bitmap_ioapic_scan_test),