Skip to content

Commit 511bc5c

Browse files
make irq_stub and interrupt_stub show in stack trace, show the faulting function and error code info, skip the error handler context
1 parent b13d3c4 commit 511bc5c

File tree

7 files changed

+93
-10
lines changed

7 files changed

+93
-10
lines changed

asm/loader.S

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ idt_loop:
4646
retq
4747

4848
.macro ISR_NOERR isr
49+
.global isr\isr
50+
.type isr\isr, @function
4951
isr\isr:
5052
MPUSHA
5153
mov $0, %rsi
@@ -54,6 +56,8 @@ isr\isr:
5456
.endm
5557

5658
.macro ISR_ERR isr
59+
.global isr\isr
60+
.type isr\isr, @function
5761
isr\isr:
5862
pop %rax
5963
MPUSHA
@@ -63,6 +67,8 @@ isr\isr:
6367
.endm
6468

6569
.macro IRQ num byte
70+
.global irq\num
71+
.type irq\num, @function
6672
irq\num:
6773
MPUSHA
6874
mov $\byte, %rdi
@@ -385,19 +391,29 @@ isrs:
385391
// Common stubs
386392
// ----------------------
387393

394+
.global irq_stub
395+
.type irq_stub, @function
388396
irq_stub:
397+
xor %rdx, %rdx /* 3rd arg (rip)=0 for IRQ path */
389398
PUSH_SENTINEL
390399
call IRQ
391400
POP_SENTINEL
392401
MPOPA
393402
iretq
403+
.size irq_stub, .-irq_stub
394404

405+
.global interrupt_stub
406+
.type interrupt_stub, @function
395407
interrupt_stub:
408+
/* MPUSHA pushed 15 regs = 120 bytes; ISR_ERR popped error code already.
409+
The HW-saved RIP is at +120(%rsp) here (kernel->kernel case). */
410+
mov 120(%rsp), %rdx /* 3rd arg (rip) for Interrupt() */
396411
PUSH_SENTINEL
397412
call Interrupt
398413
POP_SENTINEL
399414
MPOPA
400415
iretq
416+
.size interrupt_stub, .-interrupt_stub
401417

402418
exception_handlers:
403419
.quad isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7

include/debugger.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,6 @@ void gdb_decode(char* out, const uint8_t* in, size_t len);
5151
void gdb_emit();
5252
uint32_t gdb_trace(const char* str);
5353

54+
const char* findsymbol(uint64_t address, uint64_t* offset);
55+
5456
uint64_t findsymbol_addr(const char *name);

include/interrupt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ bool register_interrupt_handler(uint8_t n, isr_t handler, pci_dev_t device, void
9797
* @param isrnumber The interrupt service routine number (0–31).
9898
* @param errorcode The associated CPU-generated error code (or zero if unused).
9999
*/
100-
void Interrupt(uint64_t isrnumber, uint64_t errorcode);
100+
void Interrupt(uint64_t isrnumber, uint64_t errorcode, uint64_t rip);
101101

102102
/**
103103
* @brief Global entry point for hardware IRQs (ISR ≥ 32, remapped).

modules/e1000/e1000.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,11 @@ void e1000_handle_receive() {
207207
rx_cur = (rx_cur + 1) % E1000_NUM_RX_DESC;
208208
e1000_write_command(REG_RXDESCTAIL, old_cur);
209209
}
210+
211+
if (get_ticks() > 5000) {
212+
int *a = 0;
213+
*a = 0;
214+
}
210215
}
211216

212217
void e1000_check_link() {

src/debugger.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -459,15 +459,23 @@ void backtrace(void) {
459459
size_t depth = 0;
460460
get_kstack_bounds(&lo, &hi);
461461

462-
/* We know we’re in an ISR/exception at the top */
463-
setforeground(COLOUR_LIGHTYELLOW);
464-
aprintf("--------------------------------[ IRQ/TRAP CONTEXT ]--------------------------------\n");
462+
/* If we’re in an ISR/exception at the top */
465463
size_t remaining_markers = count_markers_ahead(frame, lo, hi, depth);
464+
uint32_t skip = 0;
466465
setforeground(COLOUR_LIGHTGREEN);
466+
467467
while (frame && CANONICAL_ADDRESS(frame) && (uintptr_t)frame >= lo && (uintptr_t)frame <= (hi - sizeof(*frame)) && depth++ < 1024) {
468468

469469
stack_frame_t *next = frame->next;
470470

471+
/* always drop error_handler -> Interrupt -> interrupt_stub.
472+
* Tracing through the error handler itself is not useful
473+
*/
474+
if (skip++ < 3) {
475+
frame = next;
476+
continue;
477+
}
478+
471479
if (next && (uintptr_t)next <= (uintptr_t)frame) {
472480
break;
473481
} else if (frame->addr == BT_IRQ_MARKER) {
@@ -487,7 +495,6 @@ void backtrace(void) {
487495
uint64_t offset = 0;
488496
const char *mname = NULL, *sname = NULL;
489497
if (module_addr_to_symbol(frame->addr, &mname, &sname, &offset)) {
490-
/* print "mname:sname+off" (or mname:[???]) */
491498
aprintf("\t%s:%s()+0%08lx [0x%lx]\n", mname, sname, offset, (uint64_t) frame->addr);
492499
} else {
493500
const char *name = findsymbol((uint64_t) frame->addr, &offset);

src/errorhandler.c

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,67 @@ const char* tail_last_lines(const char *s, size_t n) {
7272
return s;
7373
}
7474

75+
/* Tiny decoder for exceptions that carry an error code */
76+
static inline const char* print_error_code_detail(uint64_t vec, uint64_t ec) {
77+
static char message[MAX_STRINGLEN];
78+
switch (vec) {
79+
case 10: /* #TS */
80+
case 11: /* #NP */
81+
case 12: /* #SS */
82+
case 13: { /* #GP */
83+
const unsigned ext = (ec >> 0) & 1; /* set if originated externally */
84+
const unsigned idt = (ec >> 1) & 1; /* 1 => refers to IDT gate */
85+
const unsigned ti = (ec >> 2) & 1; /* 0=GDT, 1=LDT (ignored if idt=1) */
86+
const unsigned idx = (unsigned)((ec >> 3) & 0x1FFF); /* selector index */
7587

76-
void error_handler(uint8_t int_no, uint64_t errorcode, uint64_t irq_no, void* opaque) {
88+
const char *table = idt ? "IDT" : (ti ? "LDT" : "GDT");
89+
snprintf(message, MAX_STRINGLEN, "idx=%u, table=%s%s", idx, table, ext ? ", ext" : "");
90+
break;
91+
}
92+
case 14: { /* #PF: Page Fault */
93+
const int p = (ec >> 0) & 1; /* 0=not-present, 1=protection */
94+
const int wr = (ec >> 1) & 1; /* 1=write, 0=read */
95+
const int us = (ec >> 2) & 1; /* 1=user, 0=kernel */
96+
const int rsv = (ec >> 3) & 1; /* reserved bit violation */
97+
const int ift = (ec >> 4) & 1; /* instruction fetch */
98+
const int pkey= (ec >> 5) & 1; /* protection key (if enabled) */
99+
const int sstk= (ec >> 6) & 1; /* CET shadow stack (if enabled) */
100+
/* bit 7 (HLAT) exists on some parts; ignore silently if 0 */
101+
102+
snprintf(message, MAX_STRINGLEN, "%s, %s, %s%s%s%s%s",
103+
p ? "protection" : "not-present",
104+
wr ? "write" : "read",
105+
us ? "user" : "kernel",
106+
rsv ? ", rsvd-bit" : "",
107+
ift ? ", ifetch" : "",
108+
pkey ? ", pkey" : "",
109+
sstk ? ", sstk" : "");
110+
break;
111+
}
112+
default:
113+
snprintf(message, MAX_STRINGLEN, "no error detail");
114+
break;
115+
}
116+
return message;
117+
}
118+
119+
void error_handler(uint8_t int_no, uint64_t errorcode, uint64_t rip, void* opaque) {
77120
interrupts_off();
78121
setforeground(COLOUR_LIGHTRED);
79122
setbackground(COLOUR_BLACK);
80123
const char* log = tail_last_lines(dprintf_buffer_snapshot(), 15);
81-
kprintf("\nFatal exception %02X (Error code %016lx): %s\n", int_no, errorcode, error_table[int_no]);
82-
dprintf("\nFatal exception %02X (Error code %016lx): %s\n", int_no, errorcode, error_table[int_no]);
124+
aprintf("\nFatal exception %02X (Error code %016lx): %s (%s)\n", int_no, errorcode, error_table[int_no], print_error_code_detail(int_no, errorcode));
125+
if (rip) {
126+
uint64_t offset = 0;
127+
const char *mname = NULL, *sname = NULL;
128+
if (module_addr_to_symbol(rip, &mname, &sname, &offset)) {
129+
/* print "mname:sname+off" (or mname:[???]) */
130+
aprintf("\tfault @ %s:%s()+0%08lx [0x%lx]\n", mname, sname, offset, (uint64_t) rip);
131+
} else {
132+
const char *name = findsymbol(rip, &offset);
133+
aprintf("\tfault @ %s()+0%08lx [0x%lx]\n", name ? name : "[???]", offset, (uint64_t) rip);
134+
}
135+
}
83136
setforeground(COLOUR_WHITE);
84137
kprintf("------------------------------------[ DEBUG LOG ]-----------------------------------\n");
85138
setforeground(COLOUR_GREY);

src/interrupt.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ void local_apic_clear_interrupt()
8383

8484
/* Both the Interrupt() and ISR() functions are dispatched from the assembly code trampoline via a pre-set IDT */
8585

86-
void Interrupt(uint64_t isrnumber, uint64_t errorcode) {
86+
void Interrupt(uint64_t isrnumber, uint64_t errorcode, uint64_t rip) {
8787
__attribute__((aligned(16))) uint8_t fx[512];
8888
__builtin_ia32_fxsave64(&fx);
8989

@@ -92,7 +92,7 @@ void Interrupt(uint64_t isrnumber, uint64_t errorcode) {
9292
* they are purely routed to interested handlers
9393
*/
9494
if (si->interrupt_handler) {
95-
si->interrupt_handler((uint8_t) isrnumber, errorcode, 0, si->opaque);
95+
si->interrupt_handler((uint8_t) isrnumber, errorcode, rip, si->opaque);
9696
}
9797
}
9898

0 commit comments

Comments
 (0)