Files
LithosAnanake/src/starkernel/arch/amd64/isr.S
T
Robert Allan JamesandClaude Sonnet 5 8717416d36
Build / build-amd64-iso (push) Waiting to run
Build / build-aarch64-iso (push) Waiting to run
Build / build-riscv64-img (push) Waiting to run
FABRIC-3.md: version correction -- LITHOS_VERSION back to 2.0.0, plus a rename-gap fix
LITHOS_VERSION 2.0.1 was premature: per this project's own versioning
policy, 2.0.1 claims SER5 hardware-track progress (RDRAND backend +
thumbdrive image) that was never actually verified on real hardware --
that verification is FABRIC-3.md's own open topic. Reset to 2.0.0
(still a QEMU-only release, correctly). Verified 3-arch boot shows
"LithosAnanke v2.0.0" in each serial log directly, not assumed from the
Makefile edit alone.

Also closes a real gap found in today's earlier FABRIC-series rename:
Makefile.starkernel, Kconfig.kernel, scripts/bleach_zuse_img.sh, four
proof/*.thy files, and isr.S were never swept -- the original file list
only matched *.md/*.c/*.h/*.4th, silently skipping every other
extension. Fixed with the same safe placeholder substitution.
.claude/settings.local.json's historical permission-grant log and
ClaudeEXPORT/'s frozen export were deliberately left untouched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
2026-09-04 11:53:44 -04:00

200 lines
4.9 KiB
ArmAsm

/*
* isr.S - Interrupt/exception stubs for amd64
*
* Stack on entry to ISR stub (after CPU pushes):
* [rsp+0] = error code (if any, or pushed 0)
* [rsp+8] = vector (pushed by stub)
* [rsp+16] = RIP
* [rsp+24] = CS
* [rsp+32] = RFLAGS
* [rsp+40] = RSP (if privilege change)
* [rsp+48] = SS (if privilege change)
*
* For IRQs (vector >= 32), we return via IRETQ.
* For exceptions (vector < 32), we halt.
*/
.intel_syntax noprefix
.section .text
/* Mark symbols referenced from C as hidden so the C compiler uses direct
* RIP-relative addressing (LEA) rather than GOT indirection. Without this,
* -fPIC code collapses the GOT reference to a direct MOV that reads the
* symbol's *bytes* instead of its *address*, corrupting the IDT setup. */
.hidden isr_stub_table
.hidden isr_stub0
.hidden isr_stub32
.hidden isr_stub33
.hidden isr_stub_default
.hidden isr_common_entry
.macro ISR_NOERR num
.global isr_stub\num
isr_stub\num:
push 0 /* fake error code */
push \num /* vector number */
jmp isr_common_entry
.endm
.macro ISR_ERR num
.global isr_stub\num
isr_stub\num:
/* error code already on stack from CPU */
push \num /* vector number */
jmp isr_common_entry
.endm
.global isr_common_entry
isr_common_entry:
/* Save all general-purpose registers */
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
/* Stack layout now:
* [rsp+0] = r15
* [rsp+8] = r14
* ...
* [rsp+112] = rax
* [rsp+120] = vector
* [rsp+128] = error
* [rsp+136] = rip
* [rsp+144] = cs
* [rsp+152] = rflags
*/
/* Set up arguments for isr_common_handler(vector, error, rip, cs, rflags, cr2) */
mov rdi, [rsp + 120] /* vector */
mov rsi, [rsp + 128] /* error */
mov rdx, [rsp + 136] /* rip */
mov rcx, [rsp + 144] /* cs */
mov r8, [rsp + 152] /* rflags */
mov r9, cr2 /* cr2 */
/* Pass stack frame pointer (after pushes) as 7th argument */
mov rax, rsp
push rax
call isr_common_handler
add rsp, 8
/* Restore general-purpose registers */
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
/* Remove vector and error code from stack */
add rsp, 16
/* Return from interrupt */
iretq
/* Exception/interrupt stubs (0-31 explicit) */
ISR_NOERR 0
ISR_NOERR 1
ISR_NOERR 2
ISR_NOERR 3
ISR_NOERR 4
ISR_NOERR 5
ISR_NOERR 6
ISR_NOERR 7
ISR_ERR 8
ISR_NOERR 9
ISR_ERR 10
ISR_ERR 11
ISR_ERR 12
ISR_ERR 13
ISR_ERR 14
ISR_NOERR 15
ISR_NOERR 16
ISR_ERR 17
ISR_NOERR 18
ISR_NOERR 19
ISR_NOERR 20
ISR_ERR 21
ISR_NOERR 22
ISR_NOERR 23
ISR_NOERR 24
ISR_NOERR 25
ISR_NOERR 26
ISR_NOERR 27
ISR_NOERR 28
ISR_NOERR 29
ISR_ERR 30
ISR_NOERR 31
/* Stub for APIC Timer (vector 0x20 = 32) */
/* Diagnostic: write raw 'I' to COM1 (0x3F8) when stub is entered.
* If 'I' never appears in the serial log, the stub is never reached
* (bad IDT entry or fault during CPU interrupt delivery). */
.global isr_stub32
isr_stub32:
push 0
push 0x20
jmp isr_common_entry
/* Stub for i8042 keyboard IRQ1, routed via I/O APIC to vector 0x21 = 33
* (item 4.3.5, FABRIC-0.md §27.5). Before this stub existed, vector 33 fell
* through to isr_stub_default below, which unconditionally reports "255"
* regardless of which IDT slot actually fired -- the CPU legitimately took
* IDT[33] (confirmed via the LAPIC's own ISR register), but isr_common_handler
* only ever saw vector 255 and treated a real keyboard IRQ as spurious,
* silently skipping EOI and leaving vector 33 permanently stuck in-service. */
.global isr_stub33
isr_stub33:
push 0
push 33
jmp isr_common_entry
/* Default stub for other vectors (34-255) */
.global isr_stub_default
isr_stub_default:
push 0 /* fake error */
push 255 /* unknown vector, will be logged */
jmp isr_common_entry
/* Use .data instead of .rodata so UEFI applies relocations */
.section .data
.align 8
.global isr_stub_table
isr_stub_table:
.quad isr_stub0, isr_stub1, isr_stub2, isr_stub3
.quad isr_stub4, isr_stub5, isr_stub6, isr_stub7
.quad isr_stub8, isr_stub9, isr_stub10, isr_stub11
.quad isr_stub12, isr_stub13, isr_stub14, isr_stub15
.quad isr_stub16, isr_stub17, isr_stub18, isr_stub19
.quad isr_stub20, isr_stub21, isr_stub22, isr_stub23
.quad isr_stub24, isr_stub25, isr_stub26, isr_stub27
.quad isr_stub28, isr_stub29, isr_stub30, isr_stub31
/* Vector 32 = APIC Timer */
.quad isr_stub32
/* Vector 33 = i8042 keyboard IRQ1 (item 4.3.5) */
.quad isr_stub33
/* Vectors 34-255 default to unknown stub */
.rept 222
.quad isr_stub_default
.endr