问题1:支持ARMv8的Linux内核异常向量地址在哪?
答:异常向量基地址在0xffffffc000081800。通过查看编译后的linux内核的System.map文件,能确定异常向量表的基地址。通过反汇编生成的支持armv8的linux内核也可以证实。Armv8的异常向量表的定义在内核的arch/arm/kernel/entry.S中,将其摘录如下:
/*
* Exception vectors.
*/
.macro ventry label
.align 7
b \label
.endm
.align 11
ENTRY(vectors)
ventry el1_sync_invalid //Synchronous EL1t
ventry el1_irq_invalid //IRQ EL1t
ventry el1_fiq_invalid //FIQ EL1t
ventry el1_error_invalid //Error EL1t
ventry el1_sync //Synchronous EL1h
ventry el1_irq //IRQ EL1h
ventry el1_fiq_invalid //FIQ EL1h
ventry el1_error_invalid //Error EL1h
ventry el0_sync //Synchronous 64-bit EL0
ventry el0_irq //IRQ 64-bit EL0
ventry el0_fiq_invalid //FIQ 64-bit EL0
ventry el0_error_invalid //Error 64-bit EL0
#ifdefCONFIG_AARCH32_EMULATION
ventry el0_sync_compat //Synchronous 32-bit EL0
ventry el0_irq_compat //IRQ 32-bit EL0
ventry el0_fiq_invalid_compat //FIQ 32-bit EL0
ventry el0_error_invalid_compat //Error 32-bit EL0
#else
ventry el0_sync_invalid //Synchronous 32-bit EL0
ventry el0_irq_invalid //IRQ 32-bit EL0
ventry el0_fiq_invalid //FIQ 32-bit EL0
ventry el0_error_invalid //Error 32-bit EL0
#endif
END(vectors)
问题2:找出TLB中存放的ARMv8的页表格式
答:只找到了页表的格式。TLB中的格式没找到。
ARMv8支持4KB页大小的4级页表转换到64KB页大小的3级页表转换。
以下是从内核源码的Documentation找到的信息。
AArch64 Linux memory layout:
Start End Size Use
-----------------------------------------------------------------------
0000000000000000 0000007fffffffff 512GB user
ffffff8000000000 ffffffbbfffeffff ~240GB vmalloc
ffffffbbffff0000 ffffffbcffffffff 64KB [guardpage]
ffffffbc00000000 ffffffbdffffffff 8GB vmemmap
ffffffbe00000000 ffffffbffbffffff ~8GB [guard,future vmmemap]
ffffffbffc000000 ffffffbfffffffff 64MB modules
ffffffc000000000 ffffffffffffffff 256GB memory
Translation table lookup with 4KB pages:
+--------+--------+--------+--------+--------+--------+--------+--------+
|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0|
+--------+--------+--------+--------+--------+--------+--------+--------+
| | | | | |
| | | | | v
| | | | | [11:0] in-page offset
| | | | +-> [20:12] L3 index
| | | +-----------> [29:21] L2 index
| | +---------------------> [38:30] L1index
| +------------------------------->[47:39] L0 index (not used)
+------------------------------------------------->[63] TTBR0/1
Translation table lookup with 64KB pages:
+--------+--------+--------+--------+--------+--------+--------+--------+
|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0|
+--------+--------+--------+--------+--------+--------+--------+--------+
| | | | |
| | | | v
| | | | [15:0] in-page offset
| | | +----------> [28:16] L3 index
| | +--------------------------> [41:29] L2index (only 38:29 used)
| +-------------------------------> [47:42] L1 index (not used)
+------------------------------------------------->[63] TTBR0/1
问题3:ARMv8中重要的控制寄存器的各位的意思是什么?
答:源码中没找到对ARMv8控制寄存器的详细描述。
1. 关于SPSR,该寄存器是CPSR的副本,当在不同模式间转换时,该寄存器保存CPSR的内容,用于状态恢复。
在arch/arm64/include/asm/ptrace.h中找到AArch64的spsr寄存器某些位的定义,经过与ARMv7的对比发现,以下定义的位于ARMv7中定义的位意义相同。
/*AArch64 SPSR bits */
#definePSR_F_BIT 0x00000040
#definePSR_I_BIT 0x00000080
#definePSR_A_BIT 0x00000100
#definePSR_D_BIT 0x00000200
#definePSR_Q_BIT 0x08000000
#definePSR_V_BIT 0x10000000
#definePSR_C_BIT 0x20000000
#definePSR_Z_BIT 0x40000000
#define PSR_N_BIT 0x80000000
2. ARMv8中的系统控制寄存器有多个,但与ARMv7不同的是:ARMv8中抛弃了“协处理器”的概念,进而就没了MCR,MRC类的指令,见参考资料[3],其系统控制都是通过MSR,MRS类指令进行。通过阅读Linux内核源码发现,主要的控制寄存器有:
hcr_el2:el2中的hypervisor配置寄存器
cnthctl_el2:可配置通用时钟
另外还有,vmpidr_el2;vpidr_el2;sctlr_el1:cptr_el2;hstr_el2;spsr_el2;vbar_el1;ttbr0_el1;ttbr1_el1;sctlr_el1
参考资料
[1] ARMv8的编译器binutils,结构体aarch64_opcode_table定义见line 1208
[2] 结构体aarch64_opcode定义,line451
[3] 《ARMv8 InstructionSet Overview 》page11