***: fix all warnings and clippy stuff
This commit is contained in:
parent
c9af9b143a
commit
da91126293
@ -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"
|
||||||
|
@ -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);
|
||||||
|
@ -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>) {
|
||||||
|
@ -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 {
|
||||||
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}};
|
|
||||||
}
|
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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) }
|
||||||
|
@ -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> {
|
||||||
|
@ -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::{
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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)]
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
13
src/debug.rs
13
src/debug.rs
@ -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,
|
||||||
}
|
}
|
||||||
|
@ -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>);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
23
src/main.rs
23
src/main.rs
@ -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);
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user