Hardcode global scheme IDs.
This commit is contained in:
@@ -49,6 +49,7 @@
|
||||
#![feature(naked_functions)]
|
||||
#![feature(offset_of)]
|
||||
#![feature(sync_unsafe_cell)]
|
||||
#![feature(variant_count)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
|
||||
+7
-20
@@ -9,7 +9,6 @@ use spin::{Mutex, Once, RwLock};
|
||||
|
||||
use crate::acpi::{RXSDT_ENUM, RxsdtEnum};
|
||||
use crate::event;
|
||||
use crate::scheme::SchemeId;
|
||||
use crate::sync::WaitCondition;
|
||||
|
||||
use crate::syscall::data::Stat;
|
||||
@@ -23,7 +22,7 @@ use crate::syscall::flag::{
|
||||
use crate::syscall::error::{Error, Result};
|
||||
use crate::syscall::usercopy::{UserSliceRo, UserSliceWo};
|
||||
|
||||
use super::{KernelScheme, CallerCtx, OpenResult};
|
||||
use super::{GlobalSchemes, KernelScheme, CallerCtx, OpenResult};
|
||||
|
||||
/// A scheme used to access the RSDT or XSDT, which is needed for e.g. `acpid` to function.
|
||||
pub struct AcpiScheme;
|
||||
@@ -50,21 +49,15 @@ const TOPLEVEL_CONTENTS: &[u8] = b"rxsdt\nkstop\n";
|
||||
static KSTOP_WAITCOND: WaitCondition = WaitCondition::new();
|
||||
static KSTOP_FLAG: Mutex<bool> = Mutex::new(false);
|
||||
|
||||
static SCHEME_ID: Once<SchemeId> = Once::new();
|
||||
|
||||
pub fn register_kstop() -> bool {
|
||||
*KSTOP_FLAG.lock() = true;
|
||||
let mut waiters_awoken = KSTOP_WAITCOND.notify();
|
||||
|
||||
if let Some(&acpi_scheme) = SCHEME_ID.get() {
|
||||
let handles = HANDLES.read();
|
||||
let handles = HANDLES.read();
|
||||
|
||||
for (&fd, _) in handles.iter().filter(|(_, handle)| handle.kind == HandleKind::ShutdownPipe) {
|
||||
event::trigger(acpi_scheme, fd, EVENT_READ);
|
||||
waiters_awoken += 1;
|
||||
}
|
||||
} else {
|
||||
log::error!("Calling register_kstop before kernel ACPI scheme was initialized");
|
||||
for (&fd, _) in handles.iter().filter(|(_, handle)| handle.kind == HandleKind::ShutdownPipe) {
|
||||
event::trigger(GlobalSchemes::Acpi.scheme_id(), fd, EVENT_READ);
|
||||
waiters_awoken += 1;
|
||||
}
|
||||
|
||||
if waiters_awoken == 0 {
|
||||
@@ -78,13 +71,12 @@ pub fn register_kstop() -> bool {
|
||||
}
|
||||
|
||||
impl AcpiScheme {
|
||||
pub fn init(id: SchemeId) {
|
||||
pub fn init() {
|
||||
// NOTE: This __must__ be called from the main kernel context, while initializing all
|
||||
// schemes. If it is called by any other context, then all ACPI data will probably not even
|
||||
// be mapped.
|
||||
|
||||
let mut data_init = false;
|
||||
let mut id_init = false;
|
||||
|
||||
DATA.call_once(|| {
|
||||
data_init = true;
|
||||
@@ -100,13 +92,8 @@ impl AcpiScheme {
|
||||
|
||||
Box::from(table)
|
||||
});
|
||||
SCHEME_ID.call_once(|| {
|
||||
id_init = true;
|
||||
|
||||
id
|
||||
});
|
||||
|
||||
if !data_init || !id_init {
|
||||
if !data_init {
|
||||
log::error!("AcpiScheme::init called multiple times");
|
||||
}
|
||||
}
|
||||
|
||||
+3
-16
@@ -1,15 +1,12 @@
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use spin::{Once, RwLock};
|
||||
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;
|
||||
use crate::syscall::usercopy::UserSliceWo;
|
||||
|
||||
static SCHEME_ID: Once<SchemeId> = Once::new();
|
||||
use crate::syscall::usercopy::{UserSliceRo, UserSliceWo};
|
||||
|
||||
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
@@ -30,23 +27,13 @@ pub fn debug_input(data: u8) {
|
||||
|
||||
// Notify readers of input updates
|
||||
pub fn debug_notify() {
|
||||
let Some(scheme_id) = SCHEME_ID.get().copied() else {
|
||||
return;
|
||||
};
|
||||
|
||||
for (id, _handle) in HANDLES.read().iter() {
|
||||
event::trigger(scheme_id, *id, EVENT_READ);
|
||||
event::trigger(GlobalSchemes::Debug.scheme_id(), *id, EVENT_READ);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DebugScheme;
|
||||
|
||||
impl DebugScheme {
|
||||
pub fn init(scheme_id: SchemeId) {
|
||||
SCHEME_ID.call_once(|| scheme_id);
|
||||
}
|
||||
}
|
||||
|
||||
impl KernelScheme for DebugScheme {
|
||||
fn kopen(&self, path: &str, flags: usize, ctx: CallerCtx) -> Result<OpenResult> {
|
||||
if ctx.uid != 0 {
|
||||
|
||||
@@ -55,10 +55,6 @@ impl Handle {
|
||||
}
|
||||
|
||||
impl MemoryScheme {
|
||||
pub fn new() -> Self {
|
||||
MemoryScheme
|
||||
}
|
||||
|
||||
pub fn fmap_anonymous(addr_space: &Arc<RwLock<AddrSpace>>, map: &Map) -> 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))?;
|
||||
|
||||
+53
-39
@@ -111,9 +111,8 @@ pub struct SchemeList {
|
||||
map: BTreeMap<SchemeId, KernelSchemes>,
|
||||
names: BTreeMap<SchemeNamespace, BTreeMap<Box<str>, SchemeId>>,
|
||||
next_ns: usize,
|
||||
next_id: usize
|
||||
next_id: usize,
|
||||
}
|
||||
|
||||
impl SchemeList {
|
||||
/// Create a new scheme list.
|
||||
pub fn new() -> Self {
|
||||
@@ -122,8 +121,9 @@ impl SchemeList {
|
||||
names: BTreeMap::new(),
|
||||
// Scheme namespaces always start at 1. 0 is a reserved namespace, the null namespace
|
||||
next_ns: 1,
|
||||
next_id: 1
|
||||
next_id: 1 + core::mem::variant_count::<GlobalSchemes>(),
|
||||
};
|
||||
|
||||
list.new_null();
|
||||
list.new_root();
|
||||
list
|
||||
@@ -136,12 +136,9 @@ impl SchemeList {
|
||||
|
||||
//TODO: Only memory: is in the null namespace right now. It should be removed when
|
||||
//anonymous mmap's are implemented
|
||||
self.insert(ns, "memory", |_| KernelSchemes::Memory).unwrap();
|
||||
self.insert_global(ns, "memory", GlobalSchemes::Memory).unwrap();
|
||||
self.insert(ns, "thisproc", |_| KernelSchemes::Proc(Arc::new(ProcScheme::restricted()))).unwrap();
|
||||
self.insert(ns, "pipe", |scheme_id| {
|
||||
PipeScheme::init(scheme_id);
|
||||
KernelSchemes::Pipe
|
||||
}).unwrap();
|
||||
self.insert_global(ns, "pipe", GlobalSchemes::Pipe).unwrap();
|
||||
}
|
||||
|
||||
/// Initialize a new namespace
|
||||
@@ -151,13 +148,10 @@ impl SchemeList {
|
||||
self.names.insert(ns, BTreeMap::new());
|
||||
|
||||
self.insert(ns, "", |scheme_id| KernelSchemes::Root(Arc::new(RootScheme::new(ns, scheme_id)))).unwrap();
|
||||
self.insert(ns, "event", |_| KernelSchemes::Event).unwrap();
|
||||
self.insert_global(ns, "event", GlobalSchemes::Event).unwrap();
|
||||
self.insert(ns, "itimer", |_| KernelSchemes::ITimer(Arc::new(ITimerScheme::new()))).unwrap();
|
||||
self.insert(ns, "memory", |_| KernelSchemes::Memory).unwrap();
|
||||
self.insert(ns, "pipe", |scheme_id| {
|
||||
PipeScheme::init(scheme_id);
|
||||
KernelSchemes::Pipe
|
||||
}).unwrap();
|
||||
self.insert_global(ns, "memory", GlobalSchemes::Memory).unwrap();
|
||||
self.insert_global(ns, "pipe", GlobalSchemes::Pipe).unwrap();
|
||||
self.insert(ns, "sys", |_| KernelSchemes::Sys(Arc::new(SysScheme::new()))).unwrap();
|
||||
self.insert(ns, "time", |scheme_id| KernelSchemes::Time(Arc::new(TimeScheme::new(scheme_id)))).unwrap();
|
||||
|
||||
@@ -170,28 +164,19 @@ impl SchemeList {
|
||||
let ns = self.new_ns();
|
||||
|
||||
// These schemes should only be available on the root
|
||||
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
self.insert(ns, "kernel.acpi", |scheme_id| {
|
||||
AcpiScheme::init(scheme_id);
|
||||
KernelSchemes::Acpi
|
||||
}).unwrap();
|
||||
|
||||
#[cfg(all(any(target_arch = "aarch64")))]
|
||||
{
|
||||
self.insert(ns, "kernel.dtb", |scheme_id| Arc::new(DtbScheme::new(scheme_id))).unwrap();
|
||||
}
|
||||
|
||||
self.insert(ns, "debug", |scheme_id| {
|
||||
DebugScheme::init(scheme_id);
|
||||
KernelSchemes::Debug
|
||||
}).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, "debug", GlobalSchemes::Debug).unwrap();
|
||||
self.insert(ns, "irq", |scheme_id| KernelSchemes::Irq(Arc::new(IrqScheme::new(scheme_id)))).unwrap();
|
||||
self.insert(ns, "proc", |scheme_id| KernelSchemes::Proc(Arc::new(ProcScheme::new(scheme_id)))).unwrap();
|
||||
self.insert(ns, "thisproc", |_| KernelSchemes::Proc(Arc::new(ProcScheme::restricted()))).unwrap();
|
||||
self.insert(ns, "serio", |scheme_id| {
|
||||
SerioScheme::init(scheme_id);
|
||||
KernelSchemes::Serio
|
||||
}).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> {
|
||||
@@ -236,6 +221,16 @@ 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());
|
||||
|
||||
if prev.is_some() {
|
||||
return Err(Error::new(EEXIST));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 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)
|
||||
@@ -422,18 +417,23 @@ pub fn calc_seek_offset(cur_pos: usize, rel_pos: isize, whence: usize, len: usiz
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum KernelSchemes {
|
||||
Debug,
|
||||
Event,
|
||||
Irq(Arc<IrqScheme>),
|
||||
ITimer(Arc<ITimerScheme>),
|
||||
Memory,
|
||||
Pipe,
|
||||
Proc(Arc<ProcScheme>),
|
||||
Root(Arc<RootScheme>),
|
||||
Serio,
|
||||
Sys(Arc<SysScheme>),
|
||||
Time(Arc<TimeScheme>),
|
||||
User(UserScheme),
|
||||
Global(GlobalSchemes),
|
||||
}
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum GlobalSchemes {
|
||||
Debug = 1,
|
||||
Event,
|
||||
Memory,
|
||||
Pipe,
|
||||
Serio,
|
||||
|
||||
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
Acpi,
|
||||
@@ -444,21 +444,35 @@ impl core::ops::Deref for KernelSchemes {
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self {
|
||||
Self::Debug => &DebugScheme,
|
||||
Self::Event => &EventScheme,
|
||||
Self::Irq(scheme) => &**scheme,
|
||||
Self::ITimer(scheme) => &**scheme,
|
||||
Self::Memory => &MemoryScheme,
|
||||
Self::Pipe => &PipeScheme,
|
||||
Self::Proc(scheme) => &**scheme,
|
||||
Self::Root(scheme) => &**scheme,
|
||||
Self::Serio => &SerioScheme,
|
||||
Self::Sys(scheme) => &**scheme,
|
||||
Self::Time(scheme) => &**scheme,
|
||||
Self::User(scheme) => scheme,
|
||||
|
||||
Self::Global(global) => &**global,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl core::ops::Deref for GlobalSchemes {
|
||||
type Target = dyn KernelScheme;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self {
|
||||
Self::Debug => &DebugScheme,
|
||||
Self::Event => &EventScheme,
|
||||
Self::Memory => &MemoryScheme,
|
||||
Self::Pipe => &PipeScheme,
|
||||
Self::Serio => &SerioScheme,
|
||||
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
Self::Acpi => &AcpiScheme,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl GlobalSchemes {
|
||||
pub fn scheme_id(self) -> SchemeId {
|
||||
SchemeId::new(self as usize)
|
||||
}
|
||||
}
|
||||
|
||||
+5
-17
@@ -3,30 +3,24 @@ use core::sync::atomic::{AtomicUsize, Ordering, AtomicBool};
|
||||
use alloc::sync::Arc;
|
||||
use alloc::collections::{BTreeMap, VecDeque};
|
||||
|
||||
use spin::{Mutex, Once, RwLock};
|
||||
use spin::{Mutex, RwLock};
|
||||
|
||||
use crate::event;
|
||||
use crate::scheme::SchemeId;
|
||||
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 super::{KernelScheme, OpenResult, CallerCtx};
|
||||
use super::{KernelScheme, OpenResult, CallerCtx, GlobalSchemes};
|
||||
|
||||
// TODO: Preallocate a number of scheme IDs, since there can only be *one* root namespace, and
|
||||
// therefore only *one* pipe scheme.
|
||||
static SCHEME_ID: Once<SchemeId> = Once::new();
|
||||
static PIPE_NEXT_ID: AtomicUsize = AtomicUsize::new(1);
|
||||
|
||||
// TODO: SLOB?
|
||||
static PIPES: RwLock<BTreeMap<usize, Arc<Pipe>>> = RwLock::new(BTreeMap::new());
|
||||
|
||||
pub fn pipe_scheme_id() -> SchemeId {
|
||||
*SCHEME_ID.get().expect("pipe scheme must be initialized")
|
||||
}
|
||||
|
||||
const MAX_QUEUE_SIZE: usize = 65536;
|
||||
|
||||
// In almost all places where Rust (and LLVM) uses pointers, they are limited to nonnegative isize,
|
||||
@@ -56,12 +50,6 @@ pub fn pipe(flags: usize) -> Result<(usize, usize)> {
|
||||
|
||||
pub struct PipeScheme;
|
||||
|
||||
impl PipeScheme {
|
||||
pub fn init(scheme_id: SchemeId) {
|
||||
SCHEME_ID.call_once(|| scheme_id);
|
||||
}
|
||||
}
|
||||
|
||||
impl KernelScheme for PipeScheme {
|
||||
fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
|
||||
let (is_writer_not_reader, key) = from_raw_id(id);
|
||||
@@ -110,7 +98,7 @@ impl KernelScheme for PipeScheme {
|
||||
let (is_write_not_read, key) = from_raw_id(id);
|
||||
|
||||
let pipe = Arc::clone(PIPES.read().get(&key).ok_or(Error::new(EBADF))?);
|
||||
let scheme_id = pipe_scheme_id();
|
||||
let scheme_id = GlobalSchemes::Pipe.scheme_id();
|
||||
|
||||
let can_remove = if is_write_not_read {
|
||||
event::trigger(scheme_id, key, EVENT_READ);
|
||||
@@ -193,7 +181,7 @@ impl KernelScheme for PipeScheme {
|
||||
let _ = vec.drain(..bytes_read);
|
||||
|
||||
if bytes_read > 0 {
|
||||
event::trigger(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);
|
||||
@@ -242,7 +230,7 @@ impl KernelScheme for PipeScheme {
|
||||
}
|
||||
|
||||
if bytes_written > 0 {
|
||||
event::trigger(pipe_scheme_id(), key, EVENT_READ);
|
||||
event::trigger(GlobalSchemes::Pipe.scheme_id(), key, EVENT_READ);
|
||||
pipe.read_condition.notify();
|
||||
|
||||
return Ok(bytes_written);
|
||||
|
||||
+2
-14
@@ -3,7 +3,7 @@
|
||||
use core::str;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use spin::{Once, RwLock};
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::event;
|
||||
use crate::scheme::*;
|
||||
@@ -11,8 +11,6 @@ use crate::sync::WaitQueue;
|
||||
use crate::syscall::flag::{EventFlags, EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK};
|
||||
use crate::syscall::usercopy::UserSliceWo;
|
||||
|
||||
static SCHEME_ID: Once<SchemeId> = Once::new();
|
||||
|
||||
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
/// Input queue
|
||||
@@ -30,23 +28,13 @@ static HANDLES: RwLock<BTreeMap<usize, Handle>> = RwLock::new(BTreeMap::new());
|
||||
pub fn serio_input(index: usize, data: u8) {
|
||||
INPUT[index].send(data);
|
||||
|
||||
let Some(scheme_id) = SCHEME_ID.get().copied() else {
|
||||
return;
|
||||
};
|
||||
|
||||
for (id, _handle) in HANDLES.read().iter() {
|
||||
event::trigger(scheme_id, *id, EVENT_READ);
|
||||
event::trigger(GlobalSchemes::Serio.scheme_id(), *id, EVENT_READ);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SerioScheme;
|
||||
|
||||
impl SerioScheme {
|
||||
pub fn init(scheme_id: SchemeId) {
|
||||
SCHEME_ID.call_once(|| scheme_id);
|
||||
}
|
||||
}
|
||||
|
||||
impl KernelScheme for SerioScheme {
|
||||
fn kopen(&self, path: &str, flags: usize, ctx: CallerCtx) -> Result<OpenResult> {
|
||||
if ctx.uid != 0 {
|
||||
|
||||
+1
-1
@@ -214,7 +214,7 @@ pub fn sendfd(socket: FileHandle, fd: FileHandle, flags_raw: usize, arg: u64) ->
|
||||
let (scheme, number) = match current.get_file(socket).ok_or(Error::new(EBADF))?.description.read() {
|
||||
ref desc => (desc.scheme, desc.number),
|
||||
};
|
||||
let scheme = Arc::clone(scheme::schemes().get(scheme).ok_or(Error::new(ENODEV))?);
|
||||
let scheme = scheme::schemes().get(scheme).ok_or(Error::new(ENODEV))?.clone();
|
||||
|
||||
(scheme, number, current.remove_file(fd).ok_or(Error::new(EBADF))?.description)
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user