久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

中斷代碼跟蹤

 Liucw2012 2012-04-10
 

init/main.c

arch/x86/kernel/traps.c

trap_init(void)

arch/x86/kernel/traps.c

set_intr_gate(0, &divide_error);

set_intr_gate(19, &simd_coprocessor_error);

 

arch/x86/include/asm/irq_vectors.h

# define SYSCALL_VECTOR         0x80

set_system_trap_gate(SYSCALL_VECTOR, &system_call);

/*

 * This needs to use 'idt_table' rather than 'idt', and

 * thus use the _nonmapped_ version of the IDT, as the

 * Pentium F0 0F bugfix can have resulted in the mapped

 * IDT being write-protected.

 */

arch/x86/include/asm/desc.h

static inline void set_intr_gate(unsigned int n, void *addr)

{

BUG_ON((unsigned)n > 0xFF);

_set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);

}

 

arch/x86/include/asm/desc_defs.h

#ifdef CONFIG_X86_64

typedef struct gate_struct64 gate_desc;

#else

 typedef struct desc_struct gate_desc;

#endif

 

arch/x86/include/asm/irq_vectors.h

#define NR_VECTORS                         256

arch/x86/kernel/traps.c

 gate_desc idt_table[NR_VECTORS] __page_aligned_data = { { { { 0, 0 } } }, };

static inline void _set_gate(int gate, unsigned type, void *addr,

                   unsigned dpl, unsigned ist, unsigned seg)

{

gate_desc s;

pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg);

 /* 

* does not need to be atomic because it is only done once at

* setup time

 */

write_idt_entry(idt_table, gate, &s);

}

 

arch/x86/include/asm/desc.h

#define write_idt_entry(dt, entry, g)       \

native_write_idt_entry(dt, entry, g)

 

static inline void native_write_idt_entry(gate_desc *idt, int entry,

                        const gate_desc *gate)

{

memcpy(&idt[entry], gate, sizeof(*gate));

}

 

arch/x86/kernel/irqinit.c

init_IRQ(void)

x86_init.irqs.intr_init();

arch/x86/kernel/x86_init.c

.pre_vector_init    = init_ISA_irqs,

.intr_init      = native_init_IRQ,

 

void __init native_init_IRQ(void)

x86_init.irqs.pre_vector_init();

arch/x86/kernel/irqinit.c

void __init init_ISA_irqs(void)

      for (i = 0; i < legacy_pic->nr_legacy_irqs; i++) {

          struct irq_desc *desc = irq_to_desc(i);

         

          desc->status = IRQ_DISABLED;

          desc->action = NULL;

          desc->depth = 1;

 

          kernel/irq/chip.c

          set_irq_chip_and_handler_name(i, &i8259A_chip,

                            handle_level_irq, "XT");

      set_irq_chip(irq, chip);

      __set_irq_handler(irq, handle, 0, name);

 

      }

 

arch/x86/include/asm/irq_vectors.h

#define FIRST_EXTERNAL_VECTOR       0x20

for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {

if (!test_bit(i, used_vectors))

set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);//中斷處理函數(shù)

}

 

arch/x86/kernel/entry_32.S

  /*

   * Build the entry stubs and pointer table with some assembler magic.

   * We pack 7 stubs into a single 32-byte chunk, which will fit in a

   * single cache line on all modern x86 implementations.

   */

  .section .init.rodata,"a"

  ENTRY(interrupt)

  .text

      .p2align 5

      .p2align CONFIG_X86_L1_CACHE_SHIFT

  ENTRY(irq_entries_start) 

      RING0_INT_FRAME

  vector=FIRST_EXTERNAL_VECTOR

  .rept (NR_VECTORS-FIRST_EXTERNAL_VECTOR+6)/7

      .balign 32

    .rept 7

      .if vector < NR_VECTORS

        .if vector <> FIRST_EXTERNAL_VECTOR

      CFI_ADJUST_CFA_OFFSET -4

        .endif

  1:  pushl $(~vector+0x80)   /* Note: always in signed byte range */

      CFI_ADJUST_CFA_OFFSET 4

        .if ((vector-FIRST_EXTERNAL_VECTOR)%7) <> 6

      jmp 2f

        .endif

        .previous

      .long 1b

        .text

  vector=vector+1

      .endif

    .endr

  2:  jmp common_interrupt

  .endr

  END(irq_entries_start)

 

  .previous

  END(interrupt)

  .previous

 

  /*

   * the CPU automatically disables interrupts when executing an IRQ vector,

   * so IRQ-flags tracing has to follow that:

   */

      .p2align CONFIG_X86_L1_CACHE_SHIFT

  common_interrupt:

      addl $-0x80,(%esp)  /* Adjust vector into the [-256,-1] range */

      SAVE_ALL

      TRACE_IRQS_OFF

      movl %esp,%eax

      call do_IRQ

      jmp ret_from_intr

  ENDPROC(common_interrupt)

 

中斷處理入口http://www.cnblogs.com/hustcat/archive/2009/08/14/1546011.html

由上節(jié)可知,,中斷向量的對(duì)應(yīng)的處理程序位于interrupt數(shù)組中,,下面來看看interrupt:

341 .data #數(shù)據(jù)段

342 ENTRY(interrupt)

343 .text

344

345 vector=0

346 ENTRY(irq_entries_start)

347 .rept NR_IRQS #348-354行重復(fù)NR_IRQS次

348 ALIGN

349 1: pushl $vector-256 #vector在354行遞增

350 jmp common_interrupt #所有的外部中斷處理函數(shù)的統(tǒng)一部分,,以后再講述

351 .data

352 .long 1b #存儲(chǔ)著指向349行的地址,,但是隨著348行-354被gcc展開,,每次的值都不同

353 .text

354 vector=vector+1

355 .endr #與347行呼應(yīng)

356

357 ALIGN

 

#公共處理函數(shù)

common_interrupt:

SAVE_ALL /*寄存器值入棧*/

movl %esp,%eax /*棧頂指針保存到eax*/

call do_IRQ /*處理中斷*/

jmp ret_from_intr /*從中斷返回*/

分析如下:

首先342行和352行都處于.data段,,雖然看起來它們是隔開的,但實(shí)際上被gcc安排在了連續(xù)的數(shù)據(jù)段內(nèi)存中,,同理在代碼段內(nèi)存中,,354行與350行的指令序列也是連續(xù)存儲(chǔ)的。另外,,348-354行會(huì)被gcc展開NR_IRQS次,,因此每次352行都會(huì)存儲(chǔ)一個(gè)新的指針,,該指針指向每個(gè)349行展開的新對(duì)象。最后在代碼段內(nèi)存中連續(xù)存儲(chǔ)了NR_IRQS個(gè)代碼片斷,,首地址由 irq_entries_start指向,。而在數(shù)據(jù)段內(nèi)存中連續(xù)存儲(chǔ)了NR_IRQS個(gè)指針,首址存儲(chǔ)在interrupt這個(gè)全局變量中,。這樣,,例如 IRQ號(hào)是0 (從init_IRQ()調(diào)用,它對(duì)應(yīng)的中斷向量是FIRST_EXTERNAL_VECTOR)的中斷通過中斷門后會(huì)觸發(fā) interrput[0],,從而執(zhí)行:

pushl 0-256

jmp common_interrupt

的代碼片斷,,進(jìn)入到Linux內(nèi)核安排好的中斷入口路徑。

 

中斷回調(diào)函數(shù)基本格式如下

1:  pushl $(~vector+0x80)

jmp common_interrupt

SAVE_ALL

call do_IRQ

jmp ret_from_intr

 

arch/x86/kernel/irq.c

  /*

   * do_IRQ handles all normal device IRQ's (the special

   * SMP cross-CPU interrupts have their own specific

   * handlers).

   */

  unsigned int __irq_entry do_IRQ(struct pt_regs *regs)

irq_enter();

arch/x86/kernel/irq_32.c

handle_irq(irq, regs)

desc = irq_to_desc(irq);

if (!execute_on_irq_stack(overflow, desc, irq)) {

          if (unlikely(overflow))

              print_stack_overflow();

          desc->handle_irq(irq, desc);

      } 

 

irq_exit();

 

  arch/x86/kernel/irq_32.c

     execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)

  {

      union irq_ctx *curctx, *irqctx;

      u32 *isp, arg1, arg2;

 

      curctx = (union irq_ctx *) current_thread_info();

      irqctx = __get_cpu_var(hardirq_ctx);

     

      /* 

       * this is where we switch to the IRQ stack. However, if we are

       * already using the IRQ stack (because we interrupted a hardirq

       * handler) we can't do that and just have to keep using the

       * current stack (which is the irq stack already after all)

       */

      if (unlikely(curctx == irqctx))

          return 0;

         

      /* build the stack frame on the IRQ stack */

      isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));

      irqctx->tinfo.task = curctx->tinfo.task;

      irqctx->tinfo.previous_esp = current_stack_pointer;

     

      /*

        * Copy the softirq bits in preempt_count so that the

       * softirq checks work in the hardirq context.

       */

      irqctx->tinfo.preempt_count =

          (irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |

          (curctx->tinfo.preempt_count & SOFTIRQ_MASK);

 

      if (unlikely(overflow))

          call_on_stack(print_stack_overflow, isp);

/*

  *  isp為上邊計(jì)算出的棧地址,,將其存入ebx,并通過xchgl存入esp,從而將原來的棧地址保存到

  *  ebx,而新棧變?yōu)?/SPAN>isp, 在新棧上執(zhí)行desc->handle_irq,,執(zhí)行結(jié)束后,,從ebx中恢復(fù)原棧。

  */

      asm volatile("xchgl %%ebx,%%esp \n"

               "call  *%%edi      \n"

               "movl  %%ebx,%%esp \n"

               : "=a" (arg1), "=d" (arg2), "=b" (isp)

               :  "0" (irq),   "1" (desc),  "2" (isp),

              "D" (desc->handle_irq)

               : "memory", "cc", "ecx");

      return 1;

  }

 

typedef struct irq_desc {

unsigned int status; /* IRQ status */

hw_irq_controller *handler;

struct irqaction *action; /* IRQ action list */

unsigned int depth; /* nested irq disables */

unsigned int irq_count; /* For detecting broken interrupts */

unsigned int irqs_unhandled;

spinlock_t lock;

} ____cacheline_aligned irq_desc_t;

 

desc->handle_irq的初始化過程如下:

arch/x86/kernel/irqinit.c

init_IRQ(void)

x86_init.irqs.intr_init();

void __init native_init_IRQ(void)

x86_init.irqs.pre_vector_init();

arch/x86/kernel/irqinit.c

void __init init_ISA_irqs(void)

set_irq_chip_and_handler_name

desc->handle_irq=handle_level_irq

 

handle_level_irq(unsigned int irq, struct irq_desc *desc)

mask_ack_irq(desc, irq);

desc->chip->mask_ack(irq);

if (unlikely(desc->status & IRQ_INPROGRESS))

goto out_unlock;

action = desc->action;

desc->status |= IRQ_INPROGRESS;

 

kernel/irq/handle.c

handle_IRQ_event(irq, action);

if (!(action->flags & IRQF_DISABLED))

          local_irq_enable_in_hardirq();

do {

action->handler(irq, action->dev_id);

action = action->next;

} while (action);

desc->status &= ~IRQ_INPROGRESS;

if (!(desc->status & (IRQ_DISABLED | IRQ_ONESHOT)))

          unmask_irq(desc, irq);

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多