Solved General protection fault on return from any interrupt

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
max9403
Posts: 17
Joined: Sun Feb 09, 2014 3:25 pm

Solved General protection fault on return from any interrupt

Post by max9403 »

Seems I can't get this solved :/. On return from any interrupt (ISR or IRQ) I get a General protection fault, here is what is in my registers when it happens (with the struct):

Code: Select all

struct regs {
	unsigned int gs, fs, es, ds;
	unsigned int edi, esi, edp, esp, ebx, edx, ecx, eax;
	unsigned int int_no, err_code;
	unsigned int eip, cs, eflags, usersp, ss;
};

Error: 13
Error code: 0
CS: 8
DS: 1048592
FS: 1048592
GS: 1048592
SS: 0
EAX: 13
EBX: 65536
ECX: 4
EDI: 0
EDP: 0
EDX: 981
EFlags: 2162710
EIP: 1049116
ES: 65552
ESI: 0
ESP: 1079372
User SP: 32
Here is my assembly (I think the bug is hidden somewhere here but I can't see it):

Code: Select all

.code32
.intel_syntax noprefix

.extern test_print

# This wil set up a segment register.
.global gdt_flush
.extern gp
gdt_flush:
	lgdt [gp]
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax
	call test_print
	ret
	
.global idt_load
.extern idtp
idt_load:
	lidt [idtp]
	call test_print
	ret

.global isr0
...
.global isr31

isr0:
	cli
	
	push 0x0
	push 0x0
	
	jmp isr_common_stub
...
isr31:
	cli
	
	push 0x0
	push 0x1F
	
	jmp isr_common_stub
	
.extern fault_handler
isr_common_stub:
	xchg bx, bx
	pusha
	push ds
	push es
	push fs
	push gs
	xchg bx, bx
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov eax, esp
	push eax
	xchg bx, bx
	lea eax, fault_handler
	xchg bx, bx
	call eax
	xchg bx, bx
	pop eax
	pop gs
	pop fs
	pop es
	pop ds
	popa
	add esp, 8
	iret
	
.global irq0
...
.global irq15

irq0:
	cli
	
	push 0x0
	push 0x20
	
	jmp irq_common_stub
...
irq15:
	cli
	
	push 0x0
	push 0x30
	
	jmp irq_common_stub

.extern irq_handler

irq_common_stub:
	xchg bx, bx
	pusha
	push ds
	push es
	push fs
	push gs
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov eax, esp
	push eax
	xchg bx, bx
	lea eax, irq_handler
	call eax
	xchg bx, bx
	pop eax
	pop gs
	pop fs
	pop es
	pop ds
	popa
	iret
(not adding 8 to esp in irq_common_stub as that makes it 8 higher than it was originally while stack is restored to original)

And just for completion the C functions called:

Code: Select all

void irq_handler(struct Functions::regs* r) {
	Terminal::print("function: ");
	Terminal::println(Functions::intToChar(r->int_no));
	
	void (*handler) (struct Functions::regs*);
	
	handler = (void (*)(Functions::regs*)) IRQ::irqRoutines[r->int_no - 32];
	if(handler){
		handler(r);
	}
	if (r->int_no >= 40){
		IO::outb(0xA0, 0x20);
	}
	IO::outb(0x20, 0x20);
}

	void fault_handler(struct Functions::regs* r) {
		
		Terminal::print("Error: ");
		Terminal::println(Functions::intToChar(r->int_no));

... Just printing registers

		Terminal::print("User SP: ");
		Terminal::println(Functions::intToChar(r->usersp));
		
		if(r->int_no < 32){
			Terminal::println(exceptionMessages[r->int_no]);
			Terminal::println("Exception pausing");
			for(;;);
		}
	}
And here is an objdump of my OS and here the source

Please say if you need more information, I completed the set up of the bare bones tutorial from the wiki before trying to use this tutorial on osdever.net to enable GDT, etc
Last edited by max9403 on Mon Apr 14, 2014 12:49 pm, edited 1 time in total.
User avatar
Bender
Member
Member
Posts: 449
Joined: Wed Aug 21, 2013 3:53 am
Libera.chat IRC: bender|
Location: Asia, Singapore

Re: General protection fault on return from any interrupt

Post by Bender »

DS: 1048592
FS: 1048592
GS: 1048592
Cool? Right?
Are you sure these are the values you want?
"In a time of universal deceit - telling the truth is a revolutionary act." -- George Orwell
(R3X Runtime VM)(CHIP8 Interpreter OS)
User avatar
max9403
Posts: 17
Joined: Sun Feb 09, 2014 3:25 pm

Re: General protection fault on return from any interrupt

Post by max9403 »

Bender wrote:
DS: 1048592
FS: 1048592
GS: 1048592
Cool? Right?
Are you sure these are the values you want?
I'm about pretty sure they are not but they are indeed what is pushed to the stack when push DS, FS, GS are pushed :/

I do notice that the interrupt code and it's subcode don't get pulled from the stack when iret is hit

edit: seems I miss read the objdump so I added the add esp, 0x8 back in the to the irq_common_stub and now they are are removed but this is what is returned now in the general protection fault, I have not setup a LDT yet:

Code: Select all

Error: 13
Error code: 16
CS: 8
DS: 1048592
FS: 1048592
GS: 65552
SS: 16
EAX: 13
EBX: 65536
ECX: 4
EDI: 0
EDP: 0
EDX: 981
EFlags: 2162690
EIP: 1049119
ES: 1048592
ESI: 0
ESP: 1079380
User SP: 1051783
User avatar
Bender
Member
Member
Posts: 449
Joined: Wed Aug 21, 2013 3:53 am
Libera.chat IRC: bender|
Location: Asia, Singapore

Re: General protection fault on return from any interrupt

Post by Bender »

What is the value of DS/ES/FS/GS before the #GP? (Most tutorials use 0x10) You should be happy that CS is still fine.
"In a time of universal deceit - telling the truth is a revolutionary act." -- George Orwell
(R3X Runtime VM)(CHIP8 Interpreter OS)
User avatar
max9403
Posts: 17
Joined: Sun Feb 09, 2014 3:25 pm

Re: General protection fault on return from any interrupt

Post by max9403 »

as in before the interrupt?
User avatar
Bender
Member
Member
Posts: 449
Joined: Wed Aug 21, 2013 3:53 am
Libera.chat IRC: bender|
Location: Asia, Singapore

Re: General protection fault on return from any interrupt

Post by Bender »

max9403 wrote:as in before the interrupt?
Yes.
"In a time of universal deceit - telling the truth is a revolutionary act." -- George Orwell
(R3X Runtime VM)(CHIP8 Interpreter OS)
User avatar
max9403
Posts: 17
Joined: Sun Feb 09, 2014 3:25 pm

Re: General protection fault on return from any interrupt

Post by max9403 »

that would be this:

Code: Select all

CS: 13
DS: 1048592
FS: 16
GS: 16
SS: 0
EAX: 13
EBX: 65536
ECX: 2
EDI: 0
EDP: 0
EDX: 981
EFlags: 0
EIP: 1052423
ES: 1048592
ESI: 0
ESP: 1079400
User SP: 0
And just for completeness here is a screenshot:
Image
User avatar
Bender
Member
Member
Posts: 449
Joined: Wed Aug 21, 2013 3:53 am
Libera.chat IRC: bender|
Location: Asia, Singapore

Re: General protection fault on return from any interrupt

Post by Bender »

Well I just told what your problem is. All the segments are 0x10 before the interrupt, and they go crazy after the interrupt. I believe you aren't popping the registers in correct order.
EDIT: You are popping them in correct order. Maybe it's something else.
"In a time of universal deceit - telling the truth is a revolutionary act." -- George Orwell
(R3X Runtime VM)(CHIP8 Interpreter OS)
User avatar
max9403
Posts: 17
Joined: Sun Feb 09, 2014 3:25 pm

Re: General protection fault on return from any interrupt

Post by max9403 »

I'll try push them to the stack randomly to see where they change

edit: hmm after the IDT install 65552 is pushed to the stack for ES, after the ISRs ES and GS are 1048592 and and nothing is changed after the IRQ install (after the GDT they are all 16)
User avatar
Bender
Member
Member
Posts: 449
Joined: Wed Aug 21, 2013 3:53 am
Libera.chat IRC: bender|
Location: Asia, Singapore

Re: General protection fault on return from any interrupt

Post by Bender »

max9403 wrote:I'll try push them to the stack randomly to see where they change

edit: hmm after the IDT install 65552 is pushed to the stack for ES, after the ISRs ES and GS are 1048592 and and nothing is changed after the IRQ install (after the GDT they are all 16)
Are 65552 and 1048592 valid segments in your GDT? Show us your IDT Install.
"In a time of universal deceit - telling the truth is a revolutionary act." -- George Orwell
(R3X Runtime VM)(CHIP8 Interpreter OS)
User avatar
max9403
Posts: 17
Joined: Sun Feb 09, 2014 3:25 pm

Re: General protection fault on return from any interrupt

Post by max9403 »

Bender wrote:
max9403 wrote:I'll try push them to the stack randomly to see where they change

edit: hmm after the IDT install 65552 is pushed to the stack for ES, after the ISRs ES and GS are 1048592 and and nothing is changed after the IRQ install (after the GDT they are all 16)
Are 65552 and 1048592 valid segments in your GDT?
No I don't think so, this what it looks like bochs when viewing the GDTs:
Image

I don't know what could be wrong in IDTs or ISRs though...

Code: Select all

.global idt_load
.extern idtp
idt_load:
	lidt [idtp]
	ret

struct IDT::idt_entry {
	uint16_t base_low;
	uint16_t sel;
	uint8_t always0;
	uint8_t flags;
	uint16_t base_hi;
} __attribute__((packed));

struct IDT::idt_ptr {
	uint16_t limit;
	uint32_t base;
} __attribute__((packed));

struct IDT::idt_entry idt[256];
struct IDT::idt_ptr idtp;

extern "C" {
	extern void idt_load();
}

void IDT::idtSetGate(uint8_t num, uint64_t base, uint16_t sel, uint8_t flags) {
	idt[num].base_low = (base & 0xFFFF);
	idt[num].base_hi = (base >> 16) & 0xFFFF;
	
	idt[num].sel = sel;
	idt[num].always0 = 0;
	idt[num].flags = flags;
}

void IDT::idtInstall() {
	idtp.limit = (sizeof(struct idt_entry) * 256) - 1;
	idtp.base = (unsigned int)&idt;
	
	Functions::memset(&idt, 0, sizeof(struct idt_entry) * 256);
	
	//Terminal::println(Functions::intToChar(sizeof(struct idt_entry) * 256)); // Printing causes GS to be 65552 instead of ES
		
	idt_load();
}
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: General protection fault on return from any interrupt

Post by sortie »

Please be sure to consult, if you haven't already: http://wiki.osdev.org/I_Cant_Get_Interrupts_Working

On a more serious note, I can see the problem you have: You are abusing your assembler! You changed the assembler syntax of the GNU assembler so it is more Nasm-like, but it doesn't make it fully Nasm-like!

This piece of code doesn't do what you think:

Code: Select all

.intel_syntax noprefix
mov ax, 0x10
It changes the operand order, but it doesn't change how values are understood. 0x10 is understood as a memory address, rather than a literal value. Thus it means something like in C:

Code: Select all

ax = *((uint16_t*) (0x10));
while you expected it to mean:

Code: Select all

ax = 0x10;
You would want to write something like this instead:

Code: Select all

.intel_syntax noprefix
mov ax, $0x10
(Unless I am mistaken. I don't use .intel_syntax noprefix myself)

The morale of the story is that you should not change the syntax of the assembler without understanding exactly what that means. If you wanted Intel syntax, go use Nasm instead of the GNU assembler, or just embrace AT&T syntax. A kernel usually doesn't have that many assembler files and using a syntax you don't truly like for a few files isn't that bad. Either way, understand what your assembly does!

Edit: See below, this post is wrong.
User avatar
Bender
Member
Member
Posts: 449
Joined: Wed Aug 21, 2013 3:53 am
Libera.chat IRC: bender|
Location: Asia, Singapore

Re: General protection fault on return from any interrupt

Post by Bender »

A kernel usually doesn't have that many assembler files and using a syntax
Good that you had remembered to add the word "usually". 8)
"In a time of universal deceit - telling the truth is a revolutionary act." -- George Orwell
(R3X Runtime VM)(CHIP8 Interpreter OS)
User avatar
max9403
Posts: 17
Joined: Sun Feb 09, 2014 3:25 pm

Re: General protection fault on return from any interrupt

Post by max9403 »

I have looked at but it hasn't helped me thus far, also that is unfortunately not the issue as that is what .intel_syntax noprefix does, if I look at the decompiled source using objdump it looks like this:

Code: Select all

pusha  
push   %ds
push   %es
push   %fs
push   %gs
xchg   %bx,%bx
mov    $0x10,%ax
#These are all mov %ax,%register in bochs using AT&T
mov    %eax,%ds
mov    %eax,%es
mov    %eax,%fs
mov    %eax,%gs
mov    %esp,%eax
push   %eax
xchg   %bx,%bx
lea    0x1009e0,%eax
xchg   %bx,%bx
call   *%eax
xchg   %bx,%bx
pop    %eax
pop    %gs
pop    %fs
pop    %es
pop    %ds
popa   
add    $0x8,%esp
iret   
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: General protection fault on return from any interrupt

Post by sortie »

max9403 wrote:I have looked at but it hasn't helped me thus far, also that is unfortunately not the issue as that is what .intel_syntax noprefix does
Oh sorry, looks like I was wrong. .intel_syntax noprefix does change the syntax for immediate values when I test it myself.
Post Reply