通用寄存器
示例:讀取寄存器值
// 用戶態程序或內核代碼中均可使用
unsigned long reg_value;
asm volatile ("mov %0, x10" // 將X10的值保存到reg_value變量: "=r" (reg_value)
);
printk("X10 = 0x%lx\n", reg_value);
示例:寫入寄存器值
unsigned long new_value = 0x1234;
asm volatile ("mov x9, %0" // 將new_value的值寫入X9: : "r" (new_value)
);
內核模塊中直接訪問?
// 內核模塊示例
void read_registers(void) {unsigned long sp, pc;asm volatile ("mov %0, sp \n" // 讀取SP(棧指針)"mov %1, pc \n" // 讀取PC(程序計數器): "=r" (sp), "=r" (pc));pr_info("SP=0x%lx, PC=0x%lx\n", sp, pc);
}
系統寄存器
需要通過msr寫、mrs讀取:
linux內核定義了read_sysreg/write_sysreg相關的函數:arch/arm64/include/asm/sysreg.h
以讀取寄存器為例 :read_sysreg和read_sysreg_s的區別是一個檢測權限?(來自deepseek答案),實際操作read_sysreg接受字符串類型寄存器寫法,如elr_el1,vbar_el1等(這些忽略大小寫,本質上也是as匯編命令,屬于binutils軟件,中內置的)。./opcodes/aarch64-opc.c:
而read_sysreg_s只能接受SYS_ELR_EL1,SYS_VBAR_EL1這種內核定義的寄存器編碼:
sys_reg:?
/** ARMv8 ARM reserves the following encoding for system registers:* (Ref: ARMv8 ARM, Section: "System instruction class encoding overview",* C5.2, version:ARM DDI 0487A.f)* [20-19] : Op0* [18-16] : Op1* [15-12] : CRn* [11-8] : CRm* [7-5] : Op2*/
#define Op0_shift 19
#define Op0_mask 0x3
#define Op1_shift 16
#define Op1_mask 0x7
#define CRn_shift 12
#define CRn_mask 0xf
#define CRm_shift 8
#define CRm_mask 0xf
#define Op2_shift 5
#define Op2_mask 0x7#define sys_reg(op0, op1, crn, crm, op2) \(((op0) << Op0_shift) | ((op1) << Op1_shift) | \((crn) << CRn_shift) | ((crm) << CRm_shift) | \((op2) << Op2_shift))
?和寄存器的定義有說明:http://hehezhou.cn/register2025/AArch64-elr_el1.html
?案例:
uint64_t read_ttbr0_el1(void) {uint64_t ttbr0;asm volatile("mrs %0, ttbr0_el1" : "=r" (ttbr0));return ttbr0;
}
static int __init test_init(void)
{printk("ttbr0_el1 %llx\n",read_ttbr0_el1());printk("ttbr0_el1 %llx\n",read_sysreg_s(SYS_TTBR0_EL1));printk("elr_el1 %llx\n",read_sysreg(elr_el1));printk("midr_el1 %llx\n",read_sysreg(midr_el1));printk("vbar_el1 %llx\n",read_sysreg(vbar_el1));printk("vbar_el1 %llx\n",read_sysreg_s(SYS_VBAR_EL1));return 0;
}