Kernel+Userland: Addd reboot syscall (#334)

Rolling with the theme of adding a dialog to shutdown the machine, it is
probably nice to have a way to reboot the machine without performing a full
system powerdown.

A reboot program has been added to `/bin/` as well as a corresponding
`syscall` (SC_reboot). This syscall works by attempting to pulse the 8042
keyboard controller. Note that this is NOT supported on  new machines, and
should only be a fallback until we have proper ACPI support.

The implementation causes a triple fault in QEMU, which then restarts the
system. The filesystems are locked and synchronized before this occurs,
so there shouldn't be any corruption etctera.
This commit is contained in:
Jesse 2019-07-19 17:58:12 +10:00 committed by Andreas Kling
parent 23d45532fc
commit a27c9e3e01
7 changed files with 45 additions and 2 deletions

View file

@ -12,6 +12,7 @@
#include <Kernel/FileSystem/FileDescription.h>
#include <Kernel/FileSystem/SharedMemory.h>
#include <Kernel/FileSystem/VirtualFileSystem.h>
#include <Kernel/IO.h>
#include <Kernel/KSyms.h>
#include <Kernel/Multiboot.h>
#include <Kernel/Net/Socket.h>
@ -19,8 +20,8 @@
#include <Kernel/ProcessTracer.h>
#include <Kernel/RTC.h>
#include <Kernel/Scheduler.h>
#include <Kernel/StdLib.h>
#include <Kernel/SharedBuffer.h>
#include <Kernel/StdLib.h>
#include <Kernel/Syscall.h>
#include <Kernel/TTY/MasterPTY.h>
#include <Kernel/kmalloc.h>
@ -2635,6 +2636,21 @@ int Process::sys$systrace(pid_t pid)
return fd;
}
int Process::sys$reboot()
{
if (!is_superuser())
return -EPERM;
dbgprintf("acquiring FS locks...\n");
FS::lock_all();
dbgprintf("syncing mounted filesystems...\n");
FS::sync();
dbgprintf("attempting reboot via KB Controller...\n");
IO::out8(0x64, 0xFE);
return ESUCCESS;
}
ProcessTracer& Process::ensure_tracer()
{
if (!m_tracer)

View file

@ -203,6 +203,7 @@ public:
int sys$release_shared_buffer(int shared_buffer_id);
int sys$seal_shared_buffer(int shared_buffer_id);
int sys$get_shared_buffer_size(int shared_buffer_id);
int sys$reboot();
static void initialize();

View file

@ -293,6 +293,9 @@ static u32 handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3
IO::out16(0x604, 0x2000);
break;
}
case Syscall::SC_reboot: {
return current->process().sys$reboot();
}
default:
kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3);
return -ENOSYS;

View file

@ -114,7 +114,8 @@ struct timeval;
__ENUMERATE_SYSCALL(sched_setparam) \
__ENUMERATE_SYSCALL(sched_getparam) \
__ENUMERATE_SYSCALL(fchown) \
__ENUMERATE_SYSCALL(halt)
__ENUMERATE_SYSCALL(halt) \
__ENUMERATE_SYSCALL(reboot)
namespace Syscall {

View file

@ -514,4 +514,10 @@ int fsync(int fd)
dbgprintf("FIXME: Implement fsync()\n");
return 0;
}
int reboot()
{
int rc = syscall(SC_reboot);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
}

View file

@ -93,6 +93,7 @@ char* getlogin();
int chown(const char* pathname, uid_t, gid_t);
int fchown(int fd, uid_t, gid_t);
int ftruncate(int fd, off_t length);
int reboot();
enum {
_PC_NAME_MAX,

15
Userland/reboot.cpp Normal file
View file

@ -0,0 +1,15 @@
#include <stdio.h>
#include <unistd.h>
int main(int, char**)
{
if (reboot() < 0){
perror("reboot");
return 1;
}
return 0;
}