Fix kstop and kreset.
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
use core::arch::asm;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn kreset() -> ! {
|
||||
pub unsafe fn kreset() -> ! {
|
||||
println!("kreset");
|
||||
|
||||
let val: u32 = 0x8400_0009;
|
||||
@@ -15,8 +14,7 @@ pub unsafe fn emergency_reset() -> ! {
|
||||
asm!("hvc #0", options(noreturn));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn kstop() -> ! {
|
||||
pub unsafe fn kstop() -> ! {
|
||||
println!("kstop");
|
||||
|
||||
let val: u32 = 0x8400_0008;
|
||||
|
||||
@@ -3,9 +3,8 @@ use crate::{context, scheme::acpi, time};
|
||||
|
||||
use crate::syscall::io::{Io, Pio};
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn kreset() -> ! {
|
||||
println!("kreset");
|
||||
pub unsafe fn kreset() -> ! {
|
||||
log::info!("kreset");
|
||||
|
||||
// 8042 reset
|
||||
{
|
||||
@@ -51,7 +50,7 @@ fn userspace_acpi_shutdown() {
|
||||
// TODO: Switch directly to whichever process is handling the kstop pipe. We would add an
|
||||
// event flag like EVENT_DIRECT, which has already been suggested for IRQs.
|
||||
// TODO: Waitpid with timeout? Because, what if the ACPI driver would crash?
|
||||
let _ = unsafe { context::switch() };
|
||||
let _ = context::switch();
|
||||
|
||||
let current = time::monotonic();
|
||||
if current - initial > time::NANOS_PER_SEC {
|
||||
@@ -61,8 +60,7 @@ fn userspace_acpi_shutdown() {
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn kstop() -> ! {
|
||||
pub unsafe fn kstop() -> ! {
|
||||
log::info!("Running kstop()");
|
||||
|
||||
#[cfg(feature = "acpi")]
|
||||
|
||||
+28
-2
@@ -5,15 +5,41 @@ use syscall::{
|
||||
PTRACE_FLAG_IGNORE, PTRACE_STOP_SIGNAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP,
|
||||
SIGTTIN, SIGTTOU, SIG_DFL, SIG_IGN,
|
||||
},
|
||||
ptrace_event, SignalStack, SigActionFlags, IntRegisters, Error, EINTR,
|
||||
ptrace_event, SignalStack, SigActionFlags, IntRegisters, Error, EINTR, SIGTERM,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
context::{self, switch, Status, WaitpidKey},
|
||||
ptrace,
|
||||
syscall::usercopy::UserSlice,
|
||||
syscall::usercopy::UserSlice, stop::{kstop, kreset},
|
||||
};
|
||||
|
||||
use super::ContextId;
|
||||
|
||||
pub fn kmain_signal_handler() {
|
||||
if context::context_id() != ContextId::new(1) {
|
||||
log::warn!("kmain signal didn't target PID 1, ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
let deliverable = context::current().expect("context::kmain_signal_handler not inside of context");
|
||||
let kstop_bit = 1 << (SIGKILL - 1);
|
||||
let kreset_bit = 1 << (SIGTERM - 1);
|
||||
let bits = deliverable.read().sig.deliverable();
|
||||
|
||||
if bits & kstop_bit == kstop_bit {
|
||||
unsafe {
|
||||
kstop();
|
||||
}
|
||||
} else if bits & kreset_bit == kreset_bit {
|
||||
unsafe {
|
||||
kreset();
|
||||
}
|
||||
} else {
|
||||
log::warn!("Spurious kmain signal, bitmask {bits:#0x}.");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Move everything but SIGKILL to userspace. SIGCONT and SIGSTOP do not necessarily need to
|
||||
// be done from this current context.
|
||||
pub fn signal_handler(eintr: bool) {
|
||||
|
||||
+6
-1
@@ -243,7 +243,12 @@ fn run_userspace() -> ! {
|
||||
unsafe {
|
||||
interrupt::disable();
|
||||
match context::switch() {
|
||||
SwitchResult::Switched { .. } => interrupt::enable_and_nop(),
|
||||
SwitchResult::Switched { signal } => {
|
||||
if signal {
|
||||
crate::context::signal::kmain_signal_handler();
|
||||
}
|
||||
interrupt::enable_and_nop();
|
||||
}
|
||||
SwitchResult::AllContextsIdle => {
|
||||
// Enable interrupts, then halt CPU (to save power) until the next interrupt is actually fired.
|
||||
interrupt::enable_and_halt();
|
||||
|
||||
@@ -50,26 +50,6 @@ pub fn exit(status: usize) -> ! {
|
||||
context.id
|
||||
};
|
||||
|
||||
// TODO: Find a better way to implement this, perhaps when the init process calls exit.
|
||||
if pid == ContextId::from(1) {
|
||||
println!("Main kernel thread exited with status {:X}", status);
|
||||
|
||||
extern "C" {
|
||||
fn kreset() -> !;
|
||||
fn kstop() -> !;
|
||||
}
|
||||
|
||||
if status == SIGTERM {
|
||||
unsafe {
|
||||
kreset();
|
||||
}
|
||||
} else {
|
||||
unsafe {
|
||||
kstop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Files must be closed while context is valid so that messages can be passed
|
||||
for (_fd, file_opt) in close_files.into_iter().enumerate() {
|
||||
if let Some(file) = file_opt {
|
||||
|
||||
Reference in New Issue
Block a user