Re: [PATCH 3/3] KVM: selftests: Add test for race in kvm_recalculate_apic_map()

Michal Luczaj
2023-05-28T17:27:01Z

On 5/27/23 01:40, Sean Christopherson wrote:
> All of these open coded ioctl() calls is unnecessary. Ditto for the fancy
> stuffing, which through trial and error I discovered is done to avoid having
> vCPUs with aliased xAPIC IDs, which would cause KVM to bail before triggering
> the bug. It's much easier to just create the max number of vCPUs and enable
> x2APIC on all of them.
> ...

Yup, this looks way better, thanks.
(FWIW, the #defines were deliberately named to match enum lapic_mode.)

In somewhat related news, I've hit kvm_recalculate_logical_map()'s
WARN_ON_ONCE(ldr != kvm_apic_calc_x2apic_ldr(kvm_x2apic_id(apic))):

[ 464.081627] WARNING: CPU: 2 PID: 958 at arch/x86/kvm/lapic.c:331 kvm_recalculate_apic_map+0x609/0xa00 [kvm]
[ 464.081703] Modules linked in: kvm_intel 9p fscache netfs qrtr sunrpc intel_rapl_msr kvm 9pnet_virtio 9pnet intel_rapl_common rapl pcspkr i2c_piix4 drm zram crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel ata_generic serio_raw virtio_blk virtio_console pata_acpi fuse qemu_fw_cfg [last unloaded: kvm_intel]
[ 464.081778] CPU: 2 PID: 958 Comm: recalc_apic_map Not tainted 6.4.0-rc3-vanilla+ #35
[ 464.081782] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.16.2-1-1 04/01/2014
[ 464.081785] RIP: 0010:kvm_recalculate_apic_map+0x609/0xa00 [kvm]
[ 464.081852] Code: 04 0f 84 00 02 00 00 49 8d 7e 24 e8 b1 2d 13 c1 41 8b 56 24 89 d0 83 e2 0f c1 e8 04 c1 e0 10 0f ab d0 39 e8 0f 84 50 fe ff ff <0f> 0b e9 49 fe ff ff 4c 8d a5 b0 02 00 00 4c 89 e7 e8 a1 2e 13 c1
[ 464.081855] RSP: 0018:ffffc900015cf6c8 EFLAGS: 00010297
[ 464.081860] RAX: 0000000000000001 RBX: ffff888108bb3c00 RCX: dffffc0000000000
[ 464.081863] RDX: 0000000000000000 RSI: ffffffffc04875ef RDI: ffff888178a651a4
[ 464.081865] RBP: 0000000000000002 R08: 0000000000000000 R09: ffffffff8446e2e7
[ 464.081868] R10: fffffbfff088dc5c R11: 0000000000000000 R12: 0000000000000000
[ 464.081870] R13: 0000000000000003 R14: ffff888178a65180 R15: ffff8881131b2000
[ 464.081873] FS: 00007fade8a9a740(0000) GS:ffff8883eef00000(0000) knlGS:0000000000000000
[ 464.081876] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 464.081879] CR2: 00007fade88d0008 CR3: 000000014d68b000 CR4: 0000000000752ee0
[ 464.081883] PKRU: 55555554
[ 464.081886] Call Trace:
[ 464.081888] <TASK>
[ 464.081901] ? kvm_can_use_hv_timer+0x60/0x60 [kvm]
[ 464.081969] ? queue_delayed_work_on+0x6c/0xa0
[ 464.081978] kvm_apic_set_state+0x1cf/0x5b0 [kvm]
[ 464.082050] kvm_arch_vcpu_ioctl+0x1806/0x2100 [kvm]
[ 464.082116] ? kvm_arch_vcpu_put+0x410/0x410 [kvm]
[ 464.082180] ? mark_lock+0xf4/0xce0
[ 464.082185] ? kvm_arch_vcpu_put+0x410/0x410 [kvm]
[ 464.082251] ? mark_lock+0xf4/0xce0
[ 464.082255] ? preempt_count_sub+0x14/0xc0
[ 464.082263] ? print_usage_bug.part.0+0x3b0/0x3b0
[ 464.082269] ? kvm_arch_vcpu_put+0x410/0x410 [kvm]
[ 464.082363] ? mark_lock+0xf4/0xce0
[ 464.082369] ? __kernel_text_address+0xe/0x30
[ 464.082373] ? unwind_get_return_address+0x2f/0x50
[ 464.082382] ? print_usage_bug.part.0+0x3b0/0x3b0
[ 464.082392] ? __lock_acquire+0x9ed/0x3210
[ 464.082404] ? lockdep_hardirqs_on_prepare+0x220/0x220
[ 464.082410] ? lockdep_hardirqs_on_prepare+0x220/0x220
[ 464.082420] ? lock_acquire+0x159/0x3b0
[ 464.082426] ? lock_acquire+0x169/0x3b0
[ 464.082432] ? lock_sync+0x110/0x110
[ 464.082438] ? find_held_lock+0x83/0xa0
[ 464.082444] ? lock_release+0x214/0x3a0
[ 464.082448] ? kvm_vcpu_ioctl+0x1c6/0x8a0 [kvm]
[ 464.082507] ? rcu_is_watching+0x34/0x50
[ 464.082524] ? preempt_count_sub+0x14/0xc0
[ 464.082527] ? __mutex_lock+0x201/0x1040
[ 464.082532] ? kvm_vcpu_ioctl+0x13a/0x8a0 [kvm]
[ 464.082586] ? find_held_lock+0x83/0xa0
[ 464.082591] ? kvm_vcpu_ioctl+0x13a/0x8a0 [kvm]
[ 464.082648] ? mutex_lock_io_nested+0xe40/0xe40
[ 464.082652] ? bit_wait_io_timeout+0xc0/0xc0
[ 464.082658] ? kvm_vcpu_ioctl+0x13a/0x8a0 [kvm]
[ 464.082720] ? kvm_vcpu_ioctl+0x663/0x8a0 [kvm]
[ 464.082774] kvm_vcpu_ioctl+0x663/0x8a0 [kvm]
[ 464.082831] ? kvm_vcpu_kick+0x200/0x200 [kvm]
[ 464.082884] ? vfs_fileattr_set+0x480/0x480
[ 464.082889] ? vfs_fileattr_set+0x480/0x480
[ 464.082893] ? rcu_is_watching+0x34/0x50
[ 464.082897] ? kfree+0x107/0x140
[ 464.082902] ? kvm_vcpu_ioctl+0x1d6/0x8a0 [kvm]
[ 464.082955] ? ioctl_has_perm.constprop.0.isra.0+0x133/0x1f0
[ 464.082961] ? ioctl_has_perm.constprop.0.isra.0+0x133/0x1f0
[ 464.082967] ? selinux_bprm_creds_for_exec+0x440/0x440
[ 464.082988] __x64_sys_ioctl+0xb8/0xf0
[ 464.082994] do_syscall_64+0x56/0x80
[ 464.083000] ? mark_held_locks+0x1a/0x80
[ 464.083007] ? do_syscall_64+0x62/0x80
[ 464.083011] ? lockdep_hardirqs_on+0x7d/0x100
[ 464.083015] ? do_syscall_64+0x62/0x80
[ 464.083019] ? lockdep_hardirqs_on+0x7d/0x100
[ 464.083023] entry_SYSCALL_64_after_hwframe+0x46/0xb0
[ 464.083027] RIP: 0033:0x7fade8b9dd6f
[ 464.083031] Code: 00 48 89 44 24 18 31 c0 48 8d 44 24 60 c7 04 24 10 00 00 00 48 89 44 24 08 48 8d 44 24 20 48 89 44 24 10 b8 10 00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 18 48 8b 44 24 18 64 48 2b 04 25 28 00 00
[ 464.083034] RSP: 002b:00007ffffd2d4550 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
[ 464.083038] RAX: ffffffffffffffda RBX: 00007ffffd2d4ae8 RCX: 00007fade8b9dd6f
[ 464.083041] RDX: 00007ffffd2d45c0 RSI: 000000004400ae8f RDI: 0000000000000005
[ 464.083044] RBP: 0000000000000001 R08: 00000000004150a8 R09: 0000000000415004
[ 464.083047] R10: 0000000002268301 R11: 0000000000000246 R12: 00000000022662a0
[ 464.083050] R13: 00007ffffd2d4af8 R14: 0000000000421df0 R15: 00007fade8cc0000
[ 464.083064] </TASK>
[ 464.083066] irq event stamp: 22889
[ 464.083069] hardirqs last enabled at (22895): [<ffffffff81234ede>] __up_console_sem+0x5e/0x70
[ 464.083073] hardirqs last disabled at (22900): [<ffffffff81234ec3>] __up_console_sem+0x43/0x70
[ 464.083077] softirqs last enabled at (22184): [<ffffffff811538cf>] __irq_exit_rcu+0xdf/0x1b0
[ 464.083082] softirqs last disabled at (22077): [<ffffffff811538cf>] __irq_exit_rcu+0xdf/0x1b0

diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index c9b8f16fb23f..1c7f9cf51998 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -117,6 +117,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/amx_test
TEST_GEN_PROGS_x86_64 += x86_64/max_vcpuid_cap_test
TEST_GEN_PROGS_x86_64 += x86_64/triple_fault_event_test
TEST_GEN_PROGS_x86_64 += x86_64/recalc_apic_map_race
+TEST_GEN_PROGS_x86_64 += x86_64/recalc_apic_map_warn
TEST_GEN_PROGS_x86_64 += access_tracking_perf_test
TEST_GEN_PROGS_x86_64 += demand_paging_test
TEST_GEN_PROGS_x86_64 += dirty_log_test
diff --git a/tools/testing/selftests/kvm/x86_64/recalc_apic_map_warn.c b/tools/testing/selftests/kvm/x86_64/recalc_apic_map_warn.c
new file mode 100644
index 000000000000..2845e1d9b865
--- /dev/null
+++ b/tools/testing/selftests/kvm/x86_64/recalc_apic_map_warn.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * recalc_apic_map_warn
+ *
+ * Test for hitting WARN_ON_ONCE() in kvm_recalculate_logical_map().
+ */
+
+#include "processor.h"
+#include "kvm_util.h"
+#include "apic.h"
+
+#define LAPIC_X2APIC (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE)
+
+int main(void)
+{
+ struct kvm_lapic_state lapic = {};
+ struct kvm_vcpu *vcpu;
+ struct kvm_vm *vm;
+
+ vm = vm_create_with_one_vcpu(&vcpu, NULL); /* vcpu_id = 0 */
+ vcpu_set_msr(vcpu, MSR_IA32_APICBASE, LAPIC_X2APIC);
+
+ *(u32 *)(lapic.regs + APIC_ID) = 1 << 24; /* != vcpu_id */
+ *(u32 *)(lapic.regs + APIC_SPIV) = APIC_SPIV_APIC_ENABLED;
+ vcpu_ioctl(vcpu, KVM_SET_LAPIC, &lapic);
+
+ kvm_vm_release(vm);
+
+ return 0;
+}