acpi: move ACPI to its own driver
This commit is contained in:
parent
9e48530e62
commit
6e7a42c2cb
19
Cargo.lock
generated
19
Cargo.lock
generated
@ -2460,6 +2460,22 @@ dependencies = [
|
|||||||
"bytemuck",
|
"bytemuck",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ygg_driver_acpi"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"acpi",
|
||||||
|
"acpi-system",
|
||||||
|
"aml",
|
||||||
|
"device-api",
|
||||||
|
"kernel-arch-x86",
|
||||||
|
"libk",
|
||||||
|
"libk-mm",
|
||||||
|
"libk-util",
|
||||||
|
"log",
|
||||||
|
"rsdp",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ygg_driver_ahci"
|
name = "ygg_driver_ahci"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -2658,8 +2674,6 @@ dependencies = [
|
|||||||
"abi-lib",
|
"abi-lib",
|
||||||
"abi-serde",
|
"abi-serde",
|
||||||
"acpi",
|
"acpi",
|
||||||
"acpi-system",
|
|
||||||
"aml",
|
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
@ -2690,6 +2704,7 @@ dependencies = [
|
|||||||
"tock-registers 0.9.0",
|
"tock-registers 0.9.0",
|
||||||
"vmalloc",
|
"vmalloc",
|
||||||
"yboot-proto",
|
"yboot-proto",
|
||||||
|
"ygg_driver_acpi",
|
||||||
"ygg_driver_ahci",
|
"ygg_driver_ahci",
|
||||||
"ygg_driver_input",
|
"ygg_driver_input",
|
||||||
"ygg_driver_net_core",
|
"ygg_driver_net_core",
|
||||||
|
@ -39,6 +39,7 @@ ahash = { version = "0.8.11", default-features = false, features = ["no-rng"] }
|
|||||||
|
|
||||||
# acpi
|
# acpi
|
||||||
acpi = { git = "https://github.com/alnyan/acpi.git", package = "acpi", branch = "acpi-system" }
|
acpi = { git = "https://github.com/alnyan/acpi.git", package = "acpi", branch = "acpi-system" }
|
||||||
|
rsdp = { git = "https://github.com/alnyan/acpi.git", package = "rsdp", branch = "acpi-system" }
|
||||||
aml = { git = "https://github.com/alnyan/acpi.git", branch = "acpi-system" }
|
aml = { git = "https://github.com/alnyan/acpi.git", branch = "acpi-system" }
|
||||||
acpi-system = { git = "https://github.com/alnyan/acpi-system.git" }
|
acpi-system = { git = "https://github.com/alnyan/acpi-system.git" }
|
||||||
|
|
||||||
|
@ -61,12 +61,11 @@ kernel-arch-riscv64.workspace = true
|
|||||||
yboot-proto.workspace = true
|
yboot-proto.workspace = true
|
||||||
kernel-arch-x86_64.workspace = true
|
kernel-arch-x86_64.workspace = true
|
||||||
kernel-arch-x86.workspace = true
|
kernel-arch-x86.workspace = true
|
||||||
|
ygg_driver_acpi.path = "driver/acpi"
|
||||||
|
|
||||||
ygg_driver_nvme = { path = "driver/block/nvme" }
|
ygg_driver_nvme = { path = "driver/block/nvme" }
|
||||||
|
|
||||||
acpi.workspace = true
|
acpi.workspace = true
|
||||||
aml.workspace = true
|
|
||||||
acpi-system.workspace = true
|
|
||||||
|
|
||||||
[target.'cfg(target_arch = "x86")'.dependencies]
|
[target.'cfg(target_arch = "x86")'.dependencies]
|
||||||
kernel-arch-i686.workspace = true
|
kernel-arch-i686.workspace = true
|
||||||
@ -87,6 +86,8 @@ kernel-arch-x86.workspace = true
|
|||||||
kernel-arch-aarch64.workspace = true
|
kernel-arch-aarch64.workspace = true
|
||||||
kernel-arch-riscv64.workspace = true
|
kernel-arch-riscv64.workspace = true
|
||||||
|
|
||||||
|
ygg_driver_acpi.path = "driver/acpi"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["fb_console"]
|
default = ["fb_console"]
|
||||||
fb_console = []
|
fb_console = []
|
||||||
|
@ -6,4 +6,10 @@ extern crate alloc;
|
|||||||
|
|
||||||
pub mod cpuid;
|
pub mod cpuid;
|
||||||
pub mod gdt;
|
pub mod gdt;
|
||||||
|
pub mod intrinsics;
|
||||||
pub mod registers;
|
pub mod registers;
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||||
|
pub const ISA_IRQ_OFFSET: u32 = 1024;
|
||||||
|
#[cfg(any(target_arch = "x86", rust_analyzer))]
|
||||||
|
pub const ISA_IRQ_OFFSET: u32 = 0;
|
||||||
|
18
kernel/driver/acpi/Cargo.toml
Normal file
18
kernel/driver/acpi/Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
[package]
|
||||||
|
name = "ygg_driver_acpi"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libk-util.workspace = true
|
||||||
|
libk-mm.workspace = true
|
||||||
|
libk.workspace = true
|
||||||
|
device-api.workspace = true
|
||||||
|
kernel-arch-x86.path = "../../arch/x86"
|
||||||
|
|
||||||
|
acpi.workspace = true
|
||||||
|
rsdp.workspace = true
|
||||||
|
aml.workspace = true
|
||||||
|
acpi-system.workspace = true
|
||||||
|
|
||||||
|
log.workspace = true
|
131
kernel/driver/acpi/src/aml_handler.rs
Normal file
131
kernel/driver/acpi/src/aml_handler.rs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
use core::time::Duration;
|
||||||
|
|
||||||
|
use crate::AcpiHandlerImpl;
|
||||||
|
|
||||||
|
impl aml::Handler for AcpiHandlerImpl {
|
||||||
|
fn read_io_u8(&self, port: u16) -> u8 {
|
||||||
|
<Self as acpi_system::Handler>::io_read_u8(port)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_io_u16(&self, port: u16) -> u16 {
|
||||||
|
<Self as acpi_system::Handler>::io_read_u16(port)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_io_u32(&self, port: u16) -> u32 {
|
||||||
|
<Self as acpi_system::Handler>::io_read_u32(port)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_io_u8(&self, port: u16, value: u8) {
|
||||||
|
<Self as acpi_system::Handler>::io_write_u8(port, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_io_u16(&self, port: u16, value: u16) {
|
||||||
|
<Self as acpi_system::Handler>::io_write_u16(port, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_io_u32(&self, port: u16, value: u32) {
|
||||||
|
<Self as acpi_system::Handler>::io_write_u32(port, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_u8(&self, address: usize) -> u8 {
|
||||||
|
<Self as acpi_system::Handler>::mem_read_u8(address as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_u16(&self, address: usize) -> u16 {
|
||||||
|
<Self as acpi_system::Handler>::mem_read_u16(address as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_u32(&self, address: usize) -> u32 {
|
||||||
|
<Self as acpi_system::Handler>::mem_read_u32(address as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_u64(&self, address: usize) -> u64 {
|
||||||
|
<Self as acpi_system::Handler>::mem_read_u64(address as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_u8(&self, address: usize, value: u8) {
|
||||||
|
<Self as acpi_system::Handler>::mem_write_u8(address as u64, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_u16(&self, address: usize, value: u16) {
|
||||||
|
<Self as acpi_system::Handler>::mem_write_u16(address as u64, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_u32(&self, address: usize, value: u32) {
|
||||||
|
<Self as acpi_system::Handler>::mem_write_u32(address as u64, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_u64(&self, address: usize, value: u64) {
|
||||||
|
<Self as acpi_system::Handler>::mem_write_u64(address as u64, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_pci_u8(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16) -> u8 {
|
||||||
|
0xFF
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_pci_u16(
|
||||||
|
&self,
|
||||||
|
_segment: u16,
|
||||||
|
_bus: u8,
|
||||||
|
_device: u8,
|
||||||
|
_function: u8,
|
||||||
|
_offset: u16,
|
||||||
|
) -> u16 {
|
||||||
|
0xFFFF
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_pci_u32(
|
||||||
|
&self,
|
||||||
|
_segment: u16,
|
||||||
|
_bus: u8,
|
||||||
|
_device: u8,
|
||||||
|
_function: u8,
|
||||||
|
_offset: u16,
|
||||||
|
) -> u32 {
|
||||||
|
0xFFFFFFFF
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_pci_u8(
|
||||||
|
&self,
|
||||||
|
_segment: u16,
|
||||||
|
_bus: u8,
|
||||||
|
_device: u8,
|
||||||
|
_function: u8,
|
||||||
|
_offset: u16,
|
||||||
|
_value: u8,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_pci_u16(
|
||||||
|
&self,
|
||||||
|
_segment: u16,
|
||||||
|
_bus: u8,
|
||||||
|
_device: u8,
|
||||||
|
_function: u8,
|
||||||
|
_offset: u16,
|
||||||
|
_value: u16,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_pci_u32(
|
||||||
|
&self,
|
||||||
|
_segment: u16,
|
||||||
|
_bus: u8,
|
||||||
|
_device: u8,
|
||||||
|
_function: u8,
|
||||||
|
_offset: u16,
|
||||||
|
_value: u32,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_ec_u8(&self, _address: u64) -> u8 {
|
||||||
|
0x00
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_ec_u8(&self, _address: u64, _value: u8) {}
|
||||||
|
|
||||||
|
fn sleep(&self, _duration: Duration) {
|
||||||
|
todo!()
|
||||||
|
// util::polling_sleep(duration).unwrap();
|
||||||
|
}
|
||||||
|
}
|
171
kernel/driver/acpi/src/handler.rs
Normal file
171
kernel/driver/acpi/src/handler.rs
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
use core::{ptr::NonNull, time::Duration};
|
||||||
|
|
||||||
|
use acpi::PhysicalMapping;
|
||||||
|
use acpi_system::AcpiSystemError;
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
use device_api::{
|
||||||
|
device::Device,
|
||||||
|
interrupt::{InterruptHandler, Irq},
|
||||||
|
};
|
||||||
|
use kernel_arch_x86::{intrinsics, ISA_IRQ_OFFSET};
|
||||||
|
use libk::device::external_interrupt_controller;
|
||||||
|
use libk_mm::{
|
||||||
|
address::{PhysicalAddress, Virtualize},
|
||||||
|
pointer::PhysicalRef,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
mem::{read_memory, write_memory},
|
||||||
|
ACPI_SYSTEM,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub struct AcpiHandlerImpl;
|
||||||
|
|
||||||
|
struct SciHandler;
|
||||||
|
|
||||||
|
impl acpi_system::Handler for AcpiHandlerImpl {
|
||||||
|
type MappedSlice = PhysicalRef<'static, [u8]>;
|
||||||
|
|
||||||
|
unsafe fn map_slice(address: u64, length: u64) -> Self::MappedSlice {
|
||||||
|
unsafe {
|
||||||
|
PhysicalRef::map_slice(
|
||||||
|
PhysicalAddress::from_u64(address),
|
||||||
|
length.try_into().unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn io_read_u8(port: u16) -> u8 {
|
||||||
|
let value = unsafe { intrinsics::inb(port) };
|
||||||
|
log::trace!("io_read_u8 {:#x} <- {:#x}", port, value);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn io_read_u16(port: u16) -> u16 {
|
||||||
|
let value = unsafe { intrinsics::inw(port) };
|
||||||
|
log::trace!("io_read_u16 {:#x} <- {:#x}", port, value);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn io_read_u32(port: u16) -> u32 {
|
||||||
|
let value = unsafe { intrinsics::inl(port) };
|
||||||
|
log::trace!("io_read_u32 {:#x} <- {:#x}", port, value);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn io_write_u8(port: u16, value: u8) {
|
||||||
|
log::trace!("io_write_u8 {:#x}, {:#x}", port, value);
|
||||||
|
unsafe { intrinsics::outb(port, value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn io_write_u16(port: u16, value: u16) {
|
||||||
|
log::trace!("io_write_u16 {:#x}, {:#x}", port, value);
|
||||||
|
unsafe { intrinsics::outw(port, value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn io_write_u32(port: u16, value: u32) {
|
||||||
|
log::trace!("io_write_u32 {:#x}, {:#x}", port, value);
|
||||||
|
unsafe { intrinsics::outl(port, value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mem_read_u8(address: u64) -> u8 {
|
||||||
|
let value = unsafe { read_memory(PhysicalAddress::from_u64(address)) };
|
||||||
|
log::trace!("mem_read_u8 {:#x} -> {:#x}", address, value);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mem_read_u16(address: u64) -> u16 {
|
||||||
|
let value = unsafe { read_memory(PhysicalAddress::from_u64(address)) };
|
||||||
|
log::trace!("mem_read_u16 {:#x} -> {:#x}", address, value);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mem_read_u32(address: u64) -> u32 {
|
||||||
|
let value = unsafe { read_memory(PhysicalAddress::from_u64(address)) };
|
||||||
|
log::trace!("mem_read_u32 {:#x} -> {:#x}", address, value);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mem_read_u64(address: u64) -> u64 {
|
||||||
|
let value = unsafe { read_memory(PhysicalAddress::from_u64(address)) };
|
||||||
|
log::trace!("mem_read_u64 {:#x} -> {:#x}", address, value);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mem_write_u8(address: u64, value: u8) {
|
||||||
|
log::trace!("mem_write_u8 {:#x}, {:#x}", address, value);
|
||||||
|
unsafe { write_memory(PhysicalAddress::from_u64(address), value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mem_write_u16(address: u64, value: u16) {
|
||||||
|
log::trace!("mem_write_u16 {:#x}, {:#x}", address, value);
|
||||||
|
unsafe { write_memory(PhysicalAddress::from_u64(address), value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mem_write_u32(address: u64, value: u32) {
|
||||||
|
log::trace!("mem_write_u32 {:#x}, {:#x}", address, value);
|
||||||
|
unsafe { write_memory(PhysicalAddress::from_u64(address), value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mem_write_u64(address: u64, value: u64) {
|
||||||
|
log::trace!("mem_write_u64 {:#x}, {:#x}", address, value);
|
||||||
|
unsafe { write_memory(PhysicalAddress::from_u64(address), value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn install_interrupt_handler(irq: u32) -> Result<(), AcpiSystemError> {
|
||||||
|
log::info!("Installing ACPI SCI handler at IRQ #{}", irq);
|
||||||
|
|
||||||
|
let intc = external_interrupt_controller().expect("No external intc");
|
||||||
|
let handler = Arc::new(SciHandler);
|
||||||
|
let irq = Irq::External(irq + ISA_IRQ_OFFSET);
|
||||||
|
|
||||||
|
intc.register_irq(irq, Default::default(), handler).unwrap();
|
||||||
|
intc.enable_irq(irq).unwrap();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stall(_duration: Duration) {
|
||||||
|
// TODO polling_sleep is not yet implemented properly
|
||||||
|
todo!()
|
||||||
|
// util::polling_sleep(duration).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl rsdp::handler::AcpiHandler for AcpiHandlerImpl {
|
||||||
|
unsafe fn map_physical_region<T>(
|
||||||
|
&self,
|
||||||
|
physical_address: usize,
|
||||||
|
size: usize,
|
||||||
|
) -> PhysicalMapping<Self, T> {
|
||||||
|
unsafe {
|
||||||
|
PhysicalMapping::new(
|
||||||
|
physical_address,
|
||||||
|
NonNull::new_unchecked(
|
||||||
|
PhysicalAddress::from_usize(physical_address).virtualize() as *mut T
|
||||||
|
),
|
||||||
|
size,
|
||||||
|
size,
|
||||||
|
*self,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unmap_physical_region<T>(_region: &acpi::PhysicalMapping<Self, T>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InterruptHandler for SciHandler {
|
||||||
|
fn handle_irq(self: Arc<Self>, _vector: Option<usize>) -> bool {
|
||||||
|
log::trace!("ACPI SCI received");
|
||||||
|
ACPI_SYSTEM.get().lock().handle_sci();
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Device for SciHandler {
|
||||||
|
fn display_name(&self) -> &str {
|
||||||
|
"ACPI SCI handler"
|
||||||
|
}
|
||||||
|
}
|
74
kernel/driver/acpi/src/lib.rs
Normal file
74
kernel/driver/acpi/src/lib.rs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#![feature(allocator_api)]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
use acpi::AcpiTables;
|
||||||
|
use acpi_system::{AcpiInterruptMethod, AcpiSystem};
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use libk::error::Error;
|
||||||
|
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
pub mod mem;
|
||||||
|
pub use mem::AcpiAllocator;
|
||||||
|
pub mod handler;
|
||||||
|
pub use handler::AcpiHandlerImpl;
|
||||||
|
pub mod aml_handler;
|
||||||
|
|
||||||
|
pub use acpi_system::{EventAction, FixedEvent};
|
||||||
|
|
||||||
|
static ACPI_SYSTEM: OneTimeInit<IrqSafeSpinlock<AcpiSystem<AcpiHandlerImpl>>> = OneTimeInit::new();
|
||||||
|
|
||||||
|
pub fn add_event_handler<F: Fn(&AcpiSystem<AcpiHandlerImpl>) -> EventAction + 'static>(
|
||||||
|
event: &FixedEvent,
|
||||||
|
handler: F,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
ACPI_SYSTEM
|
||||||
|
.get()
|
||||||
|
.lock()
|
||||||
|
.enable_fixed_event(event, Box::new(handler))
|
||||||
|
.map_err(|_| Error::InvalidArgument)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initializes ACPI management
|
||||||
|
pub fn switch_to_acpi(tables: &'static AcpiTables<AcpiHandlerImpl>) -> Result<(), Error> {
|
||||||
|
// NOTE mostly broken for real HW
|
||||||
|
let mut system = AcpiSystem::new(tables, Box::new(AcpiHandlerImpl)).unwrap();
|
||||||
|
|
||||||
|
system.initialize(AcpiInterruptMethod::Apic).unwrap();
|
||||||
|
|
||||||
|
// system
|
||||||
|
// .enable_fixed_event(
|
||||||
|
// &FixedEvent::POWER_BUTTON,
|
||||||
|
// Box::new(|_| {
|
||||||
|
// log::info!("Power button was pressed");
|
||||||
|
|
||||||
|
// // TODO the correct way would be to
|
||||||
|
// // 1. Nicely ask all the processes to quit
|
||||||
|
// // 2. Wait for some time
|
||||||
|
// // 3. Kill the remaining ones
|
||||||
|
// // 4. Halt other cores
|
||||||
|
// // 5. Sync filesystem
|
||||||
|
// // 6. Do something with the devices
|
||||||
|
// // 7. Actually enter the S5 state
|
||||||
|
|
||||||
|
// unsafe {
|
||||||
|
// PLATFORM
|
||||||
|
// .send_ipi(IpiDeliveryTarget::OtherCpus, IpiMessage::Shutdown)
|
||||||
|
// .unwrap();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// SHUTDOWN_FENCE.signal();
|
||||||
|
// SHUTDOWN_FENCE.wait_all(CPU_COUNT.load(Ordering::Acquire));
|
||||||
|
|
||||||
|
// log::info!("CPUs are parked, can shutdown now");
|
||||||
|
|
||||||
|
// EventAction::EnterSleepState(AcpiSleepState::S5)
|
||||||
|
// }),
|
||||||
|
// )
|
||||||
|
// .unwrap();
|
||||||
|
|
||||||
|
ACPI_SYSTEM.init(IrqSafeSpinlock::new(system));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
64
kernel/driver/acpi/src/mem.rs
Normal file
64
kernel/driver/acpi/src/mem.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
//! ACPI memory IO and management functions
|
||||||
|
|
||||||
|
use core::{
|
||||||
|
alloc::{AllocError, Allocator, GlobalAlloc, Layout},
|
||||||
|
ptr::NonNull,
|
||||||
|
};
|
||||||
|
|
||||||
|
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryMapping, heap::GLOBAL_HEAP};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub struct AcpiAllocator;
|
||||||
|
|
||||||
|
unsafe impl Allocator for AcpiAllocator {
|
||||||
|
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
||||||
|
let ptr = unsafe { GLOBAL_HEAP.alloc(layout) };
|
||||||
|
log::trace!("ACPI alloc: {:?} -> {:p}", layout, ptr);
|
||||||
|
|
||||||
|
if ptr.is_null() {
|
||||||
|
Err(AllocError)
|
||||||
|
} else {
|
||||||
|
unsafe {
|
||||||
|
Ok(NonNull::slice_from_raw_parts(
|
||||||
|
NonNull::new_unchecked(ptr),
|
||||||
|
layout.size(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
|
||||||
|
log::trace!("ACPI dealloc: {:?}, {:?}", ptr, layout);
|
||||||
|
unsafe { GLOBAL_HEAP.dealloc(ptr.as_ptr(), layout) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO don't map memory as device if not necessary
|
||||||
|
pub unsafe fn read_memory<T>(address: PhysicalAddress) -> T {
|
||||||
|
let io =
|
||||||
|
unsafe { DeviceMemoryMapping::map(address, size_of::<T>(), Default::default()).unwrap() };
|
||||||
|
let address = io.address();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
if address % align_of::<T>() == 0 {
|
||||||
|
(address as *const T).read_volatile()
|
||||||
|
} else {
|
||||||
|
(address as *const T).read_unaligned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn write_memory<T>(address: PhysicalAddress, value: T) {
|
||||||
|
let io =
|
||||||
|
unsafe { DeviceMemoryMapping::map(address, size_of::<T>(), Default::default()).unwrap() };
|
||||||
|
let address = io.address();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
if address % align_of::<T>() == 0 {
|
||||||
|
(address as *mut T).write_volatile(value)
|
||||||
|
} else {
|
||||||
|
(address as *mut T).write_unaligned(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@
|
|||||||
use abi::error::Error;
|
use abi::error::Error;
|
||||||
use alloc::{sync::Arc, vec::Vec};
|
use alloc::{sync::Arc, vec::Vec};
|
||||||
use device_api::{device::Device, interrupt::Irq};
|
use device_api::{device::Device, interrupt::Irq};
|
||||||
|
use kernel_arch_x86::ISA_IRQ_OFFSET;
|
||||||
use libk::{
|
use libk::{
|
||||||
config, debug,
|
config, debug,
|
||||||
fs::{devfs, sysfs},
|
fs::{devfs, sysfs},
|
||||||
@ -22,13 +23,6 @@ use crate::fs::{Initrd, INITRD_DATA};
|
|||||||
|
|
||||||
use super::L3;
|
use super::L3;
|
||||||
|
|
||||||
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
|
||||||
pub const ISA_IRQ_OFFSET: u32 = crate::arch::x86_64::ISA_IRQ_OFFSET;
|
|
||||||
|
|
||||||
#[cfg(any(target_arch = "x86", rust_analyzer))]
|
|
||||||
pub const ISA_IRQ_OFFSET: u32 = 0;
|
|
||||||
|
|
||||||
pub mod intrinsics;
|
|
||||||
mod pci;
|
mod pci;
|
||||||
pub mod peripherals;
|
pub mod peripherals;
|
||||||
|
|
||||||
@ -76,13 +70,13 @@ pub fn register_pci_drivers() {
|
|||||||
Some(0x01),
|
Some(0x01),
|
||||||
ygg_driver_ahci::probe,
|
ygg_driver_ahci::probe,
|
||||||
);
|
);
|
||||||
ygg_driver_pci::register_class_driver(
|
// ygg_driver_pci::register_class_driver(
|
||||||
"USB xHCI",
|
// "USB xHCI",
|
||||||
0x0C,
|
// 0x0C,
|
||||||
Some(0x03),
|
// Some(0x03),
|
||||||
Some(0x30),
|
// Some(0x30),
|
||||||
ygg_driver_usb_xhci::probe,
|
// ygg_driver_usb_xhci::probe,
|
||||||
);
|
// );
|
||||||
ygg_driver_pci::register_vendor_driver(
|
ygg_driver_pci::register_vendor_driver(
|
||||||
"Virtio PCI GPU Device",
|
"Virtio PCI GPU Device",
|
||||||
0x1AF4,
|
0x1AF4,
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
|
use kernel_arch_x86::intrinsics::{IoPort, IoPortAccess};
|
||||||
use libk_util::sync::IrqSafeSpinlock;
|
use libk_util::sync::IrqSafeSpinlock;
|
||||||
use ygg_driver_pci::LegacyPciAccess;
|
use ygg_driver_pci::LegacyPciAccess;
|
||||||
|
|
||||||
use crate::arch::x86::intrinsics::IoPortAccess;
|
|
||||||
|
|
||||||
use super::intrinsics::IoPort;
|
|
||||||
|
|
||||||
struct LegacyPciInner {
|
struct LegacyPciInner {
|
||||||
address: IoPort<u32>,
|
address: IoPort<u32>,
|
||||||
data: IoPort<u32>,
|
data: IoPort<u32>,
|
||||||
|
@ -4,13 +4,12 @@ use device_api::{
|
|||||||
device::Device,
|
device::Device,
|
||||||
interrupt::{InterruptHandler, Irq},
|
interrupt::{InterruptHandler, Irq},
|
||||||
};
|
};
|
||||||
use libk::{device::external_interrupt_controller, task::runtime, time};
|
use kernel_arch_x86::{
|
||||||
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
|
||||||
|
|
||||||
use crate::arch::x86::{
|
|
||||||
intrinsics::{IoPort, IoPortAccess},
|
intrinsics::{IoPort, IoPortAccess},
|
||||||
ISA_IRQ_OFFSET,
|
ISA_IRQ_OFFSET,
|
||||||
};
|
};
|
||||||
|
use libk::{device::external_interrupt_controller, task::runtime, time};
|
||||||
|
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
||||||
|
|
||||||
const FREQUENCY: u32 = 1193180;
|
const FREQUENCY: u32 = 1193180;
|
||||||
|
|
||||||
|
@ -9,10 +9,9 @@ use device_api::{
|
|||||||
IrqOptions,
|
IrqOptions,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use kernel_arch_x86::intrinsics::{IoPort, IoPortAccess};
|
||||||
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
||||||
|
|
||||||
use crate::arch::x86::intrinsics::{IoPort, IoPortAccess};
|
|
||||||
|
|
||||||
#[cfg(any(target_arch = "x86", rust_analyzer))]
|
#[cfg(any(target_arch = "x86", rust_analyzer))]
|
||||||
use crate::arch::i686::exception;
|
use crate::arch::i686::exception;
|
||||||
#[cfg(any(target_arch = "x86", rust_analyzer))]
|
#[cfg(any(target_arch = "x86", rust_analyzer))]
|
||||||
|
@ -8,14 +8,14 @@ use device_api::{
|
|||||||
device::Device,
|
device::Device,
|
||||||
interrupt::{InterruptHandler, Irq},
|
interrupt::{InterruptHandler, Irq},
|
||||||
};
|
};
|
||||||
|
use kernel_arch_x86::{
|
||||||
|
intrinsics::{IoPort, IoPortAccess},
|
||||||
|
ISA_IRQ_OFFSET,
|
||||||
|
};
|
||||||
use libk::device::external_interrupt_controller;
|
use libk::device::external_interrupt_controller;
|
||||||
use libk_util::sync::IrqSafeSpinlock;
|
use libk_util::sync::IrqSafeSpinlock;
|
||||||
|
|
||||||
use crate::arch::x86::{
|
use codeset::{CODE_SET_1_00, CODE_SET_1_E0};
|
||||||
intrinsics::{IoPort, IoPortAccess},
|
|
||||||
peripherals::ps2::codeset::{CODE_SET_1_00, CODE_SET_1_E0},
|
|
||||||
ISA_IRQ_OFFSET,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod codeset;
|
mod codeset;
|
||||||
|
|
||||||
|
@ -5,13 +5,12 @@ use device_api::{
|
|||||||
interrupt::{InterruptHandler, Irq},
|
interrupt::{InterruptHandler, Irq},
|
||||||
};
|
};
|
||||||
use kernel_arch::{Architecture, ArchitectureImpl};
|
use kernel_arch::{Architecture, ArchitectureImpl};
|
||||||
use libk::{device::external_interrupt_controller, time};
|
use kernel_arch_x86::{
|
||||||
use libk_util::sync::IrqSafeSpinlock;
|
|
||||||
|
|
||||||
use crate::arch::x86::{
|
|
||||||
intrinsics::{io_wait, IoPort, IoPortAccess},
|
intrinsics::{io_wait, IoPort, IoPortAccess},
|
||||||
ISA_IRQ_OFFSET,
|
ISA_IRQ_OFFSET,
|
||||||
};
|
};
|
||||||
|
use libk::{device::external_interrupt_controller, time};
|
||||||
|
use libk_util::sync::IrqSafeSpinlock;
|
||||||
|
|
||||||
const NMI_DISABLE: u8 = 1 << 7;
|
const NMI_DISABLE: u8 = 1 << 7;
|
||||||
const CMOS_REG_SEC: u8 = 0x00;
|
const CMOS_REG_SEC: u8 = 0x00;
|
||||||
|
@ -5,6 +5,7 @@ use device_api::{
|
|||||||
device::Device,
|
device::Device,
|
||||||
interrupt::{InterruptHandler, Irq},
|
interrupt::{InterruptHandler, Irq},
|
||||||
};
|
};
|
||||||
|
use kernel_arch_x86::intrinsics::{IoPort, IoPortAccess};
|
||||||
use libk::{
|
use libk::{
|
||||||
debug::DebugSink,
|
debug::DebugSink,
|
||||||
device::{external_interrupt_controller, manager::DEVICE_REGISTRY},
|
device::{external_interrupt_controller, manager::DEVICE_REGISTRY},
|
||||||
@ -12,8 +13,6 @@ use libk::{
|
|||||||
};
|
};
|
||||||
use libk_util::sync::IrqSafeSpinlock;
|
use libk_util::sync::IrqSafeSpinlock;
|
||||||
|
|
||||||
use crate::arch::x86::intrinsics::{IoPort, IoPortAccess};
|
|
||||||
|
|
||||||
// Single port
|
// Single port
|
||||||
struct Regs {
|
struct Regs {
|
||||||
dr: IoPort<u8>,
|
dr: IoPort<u8>,
|
||||||
|
@ -1,390 +0,0 @@
|
|||||||
//! x86-64 implementation of ACPI management interfaces
|
|
||||||
use core::{
|
|
||||||
alloc::{AllocError, Allocator, GlobalAlloc, Layout},
|
|
||||||
ptr::NonNull,
|
|
||||||
sync::atomic::Ordering,
|
|
||||||
time::Duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
use ::acpi::{AcpiHandler, AcpiTables, PhysicalMapping};
|
|
||||||
use acpi_system::{
|
|
||||||
AcpiInterruptMethod, AcpiSleepState, AcpiSystem, AcpiSystemError, EventAction, FixedEvent,
|
|
||||||
};
|
|
||||||
use alloc::{boxed::Box, sync::Arc};
|
|
||||||
use device_api::{
|
|
||||||
device::Device,
|
|
||||||
interrupt::{InterruptHandler, IpiDeliveryTarget, IpiMessage, Irq},
|
|
||||||
};
|
|
||||||
use kernel_arch_x86_64::CPU_COUNT;
|
|
||||||
use libk::device::external_interrupt_controller;
|
|
||||||
use libk_mm::{
|
|
||||||
address::{PhysicalAddress, Virtualize},
|
|
||||||
heap::GLOBAL_HEAP,
|
|
||||||
pointer::PhysicalRef,
|
|
||||||
};
|
|
||||||
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
|
|
||||||
use yggdrasil_abi::error::Error;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
arch::{
|
|
||||||
x86_64::{apic::ioapic::ISA_IRQ_OFFSET, SHUTDOWN_FENCE},
|
|
||||||
Platform, PLATFORM,
|
|
||||||
},
|
|
||||||
mem::{read_memory, write_memory},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::intrinsics;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct AcpiAllocator;
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct AcpiHandlerImpl;
|
|
||||||
struct SciHandler;
|
|
||||||
|
|
||||||
static ACPI_SYSTEM: OneTimeInit<IrqSafeSpinlock<AcpiSystem<AcpiHandlerImpl>>> = OneTimeInit::new();
|
|
||||||
|
|
||||||
// impl Device for SciHandler {
|
|
||||||
// fn display_name(&self) -> &'static str {
|
|
||||||
// "ACPI interrupt handler"
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl Device for SciHandler {
|
|
||||||
fn display_name(&self) -> &str {
|
|
||||||
"ACPI SCI Handler"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InterruptHandler for SciHandler {
|
|
||||||
fn handle_irq(self: Arc<Self>, _vector: Option<usize>) -> bool {
|
|
||||||
log::trace!("ACPI SCI received");
|
|
||||||
ACPI_SYSTEM.get().lock().handle_sci();
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Allocator for AcpiAllocator {
|
|
||||||
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
|
||||||
let ptr = unsafe { GLOBAL_HEAP.alloc(layout) };
|
|
||||||
log::trace!("ACPI alloc: {:?} -> {:p}", layout, ptr);
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
|
||||||
Err(AllocError)
|
|
||||||
} else {
|
|
||||||
unsafe {
|
|
||||||
Ok(NonNull::slice_from_raw_parts(
|
|
||||||
NonNull::new_unchecked(ptr),
|
|
||||||
layout.size(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
|
|
||||||
log::trace!("ACPI dealloc: {:?}, {:?}", ptr, layout);
|
|
||||||
GLOBAL_HEAP.dealloc(ptr.as_ptr(), layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl acpi_system::Handler for AcpiHandlerImpl {
|
|
||||||
type MappedSlice = PhysicalRef<'static, [u8]>;
|
|
||||||
|
|
||||||
unsafe fn map_slice(address: u64, length: u64) -> Self::MappedSlice {
|
|
||||||
PhysicalRef::map_slice(
|
|
||||||
PhysicalAddress::from_u64(address),
|
|
||||||
length.try_into().unwrap(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn io_read_u8(port: u16) -> u8 {
|
|
||||||
let value = unsafe { intrinsics::inb(port) };
|
|
||||||
log::trace!("io_read_u8 {:#x} <- {:#x}", port, value);
|
|
||||||
value
|
|
||||||
}
|
|
||||||
|
|
||||||
fn io_read_u16(port: u16) -> u16 {
|
|
||||||
let value = unsafe { intrinsics::inw(port) };
|
|
||||||
log::trace!("io_read_u16 {:#x} <- {:#x}", port, value);
|
|
||||||
value
|
|
||||||
}
|
|
||||||
|
|
||||||
fn io_read_u32(port: u16) -> u32 {
|
|
||||||
let value = unsafe { intrinsics::inl(port) };
|
|
||||||
log::trace!("io_read_u32 {:#x} <- {:#x}", port, value);
|
|
||||||
value
|
|
||||||
}
|
|
||||||
|
|
||||||
fn io_write_u8(port: u16, value: u8) {
|
|
||||||
log::trace!("io_write_u8 {:#x}, {:#x}", port, value);
|
|
||||||
unsafe { intrinsics::outb(port, value) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn io_write_u16(port: u16, value: u16) {
|
|
||||||
log::trace!("io_write_u16 {:#x}, {:#x}", port, value);
|
|
||||||
unsafe { intrinsics::outw(port, value) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn io_write_u32(port: u16, value: u32) {
|
|
||||||
log::trace!("io_write_u32 {:#x}, {:#x}", port, value);
|
|
||||||
unsafe { intrinsics::outl(port, value) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mem_read_u8(address: u64) -> u8 {
|
|
||||||
let value = unsafe { read_memory(PhysicalAddress::from_u64(address)) };
|
|
||||||
log::trace!("mem_read_u8 {:#x} -> {:#x}", address, value);
|
|
||||||
value
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mem_read_u16(address: u64) -> u16 {
|
|
||||||
let value = unsafe { read_memory(PhysicalAddress::from_u64(address)) };
|
|
||||||
log::trace!("mem_read_u16 {:#x} -> {:#x}", address, value);
|
|
||||||
value
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mem_read_u32(address: u64) -> u32 {
|
|
||||||
let value = unsafe { read_memory(PhysicalAddress::from_u64(address)) };
|
|
||||||
log::trace!("mem_read_u32 {:#x} -> {:#x}", address, value);
|
|
||||||
value
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mem_read_u64(address: u64) -> u64 {
|
|
||||||
let value = unsafe { read_memory(PhysicalAddress::from_u64(address)) };
|
|
||||||
log::trace!("mem_read_u64 {:#x} -> {:#x}", address, value);
|
|
||||||
value
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mem_write_u8(address: u64, value: u8) {
|
|
||||||
log::trace!("mem_write_u8 {:#x}, {:#x}", address, value);
|
|
||||||
unsafe { write_memory(PhysicalAddress::from_u64(address), value) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mem_write_u16(address: u64, value: u16) {
|
|
||||||
log::trace!("mem_write_u16 {:#x}, {:#x}", address, value);
|
|
||||||
unsafe { write_memory(PhysicalAddress::from_u64(address), value) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mem_write_u32(address: u64, value: u32) {
|
|
||||||
log::trace!("mem_write_u32 {:#x}, {:#x}", address, value);
|
|
||||||
unsafe { write_memory(PhysicalAddress::from_u64(address), value) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mem_write_u64(address: u64, value: u64) {
|
|
||||||
log::trace!("mem_write_u64 {:#x}, {:#x}", address, value);
|
|
||||||
unsafe { write_memory(PhysicalAddress::from_u64(address), value) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn install_interrupt_handler(irq: u32) -> Result<(), AcpiSystemError> {
|
|
||||||
log::info!("Installing ACPI SCI handler at IRQ #{}", irq);
|
|
||||||
|
|
||||||
let intc = external_interrupt_controller().expect("No external intc");
|
|
||||||
let handler = Arc::new(SciHandler);
|
|
||||||
let irq = Irq::External(irq + ISA_IRQ_OFFSET);
|
|
||||||
|
|
||||||
intc.register_irq(irq, Default::default(), handler).unwrap();
|
|
||||||
intc.enable_irq(irq).unwrap();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stall(_duration: Duration) {
|
|
||||||
// TODO polling_sleep is not yet implemented properly
|
|
||||||
todo!()
|
|
||||||
// util::polling_sleep(duration).ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl aml::Handler for AcpiHandlerImpl {
|
|
||||||
fn read_io_u8(&self, port: u16) -> u8 {
|
|
||||||
<Self as acpi_system::Handler>::io_read_u8(port)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_io_u16(&self, port: u16) -> u16 {
|
|
||||||
<Self as acpi_system::Handler>::io_read_u16(port)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_io_u32(&self, port: u16) -> u32 {
|
|
||||||
<Self as acpi_system::Handler>::io_read_u32(port)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_io_u8(&self, port: u16, value: u8) {
|
|
||||||
<Self as acpi_system::Handler>::io_write_u8(port, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_io_u16(&self, port: u16, value: u16) {
|
|
||||||
<Self as acpi_system::Handler>::io_write_u16(port, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_io_u32(&self, port: u16, value: u32) {
|
|
||||||
<Self as acpi_system::Handler>::io_write_u32(port, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_u8(&self, address: usize) -> u8 {
|
|
||||||
<Self as acpi_system::Handler>::mem_read_u8(address as u64)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_u16(&self, address: usize) -> u16 {
|
|
||||||
<Self as acpi_system::Handler>::mem_read_u16(address as u64)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_u32(&self, address: usize) -> u32 {
|
|
||||||
<Self as acpi_system::Handler>::mem_read_u32(address as u64)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_u64(&self, address: usize) -> u64 {
|
|
||||||
<Self as acpi_system::Handler>::mem_read_u64(address as u64)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_u8(&self, address: usize, value: u8) {
|
|
||||||
<Self as acpi_system::Handler>::mem_write_u8(address as u64, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_u16(&self, address: usize, value: u16) {
|
|
||||||
<Self as acpi_system::Handler>::mem_write_u16(address as u64, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_u32(&self, address: usize, value: u32) {
|
|
||||||
<Self as acpi_system::Handler>::mem_write_u32(address as u64, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_u64(&self, address: usize, value: u64) {
|
|
||||||
<Self as acpi_system::Handler>::mem_write_u64(address as u64, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_pci_u8(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16) -> u8 {
|
|
||||||
0xFF
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_pci_u16(
|
|
||||||
&self,
|
|
||||||
_segment: u16,
|
|
||||||
_bus: u8,
|
|
||||||
_device: u8,
|
|
||||||
_function: u8,
|
|
||||||
_offset: u16,
|
|
||||||
) -> u16 {
|
|
||||||
0xFFFF
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_pci_u32(
|
|
||||||
&self,
|
|
||||||
_segment: u16,
|
|
||||||
_bus: u8,
|
|
||||||
_device: u8,
|
|
||||||
_function: u8,
|
|
||||||
_offset: u16,
|
|
||||||
) -> u32 {
|
|
||||||
0xFFFFFFFF
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_pci_u8(
|
|
||||||
&self,
|
|
||||||
_segment: u16,
|
|
||||||
_bus: u8,
|
|
||||||
_device: u8,
|
|
||||||
_function: u8,
|
|
||||||
_offset: u16,
|
|
||||||
_value: u8,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_pci_u16(
|
|
||||||
&self,
|
|
||||||
_segment: u16,
|
|
||||||
_bus: u8,
|
|
||||||
_device: u8,
|
|
||||||
_function: u8,
|
|
||||||
_offset: u16,
|
|
||||||
_value: u16,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_pci_u32(
|
|
||||||
&self,
|
|
||||||
_segment: u16,
|
|
||||||
_bus: u8,
|
|
||||||
_device: u8,
|
|
||||||
_function: u8,
|
|
||||||
_offset: u16,
|
|
||||||
_value: u32,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_ec_u8(&self, _address: u64) -> u8 {
|
|
||||||
0x00
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_ec_u8(&self, _address: u64, _value: u8) {}
|
|
||||||
|
|
||||||
fn sleep(&self, _duration: Duration) {
|
|
||||||
todo!()
|
|
||||||
// util::polling_sleep(duration).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AcpiHandler for AcpiHandlerImpl {
|
|
||||||
// No actual address space modification is performed
|
|
||||||
unsafe fn map_physical_region<T>(
|
|
||||||
&self,
|
|
||||||
physical_address: usize,
|
|
||||||
size: usize,
|
|
||||||
) -> PhysicalMapping<Self, T> {
|
|
||||||
PhysicalMapping::new(
|
|
||||||
physical_address,
|
|
||||||
NonNull::new_unchecked(
|
|
||||||
PhysicalAddress::from_usize(physical_address).virtualize() as *mut T
|
|
||||||
),
|
|
||||||
size,
|
|
||||||
size,
|
|
||||||
*self,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmap nothing, these addresses are "virtualized" to high address space
|
|
||||||
fn unmap_physical_region<T>(_region: &PhysicalMapping<Self, T>) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Initializes ACPI management
|
|
||||||
#[allow(unused)]
|
|
||||||
pub fn init_acpi(tables: &'static AcpiTables<AcpiHandlerImpl>) -> Result<(), Error> {
|
|
||||||
// TODO currently broken for real HW
|
|
||||||
let mut system = AcpiSystem::new(tables, Box::new(AcpiHandlerImpl)).unwrap();
|
|
||||||
|
|
||||||
system.initialize(AcpiInterruptMethod::Apic).unwrap();
|
|
||||||
|
|
||||||
system
|
|
||||||
.enable_fixed_event(
|
|
||||||
&FixedEvent::POWER_BUTTON,
|
|
||||||
Box::new(|_| {
|
|
||||||
log::info!("Power button was pressed");
|
|
||||||
|
|
||||||
// TODO the correct way would be to
|
|
||||||
// 1. Nicely ask all the processes to quit
|
|
||||||
// 2. Wait for some time
|
|
||||||
// 3. Kill the remaining ones
|
|
||||||
// 4. Halt other cores
|
|
||||||
// 5. Sync filesystem
|
|
||||||
// 6. Do something with the devices
|
|
||||||
// 7. Actually enter the S5 state
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
PLATFORM
|
|
||||||
.send_ipi(IpiDeliveryTarget::OtherCpus, IpiMessage::Shutdown)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
SHUTDOWN_FENCE.signal();
|
|
||||||
SHUTDOWN_FENCE.wait_all(CPU_COUNT.load(Ordering::Acquire));
|
|
||||||
|
|
||||||
log::info!("CPUs are parked, can shutdown now");
|
|
||||||
|
|
||||||
EventAction::EnterSleepState(AcpiSleepState::S5)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
ACPI_SYSTEM.init(IrqSafeSpinlock::new(system));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -9,6 +9,7 @@ use device_api::{
|
|||||||
IrqLevel, IrqOptions, IrqTrigger,
|
IrqLevel, IrqOptions, IrqTrigger,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use kernel_arch_x86::ISA_IRQ_OFFSET;
|
||||||
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIo};
|
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIo};
|
||||||
use libk_util::sync::{spin_rwlock::IrqSafeRwLock, IrqSafeSpinlock};
|
use libk_util::sync::{spin_rwlock::IrqSafeRwLock, IrqSafeSpinlock};
|
||||||
use tock_registers::{
|
use tock_registers::{
|
||||||
@ -16,13 +17,12 @@ use tock_registers::{
|
|||||||
register_structs,
|
register_structs,
|
||||||
registers::{ReadWrite, WriteOnly},
|
registers::{ReadWrite, WriteOnly},
|
||||||
};
|
};
|
||||||
|
use ygg_driver_acpi::AcpiAllocator;
|
||||||
|
|
||||||
use crate::arch::x86_64::{acpi::AcpiAllocator, apic::local::BSP_APIC_ID};
|
use crate::arch::x86_64::apic::local::BSP_APIC_ID;
|
||||||
|
|
||||||
use super::{APIC_EXTERNAL_OFFSET, POPULATED_EXTERNAL_VECTORS};
|
use super::{APIC_EXTERNAL_OFFSET, POPULATED_EXTERNAL_VECTORS};
|
||||||
|
|
||||||
pub const ISA_IRQ_OFFSET: u32 = 1024;
|
|
||||||
|
|
||||||
// IRQ 0 is timer, IRQ 1 reserved (for now?), +32 offset for exception entries
|
// IRQ 0 is timer, IRQ 1 reserved (for now?), +32 offset for exception entries
|
||||||
const IO_APIC_VECTOR_OFFSET: u32 = 32 + APIC_EXTERNAL_OFFSET;
|
const IO_APIC_VECTOR_OFFSET: u32 = 32 + APIC_EXTERNAL_OFFSET;
|
||||||
|
|
||||||
|
@ -3,13 +3,12 @@ use core::{mem::size_of, ops::DerefMut, ptr::null_mut, sync::atomic::Ordering};
|
|||||||
|
|
||||||
use ::acpi::{mcfg::Mcfg, AcpiTables, HpetInfo, InterruptModel};
|
use ::acpi::{mcfg::Mcfg, AcpiTables, HpetInfo, InterruptModel};
|
||||||
use abi::error::Error;
|
use abi::error::Error;
|
||||||
use acpi::{AcpiAllocator, AcpiHandlerImpl};
|
|
||||||
use alloc::{boxed::Box, sync::Arc};
|
use alloc::{boxed::Box, sync::Arc};
|
||||||
use apic::{ioapic::IoApic, local::LocalApic};
|
use apic::{ioapic::IoApic, local::LocalApic};
|
||||||
use device_api::device::Device;
|
use device_api::device::Device;
|
||||||
use kernel_arch_x86::{
|
use kernel_arch_x86::{
|
||||||
cpuid::{self, CpuFeatures, EcxFeatures, EdxFeatures, ExtEdxFeatures},
|
cpuid::{self, CpuFeatures, EcxFeatures, EdxFeatures, ExtEdxFeatures},
|
||||||
gdt,
|
gdt, intrinsics,
|
||||||
};
|
};
|
||||||
use kernel_arch_x86_64::{
|
use kernel_arch_x86_64::{
|
||||||
mem::{
|
mem::{
|
||||||
@ -34,14 +33,14 @@ use libk_mm::{
|
|||||||
phys::{self, reserved::reserve_region, PhysicalMemoryRegion},
|
phys::{self, reserved::reserve_region, PhysicalMemoryRegion},
|
||||||
table::{EntryLevel, EntryLevelExt},
|
table::{EntryLevel, EntryLevelExt},
|
||||||
};
|
};
|
||||||
use libk_util::{sync::SpinFence, OneTimeInit};
|
use libk_util::OneTimeInit;
|
||||||
use yboot_proto::{
|
use yboot_proto::{
|
||||||
v1::{self, AvailableMemoryRegion},
|
v1::{self, AvailableMemoryRegion},
|
||||||
LoadProtocolV1,
|
LoadProtocolV1,
|
||||||
};
|
};
|
||||||
|
use ygg_driver_acpi::{AcpiAllocator, AcpiHandlerImpl, EventAction, FixedEvent};
|
||||||
use ygg_driver_pci::PciBusManager;
|
use ygg_driver_pci::PciBusManager;
|
||||||
|
|
||||||
mod acpi;
|
|
||||||
mod apic;
|
mod apic;
|
||||||
mod boot;
|
mod boot;
|
||||||
mod exception;
|
mod exception;
|
||||||
@ -55,13 +54,7 @@ use crate::{
|
|||||||
|
|
||||||
use self::boot::BootData;
|
use self::boot::BootData;
|
||||||
|
|
||||||
use super::{
|
use super::{x86::InitrdSource, Platform};
|
||||||
x86::{intrinsics, InitrdSource},
|
|
||||||
Platform,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Offset where legacy ISA IRQs are remapped
|
|
||||||
pub const ISA_IRQ_OFFSET: u32 = apic::ioapic::ISA_IRQ_OFFSET;
|
|
||||||
|
|
||||||
/// x86-64 architecture implementation
|
/// x86-64 architecture implementation
|
||||||
pub struct X86_64 {
|
pub struct X86_64 {
|
||||||
@ -71,8 +64,6 @@ pub struct X86_64 {
|
|||||||
fbconsole: OneTimeInit<Arc<FramebufferConsole>>,
|
fbconsole: OneTimeInit<Arc<FramebufferConsole>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
static SHUTDOWN_FENCE: SpinFence = SpinFence::new();
|
|
||||||
|
|
||||||
/// Global x86-64 architecture value
|
/// Global x86-64 architecture value
|
||||||
pub static PLATFORM: X86_64 = X86_64 {
|
pub static PLATFORM: X86_64 = X86_64 {
|
||||||
boot_data: OneTimeInit::new(),
|
boot_data: OneTimeInit::new(),
|
||||||
@ -385,7 +376,18 @@ impl X86_64 {
|
|||||||
let ioapic = IoApic::from_acpi(&apic_info)?;
|
let ioapic = IoApic::from_acpi(&apic_info)?;
|
||||||
register_external_interrupt_controller(ioapic);
|
register_external_interrupt_controller(ioapic);
|
||||||
|
|
||||||
// acpi::init_acpi(acpi).unwrap();
|
if let Err(error) = ygg_driver_acpi::switch_to_acpi(acpi) {
|
||||||
|
log::error!("ACPI initialization error: {error:?}");
|
||||||
|
} else {
|
||||||
|
if let Err(error) =
|
||||||
|
ygg_driver_acpi::add_event_handler(&FixedEvent::POWER_BUTTON, |_| {
|
||||||
|
log::info!("Power button pressed!");
|
||||||
|
EventAction::Nothing
|
||||||
|
})
|
||||||
|
{
|
||||||
|
log::error!("Couldn't set ACPI power button handler: {error:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Ok(mcfg) = acpi.find_table::<Mcfg>() {
|
if let Ok(mcfg) = acpi.find_table::<Mcfg>() {
|
||||||
for entry in mcfg.entries() {
|
for entry in mcfg.entries() {
|
||||||
|
@ -18,11 +18,10 @@ use libk_mm::{
|
|||||||
pointer::PhysicalRefMut,
|
pointer::PhysicalRefMut,
|
||||||
TableAllocatorImpl,
|
TableAllocatorImpl,
|
||||||
};
|
};
|
||||||
|
use ygg_driver_acpi::AcpiAllocator;
|
||||||
|
|
||||||
use crate::arch::x86_64::boot::__x86_64_ap_entry;
|
use crate::arch::x86_64::boot::__x86_64_ap_entry;
|
||||||
|
|
||||||
use super::acpi::AcpiAllocator;
|
|
||||||
|
|
||||||
static AP_BOOTSTRAP_BIN: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/__x86_64_ap_boot.bin"));
|
static AP_BOOTSTRAP_BIN: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/__x86_64_ap_boot.bin"));
|
||||||
|
|
||||||
const AP_STACK_PAGES: usize = 8;
|
const AP_STACK_PAGES: usize = 8;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user