Dedup some more code between x86 and x86_64

This commit is contained in:
bjorn3
2024-01-24 21:31:15 +01:00
committed by Jeremy Soller
parent 0d092d7921
commit 86fb4208f2
7 changed files with 10 additions and 141 deletions
+2 -5
View File
@@ -1,3 +1,5 @@
pub use crate::arch::x86_shared::*;
#[macro_use]
pub mod macros;
@@ -37,11 +39,6 @@ pub mod rmm;
/// Initialization and start function
pub mod start;
/// Stop function
pub mod stop;
pub mod time;
use crate::{memory::PAGE_SIZE, Bootstrap};
use ::rmm::Arch;
pub use ::rmm::X86Arch as CurrentRmmArch;
+2 -5
View File
@@ -2,6 +2,8 @@ use crate::Bootstrap;
use self::paging::PAGE_SIZE;
pub use crate::arch::x86_shared::*;
pub mod alternative;
#[macro_use]
@@ -46,11 +48,6 @@ pub mod rmm;
/// Initialization and start function
pub mod start;
/// Stop function
pub mod stop;
pub mod time;
use ::rmm::Arch;
pub use ::rmm::X8664Arch as CurrentRmmArch;
-91
View File
@@ -1,91 +0,0 @@
#[cfg(feature = "acpi")]
use crate::{context, scheme::acpi, time};
use crate::syscall::io::{Io, Pio};
#[no_mangle]
pub unsafe extern "C" fn kreset() -> ! {
println!("kreset");
// 8042 reset
{
println!("Reset with 8042");
let mut port = Pio::<u8>::new(0x64);
while port.readf(2) {}
port.write(0xFE);
}
emergency_reset();
}
pub unsafe fn emergency_reset() -> ! {
// Use triple fault to guarantee reset
core::arch::asm!(
"
cli
lidt cs:0
int $3
",
options(noreturn)
);
}
#[cfg(feature = "acpi")]
fn userspace_acpi_shutdown() {
log::info!("Notifying any potential ACPI driver");
// Tell whatever driver that handles ACPI, that it should enter the S5 state (i.e.
// shutdown).
if !acpi::register_kstop() {
// There was no context to switch to.
log::info!("No ACPI driver was alive to handle shutdown.");
return;
}
log::info!("Waiting one second for ACPI driver to run the shutdown sequence.");
let initial = time::monotonic();
// Since this driver is a userspace process, and we do not use any magic like directly
// context switching, we have to wait for the userspace driver to complete, with a timeout.
//
// We switch context, and wait for one second.
loop {
// 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 current = time::monotonic();
if current - initial > time::NANOS_PER_SEC {
log::info!("Timeout reached, thus falling back to other shutdown methods.");
return;
}
}
}
#[no_mangle]
pub unsafe extern "C" fn kstop() -> ! {
log::info!("Running kstop()");
#[cfg(feature = "acpi")]
userspace_acpi_shutdown();
// Magic shutdown code for bochs and qemu (older versions).
for c in "Shutdown".bytes() {
let port = 0x8900;
println!("Shutdown with outb(0x{:X}, '{}')", port, c as char);
Pio::<u8>::new(port).write(c);
}
// Magic shutdown using qemu default ACPI method
{
let port = 0x604;
let data = 0x2000;
println!("Shutdown with outb(0x{:X}, 0x{:X})", port, data);
Pio::<u16>::new(port).write(data);
}
// Magic code for VMWare. Also a hard lock.
println!("Shutdown with cli hlt");
loop {
core::arch::asm!("cli; hlt");
}
}
-40
View File
@@ -1,40 +0,0 @@
#[cfg(feature = "acpi")]
use super::device::hpet;
use super::device::pit;
pub fn counter() -> u128 {
#[cfg(feature = "acpi")]
if let Some(ref hpet) = *crate::acpi::ACPI_TABLE.hpet.read() {
//TODO: handle rollover?
//TODO: improve performance
// Current count
let counter = unsafe { hpet.base_address.read_u64(hpet::MAIN_COUNTER_OFFSET) };
// Comparator holds next interrupt count
let comparator = unsafe { hpet.base_address.read_u64(hpet::T0_COMPARATOR_OFFSET) };
// Get period in femtoseconds
let capability = unsafe { hpet.base_address.read_u64(hpet::CAPABILITY_OFFSET) };
// There seems to be a bug in qemu on macos that causes the calculation to produce 0 for
// period_fs and hence a divide by zero calculating the divisor - workaround it while we
// try and get a fix from qemu: https://gitlab.com/qemu-project/qemu/-/issues/1570
let mut period_fs = capability >> 32;
if period_fs == 0 {
period_fs = 10_000_000;
}
// Calculate divisor
let divisor = (pit::RATE as u64 * 1_000_000) / period_fs;
// Calculate last interrupt
let last_interrupt = comparator.saturating_sub(divisor);
// Calculate ticks since last interrupt
let elapsed = counter.saturating_sub(last_interrupt);
// Calculate nanoseconds since last interrupt
return (elapsed as u128 * period_fs as u128) / 1_000_000;
}
// Read ticks since last interrupt
let elapsed = unsafe { pit::read() };
// Calculate nanoseconds since last interrupt
(elapsed as u128 * pit::PERIOD_FS) / 1_000_000
}
+6
View File
@@ -1 +1,7 @@
/// Devices
pub mod device;
/// Stop function
pub mod stop;
pub mod time;