I have a problem with my interrupt return. First of all, here is my code:
Code: Select all
extern "C" void idt_handler(struct interrupted_context * ic)
{
if (ic->intNo >= 40)
{
Ports::outportb(PIC2_COMMAND, 0x20);
}
Ports::outportb(PIC1_COMMAND, 0x20);
if (ic->intNo]== 32 )
{
ticks ++;
video.setPosition(30,10);
video.putString("Ticks: ",COLOR_RED,COLOR_LIGHT_BROWN);
video.putHexa(ticks,COLOR_RED,COLOR_LIGHT_BROWN);
video.putString("]\n",COLOR_RED,COLOR_LIGHT_BROWN);
}
else
{
video.setPosition(30,10);
if ( ic->intNo < IRQ0)
{
video.putString(exception_messages[ic->intNo],COLOR_RED,COLOR_LIGHT_BROWN);
video.putString("[",COLOR_RED,COLOR_LIGHT_BROWN);
video.putHexa(ic->intNo,COLOR_RED,COLOR_LIGHT_BROWN);
video.putString("]\n",COLOR_RED,COLOR_LIGHT_BROWN);
}
else
{
video.putString("Unhandled Interrupt",COLOR_RED,COLOR_LIGHT_BROWN);
video.putString("[",COLOR_RED,COLOR_LIGHT_BROWN);
video.putDecimal(ic->intNo,COLOR_RED,COLOR_LIGHT_BROWN);
video.putString("]\n",COLOR_RED,COLOR_LIGHT_BROWN);
}
}
}
void iloop_function ()
{
for (uint64_t i = 0 ; ; i++ )
{
video.setPosition(45,5);
video.putString("iloop_function: ",COLOR_LIGHT_BROWN,COLOR_RED);
video.putHexa(i,COLOR_LIGHT_BROWN,COLOR_RED);
video.putString("\n",COLOR_LIGHT_BROWN,COLOR_RED);
i ++;
}
}
extern "C" void kernel_main(uint64_t initial_stack_start_address,uint64_t initial_stack_end_address)
{
video.initialize();
video.clearScreen(COLOR_BLACK);
video.putString("C++ Code\n",COLOR_LIGHT_BROWN,COLOR_RED);
interruptManager = new InterruptManager();
interruptManager->registerInterrupt(32,pitScheduler);
iloop_function();
}
Code: Select all
[BITS 64]
global idtInit
extern idtP
extern interruptDescriptorTablePointer;
idtInit:
lidt [interruptDescriptorTablePointer]
ret
extern idt_handler
idt_common_stub:
mov ax, ds
push rax
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov rdi,rsp
mov rax,idt_handler
call rax
pop rbx
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
add rsp,16
sti
iretq
%macro ISR_NOERRCODE 1
[GLOBAL isr%1]
isr%1:
cli
push byte 0
push byte %1
jmp idt_common_stub
%endmacro
%macro ISR_ERRCODE 1
[GLOBAL isr%1]
isr%1:
cli
push byte %1
jmp idt_common_stub
%endmacro
%macro IRQ 2
global irq%1
irq%1:
cli
push byte 0
push byte %2
jmp idt_common_stub
%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
IRQ 0, 32
IRQ 1, 33
IRQ 2, 34
IRQ 3, 35
IRQ 4, 36
IRQ 5, 37
IRQ 6, 38
IRQ 7, 39
IRQ 8, 40
IRQ 9, 41
IRQ 10, 42
IRQ 11, 43
IRQ 12, 44
IRQ 13, 45
IRQ 14, 46
IRQ 15, 47
Code: Select all
[BITS 64]
SECTION .text
global _start
_start:
jmp Main64
Main64:
cli ; Clear the interrupt flag.
mov rsp,_stack_start
mov rdi,rsp
mov rsi,_stack_end
extern kernel_main
call kernel_main
khalt:
hlt
jmp khalt
SECTION .bss
_stack_end:
resb 8192
_stack_start:
That above code was originally working without the iloop_function, and it used to work fine and whenever I start it in qemu it keeps on incrementing the ticks on the screen normally.
Basically when the interrupt handler of the PIT fires it executes the increment and the print of the ticks variable and it return to the address of the khalt label so I noticed no problem.
My problem started when I introducted the call to the iloop_function. What happens is that when the interrupt fires, it executes and return back to the correct address but the counter of the loop is rest to zero.
I expect that there is something wrong with the stack as the local variables are not being preserved after the interrupt return.
If any one came accross a similar problem, kindly let me know how to solve.
Thanks
Karim.