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. :wink:
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....