diff --git a/Makefile b/Makefile index 4f6546b..80d3fe8 100644 --- a/Makefile +++ b/Makefile @@ -130,6 +130,7 @@ UPROGS=\ $P/_usertests\ $P/_wc\ $P/_zombie\ + $P/_shutdown\ fs.img: mkfs/mkfs README $(UPROGS) mkfs/mkfs fs.img README $(UPROGS) diff --git a/kernel/memlayout.h b/kernel/memlayout.h index 776f98c..4687bc1 100644 --- a/kernel/memlayout.h +++ b/kernel/memlayout.h @@ -17,6 +17,9 @@ // end -- start of kernel page allocation area // PHYSTOP -- end RAM used by the kernel +// QEMU test interface. Used for poweroff and on. +#define QEMU_POWER 0x100000 + // qemu puts UART registers here in physical memory. #define UART0 0x10000000L #define UART0_IRQ 10 diff --git a/kernel/rustkernel/src/riscv/memlayout.rs b/kernel/rustkernel/src/riscv/memlayout.rs index 4f4d26b..25d0eaa 100644 --- a/kernel/rustkernel/src/riscv/memlayout.rs +++ b/kernel/rustkernel/src/riscv/memlayout.rs @@ -18,6 +18,9 @@ use super::{MAXVA, PGSIZE}; +// QEMU test interface. Used for power off and on. +pub const QEMU_POWER: u64 = 0x100000u64; + // QEMU puts UART registers here in physical memory. pub const UART0: u64 = 0x10000000; pub const UART0_IRQ: i32 = 10; diff --git a/kernel/rustkernel/src/syscall.rs b/kernel/rustkernel/src/syscall.rs index c2d949c..d11c5e0 100644 --- a/kernel/rustkernel/src/syscall.rs +++ b/kernel/rustkernel/src/syscall.rs @@ -1,7 +1,7 @@ use crate::{ console::printf::print, proc::{self, myproc, sleep_lock}, - riscv::Pagetable, + riscv::{Pagetable, memlayout::QEMU_POWER}, string::strlen, }; use core::{mem::size_of, ptr::addr_of_mut}; @@ -47,6 +47,7 @@ pub enum Syscall { Link, Mkdir, Close, + Shutdown, } impl Syscall { pub unsafe fn call(&self) -> u64 { @@ -113,6 +114,11 @@ impl Syscall { Syscall::Link => sys_link(), Syscall::Mkdir => sys_mkdir(), Syscall::Close => sys_close(), + Syscall::Shutdown => { + let qemu_power = QEMU_POWER as usize as *mut u32; + qemu_power.write_volatile(0x5555u32); + panic!("shutdown"); + } } } } @@ -142,6 +148,7 @@ impl TryFrom for Syscall { 19 => Ok(Syscall::Link), 20 => Ok(Syscall::Mkdir), 21 => Ok(Syscall::Close), + 22 => Ok(Syscall::Shutdown), _ => Err(()), } } @@ -170,6 +177,7 @@ impl From for usize { Syscall::Link => 19, Syscall::Mkdir => 20, Syscall::Close => 21, + Syscall::Shutdown => 22, } } } diff --git a/kernel/syscall.h b/kernel/syscall.h index bc5f356..1913514 100644 --- a/kernel/syscall.h +++ b/kernel/syscall.h @@ -20,3 +20,4 @@ #define SYS_link 19 #define SYS_mkdir 20 #define SYS_close 21 +#define SYS_shutdown 22 diff --git a/kernel/vm.c b/kernel/vm.c index 9f69783..f7d7a94 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -24,6 +24,9 @@ kvmmake(void) kpgtbl = (pagetable_t) kalloc(); memset(kpgtbl, 0, PGSIZE); + // QEMU test interface used for power management. + kvmmap(kpgtbl, QEMU_POWER, QEMU_POWER, PGSIZE, PTE_R | PTE_W); + // uart registers kvmmap(kpgtbl, UART0, UART0, PGSIZE, PTE_R | PTE_W); diff --git a/programs/shutdown.c b/programs/shutdown.c new file mode 100644 index 0000000..e30bfd8 --- /dev/null +++ b/programs/shutdown.c @@ -0,0 +1,10 @@ +#include "kernel/types.h" +#include "kernel/stat.h" +#include "user/user.h" + +int main(int argc, char *argv[]) +{ + shutdown(); + // Unreachable + exit(1); +} diff --git a/user/user.h b/user/user.h index 4d398d5..d0426ec 100644 --- a/user/user.h +++ b/user/user.h @@ -22,6 +22,7 @@ int getpid(void); char* sbrk(int); int sleep(int); int uptime(void); +void shutdown(void); // ulib.c int stat(const char*, struct stat*); diff --git a/user/usys.pl b/user/usys.pl index 01e426e..461806c 100755 --- a/user/usys.pl +++ b/user/usys.pl @@ -36,3 +36,4 @@ entry("getpid"); entry("sbrk"); entry("sleep"); entry("uptime"); +entry("shutdown");