展示代码
/*
* Set the IPS bits in TCR_EL1.
*/
tcr_compute_pa_size x10, #TCR_IPS_SHIFT, x5, x6
分析代码
第1到第3行是注释,含义是设置 TCR_EL1 的 IPS 域
第4行涉及到宏定义 tcr_compute_pa_size 和 TCR_IPS_SHIFT
TCR_IPS_SHIFT 的宏作为第二个入参传入,定义其如下
#define TCR_IPS_SHIFT 32
其中,tcr_compute_pa_size 的定义如下
/*
* tcr_compute_pa_size - set TCR.(I)PS to the highest supported
* ID_AA64MMFR0_EL1.PARange value
*
* tcr: register with the TCR_ELx value to be updated
* pos: IPS or PS bitfield position
* tmp{0,1}: temporary registers
*/
.macro tcr_compute_pa_size, tcr, pos, tmp0, tmp1
mrs \tmp0, ID_AA64MMFR0_EL1
// Narrow PARange to fit the PS field in TCR_ELx
ubfx \tmp0, \tmp0, #ID_AA64MMFR0_PARANGE_SHIFT, #3
mov \tmp1, #ID_AA64MMFR0_PARANGE_MAX
cmp \tmp0, \tmp1
csel \tmp0, \tmp1, \tmp0, hi
bfi \tcr, \tmp0, \pos, #3
.endm
根据注释分析,该宏定义时给第一个入参 TCR 赋值,第三,第四个入参 tmp0 和 tmp1 是临时寄存器
在该宏定义里面,ID_AA64MMFR0_EL1, AArch64 Memory Model Feature Register 0
含义如下 Provides information about the implemented memory model and memory management support in AArch64 state
提供 EL1 异常模式下 内存模型和内存管理的信息,涉及到的宏定义如下
#define ID_AA64MMFR0_PARANGE_SHIFT 0
该宏首先提取 位域 PARange[2:0] bit 到 tmp0
PARange, bits [3:0]
Physical Address range supported. Defined values are:
0b0000 32 bits, 4GB.
0b0001 36 bits, 64GB.
0b0010 40 bits, 1TB.
0b0011 42 bits, 4TB.
0b0100 44 bits, 16TB.
0b0101 48 bits, 256TB.
0b0110 52 bits, 4PB.
我们可以看到 bit[3] 始终为0, 所以可以忽略掉。
#ifdef CONFIG_ARM64_PA_BITS_52
#define ID_AA64MMFR0_PARANGE_MAX ID_AA64MMFR0_PARANGE_52
#else
#define ID_AA64MMFR0_PARANGE_MAX ID_AA64MMFR0_PARANGE_48
#endif
#define ID_AA64MMFR0_PARANGE_48 0x5
cmp \tmp0, \tmp1 比较 tmp0 和 tmp1 的大小,并根据比较的结果更新条件标志位,但是不存储比较的结果。
CSEL 指令的含义如下:
CSEL Xd, Xn, Xm, cond
Xd:目标寄存器,计算结果将被存入此寄存器。
Xn:第一个源操作数,如果条件满足,它的值将被复制到Xd。
Xm:第二个源操作数,如果条件不满足,它的值将被复制到Xd。
cond:条件码,根据上一条 cmp 指令更新的条件标志位决定了选择Xn还是Xm。条件码可以是EQ(等于)、NE(不等于)、HS(无符号数大于/等于)、LO(无符号数小于)、MI(负数)、PL(非负数)、VS(上溢出)、VC(没有上溢出)、GE(大于等于)、LT(小于)、GT(大于)、LE(小于等于)等,或者是AL(无条件执行)。
也就是说,如果有一个条件比较操作,你想根据比较的结果来决定是设置寄存器的值还是保持不变,你可以使用csel指令来实现这一点。如果条件满足,它将执行类似于三元运算符的操作:Xd = condition ? Xn : Xm
所以,csel 指令选择 tmp0 和 tmp1 中较小的一个存储在 tmp0
BFI(Bit Field Insert)指令用于将一个寄存器中的位字段插入到另一个寄存器的指定位置。BFI指令的格式如下:
BFI 目标寄存器, 源寄存器, #lsb, #宽度
目标寄存器:将被插入位字段的寄存器。
源寄存器:包含要插入的位字段的寄存器。
lsb:在目标寄存器中插入位字段的最低位的位置。
宽度:要插入的位字段的宽度。
所以宏定义的最后一句话的含义是将 tmp0 的最低 3bit 插入到 tcr 的 bit[32 + 3, 32], tcr 也就是 x10