λ

furix

cute os

settings

include/arch/x86_64/percpu.h

1642 bytes raw

#ifndef FURIX_ARCH_X86_64_PERCPU_H
#define FURIX_ARCH_X86_64_PERCPU_H

#include <types.h>

/*
 * number of per-CPU slots. the array is indexed densely from 0, not by APIC
 * ID: an x2APIC MADT can report an ID far larger than the number of
 * processors, so the ID itself is not a usable index. 256 is also the largest
 * count the trampoline can carry, since it passes the slot in one byte.
 */
#define PERCPU_MAX_CPUS 256

/* per-AP stack; statically reserved until the buddy allocator exists */
#define PERCPU_STACK_SIZE 4096

/* bring up GS-based per-CPU data for the BSP */
void percpu_init(void);

/*
 * point %gs at the per-CPU area for `slot`, recording `apic_id` as this CPU's
 * identity. used by the BSP once at boot and by each AP from its trampoline.
 * must not be called for APIC ID 0 before percpu_init(), since that is where the
 * BSP's swapgs lands.
 */
void percpu_attach(uint32_t apic_id, uint8_t slot);

void percpu_set_id(uint32_t apic_id);

/* this CPU's APIC ID, as recorded by percpu_attach() */
uint32_t percpu_apic_id(void);

/* address of this CPU's per-CPU area */
uint64_t percpu_address(void);

/* per-CPU area for a slot, for the AP trampolines */
uint64_t percpu_area(uint8_t slot);

/* top of the stack for a slot, for the AP trampoline */
uint64_t percpu_stack_top(uint8_t slot);

/* store a value through %gs:0 and read it back the same way */
uint64_t percpu_gs_selftest(uint64_t value);

/*
 * same, but the read-back goes through the C variable, proving GS.base and the
 * compiler-generated access agree.
 */
uint64_t percpu_gs_selftest_via_c(uint64_t value);

#endif /* FURIX_ARCH_X86_64_PERCPU_H */