[AArch64 / Bare metal] Need help with CPU communication
Posted: Fri Jan 18, 2019 11:36 am
Been trying to solve this for a week, decided to reach out for help.
What I have is code running on bare metal (RPI Model B 3+).
I'm trying to initialize every CPU with general stuff and then wait for CPU0 to zero out the BSS (and stuff like MMU setup in the future).
After CPU0 initialized all the stuff it needed to it is supposed to release secondary CPUs and then every single CPU jumps into the kernel by calling kmain.
kmain containts very primitive waiting function (for now, just to check if other CPUs get there) and prints out every CPU's id.
The problem is only CPU0 gets to kmain.
start.S
asm/macros.h
kmain.c
link64.ld
Would love some help, because I'm going crazy at this point.
What I have is code running on bare metal (RPI Model B 3+).
I'm trying to initialize every CPU with general stuff and then wait for CPU0 to zero out the BSS (and stuff like MMU setup in the future).
After CPU0 initialized all the stuff it needed to it is supposed to release secondary CPUs and then every single CPU jumps into the kernel by calling kmain.
kmain containts very primitive waiting function (for now, just to check if other CPUs get there) and prints out every CPU's id.
The problem is only CPU0 gets to kmain.
start.S
Code: Select all
#include "asm/macros.h"
#include "arch/arch.h"
#include "board/spec.h"
.section .bss.stack
.align 8
.skip ARCH_STACK_SIZE * BOARD_NUM_CPUS
DATA(___stack_end)
.section .data
.align 8
DATA(cpu_barrier)
.long 1
.section .text
cpuid .req x9
FUNCTION(_start)
// ----------------------------------------
// Initialization to carry out on every CPU
// ----------------------------------------
// Find out which CPU we are running at
mrs cpuid, mpidr_el1
and cpuid, cpuid, #0xff
// Set up the stack
adr x0, ___stack_end
ldr x1, =ARCH_STACK_SIZE
mul x1, x1, cpuid
sub sp, x0, x1
// -----------------------------------
// Initialization to carry out on CPU0
// -----------------------------------
cbnz cpuid, .Lwait_for_primary_cpu
// Zero out the bss section
// Note: relies on ___bss and ___bss_end being 16 byte aligned
adr x0, ___bss
adr x1, ___bss_end
sub x1, x1, x0
cbz x1, .Lbss_init_done
.Lbss_init_loop:
stp xzr, xzr, [x0], #16
sub x1, x1, #16
cbnz x1, .Lbss_init_loop
.Lbss_init_done:
// Release secondary cpus
adr x0, cpu_barrier
str xzr, [x0]
b .Lwait_for_primary_cpu_done
// Wait for primary cpu
.Lwait_for_primary_cpu:
adr x0, cpu_barrier
.Lwait_for_primary_cpu_loop:
ldr x1, [x0]
cbnz x1, .Lwait_for_primary_cpu_loop
.Lwait_for_primary_cpu_done:
// Jump into the kernel
.Lkernel_entry:
mov x0, cpuid
bl kmain
.Lhang:
wfe
b .Lhang
Code: Select all
#ifndef INCLUDE_ASM_MACROS_H
#define INCLUDE_ASM_MACROS_H
#define FUNCTION(x) .global x; .type x, STT_FUNC; x:
#define DATA(x) .global x; .type x, STT_OBJECT; x:
#define LOCALFUNCTION(x) .type x, STT_FUNC; x:
#define LOCALDATA(x) .type x, STT_OBJECT; x:
#endif /*INCLUDE_ASM_MACROS_H*/
Code: Select all
#include <stdint.h>
#include "peripherals/mu.h"
static void wait(const uint64_t c)
{
for (uint64_t i = 0; i < c; ++i) {
__asm__ volatile("nop");
}
}
void kmain(const uint64_t cpuid)
{
if (cpuid) {
wait(1000000 * cpuid);
} else {
mu_init(9600);
}
mu_putc((char)cpuid + '0');
}
Code: Select all
ENTRY(_start)
SECTIONS
{
. = 0x80000;
.text : {
*(.text)
}
.rodata : {
*(.rodata)
}
.data : {
*(.data)
}
.bss : {
. = ALIGN(8);
*(.bss.stack)
. = ALIGN(16);
___bss = .;
*(.bss)
. = ALIGN(16);
___bss_end = .;
}
}