linux-perf-users.vger.kernel.org archive mirror
 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@vger.kernel.org, platform-driver-x86@vger.kernel.org,
	iommu@lists.linux.dev, linux-hyperv@vger.kernel.org,
	linux-perf-users@vger.kernel.org, x86@kernel.org,
	tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
	dave.hansen@linux.intel.com, hpa@zytor.com, steve.wahl@hpe.com,
	mike.travis@hpe.com, Sivanich, Dimitri, Anderson, Russ,
	dvhart@infradead.org, andy@infradead.org, joro@8bytes.org,
	suravee.suthikulpanit@amd.com, will@kernel.org,
	robin.murphy@arm.com, kys@microsoft.com, haiyangz@microsoft.com,
	wei.liu@kernel.org, Cui, Dexuan, dwmw2@infradead.org,
	baolu.lu@linux.intel.com, acme@kernel.org, mark.rutland@arm.com,
	alexander.shishkin@linux.intel.com, jolsa@kernel.org,
	namhyung@kernel.org, irogers@google.com, Hunter, Adrian,
	Christopherson,, Sean, jiangshanlai@gmail.com, jgg@ziepe.ca,
	yangtiezhu@loongson.cn

> > +/*
> > + * 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@vger.kernel.org,
	platform-driver-x86@vger.kernel.org, iommu@lists.linux.dev,
	linux-hyperv@vger.kernel.org, linux-perf-users@vger.kernel.org,
	x86@kernel.org
  Cc: mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com,
	hpa@zytor.com, steve.wahl@hpe.com, mike.travis@hpe.com,
	Sivanich, Dimitri, Anderson, Russ, dvhart@infradead.org,
	andy@infradead.org, joro@8bytes.org,
	suravee.suthikulpanit@amd.com, will@kernel.org,
	robin.murphy@arm.com, kys@microsoft.com, haiyangz@microsoft.com,
	wei.liu@kernel.org, Cui, Dexuan, dwmw2@infradead.org,
	baolu.lu@linux.intel.com, peterz@infradead.org, acme@kernel.org,
	mark.rutland@arm.com, alexander.shishkin@linux.intel.com,
	jolsa@kernel.org, namhyung@kernel.org, irogers@google.com,
	Hunter, Adrian, Christopherson,, Sean, jiangshanlai@gmail.com,
	jgg@ziepe.ca, yangtiezhu@loongson.cn

> > +/*
> > + * 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@vger.kernel.org, platform-driver-x86@vger.kernel.org,
	iommu@lists.linux.dev, linux-hyperv@vger.kernel.org,
	linux-perf-users@vger.kernel.org, x86@kernel.org,
	tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
	dave.hansen@linux.intel.com, hpa@zytor.com, Sivanich, Dimitri,
	Anderson, Russ, dvhart@infradead.org, andy@infradead.org,
	joro@8bytes.org, suravee.suthikulpanit@amd.com, will@kernel.org,
	robin.murphy@arm.com, kys@microsoft.com, haiyangz@microsoft.com,
	wei.liu@kernel.org, Cui, Dexuan, dwmw2@infradead.org,
	baolu.lu@linux.intel.com, peterz@infradead.org, acme@kernel.org,
	mark.rutland@arm.com, alexander.shishkin@linux.intel.com,
	jolsa@kernel.org, namhyung@kernel.org, irogers@google.com,
	Hunter, Adrian, Christopherson,, Sean, jiangshanlai@gmail.com,
	jgg@ziepe.ca, yangtiezhu@loongson.cn

> 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).