virtio-blk worked.
This commit is contained in:
parent
2d34cab989
commit
eca5ee2eb7
12 changed files with 145 additions and 11 deletions
|
@ -13,6 +13,8 @@ buddy_system_allocator = "0.6"
|
||||||
spin = "0.7.0"
|
spin = "0.7.0"
|
||||||
bitflags = "1.2.1"
|
bitflags = "1.2.1"
|
||||||
xmas-elf = "0.7.0"
|
xmas-elf = "0.7.0"
|
||||||
|
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers" }
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
board_qemu = []
|
board_qemu = []
|
||||||
|
|
|
@ -50,7 +50,9 @@ ifeq ($(BOARD),qemu)
|
||||||
-machine virt \
|
-machine virt \
|
||||||
-nographic \
|
-nographic \
|
||||||
-bios $(BOOTLOADER) \
|
-bios $(BOOTLOADER) \
|
||||||
-device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA)
|
-device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) \
|
||||||
|
-drive file=fs.img,if=none,format=raw,id=x0 \
|
||||||
|
-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
|
||||||
else
|
else
|
||||||
@cp $(BOOTLOADER) $(BOOTLOADER).copy
|
@cp $(BOOTLOADER) $(BOOTLOADER).copy
|
||||||
@dd if=$(KERNEL_BIN) of=$(BOOTLOADER).copy bs=128K seek=1
|
@dd if=$(KERNEL_BIN) of=$(BOOTLOADER).copy bs=128K seek=1
|
||||||
|
|
|
@ -9,7 +9,12 @@ pub const TRAMPOLINE: usize = usize::MAX - PAGE_SIZE + 1;
|
||||||
pub const TRAP_CONTEXT: usize = TRAMPOLINE - PAGE_SIZE;
|
pub const TRAP_CONTEXT: usize = TRAMPOLINE - PAGE_SIZE;
|
||||||
|
|
||||||
#[cfg(feature = "board_k210")]
|
#[cfg(feature = "board_k210")]
|
||||||
pub const CPU_FREQ: usize = 10000000;
|
pub const CLOCK_FREQ: usize = 10000000;
|
||||||
|
|
||||||
#[cfg(feature = "board_qemu")]
|
#[cfg(feature = "board_qemu")]
|
||||||
pub const CPU_FREQ: usize = 12500000;
|
pub const CLOCK_FREQ: usize = 12500000;
|
||||||
|
|
||||||
|
#[cfg(feature = "board_qemu")]
|
||||||
|
pub const MMIO: &[(usize, usize)] = &[
|
||||||
|
(0x10001000, 0x10000),
|
||||||
|
];
|
30
os/src/drivers/block/mod.rs
Normal file
30
os/src/drivers/block/mod.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
mod virtio_blk;
|
||||||
|
|
||||||
|
use lazy_static::*;
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
use core::any::Any;
|
||||||
|
|
||||||
|
pub trait BlockDevice : Send + Sync + Any {
|
||||||
|
fn read_block(&self, block_id: usize, buf: &mut [u8]);
|
||||||
|
fn write_block(&self, block_id: usize, buf: &[u8]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "board_qemu")]
|
||||||
|
type BlockDeviceImpl = virtio_blk::VirtIOBlock;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref BLOCK_DEVICE: Arc<dyn BlockDevice> = Arc::new(BlockDeviceImpl::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn block_device_test() {
|
||||||
|
let block_device = BLOCK_DEVICE.clone();
|
||||||
|
let mut write_buffer = [0u8; 512];
|
||||||
|
let mut read_buffer = [0u8; 512];
|
||||||
|
for i in 0..512 {
|
||||||
|
for byte in write_buffer.iter_mut() { *byte = i as u8; }
|
||||||
|
block_device.write_block(i as usize, &write_buffer);
|
||||||
|
block_device.read_block(i as usize, &mut read_buffer);
|
||||||
|
assert_eq!(write_buffer, read_buffer);
|
||||||
|
}
|
||||||
|
println!("block device test passed!");
|
||||||
|
}
|
71
os/src/drivers/block/virtio_blk.rs
Normal file
71
os/src/drivers/block/virtio_blk.rs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
use virtio_drivers::{VirtIOBlk, VirtIOHeader};
|
||||||
|
use crate::mm::{
|
||||||
|
PhysAddr,
|
||||||
|
VirtAddr,
|
||||||
|
frame_alloc,
|
||||||
|
frame_dealloc,
|
||||||
|
PhysPageNum,
|
||||||
|
FrameTracker,
|
||||||
|
StepByOne,
|
||||||
|
};
|
||||||
|
use super::BlockDevice;
|
||||||
|
use spin::Mutex;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
use lazy_static::*;
|
||||||
|
|
||||||
|
const VIRTIO0: usize = 0x10001000;
|
||||||
|
|
||||||
|
pub struct VirtIOBlock(Mutex<VirtIOBlk<'static>>);
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref QUEUE_FRAMES: Mutex<Vec<FrameTracker>> = Mutex::new(Vec::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockDevice for VirtIOBlock {
|
||||||
|
fn read_block(&self, block_id: usize, buf: &mut [u8]) {
|
||||||
|
self.0.lock().read_block(block_id, buf).expect("Error when reading VirtIOBlk");
|
||||||
|
}
|
||||||
|
fn write_block(&self, block_id: usize, buf: &[u8]) {
|
||||||
|
self.0.lock().write_block(block_id, buf).expect("Error when writing VirtIOBlk");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VirtIOBlock {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(Mutex::new(VirtIOBlk::new(
|
||||||
|
unsafe { &mut *(VIRTIO0 as *mut VirtIOHeader) }
|
||||||
|
).unwrap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn virtio_dma_alloc(pages: usize) -> PhysAddr {
|
||||||
|
let mut ppn_base = PhysPageNum(0);
|
||||||
|
for i in 0..pages {
|
||||||
|
let frame = frame_alloc().unwrap();
|
||||||
|
if i == 0 { ppn_base = frame.ppn; }
|
||||||
|
assert_eq!(frame.ppn.0, ppn_base.0 + i);
|
||||||
|
QUEUE_FRAMES.lock().push(frame);
|
||||||
|
}
|
||||||
|
ppn_base.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn virtio_dma_dealloc(pa: PhysAddr, pages: usize) -> i32 {
|
||||||
|
let mut ppn_base: PhysPageNum = pa.into();
|
||||||
|
for _ in 0..pages {
|
||||||
|
frame_dealloc(ppn_base);
|
||||||
|
ppn_base.step();
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn virtio_phys_to_virt(paddr: PhysAddr) -> VirtAddr {
|
||||||
|
VirtAddr(paddr.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn virtio_virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
|
||||||
|
PhysAddr(vaddr.0)
|
||||||
|
}
|
3
os/src/drivers/mod.rs
Normal file
3
os/src/drivers/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
mod block;
|
||||||
|
|
||||||
|
pub use block::{BLOCK_DEVICE, block_device_test};
|
|
@ -23,6 +23,7 @@ mod task;
|
||||||
mod timer;
|
mod timer;
|
||||||
mod mm;
|
mod mm;
|
||||||
mod fs;
|
mod fs;
|
||||||
|
mod drivers;
|
||||||
|
|
||||||
global_asm!(include_str!("entry.asm"));
|
global_asm!(include_str!("entry.asm"));
|
||||||
global_asm!(include_str!("link_app.S"));
|
global_asm!(include_str!("link_app.S"));
|
||||||
|
@ -43,6 +44,7 @@ pub fn rust_main() -> ! {
|
||||||
println!("[kernel] Hello, world!");
|
println!("[kernel] Hello, world!");
|
||||||
mm::init();
|
mm::init();
|
||||||
mm::remap_test();
|
mm::remap_test();
|
||||||
|
drivers::block_device_test();
|
||||||
task::add_initproc();
|
task::add_initproc();
|
||||||
println!("after initproc!");
|
println!("after initproc!");
|
||||||
trap::init();
|
trap::init();
|
||||||
|
|
|
@ -3,15 +3,19 @@ use super::PageTableEntry;
|
||||||
use core::fmt::{self, Debug, Formatter};
|
use core::fmt::{self, Debug, Formatter};
|
||||||
|
|
||||||
/// Definitions
|
/// Definitions
|
||||||
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
pub struct PhysAddr(pub usize);
|
pub struct PhysAddr(pub usize);
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
pub struct VirtAddr(pub usize);
|
pub struct VirtAddr(pub usize);
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
pub struct PhysPageNum(pub usize);
|
pub struct PhysPageNum(pub usize);
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
pub struct VirtPageNum(pub usize);
|
pub struct VirtPageNum(pub usize);
|
||||||
|
|
||||||
|
@ -144,6 +148,11 @@ impl StepByOne for VirtPageNum {
|
||||||
self.0 += 1;
|
self.0 += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl StepByOne for PhysPageNum {
|
||||||
|
fn step(&mut self) {
|
||||||
|
self.0 += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct SimpleRange<T> where
|
pub struct SimpleRange<T> where
|
||||||
|
|
|
@ -108,7 +108,7 @@ pub fn frame_alloc() -> Option<FrameTracker> {
|
||||||
.map(|ppn| FrameTracker::new(ppn))
|
.map(|ppn| FrameTracker::new(ppn))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame_dealloc(ppn: PhysPageNum) {
|
pub fn frame_dealloc(ppn: PhysPageNum) {
|
||||||
FRAME_ALLOCATOR
|
FRAME_ALLOCATOR
|
||||||
.lock()
|
.lock()
|
||||||
.dealloc(ppn);
|
.dealloc(ppn);
|
||||||
|
|
|
@ -13,7 +13,8 @@ use crate::config::{
|
||||||
PAGE_SIZE,
|
PAGE_SIZE,
|
||||||
TRAMPOLINE,
|
TRAMPOLINE,
|
||||||
TRAP_CONTEXT,
|
TRAP_CONTEXT,
|
||||||
USER_STACK_SIZE
|
USER_STACK_SIZE,
|
||||||
|
MMIO,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -126,6 +127,15 @@ impl MemorySet {
|
||||||
MapType::Identical,
|
MapType::Identical,
|
||||||
MapPermission::R | MapPermission::W,
|
MapPermission::R | MapPermission::W,
|
||||||
), None);
|
), None);
|
||||||
|
println!("mapping memory-mapped registers");
|
||||||
|
for pair in MMIO {
|
||||||
|
memory_set.push(MapArea::new(
|
||||||
|
(*pair).0.into(),
|
||||||
|
((*pair).0 + (*pair).1).into(),
|
||||||
|
MapType::Identical,
|
||||||
|
MapPermission::R | MapPermission::W,
|
||||||
|
), None);
|
||||||
|
}
|
||||||
memory_set
|
memory_set
|
||||||
}
|
}
|
||||||
/// Include sections in elf and trampoline and TrapContext and user stack,
|
/// Include sections in elf and trampoline and TrapContext and user stack,
|
||||||
|
|
|
@ -5,9 +5,9 @@ mod page_table;
|
||||||
mod memory_set;
|
mod memory_set;
|
||||||
|
|
||||||
use page_table::{PageTable, PTEFlags};
|
use page_table::{PageTable, PTEFlags};
|
||||||
use address::{VPNRange, StepByOne};
|
use address::VPNRange;
|
||||||
pub use address::{PhysAddr, VirtAddr, PhysPageNum, VirtPageNum};
|
pub use address::{PhysAddr, VirtAddr, PhysPageNum, VirtPageNum, StepByOne};
|
||||||
pub use frame_allocator::{FrameTracker, frame_alloc};
|
pub use frame_allocator::{FrameTracker, frame_alloc, frame_dealloc,};
|
||||||
pub use page_table::{
|
pub use page_table::{
|
||||||
PageTableEntry,
|
PageTableEntry,
|
||||||
translated_byte_buffer,
|
translated_byte_buffer,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use riscv::register::time;
|
use riscv::register::time;
|
||||||
use crate::sbi::set_timer;
|
use crate::sbi::set_timer;
|
||||||
use crate::config::CPU_FREQ;
|
use crate::config::CLOCK_FREQ;
|
||||||
|
|
||||||
const TICKS_PER_SEC: usize = 100;
|
const TICKS_PER_SEC: usize = 100;
|
||||||
const MSEC_PER_SEC: usize = 1000;
|
const MSEC_PER_SEC: usize = 1000;
|
||||||
|
@ -10,9 +10,9 @@ pub fn get_time() -> usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_time_ms() -> usize {
|
pub fn get_time_ms() -> usize {
|
||||||
time::read() / (CPU_FREQ / MSEC_PER_SEC)
|
time::read() / (CLOCK_FREQ / MSEC_PER_SEC)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_next_trigger() {
|
pub fn set_next_trigger() {
|
||||||
set_timer(get_time() + CPU_FREQ / TICKS_PER_SEC);
|
set_timer(get_time() + CLOCK_FREQ / TICKS_PER_SEC);
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue