Course contentsShow
← Rust
Lesson 1502 of 1,91012. Unsafe Rust and Low-Level AccessFree lesson

Multiprocessor Startup Sequences

You will coordinate the activation of additional CPU cores in a multi-core environment.

In this lesson, you will learn how to orchestrate the transition of secondary application processors (APs) from a dormant state into executing your Rust kernel code.

The Bootstrap Problem

When your system boots, typically only the Bootstrap Processor (BSP) is active. To utilize the rest of your hardware, the BSP must signal the APs to start execution. On x86_64, this involves the Multi-Processor Initialization Protocol, where the BSP sends Inter-Processor Interrupts (IPIs) to the APs.

Because these cores do not yet have a stack, a page table, or even a knowledge of your Rust runtime, they cannot run complex code immediately. They start in "Real Mode" (16-bit) and must be manually transitioned through Protected Mode into 64-bit Long Mode before they can safely execute Rust functions.

The Trampoline

To bridge this gap, we use a "trampoline"—a small piece of position-independent assembly code placed in low memory (below the 1MB mark). The BSP writes the address of this trampoline into a specific hardware register (the Local APIC), triggering an IPI.

The AP begins executing the trampoline, which performs the bare minimum setup:

  1. Loading a temporary Global Descriptor Table (GDT).
  2. Enabling Paging using the page tables defined by your kernel.
  3. Jumping to a 64-bit entry point.

Once in 64-bit mode, the AP needs a stack. You must allocate a unique memory region for each AP's stack before signaling it to start. The assembly code then jumps to a "Rust-level" entry point, usually a function marked #[no_mangle], which assumes responsibility for initializing the local CPU state (like loading the IDT).

// Simplified representation of an AP entry point
#[no_mangle]
pub extern "C" fn ap_entry_point() -> ! {
    // 1. Load the IDT for this specific core
    // 2. Initialize local APIC / timer
    // 3. Enter the kernel's main loop
    loop {
        x86_64::instructions::hlt();
    }
}

This sequence is highly unsafe, as you are manually managing stack pointers and CPU registers. You must ensure that no Rust code executes until the segment registers and page tables are perfectly aligned with your kernel's memory map.

Key Takeaway: Orchestrating multiprocessor startup requires a bridge of assembly "trampoline" code that transitions secondary cores from 16-bit real mode into your 64-bit kernel environment before invoking any Rust logic.