Re: [GIT PULL] arm64 fixes for 5.15-rc5

From: Thomas Gleixner
Date: Tue Oct 12 2021 - 11:40:05 EST


On Tue, Oct 12 2021 at 15:02, Mark Rutland wrote:
> On Tue, Oct 12, 2021 at 03:18:16PM +0200, Thomas Gleixner wrote:
>> On Mon, Oct 11 2021 at 12:54, Linus Torvalds wrote:
> I'm happy with this in principle. The only reason we didn't go down that
> route initially is because the callers are (typically) in the bowels of
> arch asm or platform code, they all need to be fixed in one go to avoid
> breaking anything, and it's a headache if we collide with any rework
> (e.g. MIPS moving to generic entry).

mips-next looks pretty empty vs. that.

>> > It really looks like there is a very tight connection between "uses
>> > handle_domain_irq()" and "uses handle_arch_irq/set_handle_irq()". No?
>>
>> Looks like. That might conflict with the MIPS rework though. I don't
>> know how far that came already. Cc'ed the MIPS people.
>
> There's also a bunch of old platforms on arch/arm which have a
> hard-coded handler (so not using handle_arch_irq/set_handle_irq()) which
> calls handle_domain_irq() -- those can be fixed up.

If that turns out to be ugly, then somehting like the below might be
less horrible as a stop gap.

Thanks,

tglx
---

--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -268,20 +268,16 @@ void xen_send_IPI_allbutself(int vector)

static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id)
{
- irq_enter();
generic_smp_call_function_interrupt();
inc_irq_stat(irq_call_count);
- irq_exit();

return IRQ_HANDLED;
}

static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id)
{
- irq_enter();
generic_smp_call_function_single_interrupt();
inc_irq_stat(irq_call_count);
- irq_exit();

return IRQ_HANDLED;
}
--- a/arch/x86/xen/smp_pv.c
+++ b/arch/x86/xen/smp_pv.c
@@ -458,10 +458,8 @@ static void xen_pv_stop_other_cpus(int w

static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id)
{
- irq_enter();
irq_work_run();
inc_irq_stat(apic_irq_work_irqs);
- irq_exit();

return IRQ_HANDLED;
}
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -33,6 +33,9 @@ config HOTPLUG_SMT
config GENERIC_ENTRY
bool

+config ARCH_ENTRY_RCU_CLEAN
+ bool
+
config KPROBES
bool "Kprobes"
depends on MODULES
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -66,6 +66,7 @@ config X86
select ARCH_ENABLE_MEMORY_HOTREMOVE if MEMORY_HOTPLUG
select ARCH_ENABLE_SPLIT_PMD_PTLOCK if (PGTABLE_LEVELS > 2) && (X86_64 || X86_PAE)
select ARCH_ENABLE_THP_MIGRATION if X86_64 && TRANSPARENT_HUGEPAGE
+ select ARCH_ENTRY_RCU_CLEAN
select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
select ARCH_HAS_CACHE_LINE_SIZE
select ARCH_HAS_DEBUG_VIRTUAL
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -677,24 +677,13 @@ int generic_handle_domain_irq(struct irq
EXPORT_SYMBOL_GPL(generic_handle_domain_irq);

#ifdef CONFIG_HANDLE_DOMAIN_IRQ
-/**
- * handle_domain_irq - Invoke the handler for a HW irq belonging to a domain,
- * usually for a root interrupt controller
- * @domain: The domain where to perform the lookup
- * @hwirq: The HW irq number to convert to a logical one
- * @regs: Register file coming from the low-level handling code
- *
- * Returns: 0 on success, or -EINVAL if conversion has failed
- */
-int handle_domain_irq(struct irq_domain *domain,
- unsigned int hwirq, struct pt_regs *regs)
+static int __handle_domain_irq(struct irq_domain *domain,
+ unsigned int hwirq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
struct irq_desc *desc;
int ret = 0;

- irq_enter();
-
/* The irqdomain code provides boundary checks */
desc = irq_resolve_mapping(domain, hwirq);
if (likely(desc))
@@ -702,12 +691,41 @@ int handle_domain_irq(struct irq_domain
else
ret = -EINVAL;

- irq_exit();
set_irq_regs(old_regs);
return ret;
}

/**
+ * handle_domain_irq - Invoke the handler for a HW irq belonging to a domain,
+ * usually for a root interrupt controller
+ * @domain: The domain where to perform the lookup
+ * @hwirq: The HW irq number to convert to a logical one
+ * @regs: Register file coming from the low-level handling code
+ *
+ * Returns: 0 on success, or -EINVAL if conversion has failed
+ */
+#ifdef CONFIG_ARCH_ENTRY_RCU_CLEAN
+int handle_domain_irq(struct irq_domain *domain,
+ unsigned int hwirq, struct pt_regs *regs)
+{
+ __handle_domain_irq(domain, hwirq, regs);
+}
+#else
+int handle_domain_irq(struct irq_domain *domain,
+ unsigned int hwirq, struct pt_regs *regs)
+{
+ /*
+ * irq_enter()/exit() has to be done in low level
+ * architecture code. Bandaid for not yet fixed
+ * architectures.
+ */
+ irq_enter();
+ __handle_domain_irq(domain, hwirq, regs);
+ irq_exit();
+}
+#endif
+
+/**
* handle_domain_nmi - Invoke the handler for a HW irq belonging to a domain
* @domain: The domain where to perform the lookup
* @hwirq: The HW irq number to convert to a logical one
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -601,6 +601,7 @@ void irq_enter_rcu(void)
account_hardirq_enter(current);
}

+#ifndef ARCH_ENTRY_RCU_CLEAN
/**
* irq_enter - Enter an interrupt context including RCU update
*/
@@ -609,6 +610,7 @@ void irq_enter(void)
rcu_irq_enter();
irq_enter_rcu();
}
+#endif

static inline void tick_irq_exit(void)
{
@@ -650,6 +652,7 @@ void irq_exit_rcu(void)
lockdep_hardirq_exit();
}

+#ifndef ARCH_ENTRY_RCU_CLEAN
/**
* irq_exit - Exit an interrupt context, update RCU and lockdep
*
@@ -662,6 +665,7 @@ void irq_exit(void)
/* must be last! */
lockdep_hardirq_exit();
}
+#endif

/*
* This function must run with irqs disabled!