|
@@ -13,6 +13,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
13
|
13
|
#include <ipxe/profile.h>
|
14
|
14
|
#include <realmode.h>
|
15
|
15
|
#include <pic8259.h>
|
|
16
|
+#include <ipxe/shell.h>
|
16
|
17
|
|
17
|
18
|
/*
|
18
|
19
|
* This file provides functions for managing librm.
|
|
@@ -43,6 +44,9 @@ struct idtr64 idtr64 = {
|
43
|
44
|
.limit = ( sizeof ( idt64 ) - 1 ),
|
44
|
45
|
};
|
45
|
46
|
|
|
47
|
+/** Length of stack dump */
|
|
48
|
+#define STACK_DUMP_LEN 128
|
|
49
|
+
|
46
|
50
|
/** Timer interrupt profiler */
|
47
|
51
|
static struct profiler timer_irq_profiler __profiler = { .name = "irq.timer" };
|
48
|
52
|
|
|
@@ -159,15 +163,101 @@ static struct profiler * interrupt_profiler ( int intr ) {
|
159
|
163
|
}
|
160
|
164
|
}
|
161
|
165
|
|
|
166
|
+/**
|
|
167
|
+ * Display interrupt stack dump (for debugging)
|
|
168
|
+ *
|
|
169
|
+ * @v intr Interrupt number
|
|
170
|
+ * @v frame32 32-bit interrupt wrapper stack frame (or NULL)
|
|
171
|
+ * @v frame64 64-bit interrupt wrapper stack frame (or NULL)
|
|
172
|
+ */
|
|
173
|
+static __attribute__ (( unused )) void
|
|
174
|
+interrupt_dump ( int intr, struct interrupt_frame32 *frame32,
|
|
175
|
+ struct interrupt_frame64 *frame64 ) {
|
|
176
|
+ unsigned long sp;
|
|
177
|
+ void *stack;
|
|
178
|
+
|
|
179
|
+ /* Do nothing unless debugging is enabled */
|
|
180
|
+ if ( ! DBG_LOG )
|
|
181
|
+ return;
|
|
182
|
+
|
|
183
|
+ /* Print register dump */
|
|
184
|
+ if ( ( sizeof ( physaddr_t ) <= sizeof ( uint32_t ) ) || frame32 ) {
|
|
185
|
+ sp = ( frame32->esp + sizeof ( *frame32 ) -
|
|
186
|
+ offsetof ( typeof ( *frame32 ), esp ) );
|
|
187
|
+ DBGC ( &intr, "INT%d at %04x:%08x (stack %04x:%08lx):\n",
|
|
188
|
+ intr, frame32->cs, frame32->eip, frame32->ss, sp );
|
|
189
|
+ DBGC ( &intr, "cs = %04x ds = %04x es = %04x fs = %04x "
|
|
190
|
+ "gs = %04x ss = %04x\n", frame32->cs, frame32->ds,
|
|
191
|
+ frame32->es, frame32->fs, frame32->gs, frame32->ss );
|
|
192
|
+ DBGC ( &intr, "eax = %08x ebx = %08x ecx = %08x "
|
|
193
|
+ "edx = %08x flg = %08x\n", frame32->eax, frame32->ebx,
|
|
194
|
+ frame32->ecx, frame32->edx, frame32->eflags );
|
|
195
|
+ DBGC ( &intr, "esi = %08x edi = %08x ebp = %08x "
|
|
196
|
+ "esp = %08lx eip = %08x\n", frame32->esi, frame32->edi,
|
|
197
|
+ frame32->ebp, sp, frame32->eip );
|
|
198
|
+ stack = ( ( ( void * ) frame32 ) + sizeof ( *frame32 ) );
|
|
199
|
+ } else {
|
|
200
|
+ DBGC ( &intr, "INT%d at %04llx:%016llx (stack "
|
|
201
|
+ "%04llx:%016llx):\n", intr,
|
|
202
|
+ ( ( unsigned long long ) frame64->cs ),
|
|
203
|
+ ( ( unsigned long long ) frame64->rip ),
|
|
204
|
+ ( ( unsigned long long ) frame64->ss ),
|
|
205
|
+ ( ( unsigned long long ) frame64->rsp ) );
|
|
206
|
+ DBGC ( &intr, "rax = %016llx rbx = %016llx rcx = %016llx\n",
|
|
207
|
+ ( ( unsigned long long ) frame64->rax ),
|
|
208
|
+ ( ( unsigned long long ) frame64->rbx ),
|
|
209
|
+ ( ( unsigned long long ) frame64->rcx ) );
|
|
210
|
+ DBGC ( &intr, "rdx = %016llx rsi = %016llx rdi = %016llx\n",
|
|
211
|
+ ( ( unsigned long long ) frame64->rdx ),
|
|
212
|
+ ( ( unsigned long long ) frame64->rsi ),
|
|
213
|
+ ( ( unsigned long long ) frame64->rdi ) );
|
|
214
|
+ DBGC ( &intr, "rbp = %016llx rsp = %016llx flg = %016llx\n",
|
|
215
|
+ ( ( unsigned long long ) frame64->rbp ),
|
|
216
|
+ ( ( unsigned long long ) frame64->rsp ),
|
|
217
|
+ ( ( unsigned long long ) frame64->rflags ) );
|
|
218
|
+ DBGC ( &intr, "r8 = %016llx r9 = %016llx r10 = %016llx\n",
|
|
219
|
+ ( ( unsigned long long ) frame64->r8 ),
|
|
220
|
+ ( ( unsigned long long ) frame64->r9 ),
|
|
221
|
+ ( ( unsigned long long ) frame64->r10 ) );
|
|
222
|
+ DBGC ( &intr, "r11 = %016llx r12 = %016llx r13 = %016llx\n",
|
|
223
|
+ ( ( unsigned long long ) frame64->r11 ),
|
|
224
|
+ ( ( unsigned long long ) frame64->r12 ),
|
|
225
|
+ ( ( unsigned long long ) frame64->r13 ) );
|
|
226
|
+ DBGC ( &intr, "r14 = %016llx r15 = %016llx\n",
|
|
227
|
+ ( ( unsigned long long ) frame64->r14 ),
|
|
228
|
+ ( ( unsigned long long ) frame64->r15 ) );
|
|
229
|
+ sp = frame64->rsp;
|
|
230
|
+ stack = phys_to_virt ( sp );
|
|
231
|
+ }
|
|
232
|
+
|
|
233
|
+ /* Print stack dump */
|
|
234
|
+ DBGC_HDA ( &intr, sp, stack, STACK_DUMP_LEN );
|
|
235
|
+}
|
|
236
|
+
|
162
|
237
|
/**
|
163
|
238
|
* Interrupt handler
|
164
|
239
|
*
|
165
|
240
|
* @v intr Interrupt number
|
|
241
|
+ * @v frame32 32-bit interrupt wrapper stack frame (or NULL)
|
|
242
|
+ * @v frame64 64-bit interrupt wrapper stack frame (or NULL)
|
|
243
|
+ * @v frame Interrupt wrapper stack frame
|
166
|
244
|
*/
|
167
|
|
-void __attribute__ (( regparm ( 1 ) )) interrupt ( int intr ) {
|
|
245
|
+void __attribute__ (( regparm ( 3 ) ))
|
|
246
|
+interrupt ( int intr, struct interrupt_frame32 *frame32,
|
|
247
|
+ struct interrupt_frame64 *frame64 ) {
|
168
|
248
|
struct profiler *profiler = interrupt_profiler ( intr );
|
169
|
249
|
uint32_t discard_eax;
|
170
|
250
|
|
|
251
|
+ /* Trap CPU exceptions if debugging is enabled. Note that we
|
|
252
|
+ * cannot treat INT8+ as exceptions, since we are not
|
|
253
|
+ * permitted to rebase the PIC.
|
|
254
|
+ */
|
|
255
|
+ if ( DBG_LOG && ( intr < IRQ_INT ( 0 ) ) ) {
|
|
256
|
+ interrupt_dump ( intr, frame32, frame64 );
|
|
257
|
+ DBG ( "CPU exception: dropping to emergency shell\n" );
|
|
258
|
+ shell();
|
|
259
|
+ }
|
|
260
|
+
|
171
|
261
|
/* Reissue interrupt in real mode */
|
172
|
262
|
profile_start ( profiler );
|
173
|
263
|
__asm__ __volatile__ ( REAL_CODE ( "movb %%al, %%cs:(1f + 1)\n\t"
|