PatchworkOS  da8a090
A non-POSIX operating system.
Loading...
Searching...
No Matches

CPU. More...

Collaboration diagram for CPU:

Detailed Description

CPU.

CPU structures and functions.

Events

Each CPU can generate events which can be handled by registering event handlers using cpu_handler_register().

As an example, the CPU_ONLINE event allows other subsystems to perform per-CPU initialization on each CPU no matter when they are initialized or even if IPIs are available yet.

This is what makes it possible for SMP to be in a module, at the cost of the system being perhaps slightly unintuitive and edge case heavy.

For more details see cpu_handler_register(), cpu_handler_unregister(), and cpu_handlers_check().

Per-CPU Data

Todo:
Implement per-CPU data. Use separate linker section?

Modules

 GDT
 Global Descriptor Table.
 
 IDT
 Interrupt Descriptor Table.
 
 Interrupts
 Interrupt Handling.
 
 Port I/O
 I/O port operations and reservations.
 
 IPI
 Inter-Processor Interrupts (IPIs)
 
 IRQ
 Interrupt Requests (IRQs)
 
 SIMD
 SIMD context management.
 
 Stack Pointer
 Helpers for managing stacks.
 
 Syscall
 System Call Interface.
 
 TSS
 Task State Segment.
 

Data Structures

struct  cpu_event_t
 CPU event structure. More...
 
struct  cpu_handler_t
 
struct  cpu_t
 CPU structure. More...
 

Macros

#define CPU_MAX   (UINT8_MAX + 1)
 Maximum number of CPUs supported.
 
#define CPU_ID_BOOTSTRAP   0
 ID of the bootstrap CPU.
 
#define CPU_ID_INVALID   UINT16_MAX
 Invalid CPU ID.
 
#define CPU_STACK_CANARY   0x1234567890ABCDEFULL
 CPU stack canary value.
 
#define CPU_MAX_EVENT_HANDLERS   32
 Maximum number of CPU event handlers that can be registered.
 
#define CPU_FOR_EACH(cpu)
 Macro to iterate over all CPUs.
 
#define CPU_MAX   UINT8_MAX
 Maximum number of CPUs supported.
 
#define CPU_ID_BOOTSTRAP   0
 ID of the bootstrap CPU.
 
#define CPU_ID_INVALID   UINT16_MAX
 Invalid CPU ID.
 

Typedefs

typedef uint16_t cpuid_t
 Type used to identify a CPU.
 
typedef void(* cpu_func_t) (cpu_t *cpu, const cpu_event_t *event)
 CPU event function type.
 
typedef uint16_t cpuid_t
 Type used to identify a CPU.
 

Enumerations

enum  cpu_event_type_t { CPU_ONLINE , CPU_OFFLINE }
 CPU event types. More...
 

Functions

void cpu_init_early (cpu_t *cpu)
 Only initialize the parts of the CPU structure needed for early boot.
 
void cpu_init (cpu_t *cpu)
 Initializes the CPU represented by the cpu_t structure.
 
uint64_t cpu_handler_register (cpu_func_t func)
 Registers a CPU event handler for all CPUs.
 
void cpu_handler_unregister (cpu_func_t func)
 Unregisters a previously registered CPU event handler.
 
void cpu_handlers_check (cpu_t *cpu)
 Checks if any handlers have been registered since the last check, and invokes them if so.
 
void cpu_stacks_overflow_check (cpu_t *cpu)
 Checks for CPU stack overflows.
 
uint64_t cpu_halt_others (void)
 Halts all other CPUs.
 
static uint16_t cpu_amount (void)
 Gets the number of identified CPUs.
 
static cpu_tcpu_get_by_id (cpuid_t id)
 Gets a CPU structure by its ID.
 
static cpu_tcpu_get (void)
 Gets the current CPU structure.
 
static void cpu_put (void)
 Releases the current CPU structure.
 
static cpu_tcpu_get_unsafe (void)
 Gets the current CPU structure without disabling interrupts.
 
static cpuid_t cpu_get_id_unsafe (void)
 Gets the current CPU ID.
 
static cpu_tcpu_get_next (cpu_t *current)
 Gets the next CPU in the CPU array.
 

Variables

cpu_t_cpus [CPU_MAX]
 Array of pointers to cpu_t structures for each CPU, indexed by CPU ID.
 
uint16_t _cpuAmount
 The number of CPUs currently identified.
 

Macro Definition Documentation

◆ CPU_MAX [1/2]

#define CPU_MAX   (UINT8_MAX + 1)

Maximum number of CPUs supported.

Definition at line 51 of file cpu.h.

◆ CPU_ID_BOOTSTRAP [1/2]

#define CPU_ID_BOOTSTRAP   0

ID of the bootstrap CPU.

Definition at line 56 of file cpu.h.

◆ CPU_ID_INVALID [1/2]

#define CPU_ID_INVALID   UINT16_MAX

Invalid CPU ID.

Definition at line 61 of file cpu.h.

◆ CPU_STACK_CANARY

#define CPU_STACK_CANARY   0x1234567890ABCDEFULL

CPU stack canary value.

Placed at the bottom of CPU stacks, we then check in the interrupt handler if any of the stacks have overflowed by checking if its canary has been modified.

Definition at line 74 of file cpu.h.

◆ CPU_MAX_EVENT_HANDLERS

#define CPU_MAX_EVENT_HANDLERS   32

Maximum number of CPU event handlers that can be registered.

We need to statically allocate the event handler array such that handlers can be registered before memory allocation has been initialized.

Definition at line 100 of file cpu.h.

◆ CPU_FOR_EACH

#define CPU_FOR_EACH (   cpu)
Value:
for (cpuid_t _cpuId = 0; _cpuId < _cpuAmount; _cpuId++) \
for (cpu_t* cpu = _cpus[_cpuId]; cpu != NULL; cpu = NULL)
cpu_t * _cpus[CPU_MAX]
Array of pointers to cpu_t structures for each CPU, indexed by CPU ID.
Definition cpu.c:23
uint16_t _cpuAmount
The number of CPUs currently identified.
Definition cpu.c:24
uint16_t cpuid_t
Type used to identify a CPU.
Definition cpu.h:66
#define NULL
Pointer error value.
Definition NULL.h:23
CPU structure.
Definition cpu.h:122

Macro to iterate over all CPUs.

The main reason for using this macro is to avoid changes the the internal implementation of how CPUs are stored affecting other parts of the code.

Parameters
cpuLoop variable, a pointer to the current cpu_t.

Definition at line 339 of file cpu.h.

◆ CPU_MAX [2/2]

#define CPU_MAX   UINT8_MAX

Maximum number of CPUs supported.

Definition at line 14 of file cpu_id.h.

◆ CPU_ID_BOOTSTRAP [2/2]

#define CPU_ID_BOOTSTRAP   0

ID of the bootstrap CPU.

Definition at line 19 of file cpu_id.h.

◆ CPU_ID_INVALID [2/2]

#define CPU_ID_INVALID   UINT16_MAX

Invalid CPU ID.

Definition at line 24 of file cpu_id.h.

Typedef Documentation

◆ cpuid_t [1/2]

typedef uint16_t cpuid_t

Type used to identify a CPU.

Definition at line 66 of file cpu.h.

◆ cpu_func_t

typedef void(* cpu_func_t) (cpu_t *cpu, const cpu_event_t *event)

CPU event function type.

Definition at line 105 of file cpu.h.

◆ cpuid_t [2/2]

typedef uint16_t cpuid_t

Type used to identify a CPU.

Definition at line 29 of file cpu_id.h.

Enumeration Type Documentation

◆ cpu_event_type_t

CPU event types.

Enumerator
CPU_ONLINE 
CPU_OFFLINE 

Definition at line 80 of file cpu.h.

Function Documentation

◆ cpu_init_early()

void cpu_init_early ( cpu_t cpu)

Only initialize the parts of the CPU structure needed for early boot.

The only reason we need this is to split the initialization of the bootstrap CPU to avoid circular dependencies during early boot and since we cant use memory allocation yet.

Parameters
cpuThe CPU structure to initialize.

Definition at line 30 of file cpu.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpu_init()

void cpu_init ( cpu_t cpu)

Initializes the CPU represented by the cpu_t structure.

Must be called on the CPU that will be represented by the cpu structure, after setting the CPU ID MSR using cpu_init_early().

Parameters
cpuThe CPU structure to initialize.

Definition at line 78 of file cpu.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpu_handler_register()

uint64_t cpu_handler_register ( cpu_func_t  func)

Registers a CPU event handler for all CPUs.

The registered handler will be immediately invoked with a CPU_ONLINE event on the current CPU, then invoked on all others when they call cpu_handlers_check() and on any new cpus when they are initialized.

Parameters
funcThe event function to register a handler for.
Returns
On success, 0. On failure, ERR and errno is set to:
  • EINVAL: Invalid parameters.
  • EBUSY: Too many event handlers registered.
  • EEXIST: A handler with the same function is already registered.

Definition at line 100 of file cpu.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpu_handler_unregister()

void cpu_handler_unregister ( cpu_func_t  func)

Unregisters a previously registered CPU event handler.

Will be a no-op if the handler was not registered.

Parameters
funcThe event function of the handler to unregister, or NULL for no-op.

Definition at line 150 of file cpu.c.

Here is the call graph for this function:

◆ cpu_handlers_check()

void cpu_handlers_check ( cpu_t cpu)

Checks if any handlers have been registered since the last check, and invokes them if so.

Parameters
cpuThe CPU to check, must be the current CPU.

Definition at line 172 of file cpu.c.

Here is the call graph for this function:

◆ cpu_stacks_overflow_check()

void cpu_stacks_overflow_check ( cpu_t cpu)

Checks for CPU stack overflows.

Checks the canary values at the bottom of each CPU stack and if its been modified panics.

Parameters
cpuThe CPU to check.

Definition at line 193 of file cpu.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpu_halt_others()

uint64_t cpu_halt_others ( void  )

Halts all other CPUs.

Returns
On success, 0. On failure, ERR and errno is set.

Definition at line 225 of file cpu.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpu_amount()

static uint16_t cpu_amount ( void  )
inlinestatic

Gets the number of identified CPUs.

Use this over _cpuAmount.

Returns
The number of identified CPUs.

Definition at line 234 of file cpu.h.

Here is the caller graph for this function:

◆ cpu_get_by_id()

static cpu_t * cpu_get_by_id ( cpuid_t  id)
inlinestatic

Gets a CPU structure by its ID.

Parameters
idThe ID of the CPU to get.
Returns
A pointer to the CPU structure, or NULL if no CPU with the given ID exists.

Definition at line 245 of file cpu.h.

◆ cpu_get()

static cpu_t * cpu_get ( void  )
inlinestatic

Gets the current CPU structure.

Disables interrupts to prevent migration to another CPU.

Should be followed be a call to cpu_put() to re-enable interrupts.

Returns
A pointer to the current CPU structure.

Definition at line 263 of file cpu.h.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpu_put()

static void cpu_put ( void  )
inlinestatic

Releases the current CPU structure.

Re-enables interrupts.

Definition at line 277 of file cpu.h.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpu_get_unsafe()

static cpu_t * cpu_get_unsafe ( void  )
inlinestatic

Gets the current CPU structure without disabling interrupts.

Warning
This function does not disable interrupts, it should thus only be used when interrupts are already disabled.
Returns
A pointer to the current CPU structure.

Definition at line 289 of file cpu.h.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpu_get_id_unsafe()

static cpuid_t cpu_get_id_unsafe ( void  )
inlinestatic

Gets the current CPU ID.

Warning
This function does not disable interrupts, it should thus only be used when interrupts are already disabled.
Returns
The current CPU ID.

Definition at line 306 of file cpu.h.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cpu_get_next()

static cpu_t * cpu_get_next ( cpu_t current)
inlinestatic

Gets the next CPU in the CPU array.

Wraps around to the first CPU if the current CPU is the last one.

Parameters
currentThe current CPU.
Returns
A pointer to the next CPU.

Definition at line 321 of file cpu.h.

Variable Documentation

◆ _cpus

cpu_t* _cpus[CPU_MAX]
extern

Array of pointers to cpu_t structures for each CPU, indexed by CPU ID.

We make this global since its accessed very frequently, so its a slight optimization.

Definition at line 23 of file cpu.c.

◆ _cpuAmount

uint16_t _cpuAmount
extern

The number of CPUs currently identified.

Use cpu_amount() over this variable.

Definition at line 24 of file cpu.c.