IDT problems after enabling paging
Posted: Wed Jun 19, 2013 3:10 pm
So, i just set up a page directory and a couple of page tables so i could start using virtual memory.
I load my kernel at 1mb, and run it at 3gb (0xc0000000). I have identity mapped the first 4mb of memory to make enabling paging easier. The only other page table set up is for 4mb starting at VA 0xC0000000.
I'm not sure this issue is directly related to having enabled paging, but who knows. My problem is when i'm installing the IDT:
The problem is when it returns from the install_idt() call:
Shortly after it returns from this function, i get a loop of general protection faults, and double faults. Here's the output from bochs:
I notice that GCC decided to replace my install_idt() function call with a short jump... doesn't that mess up the stack for the return from install_idt()?
Also, why is it executing the same instruction at the same address, twice?
Here's a bochs disassembly of the code:
This is confusing. Before enabling virtual memory, my interrupts worked fine. I even had keyboard input working with a basic command line...
So, why is this happening now?
Edit:
If i replace the install_idt() function call with:
__asm("call install_idt");
It then actually calls the function and returns properly, but i'm still getting those exceptions:
I load my kernel at 1mb, and run it at 3gb (0xc0000000). I have identity mapped the first 4mb of memory to make enabling paging easier. The only other page table set up is for 4mb starting at VA 0xC0000000.
I'm not sure this issue is directly related to having enabled paging, but who knows. My problem is when i'm installing the IDT:
Code: Select all
void idt_init()
{
idt_location.offset = (unsigned long) &idt;
idt_location.size = (sizeof(struct IDT_ENTRY) * 256) - 1;
unsigned char *zero_idt = (unsigned char*) idt;
for(unsigned long i = 0; i <= idt_location.size; i++)
zero_idt[i] = 0;
unsigned char flags = 0x8E; // standard 32 bit interrupt gate
unsigned long offset[256] = {0};
offset[0] = (unsigned long) isr_divide_by_zero;
offset[1] = (unsigned long) isr_debugger;
offset[2] = (unsigned long) isr_nmi;
offset[3] = (unsigned long) isr_breakpoint;
offset[4] = (unsigned long) isr_overflow;
offset[5] = (unsigned long) isr_bounds;
offset[6] = (unsigned long) isr_invalid_opcode;
offset[7] = (unsigned long) isr_coprocessor_not_avail;
offset[8] = (unsigned long) isr_double_fault;
offset[9] = (unsigned long) isr_coprocessor_segment_overrun;
offset[10] = (unsigned long) isr_invalid_tss;
offset[11] = (unsigned long) isr_segment_not_present;
offset[12] = (unsigned long) isr_stack_fault;
offset[13] = (unsigned long) isr_general_protection_fault;
offset[14] = (unsigned long) isr_page_fault;
offset[15] = (unsigned long) isr_reserved;
offset[16] = (unsigned long) isr_math_fault;
offset[17] = (unsigned long) isr_alignment_check;
offset[18] = (unsigned long) isr_machine_check;
offset[19] = (unsigned long) isr_simd_floating_point_exception;
for(int i = 20; i < 256; i++)
offset[i] = (unsigned long) isr_reserved;
offset[32] = (unsigned long) isr_sys_timer;
offset[33] = (unsigned long) isr_keyboard;
offset[34] = (unsigned long) isr_9;
offset[35] = (unsigned long) isr_3;
offset[36] = (unsigned long) isr_4;
offset[37] = (unsigned long) isr_5;
offset[38] = (unsigned long) isr_6;
offset[39] = (unsigned long) isr_7;
offset[40] = (unsigned long) isr_8;
offset[41] = (unsigned long) isr_9;
offset[42] = (unsigned long) isr_10;
offset[43] = (unsigned long) isr_11;
offset[44] = (unsigned long) isr_12;
offset[45] = (unsigned long) isr_13;
offset[46] = (unsigned long) isr_14;
offset[47] = (unsigned long) isr_15;
for(int i = 0; i < 256; i++)
{
// if(i < 20)
// {
// printf("setting isr #%d routine address: 0x%.8x\n", i, offset[i]);
// }
//uncommenting the above block of code causes the problem
idt[i].offset_low = (offset[i] & 0xFFFF);
idt[i].offset_high = ((offset[i] >> 16) & 0xFFFF);
idt[i].selector = 0x08;
idt[i].zero = 0;
idt[i].type_attr = flags;
}
__asm("xchg %bx, %bx"); // bochs magic breakpoint
install_idt();
}
Code: Select all
extern idt_location
global install_idt
install_idt:
lidt [idt_location]
sti
ret
Code: Select all
00024837288i[CPU0 ] [24837288] Stopped on MAGIC BREAKPOINT
(0) Magic breakpoint
Next at t=24837288
(0) [0x000000106a63] 0008:00000000c0106a63 (unk. ctxt): add esp, 0x0000041c
; 81c41c040000
<bochs:2> s
Next at t=24837289
(0) [0x000000106a69] 0008:00000000c0106a69 (unk. ctxt): pop ebx
; 5b
<bochs:3>
Next at t=24837290
(0) [0x000000106a6a] 0008:00000000c0106a6a (unk. ctxt): pop esi
; 5e
<bochs:4>
Next at t=24837291
(0) [0x000000106a6b] 0008:00000000c0106a6b (unk. ctxt): pop edi
; 5f
<bochs:5>
Next at t=24837292
(0) [0x000000106a6c] 0008:00000000c0106a6c (unk. ctxt): pop ebp
; 5d
<bochs:6>
Next at t=24837293
(0) [0x000000106a6d] 0008:00000000c0106a6d (unk. ctxt): jmp .+910 (0xc0106e00) // jump(?) to install_idt()
; e98e030000
<bochs:7>
Next at t=24837294
(0) [0x000000106e00] 0008:00000000c0106e00 (unk. ctxt): lidt ds:0xc012a000
; 0f011d00a012c0
<bochs:8>
Next at t=24837295
(0) [0x000000106e07] 0008:00000000c0106e07 (unk. ctxt): sti
; fb
<bochs:9>
Next at t=24837296
(0) [0x000000106e08] 0008:00000000c0106e08 (unk. ctxt): ret
; c3
<bochs:10>
Next at t=24837297
(0) [0x000000101023] 0008:00000000c0101023 (unk. ctxt): mov dword ptr ss:[esp+4]
, 0x00000028 ; c744240428000000
<bochs:11>
Next at t=24837298
(0) [0x000000101023] 0008:00000000c0101023 (unk. ctxt): mov dword ptr ss:[esp+4] // it seems to repeat this instruction twice, and then double faults?
, 0x00000028 ; c744240428000000
<bochs:12>
Next at t=24837299
(0) [0x000000106e19] 0008:00000000c0106e19 (unk. ctxt): iretd
; cf
<bochs:13>
00024837299e[CPU0 ] fetch_raw_descriptor: GDT: index (297) 52 > limit (17)
Next at t=24837300
(0) [0x000000106e21] 0008:00000000c0106e21 (unk. ctxt): pop eax
; 58
<bochs:14>
Next at t=24837301
(0) [0x000000106e22] 0008:00000000c0106e22 (unk. ctxt): iretd
; cf
<bochs:15>
Next at t=24837302
(0) [0x000000106e19] 0008:00000000c0106e19 (unk. ctxt): iretd
; cf
Also, why is it executing the same instruction at the same address, twice?
Here's a bochs disassembly of the code:
Code: Select all
c0106a63: ( ): add esp, 0x0000041c ; 81c41c040000
c0106a69: ( ): pop ebx ; 5b
c0106a6a: ( ): pop esi ; 5e
c0106a6b: ( ): pop edi ; 5f
c0106a6c: ( ): pop ebp ; 5d
c0106a6d: ( ): jmp .+910 ; e98e030000
c0106a72: ( ): lea esi, dword ptr ds:[esi] ; 8db42600000000
c0106a79: ( ): lea edi, dword ptr ds:[edi] ; 8dbc2700000000
c0106a80: ( ): sub esp, 0x0000001c ; 83ec1c
c0106a83: ( ): mov dword ptr ss:[esp+8], 0x00000004 ; c744240
804000000
c0106a8b: ( ): mov dword ptr ss:[esp+4], 0x0000000f ; c744240
40f000000
c0106a93: ( ): mov dword ptr ss:[esp], 0xc0108438 ; c70424388
410c0
c0106a9a: ( ): call .-1119 ; e8a1fbffff
c0106a9f: ( ): add esp, 0x0000001c ; 83c41c
c0106aa2: ( ): ret ; c3
So, why is this happening now?
Edit:
If i replace the install_idt() function call with:
__asm("call install_idt");
It then actually calls the function and returns properly, but i'm still getting those exceptions:
Code: Select all
00027133602i[CPU0 ] [27133602] Stopped on MAGIC BREAKPOINT
(0) Magic breakpoint
Next at t=27133602
(0) [0x000000106a63] 0008:00000000c0106a63 (unk. ctxt): call .+920 (0xc0106e00)
; e898030000
<bochs:2> s
Next at t=27133603
(0) [0x000000106e00] 0008:00000000c0106e00 (unk. ctxt): lidt ds:0xc012a000
; 0f011d00a012c0
<bochs:3>
Next at t=27133604
(0) [0x000000106e07] 0008:00000000c0106e07 (unk. ctxt): sti
; fb
<bochs:4>
Next at t=27133605
(0) [0x000000106e08] 0008:00000000c0106e08 (unk. ctxt): ret
; c3
<bochs:5>
Next at t=27133606
(0) [0x000000106a68] 0008:00000000c0106a68 (unk. ctxt): add esp, 0x0000041c
; 81c41c040000
<bochs:6>
Next at t=27133607
(0) [0x000000106e19] 0008:00000000c0106e19 (unk. ctxt): iretd
; cf
<bochs:7>
00027133607e[CPU0 ] check_cs(0x0246): not a valid code segment !
Next at t=27133608
(0) [0x000000106e21] 0008:00000000c0106e21 (unk. ctxt): pop eax
; 58
<bochs:8>
Next at t=27133609
(0) [0x000000106e22] 0008:00000000c0106e22 (unk. ctxt): iretd
; cf
<bochs:9>
Next at t=27133610
(0) [0x000000106e19] 0008:00000000c0106e19 (unk. ctxt): iretd
; cf