Add rustfmt from relibc and apply it with cargo fmt

This commit is contained in:
Jeremy Soller
2024-01-17 13:52:01 -07:00
parent 73897bd83d
commit 45f1c4e29e
166 changed files with 7353 additions and 3851 deletions
+56 -36
View File
@@ -1,28 +1,30 @@
use core::convert::TryInto;
use core::str;
use core::sync::atomic::{self, AtomicUsize};
use core::{
convert::TryInto,
str,
sync::atomic::{self, AtomicUsize},
};
use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use alloc::{boxed::Box, collections::BTreeMap};
use spin::{Mutex, Once, RwLock};
use crate::acpi::{RXSDT_ENUM, RxsdtEnum};
use crate::event;
use crate::sync::WaitCondition;
use crate::syscall::data::Stat;
use crate::syscall::error::{EACCES, EBADF, EBADFD, EINTR, EINVAL, EISDIR, ENOENT, ENOTDIR, EROFS};
use crate::syscall::flag::{
EventFlags, EVENT_READ,
MODE_CHR, MODE_DIR, MODE_FILE,
O_ACCMODE, O_CREAT, O_DIRECTORY, O_EXCL, O_RDONLY, O_STAT, O_SYMLINK,
SEEK_SET, SEEK_CUR, SEEK_END,
use crate::{
acpi::{RxsdtEnum, RXSDT_ENUM},
event,
sync::WaitCondition,
};
use crate::syscall::error::{Error, Result};
use crate::syscall::usercopy::{UserSliceRo, UserSliceWo};
use super::{GlobalSchemes, KernelScheme, CallerCtx, OpenResult};
use crate::syscall::{
data::Stat,
error::{Error, Result, EACCES, EBADF, EBADFD, EINTR, EINVAL, EISDIR, ENOENT, ENOTDIR, EROFS},
flag::{
EventFlags, EVENT_READ, MODE_CHR, MODE_DIR, MODE_FILE, O_ACCMODE, O_CREAT, O_DIRECTORY,
O_EXCL, O_RDONLY, O_STAT, O_SYMLINK, SEEK_CUR, SEEK_END, SEEK_SET,
},
usercopy::{UserSliceRo, UserSliceWo},
};
use super::{CallerCtx, GlobalSchemes, KernelScheme, OpenResult};
/// A scheme used to access the RSDT or XSDT, which is needed for e.g. `acpid` to function.
pub struct AcpiScheme;
@@ -56,7 +58,10 @@ pub fn register_kstop() -> bool {
let handles = HANDLES.read();
for (&fd, _) in handles.iter().filter(|(_, handle)| handle.kind == HandleKind::ShutdownPipe) {
for (&fd, _) in handles
.iter()
.filter(|(_, handle)| handle.kind == HandleKind::ShutdownPipe)
{
event::trigger(GlobalSchemes::Acpi.scheme_id(), fd, EVENT_READ);
waiters_awoken += 1;
}
@@ -142,11 +147,14 @@ impl KernelScheme for AcpiScheme {
let fd = NEXT_FD.fetch_add(1, atomic::Ordering::Relaxed);
let mut handles_guard = HANDLES.write();
let _ = handles_guard.insert(fd, Handle {
offset: 0,
kind: handle_kind,
stat: flags & O_STAT == O_STAT,
});
let _ = handles_guard.insert(
fd,
Handle {
offset: 0,
kind: handle_kind,
stat: flags & O_STAT == O_STAT,
},
);
Ok(OpenResult::SchemeLocal(fd))
}
@@ -166,15 +174,24 @@ impl KernelScheme for AcpiScheme {
let new_offset = match whence {
SEEK_SET => pos as usize,
SEEK_CUR => if pos < 0 {
handle.offset.checked_sub((-pos) as usize).ok_or(Error::new(EINVAL))?
} else {
handle.offset.saturating_add(pos as usize)
SEEK_CUR => {
if pos < 0 {
handle
.offset
.checked_sub((-pos) as usize)
.ok_or(Error::new(EINVAL))?
} else {
handle.offset.saturating_add(pos as usize)
}
}
SEEK_END => if pos < 0 {
file_len.checked_sub((-pos) as usize).ok_or(Error::new(EINVAL))?
} else {
file_len
SEEK_END => {
if pos < 0 {
file_len
.checked_sub((-pos) as usize)
.ok_or(Error::new(EINVAL))?
} else {
file_len
}
}
_ => return Err(Error::new(EINVAL)),
};
@@ -222,7 +239,7 @@ impl KernelScheme for AcpiScheme {
if *flag_guard {
break;
} else if ! KSTOP_WAITCOND.wait(flag_guard, "waiting for kstop") {
} else if !KSTOP_WAITCOND.wait(flag_guard, "waiting for kstop") {
return Err(Error::new(EINTR));
}
}
@@ -258,10 +275,13 @@ impl KernelScheme for AcpiScheme {
st_size: data.len().try_into().unwrap_or(u64::max_value()),
..Default::default()
}
},
}
HandleKind::TopLevel => Stat {
st_mode: MODE_DIR,
st_size: TOPLEVEL_CONTENTS.len().try_into().unwrap_or(u64::max_value()),
st_size: TOPLEVEL_CONTENTS
.len()
.try_into()
.unwrap_or(u64::max_value()),
..Default::default()
},
HandleKind::ShutdownPipe => Stat {
+32 -17
View File
@@ -1,12 +1,16 @@
use core::sync::atomic::{AtomicUsize, Ordering};
use spin::RwLock;
use crate::arch::debug::Writer;
use crate::event;
use crate::scheme::*;
use crate::sync::WaitQueue;
use crate::syscall::flag::{EventFlags, EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK};
use crate::syscall::usercopy::{UserSliceRo, UserSliceWo};
use crate::{
arch::debug::Writer,
event,
scheme::*,
sync::WaitQueue,
syscall::{
flag::{EventFlags, EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK},
usercopy::{UserSliceRo, UserSliceWo},
},
};
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
@@ -54,10 +58,13 @@ impl KernelScheme for DebugScheme {
};
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
HANDLES.write().insert(id, Handle {
flags: flags & ! O_ACCMODE,
num,
});
HANDLES.write().insert(
id,
Handle {
flags: flags & !O_ACCMODE,
num,
},
);
Ok(OpenResult::SchemeLocal(id))
}
@@ -68,10 +75,10 @@ impl KernelScheme for DebugScheme {
match cmd {
F_GETFL => Ok(handle.flags),
F_SETFL => {
handle.flags = arg & ! O_ACCMODE;
handle.flags = arg & !O_ACCMODE;
Ok(0)
},
_ => Err(Error::new(EINVAL))
}
_ => Err(Error::new(EINVAL)),
}
} else {
Err(Error::new(EBADF))
@@ -113,11 +120,17 @@ impl KernelScheme for DebugScheme {
#[cfg(feature = "profiling")]
if handle.num != !0 {
return crate::profiling::drain_buffer(crate::LogicalCpuId::new(handle.num as u32), buf);
return crate::profiling::drain_buffer(
crate::LogicalCpuId::new(handle.num as u32),
buf,
);
}
INPUT
.receive_into_user(buf, handle.flags & O_NONBLOCK != O_NONBLOCK, "DebugScheme::read")
INPUT.receive_into_user(
buf,
handle.flags & O_NONBLOCK != O_NONBLOCK,
"DebugScheme::read",
)
}
fn kwrite(&self, id: usize, buf: UserSliceRo) -> Result<usize> {
@@ -155,7 +168,9 @@ impl KernelScheme for DebugScheme {
// TODO: Copy elsewhere in the kernel?
const SRC: &[u8] = b"debug:";
let byte_count = core::cmp::min(buf.len(), SRC.len());
buf.limit(byte_count).expect("must succeed").copy_from_slice(&SRC[..byte_count])?;
buf.limit(byte_count)
.expect("must succeed")
.copy_from_slice(&SRC[..byte_count])?;
Ok(byte_count)
}
+39 -32
View File
@@ -1,21 +1,19 @@
use core::sync::atomic::{self, AtomicUsize};
use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use alloc::{boxed::Box, collections::BTreeMap};
use spin::{Once, RwLock};
use crate::dtb::DTB_BINARY;
use crate::scheme::SchemeId;
use crate::syscall::flag::{
MODE_FILE,
O_STAT,
SEEK_CUR, SEEK_END, SEEK_SET,
use super::{CallerCtx, KernelScheme, OpenResult};
use crate::{
dtb::DTB_BINARY,
scheme::SchemeId,
syscall::{
data::Stat,
error::*,
flag::{MODE_FILE, O_STAT, SEEK_CUR, SEEK_END, SEEK_SET},
usercopy::{UserSliceRo, UserSliceWo},
},
};
use crate::syscall::data::Stat;
use crate::syscall::error::*;
use crate::syscall::usercopy::{UserSliceRo, UserSliceWo};
use super::{KernelScheme, OpenResult, CallerCtx};
pub struct DtbScheme;
@@ -43,7 +41,7 @@ impl DtbScheme {
let dtb = match DTB_BINARY.get() {
Some(dtb) => dtb.as_slice(),
None => &[]
None => &[],
};
Box::from(dtb)
@@ -56,9 +54,7 @@ impl DtbScheme {
}
impl KernelScheme for DtbScheme {
fn kopen(&self, path: &str, _flags: usize, _ctx: CallerCtx) -> Result<OpenResult> {
let path = path.trim_matches('/');
if path.is_empty() {
@@ -66,12 +62,15 @@ impl KernelScheme for DtbScheme {
let mut handles_guard = HANDLES.write();
let _ = handles_guard.insert(id, Handle {
offset: 0,
kind: HandleKind::RawData,
stat: _flags & O_STAT == O_STAT,
});
return Ok(OpenResult::SchemeLocal(id))
let _ = handles_guard.insert(
id,
Handle {
offset: 0,
kind: HandleKind::RawData,
stat: _flags & O_STAT == O_STAT,
},
);
return Ok(OpenResult::SchemeLocal(id));
}
Err(Error::new(ENOENT))
@@ -91,15 +90,24 @@ impl KernelScheme for DtbScheme {
let new_offset = match whence {
SEEK_SET => pos as usize,
SEEK_CUR => if pos < 0 {
handle.offset.checked_sub((-pos) as usize).ok_or(Error::new(EINVAL))?
} else {
handle.offset.saturating_add(pos as usize)
SEEK_CUR => {
if pos < 0 {
handle
.offset
.checked_sub((-pos) as usize)
.ok_or(Error::new(EINVAL))?
} else {
handle.offset.saturating_add(pos as usize)
}
}
SEEK_END => if pos < 0 {
file_len.checked_sub((-pos) as usize).ok_or(Error::new(EINVAL))?
} else {
file_len
SEEK_END => {
if pos < 0 {
file_len
.checked_sub((-pos) as usize)
.ok_or(Error::new(EINVAL))?
} else {
file_len
}
}
_ => return Err(Error::new(EINVAL)),
};
@@ -144,11 +152,10 @@ impl KernelScheme for DtbScheme {
}
fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result<()> {
let handles = HANDLES.read();
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
buf.copy_exactly(&match handle.kind {
HandleKind::RawData => {
HandleKind::RawData => {
let data = DATA.get().ok_or(Error::new(EBADFD))?;
Stat {
st_mode: MODE_FILE,
+13 -6
View File
@@ -1,12 +1,16 @@
use alloc::sync::Arc;
use core::mem;
use crate::event::{EventQueue, EventQueueId, next_queue_id, queues, queues_mut};
use crate::syscall::data::Event;
use crate::syscall::error::*;
use crate::syscall::usercopy::{UserSliceWo, UserSliceRo};
use crate::{
event::{next_queue_id, queues, queues_mut, EventQueue, EventQueueId},
syscall::{
data::Event,
error::*,
usercopy::{UserSliceRo, UserSliceWo},
},
};
use super::{KernelScheme, CallerCtx, OpenResult};
use super::{CallerCtx, KernelScheme, OpenResult};
pub struct EventScheme;
@@ -34,7 +38,10 @@ impl KernelScheme for EventScheme {
fn close(&self, id: usize) -> Result<()> {
let id = EventQueueId::from(id);
queues_mut().remove(&id).ok_or(Error::new(EBADF)).and(Ok(()))
queues_mut()
.remove(&id)
.ok_or(Error::new(EBADF))
.and(Ok(()))
}
fn kread(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
let id = EventQueueId::from(id);
+115 -76
View File
@@ -1,23 +1,28 @@
use core::{mem, str};
use core::str::FromStr;
use core::sync::atomic::{AtomicUsize, Ordering};
use core::{
mem, str,
str::FromStr,
sync::atomic::{AtomicUsize, Ordering},
};
use alloc::collections::BTreeMap;
use alloc::vec::Vec;
use alloc::string::String;
use alloc::{collections::BTreeMap, string::String, vec::Vec};
use spin::{Mutex, RwLock, Once};
use spin::{Mutex, Once, RwLock};
use crate::arch::interrupt::{available_irqs_iter, bsp_apic_id, is_reserved, set_reserved};
use crate::{event, LogicalCpuId};
use crate::interrupt::irq::acknowledge;
use crate::syscall::data::Stat;
use crate::syscall::error::*;
use crate::syscall::flag::{EventFlags, EVENT_READ, O_DIRECTORY, O_CREAT, O_STAT, MODE_CHR, MODE_DIR};
use crate::syscall::usercopy::{UserSliceWo, UserSliceRo};
use crate::{
event,
interrupt::irq::acknowledge,
syscall::{
data::Stat,
error::*,
flag::{EventFlags, EVENT_READ, MODE_CHR, MODE_DIR, O_CREAT, O_DIRECTORY, O_STAT},
usercopy::{UserSliceRo, UserSliceWo},
},
LogicalCpuId,
};
use super::{GlobalSchemes, OpenResult, CallerCtx, calc_seek_offset};
use super::{calc_seek_offset, CallerCtx, GlobalSchemes, OpenResult};
/// IRQ queues
pub(super) static COUNTS: Mutex<[usize; 224]> = Mutex::new([0; 224]);
@@ -42,21 +47,23 @@ const INO_BSP: u64 = 0x8001_0000_0000_0000;
/// Add to the input queue
#[no_mangle]
pub extern fn irq_trigger(irq: u8) {
pub extern "C" fn irq_trigger(irq: u8) {
COUNTS.lock()[irq as usize] += 1;
for (fd, _) in HANDLES.read().iter().filter_map(|(fd, handle)| Some((fd, handle.as_irq_handle()?))).filter(|&(_, (_, handle_irq))| handle_irq == irq) {
for (fd, _) in HANDLES
.read()
.iter()
.filter_map(|(fd, handle)| Some((fd, handle.as_irq_handle()?)))
.filter(|&(_, (_, handle_irq))| handle_irq == irq)
{
event::trigger(GlobalSchemes::Irq.scheme_id(), *fd, EVENT_READ);
}
}
enum Handle {
Irq {
ack: AtomicUsize,
irq: u8,
},
Avail(u8, Vec<u8>, AtomicUsize), // CPU id, data, offset
TopLevel(Vec<u8>, AtomicUsize), // data, offset
Irq { ack: AtomicUsize, irq: u8 },
Avail(u8, Vec<u8>, AtomicUsize), // CPU id, data, offset
TopLevel(Vec<u8>, AtomicUsize), // data, offset
Bsp,
}
impl Handle {
@@ -80,49 +87,59 @@ impl IrqScheme {
use crate::acpi::madt::*;
match unsafe { MADT.as_ref() } {
Some(madt) => {
madt.iter().filter_map(|entry| match entry {
Some(madt) => madt
.iter()
.filter_map(|entry| match entry {
MadtEntry::LocalApic(apic) => Some(apic.id),
_ => None,
}).collect::<Vec<_>>()
},
})
.collect::<Vec<_>>(),
None => {
log::warn!("no MADT found, defaulting to 1 CPU");
vec!(0)
vec![0]
}
}
};
#[cfg(not(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64"))))]
let cpus = vec!(0);
let cpus = vec![0];
CPUS.call_once(|| cpus);
}
fn open_ext_irq(flags: usize, cpu_id: u8, path_str: &str) -> Result<Handle> {
let irq_number = u8::from_str(path_str).or(Err(Error::new(ENOENT)))?;
Ok(if irq_number < BASE_IRQ_COUNT && Some(u32::from(cpu_id)) == bsp_apic_id() {
// Give legacy IRQs only to `irq:{0..15}` and `irq:cpu-<BSP>/{0..15}` (same handles).
//
// The only CPUs don't have the legacy IRQs in their IDTs.
Ok(
if irq_number < BASE_IRQ_COUNT && Some(u32::from(cpu_id)) == bsp_apic_id() {
// Give legacy IRQs only to `irq:{0..15}` and `irq:cpu-<BSP>/{0..15}` (same handles).
//
// The only CPUs don't have the legacy IRQs in their IDTs.
Handle::Irq {
ack: AtomicUsize::new(0),
irq: irq_number,
}
} else if irq_number < TOTAL_IRQ_COUNT {
if flags & O_CREAT == 0 && flags & O_STAT == 0 {
return Err(Error::new(EINVAL));
}
if flags & O_STAT == 0 {
if is_reserved(LogicalCpuId::new(cpu_id.into()), irq_to_vector(irq_number)) {
return Err(Error::new(EEXIST));
Handle::Irq {
ack: AtomicUsize::new(0),
irq: irq_number,
}
set_reserved(LogicalCpuId::new(cpu_id.into()), irq_to_vector(irq_number), true);
}
Handle::Irq { ack: AtomicUsize::new(0), irq: irq_number }
} else {
return Err(Error::new(ENOENT));
})
} else if irq_number < TOTAL_IRQ_COUNT {
if flags & O_CREAT == 0 && flags & O_STAT == 0 {
return Err(Error::new(EINVAL));
}
if flags & O_STAT == 0 {
if is_reserved(LogicalCpuId::new(cpu_id.into()), irq_to_vector(irq_number)) {
return Err(Error::new(EEXIST));
}
set_reserved(
LogicalCpuId::new(cpu_id.into()),
irq_to_vector(irq_number),
true,
);
}
Handle::Irq {
ack: AtomicUsize::new(0),
irq: irq_number,
}
} else {
return Err(Error::new(ENOENT));
},
)
}
}
@@ -135,12 +152,16 @@ const fn vector_to_irq(vector: u8) -> u8 {
impl crate::scheme::KernelScheme for IrqScheme {
fn kopen(&self, path: &str, flags: usize, ctx: CallerCtx) -> Result<OpenResult> {
if ctx.uid != 0 { return Err(Error::new(EACCES)) }
if ctx.uid != 0 {
return Err(Error::new(EACCES));
}
let path_str = path.trim_start_matches('/');
let handle: Handle = if path_str.is_empty() {
if flags & O_DIRECTORY == 0 && flags & O_STAT == 0 { return Err(Error::new(EISDIR)) }
if flags & O_DIRECTORY == 0 && flags & O_STAT == 0 {
return Err(Error::new(EISDIR));
}
// list every logical CPU in the format of e.g. `cpu-1b`
@@ -192,7 +213,10 @@ impl crate::scheme::KernelScheme for IrqScheme {
}
} else if let Ok(plain_irq_number) = u8::from_str(path_str) {
if plain_irq_number < BASE_IRQ_COUNT {
Handle::Irq { ack: AtomicUsize::new(0), irq: plain_irq_number }
Handle::Irq {
ack: AtomicUsize::new(0),
irq: plain_irq_number,
}
} else {
return Err(Error::new(ENOENT));
}
@@ -220,7 +244,6 @@ impl crate::scheme::KernelScheme for IrqScheme {
}
}
fn fcntl(&self, _id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
Ok(0)
}
@@ -229,7 +252,6 @@ impl crate::scheme::KernelScheme for IrqScheme {
Ok(EventFlags::empty())
}
fn fsync(&self, _file: usize) -> Result<()> {
Ok(())
}
@@ -238,7 +260,10 @@ impl crate::scheme::KernelScheme for IrqScheme {
let handles_guard = HANDLES.read();
let handle = handles_guard.get(&id).ok_or(Error::new(EBADF))?;
if let &Handle::Irq { irq: handle_irq, .. } = handle {
if let &Handle::Irq {
irq: handle_irq, ..
} = handle
{
if handle_irq > BASE_IRQ_COUNT {
set_reserved(LogicalCpuId::BSP, irq_to_vector(handle_irq), false);
}
@@ -250,19 +275,26 @@ impl crate::scheme::KernelScheme for IrqScheme {
let handle = handles_guard.get(&file).ok_or(Error::new(EBADF))?;
match handle {
&Handle::Irq { irq: handle_irq, ack: ref handle_ack } => if buffer.len() >= mem::size_of::<usize>() {
let ack = buffer.read_usize()?;
let current = COUNTS.lock()[handle_irq as usize];
&Handle::Irq {
irq: handle_irq,
ack: ref handle_ack,
} => {
if buffer.len() >= mem::size_of::<usize>() {
let ack = buffer.read_usize()?;
let current = COUNTS.lock()[handle_irq as usize];
if ack == current {
handle_ack.store(ack, Ordering::SeqCst);
unsafe { acknowledge(handle_irq as usize); }
Ok(mem::size_of::<usize>())
if ack == current {
handle_ack.store(ack, Ordering::SeqCst);
unsafe {
acknowledge(handle_irq as usize);
}
Ok(mem::size_of::<usize>())
} else {
Ok(0)
}
} else {
Ok(0)
Err(Error::new(EINVAL))
}
} else {
Err(Error::new(EINVAL))
}
_ => Err(Error::new(EBADF)),
}
@@ -273,7 +305,9 @@ impl crate::scheme::KernelScheme for IrqScheme {
let handle = handles_guard.get(&id).ok_or(Error::new(EBADF))?;
buf.copy_exactly(&match *handle {
Handle::Irq { irq: handle_irq, .. } => Stat {
Handle::Irq {
irq: handle_irq, ..
} => Stat {
st_mode: MODE_CHR | 0o600,
st_size: mem::size_of::<usize>() as u64,
st_blocks: 1,
@@ -318,7 +352,8 @@ impl crate::scheme::KernelScheme for IrqScheme {
Handle::Bsp => format!("irq:bsp"),
Handle::Avail(cpu_id, _, _) => format!("irq:cpu-{:2x}", cpu_id),
Handle::TopLevel(_, _) => format!("irq:"),
}.into_bytes();
}
.into_bytes();
buf.copy_common_bytes_from_slice(&scheme_path)
}
@@ -328,16 +363,21 @@ impl crate::scheme::KernelScheme for IrqScheme {
match *handle {
// Ensures that the length of the buffer is larger than the size of a usize
Handle::Irq { irq: handle_irq, ack: ref handle_ack } => if buffer.len() >= mem::size_of::<usize>() {
let current = COUNTS.lock()[handle_irq as usize];
if handle_ack.load(Ordering::SeqCst) != current {
buffer.write_usize(current)?;
Ok(mem::size_of::<usize>())
Handle::Irq {
irq: handle_irq,
ack: ref handle_ack,
} => {
if buffer.len() >= mem::size_of::<usize>() {
let current = COUNTS.lock()[handle_irq as usize];
if handle_ack.load(Ordering::SeqCst) != current {
buffer.write_usize(current)?;
Ok(mem::size_of::<usize>())
} else {
Ok(0)
}
} else {
Ok(0)
Err(Error::new(EINVAL))
}
} else {
Err(Error::new(EINVAL))
}
Handle::Bsp => {
if buffer.len() < mem::size_of::<usize>() {
@@ -359,5 +399,4 @@ impl crate::scheme::KernelScheme for IrqScheme {
}
}
}
}
+22 -12
View File
@@ -1,14 +1,18 @@
use alloc::collections::BTreeMap;
use core::{mem, str};
use core::sync::atomic::{AtomicUsize, Ordering};
use core::{
mem, str,
sync::atomic::{AtomicUsize, Ordering},
};
use spin::RwLock;
use crate::syscall::data::ITimerSpec;
use crate::syscall::error::*;
use crate::syscall::flag::{CLOCK_REALTIME, CLOCK_MONOTONIC, EventFlags};
use crate::syscall::usercopy::{UserSliceWo, UserSliceRo};
use crate::syscall::{
data::ITimerSpec,
error::*,
flag::{EventFlags, CLOCK_MONOTONIC, CLOCK_REALTIME},
usercopy::{UserSliceRo, UserSliceWo},
};
use super::{KernelScheme, CallerCtx, OpenResult};
use super::{CallerCtx, KernelScheme, OpenResult};
pub struct ITimerScheme;
static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
@@ -22,7 +26,7 @@ impl KernelScheme for ITimerScheme {
match clock {
CLOCK_REALTIME => (),
CLOCK_MONOTONIC => (),
_ => return Err(Error::new(ENOENT))
_ => return Err(Error::new(ENOENT)),
}
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
@@ -35,9 +39,12 @@ impl KernelScheme for ITimerScheme {
Ok(0)
}
fn fevent(&self, id: usize, _flags: EventFlags) -> Result<EventFlags> {
fn fevent(&self, id: usize, _flags: EventFlags) -> Result<EventFlags> {
let handles = HANDLES.read();
handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(EventFlags::empty()))
handles
.get(&id)
.ok_or(Error::new(EBADF))
.and(Ok(EventFlags::empty()))
}
fn fsync(&self, id: usize) -> Result<()> {
@@ -45,7 +52,11 @@ impl KernelScheme for ITimerScheme {
}
fn close(&self, id: usize) -> Result<()> {
HANDLES.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(()))
HANDLES
.write()
.remove(&id)
.ok_or(Error::new(EBADF))
.and(Ok(()))
}
fn kread(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
let _clock = {
@@ -89,5 +100,4 @@ impl KernelScheme for ITimerScheme {
buf.copy_common_bytes_from_slice(format!("time:{}", clock).as_bytes())
}
}
+118 -58
View File
@@ -1,22 +1,25 @@
use core::num::NonZeroUsize;
use alloc::sync::Arc;
use alloc::{sync::Arc, vec::Vec};
use rmm::PhysicalAddress;
use alloc::vec::Vec;
use spin::RwLock;
use crate::memory::{free_frames, used_frames, PAGE_SIZE, Frame};
use crate::context::memory::{AddrSpace, Grant, PageSpan, handle_notify_files};
use crate::paging::VirtualAddress;
use crate::{
context::memory::{handle_notify_files, AddrSpace, Grant, PageSpan},
memory::{free_frames, used_frames, Frame, PAGE_SIZE},
paging::VirtualAddress,
};
use crate::paging::entry::EntryFlags;
use crate::syscall::data::{Map, StatVfs};
use crate::syscall::flag::MapFlags;
use crate::syscall::error::*;
use crate::syscall::usercopy::UserSliceWo;
use crate::syscall::{
data::{Map, StatVfs},
error::*,
flag::MapFlags,
usercopy::UserSliceWo,
};
use super::{KernelScheme, CallerCtx, OpenResult};
use super::{CallerCtx, KernelScheme, OpenResult};
pub struct MemoryScheme;
@@ -59,14 +62,18 @@ fn from_raw(raw: u32) -> Option<(HandleTy, MemoryType, HandleFlags)> {
_ => return None,
},
HandleFlags::from_bits_truncate((raw >> 16) as u16)
HandleFlags::from_bits_truncate((raw >> 16) as u16),
))
}
impl MemoryScheme {
pub fn fmap_anonymous(addr_space: &Arc<RwLock<AddrSpace>>, map: &Map, is_phys_contiguous: bool) -> Result<usize> {
let span = PageSpan::validate_nonempty(VirtualAddress::new(map.address), map.size).ok_or(Error::new(EINVAL))?;
pub fn fmap_anonymous(
addr_space: &Arc<RwLock<AddrSpace>>,
map: &Map,
is_phys_contiguous: bool,
) -> Result<usize> {
let span = PageSpan::validate_nonempty(VirtualAddress::new(map.address), map.size)
.ok_or(Error::new(EINVAL))?;
let page_count = NonZeroUsize::new(span.count).ok_or(Error::new(EINVAL))?;
let mut notify_files = Vec::new();
@@ -76,65 +83,93 @@ impl MemoryScheme {
return Err(Error::new(EOPNOTSUPP));
}
let page = addr_space
.write()
.mmap((map.address != 0).then_some(span.base), page_count, map.flags, &mut notify_files, |dst_page, flags, mapper, flusher| {
let page = addr_space.write().mmap(
(map.address != 0).then_some(span.base),
page_count,
map.flags,
&mut notify_files,
|dst_page, flags, mapper, flusher| {
let span = PageSpan::new(dst_page, page_count.get());
if is_phys_contiguous {
Ok(Grant::zeroed_phys_contiguous(span, flags, mapper, flusher)?)
} else {
Ok(Grant::zeroed(span, flags, mapper, flusher, map.flags.contains(MapFlags::MAP_SHARED))?)
Ok(Grant::zeroed(
span,
flags,
mapper,
flusher,
map.flags.contains(MapFlags::MAP_SHARED),
)?)
}
})?;
},
)?;
handle_notify_files(notify_files);
Ok(page.start_address().data())
}
pub fn physmap(physical_address: usize, size: usize, flags: MapFlags, memory_type: MemoryType) -> Result<usize> {
pub fn physmap(
physical_address: usize,
size: usize,
flags: MapFlags,
memory_type: MemoryType,
) -> Result<usize> {
// TODO: Check physical_address against the real MAXPHYADDR.
let end = 1 << 52;
if (physical_address.saturating_add(size) as u64) > end || physical_address % PAGE_SIZE != 0 {
if (physical_address.saturating_add(size) as u64) > end || physical_address % PAGE_SIZE != 0
{
return Err(Error::new(EINVAL));
}
if size % PAGE_SIZE != 0 {
log::warn!("physmap size {} is not multiple of PAGE_SIZE {}", size, PAGE_SIZE);
log::warn!(
"physmap size {} is not multiple of PAGE_SIZE {}",
size,
PAGE_SIZE
);
return Err(Error::new(EINVAL));
}
let page_count = NonZeroUsize::new(size.div_ceil(PAGE_SIZE)).ok_or(Error::new(EINVAL))?;
AddrSpace::current()?.write().mmap_anywhere(page_count, flags, |dst_page, mut page_flags, dst_mapper, dst_flusher| {
match memory_type {
// Default
MemoryType::Writeback => (),
AddrSpace::current()?
.write()
.mmap_anywhere(
page_count,
flags,
|dst_page, mut page_flags, dst_mapper, dst_flusher| {
match memory_type {
// Default
MemoryType::Writeback => (),
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] // TODO: AARCH64
MemoryType::WriteCombining => page_flags = page_flags.custom_flag(EntryFlags::HUGE_PAGE.bits(), true),
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] // TODO: AARCH64
MemoryType::WriteCombining => {
page_flags = page_flags.custom_flag(EntryFlags::HUGE_PAGE.bits(), true)
}
MemoryType::Uncacheable => page_flags = page_flags.custom_flag(EntryFlags::NO_CACHE.bits(), true),
MemoryType::Uncacheable => {
page_flags = page_flags.custom_flag(EntryFlags::NO_CACHE.bits(), true)
}
// MemoryType::DeviceMemory doesn't exist on x86 && x86_64, which instead support
// uncacheable, write-combining, write-through, write-protect, and write-back.
// MemoryType::DeviceMemory doesn't exist on x86 && x86_64, which instead support
// uncacheable, write-combining, write-through, write-protect, and write-back.
#[cfg(target_arch = "aarch64")]
MemoryType::DeviceMemory => {
page_flags = page_flags.custom_flag(EntryFlags::DEV_MEM.bits(), true)
}
#[cfg(target_arch = "aarch64")]
MemoryType::DeviceMemory => page_flags = page_flags.custom_flag(EntryFlags::DEV_MEM.bits(), true),
_ => (),
}
_ => (),
}
Grant::physmap(
Frame::containing_address(PhysicalAddress::new(physical_address)),
PageSpan::new(
dst_page,
page_count.get(),
),
page_flags,
dst_mapper,
dst_flusher,
Grant::physmap(
Frame::containing_address(PhysicalAddress::new(physical_address)),
PageSpan::new(dst_page, page_count.get()),
page_flags,
dst_mapper,
dst_flusher,
)
},
)
}).map(|page| page.start_address().data())
.map(|page| page.start_address().data())
}
}
impl KernelScheme for MemoryScheme {
@@ -162,19 +197,31 @@ impl KernelScheme for MemoryScheme {
_ => return Err(Error::new(ENOENT)),
};
let flags = type_str.split(',').filter_map(|ty_str| match ty_str {
//"32" => HandleFlags::BELOW_4G,
"phys_contiguous" => Some(Some(HandleFlags::PHYS_CONTIGUOUS)),
"" => None,
_ => Some(None),
}).collect::<Option<HandleFlags>>().ok_or(Error::new(ENOENT))?;
let flags = type_str
.split(',')
.filter_map(|ty_str| match ty_str {
//"32" => HandleFlags::BELOW_4G,
"phys_contiguous" => Some(Some(HandleFlags::PHYS_CONTIGUOUS)),
"" => None,
_ => Some(None),
})
.collect::<Option<HandleFlags>>()
.ok_or(Error::new(ENOENT))?;
// TODO: Support arches with other default memory types?
if ctx.uid != 0 && (!flags.is_empty() || !matches!((handle_ty, mem_ty), (HandleTy::Allocated, MemoryType::Writeback))) {
if ctx.uid != 0
&& (!flags.is_empty()
|| !matches!(
(handle_ty, mem_ty),
(HandleTy::Allocated, MemoryType::Writeback)
))
{
return Err(Error::new(EACCES));
}
Ok(OpenResult::SchemeLocal((handle_ty as usize) | ((mem_ty as usize) << 8) | (usize::from(flags.bits()) << 16)))
Ok(OpenResult::SchemeLocal(
(handle_ty as usize) | ((mem_ty as usize) << 8) | (usize::from(flags.bits()) << 16),
))
}
fn fcntl(&self, _id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
@@ -184,11 +231,24 @@ impl KernelScheme for MemoryScheme {
fn close(&self, _id: usize) -> Result<()> {
Ok(())
}
fn kfmap(&self, id: usize, addr_space: &Arc<RwLock<AddrSpace>>, map: &Map, _consume: bool) -> Result<usize> {
let (handle_ty, mem_ty, flags) = u32::try_from(id).ok().and_then(from_raw).ok_or(Error::new(EBADF))?;
fn kfmap(
&self,
id: usize,
addr_space: &Arc<RwLock<AddrSpace>>,
map: &Map,
_consume: bool,
) -> Result<usize> {
let (handle_ty, mem_ty, flags) = u32::try_from(id)
.ok()
.and_then(from_raw)
.ok_or(Error::new(EBADF))?;
match handle_ty {
HandleTy::Allocated => Self::fmap_anonymous(addr_space, map, flags.contains(HandleFlags::PHYS_CONTIGUOUS)),
HandleTy::Allocated => Self::fmap_anonymous(
addr_space,
map,
flags.contains(HandleFlags::PHYS_CONTIGUOUS),
),
HandleTy::PhysBorrow => Self::physmap(map.offset, map.size, map.flags, mem_ty),
}
}
+118 -53
View File
@@ -6,40 +6,30 @@
//! The kernel validates paths and file descriptors before they are passed to schemes,
//! also stripping the scheme identifier of paths if necessary.
use alloc::{
boxed::Box,
collections::BTreeMap,
string::ToString,
sync::Arc,
vec::Vec,
};
use hashbrown::HashMap;
use syscall::{MunmapFlags, SendFdFlags, EventFlags, SEEK_SET, SEEK_CUR, SEEK_END};
use alloc::{boxed::Box, collections::BTreeMap, string::ToString, sync::Arc, vec::Vec};
use core::sync::atomic::AtomicUsize;
use hashbrown::HashMap;
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
use syscall::{EventFlags, MunmapFlags, SendFdFlags, SEEK_CUR, SEEK_END, SEEK_SET};
use crate::context::file::FileDescription;
use crate::context::memory::AddrSpace;
use crate::syscall::error::*;
use crate::syscall::usercopy::{UserSliceRo, UserSliceWo};
use crate::{
context::{file::FileDescription, memory::AddrSpace},
syscall::{
error::*,
usercopy::{UserSliceRo, UserSliceWo},
},
};
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
use self::acpi::AcpiScheme;
#[cfg(all(any(target_arch = "aarch64")))]
use self::dtb::DtbScheme;
use self::debug::DebugScheme;
use self::event::EventScheme;
use self::irq::IrqScheme;
use self::itimer::ITimerScheme;
use self::memory::MemoryScheme;
use self::pipe::PipeScheme;
use self::proc::ProcScheme;
use self::root::RootScheme;
use self::serio::SerioScheme;
use self::sys::SysScheme;
use self::time::TimeScheme;
use self::user::UserScheme;
use self::{
debug::DebugScheme, event::EventScheme, irq::IrqScheme, itimer::ITimerScheme,
memory::MemoryScheme, pipe::PipeScheme, proc::ProcScheme, root::RootScheme, serio::SerioScheme,
sys::SysScheme, time::TimeScheme, user::UserScheme,
};
/// When compiled with the "acpi" feature - `acpi:` - allows drivers to read a limited set of ACPI tables.
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
@@ -96,7 +86,7 @@ int_like!(SchemeId, usize);
int_like!(FileHandle, AtomicFileHandle, usize, AtomicUsize);
pub struct SchemeIter<'a> {
inner: Option<hashbrown::hash_map::Iter<'a, Box<str>, SchemeId>>
inner: Option<hashbrown::hash_map::Iter<'a, Box<str>, SchemeId>>,
}
impl<'a> Iterator for SchemeIter<'a> {
@@ -127,14 +117,27 @@ impl SchemeList {
let mut insert_globals = |globals: &[GlobalSchemes]| {
for &g in globals {
list.map.insert(SchemeId::from(g as usize), KernelSchemes::Global(g));
list.map
.insert(SchemeId::from(g as usize), KernelSchemes::Global(g));
}
};
// TODO: impl TryFrom<SchemeId> and bypass map for global schemes?
{
use GlobalSchemes::*;
insert_globals(&[Debug, Event, Memory, Pipe, Serio, Irq, Time, ITimer, Sys, ProcFull, ProcRestricted]);
insert_globals(&[
Debug,
Event,
Memory,
Pipe,
Serio,
Irq,
Time,
ITimer,
Sys,
ProcFull,
ProcRestricted,
]);
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
insert_globals(&[Acpi]);
@@ -155,8 +158,10 @@ impl SchemeList {
//TODO: Only memory: is in the null namespace right now. It should be removed when
//anonymous mmap's are implemented
self.insert_global(ns, "memory", GlobalSchemes::Memory).unwrap();
self.insert_global(ns, "thisproc", GlobalSchemes::ProcRestricted).unwrap();
self.insert_global(ns, "memory", GlobalSchemes::Memory)
.unwrap();
self.insert_global(ns, "thisproc", GlobalSchemes::ProcRestricted)
.unwrap();
self.insert_global(ns, "pipe", GlobalSchemes::Pipe).unwrap();
}
@@ -166,10 +171,16 @@ impl SchemeList {
self.next_ns += 1;
self.names.insert(ns, HashMap::new());
self.insert(ns, "", |scheme_id| KernelSchemes::Root(Arc::new(RootScheme::new(ns, scheme_id)))).unwrap();
self.insert_global(ns, "event", GlobalSchemes::Event).unwrap();
self.insert_global(ns, "itimer", GlobalSchemes::ITimer).unwrap();
self.insert_global(ns, "memory", GlobalSchemes::Memory).unwrap();
self.insert(ns, "", |scheme_id| {
KernelSchemes::Root(Arc::new(RootScheme::new(ns, scheme_id)))
})
.unwrap();
self.insert_global(ns, "event", GlobalSchemes::Event)
.unwrap();
self.insert_global(ns, "itimer", GlobalSchemes::ITimer)
.unwrap();
self.insert_global(ns, "memory", GlobalSchemes::Memory)
.unwrap();
self.insert_global(ns, "pipe", GlobalSchemes::Pipe).unwrap();
self.insert_global(ns, "sys", GlobalSchemes::Sys).unwrap();
self.insert_global(ns, "time", GlobalSchemes::Time).unwrap();
@@ -185,20 +196,30 @@ impl SchemeList {
// These schemes should only be available on the root
#[cfg(all(any(target_arch = "aarch64")))]
{
self.insert_global(ns, "kernel.dtb", GlobalSchemes::Dtb).unwrap();
self.insert_global(ns, "kernel.dtb", GlobalSchemes::Dtb)
.unwrap();
}
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
{
self.insert_global(ns, "kernel.acpi", GlobalSchemes::Acpi).unwrap();
self.insert_global(ns, "kernel.acpi", GlobalSchemes::Acpi)
.unwrap();
}
self.insert_global(ns, "debug", GlobalSchemes::Debug).unwrap();
self.insert_global(ns, "debug", GlobalSchemes::Debug)
.unwrap();
self.insert_global(ns, "irq", GlobalSchemes::Irq).unwrap();
self.insert_global(ns, "proc", GlobalSchemes::ProcFull).unwrap();
self.insert_global(ns, "thisproc", GlobalSchemes::ProcRestricted).unwrap();
self.insert_global(ns, "serio", GlobalSchemes::Serio).unwrap();
self.insert_global(ns, "proc", GlobalSchemes::ProcFull)
.unwrap();
self.insert_global(ns, "thisproc", GlobalSchemes::ProcRestricted)
.unwrap();
self.insert_global(ns, "serio", GlobalSchemes::Serio)
.unwrap();
}
pub fn make_ns(&mut self, from: SchemeNamespace, names: impl IntoIterator<Item = Box<str>>) -> Result<SchemeNamespace> {
pub fn make_ns(
&mut self,
from: SchemeNamespace,
names: impl IntoIterator<Item = Box<str>>,
) -> Result<SchemeNamespace> {
// Create an empty namespace
let to = self.new_ns();
@@ -209,7 +230,10 @@ impl SchemeList {
};
if let Some(ref mut names) = self.names.get_mut(&to) {
if names.insert(name.to_string().into_boxed_str(), id).is_some() {
if names
.insert(name.to_string().into_boxed_str(), id)
.is_some()
{
return Err(Error::new(EEXIST));
}
} else {
@@ -222,7 +246,7 @@ impl SchemeList {
pub fn iter_name(&self, ns: SchemeNamespace) -> SchemeIter {
SchemeIter {
inner: self.names.get(&ns).map(|names| names.iter())
inner: self.names.get(&ns).map(|names| names.iter()),
}
}
@@ -240,8 +264,17 @@ impl SchemeList {
None
}
pub fn insert_global(&mut self, ns: SchemeNamespace, name: &str, global: GlobalSchemes) -> Result<()> {
let prev = self.names.get_mut(&ns).ok_or(Error::new(ENODEV))?.insert(name.into(), global.scheme_id());
pub fn insert_global(
&mut self,
ns: SchemeNamespace,
name: &str,
global: GlobalSchemes,
) -> Result<()> {
let prev = self
.names
.get_mut(&ns)
.ok_or(Error::new(ENODEV))?
.insert(name.into(), global.scheme_id());
if prev.is_some() {
return Err(Error::new(EEXIST));
@@ -251,11 +284,22 @@ impl SchemeList {
}
/// Create a new scheme.
pub fn insert(&mut self, ns: SchemeNamespace, name: &str, scheme_fn: impl FnOnce(SchemeId) -> KernelSchemes) -> Result<SchemeId> {
self.insert_and_pass(ns, name, |id| (scheme_fn(id), ())).map(|(id, ())| id)
pub fn insert(
&mut self,
ns: SchemeNamespace,
name: &str,
scheme_fn: impl FnOnce(SchemeId) -> KernelSchemes,
) -> Result<SchemeId> {
self.insert_and_pass(ns, name, |id| (scheme_fn(id), ()))
.map(|(id, ())| id)
}
pub fn insert_and_pass<T>(&mut self, ns: SchemeNamespace, name: &str, scheme_fn: impl FnOnce(SchemeId) -> (KernelSchemes, T)) -> Result<(SchemeId, T)> {
pub fn insert_and_pass<T>(
&mut self,
ns: SchemeNamespace,
name: &str,
scheme_fn: impl FnOnce(SchemeId) -> (KernelSchemes, T),
) -> Result<(SchemeId, T)> {
if let Some(names) = self.names.get(&ns) {
if names.contains_key(name) {
return Err(Error::new(EEXIST));
@@ -283,7 +327,9 @@ impl SchemeList {
assert!(self.map.insert(id, new_scheme).is_none());
if let Some(ref mut names) = self.names.get_mut(&ns) {
assert!(names.insert(name.to_string().into_boxed_str(), id).is_none());
assert!(names
.insert(name.to_string().into_boxed_str(), id)
.is_none());
} else {
// Nonexistent namespace, posssibly null namespace
return Err(Error::new(ENODEV));
@@ -332,7 +378,13 @@ pub trait KernelScheme: Send + Sync + 'static {
Err(Error::new(ENOENT))
}
fn kfmap(&self, number: usize, addr_space: &Arc<RwLock<AddrSpace>>, map: &crate::syscall::data::Map, consume: bool) -> Result<usize> {
fn kfmap(
&self,
number: usize,
addr_space: &Arc<RwLock<AddrSpace>>,
map: &crate::syscall::data::Map,
consume: bool,
) -> Result<usize> {
Err(Error::new(EOPNOTSUPP))
}
fn kfunmap(&self, number: usize, offset: usize, size: usize, flags: MunmapFlags) -> Result<()> {
@@ -361,7 +413,13 @@ pub trait KernelScheme: Send + Sync + 'static {
Err(Error::new(EBADF))
}
fn ksendfd(&self, id: usize, desc: Arc<RwLock<FileDescription>>, flags: SendFdFlags, arg: u64) -> Result<usize> {
fn ksendfd(
&self,
id: usize,
desc: Arc<RwLock<FileDescription>>,
flags: SendFdFlags,
arg: u64,
) -> Result<usize> {
Err(Error::new(EOPNOTSUPP))
}
@@ -411,10 +469,17 @@ pub struct CallerCtx {
pub gid: u32,
}
pub fn calc_seek_offset(cur_pos: usize, rel_pos: isize, whence: usize, len: usize) -> Result<usize> {
pub fn calc_seek_offset(
cur_pos: usize,
rel_pos: isize,
whence: usize,
len: usize,
) -> Result<usize> {
match whence {
SEEK_SET => usize::try_from(rel_pos).map_err(|_| Error::new(EINVAL)),
SEEK_CUR => cur_pos.checked_add_signed(rel_pos).ok_or(Error::new(EOVERFLOW)),
SEEK_CUR => cur_pos
.checked_add_signed(rel_pos)
.ok_or(Error::new(EOVERFLOW)),
SEEK_END => len.checked_add_signed(rel_pos).ok_or(Error::new(EOVERFLOW)),
_ => return Err(Error::new(EINVAL)),
+56 -30
View File
@@ -1,18 +1,26 @@
use core::sync::atomic::{AtomicUsize, Ordering, AtomicBool};
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use alloc::sync::Arc;
use alloc::collections::{BTreeMap, VecDeque};
use alloc::{
collections::{BTreeMap, VecDeque},
sync::Arc,
};
use spin::{Mutex, RwLock};
use crate::event;
use crate::sync::WaitCondition;
use crate::syscall::error::{Error, Result, EAGAIN, EBADF, EINTR, EINVAL, ENOENT, EPIPE, ESPIPE};
use crate::syscall::flag::{EventFlags, EVENT_READ, EVENT_WRITE, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK, MODE_FIFO};
use crate::syscall::data::Stat;
use crate::syscall::usercopy::{UserSliceWo, UserSliceRo};
use crate::{
event,
sync::WaitCondition,
syscall::{
data::Stat,
error::{Error, Result, EAGAIN, EBADF, EINTR, EINVAL, ENOENT, EPIPE, ESPIPE},
flag::{
EventFlags, EVENT_READ, EVENT_WRITE, F_GETFL, F_SETFL, MODE_FIFO, O_ACCMODE, O_NONBLOCK,
},
usercopy::{UserSliceRo, UserSliceWo},
},
};
use super::{KernelScheme, OpenResult, CallerCtx, GlobalSchemes};
use super::{CallerCtx, GlobalSchemes, KernelScheme, OpenResult};
// TODO: Preallocate a number of scheme IDs, since there can only be *one* root namespace, and
// therefore only *one* pipe scheme.
@@ -35,16 +43,19 @@ fn from_raw_id(id: usize) -> (bool, usize) {
pub fn pipe(flags: usize) -> Result<(usize, usize)> {
let id = PIPE_NEXT_ID.fetch_add(1, Ordering::Relaxed);
PIPES.write().insert(id, Arc::new(Pipe {
read_flags: AtomicUsize::new(flags),
write_flags: AtomicUsize::new(flags),
queue: Mutex::new(VecDeque::new()),
read_condition: WaitCondition::new(),
write_condition: WaitCondition::new(),
writer_is_alive: AtomicBool::new(true),
reader_is_alive: AtomicBool::new(true),
has_run_dup: AtomicBool::new(false),
}));
PIPES.write().insert(
id,
Arc::new(Pipe {
read_flags: AtomicUsize::new(flags),
write_flags: AtomicUsize::new(flags),
queue: Mutex::new(VecDeque::new()),
read_condition: WaitCondition::new(),
write_condition: WaitCondition::new(),
writer_is_alive: AtomicBool::new(true),
reader_is_alive: AtomicBool::new(true),
has_run_dup: AtomicBool::new(false),
}),
);
Ok((id, id | WRITE_NOT_READ_BIT))
}
@@ -56,15 +67,19 @@ impl KernelScheme for PipeScheme {
let (is_writer_not_reader, key) = from_raw_id(id);
let pipe = Arc::clone(PIPES.read().get(&key).ok_or(Error::new(EBADF))?);
let flags = if is_writer_not_reader { &pipe.write_flags } else { &pipe.read_flags };
let flags = if is_writer_not_reader {
&pipe.write_flags
} else {
&pipe.read_flags
};
match cmd {
F_GETFL => Ok(flags.load(Ordering::SeqCst)),
F_SETFL => {
flags.store(arg & !O_ACCMODE, Ordering::SeqCst);
Ok(0)
},
_ => Err(Error::new(EINVAL))
}
_ => Err(Error::new(EINVAL)),
}
}
@@ -172,17 +187,26 @@ impl KernelScheme for PipeScheme {
let (s1, s2) = vec.as_slices();
let s1_count = core::cmp::min(user_buf.len(), s1.len());
let (s1_dst, s2_buf) = user_buf.split_at(s1_count).expect("s1_count <= user_buf.len()");
let (s1_dst, s2_buf) = user_buf
.split_at(s1_count)
.expect("s1_count <= user_buf.len()");
s1_dst.copy_from_slice(&s1[..s1_count])?;
let s2_count = core::cmp::min(s2_buf.len(), s2.len());
s2_buf.limit(s2_count).expect("s2_count <= s2_buf.len()").copy_from_slice(&s2[..s2_count])?;
s2_buf
.limit(s2_count)
.expect("s2_count <= s2_buf.len()")
.copy_from_slice(&s2[..s2_count])?;
let bytes_read = s1_count + s2_count;
let _ = vec.drain(..bytes_read);
if bytes_read > 0 {
event::trigger(GlobalSchemes::Pipe.scheme_id(), key | WRITE_NOT_READ_BIT, EVENT_WRITE);
event::trigger(
GlobalSchemes::Pipe.scheme_id(),
key | WRITE_NOT_READ_BIT,
EVENT_WRITE,
);
pipe.write_condition.notify();
return Ok(bytes_read);
@@ -212,7 +236,9 @@ impl KernelScheme for PipeScheme {
let bytes_left = MAX_QUEUE_SIZE.saturating_sub(vec.len());
let bytes_to_write = core::cmp::min(bytes_left, user_buf.len());
let src_buf = user_buf.limit(bytes_to_write).expect("bytes_to_write <= user_buf.len()");
let src_buf = user_buf
.limit(bytes_to_write)
.expect("bytes_to_write <= user_buf.len()");
const TMPBUF_SIZE: usize = 512;
let mut tmp_buf = [0_u8; TMPBUF_SIZE];
@@ -259,9 +285,9 @@ impl KernelScheme for PipeScheme {
}
pub struct Pipe {
read_flags: AtomicUsize, // fcntl read flags
write_flags: AtomicUsize, // fcntl write flags
read_condition: WaitCondition, // signals whether there are available bytes to read
read_flags: AtomicUsize, // fcntl read flags
write_flags: AtomicUsize, // fcntl write flags
read_condition: WaitCondition, // signals whether there are available bytes to read
write_condition: WaitCondition, // signals whether there is room for additional bytes
queue: Mutex<VecDeque<u8>>,
reader_is_alive: AtomicBool, // starts set, unset when reader closes
+525 -184
View File
File diff suppressed because it is too large Load Diff
+77 -89
View File
@@ -1,27 +1,31 @@
use alloc::{
boxed::Box,
string::ToString,
sync::Arc,
vec::Vec,
use alloc::{boxed::Box, string::ToString, sync::Arc, vec::Vec};
use core::{
str,
sync::atomic::{AtomicUsize, Ordering},
};
use hashbrown::HashMap;
use core::str;
use core::sync::atomic::{AtomicUsize, Ordering};
use spin::{Mutex, RwLock};
use crate::context;
use crate::syscall::data::Stat;
use crate::syscall::error::*;
use crate::syscall::flag::{EventFlags, O_CREAT, MODE_FILE, MODE_DIR};
use crate::scheme::{self, SchemeNamespace, SchemeId};
use crate::scheme::user::{UserInner, UserScheme};
use crate::syscall::usercopy::{UserSliceWo, UserSliceRo};
use crate::{
context,
scheme::{
self,
user::{UserInner, UserScheme},
SchemeId, SchemeNamespace,
},
syscall::{
data::Stat,
error::*,
flag::{EventFlags, MODE_DIR, MODE_FILE, O_CREAT},
usercopy::{UserSliceRo, UserSliceWo},
},
};
use super::{KernelScheme, KernelSchemes, CallerCtx, OpenResult, calc_seek_offset};
use super::{calc_seek_offset, CallerCtx, KernelScheme, KernelSchemes, OpenResult};
struct FolderInner {
data: Box<[u8]>,
pos: Mutex<usize>
pos: Mutex<usize>,
}
impl FolderInner {
@@ -47,7 +51,7 @@ impl FolderInner {
enum Handle {
Scheme(Arc<UserInner>),
File(Arc<Box<[u8]>>),
Folder(Arc<FolderInner>)
Folder(Arc<FolderInner>),
}
pub struct RootScheme {
@@ -94,10 +98,21 @@ impl KernelScheme for RootScheme {
let path_box = path.to_string().into_boxed_str();
let mut schemes = scheme::schemes_mut();
let (_scheme_id, inner) = schemes.insert_and_pass(self.scheme_ns, path, |scheme_id| {
let inner = Arc::new(UserInner::new(self.scheme_id, scheme_id, id, path_box, flags, context));
(KernelSchemes::User(UserScheme::new(Arc::downgrade(&inner))), inner)
})?;
let (_scheme_id, inner) =
schemes.insert_and_pass(self.scheme_ns, path, |scheme_id| {
let inner = Arc::new(UserInner::new(
self.scheme_id,
scheme_id,
id,
path_box,
flags,
context,
));
(
KernelSchemes::User(UserScheme::new(Arc::downgrade(&inner))),
inner,
)
})?;
inner
};
@@ -124,16 +139,14 @@ impl KernelScheme for RootScheme {
let inner = Arc::new(FolderInner {
data: data.into_boxed_slice(),
pos: Mutex::new(0)
pos: Mutex::new(0),
});
let id = self.next_id.fetch_add(1, Ordering::Relaxed);
self.handles.write().insert(id, Handle::Folder(inner));
Ok(OpenResult::SchemeLocal(id))
} else {
let inner = Arc::new(
path.as_bytes().to_vec().into_boxed_slice()
);
let inner = Arc::new(path.as_bytes().to_vec().into_boxed_slice());
let id = self.next_id.fetch_add(1, Ordering::Relaxed);
self.handles.write().insert(id, Handle::File(inner));
@@ -149,23 +162,25 @@ impl KernelScheme for RootScheme {
}
let inner = {
let handles = self.handles.read();
handles.iter().find_map(|(_id, handle)| {
match handle {
Handle::Scheme(inner) => {
if path == inner.name.as_ref() {
return Some(inner.clone());
handles
.iter()
.find_map(|(_id, handle)| {
match handle {
Handle::Scheme(inner) => {
if path == inner.name.as_ref() {
return Some(inner.clone());
}
}
},
_ => (),
}
None
}).ok_or(Error::new(ENOENT))?
_ => (),
}
None
})
.ok_or(Error::new(ENOENT))?
};
inner.unmount()
}
fn seek(&self, file: usize, pos: isize, whence: usize) -> Result<usize> {
let handle = {
let handles = self.handles.read();
@@ -174,15 +189,9 @@ impl KernelScheme for RootScheme {
};
match handle {
Handle::Scheme(_) => {
Err(Error::new(EBADF))
},
Handle::File(_) => {
Err(Error::new(EBADF))
},
Handle::Folder(inner) => {
inner.seek(pos, whence)
}
Handle::Scheme(_) => Err(Error::new(EBADF)),
Handle::File(_) => Err(Error::new(EBADF)),
Handle::Folder(inner) => inner.seek(pos, whence),
}
}
@@ -194,15 +203,9 @@ impl KernelScheme for RootScheme {
};
match handle {
Handle::Scheme(inner) => {
inner.fevent(flags)
},
Handle::File(_) => {
Err(Error::new(EBADF))
},
Handle::Folder(_) => {
Err(Error::new(EBADF))
}
Handle::Scheme(inner) => inner.fevent(flags),
Handle::File(_) => Err(Error::new(EBADF)),
Handle::Folder(_) => Err(Error::new(EBADF)),
}
}
@@ -219,11 +222,11 @@ impl KernelScheme for RootScheme {
match handle {
Handle::Scheme(inner) => {
bytes_copied += buf.copy_common_bytes_from_slice(inner.name.as_bytes())?;
},
}
Handle::File(inner) => {
bytes_copied += buf.copy_common_bytes_from_slice(&inner)?;
},
Handle::Folder(_) => ()
}
Handle::Folder(_) => (),
}
Ok(bytes_copied)
@@ -237,25 +240,23 @@ impl KernelScheme for RootScheme {
};
match handle {
Handle::Scheme(inner) => {
inner.fsync()
},
Handle::File(_) => {
Err(Error::new(EBADF))
},
Handle::Folder(_) => {
Err(Error::new(EBADF))
}
Handle::Scheme(inner) => inner.fsync(),
Handle::File(_) => Err(Error::new(EBADF)),
Handle::Folder(_) => Err(Error::new(EBADF)),
}
}
fn close(&self, file: usize) -> Result<()> {
let handle = self.handles.write().remove(&file).ok_or(Error::new(EBADF))?;
let handle = self
.handles
.write()
.remove(&file)
.ok_or(Error::new(EBADF))?;
match handle {
Handle::Scheme(inner) => {
scheme::schemes_mut().remove(inner.scheme_id);
},
_ => ()
}
_ => (),
}
Ok(())
}
@@ -267,15 +268,9 @@ impl KernelScheme for RootScheme {
};
match handle {
Handle::Scheme(inner) => {
inner.read(buf)
},
Handle::File(_) => {
Err(Error::new(EBADF))
},
Handle::Folder(inner) => {
inner.read(buf)
}
Handle::Scheme(inner) => inner.read(buf),
Handle::File(_) => Err(Error::new(EBADF)),
Handle::Folder(inner) => inner.read(buf),
}
}
@@ -287,15 +282,9 @@ impl KernelScheme for RootScheme {
};
match handle {
Handle::Scheme(inner) => {
inner.write(buf)
},
Handle::File(_) => {
Err(Error::new(EBADF))
},
Handle::Folder(_) => {
Err(Error::new(EBADF))
}
Handle::Scheme(inner) => inner.write(buf),
Handle::File(_) => Err(Error::new(EBADF)),
Handle::Folder(_) => Err(Error::new(EBADF)),
}
}
@@ -327,10 +316,9 @@ impl KernelScheme for RootScheme {
st_gid: 0,
st_size: inner.data.len() as u64,
..Default::default()
}
},
})?;
Ok(())
}
}
+29 -19
View File
@@ -1,15 +1,21 @@
//! PS/2 unfortunately requires a kernel driver to prevent race conditions due
//! to how status is utilized
use core::str;
use core::sync::atomic::{AtomicUsize, Ordering};
use core::{
str,
sync::atomic::{AtomicUsize, Ordering},
};
use spin::RwLock;
use crate::event;
use crate::scheme::*;
use crate::sync::WaitQueue;
use crate::syscall::flag::{EventFlags, EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK};
use crate::syscall::usercopy::UserSliceWo;
use crate::{
event,
scheme::*,
sync::WaitQueue,
syscall::{
flag::{EventFlags, EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK},
usercopy::UserSliceWo,
},
};
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
@@ -45,18 +51,19 @@ impl KernelScheme for SerioScheme {
return Err(Error::new(EPERM));
}
let index = path
.parse::<usize>()
.or(Err(Error::new(ENOENT)))?;
let index = path.parse::<usize>().or(Err(Error::new(ENOENT)))?;
if index >= INPUT.len() {
return Err(Error::new(ENOENT));
}
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
HANDLES.write().insert(id, Handle {
index,
flags: flags & ! O_ACCMODE
});
HANDLES.write().insert(
id,
Handle {
index,
flags: flags & !O_ACCMODE,
},
);
Ok(OpenResult::SchemeLocal(id))
}
@@ -67,10 +74,10 @@ impl KernelScheme for SerioScheme {
match cmd {
F_GETFL => Ok(handle.flags),
F_SETFL => {
handle.flags = arg & ! O_ACCMODE;
handle.flags = arg & !O_ACCMODE;
Ok(0)
},
_ => Err(Error::new(EINVAL))
}
_ => Err(Error::new(EINVAL)),
}
} else {
Err(Error::new(EBADF))
@@ -110,8 +117,11 @@ impl KernelScheme for SerioScheme {
*handles.get(&id).ok_or(Error::new(EBADF))?
};
INPUT[handle.index]
.receive_into_user(buf, handle.flags & O_NONBLOCK != O_NONBLOCK, "SerioScheme::read")
INPUT[handle.index].receive_into_user(
buf,
handle.flags & O_NONBLOCK != O_NONBLOCK,
"SerioScheme::read",
)
}
fn kfpath(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
+3 -5
View File
@@ -1,9 +1,7 @@
use alloc::string::String;
use alloc::vec::Vec;
use alloc::{string::String, vec::Vec};
use core::fmt::Write;
use crate::context;
use crate::syscall::error::Result;
use crate::{context, syscall::error::Result};
pub fn resource() -> Result<Vec<u8>> {
let mut string = String::new();
@@ -24,7 +22,7 @@ pub fn resource() -> Result<Vec<u8>> {
let _ = writeln!(string, "{}: {}", id, name);
if ! row.2.is_empty() {
if !row.2.is_empty() {
let _ = writeln!(string, " {}", row.2);
}
}
+52 -46
View File
@@ -1,28 +1,27 @@
use alloc::string::String;
use alloc::vec::Vec;
use alloc::{string::String, vec::Vec};
use crate::context;
use crate::paging::PAGE_SIZE;
use crate::syscall::error::Result;
use crate::{context, paging::PAGE_SIZE, syscall::error::Result};
pub fn resource() -> Result<Vec<u8>> {
let mut string = format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<12}{:<8}{}\n",
"PID",
"PGID",
"PPID",
"SID",
"RUID",
"RGID",
"RNS",
"EUID",
"EGID",
"ENS",
"STAT",
"CPU",
"AFF",
"TIME",
"MEM",
"NAME");
let mut string = format!(
"{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<12}{:<8}{}\n",
"PID",
"PGID",
"PPID",
"SID",
"RUID",
"RGID",
"RNS",
"EUID",
"EGID",
"ENS",
"STAT",
"CPU",
"AFF",
"TIME",
"MEM",
"NAME"
);
{
let contexts = context::contexts();
for (_id, context_lock) in contexts.iter() {
@@ -43,12 +42,14 @@ pub fn resource() -> Result<Vec<u8>> {
match context.status {
context::Status::Runnable => {
stat_string.push('R');
},
context::Status::Blocked | context::Status::HardBlocked { .. } => if context.wake.is_some() {
stat_string.push('S');
} else {
stat_string.push('B');
},
}
context::Status::Blocked | context::Status::HardBlocked { .. } => {
if context.wake.is_some() {
stat_string.push('S');
} else {
stat_string.push('B');
}
}
context::Status::Stopped(_sig) => {
stat_string.push('T');
}
@@ -65,7 +66,10 @@ pub fn resource() -> Result<Vec<u8>> {
} else {
format!("?")
};
let affinity = format!("{:#x}", context.sched_affinity.get() & ((1 << crate::cpu_count()) - 1));
let affinity = format!(
"{:#x}",
context.sched_affinity.get() & ((1 << crate::cpu_count()) - 1)
);
let cpu_time_s = context.cpu_time / crate::time::NANOS_PER_SEC;
let cpu_time_ns = context.cpu_time % crate::time::NANOS_PER_SEC;
@@ -100,23 +104,25 @@ pub fn resource() -> Result<Vec<u8>> {
format!("{} B", memory)
};
string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<12}{:<8}{}\n",
context.id.get(),
context.pgid.get(),
context.ppid.get(),
context.session_id.get(),
context.ruid,
context.rgid,
context.rns.get(),
context.euid,
context.egid,
context.ens.get(),
stat_string,
cpu_string,
affinity,
cpu_time_string,
memory_string,
context.name));
string.push_str(&format!(
"{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<12}{:<8}{}\n",
context.id.get(),
context.pgid.get(),
context.ppid.get(),
context.session_id.get(),
context.ruid,
context.rgid,
context.rns.get(),
context.euid,
context.egid,
context.ens.get(),
stat_string,
cpu_string,
affinity,
cpu_time_string,
memory_string,
context.name
));
}
}
+5 -3
View File
@@ -1,13 +1,15 @@
use alloc::vec::Vec;
use crate::device::cpu::cpu_info;
use crate::syscall::error::{Error, EIO, Result};
use crate::{
device::cpu::cpu_info,
syscall::error::{Error, Result, EIO},
};
pub fn resource() -> Result<Vec<u8>> {
let mut string = format!("CPUs: {}\n", crate::cpu_count());
match cpu_info(&mut string) {
Ok(()) => Ok(string.into_bytes()),
Err(_) => Err(Error::new(EIO))
Err(_) => Err(Error::new(EIO)),
}
}
+7 -3
View File
@@ -1,8 +1,12 @@
use alloc::vec::Vec;
use crate::context;
use crate::syscall::error::Result;
use crate::{context, syscall::error::Result};
pub fn resource() -> Result<Vec<u8>> {
Ok(context::current()?.read().name.clone().into_owned().into_bytes())
Ok(context::current()?
.read()
.name
.clone()
.into_owned()
.into_bytes())
}
+11 -7
View File
@@ -1,9 +1,6 @@
use alloc::string::String;
use alloc::vec::Vec;
use crate::{context, scheme, syscall::error::Result};
use alloc::{string::String, vec::Vec};
use core::fmt::Write;
use crate::context;
use crate::scheme;
use crate::syscall::error::Result;
pub fn resource() -> Result<Vec<u8>> {
let mut string = String::new();
@@ -26,7 +23,7 @@ pub fn resource() -> Result<Vec<u8>> {
for (fd, f) in row.2.iter().enumerate() {
let file = match *f {
None => continue,
Some(ref file) => file.clone()
Some(ref file) => file.clone(),
};
let description = file.description.read();
@@ -36,7 +33,14 @@ pub fn resource() -> Result<Vec<u8>> {
match schemes.get(description.scheme) {
Some(scheme) => scheme.clone(),
None => {
let _ = writeln!(string, " {:>4}: {:>8} {:>8} {:>08X}: no scheme", fd, description.scheme.get(), description.number, description.flags);
let _ = writeln!(
string,
" {:>4}: {:>8} {:>8} {:>08X}: no scheme",
fd,
description.scheme.get(),
description.number,
description.flags
);
continue;
}
}
+1 -4
View File
@@ -1,7 +1,4 @@
use alloc::{
string::String,
vec::Vec,
};
use alloc::{string::String, vec::Vec};
use core::fmt::Write;
use crate::syscall::error::Result;
+1 -2
View File
@@ -1,7 +1,6 @@
use alloc::vec::Vec;
use crate::log::LOG;
use crate::syscall::error::Result;
use crate::{log::LOG, syscall::error::Result};
pub fn resource() -> Result<Vec<u8>> {
let mut vec = Vec::new();
+41 -27
View File
@@ -1,16 +1,21 @@
use alloc::collections::BTreeMap;
use alloc::vec::Vec;
use core::str;
use core::sync::atomic::{AtomicUsize, Ordering};
use alloc::{collections::BTreeMap, vec::Vec};
use core::{
str,
sync::atomic::{AtomicUsize, Ordering},
};
use spin::RwLock;
use crate::syscall::data::Stat;
use crate::syscall::error::{Error, EBADF, ENOENT, Result};
use crate::syscall::flag::{MODE_DIR, MODE_FILE};
use crate::arch::interrupt;
use crate::syscall::usercopy::UserSliceWo;
use crate::{
arch::interrupt,
syscall::{
data::Stat,
error::{Error, Result, EBADF, ENOENT},
flag::{MODE_DIR, MODE_FILE},
usercopy::UserSliceWo,
},
};
use super::{KernelScheme, CallerCtx, OpenResult, calc_seek_offset};
use super::{calc_seek_offset, CallerCtx, KernelScheme, OpenResult};
mod block;
mod context;
@@ -28,7 +33,7 @@ struct Handle {
path: &'static str,
data: Vec<u8>,
mode: u16,
seek: usize
seek: usize,
}
type SysFn = fn() -> Result<Vec<u8>>;
@@ -70,32 +75,38 @@ impl KernelScheme for SysScheme {
if path.is_empty() {
let mut data = Vec::new();
for entry in FILES.iter() {
if ! data.is_empty() {
if !data.is_empty() {
data.push(b'\n');
}
data.extend_from_slice(entry.0.as_bytes());
}
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
HANDLES.write().insert(id, Handle {
path: "",
data,
mode: MODE_DIR | 0o444,
seek: 0
});
return Ok(OpenResult::SchemeLocal(id))
HANDLES.write().insert(
id,
Handle {
path: "",
data,
mode: MODE_DIR | 0o444,
seek: 0,
},
);
return Ok(OpenResult::SchemeLocal(id));
} else {
//Have to iterate to get the path without allocation
for entry in FILES.iter() {
if &entry.0 == &path {
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
let data = entry.1()?;
HANDLES.write().insert(id, Handle {
path: entry.0,
data,
mode: MODE_FILE | 0o444,
seek: 0
});
HANDLES.write().insert(
id,
Handle {
path: entry.0,
data,
mode: MODE_FILE | 0o444,
seek: 0,
},
);
return Ok(OpenResult::SchemeLocal(id));
}
}
@@ -118,7 +129,11 @@ impl KernelScheme for SysScheme {
}
fn close(&self, id: usize) -> Result<()> {
HANDLES.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(()))
HANDLES
.write()
.remove(&id)
.ok_or(Error::new(EBADF))
.and(Ok(()))
}
fn kfpath(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
let handles = HANDLES.read();
@@ -131,7 +146,6 @@ impl KernelScheme for SysScheme {
bytes_read += remaining.copy_common_bytes_from_slice(handle.path.as_bytes())?;
}
Ok(bytes_read)
}
fn kread(&self, id: usize, buffer: UserSliceWo) -> Result<usize> {
+4 -3
View File
@@ -1,8 +1,9 @@
use alloc::vec::Vec;
use crate::context;
use crate::scheme;
use crate::syscall::error::{Error, ESRCH, Result};
use crate::{
context, scheme,
syscall::error::{Error, Result, ESRCH},
};
pub fn resource() -> Result<Vec<u8>> {
let scheme_ns = {
+4 -3
View File
@@ -1,8 +1,9 @@
use alloc::vec::Vec;
use crate::context;
use crate::scheme;
use crate::syscall::error::{Error, ESRCH, Result};
use crate::{
context, scheme,
syscall::error::{Error, Result, ESRCH},
};
pub fn resource() -> Result<Vec<u8>> {
let scheme_ns = {
+7 -6
View File
@@ -1,10 +1,7 @@
use alloc::string::String;
use alloc::vec::Vec;
use alloc::{string::String, vec::Vec};
use core::fmt::Write;
use crate::context;
use crate::syscall;
use crate::syscall::error::Result;
use crate::{context, syscall, syscall::error::Result};
pub fn resource() -> Result<Vec<u8>> {
let mut string = String::new();
@@ -26,7 +23,11 @@ pub fn resource() -> Result<Vec<u8>> {
let _ = writeln!(string, "{}: {}", id, name);
if let Some((a, b, c, d, e, f)) = row.2 {
let _ = writeln!(string, " {}", syscall::debug::format_call(a, b, c, d, e, f));
let _ = writeln!(
string,
" {}",
syscall::debug::format_call(a, b, c, d, e, f)
);
}
}
}
+7 -5
View File
@@ -1,9 +1,11 @@
use alloc::vec::Vec;
use crate::syscall::error::Result;
use alloc::vec::Vec;
pub fn resource() -> Result<Vec<u8>> {
Ok(format!("Redox\n\n{}\n\n{}\n",
env!("CARGO_PKG_VERSION"),
env!("TARGET").split('-').next().unwrap()).into_bytes())
Ok(format!(
"Redox\n\n{}\n\n{}\n",
env!("CARGO_PKG_VERSION"),
env!("TARGET").split('-').next().unwrap()
)
.into_bytes())
}
+28 -15
View File
@@ -1,16 +1,22 @@
use alloc::collections::BTreeMap;
use core::{mem, str};
use core::sync::atomic::{AtomicUsize, Ordering};
use core::{
mem, str,
sync::atomic::{AtomicUsize, Ordering},
};
use spin::RwLock;
use crate::context::timeout;
use crate::syscall::data::TimeSpec;
use crate::syscall::error::*;
use crate::syscall::flag::{CLOCK_REALTIME, CLOCK_MONOTONIC, EventFlags};
use crate::syscall::usercopy::{UserSliceWo, UserSliceRo};
use crate::time;
use crate::{
context::timeout,
syscall::{
data::TimeSpec,
error::*,
flag::{EventFlags, CLOCK_MONOTONIC, CLOCK_REALTIME},
usercopy::{UserSliceRo, UserSliceWo},
},
time,
};
use super::{GlobalSchemes, KernelScheme, CallerCtx, OpenResult};
use super::{CallerCtx, GlobalSchemes, KernelScheme, OpenResult};
static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
// Using BTreeMap as hashbrown doesn't have a const constructor.
@@ -25,7 +31,7 @@ impl KernelScheme for TimeScheme {
match clock {
CLOCK_REALTIME => (),
CLOCK_MONOTONIC => (),
_ => return Err(Error::new(ENOENT))
_ => return Err(Error::new(ENOENT)),
}
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
@@ -39,7 +45,11 @@ impl KernelScheme for TimeScheme {
}
fn fevent(&self, id: usize, _flags: EventFlags) -> Result<EventFlags> {
HANDLES.read().get(&id).ok_or(Error::new(EBADF)).and(Ok(EventFlags::empty()))
HANDLES
.read()
.get(&id)
.ok_or(Error::new(EBADF))
.and(Ok(EventFlags::empty()))
}
fn fsync(&self, id: usize) -> Result<()> {
@@ -48,7 +58,11 @@ impl KernelScheme for TimeScheme {
}
fn close(&self, id: usize) -> Result<()> {
HANDLES.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(()))
HANDLES
.write()
.remove(&id)
.ok_or(Error::new(EBADF))
.and(Ok(()))
}
fn kread(&self, id: usize, buf: UserSliceWo) -> Result<usize> {
let clock = *HANDLES.read().get(&id).ok_or(Error::new(EBADF))?;
@@ -59,7 +73,7 @@ impl KernelScheme for TimeScheme {
let arch_time = match clock {
CLOCK_REALTIME => time::realtime(),
CLOCK_MONOTONIC => time::monotonic(),
_ => return Err(Error::new(EINVAL))
_ => return Err(Error::new(EINVAL)),
};
let time = TimeSpec {
tv_sec: (arch_time / time::NANOS_PER_SEC) as i64,
@@ -84,7 +98,7 @@ impl KernelScheme for TimeScheme {
timeout::register(GlobalSchemes::Time.scheme_id(), id, clock, time);
bytes_written += mem::size_of::<TimeSpec>();
};
}
Ok(bytes_written)
}
@@ -94,5 +108,4 @@ impl KernelScheme for TimeScheme {
let scheme_path = format!("time:{}", clock).into_bytes();
buf.copy_common_bytes_from_slice(&scheme_path)
}
}
+391 -157
View File
@@ -1,31 +1,47 @@
use alloc::sync::{Arc, Weak};
use alloc::boxed::Box;
use alloc::vec::Vec;
use syscall::{SKMSG_FRETURNFD, SKMSG_PROVIDE_MMAP, MAP_FIXED_NOREPLACE, MunmapFlags, SKMSG_FOBTAINFD, FobtainFdFlags, SendFdFlags};
use core::mem::size_of;
use core::num::NonZeroUsize;
use core::sync::atomic::{AtomicBool, Ordering};
use core::{mem, usize};
use alloc::{
boxed::Box,
sync::{Arc, Weak},
vec::Vec,
};
use core::{
mem,
mem::size_of,
num::NonZeroUsize,
sync::atomic::{AtomicBool, Ordering},
usize,
};
use hashbrown::hash_map::{Entry, HashMap};
use spin::{Mutex, RwLock};
use syscall::{
FobtainFdFlags, MunmapFlags, SendFdFlags, MAP_FIXED_NOREPLACE, SKMSG_FOBTAINFD,
SKMSG_FRETURNFD, SKMSG_PROVIDE_MMAP,
};
use crate::context::context::HardBlockedReason;
use crate::context::{self, Context, BorrowedHtBuf, Status};
use crate::context::file::{FileDescription, FileDescriptor};
use crate::context::memory::{AddrSpace, DANGLING, Grant, GrantFileRef, PageSpan, MmapMode, BorrowedFmapSource};
use crate::event;
use crate::memory::Frame;
use crate::paging::mapper::InactiveFlusher;
use crate::paging::{PAGE_SIZE, Page, VirtualAddress};
use crate::scheme::SchemeId;
use crate::sync::WaitQueue;
use crate::syscall::data::{Map, Packet};
use crate::syscall::error::*;
use crate::syscall::flag::{EventFlags, EVENT_READ, O_NONBLOCK, PROT_READ, PROT_WRITE, MapFlags};
use crate::syscall::number::*;
use crate::syscall::usercopy::{UserSlice, UserSliceWo, UserSliceRo};
use crate::{
context::{
self,
context::HardBlockedReason,
file::{FileDescription, FileDescriptor},
memory::{
AddrSpace, BorrowedFmapSource, Grant, GrantFileRef, MmapMode, PageSpan, DANGLING,
},
BorrowedHtBuf, Context, Status,
},
event,
memory::Frame,
paging::{mapper::InactiveFlusher, Page, VirtualAddress, PAGE_SIZE},
scheme::SchemeId,
sync::WaitQueue,
syscall::{
data::{Map, Packet},
error::*,
flag::{EventFlags, MapFlags, EVENT_READ, O_NONBLOCK, PROT_READ, PROT_WRITE},
number::*,
usercopy::{UserSlice, UserSliceRo, UserSliceWo},
},
};
use super::{FileHandle, OpenResult, KernelScheme, CallerCtx};
use super::{CallerCtx, FileHandle, KernelScheme, OpenResult};
pub struct UserInner {
root_id: SchemeId,
@@ -41,7 +57,10 @@ pub struct UserInner {
}
enum State {
Waiting { context: Weak<RwLock<Context>>, fd: Option<Arc<RwLock<FileDescription>>> },
Waiting {
context: Weak<RwLock<Context>>,
fd: Option<Arc<RwLock<FileDescription>>>,
},
Responded(Response),
Fmap(Weak<RwLock<Context>>),
Placeholder,
@@ -59,7 +78,14 @@ const ONE: NonZeroUsize = match NonZeroUsize::new(1) {
};
impl UserInner {
pub fn new(root_id: SchemeId, scheme_id: SchemeId, handle_id: usize, name: Box<str>, flags: usize, context: Weak<RwLock<Context>>) -> UserInner {
pub fn new(
root_id: SchemeId,
scheme_id: SchemeId,
handle_id: usize,
name: Box<str>,
flags: usize,
context: Weak<RwLock<Context>>,
) -> UserInner {
UserInner {
root_id,
handle_id,
@@ -109,20 +135,32 @@ impl UserInner {
}
}
pub fn call_extended(&self, ctx: CallerCtx, fd: Option<Arc<RwLock<FileDescription>>>, [a, b, c, d]: [usize; 4]) -> Result<Response> {
self.call_extended_inner(fd, Packet {
id: self.next_id(),
pid: ctx.pid,
uid: ctx.uid,
gid: ctx.gid,
a,
b,
c,
d
})
pub fn call_extended(
&self,
ctx: CallerCtx,
fd: Option<Arc<RwLock<FileDescription>>>,
[a, b, c, d]: [usize; 4],
) -> Result<Response> {
self.call_extended_inner(
fd,
Packet {
id: self.next_id(),
pid: ctx.pid,
uid: ctx.uid,
gid: ctx.gid,
a,
b,
c,
d,
},
)
}
fn call_extended_inner(&self, fd: Option<Arc<RwLock<FileDescription>>>, packet: Packet) -> Result<Response> {
fn call_extended_inner(
&self,
fd: Option<Arc<RwLock<FileDescription>>>,
packet: Packet,
) -> Result<Response> {
if self.unmounting.load(Ordering::SeqCst) {
return Err(Error::new(ENODEV));
}
@@ -134,7 +172,13 @@ impl UserInner {
{
let mut states = self.states.lock();
current_context.write().block("UserScheme::call");
states.insert(id, State::Waiting { context: Arc::downgrade(&current_context), fd });
states.insert(
id,
State::Waiting {
context: Arc::downgrade(&current_context),
fd,
},
);
}
self.todo.send(packet);
@@ -166,7 +210,7 @@ impl UserInner {
o.remove();
return Ok(response);
}
}
},
}
}
}
@@ -174,14 +218,20 @@ impl UserInner {
/// Map a readable structure to the scheme's userspace and return the
/// pointer
#[must_use = "copying back to head/tail buffers can fail"]
pub fn capture_user<const READ: bool, const WRITE: bool>(&self, buf: UserSlice<READ, WRITE>) -> Result<CaptureGuard<READ, WRITE>> {
UserInner::capture_inner(
&self.context,
buf,
)
pub fn capture_user<const READ: bool, const WRITE: bool>(
&self,
buf: UserSlice<READ, WRITE>,
) -> Result<CaptureGuard<READ, WRITE>> {
UserInner::capture_inner(&self.context, buf)
}
pub fn copy_and_capture_tail(&self, buf: &[u8]) -> Result<CaptureGuard<false, false>> {
let dst_addr_space = Arc::clone(self.context.upgrade().ok_or(Error::new(ENODEV))?.read().addr_space()?);
let dst_addr_space = Arc::clone(
self.context
.upgrade()
.ok_or(Error::new(ENODEV))?
.read()
.addr_space()?,
);
let mut tail = BorrowedHtBuf::tail()?;
let tail_frame = tail.frame();
@@ -191,7 +241,15 @@ impl UserInner {
tail.buf_mut()[..buf.len()].copy_from_slice(buf);
let is_pinned = true;
let dst_page = dst_addr_space.write().mmap_anywhere(ONE, PROT_READ, |dst_page, flags, mapper, flusher| Ok(Grant::allocated_shared_one_page(tail_frame, dst_page, flags, mapper, flusher, is_pinned)?))?;
let dst_page = dst_addr_space.write().mmap_anywhere(
ONE,
PROT_READ,
|dst_page, flags, mapper, flusher| {
Ok(Grant::allocated_shared_one_page(
tail_frame, dst_page, flags, mapper, flusher, is_pinned,
)?)
},
)?;
Ok(CaptureGuard {
destroyed: false,
@@ -202,7 +260,10 @@ impl UserInner {
src: Some(tail),
dst: None,
},
tail: CopyInfo { src: None, dst: None },
tail: CopyInfo {
src: None,
dst: None,
},
})
}
@@ -212,7 +273,10 @@ impl UserInner {
/// Capture a buffer owned by userspace, mapping it contiguously onto scheme memory.
// TODO: Hypothetical accept_head_leak, accept_tail_leak options might be useful for
// libc-controlled buffer pools.
fn capture_inner<const READ: bool, const WRITE: bool>(context_weak: &Weak<RwLock<Context>>, user_buf: UserSlice<READ, WRITE>) -> Result<CaptureGuard<READ, WRITE>> {
fn capture_inner<const READ: bool, const WRITE: bool>(
context_weak: &Weak<RwLock<Context>>,
user_buf: UserSlice<READ, WRITE>,
) -> Result<CaptureGuard<READ, WRITE>> {
let (mode, map_flags) = match (READ, WRITE) {
(true, false) => (Mode::Ro, PROT_READ),
(false, true) => (Mode::Wo, PROT_WRITE),
@@ -232,13 +296,25 @@ impl UserInner {
base: DANGLING,
len: 0,
space: None,
head: CopyInfo { src: None, dst: None },
tail: CopyInfo { src: None, dst: None },
head: CopyInfo {
src: None,
dst: None,
},
tail: CopyInfo {
src: None,
dst: None,
},
});
}
let cur_space_lock = AddrSpace::current()?;
let dst_space_lock = Arc::clone(context_weak.upgrade().ok_or(Error::new(ESRCH))?.read().addr_space()?);
let dst_space_lock = Arc::clone(
context_weak
.upgrade()
.ok_or(Error::new(ESRCH))?
.read()
.addr_space()?,
);
if Arc::ptr_eq(&dst_space_lock, &cur_space_lock) {
// Same address space, no need to remap anything!
@@ -247,8 +323,14 @@ impl UserInner {
base: user_buf.addr(),
len: user_buf.len(),
space: None,
head: CopyInfo { src: None, dst: None },
tail: CopyInfo { src: None, dst: None },
head: CopyInfo {
src: None,
dst: None,
},
tail: CopyInfo {
src: None,
dst: None,
},
});
}
@@ -261,7 +343,10 @@ impl UserInner {
let mut dst_space = dst_space_lock.write();
let free_span = dst_space.grants.find_free(dst_space.mmap_min, page_count).ok_or(Error::new(ENOMEM))?;
let free_span = dst_space
.grants
.find_free(dst_space.mmap_min, page_count)
.ok_or(Error::new(ENOMEM))?;
let head = if !head_part_of_buf.is_empty() {
// FIXME: Signal context can probably recursively use head/tail.
@@ -276,19 +361,30 @@ impl UserInner {
array.buf_mut()[offset + len..].fill(0_u8);
let slice = &mut array.buf_mut()[offset..][..len];
let head_part_of_buf = user_buf.limit(len).expect("always smaller than max len");
let head_part_of_buf =
user_buf.limit(len).expect("always smaller than max len");
head_part_of_buf.reinterpret_unchecked::<true, false>().copy_to_slice(slice)?;
head_part_of_buf
.reinterpret_unchecked::<true, false>()
.copy_to_slice(slice)?;
}
Mode::Wo => {
array.buf_mut().fill(0_u8);
}
}
dst_space.mmap(Some(free_span.base), ONE, map_flags | MAP_FIXED_NOREPLACE, &mut Vec::new(), move |dst_page, page_flags, mapper, flusher| {
let is_pinned = true;
Ok(Grant::allocated_shared_one_page(frame, dst_page, page_flags, mapper, flusher, is_pinned)?)
})?;
dst_space.mmap(
Some(free_span.base),
ONE,
map_flags | MAP_FIXED_NOREPLACE,
&mut Vec::new(),
move |dst_page, page_flags, mapper, flusher| {
let is_pinned = true;
Ok(Grant::allocated_shared_one_page(
frame, dst_page, page_flags, mapper, flusher, is_pinned,
)?)
},
)?;
let head = CopyInfo {
src: Some(array),
@@ -302,30 +398,54 @@ impl UserInner {
dst: None,
}
};
let (first_middle_dst_page, first_middle_src_page) = if !head_part_of_buf.is_empty() { (free_span.base.next(), src_page.next()) } else { (free_span.base, src_page) };
let (first_middle_dst_page, first_middle_src_page) = if !head_part_of_buf.is_empty() {
(free_span.base.next(), src_page.next())
} else {
(free_span.base, src_page)
};
let middle_page_count = middle_tail_part_of_buf.len() / PAGE_SIZE;
let tail_size = middle_tail_part_of_buf.len() % PAGE_SIZE;
let (_middle_part_of_buf, tail_part_of_buf) = middle_tail_part_of_buf.split_at(middle_page_count * PAGE_SIZE).expect("split must succeed");
let (_middle_part_of_buf, tail_part_of_buf) = middle_tail_part_of_buf
.split_at(middle_page_count * PAGE_SIZE)
.expect("split must succeed");
if let Some(middle_page_count) = NonZeroUsize::new(middle_page_count) {
dst_space.mmap(Some(first_middle_dst_page), middle_page_count, map_flags | MAP_FIXED_NOREPLACE, &mut Vec::new(), move |dst_page, _, mapper, flusher| {
let eager = true;
dst_space.mmap(
Some(first_middle_dst_page),
middle_page_count,
map_flags | MAP_FIXED_NOREPLACE,
&mut Vec::new(),
move |dst_page, _, mapper, flusher| {
let eager = true;
// It doesn't make sense to allow a context, that has borrowed non-RAM physical
// memory, to DIRECTLY do scheme calls onto that memory.
//
// (TODO: Maybe there are some niche use cases for that, possibly PCI transfer
// BARs, but it doesn't make sense yet.)
let allow_phys = false;
// It doesn't make sense to allow a context, that has borrowed non-RAM physical
// memory, to DIRECTLY do scheme calls onto that memory.
//
// (TODO: Maybe there are some niche use cases for that, possibly PCI transfer
// BARs, but it doesn't make sense yet.)
let allow_phys = false;
// Deny any attempts by the scheme, to unmap these temporary pages. The only way to
// unmap them is to respond to the scheme socket.
let is_pinned_userscheme_borrow = true;
// Deny any attempts by the scheme, to unmap these temporary pages. The only way to
// unmap them is to respond to the scheme socket.
let is_pinned_userscheme_borrow = true;
Ok(Grant::borrow(Arc::clone(&cur_space_lock), &mut *cur_space_lock.write(), first_middle_src_page, dst_page, middle_page_count.get(), map_flags, mapper, flusher, eager, allow_phys, is_pinned_userscheme_borrow)?)
})?;
Ok(Grant::borrow(
Arc::clone(&cur_space_lock),
&mut *cur_space_lock.write(),
first_middle_src_page,
dst_page,
middle_page_count.get(),
map_flags,
mapper,
flusher,
eager,
allow_phys,
is_pinned_userscheme_borrow,
)?)
},
)?;
}
let tail = if !tail_part_of_buf.is_empty() {
@@ -342,17 +462,27 @@ impl UserInner {
to_zero.fill(0_u8);
// FIXME: remove reinterpret_unchecked
tail_part_of_buf.reinterpret_unchecked::<true, false>().copy_to_slice(to_copy)?;
tail_part_of_buf
.reinterpret_unchecked::<true, false>()
.copy_to_slice(to_copy)?;
}
Mode::Wo => {
array.buf_mut().fill(0_u8);
}
}
dst_space.mmap(Some(tail_dst_page), ONE, map_flags | MAP_FIXED_NOREPLACE, &mut Vec::new(), move |dst_page, page_flags, mapper, flusher| {
let is_pinned = true;
Ok(Grant::allocated_shared_one_page(frame, dst_page, page_flags, mapper, flusher, is_pinned)?)
})?;
dst_space.mmap(
Some(tail_dst_page),
ONE,
map_flags | MAP_FIXED_NOREPLACE,
&mut Vec::new(),
move |dst_page, page_flags, mapper, flusher| {
let is_pinned = true;
Ok(Grant::allocated_shared_one_page(
frame, dst_page, page_flags, mapper, flusher, is_pinned,
)?)
},
)?;
CopyInfo {
src: Some(array),
@@ -407,7 +537,13 @@ impl UserInner {
Ok(packets_read * size_of::<Packet>())
}
pub fn request_fmap(&self, id: usize, offset: u64, required_page_count: usize, flags: MapFlags) -> Result<()> {
pub fn request_fmap(
&self,
id: usize,
offset: u64,
required_page_count: usize,
flags: MapFlags,
) -> Result<()> {
log::info!("REQUEST FMAP");
let packet_id = self.next_id();
@@ -432,8 +568,12 @@ impl UserInner {
if packet.id == 0 {
// TODO: Simplify logic by using SKMSG with packet.id being ignored?
match packet.a {
SYS_FEVENT => event::trigger(self.scheme_id, packet.b, EventFlags::from_bits_truncate(packet.c)),
_ => log::warn!("Unknown scheme -> kernel message {}", packet.a)
SYS_FEVENT => event::trigger(
self.scheme_id,
packet.b,
EventFlags::from_bits_truncate(packet.c),
),
_ => log::warn!("Unknown scheme -> kernel message {}", packet.a),
}
} else if Error::demux(packet.a) == Err(Error::new(ESKMSG)) {
// The reason why the new ESKMSG mechanism was introduced, is that passing packet IDs
@@ -442,13 +582,22 @@ impl UserInner {
SKMSG_FRETURNFD => {
let fd = packet.c;
let desc = context::current()?.read().remove_file(FileHandle::from(fd)).ok_or(Error::new(EINVAL))?.description;
let desc = context::current()?
.read()
.remove_file(FileHandle::from(fd))
.ok_or(Error::new(EINVAL))?
.description;
self.respond(packet.id, Response::Fd(desc))?;
}
SKMSG_FOBTAINFD => {
let flags = FobtainFdFlags::from_bits(packet.d).ok_or(Error::new(EINVAL))?;
let description = match self.states.lock().get_mut(&packet.id).ok_or(Error::new(EINVAL))? {
let description = match self
.states
.lock()
.get_mut(&packet.id)
.ok_or(Error::new(EINVAL))?
{
State::Waiting { ref mut fd, .. } => fd.take().ok_or(Error::new(ENOENT))?,
_ => return Err(Error::new(ENOENT)),
};
@@ -456,9 +605,21 @@ impl UserInner {
// FIXME: Description can leak if context::current() fails, or if there is no
// additional file table space.
if flags.contains(FobtainFdFlags::MANUAL_FD) {
context::current()?.read().insert_file(FileHandle::from(packet.c), FileDescriptor { description, cloexec: true });
context::current()?.read().insert_file(
FileHandle::from(packet.c),
FileDescriptor {
description,
cloexec: true,
},
);
} else {
let fd = context::current()?.read().add_file(FileDescriptor { description, cloexec: true }).ok_or(Error::new(EMFILE))?;
let fd = context::current()?
.read()
.add_file(FileDescriptor {
description,
cloexec: true,
})
.ok_or(Error::new(EMFILE))?;
UserSlice::wo(packet.c, size_of::<usize>())?.write_usize(fd.get())?;
}
}
@@ -477,38 +638,48 @@ impl UserInner {
let page_count = packet.d;
if page_count != 1 { return Err(Error::new(EINVAL)); }
if page_count != 1 {
return Err(Error::new(EINVAL));
}
let context = match self.states.lock().entry(packet.id) {
Entry::Occupied(mut o) => match mem::replace(o.get_mut(), State::Placeholder) {
// invalid state
State::Placeholder => {
return Err(Error::new(EBADFD));
Entry::Occupied(mut o) => {
match mem::replace(o.get_mut(), State::Placeholder) {
// invalid state
State::Placeholder => {
return Err(Error::new(EBADFD));
}
// invalid kernel to scheme call
old_state @ (State::Waiting { .. } | State::Responded(_)) => {
*o.get_mut() = old_state;
return Err(Error::new(EINVAL));
}
State::Fmap(context) => {
o.remove();
context
}
}
// invalid kernel to scheme call
old_state @ (State::Waiting { .. } | State::Responded(_)) => {
*o.get_mut() = old_state;
return Err(Error::new(EINVAL));
}
State::Fmap(context) => {
o.remove();
context
}
},
}
Entry::Vacant(_) => return Err(Error::new(EINVAL)),
};
let context = context.upgrade().ok_or(Error::new(ESRCH))?;
let (frame, _) = AddrSpace::current()?.read().table.utable.translate(base_addr).ok_or(Error::new(EFAULT))?;
let (frame, _) = AddrSpace::current()?
.read()
.table
.utable
.translate(base_addr)
.ok_or(Error::new(EFAULT))?;
let mut context = context.write();
match context.status {
Status::HardBlocked { reason: HardBlockedReason::AwaitingMmap { .. } } => context.status = Status::Runnable,
Status::HardBlocked {
reason: HardBlockedReason::AwaitingMmap { .. },
} => context.status = Status::Runnable,
_ => (),
}
context.fmap_ret = Some(Frame::containing_address(frame));
}
_ => return Err(Error::new(EINVAL)),
}
@@ -532,7 +703,9 @@ impl UserInner {
}
State::Waiting { context, fd } => {
to_close = fd.and_then(|f| Arc::try_unwrap(f).ok()).map(RwLock::into_inner);
to_close = fd
.and_then(|f| Arc::try_unwrap(f).ok())
.map(RwLock::into_inner);
if let Some(context) = context.upgrade() {
context.write().unblock();
@@ -541,7 +714,7 @@ impl UserInner {
o.remove();
}
}
}
},
// invalid state
Entry::Vacant(_) => return Err(Error::new(EBADFD)),
}
@@ -560,7 +733,12 @@ impl UserInner {
Ok(())
}
fn fmap_inner(&self, dst_addr_space: Arc<RwLock<AddrSpace>>, file: usize, map: &Map) -> Result<usize> {
fn fmap_inner(
&self,
dst_addr_space: Arc<RwLock<AddrSpace>>,
file: usize,
map: &Map,
) -> Result<usize> {
let unaligned_size = map.size;
if unaligned_size == 0 {
@@ -572,15 +750,19 @@ impl UserInner {
if map.address % PAGE_SIZE != 0 {
return Err(Error::new(EINVAL));
};
let dst_base = (map.address != 0).then_some(Page::containing_address(VirtualAddress::new(map.address)));
let dst_base = (map.address != 0)
.then_some(Page::containing_address(VirtualAddress::new(map.address)));
if map.offset % PAGE_SIZE != 0 {
return Err(Error::new(EINVAL));
}
let src_address_space = Arc::clone(
self.context.upgrade().ok_or(Error::new(ENODEV))?
.read().addr_space()?
self.context
.upgrade()
.ok_or(Error::new(ENODEV))?
.read()
.addr_space()?,
);
if Arc::ptr_eq(&src_address_space, &dst_addr_space) {
return Err(Error::new(EBUSY));
@@ -605,20 +787,23 @@ impl UserInner {
(context.id, desc.description)
};
let response = self.call_extended_inner(None, Packet {
id: self.next_id(),
pid: pid.into(),
a: KSMSG_MMAP_PREP,
b: file,
c: unaligned_size,
d: map.flags.bits(),
// The uid and gid can be obtained by the proc scheme anyway, if the pid is provided.
uid: map.offset as u32,
#[cfg(target_pointer_width = "64")]
gid: (map.offset >> 32) as u32,
#[cfg(target_pointer_width = "32")]
gid: 0,
})?;
let response = self.call_extended_inner(
None,
Packet {
id: self.next_id(),
pid: pid.into(),
a: KSMSG_MMAP_PREP,
b: file,
c: unaligned_size,
d: map.flags.bits(),
// The uid and gid can be obtained by the proc scheme anyway, if the pid is provided.
uid: map.offset as u32,
#[cfg(target_pointer_width = "64")]
gid: (map.offset >> 32) as u32,
#[cfg(target_pointer_width = "32")]
gid: 0,
},
)?;
// TODO: I've previously tested that this works, but because the scheme trait all of
// Redox's schemes currently rely on doesn't allow one-way messages, there's no current
@@ -628,8 +813,7 @@ impl UserInner {
let mapping_is_lazy = false;
let base_page_opt = match response {
Response::Regular(code) => (!mapping_is_lazy)
.then_some(Error::demux(code)?),
Response::Regular(code) => (!mapping_is_lazy).then_some(Error::demux(code)?),
Response::Fd(_) => {
log::debug!("Scheme incorrectly returned an fd for fmap.");
@@ -661,7 +845,7 @@ impl UserInner {
flusher: {
flusher = InactiveFlusher::new();
&mut flusher
}
},
}
}),
None => None,
@@ -669,9 +853,22 @@ impl UserInner {
let page_count_nz = NonZeroUsize::new(page_count).expect("already validated map.size != 0");
let mut notify_files = Vec::new();
let dst_base = dst_addr_space.write().mmap(dst_base, page_count_nz, map.flags, &mut notify_files, |dst_base, flags, mapper, flusher| {
Grant::borrow_fmap(PageSpan::new(dst_base, page_count), flags, file_ref, src, mapper, flusher)
})?;
let dst_base = dst_addr_space.write().mmap(
dst_base,
page_count_nz,
map.flags,
&mut notify_files,
|dst_base, flags, mapper, flusher| {
Grant::borrow_fmap(
PageSpan::new(dst_base, page_count),
flags,
file_ref,
src,
mapper,
flusher,
)
},
)?;
for map in notify_files {
let _ = map.unmap();
@@ -691,8 +888,12 @@ pub struct CaptureGuard<const READ: bool, const WRITE: bool> {
tail: CopyInfo<READ, WRITE>,
}
impl<const READ: bool, const WRITE: bool> CaptureGuard<READ, WRITE> {
fn base(&self) -> usize { self.base }
fn len(&self) -> usize { self.len }
fn base(&self) -> usize {
self.base
}
fn len(&self) -> usize {
self.len
}
}
struct CopyInfo<const READ: bool, const WRITE: bool> {
src: Option<BorrowedHtBuf>,
@@ -714,10 +915,20 @@ impl<const READ: bool, const WRITE: bool> CaptureGuard<READ, WRITE> {
let mut result = Ok(());
// TODO: Encode src and dst better using const generics.
if let CopyInfo { src: Some(ref src), dst: Some(ref mut dst) } = self.head {
result = result.and_then(|()| dst.copy_from_slice(&src.buf()[self.base % PAGE_SIZE..][..dst.len()]));
if let CopyInfo {
src: Some(ref src),
dst: Some(ref mut dst),
} = self.head
{
result = result.and_then(|()| {
dst.copy_from_slice(&src.buf()[self.base % PAGE_SIZE..][..dst.len()])
});
}
if let CopyInfo { src: Some(ref src), dst: Some(ref mut dst) } = self.tail {
if let CopyInfo {
src: Some(ref src),
dst: Some(ref mut dst),
} = self.tail
{
result = result.and_then(|()| dst.copy_from_slice(&src.buf()[..dst.len()]));
}
let Some(space) = self.space.take() else {
@@ -727,7 +938,9 @@ impl<const READ: bool, const WRITE: bool> CaptureGuard<READ, WRITE> {
let (first_page, page_count, _offset) = page_range_containing(self.base, self.len);
let unpin = true;
space.write().munmap(PageSpan::new(first_page, page_count), unpin)?;
space
.write()
.munmap(PageSpan::new(first_page, page_count), unpin)?;
result
}
@@ -751,7 +964,7 @@ fn page_range_containing(base: usize, size: usize) -> (Page, usize, usize) {
/// `UserInner` has to be wrapped
#[derive(Clone)]
pub struct UserScheme {
pub(crate) inner: Weak<UserInner>
pub(crate) inner: Weak<UserInner>,
}
impl UserScheme {
@@ -818,7 +1031,9 @@ impl KernelScheme for UserScheme {
fn fevent(&self, file: usize, flags: EventFlags) -> Result<EventFlags> {
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
inner.call(SYS_FEVENT, file, flags.bits(), 0).map(EventFlags::from_bits_truncate)
inner
.call(SYS_FEVENT, file, flags.bits(), 0)
.map(EventFlags::from_bits_truncate)
}
/*
@@ -946,7 +1161,13 @@ impl KernelScheme for UserScheme {
address.release()?;
result.map(|_| ())
}
fn kfmap(&self, file: usize, addr_space: &Arc<RwLock<AddrSpace>>, map: &Map, _consume: bool) -> Result<usize> {
fn kfmap(
&self,
file: usize,
addr_space: &Arc<RwLock<AddrSpace>>,
map: &Map,
_consume: bool,
) -> Result<usize> {
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
inner.fmap_inner(Arc::clone(addr_space), file, map)
@@ -954,31 +1175,44 @@ impl KernelScheme for UserScheme {
fn kfunmap(&self, number: usize, offset: usize, size: usize, flags: MunmapFlags) -> Result<()> {
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
let res = inner.call_extended(CallerCtx {
pid: context::context_id().into(),
uid: offset as u32,
#[cfg(target_pointer_width = "64")]
gid: (offset >> 32) as u32,
let res = inner.call_extended(
CallerCtx {
pid: context::context_id().into(),
uid: offset as u32,
#[cfg(target_pointer_width = "64")]
gid: (offset >> 32) as u32,
// TODO: saturating_shr?
#[cfg(not(target_pointer_width = "64"))]
gid: 0,
}, None, [KSMSG_MUNMAP, number, size, flags.bits()])?;
// TODO: saturating_shr?
#[cfg(not(target_pointer_width = "64"))]
gid: 0,
},
None,
[KSMSG_MUNMAP, number, size, flags.bits()],
)?;
match res {
Response::Regular(_) => Ok(()),
Response::Fd(_) => Err(Error::new(EIO)),
}
}
fn ksendfd(&self, number: usize, desc: Arc<RwLock<FileDescription>>, flags: SendFdFlags, arg: u64) -> Result<usize> {
fn ksendfd(
&self,
number: usize,
desc: Arc<RwLock<FileDescription>>,
flags: SendFdFlags,
arg: u64,
) -> Result<usize> {
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
let res = inner.call_extended(CallerCtx {
pid: context::context_id().into(),
uid: arg as u32,
gid: (arg >> 32) as u32,
}, Some(desc), [SYS_SENDFD, number, flags.bits(), 0])?;
let res = inner.call_extended(
CallerCtx {
pid: context::context_id().into(),
uid: arg as u32,
gid: (arg >> 32) as u32,
},
Some(desc),
[SYS_SENDFD, number, flags.bits(), 0],
)?;
match res {
Response::Regular(res) => Ok(res),