mirror of
https://github.com/sgmarz/osblog.git
synced 2024-11-24 02:16:19 +04:00
Updates to add a process for a file system read in the system call.
This commit is contained in:
parent
2e48b86656
commit
73636c1de1
@ -3,11 +3,11 @@
|
|||||||
// Stephen Marz
|
// Stephen Marz
|
||||||
// 10 March 2020
|
// 10 March 2020
|
||||||
|
|
||||||
use crate::{kmem::{kfree, kmalloc},
|
use crate::{kmem::{kfree, kmalloc, talloc, tfree},
|
||||||
page::{zalloc, PAGE_SIZE},
|
page::{zalloc, PAGE_SIZE},
|
||||||
virtio,
|
virtio,
|
||||||
virtio::{Descriptor, MmioOffsets, Queue, StatusField, VIRTIO_RING_SIZE}};
|
virtio::{Descriptor, MmioOffsets, Queue, StatusField, VIRTIO_RING_SIZE}};
|
||||||
use crate::process::{set_running, set_waiting};
|
use crate::process::{set_running, set_waiting, get_by_pid, add_kernel_process_args};
|
||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -376,13 +376,53 @@ pub fn handle_interrupt(idx: usize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_read(pid: u16, dev: usize, buffer: *mut u8, size: u32, offset: u64) -> Result<u32, BlockErrors> {
|
|
||||||
println!("Process read {}, {}, 0x{:x}, {}, {}", pid, dev, buffer as usize, size, offset);
|
// ///////////////////////////////////////////////
|
||||||
set_waiting(pid);
|
// // BLOCK PROCESSES (KERNEL PROCESSES)
|
||||||
block_op(dev, buffer, size, offset, false, pid)
|
// ///////////////////////////////////////////////
|
||||||
|
struct ProcArgs {
|
||||||
|
pub pid: u16,
|
||||||
|
pub dev: usize,
|
||||||
|
pub buffer: *mut u8,
|
||||||
|
pub size: u32,
|
||||||
|
pub offset: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_write(pid: u16, dev: usize, buffer: *mut u8, size: u32, offset: u64) -> Result<u32, BlockErrors> {
|
fn read_proc(args_addr: usize) {
|
||||||
set_waiting(pid);
|
let args_ptr = args_addr as *mut ProcArgs;
|
||||||
block_op(dev, buffer, size, offset, true, pid)
|
let args = unsafe { args_ptr.as_ref().unwrap() };
|
||||||
|
let _ = block_op(args.dev, args.buffer, args.size, args.offset, false, args.pid);
|
||||||
|
tfree(args_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_read(pid: u16, dev: usize, buffer: *mut u8, size: u32, offset: u64) {
|
||||||
|
// println!("Block read {}, {}, 0x{:x}, {}, {}", pid, dev, buffer as usize, size, offset);
|
||||||
|
let args = talloc::<ProcArgs>().unwrap();
|
||||||
|
args.pid = pid;
|
||||||
|
args.dev = dev;
|
||||||
|
args.buffer = buffer;
|
||||||
|
args.size = size;
|
||||||
|
args.offset = offset;
|
||||||
|
set_waiting(pid);
|
||||||
|
let _ = add_kernel_process_args(read_proc, args as *mut ProcArgs as usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_proc(args_addr: usize) {
|
||||||
|
let args_ptr = args_addr as *mut ProcArgs;
|
||||||
|
let args = unsafe { args_ptr.as_ref().unwrap() };
|
||||||
|
|
||||||
|
let _ = block_op(args.dev, args.buffer, args.size, args.offset, true, args.pid);
|
||||||
|
|
||||||
|
tfree(args_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_write(pid: u16, dev: usize, buffer: *mut u8, size: u32, offset: u64) {
|
||||||
|
let args = talloc::<ProcArgs>().unwrap();
|
||||||
|
args.pid = pid;
|
||||||
|
args.dev = dev;
|
||||||
|
args.buffer = buffer;
|
||||||
|
args.size = size;
|
||||||
|
args.offset = offset;
|
||||||
|
set_waiting(pid);
|
||||||
|
let _ = add_kernel_process_args(write_proc, args as *mut ProcArgs as usize);
|
||||||
}
|
}
|
@ -233,3 +233,14 @@ pub fn satp_fence_asid(asid: usize) {
|
|||||||
asm!("sfence.vma zero, $0" :: "r"(asid));
|
asm!("sfence.vma zero, $0" :: "r"(asid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MMIO_MTIME: *const u64 = 0x0200_BFF8 as *const u64;
|
||||||
|
|
||||||
|
pub fn get_mtime() -> usize {
|
||||||
|
unsafe {
|
||||||
|
(*MMIO_MTIME) as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ pub struct Descriptor {
|
|||||||
pub node: u32,
|
pub node: u32,
|
||||||
pub loc: u32,
|
pub loc: u32,
|
||||||
pub size: u32,
|
pub size: u32,
|
||||||
|
pub pid: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum FsError {
|
pub enum FsError {
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
use crate::{block,
|
use crate::{block,
|
||||||
fs::{Descriptor, FileSystem, FsError, Stat},
|
fs::{Descriptor, FileSystem, FsError, Stat},
|
||||||
kmem::{kfree, kmalloc, talloc, tfree}};
|
kmem::{kfree, kmalloc, talloc, tfree}};
|
||||||
|
use crate::process::{set_waiting, set_running, add_kernel_process_args};
|
||||||
|
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use core::{mem::size_of, ptr::null_mut};
|
use core::{mem::size_of, ptr::null_mut};
|
||||||
@ -108,7 +109,7 @@ impl MinixFileSystem {
|
|||||||
/// the file's size. They are stored above the data zones, but to figure out where we
|
/// the file's size. They are stored above the data zones, but to figure out where we
|
||||||
/// need to go to get the inode, we first need the superblock, which is where we can
|
/// need to go to get the inode, we first need the superblock, which is where we can
|
||||||
/// find all of the information about the filesystem itself.
|
/// find all of the information about the filesystem itself.
|
||||||
pub fn get_inode(bdev: usize, inode_num: u32) -> Option<Inode> {
|
pub fn get_inode(desc: &Descriptor, inode_num: u32) -> Option<Inode> {
|
||||||
// When we read, everything needs to be a multiple of a sector (512 bytes)
|
// When we read, everything needs to be a multiple of a sector (512 bytes)
|
||||||
// So, we need to have memory available that's at least 512 bytes, even if
|
// So, we need to have memory available that's at least 512 bytes, even if
|
||||||
// we only want 10 bytes or 32 bytes (size of an Inode).
|
// we only want 10 bytes or 32 bytes (size of an Inode).
|
||||||
@ -119,14 +120,12 @@ impl MinixFileSystem {
|
|||||||
// simultaneously, we can overlap the memory regions.
|
// simultaneously, we can overlap the memory regions.
|
||||||
let super_block = unsafe { &*(buffer.get_mut() as *mut SuperBlock) };
|
let super_block = unsafe { &*(buffer.get_mut() as *mut SuperBlock) };
|
||||||
let inode = unsafe { &*(buffer.get_mut() as *mut Inode) };
|
let inode = unsafe { &*(buffer.get_mut() as *mut Inode) };
|
||||||
|
|
||||||
// Read from the block device. The size is 1 sector (512 bytes) and our offset is past
|
// Read from the block device. The size is 1 sector (512 bytes) and our offset is past
|
||||||
// the boot block (first 1024 bytes). This is where the superblock sits.
|
// the boot block (first 1024 bytes). This is where the superblock sits.
|
||||||
let result = block::read(bdev, buffer.get_mut(), 512, 1024);
|
println!("DO READ, magic should be next, buffer is at {:p}, desc is at {:p}", buffer.get(), desc as *const Descriptor);
|
||||||
for _ in 0..1000000 {
|
syc_read(desc, buffer.get_mut(), 512, 1024);
|
||||||
|
println!("Magic is {:x}", super_block.magic);
|
||||||
}
|
if super_block.magic == MAGIC {
|
||||||
if result.is_ok() && super_block.magic == MAGIC {
|
|
||||||
// If we get here, we successfully read what we think is the super block.
|
// If we get here, we successfully read what we think is the super block.
|
||||||
// The math here is 2 - one for the boot block, one for the super block. Then we
|
// The math here is 2 - one for the boot block, one for the super block. Then we
|
||||||
// have to skip the bitmaps blocks. We have a certain number of inode map blocks (imap)
|
// have to skip the bitmaps blocks. We have a certain number of inode map blocks (imap)
|
||||||
@ -136,14 +135,9 @@ impl MinixFileSystem {
|
|||||||
* BLOCK_SIZE as usize + (inode_num as usize - 1) * size_of::<Inode>();
|
* BLOCK_SIZE as usize + (inode_num as usize - 1) * size_of::<Inode>();
|
||||||
|
|
||||||
// Now, we read the inode itself.
|
// Now, we read the inode itself.
|
||||||
let result = block::read(bdev, buffer.get_mut(), 512, inode_offset as u64);
|
syc_read(desc, buffer.get_mut(), 512, inode_offset as u32);
|
||||||
for _ in 0..1000000 {
|
|
||||||
|
|
||||||
}
|
|
||||||
if result.is_ok() {
|
|
||||||
println!("Inode sizex = {} {:o}", inode.size, inode.mode);
|
println!("Inode sizex = {} {:o}", inode.size, inode.mode);
|
||||||
return Some(inode.clone());
|
return Some(*inode);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// If we get here, some result wasn't OK. Either the super block
|
// If we get here, some result wasn't OK. Either the super block
|
||||||
// or the inode itself.
|
// or the inode itself.
|
||||||
@ -161,13 +155,14 @@ impl FileSystem for MinixFileSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read(desc: &Descriptor, buffer: *mut u8, offset: u32, size: u32) -> u32 {
|
fn read(desc: &Descriptor, buffer: *mut u8, offset: u32, size: u32) -> u32 {
|
||||||
|
println!("MinixFileSystem::read: {}, {:p}, off: {}, sz: {}", desc.blockdev, buffer, offset, size);
|
||||||
let mut blocks_seen = 0u32;
|
let mut blocks_seen = 0u32;
|
||||||
let offset_block = offset / BLOCK_SIZE;
|
let offset_block = offset / BLOCK_SIZE;
|
||||||
let offset_byte = offset % BLOCK_SIZE;
|
let offset_byte = offset % BLOCK_SIZE;
|
||||||
|
|
||||||
|
// let stats = Self::stat(desc);
|
||||||
|
let inode_result = Self::get_inode(desc, desc.node);
|
||||||
let mut block_buffer = BlockBuffer::new(BLOCK_SIZE);
|
let mut block_buffer = BlockBuffer::new(BLOCK_SIZE);
|
||||||
let stats = Self::stat(desc);
|
|
||||||
let inode_result = Self::get_inode(desc.blockdev, desc.node);
|
|
||||||
if inode_result.is_none() {
|
if inode_result.is_none() {
|
||||||
// The inode couldn't be read, for some reason.
|
// The inode couldn't be read, for some reason.
|
||||||
return 0;
|
return 0;
|
||||||
@ -176,12 +171,12 @@ impl FileSystem for MinixFileSystem {
|
|||||||
// First, the _size parameter (now in bytes_left) is the size of the buffer, not
|
// 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.
|
// necessarily the size of the file. If our buffer is bigger than the file, we're OK.
|
||||||
// If our buffer is smaller than the file, then we can only read up to the buffer size.
|
// If our buffer is smaller than the file, then we can only read up to the buffer size.
|
||||||
let mut bytes_left = if size > stats.size {
|
// let mut bytes_left = if size > stats.size {
|
||||||
stats.size
|
// stats.size
|
||||||
}
|
// }
|
||||||
else {
|
// else {
|
||||||
size
|
// size
|
||||||
};
|
// };
|
||||||
let mut bytes_left = 0;
|
let mut bytes_left = 0;
|
||||||
let mut bytes_read = 0u32;
|
let mut bytes_read = 0u32;
|
||||||
// In Rust, our for loop automatically "declares" i from 0 to < 7. The syntax
|
// In Rust, our for loop automatically "declares" i from 0 to < 7. The syntax
|
||||||
@ -205,14 +200,10 @@ impl FileSystem for MinixFileSystem {
|
|||||||
}
|
}
|
||||||
let zone_offset = zone_num * BLOCK_SIZE;
|
let zone_offset = zone_num * BLOCK_SIZE;
|
||||||
println!("Zone #{} -> #{} -> {}", i, zone_num, zone_offset);
|
println!("Zone #{} -> #{} -> {}", i, zone_num, zone_offset);
|
||||||
if let Ok(_) = block::read(desc.blockdev, block_buffer.get_mut(), BLOCK_SIZE, zone_offset as u64) {
|
syc_read(desc, block_buffer.get_mut(), BLOCK_SIZE, zone_offset);
|
||||||
for _ in 0..100000 {}
|
|
||||||
println!("Offset = {:x}", unsafe {block_buffer.get_mut().add(32).read()});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
blocks_seen += 1;
|
blocks_seen += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes_read
|
bytes_read
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +214,7 @@ impl FileSystem for MinixFileSystem {
|
|||||||
fn close(_desc: &mut Descriptor) {}
|
fn close(_desc: &mut Descriptor) {}
|
||||||
|
|
||||||
fn stat(desc: &Descriptor) -> Stat {
|
fn stat(desc: &Descriptor) -> Stat {
|
||||||
let inode_result = Self::get_inode(desc.blockdev, desc.node);
|
let inode_result = Self::get_inode(desc, desc.node);
|
||||||
// This could be a little dangerous, but the descriptor should be checked in open().
|
// This could be a little dangerous, but the descriptor should be checked in open().
|
||||||
let inode = inode_result.unwrap();
|
let inode = inode_result.unwrap();
|
||||||
Stat { mode: inode.mode,
|
Stat { mode: inode.mode,
|
||||||
@ -232,3 +223,54 @@ impl FileSystem for MinixFileSystem {
|
|||||||
gid: inode.gid, }
|
gid: inode.gid, }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn syc_read(desc: &Descriptor, buffer: *mut u8, size: u32, offset: u32) {
|
||||||
|
extern "C" {
|
||||||
|
fn make_syscall(sysno: usize, bdev: usize, buffer: usize, size: usize, offset: usize);
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
make_syscall(180, desc.blockdev as usize, buffer as usize, size as usize, offset as usize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ProcArgs {
|
||||||
|
pub pid: u16,
|
||||||
|
pub dev: usize,
|
||||||
|
pub buffer: *mut u8,
|
||||||
|
pub size: u32,
|
||||||
|
pub offset: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_proc(args_addr: usize) {
|
||||||
|
let args_ptr = args_addr as *mut ProcArgs;
|
||||||
|
let args = unsafe { args_ptr.as_ref().unwrap() };
|
||||||
|
|
||||||
|
let desc = Descriptor {
|
||||||
|
blockdev: args.dev,
|
||||||
|
node: 1,
|
||||||
|
loc: 0,
|
||||||
|
size: 500,
|
||||||
|
pid: args.pid
|
||||||
|
};
|
||||||
|
|
||||||
|
MinixFileSystem::read(&desc, args.buffer, args.offset, args.size);
|
||||||
|
tfree(args_ptr);
|
||||||
|
unsafe {
|
||||||
|
extern "C" {
|
||||||
|
fn make_syscall(no: usize);
|
||||||
|
}
|
||||||
|
make_syscall(93);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_read(pid: u16, dev: usize, buffer: *mut u8, size: u32, offset: u32) {
|
||||||
|
// println!("FS read {}, {}, 0x{:x}, {}, {}", pid, dev, buffer as usize, size, offset);
|
||||||
|
let args = talloc::<ProcArgs>().unwrap();
|
||||||
|
args.pid = pid;
|
||||||
|
args.dev = dev;
|
||||||
|
args.buffer = buffer;
|
||||||
|
args.size = size;
|
||||||
|
args.offset = offset;
|
||||||
|
set_waiting(pid);
|
||||||
|
let _ = add_kernel_process_args(read_proc, args as *mut ProcArgs as usize);
|
||||||
|
}
|
||||||
|
@ -3,13 +3,14 @@
|
|||||||
// Stephen Marz
|
// Stephen Marz
|
||||||
// 27 Nov 2019
|
// 27 Nov 2019
|
||||||
|
|
||||||
use crate::{cpu::{build_satp, satp_fence_asid, CpuMode, SatpMode, TrapFrame},
|
use crate::{cpu::{build_satp, get_mtime, satp_fence_asid, CpuMode, SatpMode, TrapFrame},
|
||||||
page::{alloc, dealloc, map, unmap, zalloc, EntryBits, Table, PAGE_SIZE}};
|
page::{alloc, dealloc, map, unmap, zalloc, EntryBits, Table, PAGE_SIZE}};
|
||||||
use alloc::collections::vec_deque::VecDeque;
|
use alloc::collections::vec_deque::VecDeque;
|
||||||
|
use core::ptr::null_mut;
|
||||||
|
|
||||||
// How many pages are we going to give a process for their
|
// How many pages are we going to give a process for their
|
||||||
// stack?
|
// stack?
|
||||||
const STACK_PAGES: usize = 2;
|
const STACK_PAGES: usize = 5;
|
||||||
// We want to adjust the stack to be at the bottom of the memory allocation
|
// We want to adjust the stack to be at the bottom of the memory allocation
|
||||||
// regardless of where it is on the kernel heap.
|
// regardless of where it is on the kernel heap.
|
||||||
const STACK_ADDR: usize = 0x1_0000_0000;
|
const STACK_ADDR: usize = 0x1_0000_0000;
|
||||||
@ -31,10 +32,6 @@ pub static mut PROCESS_LIST: Option<VecDeque<Process>> = None;
|
|||||||
// it's probably easier and faster just to increase the pid:
|
// it's probably easier and faster just to increase the pid:
|
||||||
static mut NEXT_PID: u16 = 1;
|
static mut NEXT_PID: u16 = 1;
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
fn make_syscall(a: usize) -> usize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set a process' state to running. This doesn't do any checks.
|
/// Set a process' state to running. This doesn't do any checks.
|
||||||
/// If this PID is not found, this returns false. Otherwise, it
|
/// If this PID is not found, this returns false. Otherwise, it
|
||||||
/// returns true.
|
/// returns true.
|
||||||
@ -85,6 +82,32 @@ pub fn set_waiting(pid: u16) -> bool {
|
|||||||
retval
|
retval
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sleep a process
|
||||||
|
pub fn set_sleeping(pid: u16, duration: usize) -> bool {
|
||||||
|
// Yes, this is O(n). A better idea here would be a static list
|
||||||
|
// of process pointers.
|
||||||
|
let mut retval = false;
|
||||||
|
unsafe {
|
||||||
|
if let Some(mut pl) = PROCESS_LIST.take() {
|
||||||
|
for proc in pl.iter_mut() {
|
||||||
|
if proc.pid == pid {
|
||||||
|
proc.set_state(ProcessState::Sleeping);
|
||||||
|
proc.set_sleep_until(get_mtime() + duration);
|
||||||
|
retval = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Now, we no longer need the owned Deque, so we hand it
|
||||||
|
// back by replacing the PROCESS_LIST's None with the
|
||||||
|
// Some(pl).
|
||||||
|
PROCESS_LIST.replace(pl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retval
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete a process given by pid. If this process doesn't exist,
|
||||||
|
/// this function does nothing.
|
||||||
pub fn delete_process(pid: u16) {
|
pub fn delete_process(pid: u16) {
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(mut pl) = PROCESS_LIST.take() {
|
if let Some(mut pl) = PROCESS_LIST.take() {
|
||||||
@ -105,20 +128,36 @@ pub fn delete_process(pid: u16) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a process by PID. Since we leak the process list, this is
|
||||||
|
/// unsafe since the process can be deleted and we'll still have a pointer.
|
||||||
|
pub unsafe fn get_by_pid(pid: u16) -> *mut Process {
|
||||||
|
let mut ret = null_mut();
|
||||||
|
if let Some(mut pl) = PROCESS_LIST.take() {
|
||||||
|
for i in pl.iter_mut() {
|
||||||
|
if i.get_pid() == pid {
|
||||||
|
ret = i as *mut Process;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PROCESS_LIST.replace(pl);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
/// We will eventually move this function out of here, but its
|
/// We will eventually move this function out of here, but its
|
||||||
/// job is just to take a slot in the process list.
|
/// job is just to take a slot in the process list.
|
||||||
fn init_process() {
|
fn init_process() {
|
||||||
// We can't do much here until we have system calls because
|
// We can't do much here until we have system calls because
|
||||||
// we're running in User space.
|
// we're running in User space.
|
||||||
let mut i: usize = 0;
|
|
||||||
loop {
|
loop {
|
||||||
i += 1;
|
|
||||||
// Eventually, this will be a sleep system call.
|
// Eventually, this will be a sleep system call.
|
||||||
if i > 100_000_000 {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
make_syscall(1);
|
extern "C" {
|
||||||
|
fn make_syscall(sysno: usize, duration: usize) -> usize;
|
||||||
}
|
}
|
||||||
i = 0;
|
println!("Init is still here :), alright, back to sleep.");
|
||||||
|
make_syscall(2, 60000000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,7 +193,7 @@ pub fn add_process_default(pr: fn()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add a kernel process.
|
/// Add a kernel process.
|
||||||
pub fn add_kernel_process(func: fn()) {
|
pub fn add_kernel_process(func: fn()) -> u16 {
|
||||||
// This is the Rust-ism that really trips up C++ programmers.
|
// This is the Rust-ism that really trips up C++ programmers.
|
||||||
// PROCESS_LIST is wrapped in an Option<> enumeration, which
|
// PROCESS_LIST is wrapped in an Option<> enumeration, which
|
||||||
// means that the Option owns the Deque. We can only borrow from
|
// means that the Option owns the Deque. We can only borrow from
|
||||||
@ -172,9 +211,10 @@ pub fn add_kernel_process(func: fn()) {
|
|||||||
// We will convert NEXT_PID below into an atomic increment when
|
// We will convert NEXT_PID below into an atomic increment when
|
||||||
// we start getting into multi-hart processing. For now, we want
|
// we start getting into multi-hart processing. For now, we want
|
||||||
// a process. Get it to work, then improve it!
|
// a process. Get it to work, then improve it!
|
||||||
|
let my_pid = unsafe {NEXT_PID};
|
||||||
let mut ret_proc = Process { frame: zalloc(1) as *mut TrapFrame,
|
let mut ret_proc = Process { frame: zalloc(1) as *mut TrapFrame,
|
||||||
stack: zalloc(STACK_PAGES),
|
stack: zalloc(STACK_PAGES),
|
||||||
pid: unsafe { NEXT_PID },
|
pid: my_pid,
|
||||||
root: zalloc(1) as *mut Table,
|
root: zalloc(1) as *mut Table,
|
||||||
state: ProcessState::Running,
|
state: ProcessState::Running,
|
||||||
data: ProcessData::zero(),
|
data: ProcessData::zero(),
|
||||||
@ -201,20 +241,89 @@ pub fn add_kernel_process(func: fn()) {
|
|||||||
// back by replacing the PROCESS_LIST's None with the
|
// back by replacing the PROCESS_LIST's None with the
|
||||||
// Some(pl).
|
// Some(pl).
|
||||||
unsafe { PROCESS_LIST.replace(pl); }
|
unsafe { PROCESS_LIST.replace(pl); }
|
||||||
|
my_pid
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
// TODO: When we get to multi-hart processing, we need to keep
|
// TODO: When we get to multi-hart processing, we need to keep
|
||||||
// trying to grab the process list. We can do this with an
|
// trying to grab the process list. We can do this with an
|
||||||
// atomic instruction. but right now, we're a single-processor
|
// atomic instruction. but right now, we're a single-processor
|
||||||
// computer.
|
// computer.
|
||||||
|
0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is the same as the add_kernel_process function, except you can pass
|
||||||
|
/// arguments. Typically, this will be a memory address on the heap where
|
||||||
|
/// arguments can be found.
|
||||||
|
pub fn add_kernel_process_args(func: fn(args_ptr: usize), args: usize) -> u16 {
|
||||||
|
// This is the Rust-ism that really trips up C++ programmers.
|
||||||
|
// PROCESS_LIST is wrapped in an Option<> enumeration, which
|
||||||
|
// means that the Option owns the Deque. We can only borrow from
|
||||||
|
// it or move ownership to us. In this case, we choose the
|
||||||
|
// latter, where we move ownership to us, add a process, and
|
||||||
|
// then move ownership back to the PROCESS_LIST.
|
||||||
|
// This allows mutual exclusion as anyone else trying to grab
|
||||||
|
// the process list will get None rather than the Deque.
|
||||||
|
if let Some(mut pl) = unsafe { PROCESS_LIST.take() } {
|
||||||
|
// .take() will replace PROCESS_LIST with None and give
|
||||||
|
// us the only copy of the Deque.
|
||||||
|
let func_addr = func as usize;
|
||||||
|
let func_vaddr = func_addr; //- 0x6000_0000;
|
||||||
|
// 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
|
||||||
|
// a process. Get it to work, then improve it!
|
||||||
|
let my_pid = unsafe {NEXT_PID};
|
||||||
|
let mut ret_proc = Process { frame: zalloc(1) as *mut TrapFrame,
|
||||||
|
stack: zalloc(STACK_PAGES),
|
||||||
|
pid: my_pid,
|
||||||
|
root: zalloc(1) as *mut Table,
|
||||||
|
state: ProcessState::Running,
|
||||||
|
data: ProcessData::zero(),
|
||||||
|
sleep_until: 0, };
|
||||||
|
unsafe {
|
||||||
|
NEXT_PID += 1;
|
||||||
|
}
|
||||||
|
// Now we move the stack pointer to the bottom of the
|
||||||
|
// allocation. The spec shows that register x2 (2) is the stack
|
||||||
|
// pointer.
|
||||||
|
// We could use ret_proc.stack.add, but that's an unsafe
|
||||||
|
// function which would require an unsafe block. So, convert it
|
||||||
|
// to usize first and then add PAGE_SIZE is better.
|
||||||
|
// We also need to set the stack adjustment so that it is at the
|
||||||
|
// bottom of the memory and far away from heap allocations.
|
||||||
|
unsafe {
|
||||||
|
(*ret_proc.frame).pc = func_vaddr;
|
||||||
|
(*ret_proc.frame).regs[10] = args;
|
||||||
|
(*ret_proc.frame).regs[2] = ret_proc.stack as usize + STACK_PAGES * 4096;
|
||||||
|
(*ret_proc.frame).mode = CpuMode::Machine as usize;
|
||||||
|
(*ret_proc.frame).pid = ret_proc.pid as usize;
|
||||||
|
}
|
||||||
|
pl.push_back(ret_proc);
|
||||||
|
// Now, we no longer need the owned Deque, so we hand it
|
||||||
|
// back by replacing the PROCESS_LIST's None with the
|
||||||
|
// Some(pl).
|
||||||
|
unsafe { PROCESS_LIST.replace(pl); }
|
||||||
|
my_pid
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO: When we get to multi-hart processing, we need to keep
|
||||||
|
// trying to grab the process list. We can do this with an
|
||||||
|
// atomic instruction. but right now, we're a single-processor
|
||||||
|
// computer.
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// This should only be called once, and its job is to create
|
/// This should only be called once, and its job is to create
|
||||||
/// the init process. Right now, this process is in the kernel,
|
/// the init process. Right now, this process is in the kernel,
|
||||||
/// but later, it should call the shell.
|
/// but later, it should call the shell.
|
||||||
pub fn init() -> usize {
|
pub fn init() -> usize {
|
||||||
unsafe {
|
unsafe {
|
||||||
PROCESS_LIST = Some(VecDeque::with_capacity(15));
|
PROCESS_LIST = Some(VecDeque::with_capacity(15));
|
||||||
add_process_default(init_process);
|
// add_process_default(init_process);
|
||||||
|
add_kernel_process(init_process);
|
||||||
// Ugh....Rust is giving me fits over here!
|
// Ugh....Rust is giving me fits over here!
|
||||||
// I just want a memory address to the trap frame, but
|
// I just want a memory address to the trap frame, but
|
||||||
// due to the borrow rules of Rust, I'm fighting here. So,
|
// due to the borrow rules of Rust, I'm fighting here. So,
|
||||||
@ -267,6 +376,10 @@ impl Process {
|
|||||||
self.frame as usize
|
self.frame as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_frame(&mut self) -> *mut TrapFrame {
|
||||||
|
self.frame
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_program_counter(&self) -> usize {
|
pub fn get_program_counter(&self) -> usize {
|
||||||
unsafe { (*self.frame).pc }
|
unsafe { (*self.frame).pc }
|
||||||
}
|
}
|
||||||
@ -291,6 +404,10 @@ impl Process {
|
|||||||
self.sleep_until
|
self.sleep_until
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_sleep_until(&mut self, until: usize) {
|
||||||
|
self.sleep_until = until;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_default(func: fn()) -> Self {
|
pub fn new_default(func: fn()) -> Self {
|
||||||
let func_addr = func as usize;
|
let func_addr = func as usize;
|
||||||
let func_vaddr = func_addr; //- 0x6000_0000;
|
let func_vaddr = func_addr; //- 0x6000_0000;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
// 27 Dec 2019
|
// 27 Dec 2019
|
||||||
|
|
||||||
use crate::process::{ProcessState, PROCESS_LIST};
|
use crate::process::{ProcessState, PROCESS_LIST};
|
||||||
|
use crate::cpu::get_mtime;
|
||||||
|
|
||||||
pub fn schedule() -> usize {
|
pub fn schedule() -> usize {
|
||||||
let mut frame_addr: usize = 0x1111;
|
let mut frame_addr: usize = 0x1111;
|
||||||
@ -15,7 +16,7 @@ pub fn schedule() -> usize {
|
|||||||
// let mut mepc: usize = 0;
|
// let mut mepc: usize = 0;
|
||||||
// let mut satp: usize = 0;
|
// let mut satp: usize = 0;
|
||||||
// let mut pid: usize = 0;
|
// let mut pid: usize = 0;
|
||||||
if let Some(prc) = pl.front() {
|
if let Some(prc) = pl.front_mut() {
|
||||||
match prc.get_state() {
|
match prc.get_state() {
|
||||||
ProcessState::Running => {
|
ProcessState::Running => {
|
||||||
frame_addr =
|
frame_addr =
|
||||||
@ -25,7 +26,13 @@ pub fn schedule() -> usize {
|
|||||||
// satp = prc.get_table_address();
|
// satp = prc.get_table_address();
|
||||||
// pid = prc.get_pid() as usize;
|
// pid = prc.get_pid() as usize;
|
||||||
},
|
},
|
||||||
ProcessState::Sleeping => {},
|
ProcessState::Sleeping => {
|
||||||
|
// Awaken sleeping processes whose sleep until is in
|
||||||
|
// the past.
|
||||||
|
if prc.get_sleep_until() <= get_mtime() {
|
||||||
|
prc.set_state(ProcessState::Running);
|
||||||
|
}
|
||||||
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,11 @@
|
|||||||
// Stephen Marz
|
// Stephen Marz
|
||||||
// 3 Jan 2020
|
// 3 Jan 2020
|
||||||
|
|
||||||
use crate::{block::process_read, cpu::TrapFrame};
|
use crate::{block::block_op,
|
||||||
use crate::process::delete_process;
|
cpu::TrapFrame,
|
||||||
|
fs::FileSystem,
|
||||||
|
minixfs,
|
||||||
|
process::{delete_process, set_sleeping}};
|
||||||
|
|
||||||
pub fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize {
|
pub fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize {
|
||||||
let syscall_number;
|
let syscall_number;
|
||||||
@ -18,50 +21,7 @@ pub fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
// These system call numbers come from libgloss so that we can use newlib
|
|
||||||
// for our system calls.
|
|
||||||
// Libgloss wants the system call number in A7 and arguments in A0..A6
|
|
||||||
// #define SYS_getcwd 17
|
|
||||||
// #define SYS_dup 23
|
|
||||||
// #define SYS_fcntl 25
|
|
||||||
// #define SYS_faccessat 48
|
|
||||||
// #define SYS_chdir 49
|
|
||||||
// #define SYS_openat 56
|
|
||||||
// #define SYS_close 57
|
|
||||||
// #define SYS_getdents 61
|
|
||||||
// #define SYS_lseek 62
|
|
||||||
// #define SYS_read 63
|
|
||||||
// #define SYS_write 64
|
|
||||||
// #define SYS_writev 66
|
|
||||||
// #define SYS_pread 67
|
|
||||||
// #define SYS_pwrite 68
|
|
||||||
// #define SYS_fstatat 79
|
|
||||||
// #define SYS_fstat 80
|
|
||||||
// #define SYS_exit 93
|
|
||||||
// #define SYS_exit_group 94
|
|
||||||
// #define SYS_kill 129
|
|
||||||
// #define SYS_rt_sigaction 134
|
|
||||||
// #define SYS_times 153
|
|
||||||
// #define SYS_uname 160
|
|
||||||
// #define SYS_gettimeofday 169
|
|
||||||
// #define SYS_getpid 172
|
|
||||||
// #define SYS_getuid 174
|
|
||||||
// #define SYS_geteuid 175
|
|
||||||
// #define SYS_getgid 176
|
|
||||||
// #define SYS_getegid 177
|
|
||||||
// #define SYS_brk 214
|
|
||||||
// #define SYS_munmap 215
|
|
||||||
// #define SYS_mremap 216
|
|
||||||
// #define SYS_mmap 222
|
|
||||||
// #define SYS_open 1024
|
|
||||||
// #define SYS_link 1025
|
|
||||||
// #define SYS_unlink 1026
|
|
||||||
// #define SYS_mkdir 1030
|
|
||||||
// #define SYS_access 1033
|
|
||||||
// #define SYS_stat 1038
|
|
||||||
// #define SYS_lstat 1039
|
|
||||||
// #define SYS_time 1062
|
|
||||||
// #define SYS_getmainvars 2011
|
|
||||||
match syscall_number {
|
match syscall_number {
|
||||||
0 | 93 => unsafe {
|
0 | 93 => unsafe {
|
||||||
// Exit
|
// Exit
|
||||||
@ -75,20 +35,45 @@ pub fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize {
|
|||||||
println!("Test syscall");
|
println!("Test syscall");
|
||||||
mepc + 4
|
mepc + 4
|
||||||
},
|
},
|
||||||
|
2 => unsafe {
|
||||||
|
// Sleep
|
||||||
|
set_sleeping((*frame).pid as u16, (*frame).regs[10]);
|
||||||
|
0
|
||||||
|
},
|
||||||
63 => unsafe {
|
63 => unsafe {
|
||||||
// Read system call
|
// Read system call
|
||||||
// This is an asynchronous call. This will get the process going. We won't hear the answer until
|
// This is an asynchronous call. This will get the process going. We won't hear the answer until
|
||||||
// we an interrupt back.
|
// we an interrupt back.
|
||||||
// TODO: The buffer is a virtual memory address that needs to be translated to a physical memory
|
// TODO: The buffer is a virtual memory address that needs to be translated to a physical memory
|
||||||
// location.
|
// location.
|
||||||
let _ = process_read(
|
// This needs to be put into a process and ran.
|
||||||
|
let _ = minixfs::process_read(
|
||||||
(*frame).pid as u16,
|
(*frame).pid as u16,
|
||||||
|
(*frame).regs[10] as usize,
|
||||||
|
(*frame).regs[11] as *mut u8,
|
||||||
|
(*frame).regs[12] as u32,
|
||||||
|
(*frame).regs[13] as u32
|
||||||
|
);
|
||||||
|
// If we return 0, the trap handler will schedule another process.
|
||||||
|
0
|
||||||
|
},
|
||||||
|
180 => unsafe {
|
||||||
|
println!(
|
||||||
|
"Pid: {}, Dev: {}, Buffer: 0x{:x}, Size: {}, Offset: {}",
|
||||||
|
(*frame).pid,
|
||||||
(*frame).regs[10],
|
(*frame).regs[10],
|
||||||
|
(*frame).regs[11],
|
||||||
|
(*frame).regs[12],
|
||||||
|
(*frame).regs[13]
|
||||||
|
);
|
||||||
|
let _ = block_op((*frame).regs[10],
|
||||||
(*frame).regs[11] as *mut u8,
|
(*frame).regs[11] as *mut u8,
|
||||||
(*frame).regs[12] as u32,
|
(*frame).regs[12] as u32,
|
||||||
(*frame).regs[13] as u64,
|
(*frame).regs[13] as u64,
|
||||||
|
false,
|
||||||
|
(*frame).pid as u16
|
||||||
|
|
||||||
);
|
);
|
||||||
// If we return 0, the trap handler will schedule another process.
|
|
||||||
0
|
0
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
@ -97,3 +82,48 @@ pub fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These system call numbers come from libgloss so that we can use newlib
|
||||||
|
// for our system calls.
|
||||||
|
// Libgloss wants the system call number in A7 and arguments in A0..A6
|
||||||
|
// #define SYS_getcwd 17
|
||||||
|
// #define SYS_dup 23
|
||||||
|
// #define SYS_fcntl 25
|
||||||
|
// #define SYS_faccessat 48
|
||||||
|
// #define SYS_chdir 49
|
||||||
|
// #define SYS_openat 56
|
||||||
|
// #define SYS_close 57
|
||||||
|
// #define SYS_getdents 61
|
||||||
|
// #define SYS_lseek 62
|
||||||
|
// #define SYS_read 63
|
||||||
|
// #define SYS_write 64
|
||||||
|
// #define SYS_writev 66
|
||||||
|
// #define SYS_pread 67
|
||||||
|
// #define SYS_pwrite 68
|
||||||
|
// #define SYS_fstatat 79
|
||||||
|
// #define SYS_fstat 80
|
||||||
|
// #define SYS_exit 93
|
||||||
|
// #define SYS_exit_group 94
|
||||||
|
// #define SYS_kill 129
|
||||||
|
// #define SYS_rt_sigaction 134
|
||||||
|
// #define SYS_times 153
|
||||||
|
// #define SYS_uname 160
|
||||||
|
// #define SYS_gettimeofday 169
|
||||||
|
// #define SYS_getpid 172
|
||||||
|
// #define SYS_getuid 174
|
||||||
|
// #define SYS_geteuid 175
|
||||||
|
// #define SYS_getgid 176
|
||||||
|
// #define SYS_getegid 177
|
||||||
|
// #define SYS_brk 214
|
||||||
|
// #define SYS_munmap 215
|
||||||
|
// #define SYS_mremap 216
|
||||||
|
// #define SYS_mmap 222
|
||||||
|
// #define SYS_open 1024
|
||||||
|
// #define SYS_link 1025
|
||||||
|
// #define SYS_unlink 1026
|
||||||
|
// #define SYS_mkdir 1030
|
||||||
|
// #define SYS_access 1033
|
||||||
|
// #define SYS_stat 1038
|
||||||
|
// #define SYS_lstat 1039
|
||||||
|
// #define SYS_time 1062
|
||||||
|
// #define SYS_getmainvars 2011
|
||||||
|
@ -6,14 +6,8 @@ extern "C" {
|
|||||||
|
|
||||||
pub fn test_block() {
|
pub fn test_block() {
|
||||||
// Let's test the block driver!
|
// Let's test the block driver!
|
||||||
println!("Started test block process.");
|
|
||||||
let desc = crate::fs::Descriptor {
|
|
||||||
blockdev: 8,
|
|
||||||
node: 1,
|
|
||||||
loc: 0,
|
|
||||||
size: 500,
|
|
||||||
};
|
|
||||||
let buffer = crate::kmem::kmalloc(1024);
|
let buffer = crate::kmem::kmalloc(1024);
|
||||||
|
println!("Started test block process, buffer is at {:p}.", buffer);
|
||||||
unsafe {
|
unsafe {
|
||||||
make_syscall(63, 8, buffer as usize, 1024, 1024);
|
make_syscall(63, 8, buffer as usize, 1024, 1024);
|
||||||
for i in 0..32 {
|
for i in 0..32 {
|
||||||
|
@ -37,9 +37,6 @@ extern "C" fn m_trap(epc: usize,
|
|||||||
// number. So, here we narrow down just the cause number.
|
// number. So, here we narrow down just the cause number.
|
||||||
let cause_num = cause & 0xfff;
|
let cause_num = cause & 0xfff;
|
||||||
let mut return_pc = epc;
|
let mut return_pc = epc;
|
||||||
unsafe {
|
|
||||||
(*frame).pc = return_pc;
|
|
||||||
}
|
|
||||||
if is_async {
|
if is_async {
|
||||||
// Asynchronous trap
|
// Asynchronous trap
|
||||||
match cause_num {
|
match cause_num {
|
||||||
@ -53,8 +50,22 @@ extern "C" fn m_trap(epc: usize,
|
|||||||
// We would typically invoke the scheduler here to pick another
|
// We would typically invoke the scheduler here to pick another
|
||||||
// process to run.
|
// process to run.
|
||||||
// Machine timer
|
// Machine timer
|
||||||
// println!("CTX");
|
|
||||||
let frame = schedule();
|
let frame = schedule();
|
||||||
|
// let p = frame as *const TrapFrame;
|
||||||
|
// println!(
|
||||||
|
// "CTX Startup {}, pc = {:x}",
|
||||||
|
// (*p).pid,
|
||||||
|
// (*p).pc
|
||||||
|
// );
|
||||||
|
// print!(" ");
|
||||||
|
// for i in 1..32 {
|
||||||
|
// if i % 4 == 0 {
|
||||||
|
// println!();
|
||||||
|
// print!(" ");
|
||||||
|
// }
|
||||||
|
// print!("{:2}:{:08x} ", i, (*p).regs[i]);
|
||||||
|
// }
|
||||||
|
// println!();
|
||||||
schedule_next_context_switch(1);
|
schedule_next_context_switch(1);
|
||||||
rust_switch_to_user(frame);
|
rust_switch_to_user(frame);
|
||||||
},
|
},
|
||||||
@ -93,7 +104,21 @@ extern "C" fn m_trap(epc: usize,
|
|||||||
// the system call so that when we resume this process, we're after the ecall.
|
// the system call so that when we resume this process, we're after the ecall.
|
||||||
(*frame).pc += 4;
|
(*frame).pc += 4;
|
||||||
let frame = schedule();
|
let frame = schedule();
|
||||||
// let p = frame as *const crate::process::Process;
|
// let p = frame as *const TrapFrame;
|
||||||
|
// println!(
|
||||||
|
// "SYC Startup {}, pc = {:x}",
|
||||||
|
// (*p).pid,
|
||||||
|
// (*p).pc,
|
||||||
|
// );
|
||||||
|
// print!(" ");
|
||||||
|
// for i in 1..32 {
|
||||||
|
// if i % 4 == 0 {
|
||||||
|
// println!();
|
||||||
|
// print!(" ");
|
||||||
|
// }
|
||||||
|
// print!("{:2}:{:08x} ", i, (*p).regs[i]);
|
||||||
|
// }
|
||||||
|
// println!();
|
||||||
schedule_next_context_switch(1);
|
schedule_next_context_switch(1);
|
||||||
rust_switch_to_user(frame);
|
rust_switch_to_user(frame);
|
||||||
}
|
}
|
||||||
@ -121,7 +146,7 @@ extern "C" fn m_trap(epc: usize,
|
|||||||
return_pc += 4;
|
return_pc += 4;
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
panic!("Unhandled sync trap CPU#{} -> {}\n", hart, cause_num);
|
panic!("Unhandled sync trap {}. CPU#{} -> 0x{:08x}: 0x{:08x}\n", cause_num, hart, epc, tval);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user