From nobody Fri May 3 21:23:23 2024 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 3B4EAC7EE2D for ; Fri, 2 Jun 2023 23:33:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236862AbjFBXdJ (ORCPT ); Fri, 2 Jun 2023 19:33:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49690 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236836AbjFBXdF (ORCPT ); Fri, 2 Jun 2023 19:33:05 -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 77D33197 for ; Fri, 2 Jun 2023 16:33:04 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id d2e1a72fcca58-653843401feso403718b3a.0 for ; Fri, 02 Jun 2023 16:33:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1685748784; x=1688340784; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date:message-id:reply-to; bh=88IydSMT3h4MdgZedrdgoEtngKl/WmRfHDWOuNscQw8=; b=pEHPhuEb5kqwcEzdnoMQsduQWHqF7mPaSb55QalrwPyEi4aqtMLBsI8lMdOzk8bJKV WDeRHKXRdGpS6xsiuoo4O7Cu2xAsE21ZUGRyIiltQDgh/Kt5tmuyES0sSKqyvpDnFTJv lEyURT5JQMY+5XDQ3LFqFDSHlrtmVPLIzKc0OZqGne0xIpGtM12fj0Zv8IAvfzSYzcg0 9Uab/x8qPHEQwXy0xZ35ltGuBhs3jxiRuf9yksdXIuXUGST6F9S9c/JH7mdNAr2Dc6FK j/zBAvloqpza0OavffT0JC29z5mjr/x4plcVZ2Y+jA0MGVFPeA5WLLzulVNa037P9FkG my3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685748784; x=1688340784; 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:message-id :reply-to; bh=88IydSMT3h4MdgZedrdgoEtngKl/WmRfHDWOuNscQw8=; b=P4kRvwNvtcIXi7CdkM8AUPYRzPi1ocDj0fD/Z6VWBXFw2dXct0qsXUnteg7i+7I5PJ mNKwvuAOJtgjLH1OeUIjOMWcGGVUbpZ7pcNBvbALkLoY03L4f4sizwz4Dz7mL4TISMoq xxymzU0+UBK2UUYASOqmxukZ5w/GEkhl8Q2CtrF2hBU5Ebz8BtiIiVDWeckFCS3cyjhp VwOrWvU+gpz2nzobcjUBRFx3eGTeleDHDVHV7HX9sOasVWtp2h/sSmeu3Vjt6lrbdCNz WN9LX1xIJv5dc1ibI5zQFqGH92qeuZcWehCgNRhcjlfD1qaZF6ZRoo8AseaeBPbLY2tN iFew== X-Gm-Message-State: AC+VfDzkL4yIDqRd4p0CPDVD3qSAE4GwV3EMAjMb8yYaRMetkyWQvDJJ XS9bfDolES4hAW00Yb1MJl8A4QjRUXE= X-Google-Smtp-Source: ACHHUZ7vfJ8zCT20X9/IDVE+rN7mR0ic3gV08hpng76/5pSSylpcXLraoJZN3YaFhwOSc1g/rHyzyPnzIek= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a05:6a00:2e24:b0:64d:2cb0:c60c with SMTP id fc36-20020a056a002e2400b0064d2cb0c60cmr5046418pfb.5.1685748784040; Fri, 02 Jun 2023 16:33:04 -0700 (PDT) Reply-To: Sean Christopherson Date: Fri, 2 Jun 2023 16:32:48 -0700 In-Reply-To: <20230602233250.1014316-1-seanjc@google.com> Mime-Version: 1.0 References: <20230602233250.1014316-1-seanjc@google.com> X-Mailer: git-send-email 2.41.0.rc2.161.g9c6817b8e7-goog Message-ID: <20230602233250.1014316-2-seanjc@google.com> Subject: [PATCH v3 1/3] KVM: x86: Bail from kvm_recalculate_phys_map() if x2APIC ID is out-of-bounds From: Sean Christopherson To: Sean Christopherson , Paolo Bonzini Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Michal Luczaj Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Bail from kvm_recalculate_phys_map() and disable the optimized map if the target vCPU's x2APIC ID is out-of-bounds, i.e. if the vCPU was added and/or enabled its local APIC after the map was allocated. This fixes an out-of-bounds access bug in the !x2apic_format path where KVM would write beyond the end of phys_map. Check the x2APIC ID regardless of whether or not x2APIC is enabled, as KVM's hardcodes x2APIC ID to be the vCPU ID, i.e. it can't change, and the map allocation in kvm_recalculate_apic_map() doesn't check for x2APIC being enabled, i.e. the check won't get false postivies. Note, this also affects the x2apic_format path, which previously just ignored the "x2apic_id > new->max_apic_id" case. That too is arguably a bug fix, as ignoring the vCPU meant that KVM would not send interrupts to the vCPU until the next map recalculation. In practice, that "bug" is likely benign as a newly present vCPU/APIC would immediately trigger a recalc. But, there's no functional downside to disabling the map, and a future patch will gracefully handle the -E2BIG case by retrying instead of simply disabling the optimized map. Opportunistically add a sanity check on the xAPIC ID size, along with a comment explaining why the xAPIC ID is guaranteed to be "good". Reported-by: Michal Luczaj Signed-off-by: Sean Christopherson --- arch/x86/kvm/lapic.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index e542cf285b51..3c300a196bdf 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -228,6 +228,23 @@ static int kvm_recalculate_phys_map(struct kvm_apic_ma= p *new, u32 xapic_id =3D kvm_xapic_id(apic); u32 physical_id; =20 + /* + * For simplicity, KVM always allocates enough space for all possible + * xAPIC IDs. Yell, but don't kill the VM, as KVM can continue on + * without the optimized map. + */ + if (WARN_ON_ONCE(xapic_id > new->max_apic_id)) + return -EINVAL; + + /* + * Bail if a vCPU was added and/or enabled its APIC between allocating + * the map and doing the actual calculations for the map. Note, KVM + * hardcodes the x2APIC ID to vcpu_id, i.e. there's no TOCTOU bug if + * the compiler decides to reload x2apic_id after this check. + */ + if (x2apic_id > new->max_apic_id) + return -E2BIG; + /* * Deliberately truncate the vCPU ID when detecting a mismatched APIC * ID to avoid false positives if the vCPU ID, i.e. x2APIC ID, is a @@ -253,8 +270,7 @@ static int kvm_recalculate_phys_map(struct kvm_apic_map= *new, */ if (vcpu->kvm->arch.x2apic_format) { /* See also kvm_apic_match_physical_addr(). */ - if ((apic_x2apic_mode(apic) || x2apic_id > 0xff) && - x2apic_id <=3D new->max_apic_id) + if (apic_x2apic_mode(apic) || x2apic_id > 0xff) new->phys_map[x2apic_id] =3D apic; =20 if (!apic_x2apic_mode(apic) && !new->phys_map[xapic_id]) --=20 2.41.0.rc2.161.g9c6817b8e7-goog From nobody Fri May 3 21:23:23 2024 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 5DF0AC7EE2C for ; Fri, 2 Jun 2023 23:33:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236854AbjFBXdM (ORCPT ); Fri, 2 Jun 2023 19:33:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49710 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236840AbjFBXdI (ORCPT ); Fri, 2 Jun 2023 19:33:08 -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 9E1F219A for ; Fri, 2 Jun 2023 16:33:06 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-568a85f180dso36615147b3.2 for ; Fri, 02 Jun 2023 16:33:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1685748786; x=1688340786; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date:message-id:reply-to; bh=5mmxUWbNXCWcSKNxzb01KGCvCtOMb6rFR6D6MsiL8rA=; b=WoUEDQ5ddpi/oFfFOoBl18AoWb3GZ6rToUETa/0Sz/BJfgDYlktlML5eoKlq8u2Q+b cJBMCzxzbFBhmCaWyqTLD5b0MQi2Jlt1+Kpxpv361mlWS0fDkbi1Rtp2WT2kll/jgEpj SM+NEGAGmxKHxnlV9fh5xrJrX3GDHlJMqu5i9oE/iA0gyEOavlMdewoDkXKnwtI7A6/R OxdeBopFScxg8WK+70Qfe2uf1umiJQnX9VSojaJyXdwFYW/J0IH/OCOoMUiXgqnjZHQ2 gkU79mN3ZyosGJCBIAKfydsc54p2hbMO9A4vGUy1JsMKsCSeU+Bn4Utgm3+4y1q1438/ dj1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685748786; x=1688340786; 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:message-id :reply-to; bh=5mmxUWbNXCWcSKNxzb01KGCvCtOMb6rFR6D6MsiL8rA=; b=gBVj+iBj28kzFvpQfHLq2uckiNEzUwmxnp/+/O5mxYxIpVmofAn0i+QLZA/lhJbR+L jTuqB+cmwgCjRdKlBJJ3vAi3Zia6IiVXEBL/j8rn7OciY4TwTSYmbESC7hnva3pE3d0F BSbXuipWVZhOftO66yGNO78gxyd0oOfWY6OTfmmsjbg3fqGdJXK6KGHvuBS0pugUwdQd 8rEvk0ULUOxTak9hTbwNiv6TSxIQBqP9eg6j4l/Q3hnwvzqY7e4NI+wsP6OBReKK7Bm9 JAPNOHSBUdPq55Q1inrmwH4FUWrn0EXVvYHYnYsnX783CxZoCkNJ9bXnDK7IiNKzPeFP VTnw== X-Gm-Message-State: AC+VfDymgEwpbPF2BvqJmD5U6kqAt3/RRKsclfKyx5v+1pC+O2rEi8fM JjI5abadh26JlFvO0aeu6r+6sOIUGQc= X-Google-Smtp-Source: ACHHUZ5bEUhJdYvxdgTGwYML3221yKwmF2F7wPtdS+NYUy73iU2lQAxLNanRUxKSXSJRKxQ+GUPwQjaL14g= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a81:ac06:0:b0:561:8e86:9818 with SMTP id k6-20020a81ac06000000b005618e869818mr629972ywh.7.1685748785936; Fri, 02 Jun 2023 16:33:05 -0700 (PDT) Reply-To: Sean Christopherson Date: Fri, 2 Jun 2023 16:32:49 -0700 In-Reply-To: <20230602233250.1014316-1-seanjc@google.com> Mime-Version: 1.0 References: <20230602233250.1014316-1-seanjc@google.com> X-Mailer: git-send-email 2.41.0.rc2.161.g9c6817b8e7-goog Message-ID: <20230602233250.1014316-3-seanjc@google.com> Subject: [PATCH v3 2/3] KVM: x86: Retry APIC optimized map recalc if vCPU is added/enabled From: Sean Christopherson To: Sean Christopherson , Paolo Bonzini Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Michal Luczaj Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Retry the optimized APIC map recalculation if an APIC-enabled vCPU shows up between allocating the map and filling in the map data. Conditionally reschedule before retrying even though the number of vCPUs that can be created is bounded by KVM. Retrying a few thousand times isn't so slow as to be hugely problematic, but it's not blazing fast either. Reset xapic_id_mistach on each retry as a vCPU could change its xAPIC ID between loops, but do NOT reset max_id. The map size also factors in whether or not a vCPU's local APIC is hardware-enabled, i.e. userspace and/or the guest can theoretically keep KVM retrying indefinitely. The only downside is that KVM will allocate more memory than is strictly necessary if the vCPU with the highest x2APIC ID disabled its APIC while the recalculation was in-progress. Refresh kvm->arch.apic_map_dirty to opportunistically change it from DIRTY =3D> UPDATE_IN_PROGRESS to avoid an unnecessary recalc from a different task, i.e. if another task is waiting to attempt an update (which is likely since a retry happens if and only if an update is required). Signed-off-by: Sean Christopherson --- arch/x86/kvm/lapic.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 3c300a196bdf..cadeaba25e65 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -381,7 +381,8 @@ void kvm_recalculate_apic_map(struct kvm *kvm) struct kvm_vcpu *vcpu; unsigned long i; u32 max_id =3D 255; /* enough space for any xAPIC ID */ - bool xapic_id_mismatch =3D false; + bool xapic_id_mismatch; + int r; =20 /* Read kvm->arch.apic_map_dirty before kvm->arch.apic_map. */ if (atomic_read_acquire(&kvm->arch.apic_map_dirty) =3D=3D CLEAN) @@ -391,9 +392,14 @@ void kvm_recalculate_apic_map(struct kvm *kvm) "Dirty APIC map without an in-kernel local APIC"); =20 mutex_lock(&kvm->arch.apic_map_lock); + +retry: /* - * Read kvm->arch.apic_map_dirty before kvm->arch.apic_map - * (if clean) or the APIC registers (if dirty). + * Read kvm->arch.apic_map_dirty before kvm->arch.apic_map (if clean) + * or the APIC registers (if dirty). Note, on retry the map may have + * not yet been marked dirty by whatever task changed a vCPU's x2APIC + * ID, i.e. the map may still show up as in-progress. In that case + * this task still needs to retry and copmlete its calculation. */ if (atomic_cmpxchg_acquire(&kvm->arch.apic_map_dirty, DIRTY, UPDATE_IN_PROGRESS) =3D=3D CLEAN) { @@ -402,6 +408,15 @@ void kvm_recalculate_apic_map(struct kvm *kvm) return; } =20 + /* + * Reset the mismatch flag between attempts so that KVM does the right + * thing if a vCPU changes its xAPIC ID, but do NOT reset max_id, i.e. + * keep max_id strictly increasing. Disallowing max_id from shrinking + * ensures KVM won't get stuck in an infinite loop, e.g. if the vCPU + * with the highest x2APIC ID is toggling its APIC on and off. + */ + xapic_id_mismatch =3D false; + kvm_for_each_vcpu(i, vcpu, kvm) if (kvm_apic_present(vcpu)) max_id =3D max(max_id, kvm_x2apic_id(vcpu->arch.apic)); @@ -420,9 +435,15 @@ void kvm_recalculate_apic_map(struct kvm *kvm) if (!kvm_apic_present(vcpu)) continue; =20 - if (kvm_recalculate_phys_map(new, vcpu, &xapic_id_mismatch)) { + r =3D kvm_recalculate_phys_map(new, vcpu, &xapic_id_mismatch); + if (r) { kvfree(new); new =3D NULL; + if (r =3D=3D -E2BIG) { + cond_resched(); + goto retry; + } + goto out; } =20 --=20 2.41.0.rc2.161.g9c6817b8e7-goog From nobody Fri May 3 21:23:23 2024 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 0C081C7EE2E for ; Fri, 2 Jun 2023 23:33:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236904AbjFBXdR (ORCPT ); Fri, 2 Jun 2023 19:33:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49724 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236871AbjFBXdJ (ORCPT ); Fri, 2 Jun 2023 19:33:09 -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 81025E43 for ; Fri, 2 Jun 2023 16:33:08 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id 41be03b00d2f7-5343c1d114cso2557611a12.0 for ; Fri, 02 Jun 2023 16:33:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1685748788; x=1688340788; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date:message-id:reply-to; bh=j6nYf/jOBntGS2igA5vSyIxcer0Y2dnZYEhcRt0bNGM=; b=Wi3H0k9BpFJWJAoAjhZGH+/ORYMPc9rbgUFp0V7StYibnfR5Xj/2eL6uRo+vy2ORjC t7IhWOLboZOtaFGAZUE5ovIvkiLsDV+67SAoJ01MJRK09U02fJoLAa4AUpOGsfC1kS7P +hjP1kmcc8hDU9rMT9LiNwBTg5BYbmCeWKvHScZv9HRM/kblDg9yNpxucaTAI3D5S7nI jQFbapqcnP3k3m32lzqRcCZH4s+IoewCx1fJp3P83YZ2/GpgKpGBLg6fcwxRiNZHIxPk 9nAJ5vbHtv8f6sqcuBQySNHOow5IdMVwxGuFB065jqUKW3dyVjnL9DouUtA0ENGMulPM nIDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685748788; x=1688340788; 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:message-id :reply-to; bh=j6nYf/jOBntGS2igA5vSyIxcer0Y2dnZYEhcRt0bNGM=; b=OTDlYrlLmEmbYHUUpY6Idu59r0Bd/ko7S+r+rGWUPnj54TgR5GN8Uqig93EY0Aylbp PcUMXVUI6U+29wIcq27JI81JtXLi5WV2QDBcIGIusIp9t8wrJI8/AEpDKtzwJHeK+zuX kKkwTLE8lyMNIqdVEptcT1qE7SAcB8568y5qdY/ATJwRo0m3nepsUjGnbgFG7vWAOXH9 y6AKHF03neVgdApFZNl/dU40OVgUyd/i24Anf9W/LXlTqtueES0Op5LcwpcFZm0Sw5cw NaYwNKB1vZ4WNfFvrrwboBN+jzQk4qoSCj5fAh0ojUQ6XndXSBKxIWt6rJ0XY5oUEzDH lSvg== X-Gm-Message-State: AC+VfDyT9/rnVNu11ljd+5rMsj886QtOahF9YqHCnn+rttegiYlTHYfK hGUENARuiRg0TFK4FvXW2KvZwqLse3o= X-Google-Smtp-Source: ACHHUZ5RQW9bPamlFEzYIenvVcUlgxBxW5xO/KEOYWb6HOpyK20P4kwc3nv+mQDuMb0Bq7zPa45xizLoZzA= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a65:4284:0:b0:542:96b5:b5e4 with SMTP id j4-20020a654284000000b0054296b5b5e4mr648446pgp.11.1685748787993; Fri, 02 Jun 2023 16:33:07 -0700 (PDT) Reply-To: Sean Christopherson Date: Fri, 2 Jun 2023 16:32:50 -0700 In-Reply-To: <20230602233250.1014316-1-seanjc@google.com> Mime-Version: 1.0 References: <20230602233250.1014316-1-seanjc@google.com> X-Mailer: git-send-email 2.41.0.rc2.161.g9c6817b8e7-goog Message-ID: <20230602233250.1014316-4-seanjc@google.com> Subject: [PATCH v3 3/3] KVM: selftests: Add test for race in kvm_recalculate_apic_map() From: Sean Christopherson To: Sean Christopherson , Paolo Bonzini Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Michal Luczaj Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Michal Luczaj Keep switching between LAPIC_MODE_X2APIC and LAPIC_MODE_DISABLED during APIC map construction to hunt for TOCTOU bugs in KVM. KVM's optimized map recalc makes multiple passes over the list of vCPUs, and the calculations ignore vCPU's whose APIC is hardware-disabled, i.e. there's a window where toggling LAPIC_MODE_DISABLED is quite interesting. Signed-off-by: Michal Luczaj Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson --- tools/testing/selftests/kvm/Makefile | 1 + .../kvm/x86_64/recalc_apic_map_test.c | 74 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/recalc_apic_map_test= .c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests= /kvm/Makefile index 7a5ff646e7e7..4761b768b773 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -116,6 +116,7 @@ TEST_GEN_PROGS_x86_64 +=3D x86_64/sev_migrate_tests TEST_GEN_PROGS_x86_64 +=3D x86_64/amx_test TEST_GEN_PROGS_x86_64 +=3D x86_64/max_vcpuid_cap_test TEST_GEN_PROGS_x86_64 +=3D x86_64/triple_fault_event_test +TEST_GEN_PROGS_x86_64 +=3D x86_64/recalc_apic_map_test TEST_GEN_PROGS_x86_64 +=3D access_tracking_perf_test TEST_GEN_PROGS_x86_64 +=3D demand_paging_test TEST_GEN_PROGS_x86_64 +=3D dirty_log_test diff --git a/tools/testing/selftests/kvm/x86_64/recalc_apic_map_test.c b/to= ols/testing/selftests/kvm/x86_64/recalc_apic_map_test.c new file mode 100644 index 000000000000..4c416ebe7d66 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/recalc_apic_map_test.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Test edge cases and race conditions in kvm_recalculate_apic_map(). + */ + +#include +#include +#include + +#include "processor.h" +#include "test_util.h" +#include "kvm_util.h" +#include "apic.h" + +#define TIMEOUT 5 /* seconds */ + +#define LAPIC_DISABLED 0 +#define LAPIC_X2APIC (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE) +#define MAX_XAPIC_ID 0xff + +static void *race(void *arg) +{ + struct kvm_lapic_state lapic =3D {}; + struct kvm_vcpu *vcpu =3D arg; + + while (1) { + /* Trigger kvm_recalculate_apic_map(). */ + vcpu_ioctl(vcpu, KVM_SET_LAPIC, &lapic); + pthread_testcancel(); + } + + return NULL; +} + +int main(void) +{ + struct kvm_vcpu *vcpus[KVM_MAX_VCPUS]; + struct kvm_vcpu *vcpuN; + struct kvm_vm *vm; + pthread_t thread; + time_t t; + int i; + + kvm_static_assert(KVM_MAX_VCPUS > MAX_XAPIC_ID); + + /* + * Create the max number of vCPUs supported by selftests so that KVM + * has decent amount of work to do when recalculating the map, i.e. to + * make the problematic window large enough to hit. + */ + vm =3D vm_create_with_vcpus(KVM_MAX_VCPUS, NULL, vcpus); + + /* + * Enable x2APIC on all vCPUs so that KVM doesn't bail from the recalc + * due to vCPUs having aliased xAPIC IDs (truncated to 8 bits). + */ + for (i =3D 0; i < KVM_MAX_VCPUS; i++) + vcpu_set_msr(vcpus[i], MSR_IA32_APICBASE, LAPIC_X2APIC); + + ASSERT_EQ(pthread_create(&thread, NULL, race, vcpus[0]), 0); + + vcpuN =3D vcpus[KVM_MAX_VCPUS - 1]; + for (t =3D time(NULL) + TIMEOUT; time(NULL) < t;) { + vcpu_set_msr(vcpuN, MSR_IA32_APICBASE, LAPIC_X2APIC); + vcpu_set_msr(vcpuN, MSR_IA32_APICBASE, LAPIC_DISABLED); + } + + ASSERT_EQ(pthread_cancel(thread), 0); + ASSERT_EQ(pthread_join(thread, NULL), 0); + + kvm_vm_free(vm); + + return 0; +} --=20 2.41.0.rc2.161.g9c6817b8e7-goog