//分析的内容包括中断和软中断的处理,版本基于android2.3
asmlinkage void __init start_kernel(void)
{
setup_arch(&command_line);//跟踪调用链(1)
init_IRQ();//跟踪调用链(2)
softirq_init();//跟踪调用链(3)
}
//跟踪调用链(1)
void __init setup_arch(char **cmdline_p)
{
............
init_arch_irq = mdesc->init_irq;
early_trap_init();//跟踪调用链(1)
}
//跟踪调用链(1),初始化整个中断处理向量,把中断向量拷贝到0xffff0000地方
void __init early_trap_init(void)
{
unsigned long vectors = CONFIG_VECTORS_BASE;//#define CONFIG_VECTORS_BASE 0xffff0000
extern char __stubs_start[], __stubs_end[];
extern char __vectors_start[], __vectors_end[];
/*
* Copy the vectors, stubs and kuser helpers (in entry-armv.S)
* into the vector page, mapped at 0xffff0000, and ensure these
* are visible to the instruction stream.
*/
memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);//异常向量代码
memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);//更复杂的代码
}
//异常向量代码和跳转代码
.globl __stubs_start
__stubs_start:
/*
* Interrupt dispatcher
*/
vector_stub irq, IRQ_MODE, 4
.long __irq_usr @ 0 (USR_26 / USR_32)
.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
vector_stub dabt, ABT_MODE, 8
.long __dabt_usr @ 0 (USR_26 / USR_32)
.long __dabt_invalid @ 1 (FIQ_26 / FIQ_32)
.long __dabt_invalid @ 2 (IRQ_26 / IRQ_32)
.long __dabt_svc @ 3 (SVC_26 / SVC_32)
.long __dabt_invalid @ 4
.long __dabt_invalid @ 5
.long __dabt_invalid @ 6
.long __dabt_invalid @ 7
.long __dabt_invalid @ 8
.long __dabt_invalid @ 9
.long __dabt_invalid @ a
.long __dabt_invalid @ b
.long __dabt_invalid @ c
.long __dabt_invalid @ d
.long __dabt_invalid @ e
.long __dabt_invalid @ f
vector_stub pabt, ABT_MODE, 4
.long __pabt_usr @ 0 (USR_26 / USR_32)
.long __pabt_invalid @ 1 (FIQ_26 / FIQ_32)
.long __pabt_invalid @ 2 (IRQ_26 / IRQ_32)
.long __pabt_svc @ 3 (SVC_26 / SVC_32)
.long __pabt_invalid @ 4
.long __pabt_invalid @ 5
.long __pabt_invalid @ 6
.long __pabt_invalid @ 7
.long __pabt_invalid @ 8
.long __pabt_invalid @ 9
.long __pabt_invalid @ a
.long __pabt_invalid @ b
.long __pabt_invalid @ c
.long __pabt_invalid @ d
.long __pabt_invalid @ e
.long __pabt_invalid @ f
vector_stub und, UND_MODE
.long __und_usr @ 0 (USR_26 / USR_32)
.long __und_invalid @ 1 (FIQ_26 / FIQ_32)
.long __und_invalid @ 2 (IRQ_26 / IRQ_32)
.long __und_svc @ 3 (SVC_26 / SVC_32)
.long __und_invalid @ 4
.long __und_invalid @ 5
.long __und_invalid @ 6
.long __und_invalid @ 7
.long __und_invalid @ 8
.long __und_invalid @ 9
.long __und_invalid @ a
.long __und_invalid @ b
.long __und_invalid @ c
.long __und_invalid @ d
.long __und_invalid @ e
.long __und_invalid @ f
.align 5
vector_fiq:
disable_fiq
subs pc, lr, #4
vector_addrexcptn:
b vector_addrexcptn
.align 5
.LCvswi:
.word vector_swi
.globl __stubs_end
__stubs_end:
/*********************************************************************************/
.equ stubs_offset, __vectors_start + 0x200 - __stubs_start
/*********************************************************************************/
__vectors_start:
ARM( swi SYS_ERROR0 )
THUMB( svc #0 )
THUMB( nop )
W(b) vector_und + stubs_offset
W(ldr) pc, .LCvswi + stubs_offset
W(b) vector_pabt + stubs_offset
W(b) vector_dabt + stubs_offset
W(b) vector_addrexcptn + stubs_offset
W(b) vector_irq + stubs_offset
W(b) vector_fiq + stubs_offset
.globl __vectors_end
__vectors_end:
/*********************************************************************************/
////跟踪调用链(2),全局的irq数组
void __init init_IRQ(void)
{
int irq;
for (irq = 0; irq < NR_IRQS; irq++)
irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;
init_arch_irq();////跟踪调用链(2),执行架构的machine里的irq结构体
}
////跟踪调用链(2),板级定义的结构体
MACHINE_START(MSM8X60, "QCT MSM8X60")
#ifdef CONFIG_MSM_DEBUG_UART
.phys_io = MSM_DEBUG_UART_PHYS,
.io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.map_io = msm8x60_map_io,
.init_irq = msm8x60_init_irq,
.timer = &msm_timer,
MACHINE_END
////跟踪调用链(2),对应8x60项目为.init_irq = msm8x60_init_irq,
void __init msm8x60_init_irq(void)
{
for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {//为每一个中断安装入口函数
if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
set_irq_handler(i, handle_percpu_irq);//初始化该平台的irq处理的handler函数
}
}
////跟踪调用链(2)
static inline void set_irq_handler(unsigned int irq, irq_flow_handler_t handle)
{
__set_irq_handler(irq, handle, 0, NULL);
}
////跟踪调用链(2),安装描述符的总处理函数
void __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, const char *name)
{
struct irq_desc *desc = irq_to_desc(irq);
desc->handle_irq = handle;
}
//中断注册流程,以msm_otg里面的一个注册函数为例
ret = request_irq(dev->irq, msm_otg_irq, IRQF_SHARED,"msm_otg", dev);
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)
{
return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}
int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn, unsigned long irqflags,
const char *devname, void *dev_id)
{
struct irqaction *action;
struct irq_desc *desc;
int retval;
/*
* Sanity-check: shared interrupts must pass in a real dev-ID,
* otherwise we'll have trouble later trying to figure out
* which interrupt is which (messes up the interrupt freeing
* logic etc).
*/
if ((irqflags & IRQF_SHARED) && !dev_id)
return -EINVAL;
desc = irq_to_desc(irq);
if (!desc)
return -EINVAL;
action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
if (!action)
return -ENOMEM;
action->handler = handler;//中断处理函数
action->thread_fn = thread_fn;
action->flags = irqflags;//标志位,是否是共享中断?
action->name = devname;
action->dev_id = dev_id;//共享中断时用的区分标志
chip_bus_lock(irq, desc);
retval = __setup_irq(irq, desc, action);//把初始化好的action安装到desc的action链表中
chip_bus_sync_unlock(irq, desc);
if (retval)
kfree(action);
return retval;
}
static int __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
{
struct irqaction *old, **old_ptr;
old_ptr = &desc->action;
old = *old_ptr;
if (old) {//共享中断
/*
* Can't share interrupts unless both agree to and are
* the same type (level, edge, polarity). So both flag
* fields must have IRQF_SHARED set and the bits which
* set the trigger type must match.
*/
if (!((old->flags & new->flags) & IRQF_SHARED) ||
((old->flags ^ new->flags) & IRQF_TRIGGER_MASK)) {
old_name = old->name;
goto mismatch;
}
/* add new interrupt at end of irq queue */
do {
old_ptr = &old->next;
old = *old_ptr;
} while (old);
shared = 1;
}
if (!shared) {
}
/*把新节点加入链表*/
new->irq = irq;
*old_ptr = new;
}
//执行中断,中断处理流程,总入口,由汇编进入该函数
asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
perf_mon_interrupt_in();
irq_enter();
/*
* Some hardware gives randomly wrong interrupts. Rather
* than crashing, do something sensible.
*/
if (unlikely(irq >= NR_IRQS)) {
if (printk_ratelimit())
printk(KERN_WARNING "Bad IRQ%u\n", irq);
ack_bad_irq(irq);
} else {
generic_handle_irq(irq);//通用的处理函数,在这里面处理中断
}
/* AT91 specific workaround */
irq_finish(irq);
irq_exit();//在该函数中调用软中断处理函数
set_irq_regs(old_regs);
perf_mon_interrupt_out();
}
//跟踪上面的调用链
static inline void generic_handle_irq(unsigned int irq)
{
generic_handle_irq_desc(irq, irq_to_desc(irq));
}
//跟踪上面的调用链
static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *desc)
{
#ifdef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
desc->handle_irq(irq, desc);//handle_percpu_irq,调用在板级结构体初始化时的函数
#else
if (likely(desc->handle_irq))
desc->handle_irq(irq, desc);
else
__do_IRQ(irq);
#endif
}
//调用注册的回调函数
void handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
{
action_ret = handle_IRQ_event(irq, desc->action);//处理IRQ
}
irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
{
irqreturn_t ret, retval = IRQ_NONE;
unsigned int status = 0;
do {//循环执行action链表里的handler函数,参数为irq号和注册时的最后一参数
trace_irq_handler_entry(irq, action);
ret = action->handler(irq, action->dev_id);
trace_irq_handler_exit(irq, action, ret);
switch (ret) {
...........
case IRQ_HANDLED:
status |= action->flags;
break;
default:
break;
}
retval |= ret;
action = action->next;
} while (action);
if (status & IRQF_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
local_irq_disable();
return retval;
}
//下面接着分析在中断退出时的软中断处理
void irq_exit(void)
{
if (!in_interrupt() && local_softirq_pending())//不在中断中,并且有软中断挂起
invoke_softirq();//调用软中断处理
}
# define invoke_softirq() __do_softirq()
asmlinkage void __do_softirq(void)
{
struct softirq_action *h;
__u32 pending;
int max_restart = MAX_SOFTIRQ_RESTART;//#define MAX_SOFTIRQ_RESTART 10
int cpu;
pending = local_softirq_pending();//取出软中断挂起位标志变量
account_system_vtime(current);
__local_bh_disable((unsigned long)__builtin_return_address(0));
lockdep_softirq_enter();
cpu = smp_processor_id();
restart:
/* Reset the pending bitmask before enabling irqs */
set_softirq_pending(0);//清除挂起标志位
local_irq_enable();//打开中断,这也是设计软中断的初衷
h = softirq_vec;//软中断处理数组
do {
if (pending & 1) {//取出每一个pending位
int prev_count = preempt_count();
kstat_incr_softirqs_this_cpu(h - softirq_vec);
trace_softirq_entry(h, softirq_vec);
h->action(h);//执行该软中断的处理函数
trace_softirq_exit(h, softirq_vec);
rcu_bh_qs(cpu);
}
h++;
pending >>= 1;
} while (pending);
local_irq_disable();
pending = local_softirq_pending();//再次判断是否有软中断pending
if (pending && --max_restart)//如果一直有,且达到最大次数,如果还有pending的话?
goto restart;
if (pending)//唤醒软中断处理进程帮忙处理
wakeup_softirqd();
lockdep_softirq_exit();
account_system_vtime(current);
_local_bh_enable();
}
//执行tasklet的软中断处理函数,在系统初始化时已经安装
static void tasklet_action(struct softirq_action *a)
{
struct tasklet_struct *list;
/*取出tasklet链表保存到局部变量,并清空tasklet_vec全局链表*/
local_irq_disable();
list = __get_cpu_var(tasklet_vec).head;
__get_cpu_var(tasklet_vec).head = NULL;
__get_cpu_var(tasklet_vec).tail = &__get_cpu_var(tasklet_vec).head;
local_irq_enable();
while (list) {//遍历该list
struct tasklet_struct *t = list;
list = list->next;
if (tasklet_trylock(t)) {
if (!atomic_read(&t->count)) {//看是否使能?
if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))//清除TASKLET_STATE_SCHED
BUG();
t->func(t->data);//执行tasklet处理函数
tasklet_unlock(t);
continue;
}
tasklet_unlock(t);
}
/*如果不满足条件的话,继续加入到全局tasklet_vec链表*/
local_irq_disable();
t->next = NULL;
*__get_cpu_var(tasklet_vec).tail = t;
__get_cpu_var(tasklet_vec).tail = &(t->next);
__raise_softirq_irqoff(TASKLET_SOFTIRQ);
local_irq_enable();
}
}
//驱动软中断的注册分析
enum
{
TASKLET_STATE_SCHED, /* Tasklet is scheduled for execution */
TASKLET_STATE_RUN /* Tasklet is running (SMP only) */
};
static inline void tasklet_schedule(struct tasklet_struct *t)
{
if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))//如果为TASKLET_STATE_SCHED的话不允许再提交
__tasklet_schedule(t);
}
//加入tasklet_vec链表,并置位相应的pending位
void __tasklet_schedule(struct tasklet_struct *t)
{
unsigned long flags;
local_irq_save(flags);
t->next = NULL;
*__get_cpu_var(tasklet_vec).tail = t;
__get_cpu_var(tasklet_vec).tail = &(t->next);
raise_softirq_irqoff(TASKLET_SOFTIRQ);
local_irq_restore(flags);
}
//管理软中断的结构体
/***************************************************************************************/
struct softirq_action
{
void (*action)(struct softirq_action *);
};
//软中断的类型
enum
{
HI_SOFTIRQ=0,
TIMER_SOFTIRQ,
NET_TX_SOFTIRQ,
NET_RX_SOFTIRQ,
BLOCK_SOFTIRQ,
BLOCK_IOPOLL_SOFTIRQ,
TASKLET_SOFTIRQ,
SCHED_SOFTIRQ,
HRTIMER_SOFTIRQ,
RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */
NR_SOFTIRQS
};
//管理软中断的全局变量
static struct softirq_action softirq_vec[NR_SOFTIRQS]
//软中断进行初始化
void __init softirq_init(void)
{
int cpu;
for_each_possible_cpu(cpu) {
int i;
per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head;
per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head;
for (i = 0; i < NR_SOFTIRQS; i++)
INIT_LIST_HEAD(&per_cpu(softirq_work_list[i], cpu));
}
register_hotcpu_notifier(&remote_softirq_cpu_notifier);
//下面分析
open_softirq(TASKLET_SOFTIRQ, tasklet_action);//tasklet的执行函数
open_softirq(HI_SOFTIRQ, tasklet_hi_action);
}
//安装对应软中断的处理函数
void open_softirq(int nr, void (*action)(struct softirq_action *))
{
softirq_vec[nr].action = action;
}
阅读(1774) | 评论(0) | 转发(0) |