.unreq tcr
SYM_FUNC_END(__cpu_setup)
2.5.1 设置EL0和EL1异常等级可以访问浮点运算单元
2.5.2 调试监控系统寄存器
2.5.3 设置PSTATE寄存器的调试掩码域
??宏enable_dbg定义在/arch/arm64/include/asm/assembler.h中
.macro enable_dbg
msr daifclr, #8
.endm
2.5.4 内存属性值赋值给mair(x17)
armv8内存可分为device memory和normal memory,它们又可以具有不同的属性,如:
- device memory可配置不同的nGnRnE属性,以确定其访问内存时的行为;
- normal memory可以有不同的cache策略,如cache写回、cache写通或者non cache等。寄存器MAIR_EL1用于设置内存属性表,它按八位一组分成了八组属性,其定义如下图:
??宏MAIR_EL1_SET定义在arch/arm64/mm/proc.S文件中,
/*
* Default MAIR_EL1. MT_NORMAL_TAGGED is initially mapped as Normal memory and
* changed during __cpu_setup to Normal Tagged if the system supports MTE.
*/
#define MAIR_EL1_SET \
(MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRnE, MT_DEVICE_nGnRnE) | \
MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRE, MT_DEVICE_nGnRE) | \
MAIR_ATTRIDX(MAIR_ATTR_NORMAL_NC, MT_NORMAL_NC) | \
MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL) | \
MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL_TAGGED))
2.5.5 管理页表映射的值赋值给tcr --- Translation Control Register寄存器(x16)
2.5.6 MTE
??MTE 是ARM新架构(ARM V8.5 引入)的一个特性,它通过给分配的内存打标记(tag),追踪最常见的非法内存操作。如果密钥的值和锁的值一样,表示访问成功,否则会报告一个错误。ARM MTE简介
2.5.7 清除触发此CPU上错误的TCR位
??宏tcr_clear_errata_bits定义在/arch/arm64/include/asm/assembler.h中
/*
* tcr_clear_errata_bits - Clear TCR bits that trigger an errata on this CPU.
*/
.macro tcr_clear_errata_bits, tcr, tmp1, tmp2
#ifdef CONFIG_FUJITSU_ERRATUM_010001
mrs \tmp1, midr_el1
mov_q \tmp2, MIDR_FUJITSU_ERRATUM_010001_MASK
and \tmp1, \tmp1, \tmp2
mov_q \tmp2, MIDR_FUJITSU_ERRATUM_010001
cmp \tmp1, \tmp2
b.ne 10f
mov_q \tmp2, TCR_CLEAR_FUJITSU_ERRATUM_010001
bic \tcr, \tcr, \tmp2
10:
#endif /* CONFIG_FUJITSU_ERRATUM_010001 */
.endm
2.5.8 设置TTBR0_EL1寻址的内存区域的大小为2^(64-T0SZ)字节。
2.5.9 设置TCR_EL1中的IPS位为ID_AA64MMFR0_EL1.PARange支持的最高值
??ID_AA64MMFR0_EL1 - Memory model feature register 0
/*
* 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 //pos =32
mrs \tmp0, ID_AA64MMFR0_EL1
// Narrow PARange to fit the PS field in TCR_ELx
//UBFX Xd, Xn, #lsb, #width
//ubfx指令是无符号位域提取指令:UBFX指令的意思是从Wn寄存器的第lsb位开始,提取width位到Wd寄存器,剩余高位用0填充。
ubfx \tmp0, \tmp0, #ID_AA64MMFR0_PARANGE_SHIFT, #3 //ID_AA64MMFR0_PARANGE_SHIFT = 0
mov \tmp1, #ID_AA64MMFR0_PARANGE_MAX //根据配置可能是48/52
cmp \tmp0, \tmp1
//CSEL Xd, Xn, Xm, cond :条件选择,返回第一个或第二个输入
csel \tmp0, \tmp1, \tmp0, hi //hi:无符号数大于
bfi \tcr, \tmp0, \pos, #3
.endm
2.5.10 用硬件实现更新访问脏页面的标记位
??ARMV8.1支持的硬件特性。如果支持了这个硬件特性,访问一个物理页面时,硬件会自动设置PTE的AF域,否则需要软件(缺页中断)方式来模拟。
2.5.11 系统控制寄存器(SCTLR)域值
??并未设置SCTLR在,只是作为一个参数,传给下一个函数。
2.6 C运行时环境初始化(__primary_switch )
??_primary_switch主要用于设置c运行时环境,如使能MMU,设置异常向量表,栈,BSS段等,最后跳转到C语言函数start_kernel 。该函数具体实现如下,我们暂且跳过与主流程关联较小的kaslr和内核重定向相关代码。
SYM_FUNC_START_LOCAL(__primary_switch) // __primary_switch在恒等映射段中(物理地址==虚拟地址)
#ifdef CONFIG_RANDOMIZE_BASE // ---(2.6.1)
mov x19, x0 // preserve new SCTLR_EL1 value
mrs x20, sctlr_el1 // preserve old SCTLR_EL1 value
#endif
adrp x1, init_pg_dir // kernel image的映射使用的页表起始地址【重点关注,下面TTBR1会用这个值】
bl __enable_mmu // ---(2.6.