***: fix all warnings and clippy stuff

This commit is contained in:
Mark Poliakov 2023-08-02 20:43:21 +03:00
parent c9af9b143a
commit da91126293
30 changed files with 467 additions and 439 deletions

View File

@ -20,7 +20,6 @@ cfg-if = "1.0.0"
bitmap-font = { version = "0.3.0" } bitmap-font = { version = "0.3.0" }
embedded-graphics = "0.8.0" embedded-graphics = "0.8.0"
git-version = "0.3.5" git-version = "0.3.5"
acpi = "4.1.1"
[dependencies.elf] [dependencies.elf]
version = "0.7.2" version = "0.7.2"
@ -35,3 +34,4 @@ aarch64-cpu = "9.3.1"
[target.'cfg(target_arch = "x86_64")'.dependencies] [target.'cfg(target_arch = "x86_64")'.dependencies]
yboot-proto = { git = "https://git.alnyan.me/yggdrasil/yboot-proto.git" } yboot-proto = { git = "https://git.alnyan.me/yggdrasil/yboot-proto.git" }
aml = "0.16.4" aml = "0.16.4"
acpi = "4.1.1"

View File

@ -1,12 +1,15 @@
//! AArch64-specific task context implementation //! AArch64-specific task context implementation
use core::{arch::global_asm, cell::UnsafeCell}; use core::{arch::global_asm, cell::UnsafeCell};
use abi::error::Error; use abi::{error::Error, process::ExitCode};
use alloc::boxed::Box; use alloc::boxed::Box;
use crate::mem::{ use crate::{
phys::{self, PageUsage}, mem::{
ConvertAddress, phys::{self, PageUsage},
ConvertAddress,
},
task::process::Process,
}; };
struct StackBuilder { struct StackBuilder {
@ -82,6 +85,11 @@ impl StackBuilder {
} }
impl TaskContext { impl TaskContext {
/// Extra number of bytes to offset the user stack pointer
pub const USER_STACK_EXTRA_ALIGN: usize = 0;
/// Extra number of bytes to offset the signal stack pointer
pub const SIGNAL_STACK_EXTRA_ALIGN: usize = 0;
/// Constructs a kernel thread context. For a more convenient way of constructing kernel /// Constructs a kernel thread context. For a more convenient way of constructing kernel
/// processes, see [TaskContext::kernel_closure()]. /// processes, see [TaskContext::kernel_closure()].
pub fn kernel(entry: extern "C" fn(usize) -> !, arg: usize) -> Result<Self, Error> { pub fn kernel(entry: extern "C" fn(usize) -> !, arg: usize) -> Result<Self, Error> {
@ -114,7 +122,8 @@ impl TaskContext {
extern "C" fn closure_wrapper<F: FnOnce() + Send + 'static>(closure_addr: usize) -> ! { extern "C" fn closure_wrapper<F: FnOnce() + Send + 'static>(closure_addr: usize) -> ! {
let closure = unsafe { Box::from_raw(closure_addr as *mut F) }; let closure = unsafe { Box::from_raw(closure_addr as *mut F) };
closure(); closure();
todo!("Process termination"); Process::current().exit(ExitCode::SUCCESS);
unreachable!();
} }
let closure = Box::new(f); let closure = Box::new(f);

View File

@ -3,7 +3,8 @@ use core::{arch::global_asm, fmt};
use aarch64_cpu::registers::{ELR_EL1, ESR_EL1, FAR_EL1, TTBR0_EL1, TTBR1_EL1, VBAR_EL1}; use aarch64_cpu::registers::{ELR_EL1, ESR_EL1, FAR_EL1, TTBR0_EL1, TTBR1_EL1, VBAR_EL1};
use abi::{ use abi::{
process::{SavedFrame, Signal, SignalEntryData}, arch::SavedFrame,
process::{Signal, SignalEntryData},
syscall::SyscallFunction, syscall::SyscallFunction,
}; };
use tock_registers::interfaces::{Readable, Writeable}; use tock_registers::interfaces::{Readable, Writeable};
@ -11,10 +12,10 @@ use tock_registers::interfaces::{Readable, Writeable};
use crate::{ use crate::{
arch::{aarch64::cpu::Cpu, CpuMessage, PLATFORM}, arch::{aarch64::cpu::Cpu, CpuMessage, PLATFORM},
debug::LogLevel, debug::LogLevel,
device::{interrupt::IrqContext, platform::Platform}, device::interrupt::IrqContext,
panic::panic_secondary, panic::panic_secondary,
syscall::raw_syscall_handler, syscall::raw_syscall_handler,
task::process::Process, task::process::{Process, TaskFrame},
}; };
/// Struct for register values saved when taking an exception /// Struct for register values saved when taking an exception
@ -32,9 +33,8 @@ pub struct ExceptionFrame {
// ... // ...
} }
impl ExceptionFrame { impl TaskFrame for ExceptionFrame {
/// Saves an userspace execution context into a frame "snapshot" fn store(&self) -> SavedFrame {
pub fn to_saved_frame(&self) -> SavedFrame {
SavedFrame { SavedFrame {
gp_regs: self.r, gp_regs: self.r,
spsr_el1: self.spsr_el1, spsr_el1: self.spsr_el1,
@ -43,12 +43,39 @@ impl ExceptionFrame {
} }
} }
/// Restores an userspace execution context from its frame "snapshot" fn restore(&mut self, saved: &SavedFrame) {
pub fn restore_from_signal(&mut self, frame: &SavedFrame) { self.r = saved.gp_regs;
self.r = frame.gp_regs; self.spsr_el1 = saved.spsr_el1;
self.spsr_el1 = frame.spsr_el1; self.elr_el1 = saved.elr_el1;
self.elr_el1 = frame.elr_el1; self.sp_el0 = saved.sp_el0;
self.sp_el0 = frame.sp_el0; }
fn argument(&self) -> u64 {
self.r[0]
}
fn user_ip(&self) -> usize {
self.elr_el1 as _
}
fn user_sp(&self) -> usize {
self.sp_el0 as _
}
fn set_argument(&mut self, value: u64) {
self.r[0] = value;
}
fn set_return_value(&mut self, value: u64) {
self.r[0] = value;
}
fn set_user_ip(&mut self, value: usize) {
self.elr_el1 = value as _;
}
fn set_user_sp(&mut self, value: usize) {
self.sp_el0 = value as _;
} }
} }
@ -217,7 +244,7 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) {
0b111100 => { 0b111100 => {
let proc = Process::current(); let proc = Process::current();
warnln!("Process #{} hit a breakpoint", proc.id()); warnln!("Process #{} hit a breakpoint", proc.id());
proc.try_set_signal(Signal::Aborted).ok(); proc.raise_signal(Signal::Aborted);
} }
_ => { _ => {
let iss = esr_el1 & 0x1FFFFFF; let iss = esr_el1 & 0x1FFFFFF;
@ -231,7 +258,7 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) {
FAR_EL1.get() FAR_EL1.get()
); );
proc.try_set_signal(Signal::MemoryAccessViolation).ok(); proc.raise_signal(Signal::MemoryAccessViolation);
return; return;
} }
@ -245,7 +272,7 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) {
fn irq_common() { fn irq_common() {
unsafe { unsafe {
let ic = IrqContext::new(); let ic = IrqContext::new();
PLATFORM.interrupt_controller().handle_pending_irqs(&ic); PLATFORM.gic.handle_pending_irqs(&ic);
} }
} }
@ -258,7 +285,7 @@ unsafe fn handle_signal_exit(frame: &mut ExceptionFrame) {
saved_data.frame.sp_el0 saved_data.frame.sp_el0
); );
frame.restore_from_signal(&saved_data.frame); frame.restore(&saved_data.frame);
} }
pub(super) fn ipi_handler(msg: Option<CpuMessage>) { pub(super) fn ipi_handler(msg: Option<CpuMessage>) {

View File

@ -96,6 +96,7 @@ impl Gicd {
} }
} }
#[allow(dead_code)]
pub unsafe fn set_sgir(&self, target: IpiDeliveryTarget, interrupt_id: u64) { pub unsafe fn set_sgir(&self, target: IpiDeliveryTarget, interrupt_id: u64) {
assert_eq!(interrupt_id & !0xF, 0); assert_eq!(interrupt_id & !0xF, 0);
let value = match target { let value = match target {

View File

@ -1,14 +1,11 @@
//! ARM Generic Interrupt Controller v2 driver //! ARM Generic Interrupt Controller v2 driver
use core::sync::atomic::Ordering;
use aarch64_cpu::asm::barrier;
use abi::error::Error; use abi::error::Error;
use spinning_top::Spinlock; use spinning_top::Spinlock;
use crate::{ use crate::{
arch::CpuMessage,
device::{ device::{
interrupt::{InterruptController, InterruptSource, IpiDeliveryTarget}, interrupt::{ExternalInterruptController, InterruptSource, IrqContext},
Device, Device,
}, },
mem::device::{DeviceMemory, DeviceMemoryIo}, mem::device::{DeviceMemory, DeviceMemoryIo},
@ -17,7 +14,7 @@ use crate::{
use self::{gicc::Gicc, gicd::Gicd}; use self::{gicc::Gicc, gicd::Gicd};
use super::{cpu::Cpu, exception::ipi_handler, smp::CPU_COUNT}; use super::{cpu::Cpu, exception::ipi_handler};
const MAX_IRQ: usize = 300; const MAX_IRQ: usize = 300;
const IPI_VECTOR: u64 = 1; const IPI_VECTOR: u64 = 1;
@ -82,7 +79,7 @@ impl Device for Gic {
} }
} }
impl InterruptController for Gic { impl ExternalInterruptController for Gic {
type IrqNumber = IrqNumber; type IrqNumber = IrqNumber;
fn enable_irq(&self, irq: Self::IrqNumber) -> Result<(), Error> { fn enable_irq(&self, irq: Self::IrqNumber) -> Result<(), Error> {
@ -90,34 +87,6 @@ impl InterruptController for Gic {
Ok(()) Ok(())
} }
fn handle_pending_irqs<'irq>(&'irq self, ic: &crate::device::interrupt::IrqContext<'irq>) {
let gicc = self.gicc.get();
let irq_number = gicc.pending_irq_number(ic);
if irq_number >= MAX_IRQ {
return;
}
gicc.clear_irq(irq_number, ic);
if irq_number as u64 == IPI_VECTOR {
// IPI received
let msg = Cpu::local().get_ipi();
ipi_handler(msg);
return;
}
{
let table = self.irq_table.lock();
match table[irq_number] {
None => panic!("No IRQ handler registered for irq{}", irq_number),
Some(handler) => {
drop(table);
handler.handle_irq().expect("IRQ handler failed");
}
}
}
}
fn register_handler( fn register_handler(
&self, &self,
irq: Self::IrqNumber, irq: Self::IrqNumber,
@ -135,28 +104,28 @@ impl InterruptController for Gic {
Ok(()) Ok(())
} }
unsafe fn send_ipi(&self, target: IpiDeliveryTarget, msg: CpuMessage) -> Result<(), Error> { // unsafe fn send_ipi(&self, target: IpiDeliveryTarget, msg: CpuMessage) -> Result<(), Error> {
// TODO message queue insertion should be moved // // TODO message queue insertion should be moved
match target { // match target {
IpiDeliveryTarget::AllExceptLocal => { // IpiDeliveryTarget::AllExceptLocal => {
let local = Cpu::local_id(); // let local = Cpu::local_id();
for i in 0..CPU_COUNT.load(Ordering::Acquire) { // for i in 0..CPU_COUNT.load(Ordering::Acquire) {
if i != local as usize { // if i != local as usize {
Cpu::push_ipi_queue(i as u32, msg); // Cpu::push_ipi_queue(i as u32, msg);
} // }
} // }
} // }
IpiDeliveryTarget::Specified(_) => todo!(), // IpiDeliveryTarget::Specified(_) => todo!(),
} // }
// Issue a memory barrier // // Issue a memory barrier
barrier::dsb(barrier::ISH); // barrier::dsb(barrier::ISH);
barrier::isb(barrier::SY); // barrier::isb(barrier::SY);
self.gicd.get().set_sgir(target, IPI_VECTOR); // self.gicd.get().set_sgir(target, IPI_VECTOR);
Ok(()) // Ok(())
} // }
} }
impl Gic { impl Gic {
@ -184,4 +153,33 @@ impl Gic {
self.gicc.get().init(); self.gicc.get().init();
Ok(()) Ok(())
} }
/// Handles a single pending IRQ (if there're many, the CPU will just get here again)
pub fn handle_pending_irqs<'irq>(&'irq self, ic: &IrqContext<'irq>) {
let gicc = self.gicc.get();
let irq_number = gicc.pending_irq_number(ic);
if irq_number >= MAX_IRQ {
return;
}
gicc.clear_irq(irq_number, ic);
if irq_number as u64 == IPI_VECTOR {
// IPI received
let msg = Cpu::local().get_ipi();
ipi_handler(msg);
return;
}
{
let table = self.irq_table.lock();
match table[irq_number] {
None => panic!("No IRQ handler registered for irq{}", irq_number),
Some(handler) => {
drop(table);
handler.handle_irq().expect("IRQ handler failed");
}
}
}
}
} }

View File

@ -1,13 +0,0 @@
//! Intrinsic helper functions for AArch64 platforms
/// Returns an absolute address to the given symbol
#[macro_export]
macro_rules! absolute_address {
($sym:expr) => {{
let mut _x: usize;
unsafe {
core::arch::asm!("ldr {0}, ={1}", out(reg) _x, sym $sym);
}
_x
}};
}

View File

@ -30,8 +30,6 @@ use self::{
table::{init_fixed_tables, KERNEL_TABLES}, table::{init_fixed_tables, KERNEL_TABLES},
}; };
pub mod intrinsics;
pub mod plat_qemu; pub mod plat_qemu;
pub mod boot; pub mod boot;
@ -205,7 +203,7 @@ pub fn kernel_main(dtb_phys: usize) -> ! {
AArch64::set_interrupt_mask(true); AArch64::set_interrupt_mask(true);
ARCHITECTURE.init_device_tree(dtb_phys); ARCHITECTURE.init_device_tree(dtb_phys);
PLATFORM.init_primary_serial(); PLATFORM.init_primary_debug_sink();
} }
// Setup debugging functions // Setup debugging functions
debug::init(); debug::init();

View File

@ -4,11 +4,11 @@ use abi::error::Error;
use tock_registers::interfaces::Writeable; use tock_registers::interfaces::Writeable;
use crate::{ use crate::{
debug::DebugSink,
device::{ device::{
interrupt::{InterruptController, InterruptSource}, interrupt::{ExternalInterruptController, InterruptSource},
platform::Platform, platform::Platform,
serial::{pl011::Pl011, SerialDevice}, serial::pl011::Pl011,
timer::TimestampSource,
Device, Device,
}, },
fs::devfs::{self, CharDeviceType}, fs::devfs::{self, CharDeviceType},
@ -21,7 +21,8 @@ use super::{
/// AArch64 "virt" platform implementation /// AArch64 "virt" platform implementation
pub struct QemuPlatform { pub struct QemuPlatform {
gic: Gic, /// ...
pub gic: Gic,
pl011: Pl011, pl011: Pl011,
local_timer: ArmTimer, local_timer: ArmTimer,
} }
@ -52,25 +53,39 @@ impl Platform for QemuPlatform {
Ok(()) Ok(())
} }
unsafe fn init_primary_serial(&self) { unsafe fn init_primary_debug_sink(&self) {
self.pl011.init().ok(); self.pl011.init().ok();
} }
fn primary_debug_sink(&self) -> Option<&dyn DebugSink> {
Some(&self.pl011)
}
fn interrupt_controller(
&self,
) -> &dyn ExternalInterruptController<IrqNumber = Self::IrqNumber> {
&self.gic
}
// unsafe fn init_primary_serial(&self) {
// self.pl011.init().ok();
// }
fn name(&self) -> &'static str { fn name(&self) -> &'static str {
"qemu" "qemu"
} }
fn primary_serial(&self) -> Option<&dyn SerialDevice> { // fn primary_serial(&self) -> Option<&dyn SerialDevice> {
Some(&self.pl011) // Some(&self.pl011)
} // }
fn interrupt_controller(&self) -> &dyn InterruptController<IrqNumber = Self::IrqNumber> { // fn interrupt_controller(&self) -> &dyn InterruptController<IrqNumber = Self::IrqNumber> {
&self.gic // &self.gic
} // }
fn timestamp_source(&self) -> &dyn TimestampSource { // fn timestamp_source(&self) -> &dyn TimestampSource {
&self.local_timer // &self.local_timer
} // }
} }
/// AArch64 "virt" platform /// AArch64 "virt" platform

View File

@ -12,7 +12,9 @@ use tock_registers::interfaces::Readable;
use crate::mem::{ use crate::mem::{
phys::{self, PageUsage}, phys::{self, PageUsage},
table::{EntryLevel, NextPageTable, VirtualMemoryManager}, table::{
EntryLevel, MapAttributes, NextPageTable, NonTerminalEntryLevel, VirtualMemoryManager,
},
ConvertAddress, KERNEL_VIRT_OFFSET, ConvertAddress, KERNEL_VIRT_OFFSET,
}; };
@ -306,12 +308,27 @@ impl FixedTables {
} }
} }
impl From<MapAttributes> for PageAttributes {
fn from(value: MapAttributes) -> Self {
let mut res = Self::empty();
if value.contains(MapAttributes::USER_WRITE) {
res |= PageAttributes::AP_BOTH_READWRITE;
} else {
res |= PageAttributes::AP_BOTH_READONLY;
}
if value.contains(MapAttributes::NON_GLOBAL) {
res |= PageAttributes::NON_GLOBAL;
}
res
}
}
impl VirtualMemoryManager for AddressSpace { impl VirtualMemoryManager for AddressSpace {
fn allocate( fn allocate(
&self, &self,
hint: Option<usize>, hint: Option<usize>,
len: usize, len: usize,
attrs: PageAttributes, attrs: MapAttributes,
) -> Result<usize, Error> { ) -> Result<usize, Error> {
assert_eq!(DAIF.read(DAIF::I), 1); assert_eq!(DAIF.read(DAIF::I), 1);
@ -356,6 +373,10 @@ impl VirtualMemoryManager for AddressSpace {
Ok(()) Ok(())
} }
fn map_page(&self, virt: usize, phys: usize, attrs: MapAttributes) -> Result<(), Error> {
self.write_entry(virt, PageEntry::page(phys, attrs.into()), true)
}
} }
impl AddressSpace { impl AddressSpace {
@ -412,11 +433,6 @@ impl AddressSpace {
Ok(()) Ok(())
} }
/// Inserts a single 4KiB virt -> phys mapping into the address apce
pub fn map_page(&self, virt: usize, phys: usize, attrs: PageAttributes) -> Result<(), Error> {
self.write_entry(virt, PageEntry::page(phys, attrs), true)
}
/// Returns the physical address of the address space (to be used in a TTBRn_ELx) /// Returns the physical address of the address space (to be used in a TTBRn_ELx)
pub fn physical_address(&self) -> usize { pub fn physical_address(&self) -> usize {
unsafe { (self.l1 as usize).physicalize() | ((self.asid as usize) << 48) } unsafe { (self.l1 as usize).physicalize() | ((self.asid as usize) << 48) }

View File

@ -44,7 +44,7 @@ impl TimestampSource for ArmTimer {
} }
impl InterruptSource for ArmTimer { impl InterruptSource for ArmTimer {
fn handle_irq(&self) -> Result<(), Error> { fn handle_irq(&self) -> Result<bool, Error> {
CNTP_TVAL_EL0.set(TICK_INTERVAL); CNTP_TVAL_EL0.set(TICK_INTERVAL);
let t = self.timestamp()?; let t = self.timestamp()?;
@ -55,7 +55,7 @@ impl InterruptSource for ArmTimer {
Cpu::local().queue().yield_cpu(); Cpu::local().queue().yield_cpu();
} }
Ok(()) Ok(true)
} }
unsafe fn init_irq(&'static self) -> Result<(), Error> { unsafe fn init_irq(&'static self) -> Result<(), Error> {

View File

@ -3,18 +3,32 @@
use abi::error::Error; use abi::error::Error;
use cfg_if::cfg_if; use cfg_if::cfg_if;
/// Returns an absolute address to the given symbol
#[macro_export]
macro_rules! absolute_address {
($sym:expr) => {{
let mut _x: usize;
#[cfg(target_arch = "aarch64")]
unsafe {
core::arch::asm!("ldr {0}, ={1}", out(reg) _x, sym $sym);
}
#[cfg(target_arch = "x86_64")]
unsafe {
core::arch::asm!("movabsq ${1}, {0}", out(reg) _x, sym $sym, options(att_syntax));
}
_x
}};
}
cfg_if! { cfg_if! {
if #[cfg(target_arch = "aarch64")] { if #[cfg(target_arch = "aarch64")] {
pub mod aarch64; pub mod aarch64;
pub use aarch64::intrinsics::absolute_address;
pub use aarch64::plat_qemu::{QemuPlatform as PlatformImpl, PLATFORM}; pub use aarch64::plat_qemu::{QemuPlatform as PlatformImpl, PLATFORM};
pub use aarch64::{AArch64 as ArchitectureImpl, ARCHITECTURE}; pub use aarch64::{AArch64 as ArchitectureImpl, ARCHITECTURE};
use abi::error::Error;
use cfg_if::cfg_if;
} else if #[cfg(target_arch = "x86_64")] { } else if #[cfg(target_arch = "x86_64")] {
#[macro_use]
pub mod x86_64; pub mod x86_64;
pub use x86_64::{ pub use x86_64::{

View File

@ -8,7 +8,7 @@ use crate::{
task::process::Process, task::process::Process,
}; };
use super::exception::{self, ExceptionFrame, IrqFrame}; use super::exception::{self, IrqFrame};
pub mod ioapic; pub mod ioapic;
pub mod local; pub mod local;
@ -82,15 +82,17 @@ fn apic_irq_inner(vector: u32) {
} }
} }
/// Main handler for APIC interrupts /// Main handler for APIC interrupts.
pub extern "C" fn __x86_64_apic_irq_handler(vector: u32, frame: *mut IrqFrame) { ///
let frame = unsafe { &mut *frame }; /// # Safety
///
/// Only meant to be called from the assembly irq vector.
pub unsafe extern "C" fn __x86_64_apic_irq_handler(vector: u32, frame: *mut IrqFrame) {
let frame = &mut *frame;
apic_irq_inner(vector); apic_irq_inner(vector);
if let Some(process) = Process::get_current() { if let Some(process) = Process::get_current() {
unsafe { process.handle_signal(frame);
process.handle_signal(frame);
}
} }
} }

View File

@ -1,7 +1,7 @@
//! x86-64 task context setup and switching //! x86-64 task context setup and switching
use core::{arch::global_asm, cell::UnsafeCell}; use core::{arch::global_asm, cell::UnsafeCell};
use abi::error::Error; use abi::{error::Error, process::ExitCode};
use alloc::boxed::Box; use alloc::boxed::Box;
use crate::{ use crate::{
@ -10,6 +10,7 @@ use crate::{
phys::{self, PageUsage}, phys::{self, PageUsage},
ConvertAddress, ConvertAddress,
}, },
task::process::Process,
}; };
struct StackBuilder { struct StackBuilder {
@ -84,7 +85,9 @@ impl StackBuilder {
} }
impl TaskContext { impl TaskContext {
/// Number of bytes to offset the signal stack pointer by
pub const SIGNAL_STACK_EXTRA_ALIGN: usize = 8; pub const SIGNAL_STACK_EXTRA_ALIGN: usize = 8;
/// Number of bytes to offset the user stack pointer by
pub const USER_STACK_EXTRA_ALIGN: usize = 8; pub const USER_STACK_EXTRA_ALIGN: usize = 8;
/// Constructs a kernel-space task context /// Constructs a kernel-space task context
@ -147,7 +150,8 @@ impl TaskContext {
extern "C" fn closure_wrapper<F: FnOnce() + Send + 'static>(closure_addr: usize) -> ! { extern "C" fn closure_wrapper<F: FnOnce() + Send + 'static>(closure_addr: usize) -> ! {
let closure = unsafe { Box::from_raw(closure_addr as *mut F) }; let closure = unsafe { Box::from_raw(closure_addr as *mut F) };
closure(); closure();
todo!("Process termination"); Process::current().exit(ExitCode::SUCCESS);
unreachable!();
} }
let closure = Box::new(f); let closure = Box::new(f);

View File

@ -1,32 +1,15 @@
//! x86-64 exception and interrupt handling //! x86-64 exception and interrupt handling
use core::{arch::global_asm, mem::size_of_val}; use core::{arch::global_asm, mem::size_of_val};
use abi::{ use abi::{arch::SavedFrame, primitive_enum, process::Signal};
arch::SavedFrame,
primitive_enum,
process::{Signal, SignalEntryData},
syscall::SyscallFunction,
};
use tock_registers::interfaces::{ReadWriteable, Writeable};
use crate::{ use crate::{
arch::{ arch::x86_64::apic::{self, __x86_64_apic_irq_handler},
x86_64::{ task::process::{Process, TaskFrame},
apic::{self, __x86_64_apic_irq_handler},
registers::{MSR_IA32_EFER, MSR_IA32_LSTAR, MSR_IA32_SFMASK, MSR_IA32_STAR},
},
Architecture, ArchitectureImpl,
},
mem::table::AddressSpace,
syscall::raw_syscall_handler,
task::{
process::{Process, TaskFrame},
Cpu,
},
}; };
primitive_enum! { primitive_enum! {
pub enum ExceptionKind: u64 { enum ExceptionKind: u64 {
DivisionError = 0, DivisionError = 0,
Debug = 1, Debug = 1,
NonMaskableInterrupt = 2, NonMaskableInterrupt = 2,
@ -53,119 +36,25 @@ primitive_enum! {
} }
impl ExceptionKind { impl ExceptionKind {
pub fn ring3_possible(&self) -> bool { fn ring3_possible(&self) -> bool {
match self { matches!(
self,
Self::DivisionError Self::DivisionError
| Self::Debug | Self::Debug
| Self::Breakpoint | Self::Breakpoint
| Self::Overflow | Self::Overflow
| Self::BoundRangeExceeded | Self::BoundRangeExceeded
| Self::InvalidOpcode | Self::InvalidOpcode
| Self::GeneralProtectionFault | Self::GeneralProtectionFault
| Self::PageFault | Self::PageFault
| Self::FpuException | Self::FpuException
| Self::AlignmentCheck | Self::AlignmentCheck
| Self::SimdFpuException => true, | Self::SimdFpuException
_ => false, )
}
}
}
impl TaskFrame for IrqFrame {
fn store(&self) -> SavedFrame {
todo!()
}
fn restore(&mut self, saved: &SavedFrame) {
todo!()
}
fn argument(&self) -> u64 {
todo!();
}
fn user_ip(&self) -> usize {
todo!()
}
fn user_sp(&self) -> usize {
todo!()
}
fn set_argument(&mut self, value: u64) {
self.rdi = value;
}
fn set_return_value(&mut self, value: u64) {
todo!()
}
fn set_user_ip(&mut self, value: usize) {
todo!()
}
fn set_user_sp(&mut self, value: usize) {
todo!()
}
}
impl TaskFrame for ExceptionFrame {
fn store(&self) -> SavedFrame {
SavedFrame {
rax: self.rax,
rcx: self.rcx,
rdx: self.rdx,
rbx: self.rbx,
rsi: self.rsi,
rdi: self.rdi,
rbp: self.rbp,
r8: self.r8,
r9: self.r9,
r10: self.r10,
r11: self.r11,
r12: self.r12,
r13: self.r13,
r14: self.r14,
r15: self.r15,
user_ip: self.rip,
user_sp: self.rsp,
rflags: self.rflags,
}
}
fn restore(&mut self, saved: &SavedFrame) {
todo!()
}
fn argument(&self) -> u64 {
0
}
fn user_sp(&self) -> usize {
self.rsp as _
}
fn user_ip(&self) -> usize {
self.rip as _
}
fn set_user_sp(&mut self, value: usize) {
self.rsp = value as _;
}
fn set_user_ip(&mut self, value: usize) {
self.rip = value as _;
}
fn set_return_value(&mut self, _value: u64) {
// Not in syscall, do not overwrite
}
fn set_argument(&mut self, value: u64) {
self.rdi = value;
} }
} }
/// Frame saved onto the stack when taking an IRQ
#[derive(Debug)] #[derive(Debug)]
#[repr(C)] #[repr(C)]
pub struct IrqFrame { pub struct IrqFrame {
@ -243,6 +132,101 @@ struct Pointer {
offset: usize, offset: usize,
} }
impl TaskFrame for IrqFrame {
fn store(&self) -> SavedFrame {
todo!()
}
fn restore(&mut self, _saved: &SavedFrame) {
todo!()
}
fn argument(&self) -> u64 {
todo!();
}
fn user_ip(&self) -> usize {
todo!()
}
fn user_sp(&self) -> usize {
todo!()
}
fn set_argument(&mut self, value: u64) {
self.rdi = value;
}
fn set_return_value(&mut self, _value: u64) {
todo!()
}
fn set_user_ip(&mut self, _value: usize) {
todo!()
}
fn set_user_sp(&mut self, _value: usize) {
todo!()
}
}
impl TaskFrame for ExceptionFrame {
fn store(&self) -> SavedFrame {
SavedFrame {
rax: self.rax,
rcx: self.rcx,
rdx: self.rdx,
rbx: self.rbx,
rsi: self.rsi,
rdi: self.rdi,
rbp: self.rbp,
r8: self.r8,
r9: self.r9,
r10: self.r10,
r11: self.r11,
r12: self.r12,
r13: self.r13,
r14: self.r14,
r15: self.r15,
user_ip: self.rip,
user_sp: self.rsp,
rflags: self.rflags,
}
}
fn restore(&mut self, _saved: &SavedFrame) {
todo!()
}
fn argument(&self) -> u64 {
0
}
fn user_sp(&self) -> usize {
self.rsp as _
}
fn user_ip(&self) -> usize {
self.rip as _
}
fn set_user_sp(&mut self, value: usize) {
self.rsp = value as _;
}
fn set_user_ip(&mut self, value: usize) {
self.rip = value as _;
}
fn set_return_value(&mut self, _value: u64) {
// Not in syscall, do not overwrite
}
fn set_argument(&mut self, value: u64) {
self.rdi = value;
}
}
const SIZE: usize = 256; const SIZE: usize = 256;
impl Entry { impl Entry {
@ -278,7 +262,7 @@ impl Entry {
static mut IDT: [Entry; SIZE] = [Entry::NULL; SIZE]; static mut IDT: [Entry; SIZE] = [Entry::NULL; SIZE];
fn user_exception_inner(kind: ExceptionKind, frame: &mut ExceptionFrame) { fn user_exception_inner(kind: ExceptionKind, frame: &ExceptionFrame) {
let process = Process::current(); let process = Process::current();
warnln!("{:?} in #{} {:?}", kind, process.id(), process.name()); warnln!("{:?} in #{} {:?}", kind, process.id(), process.name());
@ -295,42 +279,15 @@ fn user_exception_inner(kind: ExceptionKind, frame: &mut ExceptionFrame) {
warnln!("CR2 = {:#x}", cr2); warnln!("CR2 = {:#x}", cr2);
process.raise_signal(Signal::MemoryAccessViolation); process.raise_signal(Signal::MemoryAccessViolation);
return;
} }
ExceptionKind::InvalidOpcode => { ExceptionKind::InvalidOpcode => {
process.raise_signal(Signal::Aborted); process.raise_signal(Signal::Aborted);
return;
} }
_ => todo!("No handler for exception: {:?}", kind), _ => todo!("No handler for exception: {:?}", kind),
} }
// errorln!("Exception {}", frame.exc_number);
// errorln!("CS:RIP = {:#x}:{:#x}", frame.cs, frame.rip);
// errorln!("SS:RSP = {:#x}:{:#x}", frame.ss, frame.rsp);
// if let Some(cpu) = Cpu::get_local() {
// let current = cpu.queue().current_process();
// if let Some(current) = current {
// errorln!("In process #{} {:?}", current.id(), current.name());
// }
// }
// debugln!("Registers:\n{:#x?}", &frame);
// if frame.exc_number == 6 {
// // Invalid opcode
// warnln!("Invalid opcode");
// }
// if frame.exc_number == 14 {
// }
// loop {
// ArchitectureImpl::wait_for_interrupt();
// }
} }
fn kernel_exception_inner(kind: ExceptionKind, frame: &ExceptionFrame) -> ! { fn kernel_exception_inner(_kind: ExceptionKind, _frame: &ExceptionFrame) -> ! {
todo!() todo!()
} }
@ -349,18 +306,6 @@ extern "C" fn __x86_64_exception_handler(frame: *mut ExceptionFrame) {
} }
} }
pub unsafe fn handle_signal_exit<F: TaskFrame>(frame: &mut F) {
// TODO validate the argument
let saved_data = &*(frame.argument() as *const SignalEntryData);
infoln!(
"Handling signal exit to ip={:#x}, sp={:#x}",
saved_data.frame.user_ip,
saved_data.frame.user_sp
);
frame.restore(&saved_data.frame);
}
/// Initializes the interrupt descriptor table for the given CPU. /// Initializes the interrupt descriptor table for the given CPU.
/// ///
/// # Safety /// # Safety

View File

@ -2,18 +2,6 @@
use core::marker::PhantomData; use core::marker::PhantomData;
/// Returns an absolute address to the given symbol
#[macro_export]
macro_rules! absolute_address {
($sym:expr) => {{
let mut _x: usize;
unsafe {
core::arch::asm!("movabsq ${1}, {0}", out(reg) _x, sym $sym, options(att_syntax));
}
_x
}};
}
/// Wrapper struct providing access to an x86 I/O port /// Wrapper struct providing access to an x86 I/O port
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[repr(transparent)] #[repr(transparent)]

View File

@ -76,10 +76,10 @@ impl InterruptSource for PS2Controller {
return Ok(false); return Ok(false);
} }
let mut key = self.data.read(); let key = self.data.read();
if key == 0xE0 { if key == 0xE0 {
key = self.data.read(); self.data.read();
infoln!("TODO: handle 0xE0"); infoln!("TODO: handle 0xE0");
return Ok(true); return Ok(true);
} }

View File

@ -1,6 +1,8 @@
//! x86-64 implementation of system call interface
use core::arch::global_asm; use core::arch::global_asm;
use abi::{arch::SavedFrame, syscall::SyscallFunction}; use abi::{arch::SavedFrame, process::SignalEntryData, syscall::SyscallFunction};
use tock_registers::interfaces::{ReadWriteable, Writeable}; use tock_registers::interfaces::{ReadWriteable, Writeable};
use crate::{ use crate::{
@ -9,12 +11,10 @@ use crate::{
task::process::{Process, TaskFrame}, task::process::{Process, TaskFrame},
}; };
use super::exception::handle_signal_exit;
/// Set of registers saved when taking a syscall instruction /// Set of registers saved when taking a syscall instruction
#[derive(Debug)] #[derive(Debug)]
#[repr(C)] #[repr(C)]
pub struct SyscallFrame { struct SyscallFrame {
rax: u64, rax: u64,
args: [u64; 6], args: [u64; 6],
@ -132,6 +132,23 @@ extern "C" fn __x86_64_syscall_handler(frame: *mut SyscallFrame) {
} }
} }
unsafe fn handle_signal_exit<F: TaskFrame>(frame: &mut F) {
// TODO validate the argument
let saved_data = &*(frame.argument() as *const SignalEntryData);
infoln!(
"Handling signal exit to ip={:#x}, sp={:#x}",
saved_data.frame.user_ip,
saved_data.frame.user_sp
);
frame.restore(&saved_data.frame);
}
/// Initializes system call instruction support for the current CPU.
///
/// # Safety
///
/// Only meant to be called once per each CPU during their init.
pub unsafe fn init_syscall() { pub unsafe fn init_syscall() {
extern "C" { extern "C" {
fn __x86_64_syscall_vector(); fn __x86_64_syscall_vector();

View File

@ -182,6 +182,7 @@ impl<L: EntryLevel> PageEntry<L> {
/// An entry that is not mapped /// An entry that is not mapped
pub const INVALID: Self = Self(0, PhantomData); pub const INVALID: Self = Self(0, PhantomData);
/// Returns `true` if the entry contains a valid mapping to either a table or to a page/block
pub fn is_present(&self) -> bool { pub fn is_present(&self) -> bool {
self.0 & PageAttributes::PRESENT.bits() != 0 self.0 & PageAttributes::PRESENT.bits() != 0
} }
@ -252,12 +253,6 @@ impl<L: EntryLevel> IndexMut<usize> for PageTable<L> {
} }
} }
impl From<PageAttributes> for MapAttributes {
fn from(value: PageAttributes) -> Self {
todo!();
}
}
impl From<MapAttributes> for PageAttributes { impl From<MapAttributes> for PageAttributes {
fn from(value: MapAttributes) -> Self { fn from(value: MapAttributes) -> Self {
let mut res = PageAttributes::WRITABLE; let mut res = PageAttributes::WRITABLE;
@ -337,12 +332,6 @@ impl AddressSpace {
Ok(Self { l0 }) Ok(Self { l0 })
} }
pub unsafe fn from_cr3(cr3: usize) -> Self {
let cr3_virt = cr3.virtualize();
let l0 = unsafe { cr3_virt as *mut PageTable<L0> };
Self { l0 }
}
unsafe fn as_mut(&self) -> &'static mut PageTable<L0> { unsafe fn as_mut(&self) -> &'static mut PageTable<L0> {
self.l0.as_mut().unwrap() self.l0.as_mut().unwrap()
} }

View File

@ -3,7 +3,12 @@ use core::fmt::{self, Arguments};
use abi::error::Error; use abi::error::Error;
use crate::{arch::PLATFORM, device::platform::Platform, sync::IrqSafeSpinlock, util::OneTimeInit}; use crate::{
arch::PLATFORM,
device::{platform::Platform, serial::SerialDevice},
sync::IrqSafeSpinlock,
util::OneTimeInit,
};
// use crate::{ // use crate::{
// arch::PLATFORM, // arch::PLATFORM,
@ -46,6 +51,12 @@ pub trait DebugSink {
} }
} }
impl<T: SerialDevice> DebugSink for T {
fn putc(&self, c: u8) -> Result<(), Error> {
self.send(c)
}
}
struct DebugPrinter { struct DebugPrinter {
sink: &'static dyn DebugSink, sink: &'static dyn DebugSink,
} }

View File

@ -1,5 +1,10 @@
//! Input device interfaces
use super::{tty::TtyDevice, Device}; use super::{tty::TtyDevice, Device};
/// Generic keyboard-like input device interface
pub trait KeyboardDevice: Device { pub trait KeyboardDevice: Device {
/// Indicates to the keyboard driver that it was attached to a terminal so it knows where to
/// send its input data to
fn attach(&self, terminal: &'static dyn TtyDevice<16>); fn attach(&self, terminal: &'static dyn TtyDevice<16>);
} }

View File

@ -151,7 +151,7 @@ impl InterruptSource for Pl011 {
Ok(()) Ok(())
} }
fn handle_irq(&self) -> Result<(), Error> { fn handle_irq(&self) -> Result<bool, Error> {
let inner = self.inner.get().lock(); let inner = self.inner.get().lock();
inner.regs.ICR.write(ICR::ALL::CLEAR); inner.regs.ICR.write(ICR::ALL::CLEAR);
@ -160,7 +160,7 @@ impl InterruptSource for Pl011 {
self.recv_byte(byte as u8); self.recv_byte(byte as u8);
Ok(()) Ok(true)
} }
} }

View File

@ -19,14 +19,18 @@ use crate::{
use super::{input::KeyboardDevice, serial::SerialDevice, Device}; use super::{input::KeyboardDevice, serial::SerialDevice, Device};
// TODO rewrite this
/// Helper device to combine a display and a keyboard input into a single terminal
pub struct CombinedTerminal { pub struct CombinedTerminal {
#[allow(dead_code)]
input: &'static dyn KeyboardDevice, input: &'static dyn KeyboardDevice,
output: &'static FramebufferConsole, output: &'static FramebufferConsole,
// TODO output
input_ring: CharRing<16>, input_ring: CharRing<16>,
} }
impl CombinedTerminal { impl CombinedTerminal {
/// Create a combined terminal device from a keyboard and console output devices
pub fn new(input: &'static dyn KeyboardDevice, output: &'static FramebufferConsole) -> Self { pub fn new(input: &'static dyn KeyboardDevice, output: &'static FramebufferConsole) -> Self {
Self { Self {
input, input,
@ -43,7 +47,7 @@ impl TtyDevice<16> for CombinedTerminal {
} }
impl SerialDevice for CombinedTerminal { impl SerialDevice for CombinedTerminal {
fn receive(&self, blocking: bool) -> Result<u8, Error> { fn receive(&self, _blocking: bool) -> Result<u8, Error> {
todo!() todo!()
} }

View File

@ -19,25 +19,13 @@
use abi::{ use abi::{
error::Error, error::Error,
io::{FileMode, OpenOptions, RawFd}, io::{FileMode, OpenOptions, RawFd},
process::ExitCode,
}; };
use fs::{devfs, FileBlockAllocator, INITRD_DATA}; use fs::{devfs, FileBlockAllocator, INITRD_DATA};
use memfs::MemoryFilesystem; use memfs::MemoryFilesystem;
use task::process::Process;
use vfs::{Filesystem, IoContext, VnodeRef}; use vfs::{Filesystem, IoContext, VnodeRef};
extern crate yggdrasil_abi as abi; extern crate yggdrasil_abi as abi;
//
// use abi::{
// error::Error,
// io::{FileMode, OpenOptions, RawFd},
// process::ExitCode,
// };
// use fs::{devfs, FileBlockAllocator, INITRD_DATA};
// use memfs::MemoryFilesystem;
// use task::process::Process;
// use vfs::{Filesystem, IoContext, VnodeRef};
//
extern crate alloc; extern crate alloc;
#[macro_use] #[macro_use]
@ -94,7 +82,12 @@ pub fn kernel_main() {
let file = node.open(OpenOptions::READ, FileMode::empty()).unwrap(); let file = node.open(OpenOptions::READ, FileMode::empty()).unwrap();
let devfs = devfs::root(); let devfs = devfs::root();
#[cfg(target_arch = "x86_64")]
let console = ioctx.find(Some(devfs.clone()), "tty0", true, true).unwrap(); let console = ioctx.find(Some(devfs.clone()), "tty0", true, true).unwrap();
#[cfg(target_arch = "aarch64")]
let console = ioctx
.find(Some(devfs.clone()), "ttyS0", true, true)
.unwrap();
let stdin = console.open(OpenOptions::READ, FileMode::empty()).unwrap(); let stdin = console.open(OpenOptions::READ, FileMode::empty()).unwrap();
let stdout = console.open(OpenOptions::WRITE, FileMode::empty()).unwrap(); let stdout = console.open(OpenOptions::WRITE, FileMode::empty()).unwrap();
let stderr = stdout.clone(); let stderr = stdout.clone();
@ -112,8 +105,4 @@ pub fn kernel_main() {
user_init.enqueue_somewhere(); user_init.enqueue_somewhere();
} }
loop {}
// XXX
// Process::current().exit(ExitCode::SUCCESS);
} }

View File

@ -12,10 +12,14 @@ cfg_if! {
} }
bitflags! { bitflags! {
/// Describes how a page translation mapping should behave
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct MapAttributes: u64 { pub struct MapAttributes: u64 {
/// The data mapped can be read by the user process
const USER_READ = 1 << 0; const USER_READ = 1 << 0;
/// The data mapped can be written to by the user process
const USER_WRITE = 1 << 1; const USER_WRITE = 1 << 1;
/// The mapping is not global across the address spaces
const NON_GLOBAL = 1 << 2; const NON_GLOBAL = 1 << 2;
} }
} }
@ -31,6 +35,7 @@ pub trait VirtualMemoryManager {
attrs: MapAttributes, attrs: MapAttributes,
) -> Result<usize, Error>; ) -> Result<usize, Error>;
/// Insert a single 4KiB-page translation mapping into the table
fn map_page(&self, virt: usize, phys: usize, attrs: MapAttributes) -> Result<(), Error>; fn map_page(&self, virt: usize, phys: usize, attrs: MapAttributes) -> Result<(), Error>;
/// Releases the virtual memory region from the address space and the pages it refers to /// Releases the virtual memory region from the address space and the pages it refers to

View File

@ -106,6 +106,8 @@ fn setup_binary<S: Into<String>>(
// Fill with some sentinel value to detect stack underflows // Fill with some sentinel value to detect stack underflows
let ptr = user_sp as *mut u64; let ptr = user_sp as *mut u64;
#[allow(clippy::reversed_empty_ranges)]
for i in 0..TaskContext::USER_STACK_EXTRA_ALIGN / 8 { for i in 0..TaskContext::USER_STACK_EXTRA_ALIGN / 8 {
unsafe { unsafe {
ptr.add(i).write_foreign_volatile(&space, 0xDEADC0DE); ptr.add(i).write_foreign_volatile(&space, 0xDEADC0DE);

View File

@ -5,8 +5,6 @@ use abi::error::Error;
use alloc::{collections::LinkedList, rc::Rc}; use alloc::{collections::LinkedList, rc::Rc};
use crate::{ use crate::{
arch::PLATFORM,
device::platform::Platform,
sync::IrqSafeSpinlock, sync::IrqSafeSpinlock,
task::process::{Process, ProcessState}, task::process::{Process, ProcessState},
}; };
@ -32,6 +30,7 @@ pub struct Wait {
struct Timeout { struct Timeout {
process: Rc<Process>, process: Rc<Process>,
#[allow(dead_code)]
deadline: Duration, deadline: Duration,
} }
@ -122,7 +121,7 @@ impl Wait {
queue_lock = self.queue.lock(); queue_lock = self.queue.lock();
if let Some(deadline) = deadline { if let Some(_deadline) = deadline {
// let now = PLATFORM.timestamp_source().timestamp()?; // let now = PLATFORM.timestamp_source().timestamp()?;
// if now > deadline { // if now > deadline {
@ -147,7 +146,7 @@ impl Wait {
static TICK_LIST: IrqSafeSpinlock<LinkedList<Timeout>> = IrqSafeSpinlock::new(LinkedList::new()); static TICK_LIST: IrqSafeSpinlock<LinkedList<Timeout>> = IrqSafeSpinlock::new(LinkedList::new());
/// Suspends current task until given deadline /// Suspends current task until given deadline
pub fn sleep(timeout: Duration, remaining: &mut Duration) -> Result<(), Error> { pub fn sleep(_timeout: Duration, _remaining: &mut Duration) -> Result<(), Error> {
todo!(); todo!();
// static SLEEP_NOTIFY: Wait = Wait::new("sleep"); // static SLEEP_NOTIFY: Wait = Wait::new("sleep");
// let now = PLATFORM.timestamp_source().timestamp()?; // let now = PLATFORM.timestamp_source().timestamp()?;
@ -166,8 +165,7 @@ pub fn sleep(timeout: Duration, remaining: &mut Duration) -> Result<(), Error> {
} }
/// Updates all pending timeouts and wakes up the tasks that have reached theirs /// Updates all pending timeouts and wakes up the tasks that have reached theirs
pub fn tick(now: Duration) { pub fn tick(_now: Duration) {
todo!();
// let mut list = TICK_LIST.lock(); // let mut list = TICK_LIST.lock();
// let mut cursor = list.cursor_front_mut(); // let mut cursor = list.cursor_front_mut();

View File

@ -20,7 +20,7 @@ use crate::{
proc::{ proc::{
self, self,
io::ProcessIo, io::ProcessIo,
wait::PROCESS_EXIT_WAIT, wait::{self, PROCESS_EXIT_WAIT},
// wait::{self, PROCESS_EXIT_WAIT}, // wait::{self, PROCESS_EXIT_WAIT},
}, },
sync::IrqSafeSpinlockGuard, sync::IrqSafeSpinlockGuard,
@ -63,15 +63,14 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
Ok(0) Ok(0)
} }
SyscallFunction::Nanosleep => { SyscallFunction::Nanosleep => {
todo!(); let seconds = args[0];
// let seconds = args[0]; let nanos = args[1] as u32;
// let nanos = args[1] as u32; let duration = Duration::new(seconds, nanos);
// let duration = Duration::new(seconds, nanos); let mut remaining = Duration::ZERO;
// let mut remaining = Duration::ZERO;
// wait::sleep(duration, &mut remaining).unwrap(); wait::sleep(duration, &mut remaining).unwrap();
// Ok(0) Ok(0)
} }
SyscallFunction::Exit => { SyscallFunction::Exit => {
let code = ExitCode::from(args[0] as i32); let code = ExitCode::from(args[0] as i32);
@ -142,11 +141,11 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
debugln!("run_with_io_at {:?}", at); debugln!("run_with_io_at {:?}", at);
let file = io.ioctx().open(at, path, opts, mode)?; let file = io.ioctx().open(at, path, opts, mode)?;
// if proc.session_terminal().is_none() && if proc.session_terminal().is_none() &&
// let Ok(node) = file.borrow().node() && node.kind() == VnodeKind::Char { let Ok(node) = file.borrow().node() && node.kind() == VnodeKind::Char {
// debugln!("Session terminal set for #{}: {}", proc.id(), path); debugln!("Session terminal set for #{}: {}", proc.id(), path);
// proc.set_session_terminal(node); proc.set_session_terminal(node);
// } }
let fd = io.place_file(file)?; let fd = io.place_file(file)?;
Ok(fd.0 as usize) Ok(fd.0 as usize)
@ -179,17 +178,16 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
}) })
} }
SyscallFunction::Unmount => { SyscallFunction::Unmount => {
todo!(); let options = arg_user_ref::<UnmountOptions>(args[0] as usize)?;
// let options = arg_user_ref::<UnmountOptions>(args[0] as usize)?;
// run_with_io(|mut io| { run_with_io(|mut io| {
// let mountpoint = io.ioctx().find(None, options.mountpoint, true, false)?; let mountpoint = io.ioctx().find(None, options.mountpoint, true, false)?;
// mountpoint.unmount_target()?; mountpoint.unmount_target()?;
// debugln!("{:?}", vfs::VnodeDump::new(io.ioctx().root().clone())); debugln!("{:?}", vfs::VnodeDump::new(io.ioctx().root().clone()));
// Ok(0) Ok(0)
// }) })
} }
SyscallFunction::OpenDirectory => { SyscallFunction::OpenDirectory => {
let at = arg_option_fd(args[0] as u32); let at = arg_option_fd(args[0] as u32);
@ -218,70 +216,66 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
}) })
} }
SyscallFunction::CreateDirectory => { SyscallFunction::CreateDirectory => {
todo!(); let at = arg_option_fd(args[0] as u32);
// let at = arg_option_fd(args[0] as u32); let path = arg_user_str(args[1] as usize, args[2] as usize)?;
// let path = arg_user_str(args[1] as usize, args[2] as usize)?; let _mode = FileMode::from(args[3] as u32);
// let _mode = FileMode::from(args[3] as u32);
// run_with_io_at(at, |at, mut io| { run_with_io_at(at, |at, mut io| {
// let (parent, name) = abi::path::split_right(path); let (parent, name) = abi::path::split_right(path);
// let parent_node = io.ioctx().find(at, parent, true, true)?; let parent_node = io.ioctx().find(at, parent, true, true)?;
// parent_node.create(name, VnodeKind::Directory)?; parent_node.create(name, VnodeKind::Directory)?;
// Ok(0) Ok(0)
// }) })
} }
SyscallFunction::Remove => { SyscallFunction::Remove => {
todo!(); let at = arg_option_fd(args[0] as u32);
// let at = arg_option_fd(args[0] as u32); let path = arg_user_str(args[1] as usize, args[2] as usize)?;
// let path = arg_user_str(args[1] as usize, args[2] as usize)?; let recurse = args[3] != 0;
// let recurse = args[3] != 0;
// run_with_io_at(at, |at, mut io| { run_with_io_at(at, |at, mut io| {
// let node = io.ioctx().find(at, path, false, false)?; let node = io.ioctx().find(at, path, false, false)?;
// if node.is_root() || Rc::ptr_eq(io.ioctx().root(), &node) { if node.is_root() || Rc::ptr_eq(io.ioctx().root(), &node) {
// todo!(); todo!();
// } }
// let parent = node.parent(); let parent = node.parent();
// parent.remove(node, recurse)?; parent.remove(node, recurse)?;
// Ok(0) Ok(0)
// }) })
} }
SyscallFunction::GetMetadata => { SyscallFunction::GetMetadata => {
todo!(); let at = arg_option_fd(args[0] as u32);
// let at = arg_option_fd(args[0] as u32); let path = arg_user_str(args[1] as usize, args[2] as usize)?;
// let path = arg_user_str(args[1] as usize, args[2] as usize)?; let buffer = arg_user_mut::<MaybeUninit<FileAttr>>(args[3] as usize)?;
// let buffer = arg_user_mut::<MaybeUninit<FileAttr>>(args[3] as usize)?; let follow = args[4] != 0;
// let follow = args[4] != 0;
// run_with_io_at(at, |at, mut io| { run_with_io_at(at, |at, mut io| {
// let node = if path.is_empty() { let node = if path.is_empty() {
// at.ok_or(Error::InvalidArgument)? at.ok_or(Error::InvalidArgument)?
// } else { } else {
// io.ioctx().find(None, path, follow, true)? io.ioctx().find(None, path, follow, true)?
// }; };
// let metadata = node.metadata()?; let metadata = node.metadata()?;
// buffer.write(metadata); buffer.write(metadata);
// Ok(0) Ok(0)
// }) })
} }
SyscallFunction::Seek => { SyscallFunction::Seek => {
todo!(); let fd = RawFd(args[0] as u32);
// let fd = RawFd(args[0] as u32); let pos = SeekFrom::from(args[1]);
// let pos = SeekFrom::from(args[1]);
// run_with_io(|io| { run_with_io(|io| {
// let file = io.file(fd)?; let file = io.file(fd)?;
// let mut file_borrow = file.borrow_mut(); let mut file_borrow = file.borrow_mut();
// file_borrow.seek(pos).map(|v| v as usize) file_borrow.seek(pos).map(|v| v as usize)
// }) })
} }
SyscallFunction::Spawn => { SyscallFunction::Spawn => {
let options = arg_user_ref::<SpawnOptions>(args[0] as usize)?; let options = arg_user_ref::<SpawnOptions>(args[0] as usize)?;
@ -342,14 +336,13 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
} }
} }
SyscallFunction::SendSignal => { SyscallFunction::SendSignal => {
todo!(); let pid = args[0] as u32;
// let pid = args[0] as u32; let signal = Signal::try_from(args[1] as u32).map_err(|_| Error::InvalidArgument)?;
// let signal = Signal::try_from(args[1] as u32).map_err(|_| Error::InvalidArgument)?;
// let target = Process::get(pid as _).ok_or(Error::DoesNotExist)?; let target = Process::get(pid as _).ok_or(Error::DoesNotExist)?;
// target.try_set_signal(signal)?; target.raise_signal(signal);
// Ok(0) Ok(0)
} }
SyscallFunction::SetSignalEntry => { SyscallFunction::SetSignalEntry => {
let entry = args[0] as usize; let entry = args[0] as usize;

View File

@ -16,13 +16,6 @@ cfg_if! {
use crate::{ use crate::{
kernel_main, kernel_main,
mem::{
phys::{self, PageUsage},
table::AddressSpace,
ConvertAddress,
},
//arch::aarch64::{context::TaskContext, cpu::Cpu, smp::CPU_COUNT},
// kernel_main,
sync::{IrqSafeSpinlock, SpinFence}, sync::{IrqSafeSpinlock, SpinFence},
task::sched::CpuQueue, task::sched::CpuQueue,
}; };

View File

@ -26,17 +26,33 @@ use crate::{
use super::{sched::CpuQueue, Cpu, ProcessId, TaskContext, PROCESSES}; use super::{sched::CpuQueue, Cpu, ProcessId, TaskContext, PROCESSES};
/// Interface for task state save/restore mechanisms
pub trait TaskFrame { pub trait TaskFrame {
/// Creates a "snapshot" of a exception/syscall frame
fn store(&self) -> SavedFrame; fn store(&self) -> SavedFrame;
/// Restores the exception/syscall frame from its saved state
fn restore(&mut self, saved: &SavedFrame); fn restore(&mut self, saved: &SavedFrame);
/// Replaces the return value in the frame (or does nothing, if the frame is not a part of a
/// syscall signal handler)
fn set_return_value(&mut self, value: u64); fn set_return_value(&mut self, value: u64);
/// Replaces the userspace stack pointer in the frame
fn set_user_sp(&mut self, value: usize); fn set_user_sp(&mut self, value: usize);
/// Replaces the userspace instruction pointer in the frame
fn set_user_ip(&mut self, value: usize); fn set_user_ip(&mut self, value: usize);
/// Replaces the argument in the frame
fn set_argument(&mut self, value: u64); fn set_argument(&mut self, value: u64);
/// Returns the argument (if any) of the frame being processed
fn argument(&self) -> u64; fn argument(&self) -> u64;
/// Returns the userspace stack pointer
fn user_sp(&self) -> usize; fn user_sp(&self) -> usize;
/// Returns the userspace instruction pointer
fn user_ip(&self) -> usize; fn user_ip(&self) -> usize;
} }
@ -149,6 +165,7 @@ impl Process {
*self.id.get() *self.id.get()
} }
/// Returns the binary name of the process
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
self.name.as_str() self.name.as_str()
} }
@ -187,7 +204,6 @@ impl Process {
self.space.as_ref() self.space.as_ref()
} }
// XXX
/// Replaces the task's session terminal device with another one /// Replaces the task's session terminal device with another one
pub fn set_session_terminal(&self, terminal: VnodeRef) { pub fn set_session_terminal(&self, terminal: VnodeRef) {
self.inner.lock().session_terminal.replace(terminal); self.inner.lock().session_terminal.replace(terminal);
@ -324,7 +340,7 @@ impl Process {
Self::get_current().unwrap() Self::get_current().unwrap()
} }
// /// Handles the cleanup of an exited process /// Handles the cleanup of an exited process
pub fn handle_exit(&self) { pub fn handle_exit(&self) {
// Queue lock is still held // Queue lock is still held
assert_eq!(self.state(), ProcessState::Terminated); assert_eq!(self.state(), ProcessState::Terminated);

View File

@ -139,7 +139,9 @@ impl CpuQueue {
/// The function is only meant to be called from kernel threads (e.g. if they want to yield /// The function is only meant to be called from kernel threads (e.g. if they want to yield
/// CPU execution to wait for something) or interrupt handlers. /// CPU execution to wait for something) or interrupt handlers.
pub unsafe fn yield_cpu(&self) { pub unsafe fn yield_cpu(&self) {
assert!(ArchitectureImpl::interrupt_mask()); // Make sure the scheduling process doesn't get interrupted
ArchitectureImpl::set_interrupt_mask(true);
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
// let t = CNTPCT_EL0.get(); // let t = CNTPCT_EL0.get();