在 Raspberry Pi 3B 上调试多核内核初始化

问题描述 投票:0回答:1

我正在为 Raspberry Pi 3B 开发一个简单的内核,旨在在所有四个内核上运行基本任务。但是,似乎只有主核心正在运行 kernel_init,而其他核心从未启动。这是我的代码的相关部分:

.globl _start
_start:
    mrs    x0, mpidr_el1
    and    x0, x0,#0xFF        // Check processor id
    cbz    x0, el1_entry        // Hang for all non-primary CPU
    b    proc_hang

proc_hang: 
    wfe
    b      proc_hang

el1_entry:
    adr    x0, bss_begin
    adr    x1, bss_end
    sub    x1, x1, x0
    bl     memzero

    mov    sp, #LOW_MEMORY
     // Initialize and start secondary cores on Raspberry Pi 3
    ldr x1, =start_core_1    // Address to jump to for secondary cores
    ldr x2, =0xE0                // Mailbox register for Core 1
    str x1, [x2]

    ldr x1, =start_core_2    // Address to jump to for secondary cores
    ldr x2, =0xE8                // Mailbox register for Core 2
    str x1, [x2]
    
    ldr x1, =start_core_3    // Address to jump to for secondary cores
    ldr x2, =0xF0                // Mailbox register for Core 3
    str x1, [x2]
    sev                           // Send event to wake up all cores

    bl    kernel_init
    b     proc_hang        // should never come here

start_core_1:
    ldr    x1, =LOW_MEMORY
    ldr    x2, =PAGE_SIZE
    add    sp, x1, x2          // sp = LOW_MEMORY + PAGE_SIZE
    bl     kernel_init
    b      start_core_1

start_core_2:
    ldr    x1, =LOW_MEMORY
    ldr    x2, =PAGE_SIZE
    add    sp, x1, x2, lsl #1  // sp = LOW_MEMORY + 2*PAGE_SIZE
    bl     kernel_init
    b      start_core_2

start_core_3:
    ldr    x1, =LOW_MEMORY
    ldr    x2, =PAGE_SIZE
    mov    x3, #3
    mul    x2, x2, x3          // x2 = 3 * PAGE_SIZE
    add    sp, x1, x2          // sp = LOW_MEMORY + 3*PAGE_SIZE
    bl     kernel_init
    b      start_core_3
extern "C" void kernel_init(void)
{
    uart_init();
    init_printf(0, putc);
    printf("processor ID: %d\n", get_core_number());
    while (1)
    {
        uart_send(uart_recv());
    }
}
.global get_core_number
    get_core_number:
    mrs x0, MPIDR_EL1      // Read MPIDR_EL1 into x0
    and x0, x0, #0xff      // Check processor id
    ret                    // Return, with the result in x0

尽管写入正确的邮箱寄存器以唤醒辅助核心,UART 输出仅显示“处理器 ID:0”,并且辅助核心特定的代码似乎从未开始运行。根据我对多核编程的理解,如果所有核心都在运行,输出应该是这样的:

处理器 ID:0 处理器 ID:2 处理器 ID:1 处理器 ID:3(当然是随机顺序)

我尝试为每个核心设置不同的堆栈指针,如 start_core_X 的初始化代码所示,但仍然只有主核心处于活动状态。

我尝试过的只是做这样的事情:

_start:
    adr    x0, bss_begin
    adr    x1, bss_end
    sub    x1, x1, x0
    bl     memzero
    mov    sp, #LOW_MEMORY
    bl    kernel_init

通过此设置,我希望所有内核都执行 kernel_init,因为没有逻辑来区分内核(例如检查 MPIDR_EL1 以过滤掉非主内核)。然而,根据我得到的输出,似乎只有主核心正在执行 kernel_init:

处理器 ID:0

任何关于为什么会发生这种情况或如何确保所有核心运行初始化代码的见解或建议将不胜感激!

我也部分地阅读了 github 上的操作系统教程,所以我的很多文件都来自这里 https://github.com/s-matyukevich/raspberry-pi-os/tree/master

assembly kernel raspberry-pi3 multicore bare-metal
1个回答
0
投票

上面的代码是正确的,但是不要在这些行中使用 ldr 指令

ldr x1, =start_core_1
ldr x1, =start_core_2
ldr x1, =start_core_3

我必须像这样使用 adr 指令

adr x1, start_core_1
adr x1, start_core_2
adr x1, start_core_3

此更改是必要的,因为 adr 指令专门设计用于计算当前汇编部分内标签的地址,直接编码指令本身内的偏移量。

这是上述代码的更新版本,适用于所有四个核心:

.globl _start
_start:
    mrs x0, mpidr_el1       
    and x0, x0,#0x3     // Check processor id
    cbz x0, el1_entry       // Hang for all non-primary CPU
    b   proc_hang

proc_hang: 
    wfe
    b proc_hang


el1_entry:
    adr    x0, bss_begin
    adr    x1, bss_end
    sub    x1, x1, x0
    bl     memzero
    mov   sp, #LOW_MEMORY
    bl    wake_up_cores
    bl    kernel_init
    b     proc_hang        // should never come here

secondary:
    mrs x0, mpidr_el1
    and x0, x0, #0xFF // get processor id
    mov x1, #SECTION_SIZE
    mul x1, x1, x0 // multiply section size by processor id to give each core a different stack
    add x1, x1, #LOW_MEMORY
    mov sp, x1
    bl kernel_init

wake_up_cores:
    mov x0, #0
    adr x0, secondary
    mov x1, #0xe0
    str x0, [x1]
    mov x1, #0xe8
    str x0, [x1]
    mov x1, #0xf0
    str x0, [x1]
    sev
© www.soinside.com 2019 - 2024. All rights reserved.