I am writing a 64 bit kernel.
I am in the phase of writing the ISRs and I was able to load the IDT to the code.
The interrupt service routine gets fired successfully and execute the isr handler which is written in C code.
The problem is that when the isr tries to return it failes and the qemu keeps on restarting forever.
My code is divided in to
Assembly code:
Code: Select all
[BITS 64]
%macro pushAll 0
push rax
push rcx
push rdx
push rbx
push rbp
push rsi
push rdi
%endmacro
%macro popAll 0
pop rdi
pop rsi
pop rbp
pop rbx
pop rdx
pop rcx
pop rax
%endmacro
global idtInit
extern idtP
idtInit:
lidt [idtP]
ret
;/*
; * Interrupt Handler
; */
extern isrHandler
isrCommon:
pushAll
mov ax, ds
push rax
mov rax, rsp
push rax
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
call isrHandler
pop rbx
mov rsp,rbx
pop rbx
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
popAll
add rsp, 8
sti
iretq
%macro ISR_NOERRCODE 1
[GLOBAL isr%1]
isr%1:
cli
push byte 0
push byte %1
jmp isrCommon
%endmacro
%macro ISR_ERRCODE 1
[GLOBAL isr%1]
isr%1:
cli
push byte %1
jmp isrCommon
%endmacro
ISR_NOERRCODE 0
ISR_NOERRCODE 1
ISR_NOERRCODE 2
ISR_NOERRCODE 3
ISR_NOERRCODE 4
ISR_NOERRCODE 5
ISR_NOERRCODE 6
ISR_NOERRCODE 7
ISR_ERRCODE 8
ISR_NOERRCODE 9
ISR_ERRCODE 10
ISR_ERRCODE 11
ISR_ERRCODE 12
ISR_ERRCODE 13
ISR_ERRCODE 14
ISR_NOERRCODE 15
ISR_NOERRCODE 16
ISR_NOERRCODE 17
ISR_NOERRCODE 18
ISR_NOERRCODE 19
ISR_NOERRCODE 20
ISR_NOERRCODE 21
ISR_NOERRCODE 22
ISR_NOERRCODE 23
ISR_NOERRCODE 24
ISR_NOERRCODE 25
ISR_NOERRCODE 26
ISR_NOERRCODE 27
ISR_NOERRCODE 28
ISR_NOERRCODE 29
ISR_NOERRCODE 30
ISR_NOERRCODE 31
C Code:
Code: Select all
#define IDT_SIZE 256
typedef struct {
uint16_t baseLow;
uint16_t selector;
uint8_t reservedIst;
uint8_t flags;
uint16_t baseMid;
uint32_t baseHigh;
uint32_t reserved;
} __attribute__((packed)) idtEntry;
/*
* Interrupt Descriptor Pointer
*/
typedef struct {
uint16_t limit;
uint64_t base;
} __attribute__((packed)) idtPointer;
/*
* Pushed Registers for ISR's
*/
typedef struct {
uint64_t ds;
uint64_t rdi, rsi, rbp, rsp, rbx, rdx, rcx, rax;
uint64_t intNo, errCode;
uint64_t rip, cs, eflags, useresp, ss;
} registers;
/*
* Prototypes
*/
void idtStart(void);
void idtSet(uint8_t, uint64_t, uint16_t, uint8_t);
#if defined(__cplusplus)
extern "C" /* Use C linkage for kernel_main. */
#else
extern
#endif
void isrHandler(registers);
#if defined(__cplusplus)
extern "C" /* Use C linkage for kernel_main. */
#else
extern
#endif
void idtInit();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr0();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr1();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr2();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr3();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr4();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr5();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr6();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr7();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr8();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr9();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr10();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr11();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr12();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr13();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr14();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr15();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr16();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr17();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr18();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr19();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr20();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr21();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr22();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr23();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr24();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr25();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr26();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr27();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr28();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr29();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr30();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr31();
/* Setup Table and Pointer */
idtEntry idt[IDT_SIZE];
idtPointer idtP;
void idtStart(void) {
/* Set IDT Pointer */
idtP.limit = (sizeof(idtEntry) * IDT_SIZE) - 1;
idtP.base = (uint64_t)&idt;
/* Clear Memory for IDT's */
memset((uint8_t *)&idt, 0, sizeof(idtEntry) * IDT_SIZE);
/* Set IDT Gates */
idtSet(0, (uint64_t)isr0, 0x08, 0x8E);
idtSet(1, (uint64_t)isr1, 0x08, 0x8E);
idtSet(2, (uint64_t)isr2, 0x08, 0x8E);
idtSet(3, (uint64_t)isr3, 0x08, 0x8E);
idtSet(4, (uint64_t)isr4, 0x08, 0x8E);
idtSet(5, (uint64_t)isr5, 0x08, 0x8E);
idtSet(6, (uint64_t)isr6, 0x08, 0x8E);
idtSet(7, (uint64_t)isr7, 0x08, 0x8E);
idtSet(8, (uint64_t)isr8, 0x08, 0x8E);
idtSet(9, (uint64_t)isr9, 0x08, 0x8E);
idtSet(10, (uint64_t)isr10, 0x08, 0x8E);
idtSet(11, (uint64_t)isr11, 0x08, 0x8E);
idtSet(12, (uint64_t)isr12, 0x08, 0x8E);
idtSet(13, (uint64_t)isr13, 0x08, 0x8E);
idtSet(14, (uint64_t)isr14, 0x08, 0x8E);
idtSet(15, (uint64_t)isr15, 0x08, 0x8E);
idtSet(16, (uint64_t)isr16, 0x08, 0x8E);
idtSet(17, (uint64_t)isr17, 0x08, 0x8E);
idtSet(18, (uint64_t)isr18, 0x08, 0x8E);
idtSet(19, (uint64_t)isr19, 0x08, 0x8E);
idtSet(20, (uint64_t)isr20, 0x08, 0x8E);
idtSet(21, (uint64_t)isr21, 0x08, 0x8E);
idtSet(22, (uint64_t)isr22, 0x08, 0x8E);
idtSet(23, (uint64_t)isr23, 0x08, 0x8E);
idtSet(24, (uint64_t)isr24, 0x08, 0x8E);
idtSet(25, (uint64_t)isr25, 0x08, 0x8E);
idtSet(26, (uint64_t)isr26, 0x08, 0x8E);
idtSet(27, (uint64_t)isr27, 0x08, 0x8E);
idtSet(28, (uint64_t)isr28, 0x08, 0x8E);
idtSet(29, (uint64_t)isr29, 0x08, 0x8E);
idtSet(30, (uint64_t)isr30, 0x08, 0x8E);
idtSet(31, (uint64_t)isr31, 0x08, 0x8E);
/* Load IDT Table */
idtInit();
}
void idtSet(uint8_t number, uint64_t base, uint16_t selector, uint8_t flags) {
/* Set Base Address */
idt[number].baseLow = base & 0xFFFF;
idt[number].baseMid = (base >> 16) & 0xFFFF;
idt[number].baseHigh = (base >> 32) & 0xFFFFFFFF;
/* Set Selector */
idt[number].selector = selector;
idt[number].flags = flags;
/* Set Reserved Areas to Zero */
idt[number].reservedIst = 0;
idt[number].reserved = 0;
}
#if defined(__cplusplus)
extern "C" /* Use C linkage for kernel_main. */
#endif
void isrHandler(registers regs) {
Video video;
video.setPosition(10,10);
video.putString("interrupt: ",COLOR_BLUE,COLOR_WHITE);
video.putDecimal(regs.intNo,COLOR_BLUE,COLOR_WHITE);
video.putString("\n",COLOR_BLUE,COLOR_WHITE);
}
When I insert a hlt just before the iretq at the end of the isrCommon routine the qemu halts with no problems but ofcourse the execution is suspended and never returns, but it shows that the problem is in the return address.
If anyone has went through this before or know the solution to my problem, I appreciate sharing it with me.
Thanks a lot
karim.