Page 1 of 2
IDT & Optimization
Posted: Sat Apr 19, 2014 12:22 pm
by inixsoftware
When I compile my kernel using -O2 GCC flag, everything is fine: no crashes, everything runs as it should.
However, if I change this -O3 or -Ofast, it no longer works as it should. The GDT is loaded (no crash),
but when I load the IDT.....system reset.
The GDT and IDT structs both use attribute packed, so does the -O3 (as well as -Ofast), mess with it and disregard it...If so, wouldn't it crash at GDT installation?
I'm curious why this happens. Note: I tested this using qemu-system-i386
Re: IDT & Optimization
Posted: Sat Apr 19, 2014 3:02 pm
by Nable
Quick and usual answer: use Bochs or QEmu built-in debugger to see what is happening.
One should look at the dissassembly near 'lgdt' instruction, examine what is loaded into segment registers and what is the exact instruction that causes triple-fault.
Re: IDT & Optimization
Posted: Sat Apr 19, 2014 5:53 pm
by sortie
You may be interested in these wiki articles:
http://wiki.osdev.org/IDT_problems
http://wiki.osdev.org/James_Molloy's_Known_Bugs
http://wiki.osdev.org/System_V_ABI
My magic crystal ball tells me what your assembly is not following the ABI of your target platform or somehow writing code that the compiler is allowed to optimize because you wrote it poorly. Please share your IDT setting code and other relevant bits, so we can get an idea of what is going on. Usually when the kernel breaks when optimization levels are changed, it means that you are writing poor code and generally abuse the language and compiler, rather than working together with the compiler in a robust way.
Re: IDT & Optimization
Posted: Sat Apr 19, 2014 6:23 pm
by inixsoftware
My IDT struct code is:
Code: Select all
struct idt_entry
{
unsigned short base_lo;
unsigned short sel;
unsigned char always0;
unsigned char flags;
unsigned short base_hi;
} __attribute__((packed));
struct idt_ptr
{
unsigned short limit;
unsigned int base;
} __attribute__((packed));
struct idt_entry idt[256];
struct idt_ptr idtp;
void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags)
{
idt[num].base_lo = (base & 0xFFFF);
idt[num].base_hi = (base >> 16) & 0xFFFF;
idt[num].sel = sel;
idt[num].always0 = 0;
idt[num].flags = flags;
}
/* Installs the IDT */
void idt_install()
{
idtp.limit = (sizeof (struct idt_entry) * 256) - 1;
idtp.base = (unsigned int)&idt;
/* Clear out the entire IDT, initializing it to zeros */
memset(&idt, 0, sizeof(struct idt_entry) * 256);
idt_load();
}
/* Assembly function idt_load() in NASM */
global idt_load
extern idtp
idt_load:
lidt [idtp]
ret
Is there something wrong with this that is causing this to not work with
-O3?
Re: IDT & Optimization
Posted: Sat Apr 19, 2014 8:23 pm
by Bender
Please bother to show us the assembler output.
EDIT: For both -O2 and -O3
Re: IDT & Optimization
Posted: Sat Apr 19, 2014 8:26 pm
by inixsoftware
What do you mean by assembler output?
Re: IDT & Optimization
Posted: Sat Apr 19, 2014 8:30 pm
by Bender
Show us what you get from GCC after the initial compilation. Hint: '-S' or if you prefer disassemble the kernel.
And show only the relevant parts.
Re: IDT & Optimization
Posted: Sat Apr 19, 2014 8:41 pm
by inixsoftware
OK. Well, for -O2 I get this:
Code: Select all
.file "idt.c"
.text
.align 16
.globl idt_set_gate
.type idt_set_gate, @function
idt_set_gate:
.LFB0:
.cfi_startproc
movzbl 4(%esp), %eax
movl 8(%esp), %edx
movb $0, idt+4(,%eax,8)
movw %dx, idt(,%eax,8)
shrl $16, %edx
movw %dx, idt+6(,%eax,8)
movl 12(%esp), %edx
movw %dx, idt+2(,%eax,8)
movl 16(%esp), %edx
movb %dl, idt+5(,%eax,8)
ret
.cfi_endproc
.LFE0:
.size idt_set_gate, .-idt_set_gate
.align 16
.globl idt_install
.type idt_install, @function
idt_install:
.LFB1:
.cfi_startproc
subl $28, %esp
.cfi_def_cfa_offset 32
movl $2047, %eax
movl $2048, 8(%esp)
movl $0, 4(%esp)
movl $idt, (%esp)
movw %ax, idtp
movl $idt, idtp+2
call memset
addl $28, %esp
.cfi_def_cfa_offset 4
jmp idt_load
.cfi_endproc
.LFE1:
.size idt_install, .-idt_install
.comm idtp,6,1
.comm idt,2048,32
.ident "GCC: (GNU) 4.8.2"
and for -O3:
Code: Select all
.file "idt.c"
.text
.align 16
.globl idt_set_gate
.type idt_set_gate, @function
idt_set_gate:
.LFB0:
.cfi_startproc
movzbl 4(%esp), %eax
movl 8(%esp), %edx
movb $0, idt+4(,%eax,8)
movw %dx, idt(,%eax,8)
shrl $16, %edx
movw %dx, idt+6(,%eax,8)
movl 12(%esp), %edx
movw %dx, idt+2(,%eax,8)
movl 16(%esp), %edx
movb %dl, idt+5(,%eax,8)
ret
.cfi_endproc
.LFE0:
.size idt_set_gate, .-idt_set_gate
.align 16
.globl idt_install
.type idt_install, @function
idt_install:
.LFB1:
.cfi_startproc
subl $28, %esp
.cfi_def_cfa_offset 32
movl $2047, %eax
movl $2048, 8(%esp)
movl $0, 4(%esp)
movl $idt, (%esp)
movw %ax, idtp
movl $idt, idtp+2
call memset
addl $28, %esp
.cfi_def_cfa_offset 4
jmp idt_load
.cfi_endproc
.LFE1:
.size idt_install, .-idt_install
.comm idtp,6,1
.comm idt,2048,32
.ident "GCC: (GNU) 4.8.2"
They are both exactly the same... This makes me even more confused why one works and the other doesn't...
Re: IDT & Optimization
Posted: Sat Apr 19, 2014 9:03 pm
by Bender
They are both exactly the same... This makes me even more confused why one works and the other doesn't...
Which gives me an impression that the problem is somewhere else, or worse there may be a bug in your code itself. As previously said, use Bochs and look at it's output, I bet you'll get what you want.
Re: IDT & Optimization
Posted: Sat Apr 19, 2014 9:25 pm
by hometue
Maybe you can use breakpoints to tell exactly which line will it reset.. (afterall Bochs is just really powerful, you can do so much with it)
Re: IDT & Optimization
Posted: Sat Apr 19, 2014 9:27 pm
by Brendan
Hi,
inixsoftware wrote:They are both exactly the same... This makes me even more confused why one works and the other doesn't...
That suggests the problem is somewhere else. Possibilities include a timing dependent problem (e.g. maybe an IRQ occurs after X ms, and changing the speed of any previous code causes the IRQ to interrupt in different places), a "random" memory corruption in any previous code (e.g. writing to an uninitialised pointer, memory management bugs, etc; where minor differences in memory layout or stack layout results in something different getting trashed), a boot loader problem (e.g. only loading 4 sectors, where "-O3" makes the kernel slightly larger than 4 sectors), etc.
Mostly, you're going to need to find out more about the symptoms. Does it do the same on different computers/emulators? Does it lock up, or cause an exception? Which exception? What is the return CS:EIP for the exception? Does the memory at that address contain the instruction/s you expect (and what are they)? What is the exception's error code?
Cheers,
Brendan
Re: IDT & Optimization
Posted: Sun Apr 20, 2014 7:03 am
by inixsoftware
OK. So now from the Bochs console, when I use my kernel compiled with -O3 I get:
00128266044e[CPU0 ] interrupt(): gate.type(9) != {5,6,7,14,15}
00128266044e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x
0d)
00128266044e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x
08)
00128266044i[CPU0 ] CPU is in protected mode (active)
00128266044i[CPU0 ] CS.mode = 32 bit
00128266044i[CPU0 ] SS.mode = 32 bit
00128266044i[CPU0 ] EFER = 0x00000000
00128266044i[CPU0 ] | EAX=00000800 EBX=00108060 ECX=00000026 EDX=00000000
00128266044i[CPU0 ] | ESP=00100128 EBP=0007feac ESI=00118dc8 EDI=00118dc8
00128266044i[CPU0 ] | IOPL=0 ID vip vif ac vm RF nt OF df if tf SF zf af pf cf
00128266044i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00128266044i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 ffffffff 1 1
00128266044i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00128266044i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00128266044i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00128266044i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00128266044i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00128266044i[CPU0 ] | EIP=00100135 (00100135)
00128266044i[CPU0 ] | CR0=0x60000011 CR2=0x00000000
00128266044i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
(0).[128266044] [0x000000100135] 0008:0000000000100135 (unk. ctxt): (invalid)
; ffff
00128266044e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown
status is 00h, resetting
00128266044i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
00128266044i[CPU0 ] cpu hardware reset
while with -O2 I get no issue. Is the -O3 causing gate problems which cause the reset?
Re: IDT & Optimization
Posted: Sun Apr 20, 2014 7:14 am
by Bender
00128266044e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown
status is 00h, resetting
You know what's wrong, do you?
Re: IDT & Optimization
Posted: Sun Apr 20, 2014 7:34 am
by inixsoftware
So my IDT must be invalid causing a double fault (and since there were no double fault handlers) which caused a triple fault, system reset. Is that right?
Re: IDT & Optimization
Posted: Sun Apr 20, 2014 8:13 am
by Bender
inixsoftware wrote:So my IDT must be invalid causing a double fault (and since there were no double fault handlers) which caused a triple fault, system reset. Is that right?
Exception
13........ Does that sound familiar? Hmm....