mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-19 17:26:31 +00:00
feature: virtio console support (#1113)
feat(virtio): add virtio console driver support - Implement virtio console driver with TTY interface - Add HVC device support for console output - Update devfs to handle HVC devices - Fix virtio driver registration and initialization - Improve virtio net driver interrupt handling - Clean up block device naming implementation - Add clippy lint checks to multiple crates - Fix slab allocator alignment issues - Update QEMU run script for virtio consoleagonOS.org> --------- Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -19,3 +19,4 @@ cppcheck.xml
|
|||||||
.cache
|
.cache
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
/logs/
|
/logs/
|
||||||
|
*.log
|
||||||
|
@ -57,7 +57,7 @@ system_error = { path = "crates/system_error" }
|
|||||||
uefi = { version = "=0.26.0", features = ["alloc"] }
|
uefi = { version = "=0.26.0", features = ["alloc"] }
|
||||||
uefi-raw = "=0.5.0"
|
uefi-raw = "=0.5.0"
|
||||||
unified-init = { path = "crates/unified-init" }
|
unified-init = { path = "crates/unified-init" }
|
||||||
virtio-drivers = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/virtio-drivers", rev = "f91c807965" }
|
virtio-drivers = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/virtio-drivers", rev = "415ab38ff9" }
|
||||||
wait_queue_macros = { path = "crates/wait_queue_macros" }
|
wait_queue_macros = { path = "crates/wait_queue_macros" }
|
||||||
paste = "=1.0.14"
|
paste = "=1.0.14"
|
||||||
slabmalloc = { path = "crates/rust-slabmalloc" }
|
slabmalloc = { path = "crates/rust-slabmalloc" }
|
||||||
|
@ -7,6 +7,12 @@ pub struct BitMapCore<T: BitOps> {
|
|||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: BitOps> Default for BitMapCore<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: BitOps> BitMapCore<T> {
|
impl<T: BitOps> BitMapCore<T> {
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![allow(incomplete_features)] // for const generics
|
#![allow(incomplete_features)] // for const generics
|
||||||
#![feature(generic_const_exprs)]
|
#![feature(generic_const_exprs)]
|
||||||
|
#![deny(clippy::all)]
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![allow(clippy::needless_return)]
|
#![allow(clippy::needless_return)]
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
#![crate_name = "slabmalloc"]
|
#![crate_name = "slabmalloc"]
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![feature(maybe_uninit_as_bytes)]
|
#![feature(maybe_uninit_as_bytes)]
|
||||||
|
#![deny(clippy::all)]
|
||||||
|
#![allow(clippy::needless_return)]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
mod pages;
|
mod pages;
|
||||||
|
@ -33,7 +33,7 @@ impl Bitfield for [AtomicU64] {
|
|||||||
fn initialize(&mut self, for_size: usize, capacity: usize) {
|
fn initialize(&mut self, for_size: usize, capacity: usize) {
|
||||||
// Set everything to allocated
|
// Set everything to allocated
|
||||||
for bitmap in self.iter_mut() {
|
for bitmap in self.iter_mut() {
|
||||||
*bitmap = AtomicU64::new(u64::max_value());
|
*bitmap = AtomicU64::new(u64::MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark actual slots as free
|
// Mark actual slots as free
|
||||||
@ -56,7 +56,7 @@ impl Bitfield for [AtomicU64] {
|
|||||||
) -> Option<(usize, usize)> {
|
) -> Option<(usize, usize)> {
|
||||||
for (base_idx, b) in self.iter().enumerate() {
|
for (base_idx, b) in self.iter().enumerate() {
|
||||||
let bitval = b.load(Ordering::Relaxed);
|
let bitval = b.load(Ordering::Relaxed);
|
||||||
if bitval == u64::max_value() {
|
if bitval == u64::MAX {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
let negated = !bitval;
|
let negated = !bitval;
|
||||||
@ -117,7 +117,7 @@ impl Bitfield for [AtomicU64] {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn is_full(&self) -> bool {
|
fn is_full(&self) -> bool {
|
||||||
self.iter()
|
self.iter()
|
||||||
.filter(|&x| x.load(Ordering::Relaxed) != u64::max_value())
|
.filter(|&x| x.load(Ordering::Relaxed) != u64::MAX)
|
||||||
.count()
|
.count()
|
||||||
== 0
|
== 0
|
||||||
}
|
}
|
||||||
@ -268,10 +268,10 @@ impl<'a> ObjectPage<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// These needs some more work to be really safe...
|
// These needs some more work to be really safe...
|
||||||
unsafe impl<'a> Send for ObjectPage<'a> {}
|
unsafe impl Send for ObjectPage<'_> {}
|
||||||
unsafe impl<'a> Sync for ObjectPage<'a> {}
|
unsafe impl Sync for ObjectPage<'_> {}
|
||||||
|
|
||||||
impl<'a> AllocablePage for ObjectPage<'a> {
|
impl AllocablePage for ObjectPage<'_> {
|
||||||
const SIZE: usize = OBJECT_PAGE_SIZE;
|
const SIZE: usize = OBJECT_PAGE_SIZE;
|
||||||
|
|
||||||
fn bitfield(&self) -> &[AtomicU64; 8] {
|
fn bitfield(&self) -> &[AtomicU64; 8] {
|
||||||
@ -296,7 +296,7 @@ impl<'a> Default for ObjectPage<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> fmt::Debug for ObjectPage<'a> {
|
impl fmt::Debug for ObjectPage<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "ObjectPage")
|
write!(f, "ObjectPage")
|
||||||
}
|
}
|
||||||
@ -401,6 +401,8 @@ impl<'a, T: AllocablePage> PageList<'a, T> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
self.elements -= 1;
|
self.elements -= 1;
|
||||||
|
|
||||||
|
#[allow(clippy::manual_inspect)]
|
||||||
new_head.map(|node| {
|
new_head.map(|node| {
|
||||||
*node.prev() = Rawlink::none();
|
*node.prev() = Rawlink::none();
|
||||||
*node.next() = Rawlink::none();
|
*node.next() = Rawlink::none();
|
||||||
@ -434,6 +436,7 @@ impl<'a, P: AllocablePage + 'a> Iterator for ObjectPageIterMut<'a, P> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<&'a mut P> {
|
fn next(&mut self) -> Option<&'a mut P> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
#[allow(clippy::manual_inspect)]
|
||||||
self.head.resolve_mut().map(|next| {
|
self.head.resolve_mut().map(|next| {
|
||||||
self.head = match next.next().resolve_mut() {
|
self.head = match next.next().resolve_mut() {
|
||||||
None => Rawlink::none(),
|
None => Rawlink::none(),
|
||||||
|
@ -71,7 +71,7 @@ macro_rules! new_sc_allocator {
|
|||||||
SCAllocator {
|
SCAllocator {
|
||||||
size: $size,
|
size: $size,
|
||||||
allocation_count: 0,
|
allocation_count: 0,
|
||||||
obj_per_page: obj_per_page,
|
obj_per_page,
|
||||||
empty_slabs: PageList::new(),
|
empty_slabs: PageList::new(),
|
||||||
slabs: PageList::new(),
|
slabs: PageList::new(),
|
||||||
full_slabs: PageList::new(),
|
full_slabs: PageList::new(),
|
||||||
|
@ -3,7 +3,7 @@ use crate::driver::{
|
|||||||
base::{
|
base::{
|
||||||
device::{
|
device::{
|
||||||
device_number::{DeviceNumber, Major},
|
device_number::{DeviceNumber, Major},
|
||||||
Device, DeviceError, IdTable, BLOCKDEVS,
|
DevName, Device, DeviceError, IdTable, BLOCKDEVS,
|
||||||
},
|
},
|
||||||
map::{
|
map::{
|
||||||
DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START,
|
DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START,
|
||||||
@ -13,8 +13,8 @@ use crate::driver::{
|
|||||||
block::cache::{cached_block_device::BlockCache, BlockCacheError, BLOCK_SIZE},
|
block::cache::{cached_block_device::BlockCache, BlockCacheError, BLOCK_SIZE},
|
||||||
};
|
};
|
||||||
|
|
||||||
use alloc::{string::String, sync::Arc, vec::Vec};
|
use alloc::{sync::Arc, vec::Vec};
|
||||||
use core::{any::Any, fmt::Display, ops::Deref};
|
use core::any::Any;
|
||||||
use log::error;
|
use log::error;
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
@ -221,74 +221,11 @@ pub fn __lba_to_bytes(lba_id: usize, blk_size: usize) -> BlockId {
|
|||||||
return lba_id * blk_size;
|
return lba_id * blk_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 块设备的名字
|
|
||||||
pub struct BlockDevName {
|
|
||||||
name: Arc<String>,
|
|
||||||
id: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BlockDevName {
|
|
||||||
pub fn new(name: String, id: usize) -> Self {
|
|
||||||
return BlockDevName {
|
|
||||||
name: Arc::new(name),
|
|
||||||
id,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn id(&self) -> usize {
|
|
||||||
return self.id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl core::fmt::Debug for BlockDevName {
|
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
|
||||||
return write!(f, "{}", self.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for BlockDevName {
|
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
|
||||||
return write!(f, "{}", self.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for BlockDevName {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
return BlockDevName {
|
|
||||||
name: self.name.clone(),
|
|
||||||
id: self.id,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl core::hash::Hash for BlockDevName {
|
|
||||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
|
||||||
self.name.hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for BlockDevName {
|
|
||||||
type Target = String;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
return self.name.as_ref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq for BlockDevName {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
return self.name == other.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for BlockDevName {}
|
|
||||||
|
|
||||||
/// @brief 块设备应该实现的操作
|
/// @brief 块设备应该实现的操作
|
||||||
pub trait BlockDevice: Device {
|
pub trait BlockDevice: Device {
|
||||||
/// # dev_name
|
/// # dev_name
|
||||||
/// 返回块设备的名字
|
/// 返回块设备的名字
|
||||||
fn dev_name(&self) -> &BlockDevName;
|
fn dev_name(&self) -> &DevName;
|
||||||
|
|
||||||
fn blkdev_meta(&self) -> &BlockDevMeta;
|
fn blkdev_meta(&self) -> &BlockDevMeta;
|
||||||
|
|
||||||
|
@ -6,14 +6,14 @@ use system_error::SystemError;
|
|||||||
use unified_init::macros::unified_init;
|
use unified_init::macros::unified_init;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::base::block::gendisk::GenDisk,
|
driver::base::{block::gendisk::GenDisk, device::DevName},
|
||||||
filesystem::mbr::MbrDiskPartionTable,
|
filesystem::mbr::MbrDiskPartionTable,
|
||||||
init::initcall::INITCALL_POSTCORE,
|
init::initcall::INITCALL_POSTCORE,
|
||||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
block_device::{BlockDevName, BlockDevice, GeneralBlockRange},
|
block_device::{BlockDevice, GeneralBlockRange},
|
||||||
gendisk::GenDiskMap,
|
gendisk::GenDiskMap,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ pub struct BlockDevManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct InnerBlockDevManager {
|
struct InnerBlockDevManager {
|
||||||
disks: HashMap<BlockDevName, Arc<dyn BlockDevice>>,
|
disks: HashMap<DevName, Arc<dyn BlockDevice>>,
|
||||||
}
|
}
|
||||||
impl BlockDevManager {
|
impl BlockDevManager {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
@ -207,7 +207,7 @@ impl BlockDevManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct BlockDevMeta {
|
pub struct BlockDevMeta {
|
||||||
pub devname: BlockDevName,
|
pub devname: DevName,
|
||||||
inner: SpinLock<InnerBlockDevMeta>,
|
inner: SpinLock<InnerBlockDevMeta>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,7 +216,7 @@ pub struct InnerBlockDevMeta {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BlockDevMeta {
|
impl BlockDevMeta {
|
||||||
pub fn new(devname: BlockDevName) -> Self {
|
pub fn new(devname: DevName) -> Self {
|
||||||
BlockDevMeta {
|
BlockDevMeta {
|
||||||
devname,
|
devname,
|
||||||
inner: SpinLock::new(InnerBlockDevMeta {
|
inner: SpinLock::new(InnerBlockDevMeta {
|
||||||
|
@ -24,6 +24,8 @@ impl Major {
|
|||||||
pub const UNIX98_PTY_SLAVE_MAJOR: Self =
|
pub const UNIX98_PTY_SLAVE_MAJOR: Self =
|
||||||
Self::new(Self::UNIX98_PTY_MASTER_MAJOR.0 + Self::UNIX98_PTY_MAJOR_COUNT.0);
|
Self::new(Self::UNIX98_PTY_MASTER_MAJOR.0 + Self::UNIX98_PTY_MAJOR_COUNT.0);
|
||||||
|
|
||||||
|
pub const HVC_MAJOR: Self = Self::new(229);
|
||||||
|
|
||||||
pub const fn new(x: u32) -> Self {
|
pub const fn new(x: u32) -> Self {
|
||||||
Major(x)
|
Major(x)
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,8 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use core::intrinsics::unlikely;
|
|
||||||
use core::{any::Any, fmt::Debug};
|
use core::{any::Any, fmt::Debug};
|
||||||
|
use core::{fmt::Display, intrinsics::unlikely, ops::Deref};
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
@ -124,6 +124,69 @@ unsafe fn set_sys_devices_virtual_kset(kset: Arc<KSet>) {
|
|||||||
DEVICES_VIRTUAL_KSET_INSTANCE = Some(kset);
|
DEVICES_VIRTUAL_KSET_INSTANCE = Some(kset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// /dev下面的设备的名字
|
||||||
|
pub struct DevName {
|
||||||
|
name: Arc<String>,
|
||||||
|
id: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DevName {
|
||||||
|
pub fn new(name: String, id: usize) -> Self {
|
||||||
|
return DevName {
|
||||||
|
name: Arc::new(name),
|
||||||
|
id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn id(&self) -> usize {
|
||||||
|
return self.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Debug for DevName {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
return write!(f, "{}", self.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for DevName {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
return write!(f, "{}", self.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for DevName {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
return DevName {
|
||||||
|
name: self.name.clone(),
|
||||||
|
id: self.id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::hash::Hash for DevName {
|
||||||
|
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.name.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for DevName {
|
||||||
|
type Target = String;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
return self.name.as_ref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for DevName {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
return self.name == other.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for DevName {}
|
||||||
|
|
||||||
/// 设备应该实现的操作
|
/// 设备应该实现的操作
|
||||||
///
|
///
|
||||||
/// ## 注意
|
/// ## 注意
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use core::{any::Any, fmt::Debug};
|
use core::{any::Any, fmt::Debug};
|
||||||
|
|
||||||
use alloc::{
|
use alloc::{
|
||||||
collections::LinkedList,
|
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
@ -16,7 +15,7 @@ use crate::{
|
|||||||
driver::{
|
driver::{
|
||||||
base::{
|
base::{
|
||||||
block::{
|
block::{
|
||||||
block_device::{BlockDevName, BlockDevice, BlockId, GeneralBlockRange, LBA_SIZE},
|
block_device::{BlockDevice, BlockId, GeneralBlockRange, LBA_SIZE},
|
||||||
disk_info::Partition,
|
disk_info::Partition,
|
||||||
manager::{block_dev_manager, BlockDevMeta},
|
manager::{block_dev_manager, BlockDevMeta},
|
||||||
},
|
},
|
||||||
@ -24,7 +23,7 @@ use crate::{
|
|||||||
device::{
|
device::{
|
||||||
bus::Bus,
|
bus::Bus,
|
||||||
driver::{Driver, DriverCommonData},
|
driver::{Driver, DriverCommonData},
|
||||||
Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
|
DevName, Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
|
||||||
},
|
},
|
||||||
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
|
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
|
||||||
kset::KSet,
|
kset::KSet,
|
||||||
@ -103,7 +102,7 @@ pub struct VirtIOBlkManager {
|
|||||||
|
|
||||||
struct InnerVirtIOBlkManager {
|
struct InnerVirtIOBlkManager {
|
||||||
id_bmp: bitmap::StaticBitmap<{ VirtIOBlkManager::MAX_DEVICES }>,
|
id_bmp: bitmap::StaticBitmap<{ VirtIOBlkManager::MAX_DEVICES }>,
|
||||||
devname: [Option<BlockDevName>; VirtIOBlkManager::MAX_DEVICES],
|
devname: [Option<DevName>; VirtIOBlkManager::MAX_DEVICES],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtIOBlkManager {
|
impl VirtIOBlkManager {
|
||||||
@ -122,7 +121,7 @@ impl VirtIOBlkManager {
|
|||||||
self.inner.lock()
|
self.inner.lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alloc_id(&self) -> Option<BlockDevName> {
|
pub fn alloc_id(&self) -> Option<DevName> {
|
||||||
let mut inner = self.inner();
|
let mut inner = self.inner();
|
||||||
let idx = inner.id_bmp.first_false_index()?;
|
let idx = inner.id_bmp.first_false_index()?;
|
||||||
inner.id_bmp.set(idx, true);
|
inner.id_bmp.set(idx, true);
|
||||||
@ -132,9 +131,9 @@ impl VirtIOBlkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a new block device name like 'vda', 'vdb', etc.
|
/// Generate a new block device name like 'vda', 'vdb', etc.
|
||||||
fn format_name(id: usize) -> BlockDevName {
|
fn format_name(id: usize) -> DevName {
|
||||||
let x = (b'a' + id as u8) as char;
|
let x = (b'a' + id as u8) as char;
|
||||||
BlockDevName::new(format!("vd{}", x), id)
|
DevName::new(format!("vd{}", x), id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -204,7 +203,7 @@ impl VirtIOBlkDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BlockDevice for VirtIOBlkDevice {
|
impl BlockDevice for VirtIOBlkDevice {
|
||||||
fn dev_name(&self) -> &BlockDevName {
|
fn dev_name(&self) -> &DevName {
|
||||||
&self.blkdev_meta.devname
|
&self.blkdev_meta.devname
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,7 +348,7 @@ impl VirtIODevice for VirtIOBlkDevice {
|
|||||||
|
|
||||||
impl Device for VirtIOBlkDevice {
|
impl Device for VirtIOBlkDevice {
|
||||||
fn dev_type(&self) -> DeviceType {
|
fn dev_type(&self) -> DeviceType {
|
||||||
DeviceType::Net
|
DeviceType::Block
|
||||||
}
|
}
|
||||||
|
|
||||||
fn id_table(&self) -> IdTable {
|
fn id_table(&self) -> IdTable {
|
||||||
@ -479,7 +478,7 @@ fn virtio_blk_driver_init() -> Result<(), SystemError> {
|
|||||||
let driver = VirtIOBlkDriver::new();
|
let driver = VirtIOBlkDriver::new();
|
||||||
virtio_driver_manager()
|
virtio_driver_manager()
|
||||||
.register(driver.clone() as Arc<dyn VirtIODriver>)
|
.register(driver.clone() as Arc<dyn VirtIODriver>)
|
||||||
.expect("Add virtio net driver failed");
|
.expect("Add virtio blk driver failed");
|
||||||
unsafe {
|
unsafe {
|
||||||
VIRTIO_BLK_DRIVER = Some(driver);
|
VIRTIO_BLK_DRIVER = Some(driver);
|
||||||
}
|
}
|
||||||
@ -546,12 +545,12 @@ impl VirtIODriver for VirtIOBlkDriver {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn virtio_id_table(&self) -> LinkedList<crate::driver::virtio::VirtioDeviceId> {
|
fn virtio_id_table(&self) -> Vec<crate::driver::virtio::VirtioDeviceId> {
|
||||||
self.inner().virtio_driver_common.id_table.clone()
|
self.inner().virtio_driver_common.id_table.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_virtio_id(&self, id: VirtioDeviceId) {
|
fn add_virtio_id(&self, id: VirtioDeviceId) {
|
||||||
self.inner().virtio_driver_common.id_table.push_back(id);
|
self.inner().virtio_driver_common.id_table.push(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
kernel/src/driver/char/mod.rs
Normal file
1
kernel/src/driver/char/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod virtio_console;
|
736
kernel/src/driver/char/virtio_console.rs
Normal file
736
kernel/src/driver/char/virtio_console.rs
Normal file
@ -0,0 +1,736 @@
|
|||||||
|
use crate::{
|
||||||
|
driver::{
|
||||||
|
base::{
|
||||||
|
class::Class,
|
||||||
|
device::{
|
||||||
|
bus::Bus,
|
||||||
|
device_number::Major,
|
||||||
|
driver::{Driver, DriverCommonData},
|
||||||
|
DevName, Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
|
||||||
|
},
|
||||||
|
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
|
||||||
|
kset::KSet,
|
||||||
|
},
|
||||||
|
tty::{
|
||||||
|
console::ConsoleSwitch,
|
||||||
|
kthread::send_to_tty_refresh_thread,
|
||||||
|
termios::{WindowSize, TTY_STD_TERMIOS},
|
||||||
|
tty_core::{TtyCore, TtyCoreData},
|
||||||
|
tty_driver::{TtyDriver, TtyDriverManager, TtyDriverType, TtyOperation},
|
||||||
|
virtual_terminal::{vc_manager, virtual_console::VirtualConsoleData, VirtConsole},
|
||||||
|
},
|
||||||
|
video::console::dummycon::dummy_console,
|
||||||
|
virtio::{
|
||||||
|
sysfs::{virtio_bus, virtio_device_manager, virtio_driver_manager},
|
||||||
|
transport::VirtIOTransport,
|
||||||
|
virtio_drivers_error_to_system_error,
|
||||||
|
virtio_impl::HalImpl,
|
||||||
|
VirtIODevice, VirtIODeviceIndex, VirtIODriver, VirtIODriverCommonData, VirtioDeviceId,
|
||||||
|
VIRTIO_VENDOR_ID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
exception::{irqdesc::IrqReturn, IrqNumber},
|
||||||
|
filesystem::kernfs::KernFSInode,
|
||||||
|
init::initcall::INITCALL_POSTCORE,
|
||||||
|
libs::{
|
||||||
|
lazy_init::Lazy,
|
||||||
|
rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||||
|
spinlock::{SpinLock, SpinLockGuard},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use alloc::string::String;
|
||||||
|
use alloc::string::ToString;
|
||||||
|
use alloc::sync::{Arc, Weak};
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
use bitmap::traits::BitMapOps;
|
||||||
|
use core::fmt::Debug;
|
||||||
|
use core::fmt::Formatter;
|
||||||
|
use core::{
|
||||||
|
any::Any,
|
||||||
|
sync::atomic::{compiler_fence, Ordering},
|
||||||
|
};
|
||||||
|
use system_error::SystemError;
|
||||||
|
use unified_init::macros::unified_init;
|
||||||
|
use virtio_drivers::device::console::VirtIOConsole;
|
||||||
|
|
||||||
|
const VIRTIO_CONSOLE_BASENAME: &str = "virtio_console";
|
||||||
|
const HVC_MINOR: u32 = 0;
|
||||||
|
|
||||||
|
static mut VIRTIO_CONSOLE_DRIVER: Option<Arc<VirtIOConsoleDriver>> = None;
|
||||||
|
static mut TTY_HVC_DRIVER: Option<Arc<TtyDriver>> = None;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn tty_hvc_driver() -> &'static Arc<TtyDriver> {
|
||||||
|
unsafe { TTY_HVC_DRIVER.as_ref().unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn virtio_console(
|
||||||
|
transport: VirtIOTransport,
|
||||||
|
dev_id: Arc<DeviceId>,
|
||||||
|
dev_parent: Option<Arc<dyn Device>>,
|
||||||
|
) {
|
||||||
|
log::debug!(
|
||||||
|
"virtio_console: dev_id: {:?}, parent: {:?}",
|
||||||
|
dev_id,
|
||||||
|
dev_parent
|
||||||
|
);
|
||||||
|
let device = VirtIOConsoleDevice::new(transport, dev_id.clone());
|
||||||
|
if device.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let device = device.unwrap();
|
||||||
|
|
||||||
|
if let Some(dev_parent) = dev_parent {
|
||||||
|
device.set_dev_parent(Some(Arc::downgrade(&dev_parent)));
|
||||||
|
}
|
||||||
|
virtio_device_manager()
|
||||||
|
.device_add(device.clone() as Arc<dyn VirtIODevice>)
|
||||||
|
.expect("Add virtio console failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[cast_to([sync] VirtIODevice)]
|
||||||
|
#[cast_to([sync] Device)]
|
||||||
|
pub struct VirtIOConsoleDevice {
|
||||||
|
dev_name: Lazy<DevName>,
|
||||||
|
dev_id: Arc<DeviceId>,
|
||||||
|
_self_ref: Weak<Self>,
|
||||||
|
locked_kobj_state: LockedKObjectState,
|
||||||
|
inner: SpinLock<InnerVirtIOConsoleDevice>,
|
||||||
|
}
|
||||||
|
unsafe impl Send for VirtIOConsoleDevice {}
|
||||||
|
unsafe impl Sync for VirtIOConsoleDevice {}
|
||||||
|
|
||||||
|
impl VirtIOConsoleDevice {
|
||||||
|
pub fn new(transport: VirtIOTransport, dev_id: Arc<DeviceId>) -> Option<Arc<Self>> {
|
||||||
|
// 设置中断
|
||||||
|
if let Err(err) = transport.setup_irq(dev_id.clone()) {
|
||||||
|
log::error!(
|
||||||
|
"VirtIOConsoleDevice '{dev_id:?}' setup_irq failed: {:?}",
|
||||||
|
err
|
||||||
|
);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let irq = Some(transport.irq());
|
||||||
|
let device_inner = VirtIOConsole::<HalImpl, VirtIOTransport>::new(transport);
|
||||||
|
if let Err(e) = device_inner {
|
||||||
|
log::error!("VirtIOConsoleDevice '{dev_id:?}' create failed: {:?}", e);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut device_inner: VirtIOConsole<HalImpl, VirtIOTransport> = device_inner.unwrap();
|
||||||
|
device_inner.enable_interrupts();
|
||||||
|
|
||||||
|
let dev = Arc::new_cyclic(|self_ref| Self {
|
||||||
|
dev_id,
|
||||||
|
dev_name: Lazy::new(),
|
||||||
|
_self_ref: self_ref.clone(),
|
||||||
|
locked_kobj_state: LockedKObjectState::default(),
|
||||||
|
inner: SpinLock::new(InnerVirtIOConsoleDevice {
|
||||||
|
device_inner,
|
||||||
|
name: None,
|
||||||
|
virtio_index: None,
|
||||||
|
device_common: DeviceCommonData::default(),
|
||||||
|
kobject_common: KObjectCommonData::default(),
|
||||||
|
irq,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
Some(dev)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inner(&self) -> SpinLockGuard<InnerVirtIOConsoleDevice> {
|
||||||
|
self.inner.lock_irqsave()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct InnerVirtIOConsoleDevice {
|
||||||
|
device_inner: VirtIOConsole<HalImpl, VirtIOTransport>,
|
||||||
|
virtio_index: Option<VirtIODeviceIndex>,
|
||||||
|
name: Option<String>,
|
||||||
|
device_common: DeviceCommonData,
|
||||||
|
kobject_common: KObjectCommonData,
|
||||||
|
irq: Option<IrqNumber>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for InnerVirtIOConsoleDevice {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
f.debug_struct("InnerVirtIOConsoleDevice")
|
||||||
|
.field("virtio_index", &self.virtio_index)
|
||||||
|
.field("name", &self.name)
|
||||||
|
.field("device_common", &self.device_common)
|
||||||
|
.field("kobject_common", &self.kobject_common)
|
||||||
|
.field("irq", &self.irq)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KObject for VirtIOConsoleDevice {
|
||||||
|
fn as_any_ref(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
|
||||||
|
self.inner().kobject_common.kern_inode = inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inode(&self) -> Option<Arc<KernFSInode>> {
|
||||||
|
self.inner().kobject_common.kern_inode.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent(&self) -> Option<Weak<dyn KObject>> {
|
||||||
|
self.inner().kobject_common.parent.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
|
||||||
|
self.inner().kobject_common.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kset(&self) -> Option<Arc<KSet>> {
|
||||||
|
self.inner().kobject_common.kset.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kset(&self, kset: Option<Arc<KSet>>) {
|
||||||
|
self.inner().kobject_common.kset = kset;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||||
|
self.inner().kobject_common.kobj_type
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> String {
|
||||||
|
self.device_name()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_name(&self, _name: String) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
|
||||||
|
self.locked_kobj_state.read()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
|
||||||
|
self.locked_kobj_state.write()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kobj_state(&self, state: KObjectState) {
|
||||||
|
*self.locked_kobj_state.write() = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
|
||||||
|
self.inner().kobject_common.kobj_type = ktype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Device for VirtIOConsoleDevice {
|
||||||
|
fn dev_type(&self) -> DeviceType {
|
||||||
|
DeviceType::Char
|
||||||
|
}
|
||||||
|
|
||||||
|
fn id_table(&self) -> IdTable {
|
||||||
|
IdTable::new(VIRTIO_CONSOLE_BASENAME.to_string(), None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||||
|
self.inner().device_common.bus.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
|
||||||
|
self.inner().device_common.bus = bus;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn class(&self) -> Option<Arc<dyn Class>> {
|
||||||
|
let mut guard = self.inner();
|
||||||
|
let r = guard.device_common.class.clone()?.upgrade();
|
||||||
|
if r.is_none() {
|
||||||
|
guard.device_common.class = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_class(&self, class: Option<Weak<dyn Class>>) {
|
||||||
|
self.inner().device_common.class = class;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||||
|
let r = self.inner().device_common.driver.clone()?.upgrade();
|
||||||
|
if r.is_none() {
|
||||||
|
self.inner().device_common.driver = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
|
||||||
|
self.inner().device_common.driver = driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_dead(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_match(&self) -> bool {
|
||||||
|
self.inner().device_common.can_match
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_can_match(&self, can_match: bool) {
|
||||||
|
self.inner().device_common.can_match = can_match;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state_synced(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dev_parent(&self) -> Option<Weak<dyn Device>> {
|
||||||
|
self.inner().device_common.get_parent_weak_or_clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dev_parent(&self, parent: Option<Weak<dyn Device>>) {
|
||||||
|
self.inner().device_common.parent = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VirtIODevice for VirtIOConsoleDevice {
|
||||||
|
fn handle_irq(&self, _irq: IrqNumber) -> Result<IrqReturn, SystemError> {
|
||||||
|
let mut buf = [0u8; 8];
|
||||||
|
let mut index = 0;
|
||||||
|
// Read up to the size of the buffer
|
||||||
|
while index < buf.len() {
|
||||||
|
if let Ok(Some(c)) = self.inner().device_inner.recv(true) {
|
||||||
|
buf[index] = c;
|
||||||
|
index += 1;
|
||||||
|
} else {
|
||||||
|
break; // No more bytes to read
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
send_to_tty_refresh_thread(&buf[0..index]);
|
||||||
|
Ok(IrqReturn::Handled)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dev_id(&self) -> &Arc<DeviceId> {
|
||||||
|
&self.dev_id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_device_name(&self, name: String) {
|
||||||
|
self.inner().name = Some(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn device_name(&self) -> String {
|
||||||
|
self.inner()
|
||||||
|
.name
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| VIRTIO_CONSOLE_BASENAME.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_virtio_device_index(&self, index: VirtIODeviceIndex) {
|
||||||
|
self.inner().virtio_index = Some(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn virtio_device_index(&self) -> Option<VirtIODeviceIndex> {
|
||||||
|
self.inner().virtio_index
|
||||||
|
}
|
||||||
|
|
||||||
|
fn device_type_id(&self) -> u32 {
|
||||||
|
virtio_drivers::transport::DeviceType::Console as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vendor(&self) -> u32 {
|
||||||
|
VIRTIO_VENDOR_ID.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn irq(&self) -> Option<IrqNumber> {
|
||||||
|
self.inner().irq
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[cast_to([sync] VirtIODriver)]
|
||||||
|
#[cast_to([sync] Driver)]
|
||||||
|
struct VirtIOConsoleDriver {
|
||||||
|
inner: SpinLock<InnerVirtIOConsoleDriver>,
|
||||||
|
devices: RwLock<[Option<Arc<VirtIOConsoleDevice>>; Self::MAX_DEVICES]>,
|
||||||
|
kobj_state: LockedKObjectState,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VirtIOConsoleDriver {
|
||||||
|
const MAX_DEVICES: usize = 32;
|
||||||
|
|
||||||
|
pub fn new() -> Arc<Self> {
|
||||||
|
let inner = InnerVirtIOConsoleDriver {
|
||||||
|
virtio_driver_common: VirtIODriverCommonData::default(),
|
||||||
|
driver_common: DriverCommonData::default(),
|
||||||
|
kobj_common: KObjectCommonData::default(),
|
||||||
|
id_bmp: bitmap::StaticBitmap::new(),
|
||||||
|
devname: [const { None }; Self::MAX_DEVICES],
|
||||||
|
};
|
||||||
|
|
||||||
|
let id_table = VirtioDeviceId::new(
|
||||||
|
virtio_drivers::transport::DeviceType::Console as u32,
|
||||||
|
VIRTIO_VENDOR_ID.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = VirtIOConsoleDriver {
|
||||||
|
inner: SpinLock::new(inner),
|
||||||
|
kobj_state: LockedKObjectState::default(),
|
||||||
|
devices: RwLock::new([const { None }; Self::MAX_DEVICES]),
|
||||||
|
};
|
||||||
|
|
||||||
|
result.add_virtio_id(id_table);
|
||||||
|
Arc::new(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inner(&self) -> SpinLockGuard<InnerVirtIOConsoleDriver> {
|
||||||
|
self.inner.lock()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_install(
|
||||||
|
&self,
|
||||||
|
driver: Arc<TtyDriver>,
|
||||||
|
tty: Arc<TtyCore>,
|
||||||
|
vc: Arc<VirtConsole>,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
driver.standard_install(tty.clone())?;
|
||||||
|
vc.port().setup_internal_tty(Arc::downgrade(&tty));
|
||||||
|
tty.set_port(vc.port());
|
||||||
|
vc.devfs_setup()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct InnerVirtIOConsoleDriver {
|
||||||
|
id_bmp: bitmap::StaticBitmap<{ VirtIOConsoleDriver::MAX_DEVICES }>,
|
||||||
|
devname: [Option<DevName>; VirtIOConsoleDriver::MAX_DEVICES],
|
||||||
|
virtio_driver_common: VirtIODriverCommonData,
|
||||||
|
driver_common: DriverCommonData,
|
||||||
|
kobj_common: KObjectCommonData,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InnerVirtIOConsoleDriver {
|
||||||
|
fn alloc_id(&mut self) -> Option<DevName> {
|
||||||
|
let idx = self.id_bmp.first_false_index()?;
|
||||||
|
self.id_bmp.set(idx, true);
|
||||||
|
let name = Self::format_name(idx);
|
||||||
|
self.devname[idx] = Some(name.clone());
|
||||||
|
Some(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_name(id: usize) -> DevName {
|
||||||
|
DevName::new(format!("vport{}", id), id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free_id(&mut self, id: usize) {
|
||||||
|
if id >= VirtIOConsoleDriver::MAX_DEVICES {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.id_bmp.set(id, false);
|
||||||
|
self.devname[id] = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TtyOperation for VirtIOConsoleDriver {
|
||||||
|
fn open(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
|
||||||
|
if nr > buf.len() {
|
||||||
|
return Err(SystemError::EINVAL);
|
||||||
|
}
|
||||||
|
let index = tty.index();
|
||||||
|
if index >= VirtIOConsoleDriver::MAX_DEVICES {
|
||||||
|
return Err(SystemError::ENODEV);
|
||||||
|
}
|
||||||
|
|
||||||
|
let dev = self.devices.read()[index]
|
||||||
|
.clone()
|
||||||
|
.ok_or(SystemError::ENODEV)?;
|
||||||
|
let mut cnt = 0;
|
||||||
|
let mut inner = dev.inner();
|
||||||
|
for c in buf[0..nr].iter() {
|
||||||
|
if let Err(e) = inner.device_inner.send(*c) {
|
||||||
|
if cnt > 0 {
|
||||||
|
return Ok(cnt);
|
||||||
|
}
|
||||||
|
return Err(virtio_drivers_error_to_system_error(e));
|
||||||
|
} else {
|
||||||
|
cnt += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush_chars(&self, _tty: &TtyCoreData) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ioctl(&self, _tty: Arc<TtyCore>, _cmd: u32, _arg: usize) -> Result<(), SystemError> {
|
||||||
|
Err(SystemError::ENOIOCTLCMD)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close(&self, _tty: Arc<TtyCore>) -> Result<(), SystemError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resize(&self, tty: Arc<TtyCore>, winsize: WindowSize) -> Result<(), SystemError> {
|
||||||
|
*tty.core().window_size_write() = winsize;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
|
||||||
|
if tty.core().index() >= VirtIOConsoleDriver::MAX_DEVICES {
|
||||||
|
return Err(SystemError::ENODEV);
|
||||||
|
}
|
||||||
|
|
||||||
|
let dev = self.devices.read()[tty.core().index()]
|
||||||
|
.clone()
|
||||||
|
.ok_or(SystemError::ENODEV)?;
|
||||||
|
let info = dev.inner().device_inner.info();
|
||||||
|
let winsize = WindowSize::new(info.rows, info.columns, 1, 1);
|
||||||
|
|
||||||
|
*tty.core().window_size_write() = winsize;
|
||||||
|
let vc_data = Arc::new(SpinLock::new(VirtualConsoleData::new(usize::MAX)));
|
||||||
|
let mut vc_data_guard = vc_data.lock_irqsave();
|
||||||
|
vc_data_guard.set_driver_funcs(Arc::downgrade(&dummy_console()) as Weak<dyn ConsoleSwitch>);
|
||||||
|
vc_data_guard.init(
|
||||||
|
Some(tty.core().window_size().row.into()),
|
||||||
|
Some(tty.core().window_size().col.into()),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
drop(vc_data_guard);
|
||||||
|
|
||||||
|
let vc = VirtConsole::new(Some(vc_data));
|
||||||
|
let vc_index = vc_manager().alloc(vc.clone()).ok_or(SystemError::EBUSY)?;
|
||||||
|
self.do_install(driver, tty, vc.clone()).inspect_err(|_| {
|
||||||
|
vc_manager().free(vc_index);
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VirtIODriver for VirtIOConsoleDriver {
|
||||||
|
fn probe(&self, device: &Arc<dyn VirtIODevice>) -> Result<(), SystemError> {
|
||||||
|
log::debug!("VirtIOConsoleDriver::probe()");
|
||||||
|
let _dev = device
|
||||||
|
.clone()
|
||||||
|
.arc_any()
|
||||||
|
.downcast::<VirtIOConsoleDevice>()
|
||||||
|
.map_err(|_| {
|
||||||
|
log::error!(
|
||||||
|
"VirtIOConsoleDriver::probe() failed: device is not a VirtIO console device. Device: '{:?}'",
|
||||||
|
device.name()
|
||||||
|
);
|
||||||
|
SystemError::EINVAL
|
||||||
|
})?;
|
||||||
|
log::debug!("VirtIOConsoleDriver::probe() succeeded");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn virtio_id_table(&self) -> Vec<VirtioDeviceId> {
|
||||||
|
self.inner().virtio_driver_common.id_table.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_virtio_id(&self, id: VirtioDeviceId) {
|
||||||
|
self.inner().virtio_driver_common.id_table.push(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Driver for VirtIOConsoleDriver {
|
||||||
|
fn id_table(&self) -> Option<IdTable> {
|
||||||
|
Some(IdTable::new(VIRTIO_CONSOLE_BASENAME.to_string(), None))
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: 添加错误时,资源释放的逻辑
|
||||||
|
fn add_device(&self, device: Arc<dyn Device>) {
|
||||||
|
log::debug!("virtio console: add_device");
|
||||||
|
let virtio_con_dev = device.arc_any().downcast::<VirtIOConsoleDevice>().expect(
|
||||||
|
"VirtIOConsoleDriver::add_device() failed: device is not a VirtIOConsoleDevice",
|
||||||
|
);
|
||||||
|
if virtio_con_dev.dev_name.initialized() {
|
||||||
|
panic!("VirtIOConsoleDriver::add_device() failed: dev_name has already initialized for device: '{:?}'",
|
||||||
|
virtio_con_dev.dev_id(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
log::debug!("virtio console: add_device: to lock inner");
|
||||||
|
let mut inner = self.inner();
|
||||||
|
log::debug!("virtio console: add_device: inner.locked");
|
||||||
|
let dev_name = inner.alloc_id();
|
||||||
|
if dev_name.is_none() {
|
||||||
|
panic!("Failed to allocate ID for VirtIO console device: '{:?}', virtio console device limit exceeded.", virtio_con_dev.dev_id())
|
||||||
|
}
|
||||||
|
|
||||||
|
let dev_name = dev_name.unwrap();
|
||||||
|
|
||||||
|
virtio_con_dev.dev_name.init(dev_name);
|
||||||
|
|
||||||
|
inner
|
||||||
|
.driver_common
|
||||||
|
.devices
|
||||||
|
.push(virtio_con_dev.clone() as Arc<dyn Device>);
|
||||||
|
|
||||||
|
// avoid deadlock in `init_tty_device`
|
||||||
|
drop(inner);
|
||||||
|
|
||||||
|
let mut devices_fast_guard = self.devices.write();
|
||||||
|
let index = virtio_con_dev.dev_name.get().id();
|
||||||
|
if devices_fast_guard[index].is_none() {
|
||||||
|
devices_fast_guard[index] = Some(virtio_con_dev.clone());
|
||||||
|
} else {
|
||||||
|
panic!("VirtIOConsoleDriver::add_device() failed: device slot already occupied at index: {}", index);
|
||||||
|
}
|
||||||
|
// avoid deadlock in `init_tty_device`
|
||||||
|
drop(devices_fast_guard);
|
||||||
|
|
||||||
|
log::debug!("virtio console: add_device: to init tty device");
|
||||||
|
let r = tty_hvc_driver().init_tty_device(Some(index));
|
||||||
|
log::debug!(
|
||||||
|
"virtio console: add_device: init tty device done, index: {}, dev_name: {:?}",
|
||||||
|
index,
|
||||||
|
virtio_con_dev.dev_name.get(),
|
||||||
|
);
|
||||||
|
if let Err(e) = r {
|
||||||
|
log::error!(
|
||||||
|
"Failed to init tty device for virtio console device, index: {}, dev_name: {:?}, err: {:?}",
|
||||||
|
index,
|
||||||
|
virtio_con_dev.dev_name.get(),
|
||||||
|
e,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete_device(&self, device: &Arc<dyn Device>) {
|
||||||
|
let virtio_con_dev = device
|
||||||
|
.clone()
|
||||||
|
.arc_any()
|
||||||
|
.downcast::<VirtIOConsoleDevice>()
|
||||||
|
.expect(
|
||||||
|
"VirtIOConsoleDriver::delete_device() failed: device is not a VirtIOConsoleDevice",
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut guard = self.inner();
|
||||||
|
let mut devices_fast_guard = self.devices.write();
|
||||||
|
let index = guard
|
||||||
|
.driver_common
|
||||||
|
.devices
|
||||||
|
.iter()
|
||||||
|
.position(|dev| Arc::ptr_eq(device, dev))
|
||||||
|
.expect("VirtIOConsoleDriver::delete_device() failed: device not found");
|
||||||
|
|
||||||
|
guard.driver_common.devices.remove(index);
|
||||||
|
guard.free_id(virtio_con_dev.dev_name.get().id());
|
||||||
|
|
||||||
|
devices_fast_guard[index] = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn devices(&self) -> Vec<Arc<dyn Device>> {
|
||||||
|
self.inner().driver_common.devices.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||||
|
Some(Arc::downgrade(&virtio_bus()) as Weak<dyn Bus>)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KObject for VirtIOConsoleDriver {
|
||||||
|
fn as_any_ref(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
|
||||||
|
self.inner().kobj_common.kern_inode = inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inode(&self) -> Option<Arc<KernFSInode>> {
|
||||||
|
self.inner().kobj_common.kern_inode.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent(&self) -> Option<Weak<dyn KObject>> {
|
||||||
|
self.inner().kobj_common.parent.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
|
||||||
|
self.inner().kobj_common.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kset(&self) -> Option<Arc<KSet>> {
|
||||||
|
self.inner().kobj_common.kset.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kset(&self, kset: Option<Arc<KSet>>) {
|
||||||
|
self.inner().kobj_common.kset = kset;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||||
|
self.inner().kobj_common.kobj_type
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
|
||||||
|
self.inner().kobj_common.kobj_type = ktype;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> String {
|
||||||
|
VIRTIO_CONSOLE_BASENAME.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_name(&self, _name: String) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
|
||||||
|
self.kobj_state.read()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
|
||||||
|
self.kobj_state.write()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_kobj_state(&self, state: KObjectState) {
|
||||||
|
*self.kobj_state.write() = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unified_init(INITCALL_POSTCORE)]
|
||||||
|
fn virtio_console_driver_init() -> Result<(), SystemError> {
|
||||||
|
let driver = VirtIOConsoleDriver::new();
|
||||||
|
virtio_driver_manager()
|
||||||
|
.register(driver.clone() as Arc<dyn VirtIODriver>)
|
||||||
|
.expect("Add virtio console driver failed");
|
||||||
|
unsafe {
|
||||||
|
VIRTIO_CONSOLE_DRIVER = Some(driver.clone());
|
||||||
|
}
|
||||||
|
let hvc_tty_driver = TtyDriver::new(
|
||||||
|
VirtIOConsoleDriver::MAX_DEVICES.try_into().unwrap(),
|
||||||
|
"hvc",
|
||||||
|
0,
|
||||||
|
Major::HVC_MAJOR,
|
||||||
|
HVC_MINOR,
|
||||||
|
TtyDriverType::System,
|
||||||
|
*TTY_STD_TERMIOS,
|
||||||
|
driver.clone(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
let hvc_tty_driver = TtyDriverManager::tty_register_driver(hvc_tty_driver)?;
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
unsafe {
|
||||||
|
TTY_HVC_DRIVER = Some(hvc_tty_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
@ -1,15 +1,13 @@
|
|||||||
use super::{_port, hba::HbaCmdTable};
|
use super::{_port, hba::HbaCmdTable};
|
||||||
use crate::arch::MMArch;
|
use crate::arch::MMArch;
|
||||||
use crate::driver::base::block::block_device::{
|
use crate::driver::base::block::block_device::{BlockDevice, BlockId, GeneralBlockRange};
|
||||||
BlockDevName, BlockDevice, BlockId, GeneralBlockRange,
|
|
||||||
};
|
|
||||||
use crate::driver::base::block::disk_info::Partition;
|
use crate::driver::base::block::disk_info::Partition;
|
||||||
use crate::driver::base::block::manager::BlockDevMeta;
|
use crate::driver::base::block::manager::BlockDevMeta;
|
||||||
use crate::driver::base::class::Class;
|
use crate::driver::base::class::Class;
|
||||||
use crate::driver::base::device::bus::Bus;
|
use crate::driver::base::device::bus::Bus;
|
||||||
|
|
||||||
use crate::driver::base::device::driver::Driver;
|
use crate::driver::base::device::driver::Driver;
|
||||||
use crate::driver::base::device::{Device, DeviceType, IdTable};
|
use crate::driver::base::device::{DevName, Device, DeviceType, IdTable};
|
||||||
use crate::driver::base::kobject::{KObjType, KObject, KObjectState};
|
use crate::driver::base::kobject::{KObjType, KObject, KObjectState};
|
||||||
use crate::driver::base::kset::KSet;
|
use crate::driver::base::kset::KSet;
|
||||||
use crate::driver::disk::ahci::HBA_PxIS_TFES;
|
use crate::driver::disk::ahci::HBA_PxIS_TFES;
|
||||||
@ -520,7 +518,7 @@ impl Device for LockedAhciDisk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BlockDevice for LockedAhciDisk {
|
impl BlockDevice for LockedAhciDisk {
|
||||||
fn dev_name(&self) -> &BlockDevName {
|
fn dev_name(&self) -> &DevName {
|
||||||
&self.blkdev_meta.devname
|
&self.blkdev_meta.devname
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
pub mod acpi;
|
pub mod acpi;
|
||||||
pub mod base;
|
pub mod base;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
|
pub mod char;
|
||||||
pub mod clocksource;
|
pub mod clocksource;
|
||||||
pub mod disk;
|
pub mod disk;
|
||||||
pub mod firmware;
|
pub mod firmware;
|
||||||
|
@ -587,11 +587,13 @@ impl Drop for E1000EDevice {
|
|||||||
|
|
||||||
pub fn e1000e_init() {
|
pub fn e1000e_init() {
|
||||||
match e1000e_probe() {
|
match e1000e_probe() {
|
||||||
Ok(_code) => {
|
Ok(code) => {
|
||||||
|
if code == 1 {
|
||||||
info!("Successfully init e1000e device!");
|
info!("Successfully init e1000e device!");
|
||||||
}
|
}
|
||||||
Err(_error) => {
|
}
|
||||||
info!("Error occurred!");
|
Err(error) => {
|
||||||
|
info!("Failed to init e1000e device: {error:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -602,6 +604,7 @@ pub fn e1000e_probe() -> Result<u64, E1000EPciError> {
|
|||||||
if result.is_empty() {
|
if result.is_empty() {
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
let mut initialized = false;
|
||||||
for device in result {
|
for device in result {
|
||||||
let standard_device = device.as_standard_device().unwrap();
|
let standard_device = device.as_standard_device().unwrap();
|
||||||
if standard_device.common_header.vendor_id == 0x8086 {
|
if standard_device.common_header.vendor_id == 0x8086 {
|
||||||
@ -625,11 +628,16 @@ pub fn e1000e_probe() -> Result<u64, E1000EPciError> {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
)?;
|
)?;
|
||||||
e1000e_driver_init(e1000e);
|
e1000e_driver_init(e1000e);
|
||||||
|
initialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(1);
|
if initialized {
|
||||||
|
Ok(1)
|
||||||
|
} else {
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用到的e1000e寄存器结构体
|
// 用到的e1000e寄存器结构体
|
||||||
@ -787,6 +795,7 @@ const E1000E_TXD_CMD_RS: u8 = 1 << 3;
|
|||||||
|
|
||||||
/// E1000E驱动初始化过程中可能的错误
|
/// E1000E驱动初始化过程中可能的错误
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum E1000EPciError {
|
pub enum E1000EPciError {
|
||||||
// 获取到错误类型的BAR(IO BAR)
|
// 获取到错误类型的BAR(IO BAR)
|
||||||
// An IO BAR was provided rather than a memory BAR.
|
// An IO BAR was provided rather than a memory BAR.
|
||||||
|
@ -6,7 +6,6 @@ use core::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use alloc::{
|
use alloc::{
|
||||||
collections::LinkedList,
|
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
@ -108,7 +107,7 @@ impl VirtIONetDevice {
|
|||||||
let mac = wire::EthernetAddress::from_bytes(&driver_net.mac_address());
|
let mac = wire::EthernetAddress::from_bytes(&driver_net.mac_address());
|
||||||
debug!("VirtIONetDevice mac: {:?}", mac);
|
debug!("VirtIONetDevice mac: {:?}", mac);
|
||||||
let device_inner = VirtIONicDeviceInner::new(driver_net);
|
let device_inner = VirtIONicDeviceInner::new(driver_net);
|
||||||
|
device_inner.inner.lock_irqsave().enable_interrupts();
|
||||||
let dev = Arc::new(Self {
|
let dev = Arc::new(Self {
|
||||||
dev_id,
|
dev_id,
|
||||||
inner: SpinLock::new(InnerVirtIONetDevice {
|
inner: SpinLock::new(InnerVirtIONetDevice {
|
||||||
@ -259,7 +258,9 @@ impl Device for VirtIONetDevice {
|
|||||||
|
|
||||||
impl VirtIODevice for VirtIONetDevice {
|
impl VirtIODevice for VirtIONetDevice {
|
||||||
fn handle_irq(&self, _irq: IrqNumber) -> Result<IrqReturn, SystemError> {
|
fn handle_irq(&self, _irq: IrqNumber) -> Result<IrqReturn, SystemError> {
|
||||||
poll_ifaces_try_lock_onetime().ok();
|
if poll_ifaces_try_lock_onetime().is_err() {
|
||||||
|
log::error!("virtio_net: try lock failed");
|
||||||
|
}
|
||||||
return Ok(IrqReturn::Handled);
|
return Ok(IrqReturn::Handled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,12 +866,12 @@ impl VirtIODriver for VirtIONetDriver {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn virtio_id_table(&self) -> LinkedList<VirtioDeviceId> {
|
fn virtio_id_table(&self) -> Vec<VirtioDeviceId> {
|
||||||
self.inner().virtio_driver_common.id_table.clone()
|
self.inner().virtio_driver_common.id_table.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_virtio_id(&self, id: VirtioDeviceId) {
|
fn add_virtio_id(&self, id: VirtioDeviceId) {
|
||||||
self.inner().virtio_driver_common.id_table.push_back(id);
|
self.inner().virtio_driver_common.id_table.push(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::base::block::block_device::BlockDevName;
|
use super::base::device::DevName;
|
||||||
|
|
||||||
static mut SCSI_MANAGER: Option<ScsiManager> = None;
|
static mut SCSI_MANAGER: Option<ScsiManager> = None;
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ pub struct ScsiManager {
|
|||||||
|
|
||||||
struct InnerScsiManager {
|
struct InnerScsiManager {
|
||||||
id_bmp: bitmap::StaticBitmap<{ ScsiManager::MAX_DEVICES }>,
|
id_bmp: bitmap::StaticBitmap<{ ScsiManager::MAX_DEVICES }>,
|
||||||
devname: [Option<BlockDevName>; ScsiManager::MAX_DEVICES],
|
devname: [Option<DevName>; ScsiManager::MAX_DEVICES],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScsiManager {
|
impl ScsiManager {
|
||||||
@ -49,7 +49,7 @@ impl ScsiManager {
|
|||||||
self.inner.lock()
|
self.inner.lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alloc_id(&self) -> Option<BlockDevName> {
|
pub fn alloc_id(&self) -> Option<DevName> {
|
||||||
let mut inner = self.inner();
|
let mut inner = self.inner();
|
||||||
let idx = inner.id_bmp.first_false_index()?;
|
let idx = inner.id_bmp.first_false_index()?;
|
||||||
inner.id_bmp.set(idx, true);
|
inner.id_bmp.set(idx, true);
|
||||||
@ -59,9 +59,9 @@ impl ScsiManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a new block device name like 'sda', 'sdb', etc.
|
/// Generate a new block device name like 'sda', 'sdb', etc.
|
||||||
fn format_name(id: usize) -> BlockDevName {
|
fn format_name(id: usize) -> DevName {
|
||||||
let x = (b'a' + id as u8) as char;
|
let x = (b'a' + id as u8) as char;
|
||||||
BlockDevName::new(format!("sd{}", x), id)
|
DevName::new(format!("sd{}", x), id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -50,6 +50,7 @@ impl Drop for TtyCore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TtyCore {
|
impl TtyCore {
|
||||||
|
#[inline(never)]
|
||||||
pub fn new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self> {
|
pub fn new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self> {
|
||||||
let name = driver.tty_line_name(index);
|
let name = driver.tty_line_name(index);
|
||||||
let device_number = driver
|
let device_number = driver
|
||||||
@ -76,7 +77,6 @@ impl TtyCore {
|
|||||||
device_number,
|
device_number,
|
||||||
privete_fields: SpinLock::new(None),
|
privete_fields: SpinLock::new(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
return Arc::new(Self {
|
return Arc::new(Self {
|
||||||
core,
|
core,
|
||||||
line_discipline: Arc::new(NTtyLinediscipline {
|
line_discipline: Arc::new(NTtyLinediscipline {
|
||||||
|
@ -309,10 +309,16 @@ impl TtyDriver {
|
|||||||
} else {
|
} else {
|
||||||
idx = self.ida.lock().alloc().ok_or(SystemError::EBUSY)?;
|
idx = self.ida.lock().alloc().ok_or(SystemError::EBUSY)?;
|
||||||
}
|
}
|
||||||
|
log::debug!("init_tty_device: create TtyCore");
|
||||||
let tty = TtyCore::new(self.self_ref(), idx);
|
let tty = TtyCore::new(self.self_ref(), idx);
|
||||||
|
|
||||||
|
log::debug!("init_tty_device: to driver_install_tty");
|
||||||
self.driver_install_tty(tty.clone())?;
|
self.driver_install_tty(tty.clone())?;
|
||||||
|
log::debug!(
|
||||||
|
"init_tty_device: driver_install_tty done, index: {}, dev_name: {:?}",
|
||||||
|
idx,
|
||||||
|
tty.core().name(),
|
||||||
|
);
|
||||||
|
|
||||||
let core = tty.core();
|
let core = tty.core();
|
||||||
|
|
||||||
@ -321,18 +327,20 @@ impl TtyDriver {
|
|||||||
ports[core.index()].setup_internal_tty(Arc::downgrade(&tty));
|
ports[core.index()].setup_internal_tty(Arc::downgrade(&tty));
|
||||||
tty.set_port(ports[core.index()].clone());
|
tty.set_port(ports[core.index()].clone());
|
||||||
}
|
}
|
||||||
|
log::debug!("init_tty_device: to ldisc_setup");
|
||||||
TtyLdiscManager::ldisc_setup(tty.clone(), tty.core().link())?;
|
TtyLdiscManager::ldisc_setup(tty.clone(), tty.core().link())?;
|
||||||
|
|
||||||
// 在devfs创建对应的文件
|
// 在devfs创建对应的文件
|
||||||
|
|
||||||
|
log::debug!("init_tty_device: to new tty device");
|
||||||
let device = TtyDevice::new(
|
let device = TtyDevice::new(
|
||||||
core.name().clone(),
|
core.name().clone(),
|
||||||
IdTable::new(self.tty_line_name(idx), Some(*core.device_number())),
|
IdTable::new(self.tty_line_name(idx), Some(*core.device_number())),
|
||||||
super::tty_device::TtyType::Tty,
|
super::tty_device::TtyType::Tty,
|
||||||
);
|
);
|
||||||
|
log::debug!("init_tty_device: to devfs_register");
|
||||||
devfs_register(device.name_ref(), device.clone())?;
|
devfs_register(device.name_ref(), device.clone())?;
|
||||||
|
log::debug!("init_tty_device: to device_register");
|
||||||
device_register(device)?;
|
device_register(device)?;
|
||||||
Ok(tty)
|
Ok(tty)
|
||||||
}
|
}
|
||||||
@ -473,8 +481,8 @@ pub trait TtyOperation: Sync + Send + Debug {
|
|||||||
|
|
||||||
fn flush_chars(&self, tty: &TtyCoreData);
|
fn flush_chars(&self, tty: &TtyCoreData);
|
||||||
|
|
||||||
fn put_char(&self, _tty: &TtyCoreData, _ch: u8) -> Result<(), SystemError> {
|
fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> {
|
||||||
Err(SystemError::ENOSYS)
|
self.write(tty, &[ch], 1).map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
|
fn start(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
|
||||||
|
@ -58,6 +58,8 @@ lazy_static! {
|
|||||||
static ref VC_MANAGER: VirtConsoleManager = VirtConsoleManager::new();
|
static ref VC_MANAGER: VirtConsoleManager = VirtConsoleManager::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kernel_cmdline_param_kv!(CONSOLE_PARAM, console, "");
|
||||||
|
|
||||||
/// 获取虚拟终端管理器
|
/// 获取虚拟终端管理器
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn vc_manager() -> &'static VirtConsoleManager {
|
pub fn vc_manager() -> &'static VirtConsoleManager {
|
||||||
@ -228,7 +230,23 @@ impl VirtConsoleManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_default_vc(&self) {
|
pub fn setup_default_vc(&self) {
|
||||||
// todo: 从内核启动参数中获取
|
let mut console_value_str = CONSOLE_PARAM.value_str().unwrap_or("").trim();
|
||||||
|
if !console_value_str.is_empty() {
|
||||||
|
// 删除前缀/dev/
|
||||||
|
console_value_str = console_value_str
|
||||||
|
.strip_prefix("/dev/")
|
||||||
|
.unwrap_or(console_value_str);
|
||||||
|
if let Some(vc) = self.lookup_vc_by_tty_name(console_value_str) {
|
||||||
|
log::info!("Set vc by cmdline: {}", console_value_str);
|
||||||
|
self.set_current_vc(vc);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
panic!(
|
||||||
|
"virt console: set vc by cmdline failed, name: {}",
|
||||||
|
console_value_str
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for name in Self::DEFAULT_VC_NAMES.iter() {
|
for name in Self::DEFAULT_VC_NAMES.iter() {
|
||||||
if let Some(vc) = self.lookup_vc_by_tty_name(name) {
|
if let Some(vc) = self.lookup_vc_by_tty_name(name) {
|
||||||
log::info!("Set default vc with tty device: {}", name);
|
log::info!("Set default vc with tty device: {}", name);
|
||||||
@ -236,6 +254,7 @@ impl VirtConsoleManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
panic!("virt console: setup default vc failed");
|
panic!("virt console: setup default vc failed");
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use alloc::{collections::LinkedList, string::String, sync::Arc};
|
use alloc::{string::String, sync::Arc, vec::Vec};
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::exception::{irqdesc::IrqReturn, IrqNumber};
|
use crate::exception::{irqdesc::IrqReturn, IrqNumber};
|
||||||
@ -51,7 +51,7 @@ pub trait VirtIODevice: Device {
|
|||||||
pub trait VirtIODriver: Driver {
|
pub trait VirtIODriver: Driver {
|
||||||
fn probe(&self, device: &Arc<dyn VirtIODevice>) -> Result<(), SystemError>;
|
fn probe(&self, device: &Arc<dyn VirtIODevice>) -> Result<(), SystemError>;
|
||||||
|
|
||||||
fn virtio_id_table(&self) -> LinkedList<VirtioDeviceId>;
|
fn virtio_id_table(&self) -> Vec<VirtioDeviceId>;
|
||||||
|
|
||||||
fn add_virtio_id(&self, id: VirtioDeviceId);
|
fn add_virtio_id(&self, id: VirtioDeviceId);
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ int_like!(VirtIODeviceIndex, usize);
|
|||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct VirtIODriverCommonData {
|
pub struct VirtIODriverCommonData {
|
||||||
pub id_table: LinkedList<VirtioDeviceId>,
|
pub id_table: Vec<VirtioDeviceId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/include/linux/mod_devicetable.h#449
|
/// 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/include/linux/mod_devicetable.h#449
|
||||||
@ -75,3 +75,19 @@ impl VirtioDeviceId {
|
|||||||
Self { device, vendor }
|
Self { device, vendor }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn virtio_drivers_error_to_system_error(error: virtio_drivers::Error) -> SystemError {
|
||||||
|
match error {
|
||||||
|
virtio_drivers::Error::QueueFull => SystemError::ENOBUFS,
|
||||||
|
virtio_drivers::Error::NotReady => SystemError::EAGAIN_OR_EWOULDBLOCK,
|
||||||
|
virtio_drivers::Error::WrongToken => SystemError::EINVAL,
|
||||||
|
virtio_drivers::Error::AlreadyUsed => SystemError::EBUSY,
|
||||||
|
virtio_drivers::Error::InvalidParam => SystemError::EINVAL,
|
||||||
|
virtio_drivers::Error::DmaError => SystemError::ENOMEM,
|
||||||
|
virtio_drivers::Error::IoError => SystemError::EIO,
|
||||||
|
virtio_drivers::Error::Unsupported => SystemError::ENOSYS,
|
||||||
|
virtio_drivers::Error::ConfigSpaceTooSmall => SystemError::EINVAL,
|
||||||
|
virtio_drivers::Error::ConfigSpaceMissing => SystemError::EINVAL,
|
||||||
|
virtio_drivers::Error::SocketDeviceError(_) => SystemError::EIO,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -196,11 +196,14 @@ impl VirtIODeviceManager {
|
|||||||
dev.set_virtio_device_index(virtio_index);
|
dev.set_virtio_device_index(virtio_index);
|
||||||
dev.set_device_name(format!("virtio{}", virtio_index.data()));
|
dev.set_device_name(format!("virtio{}", virtio_index.data()));
|
||||||
|
|
||||||
|
log::debug!("virtio_device_add: dev: {:?}", dev);
|
||||||
|
// 添加设备到设备管理器
|
||||||
device_manager().add_device(dev.clone() as Arc<dyn Device>)?;
|
device_manager().add_device(dev.clone() as Arc<dyn Device>)?;
|
||||||
let r = device_manager()
|
let r = device_manager()
|
||||||
.add_groups(&(dev.clone() as Arc<dyn Device>), &[&VirtIODeviceAttrGroup]);
|
.add_groups(&(dev.clone() as Arc<dyn Device>), &[&VirtIODeviceAttrGroup]);
|
||||||
|
log::debug!("virtio_device_add: to setup irq");
|
||||||
self.setup_irq(&dev).ok();
|
self.setup_irq(&dev).ok();
|
||||||
|
log::debug!("virtio_device_add: setup irq done");
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use super::virtio_impl::HalImpl;
|
|||||||
use crate::driver::base::device::bus::Bus;
|
use crate::driver::base::device::bus::Bus;
|
||||||
use crate::driver::base::device::{Device, DeviceId};
|
use crate::driver::base::device::{Device, DeviceId};
|
||||||
use crate::driver::block::virtio_blk::virtio_blk;
|
use crate::driver::block::virtio_blk::virtio_blk;
|
||||||
|
use crate::driver::char::virtio_console::virtio_console;
|
||||||
use crate::driver::net::virtio_net::virtio_net;
|
use crate::driver::net::virtio_net::virtio_net;
|
||||||
use crate::driver::pci::pci::{
|
use crate::driver::pci::pci::{
|
||||||
get_pci_device_structures_mut_by_vendor_id, PciDeviceStructureGeneralDevice,
|
get_pci_device_structures_mut_by_vendor_id, PciDeviceStructureGeneralDevice,
|
||||||
@ -11,18 +12,24 @@ use crate::driver::pci::pci::{
|
|||||||
};
|
};
|
||||||
use crate::driver::pci::subsys::pci_bus;
|
use crate::driver::pci::subsys::pci_bus;
|
||||||
use crate::driver::virtio::transport::VirtIOTransport;
|
use crate::driver::virtio::transport::VirtIOTransport;
|
||||||
|
use crate::init::initcall::INITCALL_DEVICE;
|
||||||
|
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use log::{debug, error, warn};
|
use log::{debug, error, warn};
|
||||||
|
use system_error::SystemError;
|
||||||
|
use unified_init::macros::unified_init;
|
||||||
use virtio_drivers::transport::{DeviceType, Transport};
|
use virtio_drivers::transport::{DeviceType, Transport};
|
||||||
|
|
||||||
///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)
|
///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)
|
||||||
pub fn virtio_probe() {
|
#[unified_init(INITCALL_DEVICE)]
|
||||||
|
fn virtio_probe() -> Result<(), SystemError> {
|
||||||
#[cfg(not(target_arch = "riscv64"))]
|
#[cfg(not(target_arch = "riscv64"))]
|
||||||
virtio_probe_pci();
|
virtio_probe_pci();
|
||||||
virtio_probe_mmio();
|
virtio_probe_mmio();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -63,6 +70,7 @@ pub(super) fn virtio_device_init(
|
|||||||
DeviceType::GPU => {
|
DeviceType::GPU => {
|
||||||
warn!("Not support virtio_gpu device for now");
|
warn!("Not support virtio_gpu device for now");
|
||||||
}
|
}
|
||||||
|
DeviceType::Console => virtio_console(transport, dev_id, dev_parent),
|
||||||
DeviceType::Input => {
|
DeviceType::Input => {
|
||||||
warn!("Not support virtio_input device for now");
|
warn!("Not support virtio_input device for now");
|
||||||
}
|
}
|
||||||
|
@ -141,16 +141,21 @@ impl DevFS {
|
|||||||
.as_any_ref()
|
.as_any_ref()
|
||||||
.downcast_ref::<LockedDevFSInode>()
|
.downcast_ref::<LockedDevFSInode>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// 在 /dev/char 下创建设备节点
|
|
||||||
dev_char_inode.add_dev(name, device.clone())?;
|
|
||||||
|
|
||||||
// 特殊处理 tty 设备,挂载在 /dev 下
|
// 特殊处理 tty 设备,挂载在 /dev 下
|
||||||
if name.starts_with("tty") && name.len() > 3 {
|
if name.starts_with("tty") && name.len() > 3 {
|
||||||
dev_root_inode.add_dev(name, device.clone())?;
|
dev_root_inode.add_dev(name, device.clone())?;
|
||||||
}
|
} else if name.starts_with("hvc") && name.len() > 3 {
|
||||||
// ptmx设备
|
// 特殊处理 hvc 设备,挂载在 /dev 下
|
||||||
if name == "ptmx" {
|
|
||||||
dev_root_inode.add_dev(name, device.clone())?;
|
dev_root_inode.add_dev(name, device.clone())?;
|
||||||
|
} else if name == "console" {
|
||||||
|
dev_root_inode.add_dev(name, device.clone())?;
|
||||||
|
} else if name == "ptmx" {
|
||||||
|
// ptmx设备
|
||||||
|
dev_root_inode.add_dev(name, device.clone())?;
|
||||||
|
} else {
|
||||||
|
// 在 /dev/char 下创建设备节点
|
||||||
|
dev_char_inode.add_dev(name, device.clone())?;
|
||||||
}
|
}
|
||||||
device.set_fs(dev_char_inode.0.lock().fs.clone());
|
device.set_fs(dev_char_inode.0.lock().fs.clone());
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use system_error::SystemError;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{interrupt::TrapFrame, process::arch_switch_to_user},
|
arch::{interrupt::TrapFrame, process::arch_switch_to_user},
|
||||||
driver::{net::e1000e::e1000e::e1000e_init, virtio::virtio::virtio_probe},
|
driver::net::e1000e::e1000e::e1000e_init,
|
||||||
filesystem::vfs::core::mount_root_fs,
|
filesystem::vfs::core::mount_root_fs,
|
||||||
namespaces::NsProxy,
|
namespaces::NsProxy,
|
||||||
net::net_core::net_init,
|
net::net_core::net_init,
|
||||||
@ -45,7 +45,7 @@ fn kernel_init() -> Result<(), SystemError> {
|
|||||||
crate::driver::disk::ahci::ahci_init()
|
crate::driver::disk::ahci::ahci_init()
|
||||||
.inspect_err(|e| log::error!("ahci_init failed: {:?}", e))
|
.inspect_err(|e| log::error!("ahci_init failed: {:?}", e))
|
||||||
.ok();
|
.ok();
|
||||||
virtio_probe();
|
|
||||||
mount_root_fs().expect("Failed to mount root fs");
|
mount_root_fs().expect("Failed to mount root fs");
|
||||||
e1000e_init();
|
e1000e_init();
|
||||||
net_init().unwrap_or_else(|err| {
|
net_init().unwrap_or_else(|err| {
|
||||||
|
@ -35,6 +35,10 @@ impl SlabAllocator {
|
|||||||
Ok(nptr) => nptr.as_ptr(),
|
Ok(nptr) => nptr.as_ptr(),
|
||||||
Err(AllocationError::OutOfMemory) => {
|
Err(AllocationError::OutOfMemory) => {
|
||||||
let boxed_page = ObjectPage::new();
|
let boxed_page = ObjectPage::new();
|
||||||
|
assert_eq!(
|
||||||
|
(boxed_page.as_ref() as *const ObjectPage as usize) & (MMArch::PAGE_SIZE - 1),
|
||||||
|
0
|
||||||
|
);
|
||||||
let leaked_page = Box::leak(boxed_page);
|
let leaked_page = Box::leak(boxed_page);
|
||||||
self.zone
|
self.zone
|
||||||
.refill(layout, leaked_page)
|
.refill(layout, leaked_page)
|
||||||
|
@ -92,7 +92,8 @@ impl FsStruct {
|
|||||||
impl Namespace for MntNamespace {
|
impl Namespace for MntNamespace {
|
||||||
fn ns_common_to_ns(ns_common: Arc<NsCommon>) -> Arc<Self> {
|
fn ns_common_to_ns(ns_common: Arc<NsCommon>) -> Arc<Self> {
|
||||||
let ns_common_ptr = Arc::as_ptr(&ns_common);
|
let ns_common_ptr = Arc::as_ptr(&ns_common);
|
||||||
container_of!(ns_common_ptr, MntNamespace, ns_common)
|
// container_of!(ns_common_ptr, MntNamespace, ns_common)
|
||||||
|
panic!("not implemented")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,11 +82,14 @@ QEMU_SERIAL_LOG_FILE="../serial_opt.txt"
|
|||||||
QEMU_SERIAL="-serial file:${QEMU_SERIAL_LOG_FILE}"
|
QEMU_SERIAL="-serial file:${QEMU_SERIAL_LOG_FILE}"
|
||||||
QEMU_DRIVE="id=disk,file=${QEMU_DISK_IMAGE},if=none"
|
QEMU_DRIVE="id=disk,file=${QEMU_DISK_IMAGE},if=none"
|
||||||
QEMU_ACCELARATE=""
|
QEMU_ACCELARATE=""
|
||||||
QEMU_ARGUMENT=""
|
QEMU_ARGUMENT=" -no-reboot "
|
||||||
QEMU_DEVICES=""
|
QEMU_DEVICES=""
|
||||||
|
|
||||||
|
KERNEL_CMDLINE=""
|
||||||
|
|
||||||
BIOS_TYPE=""
|
BIOS_TYPE=""
|
||||||
#这个变量为true则使用virtio磁盘
|
#这个变量为true则使用virtio磁盘
|
||||||
VIRTIO_BLK_DEVICE=false
|
VIRTIO_BLK_DEVICE=true
|
||||||
# 如果qemu_accel不为空
|
# 如果qemu_accel不为空
|
||||||
if [ -n "${qemu_accel}" ]; then
|
if [ -n "${qemu_accel}" ]; then
|
||||||
QEMU_ACCELARATE=" -machine accel=${qemu_accel} "
|
QEMU_ACCELARATE=" -machine accel=${qemu_accel} "
|
||||||
@ -139,9 +142,13 @@ while true;do
|
|||||||
;;
|
;;
|
||||||
nographic)
|
nographic)
|
||||||
QEMU_SERIAL=" -serial chardev:mux -monitor chardev:mux -chardev stdio,id=mux,mux=on,signal=off,logfile=${QEMU_SERIAL_LOG_FILE} "
|
QEMU_SERIAL=" -serial chardev:mux -monitor chardev:mux -chardev stdio,id=mux,mux=on,signal=off,logfile=${QEMU_SERIAL_LOG_FILE} "
|
||||||
|
# 添加 virtio console 设备
|
||||||
|
QEMU_DEVICES+=" -device virtio-serial -device virtconsole,chardev=mux "
|
||||||
|
KERNEL_CMDLINE+=" console=/dev/hvc0 "
|
||||||
QEMU_MONITOR=""
|
QEMU_MONITOR=""
|
||||||
QEMU_ARGUMENT+=" --nographic "
|
QEMU_ARGUMENT+=" --nographic "
|
||||||
QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf "
|
QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf "
|
||||||
|
QEMU_ARGUMENT+="-append ${KERNEL_CMDLINE}"
|
||||||
|
|
||||||
;;
|
;;
|
||||||
esac;shift 2;;
|
esac;shift 2;;
|
||||||
@ -156,12 +163,15 @@ QEMU_DEVICES+="${QEMU_DEVICES_DISK} "
|
|||||||
QEMU_DEVICES+=" -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580 -device virtio-net-pci,vectors=5,netdev=hostnet0,id=net0 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
|
QEMU_DEVICES+=" -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580 -device virtio-net-pci,vectors=5,netdev=hostnet0,id=net0 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
|
||||||
# E1000E
|
# E1000E
|
||||||
# QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580 -net nic,model=e1000e,netdev=hostnet0,id=net0 -netdev user,id=hostnet1,hostfwd=tcp::12581-:12581 -device virtio-net-pci,vectors=5,netdev=hostnet1,id=net1 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
|
# QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580 -net nic,model=e1000e,netdev=hostnet0,id=net0 -netdev user,id=hostnet1,hostfwd=tcp::12581-:12581 -device virtio-net-pci,vectors=5,netdev=hostnet1,id=net1 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
|
||||||
|
|
||||||
|
|
||||||
QEMU_ARGUMENT+="-d ${QEMU_DISK_IMAGE} -m ${QEMU_MEMORY} -smp ${QEMU_SMP} -boot order=d ${QEMU_MONITOR} -d ${qemu_trace_std} "
|
QEMU_ARGUMENT+="-d ${QEMU_DISK_IMAGE} -m ${QEMU_MEMORY} -smp ${QEMU_SMP} -boot order=d ${QEMU_MONITOR} -d ${qemu_trace_std} "
|
||||||
|
|
||||||
QEMU_ARGUMENT+="-s ${QEMU_MACHINE} ${QEMU_CPU_FEATURES} ${QEMU_RTC_CLOCK} ${QEMU_SERIAL} -drive ${QEMU_DRIVE} ${QEMU_DEVICES} "
|
QEMU_ARGUMENT+="-s ${QEMU_MACHINE} ${QEMU_CPU_FEATURES} ${QEMU_RTC_CLOCK} ${QEMU_SERIAL} -drive ${QEMU_DRIVE} ${QEMU_DEVICES} "
|
||||||
QEMU_ARGUMENT+=" ${QEMU_SHM_OBJECT} "
|
QEMU_ARGUMENT+=" ${QEMU_SHM_OBJECT} "
|
||||||
QEMU_ARGUMENT+=" ${QEMU_ACCELARATE} "
|
QEMU_ARGUMENT+=" ${QEMU_ACCELARATE} "
|
||||||
|
|
||||||
|
QEMU_ARGUMENT+=" -D ../qemu.log "
|
||||||
|
|
||||||
|
|
||||||
# 安装riscv64的uboot
|
# 安装riscv64的uboot
|
||||||
|
Reference in New Issue
Block a user