Skip to content

Commit

Permalink
支持sysenter
Browse files Browse the repository at this point in the history
  • Loading branch information
copi143 committed Dec 18, 2024
1 parent 72de878 commit a419bae
Show file tree
Hide file tree
Showing 14 changed files with 242 additions and 57 deletions.
21 changes: 14 additions & 7 deletions include/kernel/cpu.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
#pragma once
#include <define.h>

// 遵守 sysenter/sysexit 的要求
// 原则上不应该修改,如要修改需同时修改汇编中的定义
#define RING0_CS (1 * 8)
#define RING0_DS (2 * 8)
#define RING3_CS (3 * 8)
#define RING3_DS (4 * 8)

typedef struct {
u32 eax, ebx, ecx, edx, esi, edi, ebp;
u32 edi, esi, ebp, _, ebx, edx, ecx, eax;
u32 eip;
} stack_frame;

Expand All @@ -16,10 +23,10 @@ typedef struct {
#define GET_SEL(cs, rpl) ((cs & SA_RPL_MASK & SA_TI_MASK) | (rpl))

typedef struct __PACKED__ TSS32 {
i32 backlink, esp0, ss0, esp1, ss1, esp2, ss2, cr3;
i32 eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;
i32 es, cs, ss, ds, fs, gs;
i32 ldtr;
u32 backlink, esp0, ss0, esp1, ss1, esp2, ss2, cr3;
u32 eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;
u32 es, cs, ss, ds, fs, gs;
u32 ldtr;
u16 trap, iomap;
byte io_map[8192];
} TSS32;
Expand Down Expand Up @@ -59,8 +66,8 @@ void set_segmdesc(SegmentDescriptor *sd, u32 limit, u32 base, u32 ar);
void set_gatedesc(GateDescriptor *gd, size_t offset, u32 selector, u32 ar);

typedef struct regs16 {
u16 di, si, bp, sp, bx, dx, cx, ax;
u16 gs, fs, es, ds, flags;
u16 di, si, bp, _, bx, dx, cx, ax;
u16 gs, fs, es, ds;
} regs16;

// 可参考 https://www.felixcloutier.com/x86/iret:iretd:iretq
Expand Down
1 change: 1 addition & 0 deletions include/libc-base.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ extern "C" {
#include "libc-base/asm/cr.h"
#include "libc-base/asm/io.h"
#include "libc-base/asm/mem.h"
#include "libc-base/asm/msr.h"
#include "libc-base/asm/reg.h"
#include "libc-base/asm/syscall.h"
#include "libc-base/color.h"
Expand Down
17 changes: 17 additions & 0 deletions include/libc-base/asm/msr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once
#include <define.h>

#define asm_rdmsr(msr, lo, hi) asm volatile("rdmsr\n\t" : "=a"(lo), "=d"(hi) : "c"(msr)::"memory")
#define asm_wrmsr(msr, lo, hi) asm volatile("wrmsr\n\t" ::"a"(lo), "d"(hi), "c"(msr) : "memory")

//+注意 IA32_SYSENTER_CS 的约定:
// Ring 0 的代码段 CS0
// Ring 0 的数据段 DS0 = CS0 + 8
// Ring 3 的代码段 CS3 = CS0 + 16
// Ring 3 的数据段 DS3 = CS0 + 24
// 如果有 REX.W 前缀则:
// CS3 = CS0 + 32
// DS3 = CS0 + 40
#define IA32_SYSENTER_CS 0x174
#define IA32_SYSENTER_ESP 0x175
#define IA32_SYSENTER_EIP 0x176
121 changes: 121 additions & 0 deletions include/libc-base/asm/syscall-x86-sysenter
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@

#define __syscall0(id) \
({ \
__INTPTR_TYPE__ rets; \
asm volatile("mov %%esp, %%ecx\n\t" \
"lea 1f, %%edx\n\t" \
"sysenter\n\t" \
"1:\n\t" \
: "=a"(rets) \
: "0"(id) \
: "memory", "cc", "ecx", "edx"); \
rets; \
})

#define __syscall1(id, arg1) \
({ \
__INTPTR_TYPE__ rets; \
__INTPTR_TYPE__ __arg1 = (__INTPTR_TYPE__)(arg1); \
register __INTPTR_TYPE__ _a1 asm("ebx") = __arg1; \
asm volatile("mov %%esp, %%ecx\n\t" \
"lea 1f, %%edx\n\t" \
"sysenter\n\t" \
"1:\n\t" \
: "=a"(rets) \
: "0"(id), "r"(_a1) \
: "memory", "cc", "ecx", "edx"); \
rets; \
})

#define __syscall2(id, arg1, arg2) \
({ \
__INTPTR_TYPE__ rets; \
__INTPTR_TYPE__ __arg1 = (__INTPTR_TYPE__)(arg1); \
__INTPTR_TYPE__ __arg2 = (__INTPTR_TYPE__)(arg2); \
register __INTPTR_TYPE__ _a2 asm("esi") = __arg2; \
register __INTPTR_TYPE__ _a1 asm("ebx") = __arg1; \
asm volatile("mov %%esp, %%ecx\n\t" \
"lea 1f, %%edx\n\t" \
"sysenter\n\t" \
"1:\n\t" \
: "=a"(rets) \
: "0"(id), "r"(_a1), "r"(_a2) \
: "memory", "cc", "ecx", "edx"); \
rets; \
})

#define __syscall3(id, arg1, arg2, arg3) \
({ \
__INTPTR_TYPE__ rets; \
__INTPTR_TYPE__ __arg1 = (__INTPTR_TYPE__)(arg1); \
__INTPTR_TYPE__ __arg2 = (__INTPTR_TYPE__)(arg2); \
__INTPTR_TYPE__ __arg3 = (__INTPTR_TYPE__)(arg3); \
register __INTPTR_TYPE__ _a3 asm("edi") = __arg3; \
register __INTPTR_TYPE__ _a2 asm("esi") = __arg2; \
register __INTPTR_TYPE__ _a1 asm("ebx") = __arg1; \
asm volatile("mov %%esp, %%ecx\n\t" \
"lea 1f, %%edx\n\t" \
"sysenter\n\t" \
"1:\n\t" \
: "=a"(rets) \
: "0"(id), "r"(_a1), "r"(_a2), "r"(_a3) \
: "memory", "cc", "ecx", "edx"); \
rets; \
})

#define __syscall4(id, arg1, arg2, arg3, arg4) \
({ \
__INTPTR_TYPE__ rets; \
__INTPTR_TYPE__ __arg1 = (__INTPTR_TYPE__)(arg1); \
__INTPTR_TYPE__ __arg2 = (__INTPTR_TYPE__)(arg2); \
__INTPTR_TYPE__ __arg3 = (__INTPTR_TYPE__)(arg3); \
__INTPTR_TYPE__ __arg4 = (__INTPTR_TYPE__)(arg4); \
register __INTPTR_TYPE__ _a4 asm("ecx") = __arg4; \
register __INTPTR_TYPE__ _a3 asm("edi") = __arg3; \
register __INTPTR_TYPE__ _a2 asm("esi") = __arg2; \
register __INTPTR_TYPE__ _a1 asm("ebx") = __arg1; \
asm volatile("push %%ecx\n\t" \
"mov %%esp, %%ecx\n\t" \
"lea 1f, %%edx\n\t" \
"sysenter\n\t" \
"1:\n\t" \
"pop %%ecx\n\t" \
: "=a"(rets) \
: "0"(id), "r"(_a1), "r"(_a2), "r"(_a3), "r"(_a4) \
: "memory", "cc", "edx"); \
rets; \
})

#define __syscall5(id, arg1, arg2, arg3, arg4, arg5) \
({ \
__INTPTR_TYPE__ rets; \
__INTPTR_TYPE__ __arg1 = (__INTPTR_TYPE__)(arg1); \
__INTPTR_TYPE__ __arg2 = (__INTPTR_TYPE__)(arg2); \
__INTPTR_TYPE__ __arg3 = (__INTPTR_TYPE__)(arg3); \
__INTPTR_TYPE__ __arg4 = (__INTPTR_TYPE__)(arg4); \
__INTPTR_TYPE__ __arg5 = (__INTPTR_TYPE__)(arg5); \
register __INTPTR_TYPE__ _a5 asm("edx") = __arg5; \
register __INTPTR_TYPE__ _a4 asm("ecx") = __arg4; \
register __INTPTR_TYPE__ _a3 asm("edi") = __arg3; \
register __INTPTR_TYPE__ _a2 asm("esi") = __arg2; \
register __INTPTR_TYPE__ _a1 asm("ebx") = __arg1; \
asm volatile("push %%edx\n\t" \
"push %%ecx\n\t" \
"mov %%esp, %%ecx\n\t" \
"lea 1f, %%edx\n\t" \
"sysenter\n\t" \
"1:\n\t" \
"pop %%ecx\n\t" \
"pop %%edx\n\t" \
: "=a"(rets) \
: "0"(id), "r"(_a1), "r"(_a2), "r"(_a3), "r"(_a4), "r"(_a5) \
: "memory", "cc"); \
rets; \
})

#define __syscall_concat_x(a, b) a##b
#define __syscall_concat(a, b) __syscall_concat_x(a, b)
#define __syscall_argn_private(_0, _1, _2, _3, _4, _5, n, ...) n
#define __syscall_argn(...) __syscall_argn_private(0, ##__VA_ARGS__, 5, 4, 3, 2, 1, 0)
#define __syscall(id, ...) \
__syscall_concat(__syscall, __syscall_argn(__VA_ARGS__))(id, ##__VA_ARGS__)
6 changes: 5 additions & 1 deletion include/libc-base/asm/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
#ifdef __x86_64__
# include "syscall-x64"
#else
# include "syscall-x86"
# if SYSCALL_USE_INTERRPUT
# include "syscall-x86"
# else
# include "syscall-x86-sysenter"
# endif
#endif
2 changes: 1 addition & 1 deletion src/kernel/cpu/cpu_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ __attr(fastcall) void error_inthandler(i32 id, regs32 *regs) {
kassert(id >= 0);
kassert(id < 32);
kassert(regs != null);
if (regs->fs != 1 * 8) task_kill(current_task);
if (regs->fs != RING0_DS) task_kill(current_task);
klogf("%02x: %s (#%s)", id, error_names[id].fullname, error_names[id].shortname);
abort();
}
Expand Down
18 changes: 8 additions & 10 deletions src/kernel/cpu/gdtidt.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,20 @@ void init_gdtidt() {
for (int i = 0; i < GDT_LEN; i++) {
set_segmdesc(gdt + i, 0, 0, 0);
}
set_segmdesc(gdt + 1, 0xffffffff, 0x00000000, AR_DATA32_RW);
set_segmdesc(gdt + 2, 0xffffffff, 0x00000000, AR_CODE32_ER);
set_segmdesc(gdt + 3, 0xffffffff, 0x00000000, AR_DATA32_RW | 3 << 5);
set_segmdesc(gdt + 4, 0xffffffff, 0x00000000, AR_CODE32_ER | 3 << 5);
set_segmdesc(gdt + 5, 0xffffffff, 0x70000000, AR_DATA32_RW | 3 << 5);
set_segmdesc(gdt + 1000, 0xffffffff, 0, AR_CODE32_ER); // CODE32
set_segmdesc(gdt + 1001, 0xfffff, 0, AR_CODE16_ER); // CODE16
set_segmdesc(gdt + 1002, 0xfffff, 0, AR_DATA16_RW); // DATA16
load_gdt(gdt, GDT_LEN); // 加载GDT表
set_segmdesc(gdt + 1, U32_MAX, 0, AR_CODE32_ER);
set_segmdesc(gdt + 2, U32_MAX, 0, AR_DATA32_RW);
set_segmdesc(gdt + 3, U32_MAX, 0, AR_CODE32_ER | 3 << 5);
set_segmdesc(gdt + 4, U32_MAX, 0, AR_DATA32_RW | 3 << 5);
load_gdt(gdt, GDT_LEN); // 加载GDT表

asm_wrmsr(IA32_SYSENTER_CS, RING0_CS, 0); // 为 sysenter 设置 msr

// 初始化 IDT
var idt = (GateDescriptor *)IDT_ADDR;
for (size_t i = 0; i < IDT_LEN; i++) {
int ar = i >= 0x30 ? AR_INTGATE32 | 3 << 5 : AR_INTGATE32;
size_t handler = (size_t)&asm_inthandler + i * 7;
set_gatedesc(idt + i, handler, 2 * 8, ar);
set_gatedesc(idt + i, handler, RING0_CS, ar);
}
load_idt(idt, IDT_LEN); // 加载IDT表
}
42 changes: 41 additions & 1 deletion src/kernel/cpu/handler.asm
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
[bits 32]
global asm_inthandler, asm_inthandler_quit
global asm_inthandler, asm_inthandler_quit, asm_sysenter_handler
extern inthandler
%define RING3_CS 3 * 8
%define RING3_DS 4 * 8
section .text
asm_inthandler_main:
Expand Down Expand Up @@ -89,3 +93,39 @@ asm_inthandler: ; DON'T EDIT THE CODE BELOW!
dd 0xe9f76aff, 0xfffff936, 0x2fe9f86a, 0x6afffff9, 0xf928e9f9, 0xfa6affff, 0xfff921e9, 0xe9fb6aff
dd 0xfffff91a, 0x13e9fc6a, 0x6afffff9, 0xf90ce9fd, 0xfe6affff, 0xfff905e9, 0xe9ff6aff, 0xfffff8fe
asm_inthandler_end: ; DON'T EDIT THE CODE ABOVE!
asm_sysenter_handler:
push RING3_DS ; push ss
push ecx ; push esp
pushf ; push flags
push RING3_CS ; push cs
push edx ; push eip
push 0x36 ; push error code
push 0x36 ; push interrupt number
push ds
push es
push fs
push gs
mov ecx, esi ; in sysenter, arg2 ecx replaced with esi
mov edx, edi ; in sysenter, arg3 edx replaced with edi
pusha
mov eax, dword [esp + 17 * 4]; eax <== ring3 esp
mov esi, dword [eax] ; ecx <== syscall arg4
mov edi, dword [eax + 4] ; edx <== syscall arg5
mov dword [esp + 4], esi ; set syscall arg4 esi
mov dword [esp], edi ; set syscall arg5 edi
mov ecx, 0x36 ; arg1 <== id
mov edx, esp ; arg2 <== regs
call inthandler ; void inthandler(i32 id, regs32 * regs) __attribute__((fastcall));
popa
pop gs
pop fs
pop es
pop ds
add esp, 8 ; pop error code and interrupt number
pop edx ; pop eip
add esp, 4 ; pop cs
popf ; pop flags
pop ecx ; pop esp
add esp, 4 ; pop ss
sysexit
7 changes: 5 additions & 2 deletions src/kernel/cpu/start.asm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
i386 equ 0
length equ header_end - header_start
%define RING0_CS 1 * 8
%define RING0_DS 2 * 8
section .multiboot2
header_start:
dd magic ; 魔数
Expand All @@ -30,9 +33,9 @@ _start:
cli
call init_gdtidt
call init_error_inthandler
jmp 2 * 8:.next
jmp RING0_CS:.next
.next:
mov ax, 1 * 8
mov ax, RING0_DS
mov ds, ax
mov es, ax
mov ss, ax
Expand Down
16 changes: 2 additions & 14 deletions src/kernel/cpu/x86.asm
Original file line number Diff line number Diff line change
Expand Up @@ -88,25 +88,13 @@ move_cursor_by_idx: ;移动光标
global asm_task_switch, asm_task_start
; 注意进入函数时必须 cli
asm_task_switch: ; void asm_task_switch(task_t current, task_t next) __attr(fastcall);
push ebp
push edi
push esi
push edx
push ecx
push ebx
push eax
pusha
mov [ecx], esp ; 保存esp
asm_task_start: ; void asm_task_start(task_t current, task_t next) __attr(fastcall);
mov esp, [edx]
mov eax, [edx + 4]
mov cr3, eax
pop eax
pop ebx
pop ecx
pop edx
pop esi
pop edi
pop ebp
popa
sti ; 这边必须 sti
ret
Expand Down
4 changes: 2 additions & 2 deletions src/kernel/drivers/storage/ide.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,10 @@ finline void insl(u32 port, u32 *addr, int cnt) {
}
int drive_mapping[26] = {0};
static void Read(int drive, u8 *buffer, u32 number, u32 lba) {
ide_read_sectors(drive_mapping[drive], number, lba, 1 * 8, (u32)buffer);
ide_read_sectors(drive_mapping[drive], number, lba, RING0_DS, (u32)buffer);
}
static void Write(int drive, u8 *buffer, u32 number, u32 lba) {
ide_write_sectors(drive_mapping[drive], number, lba, 1 * 8, (u32)buffer);
ide_write_sectors(drive_mapping[drive], number, lba, RING0_DS, (u32)buffer);
}

static inthandler_f ide_irq;
Expand Down
12 changes: 6 additions & 6 deletions src/kernel/exec/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,17 @@ void task_to_user_mode_elf() {
iframe->edx = (size_t)args.envp;
iframe->ecx = 0;
iframe->eax = 0;
iframe->gs = GET_SEL(5 * 8, SA_RPL3);
iframe->fs = GET_SEL(3 * 8, SA_RPL3);
iframe->es = GET_SEL(3 * 8, SA_RPL3);
iframe->ds = GET_SEL(3 * 8, SA_RPL3);
iframe->gs = 0;
iframe->fs = GET_SEL(RING3_DS, SA_RPL3);
iframe->es = GET_SEL(RING3_DS, SA_RPL3);
iframe->ds = GET_SEL(RING3_DS, SA_RPL3);
iframe->id = 0;
iframe->err = 0;
iframe->eip = 0;
iframe->cs = GET_SEL(4 * 8, SA_RPL3);
iframe->cs = GET_SEL(RING3_CS, SA_RPL3);
iframe->flags = (0 << 12 | 0b10 | 1 << 9);
iframe->esp = 0;
iframe->ss = GET_SEL(3 * 8, SA_RPL3);
iframe->ss = GET_SEL(RING3_DS, SA_RPL3);
tss.eflags = 0x202;

klogd("%lu", file->size);
Expand Down
3 changes: 3 additions & 0 deletions src/kernel/init/main.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#include <kernel.h>

void asm_sysenter_handler();

void kernel_main() {
sysinit();
asm_wrmsr(IA32_SYSENTER_EIP, asm_sysenter_handler, 0);
into_mtask();
infinite_loop {
klogf("kernel_main error");
Expand Down
Loading

0 comments on commit a419bae

Please sign in to comment.