Add rustfmt from relibc and apply it with cargo fmt
This commit is contained in:
+56
-36
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+77
-89
@@ -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
@@ -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> {
|
||||
|
||||
@@ -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
@@ -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
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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,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,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
@@ -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> {
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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(¤t_context), fd });
|
||||
states.insert(
|
||||
id,
|
||||
State::Waiting {
|
||||
context: Arc::downgrade(¤t_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),
|
||||
|
||||
Reference in New Issue
Block a user