ARM处理器 -- ARM64 MPIDR_EL1寄存器

目录

1.MPIDR_EL1寄存器作用

2.关于MPIDR_EL1的个人理解

3.Cotex-A75 spec关于MPIDR_EL寄存器的说明

4.MPIDR_EL1在devicetree中的体现

5.Linux启动过程中MPIDR_EL1的相关逻辑


本文目的在于理解MPIDR_EL1寄存器,掌握处理器亲和寄存器作用。

1.MPIDR_EL1寄存器作用

        多核处理器的亲和寄存器,每个处理器单元都具有独立该寄存器。该寄存器值为该处理单元的另一种标识、表示对应处理器单元的亲和力,该值用于系统调度。

2.关于MPIDR_EL1的个人理解

        该寄存器更像是为了解决64bit、多核系统问题,而对MPIDR寄存器的扩展;该寄存器的低32bit与MPIDR一致。

3.Cotex-A75 spec关于MPIDR_EL寄存器的说明

        a.该寄存器为只读寄存器

        b.AFF3 & AFF2 都为ClusterID(从软件角度理解为不同CPU组的ID),AFF1 为CPUID,           AFF0 为多线程核的线程ID

        d.U 表示是多Cluster还是单Cluster

4.MPIDR_EL1在devicetree中的体现

        配置DTS时,需要设置MPIDR_EL1的值到CPU node中的reg property,以ArmV8 64bit系统为例:当#address-cell property为2时,需要设置MPIDR_EL1[39:32]到reg[7:0]、MPIDR_EL1[23:0]到reg[23:0]; 当#address-cell property为1时,需要设置MPIDR_EL1[23:0]到reg[23:0];reg的其他位设置位0。

        参考:Documentation/devicetree/bindings/arm/cpus.txt

5.Linux启动过程中MPIDR_EL1的相关逻辑

        a.内核中定义了cpu的逻辑映射变量如下,该变量保存MPIDR_EL1寄存器中亲和值。

        /* * Logical CPU mapping. */
        extern u64 __cpu_logical_map[NR_CPUS];
        #define cpu_logical_map(cpu)    __cpu_logical_map[cpu]

        b.cpu0(boot cpu/primary cpu)获取mpidr_el1亲和值的方式与其他cpu(secondary cpu)

        获取方式有所不同。

    void __init smp_setup_processor_id(void)
       {
        /*启动该过程时只有boot cpu即cpu0在执行,其他cpu还未启动
        通过read_cpuid_mpidr获取的MPIDR_EL1值即为当前执行的CPU0
        的亲和值*/
        u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;

        /*将获取到的cpu0的亲和值保存在cpu_logical_map(0)*/
        cpu_logical_map(0) = mpidr;

        /*
         * clear __my_cpu_offset on boot CPU to avoid hang caused by
         * using percpu variable early, for example, lockdep will
         * access percpu variable inside lock_release
         */
        set_my_cpu_offset(0);
        pr_info("Booting Linux on physical CPU 0x%lx\n", (unsigned long)mpidr);
        }

        c.其他cpu(secondary cpu)亲和值获取方式

	static void __init of_parse_and_init_cpus(void)
	{
		struct device_node *dn;
	
		for_each_node_by_type(dn, "cpu") {      //遍历dts中cpu node
			u64 hwid = of_get_cpu_mpidr(dn);   //获取该cpu node中reg property的值
	
			if (hwid == INVALID_HWID)
				goto next;
	        //判断hwid是否重复,若重复则直接忽略、进行后续Cpu node判断;
			if (is_mpidr_duplicate(cpu_count, hwid)) {  
				pr_err("%pOF: duplicate cpu reg properties in the DT\n",
					dn);
				goto next;
			}
	
			/*
			 * The numbering scheme requires that the boot CPU
			 * must be assigned logical id 0. Record it so that
			 * the logical map built from DT is validated and can
			 * be used.
			 */
			//获取的hwid与CPU0 hwid相同时则认定该cpu node为cpu0对应的node
			if (hwid == cpu_logical_map(0)) {
				if (bootcpu_valid) {
					pr_err("%pOF: duplicate boot cpu reg property in DT\n",
						dn);
					goto next;
				}
	
				bootcpu_valid = true;
				early_map_cpu_to_node(0, of_node_to_nid(dn));
	
				/*
				 * cpu_logical_map has already been
				 * initialized and the boot cpu doesn't need
				 * the enable-method so continue without
				 * incrementing cpu.
				 */
				continue;
			}
	
			if (cpu_count >= NR_CPUS)
				goto next;
	
			pr_debug("cpu logical map 0x%llx\n", hwid);
			
			//记录该cpu的node 和 hwid
			cpu_logical_map(cpu_count) = hwid;
	
			early_map_cpu_to_node(cpu_count, of_node_to_nid(dn));
	next:
			cpu_count++;
		}
}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值