Memory Interrupt Vector Lifetimes - Mainkill1/SpiritBoot GitHub Wiki
Owned interrupt-vector roots and excess-stub lifetime
Identity and review boundary
Owned reconstructed release64 tree 1277f2b7bf45a0992ef56d45d55815396d46ac8d, product main d4350b603452e029d0862fb48e7d4907e489e8ef. The relative owned source paths below identify the reconstructed kernel build.
References below are relative to that reconstructed source tree. Exact linked size metadata is retained in the local lab's current64-inventory.json and current64-all-symbols.csv, and published in Memory-Function-and-Table-Ledger. No product edits, private reference reads, builds/tests, rig actions, or firmware qualification were performed.
Current GitHub searches for IDT, vector, unexpected handlers and interrupt stubs found no dedicated implementation PR. Issue #106 comment6091844208 already publishes this 1,344-byte lead and its unresolved arithmetic/invalid-vector boundary. PR118 and PR131 comment timelines returned no comments. This is further evidence for the existing #106 lead; do not open duplicate tracking based on this report. Search absence is not a guarantee that no unindexed work exists.
Exact emitted range
ntoskrnl/ke/i386/trap.s:83–100 restricts Xbox IDT generation to16 hardware-vector entries after vector47 and sets its descriptor limit to 0x1ff: 64 entries /512 bytes, vectors0–63. ke/i386/exp.c:29–34 explicitly limits selector conversion to those64 entries. ke/i386/kiinit.c:854–859 installs that descriptor as the live IDT.
But the separate handler generator at trap.s:111–118 uses unconditional REPEAT208, emitting vectors48–255. Each generated handler is a two-byte push plus five-byte relative jump to the shared tail. Existing owned COFF boundaries are:
| Boundary | VA |
|---|---|
Vector48 / KiStartUnexpectedRange |
0x84001208 |
| Vector63 | 0x84001271 |
| Vector64 | 0x84001278 |
| Vector255 | 0x840017b1 |
Following KiTrap00 |
0x840017b8 |
Thus excess vectors64–255 occupy the half-open range 0x84001278–0x840017b8 =192 ×7 =1,344 bytes. This is a fixed emitted assembly range with source and adjacent boundary confirmation, not an inferred compiler-function envelope. All208 stubs total1,456 bytes; valid PIC's first16 total112 bytes. Shared tail/template/trap code is excluded from that proposed excess range.
Main .text contains328,884 virtual bytes /81 pages. A layout-neutral1,344-byte reduction would yield327,540 bytes, below the80-page boundary327,680. Potential recovery is one4KiB image page, contingent on final relink/alignment and physical ownership; it is not an already measured saving or permission to discard live pages. Both memory capacities share the same source contract, but these exact VA/size measurements are release64.
Consumer-domain ledger
| Consumer/publication | Actual source domain | Evidence and consequence |
|---|---|---|
| Initial/live hardware IDT | 0–63 entries; PIC handlers48–63 | trap.s:83–100, kiinit.c:859. Vector64+ cannot normally dispatch through this installed descriptor; an interrupt/software INT beyond its limit faults rather than selecting an extra stub. |
| PIC delayed software interrupt reentry | IRQ0–15 → vectors48–63 | hal/halx86/pic/pic.c:152–195 emits16 fixed INT wrappers; its20-entry pending table contains four software slots plus16 hardware handlers (198–220). |
| HAL timer/RTC installation | timer0x30; RTC0x38 | hal/halx86/pic/halinit.c:34–52. These keep valid handlers/template/dispatch ownership resident. |
| Static owned device tree | IRQ1,9,4,5,6,14,15,3 → PIC vectors | ntoskrnl/xb/devtree.c:34–87; translation at 288–307. Its current hardware resources lie inside0–15. |
KiGetVectorDispatch |
no range validation; HAL result narrowed to UCHAR | ke/i386/irqobj.c:26–81; computes KiStartUnexpectedRange + (Entry-48)*KiUnexpectedEntrySize, then queries IDT. This arithmetic root is invisible to a direct-edge-only graph. Entries below48 underflow its intended stub domain; entries64+ exceed the real IDT. |
HalVectorToIDTEntry |
(UCHAR)Vector |
fstub/halstub.c:121–125; no installed replacement was found in the Xbox HAL sources. Large ULONG values wrap to an8-bit IDT entry, not an admission check. |
KeQueryInterruptHandler / KeRegisterInterruptHandler |
indexes Pcr->IDT[Entry] without limit check |
include/internal/i386/ke.h:330–368. Beyond63 is a data read/write past the512-byte IDT even though CPU dispatch would reject that vector. Extra code stubs do not make this memory access valid. |
KeInitializeInterrupt |
stores arbitrary caller ULONG Vector | irqobj.c:327–385. Initialization itself copies/patches the per-object dispatch template and records Vector; no connect-time table access yet. |
KeConnectInterrupt |
validates IRQL, CPU, synchronization, floating save; no Vector check | irqobj.c:407–428. Calls KiGetVectorDispatch before HalEnableSystemInterrupt. Invalid vectors therefore reach IDT access before the HAL's later enable rejection. |
| Connect/share/disconnect setter | trusts Interrupt->Vector |
irqobj.c:92–129,430–479,505–570. KiConnectVectorToInterrupt re-queries and writes the IDT; last disconnect restores the arithmetic NoDispatch pointer. Correct admission must cover the whole lifecycle, not only initial publication. |
Native IoConnectInterrupt |
forwards Vector unvalidated | io/iomgr/irq.c:23–105; driver callers must use translated resources, but the native entry itself does not enforce the Xbox bound. |
| Xbox ordinal109 initializer | forwards title's Vector to native initializer | xb/interrupt.c:101–120; shadow storage prevents structure overrun, not vector overrun. Driver-owned shadows reject replacement. |
| Xbox connect/disconnect wrappers | forward owned shadow to native lifecycle | xb/interrupt.c:161–191; driver-owned objects follow separate borrowed-owner rules. Ordinary shadows can retain invalid Vector from initialization. |
| Xbox ordinal44 HAL translator | title-supplied IRQ passed to ISA HAL | xb/xbe.c:2800–2809, xb/ordinals.map:82. It exposes the broad root-translator boundary described below. |
| Interrupt template and copied return path | required for all connected valid IRQs | trap.s:149–162; irqobj.c:370–385 copies template to mutable object storage and patches object's address. No Vector-specific copy of an unexpected stub is made. Common template, template handler and shared unexpected tail remain runtime code. |
| Processor IDT save/restore and lock-erratum relocation | preserve existing descriptor limit | ke/i386/cpu.c:997,1035,1167–1174. Copy/restore of current IDTR does not broaden its512-byte limit or create IDT roots for64–255. Title-supplied CPU state/direct ring0 modification is outside a normal fixed-platform admission proof. |
The Xbox HAL build includes PIC and system-bus sources explicitly (hal/halx86/xbox.cmake:20,40,67). APIC vector allocation rules in other source variants are not evidence of Xbox consumers.
Concrete unresolved correctness boundary
The current source does not implement one consistent fixed-PIC admission domain:
HalpGetRootInterruptVectoracceptsBusInterruptLevel <=23(hal/halx86/pic/pic.c:1265–1290). It adds primary vector base48, producing vectors64–71 for IRQs16–23. This is reachable from public ordinal44 throughXeHalGetInterruptVector, ISA bus handler registration and inheritance (legacy/bussupp.c:169–180,220–231;legacy/bus/bushndlr.c:349–357) andHalpGetSystemInterruptVector(legacy/bus/sysbus.c:115–135). The latter checks usage flags, not hardware/IDT capacity. These nonexistent PIC IRQs are accepted by implementation, not valid Xbox hardware interrupt sources.HalEnableSystemInterruptrejects onlyIrq >= CLOCK2_LEVEL(pic.c:965–967), whereCLOCK2_LEVELis28 (sdk/include/ndk/i386/asm.h:593). It therefore admits IRQ16–27 by its numeric check. Its dismiss tables have 16 entries (pic.c:55,87); level-sensitive enable can index beyond them at983.HalBeginSystemInterruptalso directly indexes the16-entry dismiss table (1049–1050). Those are existing bounds problems, not made safe by retaining handlers64–255.- The native connect path dereferences/query-writes the64-entry IDT before enable validation. Arbitrary title Vector values can also wrap through UCHAR, including into exception vectors. Assertions are not release admission checks.
Therefore the normal architectural domain is PIC IRQ0–15 /vectors48–63, but the published software APIs do not yet prove that all admitted calls stay in it. No legal fixed-PIC hardware source needs the extra192 handlers; nevertheless, unqualified deletion today would leave arithmetic addresses for invalid calls pointing into unrelated following code. The existing path is already unsafe before handler execution, so this is not evidence that the stubs are required to preserve valid behavior.
Because titles run ring0, a title could intentionally jump to any kernel byte or install its own IDT. This report does not promise to preserve arbitrary private-address execution. Public export and documented interrupt lifecycle behavior, valid resource translation, rejection of unsupported vectors and callback ownership are the relevant boundaries.
Conditions required before removal
This is a correctness-first source boundary list, not an authorized implementation or broad testing campaign:
- Define one Xbox PIC domain and reject unsupported IRQ translation before returning a supposedly usable vector.
- Reject unsupported native connect vectors before IDT query/set, arithmetic stub lookup, PIC bit shifts/table indexing or connected-state mutation. Initialization can retain an invalid marker/value only if every later consumer rejects it safely.
- Cover raw native driver paths and Xbox shadow wrappers; preserve driver-owned borrowed-interrupt lifecycle and valid shared-vector connect/disconnect behavior.
- Keep exception/debug/NMI/task-gate consumers0–47 distinct from device interrupt admission; do not apply a48–63 filter to every generic IDT helper without tracing their non-device callers.
- Bound PIC enable/disable/begin consumers according to their16-entry tables and preserve dispatch-template lifetime for valid IRQs. Establish whether all such internal calls are dominated by validated publication.
- Only then make Xbox handler generation match its16-entry IDT handler family. Retain
KiUnexpectedEntrySizefor the first16, the shared tail, and the per-object template. Verify final link/pages before reporting4KiB recovery.
Status: valid hardware root absence beyond63 is source-established; safe deletion is unproved until software admission and arithmetic consumers are closed. This audit does not claim current title crashes originate here.
Other emitted arrays and false unused symbols
Two related arrays are visibly retained at current owned COFF addresses: HalpIDTUsage at 0x8405f620 and HalpIDTUsageFlags at 0x8405f820. hal/halx86/generic/usage.c:18–19 declares each for256 entries. Their declarations use a two-byte IDTUsage payload (KIRQL byte plus relative-vector byte) and one-byte flag (hal/halx86/include/halp.h:189–198), suggesting 768 declared payload bytes versus192 for64 entries, a 576-byte domain-specialization lead. The accompanying Memory-Additional-Table-Lifetimes now independently proves both production array bodies with the captured compiler flags: 512 and 256 bytes. The 576-byte specialization difference remains conditional, not a recovered page.
They are not currently removable arrays: usage registration indexes SystemVector (usage.c:571–575), HAL translation reads flags for the broad accepted domain (sysbus.c:132–135), and generic reporting scans through MAXIMUM_IDTVECTOR (usage.c:399–409). Whole reporting-path runtime inclusion also requires care: its source presence alone does not prove a linked consumer. Shrinking only declarations would be unsafe while these readers/writers retain their bounds. They share .bss backing with live objects;576 bytes is not a demonstrated page recovery.
KiInterruptTemplate2ndDispatch and KiInterruptTemplateObject appear unrooted as standalone static graph labels, but they are interior labels in the template copied by KeInitializeInterrupt, used to compute its patch destination. They are not unused functions/stubs. Likewise the first16 unexpected handlers and SWInterruptHandlerTable entries are runtime indirect roots. No other safely unneeded retained array or public/address-taken stub was established by this bounded audit.