Dear all -
I had a publication deadline to meet last month, so I didn't put any work into Hurd. Now I'm back on it a bit.
I'll let Claude report on the progress. Remember, my idea is to get Claude to be able to describe how to get x64 smp support running so that somebody can easily do it, but without using any code authored by Claude.
The only thing I'd add to Claude's report (pasted below) is that I'm struggling to get GDB to reliably set breakpoints on the kernel. It works to a point, and I don't know exactly what point that is, but I can certainly `hbreak` on `thread_start` and it will catch the first two calls to `thread_start`, but after that it doesn't return anymore for breakpoints or `next` or `step`. What you can do is step by machine instructions using `si`, and you can step all the way through the kernel until it transfers to user space.
Fixing the debugger would really be nice, but I don't know all of the interactions with qemu that's causing this.
Anyway, here's Claude's report:
Subject: GNU Mach x86_64 SMP Development Status Report
Hello,
I'm writing to report on progress with x86_64 SMP support for GNU Mach.
## Status Summary
The x86_64 kernel now boots successfully and transitions to userspace. The kernel can:
- Boot and initialize all subsystems
- Launch the first kernel thread via Load_context()
- Create additional threads during bootstrap
- Load ELF executables via the bootstrap process
- Transition to userspace (confirmed by seeing instruction pointer in low memory)
The system appears to hang after the userspace transition, though this may be the bootstrap task running but not producing output.
## Temporary Simplifications
To achieve this progress, three main workarounds were implemented:
1. **CPU detection always returns 0** - Forces single-CPU mode by hardcoding all CPU number detection macros all CPU number detection macros
2. **Per-CPU data bypasses %gs segment** - Changed `#if NCPUS > 1` to `#if NCPUS > 100` in percpu.h files, forcing direct access to percpu_array[0] instead of using %gs:offset addressing
3. **Assembly MY() macro matches C code** - Changed from `%gs:PERCPU_##stm` to `(percpu_array+PERCPU_##stm)` to use the same fallback as C code
These workarounds disable true SMP functionality but prove the core kernel works.
## Key Bugs Fixed
**Array indexing scale factor mismatch**: The CX() macro used scale factor 8 for all per-CPU arrays, but some arrays (curr_ipl, need_ast) contain 4-byte integers, not 8-byte pointers. Split into CX() for 4-byte arrays and CX8() for 8-byte pointer arrays.
**Segment register inconsistency**: Assembly code was using %gs: addressing while C code used direct array access, causing segment faults. Made both use the same mechanism.
**Type mismatches**: Fixed several int/long type mismatches (cpu_set, in_interrupt) and corrected stack alignment from -4 to -16 bytes.
## Architecture Challenges
Main differences from i386:
- x86_64 long mode uses flat memory model, can't use %cs: segment overrides
- Pointer sizes: 8 bytes vs 4 bytes affects array indexing
- Stack alignment: 16-byte vs 4-byte requirement
- %gs segment must be properly initialized via GDT/MSR for per-CPU data
## Outstanding Questions
1. Is the system actually hung, or is the bootstrap task running without producing console output?
2. What's the next step after userspace transition - does execution continue normally?
3. Should we focus on getting console output from userspace, or on re-enabling SMP features?
## Next Steps
Once userspace execution is confirmed working, incrementally re-enable SMP features:
1. Restore proper CPU detection (test with 1 CPU first)
2. Initialize %gs segment and restore %gs-based per-CPU access
3. Test with multiple CPUs
Documentation has been created in CLAUDE.md (development log), 15Jan2026.md (debug register investigation), and MACH_KDB_GUIDE.md (kernel debugger guide).
Best regards