#ifndef _NUCLEUS_CPU_H #define _NUCLEUS_CPU_H #include #include #include typedef unsigned int cpu_t; typedef struct Processor Processor; /* Structure for CPU specific data */ struct Processor { Processor *self; cpu_t id; uint32_t inCriticalSection; uint32_t critFlags; struct InterruptFrame *frame; Scheduler *scheduler; struct IPIQueue *ipiq; }; /* Structure for an Interrupt Frame */ struct InterruptFrame { uint32_t ds; uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; uint32_t intnum, err; uint32_t eip, cs, eflags, useresp, ss; }; /* Flags for IPI Queue Messages */ enum IPIQFlag { IPIQ_ASYNC, IPIQ_SYNC, IPIQ_DONE, }; typedef void (*int_handler_t)(struct InterruptFrame *); typedef void (*ipiq_func_t)(void *); extern Processor __seg_gs *const cpu; extern Processor *cpus[]; extern size_t ncpus; extern int apic; #define for_each_cpu(c) for (cpu_t __i_ ## c = 0; ((c) = cpus[__i_ ## c]) && \ ((__i_ ## c) < ncpus); (__i_ ## c)++) extern uintptr_t lapicPtr, ioapicPtr; #define LAPIC(off) (*((uint32_t *) ((uint32_t) lapicPtr + (off)))) #define IOAPIC(off) (*((uint32_t *) ((uint32_t) ioapicPtr + (off)))) extern cpu_t lapicNums[]; #define CPUID (apic ? lapicNums[(cpu_t) (LAPIC(0x20) >> 24)] : 0) #define MAX_CPUS 2 /* Enter a critical section */ static inline void enter_critical_section(void) { uint32_t *ics = &cpu->self->inCriticalSection; if (__atomic_fetch_add(ics, 1, __ATOMIC_RELAXED) == 0) asm volatile ( "pushf;" "cli;" "pop %0" : "=r" (cpu->critFlags) : : "memory" ); } /* Exit a critical section */ static inline void exit_critical_section(void) { uint32_t *ics = &cpu->self->inCriticalSection; if (__atomic_sub_fetch(ics, 1, __ATOMIC_RELAXED) == 0) asm volatile ( "push %0;" "popf" : : "rm" (cpu->critFlags) : "memory","cc" ); } void register_exception(uint8_t num, int_handler_t addr); void register_interrupt(uint8_t num, int_handler_t addr); void register_ipi(uint8_t num, int_handler_t addr); void send_ipiq(cpu_t targid, ipiq_func_t func, void *arg, enum IPIQFlag flags); void set_fs_base(uintptr_t base); void set_gs_base(uintptr_t base); void set_kernel_stack(uintptr_t top); #endif