diff --git a/Apps/Terminal/main.vp b/Apps/Terminal/main.vp index 0bd2068..0795733 100644 --- a/Apps/Terminal/main.vp +++ b/Apps/Terminal/main.vp @@ -345,7 +345,7 @@ export def _start() -> int: term.delete(0, -1) elif string.samestr(text, "help"): term.insert("File: ls cd cat pwd mkdir rm touch") - term.insert("Sys: ver about sysinfo reboot") + term.insert("Sys: ver about sysinfo reboot shutdown") term.insert("Util: echo clear help hexdump run runb") elif string.samestr(text, "ver"): term.insert("ViperOS Terminal v1.1") @@ -370,7 +370,9 @@ export def _start() -> int: elif string.samestr(text, "sysinfo"): _cmd_sysinfo() elif string.samestr(text, "reboot"): - process.exit(0) + process.reboot() + elif string.samestr(text, "shutdown"): + process.shutdown() elif _startswith(text, "hexdump "): _cmd_hexdump(text + 8) elif _startswith(text, "run "): diff --git a/VKernel/Kernel/intr/syscall.vp b/VKernel/Kernel/intr/syscall.vp index e94ff15..7805e6e 100644 --- a/VKernel/Kernel/intr/syscall.vp +++ b/VKernel/Kernel/intr/syscall.vp @@ -9,6 +9,7 @@ import mm.mm as mm import paging.paging as paging import execrunner.elf as elf import drivers.devfs.devfs as devfs +import asm # ============================================================================ @@ -46,14 +47,42 @@ enum Syscall: 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(用户层):同上 + LOAD_SO = 0x1006 # TODO(userspace): dynamic library loading + SO_CALL1 = 0x1007 # TODO(userspace): dynamic library call + REBOOT = 0x1008 # reboot()(本系统私有) + SHUTDOWN = 0x1009 # shutdown()(本系统私有) define IA32_EFER = 0xC0000080 define IA32_STAR = 0xC0000081 define IA32_LSTAR = 0xC0000082 define IA32_FMASK = 0xC0000084 +# Reset via the 8042 controller; PCI reset and halt are fallbacks. +def power_reboot(): + serial.puts("[power] reboot\n") + asm.cli() + for _ in range(1000): + if (asm.inb(0x64) & 0x02) == 0: break + asm.outb(0x64, 0xFE) + asm.outb(0xCF9, 0x02) + asm.io_wait() + asm.outb(0xCF9, 0x06) + while True: + asm.cli() + asm.hlt() + +# ACPI S5 on the common QEMU/Bochs/VirtualBox PM1a control ports. +def power_shutdown(): + serial.puts("[power] shutdown\n") + asm.cli() + asm.outw(0x604, 0x3400) + asm.outw(0x604, 0x2000) + asm.outw(0xB004, 0x2000) + asm.outw(0x4004, 0x3400) + while True: + asm.cli() + asm.hlt() + def wrmsr(msr: uint32, val: uint64): lo: uint32 = uint32(val & 0xFFFFFFFF) hi: uint32 = uint32(val >> 32) @@ -454,6 +483,12 @@ export def syscall_handler(num: uint64, arg1: uint64, arg2: uint64, arg3: uint64 path_ptr: str = str(arg1) info_ptr: rawptr = rawptr(arg2) return uint64(STAT(path_ptr, info_ptr)) + elif n == int(Syscall.REBOOT): + power_reboot() + return uint64(0) + elif n == int(Syscall.SHUTDOWN): + power_shutdown() + return uint64(0) elif n == int(Syscall.LOAD_SO): path_ptr_so: rawptr = rawptr(arg1) return LOAD_SO(path_ptr_so) diff --git a/vpsdk/process.vp b/vpsdk/process.vp index 457c549..cf1f163 100644 --- a/vpsdk/process.vp +++ b/vpsdk/process.vp @@ -4,6 +4,14 @@ from . import syscall as syscall def exit(code: int): syscall._syscall1(uint64(syscall.Syscall.EXIT), uint64(code)) +def reboot(): + """Reset the machine.""" + syscall._syscall0(uint64(syscall.Syscall.REBOOT)) + +def shutdown(): + """Power off the machine (ACPI S5 / QEMU PM1a).""" + syscall._syscall0(uint64(syscall.Syscall.SHUTDOWN)) + def thread_exit(): """当前用户线程显式退出:内核回收其用户栈并标记线程结束(不返回)。""" syscall._syscall0(uint64(syscall.Syscall.THREAD_EXIT)) diff --git a/vpsdk/syscall.vp b/vpsdk/syscall.vp index 90364f4..0a909dc 100644 --- a/vpsdk/syscall.vp +++ b/vpsdk/syscall.vp @@ -30,8 +30,10 @@ enum Syscall: 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(用户层):同上 + LOAD_SO = 0x1006 # TODO(userspace): dynamic library loading + SO_CALL1 = 0x1007 # TODO(userspace): dynamic library call + REBOOT = 0x1008 + SHUTDOWN = 0x1009 # ---- mmap 的 prot / flags(与内核 VKernel/intr/syscall.vp 及各 Linux 同名常量一致)---- define PROT_NONE = 0x0