virtio-blk worked.

This commit is contained in:
Yifan Wu 2020-12-16 10:18:38 +08:00
parent 8e178c0080
commit f754326d0a
12 changed files with 145 additions and 11 deletions

View File

@ -13,6 +13,8 @@ buddy_system_allocator = "0.6"
spin = "0.7.0"
bitflags = "1.2.1"
xmas-elf = "0.7.0"
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers" }
[features]
board_qemu = []

View File

@ -50,7 +50,9 @@ ifeq ($(BOARD),qemu)
-machine virt \
-nographic \
-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
@cp $(BOOTLOADER) $(BOOTLOADER).copy
@dd if=$(KERNEL_BIN) of=$(BOOTLOADER).copy bs=128K seek=1

View File

@ -9,7 +9,12 @@ pub const TRAMPOLINE: usize = usize::MAX - PAGE_SIZE + 1;
pub const TRAP_CONTEXT: usize = TRAMPOLINE - PAGE_SIZE;
#[cfg(feature = "board_k210")]
pub const CPU_FREQ: usize = 10000000;
pub const CLOCK_FREQ: usize = 10000000;
#[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),
];

View 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!");
}

View 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
View File

@ -0,0 +1,3 @@
mod block;
pub use block::{BLOCK_DEVICE, block_device_test};

View File

@ -23,6 +23,7 @@ mod task;
mod timer;
mod mm;
mod fs;
mod drivers;
global_asm!(include_str!("entry.asm"));
global_asm!(include_str!("link_app.S"));
@ -43,6 +44,7 @@ pub fn rust_main() -> ! {
println!("[kernel] Hello, world!");
mm::init();
mm::remap_test();
drivers::block_device_test();
task::add_initproc();
println!("after initproc!");
trap::init();

View File

@ -3,15 +3,19 @@ use super::PageTableEntry;
use core::fmt::{self, Debug, Formatter};
/// Definitions
#[repr(C)]
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub struct PhysAddr(pub usize);
#[repr(C)]
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub struct VirtAddr(pub usize);
#[repr(C)]
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub struct PhysPageNum(pub usize);
#[repr(C)]
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub struct VirtPageNum(pub usize);
@ -144,6 +148,11 @@ impl StepByOne for VirtPageNum {
self.0 += 1;
}
}
impl StepByOne for PhysPageNum {
fn step(&mut self) {
self.0 += 1;
}
}
#[derive(Copy, Clone)]
pub struct SimpleRange<T> where

View File

@ -108,7 +108,7 @@ pub fn frame_alloc() -> Option<FrameTracker> {
.map(|ppn| FrameTracker::new(ppn))
}
fn frame_dealloc(ppn: PhysPageNum) {
pub fn frame_dealloc(ppn: PhysPageNum) {
FRAME_ALLOCATOR
.lock()
.dealloc(ppn);

View File

@ -13,7 +13,8 @@ use crate::config::{
PAGE_SIZE,
TRAMPOLINE,
TRAP_CONTEXT,
USER_STACK_SIZE
USER_STACK_SIZE,
MMIO,
};
extern "C" {
@ -126,6 +127,15 @@ impl MemorySet {
MapType::Identical,
MapPermission::R | MapPermission::W,
), 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
}
/// Include sections in elf and trampoline and TrapContext and user stack,

View File

@ -5,9 +5,9 @@ mod page_table;
mod memory_set;
use page_table::{PageTable, PTEFlags};
use address::{VPNRange, StepByOne};
pub use address::{PhysAddr, VirtAddr, PhysPageNum, VirtPageNum};
pub use frame_allocator::{FrameTracker, frame_alloc};
use address::VPNRange;
pub use address::{PhysAddr, VirtAddr, PhysPageNum, VirtPageNum, StepByOne};
pub use frame_allocator::{FrameTracker, frame_alloc, frame_dealloc,};
pub use page_table::{
PageTableEntry,
translated_byte_buffer,

View File

@ -1,6 +1,6 @@
use riscv::register::time;
use crate::sbi::set_timer;
use crate::config::CPU_FREQ;
use crate::config::CLOCK_FREQ;
const TICKS_PER_SEC: usize = 100;
const MSEC_PER_SEC: usize = 1000;
@ -10,9 +10,9 @@ pub fn get_time() -> 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() {
set_timer(get_time() + CPU_FREQ / TICKS_PER_SEC);
set_timer(get_time() + CLOCK_FREQ / TICKS_PER_SEC);
}