我修改了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_entrykernel_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),是否有一些维护步骤我错过了?

推荐答案

最后我修好了bug.这个bug不是因为我未能维护上下文恢复和保存,而是因为我的初始化没有考虑到init进程和User-mode Helper进程的情况,其中内核线程通过kernel_execve变成用户进程.

此外,我之前在pt_regs中维护寄存器的方法是不适当的(但正确的);对于每个进程无关的变量,它们不需要在每次异常或中断发生时维护,而只需要在进程切换时维护.现在我修改了arch/arm64/kernel/process.c文件中的__switch_to()函数来维护变量.它现在工作得很好,效率很高!

Linux相关问答推荐

如何更正我的CMakeLists.txt,使我的项目同时构建在Linux和Windows上?

UTF-8输入和使用XGetICValues

为什么库中不调用全局变量的构造函数?

有没有办法确定什么代码使 linux 共享对象inflating ?

从父目录中删除目录而不删除父目录 (Linux)

从另一个文件中的大文件中查找行的最快方法

未找到 SDL_Vertex 和 SDL_RenderGeometry

Linux 如何使用 PCID 的值?

如何克隆 OpenLDAP 数据库

在 Linux/POSIX 系统上获取用户全名的最简单方法是什么?

有没有办法在整个项目代码中的某个日期之后找出更改的文件?

将 bash 脚本添加到路径

谁决定任何数据类型或 struct 的大小(取决于 32 位或 64 位)?

bash 脚本中的自动 docker 登录

crt1.o:在函数_start中:-Linux 中未定义对main的引用

Linux 守护进程

如何在 UNIX 中将字符串转换为整数

当我已经 ssh 进入远程机器时,如何 scp 回到本地?

内联 if shell 脚本

如何通过命令行识别特定的 Linux 风格?