时间子系统1_lapic时钟初始化

//	参考:http://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,
};
时间: 2024-11-30 17:41:06

时间子系统1_lapic时钟初始化的相关文章

时间子系统10_hpet时钟初始化

// 时钟mult :mult/2^shift = ns/cyc // 参考:http://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 = { ... //时钟初始化 .timers = { .setup_percpu_clockev = setup_boot_API

时间子系统11_tsc时钟初始化

// tsc时钟源初始化 // 调用路径:time_init->tsc_init // 函数任务: // 1.矫正tsc,获取tsc频率,设置cpu频率等于tsc频率 // 2.初始化基于tsc的延迟函数 // 3.检查tsc的特性 // 3.1 tsc之间是否同步 // 3.1.1 如果tsc之间不同步,标记tsc不稳定,设置rating=0 // 3.2 tsc是否稳定 // 4.注册tsc时钟源设备 1.1 void __init tsc_init(void) { u64 lpj; int

Linux时间子系统之八:动态时钟框架(CONFIG_NO_HZ、tickless)【转】

转自:http://blog.csdn.net/droidphone/article/details/8112948 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] 数据结构 低分辨率下的动态时钟 1  切换至动态时钟模式 2  低分辨率动态时钟下的事件中断处理函数 3  动态时钟停止周期tick时钟事件 3  动态时钟重新开启周期tick时钟事件 高精度模式下的动态时钟 动态时钟对中断的影响   在前面章节的讨论中,我们一直基于一个假设:Linux中的时钟事件都是由

时间子系统12_clockevent设备注册

// 向系统注册时钟事件设备 // 函数任务: // 1.添加设备到clockevent_devices链表 // 2.通知tick device管理机制有clockevent设备注册 1.1 void clockevents_register_device(struct clock_event_device *dev) { unsigned long flags; raw_spin_lock_irqsave(&clockevents_lock, flags); //将设备添加到clockeve

时间子系统7_高分辨率定时器处理

// 高分辨率下的定时器软中断 // 当增加一个hrtimer到rbtree中后,会raise高分辨率定时器软中断 // 函数任务: // 1.关中断下,运行所有hrtimer // 注: // 在hrtimers_init中,open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq); 1.1 static void run_hrtimer_softirq(struct softirq_action *h) { //遍历运行所有到期的hrtimer h

bootloader功能介绍/时钟初始化设置/串口工作原理/内存工作原理/NandFlash工作原理

bootloader功能介绍 初始化开发板上主要硬件(时钟,内存,硬盘), 把操作系统从硬盘拷贝到内存,然后让cpu跳转到内存中执行操作系统. boot阶段 1.关闭影响CPU正常执行的外设 -关闭看门狗(watch dog)   WTCON 0xE2700000 -关闭中断 CPSR I和F位设置为1,关闭,不响应任何中断. 2.初始化时钟 -倍频到1Ghz,为外设分频 *串口驱动 3.初始化内存控制器,DDRAM -验证内存,往里面写一个值,然后再读出来 4.初始化硬盘,nand Flash

stm32-写一段程序完成处理器STM32F103ZET6的时钟初始化

问题描述 写一段程序完成处理器STM32F103ZET6的时钟初始化 使用IAR或者Keil软件写一段程序完成处理器STM32F103ZET6的时钟初始化,处理器使用内部8M时钟晶振,将处理器的主频设置为48M. 解决方案 http://zhidao.baidu.com/link?url=WA92iLQny_9QqfgOj5ISNYCyKfHUvS_MmYAg9CBg33k88Vxq_WXsR3GrO5zZtiwRMLDmclk8j3-M0IMAMVI2g_WaeYZJtYt8CEOKuvapD

C8051F的单片机调试时,在时钟初始化中 OSCICN = 0x88;语句出现问题

问题描述 C8051F的单片机调试时,在时钟初始化中 OSCICN = 0x88;语句出现问题 单片机开发的新手,真心求助各位前辈 代码附在下面,遇到的问题是在用keil debug的时候, OSCICN = 0x88;这句话会卡住很久,之后程序会被复位,无法往下进行 改成OSCICN = 0x08;以后debug运行到这一句就会自动退出调试界面 代码如下,用途是使用串口发一个编号: #include #include #define BAUDRATE 9600 #define Fosc 221

《云数据管理》2.1逻辑时间和Lamport时钟

本节书摘来自华章出版社<云数据管理>一书中的第2章,第1节,作者迪卫艾肯特·阿格拉沃尔,更多章节内容可以访问"华章计算机"公众号查看 2.1.1 逻辑时间和Lamport时钟 Lamport于1978年在他的一篇代表性论文里提出了一个简单的分布式系统模型[Lamport, 1978].该模型中,进程被建模成一个全序事件的序列.事件分为本地(local)事件.发送(send)事件和接收(receive)事件.发送事件负责发送消息,该消息由相应的接收事件接收.本地事件是非通信事