Each time i got an timer IRQ, the stack begin corrupted after the iret begin executed, the stack pointer is restored as it be before the IRQ. I also set up the TSS and set rsp0 pointer to special stack address that is specially allocated before.
So, here is my code:
Timer IRQ handler code:
Code: Select all
scheduler_irq:
;push qword 0
; push qword 32
; jmp irq_common_stub
call interrupt_sendEOI
iretq
Code: Select all
struct x86_64_tss {
uint32_t reserved0;
uint64_t rsp[3]; // When privilege change occur.
uint64_t reserved1;
uint64_t ist[7];
uint64_t reserved2;
uint16_t reserved3;
uint16_t iomap_base;
} __attribute__((packed));
struct GdtTssExtend {
uint32_t base_uper;
uint32_t reserved;
uint32_t zero;
uint32_t reserved1;
} __attribute__((packed));
void putTSS64() {
/* uint32_t addr = (uint32_t)(uint64_t)liminePhys(&tssEntry);
gdt_set_gate(5,addr,sizeof(tssEntry)-1,0x89,0);
*/
uint32_t addr1 = (uint32_t)((uint64_t)&tssEntry & 0xFFFFFFFF);
uint32_t addr2 = (uint32_t)(((uint64_t)&tssEntry >> 32) & 0xFFFFFFFF);
uint64_t limit = (uint64_t)&tssEntry + sizeof(struct x86_64_tss);
gdt_set_gate(5,addr1,limit & 0xFFFFFFFF,0x89,0);
struct GdtTssExtend ext_tss;
ext_tss.base_uper = addr2;
ext_tss.reserved = 0;
ext_tss.zero = 0;
ext_tss.reserved1 = 0;
gdt_entries[6] = *((gdt_entry_t*)&ext_tss);
}
I also tried it with the actual registers save/restore code:
Code: Select all
extern stack_top
irq_common_stub:
; Here we are...
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
mov rdi,rsp
call x86_irq_handler
; mov rsp,rax
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
add rsp,16 ; two 64-bit values.
iretq