I am writing a 64 Bit UEFI OS ( GNU-EFI - Bootloader ). I am wondered about User Mode and Kernel Mode in OS, I have to Implement User Mode and Kernel Mode in My OS, I found some on the Internet but It won't works for me ( I thinks it is because of 64 Bit ), So How can I do it?
I am used this:
OSDEV - Ring3
But When I implement it in my gdt, My kernel Hangs out!
My Kernel Code :
Commented are not my plain code that works these are copied from OSDEV - These Hangs Out the Kernel, SO I am Commented those.
gdt.h
// gdt.h
#pragma once
#include <stdint.h>
struct GDTDescriptor {
uint16_t Size;
uint64_t Offset;
} __attribute__((packed));
struct GDTEntry {
uint16_t Limit0;
uint16_t Base0;
uint8_t Base1;
uint8_t AccessByte;
uint8_t Limit1_Flags;
uint8_t Base2;
// These are from OSDEV, if I enable these, Kernel Hangs Out
// unsigned int Read_Write;
// unsigned int Confirming_Expand_Down;
// unsigned int Code;
// unsigned int Code_data_segment;
// unsigned int DPL;
// unsigned int present;
// unsigned int available;
// unsigned int long_mode;
// unsigned int big;
// unsigned int gran;
}__attribute__((packed));
struct GDT {
GDTEntry Null; //0x00
GDTEntry KernelCode; //0x08
GDTEntry KernelData; //0x10
GDTEntry UserNull;
GDTEntry UserCode;
GDTEntry UserData;
} __attribute__((packed))
__attribute((aligned(0x1000)));
extern GDT DefaultGDT;
extern "C" void LoadGDT(GDTDescriptor* gdtDescriptor);
gdt.cpp
// gdt.cpp
#include "gdt.h"
__attribute__((aligned(0x1000)))
GDT DefaultGDT = {
{0, 0, 0, 0x00, 0x00, 0}, // null
{0, 0, 0, 0x9a, 0xa0, 0}, // kernel code segment
{0, 0, 0, 0x92, 0xa0, 0}, // kernel data segment
{0, 0, 0, 0x00, 0x00, 0}, // user null
{0, 0, 0, 0x9a, 0xa0, 0}, // user code segment
{0, 0, 0, 0x92, 0xa0, 0}, // user data segment
};
// This is for commented vars of GDTEntry Struct
// __attribute__((aligned(0x1000)))
// GDT DefaultGDT = {
// {0, 0, 0, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // null
// {0, 0, 0, 0x9a, 0xa0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // kernel code segment
// {0, 0, 0, 0x92, 0xa0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // kernel data segment
// {0, 0, 0, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // user null
// {0xFFFF, 0, 0, 0x00, 0xF, 0, 1, 0, 1, 1, 3, 1, 1, 0, 1, 1}, // user code segment
// {0xFFFF, 0, 0, 0x00, 0xF, 0, 1, 0, 0, 1, 3, 1, 1, 0, 1, 1}, // user code segment
// };
gdt.asm
[bits 64]
LoadGDT:
lgdt [rdi]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
pop rdi
mov rax, 0x08
push rax
push rdi
retfq
GLOBAL LoadGDT
How can I enter Ring3 In 64 bit UEFI OS, Then How to Switch User Mode to Kernel Mode?