diff --git a/kernel/console.c b/kernel/console.c index 0e94a21..d9bf590 100644 --- a/kernel/console.c +++ b/kernel/console.c @@ -182,3 +182,25 @@ void consoleinit(void) { devsw[CONSOLE].read = consoleread; devsw[CONSOLE].write = consolewrite; } + +// int consoleread(int, uint64, int); +// int consolewrite(int, uint64, int); + +// struct { +// struct spinlock lock; + +// // input +// #define INPUT_BUF_SIZE 128 +// char buf[INPUT_BUF_SIZE]; +// uint r; // Read index +// uint w; // Write index +// uint e; // Edit index +// } cons; + +// // Call from consoleinit +// void connect_console_syscalls() { +// // connect read and write system calls +// // to consoleread and consolewrite. +// devsw[CONSOLE].read = consoleread; +// devsw[CONSOLE].write = consolewrite; +// } diff --git a/theseus/src/console.rs b/theseus/src/console.rs new file mode 100644 index 0000000..d90b8cb --- /dev/null +++ b/theseus/src/console.rs @@ -0,0 +1,198 @@ +use core::ptr::{addr_of, addr_of_mut, null, null_mut}; + +use crate::{ + spinlock::{initlock, SpinLock}, + uart::{uartinit, uartputc}, +}; + +// Console input and output, to the uart. +// Reads are line at a time. +// Implements special input characters: +// newline -- end of line +// control-h -- backspace +// control-u -- kill line +// control-d -- end of file +// control-p -- print process list + +extern "C" { + // proc.c + fn either_copyout(user_dst: i32, dst: u64, src: *mut (), len: u64) -> i32; + fn either_copyin(dst: *mut (), user_src: i32, src: u64, len: u64) -> i32; + fn killed(proc: *const ()) -> bool; + fn myproc() -> *const (); + fn sleep(chan: *const u64, lock: *mut SpinLock); + fn procdump(); + + // spinlock.c + fn acquire(lock: *mut SpinLock); + fn release(lock: *mut SpinLock); + + // console.c + fn connect_console_syscalls(); +} + +const fn control_modified(c: i32) -> i32 { + c - b'@' as i32 +} + +const BACKSPACE: i32 = 0x100; +const INPUT_BUF_SIZE: usize = 128; +const CODE_BACKSPACE: i32 = control_modified(b'H' as i32); +const CODE_KILL_LINE: i32 = control_modified(b'U' as i32); +const CODE_END_OF_FILE: i32 = control_modified(b'D' as i32); +const CODE_PRINT_PROCESSES: i32 = control_modified(b'P' as i32); + +// #[repr(C)] +// struct Console { +// lock: SpinLock, +// /// Input +// buf: [u8; INPUT_BUF_SIZE], +// /// Read index +// r: u64, +// /// Write index +// w: u64, +// /// Edit index +// e: u64, +// } + +// static mut CONSOLE: Console = Console { +// lock: SpinLock { +// locked: 0, +// cpu: null_mut(), +// name: null(), +// }, +// buf: [0; INPUT_BUF_SIZE], +// r: 0, +// w: 0, +// e: 0, +// }; + +// /// send one character to the uart. +// /// called by printf(), and to echo input characters, +// /// but not from write(). +// #[no_mangle] +// pub extern "C" fn consputc(c: i32) { +// if c == BACKSPACE { +// // if the user typed backspace, overwrite with a space. +// uartputc(8); +// uartputc(b' '); +// uartputc(8); +// } else { +// uartputc(c.try_into().unwrap_or(b'?')); +// } +// } + +// /// user write()s to the console go here. +// #[no_mangle] +// pub extern "C" fn consolewrite(user_src: i32, src: u64, n: i32) -> i32 { +// for i in 0..n { +// let mut c: u8 = 0; +// unsafe { +// if either_copyin(addr_of_mut!(c) as *mut (), user_src, src, 1) == -1 { +// return i; +// } +// } +// uartputc(c); +// } +// 0 +// } + +// /// user read()s from the console go here. +// /// copy (up to) a whole input line to dst. +// /// user_dist indicates whether dst is a user +// /// or kernel address. +// #[no_mangle] +// pub unsafe extern "C" fn consoleread(user_dst: i32, dst: u64, n: i32) -> i32 { +// let mut c: i32; +// let mut cbuf: u8; + +// let target = n; +// acquire(addr_of_mut!(CONSOLE.lock)); + +// let mut dst = dst; +// let mut n = n; + +// while n > 0 { +// // wait until interrupt handler has put some +// // input into cons.buffer. +// while CONSOLE.r == CONSOLE.w { +// if killed(myproc()) { +// release(addr_of_mut!(CONSOLE.lock)); +// return -1; +// } +// // sleep(&cons.r, &cons.lock); +// sleep(addr_of!(CONSOLE.r), addr_of_mut!(CONSOLE.lock)); +// } + +// c = CONSOLE.buf[CONSOLE.r as usize % INPUT_BUF_SIZE] as i32; +// CONSOLE.r += 1; + +// if c == CODE_END_OF_FILE { +// // end-of-file +// if n < target { +// // Save ^D for next time, to make sure +// // caller gets a 0-byte result. +// CONSOLE.r -= 1; +// } +// break; +// } + +// // copy the input byte to the user-space buffer. +// cbuf = c as u8; +// if either_copyout(user_dst, dst, addr_of_mut!(cbuf) as *mut (), 1) == -1 { +// break; +// } + +// dst += 1; +// n -= 1; + +// if c == b'\n' as i32 { +// // a whole line has arrived, return to +// // the user-level read(). +// break; +// } +// } +// release(addr_of_mut!(CONSOLE.lock)); + +// target - n +// } + +// pub unsafe fn consoleintr(c: i32) { +// acquire(addr_of_mut!(CONSOLE.lock)); + +// match c { +// CODE_PRINT_PROCESSES => { +// procdump(); +// } +// CODE_KILL_LINE => { +// while CONSOLE.e != CONSOLE.w +// && CONSOLE.buf[(CONSOLE.e as usize - 1) % INPUT_BUF_SIZE] != b'\n' +// { +// CONSOLE.e -= 1; +// consputc(BACKSPACE) +// } +// } +// CODE_BACKSPACE | 0x7f => { +// if CONSOLE.e != CONSOLE.w { +// CONSOLE.e -= 1; +// consputc(BACKSPACE) +// } +// } +// c => { +// if c != 0 && ((CONSOLE.e - CONSOLE.r) as usize) < INPUT_BUF_SIZE { +// let c = if c == b'\r' as i32 { b'\n' as i32 } else { c }; +// consputc(c); +// CONSOLE.buf[CONSOLE.e as usize % INPUT_BUF_SIZE] = c.try_into().unwrap(); +// CONSOLE.e += 1; +// } +// } +// } + +// release(addr_of_mut!(CONSOLE.lock)); +// } + +// pub unsafe fn consoleinit() { +// initlock(addr_of_mut!(CONSOLE.lock), c"cons".as_ptr()); +// uartinit(); +// connect_console_syscalls(); +// } diff --git a/theseus/src/kmain.rs b/theseus/src/kmain.rs index e52446f..e82e731 100644 --- a/theseus/src/kmain.rs +++ b/theseus/src/kmain.rs @@ -1,4 +1,7 @@ -use crate::riscv; +use crate::{ + // console::consoleinit, + riscv, +}; extern "C" { fn cpuid() -> u64; diff --git a/theseus/src/lib.rs b/theseus/src/lib.rs index 517c46d..d0a1a12 100644 --- a/theseus/src/lib.rs +++ b/theseus/src/lib.rs @@ -3,6 +3,7 @@ use core::ffi::CStr; +pub mod console; pub mod kmain; pub mod memlayout; pub mod param; diff --git a/theseus/src/proc.rs b/theseus/src/proc.rs new file mode 100644 index 0000000..e17f15d --- /dev/null +++ b/theseus/src/proc.rs @@ -0,0 +1,29 @@ +// Saved registers for kernel context switches. +#[repr(C)] +pub struct Context { + pub ra: u64, + pub sp: u64, + + // Callee-saved + pub s0: u64, + pub s1: u64, + pub s2: u64, + pub s3: u64, + pub s4: u64, + pub s5: u64, + pub s6: u64, + pub s7: u64, + pub s8: u64, + pub s9: u64, + pub s10: u64, + pub s11: u64, +} + +// Per-CPU state. +#[repr(C)] +pub struct CpuState { + pub proc: *mut (), // The process running on this cpu, or null. + pub context: Context, // swtch() here to enter scheduler(). + pub noff: i32, // Depth of push_off() nesting. + pub intena: i32, // Were interrupts enabled before push_off()? +} diff --git a/theseus/src/uart.rs b/theseus/src/uart.rs index bf0d7e1..a93e718 100644 --- a/theseus/src/uart.rs +++ b/theseus/src/uart.rs @@ -1,4 +1,5 @@ use crate::{ + // console::consoleintr, memlayout::UART0, spinlock::{initlock, SpinLock}, };