Skip to content

Commit 6380d07

Browse files
committed
ch9
1 parent 6dfa34f commit 6380d07

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1962
-302
lines changed

easy-fs-fuse/src/main.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ impl BlockDevice for BlockFile {
2626
.expect("Error seeking!");
2727
assert_matches!(file.write(buf), Ok(BLOCK_SZ), "Not a complete block!");
2828
}
29+
30+
fn handle_irq(&self) {
31+
unimplemented!()
32+
}
2933
}
3034

3135
#[derive(Debug, StructOpt)]
@@ -53,11 +57,11 @@ fn easy_fs_pack() -> std::io::Result<()> {
5357
.write(true)
5458
.create(true)
5559
.open(path)?;
56-
f.set_len(16 * 2048 * 512)?;
60+
f.set_len(32 * 2048 * 512)?;
5761
f
5862
})));
59-
// 16MiB block dev, bitmap 1 block == at most 4095 files
60-
let efs = EasyFileSystem::create(block_file, 16 * 2048, 1);
63+
// 32MiB block dev; bitmap 1 block == at most 4095 files
64+
let efs = EasyFileSystem::create(block_file, 32 * 2048, 1);
6165
let root_inode = Arc::new(EasyFileSystem::root_inode(&efs));
6266
let apps = read_dir(opt.source.as_path())?
6367
.into_iter()

easy-fs/src/block_dev.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ pub trait BlockDevice: Send + Sync + Any {
77
fn read_block(&self, block_id: usize, buf: &mut [u8]);
88
/// Write data from buffer to block
99
fn write_block(&self, block_id: usize, buf: &[u8]);
10+
/// IRQ handler
11+
fn handle_irq(&self);
1012
}

os/Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

os/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ bitflags = "1.2.1"
1313
xmas-elf = "0.7.0"
1414
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "4ee80e5" }
1515
easy-fs = { path = "../easy-fs" }
16+
volatile = "0.3"
17+
lose-net-stack = { git = "https://github.com/yfblock/lose-net-stack", rev = "db42380" }

os/Makefile

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ BOARD := qemu
1818
SBI ?= rustsbi
1919
BOOTLOADER := ../bootloader/$(SBI)-$(BOARD).bin
2020

21+
# GUI
22+
GUI ?= off
23+
ifeq ($(GUI), off)
24+
GUI_OPTION := -display none
25+
endif
26+
2127
# KERNEL ENTRY
2228
KERNEL_ENTRY_PA := 0x80200000
2329

@@ -76,11 +82,21 @@ disasm-vim: kernel
7682
run: run-inner
7783

7884
QEMU_ARGS := -machine virt \
79-
-nographic \
8085
-bios $(BOOTLOADER) \
86+
-serial stdio \
87+
$(GUI_OPTION) \
8188
-device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) \
8289
-drive file=$(FS_IMG),if=none,format=raw,id=x0 \
83-
-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
90+
-device virtio-blk-device,drive=x0 \
91+
-device virtio-gpu-device \
92+
-device virtio-keyboard-device \
93+
-device virtio-mouse-device \
94+
-device virtio-net-device,netdev=net0 \
95+
-netdev user,id=net0,hostfwd=udp::6200-:2000,hostfwd=tcp::6201-:80
96+
97+
fdt:
98+
@qemu-system-riscv64 -M 128m -machine virt,dumpdtb=virt.out
99+
fdtdump virt.out
84100

85101
QEMU_NAME := qemu-system-riscv64
86102
qemu-version-check:

os/src/boards/qemu.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,49 @@ pub const CLOCK_FREQ: usize = 12500000;
44
pub const MEMORY_END: usize = 0x8800_0000;
55

66
pub const MMIO: &[(usize, usize)] = &[
7-
(0x10001000, 0x1000), // Virtio Block in virt machine
7+
(0x0010_0000, 0x2000), // VIRT_TEST/RTC in virt machine
8+
(0x0200_0000, 0x10000),
9+
(VIRT_PLIC, 0x210000), // VIRT_PLIC in virt machine
10+
(VIRT_UART, 0x9000), // VIRT_UART0 with GPU in virt machine
811
];
912

13+
pub const VIRT_PLIC: usize = 0x0C00_0000;
14+
pub const VIRT_UART: usize = 0x1000_0000;
15+
1016
pub type BlockDeviceImpl = crate::drivers::block::VirtIOBlock;
17+
pub type CharDeviceImpl = crate::drivers::chardev::NS16550a<VIRT_UART>;
18+
19+
use crate::drivers::{
20+
plic::{IntrTargetPriority, PLIC},
21+
CharDevice, BLOCK_DEVICE, KEYBOARD_DEVICE, UART,
22+
};
23+
24+
pub fn device_init() {
25+
use riscv::register::sie;
26+
let mut plic = unsafe { PLIC::new(VIRT_PLIC) };
27+
let hart_id: usize = 0;
28+
let supervisor = IntrTargetPriority::Supervisor;
29+
let machine = IntrTargetPriority::Machine;
30+
plic.set_threshold(hart_id, supervisor, 0);
31+
plic.set_threshold(hart_id, machine, 1);
32+
// irq nums: 5 keyboard, 6 mouse, 8 block, 10 uart
33+
for intr_src_id in [5, 8, 10] {
34+
plic.enable(hart_id, supervisor, intr_src_id);
35+
plic.set_priority(intr_src_id, 1);
36+
}
37+
unsafe {
38+
sie::set_sext();
39+
}
40+
}
41+
42+
pub fn irq_handler() {
43+
let mut plic = unsafe { PLIC::new(VIRT_PLIC) };
44+
let intr_src_id = plic.claim(0, IntrTargetPriority::Supervisor);
45+
match intr_src_id {
46+
5 => KEYBOARD_DEVICE.handle_irq(),
47+
8 => BLOCK_DEVICE.handle_irq(),
48+
10 => UART.handle_irq(),
49+
_ => panic!("unsupported IRQ {}", intr_src_id),
50+
}
51+
plic.complete(0, IntrTargetPriority::Supervisor, intr_src_id);
52+
}

os/src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ pub use crate::board::{CLOCK_FREQ, MEMORY_END, MMIO};
55
// Memory
66
pub const USER_STACK_SIZE: usize = 4096 * 2;
77
pub const KERNEL_STACK_SIZE: usize = 4096 * 2;
8-
pub const KERNEL_HEAP_SIZE: usize = 0x30_0000;
8+
pub const KERNEL_HEAP_SIZE: usize = 0x100_0000;
99
pub const PAGE_SIZE: usize = 0x1000;
1010
pub const PAGE_SIZE_BITS: usize = 12;
1111
pub const TRAMPOLINE: usize = usize::MAX - PAGE_SIZE + 1;

os/src/console.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use crate::sbi::console_putchar;
1+
use crate::drivers::{CharDevice, UART};
22
use core::fmt::{self, Write};
33

44
struct Stdout;
55
impl Write for Stdout {
66
fn write_str(&mut self, s: &str) -> fmt::Result {
77
for c in s.chars() {
8-
console_putchar(c as usize);
8+
UART.write(c as u8);
99
}
1010
Ok(())
1111
}

os/src/drivers/block/virtio_blk.rs

Lines changed: 73 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,89 @@
1-
use alloc::vec::Vec;
2-
use easy_fs::BlockDevice;
3-
use lazy_static::lazy_static;
4-
use virtio_drivers::{Hal, VirtIOBlk, VirtIOHeader};
1+
use super::BlockDevice;
2+
use crate::drivers::bus::virtio::VirtioHal;
3+
use crate::sync::{Condvar, UPIntrFreeCell};
4+
use crate::task::schedule;
5+
use crate::DEV_NON_BLOCKING_ACCESS;
6+
use alloc::collections::BTreeMap;
7+
use virtio_drivers::{BlkResp, RespStatus, VirtIOBlk, VirtIOHeader};
58

6-
use crate::{
7-
mm::{
8-
frame_alloc, frame_dealloc, kernel_token, FrameTracker, PageTable, PhysAddr, PhysPageNum,
9-
StepByOne,
10-
},
11-
sync::UPSafeCell,
12-
};
9+
#[allow(unused)]
10+
const VIRTIO0: usize = 0x10008000;
1311

14-
const VIRTIO0: usize = 0x10001000;
15-
16-
pub struct VirtIOBlock(UPSafeCell<VirtIOBlk<'static, VirtioHal>>);
17-
18-
impl VirtIOBlock {
19-
pub fn new() -> Self {
20-
Self(unsafe {
21-
UPSafeCell::new(VirtIOBlk::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap())
22-
})
23-
}
12+
pub struct VirtIOBlock {
13+
virtio_blk: UPIntrFreeCell<VirtIOBlk<'static, VirtioHal>>,
14+
condvars: BTreeMap<u16, Condvar>,
2415
}
16+
2517
impl BlockDevice for VirtIOBlock {
2618
fn read_block(&self, block_id: usize, buf: &mut [u8]) {
27-
self.0
28-
.exclusive_access()
29-
.read_block(block_id, buf)
30-
.expect("Error when reading VirtIOBlk")
19+
let nb = *DEV_NON_BLOCKING_ACCESS.exclusive_access();
20+
if nb {
21+
let mut resp = BlkResp::default();
22+
let task_cx_ptr = self.virtio_blk.exclusive_session(|blk| {
23+
let token = unsafe { blk.read_block_nb(block_id, buf, &mut resp).unwrap() };
24+
self.condvars.get(&token).unwrap().wait_no_sched()
25+
});
26+
schedule(task_cx_ptr);
27+
assert_eq!(
28+
resp.status(),
29+
RespStatus::Ok,
30+
"Error when reading VirtIOBlk"
31+
);
32+
} else {
33+
self.virtio_blk
34+
.exclusive_access()
35+
.read_block(block_id, buf)
36+
.expect("Error when reading VirtIOBlk");
37+
}
3138
}
3239

3340
fn write_block(&self, block_id: usize, buf: &[u8]) {
34-
self.0
35-
.exclusive_access()
36-
.write_block(block_id, buf)
37-
.expect("Error when writing VirtIOBlk")
41+
let nb = *DEV_NON_BLOCKING_ACCESS.exclusive_access();
42+
if nb {
43+
let mut resp = BlkResp::default();
44+
let task_cx_ptr = self.virtio_blk.exclusive_session(|blk| {
45+
let token = unsafe { blk.write_block_nb(block_id, buf, &mut resp).unwrap() };
46+
self.condvars.get(&token).unwrap().wait_no_sched()
47+
});
48+
schedule(task_cx_ptr);
49+
assert_eq!(
50+
resp.status(),
51+
RespStatus::Ok,
52+
"Error when writing VirtIOBlk"
53+
);
54+
} else {
55+
self.virtio_blk
56+
.exclusive_access()
57+
.write_block(block_id, buf)
58+
.expect("Error when writing VirtIOBlk");
59+
}
3860
}
39-
}
40-
41-
lazy_static! {
42-
static ref QUEUE_FRAMES: UPSafeCell<Vec<FrameTracker>> = unsafe { UPSafeCell::new(Vec::new()) };
43-
}
4461

45-
pub struct VirtioHal;
46-
impl Hal for VirtioHal {
47-
fn dma_alloc(pages: usize) -> virtio_drivers::PhysAddr {
48-
let mut ppn_base = PhysPageNum(0);
49-
for i in 0..pages {
50-
let frame = frame_alloc().unwrap();
51-
if i == 0 {
52-
ppn_base = frame.ppn;
62+
fn handle_irq(&self) {
63+
self.virtio_blk.exclusive_session(|blk| {
64+
while let Ok(token) = blk.pop_used() {
65+
self.condvars.get(&token).unwrap().signal();
5366
}
54-
// make sure consecutive!
55-
assert_eq!(frame.ppn.0, ppn_base.0 + i);
56-
QUEUE_FRAMES.exclusive_access().push(frame);
57-
}
58-
let pa: PhysAddr = ppn_base.into();
59-
pa.0
67+
});
6068
}
69+
}
6170

62-
fn dma_dealloc(paddr: virtio_drivers::PhysAddr, pages: usize) -> i32 {
63-
let pa = PhysAddr::from(paddr);
64-
let mut ppn_base: PhysPageNum = pa.into();
65-
for _ in 0..pages {
66-
// make sure consecutive!
67-
frame_dealloc(ppn_base);
68-
ppn_base.step();
71+
impl VirtIOBlock {
72+
pub fn new() -> Self {
73+
let virtio_blk = unsafe {
74+
UPIntrFreeCell::new(
75+
VirtIOBlk::<VirtioHal>::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap(),
76+
)
77+
};
78+
let mut condvars = BTreeMap::new();
79+
let channels = virtio_blk.exclusive_access().virt_queue_size();
80+
for i in 0..channels {
81+
let condvar = Condvar::new();
82+
condvars.insert(i, condvar);
83+
}
84+
Self {
85+
virtio_blk,
86+
condvars,
6987
}
70-
0
71-
}
72-
73-
fn phys_to_virt(paddr: virtio_drivers::PhysAddr) -> virtio_drivers::VirtAddr {
74-
paddr
75-
}
76-
77-
fn virt_to_phys(vaddr: virtio_drivers::VirtAddr) -> virtio_drivers::PhysAddr {
78-
PageTable::from_token(kernel_token())
79-
.translate_va(vaddr.into())
80-
.unwrap()
81-
.0
8288
}
8389
}

os/src/drivers/bus/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod virtio;

0 commit comments

Comments
 (0)