m1n1/src/smp.c
Hector Martin 3733ea153f smp: fix broken spin-table routine
Only read target_cpu once, then keep a pointer our spin table.

Signed-off-by: Hector Martin <marcan@marcan.st>
2021-01-28 23:48:35 +09:00

87 lines
1.7 KiB
C

/* SPDX-License-Identifier: MIT */
#include "smp.h"
#include "types.h"
#include "utils.h"
#define CPU_START_BASE 0x23b754000L
#define RVBAR_BASE 0x210050000L
struct spin_table {
u64 flag;
u64 target;
};
void *_reset_stack;
u8 secondary_stacks[MAX_CPUS][0x8000] ALIGNED(64);
int target_cpu;
struct spin_table spin_table[MAX_CPUS];
extern u8 _vectors_start[0];
void smp_secondary_entry(void)
{
struct spin_table *me = &spin_table[target_cpu];
sysop("dmb sy");
me->flag = 1;
sysop("dmb sy");
u64 target;
while (1) {
while (!(target = me->target)) {
sysop("wfe");
}
sysop("dmb sy");
me->target = 0;
me->flag++;
sysop("dmb sy");
((void (*)(void))target)();
}
}
static void smp_start_cpu(int index, int cluster, int core)
{
int i;
int cpu_id = (cluster << 4) | core;
printf("Starting CPU %d (%d:%d)... ", index, cluster, core);
spin_table[index].flag = 0;
target_cpu = index;
_reset_stack = secondary_stacks[index];
sysop("dmb sy");
write64(RVBAR_BASE + (cpu_id << 20), (u64)_vectors_start);
if (cluster == 0) {
write32(CPU_START_BASE + 0x8, 1 << core);
} else {
write32(CPU_START_BASE + 0xc, 1 << core);
}
for (i = 0; i < 500; i++) {
sysop("dmb ld");
if (spin_table[index].flag)
break;
udelay(1000);
}
if (i >= 500)
printf("Failed!\n");
}
void smp_start_secondaries(void)
{
printf("Starting secondary CPUs...\n");
smp_start_cpu(1, 0, 1);
smp_start_cpu(2, 0, 2);
smp_start_cpu(3, 0, 3);
smp_start_cpu(4, 1, 0);
smp_start_cpu(5, 1, 1);
smp_start_cpu(6, 1, 2);
smp_start_cpu(7, 1, 3);
}