From patchwork Sat Oct 1 01:12:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12996242 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 E45F0C433F5 for ; Sat, 1 Oct 2022 01:14:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231484AbiJABOL (ORCPT ); Fri, 30 Sep 2022 21:14:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54156 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233013AbiJABNs (ORCPT ); Fri, 30 Sep 2022 21:13:48 -0400 Received: from mail-pf1-x449.google.com (mail-pf1-x449.google.com [IPv6:2607:f8b0:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 645C013DFF for ; Fri, 30 Sep 2022 18:13:05 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id be18-20020a056a001f1200b00543d4bac885so3625682pfb.13 for ; Fri, 30 Sep 2022 18:13:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date; bh=OLIOJuJhX0MzUSXrz6+yz/u+BTyao2rAE5Ph28PVgzU=; b=RRT3wXunCmMOHs878JIwHINoMuAgmTvPqLwyrteVhTuaO9w+5k/gG3esUjzLAhfVmj Mj4SKJdV1FAEbhPrEqMeE4nLc45YR0xupc7/Upe3i7UabZD57Wx6Vn1YZFJKJH7DsF4d fSWkzM9C4sRODw6H6IO9ZGcC7RHtVL2AWQCUu8OcXReKuf0rszupty+rspyzoV1or4Mt StG+6wU9djjnI33ckbYr6PKIEktaSM/I2yqUNzkdPXVFbUwZ+RXGserragoGRyywdIh8 hKQd5wa2TK1ttcnhihz+FyGzrEJ5JFFxjk7S0T8retkIKHYBB3PcVjjNPG3xuj+f/0BZ U3fA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date; bh=OLIOJuJhX0MzUSXrz6+yz/u+BTyao2rAE5Ph28PVgzU=; b=iNVbOsI7N2quY66DhIIg3RP9asWUyDkPxcamKIWHPdFHYF7P4zRa1DVmPipuBKmqGo JWzX10EfDIztPsMYlET8EMBgmP607H2FfOKYW5w1SPnjLUKrSnAuwbCHzWS7s1O/+I6s WL6ERytunHPHzXbCuV0n5SppcKzfEsW2qY03lU6gYztdWhRBB6DpOcAS44Urflx3bWrC osYA/S1SSFRNXylh9XZA0MZx7V1iFUOV7AXkKR3d/gug1zv7yCCJfkiz2tPGBAxsBsQC BSpQWcwZPCU+UxVdEe2Z+A4DODUVe3GoP3A0t8Y6u/rOC9hPt5latn4DUC30oyB+0el7 JtFA== X-Gm-Message-State: ACrzQf3m8QJTkdU0HaCaA5cSPKyw99YGkrzgVCZdYvhy/9yqyRN7vqqD CBstg2XO/yOpkpsCTdvHLr4DIslladE= X-Google-Smtp-Source: AMsMyM4rr1e+QRsghPrQo4YbOJbQ1hohkLVZ43J91qqYR//0arzF8wQuCRxNnHhOCkJD9BzZmy1k3bpO2Bc= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a17:90b:3ec9:b0:203:246e:4370 with SMTP id rm9-20020a17090b3ec900b00203246e4370mr1000329pjb.221.1664586785010; Fri, 30 Sep 2022 18:13:05 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 1 Oct 2022 01:12:53 +0000 In-Reply-To: <20221001011301.2077437-1-seanjc@google.com> Mime-Version: 1.0 References: <20221001011301.2077437-1-seanjc@google.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog Message-ID: <20221001011301.2077437-2-seanjc@google.com> Subject: [kvm-unit-tests PATCH 1/9] x86/apic: Add test config to allow running apic tests against SVM's AVIC From: Sean Christopherson To: Paolo Bonzini Cc: kvm@vger.kernel.org, Maxim Levitsky , Sean Christopherson Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add a curated "xapic" test configuration that hides x2APIC from the guest and does not expose a PIT/8254 timer to the guest so that KVM won't disable AVIC due to incompatibilities. Set the timeout to '60' as the test is painfully slow when AVIC is enabled. Cc: Maxim Levitsky Signed-off-by: Sean Christopherson --- x86/unittests.cfg | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/x86/unittests.cfg b/x86/unittests.cfg index ed65185..7600935 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -30,18 +30,31 @@ file = apic.flat smp = 2 extra_params = -cpu qemu64,+x2apic,+tsc-deadline -machine kernel_irqchip=split arch = x86_64 +groups = apic [ioapic-split] file = ioapic.flat extra_params = -cpu qemu64 -machine kernel_irqchip=split arch = x86_64 +groups = apic -[apic] +[x2apic] file = apic.flat smp = 2 extra_params = -cpu qemu64,+x2apic,+tsc-deadline arch = x86_64 timeout = 30 +groups = apic + +# Hide x2APIC and don't create a Programmable Interval Timer (PIT, a.k.a 8254) +# to allow testing SVM's AVIC, which is disabled if either is exposed to the guest. +[xapic] +file = apic.flat +smp = 2 +extra_params = -cpu qemu64,-x2apic,+tsc-deadline -machine pit=off +arch = x86_64 +timeout = 60 +groups = apic [ioapic] file = ioapic.flat From patchwork Sat Oct 1 01:12:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12996244 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 0D9F9C4332F for ; Sat, 1 Oct 2022 01:14:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231516AbiJABON (ORCPT ); Fri, 30 Sep 2022 21:14:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56872 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231968AbiJABNt (ORCPT ); Fri, 30 Sep 2022 21:13:49 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EC6191D649 for ; Fri, 30 Sep 2022 18:13:06 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id n9-20020a170902d2c900b001782ad97c7aso4231903plc.8 for ; Fri, 30 Sep 2022 18:13:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date; bh=L7bh3Ac0kjb6/oF6iY0CRuTKzYWvq2kqC1Vz5yM6wMI=; b=lBiP/b6t5qfAITn6VtqHDJ3w/Y7jGtIo/HBqtZXwA2lQ9O3NlXAfr16j1aVCy5IZlx uih6WzlS3m4pAbGdHbfS13XRiV6xo3TspOJulEQCQERqbXRWAbhvgiVZiKoLc3C7ay56 gTni6cwU6WPSkALsIihc9wDiV1vyqIkAWhudD6DeozMMKXvsUYOEQLb5oUrtgRNRhpzY iaY+ny+llxuFDNzTm7eqV47TvnAlvIGDxtw8jthb6XVNf8Dwp+VI8ubTVMFOuf/4AFbF DUHuuKE9onXhQCbIUB+Jp0CBLX5Y0+5+Rpt9FgF1Mep5zkBkPbgq57S8BqQipeQ0Pi6z Menw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date; bh=L7bh3Ac0kjb6/oF6iY0CRuTKzYWvq2kqC1Vz5yM6wMI=; b=cGs41ygN7j/4xgTcYMKWvuXvvYFRvcdZqjXY5RRS1C/XRqCJKj3MdVyTIEFdXjvCeL N0VhCkzZJO8+D9z6JTmTlftwWpW8Fr/2Lfn76w/Z/PNQx99iAEreAhWzNjg+szwZS1xW bCbAVehKkALBnfPLlSd/7hdicaEeHsngfqI7xW7jdl2W6NvdSUPQ+CxBD1/iMt622q+h HKXRcBKWmgCFjAxRHaf4I9Er1xycfBBzFFaw+Tj7yuCOIjqtfqwN7jWFRBkmbNMWyXxX faxA/JpA7X2oWDHWumaCI9uJKXLGF839FWQ2SVp87eqrCRM5Gi5x8OEpg6sFoU+jDnIM Y9KQ== X-Gm-Message-State: ACrzQf0pU8YUcPky39luM7DmJU8Um6bKR/MSiAthn4DN7oE54TmdtnZe 9IOLWwKVQVN8AtLP+Jl+Mmr4MHO72W4= X-Google-Smtp-Source: AMsMyM6BOjaeOfHKKOjYsdQzcqdZBRkdq0D2qllSfkr4La0x5rl5OjwhuSa9CqEv4cZc/gq0dRtUENlyobw= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a63:d145:0:b0:443:c25f:5dd5 with SMTP id c5-20020a63d145000000b00443c25f5dd5mr2239041pgj.554.1664586786518; Fri, 30 Sep 2022 18:13:06 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 1 Oct 2022 01:12:54 +0000 In-Reply-To: <20221001011301.2077437-1-seanjc@google.com> Mime-Version: 1.0 References: <20221001011301.2077437-1-seanjc@google.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog Message-ID: <20221001011301.2077437-3-seanjc@google.com> Subject: [kvm-unit-tests PATCH 2/9] x86/apic: Replaces spaces with tabs to fix indentation in apic.c From: Sean Christopherson To: Paolo Bonzini Cc: kvm@vger.kernel.org, Maxim Levitsky , Sean Christopherson Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Fix spaces vs. tabs indentation in apic.c to make enhancing the test slightly less painful. No functional change intended. Signed-off-by: Sean Christopherson --- x86/apic.c | 661 ++++++++++++++++++++++++++--------------------------- 1 file changed, 327 insertions(+), 334 deletions(-) diff --git a/x86/apic.c b/x86/apic.c index 23508ad..f038198 100644 --- a/x86/apic.c +++ b/x86/apic.c @@ -12,11 +12,11 @@ static void test_lapic_existence(void) { - u8 version; + u8 version; - version = (u8)apic_read(APIC_LVR); - printf("apic version: %x\n", version); - report(version >= 0x10 && version <= 0x15, "apic existence"); + version = (u8)apic_read(APIC_LVR); + printf("apic version: %x\n", version); + report(version >= 0x10 && version <= 0x15, "apic existence"); } #define TSC_DEADLINE_TIMER_VECTOR 0xef @@ -26,313 +26,311 @@ static int tdt_count; static void tsc_deadline_timer_isr(isr_regs_t *regs) { - ++tdt_count; - eoi(); + ++tdt_count; + eoi(); } static void __test_tsc_deadline_timer(void) { - handle_irq(TSC_DEADLINE_TIMER_VECTOR, tsc_deadline_timer_isr); - irq_enable(); + handle_irq(TSC_DEADLINE_TIMER_VECTOR, tsc_deadline_timer_isr); + irq_enable(); - wrmsr(MSR_IA32_TSCDEADLINE, rdmsr(MSR_IA32_TSC)); - asm volatile ("nop"); - report(tdt_count == 1, "tsc deadline timer"); - report(rdmsr(MSR_IA32_TSCDEADLINE) == 0, "tsc deadline timer clearing"); + wrmsr(MSR_IA32_TSCDEADLINE, rdmsr(MSR_IA32_TSC)); + asm volatile ("nop"); + report(tdt_count == 1, "tsc deadline timer"); + report(rdmsr(MSR_IA32_TSCDEADLINE) == 0, "tsc deadline timer clearing"); } static int enable_tsc_deadline_timer(void) { - uint32_t lvtt; + uint32_t lvtt; - if (this_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) { - lvtt = APIC_LVT_TIMER_TSCDEADLINE | TSC_DEADLINE_TIMER_VECTOR; - apic_write(APIC_LVTT, lvtt); - return 1; - } else { - return 0; - } + if (this_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) { + lvtt = APIC_LVT_TIMER_TSCDEADLINE | TSC_DEADLINE_TIMER_VECTOR; + apic_write(APIC_LVTT, lvtt); + return 1; + } else { + return 0; + } } static void test_tsc_deadline_timer(void) { - if(enable_tsc_deadline_timer()) { - __test_tsc_deadline_timer(); - } else { - report_skip("tsc deadline timer not detected"); - } + if(enable_tsc_deadline_timer()) + __test_tsc_deadline_timer(); + else + report_skip("tsc deadline timer not detected"); } static void do_write_apicbase(void *data) { - wrmsr(MSR_IA32_APICBASE, *(u64 *)data); + wrmsr(MSR_IA32_APICBASE, *(u64 *)data); } static bool test_write_apicbase_exception(u64 data) { - return test_for_exception(GP_VECTOR, do_write_apicbase, &data); + return test_for_exception(GP_VECTOR, do_write_apicbase, &data); } static void test_enable_x2apic(void) { - u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE); - u64 apicbase; + u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE); + u64 apicbase; - if (enable_x2apic()) { - printf("x2apic enabled\n"); + if (enable_x2apic()) { + printf("x2apic enabled\n"); - apicbase = orig_apicbase & ~(APIC_EN | APIC_EXTD); - report(test_write_apicbase_exception(apicbase | APIC_EXTD), - "x2apic enabled to invalid state"); - report(test_write_apicbase_exception(apicbase | APIC_EN), - "x2apic enabled to apic enabled"); + apicbase = orig_apicbase & ~(APIC_EN | APIC_EXTD); + report(test_write_apicbase_exception(apicbase | APIC_EXTD), + "x2apic enabled to invalid state"); + report(test_write_apicbase_exception(apicbase | APIC_EN), + "x2apic enabled to apic enabled"); - report(!test_write_apicbase_exception(apicbase | 0), - "x2apic enabled to disabled state"); - report(test_write_apicbase_exception(apicbase | APIC_EXTD), - "disabled to invalid state"); - report(test_write_apicbase_exception(apicbase | APIC_EN | APIC_EXTD), - "disabled to x2apic enabled"); + report(!test_write_apicbase_exception(apicbase | 0), + "x2apic enabled to disabled state"); + report(test_write_apicbase_exception(apicbase | APIC_EXTD), + "disabled to invalid state"); + report(test_write_apicbase_exception(apicbase | APIC_EN | APIC_EXTD), + "disabled to x2apic enabled"); - report(!test_write_apicbase_exception(apicbase | APIC_EN), - "apic disabled to apic enabled"); - report(test_write_apicbase_exception(apicbase | APIC_EXTD), - "apic enabled to invalid state"); + report(!test_write_apicbase_exception(apicbase | APIC_EN), + "apic disabled to apic enabled"); + report(test_write_apicbase_exception(apicbase | APIC_EXTD), + "apic enabled to invalid state"); - if (orig_apicbase & APIC_EXTD) - enable_x2apic(); - else - reset_apic(); + if (orig_apicbase & APIC_EXTD) + enable_x2apic(); + else + reset_apic(); - /* - * Disabling the APIC resets various APIC registers, restore them to - * their desired values. - */ - apic_write(APIC_SPIV, 0x1ff); - } else { - printf("x2apic not detected\n"); + /* + * Disabling the APIC resets various APIC registers, restore + * them to their desired values. + */ + apic_write(APIC_SPIV, 0x1ff); + } else { + printf("x2apic not detected\n"); - report(test_write_apicbase_exception(APIC_EN | APIC_EXTD), - "enable unsupported x2apic"); - } + report(test_write_apicbase_exception(APIC_EN | APIC_EXTD), + "enable unsupported x2apic"); + } } static void verify_disabled_apic_mmio(void) { - volatile u32 *lvr = (volatile u32 *)(APIC_DEFAULT_PHYS_BASE + APIC_LVR); - volatile u32 *tpr = (volatile u32 *)(APIC_DEFAULT_PHYS_BASE + APIC_TASKPRI); - u32 cr8 = read_cr8(); + volatile u32 *lvr = (volatile u32 *)(APIC_DEFAULT_PHYS_BASE + APIC_LVR); + volatile u32 *tpr = (volatile u32 *)(APIC_DEFAULT_PHYS_BASE + APIC_TASKPRI); + u32 cr8 = read_cr8(); - memset((void *)APIC_DEFAULT_PHYS_BASE, 0xff, PAGE_SIZE); - report(*lvr == ~0, "*0xfee00030: %x", *lvr); - report(read_cr8() == cr8, "CR8: %lx", read_cr8()); - write_cr8(cr8 ^ MAX_TPR); - report(read_cr8() == (cr8 ^ MAX_TPR), "CR8: %lx", read_cr8()); - report(*tpr == ~0, "*0xfee00080: %x", *tpr); - write_cr8(cr8); + memset((void *)APIC_DEFAULT_PHYS_BASE, 0xff, PAGE_SIZE); + report(*lvr == ~0, "*0xfee00030: %x", *lvr); + report(read_cr8() == cr8, "CR8: %lx", read_cr8()); + write_cr8(cr8 ^ MAX_TPR); + report(read_cr8() == (cr8 ^ MAX_TPR), "CR8: %lx", read_cr8()); + report(*tpr == ~0, "*0xfee00080: %x", *tpr); + write_cr8(cr8); } static void test_apic_disable(void) { - volatile u32 *lvr = (volatile u32 *)(APIC_DEFAULT_PHYS_BASE + APIC_LVR); - volatile u32 *tpr = (volatile u32 *)(APIC_DEFAULT_PHYS_BASE + APIC_TASKPRI); - u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE); - u32 apic_version = apic_read(APIC_LVR); - u32 cr8 = read_cr8(); - - report_prefix_push("apic_disable"); - assert_msg(orig_apicbase & APIC_EN, "APIC not enabled."); - - disable_apic(); - report(!(rdmsr(MSR_IA32_APICBASE) & APIC_EN), "Local apic disabled"); - report(!this_cpu_has(X86_FEATURE_APIC), - "CPUID.1H:EDX.APIC[bit 9] is clear"); - verify_disabled_apic_mmio(); - - reset_apic(); - report((rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == APIC_EN, - "Local apic enabled in xAPIC mode"); - report(this_cpu_has(X86_FEATURE_APIC), "CPUID.1H:EDX.APIC[bit 9] is set"); - report(*lvr == apic_version, "*0xfee00030: %x", *lvr); - report(*tpr == cr8, "*0xfee00080: %x", *tpr); - write_cr8(cr8 ^ MAX_TPR); - report(*tpr == (cr8 ^ MAX_TPR) << 4, "*0xfee00080: %x", *tpr); - write_cr8(cr8); - - if (enable_x2apic()) { - apic_write(APIC_SPIV, 0x1ff); - report((rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == (APIC_EN | APIC_EXTD), - "Local apic enabled in x2APIC mode"); - report(this_cpu_has(X86_FEATURE_APIC), - "CPUID.1H:EDX.APIC[bit 9] is set"); + volatile u32 *lvr = (volatile u32 *)(APIC_DEFAULT_PHYS_BASE + APIC_LVR); + volatile u32 *tpr = (volatile u32 *)(APIC_DEFAULT_PHYS_BASE + APIC_TASKPRI); + u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE); + u32 apic_version = apic_read(APIC_LVR); + u32 cr8 = read_cr8(); + + report_prefix_push("apic_disable"); + assert_msg(orig_apicbase & APIC_EN, "APIC not enabled."); + + disable_apic(); + report(!(rdmsr(MSR_IA32_APICBASE) & APIC_EN), "Local apic disabled"); + report(!this_cpu_has(X86_FEATURE_APIC), + "CPUID.1H:EDX.APIC[bit 9] is clear"); verify_disabled_apic_mmio(); - if (!(orig_apicbase & APIC_EXTD)) - reset_apic(); - } - report_prefix_pop(); + + reset_apic(); + report((rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == APIC_EN, + "Local apic enabled in xAPIC mode"); + report(this_cpu_has(X86_FEATURE_APIC), "CPUID.1H:EDX.APIC[bit 9] is set"); + report(*lvr == apic_version, "*0xfee00030: %x", *lvr); + report(*tpr == cr8, "*0xfee00080: %x", *tpr); + write_cr8(cr8 ^ MAX_TPR); + report(*tpr == (cr8 ^ MAX_TPR) << 4, "*0xfee00080: %x", *tpr); + write_cr8(cr8); + + if (enable_x2apic()) { + apic_write(APIC_SPIV, 0x1ff); + report((rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == (APIC_EN | APIC_EXTD), + "Local apic enabled in x2APIC mode"); + report(this_cpu_has(X86_FEATURE_APIC), + "CPUID.1H:EDX.APIC[bit 9] is set"); + verify_disabled_apic_mmio(); + if (!(orig_apicbase & APIC_EXTD)) + reset_apic(); + } + report_prefix_pop(); } #define ALTERNATE_APIC_BASE 0xfed40000 static void test_apicbase(void) { - u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE); - u32 lvr = apic_read(APIC_LVR); - u64 value; + u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE); + u32 lvr = apic_read(APIC_LVR); + u64 value; - wrmsr(MSR_IA32_APICBASE, orig_apicbase & ~(APIC_EN | APIC_EXTD)); - wrmsr(MSR_IA32_APICBASE, ALTERNATE_APIC_BASE | APIC_BSP | APIC_EN); + wrmsr(MSR_IA32_APICBASE, orig_apicbase & ~(APIC_EN | APIC_EXTD)); + wrmsr(MSR_IA32_APICBASE, ALTERNATE_APIC_BASE | APIC_BSP | APIC_EN); - report_prefix_push("apicbase"); + report_prefix_push("apicbase"); - report(*(volatile u32 *)(ALTERNATE_APIC_BASE + APIC_LVR) == lvr, - "relocate apic"); + report(*(volatile u32 *)(ALTERNATE_APIC_BASE + APIC_LVR) == lvr, + "relocate apic"); - value = orig_apicbase | (1UL << cpuid_maxphyaddr()); - report(test_for_exception(GP_VECTOR, do_write_apicbase, &value), - "reserved physaddr bits"); + value = orig_apicbase | (1UL << cpuid_maxphyaddr()); + report(test_for_exception(GP_VECTOR, do_write_apicbase, &value), + "reserved physaddr bits"); - value = orig_apicbase | 1; - report(test_for_exception(GP_VECTOR, do_write_apicbase, &value), - "reserved low bits"); + value = orig_apicbase | 1; + report(test_for_exception(GP_VECTOR, do_write_apicbase, &value), + "reserved low bits"); - wrmsr(MSR_IA32_APICBASE, orig_apicbase); - apic_write(APIC_SPIV, 0x1ff); + wrmsr(MSR_IA32_APICBASE, orig_apicbase); + apic_write(APIC_SPIV, 0x1ff); - report_prefix_pop(); + report_prefix_pop(); } static void do_write_apic_id(void *id) { - apic_write(APIC_ID, *(u32 *)id); + apic_write(APIC_ID, *(u32 *)id); } static void __test_apic_id(void * unused) { - u32 id, newid; - u8 initial_xapic_id = cpuid(1).b >> 24; - u32 initial_x2apic_id = cpuid(0xb).d; - bool x2apic_mode = rdmsr(MSR_IA32_APICBASE) & APIC_EXTD; + u32 id, newid; + u8 initial_xapic_id = cpuid(1).b >> 24; + u32 initial_x2apic_id = cpuid(0xb).d; + bool x2apic_mode = rdmsr(MSR_IA32_APICBASE) & APIC_EXTD; - if (x2apic_mode) - reset_apic(); + if (x2apic_mode) + reset_apic(); - id = apic_id(); - report(initial_xapic_id == id, "xapic id matches cpuid"); + id = apic_id(); + report(initial_xapic_id == id, "xapic id matches cpuid"); - newid = (id + 1) << 24; - report(!test_for_exception(GP_VECTOR, do_write_apic_id, &newid) && - (id == apic_id() || id + 1 == apic_id()), - "writeable xapic id"); + newid = (id + 1) << 24; + report(!test_for_exception(GP_VECTOR, do_write_apic_id, &newid) && + (id == apic_id() || id + 1 == apic_id()), + "writeable xapic id"); - if (!enable_x2apic()) - goto out; + if (!enable_x2apic()) + goto out; - report(test_for_exception(GP_VECTOR, do_write_apic_id, &newid), - "non-writeable x2apic id"); - report(initial_xapic_id == (apic_id() & 0xff), "sane x2apic id"); + report(test_for_exception(GP_VECTOR, do_write_apic_id, &newid), + "non-writeable x2apic id"); + report(initial_xapic_id == (apic_id() & 0xff), "sane x2apic id"); - /* old QEMUs do not set initial x2APIC ID */ - report(initial_xapic_id == (initial_x2apic_id & 0xff) && - initial_x2apic_id == apic_id(), - "x2apic id matches cpuid"); + /* old QEMUs do not set initial x2APIC ID */ + report(initial_xapic_id == (initial_x2apic_id & 0xff) && + initial_x2apic_id == apic_id(), + "x2apic id matches cpuid"); out: - reset_apic(); + reset_apic(); - report(initial_xapic_id == apic_id(), "correct xapic id after reset"); + report(initial_xapic_id == apic_id(), "correct xapic id after reset"); - /* old KVMs do not reset xAPIC ID */ - if (id != apic_id()) - apic_write(APIC_ID, id << 24); + /* old KVMs do not reset xAPIC ID */ + if (id != apic_id()) + apic_write(APIC_ID, id << 24); - if (x2apic_mode) - enable_x2apic(); + if (x2apic_mode) + enable_x2apic(); } static void test_apic_id(void) { - if (cpu_count() < 2) - return; + if (cpu_count() < 2) + return; - on_cpu(1, __test_apic_id, NULL); + on_cpu(1, __test_apic_id, NULL); } static int ipi_count; static void self_ipi_isr(isr_regs_t *regs) { - ++ipi_count; - eoi(); + ++ipi_count; + eoi(); } static void __test_self_ipi(void) { - u64 start = rdtsc(); - int vec = 0xf1; + u64 start = rdtsc(); + int vec = 0xf1; - handle_irq(vec, self_ipi_isr); - irq_enable(); - apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_FIXED | vec, - id_map[0]); + handle_irq(vec, self_ipi_isr); + irq_enable(); + apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_FIXED | vec, + id_map[0]); - do { - pause(); - } while (rdtsc() - start < 1000000000 && ipi_count == 0); + do { + pause(); + } while (rdtsc() - start < 1000000000 && ipi_count == 0); } static void test_self_ipi_xapic(void) { - u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE); + u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE); - report_prefix_push("self_ipi_xapic"); + report_prefix_push("self_ipi_xapic"); - /* Reset to xAPIC mode. */ - reset_apic(); - report((rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == APIC_EN, - "Local apic enabled in xAPIC mode"); + /* Reset to xAPIC mode. */ + reset_apic(); + report((rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == APIC_EN, + "Local apic enabled in xAPIC mode"); - ipi_count = 0; - __test_self_ipi(); - report(ipi_count == 1, "self ipi"); + ipi_count = 0; + __test_self_ipi(); + report(ipi_count == 1, "self ipi"); - /* Enable x2APIC mode if it was already enabled. */ - if (orig_apicbase & APIC_EXTD) - enable_x2apic(); + /* Enable x2APIC mode if it was already enabled. */ + if (orig_apicbase & APIC_EXTD) + enable_x2apic(); - report_prefix_pop(); + report_prefix_pop(); } static void test_self_ipi_x2apic(void) { - u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE); + u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE); - report_prefix_push("self_ipi_x2apic"); + report_prefix_push("self_ipi_x2apic"); - if (enable_x2apic()) { - report((rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == - (APIC_EN | APIC_EXTD), - "Local apic enabled in x2APIC mode"); + if (enable_x2apic()) { + report((rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == (APIC_EN | APIC_EXTD), + "Local apic enabled in x2APIC mode"); - ipi_count = 0; - __test_self_ipi(); - report(ipi_count == 1, "self ipi"); + ipi_count = 0; + __test_self_ipi(); + report(ipi_count == 1, "self ipi"); - /* Reset to xAPIC mode unless x2APIC was already enabled. */ - if (!(orig_apicbase & APIC_EXTD)) - reset_apic(); - } else { - report_skip("x2apic not detected"); - } + /* Reset to xAPIC mode unless x2APIC was already enabled. */ + if (!(orig_apicbase & APIC_EXTD)) + reset_apic(); + } else { + report_skip("x2apic not detected"); + } - report_prefix_pop(); + report_prefix_pop(); } volatile int nmi_counter_private, nmi_counter, nmi_hlt_counter, sti_loop_active; static void sti_nop(char *p) { - asm volatile ( + asm volatile ( ".globl post_sti \n\t" "sti \n" /* @@ -344,47 +342,44 @@ static void sti_nop(char *p) "cli" : : "m"(*p) ); - nmi_counter = nmi_counter_private; + nmi_counter = nmi_counter_private; } static void sti_loop(void *ignore) { - unsigned k = 0; + unsigned k = 0; - while (sti_loop_active) { - sti_nop((char *)(ulong)((k++ * 4096) % (128 * 1024 * 1024))); - } + while (sti_loop_active) + sti_nop((char *)(ulong)((k++ * 4096) % (128 * 1024 * 1024))); } static void nmi_handler(isr_regs_t *regs) { - extern void post_sti(void); - ++nmi_counter_private; - nmi_hlt_counter += regs->rip == (ulong)post_sti; + extern void post_sti(void); + ++nmi_counter_private; + nmi_hlt_counter += regs->rip == (ulong)post_sti; } static void test_sti_nmi(void) { - unsigned old_counter; + unsigned old_counter; - if (cpu_count() < 2) { - return; - } + if (cpu_count() < 2) + return; - handle_irq(2, nmi_handler); - on_cpu(1, update_cr3, (void *)read_cr3()); + handle_irq(2, nmi_handler); + on_cpu(1, update_cr3, (void *)read_cr3()); - sti_loop_active = 1; - on_cpu_async(1, sti_loop, 0); - while (nmi_counter < 30000) { - old_counter = nmi_counter; - apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, id_map[1]); - while (nmi_counter == old_counter) { - ; + sti_loop_active = 1; + on_cpu_async(1, sti_loop, 0); + while (nmi_counter < 30000) { + old_counter = nmi_counter; + apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, id_map[1]); + while (nmi_counter == old_counter) + ; } - } - sti_loop_active = 0; - report(nmi_hlt_counter == 0, "nmi-after-sti"); + sti_loop_active = 0; + report(nmi_hlt_counter == 0, "nmi-after-sti"); } static volatile bool nmi_done, nmi_flushed; @@ -394,140 +389,138 @@ static volatile int cpu0_nmi_ctr2, cpu1_nmi_ctr2; static void multiple_nmi_handler(isr_regs_t *regs) { - ++nmi_received; + ++nmi_received; } static void kick_me_nmi(void *blah) { - while (!nmi_done) { - ++cpu1_nmi_ctr1; - while (cpu1_nmi_ctr1 != cpu0_nmi_ctr1 && !nmi_done) { - pause(); + while (!nmi_done) { + ++cpu1_nmi_ctr1; + while (cpu1_nmi_ctr1 != cpu0_nmi_ctr1 && !nmi_done) + pause(); + + if (nmi_done) + return; + + apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, id_map[0]); + /* make sure the NMI has arrived by sending an IPI after it */ + apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_FIXED | APIC_INT_ASSERT + | 0x44, id_map[0]); + ++cpu1_nmi_ctr2; + while (cpu1_nmi_ctr2 != cpu0_nmi_ctr2 && !nmi_done) + pause(); } - if (nmi_done) { - return; - } - apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, id_map[0]); - /* make sure the NMI has arrived by sending an IPI after it */ - apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_FIXED | APIC_INT_ASSERT - | 0x44, id_map[0]); - ++cpu1_nmi_ctr2; - while (cpu1_nmi_ctr2 != cpu0_nmi_ctr2 && !nmi_done) { - pause(); - } - } } static void flush_nmi(isr_regs_t *regs) { - nmi_flushed = true; - apic_write(APIC_EOI, 0); + nmi_flushed = true; + apic_write(APIC_EOI, 0); } static void test_multiple_nmi(void) { - int i; - bool ok = true; + int i; + bool ok = true; - if (cpu_count() < 2) { - return; - } + if (cpu_count() < 2) + return; - sti(); - handle_irq(2, multiple_nmi_handler); - handle_irq(0x44, flush_nmi); - on_cpu_async(1, kick_me_nmi, 0); - for (i = 0; i < 100000; ++i) { - nmi_flushed = false; - nmi_received = 0; - ++cpu0_nmi_ctr1; - while (cpu1_nmi_ctr1 != cpu0_nmi_ctr1) { - pause(); - } - apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, id_map[0]); - while (!nmi_flushed) { - pause(); - } - if (nmi_received != 2) { - ok = false; - break; - } - ++cpu0_nmi_ctr2; - while (cpu1_nmi_ctr2 != cpu0_nmi_ctr2) { - pause(); + sti(); + handle_irq(2, multiple_nmi_handler); + handle_irq(0x44, flush_nmi); + on_cpu_async(1, kick_me_nmi, 0); + for (i = 0; i < 100000; ++i) { + nmi_flushed = false; + nmi_received = 0; + ++cpu0_nmi_ctr1; + while (cpu1_nmi_ctr1 != cpu0_nmi_ctr1) + pause(); + + apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, id_map[0]); + while (!nmi_flushed) + pause(); + + if (nmi_received != 2) { + ok = false; + break; + } + + ++cpu0_nmi_ctr2; + while (cpu1_nmi_ctr2 != cpu0_nmi_ctr2) + pause(); } - } - nmi_done = true; - report(ok, "multiple nmi"); + nmi_done = true; + report(ok, "multiple nmi"); } static void pending_nmi_handler(isr_regs_t *regs) { - int i; + int i; - if (++nmi_received == 1) { - for (i = 0; i < 10; ++i) - apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_NMI, 0); - } + if (++nmi_received == 1) { + for (i = 0; i < 10; ++i) + apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_NMI, 0); + } } static void test_pending_nmi(void) { - int i; + int i; - handle_irq(2, pending_nmi_handler); - for (i = 0; i < 100000; ++i) { - nmi_received = 0; + handle_irq(2, pending_nmi_handler); + for (i = 0; i < 100000; ++i) { + nmi_received = 0; - apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_NMI, 0); - while (nmi_received < 2) - pause(); + apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_NMI, 0); + while (nmi_received < 2) + pause(); - if (nmi_received != 2) - break; - } - report(nmi_received == 2, "pending nmi"); + if (nmi_received != 2) + break; + } + report(nmi_received == 2, "pending nmi"); } static volatile int lvtt_counter = 0; static void lvtt_handler(isr_regs_t *regs) { - lvtt_counter++; - eoi(); + lvtt_counter++; + eoi(); } static void test_apic_timer_one_shot(void) { - uint64_t tsc1, tsc2; - static const uint32_t interval = 0x10000; + uint64_t tsc1, tsc2; + static const uint32_t interval = 0x10000; #define APIC_LVT_TIMER_VECTOR (0xee) - handle_irq(APIC_LVT_TIMER_VECTOR, lvtt_handler); - irq_enable(); + handle_irq(APIC_LVT_TIMER_VECTOR, lvtt_handler); + irq_enable(); - /* One shot mode */ - apic_write(APIC_LVTT, APIC_LVT_TIMER_ONESHOT | - APIC_LVT_TIMER_VECTOR); - /* Divider == 1 */ - apic_write(APIC_TDCR, 0x0000000b); + /* One shot mode */ + apic_write(APIC_LVTT, APIC_LVT_TIMER_ONESHOT | + APIC_LVT_TIMER_VECTOR); + /* Divider == 1 */ + apic_write(APIC_TDCR, 0x0000000b); - tsc1 = rdtsc(); - /* Set "Initial Counter Register", which starts the timer */ - apic_write(APIC_TMICT, interval); - while (!lvtt_counter); - tsc2 = rdtsc(); + tsc1 = rdtsc(); + /* Set "Initial Counter Register", which starts the timer */ + apic_write(APIC_TMICT, interval); + while (!lvtt_counter); + tsc2 = rdtsc(); - /* - * For LVT Timer clock, SDM vol 3 10.5.4 says it should be - * derived from processor's bus clock (IIUC which is the same - * as TSC), however QEMU seems to be using nanosecond. In all - * cases, the following should satisfy on all modern - * processors. - */ - report((lvtt_counter == 1) && (tsc2 - tsc1 >= interval), - "APIC LVT timer one shot"); + /* + * For LVT Timer clock, SDM vol 3 10.5.4 says it should be + * derived from processor's bus clock (IIUC which is the same + * as TSC), however QEMU seems to be using nanosecond. In all + * cases, the following should satisfy on all modern + * processors. + */ + report((lvtt_counter == 1) && (tsc2 - tsc1 >= interval), + "APIC LVT timer one shot"); } static atomic_t broadcast_counter; @@ -567,11 +560,11 @@ static void test_physical_broadcast(void) printf("starting broadcast (%s)\n", enable_x2apic() ? "x2apic" : "xapic"); apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_FIXED | APIC_INT_ASSERT | - BROADCAST_VECTOR, broadcast_address); + BROADCAST_VECTOR, broadcast_address); report(broadcast_received(ncpus), "APIC physical broadcast address"); apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_FIXED | APIC_INT_ASSERT | - BROADCAST_VECTOR | APIC_DEST_ALLINC, 0); + BROADCAST_VECTOR | APIC_DEST_ALLINC, 0); report(broadcast_received(ncpus), "APIC physical broadcast shorthand"); } @@ -678,38 +671,38 @@ static void test_apic_change_mode(void) static void test_pv_ipi(void) { - int ret; - unsigned long a0 = 0xFFFFFFFF, a1 = 0, a2 = 0xFFFFFFFF, a3 = 0x0; + int ret; + unsigned long a0 = 0xFFFFFFFF, a1 = 0, a2 = 0xFFFFFFFF, a3 = 0x0; - asm volatile("vmcall" : "=a"(ret) :"a"(KVM_HC_SEND_IPI), "b"(a0), "c"(a1), "d"(a2), "S"(a3)); - report(!ret, "PV IPIs testing"); + asm volatile("vmcall" : "=a"(ret) :"a"(KVM_HC_SEND_IPI), "b"(a0), "c"(a1), "d"(a2), "S"(a3)); + report(!ret, "PV IPIs testing"); } int main(void) { - setup_vm(); + setup_vm(); - test_lapic_existence(); + test_lapic_existence(); - mask_pic_interrupts(); - test_apic_id(); - test_apic_disable(); - test_enable_x2apic(); - test_apicbase(); + mask_pic_interrupts(); + test_apic_id(); + test_apic_disable(); + test_enable_x2apic(); + test_apicbase(); - test_self_ipi_xapic(); - test_self_ipi_x2apic(); - test_physical_broadcast(); - if (test_device_enabled()) - test_pv_ipi(); + test_self_ipi_xapic(); + test_self_ipi_x2apic(); + test_physical_broadcast(); + if (test_device_enabled()) + test_pv_ipi(); - test_sti_nmi(); - test_multiple_nmi(); - test_pending_nmi(); + test_sti_nmi(); + test_multiple_nmi(); + test_pending_nmi(); - test_apic_timer_one_shot(); - test_apic_change_mode(); - test_tsc_deadline_timer(); + test_apic_timer_one_shot(); + test_apic_change_mode(); + test_tsc_deadline_timer(); - return report_summary(); + return report_summary(); } From patchwork Sat Oct 1 01:12:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12996245 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 786DAC433F5 for ; Sat, 1 Oct 2022 01:14:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231405AbiJABOP (ORCPT ); Fri, 30 Sep 2022 21:14:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57036 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232554AbiJABNv (ORCPT ); Fri, 30 Sep 2022 21:13:51 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E1FD65052D for ; Fri, 30 Sep 2022 18:13:08 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-356a9048111so25477457b3.6 for ; Fri, 30 Sep 2022 18:13:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date; bh=O5rbGvlbIIPD3OFir3IbfMTdhXoDT3U4VQf8r61cfVk=; b=FyG/AvlZGBby/ZTFwvRhhiTm1zGCP4RAbyl4Cgvb5aYklb/m+kcCxkA1GLnH24otfg EoW3wx7cP/SMFN+VBeinThPEDFKf21GNKNA5NjxF4jPikI1fS2GJCddlyQlZl+Cr0PUb tU7xMSUiOshoTdi02YKhke4Rml1a2tkjPnVbG5XLEKCPrD1/OX96h17zOLCy/d7Yc/vs P3e1C0nkpUFM9U356bTnnHgyDl4UoJCgCE+zCM5eMDnp8udfQgTMX5rSfL7HA3aTZEkO rBkCWAABegmsOcGMC/L1UQMYsmdSyxYJr/eH0Nz26jXULeD/VsMZJqC93BrhijCk+yCo TH2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date; bh=O5rbGvlbIIPD3OFir3IbfMTdhXoDT3U4VQf8r61cfVk=; b=lGhzrd8AaHhAukbGH8+mqdc7fwV3p1SHaOCPSYi9hpR7ZLSFjpZR1iPZTjXf6DhMAG FCxswBthp6ywRjt/7Rgz4VyNuA5886gpm9ZEiGHIIuyMpSuogAusg7yfqbHAV0Fj6Tai YfXBJz+UvOroKd47llZijhbWV/Xnd/rLW5WyS+SkFSf1etHLElV4UhaNmbIPQLoutBKX CHf4UbhS/KcvSHkAJAxU5Eu8vDwtPVYMvFuOSuYYI5Jx0Eh6y5LI948yVFIO4Bf0wL/m 0oJaPXz11Rs9bmhBv804M0O5eMlazJUER6P6yx509tCKPNNy6viOoklPyII2JlUx2hKj t6Ew== X-Gm-Message-State: ACrzQf3u9YhxP7mGVqvl4cZukGkRfqvFxUAEVOerpfwu6zXD3VAG+0Ob 7xDbvbEu7S+WWAQD2IVbyBAZnUZ4KDI= X-Google-Smtp-Source: AMsMyM4JVQwcK7XHH4cG9hL5nHudngILEOKoLDjbCYhpyHekZEbBJR4/AAuCepmC3Yc84/paTUPEFqShSzY= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a25:8c89:0:b0:6b4:75f3:8e6c with SMTP id m9-20020a258c89000000b006b475f38e6cmr11041216ybl.156.1664586788250; Fri, 30 Sep 2022 18:13:08 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 1 Oct 2022 01:12:55 +0000 In-Reply-To: <20221001011301.2077437-1-seanjc@google.com> Mime-Version: 1.0 References: <20221001011301.2077437-1-seanjc@google.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog Message-ID: <20221001011301.2077437-4-seanjc@google.com> Subject: [kvm-unit-tests PATCH 3/9] x86/apic: Add helpers to query current APIC state, e.g. xAPIC vs. x2APIC From: Sean Christopherson To: Paolo Bonzini Cc: kvm@vger.kernel.org, Maxim Levitsky , Sean Christopherson Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add helpers to query APIC state and use them to replace a bunch of open coded instances. No functional change intended. Signed-off-by: Sean Christopherson --- x86/apic.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/x86/apic.c b/x86/apic.c index f038198..650c1d0 100644 --- a/x86/apic.c +++ b/x86/apic.c @@ -10,6 +10,21 @@ #define MAX_TPR 0xf +static bool is_apic_hw_enabled(void) +{ + return rdmsr(MSR_IA32_APICBASE) & APIC_EN; +} + +static bool is_x2apic_enabled(void) +{ + return (rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == (APIC_EN | APIC_EXTD); +} + +static bool is_xapic_enabled(void) +{ + return (rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == APIC_EN; +} + static void test_lapic_existence(void) { u8 version; @@ -143,14 +158,13 @@ static void test_apic_disable(void) assert_msg(orig_apicbase & APIC_EN, "APIC not enabled."); disable_apic(); - report(!(rdmsr(MSR_IA32_APICBASE) & APIC_EN), "Local apic disabled"); + report(!is_apic_hw_enabled(), "Local apic disabled"); report(!this_cpu_has(X86_FEATURE_APIC), "CPUID.1H:EDX.APIC[bit 9] is clear"); verify_disabled_apic_mmio(); reset_apic(); - report((rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == APIC_EN, - "Local apic enabled in xAPIC mode"); + report(is_xapic_enabled(), "Local apic enabled in xAPIC mode"); report(this_cpu_has(X86_FEATURE_APIC), "CPUID.1H:EDX.APIC[bit 9] is set"); report(*lvr == apic_version, "*0xfee00030: %x", *lvr); report(*tpr == cr8, "*0xfee00080: %x", *tpr); @@ -160,8 +174,7 @@ static void test_apic_disable(void) if (enable_x2apic()) { apic_write(APIC_SPIV, 0x1ff); - report((rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == (APIC_EN | APIC_EXTD), - "Local apic enabled in x2APIC mode"); + report(is_x2apic_enabled(), "Local apic enabled in x2APIC mode"); report(this_cpu_has(X86_FEATURE_APIC), "CPUID.1H:EDX.APIC[bit 9] is set"); verify_disabled_apic_mmio(); @@ -211,7 +224,7 @@ static void __test_apic_id(void * unused) u32 id, newid; u8 initial_xapic_id = cpuid(1).b >> 24; u32 initial_x2apic_id = cpuid(0xb).d; - bool x2apic_mode = rdmsr(MSR_IA32_APICBASE) & APIC_EXTD; + bool x2apic_mode = is_x2apic_enabled(); if (x2apic_mode) reset_apic(); @@ -282,21 +295,20 @@ static void __test_self_ipi(void) static void test_self_ipi_xapic(void) { - u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE); + u64 was_x2apic = is_x2apic_enabled(); report_prefix_push("self_ipi_xapic"); /* Reset to xAPIC mode. */ reset_apic(); - report((rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == APIC_EN, - "Local apic enabled in xAPIC mode"); + report(is_xapic_enabled(), "Local apic enabled in xAPIC mode"); ipi_count = 0; __test_self_ipi(); report(ipi_count == 1, "self ipi"); /* Enable x2APIC mode if it was already enabled. */ - if (orig_apicbase & APIC_EXTD) + if (was_x2apic) enable_x2apic(); report_prefix_pop(); @@ -304,20 +316,19 @@ static void test_self_ipi_xapic(void) static void test_self_ipi_x2apic(void) { - u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE); + u64 was_xapic = is_xapic_enabled(); report_prefix_push("self_ipi_x2apic"); if (enable_x2apic()) { - report((rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == (APIC_EN | APIC_EXTD), - "Local apic enabled in x2APIC mode"); + report(is_x2apic_enabled(), "Local apic enabled in x2APIC mode"); ipi_count = 0; __test_self_ipi(); report(ipi_count == 1, "self ipi"); /* Reset to xAPIC mode unless x2APIC was already enabled. */ - if (!(orig_apicbase & APIC_EXTD)) + if (was_xapic) reset_apic(); } else { report_skip("x2apic not detected"); From patchwork Sat Oct 1 01:12:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12996246 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 1EC60C433FE for ; Sat, 1 Oct 2022 01:14:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232295AbiJABOR (ORCPT ); Fri, 30 Sep 2022 21:14:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54280 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232596AbiJABNv (ORCPT ); Fri, 30 Sep 2022 21:13:51 -0400 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 448BC5815D for ; Fri, 30 Sep 2022 18:13:10 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id cq15-20020a056a00330f00b005438e527f24so3643078pfb.23 for ; Fri, 30 Sep 2022 18:13:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date; bh=s9nQcTbWA1vaBJd+OdxvrWwoXTy8Z0AA2k1z4pE8JHE=; b=hQxDWtI39FF4zi5PG3yfqEa4s39uUDIRKRY1bt1QBiCmAUOkOJV3rdhoLNzAcgnKu4 so1EU0vaxf3tvKSE/1KqkScbbn9yw19WIzkjqnTMHcvL8I01m+ELtF+G5y/PP+AcHtT+ wDwhbkmxb/CiM0Mv6kuyDzuafRRx0r3C/munW1+Me3oSHdt/VE2z0XfiXa6M1oZFaEsD 7bD2DmnuGjejcfUf70qzTa90KmJWwQIg4oDn0KfPfReeAHtPcMDCvgT30l3JXdQkFm9Q r/CKfGlA6n0Jee2WaZo7J4JZUBP9kCevkJxaLPa3RzfXlV5VvBHKNhBU+OAXOeLKUFTH nZIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date; bh=s9nQcTbWA1vaBJd+OdxvrWwoXTy8Z0AA2k1z4pE8JHE=; b=DElrYTUXYl5FR+KqBLlOuvGkgU+WZKnLLxHysRAX/FBe/CgbXvflnD5SZHzcnbN5LQ LZkrnziYZ2iwKGgBnO+QK0iTuXX9Tz4vHBIqIao1nVMt8uUtamAgOmvlvCLX6SApQqcn 1H2MaLhVElVEHC14JNHx0mcLK1nqfxCf7m9Mckb68OVDz5ZkBaIR+Xkp4OtpoQFUzDAc fTmePUUjRAvtHiAuwCgU1JaY0zhu2c86bAwVm3lEIPBm98LVG+eDKEkIFrmUAK7y7GIh qyUtTYL8gB+5wTtTUCLDZ02GA/KxscqQdBVnw1HXv3AVZiK/ONqTkCZV6vsPqCWpLIgu i2Mg== X-Gm-Message-State: ACrzQf3w0rIipe5GJXMA/hdNxnvstaLRyRX2vo77xIJ2gwjSkee85+SS JtJKe147zwo7SmAFnB40RfIiPON0W/c= X-Google-Smtp-Source: AMsMyM6QTNanTWQ5/3CNvWssFD8mQqfCKFmUs7K7saowmXjQQsBYd348TBUz05NRiBcthW6w/gnv8AUXvqI= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a62:384e:0:b0:55a:fa17:5ca8 with SMTP id f75-20020a62384e000000b0055afa175ca8mr10291217pfa.79.1664586789881; Fri, 30 Sep 2022 18:13:09 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 1 Oct 2022 01:12:56 +0000 In-Reply-To: <20221001011301.2077437-1-seanjc@google.com> Mime-Version: 1.0 References: <20221001011301.2077437-1-seanjc@google.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog Message-ID: <20221001011301.2077437-5-seanjc@google.com> Subject: [kvm-unit-tests PATCH 4/9] x86/apic: Assert that vCPU0's APIC is enabled at the start of the test From: Sean Christopherson To: Paolo Bonzini Cc: kvm@vger.kernel.org, Maxim Levitsky , Sean Christopherson Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Assert that vCPU's APIC is fully enabled at the start of the apic test. The boot code is supposed to do that, but nothing ever actually verifies the APIC got setup correctly. Signed-off-by: Sean Christopherson --- x86/apic.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/x86/apic.c b/x86/apic.c index 650c1d0..6c555ce 100644 --- a/x86/apic.c +++ b/x86/apic.c @@ -15,6 +15,11 @@ static bool is_apic_hw_enabled(void) return rdmsr(MSR_IA32_APICBASE) & APIC_EN; } +static bool is_apic_sw_enabled(void) +{ + return apic_read(APIC_SPIV) & APIC_SPIV_APIC_ENABLED; +} + static bool is_x2apic_enabled(void) { return (rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == (APIC_EN | APIC_EXTD); @@ -691,6 +696,9 @@ static void test_pv_ipi(void) int main(void) { + assert_msg(is_apic_hw_enabled() && is_apic_sw_enabled(), + "APIC should be fully enabled by startup code."); + setup_vm(); test_lapic_existence(); From patchwork Sat Oct 1 01:12:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12996247 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 2E5A4C433F5 for ; Sat, 1 Oct 2022 01:14:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232277AbiJABOS (ORCPT ); Fri, 30 Sep 2022 21:14:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54376 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232772AbiJABNv (ORCPT ); Fri, 30 Sep 2022 21:13:51 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 148DBF027 for ; Fri, 30 Sep 2022 18:13:12 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id 88-20020a17090a09e100b00208c35d9452so3074693pjo.6 for ; Fri, 30 Sep 2022 18:13:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date; bh=JvKsep8llHvor/s05gir9lti0qYYQp8Nq7Cl7Mhl79s=; b=rbQ5SZxRfYxezW8FiOKdJsbc3bMbILJtwl9jJOm4Q0HgJWxKf0QYDjNVzbVgrhM537 V7nz9C+BET4No/aWCc00+dQXCRE+3ufb4yUf2Ludanfs6a1LCgqkJeow8/xbegg/EBI2 zTp/W5OFsRp0jIJdwff9wpuo+42LylJ2kYhOGgzV8Q8dZCmoF4oBKFEX2BxFjUB1i1Xe GqbVJJ/PbFYxhLVgSE1tSlHR9p1ylrwCaCgtUrBUZ83iF3PVOkbb54ydOS5EiPwPCi+4 XiltyDjfrCUQLe3qnx1BlUNQgQ4r2HZRtsTioT1BIvVz5B+hcd+/ecCcBedgECkGUkD5 JZgA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date; bh=JvKsep8llHvor/s05gir9lti0qYYQp8Nq7Cl7Mhl79s=; b=B6MhVe2R+SeLVarcFcqQl0+5HeSrOB1UsvzICHV88M16kLMl/jiPg8tdKze36cqhw+ VQmncEB1EhjHhkMFeHBIgR/9C586yuC63SikLWMPB5TARrBOJ7deCEboxOav6X8zaEWc /5r+MLVujZs2YEfjPikNff+0VqheN8KR4/eehv3drKR8z1oWY7ICMSQl3J2+GPmdSWbS bihWNDDgWAiKZFZvAFAY7Bsl6kPM46XkQ7SIzhEYJC9skbCGvSIQcE45V+VfhWkSOrh8 NEpw4Vi8Ec0v86r5/Rj6PDkHGI4AFZpcIMLuajVnTcIxvwUCtoxXB/7KvblcM3pADcue f6/g== X-Gm-Message-State: ACrzQf3swdM2tVtXMorOtO77o01SpH2F2kiYBO13FtGXkU/N4VZ2O+Pg z/+0I5hw5PVJC1cV4Q4+uR3N0s2jbyE= X-Google-Smtp-Source: AMsMyM4b/pssSTpheYe/VuOK0WhPFRguD4ywGeny45lk4yfevMSEEL8/QNIvuwbiulYzgXj1O7x3UiNTMSw= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a17:902:e5c1:b0:176:c2b3:6a4c with SMTP id u1-20020a170902e5c100b00176c2b36a4cmr11648279plf.87.1664586791617; Fri, 30 Sep 2022 18:13:11 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 1 Oct 2022 01:12:57 +0000 In-Reply-To: <20221001011301.2077437-1-seanjc@google.com> Mime-Version: 1.0 References: <20221001011301.2077437-1-seanjc@google.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog Message-ID: <20221001011301.2077437-6-seanjc@google.com> Subject: [kvm-unit-tests PATCH 5/9] x86/apic: Restore APIC to original state after every sub-test From: Sean Christopherson To: Paolo Bonzini Cc: kvm@vger.kernel.org, Maxim Levitsky , Sean Christopherson Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Restore the APIC to its original state after every APIC sub-test. Many of the tests already do (parts of) this manually, while others do not. Always restore to dedup code and to avoid cross-test dependencies. Signed-off-by: Sean Christopherson --- x86/apic.c | 92 +++++++++++++++++++++++++----------------------------- 1 file changed, 43 insertions(+), 49 deletions(-) diff --git a/x86/apic.c b/x86/apic.c index 6c555ce..e466a57 100644 --- a/x86/apic.c +++ b/x86/apic.c @@ -94,13 +94,12 @@ static bool test_write_apicbase_exception(u64 data) static void test_enable_x2apic(void) { - u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE); - u64 apicbase; + u64 apicbase = rdmsr(MSR_IA32_APICBASE); if (enable_x2apic()) { printf("x2apic enabled\n"); - apicbase = orig_apicbase & ~(APIC_EN | APIC_EXTD); + apicbase &= ~(APIC_EN | APIC_EXTD); report(test_write_apicbase_exception(apicbase | APIC_EXTD), "x2apic enabled to invalid state"); report(test_write_apicbase_exception(apicbase | APIC_EN), @@ -117,17 +116,6 @@ static void test_enable_x2apic(void) "apic disabled to apic enabled"); report(test_write_apicbase_exception(apicbase | APIC_EXTD), "apic enabled to invalid state"); - - if (orig_apicbase & APIC_EXTD) - enable_x2apic(); - else - reset_apic(); - - /* - * Disabling the APIC resets various APIC registers, restore - * them to their desired values. - */ - apic_write(APIC_SPIV, 0x1ff); } else { printf("x2apic not detected\n"); @@ -155,12 +143,10 @@ static void test_apic_disable(void) { volatile u32 *lvr = (volatile u32 *)(APIC_DEFAULT_PHYS_BASE + APIC_LVR); volatile u32 *tpr = (volatile u32 *)(APIC_DEFAULT_PHYS_BASE + APIC_TASKPRI); - u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE); u32 apic_version = apic_read(APIC_LVR); u32 cr8 = read_cr8(); report_prefix_push("apic_disable"); - assert_msg(orig_apicbase & APIC_EN, "APIC not enabled."); disable_apic(); report(!is_apic_hw_enabled(), "Local apic disabled"); @@ -178,13 +164,10 @@ static void test_apic_disable(void) write_cr8(cr8); if (enable_x2apic()) { - apic_write(APIC_SPIV, 0x1ff); report(is_x2apic_enabled(), "Local apic enabled in x2APIC mode"); report(this_cpu_has(X86_FEATURE_APIC), "CPUID.1H:EDX.APIC[bit 9] is set"); verify_disabled_apic_mmio(); - if (!(orig_apicbase & APIC_EXTD)) - reset_apic(); } report_prefix_pop(); } @@ -213,8 +196,8 @@ static void test_apicbase(void) report(test_for_exception(GP_VECTOR, do_write_apicbase, &value), "reserved low bits"); + /* Restore the APIC address, the "reset" helpers leave it as is. */ wrmsr(MSR_IA32_APICBASE, orig_apicbase); - apic_write(APIC_SPIV, 0x1ff); report_prefix_pop(); } @@ -300,8 +283,6 @@ static void __test_self_ipi(void) static void test_self_ipi_xapic(void) { - u64 was_x2apic = is_x2apic_enabled(); - report_prefix_push("self_ipi_xapic"); /* Reset to xAPIC mode. */ @@ -312,17 +293,11 @@ static void test_self_ipi_xapic(void) __test_self_ipi(); report(ipi_count == 1, "self ipi"); - /* Enable x2APIC mode if it was already enabled. */ - if (was_x2apic) - enable_x2apic(); - report_prefix_pop(); } static void test_self_ipi_x2apic(void) { - u64 was_xapic = is_xapic_enabled(); - report_prefix_push("self_ipi_x2apic"); if (enable_x2apic()) { @@ -331,10 +306,6 @@ static void test_self_ipi_x2apic(void) ipi_count = 0; __test_self_ipi(); report(ipi_count == 1, "self ipi"); - - /* Reset to xAPIC mode unless x2APIC was already enabled. */ - if (was_xapic) - reset_apic(); } else { report_skip("x2apic not detected"); } @@ -690,38 +661,61 @@ static void test_pv_ipi(void) int ret; unsigned long a0 = 0xFFFFFFFF, a1 = 0, a2 = 0xFFFFFFFF, a3 = 0x0; + if (!test_device_enabled()) + return; + asm volatile("vmcall" : "=a"(ret) :"a"(KVM_HC_SEND_IPI), "b"(a0), "c"(a1), "d"(a2), "S"(a3)); report(!ret, "PV IPIs testing"); } +typedef void (*apic_test_fn)(void); + int main(void) { + bool is_x2apic = is_x2apic_enabled(); + u32 spiv = apic_read(APIC_SPIV); + int i; + + const apic_test_fn tests[] = { + test_lapic_existence, + + test_apic_id, + test_apic_disable, + test_enable_x2apic, + test_apicbase, + + test_self_ipi_xapic, + test_self_ipi_x2apic, + test_physical_broadcast, + + test_pv_ipi, + + test_sti_nmi, + test_multiple_nmi, + test_pending_nmi, + + test_apic_timer_one_shot, + test_apic_change_mode, + test_tsc_deadline_timer, + }; + assert_msg(is_apic_hw_enabled() && is_apic_sw_enabled(), "APIC should be fully enabled by startup code."); setup_vm(); - test_lapic_existence(); - mask_pic_interrupts(); - test_apic_id(); - test_apic_disable(); - test_enable_x2apic(); - test_apicbase(); - test_self_ipi_xapic(); - test_self_ipi_x2apic(); - test_physical_broadcast(); - if (test_device_enabled()) - test_pv_ipi(); + for (i = 0; i < ARRAY_SIZE(tests); i++) { + tests[i](); - test_sti_nmi(); - test_multiple_nmi(); - test_pending_nmi(); + if (is_x2apic) + enable_x2apic(); + else + reset_apic(); - test_apic_timer_one_shot(); - test_apic_change_mode(); - test_tsc_deadline_timer(); + apic_write(APIC_SPIV, spiv); + } return report_summary(); } From patchwork Sat Oct 1 01:12:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12996248 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 E8D21C433FE for ; Sat, 1 Oct 2022 01:14:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232554AbiJABOU (ORCPT ); Fri, 30 Sep 2022 21:14:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51758 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232816AbiJABNv (ORCPT ); Fri, 30 Sep 2022 21:13:51 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CDE25FAF7 for ; Fri, 30 Sep 2022 18:13:13 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-354262a27c8so57324577b3.15 for ; Fri, 30 Sep 2022 18:13:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date; bh=OIejMZ1lDR6t5oXpG/Ccmc1XCYg+2ZD4LOTMaLAWyN4=; b=r3iHqPx7SCNGjuDxnCOKZfxUPbwttRJE8A2MUGTbJBuUlHSExYKeqABAFR+DZQxUfg /IDPb0MA7W7ydTSx5IzPSiDJE8KNiE8UpwVy39snLoHnt2zwc7FaL+7JgjInCXtPcC7f E8y1lmzE/f3tk3kSYYUYTd7ApS2acQsaRYZu0gPQUbWK6VBnsbILkTbsMyUvUSHBG8h4 RDggcJ/jE+xt2S71oeKH+J5dsWVgEldreLL9OoNLSiMeRzCIZSNECShGSRBbtnrihhdq ePHInO17l8iFImbCjLh10alVhRuc91UWCjIDHVu118qJlcDL7ciaY2Jc6Z/FnZjYB/Wp UUoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date; bh=OIejMZ1lDR6t5oXpG/Ccmc1XCYg+2ZD4LOTMaLAWyN4=; b=lUNvuwgapAQ4pdZveVh5amk8P7ZJ/vOD6Cgw7vvcM8GlYbwV4k1Q5guuiFGEF2jk/R /3jc01SytGgLEyJ/xNjlwMemTpGah1wjFh/rpDrcYlIRMTdfksx/e8If/9eCVC+KpA0y K7DNfhn/Qy5tnu+dz3NyXpSllXZIh3M3gH3UXmaNfEak+QeN247a8q+ipEPTVQvGDzln CcQNl/V66VI0k3tzNIQ9gJXXCBwxiS4T2fzd0J7DAYuwgPZUooTpsBTOaI1lsg3WHQRh 4LkZQOw3PvbhvW07y2pMXNenFHOTq8EdHecw2rojEkxbWRLZqfRuJZOBXdRpGQ6ud01A WYmw== X-Gm-Message-State: ACrzQf3AFrkOZz7o7Li+APbkYM7yPzaUoIGo+3jUOQvLXmYv8GqxQq2+ dWdAQqnNcGXYOFI2IdFy+keXTt01DVg= X-Google-Smtp-Source: AMsMyM71rqAVeHh0gm0/Bj+tj/iP0jTGYAAhETQFPMzIpzyRoNkE1DNua27+eHgpUcp654SpJpOEhy2nMTI= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a81:70d4:0:b0:355:4148:f041 with SMTP id l203-20020a8170d4000000b003554148f041mr9529605ywc.499.1664586793194; Fri, 30 Sep 2022 18:13:13 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 1 Oct 2022 01:12:58 +0000 In-Reply-To: <20221001011301.2077437-1-seanjc@google.com> Mime-Version: 1.0 References: <20221001011301.2077437-1-seanjc@google.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog Message-ID: <20221001011301.2077437-7-seanjc@google.com> Subject: [kvm-unit-tests PATCH 6/9] x86/apic: Enable IRQs on vCPU0 for all tests From: Sean Christopherson To: Paolo Bonzini Cc: kvm@vger.kernel.org, Maxim Levitsky , Sean Christopherson Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Enable IRQs on vCPU0 for all APIC sub-tests. Many sub-tests want to generate interrupts, and leaving IRQs disabled makes writing a new test unnecessarily frustrating (guess who forgot to enable IRQs...). Signed-off-by: Sean Christopherson --- x86/apic.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/x86/apic.c b/x86/apic.c index e466a57..3c00137 100644 --- a/x86/apic.c +++ b/x86/apic.c @@ -53,7 +53,6 @@ static void tsc_deadline_timer_isr(isr_regs_t *regs) static void __test_tsc_deadline_timer(void) { handle_irq(TSC_DEADLINE_TIMER_VECTOR, tsc_deadline_timer_isr); - irq_enable(); wrmsr(MSR_IA32_TSCDEADLINE, rdmsr(MSR_IA32_TSC)); asm volatile ("nop"); @@ -272,7 +271,6 @@ static void __test_self_ipi(void) int vec = 0xf1; handle_irq(vec, self_ipi_isr); - irq_enable(); apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_FIXED | vec, id_map[0]); @@ -485,7 +483,6 @@ static void test_apic_timer_one_shot(void) #define APIC_LVT_TIMER_VECTOR (0xee) handle_irq(APIC_LVT_TIMER_VECTOR, lvtt_handler); - irq_enable(); /* One shot mode */ apic_write(APIC_LVTT, APIC_LVT_TIMER_ONESHOT | @@ -705,6 +702,7 @@ int main(void) setup_vm(); mask_pic_interrupts(); + irq_enable(); for (i = 0; i < ARRAY_SIZE(tests); i++) { tests[i](); From patchwork Sat Oct 1 01:12:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12996249 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 4F014C43219 for ; Sat, 1 Oct 2022 01:14:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232807AbiJABOY (ORCPT ); Fri, 30 Sep 2022 21:14:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51986 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232820AbiJABNw (ORCPT ); Fri, 30 Sep 2022 21:13:52 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2C060AE6E for ; Fri, 30 Sep 2022 18:13:15 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id hk15-20020a17090b224f00b00205fa3483bdso5553361pjb.8 for ; Fri, 30 Sep 2022 18:13:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date; bh=d3z8rpME15F36lBJBWqhpN8Q8sYozxq8eC5r552UkaU=; b=V+XAi81nSBo2rFPt+tXFh8koIpQSoOakT40IcBLOkQlQTy9ydMZ2a3qhPze0V5jPQo nUlajSxvB25m58JzE6eR5djnPOxW6v+QOSt/WgvPG4MRLYXdL4zp8t3nc5RI5RzHlV5p O6DAJXGgSilkcDup7pWWw1UarX0vDp5vlPSzcgavf9ER4cIVF0TffFg3sDqapz8CzaPc 1SlKQuMTjFw5R4Ib0N1w0NTC6U+1yPpnRFx6Z+Nu91bCGPzKAC9zO4Cl2pEyNtEew/uW M65aO93Jd2QPC5mWK3genB5tLLaavd69F7Mh6DgvUJCFJvSdC3Glbnt0LxqrQqJX1/PU 4SAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date; bh=d3z8rpME15F36lBJBWqhpN8Q8sYozxq8eC5r552UkaU=; b=WAifs8BMqQuCUFweA+0EgMb5oIQIQOWKY+K9AztVB0rfrzwnTjJitLsSBfTvTKMclz t30garFNceg6PZ8MyL3OR/76Ta1nrjwcw9yTFMDe/6bTPo2WoRBhn1RQiPW+KIpGoMO0 UlEer4AtKZZ2umBKT6UDvP5b6RfCWA1EEyF1QttRiGKbOskIl8giKwTRKOY1l7KEWtxw 6Mz6XDkCdMqX7kH8g0lTDmYA6OynY3+FVaSEyjjlRRD7YURLGU81nGwrfSdWFeXvTw5e S1LFfbD7EUxmx7bKJT6Ar61ws0z4vd8Jvb4cQO+bbEWM2UXE8Krq3r+g9WtEgWwjwOqj yKKw== X-Gm-Message-State: ACrzQf1WMOCYBEjUxME1wtBeM9hce/hWHW7EDXkFirKzZrEqnnkX4Ami kfmv6ITVJTvoLYv6hm3u+yuATIf1c/w= X-Google-Smtp-Source: AMsMyM6PpJQ4CUr6KWfd55xFh5/qekK5HSt6MMCGMaGguAkp+OI6Wd7Sa08vCf8UVKO0jk/oMOA8kkPF9KE= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a62:4e8e:0:b0:54a:ee65:cde6 with SMTP id c136-20020a624e8e000000b0054aee65cde6mr11728633pfb.42.1664586794785; Fri, 30 Sep 2022 18:13:14 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 1 Oct 2022 01:12:59 +0000 In-Reply-To: <20221001011301.2077437-1-seanjc@google.com> Mime-Version: 1.0 References: <20221001011301.2077437-1-seanjc@google.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog Message-ID: <20221001011301.2077437-8-seanjc@google.com> Subject: [kvm-unit-tests PATCH 7/9] x86/apic: Run tests that modify APIC ID and/or APIC_BASE after other tests From: Sean Christopherson To: Paolo Bonzini Cc: kvm@vger.kernel.org, Maxim Levitsky , Sean Christopherson Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Run the sub-tests that modify the APIC ID and/or APIC base address after all other sub-tests. KVM disables APICv/AVIC if the ID or base is changed, and keeps APICv/AVIC disabled even if the original value is restored. I.e. run as many tests as possible with an APICv/AVIC friendly setup. Signed-off-by: Sean Christopherson --- x86/apic.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/x86/apic.c b/x86/apic.c index 3c00137..5be44b8 100644 --- a/x86/apic.c +++ b/x86/apic.c @@ -676,10 +676,8 @@ int main(void) const apic_test_fn tests[] = { test_lapic_existence, - test_apic_id, test_apic_disable, test_enable_x2apic, - test_apicbase, test_self_ipi_xapic, test_self_ipi_x2apic, @@ -694,6 +692,14 @@ int main(void) test_apic_timer_one_shot, test_apic_change_mode, test_tsc_deadline_timer, + + /* + * KVM may disable APICv if the APIC ID and/or APIC_BASE is + * modified, keep these tests at the end so that the test as a + * whole provides coverage for APICv (when it's enabled). + */ + test_apic_id, + test_apicbase, }; assert_msg(is_apic_hw_enabled() && is_apic_sw_enabled(), From patchwork Sat Oct 1 01:13:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12996250 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 8EE03C43217 for ; Sat, 1 Oct 2022 01:14:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232923AbiJABO0 (ORCPT ); Fri, 30 Sep 2022 21:14:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52274 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232823AbiJABNw (ORCPT ); Fri, 30 Sep 2022 21:13:52 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 13EC011461 for ; Fri, 30 Sep 2022 18:13:17 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id l72-20020a63914b000000b00434ac6f8214so3717457pge.13 for ; Fri, 30 Sep 2022 18:13:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date; bh=BrQJA1GEfWK5dvPJqWYwg3wcFKIFArdWH1xnahMzA7M=; b=ppgOtxDSzPIJmEbJ95yLQd6JsUPhIMglgS9nAFNj2H5aFNwBheBsvCeElOlZ7MLYg0 r3wM2kK5HfITmoWcoBvesApsWEIynOmFwZ1E0T8ojNxtDsgw62/6z9Yh2lQYjO1wX7G8 3+cAIojFsaDLLoH0MbglWzgvuRmoqjYcP1Kfl+wHmIGcsxojHMSsC1t1TAVF5rHPYw5s Vch0yPZEId4IO650EXdr2dpcEYfNDnebFD5ViNqtucJ2+nz7oVHoUct/GCxQuVL2x5XM VKoLQjFcoV8qKiNrxkcah//lcdcHo2XughlMP2kJGvufvb9CEeT0BxWyNSoxqPQ0F8bS oobQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date; bh=BrQJA1GEfWK5dvPJqWYwg3wcFKIFArdWH1xnahMzA7M=; b=YT9S4nqqKxIIxwT6ZSotnxOaeWeJoCuDlhUNpNSSUwMPnJVe7d4qC1+zfFRwYAz5JH qBxV/TScwfez8iAgvg4TDbKr8gPmTbYeoI/y6yuKSrc6CwT7rSz86VhZmSBrKNhR2GKl leP//l2kTnHaI0ac1qqXoSuVMgqAW9dyZoqfn81aZ1ikLfTjpeMMDXLMTYpYw3gnu0VS sw9lXCCkdQzungFT1xzOlNeigymxYIaC406VRbOfIbmTfmVm8x38JUC647DKTZ1GEMV9 XX2bfSt56dnhT//Hwgb637qc2ZF6CxuE/cgMSpTWS+l7JTlV7ZPQljZt2QqeLJM8cC0d eUpA== X-Gm-Message-State: ACrzQf3nv5eqaLVE7OiCn2E3AyxkMixVpfV5q8h12huHm1N62trKg8T8 8Ls9jOjwi6DhIYjteeNMPDx3m8+smiE= X-Google-Smtp-Source: AMsMyM4EUPmX6HDfzdevzPf660npw9NDqtqFyliGQVi8jvvPCwCfMv6xjNnCUqs8uXyiYYHHIRIr3/5y9w0= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a17:90a:c986:b0:205:f08c:a82b with SMTP id w6-20020a17090ac98600b00205f08ca82bmr520222pjt.1.1664586796335; Fri, 30 Sep 2022 18:13:16 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 1 Oct 2022 01:13:00 +0000 In-Reply-To: <20221001011301.2077437-1-seanjc@google.com> Mime-Version: 1.0 References: <20221001011301.2077437-1-seanjc@google.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog Message-ID: <20221001011301.2077437-9-seanjc@google.com> Subject: [kvm-unit-tests PATCH 8/9] x86/apic: Add test for logical mode IPI delivery (cluster and flat) From: Sean Christopherson To: Paolo Bonzini Cc: kvm@vger.kernel.org, Maxim Levitsky , Sean Christopherson Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add an APIC sub-test to verify the darker corners of logical mode IPI delivery. Logical mode is rather bizarre, in that each "ID" is treated as a bitmask, e.g. an ID with multiple bits set can match multiple destinations. Verify that overlapping and/or superfluous destinations and IDs with multiple target vCPUs are handled correctly for both flat and cluster modes. Signed-off-by: Sean Christopherson --- x86/apic.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 192 insertions(+), 9 deletions(-) diff --git a/x86/apic.c b/x86/apic.c index 5be44b8..1cc61d3 100644 --- a/x86/apic.c +++ b/x86/apic.c @@ -257,11 +257,11 @@ static void test_apic_id(void) on_cpu(1, __test_apic_id, NULL); } -static int ipi_count; +static atomic_t ipi_count; -static void self_ipi_isr(isr_regs_t *regs) +static void handle_ipi(isr_regs_t *regs) { - ++ipi_count; + atomic_inc(&ipi_count); eoi(); } @@ -270,13 +270,13 @@ static void __test_self_ipi(void) u64 start = rdtsc(); int vec = 0xf1; - handle_irq(vec, self_ipi_isr); + handle_irq(vec, handle_ipi); apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_FIXED | vec, id_map[0]); do { pause(); - } while (rdtsc() - start < 1000000000 && ipi_count == 0); + } while (rdtsc() - start < 1000000000 && atomic_read(&ipi_count) == 0); } static void test_self_ipi_xapic(void) @@ -287,9 +287,9 @@ static void test_self_ipi_xapic(void) reset_apic(); report(is_xapic_enabled(), "Local apic enabled in xAPIC mode"); - ipi_count = 0; + atomic_set(&ipi_count, 0); __test_self_ipi(); - report(ipi_count == 1, "self ipi"); + report(atomic_read(&ipi_count) == 1, "self ipi"); report_prefix_pop(); } @@ -301,9 +301,9 @@ static void test_self_ipi_x2apic(void) if (enable_x2apic()) { report(is_x2apic_enabled(), "Local apic enabled in x2APIC mode"); - ipi_count = 0; + atomic_set(&ipi_count, 0); __test_self_ipi(); - report(ipi_count == 1, "self ipi"); + report(atomic_read(&ipi_count) == 1, "self ipi"); } else { report_skip("x2apic not detected"); } @@ -665,6 +665,188 @@ static void test_pv_ipi(void) report(!ret, "PV IPIs testing"); } +#define APIC_LDR_CLUSTER_FLAG BIT(31) + +static void set_ldr(void *__ldr) +{ + u32 ldr = (unsigned long)__ldr; + + if (ldr & APIC_LDR_CLUSTER_FLAG) + apic_write(APIC_DFR, APIC_DFR_CLUSTER); + else + apic_write(APIC_DFR, APIC_DFR_FLAT); + + apic_write(APIC_LDR, ldr << 24); +} + +static int test_fixed_ipi(u32 dest_mode, u8 dest, u8 vector, + int nr_ipis_expected, const char *mode_name) +{ + u64 start = rdtsc(); + int got; + + atomic_set(&ipi_count, 0); + + /* + * Wait for vCPU1 to get back into HLT, i.e. into the host so that + * KVM must handle incomplete AVIC IPIs. + */ + do { + pause(); + } while (rdtsc() - start < 1000000); + + start = rdtsc(); + + apic_icr_write(dest_mode | APIC_DM_FIXED | vector, dest); + + do { + pause(); + } while (rdtsc() - start < 1000000000 && + atomic_read(&ipi_count) != nr_ipis_expected); + + /* Only report failures to cut down on the spam. */ + got = atomic_read(&ipi_count); + if (got != nr_ipis_expected) + report_fail("Want %d IPI(s) using %s mode, dest = %x, got %d IPI(s)", + nr_ipis_expected, mode_name, dest, got); + atomic_set(&ipi_count, 0); + + return got == nr_ipis_expected ? 0 : 1; +} + +static int test_logical_ipi_single_target(u8 logical_id, bool cluster, u8 dest, + u8 vector) +{ + /* Disallow broadcast, there are at least 2 vCPUs. */ + if (dest == 0xff) + return 0; + + set_ldr((void *)0); + on_cpu(1, set_ldr, + (void *)((u32)logical_id | (cluster ? APIC_LDR_CLUSTER_FLAG : 0))); + return test_fixed_ipi(APIC_DEST_LOGICAL, dest, vector, 1, + cluster ? "logical cluster" : "logical flat"); +} + +static int test_logical_ipi_multi_target(u8 vcpu0_logical_id, u8 vcpu1_logical_id, + bool cluster, u8 dest, u8 vector) +{ + /* Allow broadcast unless there are more than 2 vCPUs. */ + if (dest == 0xff && cpu_count() > 2) + return 0; + + set_ldr((void *)((u32)vcpu0_logical_id | (cluster ? APIC_LDR_CLUSTER_FLAG : 0))); + on_cpu(1, set_ldr, + (void *)((u32)vcpu1_logical_id | (cluster ? APIC_LDR_CLUSTER_FLAG : 0))); + return test_fixed_ipi(APIC_DEST_LOGICAL, dest, vector, 2, + cluster ? "logical cluster" : "logical flat"); +} + +static void test_logical_ipi_xapic(void) +{ + int c, i, j, k, f; + u8 vector = 0xf1; + + if (cpu_count() < 2) + return; + + /* + * All vCPUs must be in xAPIC mode, i.e. simply resetting this vCPUs + * APIC is not sufficient. + */ + if (is_x2apic_enabled()) + return; + + handle_irq(vector, handle_ipi); + + /* Flat mode. 8 bits for logical IDs (one per bit). */ + f = 0; + for (i = 0; i < 8; i++) { + /* + * Test all possible destination values. Non-existent targets + * should be ignored. vCPU is always targeted, i.e. should get + * an IPI. + */ + for (k = 0; k < 0xff; k++) { + /* + * Skip values that overlap the actual target the + * resulting combination will be covered by other + * numbers in the sequence. + */ + if (BIT(i) & k) + continue; + + f += test_logical_ipi_single_target(BIT(i), false, + BIT(i) | k, vector); + } + } + report(!f, "IPI to single target using logical flat mode"); + + /* Cluster mode. 4 bits for the cluster, 4 bits for logical IDs. */ + f = 0; + for (c = 0; c < 0xf; c++) { + for (i = 0; i < 4; i++) { + /* Same as above, just fewer bits... */ + for (k = 0; k < 0x10; k++) { + if (BIT(i) & k) + continue; + + test_logical_ipi_single_target(c << 4 | BIT(i), true, + c << 4 | BIT(i) | k, vector); + } + } + } + report(!f, "IPI to single target using logical cluster mode"); + + /* And now do it all over again targeting both vCPU0 and vCPU1. */ + f = 0; + for (i = 0; i < 8 && !f; i++) { + for (j = 0; j < 8 && !f; j++) { + if (i == j) + continue; + + for (k = 0; k < 0x100 && !f; k++) { + if ((BIT(i) | BIT(j)) & k) + continue; + + f += test_logical_ipi_multi_target(BIT(i), BIT(j), false, + BIT(i) | BIT(j) | k, vector); + if (f) + break; + f += test_logical_ipi_multi_target(BIT(i) | BIT(j), + BIT(i) | BIT(j), false, + BIT(i) | BIT(j) | k, vector); + } + } + } + report(!f, "IPI to multiple targets using logical flat mode"); + + f = 0; + for (c = 0; c < 0xf && !f; c++) { + for (i = 0; i < 4 && !f; i++) { + for (j = 0; j < 4 && !f; j++) { + if (i == j) + continue; + + for (k = 0; k < 0x10 && !f; k++) { + if ((BIT(i) | BIT(j)) & k) + continue; + + f += test_logical_ipi_multi_target(c << 4 | BIT(i), + c << 4 | BIT(j), true, + c << 4 | BIT(i) | BIT(j) | k, vector); + if (f) + break; + f += test_logical_ipi_multi_target(c << 4 | BIT(i) | BIT(j), + c << 4 | BIT(i) | BIT(j), true, + c << 4 | BIT(i) | BIT(j) | k, vector); + } + } + } + } + report(!f, "IPI to multiple targets using logical cluster mode"); +} + typedef void (*apic_test_fn)(void); int main(void) @@ -682,6 +864,7 @@ int main(void) test_self_ipi_xapic, test_self_ipi_x2apic, test_physical_broadcast, + test_logical_ipi_xapic, test_pv_ipi, From patchwork Sat Oct 1 01:13:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 12996251 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 13F4EC4167D for ; Sat, 1 Oct 2022 01:14:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233003AbiJABO2 (ORCPT ); Fri, 30 Sep 2022 21:14:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57074 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232830AbiJABNw (ORCPT ); Fri, 30 Sep 2022 21:13:52 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C245DB7CD for ; Fri, 30 Sep 2022 18:13:18 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id oc9-20020a17090b1c0900b00202843f7057so5118659pjb.1 for ; Fri, 30 Sep 2022 18:13:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date; bh=6LeoLx+siWNuiV22hQNpi4t4jY/oE2NYBDm2S2o/zFM=; b=W/rO87my6AaX5UFmoZ8BW4m6SgD43VQFLRaBiBXAkokhiG4lq6k7ggP/dWhKTNcEKF W2m5dfnBqAqu/az4Sje2dcQzToTuCu6Jd0tvUFq0EoTJ0IjzMC5rX4tZdUwiAG6ID75Z SdETrRc+MgpWU/QZeo/1ibe6AgD+xf96lfkHX78dtq2b7V2yhpeF0jHWcnosRG38aPqL 6NPDcSDZH5hicql4MSviwIwnU1cevklbE7vCaWSChDgQ7YyY+TdgMlVWuLqw5u8w6Msk SZhX4YoxCegwozlejBX7X+kkkZxbvH/H2xmLb2Manufvt9Zd3S0B0yTkSgho4qThu8Ll EjKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date; bh=6LeoLx+siWNuiV22hQNpi4t4jY/oE2NYBDm2S2o/zFM=; b=65p9L//VLuiQ3btQM1LHg6GptS3gbkicKv1qPSqdlj1p95NjbD5Ug8XeQcViDoN/By 5oaEtSwW7lFsQHaljuw5js7J0AkTzeWsrr55Gy6UZACuQjscxSeCmliaXAm03F0c4gcy EM2EY/8oMiuKSYdwEXFBkhnIDZatoqzQJfjYSOKQ7aR0LDt6cefxtWEg88s6PTWnUiWz m9codH9+97yB5j3RlwQRXUnkvFfpWwDKcox9ctzDllXrFB6LLE/qVD4hO0Z8qYVxLoAA KiB16TwAuQHGXANuFjDTJ6w2Ufr9Hwg5zFx1Bx8qoeOonFjkOEl7d1KybYTUSsdbktyN H11A== X-Gm-Message-State: ACrzQf2YjQBYLJyg5zHAFLDr5DAtaIfcXJpErLnHSIfThefy0ZjNHkPr 24OFtPTHzHMkwmIFhynznjOOo35G6AA= X-Google-Smtp-Source: AMsMyM7toVwt0BMTYLihyJGEGrj97RclVMxwMf1/k76+zed8aKup0dA2kHNMQ/B9o7ruU3jCcN20SJ0pNlo= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a05:6a00:198e:b0:541:f85a:6c27 with SMTP id d14-20020a056a00198e00b00541f85a6c27mr11819622pfl.81.1664586798335; Fri, 30 Sep 2022 18:13:18 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 1 Oct 2022 01:13:01 +0000 In-Reply-To: <20221001011301.2077437-1-seanjc@google.com> Mime-Version: 1.0 References: <20221001011301.2077437-1-seanjc@google.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog Message-ID: <20221001011301.2077437-10-seanjc@google.com> Subject: [kvm-unit-tests PATCH 9/9] x86/apic: Add test to verify aliased xAPIC IDs both receive IPI From: Sean Christopherson To: Paolo Bonzini Cc: kvm@vger.kernel.org, Maxim Levitsky , Sean Christopherson Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Verify that multiple vCPUs with the same physical xAPIC ID receive an IPI sent to said ID. Note, on_cpu() maintains its own CPU=>ID map and is effectively unusuable after changing the xAPIC ID. Update each vCPU's xAPIC ID from within the IRQ handler so as to avoid having to send yet another IPI from vCPU0 to tell vCPU1 to update its ID. Signed-off-by: Sean Christopherson --- lib/x86/processor.h | 1 + x86/apic.c | 67 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/lib/x86/processor.h b/lib/x86/processor.h index 0324220..280821e 100644 --- a/lib/x86/processor.h +++ b/lib/x86/processor.h @@ -219,6 +219,7 @@ static inline bool is_intel(void) #define X86_FEATURE_VMX (CPUID(0x1, 0, ECX, 5)) #define X86_FEATURE_PDCM (CPUID(0x1, 0, ECX, 15)) #define X86_FEATURE_PCID (CPUID(0x1, 0, ECX, 17)) +#define X86_FEATURE_X2APIC (CPUID(0x1, 0, ECX, 21)) #define X86_FEATURE_MOVBE (CPUID(0x1, 0, ECX, 22)) #define X86_FEATURE_TSC_DEADLINE_TIMER (CPUID(0x1, 0, ECX, 24)) #define X86_FEATURE_XSAVE (CPUID(0x1, 0, ECX, 26)) diff --git a/x86/apic.c b/x86/apic.c index 1cc61d3..20c3a1a 100644 --- a/x86/apic.c +++ b/x86/apic.c @@ -847,6 +847,72 @@ static void test_logical_ipi_xapic(void) report(!f, "IPI to multiple targets using logical cluster mode"); } +static void set_xapic_physical_id(void *apic_id) +{ + apic_write(APIC_ID, (unsigned long)apic_id << 24); +} + +static void handle_aliased_ipi(isr_regs_t *regs) +{ + u32 apic_id = apic_read(APIC_ID) >> 24; + + if (apic_id == 0xff) + apic_id = smp_id(); + else + apic_id++; + apic_write(APIC_ID, (unsigned long)apic_id << 24); + + /* + * Handle the IPI after updating the APIC ID, as the IPI count acts as + * synchronization barrier before vCPU0 sends the next IPI. + */ + handle_ipi(regs); +} + +static void test_aliased_xapic_physical_ipi(void) +{ + u8 vector = 0xf1; + int i, f; + + if (cpu_count() < 2) + return; + + /* + * All vCPUs must be in xAPIC mode, i.e. simply resetting this vCPUs + * APIC is not sufficient. + */ + if (is_x2apic_enabled()) + return; + + /* + * By default, KVM doesn't follow the x86 APIC architecture for aliased + * APIC IDs if userspace has enabled KVM_X2APIC_API_USE_32BIT_IDS. + * If x2APIC is supported, assume the userspace VMM has enabled 32-bit + * IDs and thus activated KVM's quirk. Delete this code to run the + * aliasing test on x2APIC CPUs, e.g. to run it on bare metal. + */ + if (this_cpu_has(X86_FEATURE_X2APIC)) + return; + + handle_irq(vector, handle_aliased_ipi); + + /* + * Set both vCPU0 and vCPU1's APIC IDs to 0, then start the chain + * reaction of IPIs from APIC ID 0..255. Each vCPU will increment its + * APIC ID in the handler, and then "reset" to its original ID (using + * smp_id()) after the last IPI. Using on_cpu() to set vCPU1's ID + * after this point won't work due to on_cpu() using physical mode. + */ + on_cpu(1, set_xapic_physical_id, (void *)0ul); + set_xapic_physical_id((void *)0ul); + + f = 0; + for (i = 0; i < 0x100; i++) + f += test_fixed_ipi(APIC_DEST_PHYSICAL, i, vector, 2, "physical"); + + report(!f, "IPI to aliased xAPIC physical IDs"); +} + typedef void (*apic_test_fn)(void); int main(void) @@ -883,6 +949,7 @@ int main(void) */ test_apic_id, test_apicbase, + test_aliased_xapic_physical_ipi, }; assert_msg(is_apic_hw_enabled() && is_apic_sw_enabled(),