refactor: Fix all clippy warnings
This commit is contained in:
parent
c5699db3a5
commit
55a4c89811
@ -115,6 +115,9 @@ pub struct EarlyMapping<'a, T: ?Sized> {
|
||||
}
|
||||
|
||||
impl<'a, T: Sized> EarlyMapping<'a, T> {
|
||||
/// # Safety
|
||||
///
|
||||
/// `physical` address provided must be a valid non-NULL address actually containing `T`.
|
||||
pub unsafe fn map_slice(
|
||||
physical: PhysicalAddress,
|
||||
len: usize,
|
||||
@ -216,6 +219,9 @@ unsafe fn unmap_early_page(address: usize) {
|
||||
// TODO invalidate tlb
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Only meant to be used by the architecture initialization functions.
|
||||
pub unsafe fn map_ram_l1(index: usize) {
|
||||
if index >= RAM_MAPPING_L1_COUNT {
|
||||
todo!()
|
||||
@ -226,6 +232,9 @@ pub unsafe fn map_ram_l1(index: usize) {
|
||||
((index * L1::SIZE) as u64) | ram_block_flags().bits();
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Only meant to be used by the architecture initialization functions.
|
||||
pub unsafe fn map_heap_l2(index: usize, page: PhysicalAddress) {
|
||||
if index >= 512 {
|
||||
todo!()
|
||||
@ -295,7 +304,7 @@ unsafe fn map_device_memory_l2(
|
||||
Err(Error::OutOfMemory)
|
||||
}
|
||||
|
||||
pub unsafe fn map_device_memory(
|
||||
pub(crate) unsafe fn map_device_memory(
|
||||
base: PhysicalAddress,
|
||||
size: usize,
|
||||
attrs: DeviceMemoryAttributes,
|
||||
@ -334,7 +343,7 @@ pub unsafe fn map_device_memory(
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn unmap_device_memory(map: &RawDeviceMemoryMapping<KernelTableManagerImpl>) {
|
||||
pub(crate) unsafe fn unmap_device_memory(map: &RawDeviceMemoryMapping<KernelTableManagerImpl>) {
|
||||
// debugln!(
|
||||
// "Unmap {}B @ {:#x}",
|
||||
// map.page_count * map.page_size,
|
||||
|
@ -174,9 +174,6 @@ where
|
||||
|
||||
table_ref.drop_all::<TA>();
|
||||
|
||||
// Drop the table
|
||||
drop(table_ref);
|
||||
|
||||
TA::free_page_table(table);
|
||||
} else if entry.is_present() {
|
||||
// Memory must've been cleared beforehand, so no non-table entries must be present
|
||||
|
@ -66,6 +66,9 @@ impl<A: Architecture, S: Scheduler + 'static> CpuImpl<A, S> {
|
||||
self.scheduler.get()
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// See [Architecture::set_local_cpu].
|
||||
pub unsafe fn set_local(&'static mut self) {
|
||||
A::set_local_cpu(self as *mut _ as *mut _)
|
||||
}
|
||||
|
@ -21,9 +21,19 @@ pub trait Architecture: Sized {
|
||||
type PerCpuData;
|
||||
|
||||
// Cpu management
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Precondition: this function has not yet been called on the local CPU.
|
||||
unsafe fn set_local_cpu(cpu: *mut ());
|
||||
fn local_cpu() -> *mut ();
|
||||
/// # Safety
|
||||
///
|
||||
/// Precondition: this function has not yet been called on the local CPU.
|
||||
unsafe fn init_ipi_queues(queues: Vec<IpiQueue<Self>>);
|
||||
/// # Safety
|
||||
///
|
||||
/// Precondition: this function has not yet been called on the local CPU.
|
||||
unsafe fn init_local_cpu<S: Scheduler + 'static>(id: Option<u32>, data: Self::PerCpuData);
|
||||
|
||||
fn idle_task() -> extern "C" fn(usize) -> !;
|
||||
@ -33,6 +43,9 @@ pub trait Architecture: Sized {
|
||||
|
||||
// Interrupt management
|
||||
fn interrupt_mask() -> bool;
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure it is actually safe to enable interrupts in the current context.
|
||||
unsafe fn set_interrupt_mask(mask: bool) -> bool;
|
||||
fn wait_for_interrupt();
|
||||
|
||||
|
@ -11,6 +11,12 @@ pub trait PhysicalMemoryAllocator {
|
||||
fn allocate_page() -> Result<Self::Address, Error>;
|
||||
fn allocate_contiguous_pages(count: usize) -> Result<Self::Address, Error>;
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Preconditions:
|
||||
///
|
||||
/// * The page must have been obtained through [PhysicalMemoryAllocator::allocate_page] first;
|
||||
/// * The caller must guarantee the page will not be used after this call.
|
||||
unsafe fn free_page(page: Self::Address);
|
||||
}
|
||||
|
||||
@ -45,11 +51,18 @@ pub trait KernelTableManager: Sized + fmt::Debug {
|
||||
fn virtualize(phys: u64) -> usize;
|
||||
fn physicalize(virt: usize) -> u64;
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure the `base..base + count` region is not aliased by some other code,
|
||||
/// points to a valid chunk of device memory.
|
||||
unsafe fn map_device_pages(
|
||||
base: u64,
|
||||
count: usize,
|
||||
attrs: DeviceMemoryAttributes,
|
||||
) -> Result<RawDeviceMemoryMapping<Self>, Error>;
|
||||
/// # Safety
|
||||
///
|
||||
/// Only meant to be called from "safer" wrappers like [RawDeviceMemoryMapping].
|
||||
unsafe fn unmap_device_pages(mapping: &RawDeviceMemoryMapping<Self>);
|
||||
}
|
||||
|
||||
@ -87,6 +100,10 @@ impl<A: KernelTableManager> RawDeviceMemoryMapping<A> {
|
||||
(address, base_address, page_count, page_size)
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Preconditions: all the fields must come from a [RawDeviceMemoryMapping::into_raw_parts]
|
||||
/// call.
|
||||
pub unsafe fn from_raw_parts(
|
||||
address: usize,
|
||||
base_address: usize,
|
||||
@ -103,11 +120,11 @@ impl<A: KernelTableManager> RawDeviceMemoryMapping<A> {
|
||||
}
|
||||
|
||||
/// "Casts" the mapping to a specific type T and returns a [NonNull] pointer to it
|
||||
pub unsafe fn as_non_null<T>(&self) -> NonNull<T> {
|
||||
pub fn as_non_null<T>(&self) -> NonNull<T> {
|
||||
if self.page_size * self.page_count < size_of::<T>() {
|
||||
panic!();
|
||||
}
|
||||
NonNull::new_unchecked(self.address as *mut T)
|
||||
unsafe { NonNull::new_unchecked(self.address as *mut T) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#![no_std]
|
||||
#![allow(clippy::new_without_default)]
|
||||
#![feature(
|
||||
effects,
|
||||
strict_provenance,
|
||||
|
@ -269,6 +269,9 @@ unsafe fn unmap_device_memory(map: &RawDeviceMemoryMapping<KernelTableManagerImp
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Only meant to be called from memory initialization routines.
|
||||
pub unsafe fn map_heap_block(index: usize, page: PhysicalAddress) {
|
||||
if !page.is_page_aligned_for::<L2>() {
|
||||
panic!("Attempted to map a misaligned 2MiB page");
|
||||
@ -290,6 +293,9 @@ pub struct EarlyMapping<'a, T: ?Sized> {
|
||||
}
|
||||
|
||||
impl<'a, T: Sized> EarlyMapping<'a, T> {
|
||||
/// # Safety
|
||||
///
|
||||
/// `physical` address provided must be a valid non-NULL address actually containing `T`.
|
||||
pub unsafe fn map(physical: PhysicalAddress) -> Result<EarlyMapping<'a, T>, Error> {
|
||||
let layout = Layout::new::<T>();
|
||||
let aligned = physical.page_align_down::<L3>();
|
||||
@ -302,6 +308,10 @@ impl<'a, T: Sized> EarlyMapping<'a, T> {
|
||||
Ok(EarlyMapping { value, page_count })
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// `physical` address provided must be a valid non-NULL address actually containing a `T`
|
||||
/// slice of given `len`.
|
||||
pub unsafe fn map_slice(
|
||||
physical: PhysicalAddress,
|
||||
len: usize,
|
||||
@ -365,6 +375,10 @@ pub fn clone_kernel_tables(dst: &mut PageTable<L0>) {
|
||||
/// * 0xFFFFFF8080000000 .. 0xFFFFFF8100000000 : DEVICE_MAPPING_L2
|
||||
/// * 0xFFFFFF8080000000 .. 0xFFFFFF8080800000 : DEVICE_MAPPING_L3S
|
||||
/// * 0xFFFFFF8080800000 .. 0xFFFFFF8100000000 : ...
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe, must only be called by BSP during its early init, must already be in "higher-half"
|
||||
pub unsafe fn init_fixed_tables() {
|
||||
// TODO this could be built in compile-time too?
|
||||
let early_mapping_l3_phys = addr_of!(EARLY_MAPPING_L3) as usize - KERNEL_VIRT_OFFSET;
|
||||
@ -399,6 +413,9 @@ pub unsafe fn init_fixed_tables() {
|
||||
CR3.set_address(cr3);
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// `address` must be page-aligned.
|
||||
#[inline]
|
||||
pub unsafe fn flush_tlb_entry(address: usize) {
|
||||
core::arch::asm!("invlpg ({0})", in(reg) address, options(att_syntax));
|
||||
|
@ -278,9 +278,6 @@ where
|
||||
|
||||
table_ref.drop_all::<TA>();
|
||||
|
||||
// Drop the table
|
||||
drop(table_ref);
|
||||
|
||||
TA::free_page_table(table);
|
||||
} else if entry.is_present() {
|
||||
// Memory must've been cleared beforehand, so no non-table entries must be present
|
||||
|
@ -416,10 +416,16 @@ impl FpuContext {
|
||||
value
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Only meant to be called from a context switch routine.
|
||||
pub unsafe fn save(dst: *mut FpuContext) {
|
||||
core::arch::asm!("fxsave64 ({})", in(reg) dst, options(att_syntax));
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Only meant to be called from a context switch routine.
|
||||
pub unsafe fn restore(src: *mut FpuContext) {
|
||||
core::arch::asm!("fxrstor64 ({})", in(reg) src, options(att_syntax));
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ fn main() {
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||
|
||||
generate_syscall_dispatcher(&out_dir);
|
||||
generate_syscall_dispatcher(out_dir);
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
|
@ -74,7 +74,7 @@ impl AhciController {
|
||||
|
||||
let mut fis_buffers = [const { None }; 16];
|
||||
// Allocate FIS receive buffers for the ports
|
||||
for i in 0..self.max_port_count {
|
||||
for (i, fis_buffer_slot) in fis_buffers.iter_mut().enumerate().take(self.max_port_count) {
|
||||
if pi & (1 << i) == 0 {
|
||||
continue;
|
||||
}
|
||||
@ -84,7 +84,7 @@ impl AhciController {
|
||||
|
||||
let buffer = PageBox::new(ReceivedFis::zeroed()).map_err(AhciError::MemoryError)?;
|
||||
port.set_received_fis_address_64(unsafe { buffer.as_physical_address() });
|
||||
fis_buffers[i] = Some(buffer);
|
||||
*fis_buffer_slot = Some(buffer);
|
||||
}
|
||||
|
||||
self.received_fis_buffers.init(fis_buffers);
|
||||
|
@ -226,6 +226,10 @@ pub trait PciConfigurationSpace {
|
||||
PciInterruptPin::try_from(self.read_u8(0x3D) as u32).ok()
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is only meant to be called before the device has seen any use by the OS,
|
||||
/// it has not been tested outside of this use case.
|
||||
unsafe fn bar_size(&self, index: usize) -> usize {
|
||||
let cmd = self.command();
|
||||
|
||||
@ -264,6 +268,11 @@ pub trait PciConfigurationSpace {
|
||||
/// The function is only valid for devices with `header_type() == 0`
|
||||
///
|
||||
/// The `index` corresponds to the actual configuration space BAR index.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Precondition: the device must have memory access disabled through its command register
|
||||
/// prior to setting a BAR.
|
||||
unsafe fn set_bar(&self, index: usize, value: PciBaseAddress) {
|
||||
assert!(index < 6);
|
||||
|
||||
|
@ -64,7 +64,7 @@ async fn extract_class_info(device: &UsbDeviceAccess) -> Result<Option<UsbClassI
|
||||
async fn pick_driver(
|
||||
device: &UsbDeviceAccess,
|
||||
) -> Result<Option<Arc<dyn UsbDriver + 'static>>, UsbError> {
|
||||
let Some(class) = extract_class_info(&device).await? else {
|
||||
let Some(class) = extract_class_info(device).await? else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
@ -184,9 +184,9 @@ pub mod hid_keyboard {
|
||||
) -> usize {
|
||||
let mut count = 0;
|
||||
let released = self.mods & !m;
|
||||
for i in 0..8 {
|
||||
for (i, modifier) in MODIFIER_MAP.iter().enumerate().take(8) {
|
||||
if released & (1 << i) != 0 {
|
||||
events[count].write(KeyboardKeyEvent::Released(MODIFIER_MAP[i]));
|
||||
events[count].write(KeyboardKeyEvent::Released(*modifier));
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
@ -201,9 +201,9 @@ pub mod hid_keyboard {
|
||||
) -> usize {
|
||||
let mut count = 0;
|
||||
let pressed = m & !self.mods;
|
||||
for i in 0..8 {
|
||||
for (i, modifier) in MODIFIER_MAP.iter().enumerate().take(8) {
|
||||
if pressed & (1 << i) != 0 {
|
||||
events[count].write(KeyboardKeyEvent::Pressed(MODIFIER_MAP[i]));
|
||||
events[count].write(KeyboardKeyEvent::Pressed(*modifier));
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
@ -218,13 +218,10 @@ pub mod hid_keyboard {
|
||||
) -> usize {
|
||||
let mut count = 0;
|
||||
for i in 1..256 {
|
||||
if self.state[i / 64] & (1 << (i % 64)) != 0 {
|
||||
if !keys.contains(&(i as u8)) {
|
||||
events[count]
|
||||
.write(KeyboardKeyEvent::Released(Self::translate_key(i as u8)));
|
||||
self.state[i / 64] &= !(1 << (i % 64));
|
||||
count += 1;
|
||||
}
|
||||
if self.state[i / 64] & (1 << (i % 64)) != 0 && !keys.contains(&(i as u8)) {
|
||||
events[count].write(KeyboardKeyEvent::Released(Self::translate_key(i as u8)));
|
||||
self.state[i / 64] &= !(1 << (i % 64));
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
count
|
||||
|
@ -43,8 +43,8 @@ pub trait UsbDevice: Send + Sync {
|
||||
// Endpoint "0"
|
||||
fn control_pipe(&self) -> &UsbControlPipeAccess;
|
||||
|
||||
fn open_interrupt_in_pipe<'a>(
|
||||
&'a self,
|
||||
fn open_interrupt_in_pipe(
|
||||
&self,
|
||||
number: u8,
|
||||
) -> BoxFuture<Result<UsbInterruptInPipeAccess, UsbError>> {
|
||||
unimplemented!()
|
||||
|
@ -1,4 +1,5 @@
|
||||
#![no_std]
|
||||
#![allow(clippy::new_without_default)]
|
||||
#![feature(iter_array_chunks, maybe_uninit_slice)]
|
||||
|
||||
extern crate alloc;
|
||||
|
@ -73,7 +73,7 @@ fn decode_usb_string(bytes: &[u8]) -> Result<String, UsbError> {
|
||||
|
||||
char::decode_utf16(
|
||||
bytes
|
||||
.into_iter()
|
||||
.iter()
|
||||
.array_chunks::<2>()
|
||||
.map(|[&a, &b]| u16::from_le_bytes([a, b])),
|
||||
)
|
||||
|
@ -119,8 +119,8 @@ impl UsbDevice for XhciBusDevice {
|
||||
self.xhci
|
||||
}
|
||||
|
||||
fn open_interrupt_in_pipe<'a>(
|
||||
&'a self,
|
||||
fn open_interrupt_in_pipe(
|
||||
&self,
|
||||
number: u8,
|
||||
) -> BoxFuture<Result<UsbInterruptInPipeAccess, UsbError>> {
|
||||
async move {
|
||||
|
@ -1,4 +1,5 @@
|
||||
#![no_std]
|
||||
#![allow(clippy::new_without_default)]
|
||||
#![feature(iter_array_chunks)]
|
||||
|
||||
extern crate alloc;
|
||||
@ -99,7 +100,7 @@ pub fn probe(info: &PciDeviceInfo) -> Result<&'static dyn Device, Error> {
|
||||
cmd |= PciCommandRegister::ENABLE_MEMORY | PciCommandRegister::BUS_MASTER;
|
||||
info.config_space.set_command(cmd.bits());
|
||||
|
||||
let regs = unsafe { xhci_lib::Registers::new(bar0.try_into().unwrap(), Mapper::new()) };
|
||||
let regs = unsafe { xhci_lib::Registers::new(bar0.into(), Mapper::new()) };
|
||||
let xhci = Box::leak(Box::new(Xhci::new(regs)?));
|
||||
|
||||
info.init_interrupts(PreferredInterruptMode::Msi)?;
|
||||
|
@ -107,8 +107,7 @@ impl CommandRing {
|
||||
|
||||
pub fn enqueue<C: CommandTrb>(&self, trb: C) -> PhysicalAddress {
|
||||
let mut inner = self.inner.lock();
|
||||
let address = inner.enqueue(trb);
|
||||
address
|
||||
inner.enqueue(trb)
|
||||
}
|
||||
|
||||
pub async fn address_device<E: CommandExecutor, const N: usize>(
|
||||
|
@ -177,6 +177,9 @@ impl VirtQueue {
|
||||
Self::with_capacity(transport, index, capacity, msix_vector, no_avail_irq)
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Invariants: PageBox remains valid and allocated until it is properly dequeued.
|
||||
pub unsafe fn add<'a, 'b>(
|
||||
&mut self,
|
||||
input: &'a [&'b mut PageBox<[u8]>],
|
||||
@ -288,14 +291,14 @@ impl VirtQueue {
|
||||
self.last_used_idx == self.used.index()
|
||||
}
|
||||
|
||||
pub unsafe fn pop_last_used(&mut self) -> Option<(u16, u32)> {
|
||||
pub fn pop_last_used(&mut self) -> Option<(u16, u32)> {
|
||||
let token = self.peek_used()?;
|
||||
let len = self.pop_used(token).unwrap();
|
||||
let len = unsafe { self.pop_used(token) }.unwrap();
|
||||
|
||||
Some((token, len))
|
||||
}
|
||||
|
||||
pub unsafe fn peek_used(&mut self) -> Option<u16> {
|
||||
fn peek_used(&mut self) -> Option<u16> {
|
||||
if !self.is_used_empty() {
|
||||
let last_used = self.last_used_idx % self.capacity as u16;
|
||||
Some(self.used.read_slot(last_used).0 as u16)
|
||||
@ -304,7 +307,7 @@ impl VirtQueue {
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn pop_used(&mut self, token: u16) -> Result<u32, Error> {
|
||||
unsafe fn pop_used(&mut self, token: u16) -> Result<u32, Error> {
|
||||
if self.is_used_empty() {
|
||||
return Err(Error::QueueEmpty);
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ impl Queues {
|
||||
pub fn try_receive(&self, _index: usize) -> Option<(u16, IrqSafeSpinlockGuard<VirtQueue>)> {
|
||||
let mut queue = self.receive.lock();
|
||||
// TODO use len for packet size hint
|
||||
let (token, _len) = unsafe { queue.pop_last_used() }?;
|
||||
let (token, _len) = queue.pop_last_used()?;
|
||||
Some((token, queue))
|
||||
}
|
||||
}
|
||||
@ -179,11 +179,8 @@ impl<T: Transport> VirtioNet<T> {
|
||||
let receive_vector = if let Some(pci) = self.pci_device_info.as_ref() {
|
||||
pci.init_interrupts(PreferredInterruptMode::Msi)?;
|
||||
let info = pci.map_interrupt(InterruptAffinity::Any, self)?;
|
||||
if let Some(info) = info {
|
||||
Some(info.vector as u16)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
info.map(|info| info.vector as u16)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@ -234,6 +231,7 @@ impl<T: Transport + 'static> NetworkDevice for VirtioNet<T> {
|
||||
|
||||
impl<T: Transport + 'static> InterruptHandler for VirtioNet<T> {
|
||||
fn handle_irq(&self, vector: Option<usize>) -> bool {
|
||||
#[allow(clippy::redundant_pattern_matching)]
|
||||
if let Some(_) = vector {
|
||||
// MSI/MSI-X
|
||||
let Some(queues) = self.queues.try_get() else {
|
||||
|
@ -99,10 +99,7 @@ pub fn probe_dt_node<F: FnOnce(&'static dyn Device) -> DeviceId>(
|
||||
register: F,
|
||||
) -> Option<(&'static dyn Device, DeviceId)> {
|
||||
// TODO use list, not just the first item
|
||||
let Some(compatible) = dt.node.prop("compatible") else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let compatible = dt.node.prop("compatible")?;
|
||||
let probe = dt_match_compatible(compatible)?;
|
||||
let device = Box::leak((probe.probe_func)(dt)?);
|
||||
let id = register(device);
|
||||
|
@ -30,6 +30,7 @@ pub type TNode<'a> = DevTreeIndexNode<'a, 'a, 'a>;
|
||||
pub type TProp<'a> = DevTreeIndexProp<'a, 'a, 'a>;
|
||||
|
||||
/// Helper trait to provide extra functionality for [DevTreeIndexProp]
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
pub trait DevTreeIndexPropExt {
|
||||
/// Reads a cell value from single-type cell array at given cell index
|
||||
fn cell1_array_item(&self, index: usize, cells: usize) -> Option<u64>;
|
||||
@ -142,7 +143,14 @@ impl<'a> DeviceTree<'a> {
|
||||
chosen.prop("stdout-path")
|
||||
}
|
||||
|
||||
/// Returns the length of the header provided as a slice of bytes
|
||||
/// Returns the length of the header provided as a slice of bytes.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Preconditions:
|
||||
///
|
||||
/// * `header` is at least u32-aligned;
|
||||
/// * `header` points to a slice of at least [DevTree::MIN_HEADER_SIZE] bytes.
|
||||
pub unsafe fn read_totalsize(header: &[u8]) -> Result<usize, Error> {
|
||||
DevTree::read_totalsize(header).map_err(|_| Error::InvalidArgument)
|
||||
}
|
||||
|
@ -253,8 +253,8 @@ impl File {
|
||||
Self::Regular(file) => Some(&file.node),
|
||||
Self::Block(file) => Some(&file.node),
|
||||
Self::Char(file) => Some(&file.node),
|
||||
Self::PtyMaster(_, node) => Some(&node),
|
||||
Self::PtySlave(_, node) => Some(&node),
|
||||
Self::PtyMaster(_, node) => Some(node),
|
||||
Self::PtySlave(_, node) => Some(node),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -327,10 +327,10 @@ impl IoContext {
|
||||
let token = self.check_access(Action::Read, at)?;
|
||||
// let _path = link.imp.read_to_string()?;
|
||||
match at.read_symlink_node(token) {
|
||||
Ok(node) => return Ok(node),
|
||||
Ok(node) => Ok(node),
|
||||
// Need to read the link data and resolve it manually
|
||||
Err(Error::NotImplemented) => todo!(),
|
||||
Err(e) => return Err(e),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,8 +437,8 @@ mod tests {
|
||||
|
||||
let mut ioctx = IoContext::new(root.clone());
|
||||
|
||||
let uid = UserId::from(1);
|
||||
let gid = GroupId::from(1);
|
||||
let uid = unsafe { UserId::from_raw(1) };
|
||||
let gid = unsafe { GroupId::from_raw(1) };
|
||||
|
||||
// 1:1
|
||||
ioctx.set_uid_unchecked(uid);
|
||||
|
@ -75,7 +75,10 @@ enum NodeImpl {
|
||||
Symlink(SymlinkData),
|
||||
|
||||
// These map transparently to other types of nodes
|
||||
// TODO: implement open operation on these
|
||||
#[allow(unused)]
|
||||
PseudoTerminalSlave(Arc<PseudoTerminalSlave>),
|
||||
#[allow(unused)]
|
||||
PseudoTerminalMaster(Arc<PseudoTerminalMaster>),
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,11 @@ pub trait ProcessAddressSpaceManager<TA: TableAllocator>: Sized {
|
||||
/// Returns the implementation specific physical address of this space, with ASID applied
|
||||
fn as_address_with_asid(&self) -> u64;
|
||||
|
||||
/// Clears the address space by dropping and non-global tables
|
||||
/// Clears the address space by dropping and non-global tables.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Meant to be called when a process is being dropped or a new image is being loaded,
|
||||
/// replacing the old mappings. All the mappings become invalid after this call.
|
||||
unsafe fn clear(&mut self);
|
||||
}
|
||||
|
@ -15,6 +15,9 @@ pub trait EntryLevel: Copy {
|
||||
|
||||
pub trait TableAllocator {
|
||||
fn allocate_page_table() -> Result<PhysicalAddress, Error>;
|
||||
/// # Safety
|
||||
///
|
||||
/// `address` must point to a real translation table allocated by this trait impl.
|
||||
unsafe fn free_page_table(address: PhysicalAddress);
|
||||
}
|
||||
|
||||
@ -53,10 +56,20 @@ pub trait EntryLevelDrop {
|
||||
/// Range covering the whole table
|
||||
const FULL_RANGE: Range<usize>;
|
||||
|
||||
/// Recursively destroys the specified range within the table
|
||||
/// Recursively destroys the specified range within the table.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Caller must ensure the unmapped range is not in use by some other thread and will not be
|
||||
/// referred to from this point.
|
||||
unsafe fn drop_range<TA: TableAllocator>(&mut self, range: Range<usize>);
|
||||
|
||||
/// Recursively destroys all the entries in within the table
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Caller must ensure the unmapped range is not in use by some other thread and will not be
|
||||
/// referred to from this point.
|
||||
unsafe fn drop_all<TA: TableAllocator>(&mut self) {
|
||||
self.drop_range::<TA>(Self::FULL_RANGE)
|
||||
}
|
||||
|
@ -215,15 +215,6 @@ impl<T> PageBox<MaybeUninit<T>> {
|
||||
|
||||
PageBox { value, page_count }
|
||||
}
|
||||
|
||||
pub unsafe fn into_byte_slice(self) -> PageBox<[u8]> {
|
||||
let page_count = self.page_count;
|
||||
let value = MaybeUninit::slice_assume_init_mut(MaybeUninit::as_bytes_mut(&mut *self.value));
|
||||
|
||||
core::mem::forget(self);
|
||||
|
||||
PageBox { value, page_count }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PageBox<[MaybeUninit<T>]> {
|
||||
|
@ -30,6 +30,8 @@ use crate::{
|
||||
|
||||
pub mod elf;
|
||||
|
||||
pub type LoadedProcess<PM, IO> = (Arc<ProcessImpl<PM, IO>>, Arc<Thread>);
|
||||
|
||||
pub trait ProgramLoadSource {
|
||||
type File: Seek + Read;
|
||||
|
||||
@ -173,7 +175,7 @@ fn setup_binary<S, PM, IO>(
|
||||
image: ProcessImage,
|
||||
args: &Vec<String>,
|
||||
envs: &Vec<String>,
|
||||
) -> Result<(Arc<ProcessImpl<PM, IO>>, Arc<Thread>), Error>
|
||||
) -> Result<LoadedProcess<PM, IO>, Error>
|
||||
where
|
||||
S: Into<String>,
|
||||
PM: ProcessManager<Process = ProcessImpl<PM, IO>>,
|
||||
@ -239,7 +241,7 @@ pub fn load<PS, P, PM, IO>(
|
||||
path: P,
|
||||
args: &[&str],
|
||||
envs: &[&str],
|
||||
) -> Result<(Arc<ProcessImpl<PM, IO>>, Arc<Thread>), Error>
|
||||
) -> Result<LoadedProcess<PM, IO>, Error>
|
||||
where
|
||||
PS: ProgramLoadSource,
|
||||
P: AsRef<Path>,
|
||||
|
@ -69,7 +69,7 @@ impl<T> AsyncMutex<T> {
|
||||
poll_fn(|cx| self.poll_lock(cx)).await
|
||||
}
|
||||
|
||||
pub unsafe fn force_unlock(&self) {
|
||||
unsafe fn force_unlock(&self) {
|
||||
self.lock.store(false, Ordering::Release);
|
||||
self.waker.wake_one();
|
||||
}
|
||||
|
@ -317,6 +317,10 @@ impl Thread {
|
||||
THREADS.read().get(id).cloned()
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Precondition: the caller must ensure the thread is, in fact, a current one, for example,
|
||||
/// by preventing interrupts by holding an [IrqGuard].
|
||||
pub unsafe fn upgrade(weak: &Weak<Self>) -> Option<CurrentThread> {
|
||||
let guard = IrqGuard::acquire();
|
||||
let strong = weak.upgrade()?;
|
||||
|
@ -13,6 +13,9 @@ pub struct LocalCpu<'a>(LocalCpuImpl<'a, CpuQueue>);
|
||||
pub struct Cpu(CpuImpl<CpuQueue>);
|
||||
|
||||
impl Cpu {
|
||||
/// # Safety
|
||||
///
|
||||
/// Precondition: this function has not yet been called on the local CPU.
|
||||
pub unsafe fn init_local(
|
||||
id: Option<u32>,
|
||||
data: <ArchitectureImpl as Architecture>::PerCpuData,
|
||||
|
@ -210,7 +210,6 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) {
|
||||
dump_irrecoverable_exception(frame, ec, iss);
|
||||
|
||||
thread.raise_signal(Signal::MemoryAccessViolation);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//! ARM PL011 driver
|
||||
use abi::{error::Error, io::DeviceRequest, process::ProcessId};
|
||||
use abi::{error::Error, io::DeviceRequest};
|
||||
use alloc::boxed::Box;
|
||||
use device_api::{
|
||||
interrupt::{InterruptHandler, Irq},
|
||||
@ -152,7 +152,7 @@ impl CharDevice for Pl011 {
|
||||
fn device_request(&self, req: &mut DeviceRequest) -> Result<(), Error> {
|
||||
match req {
|
||||
&mut DeviceRequest::SetTerminalGroup(id) => {
|
||||
self.set_signal_group(ProcessId::from(id));
|
||||
self.set_signal_group(id);
|
||||
Ok(())
|
||||
}
|
||||
DeviceRequest::SetTerminalOptions(config) => self.context.set_config(config),
|
||||
|
@ -233,7 +233,7 @@ mod impls {
|
||||
debugln!("{} requested terminal {:?}", pid, fd);
|
||||
let file = child_io.files.file(fd)?;
|
||||
// let node = file.node().ok_or(Error::InvalidFile)?;
|
||||
let mut req = DeviceRequest::SetTerminalGroup(child_process.group_id().into());
|
||||
let mut req = DeviceRequest::SetTerminalGroup(child_process.group_id());
|
||||
file.device_request(&mut req)?;
|
||||
|
||||
if let Some(node) = file.node() {
|
||||
|
@ -16,4 +16,8 @@ pub trait SyscallFatRegister {
|
||||
fn from_syscall_registers(meta: usize, data: usize) -> Self;
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Meant for abi-generator to provide a "hint" that the type, when wrapped in an Option or Result,
|
||||
/// can be fit into a single register.
|
||||
pub unsafe trait ThinWrapped: SyscallRegister {}
|
||||
|
@ -40,9 +40,7 @@ impl SyscallRegister for () {
|
||||
0
|
||||
}
|
||||
|
||||
fn from_syscall_register(_value: usize) -> Self {
|
||||
()
|
||||
}
|
||||
fn from_syscall_register(_value: usize) -> Self {}
|
||||
}
|
||||
|
||||
impl SyscallRegister for ! {
|
||||
|
@ -7,7 +7,7 @@ use syn::{punctuated::Punctuated, spanned::Spanned, token, Token};
|
||||
pub mod ty;
|
||||
|
||||
use crate::{
|
||||
abi::ty::ComplexType,
|
||||
abi::ty::{AbiPrimitive, ComplexType, SimpleType},
|
||||
syntax::{
|
||||
parse_abi, Attributes, BitfieldRange, BitfieldType, BitfieldTypeField,
|
||||
DocumentTypeDefinition, EnumType, EnumTypeVariant, NewType, ParseError, TypeRepr,
|
||||
@ -122,8 +122,25 @@ impl AbiBuilder {
|
||||
|
||||
let handler_fn = quote! { #impl_mod::#syscall_name };
|
||||
|
||||
let body = quote! {
|
||||
Ok((#handler_fn(#call_args)).into_syscall_register())
|
||||
let body = if syscall
|
||||
.return_type
|
||||
.as_ref()
|
||||
.map(|p| {
|
||||
matches!(
|
||||
p.as_ref(),
|
||||
ComplexType::Simple(SimpleType::Primitive(AbiPrimitive::Unit))
|
||||
)
|
||||
})
|
||||
.unwrap_or(true)
|
||||
{
|
||||
quote! {
|
||||
#handler_fn(#call_args);
|
||||
Ok(0)
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
Ok((#handler_fn(#call_args)).into_syscall_register())
|
||||
}
|
||||
};
|
||||
|
||||
let match_arm = syscall.emit_handler_branch(
|
||||
@ -138,6 +155,7 @@ impl AbiBuilder {
|
||||
}
|
||||
|
||||
let dispatcher_fn = quote! {
|
||||
#[allow(clippy::unnecessary_cast, clippy::identity_op)]
|
||||
pub(crate) fn #dispatcher_fn(#raw_fn: SyscallFunction, #raw_args: &[usize]) -> Result<usize, Error> {
|
||||
match #raw_fn {
|
||||
#branches
|
||||
@ -287,6 +305,7 @@ impl GenerateTypeDefinition for EnumType {
|
||||
self as #repr
|
||||
}
|
||||
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub const unsafe fn from_raw(value: #repr) -> Self {
|
||||
core::mem::transmute(value)
|
||||
}
|
||||
@ -294,6 +313,7 @@ impl GenerateTypeDefinition for EnumType {
|
||||
|
||||
impl From<#name> for #repr {
|
||||
#[inline]
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
fn from(value: #name) -> #repr {
|
||||
value as #repr
|
||||
}
|
||||
@ -357,6 +377,7 @@ fn generate_transparent_struct(
|
||||
self.0
|
||||
}
|
||||
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub const unsafe fn from_raw(value: #repr) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
use crate::{
|
||||
abi::ty::{SimpleType, Type},
|
||||
abi::ty::{AbiPrimitive, SimpleType, Type},
|
||||
TargetEnv,
|
||||
};
|
||||
|
||||
@ -107,6 +107,11 @@ impl Syscall {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
Some(ComplexType::Simple(SimpleType::Primitive(AbiPrimitive::Unit))) => {
|
||||
quote! {
|
||||
#sys_call;
|
||||
}
|
||||
}
|
||||
Some(ty) => {
|
||||
let ty = ty.as_rust_type();
|
||||
quote!(<#ty>::from_syscall_register(#sys_call))
|
||||
|
@ -58,7 +58,11 @@ impl Type for AbiPrimitive {
|
||||
}
|
||||
|
||||
fn emit_to_syscall_arguments(&self, _env: &TargetEnv, value: &Ident) -> TokenStream {
|
||||
quote!(#value as usize)
|
||||
if *self == Self::USize {
|
||||
quote!(#value)
|
||||
} else {
|
||||
quote!(#value as usize)
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_from_syscall_arguments(
|
||||
|
@ -371,9 +371,7 @@ impl<'a, 'd> Server<'a, 'd> {
|
||||
let (row, col) = self.focused_frame?;
|
||||
|
||||
let frame = &self.rows[row].frames[col];
|
||||
let Some(window) = frame.window.and_then(|w| self.windows.get(&w)) else {
|
||||
return None;
|
||||
};
|
||||
let window = frame.window.and_then(|w| self.windows.get(&w))?;
|
||||
|
||||
Some((frame, window))
|
||||
}
|
||||
|
@ -183,6 +183,7 @@ fn validate_ping_reply(
|
||||
l4_data == expect_l4_data
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn ping_once(
|
||||
socket: &mut RawSocket,
|
||||
poll: &mut PollChannel,
|
||||
@ -197,9 +198,8 @@ fn ping_once(
|
||||
|
||||
let source_ip = info.source_ip.into_ipv4().unwrap();
|
||||
let destination_ip = info.destination_ip.into_ipv4().unwrap();
|
||||
let mut l4_data = vec![];
|
||||
let mut l4_data = Vec::with_capacity(data_len);
|
||||
|
||||
l4_data.reserve(data_len);
|
||||
for _ in 0..data_len {
|
||||
l4_data.push(rand::random());
|
||||
}
|
||||
|
@ -167,11 +167,12 @@ fn run(mut input: Input, vars: &mut HashMap<String, String>) -> io::Result<ExitC
|
||||
if input.is_interactive() {
|
||||
eprintln!("Killed: {}", signal);
|
||||
}
|
||||
signal as i32 + 128
|
||||
signal + 128
|
||||
}
|
||||
Ok(Outcome::Exited(code)) => code % 256,
|
||||
Err(e) => {
|
||||
eprintln!("{}: {}", "<command>", e);
|
||||
// TODO stringify the command back
|
||||
eprintln!("<command>: {}", e);
|
||||
127
|
||||
}
|
||||
};
|
||||
|
@ -77,7 +77,7 @@ fn main() -> ExitCode {
|
||||
}
|
||||
|
||||
if let Err(err) = login_attempt(attempt_number % 3 == 0) {
|
||||
eprintln!("login: {}", err.to_string());
|
||||
eprintln!("login: {}", err);
|
||||
}
|
||||
attempt_number += 1;
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
use std::{env, fs::OpenOptions, io, path::Path, process::ExitCode};
|
||||
|
||||
fn touch<P: AsRef<Path>>(path: P) -> Result<(), io::Error> {
|
||||
OpenOptions::new().create(true).write(true).open(path)?;
|
||||
OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.truncate(false)
|
||||
.open(path)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
[toolchain]
|
||||
branch = "alnyan/v0.1.0"
|
||||
branch = "alnyan/yggdrasil-master"
|
||||
|
Loading…
x
Reference in New Issue
Block a user