restructure uart to compile correctly
This commit is contained in:
parent
ca962854c5
commit
4ea64e0b6b
1
Makefile
1
Makefile
@ -100,6 +100,7 @@ UPROGS=\
|
|||||||
$P/_wc\
|
$P/_wc\
|
||||||
$P/_zombie\
|
$P/_zombie\
|
||||||
$P/_shutdown\
|
$P/_shutdown\
|
||||||
|
$P/_clear\
|
||||||
|
|
||||||
fs.img: mkfs README.md $(UPROGS)
|
fs.img: mkfs README.md $(UPROGS)
|
||||||
mkfs/mkfs fs.img README.md $(UPROGS)
|
mkfs/mkfs fs.img README.md $(UPROGS)
|
||||||
|
@ -43,13 +43,7 @@ pub unsafe fn kvmmake() -> Pagetable {
|
|||||||
memset(pagetable.cast(), 0, PAGE_SIZE);
|
memset(pagetable.cast(), 0, PAGE_SIZE);
|
||||||
|
|
||||||
// QEMU test interface used for power management.
|
// QEMU test interface used for power management.
|
||||||
kvmmap(
|
kvmmap(pagetable, QEMU_POWER, QEMU_POWER, PAGE_SIZE, PTE_R | PTE_W);
|
||||||
pagetable,
|
|
||||||
QEMU_POWER,
|
|
||||||
QEMU_POWER,
|
|
||||||
PAGE_SIZE,
|
|
||||||
PTE_R | PTE_W,
|
|
||||||
);
|
|
||||||
|
|
||||||
// UART registers
|
// UART registers
|
||||||
for (_, uart) in &crate::hardware::UARTS {
|
for (_, uart) in &crate::hardware::UARTS {
|
||||||
@ -63,22 +57,10 @@ pub unsafe fn kvmmake() -> Pagetable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VirtIO MMIO disk interface
|
// VirtIO MMIO disk interface
|
||||||
kvmmap(
|
kvmmap(pagetable, VIRTIO0, VIRTIO0, PAGE_SIZE, PTE_R | PTE_W);
|
||||||
pagetable,
|
|
||||||
VIRTIO0,
|
|
||||||
VIRTIO0,
|
|
||||||
PAGE_SIZE,
|
|
||||||
PTE_R | PTE_W,
|
|
||||||
);
|
|
||||||
|
|
||||||
// PLIC
|
// PLIC
|
||||||
kvmmap(
|
kvmmap(pagetable, PLIC, PLIC, 0x400000, PTE_R | PTE_W);
|
||||||
pagetable,
|
|
||||||
PLIC,
|
|
||||||
PLIC,
|
|
||||||
0x400000,
|
|
||||||
PTE_R | PTE_W,
|
|
||||||
);
|
|
||||||
|
|
||||||
let etext_addr = addr_of!(etext) as usize;
|
let etext_addr = addr_of!(etext) as usize;
|
||||||
|
|
||||||
@ -159,16 +141,19 @@ pub unsafe fn kvminithart() {
|
|||||||
/// - 21..30: 9 bits of level 0 index.
|
/// - 21..30: 9 bits of level 0 index.
|
||||||
/// - 30..39: 9 bits of level 0 index.
|
/// - 30..39: 9 bits of level 0 index.
|
||||||
/// - 39..64: Must be zero.
|
/// - 39..64: Must be zero.
|
||||||
pub unsafe fn walk(mut pagetable: Pagetable, virtual_addr: usize, alloc: bool) -> *mut PagetableEntry {
|
pub unsafe fn walk(
|
||||||
|
mut pagetable: Pagetable,
|
||||||
|
virtual_addr: usize,
|
||||||
|
alloc: bool,
|
||||||
|
) -> *mut PagetableEntry {
|
||||||
if virtual_addr > VIRTUAL_MAX {
|
if virtual_addr > VIRTUAL_MAX {
|
||||||
panic!("walk");
|
panic!("walk");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut level = 2;
|
let mut level = 2;
|
||||||
while level > 0 {
|
while level > 0 {
|
||||||
let pte = addr_of_mut!(
|
let pte =
|
||||||
pagetable.as_mut().unwrap()[(virtual_addr >> (12 + (level * 9))) & 0x1ff]
|
addr_of_mut!(pagetable.as_mut().unwrap()[(virtual_addr >> (12 + (level * 9))) & 0x1ff]);
|
||||||
);
|
|
||||||
|
|
||||||
if (*pte) & PTE_V as u64 > 0 {
|
if (*pte) & PTE_V as u64 > 0 {
|
||||||
pagetable = (((*pte) >> 10) << 12) as usize as Pagetable;
|
pagetable = (((*pte) >> 10) << 12) as usize as Pagetable;
|
||||||
@ -202,7 +187,7 @@ pub unsafe extern "C" fn walkaddr(pagetable: Pagetable, virtual_addr: usize) ->
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pte = walk(pagetable, virtual_addr , false);
|
let pte = walk(pagetable, virtual_addr, false);
|
||||||
if pte.is_null() || *pte & PTE_V as u64 == 0 || *pte & PTE_U as u64 == 0 {
|
if pte.is_null() || *pte & PTE_V as u64 == 0 || *pte & PTE_U as u64 == 0 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -272,12 +257,7 @@ pub unsafe fn mappages(
|
|||||||
///
|
///
|
||||||
/// `virtual_addr` amust be page-aligned. The mappings must exist.
|
/// `virtual_addr` amust be page-aligned. The mappings must exist.
|
||||||
/// Optionally free the physical memory.
|
/// Optionally free the physical memory.
|
||||||
pub unsafe fn uvmunmap(
|
pub unsafe fn uvmunmap(pagetable: Pagetable, virtual_addr: usize, num_pages: usize, free: bool) {
|
||||||
pagetable: Pagetable,
|
|
||||||
virtual_addr: usize,
|
|
||||||
num_pages: usize,
|
|
||||||
free: bool,
|
|
||||||
) {
|
|
||||||
if virtual_addr % PAGE_SIZE != 0 {
|
if virtual_addr % PAGE_SIZE != 0 {
|
||||||
panic!("uvmunmap: not aligned");
|
panic!("uvmunmap: not aligned");
|
||||||
}
|
}
|
||||||
@ -359,14 +339,7 @@ pub unsafe extern "C" fn uvmalloc(
|
|||||||
|
|
||||||
memset(mem.cast(), 0, PAGE_SIZE);
|
memset(mem.cast(), 0, PAGE_SIZE);
|
||||||
|
|
||||||
if mappages(
|
if mappages(pagetable, a, PAGE_SIZE, mem as usize, PTE_R | PTE_U | xperm) != 0 {
|
||||||
pagetable,
|
|
||||||
a,
|
|
||||||
PAGE_SIZE,
|
|
||||||
mem as usize,
|
|
||||||
PTE_R | PTE_U | xperm,
|
|
||||||
) != 0
|
|
||||||
{
|
|
||||||
kfree(mem.cast());
|
kfree(mem.cast());
|
||||||
uvmdealloc(pagetable, a, old_size);
|
uvmdealloc(pagetable, a, old_size);
|
||||||
return 0;
|
return 0;
|
||||||
@ -390,14 +363,8 @@ pub unsafe extern "C" fn uvmdealloc(pagetable: Pagetable, old_size: usize, new_s
|
|||||||
}
|
}
|
||||||
|
|
||||||
if round_up_page(new_size) < round_up_page(old_size) {
|
if round_up_page(new_size) < round_up_page(old_size) {
|
||||||
let num_pages =
|
let num_pages = (round_up_page(old_size) - round_up_page(new_size)) / PAGE_SIZE;
|
||||||
(round_up_page(old_size) - round_up_page(new_size)) / PAGE_SIZE;
|
uvmunmap(pagetable, round_up_page(new_size), num_pages, true);
|
||||||
uvmunmap(
|
|
||||||
pagetable,
|
|
||||||
round_up_page(new_size),
|
|
||||||
num_pages,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new_size as u64
|
new_size as u64
|
||||||
@ -424,12 +391,7 @@ pub unsafe fn freewalk(pagetable: Pagetable) {
|
|||||||
|
|
||||||
/// Free user memory pages, then free pagetable pages.
|
/// Free user memory pages, then free pagetable pages.
|
||||||
pub unsafe fn uvmfree(pagetable: Pagetable, size: usize) {
|
pub unsafe fn uvmfree(pagetable: Pagetable, size: usize) {
|
||||||
uvmunmap(
|
uvmunmap(pagetable, 0, round_up_page(size) / PAGE_SIZE, true);
|
||||||
pagetable,
|
|
||||||
0,
|
|
||||||
round_up_page(size) / PAGE_SIZE,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
freewalk(pagetable);
|
freewalk(pagetable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,7 +525,12 @@ pub unsafe extern "C" fn copyin(
|
|||||||
// depending on usr_dst.
|
// depending on usr_dst.
|
||||||
// Returns 0 on success, -1 on error.
|
// Returns 0 on success, -1 on error.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn either_copyout(user_dst: i32, dst: usize, src: *mut u8, len: usize) -> i32 {
|
pub unsafe extern "C" fn either_copyout(
|
||||||
|
user_dst: i32,
|
||||||
|
dst: usize,
|
||||||
|
src: *mut u8,
|
||||||
|
len: usize,
|
||||||
|
) -> i32 {
|
||||||
let p = Process::current().unwrap();
|
let p = Process::current().unwrap();
|
||||||
|
|
||||||
if user_dst > 0 {
|
if user_dst > 0 {
|
||||||
|
@ -13,7 +13,7 @@ pub mod printf;
|
|||||||
use crate::{
|
use crate::{
|
||||||
arch::virtual_memory::{either_copyin, either_copyout},
|
arch::virtual_memory::{either_copyin, either_copyout},
|
||||||
fs::file::{devsw, CONSOLE},
|
fs::file::{devsw, CONSOLE},
|
||||||
hardware::uart::Uart,
|
hardware::uart::BufferedUart,
|
||||||
proc::{
|
proc::{
|
||||||
process::{procdump, Process},
|
process::{procdump, Process},
|
||||||
scheduler::wakeup,
|
scheduler::wakeup,
|
||||||
@ -22,7 +22,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use core::ptr::addr_of_mut;
|
use core::ptr::addr_of_mut;
|
||||||
|
|
||||||
pub static UART0: &Uart = &crate::hardware::UARTS[0].1;
|
pub static UART0: &BufferedUart = &crate::hardware::UARTS[0].1;
|
||||||
|
|
||||||
pub const BACKSPACE: u8 = 0x00;
|
pub const BACKSPACE: u8 = 0x00;
|
||||||
pub const INPUT_BUF_SIZE: usize = 128;
|
pub const INPUT_BUF_SIZE: usize = 128;
|
||||||
@ -48,8 +48,7 @@ impl Console {
|
|||||||
}
|
}
|
||||||
impl core::fmt::Write for Console {
|
impl core::fmt::Write for Console {
|
||||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||||
UART0.write_slice(s.as_bytes());
|
UART0.writer().write_str(s)
|
||||||
core::fmt::Result::Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,11 +72,9 @@ const fn ctrl_x(x: u8) -> u8 {
|
|||||||
pub fn consputc(c: u8) {
|
pub fn consputc(c: u8) {
|
||||||
if c == BACKSPACE {
|
if c == BACKSPACE {
|
||||||
// If the user typed backspace, overwrite with a space.
|
// If the user typed backspace, overwrite with a space.
|
||||||
UART0.write_byte(0x08);
|
UART0.write_slice_buffered(b"\x08 \x08");
|
||||||
UART0.write_byte(b' ');
|
|
||||||
UART0.write_byte(0x08);
|
|
||||||
} else {
|
} else {
|
||||||
UART0.write_byte(c);
|
UART0.write_byte_buffered(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,16 +30,18 @@ pub(crate) use println;
|
|||||||
/// Does not use any locks.
|
/// Does not use any locks.
|
||||||
macro_rules! uprint {
|
macro_rules! uprint {
|
||||||
($($arg:tt)*) => {{
|
($($arg:tt)*) => {{
|
||||||
use $crate::hardware::uart::Uart;
|
// use $crate::hardware::uart::{BufferedUart, Uart, UartWriter};
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
|
|
||||||
// Do some casts to get a mutable reference.
|
// let mut uart: UartWriter = $crate::console::UART0.writer_unbuffered();
|
||||||
// Safe because Uart's core::fmt::Write implementation
|
|
||||||
// only uses the &mut reference immutably.
|
|
||||||
let uart: *const Uart = &$crate::hardware::UARTS[0].1 as *const Uart;
|
|
||||||
let uart: &mut Uart = unsafe { &mut *uart.cast_mut() };
|
|
||||||
|
|
||||||
let _ = core::write!(uart, $($arg)*);
|
// let uart: &BufferedUart = &$crate::console::UART0;
|
||||||
|
// let uart: &Uart = &**uart;
|
||||||
|
// let mut uart: UartWriter = uart.writer();
|
||||||
|
//
|
||||||
|
let _ = core::write!($crate::console::UART0.writer_unbuffered(), $($arg)*);
|
||||||
|
|
||||||
|
// let _ = core::write!(uart, $($arg)*);
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
pub(crate) use uprint;
|
pub(crate) use uprint;
|
||||||
|
@ -4,6 +4,6 @@ pub mod ramdisk;
|
|||||||
pub mod uart;
|
pub mod uart;
|
||||||
pub mod virtio_disk;
|
pub mod virtio_disk;
|
||||||
|
|
||||||
use uart::Uart;
|
use uart::BufferedUart;
|
||||||
|
|
||||||
pub static UARTS: [(usize, Uart); 1] = [(10, Uart::new(0x1000_0000))];
|
pub static UARTS: [(usize, BufferedUart); 1] = [(10, BufferedUart::new(0x1000_0000))];
|
||||||
|
@ -2,8 +2,11 @@
|
|||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::trap::InterruptBlocker, console::consoleintr, proc::scheduler::wakeup, queue::Queue,
|
arch::trap::InterruptBlocker,
|
||||||
sync::mutex::Mutex,
|
console::consoleintr,
|
||||||
|
proc::scheduler::wakeup,
|
||||||
|
queue::Queue,
|
||||||
|
sync::mutex::{Mutex, MutexGuard},
|
||||||
};
|
};
|
||||||
use core::ptr::addr_of;
|
use core::ptr::addr_of;
|
||||||
|
|
||||||
@ -59,14 +62,10 @@ impl Register {
|
|||||||
|
|
||||||
pub struct Uart {
|
pub struct Uart {
|
||||||
pub base_address: usize,
|
pub base_address: usize,
|
||||||
pub buffer: Mutex<Queue<u8>>,
|
|
||||||
}
|
}
|
||||||
impl Uart {
|
impl Uart {
|
||||||
pub const fn new(base_address: usize) -> Uart {
|
pub const fn new(base_address: usize) -> Uart {
|
||||||
Uart {
|
Uart { base_address }
|
||||||
base_address,
|
|
||||||
buffer: Mutex::new(Queue::new()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Initialize the UART.
|
/// Initialize the UART.
|
||||||
pub unsafe fn initialize(&self) {
|
pub unsafe fn initialize(&self) {
|
||||||
@ -86,14 +85,12 @@ impl Uart {
|
|||||||
// Enable transmit and receive interrupts.
|
// Enable transmit and receive interrupts.
|
||||||
Register::InterruptEnable.write(self.base_address, IER_TX_ENABLE | IER_RX_ENABLE);
|
Register::InterruptEnable.write(self.base_address, IER_TX_ENABLE | IER_RX_ENABLE);
|
||||||
}
|
}
|
||||||
|
/// Handle an interrupt from the hardware.
|
||||||
pub fn interrupt(&self) {
|
pub fn interrupt(&self) {
|
||||||
// Read and process incoming data.
|
// Read and process incoming data.
|
||||||
while let Some(b) = self.read_byte() {
|
while let Some(b) = self.read_byte() {
|
||||||
consoleintr(b);
|
consoleintr(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send buffered characters.
|
|
||||||
self.send_buffered_bytes();
|
|
||||||
}
|
}
|
||||||
/// Read one byte from the UART.
|
/// Read one byte from the UART.
|
||||||
pub fn read_byte(&self) -> Option<u8> {
|
pub fn read_byte(&self) -> Option<u8> {
|
||||||
@ -104,40 +101,81 @@ impl Uart {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Write a byte to the UART without interrupts.
|
pub fn writer(&self) -> UartWriter<'_> {
|
||||||
/// Used for kernel printing and character echoing.
|
UartWriter(self)
|
||||||
pub fn write_byte(&self, b: u8) {
|
}
|
||||||
|
pub fn can_write_byte(&self) -> bool {
|
||||||
|
Register::LineStatus.read(self.base_address) & LSR_TX_IDLE != 0
|
||||||
|
}
|
||||||
|
/// Attempt to write one byte to the UART.
|
||||||
|
/// Returns a bool representing whether the byte was written.
|
||||||
|
pub fn write_byte(&self, byte: u8) -> bool {
|
||||||
|
// Block interrupts to prevent TOCTOU manipulation.
|
||||||
let _ = InterruptBlocker::new();
|
let _ = InterruptBlocker::new();
|
||||||
|
if self.can_write_byte() {
|
||||||
if *crate::PANICKED.lock_spinning() {
|
Register::TransmitHolding.write(self.base_address, byte);
|
||||||
loop {
|
true
|
||||||
core::hint::spin_loop();
|
} else {
|
||||||
}
|
false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Wait for Transmit Holding Empty to be set in LSR.
|
pub fn write_byte_blocking(&self, byte: u8) {
|
||||||
while Register::LineStatus.read(self.base_address) & LSR_TX_IDLE == 0 {
|
while !self.write_byte(byte) {
|
||||||
core::hint::spin_loop();
|
core::hint::spin_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
Register::TransmitHolding.write(self.base_address, b);
|
|
||||||
}
|
}
|
||||||
pub fn write_slice(&self, bytes: &[u8]) {
|
pub fn write_slice_blocking(&self, bytes: &[u8]) {
|
||||||
for b in bytes {
|
for b in bytes {
|
||||||
self.write_byte(*b);
|
self.write_byte(*b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
impl From<BufferedUart> for Uart {
|
||||||
|
fn from(value: BufferedUart) -> Self {
|
||||||
|
value.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct UartWriter<'u>(&'u Uart);
|
||||||
|
impl<'u> core::fmt::Write for UartWriter<'u> {
|
||||||
|
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||||
|
self.0.write_slice_blocking(s.as_bytes());
|
||||||
|
core::fmt::Result::Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BufferedUart {
|
||||||
|
inner: Uart,
|
||||||
|
buffer: Mutex<Queue<u8>>,
|
||||||
|
}
|
||||||
|
impl BufferedUart {
|
||||||
|
pub const fn new(base_address: usize) -> BufferedUart {
|
||||||
|
BufferedUart {
|
||||||
|
inner: Uart::new(base_address),
|
||||||
|
buffer: Mutex::new(Queue::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn interrupt(&self) {
|
||||||
|
let _ = InterruptBlocker::new();
|
||||||
|
|
||||||
|
self.inner.interrupt();
|
||||||
|
|
||||||
|
// Send buffered characters.
|
||||||
|
let buf = self.buffer.lock_spinning();
|
||||||
|
self.send_buffered_bytes(buf);
|
||||||
|
}
|
||||||
|
pub fn writer(&self) -> BufferedUartWriter<'_> {
|
||||||
|
BufferedUartWriter(self)
|
||||||
|
}
|
||||||
|
pub fn writer_unbuffered(&self) -> UartWriter<'_> {
|
||||||
|
self.inner.writer()
|
||||||
|
}
|
||||||
/// Write a byte to the UART and buffer it.
|
/// Write a byte to the UART and buffer it.
|
||||||
/// Should not be used in interrupts.
|
/// Should not be used in interrupts.
|
||||||
pub fn write_byte_buffered(&self, b: u8) {
|
pub fn write_byte_buffered(&self, byte: u8) {
|
||||||
let mut buf = self.buffer.lock_spinning();
|
let mut buf = self.buffer.lock_spinning();
|
||||||
|
|
||||||
if *crate::PANICKED.lock_spinning() {
|
|
||||||
loop {
|
|
||||||
core::hint::spin_loop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sleep until there is space in the buffer.
|
// Sleep until there is space in the buffer.
|
||||||
while buf.space_remaining() == 0 {
|
while buf.space_remaining() == 0 {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -146,48 +184,69 @@ impl Uart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the byte onto the end of the queue.
|
// Add the byte onto the end of the queue.
|
||||||
buf.push_back(b).expect("space in the uart queue");
|
buf.push_back(byte).expect("space in the uart queue");
|
||||||
// Drop buf so that send_buffered_bytes() can lock it again.
|
// Drop buf so that send_buffered_bytes() can lock it again.
|
||||||
core::mem::drop(buf);
|
self.send_buffered_bytes(buf);
|
||||||
self.send_buffered_bytes();
|
|
||||||
}
|
}
|
||||||
|
/// Write a slice to the UART and buffer it.
|
||||||
|
/// Should not be used in interrupts.
|
||||||
pub fn write_slice_buffered(&self, bytes: &[u8]) {
|
pub fn write_slice_buffered(&self, bytes: &[u8]) {
|
||||||
for b in bytes {
|
for b in bytes {
|
||||||
self.write_byte_buffered(*b);
|
self.write_byte_buffered(*b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// If the UART is idle, and a character is
|
/// If the UART is idle and a character is
|
||||||
/// waiting in the transmit buffer, send it.
|
/// waiting in the transmit buffer, send it.
|
||||||
/// self.lock should be held.
|
/// Returns how many bytes were sent.
|
||||||
fn send_buffered_bytes(&self) {
|
fn send_buffered_bytes(&self, mut buf: MutexGuard<'_, Queue<u8>>) -> usize {
|
||||||
let mut buf = self.buffer.lock_spinning();
|
let mut i = 0;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if Register::LineStatus.read(self.base_address) & LSR_TX_IDLE == 0 {
|
if !self.inner.can_write_byte() {
|
||||||
// The UART transmit holding register is full,
|
// The UART transmit holding register is full,
|
||||||
// so we cannot give it another byte.
|
// so we cannot give it another byte.
|
||||||
// It will interrupt when it's ready for a new byte.
|
// It will interrupt when it's ready for a new byte.
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pop a byte from the front of the queue.
|
// Pop a byte from the front of the queue and send it.
|
||||||
let Some(b) = buf.pop_front() else {
|
match buf.pop_front() {
|
||||||
|
Some(b) => self.inner.write_byte(b),
|
||||||
// The buffer is empty, we're finished sending bytes.
|
// The buffer is empty, we're finished sending bytes.
|
||||||
return;
|
None => return 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Maybe uartputc() is waiting for space in the buffer.
|
i += 1;
|
||||||
|
|
||||||
|
// Check if uartputc() is waiting for space in the buffer.
|
||||||
unsafe {
|
unsafe {
|
||||||
wakeup(addr_of!(*self).cast_mut().cast());
|
wakeup(addr_of!(*self).cast_mut().cast());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Register::TransmitHolding.write(self.base_address, b);
|
i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl core::ops::Deref for BufferedUart {
|
||||||
|
type Target = Uart;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<Uart> for BufferedUart {
|
||||||
|
fn from(value: Uart) -> Self {
|
||||||
|
BufferedUart {
|
||||||
|
inner: value,
|
||||||
|
buffer: Mutex::new(Queue::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl core::fmt::Write for Uart {
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct BufferedUartWriter<'u>(&'u BufferedUart);
|
||||||
|
impl<'u> core::fmt::Write for BufferedUartWriter<'u> {
|
||||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||||
self.write_slice(s.as_bytes());
|
self.0.write_slice_buffered(s.as_bytes());
|
||||||
core::fmt::Result::Ok(())
|
core::fmt::Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#![allow(clippy::missing_safety_doc)]
|
#![allow(clippy::missing_safety_doc)]
|
||||||
#![feature(negative_impls)]
|
#![feature(negative_impls)]
|
||||||
#![feature(panic_info_message)]
|
#![feature(panic_info_message)]
|
||||||
|
#![feature(str_from_raw_parts)]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate core;
|
extern crate core;
|
||||||
@ -21,9 +22,12 @@ mod sync;
|
|||||||
mod syscall;
|
mod syscall;
|
||||||
|
|
||||||
use crate::{proc::cpu::Cpu, sync::mutex::Mutex};
|
use crate::{proc::cpu::Cpu, sync::mutex::Mutex};
|
||||||
use core::ffi::{c_char, CStr};
|
use core::{
|
||||||
|
ffi::{c_char, CStr},
|
||||||
|
ptr::addr_of,
|
||||||
|
};
|
||||||
|
|
||||||
pub(crate) use crate::console::printf::{print, println, uprintln};
|
pub(crate) use crate::console::printf::{print, println, uprint, uprintln};
|
||||||
|
|
||||||
pub static mut STARTED: bool = false;
|
pub static mut STARTED: bool = false;
|
||||||
pub static PANICKED: Mutex<bool> = Mutex::new(false);
|
pub static PANICKED: Mutex<bool> = Mutex::new(false);
|
||||||
@ -79,34 +83,33 @@ pub unsafe fn main() -> ! {
|
|||||||
arch::trap::inithart();
|
arch::trap::inithart();
|
||||||
arch::interrupt::inithart();
|
arch::interrupt::inithart();
|
||||||
}
|
}
|
||||||
|
|
||||||
proc::scheduler::scheduler();
|
proc::scheduler::scheduler();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic_wrapper(panic_info: &core::panic::PanicInfo) -> ! {
|
fn panic_wrapper(panic_info: &core::panic::PanicInfo) -> ! {
|
||||||
if let Some(location) = panic_info.location() {
|
if let Some(location) = panic_info.location() {
|
||||||
print!("kernel panic ({}): ", location.file());
|
uprint!("kernel panic ({}): ", location.file());
|
||||||
} else {
|
} else {
|
||||||
print!("kernel panic: ");
|
uprint!("kernel panic: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(s) = panic_info.message() {
|
if let Some(s) = panic_info.message() {
|
||||||
println!("{}", s);
|
uprintln!("{}", s);
|
||||||
} else if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
|
} else if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
|
||||||
println!("{}", s);
|
uprintln!("{}", s);
|
||||||
} else if let Some(s) = panic_info.payload().downcast_ref::<&CStr>() {
|
} else if let Some(s) = panic_info.payload().downcast_ref::<&CStr>() {
|
||||||
println!("{:?}", s);
|
uprintln!("{:?}", s);
|
||||||
} else {
|
} else {
|
||||||
println!("could not recover error message");
|
uprintln!("could not recover error message");
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("███████╗██╗ ██╗ ██████╗██╗ ██╗██╗██╗");
|
uprintln!("███████╗██╗ ██╗ ██████╗██╗ ██╗██╗██╗");
|
||||||
println!("██╔════╝██║ ██║██╔════╝██║ ██╔╝██║██║");
|
uprintln!("██╔════╝██║ ██║██╔════╝██║ ██╔╝██║██║");
|
||||||
println!("█████╗ ██║ ██║██║ █████╔╝ ██║██║");
|
uprintln!("█████╗ ██║ ██║██║ █████╔╝ ██║██║");
|
||||||
println!("██╔══╝ ██║ ██║██║ ██╔═██╗ ╚═╝╚═╝");
|
uprintln!("██╔══╝ ██║ ██║██║ ██╔═██╗ ╚═╝╚═╝");
|
||||||
println!("██║ ╚██████╔╝╚██████╗██║ ██╗██╗██╗");
|
uprintln!("██║ ╚██████╔╝╚██████╗██║ ██╗██╗██╗");
|
||||||
println!("╚═╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝╚═╝╚═╝");
|
uprintln!("╚═╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝╚═╝╚═╝");
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
*crate::PANICKED.lock_spinning() = true;
|
*crate::PANICKED.lock_spinning() = true;
|
||||||
@ -120,8 +123,17 @@ fn panic_wrapper(panic_info: &core::panic::PanicInfo) -> ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn panic(_: *const c_char) -> ! {
|
pub unsafe extern "C" fn panic(msg: *const c_char) -> ! {
|
||||||
panic!("panic from c");
|
let mut message = [b' '; 32];
|
||||||
// let s = CStr::from_ptr(s).to_str().unwrap_or("panic from c");
|
let mut i = 0;
|
||||||
// panic!("{:?}", CStr::from_ptr(s));
|
loop {
|
||||||
|
match *msg.add(i) {
|
||||||
|
0 => break,
|
||||||
|
c => message[i] = c as u8,
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
let message = core::str::from_raw_parts(addr_of!(message[0]), i);
|
||||||
|
|
||||||
|
panic!("panic from c: {}", message);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ pub mod kalloc;
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn memset(dst: *mut u8, data: u8, max_bytes: usize) -> *mut u8 {
|
pub unsafe extern "C" fn memset(dst: *mut u8, data: u8, max_bytes: usize) -> *mut u8 {
|
||||||
for i in 0..max_bytes {
|
for i in 0..max_bytes {
|
||||||
*dst.add(i as usize) = data as u8;
|
*dst.add(i) = data;
|
||||||
}
|
}
|
||||||
dst
|
dst
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ use super::{
|
|||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
arch,
|
arch,
|
||||||
|
console::printf::println,
|
||||||
sync::spinlock::{Spinlock, SpinlockGuard},
|
sync::spinlock::{Spinlock, SpinlockGuard},
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
@ -34,6 +35,8 @@ pub unsafe fn r#yield() {
|
|||||||
// - eventually that process transfers control
|
// - eventually that process transfers control
|
||||||
// via swtch back to the scheduler.
|
// via swtch back to the scheduler.
|
||||||
pub unsafe fn scheduler() -> ! {
|
pub unsafe fn scheduler() -> ! {
|
||||||
|
println!("hart {} starting scheduler", Cpu::current_id());
|
||||||
|
|
||||||
let cpu = Cpu::current();
|
let cpu = Cpu::current();
|
||||||
cpu.proc = null_mut();
|
cpu.proc = null_mut();
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use core::{ffi::c_char, option::Option};
|
use core::ffi::c_char;
|
||||||
|
|
||||||
pub(crate) unsafe fn strlen_checked(s: *const c_char, max_chars: usize) -> Option<i32> {
|
pub(crate) unsafe fn strlen_checked(s: *const c_char, max_chars: usize) -> Option<i32> {
|
||||||
for len in 0..max_chars {
|
for len in 0..max_chars {
|
||||||
|
@ -5,7 +5,6 @@ use crate::proc::{
|
|||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
ops::Drop,
|
|
||||||
ptr::{addr_of, null_mut},
|
ptr::{addr_of, null_mut},
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
@ -4,8 +4,7 @@ use super::{
|
|||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
convert::{AsMut, AsRef},
|
ops::{Deref, DerefMut},
|
||||||
ops::{Deref, DerefMut, Drop},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Mutex<T> {
|
pub struct Mutex<T> {
|
||||||
|
8
programs/clear.c
Normal file
8
programs/clear.c
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include "kernel/types.h"
|
||||||
|
#include "kernel/stat.h"
|
||||||
|
#include "user/user.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
write(1, "\033[2J\033[H", 7);
|
||||||
|
exit(0);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user