我正在编写一个 64 位 UEFI 操作系统(GNU-EFI - Bootloader)。我想知道操作系统中的用户模式和内核模式,我必须在我的操作系统中实现用户模式和内核模式,我在互联网上找到了一些但它对我不起作用(我认为这是因为 64 位),那么我该怎么做呢?
我用这个:
OSDEV- Ring3
但是当我在我的 gdt 中实现它时,我的内核挂掉了!
我的内核代码:
评论不是我的普通代码,这些是从 OSDEV 复制的 - 这些挂在内核中,所以我评论了那些。
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
如何在 64 位 UEFI 操作系统中进入 Ring3,然后如何将用户模式切换到内核模式?