Irq0 firing general protection fault when executing iretd

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.
Post Reply
yerri07
Member
Member
Posts: 26
Joined: Sat Apr 29, 2017 6:56 am

Irq0 firing general protection fault when executing iretd

Post by yerri07 »

Hello,
I got a irq0 handler , I am using gcc cross compiler 7 version , i tried with attribute (naked & interrupt) to get rid of prologue and epilogue but these attributes are ignored by compiler. The handler producing general protection fault @ iretd

void irq () {
__asm__ __volatile__ (
"pushal;");

_pit_ticks++;

interruptdone(0);
__asm__ __volatile__(" popal;"
"iretl;");

}


00000000 <_irq >:
0: 83 ec 18 sub $0x18,%esp
3: 60 pusha
4: a1 04 00 00 00 mov 0x4,%eax
9: 6a 00 push $0x0
b: 83 c0 01 add $0x1,%eax
e: a3 04 00 00 00 mov %eax,0x4
13: e8 fc ff ff ff call 14 <_irq+0x14>
18: 61 popa
19: cf iret
1a: 83 c4 1c add $0x1c,%esp
1d: c3 ret
1e: 66 90 xchg %ax,%ax
User avatar
nielsd
Member
Member
Posts: 31
Joined: Sun Apr 05, 2015 3:15 pm

Re: Irq0 firing general protection fault when executing iret

Post by nielsd »

It is not a very good idea to write your irq handler in C, as you can see in the assembly code it produces (the esp is not the same when you enter and leave "_irq").
It is better to write your irq handler in assembly and then call some common c code which looks at the irq number and executes the code for that irq number.
osdev project, goal is to run wasm as userspace: https://github.com/kwast-os/kwast
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Irq0 firing general protection fault when executing iret

Post by iansjack »

If you want to use the "interrupt" attribute it is mandatory that your function takes a single parameter, a pointer to a struct interrupt_frame.

I find that I have better control by calling a C function (or functions) inside a wrapper written in assembler.

(PS the above applies to interrupt handlers. Exception handlers that push an error code require a second uword_t parameter.)
yerri07
Member
Member
Posts: 26
Joined: Sat Apr 29, 2017 6:56 am

Re: Irq0 firing general protection fault when executing iret

Post by yerri07 »

Thank you guys writing it in assembler works
irvanherz
Member
Member
Posts: 27
Joined: Mon Sep 19, 2016 5:34 am

Re: Irq0 firing general protection fault when executing iret

Post by irvanherz »

yerri07 wrote:Hello,
I got a irq0 handler , I am using gcc cross compiler 7 version , i tried with attribute (naked & interrupt) to get rid of prologue and epilogue but these attributes are ignored by compiler. The handler producing general protection fault @ iretd

void irq () {
__asm__ __volatile__ (
"pushal;");

_pit_ticks++;

interruptdone(0);
__asm__ __volatile__(" popal;"
"iretl;");

}


00000000 <_irq >:
0: 83 ec 18 sub $0x18,%esp
3: 60 pusha
4: a1 04 00 00 00 mov 0x4,%eax
9: 6a 00 push $0x0
b: 83 c0 01 add $0x1,%eax
e: a3 04 00 00 00 mov %eax,0x4
13: e8 fc ff ff ff call 14 <_irq+0x14>
18: 61 popa
19: cf iret
1a: 83 c4 1c add $0x1c,%esp
1d: c3 ret
1e: 66 90 xchg %ax,%ax
You can try my code. It was inspired by Linux.

Code: Select all

typedef struct Registers {
	unsigned long edi;
	unsigned long esi;
	unsigned long ebp;
	unsigned long esp;
	unsigned long ebx;
	unsigned long edx;
	unsigned long ecx;
	unsigned long eax;
	
	unsigned short gs,_gs;
	unsigned short fs,_fs;
	unsigned short es,_es;
	unsigned short ds,_ds;
	
	unsigned long code;
	
	unsigned long eip;
	unsigned short cs,_cs;
	unsigned long eflags;
} __attribute__((packed)) Registers;

/* Macros for manipulating registers
 * */
#define SAVE_REGISTERS() \
	__asm__("push ds"); \
	__asm__("push es"); \
	__asm__("push fs"); \
	__asm__("push gs"); \
	__asm__("pusha");
	
#define RESTORE_REGISTERS() \
	__asm__("popa"); \
	__asm__("pop gs"); \
	__asm__("pop fs"); \
	__asm__("pop es"); \
	__asm__("pop ds");

/* This macro will create interrupt entry point function irq_X_interrupt
 * that can be registered with set_idt_gate
 * */
#define CREATE_IRQ_HANDLER(nr,handler) \
	void irq_##nr##_interrupt(); \
	asm("irq_"#nr"_interrupt:"); \
	asm("pushd 0"); \
	SAVE_REGISTERS() \
	asm("pushd "#nr); \
	asm("call "#handler); \
	asm("add esp,4"); \
	RESTORE_REGISTERS(); \
	asm("add esp,4"); \
	asm("iretd");

///////////////////////

long tick = 0;
void pit_irq(uint nr, Registers regs){
	tick++;
}
CREATE_IRQ_HANDLER(0,pit_irq);
Don't forget to register irq_0_interrupt in your idt. You can also define other naming pattern by modify CREATE_IRQ_HANDLER's macro.
Post Reply