我正在为 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
上面的代码是正确的,但是不要在这些行中使用 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