首页 > 其他分享 >3.4.3 __ipipe_init_early之初始化root domain

3.4.3 __ipipe_init_early之初始化root domain

时间:2024-09-17 21:49:26浏览次数:13  
标签:__ domain ipd IPI virq IPIPE init ipipe

点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-CSDN博客

3.4.3 __ipipe_init_early之初始化root domain

       如下图所示,红框里面的函数当前都是空的,本章还是分析蓝框中的代码片段。

第295行,变量ipd指向了ipipe_root即ipd代表root domain。

第305行,root domain的名字被命名为“Linux”。

第306行,初始化ipd->context_offset变量,详细分析见《3.4.1.1 IPIPE基础数据结构》。

第307行,调用init_stage(ipd)对root domain进行初始化。此函数只要3行,直接在代码里面进行注释如下:

linux/kernel/ipipe/core.c:
static void init_stage(struct ipipe_domain *ipd)
{
//对ipipe_irqdesc irqs[IPIPE_NR_IRQS]数组进行清零操作。
//此数据结构的意义具体见《3.4.1.2 IPIPE对Linux中断号的改造》
	memset(&ipd->irqs, 0, sizeof(ipd->irqs));

    //对互斥量进行初始化
	mutex_init(&ipd->mutex);

//(1) 调用__ipipe_ipis_alloc()完成所有IPI中断的分配
//(2) 调用hook_internal_ipi设置IPIPE_CRITICAL_IPI
	__ipipe_hook_critical_ipi(ipd);
}

arch/arm64/kernel/ipipe.c:
void __ipipe_hook_critical_ipi(struct ipipe_domain *ipd)
{
	__ipipe_ipis_alloc();
	hook_internal_ipi(ipd, IPIPE_CRITICAL_IPI, __ipipe_do_critical_sync);
}

       init_stage最后调用的函数__ipipe_hook_critical_ipi(ipd),里面做了两件事情,需要展开说一下。

  • 调用__ipipe_ipis_alloc()完成所有IPI中断的分配
arch/arm64/kernel/smp.c:
void __ipipe_ipis_alloc(void)
{
	unsigned int virq, ipi;
	static bool done;

	if (done)
		return;

	/*
	 * We have to get virtual IRQs in the range
	 * [ IPIPE_IPI_BASE..IPIPE_IPI_BASE + NR_IPI + IPIPE_OOB_IPI_NR - 1 ],
	 * otherwise something is wrong (likely someone would have
	 * allocated virqs before we do, and this would break our
	 * fixed numbering scheme for IPIs).
	 */
	for (ipi = 0; ipi < NR_IPI + IPIPE_OOB_IPI_NR; ipi++) {
		virq = ipipe_alloc_virq();
		WARN_ON_ONCE(virq != IPIPE_IPI_BASE + ipi);
	}

	done = true;
}

        根据《3.4.1.2 IPIPE对Linux中断号的改造》的分析,NR_IPI等于7,IPIPE_OOB_IPI_NR等于3,所以for循环调用ipipe_alloc_virq()函数10次,共申请10个virtual interrupt编号。关于virtual interrupt,之前已经总结过了,它的总数量就是IPIPE_NR_VIRQS(64)。为了管理virtual interrupt,IPIPE定义了全局变量 __ipipe_virtual_irq_map,通过位图来标记是否virtual interrupt是否被占用。 

       ipipe_alloc_virq()函数的本质,就是在变量__ipipe_virtual_irq_map的64个bit中,找到第一个为0的bit位(ffz就是find first zero)即空闲的bit位,然后把此bit位设置为1即占用此bit位。从__ipipe_virtual_irq_map中找到的bit位存到变量ipos,必须再加上IPIPE_VIRQ_BASE(1024),才能得到最终的virtual interrupt的编号。

    回到__ipipe_ipis_alloc,它for循环调用ipipe_alloc_virq()函数10次,得到的10个virq是1024~1033. 注意这个范围哦,下一步的IPIPE_CRITICAL_IPI是1031,就在这个范围内!

linux/kernel/ipipe/core.c:
// 共64 bit位,通过位图来标记是否VIRQ是否被占用
static unsigned long __ipipe_virtual_irq_map;

unsigned int ipipe_alloc_virq(void)
{
	unsigned long flags, irq = 0;
	int ipos;

	raw_spin_lock_irqsave(&__ipipe_lock, flags);

	if (__ipipe_virtual_irq_map != ~0) {
		ipos = ffz(__ipipe_virtual_irq_map);
		set_bit(ipos, &__ipipe_virtual_irq_map);
		irq = ipos + IPIPE_VIRQ_BASE;
	}

	raw_spin_unlock_irqrestore(&__ipipe_lock, flags);

	return irq;
}
EXPORT_SYMBOL_GPL(ipipe_alloc_virq);
  • 调用hook_internal_ipi设置IPIPE_CRITICAL_IPI

        IPIPE_CRITICAL_IPI是OOB IPI之一,它对应的virq编号是1031。上一步已经把1031分配出来了,hook_internal_ipi就是来设置IPIPE_CRITICAL_IPI对应的中断处理程序为__ipipe_do_critical_sync()!具体这个函数的用处,后面的章节再分析。

arch/arm64/kernel/ipipe.c:
static inline void
hook_internal_ipi(struct ipipe_domain *ipd, int virq,
		  void (*handler)(unsigned int irq, void *cookie))
{
	ipd->irqs[virq].ackfn = NULL;
	ipd->irqs[virq].handler = handler;
	ipd->irqs[virq].cookie = NULL;
	/* Immediately handle in the current domain but *never* pass */
	ipd->irqs[virq].control = IPIPE_HANDLE_MASK|IPIPE_STICKY_MASK;
}

点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-CSDN博客

原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!

标签:__,domain,ipd,IPI,virq,IPIPE,init,ipipe
From: https://blog.csdn.net/aspirestro/article/details/142308365

相关文章

  • 基于智能体平台搭建交互式陪伴角色
    上一期我们搭建了一个恐怖类的生成式游戏。大家也可以尝试玩一玩。鬼宅惊魂红绣怨辅助玩家探索诡异老宅,生成情节和选项,提供游戏信息,解开谜题,找到出路。https://mbd.baidu.com/ma/s/JQ0zAsYl搭建互动式乙女游戏:智能体的角色陪伴体验在本篇文章中,我们继续探讨如何搭建一个互动......
  • Vue.js入门系列(三十一):Element-UI的基本使用与按需引入、Vue 3简介及使用 Vue CLI 与 V
    个人名片......
  • Vue.js入门系列(三十):深入理解独享路由守卫、组件内路由守卫、History模式与Hash模式
    个人名片......
  • Java 学习 day02
    javaday02DtaaType数据类型Java是一门强类型的语言。1、变量变量:指的是在Java程序运行过程中,其值可以发生改变的量。定义一个变量的语句定义格式://数据类型变量名=初始化值;注意事项:1、变量要进行初始化赋值,才可以进行使用2、在同一作用域下,变量名不能重复,可以大小......
  • 打开SSL后,百度分享就不显示图标了,有好的解决办法吗
    当您启用了SSL证书之后,可能会遇到百度分享按钮不显示的情况,这是因为安全协议的变化可能会导致一些资源加载失败。以下是一些可能的解决方案:确保所有资源都是HTTPS:检查您的网站上的所有资源(图片、脚本、样式表等)是否都已经使用了HTTPS协议加载。如果存在HTTP资源,浏览器可能会......
  • 9.输出国际象棋棋盘。
    【程序9】题目:要求输出国际象棋棋盘。1.程序分析:用i控制行,j来控制列,根据i+j的和的变化来控制输出黑方格,还是白方格。方法一:importsysforiinrange(8):forjinrange(8):if(i+j)%2==0:sys.stdout.write(chr(219))......
  • GYM 105125 C
    题目描述给定\(NM\)个数\(A_1,A_2,\dots,A_{NM}\),你要将这些数分成\(N\)个数组,每个数组\(M\)个数。接着你要将这些数组按字典序排序。对于排序后每个数组求出可能的字典序最小情况。思路我们从字典序的比较上来考虑,并把\(A\)排序。首先考虑当前数组\(i\)的第一位......
  • 能否判断自定义变量是否为空?
    不同的编程语言有不同的方式来判断一个变量是否为空。下面列出了一些常见编程语言中判断变量是否为空的方法:1.Java在Java中,你可以使用多种方法来判断一个变量是否为空:对于对象:检查是否为 null。java if(object==null){System.out.println("变量为空");}对......
  • 网站友情链接,设置新窗口打开无效
    如果网站的友情链接设置为在新窗口中打开但实际点击时并未如此,可能的原因有几个方面:HTML代码问题:确保 <a> 标签中包含了 target="_blank" 属性。这个属性告诉浏览器在点击链接时应在新窗口或新标签页中打开链接。html <ahref="http://example.com"target="_bla......
  • 后台登陆验证码怎么关闭
    关闭后台登录验证码的方法因所使用的CMS系统不同而有所差异。以下是针对几个不同版本的织梦CMS(DedeCms)关闭后台登录验证码的方法:织梦CMS5.5版本打开织梦CMS根目录下的 dede 文件夹。找到 login.php 文件,并用文本编辑器打开。查找以下代码:php if($validate==''|......