From patchwork Fri Sep 14 19:22:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jim Mattson X-Patchwork-Id: 10601161 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 082F2933 for ; Fri, 14 Sep 2018 19:23:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DACE3284AF for ; Fri, 14 Sep 2018 19:23:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CD5942855E; Fri, 14 Sep 2018 19:23:15 +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=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL 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 5E885284AF for ; Fri, 14 Sep 2018 19:23:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727847AbeIOAjE (ORCPT ); Fri, 14 Sep 2018 20:39:04 -0400 Received: from mail-it0-f73.google.com ([209.85.214.73]:33551 "EHLO mail-it0-f73.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726891AbeIOAjE (ORCPT ); Fri, 14 Sep 2018 20:39:04 -0400 Received: by mail-it0-f73.google.com with SMTP id o132-v6so4544072ite.0 for ; Fri, 14 Sep 2018 12:23:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=Fw/1InBSkzkZQSx30pI2+oOyB7PUZ/I7sMKqnENUQhc=; b=lawlRpedHChWW8LMWSRFsg1KjdfiQ016pNmnazc+ur6Tl8XN0DwV9laOJpvcb0Pu25 FB70UQkadmFl3G4JEnllHUdCzLJ/yrOFJ8JwsZU3HK0IhXKhl+zjd/fPtcn6HUf5yvel pMa72XvRhVnmpRBKvBdv5mF8yLTVCyO/3s19yD6hke0fTkQBvo4lEQJn8CxeWrKeIYC3 uaxDG/JkY9r+u79KVI30S8nNzw9IdnYYJbHadvr5LBp0BZyV6CA7CxQuIdShEirUTDdF F83vCbN6tnzwWoU8I1Pi4WM+54c4EPWy00wuaMe6sWHT3TeacuPAA3e34xAzI5MHqLLf RctQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=Fw/1InBSkzkZQSx30pI2+oOyB7PUZ/I7sMKqnENUQhc=; b=Dk27PZdCRka8NspZGYE2/D6lMPt7UTkPuwYifCnoJXWRB9+N41O2mW5UYW/H5voohG UVZkoI198vJFLszHKWAuYNGN2k7AyQu0udq2v3tV6KVsNiRBPiJ4LQ9wvgGv+QrdTsPU 3AHn/2OJm2ocwMhB+14keXBBGHtB4Rz15W+flCHCu/HOE5+fxXQX4hJ4vhYwQQIdj7YP kbzXVDQ+h1aLVvaW8N774JZ6HGhXArDJNveroQ8USttvQfSS8pS45DbGHMLoehTK0/X4 Mi2/uuInopzyXis0IyIZ4AefdCR7bWFkzE1BtiGEr9iW/YCze20Bf6ceuOrhuekfXVz8 pf9w== X-Gm-Message-State: APzg51DPRFzq2SetVM/abvCZN9p5eEhDpwmEIJy3Y3QYSl5BoV4cDa3l b1ae4DRP8TmTQk6mNWoso7oSeeIrseFskiyLSsOaenakDWNf3OdI3vGt+dConyM9ITx56GVXs4g kVugU+Si50n7yKvxAdM/3hdFcbsKqmrT7Du7hleWP7ILUeLs9vikodM6HHS0PaoY= X-Google-Smtp-Source: ANB0VdYI2Ov4w8FtRXgkFNgMjDwBDEU2XLXiHeR9E3IsYJFAPJXATB6LuYnY5kyPWJwHZQwODm2A+m4nSpRQUQ== X-Received: by 2002:a6b:8fc4:: with SMTP id r187-v6mr10524518iod.87.1536952992498; Fri, 14 Sep 2018 12:23:12 -0700 (PDT) Date: Fri, 14 Sep 2018 12:22:57 -0700 Message-Id: <20180914192257.259045-1-jmattson@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.19.0.397.gdd90340f6a-goog Subject: [kvm-unit-tests PATCH] x86: nvmx: Check #NM VM-exit reflection From: Jim Mattson To: kvm@vger.kernel.org Cc: Liran Alon , Abhiroop Dabral , Peter Shier , Jim Mattson Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When L1 intercepts #NM exceptions encountered in L2, the #NM exception should always be reflected from L0 to L1. Signed-off-by: Jim Mattson Reviewed-by: Peter Shier Reviewed-by: Liran Alon Reviewed-by: Krish Sadhukhan --- lib/x86/processor.h | 1 + x86/unittests.cfg | 6 +++++ x86/vmx_tests.c | 65 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/lib/x86/processor.h b/lib/x86/processor.h index b8e884f..15237a5 100644 --- a/lib/x86/processor.h +++ b/lib/x86/processor.h @@ -25,6 +25,7 @@ #define X86_CR0_PE 0x00000001 #define X86_CR0_MP 0x00000002 +#define X86_CR0_EM 0x00000004 #define X86_CR0_TS 0x00000008 #define X86_CR0_WP 0x00010000 #define X86_CR0_AM 0x00040000 diff --git a/x86/unittests.cfg b/x86/unittests.cfg index 9d39319..4a9702d 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -554,6 +554,12 @@ extra_params = -cpu host,+vmx -m 2560 -append vmx_cr_load_test arch = x86_64 groups = vmx +[vmx_nm_test] +file = vmx.flat +extra_params = -cpu host,+vmx -m 2560 -append vmx_nm_test +arch = x86_64 +groups = vmx + [vmx_eoi_bitmap_ioapic_scan] file = vmx.flat smp = 2 diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 0e9d900..5d4f39a 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -4585,6 +4585,70 @@ static void vmx_cr_load_test(void) TEST_ASSERT(!write_cr4_checking(cr4 & ~X86_CR4_PCIDE)); } +static void vmx_nm_test_guest(void) +{ + write_cr0(read_cr0() | X86_CR0_TS); + asm volatile("fnop"); +} + +static void check_nm_exit(const char *test) +{ + u32 reason = vmcs_read(EXI_REASON); + u32 intr_info = vmcs_read(EXI_INTR_INFO); + const u32 expected = INTR_INFO_VALID_MASK | INTR_TYPE_HARD_EXCEPTION | + NM_VECTOR; + + report("%s", reason == VMX_EXC_NMI && intr_info == expected, test); +} + +/* + * This test checks that: + * + * (a) If L2 launches with CR0.TS clear, but later sets CR0.TS, then + * a subsequent #NM VM-exit is reflected to L1. + * + * (b) If L2 launches with CR0.TS clear and CR0.EM set, then a + * subsequent #NM VM-exit is reflected to L1. + */ +static void vmx_nm_test(void) +{ + unsigned long cr0 = read_cr0(); + + test_set_guest(vmx_nm_test_guest); + + /* + * L1 wants to intercept #NM exceptions encountered in L2. + */ + vmcs_write(EXC_BITMAP, 1 << NM_VECTOR); + + /* + * Launch L2 with CR0.TS clear, but don't claim host ownership of + * any CR0 bits. L2 will set CR0.TS and then try to execute fnop, + * which will raise #NM. L0 should reflect the #NM VM-exit to L1. + */ + vmcs_write(CR0_MASK, 0); + vmcs_write(GUEST_CR0, cr0 & ~X86_CR0_TS); + enter_guest(); + check_nm_exit("fnop with CR0.TS set in L2 triggers #NM VM-exit to L1"); + + /* + * Re-enter L2 at the fnop instruction, with CR0.TS clear but + * CR0.EM set. The fnop will still raise #NM, and L0 should + * reflect the #NM VM-exit to L1. + */ + vmcs_write(GUEST_CR0, (cr0 & ~X86_CR0_TS) | X86_CR0_EM); + enter_guest(); + check_nm_exit("fnop with CR0.EM set in L2 triggers #NM VM-exit to L1"); + + /* + * Re-enter L2 at the fnop instruction, with both CR0.TS and + * CR0.EM clear. There will be no #NM, and the L2 guest should + * exit normally. + */ + vmcs_write(GUEST_CR0, cr0 & ~(X86_CR0_TS | X86_CR0_EM)); + enter_guest(); +} + static bool cpu_has_apicv(void) { return ((ctrl_cpu_rev[1].clr & CPU_APIC_REG_VIRT) && @@ -5144,6 +5208,7 @@ struct vmx_test vmx_tests[] = { TEST(vmx_vmcs_shadow_test), /* Regression tests */ TEST(vmx_cr_load_test), + TEST(vmx_nm_test), /* EPT access tests. */ TEST(ept_access_test_not_present), TEST(ept_access_test_read_only),