From patchwork Thu Nov 30 00:37:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Krish Sadhukhan X-Patchwork-Id: 10083987 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 8FEA3602B9 for ; Thu, 30 Nov 2017 00:45:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8196D29D5F for ; Thu, 30 Nov 2017 00:45:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 75DDD29D87; Thu, 30 Nov 2017 00:45:50 +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, 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 5D5FC29D5F for ; Thu, 30 Nov 2017 00:45:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753868AbdK3Apq (ORCPT ); Wed, 29 Nov 2017 19:45:46 -0500 Received: from aserp1040.oracle.com ([141.146.126.69]:49499 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753865AbdK3Apo (ORCPT ); Wed, 29 Nov 2017 19:45:44 -0500 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id vAU0jduH032145 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 30 Nov 2017 00:45:40 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.14.4/8.14.4) with ESMTP id vAU0jdlN032222 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 30 Nov 2017 00:45:39 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id vAU0jdJZ012514; Thu, 30 Nov 2017 00:45:39 GMT Received: from ban25x6uut29.us.oracle.com (/10.153.73.29) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Wed, 29 Nov 2017 16:45:38 -0800 From: Krish Sadhukhan To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, rkrcmar@redhat.com, jmattson@google.com Subject: [PATCH] x86: Add test for TPR threshold and vTPR check on VM-entry Date: Wed, 29 Nov 2017 19:37:55 -0500 Message-Id: <20171130003755.25658-2-krish.sadhukhan@oracle.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20171130003755.25658-1-krish.sadhukhan@oracle.com> References: <20171130003755.25658-1-krish.sadhukhan@oracle.com> X-Source-IP: userv0021.oracle.com [156.151.31.71] Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This test checks that a nested VM-entry fails if the "use TPR shadow" VM-execution control is set, the "virtual-interrupt delivery" VM-execution control is clear, "virtualize APIC accesses" is clear and bits 3:0 of TPR threshold is greater than bits 7:4 of vTPR. Signed-off-by: Krish Sadhukhan Signed-off-by: Jim Mattson --- x86/vmx.h | 1 + x86/vmx_tests.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 106 insertions(+), 18 deletions(-) diff --git a/x86/vmx.h b/x86/vmx.h index f0b8776..bdcaac0 100644 --- a/x86/vmx.h +++ b/x86/vmx.h @@ -388,6 +388,7 @@ enum Ctrl0 { }; enum Ctrl1 { + CPU_VIRT_APIC_ACCESSES = 1ul << 0, CPU_EPT = 1ul << 1, CPU_DESC_TABLE = 1ul << 2, CPU_RDTSCP = 1ul << 3, diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index e8c97f2..6c10281 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -3476,18 +3476,58 @@ static void test_apic_virt_addr(void) "virtual-APIC address", "Use TPR shadow", true); } -static void try_tpr_threshold(unsigned val) +static void set_vtpr(unsigned vtpr) +{ + *(u32 *)phys_to_virt(vmcs_read(APIC_VIRT_ADDR) + APIC_TASKPRI) = vtpr; +} + +static void try_tpr_threshold_and_vtpr(unsigned threshold, unsigned vtpr) +{ + bool valid = true; + u32 primary = vmcs_read(CPU_EXEC_CTRL0); + u32 secondary = vmcs_read(CPU_EXEC_CTRL1); + + if ((primary & CPU_TPR_SHADOW) && + (!(primary & CPU_SECONDARY) || + !(secondary & (CPU_VINTD | CPU_VIRT_APIC_ACCESSES)))) + valid = (threshold & 0xf) <= ((vtpr >> 4) & 0xf); + + set_vtpr(vtpr); + report_prefix_pushf("TPR threshold 0x%x, VTPR.class 0x%x", + threshold, (vtpr >> 4) & 0xf); + test_vmx_controls(valid, false); + report_prefix_pop(); +} + +/* + * Test interesting vTPR values for a given TPR threshold. + */ +static void test_vtpr_values(unsigned threshold) +{ + try_tpr_threshold_and_vtpr(threshold, threshold - 1); + try_tpr_threshold_and_vtpr(threshold, threshold); + try_tpr_threshold_and_vtpr(threshold, threshold + 1); +} + +static void try_tpr_threshold(unsigned threshold) { bool valid = true; - if ((vmcs_read(CPU_EXEC_CTRL0) & CPU_TPR_SHADOW) && - !((vmcs_read(CPU_EXEC_CTRL0) & CPU_SECONDARY) && - (vmcs_read(CPU_EXEC_CTRL1) & CPU_VINTD))) - valid = !(val >> 4); - report_prefix_pushf("TPR threshold 0x%x", val); - vmcs_write(TPR_THRESHOLD, val); + u32 primary = vmcs_read(CPU_EXEC_CTRL0); + u32 secondary = vmcs_read(CPU_EXEC_CTRL1); + + if ((primary & CPU_TPR_SHADOW) && !((primary & CPU_SECONDARY) && + (secondary & CPU_VINTD))) + valid = !(threshold >> 4); + + set_vtpr(-1); + vmcs_write(TPR_THRESHOLD, threshold); + report_prefix_pushf("TPR threshold 0x%x, VTPR.class 0xf", threshold); test_vmx_controls(valid, false); report_prefix_pop(); + + if (valid) + test_vtpr_values(threshold); } /* @@ -3506,10 +3546,21 @@ static void test_tpr_threshold_values(void) } /* - * If the "use TPR shadow" VM-execution control is 1 and the - * "virtual-interrupt delivery" VM-execution control is 0, bits 31:4 - * of the TPR threshold VM-execution control field must be 0. - * [Intel SDM] + * This test covers the following two VM entry checks: + * + * i) If the "use TPR shadow" VM-execution control is 1 and the + * "virtual-interrupt delivery" VM-execution control is 0, bits + * 31:4 of the TPR threshold VM-execution control field must + be 0. + * [Intel SDM] + * + * ii) If the "use TPR shadow" VM-execution control is 1, the + * "virtual-interrupt delivery" VM-execution control is 0 + * and the "virtualize APIC accesses" VM-execution control + * is 0, the value of bits 3:0 of the TPR threshold VM-execution + * control field must not be greater than the value of bits + * 7:4 of VTPR. + * [Intel SDM] */ static void test_tpr_threshold(void) { @@ -3524,7 +3575,7 @@ static void test_tpr_threshold(void) vmcs_write(APIC_VIRT_ADDR, virt_to_phys(virtual_apic_page)); vmcs_write(CPU_EXEC_CTRL0, primary & ~(CPU_TPR_SHADOW | CPU_SECONDARY)); - report_prefix_pushf("Use TPR shadow disabled"); + report_prefix_pushf("Use TPR shadow disabled, secondary controls disabled"); test_tpr_threshold_values(); report_prefix_pop(); vmcs_write(CPU_EXEC_CTRL0, vmcs_read(CPU_EXEC_CTRL0) | CPU_TPR_SHADOW); @@ -3532,23 +3583,59 @@ static void test_tpr_threshold(void) test_tpr_threshold_values(); report_prefix_pop(); - if ((ctrl_cpu_rev[0].clr & CPU_SECONDARY) && - (ctrl_cpu_rev[1].clr & CPU_VINTD)) { - u32 secondary = vmcs_read(CPU_EXEC_CTRL1); + if (!((ctrl_cpu_rev[0].clr & CPU_SECONDARY) && + (ctrl_cpu_rev[1].clr & (CPU_VINTD | CPU_VIRT_APIC_ACCESSES)))) + return; + + u32 secondary = vmcs_read(CPU_EXEC_CTRL1); + if (ctrl_cpu_rev[1].clr & CPU_VINTD) { vmcs_write(CPU_EXEC_CTRL1, CPU_VINTD); - report_prefix_pushf("Use TPR shadow enabled; secondary controls disabled"); + report_prefix_pushf("Use TPR shadow enabled; secondary controls disabled; virtual-interrupt delivery enabled; virtualize APIC accesses disabled"); test_tpr_threshold_values(); report_prefix_pop(); + vmcs_write(CPU_EXEC_CTRL0, vmcs_read(CPU_EXEC_CTRL0) | CPU_SECONDARY); - report_prefix_pushf("Use TPR shadow enabled; virtual-interrupt delivery enabled"); + report_prefix_pushf("Use TPR shadow enabled; secondary controls enabled; virtual-interrupt delivery enabled; virtualize APIC accesses disabled"); + test_tpr_threshold_values(); + report_prefix_pop(); + } + + if (ctrl_cpu_rev[1].clr & CPU_VIRT_APIC_ACCESSES) { + vmcs_write(CPU_EXEC_CTRL0, + vmcs_read(CPU_EXEC_CTRL0) & ~CPU_SECONDARY); + vmcs_write(CPU_EXEC_CTRL1, CPU_VIRT_APIC_ACCESSES); + report_prefix_pushf("Use TPR shadow enabled; secondary controls disabled; virtual-interrupt delivery enabled; virtualize APIC accesses enabled"); test_tpr_threshold_values(); report_prefix_pop(); - vmcs_write(CPU_EXEC_CTRL1, secondary); + vmcs_write(CPU_EXEC_CTRL0, + vmcs_read(CPU_EXEC_CTRL0) | CPU_SECONDARY); + report_prefix_pushf("Use TPR shadow enabled; secondary controls enabled; virtual-interrupt delivery enabled; virtualize APIC accesses enabled"); + test_tpr_threshold_values(); + report_prefix_pop(); } + if ((ctrl_cpu_rev[1].clr & + (CPU_VINTD | CPU_VIRT_APIC_ACCESSES)) == + (CPU_VINTD | CPU_VIRT_APIC_ACCESSES)) { + vmcs_write(CPU_EXEC_CTRL0, + vmcs_read(CPU_EXEC_CTRL0) & ~CPU_SECONDARY); + vmcs_write(CPU_EXEC_CTRL1, + CPU_VINTD | CPU_VIRT_APIC_ACCESSES); + report_prefix_pushf("Use TPR shadow enabled; secondary controls disabled; virtual-interrupt delivery enabled; virtualize APIC accesses enabled"); + test_tpr_threshold_values(); + report_prefix_pop(); + + vmcs_write(CPU_EXEC_CTRL0, + vmcs_read(CPU_EXEC_CTRL0) | CPU_SECONDARY); + report_prefix_pushf("Use TPR shadow enabled; secondary controls enabled; virtual-interrupt delivery enabled; virtualize APIC accesses enabled"); + test_tpr_threshold_values(); + report_prefix_pop(); + } + + vmcs_write(CPU_EXEC_CTRL1, secondary); vmcs_write(CPU_EXEC_CTRL0, primary); }