Compare commits

..

1 Commits

Author SHA1 Message Date
alnyan 93a0584605 fuzzy: simple syscall fuzzing tool 2025-08-08 03:47:43 +03:00
38 changed files with 327 additions and 335 deletions
-8
View File
@@ -4,8 +4,6 @@ const EXT_HSM: u64 = 0x48534D;
const EXT_TIME: u64 = 0x54494D45;
const EXT_DBCN: u64 = 0x4442434E;
const EXT_SPI: u64 = 0x735049;
const EXT_SYSTEM_SHUTDOWN: u64 = 0x53525354;
const EXT_SYSTEM_SHUTDOWN_LEGACY: u64 = 0x08;
primitive_enum! {
pub enum Status: i64 {
@@ -110,9 +108,3 @@ pub fn sbi_debug_console_write_byte(byte: u8) {
pub fn sbi_set_timer(next_event: u64) {
unsafe { sbi_do_call(EXT_TIME, 0x00, next_event, 0, 0, 0, 0, 0) }.ok();
}
pub fn sbi_system_shutdown() -> ! {
unsafe { sbi_do_call(EXT_SYSTEM_SHUTDOWN, 0x00, 0, 0, 0, 0, 0, 0) }.ok();
unsafe { sbi_do_call(EXT_SYSTEM_SHUTDOWN_LEGACY, 0x00, 0, 0, 0, 0, 0, 0) }.ok();
unreachable!()
}
+8 -13
View File
@@ -1,8 +1,8 @@
#![feature(allocator_api, never_type)]
#![feature(allocator_api)]
#![no_std]
use acpi::AcpiTables;
use acpi_system::{AcpiInterruptMethod, AcpiSleepState, AcpiSystem};
use acpi_system::{AcpiInterruptMethod, AcpiSystem};
use alloc::boxed::Box;
use libk::error::Error;
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
@@ -45,17 +45,6 @@ pub fn get_pci_route(
.ok()
}
pub fn power_off() -> Result<!, Error> {
let system = ACPI_SYSTEM.get();
unsafe {
system.lock().enter_sleep_state(AcpiSleepState::S5).ok();
loop {
core::arch::asm!("cli; hlt");
}
}
}
/// Initializes ACPI management
pub fn switch_to_acpi(tables: &'static AcpiTables<AcpiHandlerImpl>) -> Result<(), Error> {
// NOTE mostly broken for real HW
@@ -78,6 +67,12 @@ pub fn switch_to_acpi(tables: &'static AcpiTables<AcpiHandlerImpl>) -> Result<()
// // 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));
+7 -5
View File
@@ -1,12 +1,12 @@
use alloc::sync::Arc;
use device_api::{
device::{Device, DeviceInitContext},
interrupt::{InterruptHandler, IrqHandle, IrqVector},
interrupt::{FullIrq, InterruptHandler, IrqVector},
};
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
use libk::{
debug::DebugSink,
device::manager::DEVICE_REGISTRY,
device::{external_interrupt_controller, manager::DEVICE_REGISTRY},
vfs::{Terminal, TerminalInput, TerminalOutput},
};
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIo};
@@ -68,7 +68,7 @@ struct Pl011Inner {
pub struct Pl011 {
inner: OneTimeInit<Arc<Terminal<Pl011Inner>>>,
base: PhysicalAddress,
irq: IrqHandle,
irq: FullIrq,
}
impl Io {
@@ -164,12 +164,14 @@ impl Device for Pl011 {
}
unsafe fn init_irq(self: Arc<Self>) -> Result<(), Error> {
self.irq.register(self.clone())?;
let intc = external_interrupt_controller()?;
intc.register_irq(self.irq.irq, self.irq.options, self.clone())?;
{
let io = self.inner.get().output().io.lock();
io.regs.IMSC.modify(IMSC::RXIM::SET);
}
self.irq.enable()?;
intc.enable_irq(self.irq.irq)?;
Ok(())
}
+6 -5
View File
@@ -8,7 +8,7 @@ use device_api::{
GpioController, GpioInterruptEvent, GpioInterruptMode, GpioPinLevel, PinHandle,
SinglePinDirection,
},
interrupt::{InterruptHandler, IrqHandle, IrqVector},
interrupt::{FullIrq, InterruptHandler, IrqVector},
};
use device_tree::{
driver::{
@@ -17,7 +17,7 @@ use device_tree::{
},
DeviceTreePropertyRead, TProp,
};
use libk::event::signal_gpio_event;
use libk::{device::external_interrupt_controller, event::signal_gpio_event};
use libk_mm::device::DeviceMemoryIo;
use libk_util::{bit::BitField, sync::IrqSafeSpinlock};
use tock_registers::{
@@ -50,7 +50,7 @@ register_structs! {
struct Pl061 {
#[allow(unused)]
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
irq: IrqHandle,
irq: FullIrq,
clocks: Vec<ClockHandle>,
resets: Vec<ResetHandle>,
gpio_events: [AtomicU64; 8],
@@ -69,8 +69,9 @@ impl Device for Pl061 {
}
unsafe fn init_irq(self: Arc<Self>) -> Result<(), Error> {
self.irq.register(self.clone())?;
self.irq.enable()?;
let intc = external_interrupt_controller()?;
intc.register_irq(self.irq.irq, self.irq.options, self.clone())?;
intc.enable_irq(self.irq.irq)?;
Ok(())
}
+6 -5
View File
@@ -2,12 +2,12 @@ use alloc::sync::Arc;
use device_api::{
clock::ClockHandle,
device::{Device, DeviceInitContext},
interrupt::{InterruptHandler, IrqHandle, IrqVector},
interrupt::{FullIrq, InterruptHandler, IrqVector},
};
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
use libk::{
debug::DebugSink,
device::manager::DEVICE_REGISTRY,
device::{external_interrupt_controller, manager::DEVICE_REGISTRY},
vfs::{Terminal, TerminalInput, TerminalOutput},
};
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIo};
@@ -61,7 +61,7 @@ struct Inner {
/// Broadcom 283x mini-UART driver
pub struct Bcm2835AuxUart {
base: PhysicalAddress,
irq: IrqHandle,
irq: FullIrq,
clock: ClockHandle,
inner: OneTimeInit<Arc<Terminal<Inner>>>,
}
@@ -171,8 +171,9 @@ impl Device for Bcm2835AuxUart {
}
unsafe fn init_irq(self: Arc<Self>) -> Result<(), Error> {
self.irq.register(self.clone())?;
self.irq.enable()?;
let intc = external_interrupt_controller()?;
intc.register_irq(self.irq.irq, self.irq.options, self.clone())?;
intc.enable_irq(self.irq.irq)?;
let inner = self.inner.get().output();
let regs = inner.regs.lock();
+6 -4
View File
@@ -2,7 +2,7 @@ use alloc::sync::Arc;
use device_api::{
device::{Device, DeviceInitContext},
gpio::{GpioController, GpioInterruptEvent, PinHandle},
interrupt::{InterruptHandler, IrqHandle, IrqVector},
interrupt::{FullIrq, InterruptHandler, IrqVector},
};
use device_tree::{
driver::{
@@ -11,6 +11,7 @@ use device_tree::{
},
DeviceTreePropertyRead, TProp,
};
use libk::device::external_interrupt_controller;
use libk_mm::device::DeviceMemoryIo;
use libk_util::sync::IrqSafeSpinlock;
use tock_registers::{
@@ -68,7 +69,7 @@ register_structs! {
struct Bcm2711Gpio {
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
#[allow(unused)]
irqs: [IrqHandle; 2],
irqs: [FullIrq; 2],
}
impl Regs {
@@ -141,9 +142,10 @@ impl Device for Bcm2711Gpio {
regs.configure_pin_interrupts(pin, false, false, false, false);
}
let intc = external_interrupt_controller()?;
for irq in self.irqs.iter() {
irq.register(self.clone())?;
irq.enable()?;
intc.register_irq(irq.irq, irq.options, self.clone())?;
intc.enable_irq(irq.irq)?;
}
Ok(())
+4 -4
View File
@@ -2,8 +2,8 @@ use alloc::{sync::Arc, vec::Vec};
use device_api::{
device::{Device, DeviceInitContext},
interrupt::{
ExternalInterruptController, FixedInterruptTable, InterruptHandler, InterruptTable, Irq,
IrqHandle, IrqOptions, IrqVector,
ExternalInterruptController, FixedInterruptTable, FullIrq, InterruptHandler,
InterruptTable, Irq, IrqOptions, IrqVector,
},
};
use device_tree::{
@@ -261,9 +261,9 @@ impl Device for Plic {
}
impl DeviceTreeInterruptController for Plic {
fn map_interrupt(&self, property: &TProp, offset: usize) -> Option<IrqHandle> {
fn map_interrupt(&self, property: &TProp, offset: usize) -> Option<FullIrq> {
let num = property.read_cell(offset, 1)?;
Some(IrqHandle {
Some(FullIrq {
irq: Irq::External(num as _),
options: IrqOptions::default(),
})
+7 -4
View File
@@ -8,13 +8,14 @@ use device_api::{
clock::{ClockHandle, ResetHandle},
device::{Device, DeviceInitContext},
dma::DmaAllocator,
interrupt::{InterruptHandler, IrqHandle, IrqVector},
interrupt::{FullIrq, InterruptHandler, IrqVector},
};
use device_tree::driver::{
device_tree_driver, util::read_mac_address, InitSequence, Node, ProbeContext,
};
use futures_util::task::AtomicWaker;
use libk::{
device::external_interrupt_controller,
dma::DmaBuffer,
error::Error,
task::runtime::{self, psleep, pwait},
@@ -67,7 +68,7 @@ struct Stmmac {
rst_stmmaceth: ResetHandle,
rst_ahb: ResetHandle,
irq: IrqHandle,
irq: FullIrq,
softirq_events: BitmapEvent<AtomicWaker>,
inner: OneTimeInit<Inner>,
@@ -183,7 +184,9 @@ impl Device for Stmmac {
}
let dma = self.dma.init(cx.dma_allocator.clone());
self.irq.register(self.clone())?;
let intc = external_interrupt_controller()?;
intc.register_irq(self.irq.irq, self.irq.options, self.clone())?;
let tx_ring_capacity = 32;
let rx_ring_capacity = 32;
@@ -347,7 +350,7 @@ impl Device for Stmmac {
ygg_driver_net_core::register_interface(NetworkInterfaceType::Ethernet, self.clone());
self.iface_id.init(iface.id());
self.irq.enable()?;
intc.enable_irq(self.irq.irq)?;
let p = self.clone();
runtime::spawn(async move { p.softirq().await })?;
+2 -13
View File
@@ -3,11 +3,10 @@ use yggdrasil_abi::error::Error;
use crate::device::Device;
#[derive(Clone)]
pub struct IrqHandle {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FullIrq {
pub irq: Irq,
pub options: IrqOptions,
pub intc: Arc<dyn ExternalInterruptController>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -155,16 +154,6 @@ pub struct FixedInterruptTable<const N: usize> {
rows: [Option<Arc<dyn InterruptHandler>>; N],
}
impl IrqHandle {
pub fn register(&self, handler: Arc<dyn InterruptHandler>) -> Result<(), Error> {
self.intc.register_irq(self.irq, self.options, handler)
}
pub fn enable(&self) -> Result<(), Error> {
self.intc.enable_irq(self.irq)
}
}
impl<const N: usize> FixedInterruptTable<N> {
pub const fn new() -> Self {
Self {
@@ -3,7 +3,7 @@ use alloc::sync::Arc;
use device_api::{
clock::{ClockHandle, ResetHandle},
gpio::PinHandle,
interrupt::IrqHandle,
interrupt::FullIrq,
};
use fdt_rs::spec::Phandle;
@@ -83,14 +83,14 @@ pub fn map_interrupt_at(
interrupt_controller: &Arc<Node>,
property: &TProp,
offset: usize,
) -> Option<IrqHandle> {
) -> Option<FullIrq> {
let interrupt_controller = interrupt_controller.interrupt_controller.try_get()?;
interrupt_controller.clone().map_interrupt(property, offset)
interrupt_controller.map_interrupt(property, offset)
}
/// Same as [map_interrupt_at], but uses a phandle to address the `interrupt-controller` node
/// and a scaled `index`.
pub fn map_interrupt(phandle: Phandle, property: &TProp, index: usize) -> Option<IrqHandle> {
pub fn map_interrupt(phandle: Phandle, property: &TProp, index: usize) -> Option<FullIrq> {
let interrupt_controller = lookup_phandle(phandle, true)?;
let interrupt_cells = interrupt_controller.self_interrupt_cells()?;
map_interrupt_at(&interrupt_controller, property, index * interrupt_cells)
+2 -2
View File
@@ -7,7 +7,7 @@ use device_api::{
clock::{ClockHandle, ResetHandle},
device::Device,
gpio::PinHandle,
interrupt::{ExternalInterruptController, IrqHandle},
interrupt::{ExternalInterruptController, FullIrq},
};
use libk::error::Error;
@@ -25,7 +25,7 @@ pub trait Driver: Sync {
pub trait DeviceTreeInterruptController {
/// Reads interrupt information from `property` at given `offset` and maps it to
/// the interrupt used by the controller
fn map_interrupt(self: Arc<Self>, property: &TProp, offset: usize) -> Option<IrqHandle>;
fn map_interrupt(&self, property: &TProp, offset: usize) -> Option<FullIrq>;
/// Returns the [ExternalInterruptController] implementor of this node
fn as_interrupt_controller(self: Arc<Self>) -> Arc<dyn ExternalInterruptController>;
+3 -3
View File
@@ -10,7 +10,7 @@ use device_api::{
clock::{ClockController, ClockHandle, ResetHandle},
device::{Device, DeviceInitContext},
gpio::PinHandle,
interrupt::{ExternalInterruptController, IrqHandle, MessageInterruptController},
interrupt::{ExternalInterruptController, FullIrq, MessageInterruptController},
};
use fdt_rs::spec::Phandle;
use libk::dma::DummyDmaAllocator;
@@ -410,7 +410,7 @@ impl Node {
/// Reads interrupt information from `interrupts[index]` property, mapped by the node's
/// `interrupt-parent`.
pub fn interrupt(&self, index: usize) -> Option<IrqHandle> {
pub fn interrupt(&self, index: usize) -> Option<FullIrq> {
let interrupts = self.property("interrupts")?;
let phandle = self.interrupt_parent?;
map_interrupt(phandle, &interrupts, index)
@@ -418,7 +418,7 @@ impl Node {
/// Same as [Node::interrupt], but allows specifying other property to read the information
/// from.
pub fn interrupt_from(&self, property: &TProp, index: usize) -> Option<IrqHandle> {
pub fn interrupt_from(&self, property: &TProp, index: usize) -> Option<FullIrq> {
let phandle = self.interrupt_parent?;
map_interrupt(phandle, property, index)
}
+3 -2
View File
@@ -3,7 +3,7 @@
use alloc::sync::Arc;
use device_api::{
gpio::{GpioPinConfig, GpioPinLevel, InputPinBias, OutputPinBias},
interrupt::{IrqHandle, MessageInterruptController},
interrupt::{FullIrq, MessageInterruptController},
};
use fdt_rs::prelude::PropReader;
use yggdrasil_abi::net::MacAddress;
@@ -44,6 +44,7 @@ pub struct GenericPinctrlConfig {
}
/// Represents an entry in a PCIe-controller's `interrupt-map` field
#[derive(Debug)]
pub struct PcieInterruptEntry {
/// PCI address bus
pub bus: u8,
@@ -56,7 +57,7 @@ pub struct PcieInterruptEntry {
/// Destination interrupt controller
pub interrupt_controller: Arc<Node>,
/// Destination IRQ options
pub irq: IrqHandle,
pub irq: FullIrq,
}
/// Represents a single PCI address (Requester ID for a MSI(-x))
+1 -1
View File
@@ -243,7 +243,7 @@ fn validate_user_align_size(addr: usize, layout: &Layout) -> Result<(), Error> {
return Err(Error::InvalidArgument);
}
if addr + layout.size() > KERNEL_VIRT_OFFSET {
todo!();
return Err(Error::InvalidArgument);
}
Ok(())
-1
View File
@@ -310,7 +310,6 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) {
}
fn irq_common() {
// TODO some concept of "root" interrupt controller
external_interrupt_controller()
.unwrap()
.handle_pending_irqs();
+7 -9
View File
@@ -8,9 +8,9 @@ use alloc::sync::Arc;
use device_api::{
device::{Device, DeviceInitContext},
interrupt::{
ExternalInterruptController, FixedInterruptTable, InterruptHandler, InterruptTable,
IpiDeliveryTarget, IpiMessage, Irq, IrqHandle, IrqLevel, IrqOptions, IrqTrigger, IrqVector,
LocalInterruptController,
ExternalInterruptController, FixedInterruptTable, FullIrq, InterruptHandler,
InterruptTable, IpiDeliveryTarget, IpiMessage, Irq, IrqLevel, IrqOptions, IrqTrigger,
IrqVector, LocalInterruptController,
},
};
use device_tree::{
@@ -141,9 +141,8 @@ impl ExternalInterruptController for Gic {
gicc.clear_irq(irq_number);
if irq_number == IPI_VECTOR as usize {
let ipi = Cpu::local().get_ipi();
AArch64::handle_ipi(ipi);
return;
// TODO pop entry
crate::panic::panic_secondary();
}
if irq_number < GIC_PPI_START as usize {
@@ -204,7 +203,7 @@ impl LocalInterruptController for Gic {
}
impl DeviceTreeInterruptController for Gic {
fn map_interrupt(self: Arc<Self>, property: &TProp, offset: usize) -> Option<IrqHandle> {
fn map_interrupt(&self, property: &TProp, offset: usize) -> Option<FullIrq> {
// IRQ_TYPE_NONE - 0
// IRQ_TYPE_EDGE_RISING - 1
// IRQ_TYPE_EDGE_FALLING - 2
@@ -230,10 +229,9 @@ impl DeviceTreeInterruptController for Gic {
_ => return None,
};
Some(IrqHandle {
Some(FullIrq {
irq,
options: IrqOptions { trigger, level },
intc: self.clone(),
})
}
+3 -54
View File
@@ -5,15 +5,14 @@ use core::sync::atomic::{self, Ordering};
use aarch64_cpu::registers::{CNTP_CTL_EL0, CNTP_TVAL_EL0};
use alloc::sync::Arc;
use device_api::{
interrupt::{IpiDeliveryTarget, IpiMessage, Irq, LocalInterruptController},
interrupt::{Irq, LocalInterruptController},
ResetDevice,
};
use device_tree::{
driver::{unflatten_device_tree, InitSequence},
DeviceTree, DeviceTreeNodeExt,
};
use kernel_arch::Architecture;
use kernel_arch_aarch64::{mem, ArchitectureImpl, PerCpuData, CPU_COUNT};
use kernel_arch_aarch64::{mem, ArchitectureImpl, PerCpuData};
use libk::{arch::Cpu, config, debug, device::external_interrupt_controller, error::Error};
use libk_mm::{
address::PhysicalAddress,
@@ -21,7 +20,7 @@ use libk_mm::{
pointer::PhysicalRef,
table::EntryLevelExt,
};
use libk_util::{sync::SpinFence, OneTimeInit};
use libk_util::OneTimeInit;
use tock_registers::interfaces::Writeable;
use ygg_driver_pci::PciBusManager;
@@ -29,7 +28,6 @@ use crate::{
arch::{aarch64::gic::Gic, Platform},
device::{power::arm_psci::Psci, MACHINE_NAME},
fs::{Initrd, INITRD_DATA},
panic,
util::call_init_array,
};
@@ -70,8 +68,6 @@ impl<const SIZE: usize> BootStack<SIZE> {
}
}
static SHUTDOWN_FENCE: SpinFence = SpinFence::new();
impl Platform for AArch64 {
unsafe fn start_application_processors(&self) {
if let Some(compatible) = self.machine_compatible.try_get() {
@@ -100,18 +96,6 @@ impl Platform for AArch64 {
psci.reset()
}
}
unsafe fn power_off(&self) -> Result<!, Error> {
Self::halt_aps()?;
if let Some(psci) = self.psci.try_get() {
log::info!("Powering off");
psci.power_off()
} else {
log::warn!("No power off method, halting");
ArchitectureImpl::halt();
}
}
}
impl AArch64 {
@@ -119,41 +103,6 @@ impl AArch64 {
GIC.init(gic);
}
fn handle_ipi(ipi: Option<IpiMessage>) {
let Some(ipi) = ipi else {
log::warn!("Spurious IPI received, assuming panic");
panic::panic_secondary();
};
match ipi {
IpiMessage::Panic => panic::panic_secondary(),
IpiMessage::Shutdown => Self::secondary_halt_handler(),
}
}
fn secondary_halt_handler() {
log::info!("CPU halted");
SHUTDOWN_FENCE.signal();
ArchitectureImpl::halt();
}
unsafe fn halt_aps() -> Result<(), Error> {
let ap_count = CPU_COUNT.load(Ordering::Acquire) - 1;
if ap_count > 0 {
if let Some(gic) = GIC.try_get() {
gic.send_ipi(IpiDeliveryTarget::OtherCpus, IpiMessage::Shutdown)?;
SHUTDOWN_FENCE.wait_all(ap_count);
Ok(())
} else {
log::warn!("No way to handle secondary CPUs");
Err(Error::NotImplemented)
}
} else {
Ok(())
}
}
#[inline(never)]
unsafe fn init_memory_management(
&'static self,
+8 -6
View File
@@ -7,16 +7,16 @@ use abi::{error::Error, time::NANOSECONDS_IN_SECOND};
use alloc::sync::Arc;
use device_api::{
device::{Device, DeviceInitContext},
interrupt::{InterruptHandler, IrqHandle, IrqVector},
interrupt::{FullIrq, InterruptHandler, IrqVector},
};
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
use kernel_arch::task::Scheduler;
use libk::{arch::Cpu, task::runtime, time};
use libk::{arch::Cpu, device::external_interrupt_controller, task::runtime, time};
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
/// ARM Generic Timer driver
pub struct ArmTimer {
irq: IrqHandle,
irq: FullIrq,
}
/// ARM timer tick interval (in some time units?)
@@ -63,12 +63,14 @@ impl Device for ArmTimer {
unsafe fn init_irq(self: Arc<Self>) -> Result<(), Error> {
log::info!("ARM Generic Timer frequency={}Hz", CNTFRQ_EL0.get());
self.irq.register(self.clone())?;
let intc = external_interrupt_controller()?;
intc.register_irq(self.irq.irq, self.irq.options, self.clone())?;
CNTP_CTL_EL0.modify(CNTP_CTL_EL0::IMASK::CLEAR);
CNTP_TVAL_EL0.set(TICK_INTERVAL);
self.irq.enable()?;
intc.enable_irq(self.irq.irq)?;
Ok(())
}
@@ -80,7 +82,7 @@ impl ArmTimer {
/// # Safety
///
/// The caller must ensure the function has not been called before.
pub const unsafe fn new(irq: IrqHandle) -> Self {
pub const unsafe fn new(irq: FullIrq) -> Self {
Self { irq }
}
}
-14
View File
@@ -1,6 +1,5 @@
//! Provides architecture/platform-specific implementation details
use abi::error::Error;
use kernel_arch::{Architecture, ArchitectureImpl};
#[cfg(any(target_arch = "aarch64", rust_analyzer))]
@@ -52,19 +51,6 @@ pub trait Platform {
}
}
/// Performs full system powerdown.
///
/// # Safety
///
/// The caller must ensure it is actually safe to power down, i.e. no critical processes will be
/// aborted and no data will be lost.
unsafe fn power_off(&self) -> Result<!, Error> {
ArchitectureImpl::set_interrupt_mask(true);
loop {
ArchitectureImpl::wait_for_interrupt();
}
}
// /// Adds a reset device to the system
// fn register_reset_device(&self, reset: Arc<dyn ResetDevice>) -> Result<(), Error> {
// Err(Error::NotImplemented)
+1 -5
View File
@@ -11,7 +11,7 @@ use kernel_arch::{Architecture, ArchitectureImpl};
use kernel_arch_riscv64::{
mem,
registers::{SIE, SSTATUS},
sbi, PerCpuData,
PerCpuData,
};
use libk::{arch::Cpu, config};
use libk_mm::{
@@ -51,10 +51,6 @@ impl Platform for Riscv64 {
ArchitectureImpl::halt();
}
unsafe fn power_off(&self) -> Result<!, Error> {
sbi::sbi_system_shutdown()
}
unsafe fn start_application_processors(&self) {
// TODO asymmetric systems with different hart types are not yet supported.
// e.g., in JH7110 there're two different types of cores
+2 -4
View File
@@ -11,8 +11,6 @@ use libk::{
};
use static_assertions::{const_assert, const_assert_eq};
use crate::arch::x86_64::X86_64;
use super::exception;
pub mod ioapic;
@@ -117,8 +115,8 @@ unsafe extern "C" fn dummy_irq_handler() {
}
unsafe extern "C" fn ipi_handler() {
let ipi = Cpu::local().get_ipi();
X86_64::handle_ipi(ipi);
let cpu = Cpu::local();
todo!("Processor {} received an IPI", cpu.id());
}
global_asm!(
+3 -9
View File
@@ -4,12 +4,12 @@ use core::{arch::global_asm, mem::size_of};
use abi::{bitflags, primitive_enum, process::Signal};
use kernel_arch_x86::registers::{CR2, CR3};
use kernel_arch_x86_64::context::ExceptionFrame;
use libk::{arch::Cpu, task::thread::Thread};
use libk::task::thread::Thread;
use libk_mm::PageFaultKind;
use libk_util::sync::spin_rwlock::IrqSafeRwLock;
use tock_registers::interfaces::Readable;
use crate::arch::x86_64::{apic, X86_64};
use crate::arch::x86_64::apic;
primitive_enum! {
enum ExceptionKind: u64 {
@@ -231,13 +231,7 @@ extern "C" fn __x86_64_exception_handler(frame: *mut ExceptionFrame) {
}
extern "C" fn __x86_64_nmi_handler() -> ! {
let ipi = Cpu::local().get_ipi();
if let Some(ipi) = ipi {
X86_64::handle_ipi(Some(ipi));
unreachable!();
} else {
panic!("Spurious/unknown NMI received");
}
crate::panic::panic_secondary();
}
/// Initializes the interrupt descriptor table for the given CPU.
+5 -54
View File
@@ -1,20 +1,16 @@
//! x86-64 architecture implementation
use core::{ptr::null_mut, sync::atomic::Ordering};
use core::ptr::null_mut;
use abi::error::Error;
use acpi::{mcfg::Mcfg, AcpiTables, HpetInfo, InterruptModel};
use alloc::sync::Arc;
use device_api::{
device::Device,
interrupt::{IpiDeliveryTarget, IpiMessage},
};
use kernel_arch::{Architecture, ArchitectureImpl};
use device_api::device::Device;
use kernel_arch_x86::{
cpuid::{self, CpuFeatures, EcxFeatures, EdxFeatures, ExtEdxFeatures},
gdt,
};
use kernel_arch_x86_64::{mem, LocalApicInterface, PerCpuData, CPU_COUNT};
use kernel_arch_x86_64::{mem, LocalApicInterface, PerCpuData};
use libk::{
arch::Cpu,
config, debug,
@@ -31,10 +27,7 @@ use libk_mm::{
pointer::PhysicalRef,
table::EntryLevel,
};
use libk_util::{
sync::{IrqGuard, SpinFence},
OneTimeInit,
};
use libk_util::OneTimeInit;
use yboot_proto::{
v1::{self, AvailableMemoryRegion},
LoadProtocolV1,
@@ -52,7 +45,6 @@ use crate::{
Platform,
},
device::display::linear_fb::LinearFramebuffer,
panic,
util::call_init_array,
};
@@ -80,9 +72,7 @@ pub static PLATFORM: X86_64 = X86_64 {
fbconsole: OneTimeInit::new(),
};
static SHUTDOWN_FENCE: SpinFence = SpinFence::new();
//
impl Platform for X86_64 {
unsafe fn start_application_processors(&self) {
if let Some(acpi) = self.acpi.try_get() {
@@ -97,42 +87,9 @@ impl Platform for X86_64 {
smp::start_ap_cores(&pinfo);
}
}
unsafe fn power_off(&self) -> Result<!, Error> {
let _guard = IrqGuard::acquire();
let ap_count = CPU_COUNT.load(Ordering::Acquire) - 1;
if ap_count > 0 {
self.send_ipi(IpiDeliveryTarget::OtherCpus, IpiMessage::Shutdown)?;
SHUTDOWN_FENCE.wait_all(ap_count);
}
ygg_driver_acpi::power_off()
}
}
impl X86_64 {
fn handle_ipi(ipi: Option<IpiMessage>) {
let Some(ipi) = ipi else {
log::warn!("Spurious IPI received, assuming panic");
panic::panic_secondary();
};
match ipi {
IpiMessage::Shutdown => {
log::info!("Core halted");
SHUTDOWN_FENCE.signal();
ArchitectureImpl::halt()
}
IpiMessage::Panic => panic::panic_secondary(),
}
}
fn send_ipi(&self, target: IpiDeliveryTarget, message: IpiMessage) -> Result<(), Error> {
let cpu = Cpu::local();
cpu.local_apic.send_ipi(target, message)
}
fn set_boot_data(&self, data: BootData) {
match data {
BootData::YBoot(data) => {
@@ -239,12 +196,6 @@ impl X86_64 {
call_init_array();
x86::init_platform_devices(early);
extern "C" {
static __kernel_start: u8;
}
log::info!("Load base: {:p}", &raw const __kernel_start);
}
Ok(())
-7
View File
@@ -61,7 +61,6 @@ impl ResetDevice for Psci {
impl Psci {
const SYSTEM_RESET: u32 = 0x84000009;
const SYSTEM_OFF: u32 = 0x84000008;
#[inline]
unsafe fn call(&self, mut x0: u64, x1: u64, x2: u64, x3: u64) -> u64 {
@@ -75,12 +74,6 @@ impl Psci {
}
x0
}
/// Shut down the system
pub unsafe fn power_off(&self) -> Result<!, Error> {
self.call(Self::SYSTEM_OFF as _, 0, 0, 0);
unreachable!()
}
}
device_tree_driver! {
+5 -4
View File
@@ -3,7 +3,7 @@ use abi::{error::Error, io::TerminalOptions};
use alloc::sync::Arc;
use device_api::{
device::{Device, DeviceInitContext},
interrupt::{InterruptHandler, IrqHandle, IrqVector},
interrupt::{FullIrq, InterruptHandler, IrqVector},
};
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
use libk::{
@@ -79,7 +79,7 @@ struct Inner {
pub struct Ns16550a {
inner: OneTimeInit<Arc<Terminal<Inner>>>,
base: PhysicalAddress,
irq: IrqHandle,
irq: FullIrq,
}
impl Io {
@@ -135,8 +135,9 @@ impl Device for Ns16550a {
}
unsafe fn init_irq(self: Arc<Self>) -> Result<(), Error> {
self.irq.register(self.clone())?;
self.irq.enable()?;
let intc = external_interrupt_controller()?;
intc.register_irq(self.irq.irq, self.irq.options, self.clone())?;
intc.enable_irq(self.irq.irq)?;
let io = self.inner.get().output().io.lock();
io.regs.IER.modify(IER::RDR::SET);
Ok(())
+5 -4
View File
@@ -4,7 +4,7 @@ use alloc::sync::Arc;
use device_api::{
clock::{ClockHandle, Hertz, ResetHandle},
device::{Device, DeviceInitContext},
interrupt::{InterruptHandler, IrqHandle, IrqVector},
interrupt::{FullIrq, InterruptHandler, IrqVector},
};
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
use libk::{
@@ -110,7 +110,7 @@ struct Inner {
/// Synopsys DesignWare 8250 UART
pub struct DwUart {
base: PhysicalAddress,
irq: IrqHandle,
irq: FullIrq,
clk_baud: ClockHandle,
#[allow(unused)]
clk_apb: Option<ClockHandle>,
@@ -241,8 +241,9 @@ impl Device for DwUart {
}
unsafe fn init_irq(self: Arc<Self>) -> Result<(), Error> {
self.irq.register(self.clone())?;
self.irq.enable()?;
let intc = external_interrupt_controller()?;
intc.register_irq(self.irq.irq, Default::default(), self.clone())?;
intc.enable_irq(self.irq.irq)?;
let output = self.inner.get().output();
let io = output.io.lock();
+2 -15
View File
@@ -16,7 +16,7 @@ use abi::{
option::OptionValue,
path::Path,
process::{ExecveOptions, ProcessId},
system::{self, SystemControlVariant, SystemInfoVariant},
system::{self, SystemInfoVariant},
time::{ClockType, SystemTime},
};
use libk::{
@@ -26,10 +26,7 @@ use libk::{
};
use libk_mm::phys;
use crate::{
arch::{Platform, PLATFORM},
fs,
};
use crate::fs;
use super::run_with_io;
@@ -89,16 +86,6 @@ pub(crate) fn set_clock(ty: ClockType, value: &SystemTime) -> Result<(), Error>
}
}
pub(crate) fn system_control(option: u32, value: &mut [u8], size: usize) -> Result<usize, Error> {
let _ = (value, size);
let option = SystemControlVariant::try_from(option)?;
match option {
SystemControlVariant::PowerOff => {
unsafe { PLATFORM.power_off() }?;
}
}
}
pub(crate) fn get_system_info(option: u32, buffer: &mut [u8]) -> Result<usize, Error> {
let option = SystemInfoVariant::try_from(option)?;
match option {
-1
View File
@@ -80,7 +80,6 @@ syscall unmount(opts: &UnmountOptions) -> Result<()>;
syscall load_module(path: &str) -> Result<()>;
syscall filesystem_control(fd: Option<RawFd>, option: u32, value: &mut [u8], len: usize) -> Result<usize>;
syscall system_control(option: u32, value: &mut [u8], len: usize) -> Result<usize>;
syscall get_system_info(option: u32, value: &mut [u8]) -> Result<usize>;
-8
View File
@@ -21,14 +21,6 @@ option_group!(
}
);
request_group!(
#[doc = "Common system controls"]
pub enum SystemControlVariant<'de> {
#[doc = "Power down the system"]
0x1000: PowerOff((), ()),
}
);
abi_serde::impl_struct_serde!(
SystemMemoryStats: [total_usable_pages, allocated_pages, free_pages, page_size]
);
+1 -14
View File
@@ -1,10 +1,7 @@
//! System-related parameters
pub use abi::system::*;
use abi::{
error::Error,
option::{OptionValue, RequestValue},
};
use abi::{error::Error, option::OptionValue};
/// Helper macro for [get_system_info]
pub macro get_system_info($variant_ty:ty) {{
@@ -17,13 +14,3 @@ pub fn get_system_info<'de, T: OptionValue<'de>>(buffer: &'de mut [u8]) -> Resul
let len = unsafe { crate::sys::get_system_info(T::VARIANT.into(), buffer) }?;
T::load(&buffer[..len])
}
/// Performs an operation on the system, like power management, reset etc
pub fn system_control<'de, T: RequestValue<'de>>(
buffer: &'de mut [u8],
request: &T::Request,
) -> Result<T::Response, Error> {
let len = T::store_request(request, buffer)?;
let len = unsafe { crate::sys::system_control(T::VARIANT.into(), buffer, len) }?;
T::load_response(&buffer[..len])
}
+24
View File
@@ -901,6 +901,12 @@ dependencies = [
"zeroize",
]
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "elf"
version = "0.7.4"
@@ -1089,6 +1095,15 @@ dependencies = [
"slab",
]
[[package]]
name = "fuzzy"
version = "0.1.0"
dependencies = [
"itertools",
"rand",
"runtime",
]
[[package]]
name = "generic-array"
version = "0.14.7"
@@ -1410,6 +1425,15 @@ version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.15"
+1
View File
@@ -17,6 +17,7 @@ members = [
"netutils",
"sysutils",
"tools/crypt",
"tools/fuzzy",
"tools/init",
"tools/md2txt",
"tools/ntpc",
-11
View File
@@ -33,9 +33,6 @@ yggdrasil-abi.workspace = true
yggdrasil-rt.workspace = true
runtime.workspace = true
[dev-dependencies]
runtime.workspace = true
[lib]
path = "src/lib.rs"
@@ -44,14 +41,6 @@ path = "src/lib.rs"
name = "mount"
path = "src/mount.rs"
[[bin]]
name = "poweroff"
path = "src/poweroff.rs"
[[bin]]
name = "reboot"
path = "src/reboot.rs"
[[bin]]
name = "chroot"
path = "src/chroot.rs"
-15
View File
@@ -1,15 +0,0 @@
#![feature(rustc_private)]
use std::{io, process::ExitCode};
use runtime::{abi::system, rt::system::system_control};
fn main() -> ExitCode {
if let Err(error) = system_control::<system::PowerOff>(&mut [], &()) {
let error = io::Error::from(error);
eprintln!("{error}");
ExitCode::FAILURE
} else {
ExitCode::SUCCESS
}
}
-1
View File
@@ -1 +0,0 @@
fn main() {}
+12
View File
@@ -0,0 +1,12 @@
[package]
name = "fuzzy"
version = "0.1.0"
edition = "2021"
[dependencies]
itertools = "0.14.0"
rand.workspace = true
runtime.workspace = true
[lints]
workspace = true
+164
View File
@@ -0,0 +1,164 @@
#![feature(rustc_private)]
use itertools::Itertools;
use rand::Rng;
use runtime::abi::SyscallFunction;
enum Argument {
Fd,
OptionFd,
Path,
AccessMode,
BytesRef,
BytesMut,
FileSize,
Enum(usize),
Number(usize, usize),
}
struct Definition {
name: &'static str,
number: usize,
args: &'static [Argument],
}
const fn syscall(
func: SyscallFunction,
name: &'static str,
args: &'static [Argument],
) -> Definition {
Definition {
name,
number: func as _,
args,
}
}
const DEFS: &[Definition] = const {
use Argument::*;
&[
// syscall get_random(buffer: &mut [u8]);
syscall(SyscallFunction::GetRandom, "get_random", &[BytesMut]),
// syscall get_clock(clock: ClockType, out: &mut MaybeUninit<SystemTime>) -> Result<()>;
// syscall set_clock(clock: ClockType, value: &SystemTime) -> Result<()>;
// syscall mount(opts: &MountOptions<'_>) -> Result<()>;
// syscall unmount(opts: &UnmountOptions) -> Result<()>;
// syscall load_module(path: &str) -> Result<()>;
// syscall filesystem_control(fd: Option<RawFd>, option: u32, value: &mut [u8], len: usize) -> Result<usize>;
// syscall get_system_info(option: u32, value: &mut [u8]) -> Result<usize>;
// syscall open(at: Option<RawFd>, path: &str, opts: OpenOptions, mode: FileMode) -> Result<RawFd>;
syscall(SyscallFunction::Open, "open", &[OptionFd, Path, AccessMode]),
// syscall check_access(at: Option<RawFd>, path: &str, access: AccessMode) -> Result<()>;
syscall(
SyscallFunction::CheckAccess,
"check_access",
&[OptionFd, Path, AccessMode],
),
// syscall close(fd: RawFd) -> Result<()>;
syscall(SyscallFunction::Close, "close", &[Fd]),
// syscall write(fd: RawFd, data: &[u8]) -> Result<usize>;
syscall(SyscallFunction::Write, "write", &[Fd, BytesRef]),
// syscall read(fd: RawFd, data: &mut [u8]) -> Result<usize>;
syscall(SyscallFunction::Read, "read", &[Fd, BytesMut]),
// syscall seek(fd: RawFd, pos: SeekFrom, output: &mut u64) -> Result<()>; TODO
// syscall truncate(fd: RawFd, size: u64) -> Result<()>;
syscall(SyscallFunction::Truncate, "truncate", &[Fd, FileSize]),
// syscall fsync(fd: RawFd, what: FileSync) -> Result<()>;
// syscall(SyscallFunction::Fsync, "fsync", &[Fd, Enum(123)]), TODO not implemented
// syscall read_at(fd: RawFd, pos: u64, data: &mut [u8]) -> Result<usize>;
syscall(
SyscallFunction::ReadAt,
"read_at",
&[Fd, FileSize, BytesMut],
),
// syscall write_at(fd: RawFd, pos: u64, data: &[u8]) -> Result<usize>;
syscall(
SyscallFunction::WriteAt,
"write_at",
&[Fd, FileSize, BytesRef],
),
// syscall get_file_option(fd: RawFd, option: u32, data: &mut [u8]) -> Result<usize>;
syscall(
SyscallFunction::GetFileOption,
"get_file_option",
&[Fd, Number(usize::MIN, usize::MAX), BytesMut],
),
// syscall set_file_option(fd: RawFd, option: u32, data: &[u8]) -> Result<()>;
syscall(
SyscallFunction::SetFileOption,
"set_file_option",
&[Fd, Number(usize::MIN, usize::MAX), BytesRef],
),
]
};
fn generate_argument_variants(arg: &Argument) -> Vec<Vec<usize>> {
match arg {
Argument::Path | Argument::BytesRef => {
vec![vec![0, 0], vec![0, 123], vec![0xFFFFFF8012345678, 123]]
}
Argument::BytesMut => {
vec![
vec![0, 0],
vec![0, 123],
vec![0xFFFFFF8012345678, 123],
vec!["abcdef".as_ptr().addr(), 123],
]
}
Argument::OptionFd | Argument::Fd => {
vec![vec![1234], vec![usize::MAX]]
}
Argument::AccessMode => {
vec![vec![0], vec![usize::MAX]]
}
Argument::FileSize => {
vec![vec![usize::MAX]]
}
&Argument::Enum(lower_bound) => {
vec![vec![lower_bound + 1], vec![usize::MAX]]
}
&Argument::Number(a, b) => (0..100)
.map(|_| rand::thread_rng().gen_range(a..b))
.map(|a| vec![a])
.collect(),
}
}
fn fuzz(def: &Definition) {
let argument_variants = def
.args
.iter()
.map(generate_argument_variants)
.multi_cartesian_product()
.map(|combo| combo.into_iter().flatten());
for variant in argument_variants {
let variant = variant.collect::<Vec<_>>();
println!("{}: {:x?}", def.name, variant);
let result = unsafe {
match variant.len() {
1 => runtime::rt::syscall!(def.number, variant[0]),
2 => runtime::rt::syscall!(def.number, variant[0], variant[1]),
3 => runtime::rt::syscall!(def.number, variant[0], variant[1], variant[2]),
4 => runtime::rt::syscall!(
def.number, variant[0], variant[1], variant[2], variant[3]
),
5 => runtime::rt::syscall!(
def.number, variant[0], variant[1], variant[2], variant[3], variant[4]
),
_ => unimplemented!(),
}
};
println!(" -> {:#x} ({})", result, result as isize);
}
}
fn main() {
for def in DEFS {
fuzz(def);
}
}
+25 -26
View File
@@ -29,37 +29,35 @@ const PROGRAMS: &[(&str, &str)] = &[
// shell
("shell", "bin/sh"),
// sysutils
("cat", "bin/cat"),
("chmod", "bin/chmod"),
("chroot", "sbin/chroot"),
("date", "bin/date"),
("dd", "bin/dd"),
("echo", "bin/echo"),
("env", "bin/env"),
("grep", "bin/grep"),
("hexd", "bin/hexd"),
("ln", "bin/ln"),
("login", "sbin/login"),
("ls", "bin/ls"),
("lspci", "bin/lspci"),
("md2txt", "bin/md2txt"),
("mkdir", "bin/mkdir"),
("mount", "sbin/mount"),
("mv", "bin/mv"),
("poweroff", "sbin/poweroff"),
("ps", "bin/ps"),
("random", "bin/random"),
("reboot", "sbin/reboot"),
("rm", "bin/rm"),
("sha256sum", "bin/sha256sum"),
("sleep", "bin/sleep"),
("chroot", "sbin/chroot"),
("login", "sbin/login"),
("strace", "bin/strace"),
("sync", "bin/sync"),
("sysmon", "bin/sysmon"),
("top", "bin/top"),
("ls", "bin/ls"),
("mv", "bin/mv"),
("ln", "bin/ln"),
("mkdir", "bin/mkdir"),
("touch", "bin/touch"),
("tst", "bin/tst"),
("env", "bin/env"),
("rm", "bin/rm"),
("cat", "bin/cat"),
("hexd", "bin/hexd"),
("dd", "bin/dd"),
("random", "bin/random"),
("view", "bin/view"),
("grep", "bin/grep"),
("chmod", "bin/chmod"),
("sha256sum", "bin/sha256sum"),
("sysmon", "bin/sysmon"),
("date", "bin/date"),
("sync", "bin/sync"),
("sleep", "bin/sleep"),
("lspci", "bin/lspci"),
("ps", "bin/ps"),
("top", "bin/top"),
("tst", "bin/tst"),
("md2txt", "bin/md2txt"),
// netutils
("netconf", "sbin/netconf"),
("dhcp-client", "sbin/dhcp-client"),
@@ -83,6 +81,7 @@ const PROGRAMS: &[(&str, &str)] = &[
// crypt
("crypt", "bin/crypt"),
("dyn-loader", "libexec/dyn-loader"),
("fuzzy", "sbin/fuzzy"),
// TODO: proper process for C program builds
];