61 lines
1.4 KiB
C
61 lines
1.4 KiB
C
#include <zinnia/alloc.h>
|
|
#include <zinnia/cmdline.h>
|
|
#include <zinnia/compiler.h>
|
|
#include <zinnia/percpu.h>
|
|
#include <zinnia/string.h>
|
|
#include <zinnia/utils.h>
|
|
#include <arch/percpu.h>
|
|
#include <stdatomic.h>
|
|
|
|
extern uint8_t __ld_percpu_start[];
|
|
extern uint8_t __ld_percpu_end[];
|
|
|
|
static _Atomic(size_t) num_cpus = 1;
|
|
|
|
static size_t max_cpus = SIZE_MAX;
|
|
static void smp_option(uintptr_t value) {
|
|
max_cpus = value;
|
|
}
|
|
CMDLINE_OPTION("smp", "Maximum number of CPUs to use", smp_option);
|
|
|
|
[[__used, __section(".percpu.init")]]
|
|
struct percpu percpu_bsp = {
|
|
.self = &percpu_bsp,
|
|
.id = 0,
|
|
.online = false,
|
|
};
|
|
|
|
struct percpu* percpu_new() {
|
|
const size_t size = __ld_percpu_end - __ld_percpu_start;
|
|
const size_t num_pages = ALIGN_UP(size, arch_mem_page_size()) / arch_mem_page_size();
|
|
|
|
// TODO: Map pages past the end of the kernel.
|
|
// TODO: Document how allocations work.
|
|
|
|
phys_t mem;
|
|
if (mem_phys_alloc(num_pages, 0, &mem))
|
|
return nullptr;
|
|
|
|
struct percpu* cpu = HHDM_PTR(mem);
|
|
cpu->self = cpu;
|
|
cpu->id = atomic_fetch_add_explicit(&num_cpus, 1, memory_order_relaxed);
|
|
cpu->online = false;
|
|
return cpu;
|
|
}
|
|
|
|
size_t percpu_max_cpus() {
|
|
return max_cpus;
|
|
}
|
|
|
|
struct percpu* percpu_get() {
|
|
return arch_percpu_get();
|
|
}
|
|
|
|
void percpu_bsp_init() {
|
|
arch_percpu_bsp_init();
|
|
}
|
|
|
|
void percpu_init() {
|
|
arch_percpu_init();
|
|
}
|