看到start_kernel的代码,看到smp_setup_processor_id(void)记一下,更多的是GCC语法,以及一点arm指令的分析。
从函数名也可以看出,这里是设置处理器ID。
void __init smp_setup_processor_id(void)
{
u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
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%010lx [0x%08x]\n",
(unsigned long)mpidr, read_cpuid_id());
}
static inline u64 __attribute_const__ read_cpuid_mpidr(void)
{
return read_cpuid(MPIDR_EL1);
}
read_cpuid是个宏,定义如下:
#define read_cpuid(reg) read_sysreg_s(SYS_ ## reg)
//-------->
read_sysreg_s(SYS_MPIDR_EL1)
#define read_sysreg_s(r) ({ \
u64 __val; \
asm volatile(__mrs_s("%0", r) : "=r" (__val)); \
__val; \
})
//-------->
{
u64 __val;
asm volatile(__msrs_s("%0", SYS_MPIDR_EL1) : "=r" (__val));
__val;
}
#define __mrs_s(v, r) \
DEFINE_MRS_S \
" mrs_s " v ", " __stringify(r) "\n" \
UNDEFINE_MRS_S
//-------->
DEFINE_MRS_S
"mrs_s %0, SYS_MPIDR_EL1\n"
UNDEFINE_MRS_S
#define __DEFINE_MRS_MSR_S_REGNUM \
" .irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\n" \
" .equ .L__reg_num_x\\num, \\num\n" \
" .endr\n" \
" .equ .L__reg_num_xzr, 31\n"
#define DEFINE_MRS_S \
__DEFINE_MRS_MSR_S_REGNUM \
" .macro mrs_s, rt, sreg\n" \
__emit_inst(0xd5200000|(\\sreg)|(.L__reg_num_\\rt)) \
" .endm\n"
#define UNDEFINE_MRS_S \
" .purgem mrs_s\n"
//-------->
.equ .L__reg_num_x0, 0
.equ .L__reg_num_x1, 1
.equ .L__reg_num_x2, 2
.equ .L__reg_num_x3, 3
.equ .L__reg_num_x4, 4
.equ .L__reg_num_x5, 5
.equ .L__reg_num_x6, 6
.equ .L__reg_num_x7, 7
.equ .L__reg_num_x8, 8
.equ .L__reg_num_x9, 9
.equ .L__reg_num_x10, 10
.equ .L__reg_num_x11, 11
.equ .L__reg_num_x12, 12
.equ .L__reg_num_x13, 13
.equ .L__reg_num_x14, 14
.equ .L__reg_num_x15, 15
.equ .L__reg_num_x16, 16
.equ .L__reg_num_x17, 17
.equ .L__reg_num_x18, 18
.equ .L__reg_num_x19, 19
.equ .L__reg_num_x20, 20
.equ .L__reg_num_x21, 21
.equ .L__reg_num_x22, 22
.equ .L__reg_num_x23, 23
.equ .L__reg_num_x24, 24
.equ .L__reg_num_x25, 25
.equ .L__reg_num_x26, 26
.equ .L__reg_num_x27, 27
.equ .L__reg_num_x28, 28
.equ .L__reg_num_x29, 29
.equ .L__reg_num_x30, 30
.equ .L__reg_num_xzr, 31
.macro mrs_s, rt, sreg
.inst 0xd5000000|(\\sreg)|(.L__reg_num_\\rt)
.endm
mrs_s %0, SYS_MPIDR_EL1\n
//->
.inst(0xd5000000|(0x1800A0)|.L__reg_num_0)
//不懂为什么是L__reg_num_0而不是L__reg_num_x0,可能是"%0"中的%被解析成了x