proc: add SyscallFunction::GetRandom

This commit is contained in:
Mark Poliakov 2023-12-05 12:23:44 +02:00
parent e431d49ffb
commit 15d3e38a2d
5 changed files with 89 additions and 64 deletions

View File

@ -9,7 +9,10 @@ use vfs::{
CharDevice, Node, NodeFlags, NodeRef,
};
use crate::arch::{Architecture, ARCHITECTURE};
use crate::{
arch::{Architecture, ARCHITECTURE},
proc::random,
};
/// Describes the kind of a character device
#[derive(Debug)]
@ -21,58 +24,6 @@ pub enum CharDeviceType {
}
static DEVFS_ROOT: OneTimeInit<NodeRef> = OneTimeInit::new();
struct RandomState {
data: [u8; 1024],
pos: usize,
last_state: u32,
}
impl RandomState {
fn new(seed: u32) -> Self {
Self {
data: [0; 1024],
pos: 1024,
last_state: seed,
}
}
fn next(&mut self) -> u32 {
let mut x = self.last_state;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
self.last_state = x;
x
}
fn fill_buf(&mut self) {
self.pos = 0;
for i in (0..self.data.len()).step_by(4) {
let v = self.next();
self.data[i..i + 4].copy_from_slice(&v.to_ne_bytes());
}
}
fn read_buf(&mut self, buf: &mut [u8]) {
let mut rem = buf.len();
let mut pos = 0;
while rem != 0 {
if self.pos == 1024 {
self.fill_buf();
}
let count = core::cmp::min(rem, 1024 - self.pos);
buf[pos..pos + count].copy_from_slice(&self.data[self.pos..self.pos + count]);
self.pos += count;
rem -= count;
pos += count;
}
}
}
/// Sets up the device filesystem
pub fn init() {
let root = MemoryDirectory::empty();
@ -113,17 +64,8 @@ pub fn add_char_device(dev: &'static dyn CharDevice, kind: CharDeviceType) -> Re
}
pub fn add_pseudo_devices() -> Result<(), Error> {
let now = ARCHITECTURE
.monotonic_timer()
.monotonic_timestamp()
.unwrap();
let random_seed = now.subsec_millis();
let mut random_state = RandomState::new(random_seed);
random_state.fill_buf();
let random_state = IrqSafeSpinlock::new(random_state);
let random = read_fn_node(move |_, buf| {
random_state.lock().read_buf(buf);
random::read(buf);
Ok(buf.len())
});

View File

@ -37,6 +37,7 @@ use crate::{
arch::{ArchitectureImpl, ARCHITECTURE},
fs::{devfs, sysfs},
mem::heap,
proc::random,
task::{spawn_kernel_closure, Cpu},
};
@ -87,6 +88,8 @@ pub fn kernel_secondary_main() -> ! {
pub fn kernel_main() -> ! {
debugln!("Heap: {:#x?}", heap::heap_range());
random::init();
// Setup the sysfs
sysfs::init();
devfs::add_pseudo_devices().unwrap();

View File

@ -3,3 +3,4 @@
pub mod elf;
pub mod exec;
pub mod io;
pub mod random;

74
src/proc/random.rs Normal file
View File

@ -0,0 +1,74 @@
use kernel_util::{sync::IrqSafeSpinlock, util::OneTimeInit};
use crate::arch::{Architecture, ARCHITECTURE};
struct RandomState {
data: [u8; 1024],
pos: usize,
last_state: u32,
}
impl RandomState {
fn new(seed: u32) -> Self {
Self {
data: [0; 1024],
pos: 1024,
last_state: seed,
}
}
fn next(&mut self) -> u32 {
let mut x = self.last_state;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
self.last_state = x;
x
}
fn fill_buf(&mut self) {
self.pos = 0;
for i in (0..self.data.len()).step_by(4) {
let v = self.next();
self.data[i..i + 4].copy_from_slice(&v.to_ne_bytes());
}
}
fn read_buf(&mut self, buf: &mut [u8]) {
let mut rem = buf.len();
let mut pos = 0;
while rem != 0 {
if self.pos == 1024 {
self.fill_buf();
}
let count = core::cmp::min(rem, 1024 - self.pos);
buf[pos..pos + count].copy_from_slice(&self.data[self.pos..self.pos + count]);
self.pos += count;
rem -= count;
pos += count;
}
}
}
static RANDOM_STATE: OneTimeInit<IrqSafeSpinlock<RandomState>> = OneTimeInit::new();
pub fn read(buf: &mut [u8]) {
let state = RANDOM_STATE.get();
state.lock().read_buf(buf)
}
pub fn init() {
let now = ARCHITECTURE
.monotonic_timer()
.monotonic_timestamp()
.unwrap();
let random_seed = now.subsec_millis();
let mut state = RandomState::new(random_seed);
state.fill_buf();
RANDOM_STATE.init(IrqSafeSpinlock::new(state));
}

View File

@ -22,7 +22,7 @@ use crate::{
debug::LogLevel,
fs,
mem::{phys, table::MapAttributes},
proc::{self, io::ProcessIo},
proc::{self, io::ProcessIo, random},
task::{
process::{Process, ProcessId},
runtime,
@ -72,6 +72,11 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
Ok(0)
}
SyscallFunction::GetRandom => {
let buf = arg_buffer_mut(args[0] as _, args[1] as _)?;
random::read(buf);
Ok(0)
}
SyscallFunction::Nanosleep => {
let seconds = args[0];
let nanos = args[1] as u32;