On 10/19/2021 2:26 PM, xuejinze wrote:
> 彭总您好,
>
> 很抱歉打扰您,有个qemu的问题想向您请教下。
>
> 关于commit *8e19c7e6*添加的kunpeng-920的cpu寄存器的定义,我对比了直接从
> kunpeng920服务器上直接读出来的寄存器的值,有很多是和patch里面是有出入的。
>
> 想请教下修改中这些值是基于什么来定义的。
>
> 下面是我这台设备cpuinfo里面的信息:
>
> processor : 95
>
> model name : HUAWEI,Kunpeng 920
>
> BogoMIPS : 200.00
>
> Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
> asimdhp cpuid asimdrdm jscvt fcma dcpop asimddp asimdfhm
>
> CPU implementer : 0x48
>
> CPU architecture: 8
>
> CPU variant : 0x1
>
> CPU part : 0xd01
>
> CPU revision : 0
>
> 下面是我用的读取寄存器的程序:
>
> /*
> * Sample program to demonstrate the MRS emulation ABI.
> *
> * Copyright (C) 2015-2016, ARM Ltd
> *
> * Author: Suzuki K Poulose <suzuki.poulose(a)arm.com>
> *
> * This program is free software; you can redistribute it and/or modify
> * it under the terms of the GNU General Public License version 2 as
> * published by the Free Software Foundation.
> *
> * This program is distributed in the hope that it will be useful,
> * but WITHOUT ANY WARRANTY; without even the implied warranty of
> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> * GNU General Public License for more details.
> * This program is free software; you can redistribute it and/or modify
> * it under the terms of the GNU General Public License version 2 as
> * published by the Free Software Foundation.
> *
> * This program is distributed in the hope that it will be useful,
> * but WITHOUT ANY WARRANTY; without even the implied warranty of
> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> * GNU General Public License for more details.
> */
>
> #include <asm/hwcap.h>
> #include <stdio.h>
> #include <sys/auxv.h>
>
> #define get_cpu_ftr(id) ({ \
> unsigned long __val; \
> asm("mrs %0, "#id : "=r" (__val)); \
> printf("%-20s: 0x%016lx\n", #id, __val); \
> })
>
> int main(void)
> {
>
> if (!(getauxval(AT_HWCAP) & HWCAP_CPUID)) {
> fputs("CPUID registers unavailable\n", stderr);
> return 1;
> }
>
> get_cpu_ftr(ID_AA64ISAR0_EL1);
> get_cpu_ftr(ID_AA64ISAR1_EL1);
> get_cpu_ftr(ID_AA64MMFR0_EL1);
> get_cpu_ftr(ID_AA64MMFR1_EL1);
> get_cpu_ftr(ID_AA64PFR0_EL1);
> get_cpu_ftr(ID_AA64PFR1_EL1);
> get_cpu_ftr(ID_AA64DFR0_EL1);
> get_cpu_ftr(ID_AA64DFR1_EL1);
>
> get_cpu_ftr(MIDR_EL1);
> get_cpu_ftr(MPIDR_EL1);
> get_cpu_ftr(REVIDR_EL1);
> get_cpu_ftr(CTR_EL0);
> #if 0
> /* Unexposed register access causes SIGILL */
> get_cpu_ftr(ID_MMFR0_EL1);
> #endif
>
> return 0;
> }
>
> 下面是用以上程序读出来的值:
>
> [root@host203 ~]# ./a.out
> ID_AA64ISAR0_EL1 : 0x0001100010211120
> ID_AA64ISAR1_EL1 : 0x0000000000011001
> ID_AA64MMFR0_EL1 : 0x00000000ff000000
> ID_AA64MMFR1_EL1 : 0x0000000000000000
> ID_AA64PFR0_EL1 : 0x0000000000110011
> ID_AA64PFR1_EL1 : 0x0000000000000000
> ID_AA64DFR0_EL1 : 0x0000000000000006
> ID_AA64DFR1_EL1 : 0x0000000000000000
> MIDR_EL1 : 0x00000000481fd010
> MPIDR_EL1 : 0x0000000080000000
> REVIDR_EL1 : 0x0000000000000000
> CTR_EL0 : 0x0000000084448004
>
>
我只对ID寄存器清除一点,其他的寄存器我也不是很清楚。所以下面说的都*只*针
对ID寄存器。
内核因为安全的原因,对于用户态的应用读取这些系统寄存器,只会呈现出一部分
值,还有一部分设置为了默认值,每个寄存器呈现出来的field的文档在
linux/Documentation/arm64/cpu-feature-registers.rst,就在这段代码的前面。
如果先要读取完整的寄存器值,可以写个内核模块在内核中读取。例如:
#include <linux/module.h>
#define get_idreg(id) printk("%-20s: 0x%016llx\n", #id,
read_sysreg_s(SYS_ ##id))
static int __init get_feature_init(void)
{
get_idreg(ID_AA64ISAR0_EL1);
get_idreg(ID_AA64ISAR1_EL1);
get_idreg(ID_AA64MMFR0_EL1);
get_idreg(ID_AA64MMFR1_EL1);
get_idreg(ID_AA64PFR0_EL1);
get_idreg(ID_AA64PFR1_EL1);
get_idreg(ID_AA64DFR0_EL1);
get_idreg(ID_AA64DFR1_EL1);
get_idreg(MIDR_EL1);
get_idreg(MPIDR_EL1);
get_idreg(REVIDR_EL1);
return 0;
}
static void __exit get_feature_exit(void)
{
}
module_init(get_feature_init);
module_exit(get_feature_exit);
MODULE_LICENSE("GPL");
在我的机器上插入内核模块后会在dmesg中打印如下信息:
[38928.608723] ID_AA64ISAR0_EL1 : 0x0001100010211120
[38928.608724] ID_AA64ISAR1_EL1 : 0x0000000000011001
[38928.608725] ID_AA64MMFR0_EL1 : 0x0000000000101125
[38928.608726] ID_AA64MMFR1_EL1 : 0x0000000010211122
[38928.608727] ID_AA64PFR0_EL1 : 0x0000010011111111
[38928.608727] ID_AA64PFR1_EL1 : 0x0000000000000000
[38928.608728] ID_AA64DFR0_EL1 : 0x0000000110305408
[38928.608729] ID_AA64DFR1_EL1 : 0x0000000000000000
[38928.608729] MIDR_EL1 : 0x00000000481fd010
[38928.608730] MPIDR_EL1 : 0x0000000081180300
[38928.608731] REVIDR_EL1 : 0x0000000000000000
具体隐藏的实现逻辑因为有段时间没有看这块代码了,有点记不太清了,所以下面
说的可能会有错误。在linux/arch/arm64/kernel/cpufeature.c中,定义了很多
ftr_id_*的变量,其中如果一个field定义为FTR_HIDDEN,则说明这个field对于用
户态是隐藏的。在init_cpu_ftr_reg中会根据定义的ftr_id_*初始化对应的
user_val、user_mask、sys_val。在用用户态读取这些寄存器的时候,在内核中会
调用到emulate_mrs,在这里面会根据之前初始化好的user_val、user_mask、
sys_val返回给用户态相应的值。
Thanks,
Peng