Files
ViperOS/VKernel/Kernel/intr/syscall.vp
T
TermiNexus 7d5380148b feat(mmap): S1c —— MMAP 改 Linux 六参形态并支持映射 /dev/fb0
内核 MMAP(addr,length,prot,flags,fd,offset):fd=-1 + MAP_ANONYMOUS 走匿名映射(分配物理页、清零后映射到本进程新 VA,对齐 Linux"匿名必为零"语义);fd 是带 mmap_info 的 devfs 设备(当前仅 /dev/fb0)则把 [phys+offset, phys+offset+len) 按页映射进调用者地址空间(PTE_USER|WRITE)。addr/MAP_FIXED 暂未实现,一律由内核挑 VA 并返回真实起始地址。新增 PROT_*/MAP_*/MMAP_FD_ANON 常量。

参数次序与 Linux mmap 完全一致(rdi/rsi/rdx/r10/r8/r9),syscall_entry 的搬运顺序本就是这个约定,SDK 侧 vpsdk/syscall.vp 加 mmap() 助手走 _syscall6。stdlib.malloc 随之改为匿名映射调用(fd=-1、MAP_PRIVATE|MAP_ANONYMOUS、PROT_READ|PROT_WRITE),行为与原 MMAP(size) 一致且多一层清零。
2026-10-16 18:40:14 +08:00

601 lines
24 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import drivers.serial.uart.serial as serial
import services.desktop as desktop
import drivers.fs.fat32.fat32 as fat32
import drivers.fs.fat32.fat32_types as fat32_types
import sched.sched as sched
import sched.process as process
import viperlib
import string
import mm.mm as mm
import paging.paging as paging
import execrunner.elf as elf
import drivers.devfs.devfs as devfs
# ============================================================================
# 系统调用号表(唯一权威来源)。与 Linux x86-64 ABI **同名同号**:
# · Linux 有同名调用 → 直接用它的号;Linux 有而我们未实现的**留空不占号**
# (12 brk / 39 getpid / 84 rmdir / 217 getdents64 / 257 openat … 需要时按号补上);
# · 我们独有的能力**不再新增 syscall**,一律走 devfs 设备文件(open/read/write)
# 或下沉到用户层(见下面「临时私有段」的逐条迁移标注)。
# 注意:vpsdk/syscall.vp 有一份逐字对应的镜像(vpsdk 不允许依赖 VKernel),
# 增删/改号/改名必须两边同步。
# ============================================================================
enum Syscall:
# ---- Linux 对齐段(号 = Linux x86-64 的号)----
READ = 0 # read(fd, buf, count)
WRITE = 1 # write(fd, buf, count)
OPEN = 2 # open(path, flags)
CLOSE = 3 # close(fd)
STAT = 4 # stat(path, info)(结构体仍是本系统的 fileinfo)
SEEK = 8 # lseek(fd, offset, whence)(whence 目前恒 0 = SEEK_SET)
MMAP = 9 # mmap(size) → VA(ABI 待向 Linux 的 addr/len/prot/flags/fd/off 靠拢)
MUNMAP = 11 # munmap(ptr, size)(目前空实现)
IOCTL = 16 # ioctl(fd, request, arg):设备控制(当前用于 /dev/fb0 查几何)
YIELD = 24 # sched_yield()
THREAD_CREATE = 56 # clone():建用户线程,返回 tid
SPAWN = 59 # execve():加载并运行新 ELF,返回 pid
THREAD_EXIT = 60 # exit():退役当前线程
MKDIR = 83 # mkdir(path)
REMOVE = 87 # unlink(path)
EXIT = 231 # exit_group():退役当前线程 + 拆掉本 pid 的窗口
# ---- 临时私有段(0x1000+):Linux 无对应,且**逐条都会被消掉** ----
# 目标形态:私有能力不占 syscall 号 → 改 devfs 设备文件;UI 11 个 → 由用户态
# explorer(图形壳)接管 framebuffer 与输入后删除。当前保留只为让现有 app 还能跑。
SERIAL_PUTS = 0x1000 # TODO(devfs):改为 write(/dev/serial0)
TELL = 0x1001 # TODO(linux):可由 lseek(fd, 0, SEEK_CUR) 表达
SIZE = 0x1002 # TODO(linux):可由 fstat 表达
OPENDIR = 0x1003 # TODO(linux):openat(O_DIRECTORY) + getdents64
READDIR = 0x1004 # TODO(linux):getdents64
CLOSEDIR = 0x1005 # TODO(linux):close
LOAD_SO = 0x1006 # TODO(用户层):动态库加载下沉
SO_CALL1 = 0x1007 # TODO(用户层):同上
WAIT_WINDOW = 0x1008 # TODO(explorer):UI
CREATE_WINDOW = 0x1009 # TODO(explorer):UI
DRAW_TEXT = 0x100A # TODO(explorer):UI
GET_WINBUF = 0x100B # TODO(explorer):UI
WIN_FLUSH = 0x100C # TODO(explorer):UI
POLL_EVENT = 0x100D # TODO(explorer):UI
SET_CURSOR = 0x100E # TODO(explorer):UI
SET_TITLE = 0x100F # TODO(explorer):UI
SET_GEOMETRY = 0x1010 # TODO(explorer):UI
SET_RESIZABLE = 0x1011 # TODO(explorer):UI
GET_WIN_SIZE = 0x1012 # TODO(explorer):UI
define IA32_EFER = 0xC0000080
define IA32_STAR = 0xC0000081
define IA32_LSTAR = 0xC0000082
define IA32_FMASK = 0xC0000084
def wrmsr(msr: uint32, val: uint64):
lo: uint32 = uint32(val & 0xFFFFFFFF)
hi: uint32 = uint32(val >> 32)
__asm__(f"""mov ecx, {asminp(msr, ASM_DESCR.REG_ANY)}
mov eax, {asminp(lo, ASM_DESCR.REG_ANY)}
mov edx, {asminp(hi, ASM_DESCR.REG_ANY)}
wrmsr""",
op=[ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RDX])
def rdmsr(msr: uint32) -> uint64:
lo: uint32
hi: uint32
# rdmsr 固定写 EDX:EAX;out 绑定 + CLOBBER_RAX/RDX 冲突会导致 lo/hi
# 分配到非 EAX/EDX 读到垃圾。显式 mov 到输出寄存器(与 asm.inb 修复同模式)。
__asm__(f"""mov ecx, {asminp(msr, ASM_DESCR.REG_ANY)}
rdmsr
mov {asmout(lo, ASM_DESCR.OUTPUT_REG)}, eax
mov {asmout(hi, ASM_DESCR.OUTPUT_REG)}, edx""",
out=[asmout(lo, ASM_DESCR.OUTPUT_REG), asmout(hi, ASM_DESCR.OUTPUT_REG)],
op=[ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RDX])
return uint64(lo) | (uint64(hi) << 32)
def _current_proc() -> process.Process*:
return process.ProcessManager.current()
def _fd_alloc(p: process.Process*) -> int:
for i in range(process.PROC_MAX_FDS):
if not p.fd_used[i]:
p.fd_used[i] = 1
return i
return -1
def _fd_free(p: process.Process*, fd: int):
if fd >= 0 and fd < process.PROC_MAX_FDS:
p.fd_used[fd] = None
p.fd_table[fd] = None
def _dir_alloc(p: process.Process*) -> int:
for i in range(process.PROC_MAX_DIRS):
if not p.dir_used[i]:
p.dir_used[i] = 1
return i
return -1
def _dir_free(p: process.Process*, dd: int):
if dd >= 0 and dd < process.PROC_MAX_DIRS:
p.dir_used[dd] = None
p.dir_table[dd] = None
def CREATE_WINDOW(x: int, y: int, w: int, h: int, title: const str, style: int) -> int:
desktop.set_app_pid(process.current())
return desktop.create(x, y, w, h, title, style)
def DRAW_TEXT(win_id: int, x: int, y: int, text: const str, color: uint32) -> int:
return desktop.draw_text(win_id, x, y, text, color)
def EXIT(code: int) -> int:
serial.puts("[syscall] exit called\n")
desktop.destroy_by_pid(process.current())
# 真正的退出:退役本线程并让出,**绝不返回用户态**。
# 只 destroy 窗口不够:app 的 _start 在 process.exit(0) 之后还有 `return 0`,而内核是以
# rsp = USER_STACK_VTOP 进入 _start 的(elf.vp:379),VTOP 正是用户栈映射
# [VTOP-64K, VTOP) 的上界之外那一字节 ⇒ 一旦 _start 收尾 `ret` 就会去读 [VTOP]:
# #PF cr2=rsp=0x7fffffe00000,rip 在 _start 内,rbp=0,rax=退出码(实测现场)。
# 口径与异常终止路径一致(idt.vp 的 free_user_thread + state=THREAD_DONE + 不再回用户态)。
sched.Scheduler.exit_current_thread()
# 【硬保护】这里绝不允许返回:一旦返回就会沿调用链回到 app 的 _start 末尾,那里 `ret`
# 会弹到一个 0 返回地址并去 0 取指(现场:[0E] rip=0x0 err=0x15 = 用户态取指缺页,
# 紧随 [syscall] exit called,tid=5)。停留在此让调度器彻底不再调度本线程。
while True:
sched.Scheduler._yield()
return 0
def WAIT_WINDOW(win_id: int) -> int:
while desktop.is_active(win_id):
sched.Scheduler.try_reschedule()
return 0
def SERIAL_PUTS(str_ptr: str) -> int:
s: const str = str_ptr
serial.puts(s)
return 0
_loaded_so_base: rawptr = None
_loaded_so_path: [64]char
def LOAD_SO(path_ptr: str) -> uint64:
global _loaded_so_base
path: const str = path_ptr
serial.puts("[so] loading: ")
serial.puts(path)
serial.puts("\n")
base: rawptr = elf.load_so(path)
if base is not None:
_loaded_so_base = base
for i in range(63):
ch: char = path[i]
_loaded_so_path[i] = ch
if ch == 0: break
_loaded_so_path[63] = 0
return uint64(base)
return 0
def SO_CALL1(sym_name_ptr: str, arg1: rawptr) -> int:
if _loaded_so_base is None: return -1
sym_name: const str = sym_name_ptr
fn: rawptr = elf.get_so_symbol(_loaded_so_base, sym_name, &_loaded_so_path[0])
if fn is None:
serial.puts("[so] symbol not found\n")
return -2
__asm__(f"""mov rdi, {asminp(arg1, ASM_DESCR.REG_ANY)}
call {asminp(fn, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RDI, ASM_DESCR.CLOBBER_RSI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
serial.puts("[so] call returned\n")
return 0
def GET_WINBUF(win_id: int) -> uint64:
buf: rawptr = desktop.get_fb(win_id)
if buf is None:
return 0
return uint64(buf)
def WIN_FLUSH(win_id: int, src: rawptr) -> int:
"""把 app 的**用户缓冲**内容拷进窗口的内核后备缓冲,再上屏。
旧设计由 GET_WINBUF 把内核缓冲地址直接交给用户态,而那片页 U=0 → app 一画就 #PF(err=0x7)。
现在 app 画在自己的用户缓冲(MMAP 分配)里,由这里 memcpy 进窗口缓冲。
"""
if src is None: return -1
dst: rawptr = desktop.get_fb(win_id) # 可能按 resize 重建 → 先取指针
n: int = desktop.get_fb_bytes(win_id) # 再取尺寸,保证与刚取的指针一致
if dst is None or n <= 0: return -1
string.memcpy(dst, src, n)
desktop.flush(win_id)
return 0
def SET_CURSOR(win_id: int, cursor_t: int) -> int:
desktop.set_cursor_type(win_id, cursor_t)
return 0
def _is_dev_path(path: const str) -> int:
"""路径是否以 "/dev/" 开头(走 devfs 设备节点而不是 FAT32)。逐字符比较,不引 str 库。"""
if path[0] != 47: return 0 # '/'
if path[1] != 100: return 0 # 'd'
if path[2] != 101: return 0 # 'e'
if path[3] != 118: return 0 # 'v'
if path[4] != 47: return 0 # '/'
return 1
def OPEN(path_ptr: str, mode: uint32) -> int:
p: process.Process* = _current_proc()
path: const str = path_ptr
# /dev/* 走 devfs 设备节点(serial / 输入 / fb…),其余仍走 FAT32 文件系统。
# 判据用逐字符比较(不引 str 库函数):"/dev/" = 47 '/'、100 'd'、101 'e'、118 'v'、47 '/'。
if _is_dev_path(path):
dfd: int = devfs.devfs_open(path, int(mode))
if dfd < 0:
return -1
fd: int = _fd_alloc(p)
if fd < 0:
devfs.devfs_close(dfd)
return -1
# 存 devfs_fd+1:devfs fd 0 是合法值,直接用会与"空槽位"混淆
p.fd_table[fd] = rawptr(uint64(dfd + 1))
p.fd_kind[fd] = process.FD_KIND_DEVFS
return fd
fat32.lock()
fp: rawptr = fat32.open(path, uint8(mode))
if not fp:
fat32.unlock()
return -1
fd: int = _fd_alloc(p)
if fd < 0:
fat32.close(fp)
fat32.unlock()
return -1
p.fd_table[fd] = fp
p.fd_kind[fd] = process.FD_KIND_FAT32
fat32.unlock()
return fd
def CLOSE(fd: int) -> int:
p: process.Process* = _current_proc()
if fd < 0 or fd >= process.PROC_MAX_FDS:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
fp: rawptr = p.fd_table[fd]
if not fp:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
if p.fd_kind[fd] == process.FD_KIND_DEVFS:
res_dev: int = devfs.devfs_close(int(uint64(fp)) - 1)
_fd_free(p, fd)
return res_dev
fat32.lock()
res: int = int(fat32.close(fp))
fat32.unlock()
_fd_free(p, fd)
return res
def READ(fd: int, buf_ptr: rawptr, count: uint32) -> int:
p: process.Process* = _current_proc()
if fd < 0 or fd >= process.PROC_MAX_FDS:
return -1
fp: rawptr = p.fd_table[fd]
if not fp:
return -1
if p.fd_kind[fd] == process.FD_KIND_DEVFS:
return devfs.devfs_read(int(uint64(fp)) - 1, buf_ptr, count)
fat32.lock()
br: uint32 = fat32.read(fp, buf_ptr, count)
fat32.unlock()
return int(br)
def WRITE(fd: int, buf_ptr: rawptr, count: uint32) -> int:
p: process.Process* = _current_proc()
if fd < 0 or fd >= process.PROC_MAX_FDS:
return -1
fp: rawptr = p.fd_table[fd]
if not fp:
return -1
if p.fd_kind[fd] == process.FD_KIND_DEVFS:
return devfs.devfs_write(int(uint64(fp)) - 1, buf_ptr, count)
fat32.lock()
bw: uint32 = fat32.write(fp, buf_ptr, count)
fat32.unlock()
return int(bw)
def IOCTL(fd: int, request: uint32, arg: rawptr) -> int:
"""设备控制(Linux ioctl 的子集):当前只有 devfs 设备支持,用于 /dev/fb0 查几何。"""
p: process.Process* = _current_proc()
if fd < 0 or fd >= process.PROC_MAX_FDS:
return -1
if not p.fd_used[fd]:
return -1
if p.fd_kind[fd] != process.FD_KIND_DEVFS:
return -1
return devfs.devfs_ioctl(int(uint64(p.fd_table[fd])) - 1, request, arg)
def SEEK(fd: int, offset: uint32) -> int:
p: process.Process* = _current_proc()
if fd < 0 or fd >= process.PROC_MAX_FDS:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
fp: rawptr = p.fd_table[fd]
if not fp:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
fat32.lock()
r: int = int(fat32.seek(fp, offset))
fat32.unlock()
return r
def TELL(fd: int) -> uint32:
p: process.Process* = _current_proc()
if fd < 0 or fd >= process.PROC_MAX_FDS:
return 0
fp: rawptr = p.fd_table[fd]
if not fp:
return 0
fat32.lock()
pos: uint32 = fat32.tell(fp)
fat32.unlock()
return pos
def fsize(fd: int) -> uint32:
p: process.Process* = _current_proc()
if fd < 0 or fd >= process.PROC_MAX_FDS:
return 0
fp: rawptr = p.fd_table[fd]
if not fp:
return 0
fat32.lock()
sz: uint32 = fat32.size(fp)
fat32.unlock()
return sz
def MKDIR(path_ptr: str) -> int:
path: const str = path_ptr
fat32.lock()
r: int = int(fat32.mkdir(path))
fat32.unlock()
return r
def REMOVE(path_ptr: str) -> int:
path: const str = path_ptr
fat32.lock()
r: int = int(fat32.remove(path))
fat32.unlock()
return r
def OPENdir(path_ptr: str) -> int:
p: process.Process* = _current_proc()
path: const str = path_ptr
dd: int = _dir_alloc(p)
if dd < 0:
return -1
dp: fat32_types.dirobj* = &p.dir_pool[dd]
fat32.lock()
res: int = int(fat32.opendir(path, dp))
fat32.unlock()
if res != 0:
_dir_free(p, dd)
return -1
p.dir_table[dd] = rawptr(uint64(dp))
return dd
def READdir(dd: int, info_ptr: rawptr) -> int:
p: process.Process* = _current_proc()
if dd < 0 or dd >= process.PROC_MAX_DIRS:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
dp: rawptr = p.dir_table[dd]
if not dp:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
info: fat32_types.fileinfo* = info_ptr
fat32.lock()
r: int = int(fat32.readdir(dp, info))
fat32.unlock()
return r
def CLOSEdir(dd: int) -> int:
p: process.Process* = _current_proc()
if dd < 0 or dd >= process.PROC_MAX_DIRS:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
dp: rawptr = p.dir_table[dd]
if not dp:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
fat32.lock()
fat32.closedir(dp)
fat32.unlock()
_dir_free(p, dd)
return 0
def STAT(path_ptr: str, info_ptr: rawptr) -> int:
path: const str = path_ptr
info: fat32_types.fileinfo* = info_ptr
fat32.lock()
r: int = int(fat32.stat(path, info))
fat32.unlock()
return r
def SPAWN(path_ptr: str, blocking: int) -> int:
path: const str = path_ptr
pid: int = elf.spawn_elf(path)
if pid < 0:
return pid
if blocking:
p: process.Process* = process.ProcessManager.get_process(pid)
if p:
while p.state != process.PROC_DONE:
sched.Scheduler.try_reschedule()
return pid
define USER_HEAP_BASE = 0x20000000
# ---- mmap 的 prot / flags(值与 Linux 同名常量一致)----
define PROT_NONE = 0x0
define PROT_READ = 0x1
define PROT_WRITE = 0x2
define PROT_EXEC = 0x4
define MAP_SHARED = 0x01
define MAP_PRIVATE = 0x02
define MAP_FIXED = 0x10
define MAP_ANONYMOUS = 0x20
# fd = -1(Linux 匿名映射约定)
define MMAP_FD_ANON: uint64 = 0xFFFFFFFFFFFFFFFF
def MMAP(addr: uint64, length: uint64, prot: uint64, flags: uint64, fd: uint64, offset: uint64) -> uint64:
"""mmap(addr, length, prot, flags, fd, offset):与 Linux 同名同参。
· fd == MMAP_FD_ANON(-1) 且带 MAP_ANONYMOUS:匿名映射 —— 分配物理页、清零后映射到
本进程新 VA(对齐 Linux 的"匿名映射必为 0"语义);
· fd 是带 mmap_info 的 devfs 设备 fd(当前仅 /dev/fb0):把设备物理区间
[phys+offset, phys+offset+length) 按页映射进来(用户可读写)。
addr 与 MAP_FIXED 暂未实现:一律由内核挑 VA,返回真实起始地址。失败返回 0。
"""
p: process.Process* = _current_proc()
if length == 0: return 0
aligned: uint64 = (length + 4095) & ~uint64(4095)
if p.heap_start == 0:
p.heap_start = USER_HEAP_BASE
va: uint64 = p.heap_start + p.heap_size
if fd == MMAP_FD_ANON:
if (flags & MAP_ANONYMOUS) == 0: return 0
for off in range(0, aligned, 4096):
phys_page: rawptr = mm.malloc(4096)
if phys_page is None: return 0
string.memset(phys_page, 0, 4096)
paging.MapPage(va + off, uint64(phys_page),
paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER)
else:
fdi: int = int(fd)
if fdi < 0 or fdi >= process.PROC_MAX_FDS: return 0
if not p.fd_used[fdi]: return 0
if p.fd_kind[fdi] != process.FD_KIND_DEVFS: return 0
dev_phys: uint64 = 0
dev_size: uint64 = 0
if devfs.devfs_get_mmap_info(int(uint64(p.fd_table[fdi])) - 1, &dev_phys, &dev_size) != 0:
return 0
if offset + aligned > dev_size: return 0
for off in range(0, aligned, 4096):
paging.MapPage(va + off, dev_phys + offset + off,
paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER)
p.heap_size = p.heap_size + aligned
return va
def MUNMAP(ptr: uint64, size: uint64) -> int:
return 0
extern def syscall_entry()
export def syscall_handler(num: uint64, arg1: uint64, arg2: uint64, arg3: uint64, arg4: uint64, arg5: uint64, arg6: uint64) -> uint64:
n: int = int(num)
if n == int(Syscall.CREATE_WINDOW):
title_ptr: str = str(arg5)
return uint64(CREATE_WINDOW(int(arg1), int(arg2), int(arg3), int(arg4), title_ptr, int(arg6)))
elif n == int(Syscall.DRAW_TEXT):
text_ptr: str = str(arg4)
return uint64(DRAW_TEXT(int(arg1), int(arg2), int(arg3), text_ptr, uint32(arg5)))
elif n == int(Syscall.EXIT):
return uint64(EXIT(int(arg1)))
elif n == int(Syscall.OPEN):
path_ptr: str = str(arg1)
return uint64(OPEN(path_ptr, uint32(arg2)))
elif n == int(Syscall.CLOSE):
return uint64(CLOSE(int(arg1)))
elif n == int(Syscall.READ):
buf_ptr: rawptr = rawptr(arg2)
return uint64(READ(int(arg1), buf_ptr, uint32(arg3)))
elif n == int(Syscall.WRITE):
buf_ptr: rawptr = rawptr(arg2)
return uint64(WRITE(int(arg1), buf_ptr, uint32(arg3)))
elif n == int(Syscall.IOCTL):
return uint64(IOCTL(int(arg1), uint32(arg2), rawptr(arg3)))
elif n == int(Syscall.SEEK):
return uint64(SEEK(int(arg1), uint32(arg2)))
elif n == int(Syscall.TELL):
return uint64(TELL(int(arg1)))
elif n == int(Syscall.SIZE):
return uint64(fsize(int(arg1)))
elif n == int(Syscall.MKDIR):
path_ptr: str = str(arg1)
return uint64(MKDIR(path_ptr))
elif n == int(Syscall.REMOVE):
path_ptr: str = str(arg1)
return uint64(REMOVE(path_ptr))
elif n == int(Syscall.OPENDIR):
path_ptr: str = str(arg1)
return uint64(OPENdir(path_ptr))
elif n == int(Syscall.READDIR):
info_ptr: rawptr = rawptr(arg2)
return uint64(READdir(int(arg1), info_ptr))
elif n == int(Syscall.CLOSEDIR):
return uint64(CLOSEdir(int(arg1)))
elif n == int(Syscall.STAT):
path_ptr: str = str(arg1)
info_ptr: rawptr = rawptr(arg2)
return uint64(STAT(path_ptr, info_ptr))
elif n == int(Syscall.WAIT_WINDOW):
if int(arg2) == 1:
return uint64(desktop.is_active(int(arg1)))
elif int(arg2) == 2:
sched.Scheduler.try_reschedule()
return 0
return uint64(WAIT_WINDOW(int(arg1)))
elif n == int(Syscall.SERIAL_PUTS):
str_ptr_sp: str = str(arg1)
return uint64(SERIAL_PUTS(str_ptr_sp))
elif n == int(Syscall.LOAD_SO):
path_ptr_so: rawptr = rawptr(arg1)
return LOAD_SO(path_ptr_so)
elif n == int(Syscall.SO_CALL1):
sym_ptr: rawptr = rawptr(arg1)
return uint64(SO_CALL1(sym_ptr, rawptr(arg2)))
elif n == int(Syscall.GET_WINBUF):
return GET_WINBUF(int(arg1))
elif n == int(Syscall.WIN_FLUSH):
return uint64(WIN_FLUSH(int(arg1), rawptr(arg2)))
elif n == int(Syscall.POLL_EVENT):
buf_ptr_ev: rawptr = rawptr(arg1)
caller_pid_ev: int = process.current()
return uint64(desktop.poll_event(buf_ptr_ev, caller_pid_ev))
elif n == int(Syscall.SET_CURSOR):
desktop.set_cursor_type(int(arg1), int(arg2))
return 0
elif n == int(Syscall.YIELD):
sched.Scheduler.try_reschedule()
return 0
elif n == int(Syscall.SET_TITLE):
title_ptr_st: rawptr = rawptr(arg2)
return uint64(desktop.set_title(int(arg1), title_ptr_st))
elif n == int(Syscall.SET_GEOMETRY):
return uint64(desktop.set_geometry(int(arg1), int(arg2), int(arg3), int(arg4), int(arg5)))
elif n == int(Syscall.SET_RESIZABLE):
return uint64(desktop.set_resizable(int(arg1), int(arg2), int(arg3)))
elif n == int(Syscall.GET_WIN_SIZE):
return uint64(desktop.get_size(int(arg1)))
elif n == int(Syscall.SPAWN):
path_ptr_sp: rawptr = rawptr(arg1)
return uint64(SPAWN(path_ptr_sp, int(arg2)))
elif n == int(Syscall.MMAP):
return MMAP(arg1, arg2, arg3, arg4, arg5, arg6)
elif n == int(Syscall.MUNMAP):
return uint64(MUNMAP(arg1, arg2))
elif n == int(Syscall.THREAD_CREATE):
func_ptr: rawptr = rawptr(arg1)
arg_ptr: rawptr = rawptr(arg2)
cur_pid: int = process.current()
# app 传进来的是**用户地址**:必须用 create_user_thread(独立用户栈 + 独立内核栈、
# 走 drop_to_user_mode 进 Ring 3),不能用 create_thread 在 Ring 0 直接 call。
th: sched.Thread* = sched.Scheduler.create_user_thread(cur_pid, func_ptr, arg_ptr)
if th is None: return uint64(0xFFFFFFFFFFFFFFFF)
p: process.Process* = process.ProcessManager.get_process(cur_pid)
if p:
p.addThread(th.tid)
return uint64(th.tid)
elif n == int(Syscall.THREAD_EXIT):
# 用户线程显式退出(回收用户栈等资源后让出,永不返回)。
sched.Scheduler.exit_current_thread()
return 0
return 0
def init():
efer: uint64 = rdmsr(IA32_EFER)
efer = efer | 1
wrmsr(IA32_EFER, efer)
star_val: uint64 = (uint64(0x08) << 32) | (uint64(0x1B) << 48)
wrmsr(IA32_STAR, star_val)
wrmsr(IA32_LSTAR, uint64(syscall_entry))
wrmsr(IA32_FMASK, 0x200)
serial.puts("[syscall] MSR init done\n")