From 0696d059f23c05f2dbc3b19ef50e5bdd175b782b Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 16 Oct 2017 16:16:19 +0200 Subject: x86/vector: Use correct per cpu variable in free_moved_vector() free_moved_vector() accesses the per cpu vector array with this_cpu_write() to clear the vector. The function has two call sites: 1) The vector cleanup IPI 2) The force_complete_move() code path For #1 this_cpu_write() is correct as it runs on the CPU on which the vector needs to be freed. For #2 this_cpu_write() is wrong because the function is called from an outgoing CPU which is not necessarily the CPU on which the previous vector needs to be freed. As a result it sets the vector on the outgoing CPU to NULL, which is pointless as that CPU does not handle interrupts anymore. What's worse is that it leaves the vector on the previous target CPU in place which later on triggers the BUG_ON(vector) in the vector allocation code when the vector gets reused. That's possible because the bitmap allocator entry of that CPU is freed correctly. Always use the CPU to which the vector was associated and clear the vector entry on that CPU. Fixup the tracepoint as well so it tracks on which CPU the vector gets removed. Fixes: 69cde0004a4b ("x86/vector: Use matrix allocator for vector assignment") Reported-by: Petri Latvala Signed-off-by: Thomas Gleixner Cc: Juergen Gross Cc: Tony Luck Cc: Len Brown Cc: Marc Zyngier Cc: Joerg Roedel Cc: "Rafael J. Wysocki" Cc: Steven Rostedt Cc: Christoph Hellwig Cc: Peter Zijlstra Cc: Rui Zhang Cc: Borislav Petkov Cc: Paolo Bonzini Cc: Boris Ostrovsky Cc: "K. Y. Srinivasan" Cc: Arjan van de Ven Cc: Alok Kataria Cc: Dan Williams Cc: Yu Chen Link: https://lkml.kernel.org/r/alpine.DEB.2.20.1710161614430.1973@nanos --- arch/x86/kernel/apic/vector.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86/kernel/apic/vector.c') diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 573538e0981e..05c85e693a5d 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -797,9 +797,9 @@ static void free_moved_vector(struct apic_chip_data *apicd) */ WARN_ON_ONCE(managed); - trace_vector_free_moved(apicd->irq, vector, managed); + trace_vector_free_moved(apicd->irq, cpu, vector, managed); irq_matrix_free(vector_matrix, cpu, vector, managed); - __this_cpu_write(vector_irq[vector], VECTOR_UNUSED); + per_cpu(vector_irq, cpu)[vector] = VECTOR_UNUSED; hlist_del_init(&apicd->clist); apicd->prev_vector = 0; apicd->move_in_progress = 0; -- cgit