在Arm Base FVP平台上,linux的默认配置是打开了MTE的,也就是:
CONFIG_ARM64_AS_HAS_MTE=y
CONFIG_ARM64_MTE=y
当运行Base FVP的时候加上如下参数:
-C cluster0.memory_tagging_support_level=4 \
-C cluster1.memory_tagging_support_level=4 \
这个时候运行Linux kernel的时候会出现如下错误:
[ 0.000000] CPU features: detected: Virtualization Host Extensions
[ 0.000000] CPU features: detected: Memory Tagging Extension
[ 0.000000] CPU features: detected: Asymmetric MTE Tag Check Fault
[ 0.000000] Internal error: Oops - Undefined instruction: 0000000002000000 [#1] PREEMPT SMP
[ 0.000000] Modules linked in:
[ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 6.10.0-rc1-00013-g2bfcfd584ff5 #2
[ 0.000000] Hardware name: FVP Base RevC (DT)
[ 0.000000] pstate: 200000c9 (nzCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 0.000000] pc : mte_cpu_setup+0x2c/0x74
[ 0.000000] lr : cpu_enable_mte+0x30/0x14c
[ 0.000000] sp : ffff800082623db0
[ 0.000000] x29: ffff800082623db0 x28: 00000000fe6d4c40 x27: 0000000000000000
[ 0.000000] x26: ffff800081b8ff30 x25: ffff800082629b40 x24: ffff800082ae3000
[ 0.000000] x23: 0000000000000004 x22: ffff800082ae3250 x21: ffff800081b92000
[ 0.000000] x20: ffff800081b91458 x19: ffff800081b912f8 x18: 0000000000000006
[ 0.000000] x17: 687469726f676c61 x16: 2046454420504d49 x15: ffff800082623800
[ 0.000000] x14: 0000000000000000 x13: ffff800082641f90 x12: 0000000000000072
[ 0.000000] x11: 0000000000000026 x10: ffff800082699f90 x9 : ffff800082641f90
[ 0.000000] x8 : 00000000ffffefff x7 : 000000000000003c x6 : 000000000000000f
[ 0.000000] x5 : 00000000410fd0f0 x4 : 0000000000000000 x3 : 0000000000000001
[ 0.000000] x2 : 0314000040000321 x1 : 000000040044ffff x0 : 000000000001ffff
[ 0.000000] Call trace:
[ 0.000000] mte_cpu_setup+0x2c/0x74
[ 0.000000] enable_cpu_capabilities+0x90/0xe4
[ 0.000000] setup_boot_cpu_features+0x34/0x44
[ 0.000000] smp_prepare_boot_cpu+0x34/0x40
[ 0.000000] start_kernel+0x1a4/0x708
[ 0.000000] __primary_switched+0x80/0x88
[ 0.000000] Code: eb00003f 54000040 d518a200 b24043e0 (d51810c0)
[ 0.000000] ---[ end trace 0000000000000000 ]---
[ 0.000000] Kernel panic - not syncing: Attempted to kill the idle task!
[ 0.000000] ---[ end Kernel panic - not syncing: Attempted to kill the idle task! ]---
这里出现这个错误的原因是写寄存器 GCR_EL1的时候出现了Undefined instruction。 对应的代码和汇编:
void mte_cpu_setup(void)
{
//...
write_sysreg_s(KERNEL_GCR_EL1, SYS_GCR_EL1);
mte_cpu_setup:
EL2N:0xFFFF800080031210 : MRS x0,TTBR0_EL1
EL2N:0xFFFF800080031214 : TBNZ w0,#0,{pc}+104 ; 0xFFFF80008003127C
EL2N:0xFFFF800080031218 : MRS x0,TTBR1_EL1
EL2N:0xFFFF80008003121C : TBNZ w0,#0,{pc}+100 ; 0xFFFF800080031280
EL2N:0xFFFF800080031220 : MRS x1,MAIR_EL1
EL2N:0xFFFF800080031224 : AND x0,x1,#0xffffffffffff00ff
EL2N:0xFFFF800080031228 : ORR x0,x0,#0xf000
EL2N:0xFFFF80008003122C : CMP x1,x0
EL2N:0xFFFF800080031230 : B.EQ {pc}+8 ; 0xFFFF800080031238
EL2N:0xFFFF800080031234 : MSR MAIR_EL1,x0
EL2N:0xFFFF800080031238 : ORR x0,xzr,#0x1ffff
EL2N:0xFFFF80008003123C : MSR GCR_EL1,x0
根据Arm Arm D23.2.47的定义:
//....
elsif PSTATE.EL == EL2 then
if HaveEL(EL3) && EL3SDDUndefPriority() && SCR_EL3.ATA == '0' then
UNDEFINED;
elsif HaveEL(EL3) && SCR_EL3.ATA == '0' then
if EL3SDDUndef() then
UNDEFINED;
else
AArch64.SystemAccessTrap(EL3, 0x18);
else
GCR_EL1 = X[t, 64];
再在armdbg里检查一下SCR_EL3.ATA
>p/t $SCR_EL3
$3 = 110000011100110001
>p/t $SCR_EL3 >> 26
$4 = 0
基本上可以确定在TF-A里面没有使能这个ATA bit, 修改TF-A的编译参数,在编译时加上 ENABLE_FEAT_MTE2=1 :
make PLAT=fvp DEBUG=1 BL33=$(SRC_DIR)/u-boot/u-boot.bin all fip V=1 ENABLE_FEAT_MTE2=1
再检查SCR_EL3的值, Linux就可以正常boot了。
>p/t $SCR_EL3
$4 = 100000000110000011100110001
>p/t $SCR_EL3 >>25
$10 = 10
小技巧
如果想在boot阶段临时把MTE feature 给临时关闭掉,可以在bootargs里面加上参数arm64.nomte:
u-boot 里面修改:
CONFIG_BOOTARGS="console=ttyAMA0 earlycon=pl011,0x1c090000 root=/dev/vda1 rw ip=dhcp debug user_debug=31 loglevel=9 arm64.nomte "
u-boot 启动阶段临时修改:
bootargs=console=ttyAMA0 earlycon=pl011,0x1c090000 root=/dev/vda1 rw ip=dhcp debug user_debug=31 loglevel=9
参考代码 arch/arm64/kernel/pi/idreg-override.c:
static const struct {
char alias[FTR_ALIAS_NAME_LEN];
char feature[FTR_ALIAS_OPTION_LEN];
} aliases[] __initconst = {
{ "kvm_arm.mode=nvhe", "id_aa64mmfr1.vh=0" },
{ "kvm_arm.mode=protected", "id_aa64mmfr1.vh=0" },
{ "arm64.nosve", "id_aa64pfr0.sve=0" },
{ "arm64.nosme", "id_aa64pfr1.sme=0" },
{ "arm64.nobti", "id_aa64pfr1.bt=0" },
{ "arm64.nopauth",
"id_aa64isar1.gpi=0 id_aa64isar1.gpa=0 "
"id_aa64isar1.api=0 id_aa64isar1.apa=0 "
"id_aa64isar2.gpa3=0 id_aa64isar2.apa3=0" },
{ "arm64.nomops", "id_aa64isar2.mops=0" },
{ "arm64.nomte", "id_aa64pfr1.mte=0" },
{ "nokaslr", "arm64_sw.nokaslr=1" },
{ "rodata=off", "arm64_sw.rodataoff=1" },
{ "arm64.nolva", "id_aa64mmfr2.varange=0" },
};
Comments !