zoukankan      html  css  js  c++  java
  • 部分中断相关函数浅析

    1. /kernel/irq.c softirq_init 2.6.32.25

    1.1 for_each_possible_cpu

    for ( ( ( cpu ) ) = - 1 ; ( ( cpu ) ) = cpumask_next ( ( ( cpu ) ) , ( cpu_possible_mask ) ) , ( ( cpu ) ) < nr_cpu_ids ; )

    1.2 per_cpu(tasklet_vec, cpu);

    //取per_cpu_tasklet_vec[cpu],即cpu的tasklet_vec结构。

    per_cpu(tasklet_vec, cpu);

    ( * ( { unsigned long __ptr ; __ptr = ( unsigned long ) ( ( & per_cpu__tasklet_vec ) ) ; ( typeof ( ( & per_cpu__tasklet_vec ) ) ) ( __ptr + ( ( ( __per_cpu_offset [ cpu ] ) ) ) ) ; } ) ) ;

    1.3 tasklet_vec / tasklet_hi_vec

    clip_image002

    static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);

     

    static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);

    static __attribute__ ( ( section ( ".data.percpu" ) ) ) __typeof__ ( struct tasklet_head ) per_cpu__tasklet_vec ;

    clip_image004

    static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);

    static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);

    static __attribute__ ( ( section ( ".data.percpu" ) ) ) __typeof__ ( struct tasklet_head ) per_cpu__tasklet_hi_vec ;

    struct tasklet_head

    struct tasklet_head{

    struct tasklet_struct *head;

    struct tasklet_struct **tail;

    };

    struct tasklet_struct

    struct tasklet_struct{

    struct tasklet_struct *next;

    unsigned long state;

    atomic_t count;

    void (*func)(unsigned long);

    unsigned long data;

    };

    1.4 softirq_work_list

    DECLARE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);

    DECLARE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);

    extern __attribute__ ( ( section ( ".data.percpu" ) ) ) __typeof__ ( struct list_head [ NR_SOFTIRQS ] ) per_cpu__softirq_work_list ;

    DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);

    DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);

    __attribute__ ( ( section ( ".data.percpu" ) ) ) __typeof__ ( struct list_head [ NR_SOFTIRQS ] ) per_cpu__softirq_work_list ;

    1.5 x86_init

    extern struct x86_init_ops x86_init;

    struct x86_init_ops {

    struct x86_init_resources resources;

    struct x86_init_mpparse mpparse;

    struct x86_init_irqs irqs;

    struct x86_init_oem oem;

    struct x86_init_paging paging;

    struct x86_init_timers timers;

    };

    struct x86_init_resources {

    void (*probe_roms)(void);

    void (*reserve_resources)(void);

    char *(*memory_setup)(void);

    };

    struct x86_init_mpparse {

    void (*mpc_record)(unsigned int mode);

    void (*setup_ioapic_ids)(void);

    int (*mpc_apic_id)(struct mpc_cpu *m);

    void (*smp_read_mpc_oem)(struct mpc_table *mpc);

    void (*mpc_oem_pci_bus)(struct mpc_bus *m);

    void (*mpc_oem_bus_info)(struct mpc_bus *m, char *name);

    void (*find_smp_config)(unsigned int reserve);

    void (*get_smp_config)(unsigned int early);

    };

    struct x86_init_irqs {

    void (*pre_vector_init)(void);

    void (*intr_init)(void);

    void (*trap_init)(void);

    };

    struct x86_init_oem {

    void (*arch_setup)(void);

    void (*banner)(void);

    };

    struct x86_init_paging {

    void (*pagetable_setup_start)(pgd_t *base);

    void (*pagetable_setup_done)(pgd_t *base);

    };

    struct x86_init_timers {

    void (*setup_percpu_clockev)(void);

    void (*tsc_pre_init)(void);

    void (*timer_init)(void);

    };

    1.6 test_and_set_bit

    BTS—Bit Test and Set

    Description:

    Selects the bit in a bit string (specified with the first operand, called the bit base) at the bit-position designated by the bit offset operand (second operand), stores the value of the bit in the CF flag, and sets the selected bit in the bit string to 1. The bit base operand can be a register or a memory location; the bit offset operand can be a register or an immediate value:

    • If the bit base operand specifies a register, the instruction takes the modulo 16, 32, or 64 of the bit offset operand (modulo size depends on the mode and register size; 64-bit operands are available only in 64-bit mode). This allows any bit position to be selected.

    • If the bit base operand specifies a memory location, the operand represents the address of the byte in memory that contains the bit base (bit 0 of the specified byte) of the bit string. The range of the bit position that can be referenced by the offset operand depends on the operand size.

    See also: Bit(BitBase, BitOffset) on page 3-14.

    Some assemblers support immediate bit offsets larger than 31 by using the imme-diate bit offset field in combination with the displacement field of the memory operand. See “BT—Bit Test” in this chapter for more information on this addressing mechanism.

    This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.

    In 64-bit mode, the instruction’s default operation size is 32 bits. Using a REX prefix in the form of REX.R permits access to additional registers (R8-R15). Using a REX prefix in the form of REX.W promotes operation to 64 bits. See the summary chart at the beginning of this section for encoding data and limits.

    Operation

    CF ← Bit(BitBase, BitOffset);

    Bit(BitBase, BitOffset) ← 1;

    Flags Affected

    The CF flag contains the value of the selected bit before it is set. The ZF flag is unaf-

    fected. The OF, SF, AF, and PF flags are undefined.

    SBB—Integer Subtraction with Borrow;

    Description:

    Adds the source operand (second operand) and the carry (CF) flag, and subtracts the result from the destination operand (first operand). The result of the subtraction is stored in the destination operand. The destination operand can be a register or a memory location; the source operand can be an immediate, a register, or a memory location. (However, two memory operands cannot be used in one instruction.) The state of the CF flag represents a borrow from a previous subtraction.

    When an immediate value is used as an operand, it is sign-extended to the length of the destination operand format.

    The SBB instruction does not distinguish between signed or unsigned operands. Instead, the processor evaluates the result for both data types and sets the OF and CF flags to indicate a borrow in the signed or unsigned result, respectively. The SF flag indicates the sign of the signed result.

    The SBB instruction is usually executed as part of a multibyte or multiword subtrac-tion in which a SUB instruction is followed by a SBB instruction.

    This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.

    In 64-bit mode, the instruction’s default operation size is 32 bits. Using a REX prefix in the form of REX.R permits access to additional registers (R8-R15). Using a REX prefix in the form of REX.W promotes operation to 64 bits. See the summary chart at the beginning of this section for encoding data and limits.

    Operation

    DEST ← (DEST – (SRC + CF));

    Flags Affected

    The OF, SF, ZF, AF, PF, and CF flags are set according to the result.

    // \linux-2.6.32.25\arch\x86\include\asm\ bitops.h

    static inline int test_and_set_bit(int nr, volatile unsigned long *addr){

    int oldbit;

    asm volatile(LOCK_PREFIX "bts %2,%1\n\t"

    "sbb %0,%0" : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");

    return oldbit;

    }

    #define ADDR BITOP_ADDR(addr)

    #define BITOP_ADDR(x) "=m" (*(volatile long *) (x))

    #define LOCK_PREFIX \

    ".section .smp_locks,\"a\"\n" \

    _ASM_ALIGN "\n" \

    _ASM_PTR "661f\n" /* address */ \

    ".previous\n" \

    "661:\n\tlock; "

    #define _ASM_ALIGN __ASM_SEL(.balign 4, .balign 8)

    #define _ASM_PTR __ASM_SEL(.long, .quad)

    #define __ASM_SEL(a,b) __ASM_FORM(a)

    #ifdef __ASSEMBLY__

    #define __ASM_FORM(x) x

    #define __ASM_EX_SEC .section __ex_table, "a"

    #else

    # define __ASM_FORM(x) " " #x " "

    # define __ASM_EX_SEC " .section __ex_table,\"a\"\n"

    #endif

    LOCK_PRIFIX根据宏定义展开过后为:".section .smp_locks,\"a\"\n .balign 4 \n .long 661f\n.previous\n661:\n\tlock; " ;

    //\linux-2.6.32.25\include\asm-generic\bitops\ atomic.h

    static inline int test_and_set_bit(int nr, volatile unsigned long *addr)

    {

    unsigned long mask = BIT_MASK(nr);

    unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);

    unsigned long old;

    unsigned long flags;

    _atomic_spin_lock_irqsave(p, flags);

    old = *p;

    *p = old | mask;

    _atomic_spin_unlock_irqrestore(p, flags);

    return (old & mask) != 0;

    }

    有两个test_and_set_bit定义,一直搞不清楚到底是用的哪一个,什么时候用哪一个?分析了第一个,第二个还没来得及分析。

    2. raise_softirq_irqoff softirq.c 2.6.38.2

    2.1 重要宏定义和数据结构

    1. /*Softirq.c*/

    2. void raise_softirq(unsigned int nr)

    3. {

    4. unsigned long flags;

    5.

    6. local_irq_save(flags);

    7. raise_softirq_irqoff(nr);

    8. local_irq_restore(flags);

    9. }

    10.

    11. /*Softirq.c*/

    12. inline void raise_softirq_irqoff(unsigned int nr)

    13. {

    14. __raise_softirq_irqoff(nr);

    15.

    16. /*

    17. * If we're in an interrupt or softirq, we're done

    18. * (this also catches softirq-disabled code). We will

    19. * actually run the softirq once we return from

    20. * the irq or softirq.

    21. *

    22. * Otherwise we wake up ksoftirqd to make sure we

    23. * schedule the softirq soon.

    24. */

    25. if (!in_interrupt())

    26. wakeup_softirqd();

    27. }

    28.

    29. /*include/linux/Interrupt.h*/

    30. static inline void __raise_softirq_irqoff(unsigned int nr)

    31. {

    32. trace_softirq_raise(nr);

    33. or_softirq_pending(1UL << nr);

    34. }

    35.

    36. /*include/linux/Interrupt.h*/

    37. #ifndef __ARCH_SET_SOFTIRQ_PENDING

    38. #define set_softirq_pending(x) (local_softirq_pending() = (x))

    39. #define or_softirq_pending(x) (local_softirq_pending() |= (x))

    40. #endif

    41.

    42.

    43. /*include/linux/Interrupt.h*/

    44. #ifndef __ARCH_IRQ_STAT

    45. extern irq_cpustat_t irq_stat[]; /* defined in asm/hardirq.h */

    46. #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member)

    47. #endif

    48.

    49. /* arch independent irq_stat fields */

    50. #define local_softirq_pending() \

    51. __IRQ_STAT(smp_processor_id(), __softirq_pending)

    52. /********************************************************/

    53. /*arch/x86/include/asm/Hardirq.h*/

    54. typedef struct {

    55. unsigned int __softirq_pending;

    56. unsigned int __nmi_count; /* arch dependent */

    57. unsigned int irq0_irqs;

    58. #ifdef CONFIG_X86_LOCAL_APIC

    59. unsigned int apic_timer_irqs; /* arch dependent */

    60. unsigned int irq_spurious_count;

    61. #endif

    62. unsigned int x86_platform_ipis; /* arch dependent */

    63. unsigned int apic_perf_irqs;

    64. unsigned int apic_irq_work_irqs;

    65. #ifdef CONFIG_SMP

    66. unsigned int irq_resched_count;

    67. unsigned int irq_call_count;

    68. unsigned int irq_tlb_count;

    69. #endif

    70. #ifdef CONFIG_X86_THERMAL_VECTOR

    71. unsigned int irq_thermal_count;

    72. #endif

    73. #ifdef CONFIG_X86_MCE_THRESHOLD

    74. unsigned int irq_threshold_count;

    75. #endif

    76. } ____cacheline_aligned irq_cpustat_t;

    77.

    78. DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);

    79.

    80. /*include/linux/percpu_defs.h*/

    81. #define DECLARE_PER_CPU_SHARED_ALIGNED(type, name) \

    82. DECLARE_PER_CPU_SECTION(type, name, PER_CPU_SHARED_ALIGNED_SECTION) \

    83. ____cacheline_aligned_in_smp

    84. #define DECLARE_PER_CPU_SECTION(type, name, sec) \

    85. extern __PCPU_ATTRS(sec) __typeof__(type) name

    86.

    87. #define __PCPU_DUMMY_ATTRS \

    88. __attribute__((section(".discard"), unused))

    89.

    90. #define __PCPU_ATTRS(sec) \

    91. __percpu __attribute__((section(PER_CPU_BASE_SECTION sec))) \

    92. PER_CPU_ATTRIBUTES

    93.

    94.

    95. /*include/asm-generic/Percpu.h*/

    96. #define PER_CPU_SHARED_ALIGNED_SECTION "..shared_aligned"

    97.

    98. #ifndef PER_CPU_ATTRIBUTES

    99. #define PER_CPU_ATTRIBUTES

    100. #endif

    101. /*include/linux/Cache.h*/

    102. #define ____cacheline_aligned_in_smp ____cacheline_aligned

    103.

    104.

    105. /*include/linux/compiler.h*/

    106. # define __percpu

    2.2 or_softirq_pending ( 1UL << nr ) ;

    ( irq_stat [ smp_processor_id ( ) ] . __softirq_pending ) |= ( 1UL << nr ) ) ;

    2.3 local_softirq_pending();

    ( irq_stat [ smp_processor_id ( ) ] . __softirq_pending ) ;

    2.4 DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);

    extern __attribute__ ( ( section ( PER_CPU_BASE_SECTION "..shared_aligned" ) ) ) __typeof__ ( irq_cpustat_t ) irq_stat ____cacheline_aligned ;

    2.5 irq_cpustat_t

    /*arch/x86/include/asm/Hardirq.h*/

    typedef struct {

    unsigned int __softirq_pending;

    unsigned int __nmi_count; /* arch dependent */

    unsigned int irq0_irqs;

    #ifdef CONFIG_X86_LOCAL_APIC

    unsigned int apic_timer_irqs; /* arch dependent */

    unsigned int irq_spurious_count;

    #endif

    unsigned int x86_platform_ipis; /* arch dependent */

    unsigned int apic_perf_irqs;

    unsigned int apic_irq_work_irqs;

    #ifdef CONFIG_SMP

    unsigned int irq_resched_count;

    unsigned int irq_call_count;

    unsigned int irq_tlb_count;

    #endif

    #ifdef CONFIG_X86_THERMAL_VECTOR

    unsigned int irq_thermal_count;

    #endif

    #ifdef CONFIG_X86_MCE_THRESHOLD

    unsigned int irq_threshold_count;

    #endif

    } ____cacheline_aligned irq_cpustat_t;

    2.6 流程总结

    clip_image005

    clip_image007

    clip_image009

  • 相关阅读:
    调试
    webpack output的path publicPath
    CSS实现单行、多行文本溢出显示省略号
    docker安装mysql
    构建docker镜像
    Tensorflow博文列表
    ML理论知识博文列表
    Python博文列表
    Opencv博文收藏列表
    Centos文章列表
  • 原文地址:https://www.cnblogs.com/justinzhang/p/2109930.html
Copyright © 2011-2022 走看看