Code: Select all
global gdt_flush
gdt_flush:
LGDT [RDI]
jmp reloadSegments
RET
global reloadSegments
reloadSegments:
; Reload CS register:
PUSH 0x08 ; Push code segment to stack, 0x08 is a stand-in for your code segment
LEA RAX, [rel reload_CS] ; Load address of reload_CS into RAX, LEA (Load Effective Address),
PUSH RAX ; Push this value to the stack
RETFQ ; Perform a far return, RETFQ or LRETQ depending on syntax
reload_CS:
; Reload data segment registers
MOV AX, 0x10 ; 0x10 is a stand-in for your data segment
MOV DS, AX
MOV ES, AX
MOV FS, AX
MOV GS, AX
MOV SS, AX
RET
Code: Select all
struct gdt_entry
{// 64-Bit
uint16_t limit_low; // Lower 16 bits of the segment limit
uint16_t base_low; // Lower 16 bits of the base address
uint8_t base_middle; // Next 8 bits of the base address
uint8_t access; // Access byte
uint8_t granularity; // Flags and upper limit
uint8_t base_high; // Next 8 bits of the base address
} __attribute__((packed));
typedef struct gdt_entry gdt_entry_t;
// Structure for GDTR
struct gdtr {
uint16_t limit;
uint64_t base; // Use uint64_t for 64-bit systems
} __attribute__((packed));
typedef struct gdtr gdtr_t;
Code: Select all
void gdt_setup( uint8_t idx, uint64_t base, uint32_t limit, uint8_t access, uint8_t granularity){
gdt_entries[idx].limit_low = limit & 0xFFFF; // 16 bit
gdt_entries[idx].base_low = base & 0xFFFF; // 16 bit
gdt_entries[idx].base_middle = (base >> 16) & 0xFF; // 8 bit
gdt_entries[idx].access = access;
gdt_entries[idx].granularity = (limit >> 16) & 0x0F; // Set limit : lower 4 bit
gdt_entries[idx].granularity |= granularity & 0xF0; // Set Flags : upper 4 bit
gdt_entries[idx].base_high = (base >> 24) & 0xFF; // 8 bit
}
void init_gdt(){
//gdt_setup(index, base, limit, access, granularity)
gdt_setup(0, 0, 0x0, 0x0, 0x0); // null descriptor selector : 0x0
gdt_setup(1, 0, 0xFFFF, 0x9A, 0xA0); // kernel mode code segment, selector : 0x8
gdt_setup(2, 0, 0xFFFF, 0x92, 0xA0); // kernel mode data segment, selector : 0x10
gdt_setup(3, 0, 0xFFFF, 0xFA, 0xA0); // user mode code segment, selector : 0x18
gdt_setup(4, 0, 0xFFFF, 0xF2, 0xA0); // user mode data segment, selector : 0x20
// Calculate the GDT limit and base address
gdtr_instance.limit = (uint16_t) (5 * sizeof(gdt_entry_t) - 1); // sizeof(gdt_entries) = sizeof(gdt_entry_t) * 5 = 40
gdtr_instance.base = (uint64_t) &gdt_entries;
gdt_flush((gdtr_t *) &gdtr_instance);
print("Successfully GDT Enabled!\n");
}
loading idt by
Code: Select all
;
; This prgrame will load idt in idtr
; The ISR's which not push any error code we are pushing a dummy error code 0
; 0x10 is represent kernel data selector in GDT
; 0x8 is represent kernel code selector in GDT
; https://stackoverflow.com/questions/79282721/why-is-isr-common-stub-not-calling-my-isr-handler-function?noredirect=1#comment139806502_79282721
;
[extern isr_handler] ; defined in idt.c
[extern irq_handler] ; defined in idt.c
;
; These macros will store the current registers into stack and restore from stack
; The order is follow by registers_t structure defined in util.h
;
; Save all segment and general purpose registers
%macro SAVE_REGISTERS 0
push rax
push rbx
push rcx
push rdx
push rbp
push rsi
push rdi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
push gs
push fs
mov ax, es ; we can not push es directly into stack
push rax
mov ax, ds ; we can not push ds directly into stack
push rax
%endmacro
; Restore all segment and general purpose registers
%macro RESTORE_REGISTERS 0
pop rax ; Restore `ds` (was pushed last)
mov ds, ax
pop rax ; Restore `es`
mov es, ax
pop fs ; Restore `fs`
pop gs
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rbp
pop rdx
pop rcx
pop rbx
pop rax
%endmacro
section .text
[global idt_flush]
idt_flush:
lidt [rdi] ; Load the IDT pointer
ret
; Setup Interrupt Service Routine(ISR)
%macro ISR_NOERRCODE 1
[global isr%1]
isr%1:
push 0 ; Pushing Dummy error code into stack
push %1 ; Pushing Interrupt number into stack
jmp isr_common_stub
%endmacro
%macro ISR_ERRCODE 1
[global isr%1]
isr%1:
; don't need to push error code as it is autometically push
push %1 ; Pusing Interrupt number only into the stack
jmp isr_common_stub
%endmacro
isr_common_stub:
SAVE_REGISTERS
; Print stack pointer before alignment
; mov rax, rsp
; call print_hex
; print("\n")
and rsp, ~(0xF) ; Ensure 16-byte stack alignment
; Print stack pointer after alignment
; mov rax, rsp
; call print_hex
; print("\n")
mov ax, 0x10 ; Load the kernel data segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov rdi, rsp ; Pass the current stack pointer to `isr_handler`
cld ; Required by AMD64 System V ABI
call isr_handler
RESTORE_REGISTERS
add rsp, 16
iretq ; Return from Interrupt
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
ISR_NOERRCODE 128 ; System Call
ISR_NOERRCODE 177 ; System Call
; Setup Interrupt Request(IRQ)
%macro IRQ 2
[global irq%1]
irq%1:
push 0 ; Push a dummy error code
push %2 ; Push irq code
jmp irq_common_stub
%endmacro
; This is a stub that we have created for IRQ based ISRs. This calls
irq_common_stub:
SAVE_REGISTERS
; and rsp, ~(0xF) ; Ensure 16-byte stack alignment
mov ax, 0x10 ; Load the Kernel Data Segment descriptor!
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov rdi, rsp ; Pass stack pointer to `irq_handler`
cld ; Required by AMD64 System V ABI
call irq_handler
RESTORE_REGISTERS
add rsp, 16 ; Clean up pushed error code and IRQ number
iretq ; Return from Interrupt
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
No kernel modules found!
Successfully GDT Enabled!
Successfully IDT Enabled!
Error Code (Decimal): 8904
Error Code (Hexadecimal): 0x22C8
Decoding Error Code:
External: The fault was not caused by an external event. Table: The fault involves the Global Descriptor Table (GDT). Index: The fault involves a segment selector in the GDT/LDT. Selector Index: 1113
The fault was caused by a non-null segment selector.
Summary:
The fault likely occurred due to an invalid or misconfigured GDT/LDT entry. Check the segment selector index (1113) in the corresponding descriptor table. recieved interrupt: 13
General protection fault (pushes an error code)
Error Code: 8904
CS: 0x8, RIP: 0xFFFFFFFF80005684
Stack Contents:
[0xFFFF800003F51FB0] = 0x0
=
[0xFFFF800003F51FB8]
0xFFFFFFFF800022C8
[0xFFFF800003F51FC0] = 0x8
[0xFFFF800003F51FC8] = 0x10246
[0xFFFF800003F51FD0] = 0xFFFF800003F51FE0
[0xFFFF800003F51FD8] = 0x10
[0xFFFF800003F51FE0] = 0xFFFF800003F51FF0
[0xFFFF800003F51FE8] = 0xFFFFFFFF8000ZZBO
[0xFFFF800003F51FF0] = 0x0
[0xFFFF800003F51FF8] = 0x0
[0xFFFF800003F520001 = 0x800000015CD00037
[0xFFFF800003F52008] = 0xFFFF
[0xFFFF800003F52010) =
0x0
[0xFFFF800003F52018) =
[0xFFFF800003F520201 =
0x0 0x0
[0xFFFF800003F52028] = 0x0
[0xFFFF800003F52030] = 0x0
[0xFFFF800003F52038] = 0x0
[0xFFFF800003F52040] = 0x0
System Halted!
Code: Select all
typedef struct registers
{
uint64_t rax, rbx, rcx, rdx, rbp, rsi, rdi; // General-purpose registers
uint64_t r8, r9, r10, r11, r12, r13, r14, r15; // General-purpose registers
uint64_t gs, fs, es, ds; // Segment registers
uint64_t int_no, err_code; // Interrupt number and error code (if applicable)
uint64_t iret_rip, iret_cs, iret_rflags, iret_rsp, iret_ss; // CPU state
} registers_t;
stackoverflow version of this qustion : https://stackoverflow.com/questions/793 ... 3-in-my-x8
I have tried to change SAVE_REGISTERS, and RESTORE_REGISTERS by 16 byte stack alignment and checked gdt.c, gdt.h, gdt_load.asm, idt.c, idt.h and idt_load.asm files but unable to detect the cause of this problem. I know virtualbox is more near of actual hardware so this problem will be available in real machine so I am desparate to resolve this issue.