All of lore.kernel.org
 help / color / mirror / Atom feed
* interrupt handler in arm question
@ 2011-12-10 21:31 subin gangadharan
  2011-12-11 13:00 ` Konstantin Zertsekel
  0 siblings, 1 reply; 9+ messages in thread
From: subin gangadharan @ 2011-12-10 21:31 UTC (permalink / raw)
  To: kernelnewbies

Hi All,

I am trying to understand how the interrupt handler in arm working.By
looking at the code,what I understood,when an interrupt
happens arm disables the irq, saves the cpsr to spsr,save current pc
to lr and switches to irq mode.

So in case of interrupt it branches to the vector_irq and there it
saves some registers and depending on which context
its happened,it will call __irq_user or __irq_svc.But before that it
switches to the supervisory mode.

Here I got confused,because in this case user registered handler will
be executed in supervisory mode.
I was thinking interrupt handler will always be executed in interrupt mode.

Could any one please give some pointers on this.


-- 
With Regards
Subin Gangadharan

I am not afraid and I am also not afraid of being afraid.

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

* interrupt handler in arm question
  2011-12-10 21:31 interrupt handler in arm question subin gangadharan
@ 2011-12-11 13:00 ` Konstantin Zertsekel
  2011-12-11 15:32   ` subin gangadharan
  0 siblings, 1 reply; 9+ messages in thread
From: Konstantin Zertsekel @ 2011-12-11 13:00 UTC (permalink / raw)
  To: kernelnewbies

> I am trying to understand how the interrupt handler in arm working.By
> looking at the code,what I understood,when an interrupt
> happens arm disables the irq, saves the cpsr to spsr,save current pc
> to lr and switches to irq mode.

Yes, that's right.
Important to understand that IRQ processor mode has its (mode-private)
own sp, lr and spsr registers.
Additionally, mode-private registers (sp, lr and spsr) are
inaccessible from other modes.

> So in case of interrupt it branches to the vector_irq and there it
> saves some registers and depending on which context
> its happened,it will call __irq_user or __irq_svc. But before that it
> switches to the supervisory mode.

That's right. In Linux Kernel the IRQ, Data Abort, Prefetch Abort, SWI
and Undefined exceptions
are handled in SVC processor mode. In Linux SVC processor mode of ARM
CPU is called "Kernel mode".
You have to switch to SVC processor mode from IRQ (and other processor
modes) to enabled reentrant
interrupts.
Simplistically, it works like this: (1) IRQ exception is entered, (2)
spsr_irq, r0 and lr_irq is saved
on the private IRQ stack (its size is only 12 bytes), (3)
'vector_stub' macro check from what
processor mode we got here - kernel mode or user mode - and calculates
what to call __irq_user
or__irq_svc and (4) the last thing it does 'movs pc, lr' which loads
spsr_irq into cpsr and puts lr
into pc (lr now contains __irq_svc or __irq_user and spsr_irq[4:0]
contains SVC mode bits).
Mind, that r0 points to private IRQ stack that contains original r0,
lr_irq and spsr_irq.

> Here I got confused,because in this case user registered handler will
> be executed in supervisory mode.
> I was thinking interrupt handler will always be executed in interrupt mode.

As said above, interrupt handler is executed in kernel mode.
This is must to support reentrant interrupts.

--- Kosta

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

* interrupt handler in arm question
  2011-12-11 13:00 ` Konstantin Zertsekel
@ 2011-12-11 15:32   ` subin gangadharan
  2011-12-11 16:07     ` Konstantin Zertsekel
  0 siblings, 1 reply; 9+ messages in thread
From: subin gangadharan @ 2011-12-11 15:32 UTC (permalink / raw)
  To: kernelnewbies

Hi Kosta,
Thank you very much for information.I have two more questions related
to this one.
1) Does the LINUX handles the interrupt like this in all other
architectures.I mean handler will? ? always be executed in SVC mode.
2) In case of FIQ mode to which routine it jumps to,basically in IRQ
mode it jumps to? ? either __irq_svc or __irq_usr as you explained
earlier.
    I have looked at the source code, but I couldn't figure out in
case of FIQ, where its    branching to.

Could you please give me a bit more explanation on this.
Thanks in advance.

On Sun, Dec 11, 2011 at 7:00 AM, Konstantin Zertsekel
<zertsekel@gmail.com> wrote:
>> I am trying to understand how the interrupt handler in arm working.By
>> looking at the code,what I understood,when an interrupt
>> happens arm disables the irq, saves the cpsr to spsr,save current pc
>> to lr and switches to irq mode.
>
> Yes, that's right.
> Important to understand that IRQ processor mode has its (mode-private)
> own sp, lr and spsr registers.
> Additionally, mode-private registers (sp, lr and spsr) are
> inaccessible from other modes.
>
>> So in case of interrupt it branches to the vector_irq and there it
>> saves some registers and depending on which context
>> its happened,it will call __irq_user or __irq_svc. But before that it
>> switches to the supervisory mode.
>
> That's right. In Linux Kernel the IRQ, Data Abort, Prefetch Abort, SWI
> and Undefined exceptions
> are handled in SVC processor mode. In Linux SVC processor mode of ARM
> CPU is called "Kernel mode".
> You have to switch to SVC processor mode from IRQ (and other processor
> modes) to enabled reentrant
> interrupts.
> Simplistically, it works like this: (1) IRQ exception is entered, (2)
> spsr_irq, r0 and lr_irq is saved
> on the private IRQ stack (its size is only 12 bytes), (3)
> 'vector_stub' macro check from what
> processor mode we got here - kernel mode or user mode - and calculates
> what to call __irq_user
> or__irq_svc and (4) the last thing it does 'movs pc, lr' which loads
> spsr_irq into cpsr and puts lr
> into pc (lr now contains __irq_svc or __irq_user and spsr_irq[4:0]
> contains SVC mode bits).
> Mind, that r0 points to private IRQ stack that contains original r0,
> lr_irq and spsr_irq.
>
>> Here I got confused,because in this case user registered handler will
>> be executed in supervisory mode.
>> I was thinking interrupt handler will always be executed in interrupt mode.
>
> As said above, interrupt handler is executed in kernel mode.
> This is must to support reentrant interrupts.
>
> --- Kosta



-- 
With Regards
Subin Gangadharan

I am not afraid and I am also not afraid of being afraid.

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

* interrupt handler in arm question
  2011-12-11 15:32   ` subin gangadharan
@ 2011-12-11 16:07     ` Konstantin Zertsekel
  2011-12-11 18:05       ` subin gangadharan
  0 siblings, 1 reply; 9+ messages in thread
From: Konstantin Zertsekel @ 2011-12-11 16:07 UTC (permalink / raw)
  To: kernelnewbies

> 2) In case of FIQ mode to which routine it jumps to,basically in IRQ
> mode it jumps to    either __irq_svc or __irq_usr as you explained
> earlier.
>    I have looked at the source code, but I couldn't figure out in
> case of FIQ, where its    branching to.

That's for a good reason :-)
FIQ exception is not implemented in Linux Kernel.
Actually, when ARM CPU takes FIQ exception, it branches to 0xffff001c
address, which contains the below code from entry-armv.S:
vector_fiq:
        disable_fiq
        subs    pc, lr, #4

Now, disable_fiq not implemented for all the platforms.
But, anyway, 'subs pc, lr, #4' returns the CPU to the point where
FIQ exception has happened and the system continues to run as usual.


>>> I am trying to understand how the interrupt handler in arm working.By
>>> looking at the code,what I understood,when an interrupt
>>> happens arm disables the irq, saves the cpsr to spsr,save current pc
>>> to lr and switches to irq mode.
>>
>> Yes, that's right.
>> Important to understand that IRQ processor mode has its (mode-private)
>> own sp, lr and spsr registers.
>> Additionally, mode-private registers (sp, lr and spsr) are
>> inaccessible from other modes.

>>> So in case of interrupt it branches to the vector_irq and there it
>>> saves some registers and depending on which context
>>> its happened,it will call __irq_user or __irq_svc. But before that it
>>> switches to the supervisory mode.

>> That's right. In Linux Kernel the IRQ, Data Abort, Prefetch Abort, SWI
>> and Undefined exceptions
>> are handled in SVC processor mode. In Linux SVC processor mode of ARM
>> CPU is called "Kernel mode".
>> You have to switch to SVC processor mode from IRQ (and other processor
>> modes) to enabled reentrant
>> interrupts.
>> Simplistically, it works like this: (1) IRQ exception is entered, (2)
>> spsr_irq, r0 and lr_irq is saved
>> on the private IRQ stack (its size is only 12 bytes), (3)
>> 'vector_stub' macro check from what
>> processor mode we got here - kernel mode or user mode - and calculates
>> what to call __irq_user
>> or__irq_svc and (4) the last thing it does 'movs pc, lr' which loads
>> spsr_irq into cpsr and puts lr
>> into pc (lr now contains __irq_svc or __irq_user and spsr_irq[4:0]
>> contains SVC mode bits).
>> Mind, that r0 points to private IRQ stack that contains original r0,
>> lr_irq and spsr_irq.

> 1) Does the LINUX handles the interrupt like this in all other
> architectures.I mean handler will always be executed in SVC mode.

Sorry, I am too unfamiliar with other architectures... to my detriment actually.
Can anybody fill the knowledge gap here?!

--- Kosta

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

* interrupt handler in arm question
  2011-12-11 16:07     ` Konstantin Zertsekel
@ 2011-12-11 18:05       ` subin gangadharan
  2011-12-12  8:23         ` Konstantin Zertsekel
  0 siblings, 1 reply; 9+ messages in thread
From: subin gangadharan @ 2011-12-11 18:05 UTC (permalink / raw)
  To: kernelnewbies

Hi Kosta,

Thanks for answering.I really appreciate you taking the time to answer
my question.


On Sun, Dec 11, 2011 at 10:07 AM, Konstantin Zertsekel
<zertsekel@gmail.com> wrote:
>> 2) In case of FIQ mode to which routine it jumps to,basically in IRQ
>> mode it jumps to ? ?either __irq_svc or __irq_usr as you explained
>> earlier.
>> ? ?I have looked at the source code, but I couldn't figure out in
>> case of FIQ, where its ? ?branching to.
>
> That's for a good reason :-)
> FIQ exception is not implemented in Linux Kernel.
> Actually, when ARM CPU takes FIQ exception, it branches to 0xffff001c
> address, which contains the below code from entry-armv.S:
> vector_fiq:
> ? ? ? ?disable_fiq
> ? ? ? ?subs ? ?pc, lr, #4
>
> Now, disable_fiq not implemented for all the platforms.
> But, anyway, 'subs pc, lr, #4' returns the CPU to the point where
> FIQ exception has happened and the system continues to run as usual.

As you said, disable_fiq is empty in OMAP architecture.
.macro  disable_fiq
.endm

So from the above explanation,I can saythat LINUX is not making use of
FIQ feature of arm.Am I right?


>
>>>> I am trying to understand how the interrupt handler in arm working.By
>>>> looking at the code,what I understood,when an interrupt
>>>> happens arm disables the irq, saves the cpsr to spsr,save current pc
>>>> to lr and switches to irq mode.
>>>
>>> Yes, that's right.
>>> Important to understand that IRQ processor mode has its (mode-private)
>>> own sp, lr and spsr registers.
>>> Additionally, mode-private registers (sp, lr and spsr) are
>>> inaccessible from other modes.
>
>>>> So in case of interrupt it branches to the vector_irq and there it
>>>> saves some registers and depending on which context
>>>> its happened,it will call __irq_user or __irq_svc. But before that it
>>>> switches to the supervisory mode.
>
>>> That's right. In Linux Kernel the IRQ, Data Abort, Prefetch Abort, SWI
>>> and Undefined exceptions
>>> are handled in SVC processor mode. In Linux SVC processor mode of ARM
>>> CPU is called "Kernel mode".
>>> You have to switch to SVC processor mode from IRQ (and other processor
>>> modes) to enabled reentrant
>>> interrupts.
>>> Simplistically, it works like this: (1) IRQ exception is entered, (2)
>>> spsr_irq, r0 and lr_irq is saved
>>> on the private IRQ stack (its size is only 12 bytes), (3)
>>> 'vector_stub' macro check from what
>>> processor mode we got here - kernel mode or user mode - and calculates
>>> what to call __irq_user
>>> or__irq_svc and (4) the last thing it does 'movs pc, lr' which loads
>>> spsr_irq into cpsr and puts lr
>>> into pc (lr now contains __irq_svc or __irq_user and spsr_irq[4:0]
>>> contains SVC mode bits).
>>> Mind, that r0 points to private IRQ stack that contains original r0,
>>> lr_irq and spsr_irq.
>
>> 1) Does the LINUX handles the interrupt like this in all other
>> architectures.I mean handler will always be executed in SVC mode.
>
> Sorry, I am too unfamiliar with other architectures... to my detriment actually.
> Can anybody fill the knowledge gap here?!
>
> --- Kosta



-- 
With Regards
Subin Gangadharan

I am not afraid and I am also not afraid of being afraid.

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

* interrupt handler in arm question
  2011-12-11 18:05       ` subin gangadharan
@ 2011-12-12  8:23         ` Konstantin Zertsekel
  2011-12-12 18:53           ` subin gangadharan
  0 siblings, 1 reply; 9+ messages in thread
From: Konstantin Zertsekel @ 2011-12-12  8:23 UTC (permalink / raw)
  To: kernelnewbies

>> FIQ exception is not implemented in Linux Kernel.
>> Actually, when ARM CPU takes FIQ exception, it branches to 0xffff001c
>> address, which contains the below code from entry-armv.S:
>> vector_fiq:
>> ? ? ? ?disable_fiq
>> ? ? ? ?subs ? ?pc, lr, #4
>>
>> Now, disable_fiq not implemented for all the platforms.
>> But, anyway, 'subs pc, lr, #4' returns the CPU to the point where
>> FIQ exception has happened and the system continues to run as usual.
>
> As you said, disable_fiq is empty in OMAP architecture.
> .macro ?disable_fiq
> .endm
>
> So from the above explanation,I can saythat LINUX is not making use of
> FIQ feature of arm.Am I right?

Absolutely. --- Kosta

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

* interrupt handler in arm question
  2011-12-12  8:23         ` Konstantin Zertsekel
@ 2011-12-12 18:53           ` subin gangadharan
  2011-12-13 12:52             ` Konstantin Zertsekel
  0 siblings, 1 reply; 9+ messages in thread
From: subin gangadharan @ 2011-12-12 18:53 UTC (permalink / raw)
  To: kernelnewbies

Hi Kosta,

I have one more question.I have searched in the source code,but
couldn't figure it out.
As you mentioned earlier,running ISR in SVC is mainly to make it re
entrant,but where
its getting enabled again(interrupt) after ARM has been disabled it
when an interrupt happens.

Could you please give an idea on this.

With Regards,
Subin K G

On Mon, Dec 12, 2011 at 2:23 AM, Konstantin Zertsekel
<zertsekel@gmail.com> wrote:
>>> FIQ exception is not implemented in Linux Kernel.
>>> Actually, when ARM CPU takes FIQ exception, it branches to 0xffff001c
>>> address, which contains the below code from entry-armv.S:
>>> vector_fiq:
>>> ? ? ? ?disable_fiq
>>> ? ? ? ?subs ? ?pc, lr, #4
>>>
>>> Now, disable_fiq not implemented for all the platforms.
>>> But, anyway, 'subs pc, lr, #4' returns the CPU to the point where
>>> FIQ exception has happened and the system continues to run as usual.
>>
>> As you said, disable_fiq is empty in OMAP architecture.
>> .macro ?disable_fiq
>> .endm
>>
>> So from the above explanation,I can saythat LINUX is not making use of
>> FIQ feature of arm.Am I right?
>
> Absolutely. --- Kosta



-- 
With Regards
Subin Gangadharan

I am not afraid and I am also not afraid of being afraid.

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

* interrupt handler in arm question
  2011-12-12 18:53           ` subin gangadharan
@ 2011-12-13 12:52             ` Konstantin Zertsekel
  2011-12-14 19:04               ` subin gangadharan
  0 siblings, 1 reply; 9+ messages in thread
From: Konstantin Zertsekel @ 2011-12-13 12:52 UTC (permalink / raw)
  To: kernelnewbies

> I have one more question.I have searched in the source code,but
> couldn't figure it out.
> As you mentioned earlier,running ISR in SVC is mainly to make it re
> entrant,but where
> its getting enabled again(interrupt) after ARM has been disabled it
> when an interrupt happens.
> Could you please give an idea on this.

Please take a look at handle_IRQ_event in kernel/irq/handle.c:

irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
{
        irqreturn_t ret, retval = IRQ_NONE;
        unsigned int status = 0;

        if (!(action->flags & IRQF_DISABLED))
                local_irq_enable_in_hardirq();  <--- !!!!!!!!!!!!!!!!!!!!!!!!!

        ...
}

It is called from kernel/irq/chip.c file for every type of IRQ
interrupt (simple IRQ, level IRQ, enge IRQ and percpu IRQ).

Now, local_irq_enable_in_hardirq is defined in inlude/linux/interrupt.h:

#ifdef CONFIG_LOCKDEP
# define local_irq_enable_in_hardirq()  do { } while (0)
#else
# define local_irq_enable_in_hardirq()  local_irq_enable()
#endif

Now, local_irq_enable is defined in include/linux/irqflags.h:

#define local_irq_enable() \
        do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0)
And,@last, raw_local_irq_enable is defined in
arch/arm/include/asm/irqflags.h:

#define raw_local_irq_enable()                                  \
        ({                                                      \
                unsigned long temp;                             \
        __asm__ __volatile__(                                   \
        "mrs    %0, cpsr                @ local_irq_enable\n"   \
"       bic     %0, %0, #128\n"                                 \
"       msr     cpsr_c, %0"                                     \
        : "=r" (temp)                                           \
        :                                                       \
        : "memory", "cc");                                      \
        })

This last macro essentially clears the I (big i) bit in CPSR register
- this enables IRQ exceptions.

Hope, it helps.
--- Kosta

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

* interrupt handler in arm question
  2011-12-13 12:52             ` Konstantin Zertsekel
@ 2011-12-14 19:04               ` subin gangadharan
  0 siblings, 0 replies; 9+ messages in thread
From: subin gangadharan @ 2011-12-14 19:04 UTC (permalink / raw)
  To: kernelnewbies

Thanks Kosta,

I have looked at the code,but it seems 3.0 is slightly different.
Anyway your pointers will help me to understanding it better.



On Tue, Dec 13, 2011 at 6:52 AM, Konstantin Zertsekel
<zertsekel@gmail.com> wrote:
>> I have one more question.I have searched in the source code,but
>> couldn't figure it out.
>> As you mentioned earlier,running ISR in SVC is mainly to make it re
>> entrant,but where
>> its getting enabled again(interrupt) after ARM has been disabled it
>> when an interrupt happens.
>> Could you please give an idea on this.
>
> Please take a look at handle_IRQ_event in kernel/irq/handle.c:
>
> irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
> {
> ? ? ? ?irqreturn_t ret, retval = IRQ_NONE;
> ? ? ? ?unsigned int status = 0;
>
> ? ? ? ?if (!(action->flags & IRQF_DISABLED))
> ? ? ? ? ? ? ? ?local_irq_enable_in_hardirq(); ?<--- !!!!!!!!!!!!!!!!!!!!!!!!!
>
> ? ? ? ?...
> }
>
> It is called from kernel/irq/chip.c file for every type of IRQ
> interrupt (simple IRQ, level IRQ, enge IRQ and percpu IRQ).
>
> Now, local_irq_enable_in_hardirq is defined in inlude/linux/interrupt.h:
>
> #ifdef CONFIG_LOCKDEP
> # define local_irq_enable_in_hardirq() ?do { } while (0)
> #else
> # define local_irq_enable_in_hardirq() ?local_irq_enable()
> #endif
>
> Now, local_irq_enable is defined in include/linux/irqflags.h:
>
> #define local_irq_enable() \
> ? ? ? ?do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0)
> And, at last, raw_local_irq_enable is defined in
> arch/arm/include/asm/irqflags.h:
>
> #define raw_local_irq_enable() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\
> ? ? ? ?({ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\
> ? ? ? ? ? ? ? ?unsigned long temp; ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
> ? ? ? ?__asm__ __volatile__( ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
> ? ? ? ?"mrs ? ?%0, cpsr ? ? ? ? ? ? ? ?@ local_irq_enable\n" ? \
> " ? ? ? bic ? ? %0, %0, #128\n" ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
> " ? ? ? msr ? ? cpsr_c, %0" ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
> ? ? ? ?: "=r" (temp) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
> ? ? ? ?: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
> ? ? ? ?: "memory", "cc"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\
> ? ? ? ?})
>
> This last macro essentially clears the I (big i) bit in CPSR register
> - this enables IRQ exceptions.
>
> Hope, it helps.
> --- Kosta



-- 
With Regards
Subin Gangadharan

I am not afraid and I am also not afraid of being afraid.

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

end of thread, other threads:[~2011-12-14 19:04 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-10 21:31 interrupt handler in arm question subin gangadharan
2011-12-11 13:00 ` Konstantin Zertsekel
2011-12-11 15:32   ` subin gangadharan
2011-12-11 16:07     ` Konstantin Zertsekel
2011-12-11 18:05       ` subin gangadharan
2011-12-12  8:23         ` Konstantin Zertsekel
2011-12-12 18:53           ` subin gangadharan
2011-12-13 12:52             ` Konstantin Zertsekel
2011-12-14 19:04               ` subin gangadharan

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.