feat: Fase 8a — Per-CPU data infrastructure with GS-segment access
New files:
- include/arch/x86/percpu.h — Per-CPU data structure and GS-based
accessors (percpu_get, percpu_cpu_index, percpu_current, etc.)
- src/arch/x86/percpu.c — Per-CPU init: creates GDT entries for each
CPU's GS segment pointing to its percpu_data instance
Changes:
- include/arch/x86/smp.h: Split smp_init into smp_enumerate() and
smp_start_aps() to allow percpu_init between enumeration and SIPI
- src/arch/x86/smp.c: Implement two-phase SMP init
- include/arch/x86/gdt.h: Export gdt_ptr struct, gp variable, and
gdt_set_gate_ext() for per-CPU GDT entry creation
- src/arch/x86/gdt.c: Expand GDT from 6 to 24 entries (6 base +
up to 16 per-CPU GS segments). Add gdt_set_gate_ext(). Make gp
non-static.
- src/arch/x86/arch_platform.c: Call smp_enumerate() -> percpu_init()
-> percpu_setup_gs(0) -> smp_start_aps() in correct order
Boot sequence for per-CPU setup:
1. smp_enumerate() — populate cpu_info from ACPI MADT
2. percpu_init() — create GDT entries for each CPU's GS segment
3. percpu_setup_gs(0) — BSP loads its own GS selector
4. smp_start_aps() — send INIT-SIPI-SIPI; each AP calls
percpu_setup_gs(i) during its init
Passes: make, cppcheck, QEMU smoke test (-smp 1 and -smp 4)