From patchwork Wed Mar 21 23:23:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liran Alon X-Patchwork-Id: 10300649 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 427C260349 for ; Wed, 21 Mar 2018 23:24:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 33CF929908 for ; Wed, 21 Mar 2018 23:24:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 26C4829917; Wed, 21 Mar 2018 23:24:20 +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=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, 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 9DD2C29908 for ; Wed, 21 Mar 2018 23:24:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754221AbeCUXYR (ORCPT ); Wed, 21 Mar 2018 19:24:17 -0400 Received: from userp2130.oracle.com ([156.151.31.86]:49198 "EHLO userp2130.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754100AbeCUXYO (ORCPT ); Wed, 21 Mar 2018 19:24:14 -0400 Received: from pps.filterd (userp2130.oracle.com [127.0.0.1]) by userp2130.oracle.com (8.16.0.22/8.16.0.22) with SMTP id w2LND3un047678; Wed, 21 Mar 2018 23:24:12 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-2017-10-26; bh=mnyZodclA5Pz98ygywAKs08vbVmVKX2S8Dwb9XGw4W0=; b=tD/WBlgnoSta1xfG1U8YfT1w6unq/ie/2DLV8e8FIB5AFAZHyaD7iQaZMYnCPb3wqUQr 9RKippyq4O1dON5pJ7q1zS1JJuYTu9Au18Y9aHgtTnJ9GuqvxPVqTteOcRfNmkSy1Zai 0Zie8oj5bKm+9Di2Gi+NbjSs8KpJxCAVcHn7n1/k/6bTVGsUD3EaQOx2Vwqd0dc2qFyO FlkYRDnaPW6/jyJdLCEA43JKZ7hMotBDuB+lZpFQ1yF/VcOfzwx2ZHbKUg8cjjxHFlf6 T87erEvH5ewHfREkboULn5+hpc6tzpJa17b4XQpDcRB3kt0uuyolbgG0RjUaL1i9btEU fA== Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp2130.oracle.com with ESMTP id 2gv0vdr0v9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 21 Mar 2018 23:24:12 +0000 Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.14.4/8.14.4) with ESMTP id w2LNO763005139 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 21 Mar 2018 23:24:07 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id w2LNO67J012353; Wed, 21 Mar 2018 23:24:07 GMT Received: from liran-pc.Home (/109.66.44.151) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Wed, 21 Mar 2018 16:24:06 -0700 From: Liran Alon To: pbonzini@redhat.com, rkrcmar@redhat.com, kvm@vger.kernel.org Cc: idan.brown@oracle.com, Arbel Moshe , Liran Alon , Krish Sadhukhan Subject: [PATCH 5/7] x86: nVMX: Verify vmcs12 EOI-exit-bitmap not corrupted on L1 IOAPIC scan Date: Thu, 22 Mar 2018 01:23:12 +0200 Message-Id: <1521674594-12085-6-git-send-email-liran.alon@oracle.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1521674594-12085-1-git-send-email-liran.alon@oracle.com> References: <1521674594-12085-1-git-send-email-liran.alon@oracle.com> X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=8839 signatures=668695 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=0 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-1711220000 definitions=main-1803200127 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Arbel Moshe This test aims to verify that L1 IOAPIC scan requests don't corrupt vmcs02->eoi_exit_bitmap which should always be equal to vmcs12->eoi_exit_bitmap. Test configures CPU0 to run L2 with virtual-interrupt-delivery and empty EOI-exit-bitmap. Therefore, expecting no vmexit on EOI_INDUCED when L2 performs EOI. Before L2 performs EOI, test makes CPU1 modify IOAPIC redirection table which will trigger an IOAPIC scan on all vCPUs. Then, L2 performs EOI followed by a VMCALL. Test fails if L1 got a vmexit other than VMCALL. The issue tested in this patch was fixed in KVM commit ("KVM: nVMX: Do not load EOI-exitmap while running L2"). For more details, refer to that commit message. Signed-off-by: Arbel Moshe Suggested-by: Liran Alon Signed-off-by: Liran Alon Signed-off-by: Krish Sadhukhan --- x86/unittests.cfg | 7 ++++ x86/vmx.c | 2 +- x86/vmx_tests.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 1 deletion(-) diff --git a/x86/unittests.cfg b/x86/unittests.cfg index 22c62d5d373d..639e487cd777 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -544,6 +544,13 @@ extra_params = -cpu host,+vmx -m 2560 -append vmx_cr_load_test arch = x86_64 groups = vmx +[vmx_eoi_bitmap_ioapic_scan] +file = vmx.flat +smp = 2 +extra_params = -cpu host,+vmx -m 2048 -append vmx_eoi_bitmap_ioapic_scan_test +arch = x86_64 +groups = vmx + [debug] file = debug.flat arch = x86_64 diff --git a/x86/vmx.c b/x86/vmx.c index 75ee8e75ad0a..aa04ac68dab5 100644 --- a/x86/vmx.c +++ b/x86/vmx.c @@ -1816,7 +1816,7 @@ int main(int argc, const char *argv[]) int i = 0; setup_vm(); - setup_idt(); + smp_init(); hypercall_field = 0; argv++; diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 613a8bd18c27..0bf081846533 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -14,6 +14,8 @@ #include "types.h" #include "vmalloc.h" #include "alloc_page.h" +#include "smp.h" +#include "delay.h" #define NONCANONICAL 0xaaaaaaaaaaaaaaaaull @@ -3916,6 +3918,106 @@ static void vmx_cr_load_test(void) TEST_ASSERT(!write_cr4_checking(cr4 & ~X86_CR4_PCIDE)); } +static bool cpu_has_apicv(void) +{ + return ((ctrl_cpu_rev[1].clr & CPU_APIC_REG_VIRT) && + (ctrl_cpu_rev[1].clr & CPU_VINTD) && + (ctrl_pin_rev.clr & PIN_POST_INTR)); +} + +static void trigger_ioapic_scan_thread(void *data) +{ + /* Wait until other CPU entered L2 */ + while (vmx_get_test_stage() != 1) + ; + + /* Trigger ioapic scan */ + ioapic_set_redir(0xf, 0x79, TRIGGER_LEVEL); + vmx_set_test_stage(2); +} + +static void irq_79_handler_guest(isr_regs_t *regs) +{ + eoi(); + + /* L1 expects vmexit on VMX_VMCALL and not VMX_EOI_INDUCED */ + vmcall(); +} + +/* + * Constant for num of busy-loop iterations after which + * a timer interrupt should have happened in host + */ +#define TIMER_INTERRUPT_DELAY 100000000 + +static void vmx_eoi_bitmap_ioapic_scan_test_guest(void) +{ + handle_irq(0x79, irq_79_handler_guest); + irq_enable(); + + /* Signal to L1 CPU to trigger ioapic scan */ + vmx_set_test_stage(1); + /* Wait until L1 CPU to trigger ioapic scan */ + while (vmx_get_test_stage() != 2) + ; + + /* + * Wait for L0 timer interrupt to be raised while we run in L2 + * such that L0 will process the IOAPIC scan request before + * resuming L2 + */ + delay(TIMER_INTERRUPT_DELAY); + + asm volatile ("int $0x79"); +} + +static void vmx_eoi_bitmap_ioapic_scan_test(void) +{ + void *msr_bitmap; + void *virtual_apic_page; + + if (!cpu_has_apicv() || (cpu_count() < 2)) { + report_skip(__func__); + return; + } + + msr_bitmap = alloc_page(); + virtual_apic_page = alloc_page(); + + u64 cpu_ctrl_0 = CPU_SECONDARY | CPU_TPR_SHADOW | CPU_MSR_BITMAP; + u64 cpu_ctrl_1 = CPU_VINTD | CPU_VIRT_X2APIC; + + memset(msr_bitmap, 0x0, PAGE_SIZE); + vmcs_write(MSR_BITMAP, (u64)msr_bitmap); + + vmcs_write(APIC_VIRT_ADDR, (u64)virtual_apic_page); + vmcs_write(PIN_CONTROLS, vmcs_read(PIN_CONTROLS) | PIN_EXTINT); + + vmcs_write(EOI_EXIT_BITMAP0, 0x0); + vmcs_write(EOI_EXIT_BITMAP1, 0x0); + vmcs_write(EOI_EXIT_BITMAP2, 0x0); + vmcs_write(EOI_EXIT_BITMAP3, 0x0); + + vmcs_write(CPU_EXEC_CTRL0, vmcs_read(CPU_EXEC_CTRL0) | cpu_ctrl_0); + vmcs_write(CPU_EXEC_CTRL1, vmcs_read(CPU_EXEC_CTRL1) | cpu_ctrl_1); + + on_cpu_async(1, trigger_ioapic_scan_thread, NULL); + test_set_guest(vmx_eoi_bitmap_ioapic_scan_test_guest); + + /* + * Launch L2. + * We expect the exit reason to be VMX_VMCALL (and not EOI INDUCED). + * In case the reason isn't VMX_VMCALL, the asserion inside + * skip_exit_vmcall() will fail. + */ + enter_guest(); + skip_exit_vmcall(); + + /* Let L2 finish */ + enter_guest(); + report(__func__, 1); +} + #define TEST(name) { #name, .v2 = name } /* name/init/guest_main/exit_handler/syscall_handler/guest_regs */ @@ -3982,6 +4084,8 @@ struct vmx_test vmx_tests[] = { /* VM-entry tests */ TEST(vmx_controls_test), TEST(vmentry_movss_shadow_test), + /* APICv tests */ + TEST(vmx_eoi_bitmap_ioapic_scan_test), /* Regression tests */ TEST(vmx_cr_load_test), { NULL, NULL, NULL, NULL, NULL, {0} },