253
技術社區[雲棲]
時間子係統1_lapic時鍾初始化
// 參考:https://www.bluezd.info/archives/reg_clock_event_device_1 // x86平台初始化 // 注:arch/x86/kernel/x86_init.c 1.1 struct x86_init_ops x86_init __initdata = { ... //apic控製器初始化 .irqs = { .pre_vector_init = init_ISA_irqs, .intr_init = native_init_IRQ, .trap_init = x86_init_noop, }, ... }; // 中斷初始化 // 調用路徑:start_kernel->init_IRQ 1.2 void __init init_IRQ(void) { //中斷初始化 ... x86_init.irqs.intr_init(); } // x86體係結構中斷初始化 // 函數任務: // 1.初始化isa 0~15號中斷 // 2.初始化apic中斷 1.3 void __init native_init_IRQ(void) { int i; //初始化isa 0~15號中斷 x86_init.irqs.pre_vector_init(); //初始化apic中斷 apic_intr_init(); ... } // apic中斷初始化 // 函數任務: // 1.smp 中斷初始化 // 2.lapic時鍾中斷初始化 // 3.x86平台專用ipi // 4.其他 1.4 static void __init apic_intr_init(void) { //smp 中斷初始化 smp_intr_init(); ... #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC) //lapic時鍾中斷初始化 alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); //x86平台專用ipi alloc_intr_gate(X86_PLATFORM_IPI_VECTOR, x86_platform_ipi); ... #endif } // smp ipi中斷初始化 // 函數任務: // 1.cpu間重調度ipi // 2.cpu間函數調用ipi // 3.係統關機,重啟ipi // 4.其他 1.5 static void __init smp_intr_init(void) { #ifdef CONFIG_SMP #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC) //cpu間重調度ipi,由wake_up驅動 alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt); //cpu間函數調用ipi,通知其他cpu在中斷上下文執行某函數 alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR, call_function_single_interrupt); //係統關機,重啟ipi alloc_intr_gate(REBOOT_VECTOR, reboot_interrupt); #endif #endif } // lapic時鍾中斷 // 注:#define LOCAL_TIMER_VECTOR 0xef 1.6 void __irq_entry smp_apic_timer_interrupt(struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); //ack irq ack_APIC_irq(); //如果本cpu上運行idle進程,退出idle狀態 exit_idle(); irq_enter(); //lapic的時鍾處理函數 local_apic_timer_interrupt(); irq_exit(); set_irq_regs(old_regs); } // lapic時鍾中斷處理程序 // 函數任務: // 1.檢查是否為錯誤的中斷信號 // 1.1 lapic中斷比lapic時鍾源先使能,因此產生中斷時, // 可能相應的事件處理函數還沒有建立,此時,關閉時鍾源,退出處理 // 2.統計apic中斷次數 // 3.執行apic事件處理函數 1.7 static void local_apic_timer_interrupt(void) { int cpu = smp_processor_id(); //lapic per-cpu clockevent 設備 struct clock_event_device *evt = &per_cpu(lapic_events, cpu); //lapic中斷比lapic時鍾源先使能,因此產生中斷時,可能相應的事件處理函數還沒有建立 if (!evt->event_handler) { //錯誤的中斷信號,關閉時鍾源 pr_warning("Spurious LAPIC timer interrupt on cpu %d\n", cpu); lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, evt); return; } //apic中斷統計 inc_irq_stat(apic_timer_irqs); //執行apic事件處理函數 evt->event_handler(evt); } // 創建lapic時鍾源 // 函數任務: // 1.設置lapic服務當前cpu // 2.注冊lapic設備 2.1 static void __cpuinit setup_APIC_timer(void) { //本cpu的lapic struct clock_event_device *levt = &__get_cpu_var(lapic_events); //lapic受省電模式C3的影響 if (cpu_has(¤t_cpu_data, X86_FEATURE_ARAT)) { lapic_clockevent.features &= ~CLOCK_EVT_FEAT_C3STOP; lapic_clockevent.rating = 150; } //lapic_clockevent作為所有lapic clockevent模板 memcpy(levt, &lapic_clockevent, sizeof(*levt)); //lapic服務的cpu levt->cpumask = cpumask_of(smp_processor_id()); //注冊lapic設備 clockevents_register_device(levt); } // lapic clockevent設備 // 注:lapic在注冊時,默認關閉狀態 2.1 static struct clock_event_device lapic_clockevent = { .name = "lapic", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY, .shift = 32, .set_mode = lapic_timer_setup, .set_next_event = lapic_next_event, .broadcast = lapic_timer_broadcast, .rating = 100, .irq = -1, };
最後更新:2017-04-03 14:54:27