Re: [PATCH dovetail 02/11] riscv: irq_pipeline: add IRQ pipelining core

Philippe Gerum <[email protected]>
Newsgroups dev.linux.lists.xenomai
Message-ID <87cxzib44d.fsf@2a01cb0804738000b42250ae26cae50b.ipv6.abo.wanadoo.fr>
Tobias Schaffner <[email protected]> writes:

> This patchset integrates IRQ pipelining into the RISC-V architecture,
> bringing it in line with the Dovetail/IRQ pipeline model used on other
> architectures. It adds the core pipelining infrastructure and adapts
> low-level primitives to cleanly separate in-band and out-of-band
> interrupt handling.
>
> @@ -176,9 +204,12 @@ asmlinkage __visible __trap_section void do_trap_insn_illegal(struct pt_regs *re
>  
>  	if (user_mode(regs)) {
>  		irqentry_enter_from_user_mode(regs);
> -		local_irq_enable();
> +		hard_local_irq_enable();
>

irqentry_enter_from_user_mode() has just stalled the in-band stage, so
we end up here with hard irqs on, but irqs_disabled() now yields true.
Maybe riscv_v_first_use_handler() would never complain about running
with irqs (virtually) disabled although the caller explicitly enables
them, but maybe it would, right now or as a result of a future upstream
change.

As a rule of thumb, I would always keep the assumption the original
kernel logic may make about the interrupt state when running in-band,
in this case (*):

-	local_irq_enable();
+	unstall_inband_nocheck();
+	hard_local_irq_enable();

(*) hard irqs must be off when manipulating the stall bit, so the proper
sequence is always unstall+enable when entering with hard irqs off,
disable+stall when entering with hard irqs on.

>  		handled = riscv_v_first_use_handler(regs);
> +
> +		hard_local_irq_disable();
> +

and conversely,

+	hard_local_irq_disable();
+	stall_inband_nocheck();

>  		if (!handled)
>  			do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->epc,
>  				      "Oops - illegal instruction");
> @@ -308,11 +339,12 @@ asmlinkage __visible __trap_section void do_trap_break(struct pt_regs *regs)
>  {
>  	if (user_mode(regs)) {
>  		irqentry_enter_from_user_mode(regs);
> -		local_irq_enable();
> +		hard_local_irq_enable();
>

Ditto.

>  		handle_break(regs);
>  
> -		local_irq_disable();
> +		hard_local_irq_disable();
> +
>  		irqentry_exit_to_user_mode(regs);
>  	} else {
>  		irqentry_state_t state = irqentry_nmi_enter(regs);
> @@ -428,13 +460,69 @@ asmlinkage __visible noinstr void do_page_fault(struct pt_regs *regs)
>  	irqentry_state_t state = irqentry_enter(regs);
>  
>  	handle_page_fault(regs);
> -
> -	local_irq_disable();
> +	hard_local_irq_disable();
>

Ditto.

>  	irqentry_exit(regs, state);
>  }
>  #endif
>  
> +#ifdef CONFIG_IRQ_PIPELINE
> +
> +extern void (*handle_arch_irq)(struct pt_regs *);
> +
> +static void noinstr handle_riscv_irq_pipelined(struct pt_regs *regs)
> +{
> +	struct pt_regs *old_regs = set_irq_regs(regs);
> +	handle_arch_irq(regs);
> +	set_irq_regs(old_regs);
> +}
> +
> +DEFINE_PER_CPU(int, irq_nesting);
> +
> +static void noinstr handle_riscv_irq_pipelined_on_stack(struct pt_regs *regs)
> +{
> +	if (IS_ENABLED(CONFIG_IRQ_STACKS) && this_cpu_inc_return(irq_nesting) == 1)
> +		call_on_irq_stack(regs, handle_riscv_irq_pipelined);
> +	else
> +		handle_riscv_irq_pipelined(regs);
> +	this_cpu_dec(irq_nesting);

What if CONFIG_IRQ_STACKS is off? Imbalance?

-- 
Philippe.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.