All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Do IRQ move cleanup with a timer instead of an IPI
@ 2023-06-19 23:16 Xin Li
  2023-06-19 23:16 ` [PATCH 1/3] x86/vector: Rename send_cleanup_vector() to vector_schedule_cleanup() Xin Li
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Xin Li @ 2023-06-19 23:16 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, iommu, linux-hyperv,
	linux-perf-users, x86
  Cc: tglx, mingo, bp, dave.hansen, hpa, steve.wahl, mike.travis,
	dimitri.sivanich, russ.anderson, dvhart, andy, joro,
	suravee.suthikulpanit, will, robin.murphy, kys, haiyangz,
	wei.liu, decui, dwmw2, baolu.lu, peterz, acme, mark.rutland,
	alexander.shishkin, jolsa, namhyung, irogers, adrian.hunter,
	xin3.li, seanjc, jiangshanlai, jgg, yangtiezhu

No point to waste a vector for cleaning up the leftovers of a moved
interrupt. Aside of that this must be the lowest priority of all vectors
which makes FRED systems utilizing vectors 0x10-0x1f more complicated
than necessary.

Schedule a timer instead.

Thomas Gleixner (2):
  x86/vector: Rename send_cleanup_vector() to vector_schedule_cleanup()
  x86/vector: Replace IRQ_MOVE_CLEANUP_VECTOR with a timer callback

Xin Li (1):
  tools: Get rid of IRQ_MOVE_CLEANUP_VECTOR from tools

 arch/x86/include/asm/hw_irq.h                 |   4 +-
 arch/x86/include/asm/idtentry.h               |   1 -
 arch/x86/include/asm/irq_vectors.h            |   7 --
 arch/x86/kernel/apic/vector.c                 | 109 ++++++++++++++----
 arch/x86/kernel/idt.c                         |   1 -
 arch/x86/platform/uv/uv_irq.c                 |   2 +-
 drivers/iommu/amd/iommu.c                     |   2 +-
 drivers/iommu/hyperv-iommu.c                  |   4 +-
 drivers/iommu/intel/irq_remapping.c           |   2 +-
 tools/arch/x86/include/asm/irq_vectors.h      |   7 --
 .../beauty/tracepoints/x86_irq_vectors.sh     |   2 +-
 11 files changed, 92 insertions(+), 49 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] x86/vector: Rename send_cleanup_vector() to vector_schedule_cleanup()
  2023-06-19 23:16 [PATCH 0/3] Do IRQ move cleanup with a timer instead of an IPI Xin Li
@ 2023-06-19 23:16 ` Xin Li
  2023-06-20 16:27   ` Steve Wahl
  2023-06-19 23:16 ` [PATCH 2/3] x86/vector: Replace IRQ_MOVE_CLEANUP_VECTOR with a timer callback Xin Li
  2023-06-19 23:16 ` [PATCH 3/3] tools: Get rid of IRQ_MOVE_CLEANUP_VECTOR from tools Xin Li
  2 siblings, 1 reply; 10+ messages in thread
From: Xin Li @ 2023-06-19 23:16 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, iommu, linux-hyperv,
	linux-perf-users, x86
  Cc: tglx, mingo, bp, dave.hansen, hpa, steve.wahl, mike.travis,
	dimitri.sivanich, russ.anderson, dvhart, andy, joro,
	suravee.suthikulpanit, will, robin.murphy, kys, haiyangz,
	wei.liu, decui, dwmw2, baolu.lu, peterz, acme, mark.rutland,
	alexander.shishkin, jolsa, namhyung, irogers, adrian.hunter,
	xin3.li, seanjc, jiangshanlai, jgg, yangtiezhu

From: Thomas Gleixner <tglx@linutronix.de>

Rename send_cleanup_vector() to vector_schedule_cleanup() for the next
patch to replace vector cleanup IPI with a timer callback.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Xin Li <xin3.li@intel.com>
---
 arch/x86/include/asm/hw_irq.h       | 4 ++--
 arch/x86/kernel/apic/vector.c       | 8 ++++----
 arch/x86/platform/uv/uv_irq.c       | 2 +-
 drivers/iommu/amd/iommu.c           | 2 +-
 drivers/iommu/hyperv-iommu.c        | 4 ++--
 drivers/iommu/intel/irq_remapping.c | 2 +-
 6 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index d465ece58151..551829884734 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -97,10 +97,10 @@ extern struct irq_cfg *irqd_cfg(struct irq_data *irq_data);
 extern void lock_vector_lock(void);
 extern void unlock_vector_lock(void);
 #ifdef CONFIG_SMP
-extern void send_cleanup_vector(struct irq_cfg *);
+extern void vector_schedule_cleanup(struct irq_cfg *);
 extern void irq_complete_move(struct irq_cfg *cfg);
 #else
-static inline void send_cleanup_vector(struct irq_cfg *c) { }
+static inline void vector_schedule_cleanup(struct irq_cfg *c) { }
 static inline void irq_complete_move(struct irq_cfg *c) { }
 #endif
 
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index c1efebd27e6c..aa370bd0d933 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -967,7 +967,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_irq_move_cleanup)
 	raw_spin_unlock(&vector_lock);
 }
 
-static void __send_cleanup_vector(struct apic_chip_data *apicd)
+static void __vector_schedule_cleanup(struct apic_chip_data *apicd)
 {
 	unsigned int cpu;
 
@@ -983,13 +983,13 @@ static void __send_cleanup_vector(struct apic_chip_data *apicd)
 	raw_spin_unlock(&vector_lock);
 }
 
-void send_cleanup_vector(struct irq_cfg *cfg)
+void vector_schedule_cleanup(struct irq_cfg *cfg)
 {
 	struct apic_chip_data *apicd;
 
 	apicd = container_of(cfg, struct apic_chip_data, hw_irq_cfg);
 	if (apicd->move_in_progress)
-		__send_cleanup_vector(apicd);
+		__vector_schedule_cleanup(apicd);
 }
 
 void irq_complete_move(struct irq_cfg *cfg)
@@ -1007,7 +1007,7 @@ void irq_complete_move(struct irq_cfg *cfg)
 	 * on the same CPU.
 	 */
 	if (apicd->cpu == smp_processor_id())
-		__send_cleanup_vector(apicd);
+		__vector_schedule_cleanup(apicd);
 }
 
 /*
diff --git a/arch/x86/platform/uv/uv_irq.c b/arch/x86/platform/uv/uv_irq.c
index ee21d6a36a80..4221259a5870 100644
--- a/arch/x86/platform/uv/uv_irq.c
+++ b/arch/x86/platform/uv/uv_irq.c
@@ -58,7 +58,7 @@ uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
 	ret = parent->chip->irq_set_affinity(parent, mask, force);
 	if (ret >= 0) {
 		uv_program_mmr(cfg, data->chip_data);
-		send_cleanup_vector(cfg);
+		vector_schedule_cleanup(cfg);
 	}
 
 	return ret;
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index dc1ec6849775..b5900e70de60 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -3658,7 +3658,7 @@ static int amd_ir_set_affinity(struct irq_data *data,
 	 * at the new destination. So, time to cleanup the previous
 	 * vector allocation.
 	 */
-	send_cleanup_vector(cfg);
+	vector_schedule_cleanup(cfg);
 
 	return IRQ_SET_MASK_OK_DONE;
 }
diff --git a/drivers/iommu/hyperv-iommu.c b/drivers/iommu/hyperv-iommu.c
index 8302db7f783e..8a5c17b97310 100644
--- a/drivers/iommu/hyperv-iommu.c
+++ b/drivers/iommu/hyperv-iommu.c
@@ -51,7 +51,7 @@ static int hyperv_ir_set_affinity(struct irq_data *data,
 	if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)
 		return ret;
 
-	send_cleanup_vector(cfg);
+	vector_schedule_cleanup(cfg);
 
 	return 0;
 }
@@ -257,7 +257,7 @@ static int hyperv_root_ir_set_affinity(struct irq_data *data,
 	if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)
 		return ret;
 
-	send_cleanup_vector(cfg);
+	vector_schedule_cleanup(cfg);
 
 	return 0;
 }
diff --git a/drivers/iommu/intel/irq_remapping.c b/drivers/iommu/intel/irq_remapping.c
index a1b987335b31..55d899f5a14b 100644
--- a/drivers/iommu/intel/irq_remapping.c
+++ b/drivers/iommu/intel/irq_remapping.c
@@ -1180,7 +1180,7 @@ intel_ir_set_affinity(struct irq_data *data, const struct cpumask *mask,
 	 * at the new destination. So, time to cleanup the previous
 	 * vector allocation.
 	 */
-	send_cleanup_vector(cfg);
+	vector_schedule_cleanup(cfg);
 
 	return IRQ_SET_MASK_OK_DONE;
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/3] x86/vector: Replace IRQ_MOVE_CLEANUP_VECTOR with a timer callback
  2023-06-19 23:16 [PATCH 0/3] Do IRQ move cleanup with a timer instead of an IPI Xin Li
  2023-06-19 23:16 ` [PATCH 1/3] x86/vector: Rename send_cleanup_vector() to vector_schedule_cleanup() Xin Li
@ 2023-06-19 23:16 ` Xin Li
  2023-06-20  7:20   ` Peter Zijlstra
  2023-06-20  8:37   ` Thomas Gleixner
  2023-06-19 23:16 ` [PATCH 3/3] tools: Get rid of IRQ_MOVE_CLEANUP_VECTOR from tools Xin Li
  2 siblings, 2 replies; 10+ messages in thread
From: Xin Li @ 2023-06-19 23:16 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, iommu, linux-hyperv,
	linux-perf-users, x86
  Cc: tglx, mingo, bp, dave.hansen, hpa, steve.wahl, mike.travis,
	dimitri.sivanich, russ.anderson, dvhart, andy, joro,
	suravee.suthikulpanit, will, robin.murphy, kys, haiyangz,
	wei.liu, decui, dwmw2, baolu.lu, peterz, acme, mark.rutland,
	alexander.shishkin, jolsa, namhyung, irogers, adrian.hunter,
	xin3.li, seanjc, jiangshanlai, jgg, yangtiezhu

From: Thomas Gleixner <tglx@linutronix.de>

Replace IRQ_MOVE_CLEANUP_VECTOR with a timer callback for cleaning
up the leftovers of a moved interrupt.

The only new job incurred is to do vector cleanup in lapic_offline()
in case the vector cleanup timer has not expired.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Xin Li <xin3.li@intel.com>
---
 arch/x86/include/asm/idtentry.h    |   1 -
 arch/x86/include/asm/irq_vectors.h |   7 --
 arch/x86/kernel/apic/vector.c      | 101 +++++++++++++++++++++++------
 arch/x86/kernel/idt.c              |   1 -
 4 files changed, 80 insertions(+), 30 deletions(-)

diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h
index b241af4ce9b4..cd5c10a74071 100644
--- a/arch/x86/include/asm/idtentry.h
+++ b/arch/x86/include/asm/idtentry.h
@@ -648,7 +648,6 @@ DECLARE_IDTENTRY_SYSVEC(X86_PLATFORM_IPI_VECTOR,	sysvec_x86_platform_ipi);
 
 #ifdef CONFIG_SMP
 DECLARE_IDTENTRY(RESCHEDULE_VECTOR,			sysvec_reschedule_ipi);
-DECLARE_IDTENTRY_SYSVEC(IRQ_MOVE_CLEANUP_VECTOR,	sysvec_irq_move_cleanup);
 DECLARE_IDTENTRY_SYSVEC(REBOOT_VECTOR,			sysvec_reboot);
 DECLARE_IDTENTRY_SYSVEC(CALL_FUNCTION_SINGLE_VECTOR,	sysvec_call_function_single);
 DECLARE_IDTENTRY_SYSVEC(CALL_FUNCTION_VECTOR,		sysvec_call_function);
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index 43dcb9284208..3a19904c2db6 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -35,13 +35,6 @@
  */
 #define FIRST_EXTERNAL_VECTOR		0x20
 
-/*
- * Reserve the lowest usable vector (and hence lowest priority)  0x20 for
- * triggering cleanup after irq migration. 0x21-0x2f will still be used
- * for device interrupts.
- */
-#define IRQ_MOVE_CLEANUP_VECTOR		FIRST_EXTERNAL_VECTOR
-
 #define IA32_SYSCALL_VECTOR		0x80
 
 /*
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index aa370bd0d933..23a3f3b6dd2c 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -44,7 +44,18 @@ static cpumask_var_t vector_searchmask;
 static struct irq_chip lapic_controller;
 static struct irq_matrix *vector_matrix;
 #ifdef CONFIG_SMP
-static DEFINE_PER_CPU(struct hlist_head, cleanup_list);
+
+static void vector_cleanup_callback(struct timer_list *tmr);
+
+struct vector_cleanup {
+	struct hlist_head	head;
+	struct timer_list	timer;
+};
+
+static DEFINE_PER_CPU(struct vector_cleanup, vector_cleanup) = {
+	.head	= HLIST_HEAD_INIT,
+	.timer	= __TIMER_INITIALIZER(vector_cleanup_callback, TIMER_PINNED),
+};
 #endif
 
 void lock_vector_lock(void)
@@ -841,10 +852,21 @@ void lapic_online(void)
 		this_cpu_write(vector_irq[vector], __setup_vector_irq(vector));
 }
 
+static void __vector_cleanup(struct vector_cleanup *cl, bool check_irr);
+
 void lapic_offline(void)
 {
+	struct vector_cleanup *cl = this_cpu_ptr(&vector_cleanup);
+
 	lock_vector_lock();
+
+	/* In case the vector cleanup timer has not expired */
+	__vector_cleanup(cl, false);
+
 	irq_matrix_offline(vector_matrix);
+	WARN_ON_ONCE(try_to_del_timer_sync(&cl->timer) < 0);
+	WARN_ON_ONCE(!hlist_empty(&cl->head));
+
 	unlock_vector_lock();
 }
 
@@ -934,49 +956,86 @@ static void free_moved_vector(struct apic_chip_data *apicd)
 	apicd->move_in_progress = 0;
 }
 
-DEFINE_IDTENTRY_SYSVEC(sysvec_irq_move_cleanup)
+/*
+ * Called with vector_lock held
+ */
+static void __vector_cleanup(struct vector_cleanup *cl, bool check_irr)
 {
-	struct hlist_head *clhead = this_cpu_ptr(&cleanup_list);
 	struct apic_chip_data *apicd;
 	struct hlist_node *tmp;
+	bool rearm = false;
 
-	ack_APIC_irq();
-	/* Prevent vectors vanishing under us */
-	raw_spin_lock(&vector_lock);
-
-	hlist_for_each_entry_safe(apicd, tmp, clhead, clist) {
+	hlist_for_each_entry_safe(apicd, tmp, &cl->head, clist) {
 		unsigned int irr, vector = apicd->prev_vector;
 
 		/*
 		 * Paranoia: Check if the vector that needs to be cleaned
-		 * up is registered at the APICs IRR. If so, then this is
-		 * not the best time to clean it up. Clean it up in the
-		 * next attempt by sending another IRQ_MOVE_CLEANUP_VECTOR
-		 * to this CPU. IRQ_MOVE_CLEANUP_VECTOR is the lowest
-		 * priority external vector, so on return from this
-		 * interrupt the device interrupt will happen first.
+		 * up is registered at the APICs IRR. That's clearly a
+		 * hardware issue if the vector arrived on the old target
+		 * _after_ interrupts were disabled above. Keep @apicd
+		 * on the list and schedule the timer again to give the CPU
+		 * a chance to handle the pending interrupt.
+		 *
+		 * Do not check IRR when called from lapic_offline(), because
+		 * fixup_irqs() was just called to scan IRR for set bits and
+		 * forward them to new destination CPUs via IPIs.
 		 */
-		irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
+		irr = check_irr ? apic_read(APIC_IRR + (vector / 32 * 0x10)) : 0;
 		if (irr & (1U << (vector % 32))) {
-			apic->send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR);
+			pr_warn_once("Moved interrupt pending in old target APIC %u\n", apicd->irq);
+			rearm = true;
 			continue;
 		}
 		free_moved_vector(apicd);
 	}
 
-	raw_spin_unlock(&vector_lock);
+	/*
+	 * Must happen under vector_lock to make the timer_pending() check
+	 * in __vector_schedule_cleanup() race free against the rearm here.
+	 */
+	if (rearm)
+		mod_timer(&cl->timer, jiffies + 1);
+}
+
+static void vector_cleanup_callback(struct timer_list *tmr)
+{
+	struct vector_cleanup *cl = container_of(tmr, typeof(*cl), timer);
+
+	/* Prevent vectors vanishing under us */
+	raw_spin_lock_irq(&vector_lock);
+	__vector_cleanup(cl, true);
+	raw_spin_unlock_irq(&vector_lock);
 }
 
 static void __vector_schedule_cleanup(struct apic_chip_data *apicd)
 {
-	unsigned int cpu;
+	unsigned int cpu = apicd->prev_cpu;
 
 	raw_spin_lock(&vector_lock);
 	apicd->move_in_progress = 0;
-	cpu = apicd->prev_cpu;
 	if (cpu_online(cpu)) {
-		hlist_add_head(&apicd->clist, per_cpu_ptr(&cleanup_list, cpu));
-		apic->send_IPI(cpu, IRQ_MOVE_CLEANUP_VECTOR);
+		struct vector_cleanup *cl = per_cpu_ptr(&vector_cleanup, cpu);
+
+		hlist_add_head(&apicd->clist, &cl->head);
+
+		/*
+		 * The lockless timer_pending() check is safe here. If it
+		 * returns true, then the callback will observe this new
+		 * apic data in the hlist as everything is serialized by
+		 * vector lock.
+		 *
+		 * If it returns false then the timer is either not armed
+		 * or the other CPU executes the callback, which again
+		 * would be blocked on vector lock. Rearming it in the
+		 * latter case makes it fire for nothing.
+		 *
+		 * This is also safe against the callback rearming the timer
+		 * because that's serialized via vector lock too.
+		 */
+		if (!timer_pending(&cl->timer)) {
+			cl->timer.expires = jiffies + 1;
+			add_timer_on(&cl->timer, cpu);
+		}
 	} else {
 		apicd->prev_vector = 0;
 	}
diff --git a/arch/x86/kernel/idt.c b/arch/x86/kernel/idt.c
index a58c6bc1cd68..f3958262c725 100644
--- a/arch/x86/kernel/idt.c
+++ b/arch/x86/kernel/idt.c
@@ -131,7 +131,6 @@ static const __initconst struct idt_data apic_idts[] = {
 	INTG(RESCHEDULE_VECTOR,			asm_sysvec_reschedule_ipi),
 	INTG(CALL_FUNCTION_VECTOR,		asm_sysvec_call_function),
 	INTG(CALL_FUNCTION_SINGLE_VECTOR,	asm_sysvec_call_function_single),
-	INTG(IRQ_MOVE_CLEANUP_VECTOR,		asm_sysvec_irq_move_cleanup),
 	INTG(REBOOT_VECTOR,			asm_sysvec_reboot),
 #endif
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/3] tools: Get rid of IRQ_MOVE_CLEANUP_VECTOR from tools
  2023-06-19 23:16 [PATCH 0/3] Do IRQ move cleanup with a timer instead of an IPI Xin Li
  2023-06-19 23:16 ` [PATCH 1/3] x86/vector: Rename send_cleanup_vector() to vector_schedule_cleanup() Xin Li
  2023-06-19 23:16 ` [PATCH 2/3] x86/vector: Replace IRQ_MOVE_CLEANUP_VECTOR with a timer callback Xin Li
@ 2023-06-19 23:16 ` Xin Li
  2 siblings, 0 replies; 10+ messages in thread
From: Xin Li @ 2023-06-19 23:16 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, iommu, linux-hyperv,
	linux-perf-users, x86
  Cc: tglx, mingo, bp, dave.hansen, hpa, steve.wahl, mike.travis,
	dimitri.sivanich, russ.anderson, dvhart, andy, joro,
	suravee.suthikulpanit, will, robin.murphy, kys, haiyangz,
	wei.liu, decui, dwmw2, baolu.lu, peterz, acme, mark.rutland,
	alexander.shishkin, jolsa, namhyung, irogers, adrian.hunter,
	xin3.li, seanjc, jiangshanlai, jgg, yangtiezhu

Get rid of IRQ_MOVE_CLEANUP_VECTOR from tools.

Signed-off-by: Xin Li <xin3.li@intel.com>
---
 tools/arch/x86/include/asm/irq_vectors.h               | 7 -------
 tools/perf/trace/beauty/tracepoints/x86_irq_vectors.sh | 2 +-
 2 files changed, 1 insertion(+), 8 deletions(-)

diff --git a/tools/arch/x86/include/asm/irq_vectors.h b/tools/arch/x86/include/asm/irq_vectors.h
index 43dcb9284208..3a19904c2db6 100644
--- a/tools/arch/x86/include/asm/irq_vectors.h
+++ b/tools/arch/x86/include/asm/irq_vectors.h
@@ -35,13 +35,6 @@
  */
 #define FIRST_EXTERNAL_VECTOR		0x20
 
-/*
- * Reserve the lowest usable vector (and hence lowest priority)  0x20 for
- * triggering cleanup after irq migration. 0x21-0x2f will still be used
- * for device interrupts.
- */
-#define IRQ_MOVE_CLEANUP_VECTOR		FIRST_EXTERNAL_VECTOR
-
 #define IA32_SYSCALL_VECTOR		0x80
 
 /*
diff --git a/tools/perf/trace/beauty/tracepoints/x86_irq_vectors.sh b/tools/perf/trace/beauty/tracepoints/x86_irq_vectors.sh
index eed9ce0fcbe6..87dc68c7de0c 100755
--- a/tools/perf/trace/beauty/tracepoints/x86_irq_vectors.sh
+++ b/tools/perf/trace/beauty/tracepoints/x86_irq_vectors.sh
@@ -12,7 +12,7 @@ x86_irq_vectors=${arch_x86_header_dir}/irq_vectors.h
 
 # FIRST_EXTERNAL_VECTOR is not that useful, find what is its number
 # and then replace whatever is using it and that is useful, which at
-# the time of writing of this script was: IRQ_MOVE_CLEANUP_VECTOR.
+# the time of writing of this script was: 0x20.
 
 first_external_regex='^#define[[:space:]]+FIRST_EXTERNAL_VECTOR[[:space:]]+(0x[[:xdigit:]]+)$'
 first_external_vector=$(grep -E ${first_external_regex} ${x86_irq_vectors} | sed -r "s/${first_external_regex}/\1/g")
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] x86/vector: Replace IRQ_MOVE_CLEANUP_VECTOR with a timer callback
  2023-06-19 23:16 ` [PATCH 2/3] x86/vector: Replace IRQ_MOVE_CLEANUP_VECTOR with a timer callback Xin Li
@ 2023-06-20  7:20   ` Peter Zijlstra
  2023-06-20  7:47     ` Li, Xin3
  2023-06-20  8:37   ` Thomas Gleixner
  1 sibling, 1 reply; 10+ messages in thread
From: Peter Zijlstra @ 2023-06-20  7:20 UTC (permalink / raw)
  To: Xin Li
  Cc: linux-kernel, platform-driver-x86, iommu, linux-hyperv,
	linux-perf-users, x86, tglx, mingo, bp, dave.hansen, hpa,
	steve.wahl, mike.travis, dimitri.sivanich, russ.anderson, dvhart,
	andy, joro, suravee.suthikulpanit, will, robin.murphy, kys,
	haiyangz, wei.liu, decui, dwmw2, baolu.lu, acme, mark.rutland,
	alexander.shishkin, jolsa, namhyung, irogers, adrian.hunter,
	seanjc, jiangshanlai, jgg, yangtiezhu

On Mon, Jun 19, 2023 at 04:16:10PM -0700, Xin Li wrote:

> +/*
> + * Called with vector_lock held
> + */

Instead of comments like that, I tend to add a lockdep_assert*()
statement to the same effect. Which unlike comment actually validate the
claim and since it's code it tends to not go stale like comments do.

> +static void __vector_cleanup(struct vector_cleanup *cl, bool check_irr)
>  {
>  	struct apic_chip_data *apicd;
>  	struct hlist_node *tmp;
> +	bool rearm = false;

	lockdep_assert_held(&vector_lock);

> +	hlist_for_each_entry_safe(apicd, tmp, &cl->head, clist) {
>  		unsigned int irr, vector = apicd->prev_vector;
>  
>  		/*
>  		 * Paranoia: Check if the vector that needs to be cleaned
> +		 * up is registered at the APICs IRR. That's clearly a
> +		 * hardware issue if the vector arrived on the old target
> +		 * _after_ interrupts were disabled above. Keep @apicd
> +		 * on the list and schedule the timer again to give the CPU
> +		 * a chance to handle the pending interrupt.
> +		 *
> +		 * Do not check IRR when called from lapic_offline(), because
> +		 * fixup_irqs() was just called to scan IRR for set bits and
> +		 * forward them to new destination CPUs via IPIs.
>  		 */
> +		irr = check_irr ? apic_read(APIC_IRR + (vector / 32 * 0x10)) : 0;
>  		if (irr & (1U << (vector % 32))) {
> +			pr_warn_once("Moved interrupt pending in old target APIC %u\n", apicd->irq);
> +			rearm = true;
>  			continue;
>  		}
>  		free_moved_vector(apicd);
>  	}
>  
> +	/*
> +	 * Must happen under vector_lock to make the timer_pending() check
> +	 * in __vector_schedule_cleanup() race free against the rearm here.
> +	 */
> +	if (rearm)
> +		mod_timer(&cl->timer, jiffies + 1);
> +}
> +
> +static void vector_cleanup_callback(struct timer_list *tmr)
> +{
> +	struct vector_cleanup *cl = container_of(tmr, typeof(*cl), timer);
> +
> +	/* Prevent vectors vanishing under us */
> +	raw_spin_lock_irq(&vector_lock);
> +	__vector_cleanup(cl, true);
> +	raw_spin_unlock_irq(&vector_lock);
>  }

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 2/3] x86/vector: Replace IRQ_MOVE_CLEANUP_VECTOR with a timer callback
  2023-06-20  7:20   ` Peter Zijlstra
@ 2023-06-20  7:47     ` Li, Xin3
  0 siblings, 0 replies; 10+ messages in thread
From: Li, Xin3 @ 2023-06-20  7:47 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, platform-driver-x86, iommu, linux-hyperv,
	linux-perf-users, x86, tglx, mingo, bp, dave.hansen, hpa,
	steve.wahl, mike.travis, Sivanich, Dimitri, Anderson, Russ,
	dvhart, andy, joro, suravee.suthikulpanit, will, robin.murphy,
	kys, haiyangz, wei.liu, Cui, Dexuan, dwmw2, baolu.lu, acme,
	mark.rutland, alexander.shishkin, jolsa, namhyung, irogers,
	Hunter, Adrian, Christopherson,,
	Sean, jiangshanlai, jgg, yangtiezhu

> > +/*
> > + * Called with vector_lock held
> > + */
> 
> Instead of comments like that, I tend to add a lockdep_assert*() statement to the
> same effect. Which unlike comment actually validate the claim and since it's code
> it tends to not go stale like comments do.

neat, will do!

> > +	bool rearm = false;
> 
> 	lockdep_assert_held(&vector_lock);

My bad, didn't notice that quite a few functions in the file already do that. 



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] x86/vector: Replace IRQ_MOVE_CLEANUP_VECTOR with a timer callback
  2023-06-19 23:16 ` [PATCH 2/3] x86/vector: Replace IRQ_MOVE_CLEANUP_VECTOR with a timer callback Xin Li
  2023-06-20  7:20   ` Peter Zijlstra
@ 2023-06-20  8:37   ` Thomas Gleixner
  2023-06-20 17:30     ` Li, Xin3
  1 sibling, 1 reply; 10+ messages in thread
From: Thomas Gleixner @ 2023-06-20  8:37 UTC (permalink / raw)
  To: Xin Li, linux-kernel, platform-driver-x86, iommu, linux-hyperv,
	linux-perf-users, x86
  Cc: mingo, bp, dave.hansen, hpa, steve.wahl, mike.travis,
	dimitri.sivanich, russ.anderson, dvhart, andy, joro,
	suravee.suthikulpanit, will, robin.murphy, kys, haiyangz,
	wei.liu, decui, dwmw2, baolu.lu, peterz, acme, mark.rutland,
	alexander.shishkin, jolsa, namhyung, irogers, adrian.hunter,
	xin3.li, seanjc, jiangshanlai, jgg, yangtiezhu

On Mon, Jun 19 2023 at 16:16, Xin Li wrote:
> +/*
> + * Called with vector_lock held
> + */

Such a comment is patently bad. 

> +static void __vector_cleanup(struct vector_cleanup *cl, bool check_irr)
>  {
        ....

        lockdep_assert_held(&vector_lock);

Documents the requirement clearly _and_ catches any caller which does not
hold the lock when lockdep is enabled.

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] x86/vector: Rename send_cleanup_vector() to vector_schedule_cleanup()
  2023-06-19 23:16 ` [PATCH 1/3] x86/vector: Rename send_cleanup_vector() to vector_schedule_cleanup() Xin Li
@ 2023-06-20 16:27   ` Steve Wahl
  2023-06-20 17:33     ` Li, Xin3
  0 siblings, 1 reply; 10+ messages in thread
From: Steve Wahl @ 2023-06-20 16:27 UTC (permalink / raw)
  To: Xin Li
  Cc: linux-kernel, platform-driver-x86, iommu, linux-hyperv,
	linux-perf-users, x86, tglx, mingo, bp, dave.hansen, hpa,
	steve.wahl, dimitri.sivanich, russ.anderson, dvhart, andy, joro,
	suravee.suthikulpanit, will, robin.murphy, kys, haiyangz,
	wei.liu, decui, dwmw2, baolu.lu, peterz, acme, mark.rutland,
	alexander.shishkin, jolsa, namhyung, irogers, adrian.hunter,
	seanjc, jiangshanlai, jgg, yangtiezhu

Reviewed-by: Steve Wahl <steve.wahl@hpe.com>

On Mon, Jun 19, 2023 at 04:16:09PM -0700, Xin Li wrote:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> Rename send_cleanup_vector() to vector_schedule_cleanup() for the next
> patch to replace vector cleanup IPI with a timer callback.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Xin Li <xin3.li@intel.com>
> ---
>  arch/x86/include/asm/hw_irq.h       | 4 ++--
>  arch/x86/kernel/apic/vector.c       | 8 ++++----
>  arch/x86/platform/uv/uv_irq.c       | 2 +-
>  drivers/iommu/amd/iommu.c           | 2 +-
>  drivers/iommu/hyperv-iommu.c        | 4 ++--
>  drivers/iommu/intel/irq_remapping.c | 2 +-
>  6 files changed, 11 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
> index d465ece58151..551829884734 100644
> --- a/arch/x86/include/asm/hw_irq.h
> +++ b/arch/x86/include/asm/hw_irq.h
> @@ -97,10 +97,10 @@ extern struct irq_cfg *irqd_cfg(struct irq_data *irq_data);
>  extern void lock_vector_lock(void);
>  extern void unlock_vector_lock(void);
>  #ifdef CONFIG_SMP
> -extern void send_cleanup_vector(struct irq_cfg *);
> +extern void vector_schedule_cleanup(struct irq_cfg *);
>  extern void irq_complete_move(struct irq_cfg *cfg);
>  #else
> -static inline void send_cleanup_vector(struct irq_cfg *c) { }
> +static inline void vector_schedule_cleanup(struct irq_cfg *c) { }
>  static inline void irq_complete_move(struct irq_cfg *c) { }
>  #endif
>  
> diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
> index c1efebd27e6c..aa370bd0d933 100644
> --- a/arch/x86/kernel/apic/vector.c
> +++ b/arch/x86/kernel/apic/vector.c
> @@ -967,7 +967,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_irq_move_cleanup)
>  	raw_spin_unlock(&vector_lock);
>  }
>  
> -static void __send_cleanup_vector(struct apic_chip_data *apicd)
> +static void __vector_schedule_cleanup(struct apic_chip_data *apicd)
>  {
>  	unsigned int cpu;
>  
> @@ -983,13 +983,13 @@ static void __send_cleanup_vector(struct apic_chip_data *apicd)
>  	raw_spin_unlock(&vector_lock);
>  }
>  
> -void send_cleanup_vector(struct irq_cfg *cfg)
> +void vector_schedule_cleanup(struct irq_cfg *cfg)
>  {
>  	struct apic_chip_data *apicd;
>  
>  	apicd = container_of(cfg, struct apic_chip_data, hw_irq_cfg);
>  	if (apicd->move_in_progress)
> -		__send_cleanup_vector(apicd);
> +		__vector_schedule_cleanup(apicd);
>  }
>  
>  void irq_complete_move(struct irq_cfg *cfg)
> @@ -1007,7 +1007,7 @@ void irq_complete_move(struct irq_cfg *cfg)
>  	 * on the same CPU.
>  	 */
>  	if (apicd->cpu == smp_processor_id())
> -		__send_cleanup_vector(apicd);
> +		__vector_schedule_cleanup(apicd);
>  }
>  
>  /*
> diff --git a/arch/x86/platform/uv/uv_irq.c b/arch/x86/platform/uv/uv_irq.c
> index ee21d6a36a80..4221259a5870 100644
> --- a/arch/x86/platform/uv/uv_irq.c
> +++ b/arch/x86/platform/uv/uv_irq.c
> @@ -58,7 +58,7 @@ uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
>  	ret = parent->chip->irq_set_affinity(parent, mask, force);
>  	if (ret >= 0) {
>  		uv_program_mmr(cfg, data->chip_data);
> -		send_cleanup_vector(cfg);
> +		vector_schedule_cleanup(cfg);
>  	}
>  
>  	return ret;
> diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
> index dc1ec6849775..b5900e70de60 100644
> --- a/drivers/iommu/amd/iommu.c
> +++ b/drivers/iommu/amd/iommu.c
> @@ -3658,7 +3658,7 @@ static int amd_ir_set_affinity(struct irq_data *data,
>  	 * at the new destination. So, time to cleanup the previous
>  	 * vector allocation.
>  	 */
> -	send_cleanup_vector(cfg);
> +	vector_schedule_cleanup(cfg);
>  
>  	return IRQ_SET_MASK_OK_DONE;
>  }
> diff --git a/drivers/iommu/hyperv-iommu.c b/drivers/iommu/hyperv-iommu.c
> index 8302db7f783e..8a5c17b97310 100644
> --- a/drivers/iommu/hyperv-iommu.c
> +++ b/drivers/iommu/hyperv-iommu.c
> @@ -51,7 +51,7 @@ static int hyperv_ir_set_affinity(struct irq_data *data,
>  	if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)
>  		return ret;
>  
> -	send_cleanup_vector(cfg);
> +	vector_schedule_cleanup(cfg);
>  
>  	return 0;
>  }
> @@ -257,7 +257,7 @@ static int hyperv_root_ir_set_affinity(struct irq_data *data,
>  	if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)
>  		return ret;
>  
> -	send_cleanup_vector(cfg);
> +	vector_schedule_cleanup(cfg);
>  
>  	return 0;
>  }
> diff --git a/drivers/iommu/intel/irq_remapping.c b/drivers/iommu/intel/irq_remapping.c
> index a1b987335b31..55d899f5a14b 100644
> --- a/drivers/iommu/intel/irq_remapping.c
> +++ b/drivers/iommu/intel/irq_remapping.c
> @@ -1180,7 +1180,7 @@ intel_ir_set_affinity(struct irq_data *data, const struct cpumask *mask,
>  	 * at the new destination. So, time to cleanup the previous
>  	 * vector allocation.
>  	 */
> -	send_cleanup_vector(cfg);
> +	vector_schedule_cleanup(cfg);
>  
>  	return IRQ_SET_MASK_OK_DONE;
>  }
> -- 
> 2.34.1
> 

-- 
Steve Wahl, Hewlett Packard Enterprise

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 2/3] x86/vector: Replace IRQ_MOVE_CLEANUP_VECTOR with a timer callback
  2023-06-20  8:37   ` Thomas Gleixner
@ 2023-06-20 17:30     ` Li, Xin3
  0 siblings, 0 replies; 10+ messages in thread
From: Li, Xin3 @ 2023-06-20 17:30 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel, platform-driver-x86, iommu,
	linux-hyperv, linux-perf-users, x86
  Cc: mingo, bp, dave.hansen, hpa, steve.wahl, mike.travis, Sivanich,
	Dimitri, Anderson, Russ, dvhart, andy, joro,
	suravee.suthikulpanit, will, robin.murphy, kys, haiyangz,
	wei.liu, Cui, Dexuan, dwmw2, baolu.lu, peterz, acme,
	mark.rutland, alexander.shishkin, jolsa, namhyung, irogers,
	Hunter, Adrian, Christopherson,,
	Sean, jiangshanlai, jgg, yangtiezhu

> > +/*
> > + * Called with vector_lock held
> > + */
> 
> Such a comment is patently bad.
> 
> > +static void __vector_cleanup(struct vector_cleanup *cl, bool
> > +check_irr)
> >  {
>         ....
> 
>         lockdep_assert_held(&vector_lock);
> 
> Documents the requirement clearly _and_ catches any caller which does not hold
> the lock when lockdep is enabled.

Peter Z gave the same comment, I will address in the next iteration.

Thanks!
  Xin

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 1/3] x86/vector: Rename send_cleanup_vector() to vector_schedule_cleanup()
  2023-06-20 16:27   ` Steve Wahl
@ 2023-06-20 17:33     ` Li, Xin3
  0 siblings, 0 replies; 10+ messages in thread
From: Li, Xin3 @ 2023-06-20 17:33 UTC (permalink / raw)
  To: Steve Wahl
  Cc: linux-kernel, platform-driver-x86, iommu, linux-hyperv,
	linux-perf-users, x86, tglx, mingo, bp, dave.hansen, hpa,
	Sivanich, Dimitri, Anderson, Russ, dvhart, andy, joro,
	suravee.suthikulpanit, will, robin.murphy, kys, haiyangz,
	wei.liu, Cui, Dexuan, dwmw2, baolu.lu, peterz, acme,
	mark.rutland, alexander.shishkin, jolsa, namhyung, irogers,
	Hunter, Adrian, Christopherson,,
	Sean, jiangshanlai, jgg, yangtiezhu

> Reviewed-by: Steve Wahl <steve.wahl@hpe.com>

Thanks, will add your RB to this patch in the next iteration.

  Xin

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2023-06-20 17:34 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-19 23:16 [PATCH 0/3] Do IRQ move cleanup with a timer instead of an IPI Xin Li
2023-06-19 23:16 ` [PATCH 1/3] x86/vector: Rename send_cleanup_vector() to vector_schedule_cleanup() Xin Li
2023-06-20 16:27   ` Steve Wahl
2023-06-20 17:33     ` Li, Xin3
2023-06-19 23:16 ` [PATCH 2/3] x86/vector: Replace IRQ_MOVE_CLEANUP_VECTOR with a timer callback Xin Li
2023-06-20  7:20   ` Peter Zijlstra
2023-06-20  7:47     ` Li, Xin3
2023-06-20  8:37   ` Thomas Gleixner
2023-06-20 17:30     ` Li, Xin3
2023-06-19 23:16 ` [PATCH 3/3] tools: Get rid of IRQ_MOVE_CLEANUP_VECTOR from tools Xin Li

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.