38MALLOC_DEFINE(M_IDLE_STACK,
"idle-stack",
"a CPU's idle stack");
40#define IDLE_STACK_SIZE 8192
44#define ICR_INIT 0x00000500
45#define ICR_STARTUP 0x00000600
46#define ICR_ASSERT 0x00004000
61#define TABLES (X86_TRAMPOLINE + 0x1000)
63#define PG_PRESENT 0x001
67#define MSR_EFER 0xC0000080
84 asm volatile(
"" :::
"memory");
90 __builtin_unreachable();
116 for (
int i = 768; i < 1024; ++i)
128 for (
int i = 256; i < 512; ++i)
150 asm volatile(
"" :::
"memory");
157 for (
int sipi = 0; sipi < 2 && !
ap_started; ++sipi) {
163 for (
int ms = 0; ms < 100 && !
ap_started; ++ms)
184 const char *arg =
NULL;
191 if (!
kargs_get(
"smp", &arg) && arg && !strcmp(arg,
"off")) {
192 printk(
"smp: off (smp=off), %d CPUs\n", n);
200 printk(
"smp: the trampoline is more than a page\n");
210 data->
cr0 = read_cr0();
220 if (ids[i] ==
cpus[0].arch.apic_id)
235 printk(
"smp: the CPU with local APIC %d didn't start\n", ids[i]);
void arch_cpu_kick(struct cpu *cpu)
Makes another CPU enter the kernel now, with an inter-processor interrupt: to run a thread that just ...
void arch_idle(void)
Makes this CPU idle, on its idle stack, until an interrupt makes a thread ready.
static uintptr_t read_cr4(void)
void x86_gdt_setup(struct cpu *cpu, uintptr_t sp)
Sets up and loads the running CPU's GDT and TSS, and points gs (or the GS base, on x86_64) at its str...
static volatile int ap_started
static void x86_ap_start(struct cpu *cpu)
Where an AP enters the kernel, from the trampoline: it sets up its own CPU structures,...
static int ap_boot(struct cpu *cpu, uint32_t id)
Starts the CPU whose local APIC is id, as cpu.
void x86_smp_init(void)
Starts the other CPUs, at boot, unless the kernel's command line says smp=off.
char x86_trampoline_end[]
static paddr_t tables_build(void)
Builds the trampoline's page tables, which map the trampoline's page where it is and the kernel's hal...
char x86_trampoline_data[]
void x86_idt_setup()
Loads the IDT on the running CPU.
struct cpu cpus[CPUS_MAX]
int kargs_get(const char *key, const char **value)
Looks up an argument of the kernel's command line.
#define MALLOC_DEFINE(type, _name, _desc)
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
void kfree(void *)
Frees an object that kmalloc() gave.
void * memset(void *dst, int c, size_t n)
Sets n bytes to c.
void * memcpy(void *dst, const void *src, size_t n)
Copies n bytes; dst and src must not overlap.
void x86_pit_delay(uint32_t us)
Waits us microseconds, at most 54 ms, busy.
int x86_apic_cpus(uint32_t *ids, int max)
Lists the CPUs' local APIC IDs, the boot CPU's among them.
void x86_lapic_ipi(uint32_t id, uint32_t icr)
Sends an IPI to a CPU, and waits until it is delivered.
void x86_lapic_cpu_setup(void)
Sets up the running CPU's local APIC: enabled, with the spurious vector 0xFF, its timer off,...
struct pmap * pmap_switch(struct pmap *pmap)
Switches this CPU to an address space's page tables.
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
unsigned long long int uint64_t
A processor, and what runs on it.
What an AP needs to reach the kernel, at x86_trampoline_data (the fields are at trampoline....
struct pmap * pmap
its page tables (the architecture's)
struct vm_space kvm_space