In order to understand the code, at the moment I ignored 'stubs_offset'.

>/*
> * Interrupt dispatcher
  >*/
  >     vector_stub     irq, IRQ_MODE, 4

After expansion it will look some thing like this -

*vector_irq:
                ...
                blah - blah
                ...
       @ the branch table must immediately follow this code
        and     lr, lr, #0x0f
        mov     r0, sp
        ldr     lr, [pc, lr, lsl #2]
        movs    pc, lr          @ branch to handler in SVC mode
       .long   __irq_invalid                 @  1  (FIQ_26 / FIQ_32)
  .    .long   __irq_invalid                @  2  (IRQ_26 / IRQ_32)
       .long   __irq_svc                   @  3  (SVC_26 / SVC_32)
       .long   __irq_invalid                   @  4
       .long   __irq_invalid                   @  5
       .long   __irq_invalid                   @  6
       .long   __irq_invalid                   @  7
       .long   __irq_invalid                   @  8
       .long   __irq_invalid                   @  9
       .long   __irq_invalid                   @  a
       .long   __irq_invalid                   @  b
       .long   __irq_invalid                   @  c
       .long   __irq_invalid                   @  d
       .long   __irq_invalid                   @  e
       .long   __irq_invalid                   @  f*

I guess that the instruction in the above code -
*    movs    pc, lr          @ branch to handler in SVC mode
*will jump to address specified by *
   .long   __irq_svc                   @  3  (SVC_26 / SVC_32)*

Assuming I am right then the instruction -

ldr     lr, [pc, lr, lsl #2]

will set 'lr' to the address of '__Irq_svc'. But I am unable to understand
how come this instruction is setting up lr to point to __irq_svc?
In the above code while executing 'and' instruction 'lr' contains the value
of 'spsr' and last four bits are mode bits then this 'and' instruction is
preserving those 4 bits (mode bits). But why do we need those bits and in
'ldr' why we are doing left shift by 2? Cannot we simply add 16 (since there
are one instruction and 3 handler addresses after 'ldr' instruction) to 'pc'
and load it into 'lr' so that 'lr' starts pointing to __irq_svc, which is 4
words down the 'ldr' instruction?
And one more question why do we have 16 handlers in each exception stub? why
not just 1 (e.g. __irq_svc) or 2 (__irq_usr and __irq_svc)? and what is use
of __irq_usr?

I am sorry I have put lot of questions in this email. But answers to them
would really help me in understanding the code.

Thanks in advance.
- A Sahlot

On Sat, Apr 26, 2008 at 11:37 AM, sahlot arvind <[EMAIL PROTECTED]> wrote:

> Thanks Russell. I will re-try and get back in case dont understand.
>
> - A
>
> On Sat, Apr 26, 2008 at 2:09 AM, Russell King - ARM Linux <
> [EMAIL PROTECTED]> wrote:
>
> >  On Fri, Apr 25, 2008 at 02:31:20PM +0530, sahlot arvind wrote:
> > > Guys,
> > >
> > > I am trying to understand the flow of control when an interrupt comes.
> > > I am reading linux-2.6.24 src code and looking at
> > > arch/arm/kernel/entry-armv.S.
> > > At the bottom of this file I see the vector table as below -
> > >
> > > __vectors_start:
> > >     swi SYS_ERROR0
> > >     b   vector_und + stubs_offset
> > >     ldr pc, .LCvswi + stubs_offset
> > >     b   vector_pabt + stubs_offset
> > >     b   vector_dabt + stubs_offset
> > >     b   vector_addrexcptn + stubs_offset
> > >     b   vector_irq + stubs_offset
> > >     b   vector_fiq + stubs_offset
> > >
> > >     .globl  __vectors_end
> > >
> > >
> > > Here is not 'stubs_offset' a constant? and after seeing an IRQ where
> > are we
> > > branching by doing ' b   vector_irq + stubs_offset'  and what is the
> > flow of
> > > control???
> >
> > It's all rather mystical if you don't understand the ARM instruction
> > set.
> >
> > 1. 'b' is a branch instruction.  All branches are relative to the
> >   current PC.
> >
> > 2. the code is not executed in the location where you find it in
> >   the kernel.  It is copied to other locations in memory.  Other
> >   code (between __stubs_start and __stubs_end) is copied to 512
> >   bytes above the start of the vectors, and these branch instructions
> >   branch to that other code.
> >
> > 3. __stubs_offset is just a correction factor to convert the branches
> >   to point at the correct _relative_ position when they're copied to
> >   their proper location in memory.
> >
> > The simple way to _read_ the code is to ignore the 'stubs_offset' and
> > just
> > follow the branch instruction to vector_irq:
> >
> > /*
> >  * Interrupt dispatcher
> >  */
> >        vector_stub     irq, IRQ_MODE, 4
> >
> > and then look at what vector_stub expands to.
> >
>
>
>
> --
> http://linuxexplained.blogspot.com




-- 
http://linuxexplained.blogspot.com

Reply via email to