Interrupt(6): interrupt handling in OS

When an interrupt occurs,
  • Interrupt controller asserts one signal to the processor.
  • the CPU jumps to the vector table, looking for the handler for that type of exception.
  • the handler (pieces of assembly code, generated by cpu_init_interrupt())
    • intr_entry_start          // services/system/ker/arm/kernel.S
      • save registers, branch to id()
    • id()
      • acknowledge the GIC by reading the acknowledge register.
      • mask/disable the interrupt ID in GIC.
      • return interrupt number in r4.
    • if it is cascaded interrupt, branch to cascaded interrupt id()
      • find the interrupt source by reading registers
      • mask/disable the interrupt source in the controller
      • return the interrupt ID in r4
    • intr_process_queue
      • dispatch the interrupt to the appropriate handlers, — branch to interrupt().
      • This passes the INTRLEVEL in r8.
    • interrupt(): defined in services/system/ker/arm/interrupt.c
      • interruptEnable(); what’s the purpose of doing this?
      • find ilp->queue, and look for the handler for each entry in that queue
        • if there is a handler, execute it;
          • if the event returned by the handler is not NULL,  call intrevent_add();
        • if there is no handler,
          • interrrupt_mask(isr->level, isr);
          • intrevent_add();
      • InterruptDisable();
    • if it is cascaded interrupt, and if it is necessary (another interrupt ID), call id() callout again ?????
    • eoi()
    • intr_done
      • return from interrupt handling.

note:

  1. the input of eoi is a interrupt id. so it is only possible to unmask one interrupt.
  2. mask_count is for a particular Interrupt Level (IRQ)
    • The mask count increases for every interrupt handler you have attached to the same vector. So when you attach an interrupt handler the Kernel will call the unmask callout (to enable the interrupt vector) and increment the mask count. When the interrupt goes off the ID callout occurs and masks/disables the interrupt and then calls each handler that is attach on that vector. When each interrupt handler completes the mask count is  decremented and the eoi callout is called. The last handler to exit will cause the mask count to reach 0 and the eoi will unmask/re-enable the interrupt.
  3. If there are two SDMA channel complete at the same time – two bits are set in IRQSTATUS. My understanding is, based on the reading of the callout code, id() will be entered twice, so does the eoi().
    • the first time sdma_id() is called, there are two bits set in IRQSTATUS, the code scan for first set bit, and disable the corresponding bit in IRQENABLE.
    • when eoi() is entered, it checks if  mask_count is zero (all handlers for that IRQ have exited). if yes, clear the bit in IRQSTATUS, and set the bit in IRQENABLE.
    • the 2nd id() is entered, there is only one bit left in IRQSTATUS.

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s