Browse Source

fix: UserBuffer move CheckedUserPointer on fill called

greatbridf 4 months ago
parent
commit
0295d3e954

+ 15 - 1
src/kernel/chardev.rs

@@ -7,7 +7,14 @@ use bindings::{EEXIST, EIO};
 
 use crate::{io::Buffer, kernel::console::CONSOLE, prelude::*};
 
-use super::{block::make_device, terminal::Terminal, vfs::DevId};
+use super::{
+    block::make_device,
+    terminal::Terminal,
+    vfs::{
+        file::{File, TerminalFile},
+        DevId,
+    },
+};
 
 use lazy_static::lazy_static;
 
@@ -64,6 +71,13 @@ impl CharDevice {
             Entry::Occupied(_) => Err(EEXIST),
         }
     }
+
+    pub fn open(self: &Arc<Self>) -> KResult<Arc<File>> {
+        Ok(match &self.device {
+            CharDeviceType::Terminal(terminal) => TerminalFile::new(terminal.clone()),
+            CharDeviceType::Virtual(_) => Arc::new(File::CharDev(self.clone())),
+        })
+    }
 }
 
 struct NullDevice;

+ 1 - 0
src/kernel/constants.rs

@@ -16,6 +16,7 @@ pub const SIG_SETMASK: u32 = 2;
 pub const CLOCK_REALTIME: u32 = 0;
 pub const CLOCK_MONOTONIC: u32 = 1;
 
+pub const ENXIO: u32 = 6;
 pub const ENOEXEC: u32 = 8;
 
 bitflags! {

+ 1 - 1
src/kernel/mem/mm_list/page_fault.rs

@@ -196,7 +196,7 @@ pub fn handle_page_fault(int_stack: &mut interrupt_stack) {
         .handle_page_fault(int_stack, vaddr, error);
 
     if let Err(signal) = result {
-        println_debug!("Page fault in user space at {:#x}", vaddr.0);
+        println_debug!("Page fault on {:#x} in user space at {:#x}", vaddr.0, int_stack.v_rip);
         ProcessList::kill_current(signal)
     }
 }

+ 5 - 1
src/kernel/mem/vrange.rs

@@ -159,6 +159,10 @@ impl VRange {
     }
 
     pub fn into_range(self) -> impl RangeBounds<Self> {
-        VRange::from(self.start())..VRange::from(self.end())
+        if self.len() == 0 {
+            VRange::from(self.start())..=VRange::from(self.start())
+        } else {
+            VRange::from(self.start())..=VRange::from(self.end() - 1)
+        }
     }
 }

+ 0 - 6
src/kernel/task/thread.rs

@@ -375,12 +375,6 @@ impl ProcessList {
     }
 
     pub fn kill_current(signal: Signal) -> ! {
-        println_debug!(
-            "Killing thread {} with signal {:?}",
-            Thread::current().tid,
-            signal,
-        );
-
         ProcessList::get().do_kill_process(
             &Thread::current().process,
             ((signal.to_signum() + 128) << 8) | (signal.to_signum() & 0xff),

+ 5 - 2
src/kernel/user/dataflow.rs

@@ -76,8 +76,10 @@ impl CheckedUserPointer {
         }
     }
 
-    pub fn get_mut<T>(&self) -> *mut T {
-        self.ptr as *mut T
+    pub fn forward(&mut self, offset: usize) {
+        assert!(offset <= self.len);
+        self.ptr = self.ptr.wrapping_offset(offset as isize);
+        self.len -= offset;
     }
 
     pub fn get_const<T>(&self) -> *const T {
@@ -234,6 +236,7 @@ impl<'lt> Buffer for UserBuffer<'lt> {
         }
 
         self.ptr.write(data.as_ptr() as *mut (), to_write)?;
+        self.ptr.forward(to_write);
         self.cur += to_write;
 
         if to_write == data.len() {

+ 12 - 2
src/kernel/vfs/file.rs

@@ -8,6 +8,7 @@ use crate::{
         task::{Signal, Thread},
         terminal::{Terminal, TerminalIORequest},
         user::{UserPointer, UserPointerMut},
+        CharDevice,
     },
     prelude::*,
     sync::CondVar,
@@ -58,11 +59,18 @@ pub struct TerminalFile {
     terminal: Arc<Terminal>,
 }
 
+// TODO: We should use `File` as the base type, instead of `Arc<File>`
+//       If we need shared states, like for `InodeFile`, the files themselves should
+//       have their own shared semantics. All `File` variants will just keep the
+//       `Clone` semantics.
+//
+//       e.g. The `CharDevice` itself is stateless.
 pub enum File {
     Inode(InodeFile),
     PipeRead(PipeReadEnd),
     PipeWrite(PipeWriteEnd),
     TTY(TerminalFile),
+    CharDev(Arc<CharDevice>),
 }
 
 pub enum SeekOption {
@@ -439,6 +447,7 @@ impl File {
             File::Inode(inode) => inode.read(buffer),
             File::PipeRead(pipe) => pipe.pipe.read(buffer),
             File::TTY(tty) => tty.read(buffer),
+            File::CharDev(device) => device.read(buffer),
             _ => Err(EBADF),
         }
     }
@@ -463,6 +472,7 @@ impl File {
             File::Inode(inode) => inode.write(buffer),
             File::PipeWrite(pipe) => pipe.pipe.write(buffer),
             File::TTY(tty) => tty.write(buffer),
+            File::CharDev(device) => device.write(buffer),
             _ => Err(EBADF),
         }
     }
@@ -470,7 +480,7 @@ impl File {
     pub fn seek(&self, option: SeekOption) -> KResult<usize> {
         match self {
             File::Inode(inode) => inode.seek(option),
-            File::PipeRead(_) | File::PipeWrite(_) | File::TTY(_) => Err(ESPIPE),
+            _ => Err(ESPIPE),
         }
     }
 
@@ -532,9 +542,9 @@ impl File {
 
     pub fn poll(&self, event: PollEvent) -> KResult<PollEvent> {
         match self {
-            File::PipeRead(_) | File::PipeWrite(_) => unimplemented!("Poll event not supported."),
             File::Inode(_) => Ok(event),
             File::TTY(tty) => tty.poll(event),
+            _ => unimplemented!("Poll event not supported."),
         }
     }
 }

+ 4 - 0
src/kernel/vfs/filearray.rs

@@ -3,8 +3,10 @@ use core::sync::atomic::Ordering;
 use crate::{
     kernel::{
         console::CONSOLE,
+        constants::ENXIO,
         task::Thread,
         vfs::{dentry::Dentry, file::Pipe, s_isdir, s_isreg},
+        CharDevice,
     },
     path::Path,
     prelude::*,
@@ -204,6 +206,8 @@ impl FileArray {
                 fdflag as u64,
                 TerminalFile::new(CONSOLE.lock_irq().get_terminal().unwrap()),
             );
+
+            let device = CharDevice::get(inode.devid()?).ok_or(ENXIO)?;
         } else {
             inner.do_insert(
                 fd,