Am Thursday 18 March 2010 14:07:26 schrieben Sie:
> Hi,
>
> On Wednesday 17 March 2010 00:15:48 Michael Walle wrote:
> > Am Tuesday 16 March 2010 15:53:41 schrieb Sébastien Bourdeauducq:
> > > Therefore, it gets ALL interrupts (masked or not). We should AND
> > > register IP with register IM.
> >
> > yep. imho that should be done within the asm code.
>
> Yes, but this requires extra asm instructions that no longer fit between
> two LM32 exception vectors and therefore a jump is needed. I wanted to
> avoid it, that's why I did it this way. But since it is inconsistent with
> other Linux ports, I will change it.
>
> > other linux ports pass only one single irq number to do_IRQ().
> >
> > What about the following steps:
> >   1. interrupt vector gets called
> >   2. save regs
> >   3. r2 <- IM & IP
> >   4. find position of first bit set in r2, store it in r1
> >  (4a. r2 <- pt_regs)
> >   5. mask irq
> >   6. call do_IRQ (which only takes one irq number)
> >   7. ack irq
> >   8. unmask irq
> >   9. restore regs
> >  10. eret
> >
> > Processing only one interrupt at a time should avoid the second problem,
> > mentioned above.
>
> Sounds good. It takes more CPU cycles to achieve the same thing when
> interrupts come at the same time, but since I guess this rarely happens,
> the small performance improvement is not worth the cost of doing
> differently than other Linux ports.

see attachment

-- 
wkr michael
From e6b18c3b3f63df3ed184403b1afb662974508906 Mon Sep 17 00:00:00 2001
From: Michael Walle <[email protected]>
Date: Thu, 1 Apr 2010 00:01:54 +0200
Subject: [PATCH] new irq handling code

---
 arch/lm32/kernel/entry.S |   38 ++++++++++++++++++++++++++++++--------
 arch/lm32/kernel/irq.c   |   27 ++++++---------------------
 2 files changed, 36 insertions(+), 29 deletions(-)

diff --git a/arch/lm32/kernel/entry.S b/arch/lm32/kernel/entry.S
index 15d8d39..232d253 100644
--- a/arch/lm32/kernel/entry.S
+++ b/arch/lm32/kernel/entry.S
@@ -79,14 +79,13 @@ ENTRY(divide_by_zero_handler)
 	KERNEL_EXCEPTION_VECTOR(160)
 
 ENTRY(interrupt_handler)
-	addi    sp, sp, -128
-	sw      (sp+120), ra
-	calli   _save_irq_frame
-	rcsr    r1, IP
-
-	addi    r2, sp, 4
-	calli   asm_do_IRQ
-	bi      _restore_irq_frame_and_return
+	bi      _long_interrupt_handler
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
 	nop
 
 ENTRY(system_call)
@@ -358,6 +357,29 @@ ENTRY(sys_clone_wrapper)
 /* in IRQ we call a function between save and restore */
 /* we therefore only save and restore the caller saved registers */
 /* (r1-r10, ra, ea because an interrupt could interrupt another one) */
+_long_interrupt_handler:
+	addi    sp, sp, -128
+	sw      (sp+120), ra
+	calli   _save_irq_frame
+
+	rcsr    r2, IP
+	rcsr    r3, IM
+	mvi     r1, 0
+	and     r2, r2, r3
+	mvi     r3, 1
+	be      r2, r0, 3f
+1:
+	and     r4, r2, r3
+	bne     r4, r0, 2f
+	sli     r3, r3, 1
+	addi    r1, r1, 1
+	bi      1b
+2:
+	addi    r2, sp, 4
+	calli   asm_do_IRQ
+3:
+	bi      _restore_irq_frame_and_return
+
 _save_irq_frame:
 	sw      (sp+8),   r1
 	sw      (sp+12),  r2
diff --git a/arch/lm32/kernel/irq.c b/arch/lm32/kernel/irq.c
index 2dd57f4..32e7256 100644
--- a/arch/lm32/kernel/irq.c
+++ b/arch/lm32/kernel/irq.c
@@ -188,31 +188,16 @@ asmlinkage void manage_signals_irq(struct pt_regs* regs);
  * come via this function.  Instead, they should provide their
  * own 'handler'
  */
-asmlinkage void asm_do_IRQ(unsigned long vec, struct pt_regs *regs)
+asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
-	struct pt_regs *old_regs;
-	unsigned int irq;
-	
-	old_regs = set_irq_regs(regs);
+	struct pt_regs *old_regs = set_irq_regs(regs);
 
 	irq_enter();
 
-	/* Only process unmasked interrupts.
-	 * This avoids a race condition if several interrupts
-	 * arrive at the same time!
-	 */
-	vec &= lm32_current_irq_mask;
-	/* mask ALL interrupts we are going to process */
-	lm32_irq_multimask(vec);
-	
-	/* decode irq */
-	for (irq=0 ; irq<32; ++irq ) {
-		if ( vec & (1 << irq) ) {
-			generic_handle_irq(irq); /* < this (re)enables interrupts globally */
-			lm32_irq_ack(irq);
-			lm32_irq_unmask(irq);
-		}
-	}
+	lm32_irq_mask(irq);
+	generic_handle_irq(irq); /* < this (re)enables interrupts globally */
+	lm32_irq_ack(irq);
+	lm32_irq_unmask(irq);
 
 	irq_exit();
 
-- 
1.5.6.5

_______________________________________________
http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org
IRC: #milkym...@freenode
Webchat: www.milkymist.org/irc.html
Wiki: www.milkymist.org/wiki

Reply via email to