Linux时钟与时间初始流程
触发其他CPU启动 clocksource发生切换后 tick_periodic()函数中会感知 start_kernel timekeeping_init() rest_init() time_init() late_time_init() 实际上调用x86_late_time_init() kernel_init() if (!hpet_enable()) setup_pit_timer(); late_time_init = x86_late_time_init 从persistent_clock设备读取时间,初始化timekeeper 时钟源指向clocksource_jiffies,基于从persistent_clock所读取的 时间设置墙上时间 tsc_init() 会通过cpuid指令获取cpu freq和tsc freq setup_default_timer_irq() kernel_init_freeable() smp_prepare_cpus() clockevents_config_and_register(&i8253_clocevent) x86_init.timers.setup_percpu_clockdev() 实际上调用setup_boot_APIC_clock() clockevents_register_device(lapic_devents) smp_init() for_each_present_cpu(cpu) cpu_up(cpu) __cpu_up() 实际上调用native_cpu_up() do_boot_cpu(cpu) start_secondary() x86_cpuinit.setup_percpu_clockev(); 实际为 setup_secondary_APIC_clock setup_APIC_timer() clockevents_register_device(lapic_devents) do_basic_setup() do_initcalls() for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) do_initcall_level(level); init_tsc_clocksource() 若tsc为reliable(即cpu进入C3 state时不会停止) 则直接注册(clock_source_register(tsc_clocksource)) 否则在delay work中进行修正,修正后再注册 对于CONTINUOUS的clocksource,可以用作HRES时间, timekeeping机制选用此类clocksource后,tick device可以 切换为NOHZ模式(根据需要切换为LOWRES或者HIRES) setup_arch(&command_line) kvmclock_init() tick_periodic() 由periodic模式切换为ONESHOT模式