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.
版权声明:本文标题:c - What is the reason of general protection fault due to GDT selector 1113 in my x86_64 OS? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736281307a1926278.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论