i686: add PCI functionality for i686

This commit is contained in:
Mark Poliakov 2024-10-11 15:29:41 +03:00
parent 4b25a4db89
commit b9e2998248
49 changed files with 484 additions and 300 deletions

View File

@ -12,7 +12,7 @@ use yggdrasil_abi::{arch::SavedFrame, error::Error};
#[repr(C)]
pub struct ExceptionFrame {
/// General-purpose registers
pub r: [u64; 32],
pub r: [usize; 32],
/// SPSR_EL1, userspace flags register
pub spsr_el1: u64,
/// ELR_EL1, userspace program counter
@ -65,7 +65,7 @@ impl TaskFrame for ExceptionFrame {
}
fn argument(&self) -> u64 {
self.r[0]
self.r[0] as _
}
fn user_ip(&self) -> usize {
@ -77,11 +77,11 @@ impl TaskFrame for ExceptionFrame {
}
fn set_argument(&mut self, value: u64) {
self.r[0] = value;
self.r[0] = value as _;
}
fn set_return_value(&mut self, value: u64) {
self.r[0] = value;
self.r[0] = value as _;
}
fn set_user_ip(&mut self, value: usize) {

View File

@ -10,6 +10,7 @@ use yggdrasil_abi::{arch::SavedFrame, error::Error};
use crate::{gdt::TSS, mem::KERNEL_TABLES, registers::CR3};
#[allow(unused)]
#[repr(C)]
pub struct ExceptionFrame {
pub eax: u32,
@ -30,6 +31,7 @@ pub struct ExceptionFrame {
ss: u32,
}
#[allow(unused)]
#[derive(Debug)]
#[repr(C)]
pub struct SyscallFrame {
@ -44,6 +46,7 @@ pub struct SyscallFrame {
pub ss: u32,
}
#[allow(unused)]
#[repr(C)]
pub struct InterruptFrame {
pub eax: u32,
@ -91,7 +94,7 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
const USER_STACK_EXTRA_ALIGN: usize = 0;
fn user(context: UserContextInfo) -> Result<Self, Error> {
const USER_TASK_PAGES: usize = 8;
const USER_TASK_PAGES: usize = 16;
let stack_base_phys = PA::allocate_contiguous_pages(USER_TASK_PAGES)?;
let stack_base = stack_base_phys.raw_virtualize::<K>();
@ -218,7 +221,17 @@ impl TaskFrame for SyscallFrame {
}
fn restore(&mut self, saved: &SavedFrame) {
todo!()
self.eax = saved.eax as _;
self.args[0] = saved.ebx as _;
self.args[1] = saved.ecx as _;
self.args[2] = saved.edx as _;
self.args[3] = saved.esi as _;
self.args[4] = saved.edi as _;
self.args[5] = saved.ebp as _;
self.eip = saved.user_ip;
self.esp = saved.user_sp;
self.eflags = saved.eflags;
}
fn user_sp(&self) -> usize {
@ -230,7 +243,7 @@ impl TaskFrame for SyscallFrame {
}
fn argument(&self) -> u64 {
todo!()
self.args[0] as _
}
fn set_user_sp(&mut self, value: usize) {
@ -250,7 +263,7 @@ impl TaskFrame for SyscallFrame {
self.eax = value as usize;
}
fn set_single_step(&mut self, step: bool) {
fn set_single_step(&mut self, _step: bool) {
todo!()
}
@ -281,7 +294,7 @@ impl TaskFrame for InterruptFrame {
}
}
fn restore(&mut self, saved: &SavedFrame) {
fn restore(&mut self, _saved: &SavedFrame) {
todo!()
}
@ -314,7 +327,7 @@ impl TaskFrame for InterruptFrame {
self.eax = value as u32;
}
fn set_single_step(&mut self, step: bool) {
fn set_single_step(&mut self, _step: bool) {
todo!()
}
@ -345,7 +358,7 @@ impl TaskFrame for ExceptionFrame {
}
}
fn restore(&mut self, saved: &SavedFrame) {
fn restore(&mut self, _saved: &SavedFrame) {
todo!()
}
@ -378,7 +391,7 @@ impl TaskFrame for ExceptionFrame {
self.eax = value as u32;
}
fn set_single_step(&mut self, step: bool) {
fn set_single_step(&mut self, _step: bool) {
todo!()
}

View File

@ -3,7 +3,7 @@
extern crate alloc;
use core::ptr::{addr_of_mut, null_mut};
use core::ptr::null_mut;
use alloc::vec::Vec;
use device_api::interrupt::{LocalInterruptController, MessageInterruptController};
@ -100,11 +100,11 @@ impl Architecture for ArchitectureImpl {
}
fn message_interrupt_controller() -> &'static dyn MessageInterruptController {
loop {}
unimplemented!()
}
fn local_interrupt_controller() -> &'static dyn LocalInterruptController {
loop {}
unimplemented!()
}
fn idle_task() -> extern "C" fn(usize) -> ! {

View File

@ -1,19 +1,25 @@
use kernel_arch_interface::KERNEL_VIRT_OFFSET;
use libk_mm_interface::address::PhysicalAddress;
use kernel_arch_interface::{sync::IrqSafeSpinlock, KERNEL_VIRT_OFFSET};
use libk_mm_interface::{address::PhysicalAddress, table::EntryLevel, KernelImageObject};
use yggdrasil_abi::error::Error;
use crate::mem::KERNEL_TABLES;
use crate::{
mem::{flush_tlb_entry, table::PageAttributes, KERNEL_TABLES},
ArchitectureImpl,
};
use super::table::{PageEntry, PageTable, L0, L3};
pub const KERNEL_SPLIT_L0: usize = KERNEL_VIRT_OFFSET >> 22;
pub const DYNAMIC_MAP_COUNT: usize = 64;
pub const FIXED_MAP_COUNT: usize = 1024 - (KERNEL_SPLIT_L0 + DYNAMIC_MAP_COUNT);
pub const DYNAMIC_MAP_OFFSET: usize = (KERNEL_SPLIT_L0 + FIXED_MAP_COUNT) << L0::SHIFT;
pub const MAX_FIXED_PHYSICAL: PhysicalAddress =
PhysicalAddress::from_u64((FIXED_MAP_COUNT as u64) << 22);
#[repr(C)]
pub struct FixedTables {
pub l0: KernelL0,
pub dynamic: KernelDynamic,
pub dynamic: IrqSafeSpinlock<ArchitectureImpl, KernelDynamic>,
}
#[repr(C, align(0x1000))]
@ -23,16 +29,17 @@ pub struct KernelL0 {
pub dynamic: [PageEntry<L0>; DYNAMIC_MAP_COUNT],
}
#[allow(unused)]
pub struct KernelDynamic {
l3s: [PageTable<L3>; DYNAMIC_MAP_COUNT],
refcounts: [u32; DYNAMIC_MAP_COUNT],
pub l3s: [KernelImageObject<PageTable<L3>>; DYNAMIC_MAP_COUNT],
free: usize,
}
impl FixedTables {
pub const fn zeroed() -> Self {
Self {
l0: KernelL0::zeroed(),
dynamic: KernelDynamic::zeroed(),
dynamic: IrqSafeSpinlock::new(KernelDynamic::zeroed()),
}
}
@ -41,7 +48,7 @@ impl FixedTables {
// It's a fixed address
address.into_u64() as usize + KERNEL_VIRT_OFFSET
} else {
loop {}
todo!()
}
}
@ -54,9 +61,13 @@ impl FixedTables {
// It's a fixed address
Some(PhysicalAddress::from_usize(address - KERNEL_VIRT_OFFSET))
} else {
loop {}
todo!()
}
}
pub fn map_dynamic_memory(&mut self, base: u64, page_count: usize) -> Result<usize, Error> {
self.dynamic.lock().map(base, page_count)
}
}
impl KernelL0 {
@ -72,10 +83,47 @@ impl KernelL0 {
impl KernelDynamic {
pub const fn zeroed() -> Self {
Self {
l3s: [PageTable::zeroed(); DYNAMIC_MAP_COUNT],
refcounts: [0; DYNAMIC_MAP_COUNT],
l3s: [const { unsafe { KernelImageObject::new(PageTable::zeroed()) } };
DYNAMIC_MAP_COUNT],
free: DYNAMIC_MAP_COUNT * 1024,
}
}
fn map(&mut self, base: u64, page_count: usize) -> Result<usize, Error> {
if page_count > self.free {
return Err(Error::OutOfMemory);
}
'l0: for i in 0..DYNAMIC_MAP_COUNT * 1024 - page_count {
for j in 0..page_count {
let entry = self.entry(i + j);
if entry.is_present() {
continue 'l0;
}
}
self.free -= page_count;
for j in 0..page_count {
let address = PhysicalAddress::from_u64(base + ((j as u64) << L3::SHIFT));
*self.entry_mut(i + j) = PageEntry::page(address, PageAttributes::WRITABLE);
unsafe {
flush_tlb_entry(DYNAMIC_MAP_OFFSET + ((i + j) << L3::SHIFT));
}
}
let addr = DYNAMIC_MAP_OFFSET + (i << L3::SHIFT);
return Ok(addr);
}
Err(Error::OutOfMemory)
}
fn entry(&self, index: usize) -> &PageEntry<L3> {
&self.l3s[index / 1024][index % 1024]
}
fn entry_mut(&mut self, index: usize) -> &mut PageEntry<L3> {
&mut self.l3s[index / 1024][index % 1024]
}
}
pub fn clone_kernel_tables(dst: &mut PageTable<L0>) {
@ -83,5 +131,7 @@ pub fn clone_kernel_tables(dst: &mut PageTable<L0>) {
dst[i + KERNEL_SPLIT_L0] = *entry;
}
// TODO dynamic entries
for (i, entry) in unsafe { KERNEL_TABLES.l0.dynamic.iter().enumerate() } {
dst[i + KERNEL_SPLIT_L0 + FIXED_MAP_COUNT] = *entry;
}
}

View File

@ -3,8 +3,12 @@ use kernel_arch_interface::{
mem::{DeviceMemoryAttributes, KernelTableManager, RawDeviceMemoryMapping},
KERNEL_VIRT_OFFSET,
};
use libk_mm_interface::{address::PhysicalAddress, KernelImageObject};
use table::{PageAttributes, PageEntry};
use libk_mm_interface::{
address::{AsPhysicalAddress, PhysicalAddress},
table::page_count,
KernelImageObject,
};
use table::{PageAttributes, PageEntry, L3};
use yggdrasil_abi::error::Error;
pub mod fixed;
@ -28,6 +32,7 @@ impl KernelTableManager for KernelTableManagerImpl {
) -> Result<RawDeviceMemoryMapping<Self>, Error> {
// TODO page align up
let end = base + count as u64;
assert_eq!(base & 0xFFF, 0);
if end < fixed::MAX_FIXED_PHYSICAL.into_u64() {
// 1:1
let address = Self::virtualize(base);
@ -35,12 +40,19 @@ impl KernelTableManager for KernelTableManagerImpl {
address, address, 0, 0,
))
} else {
loop {}
assert_eq!(base & 0xFFF, 0);
log::info!("map_device_pages({:#x}, {})", base, count);
let page_count = page_count::<L3>(count);
let virt = KERNEL_TABLES.map_dynamic_memory(base, page_count)?;
Ok(RawDeviceMemoryMapping::from_raw_parts(
virt, virt, page_count, 0,
))
}
}
unsafe fn unmap_device_pages(mapping: &RawDeviceMemoryMapping<Self>) {
loop {}
unsafe fn unmap_device_pages(_mapping: &RawDeviceMemoryMapping<Self>) {
todo!()
}
fn virtualize(phys: u64) -> usize {
@ -68,6 +80,14 @@ pub unsafe fn init_fixed_tables() {
*entry = PageEntry::block(PhysicalAddress::from_u32(phys), PageAttributes::WRITABLE);
flush_tlb_entry(virt);
}
for (l0_entry, entry) in Iterator::zip(
KERNEL_TABLES.l0.dynamic.iter_mut(),
KERNEL_TABLES.dynamic.lock().l3s.iter(),
) {
let phys = entry.as_physical_address();
*l0_entry = PageEntry::table(phys, PageAttributes::WRITABLE);
}
}
/// # Safety

View File

@ -6,3 +6,6 @@ edition = "2021"
[dependencies]
yggdrasil-abi = { path = "../../../lib/abi" }
device-api = { path = "../../lib/device-api", features = ["derive"] }
[lints.rust]
unexpected_cfgs = { level = "allow", check-cfg = ['cfg(rust_analyzer)'] }

View File

@ -124,13 +124,19 @@ pub trait TaskContext<K: KernelTableManager, PA: PhysicalMemoryAllocator>: Sized
// XXX
/// Constructs a safe wrapper process to execute a kernel-space closure
fn kernel_closure<F: FnOnce() -> ! + Send + 'static>(f: F) -> Result<Self, Error> {
extern "C" fn closure_wrapper<F: FnOnce() -> ! + Send + 'static>(closure_addr: usize) -> ! {
extern "C" fn closure_wrapper<F: FnOnce() -> ! + Send + 'static>(
mut closure_addr: usize,
) -> ! {
if closure_addr == 0 {
closure_addr = align_of::<F>();
}
let closure = unsafe { Box::from_raw(closure_addr as *mut F) };
closure()
}
let closure = Box::new(f);
Self::kernel(closure_wrapper::<F>, Box::into_raw(closure) as usize)
let ptr = Box::into_raw(closure) as usize;
Self::kernel(closure_wrapper::<F>, ptr)
}
}

View File

@ -70,8 +70,8 @@ pub struct ExceptionFrame {
#[derive(Debug)]
#[repr(C)]
pub struct SyscallFrame {
pub rax: u64,
pub args: [u64; 6],
pub rax: usize,
pub args: [usize; 6],
pub rcx: u64,
pub r11: u64,
@ -254,23 +254,23 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
}
fn set_return_value(&mut self, value: u64) {
self.rax = value;
self.rax = value as _;
}
}
impl TaskFrame for SyscallFrame {
fn store(&self) -> SavedFrame {
SavedFrame {
rax: self.rax,
rax: self.rax as _,
rcx: self.rcx,
rdx: self.args[2],
rdx: self.args[2] as _,
rbx: self.rbx,
rsi: self.args[1],
rdi: self.args[0],
rsi: self.args[1] as _,
rdi: self.args[0] as _,
rbp: self.rbp,
r8: self.args[4],
r9: self.args[5],
r10: self.args[3],
r8: self.args[4] as _,
r9: self.args[5] as _,
r10: self.args[3] as _,
r11: self.r11,
r12: self.r12,
r13: self.r13,
@ -283,13 +283,13 @@ impl TaskFrame for SyscallFrame {
}
fn restore(&mut self, saved: &SavedFrame) {
self.rax = saved.rax;
self.args[0] = saved.rdi;
self.args[1] = saved.rsi;
self.args[2] = saved.rdx;
self.args[3] = saved.r10;
self.args[4] = saved.r8;
self.args[5] = saved.r9;
self.rax = saved.rax as _;
self.args[0] = saved.rdi as _;
self.args[1] = saved.rsi as _;
self.args[2] = saved.rdx as _;
self.args[3] = saved.r10 as _;
self.args[4] = saved.r8 as _;
self.args[5] = saved.r9 as _;
self.rcx = saved.rcx;
self.r11 = saved.r11;
@ -307,7 +307,7 @@ impl TaskFrame for SyscallFrame {
}
fn argument(&self) -> u64 {
self.args[0]
self.args[0] as _
}
fn user_sp(&self) -> usize {
@ -327,11 +327,11 @@ impl TaskFrame for SyscallFrame {
}
fn set_return_value(&mut self, value: u64) {
self.rax = value;
self.rax = value as _;
}
fn set_argument(&mut self, value: u64) {
self.args[0] = value;
self.args[0] = value as _;
}
fn set_single_step(&mut self, step: bool) {

View File

@ -17,3 +17,6 @@ tock-registers = "0.8.1"
[target.'cfg(target_arch = "x86_64")'.dependencies]
acpi = { git = "https://github.com/alnyan/acpi.git", package = "acpi", branch = "acpi-system" }
[lints.rust]
unexpected_cfgs = { level = "allow", check-cfg = ['cfg(rust_analyzer)'] }

View File

@ -50,7 +50,9 @@ pub enum PreferredInterruptMode {
enum ConfiguredInterruptMode {
MsiX(MsiXVectorTable<'static>),
Msi,
Legacy(PciInterruptPin),
LegacyPin(PciInterruptPin),
#[cfg_attr(not(target_arch = "x86"), allow(unused))]
LegacyLine(u8),
None,
}
@ -102,11 +104,11 @@ impl PciDeviceInfo {
} else if self.config_space.capability::<MsiCapability>().is_some() {
ConfiguredInterruptMode::Msi
} else {
self.interrupt_mode_from_pin()
self.legacy_interrupt_mode()
}
} else {
// Ignore preferred_mode, the only supported is Legacy
self.interrupt_mode_from_pin()
self.legacy_interrupt_mode()
};
IrqSafeRwLock::new(InterruptConfig {
@ -119,9 +121,16 @@ impl PciDeviceInfo {
Ok(())
}
fn interrupt_mode_from_pin(&self) -> ConfiguredInterruptMode {
fn legacy_interrupt_mode(&self) -> ConfiguredInterruptMode {
#[cfg(any(target_arch = "x86", rust_analyzer))]
{
if let Some(irq) = self.config_space.interrupt_line() {
return ConfiguredInterruptMode::LegacyLine(irq);
}
}
match self.config_space.interrupt_pin() {
Some(pin) => ConfiguredInterruptMode::Legacy(pin),
Some(pin) => ConfiguredInterruptMode::LegacyPin(pin),
None => ConfiguredInterruptMode::None,
}
}
@ -149,10 +158,14 @@ impl PciDeviceInfo {
Ok(Some(info))
}
ConfiguredInterruptMode::Legacy(pin) => {
ConfiguredInterruptMode::LegacyPin(pin) => {
self.try_map_legacy(*pin, handler)?;
Ok(None)
}
ConfiguredInterruptMode::LegacyLine(irq) => {
self.try_map_legacy_line(*irq, handler)?;
Ok(None)
}
ConfiguredInterruptMode::None => Err(Error::InvalidOperation),
}
}
@ -203,6 +216,16 @@ impl PciDeviceInfo {
register_global_interrupt(route.number, route.options, handler)
}
fn try_map_legacy_line(
&self,
line: u8,
handler: &'static dyn InterruptHandler,
) -> Result<(), Error> {
log::debug!("PCI {} -> IRQ#{}", self.address, line);
register_global_interrupt(line as _, Default::default(), handler)
}
}
impl TryFrom<u32> for PciInterruptPin {

View File

@ -122,7 +122,7 @@ struct BusAddressAllocator {
offset_32: u32,
}
#[cfg_attr(target_arch = "x86_64", allow(dead_code))]
#[cfg_attr(any(target_arch = "x86_64", target_arch = "x86"), allow(dead_code))]
impl BusAddressAllocator {
pub fn from_ranges(ranges: &[PciAddressRange]) -> Self {
let mut range_32 = None;

View File

@ -1,4 +1,4 @@
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
use libk_util::OneTimeInit;
use yggdrasil_abi::error::Error;
use crate::{PciAddress, PciConfigurationSpace};

View File

@ -220,6 +220,15 @@ pub trait PciConfigurationSpace {
PciInterruptPin::try_from(self.read_u8(0x3D) as u32).ok()
}
fn interrupt_line(&self) -> Option<u8> {
let value = self.read_u8(0x3C);
if value < 16 {
Some(value)
} else {
None
}
}
/// # Safety
///
/// This function is only meant to be called before the device has seen any use by the OS,

View File

@ -1,6 +1,6 @@
use core::any::Any;
use alloc::{string::String, sync::Arc, vec::Vec};
use alloc::{sync::Arc, vec::Vec};
use libk::{
block,
error::Error,
@ -63,7 +63,7 @@ impl SymlinkNode {
}
impl CommonImpl for SymlinkNode {
fn size(&self, node: &NodeRef) -> Result<u64, Error> {
fn size(&self, _node: &NodeRef) -> Result<u64, Error> {
Ok(self.inode.size_lower as _)
}
@ -71,7 +71,7 @@ impl CommonImpl for SymlinkNode {
self
}
fn metadata(&self, node: &NodeRef) -> Result<Metadata, Error> {
fn metadata(&self, _node: &NodeRef) -> Result<Metadata, Error> {
Ok(self.inode.metadata())
}
}

View File

@ -6,8 +6,8 @@ use core::task::{Context, Poll};
use alloc::boxed::Box;
use async_trait::async_trait;
use libk::vfs::{CharDevice, FileReadiness, TerminalInput};
use libk_util::{ring::LossyRingQueue, sync::spin_rwlock::IrqSafeRwLock, StaticVector};
use libk::vfs::{CharDevice, FileReadiness};
use libk_util::ring::LossyRingQueue;
use yggdrasil_abi::{
error::Error,
io::{DeviceRequest, KeyboardKeyEvent},

View File

@ -92,6 +92,7 @@ impl NetworkInterface {
ArpTable::flush_address(self.id, address);
}
log::info!("Assigned address: {:?} -> {:?}", self.name, address);
addr.replace(address);
ArpTable::insert_address(self.id, self.mac, address, true);

View File

@ -100,12 +100,11 @@ pub fn probe(info: &PciDeviceInfo) -> Result<&'static dyn Device, Error> {
cmd |= PciCommandRegister::ENABLE_MEMORY | PciCommandRegister::BUS_MASTER;
info.config_space.set_command(cmd.bits());
todo!()
// let regs = unsafe { xhci_lib::Registers::new(bar0.into(), Mapper::new()) };
// let xhci = Box::leak(Box::new(Xhci::new(regs)?));
let regs = unsafe { xhci_lib::Registers::new(bar0.try_into_usize().unwrap(), Mapper::new()) };
let xhci = Box::leak(Box::new(Xhci::new(regs)?));
// info.init_interrupts(PreferredInterruptMode::Msi)?;
// info.map_interrupt(InterruptAffinity::Any, xhci)?;
info.init_interrupts(PreferredInterruptMode::Msi)?;
info.map_interrupt(InterruptAffinity::Any, xhci)?;
// Ok(xhci)
Ok(xhci)
}

View File

@ -64,7 +64,7 @@ pub struct VirtQueue {
impl AvailableRing {
pub fn with_capacity(no_irq: bool, capacity: usize) -> Result<Self, Error> {
let mut data = PageBox::new_uninit_slice(capacity + 3)?;
let mut data = PageBox::new_zeroed_slice(capacity + 3)?;
if no_irq {
data[0].write(1);
@ -86,7 +86,7 @@ impl AvailableRing {
impl UsedRing {
pub fn with_capacity(capacity: usize) -> Result<Self, Error> {
let mut data = PageBox::new_uninit_slice(capacity * 2 + 2)?;
let mut data = PageBox::new_zeroed_slice(capacity * 2 + 2)?;
data[0].write(0);
@ -127,7 +127,7 @@ impl VirtQueue {
return Err(Error::QueueTooLarge);
}
let descriptor_table = PageBox::new_uninit_slice(capacity)?;
let descriptor_table = PageBox::new_zeroed_slice(capacity)?;
let available = AvailableRing::with_capacity(no_avail_irq, capacity)?;
let used = UsedRing::with_capacity(capacity)?;

View File

@ -14,3 +14,6 @@ discrete_range_map = { git = "https://git.alnyan.me/yggdrasil/discrete_range_map
[dev-dependencies]
itertools = "0.11.0"
proptest = "1.2.0"
[lints.rust]
unexpected_cfgs = { level = "allow", check-cfg = ['cfg(rust_analyzer)'] }

View File

@ -12,3 +12,6 @@ kernel-arch-interface = { path = "../../../arch/interface" }
bitflags = "2.6.0"
bytemuck = { version = "1.16.1", features = ["derive"] }
[lints.rust]
unexpected_cfgs = { level = "allow", check-cfg = ['cfg(rust_analyzer)'] }

View File

@ -1,7 +1,7 @@
//! Kernel's global heap allocator
use core::{
alloc::{GlobalAlloc, Layout},
ptr::{null_mut, NonNull},
ptr::NonNull,
};
use kernel_arch::KernelTableManagerImpl;
@ -52,8 +52,7 @@ unsafe impl GlobalAlloc for KernelAllocator {
match self.inner.lock().allocate(layout) {
Some(p) => p.as_ptr(),
None => {
log::error!("Failed to allocate {:?}", layout);
null_mut()
panic!("Failed to allocate {:?}", layout);
}
}
}

View File

@ -79,17 +79,20 @@ impl PhysicalMemoryAllocator for GlobalPhysicalAllocator {
/// Allocates a single physical page from the global manager
pub fn alloc_page() -> Result<PhysicalAddress, Error> {
PHYSICAL_MEMORY.get().lock().alloc_page()
let p = PHYSICAL_MEMORY.get().lock().alloc_page();
p
}
/// Allocates a contiguous range of physical pages from the global manager
pub fn alloc_pages_contiguous(count: usize) -> Result<PhysicalAddress, Error> {
PHYSICAL_MEMORY.get().lock().alloc_contiguous_pages(count)
let p = PHYSICAL_MEMORY.get().lock().alloc_contiguous_pages(count);
p
}
/// Allocates a single 2MiB page of physical memory from the global manager
pub fn alloc_2m_page() -> Result<PhysicalAddress, Error> {
PHYSICAL_MEMORY.get().lock().alloc_2m_page()
let p = PHYSICAL_MEMORY.get().lock().alloc_2m_page();
p
}
/// Returns physical memory stats

View File

@ -54,6 +54,15 @@ impl<T: Copy> RingBuffer<T> {
})
}
pub fn reserve(&mut self) -> Result<(), Error> {
if self.data.is_none() {
let buffer =
Box::try_new_uninit_slice(self.capacity).map_err(|_| Error::OutOfMemory)?;
self.data = Some(buffer);
}
Ok(())
}
const fn readable_count_at(&self, at: usize) -> usize {
if at <= self.wr {
self.wr - at

View File

@ -57,7 +57,11 @@ pub fn load_kernel_symbol_table<P: AsRef<Path>>(
ioctx: &mut IoContext,
path: P,
) -> Result<(), Error> {
let symbol_file = ioctx.open(None, path, OpenOptions::READ, FileMode::empty())?;
let symbol_file = match ioctx.open(None, path, OpenOptions::READ, FileMode::empty()) {
Ok(file) => file,
Err(Error::DoesNotExist) => return Ok(()),
Err(err) => return Err(err),
};
let mut string_buffer = PageBox::new_slice(0, 4096)?;
let mut map = DefaultHashTable::new();

View File

@ -472,9 +472,8 @@ fn write_rela(rela: &Rela, space: &ProcessAddressSpace, b: usize) -> Result<(),
match width {
8 => {
todo!();
// unsafe { (dst.as_mut_ptr() as *mut u64).write_volatile(value as u64) };
// Ok(())
unsafe { (dst.as_mut_ptr() as *mut u64).write_volatile(value as u64) };
Ok(())
}
_ => todo!("Unhandled relocation width: {}", width),
}

View File

@ -147,6 +147,7 @@ fn setup_context(
virt_stack_base + USER_STACK_PAGES * 0x1000 - TaskContextImpl::USER_STACK_EXTRA_ALIGN;
// Fill with some sentinel value to detect stack underflows
#[allow(unused_mut)]
let mut ptr = user_sp as *mut usize;
#[cfg(any(target_arch = "x86", rust_analyzer))]

View File

@ -1,6 +1,5 @@
use core::{
fmt,
mem::size_of,
sync::atomic::{AtomicU32, AtomicU64, Ordering},
};
@ -157,6 +156,8 @@ impl AllocateProcessId for ProcessId {
impl ProcessTlsLayout {
/// Constructs a new thread-local storage layout info struct
pub fn new(align: usize, data_size: usize, mem_size: usize) -> Self {
use core::mem::size_of;
debug_assert!(align.is_power_of_two());
let tls_block0_offset = (size_of::<usize>() * 2 + align - 1) & !(align - 1);
@ -178,6 +179,8 @@ impl ProcessTlsLayout {
impl ProcessTlsLayout {
/// Constructs a new thread-local storage layout info struct
pub fn new(align: usize, data_size: usize, mem_size: usize) -> Self {
use core::mem::size_of;
// The static TLS blocks are placed below TP
// TP points to the TCB
debug_assert!(align.is_power_of_two());
@ -201,7 +204,7 @@ impl ProcessTlsLayout {
#[cfg(any(target_arch = "x86", rust_analyzer))]
impl ProcessTlsLayout {
pub fn new(align: usize, data_size: usize, mem_size: usize) -> Self {
pub fn new(_align: usize, _data_size: usize, _mem_size: usize) -> Self {
todo!()
}
}

View File

@ -263,7 +263,7 @@ dependencies = [
"device-api",
"kernel-arch-interface",
"libk-mm-interface",
"memtables",
"log",
"static_assertions",
"tock-registers",
"yggdrasil-abi",

View File

@ -175,7 +175,7 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) {
// SVC in AArch64
0b010101 => {
let func = frame.r[8];
if func == usize::from(SyscallFunction::ExitSignal) as u64 {
if func == usize::from(SyscallFunction::ExitSignal) {
unsafe {
syscall::handle_signal_exit(frame);
}
@ -183,7 +183,7 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) {
}
let args = &frame.r[0..6];
let result = raw_syscall_handler(func, args);
let result = raw_syscall_handler(func, args) as _;
frame.r[0] = result;
}
// Software Step from lower Exception Level

View File

@ -1,121 +1,16 @@
use core::arch::global_asm;
use bytemuck::{Pod, Zeroable};
use kernel_arch_i686::{
mem::KERNEL_TABLES,
registers::{CR0, CR4},
};
use kernel_fs::devfs;
use libk::task::runtime;
use libk_mm::{
address::{PhysicalAddress, Virtualize},
phys::PhysicalMemoryRegion,
pointer::PhysicalRef,
};
use tock_registers::interfaces::ReadWriteable;
use kernel_arch_i686::mem::KERNEL_TABLES;
use libk_mm::{address::PhysicalAddress, pointer::PhysicalRef};
use multiboot::MultibootInfo;
use crate::{arch::x86::gdt, kernel_main, mem::KERNEL_VIRT_OFFSET};
use crate::{kernel_main, mem::KERNEL_VIRT_OFFSET};
use super::{exception, I686, PLATFORM};
use super::PLATFORM;
const BOOT_STACK_SIZE: usize = 64 * 1024;
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
#[repr(C)]
pub struct MultibootInfo {
pub flags: u32,
pub mem_lower: u32,
pub mem_upper: u32,
pub boot_device: u32,
pub cmdline: u32,
pub mods_count: u32,
pub mods_addr: u32,
pub syms: [u32; 4],
pub mmap_length: u32,
pub mmap_addr: u32,
// ...
}
#[derive(Clone)]
pub struct MultibootMemoryMapIter<'a> {
multiboot_info: &'a MultibootInfo,
base: usize,
pos: usize,
}
#[derive(Clone)]
pub struct MultibootModuleIter<'a> {
multiboot_info: &'a MultibootInfo,
base: usize,
pos: usize,
}
#[derive(Clone, Copy, Debug)]
#[repr(C, packed)]
pub struct MultibootMemoryMapEntry {
pub size: u32,
pub addr: u64,
pub len: u64,
pub ty: u32,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MultibootModuleEntry {
pub mod_start: u32,
pub mod_end: u32,
pub cmdline: u32,
_pad: u32,
}
impl<'a> Iterator for MultibootMemoryMapIter<'a> {
type Item = PhysicalMemoryRegion;
fn next(&mut self) -> Option<Self::Item> {
loop {
if self.pos + size_of::<MultibootMemoryMapEntry>()
>= self.multiboot_info.mmap_length as usize
{
return None;
}
let entry: &MultibootMemoryMapEntry =
unsafe { core::mem::transmute(self.base + self.pos) };
self.pos += entry.size as usize + size_of::<u32>();
if !entry.is_available() {
continue;
}
return Some(PhysicalMemoryRegion {
base: PhysicalAddress::from_u64(entry.addr),
size: entry.len.try_into().unwrap(),
});
}
}
}
impl MultibootInfo {
pub fn memory_map_iter(&self) -> MultibootMemoryMapIter {
MultibootMemoryMapIter {
multiboot_info: self,
base: PhysicalAddress::from_u32(self.mmap_addr).virtualize(),
pos: 0,
}
}
pub fn modules(&self) -> &[MultibootModuleEntry] {
let base = PhysicalAddress::from_u32(self.mods_addr).virtualize();
unsafe { core::slice::from_raw_parts(base as *const _, self.mods_count as usize) }
}
}
impl MultibootMemoryMapEntry {
pub fn is_available(&self) -> bool {
self.ty == 1
}
}
pub mod multiboot;
#[repr(C, align(0x20))]
struct BootStack {

View File

@ -0,0 +1,94 @@
use libk_mm::{
address::{PhysicalAddress, Virtualize},
phys::PhysicalMemoryRegion,
};
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MultibootInfo {
pub flags: u32,
pub mem_lower: u32,
pub mem_upper: u32,
pub boot_device: u32,
pub cmdline: u32,
pub mods_count: u32,
pub mods_addr: u32,
pub syms: [u32; 4],
pub mmap_length: u32,
pub mmap_addr: u32,
// ...
}
#[derive(Clone)]
pub struct MultibootMemoryMapIter<'a> {
multiboot_info: &'a MultibootInfo,
base: usize,
pos: usize,
}
#[derive(Clone, Copy, Debug)]
#[repr(C, packed)]
pub struct MultibootMemoryMapEntry {
pub size: u32,
pub addr: u64,
pub len: u64,
pub ty: u32,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MultibootModuleEntry {
pub mod_start: u32,
pub mod_end: u32,
pub cmdline: u32,
_pad: u32,
}
impl<'a> Iterator for MultibootMemoryMapIter<'a> {
type Item = PhysicalMemoryRegion;
fn next(&mut self) -> Option<Self::Item> {
loop {
if self.pos + size_of::<MultibootMemoryMapEntry>()
>= self.multiboot_info.mmap_length as usize
{
return None;
}
let entry: &MultibootMemoryMapEntry =
unsafe { core::mem::transmute(self.base + self.pos) };
self.pos += entry.size as usize + size_of::<u32>();
if !entry.is_available() {
continue;
}
return Some(PhysicalMemoryRegion {
base: PhysicalAddress::from_u64(entry.addr),
size: entry.len.try_into().unwrap(),
});
}
}
}
impl MultibootInfo {
pub fn memory_map_iter(&self) -> MultibootMemoryMapIter {
MultibootMemoryMapIter {
multiboot_info: self,
base: PhysicalAddress::from_u32(self.mmap_addr).virtualize(),
pos: 0,
}
}
pub fn modules(&self) -> &[MultibootModuleEntry] {
let base = PhysicalAddress::from_u32(self.mods_addr).virtualize();
unsafe { core::slice::from_raw_parts(base as *const _, self.mods_count as usize) }
}
}
impl MultibootMemoryMapEntry {
pub fn is_available(&self) -> bool {
self.ty == 1
}
}

View File

@ -1,9 +1,8 @@
use core::{arch::global_asm, ptr::addr_of};
use abi::{primitive_enum, process::Signal};
use abi::{primitive_enum, process::Signal, SyscallFunction};
use kernel_arch_i686::context::{ExceptionFrame, SyscallFrame};
use libk::task::thread::Thread;
use static_assertions::const_assert_eq;
use crate::{arch::x86::peripherals::i8259, syscall};
@ -165,7 +164,7 @@ fn kernel_exception_inner(kind: ExceptionKind, frame: &ExceptionFrame) -> ! {
panic!("Irrecoverable exception")
}
fn user_exception_inner(kind: ExceptionKind, frame: &ExceptionFrame) {
fn user_exception_inner(kind: ExceptionKind, _frame: &ExceptionFrame) {
let thread = Thread::current();
let cr3: usize;
unsafe {
@ -214,6 +213,21 @@ extern "C" fn __i686_exception_handler(frame: *mut ExceptionFrame) {
extern "C" fn __i686_syscall_handler(frame: *mut SyscallFrame) {
let frame = unsafe { &mut *frame };
if frame.eax == usize::from(SyscallFunction::ExitSignal) {
unsafe {
syscall::handle_signal_exit(frame);
return;
}
}
if frame.eax == usize::from(SyscallFunction::Fork) {
todo!()
// unsafe {
// Process::raw_fork(frame);
// return;
// }
}
// TODO check that cs == 0x1B, kernel to kernel syscalls disallowed
let result = syscall::raw_syscall_handler(frame.eax, &frame.args);

View File

@ -1,9 +1,6 @@
#![allow(missing_docs)]
use abi::{
error::Error,
io::{KeyboardKey, KeyboardKeyEvent},
};
use boot::{MultibootInfo, MultibootMemoryMapEntry};
use abi::error::Error;
use boot::multiboot::MultibootInfo;
use device_api::{
interrupt::{IpiDeliveryTarget, IpiMessage, Irq},
Device, ResetDevice,
@ -14,7 +11,7 @@ use kernel_fs::devfs::{self, CharDeviceType};
use libk::{
arch::Cpu,
task::runtime,
vfs::{CharDevice, Terminal, TerminalInput},
vfs::{Terminal, TerminalInput},
};
use libk_device::{register_external_interrupt_controller, register_monotonic_timestamp_provider};
use libk_mm::{
@ -40,7 +37,7 @@ use crate::{
debug::{self, LogLevel},
device::{
self,
display::console::{add_console_autoflush, ConsoleWrapper, DisplayConsole},
display::console::{add_console_autoflush, ConsoleWrapper},
},
fs::{Initrd, INITRD_DATA},
};
@ -89,7 +86,7 @@ impl Platform for I686 {
loop {}
}
unsafe fn send_ipi(&self, target: IpiDeliveryTarget, msg: IpiMessage) -> Result<(), Error> {
unsafe fn send_ipi(&self, _target: IpiDeliveryTarget, _msg: IpiMessage) -> Result<(), Error> {
Ok(())
}
@ -97,8 +94,8 @@ impl Platform for I686 {
// No APs in i686, go get a better CPU
}
fn register_reset_device(&self, reset: &'static dyn ResetDevice) -> Result<(), Error> {
loop {}
fn register_reset_device(&self, _reset: &'static dyn ResetDevice) -> Result<(), Error> {
todo!()
}
}
@ -135,8 +132,6 @@ impl I686 {
.init(ComPort::new(0x3F8, 0x3E8, Irq::External(4)));
debug::add_sink(com1_3.port_a(), LogLevel::Debug);
debug::init();
reserve_region(
"lowmem",
PhysicalMemoryRegion {
@ -169,6 +164,8 @@ impl I686 {
// Initialize physical memory
phys::init_from_iter(multiboot_info.memory_map_iter(), |_, _, _| Ok(()))?;
debug::init();
unsafe {
gdt::init();
exception::init_exceptions();
@ -180,6 +177,29 @@ impl I686 {
runtime::init_task_queue();
devfs::init();
// Register the PCI drivers
// TODO make this implicit init
ygg_driver_pci::register_class_driver(
"AHCI SATA Controller",
0x01,
Some(0x06),
Some(0x01),
ygg_driver_ahci::probe,
);
ygg_driver_pci::register_class_driver(
"USB xHCI",
0x0C,
Some(0x03),
Some(0x30),
ygg_driver_usb_xhci::probe,
);
ygg_driver_pci::register_vendor_driver(
"Virtio PCI Network Device",
0x1AF4,
0x1000,
ygg_driver_virtio_net::probe,
);
I8259.init().expect("Could not initialize i8259 PIC");
register_external_interrupt_controller(&I8259);
I8253.init().expect("Could not initialize i8253 Timer");

View File

@ -135,7 +135,7 @@ fn convert_attrs(ch: &ConsoleChar) -> u8 {
if attr.contains(Attributes::BOLD) {
fg += 8;
}
(fg | (bg << 4))
fg | (bg << 4)
}
fn convert_color(c: ColorAttribute) -> u8 {

View File

@ -1,7 +1,3 @@
use core::mem::size_of;
use alloc::boxed::Box;
#[allow(dead_code)]
#[repr(packed)]
struct Entry {
@ -31,9 +27,6 @@ impl Entry {
#[allow(unused)]
const ACC_ACCESS: u8 = 1 << 0;
const FLAG_4K: u8 = 1 << 7;
const FLAG_32: u8 = 1 << 6;
const NULL: Self = Self {
base_lo: 0,
base_mi: 0,
@ -57,6 +50,8 @@ impl Entry {
#[cfg(any(target_arch = "x86", rust_analyzer))]
mod imp {
use core::ptr::addr_of_mut;
use alloc::boxed::Box;
use super::{Entry, Pointer};
@ -64,6 +59,9 @@ mod imp {
pub use kernel_arch_i686::gdt::{Tss, TSS};
impl Entry {
const FLAG_4K: u8 = 1 << 7;
const FLAG_32: u8 = 1 << 6;
const RING0_CS32: Entry = Entry::new(
0,
0xFFFFF,
@ -99,12 +97,12 @@ mod imp {
}
}
pub fn create_gdt() -> (&'static [Entry], &'static Tss) {
pub(super) fn create_gdt() -> (&'static [Entry], &'static Tss) {
// Won't be deallocated, so leaks are not a concern
let tss = unsafe { &mut TSS };
let tss = unsafe { &mut *addr_of_mut!(TSS) };
tss.ss0 = 0x10;
let tss_addr = (tss as *mut Tss).addr();
let mut gdt = Box::new([
let gdt = Box::new([
Entry::NULL,
Entry::RING0_CS32,
Entry::RING0_DS32,
@ -116,7 +114,7 @@ mod imp {
(Box::leak(gdt), tss)
}
pub unsafe fn load_gdt(gdt: &'static [Entry]) {
pub(super) unsafe fn load_gdt(gdt: &'static [Entry]) {
let gdt_addr = gdt.as_ptr().addr();
let gdtr = Pointer {
limit: (gdt.len() * size_of::<Entry>()) as u16 - 1,
@ -150,11 +148,13 @@ mod imp {
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
mod imp {
use alloc::boxed::Box;
use super::{Entry, Pointer};
#[allow(dead_code)]
#[repr(packed)]
struct Tss {
pub struct Tss {
_0: u32,
rsp0: u64,
rsp1: u64,
@ -230,10 +230,10 @@ mod imp {
}
}
pub fn create_gdt() -> (&'static [Entry], &'static Tss) {
pub(super) fn create_gdt() -> (&'static [Entry], &'static Tss) {
// Won't be deallocated, so leaks are not a concern
let tss = Box::leak(Box::new(Tss::NULL));
let tss_addr = (tss as *mut _).addr();
let tss_addr = (tss as *mut Tss).addr();
let mut gdt = Box::new([
Entry::NULL,
Entry::RING0_CS64,
@ -247,16 +247,13 @@ mod imp {
let tss_high = &mut gdt[6] as *mut _ as *mut u64;
unsafe { tss_high.write_unaligned((tss_addr >> 32) as u64) };
Box::leak(gdt)
// let gdt_addr = Box::into_raw(gdt) as usize;
// todo!()
(Box::leak(gdt), tss)
}
pub unsafe fn load_gdt(gdt: &'static [Entry]) {
pub(super) unsafe fn load_gdt(gdt: &'static [Entry]) {
let gdt_addr = gdt.as_ptr().addr();
let gdtr = Pointer {
limit: (GDT_SIZE * size_of::<Entry>()) as u16 - 1,
limit: (gdt.len() * size_of::<Entry>()) as u16 - 1,
offset: gdt_addr,
};

View File

@ -3,7 +3,7 @@
#![allow(missing_docs)]
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
pub const ISA_IRQ_OFFSET: u32 = ISA_IRQ_OFFSET;
pub const ISA_IRQ_OFFSET: u32 = crate::arch::x86_64::ISA_IRQ_OFFSET;
#[cfg(any(target_arch = "x86", rust_analyzer))]
pub const ISA_IRQ_OFFSET: u32 = 0;

View File

@ -1,7 +1,5 @@
//! Intel 8259 interrupt controller
use core::arch::global_asm;
use abi::error::Error;
use device_api::{
interrupt::{
@ -10,18 +8,14 @@ use device_api::{
},
Device,
};
use kernel_arch::task::Scheduler;
use kernel_arch_i686::context::InterruptFrame;
use libk::{
arch::Cpu,
task::{sched, thread::Thread},
};
use libk_util::sync::IrqSafeSpinlock;
use crate::arch::{
i686::exception,
x86::intrinsics::{IoPort, IoPortAccess},
};
use crate::arch::x86::intrinsics::{IoPort, IoPortAccess};
#[cfg(any(target_arch = "x86", rust_analyzer))]
use crate::arch::i686::exception;
#[cfg(any(target_arch = "x86", rust_analyzer))]
use kernel_arch_i686::context::InterruptFrame;
use super::i8253::I8253;
@ -56,6 +50,7 @@ impl Device for I8259 {
impl ExternalInterruptController for I8259 {
fn enable_irq(&self, irq: Irq) -> Result<(), Error> {
let Irq::External(irq) = irq else { panic!() };
log::debug!("Enable IRQ#{}", irq);
let inner = self.inner.lock();
let port = if irq < 8 {
&inner.master_data
@ -63,7 +58,6 @@ impl ExternalInterruptController for I8259 {
&inner.slave_data
};
let mask = port.read();
log::debug!("Enable IRQ#{}", irq);
port.write(mask & !(1 << (irq % 8)));
Ok(())
}
@ -71,7 +65,7 @@ impl ExternalInterruptController for I8259 {
fn register_irq(
&self,
irq: Irq,
options: IrqOptions,
_options: IrqOptions,
handler: &'static dyn InterruptHandler,
) -> Result<(), Error> {
let Irq::External(irq) = irq else {
@ -96,15 +90,13 @@ impl ExternalInterruptController for I8259 {
I8253.irq_handler_fastpath();
} else if index < 16 {
// Rest of IRQs
self.eoi(index);
let table = self.table.lock();
if let Some(handler) = table.handler(index - 1) {
handler.handle_irq(None);
} else {
warnln!("No handler set for IRQ#{}", index);
}
self.eoi(index);
}
}
}
@ -161,16 +153,19 @@ impl I8259 {
inner.master_data.write(ICW4_8086);
inner.slave_data.write(ICW4_8086);
// Mask everything
inner.master_data.write(0xFF);
// Mask everything (except IRQ#2 on master, used for cascading)
inner.master_data.write(0xFF & !(1 << 2));
inner.slave_data.write(0xFF);
inner.master_cmd.write(0x20);
inner.slave_cmd.write(0x20);
}
pub fn eoi(&self, index: usize) {
let inner = self.inner.lock();
inner.master_cmd.write(0x20);
if index >= 12 {
if index >= 8 {
inner.slave_cmd.write(0x20);
}
}
@ -178,6 +173,7 @@ impl I8259 {
pub static I8259: I8259 = I8259::new();
#[cfg(any(target_arch = "x86", rust_analyzer))]
pub fn setup_vectors(idt: &mut [exception::Entry]) {
extern "C" {
// IRQ vectors
@ -193,7 +189,10 @@ pub fn setup_vectors(idt: &mut [exception::Entry]) {
}
}
#[cfg(any(target_arch = "x86", rust_analyzer))]
extern "C" fn irq_handler(frame: *mut InterruptFrame) {
use libk::task::thread::Thread;
let frame = unsafe { &mut *frame };
I8259.handle_specific_irq(frame.irq_number as _);
@ -203,4 +202,5 @@ extern "C" fn irq_handler(frame: *mut InterruptFrame) {
}
}
global_asm!(include_str!("i8259_vectors.S"), irq_handler = sym irq_handler, options(att_syntax));
#[cfg(any(target_arch = "x86", rust_analyzer))]
core::arch::global_asm!(include_str!("i8259_vectors.S"), irq_handler = sym irq_handler, options(att_syntax));

View File

@ -31,19 +31,11 @@ mod apic;
mod boot;
mod cpuid;
mod exception;
#[path = "../i686/intrinsics.rs"]
mod intrinsics;
mod smp;
mod syscall;
use crate::{
arch::{
x86::peripherals::{i8253::I8253, i8259::I8259, ps2::PS2},
x86_64::{
apic::ioapic::ISA_IRQ_OFFSET,
intrinsics::{IoPort, IoPortAccess},
},
},
arch::x86::peripherals::{i8253::I8253, i8259::I8259, ps2::PS2, serial::ComPort},
debug::{self, LogLevel},
device::{
self,
@ -57,10 +49,15 @@ use self::{
apic::{ioapic::IoApic, local::LocalApic},
boot::BootData,
cpuid::{ProcessorFeatures, PROCESSOR_FEATURES},
peripherals::{i8253::I8253, ps2::PS2Controller, serial::ComPort},
};
use super::{IpiMessage, Platform};
use super::{
x86::{gdt, intrinsics},
IpiMessage, Platform,
};
/// Offset where legacy ISA IRQs are remapped
pub const ISA_IRQ_OFFSET: u32 = apic::ioapic::ISA_IRQ_OFFSET;
/// x86-64 architecture implementation
pub struct X86_64 {
@ -342,7 +339,7 @@ impl X86_64 {
I8253.init_irq()?;
// ps2.connect(self.tty.get());
ps2.init_irq()?;
PS2.init_irq()?;
device::register_device(&PS2);

View File

@ -13,13 +13,13 @@ use tock_registers::interfaces::{ReadWriteable, Writeable};
use crate::syscall::{self, raw_syscall_handler};
fn syscall_inner(frame: &mut SyscallFrame) {
if frame.rax == usize::from(SyscallFunction::ExitSignal) as u64 {
if frame.rax == usize::from(SyscallFunction::ExitSignal) {
unsafe {
syscall::handle_signal_exit(frame);
return;
}
}
if frame.rax == usize::from(SyscallFunction::Fork) as u64 {
if frame.rax == usize::from(SyscallFunction::Fork) {
unsafe {
Process::raw_fork(frame);
return;
@ -28,7 +28,7 @@ fn syscall_inner(frame: &mut SyscallFrame) {
let result = raw_syscall_handler(frame.rax, &frame.args);
frame.rax = result;
frame.rax = result as _;
}
extern "C" fn __x86_64_syscall_handler(frame: *mut SyscallFrame) {

View File

@ -1,5 +1,8 @@
//! Utilities for debug information logging
use core::fmt::{self, Arguments};
use core::{
fmt::{self, Arguments},
sync::atomic::{AtomicBool, Ordering},
};
use abi::error::Error;
use libk::task::process::Process;
@ -8,6 +11,8 @@ use libk_util::{ring::RingBuffer, sync::IrqSafeSpinlock, StaticVector};
const MAX_DEBUG_SINKS: usize = 4;
const RING_LOGGER_CAPACITY: usize = 65536;
static RING_AVAILABLE: AtomicBool = AtomicBool::new(false);
struct SimpleLogger;
struct RingLoggerInner {
@ -178,6 +183,10 @@ impl RingLoggerSink {
use fmt::Write;
self.inner.lock().write_fmt(args)
}
fn init_buffer(&self) -> Result<(), Error> {
self.inner.lock().data.reserve()
}
}
impl fmt::Write for RingLoggerInner {
@ -252,6 +261,10 @@ pub fn program_trace(process: &Process, message: &str) {
/// Resets the debugging terminal by clearing it
pub fn init() {
if RING_LOGGER_SINK.init_buffer().is_ok() {
RING_AVAILABLE.store(true, Ordering::Release);
}
log::set_logger(&LOGGER)
.map(|_| log::set_max_level(log::LevelFilter::Trace))
.ok();
@ -263,7 +276,9 @@ pub fn init() {
pub fn debug_internal(args: Arguments, level: LogLevel) {
use fmt::Write;
// RING_LOGGER_SINK.write_fmt(args).ok();
if RING_AVAILABLE.load(Ordering::Acquire) {
RING_LOGGER_SINK.write_fmt(args).ok();
}
for sink in DEBUG_SINKS.lock().iter_mut() {
if level < sink.level {

View File

@ -71,7 +71,7 @@ pub fn kinit() -> Result<(), Error> {
// TODO move this to userspace so it doesn't block the init process, maybe lazy-load on first
// attempt to load a module?
// load_kernel_symbol_table(&mut ioctx, "/kernel.sym")?;
load_kernel_symbol_table(&mut ioctx, "/kernel.sym")?;
{
let group_id = Process::create_group();

View File

@ -37,7 +37,6 @@
#![no_std]
#![no_main]
use alloc::boxed::Box;
use arch::Platform;
use kernel_arch::{Architecture, ArchitectureImpl};
use libk::arch::Cpu;

View File

@ -209,12 +209,16 @@ pub(crate) fn mutex(mutex: &AtomicU32, op: &MutexOperation) -> Result<(), Error>
let mutex = process.get_or_insert_mutex((mutex as *const AtomicU32).addr());
match op {
&MutexOperation::Wait(value, _timeout) => block! { mutex.wait(value).await }.unwrap(),
MutexOperation::Wake => mutex.wake(),
MutexOperation::WakeAll => mutex.wake_all(),
&MutexOperation::Wait(value, _timeout) => block! { mutex.wait(value).await },
MutexOperation::Wake => {
mutex.wake();
Ok(())
}
MutexOperation::WakeAll => {
mutex.wake_all();
Ok(())
}
}
Ok(())
}
pub(crate) fn start_session() -> Result<(), Error> {

View File

@ -4,7 +4,7 @@
#[derive(Clone, Debug, Default)]
#[repr(C)]
pub struct SavedFrame {
pub gp_regs: [u64; 32],
pub gp_regs: [usize; 32],
pub spsr_el1: u64,
pub elr_el1: u64,
pub sp_el0: u64,

View File

@ -14,7 +14,7 @@ use super::{
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
#[repr(C)]
#[repr(C, packed)]
pub struct EthernetFrame {
pub destination_mac: MacAddress,
pub source_mac: MacAddress,

View File

@ -6,7 +6,6 @@ use std::{
fd::AsRawFd,
yggdrasil::{
io::{poll::PollChannel, raw_socket::RawSocket, timer::TimerFd},
signal::{set_signal_handler, Signal, SignalHandler},
},
},
process::ExitCode,
@ -319,14 +318,10 @@ fn ping(
Ok(stats)
}
fn interrupt(_: Signal) {
INTERRUPTED.store(true, Ordering::Release);
}
static INTERRUPTED: AtomicBool = AtomicBool::new(false);
fn main() -> ExitCode {
set_signal_handler(Signal::Interrupted, SignalHandler::Function(interrupt));
// set_signal_handler(Signal::Interrupted, SignalHandler::Function(interrupt));
let args = Args::parse();

View File

@ -1,4 +1,4 @@
use std::fs::{self, File};
use std::fs;
use crate::{env::BuildEnv, error::Error, util::run_external_command};

View File

@ -87,12 +87,15 @@ pub fn build_all(env: BuildEnv) -> Result<AllBuilt, Error> {
Arch::i686 => KernelProcessed(kernel),
_ => generate_kernel_tables(&env.kernel_symbol_file, kernel, tools)?,
};
// let modules = build_modules(&env, env.workspace_root.join("kernel/modules"))?;
let modules = match env.arch {
Arch::i686 => Vec::new(),
_ => build_modules(&env, env.workspace_root.join("kernel/modules"))?,
};
let mut install_extra = vec![];
// for module in modules {
// install_extra.push((module.clone(), module.file_name().unwrap().into()));
// }
for module in modules {
install_extra.push((module.clone(), module.file_name().unwrap().into()));
}
// Userspace stuff
let initrd = userspace::build_initrd(&env, install_extra, check)?;

View File

@ -1,4 +1,4 @@
// #![deny(warnings)]
#![deny(warnings)]
use std::{fs, path::PathBuf, process::ExitCode};