admin管理员组

文章数量:1122833

I am developing a x86 architecture based 64 bit Operating System which is using limine-8.6.0 bootloader. I have enabled GDT by

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
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;

initialized 5 GDT by

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");
}

Here 5 selector there is no more gdt entry although ISR is showing interrupt 13 with error code 8904 (0x22c8) which show the interrupt caused by externel event. The serror code also showing the error caused by 1113th GDT selector entry.Here I also checked the corresponding RIS value is 0xFFFFFFFF80005684 This address in objdump is showing ffffffff80005684: 48 cf iretq so the problem may releted iretq.I also checked 16 byte stack alignment before calling isr_handler and irq_handler which are defined in idt.c file.

When I am running in QEmu it is showing nothing but when I am running in Virtualbox Showing following error:


KeblaOS [Running] - Oracle VM VirtualBox
File
Machine View
Input
Devices Help
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!

registers_t structure defined by

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;

What is the reason of this error? Edit : It take little time to show the error. The full code repository in here .

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.

本文标签: cWhat is the reason of general protection fault due to GDT selector 1113 in my x8664 OSStack Overflow