rename sleep to sleep_lock
This commit is contained in:
parent
38e44e020b
commit
d06d271c9e
@ -1,10 +1,10 @@
|
|||||||
//! Buffer cache.
|
//! Buffer cache.
|
||||||
//!
|
//!
|
||||||
//! The buffer cache is a linked list of buf strctures holding
|
//! The buffer cache is a linked list of buf strctures holding
|
||||||
//! cached copies of disk block contents. Caching disk blocks
|
//! cached copies of disk block contents. Caching disk blocks
|
||||||
//! in memory reduces the number of disk reads and also provides
|
//! in memory reduces the number of disk reads and also provides
|
||||||
//! a synchronization point for disk blocks used by multiple processes.
|
//! a synchronization point for disk blocks used by multiple processes.
|
||||||
//!
|
//!
|
||||||
//! Interface:
|
//! Interface:
|
||||||
//! - To get a buffer for a particular disk block, call bread.
|
//! - To get a buffer for a particular disk block, call bread.
|
||||||
//! - After changing buffer data, call bwrite to write it to disk.
|
//! - After changing buffer data, call bwrite to write it to disk.
|
||||||
@ -13,28 +13,20 @@
|
|||||||
//! - Only one process at a time can use a buffer,
|
//! - Only one process at a time can use a buffer,
|
||||||
//! so do not keep them longer than necessary.
|
//! so do not keep them longer than necessary.
|
||||||
|
|
||||||
use crate::{
|
use crate::{buf::Buffer, param::NBUF, sync::spinlock::Spinlock};
|
||||||
sync::sleeplock::{holdingsleep, acquiresleep, releasesleep},
|
|
||||||
sync::spinlock::Spinlock,
|
|
||||||
buf::Buffer,
|
|
||||||
param::NBUF,
|
|
||||||
virtio_disk::virtio_disk_rw,
|
|
||||||
};
|
|
||||||
use core::ptr::addr_of_mut;
|
|
||||||
|
|
||||||
pub struct BufferCache {
|
pub struct BufferCache {
|
||||||
pub buffers: [Buffer; NBUF],
|
pub buffers: [Buffer; NBUF],
|
||||||
}
|
}
|
||||||
impl BufferCache {
|
impl BufferCache {
|
||||||
/// Look through the buffer cache for block on device dev.
|
/// Look through the buffer cache for block on device dev.
|
||||||
///
|
///
|
||||||
/// If not found, allocate a buffer.
|
/// If not found, allocate a buffer.
|
||||||
/// In either case, return locked buffer.
|
/// In either case, return locked buffer.
|
||||||
fn get(&mut self, dev: u32, blockno: u32) {
|
fn get(&mut self, dev: u32, blockno: u32) {
|
||||||
for buf in &mut self.buffers {
|
for buf in &mut self.buffers {
|
||||||
if buf.dev == dev && buf.blockno == blockno {
|
if buf.dev == dev && buf.blockno == blockno {
|
||||||
buf.refcnt += 1;
|
buf.refcnt += 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,7 +56,7 @@ extern "C" {
|
|||||||
// pub unsafe extern "C" fn bget(dev: u32, blockno: u32) -> *mut Buffer {
|
// pub unsafe extern "C" fn bget(dev: u32, blockno: u32) -> *mut Buffer {
|
||||||
// let mut b: *mut Buffer;
|
// let mut b: *mut Buffer;
|
||||||
// let _guard = bcache.lock.lock();
|
// let _guard = bcache.lock.lock();
|
||||||
//
|
//
|
||||||
// // Is the block already cached?
|
// // Is the block already cached?
|
||||||
// b = bcache.head.next;
|
// b = bcache.head.next;
|
||||||
// while b != addr_of_mut!(bcache.head) {
|
// while b != addr_of_mut!(bcache.head) {
|
||||||
@ -77,7 +69,7 @@ extern "C" {
|
|||||||
// b = (*b).next;
|
// b = (*b).next;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// // Not cached.
|
// // Not cached.
|
||||||
// // Recycle the least recently used unused buffer.
|
// // Recycle the least recently used unused buffer.
|
||||||
// b = bcache.head.prev;
|
// b = bcache.head.prev;
|
||||||
@ -92,7 +84,7 @@ extern "C" {
|
|||||||
// return b;
|
// return b;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// panic!("bget: no buffers");
|
// panic!("bget: no buffers");
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@ -100,22 +92,22 @@ extern "C" {
|
|||||||
// #[no_mangle]
|
// #[no_mangle]
|
||||||
// pub unsafe extern "C" fn bread(dev: u32, blockno: u32) -> *mut Buffer {
|
// pub unsafe extern "C" fn bread(dev: u32, blockno: u32) -> *mut Buffer {
|
||||||
// let b = bget(dev, blockno);
|
// let b = bget(dev, blockno);
|
||||||
//
|
//
|
||||||
// if (*b).valid == 0 {
|
// if (*b).valid == 0 {
|
||||||
// virtio_disk_rw(b, 0);
|
// virtio_disk_rw(b, 0);
|
||||||
// (*b).valid = 1;
|
// (*b).valid = 1;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// b
|
// b
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// #[no_mangle]
|
// #[no_mangle]
|
||||||
// pub unsafe extern "C" fn bwrite(b: *mut Buffer) {
|
// pub unsafe extern "C" fn bwrite(b: *mut Buffer) {
|
||||||
// if holdingsleep(addr_of_mut!((*b).lock)) == 0 {
|
// if holdingsleep(addr_of_mut!((*b).lock)) == 0 {
|
||||||
// // if !(*b).lock.held_by_current_proc() {
|
// // if !(*b).lock.held_by_current_proc() {
|
||||||
// panic!("bwrite");
|
// panic!("bwrite");
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// virtio_disk_rw(b, 1);
|
// virtio_disk_rw(b, 1);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@ -125,11 +117,11 @@ extern "C" {
|
|||||||
// (*b).refcnt += 1;
|
// (*b).refcnt += 1;
|
||||||
// // bcache.lock.unlock();
|
// // bcache.lock.unlock();
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// #[no_mangle]
|
// #[no_mangle]
|
||||||
// pub unsafe extern "C" fn bunpin(b: *mut Buffer) {
|
// pub unsafe extern "C" fn bunpin(b: *mut Buffer) {
|
||||||
// let _guard = bcache.lock.lock();
|
// let _guard = bcache.lock.lock();
|
||||||
// (*b).refcnt -= 1;
|
// (*b).refcnt -= 1;
|
||||||
// // bcache.lock.unlock();
|
// // bcache.lock.unlock();
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
@ -108,6 +108,8 @@ pub unsafe extern "C" fn consoleread(user_dst: i32, mut dst: u64, mut n: i32) ->
|
|||||||
// cons.lock.unlock();
|
// cons.lock.unlock();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
// let channel = addr_of_mut!(console.read_index).cast();
|
||||||
|
// console.sleep(channel);
|
||||||
sleep_mutex(addr_of_mut!(console.read_index).cast(), &mut console);
|
sleep_mutex(addr_of_mut!(console.read_index).cast(), &mut console);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
kernel/rustkernel/src/pipe.rs
Normal file
18
kernel/rustkernel/src/pipe.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use crate::sync::spinlock::Spinlock;
|
||||||
|
use core::ffi::c_char;
|
||||||
|
|
||||||
|
pub const PIPESIZE: usize = 512usize;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Pipe {
|
||||||
|
lock: Spinlock,
|
||||||
|
data: [c_char; PIPESIZE],
|
||||||
|
/// Number of bytes read.
|
||||||
|
nread: u32,
|
||||||
|
/// Number of bytes written.
|
||||||
|
nwrite: u32,
|
||||||
|
/// Read fd is still open.
|
||||||
|
readopen: i32,
|
||||||
|
/// Write fd is still open.
|
||||||
|
writeopen: i32,
|
||||||
|
}
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
kalloc::kfree,
|
kalloc::kfree,
|
||||||
param::*,
|
param::*,
|
||||||
riscv::{self, Pagetable, PTE_W},
|
riscv::{self, Pagetable, PTE_W},
|
||||||
sync::spinlock::{pop_off, push_off, Spinlock},
|
sync::spinlock::Spinlock,
|
||||||
sync::spinmutex::SpinMutexGuard,
|
sync::spinmutex::SpinMutexGuard,
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
@ -241,8 +241,7 @@ pub unsafe extern "C" fn mycpu() -> *mut Cpu {
|
|||||||
pub unsafe extern "C" fn myproc() -> *mut Proc {
|
pub unsafe extern "C" fn myproc() -> *mut Proc {
|
||||||
let _ = crate::trap::InterruptBlocker::new();
|
let _ = crate::trap::InterruptBlocker::new();
|
||||||
let c = mycpu();
|
let c = mycpu();
|
||||||
let p = (*c).proc;
|
(*c).proc
|
||||||
p
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -408,7 +407,7 @@ pub unsafe extern "C" fn sched() {
|
|||||||
/// Atomically release lock and sleep on chan.
|
/// Atomically release lock and sleep on chan.
|
||||||
/// Reacquires lock when awakened.
|
/// Reacquires lock when awakened.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sleep(chan: *mut c_void, lock: *mut Spinlock) {
|
pub unsafe extern "C" fn sleep_lock(chan: *mut c_void, lock: *mut Spinlock) {
|
||||||
let p = myproc();
|
let p = myproc();
|
||||||
|
|
||||||
// Must acquire p->lock in order to
|
// Must acquire p->lock in order to
|
||||||
@ -455,6 +454,20 @@ pub unsafe fn sleep_mutex<T>(chan: *mut c_void, mutex: &mut SpinMutexGuard<T>) {
|
|||||||
core::mem::forget(guard);
|
core::mem::forget(guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pub unsafe fn sleep(chan: *mut c_void) {
|
||||||
|
// let p = myproc();
|
||||||
|
// let _guard = (*p).lock.lock();
|
||||||
|
//
|
||||||
|
// // Go to sleep.
|
||||||
|
// (*p).chan = chan;
|
||||||
|
// (*p).state = ProcState::Sleeping;
|
||||||
|
//
|
||||||
|
// sched();
|
||||||
|
//
|
||||||
|
// // Clean up.
|
||||||
|
// (*p).chan = null_mut();
|
||||||
|
// }
|
||||||
|
|
||||||
/// Kill the process with the given pid.
|
/// Kill the process with the given pid.
|
||||||
/// The victim won't exit until it tries to return
|
/// The victim won't exit until it tries to return
|
||||||
/// to user space (see usertrap() in trap.c).
|
/// to user space (see usertrap() in trap.c).
|
||||||
@ -486,6 +499,5 @@ pub unsafe extern "C" fn setkilled(p: *mut Proc) {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn killed(p: *mut Proc) -> i32 {
|
pub unsafe extern "C" fn killed(p: *mut Proc) -> i32 {
|
||||||
let _guard = (*p).lock.lock();
|
let _guard = (*p).lock.lock();
|
||||||
let k = (*p).killed;
|
(*p).killed
|
||||||
k
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
pub(crate) mod mutex;
|
||||||
pub mod sleeplock;
|
pub mod sleeplock;
|
||||||
pub mod spinlock;
|
pub mod spinlock;
|
||||||
pub mod spinmutex;
|
pub mod spinmutex;
|
||||||
|
85
kernel/rustkernel/src/sync/mutex.rs
Normal file
85
kernel/rustkernel/src/sync/mutex.rs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// use core::{
|
||||||
|
// cell::UnsafeCell,
|
||||||
|
// ops::{Deref, DerefMut, Drop},
|
||||||
|
// sync::atomic::{AtomicBool, Ordering},
|
||||||
|
// ffi::c_void,
|
||||||
|
// ptr::addr_of,
|
||||||
|
// };
|
||||||
|
// use crate::proc::{sleep, wakeup, sched, myproc, ProcState};
|
||||||
|
//
|
||||||
|
// pub struct Mutex<T> {
|
||||||
|
// locked: AtomicBool,
|
||||||
|
// inner: UnsafeCell<T>,
|
||||||
|
// }
|
||||||
|
// impl<T> Mutex<T> {
|
||||||
|
// pub const fn new(value: T) -> Mutex<T> {
|
||||||
|
// Mutex {
|
||||||
|
// locked: AtomicBool::new(false),
|
||||||
|
// inner: UnsafeCell::new(value),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// pub unsafe fn get_inner(&self) -> *mut T {
|
||||||
|
// self.inner.get()
|
||||||
|
// }
|
||||||
|
// /// Spin until the mutex is unlocked, acquiring afterwards.
|
||||||
|
// pub fn spin_lock(&self) -> MutexGuard<'_, T> {
|
||||||
|
// while self.locked.swap(true, Ordering::Acquire) {
|
||||||
|
// core::hint::spin_loop();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// MutexGuard { mutex: self }
|
||||||
|
// }
|
||||||
|
// /// Sleep until the mutex is unlocked, acquiring afterwards.
|
||||||
|
// pub fn sleep_lock(&self) -> MutexGuard<'_, T> {
|
||||||
|
// while self.locked.swap(true, Ordering::Acquire) {
|
||||||
|
// unsafe {
|
||||||
|
// sleep(addr_of!(*self).cast_mut().cast());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// MutexGuard { mutex: self }
|
||||||
|
// }
|
||||||
|
// pub unsafe fn unlock(&self) {
|
||||||
|
// self.locked.store(false, Ordering::Release);
|
||||||
|
// wakeup(addr_of!(*self).cast_mut().cast());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// unsafe impl<T> Sync for Mutex<T> where T: Send {}
|
||||||
|
//
|
||||||
|
// pub struct MutexGuard<'m, T> {
|
||||||
|
// pub mutex: &'m Mutex<T>,
|
||||||
|
// }
|
||||||
|
// impl<'m, T> MutexGuard<'m, T> {
|
||||||
|
// pub unsafe fn sleep(&mut self, channel: *mut c_void){
|
||||||
|
// let p = myproc();
|
||||||
|
// let _guard = (*p).lock.lock();
|
||||||
|
// self.mutex.unlock();
|
||||||
|
//
|
||||||
|
// // Go to sleep.
|
||||||
|
// (*p).chan = channel;
|
||||||
|
// (*p).state = ProcState::Sleeping;
|
||||||
|
// sched();
|
||||||
|
//
|
||||||
|
// // Clean up.
|
||||||
|
// let guard = self.mutex.spin_lock();
|
||||||
|
// core::mem::forget(guard);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl<'m, T> Deref for MutexGuard<'m, T> {
|
||||||
|
// type Target = T;
|
||||||
|
//
|
||||||
|
// fn deref(&self) -> &Self::Target {
|
||||||
|
// unsafe { &*self.mutex.get_inner() }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl<'m, T> DerefMut for MutexGuard<'m, T> {
|
||||||
|
// fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
// unsafe { &mut *self.mutex.get_inner() }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl<'m, T> Drop for MutexGuard<'m, T> {
|
||||||
|
// fn drop(&mut self) {
|
||||||
|
// unsafe { self.mutex.unlock() }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
@ -1,8 +1,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
proc::{myproc, sleep, wakeup},
|
proc::{myproc, sleep_lock, wakeup},
|
||||||
sync::spinlock::{self, Spinlock},
|
sync::spinlock::Spinlock,
|
||||||
|
};
|
||||||
|
use core::{
|
||||||
|
ffi::c_char,
|
||||||
|
ptr::{addr_of, null_mut},
|
||||||
};
|
};
|
||||||
use core::{ffi::c_char, ptr::{addr_of, null_mut}};
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Sleeplock {
|
pub struct Sleeplock {
|
||||||
@ -31,12 +34,16 @@ impl Sleeplock {
|
|||||||
}
|
}
|
||||||
/// Check whether this proc is holding the lock.
|
/// Check whether this proc is holding the lock.
|
||||||
pub fn held_by_current_proc(&self) -> bool {
|
pub fn held_by_current_proc(&self) -> bool {
|
||||||
self.locked > 0 && self.pid == unsafe { (*myproc()).pid }
|
self.locked > 0 && self.pid == unsafe { (*myproc()).pid }
|
||||||
}
|
}
|
||||||
|
#[allow(clippy::while_immutable_condition)]
|
||||||
pub unsafe fn lock_unguarded(&self) {
|
pub unsafe fn lock_unguarded(&self) {
|
||||||
let _guard = self.inner.lock();
|
let _guard = self.inner.lock();
|
||||||
while self.locked > 0 {
|
while self.locked > 0 {
|
||||||
sleep(addr_of!(*self).cast_mut().cast(), addr_of!(self.inner).cast_mut().cast());
|
sleep_lock(
|
||||||
|
addr_of!(*self).cast_mut().cast(),
|
||||||
|
addr_of!(self.inner).cast_mut().cast(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let this: &mut Self = &mut *addr_of!(*self).cast_mut();
|
let this: &mut Self = &mut *addr_of!(*self).cast_mut();
|
||||||
this.locked = 1;
|
this.locked = 1;
|
||||||
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
ffi::c_char,
|
ffi::c_char,
|
||||||
ptr::{null_mut, addr_of},
|
ptr::{addr_of, null_mut},
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
proc::{exit, fork, growproc, kill, killed, myproc, sleep, wait},
|
proc::{exit, fork, growproc, kill, killed, myproc, sleep_lock, wait},
|
||||||
syscall::{argaddr, argint},
|
syscall::{argaddr, argint},
|
||||||
};
|
};
|
||||||
use core::ptr::addr_of_mut;
|
use core::ptr::addr_of_mut;
|
||||||
@ -53,7 +53,7 @@ pub unsafe extern "C" fn sys_sleep() -> u64 {
|
|||||||
crate::trap::tickslock.unlock();
|
crate::trap::tickslock.unlock();
|
||||||
return -1i64 as u64;
|
return -1i64 as u64;
|
||||||
}
|
}
|
||||||
sleep(
|
sleep_lock(
|
||||||
addr_of_mut!(crate::trap::ticks).cast(),
|
addr_of_mut!(crate::trap::ticks).cast(),
|
||||||
addr_of_mut!(crate::trap::tickslock).cast(),
|
addr_of_mut!(crate::trap::tickslock).cast(),
|
||||||
)
|
)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
console::consoleintr,
|
console::consoleintr,
|
||||||
proc::{sleep, sleep_mutex, wakeup},
|
proc::{sleep_lock, wakeup},
|
||||||
riscv::memlayout::UART0,
|
riscv::memlayout::UART0,
|
||||||
sync::spinlock::Spinlock,
|
sync::spinlock::Spinlock,
|
||||||
sync::spinmutex::SpinMutex,
|
sync::spinmutex::SpinMutex,
|
||||||
@ -171,7 +171,7 @@ pub(crate) unsafe fn uartputc(c: u8) {
|
|||||||
while uart_tx_w == uart_tx_r + UART_TX_BUF_SIZE {
|
while uart_tx_w == uart_tx_r + UART_TX_BUF_SIZE {
|
||||||
// Buffer is full.
|
// Buffer is full.
|
||||||
// Wait for uartstart() to open up space in the buffer.
|
// Wait for uartstart() to open up space in the buffer.
|
||||||
sleep(
|
sleep_lock(
|
||||||
addr_of_mut!(uart_tx_r).cast(),
|
addr_of_mut!(uart_tx_r).cast(),
|
||||||
addr_of_mut!(uart_tx_lock).cast(),
|
addr_of_mut!(uart_tx_lock).cast(),
|
||||||
);
|
);
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
//! Virtio device driver.
|
//! Virtio device driver.
|
||||||
//!
|
//!
|
||||||
//! For both the MMIO interface, and virtio descriptors.
|
//! For both the MMIO interface, and virtio descriptors.
|
||||||
//! Only tested with qemu.
|
//! Only tested with qemu.
|
||||||
//!
|
//!
|
||||||
//! The virtio spec: https://docs.oasis-open.org/virtio/virtio/v1.1/virtio-v1.1.pdf
|
//! The virtio spec: https://docs.oasis-open.org/virtio/virtio/v1.1/virtio-v1.1.pdf
|
||||||
//! qemu ... -drive file=fs.img,if=none,format=raw,id=x0 -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
|
//! qemu ... -drive file=fs.img,if=none,format=raw,id=x0 -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
|
||||||
|
|
||||||
use crate::{sync::spinlock::Spinlock, buf::Buffer};
|
use crate::{buf::Buffer, sync::spinlock::Spinlock};
|
||||||
use core::ffi::c_char;
|
use core::ffi::c_char;
|
||||||
|
|
||||||
// Virtio MMIO control registers, mapped starting at 0x10001000
|
// Virtio MMIO control registers, mapped starting at 0x10001000
|
||||||
@ -17,61 +17,61 @@ pub const VIRTIO_MMIO_MAGIC_VALUE: u64 = 0x000u64;
|
|||||||
/// Version - should be 2.
|
/// Version - should be 2.
|
||||||
pub const VIRTIO_MMIO_VERSION: u64 = 0x004u64;
|
pub const VIRTIO_MMIO_VERSION: u64 = 0x004u64;
|
||||||
/// Device type.
|
/// Device type.
|
||||||
///
|
///
|
||||||
/// 1: Network
|
/// 1: Network
|
||||||
/// 2: Disk
|
/// 2: Disk
|
||||||
pub const VIRTIO_MMIO_DEVICE_ID: u64 = 0x008u64;
|
pub const VIRTIO_MMIO_DEVICE_ID: u64 = 0x008u64;
|
||||||
/// 0x554d4551
|
/// 0x554d4551
|
||||||
pub const VIRTIO_MMIO_VENDOR_ID: u64 = 0x00cu64;
|
pub const VIRTIO_MMIO_VENDOR_ID: u64 = 0x00cu64;
|
||||||
pub const VIRTIO_MMIO_DEVICE_FEATURES: u64 = 0x010u64;
|
pub const VIRTIO_MMIO_DEVICE_FEATURES: u64 = 0x010u64;
|
||||||
pub const VIRTIO_MMIO_DRIVER_FEATURES: u64 = 0x020u64;
|
pub const VIRTIO_MMIO_DRIVER_FEATURES: u64 = 0x020u64;
|
||||||
/// Select queue, write-only.
|
/// Select queue, write-only.
|
||||||
pub const VIRTIO_MMIO_QUEUE_SEL: u64 = 0x030u64;
|
pub const VIRTIO_MMIO_QUEUE_SEL: u64 = 0x030u64;
|
||||||
/// Max size of current queue, read-only.
|
/// Max size of current queue, read-only.
|
||||||
pub const VIRTIO_MMIO_QUEUE_NUM_MAX: u64 = 0x034u64;
|
pub const VIRTIO_MMIO_QUEUE_NUM_MAX: u64 = 0x034u64;
|
||||||
/// Size of current queue, write-only.
|
/// Size of current queue, write-only.
|
||||||
pub const VIRTIO_MMIO_QUEUE_NUM: u64 = 0x038u64;
|
pub const VIRTIO_MMIO_QUEUE_NUM: u64 = 0x038u64;
|
||||||
/// Ready bit.
|
/// Ready bit.
|
||||||
pub const VIRTIO_MMIO_QUEUE_READY: u64 = 0x044u64;
|
pub const VIRTIO_MMIO_QUEUE_READY: u64 = 0x044u64;
|
||||||
/// Write-only.
|
/// Write-only.
|
||||||
pub const VIRTIO_MMIO_QUEUE_NOTIFY: u64 = 0x050u64;
|
pub const VIRTIO_MMIO_QUEUE_NOTIFY: u64 = 0x050u64;
|
||||||
/// Read-only.
|
/// Read-only.
|
||||||
pub const VIRTIO_MMIO_INTERRUPT_STATUS: u64 = 0x060u64;
|
pub const VIRTIO_MMIO_INTERRUPT_STATUS: u64 = 0x060u64;
|
||||||
/// Write-only.
|
/// Write-only.
|
||||||
pub const VIRTIO_MMIO_INTERRUPT_ACK: u64 = 0x064u64;
|
pub const VIRTIO_MMIO_INTERRUPT_ACK: u64 = 0x064u64;
|
||||||
/// Read/write.
|
/// Read/write.
|
||||||
pub const VIRTIO_MMIO_STATUS: u64 = 0x070u64;
|
pub const VIRTIO_MMIO_STATUS: u64 = 0x070u64;
|
||||||
/// Physical address for descriptor table, write-only.
|
/// Physical address for descriptor table, write-only.
|
||||||
pub const VIRTIO_MMIO_QUEUE_DESC_LOW: u64 = 0x080u64;
|
pub const VIRTIO_MMIO_QUEUE_DESC_LOW: u64 = 0x080u64;
|
||||||
pub const VIRTIO_MMIO_QUEUE_DESC_HIGH: u64 = 0x084u64;
|
pub const VIRTIO_MMIO_QUEUE_DESC_HIGH: u64 = 0x084u64;
|
||||||
/// Physical address for available ring, write-only.
|
/// Physical address for available ring, write-only.
|
||||||
pub const VIRTIO_MMIO_DRIVER_DESC_LOW: u64 = 0x090u64;
|
pub const VIRTIO_MMIO_DRIVER_DESC_LOW: u64 = 0x090u64;
|
||||||
pub const VIRTIO_MMIO_DRIVER_DESC_HIGH: u64 = 0x094u64;
|
pub const VIRTIO_MMIO_DRIVER_DESC_HIGH: u64 = 0x094u64;
|
||||||
/// Physical address for used ring, write-only.
|
/// Physical address for used ring, write-only.
|
||||||
pub const VIRTIO_MMIO_DEVICE_DESC_LOW: u64 = 0x0a0u64;
|
pub const VIRTIO_MMIO_DEVICE_DESC_LOW: u64 = 0x0a0u64;
|
||||||
pub const VIRTIO_MMIO_DEVICE_DESC_HIGH: u64 = 0x0a4u64;
|
pub const VIRTIO_MMIO_DEVICE_DESC_HIGH: u64 = 0x0a4u64;
|
||||||
|
|
||||||
// Status register bits, from qemu virtio_config.h.
|
// Status register bits, from qemu virtio_config.h.
|
||||||
pub const VIRTIO_CONFIG_S_ACKNOWLEDGE: u8 = 0x01u8;
|
pub const VIRTIO_CONFIG_S_ACKNOWLEDGE: u8 = 0x01u8;
|
||||||
pub const VIRTIO_CONFIG_S_DRIVER: u8 = 0x02u8;
|
pub const VIRTIO_CONFIG_S_DRIVER: u8 = 0x02u8;
|
||||||
pub const VIRTIO_CONFIG_S_DRIVER_OK: u8 = 0x04u8;
|
pub const VIRTIO_CONFIG_S_DRIVER_OK: u8 = 0x04u8;
|
||||||
pub const VIRTIO_CONFIG_S_FEATURES_OK: u8 = 0x08u8;
|
pub const VIRTIO_CONFIG_S_FEATURES_OK: u8 = 0x08u8;
|
||||||
|
|
||||||
// Device feature bits
|
// Device feature bits
|
||||||
/// Disk is read-only.
|
/// Disk is read-only.
|
||||||
pub const VIRTIO_BLK_F_RO: u8 = 5u8;
|
pub const VIRTIO_BLK_F_RO: u8 = 5u8;
|
||||||
/// Supports SCSI command passthrough.
|
/// Supports SCSI command passthrough.
|
||||||
pub const VIRTIO_BLK_F_SCSI: u8 = 7u8;
|
pub const VIRTIO_BLK_F_SCSI: u8 = 7u8;
|
||||||
/// Writeback mode available in config.
|
/// Writeback mode available in config.
|
||||||
pub const VIRTIO_BLK_F_CONFIG_WCE: u8 = 11u8;
|
pub const VIRTIO_BLK_F_CONFIG_WCE: u8 = 11u8;
|
||||||
/// Support more than one vq.
|
/// Support more than one vq.
|
||||||
pub const VIRTIO_BLK_F_MQ: u8 = 12u8;
|
pub const VIRTIO_BLK_F_MQ: u8 = 12u8;
|
||||||
pub const VIRTIO_F_ANY_LAYOUT: u8 = 27u8;
|
pub const VIRTIO_F_ANY_LAYOUT: u8 = 27u8;
|
||||||
pub const VIRTIO_RING_F_INDIRECT_DESC: u8 = 28u8;
|
pub const VIRTIO_RING_F_INDIRECT_DESC: u8 = 28u8;
|
||||||
pub const VIRTIO_RING_F_EVENT_IDX: u8 = 29u8;
|
pub const VIRTIO_RING_F_EVENT_IDX: u8 = 29u8;
|
||||||
|
|
||||||
/// This many virtio descriptors.
|
/// This many virtio descriptors.
|
||||||
///
|
///
|
||||||
/// Must be a power of two.
|
/// Must be a power of two.
|
||||||
pub const NUM_DESCRIPTORS: usize = 8usize;
|
pub const NUM_DESCRIPTORS: usize = 8usize;
|
||||||
|
|
||||||
@ -123,12 +123,12 @@ pub struct VirtqUsed {
|
|||||||
// Described in section 5.2 of the spec.
|
// Described in section 5.2 of the spec.
|
||||||
|
|
||||||
/// Read the disk.
|
/// Read the disk.
|
||||||
pub const VIRTIO_BLK_T_IN: u32 = 0u32;
|
pub const VIRTIO_BLK_T_IN: u32 = 0u32;
|
||||||
/// Write the disk.
|
/// Write the disk.
|
||||||
pub const VIRTIO_BLK_T_OUT: u32 = 1u32;
|
pub const VIRTIO_BLK_T_OUT: u32 = 1u32;
|
||||||
|
|
||||||
/// The format of the first descriptor in a disk request.
|
/// The format of the first descriptor in a disk request.
|
||||||
///
|
///
|
||||||
/// To be followed by two more descriptors containing
|
/// To be followed by two more descriptors containing
|
||||||
/// the block, and a one-byte status.
|
/// the block, and a one-byte status.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -151,7 +151,7 @@ pub struct Disk {
|
|||||||
/// A set (not a ring) of DMA descriptors, with which the
|
/// A set (not a ring) of DMA descriptors, with which the
|
||||||
/// driver tells the device where to read and write individual
|
/// driver tells the device where to read and write individual
|
||||||
/// disk operations. There are NUM descriptors.
|
/// disk operations. There are NUM descriptors.
|
||||||
///
|
///
|
||||||
/// Most commands consist of a "chain" (linked list)
|
/// Most commands consist of a "chain" (linked list)
|
||||||
/// of a couple of these descriptors.
|
/// of a couple of these descriptors.
|
||||||
pub descriptors: *mut VirtqDescriptor,
|
pub descriptors: *mut VirtqDescriptor,
|
||||||
@ -173,11 +173,10 @@ pub struct Disk {
|
|||||||
|
|
||||||
/// Track info about in-flight operations,
|
/// Track info about in-flight operations,
|
||||||
/// for use when completion interrupt arrives.
|
/// for use when completion interrupt arrives.
|
||||||
///
|
///
|
||||||
/// Indexed by first descriptor index of chain.
|
/// Indexed by first descriptor index of chain.
|
||||||
pub info: [DiskInfo; NUM_DESCRIPTORS],
|
pub info: [DiskInfo; NUM_DESCRIPTORS],
|
||||||
|
|
||||||
|
|
||||||
/// Disk command headers.
|
/// Disk command headers.
|
||||||
/// One-for-one with descriptors, for convenience.
|
/// One-for-one with descriptors, for convenience.
|
||||||
pub ops: [VirtioBlockRequest; NUM_DESCRIPTORS],
|
pub ops: [VirtioBlockRequest; NUM_DESCRIPTORS],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user