我修改了ARM的硬件(在gem5上),增加了两个寄存器.我希望它们独立于进程,每个进程都有自己的相应值存储在这些寄存器中,就像ttbr0
一样.
我想修改Linux内核(v5.15.36)来维护这两个寄存器.我做了以下更改,但有一个失败,这两个寄存器的值变为0,这是没有意义的.
首先,我在pt_regs
中添加了对应于这两个寄存器的变量,
struct pt_regs {
union {
struct user_pt_regs user_regs;
struct {
u64 regs[31];
u64 sp;
u64 pc;
u64 pstate;
};
};
// other original code .......
u64 isa_domain; // <================ my register
u64 inst_priv_base; // <================ my register
};
我还在arch/arm/kernel/asm-offsets.h
处添加了相应的宏定义:
DEFINE(S_ISA_DOMAIN, offsetof(struct pt_regs, isa_domain));
DEFINE(S_INST_PRIV_BASE, offsetof(struct pt_regs, inst_priv_base));
我将在copying_thread
(fork
的子函数)中初始化这两个寄存器,
int copy_thread(unsigned long clone_flags, unsigned long stack_start,
unsigned long stk_sz, struct task_struct *p, unsigned long tls)
{
struct pt_regs *childregs = task_pt_regs(p);
memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
fpsimd_flush_task_state(p);
ptrauth_thread_init_kernel(p);
if (likely(!(p->flags & (PF_KTHREAD | PF_IO_WORKER)))) {
*childregs = *current_pt_regs();
childregs->regs[0] = 0;
// <=============== init the register
childregs->inst_priv_base = isa_grid_get_inst_base_pa(user_id);
regs->isa_domain = 1;
// other code .....
}
}
最后,我在堆栈kernel_entry
和kernel_exit
中保存并恢复它们.
.macro kernel_entry, el, regsize = 64
// some original code
stp x24, x25, [sp, #16 * 12]
stp x26, x27, [sp, #16 * 13]
stp x28, x29, [sp, #16 * 14]
// ISA-Grid
.if \el == 0
mrs x20, S3_7_C7_C1_0
str x20, [sp, #S_ISA_DOMAIN]
mrs x20, S3_7_C7_C1_1
str x20, [sp, #S_INST_PRIV_BASE]
.endif
// some original code
.endm
.macro kernel_exit, el
// some original code
apply_ssbd 0, x0, x1
.endif
msr elr_el1, x21 // set up the return data
msr spsr_el1, x22
// ISA-Grid
.if \el == 0
ldr x20, [sp, #S_ISA_DOMAIN]
msr S3_7_C7_C1_0, x20
ldr x20, [sp, #S_INST_PRIV_BASE]
msr S3_7_C7_C1_1, x20
.endif
ldp x0, x1, [sp, #16 * 0]
ldp x2, x3, [sp, #16 * 1]
ldp x4, x5, [sp, #16 * 2]
ldp x6, x7, [sp, #16 * 3]
ldp x8, x9, [sp, #16 * 4]
// some original code
.endm
但似乎有些时候寄存器的值为0(我不会将这两个寄存器初始化为0),是否有一些维护步骤我错过了?