1
0
mirror of https://github.com/sgmarz/osblog.git synced 2024-11-24 02:16:19 +04:00

Removed mapping the kernel memory into a process' virtual address space.

This commit is contained in:
Stephen Marz 2020-04-25 19:34:20 -04:00
parent 84e5126d29
commit e5f3eb7f6b
2 changed files with 47 additions and 20 deletions

View File

@ -155,15 +155,23 @@ impl MinixFileSystem {
}
impl FileSystem for MinixFileSystem {
/// Init is where we would cache the superblock and inode to avoid having to read
/// it over and over again, like we do for read right now.
fn init(_bdev: usize) -> bool {
false
}
/// The goal of open is to traverse the path given by path. If we cache the inodes
/// in RAM, it might make this much quicker. For now, this doesn't do anything since
/// we're just testing read based on if we know the Inode we're looking for.
fn open(_path: &String) -> Result<Descriptor, FsError> {
Err(FsError::FileNotFound)
}
fn read(desc: &Descriptor, buffer: *mut u8, size: u32, offset: u32) -> u32 {
// Our strategy here is to use blocks to see when we need to start reading
// based on the offset. That's offset_block. Then, the actual byte within
// that block that we need is offset_byte.
let mut blocks_seen = 0u32;
let offset_block = offset / BLOCK_SIZE;
let mut offset_byte = offset % BLOCK_SIZE;
@ -173,6 +181,7 @@ impl FileSystem for MinixFileSystem {
// The inode couldn't be read, for some reason.
return 0;
}
// We've already checked is_none() above, so we can safely unwrap here.
let inode = inode_result.unwrap();
// First, the _size parameter (now in bytes_left) is the size of the buffer, not
// necessarily the size of the file. If our buffer is bigger than the file, we're OK.
@ -189,6 +198,22 @@ impl FileSystem for MinixFileSystem {
// 10 bytes, we have to read the entire block (really only 512 bytes of the block) first.
// So, we use the block_buffer as the middle man, which is then copied into the buffer.
let mut block_buffer = BlockBuffer::new(BLOCK_SIZE);
// Triply indirect zones point to a block of pointers (BLOCK_SIZE / 4). Each one of those pointers
// points to another block of pointers (BLOCK_SIZE / 4). Each one of those pointers yet again points
// to another block of pointers (BLOCK_SIZE / 4). This is why we have indirect, iindirect (doubly),
// and iiindirect (triply).
let mut indirect_buffer = BlockBuffer::new(BLOCK_SIZE);
let mut iindirect_buffer = BlockBuffer::new(BLOCK_SIZE);
let mut iiindirect_buffer = BlockBuffer::new(BLOCK_SIZE);
// I put the pointers *const u32 here. That means we will allocate the indirect,
// doubly indirect, and triply indirect even for small files. I initially had these
// in their respective scopes, but that required us to recreate the indirect buffer for
// doubly indirect and both the indirect and doubly indirect buffers for the
// triply indirect. Not sure which is better, but I probably wasted brain cells
// on this.
let izones = indirect_buffer.get() as *const u32;
let iizones = iindirect_buffer.get() as *const u32;
let iiizones = iiindirect_buffer.get() as *const u32;
// ////////////////////////////////////////////
// // DIRECT ZONES
@ -257,7 +282,6 @@ impl FileSystem for MinixFileSystem {
// point to zones where the data can be found. Just like with the direct zones,
// we need to make sure the zone isn't 0. A zone of 0 means skip it.
if inode.zones[7] != 0 {
let mut indirect_buffer = BlockBuffer::new(BLOCK_SIZE);
syc_read(desc, indirect_buffer.get_mut(), BLOCK_SIZE, BLOCK_SIZE * inode.zones[7]);
let izones = indirect_buffer.get() as *const u32;
for i in 0..num_indirect_pointers {
@ -298,17 +322,16 @@ impl FileSystem for MinixFileSystem {
// // DOUBLY INDIRECT ZONES
// ////////////////////////////////////////////
if inode.zones[8] != 0 {
let mut indirect_buffer = BlockBuffer::new(BLOCK_SIZE);
let mut iindirect_buffer = BlockBuffer::new(BLOCK_SIZE);
syc_read(desc, indirect_buffer.get_mut(), BLOCK_SIZE, BLOCK_SIZE * inode.zones[8]);
let izones = indirect_buffer.get() as *const u32;
let iizones = iindirect_buffer.get() as *const u32;
unsafe {
for i in 0..num_indirect_pointers {
if izones.add(i).read() != 0 {
syc_read(desc, iindirect_buffer.get_mut(), BLOCK_SIZE, BLOCK_SIZE * izones.add(i).read());
for j in 0..num_indirect_pointers {
if iizones.add(j).read() != 0 {
// Notice that this inner code is the same for all end-zone pointers. I'm thinking about
// moving this out of here into a function of its own, but that might make it harder
// to follow.
if offset_block <= blocks_seen {
syc_read(
desc,
@ -345,13 +368,7 @@ impl FileSystem for MinixFileSystem {
// // TRIPLY INDIRECT ZONES
// ////////////////////////////////////////////
if inode.zones[9] != 0 {
let mut indirect_buffer = BlockBuffer::new(BLOCK_SIZE);
let mut iindirect_buffer = BlockBuffer::new(BLOCK_SIZE);
let mut iiindirect_buffer = BlockBuffer::new(BLOCK_SIZE);
syc_read(desc, indirect_buffer.get_mut(), BLOCK_SIZE, BLOCK_SIZE * inode.zones[9]);
let izones = indirect_buffer.get() as *const u32;
let iizones = iindirect_buffer.get() as *const u32;
let iiizones = iiindirect_buffer.get() as *const u32;
unsafe {
for i in 0..num_indirect_pointers {
if izones.add(i).read() != 0 {
@ -366,6 +383,7 @@ impl FileSystem for MinixFileSystem {
);
for k in 0..num_indirect_pointers {
if iiizones.add(k).read() != 0 {
// Hey look! This again.
if offset_block <= blocks_seen {
syc_read(
desc,

View File

@ -33,6 +33,10 @@ pub static mut PROCESS_LIST: Option<VecDeque<Process>> = None;
// it's probably easier and faster just to increase the pid:
static mut NEXT_PID: u16 = 1;
// The following set_* and get_by_pid functions are C-style functions
// They probably need to be re-written in a more Rusty style, but for
// now they are how we control processes by PID.
/// Set a process' state to running. This doesn't do any checks.
/// If this PID is not found, this returns false. Otherwise, it
/// returns true.
@ -157,7 +161,12 @@ fn init_process() {
// the scheduler is called in an interrupt context, nothing else
// can happen until a process becomes available.
println!("Init is still here :), alright, back to sleep.");
// 500 wfi's should take 500 context switches before we print Init is still here.
// Depending on our context switch time, this might be around 3 seconds.
for _ in 0..500 {
// We can only write wfi here because init_process is being ran
// as a kernel process. If we ran this as a user process, it'd
// need a system call to execute a privileged instruction.
unsafe { asm!("wfi") };
}
}
@ -383,6 +392,14 @@ pub struct Process {
sleep_until: usize,
}
// Most of this operating system runs more of a C-style, where
// we have direct access to the structure members. By default, Rust
// will make them private unless we add the keyword pub in front of
// EVERY member. I wrote the process structure this way to show
// both ways Rust allows us to access members. Just like Python,
// the first parameter (the *this parameter in C++) is a reference
// to ourself. We can write static functions as a member of this
// structure by omitting a self.
impl Process {
pub fn get_frame_address(&self) -> usize {
self.frame as usize
@ -422,7 +439,7 @@ impl Process {
pub fn new_default(func: fn()) -> Self {
let func_addr = func as usize;
let func_vaddr = func_addr; //- 0x6000_0000;
let func_vaddr = func_addr;
// println!("func_addr = {:x} -> {:x}", func_addr, func_vaddr);
// We will convert NEXT_PID below into an atomic increment when
// we start getting into multi-hart processing. For now, we want
@ -473,14 +490,6 @@ impl Process {
let modifier = i * 0x1000;
map(pt, func_vaddr + modifier, func_addr + modifier, EntryBits::UserReadWriteExecute.val(), 0);
}
// This is the make_syscall function
// The reason we need this is because we're running a process
// that is inside of the kernel. When we start loading from a block
// devices, we can load the instructions anywhere in memory.
for i in 0..=7 {
let addr = 0x8000_0000 | i << 12;
map(pt, addr, addr, EntryBits::UserReadExecute.val(), 0);
}
ret_proc
}
}