Fix kstop and kreset.

This commit is contained in:
4lDO2
2024-03-07 15:03:01 +01:00
parent b97e733d94
commit 8e19da338b
5 changed files with 40 additions and 33 deletions
+2 -4
View File
@@ -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;
+4 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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();
-20
View File
@@ -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 {