mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-19 04:56:30 +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
|
||||
compile_commands.json
|
||||
/logs/
|
||||
*.log
|
||||
|
@ -57,7 +57,7 @@ system_error = { path = "crates/system_error" }
|
||||
uefi = { version = "=0.26.0", features = ["alloc"] }
|
||||
uefi-raw = "=0.5.0"
|
||||
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" }
|
||||
paste = "=1.0.14"
|
||||
slabmalloc = { path = "crates/rust-slabmalloc" }
|
||||
|
@ -7,6 +7,12 @@ pub struct BitMapCore<T: BitOps> {
|
||||
phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: BitOps> Default for BitMapCore<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BitOps> BitMapCore<T> {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
|
@ -2,6 +2,7 @@
|
||||
#![feature(core_intrinsics)]
|
||||
#![allow(incomplete_features)] // for const generics
|
||||
#![feature(generic_const_exprs)]
|
||||
#![deny(clippy::all)]
|
||||
#![allow(internal_features)]
|
||||
#![allow(clippy::needless_return)]
|
||||
|
||||
|
@ -23,7 +23,8 @@
|
||||
#![crate_name = "slabmalloc"]
|
||||
#![crate_type = "lib"]
|
||||
#![feature(maybe_uninit_as_bytes)]
|
||||
|
||||
#![deny(clippy::all)]
|
||||
#![allow(clippy::needless_return)]
|
||||
extern crate alloc;
|
||||
|
||||
mod pages;
|
||||
|
@ -33,7 +33,7 @@ impl Bitfield for [AtomicU64] {
|
||||
fn initialize(&mut self, for_size: usize, capacity: usize) {
|
||||
// Set everything to allocated
|
||||
for bitmap in self.iter_mut() {
|
||||
*bitmap = AtomicU64::new(u64::max_value());
|
||||
*bitmap = AtomicU64::new(u64::MAX);
|
||||
}
|
||||
|
||||
// Mark actual slots as free
|
||||
@ -56,7 +56,7 @@ impl Bitfield for [AtomicU64] {
|
||||
) -> Option<(usize, usize)> {
|
||||
for (base_idx, b) in self.iter().enumerate() {
|
||||
let bitval = b.load(Ordering::Relaxed);
|
||||
if bitval == u64::max_value() {
|
||||
if bitval == u64::MAX {
|
||||
continue;
|
||||
} else {
|
||||
let negated = !bitval;
|
||||
@ -117,7 +117,7 @@ impl Bitfield for [AtomicU64] {
|
||||
#[inline(always)]
|
||||
fn is_full(&self) -> bool {
|
||||
self.iter()
|
||||
.filter(|&x| x.load(Ordering::Relaxed) != u64::max_value())
|
||||
.filter(|&x| x.load(Ordering::Relaxed) != u64::MAX)
|
||||
.count()
|
||||
== 0
|
||||
}
|
||||
@ -268,10 +268,10 @@ impl<'a> ObjectPage<'a> {
|
||||
}
|
||||
|
||||
// These needs some more work to be really safe...
|
||||
unsafe impl<'a> Send for ObjectPage<'a> {}
|
||||
unsafe impl<'a> Sync for ObjectPage<'a> {}
|
||||
unsafe impl Send for ObjectPage<'_> {}
|
||||
unsafe impl Sync for ObjectPage<'_> {}
|
||||
|
||||
impl<'a> AllocablePage for ObjectPage<'a> {
|
||||
impl AllocablePage for ObjectPage<'_> {
|
||||
const SIZE: usize = OBJECT_PAGE_SIZE;
|
||||
|
||||
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 {
|
||||
write!(f, "ObjectPage")
|
||||
}
|
||||
@ -401,6 +401,8 @@ impl<'a, T: AllocablePage> PageList<'a, T> {
|
||||
});
|
||||
|
||||
self.elements -= 1;
|
||||
|
||||
#[allow(clippy::manual_inspect)]
|
||||
new_head.map(|node| {
|
||||
*node.prev() = Rawlink::none();
|
||||
*node.next() = Rawlink::none();
|
||||
@ -434,6 +436,7 @@ impl<'a, P: AllocablePage + 'a> Iterator for ObjectPageIterMut<'a, P> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'a mut P> {
|
||||
unsafe {
|
||||
#[allow(clippy::manual_inspect)]
|
||||
self.head.resolve_mut().map(|next| {
|
||||
self.head = match next.next().resolve_mut() {
|
||||
None => Rawlink::none(),
|
||||
|
@ -71,7 +71,7 @@ macro_rules! new_sc_allocator {
|
||||
SCAllocator {
|
||||
size: $size,
|
||||
allocation_count: 0,
|
||||
obj_per_page: obj_per_page,
|
||||
obj_per_page,
|
||||
empty_slabs: PageList::new(),
|
||||
slabs: PageList::new(),
|
||||
full_slabs: PageList::new(),
|
||||
|
@ -3,7 +3,7 @@ use crate::driver::{
|
||||
base::{
|
||||
device::{
|
||||
device_number::{DeviceNumber, Major},
|
||||
Device, DeviceError, IdTable, BLOCKDEVS,
|
||||
DevName, Device, DeviceError, IdTable, BLOCKDEVS,
|
||||
},
|
||||
map::{
|
||||
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},
|
||||
};
|
||||
|
||||
use alloc::{string::String, sync::Arc, vec::Vec};
|
||||
use core::{any::Any, fmt::Display, ops::Deref};
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use core::any::Any;
|
||||
use log::error;
|
||||
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;
|
||||
}
|
||||
|
||||
/// 块设备的名字
|
||||
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 块设备应该实现的操作
|
||||
pub trait BlockDevice: Device {
|
||||
/// # dev_name
|
||||
/// 返回块设备的名字
|
||||
fn dev_name(&self) -> &BlockDevName;
|
||||
fn dev_name(&self) -> &DevName;
|
||||
|
||||
fn blkdev_meta(&self) -> &BlockDevMeta;
|
||||
|
||||
|
@ -6,14 +6,14 @@ use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
|
||||
use crate::{
|
||||
driver::base::block::gendisk::GenDisk,
|
||||
driver::base::{block::gendisk::GenDisk, device::DevName},
|
||||
filesystem::mbr::MbrDiskPartionTable,
|
||||
init::initcall::INITCALL_POSTCORE,
|
||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||
};
|
||||
|
||||
use super::{
|
||||
block_device::{BlockDevName, BlockDevice, GeneralBlockRange},
|
||||
block_device::{BlockDevice, GeneralBlockRange},
|
||||
gendisk::GenDiskMap,
|
||||
};
|
||||
|
||||
@ -38,7 +38,7 @@ pub struct BlockDevManager {
|
||||
}
|
||||
|
||||
struct InnerBlockDevManager {
|
||||
disks: HashMap<BlockDevName, Arc<dyn BlockDevice>>,
|
||||
disks: HashMap<DevName, Arc<dyn BlockDevice>>,
|
||||
}
|
||||
impl BlockDevManager {
|
||||
pub fn new() -> Self {
|
||||
@ -207,7 +207,7 @@ impl BlockDevManager {
|
||||
}
|
||||
|
||||
pub struct BlockDevMeta {
|
||||
pub devname: BlockDevName,
|
||||
pub devname: DevName,
|
||||
inner: SpinLock<InnerBlockDevMeta>,
|
||||
}
|
||||
|
||||
@ -216,7 +216,7 @@ pub struct InnerBlockDevMeta {
|
||||
}
|
||||
|
||||
impl BlockDevMeta {
|
||||
pub fn new(devname: BlockDevName) -> Self {
|
||||
pub fn new(devname: DevName) -> Self {
|
||||
BlockDevMeta {
|
||||
devname,
|
||||
inner: SpinLock::new(InnerBlockDevMeta {
|
||||
|
@ -24,6 +24,8 @@ impl Major {
|
||||
pub const UNIX98_PTY_SLAVE_MAJOR: Self =
|
||||
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 {
|
||||
Major(x)
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
use core::intrinsics::unlikely;
|
||||
use core::{any::Any, fmt::Debug};
|
||||
use core::{fmt::Display, intrinsics::unlikely, ops::Deref};
|
||||
use system_error::SystemError;
|
||||
|
||||
use self::{
|
||||
@ -124,6 +124,69 @@ unsafe fn set_sys_devices_virtual_kset(kset: Arc<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 alloc::{
|
||||
collections::LinkedList,
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
@ -16,7 +15,7 @@ use crate::{
|
||||
driver::{
|
||||
base::{
|
||||
block::{
|
||||
block_device::{BlockDevName, BlockDevice, BlockId, GeneralBlockRange, LBA_SIZE},
|
||||
block_device::{BlockDevice, BlockId, GeneralBlockRange, LBA_SIZE},
|
||||
disk_info::Partition,
|
||||
manager::{block_dev_manager, BlockDevMeta},
|
||||
},
|
||||
@ -24,7 +23,7 @@ use crate::{
|
||||
device::{
|
||||
bus::Bus,
|
||||
driver::{Driver, DriverCommonData},
|
||||
Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
|
||||
DevName, Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
@ -103,7 +102,7 @@ pub struct VirtIOBlkManager {
|
||||
|
||||
struct InnerVirtIOBlkManager {
|
||||
id_bmp: bitmap::StaticBitmap<{ VirtIOBlkManager::MAX_DEVICES }>,
|
||||
devname: [Option<BlockDevName>; VirtIOBlkManager::MAX_DEVICES],
|
||||
devname: [Option<DevName>; VirtIOBlkManager::MAX_DEVICES],
|
||||
}
|
||||
|
||||
impl VirtIOBlkManager {
|
||||
@ -122,7 +121,7 @@ impl VirtIOBlkManager {
|
||||
self.inner.lock()
|
||||
}
|
||||
|
||||
pub fn alloc_id(&self) -> Option<BlockDevName> {
|
||||
pub fn alloc_id(&self) -> Option<DevName> {
|
||||
let mut inner = self.inner();
|
||||
let idx = inner.id_bmp.first_false_index()?;
|
||||
inner.id_bmp.set(idx, true);
|
||||
@ -132,9 +131,9 @@ impl VirtIOBlkManager {
|
||||
}
|
||||
|
||||
/// 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;
|
||||
BlockDevName::new(format!("vd{}", x), id)
|
||||
DevName::new(format!("vd{}", x), id)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -204,7 +203,7 @@ impl VirtIOBlkDevice {
|
||||
}
|
||||
|
||||
impl BlockDevice for VirtIOBlkDevice {
|
||||
fn dev_name(&self) -> &BlockDevName {
|
||||
fn dev_name(&self) -> &DevName {
|
||||
&self.blkdev_meta.devname
|
||||
}
|
||||
|
||||
@ -349,7 +348,7 @@ impl VirtIODevice for VirtIOBlkDevice {
|
||||
|
||||
impl Device for VirtIOBlkDevice {
|
||||
fn dev_type(&self) -> DeviceType {
|
||||
DeviceType::Net
|
||||
DeviceType::Block
|
||||
}
|
||||
|
||||
fn id_table(&self) -> IdTable {
|
||||
@ -479,7 +478,7 @@ fn virtio_blk_driver_init() -> Result<(), SystemError> {
|
||||
let driver = VirtIOBlkDriver::new();
|
||||
virtio_driver_manager()
|
||||
.register(driver.clone() as Arc<dyn VirtIODriver>)
|
||||
.expect("Add virtio net driver failed");
|
||||
.expect("Add virtio blk driver failed");
|
||||
unsafe {
|
||||
VIRTIO_BLK_DRIVER = Some(driver);
|
||||
}
|
||||
@ -546,12 +545,12 @@ impl VirtIODriver for VirtIOBlkDriver {
|
||||
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()
|
||||
}
|
||||
|
||||
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 crate::arch::MMArch;
|
||||
use crate::driver::base::block::block_device::{
|
||||
BlockDevName, BlockDevice, BlockId, GeneralBlockRange,
|
||||
};
|
||||
use crate::driver::base::block::block_device::{BlockDevice, BlockId, GeneralBlockRange};
|
||||
use crate::driver::base::block::disk_info::Partition;
|
||||
use crate::driver::base::block::manager::BlockDevMeta;
|
||||
use crate::driver::base::class::Class;
|
||||
use crate::driver::base::device::bus::Bus;
|
||||
|
||||
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::kset::KSet;
|
||||
use crate::driver::disk::ahci::HBA_PxIS_TFES;
|
||||
@ -520,7 +518,7 @@ impl Device for LockedAhciDisk {
|
||||
}
|
||||
|
||||
impl BlockDevice for LockedAhciDisk {
|
||||
fn dev_name(&self) -> &BlockDevName {
|
||||
fn dev_name(&self) -> &DevName {
|
||||
&self.blkdev_meta.devname
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
pub mod acpi;
|
||||
pub mod base;
|
||||
pub mod block;
|
||||
pub mod char;
|
||||
pub mod clocksource;
|
||||
pub mod disk;
|
||||
pub mod firmware;
|
||||
|
@ -587,11 +587,13 @@ impl Drop for E1000EDevice {
|
||||
|
||||
pub fn e1000e_init() {
|
||||
match e1000e_probe() {
|
||||
Ok(_code) => {
|
||||
info!("Successfully init e1000e device!");
|
||||
Ok(code) => {
|
||||
if code == 1 {
|
||||
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() {
|
||||
return Ok(0);
|
||||
}
|
||||
let mut initialized = false;
|
||||
for device in result {
|
||||
let standard_device = device.as_standard_device().unwrap();
|
||||
if standard_device.common_header.vendor_id == 0x8086 {
|
||||
@ -625,11 +628,16 @@ pub fn e1000e_probe() -> Result<u64, E1000EPciError> {
|
||||
.unwrap(),
|
||||
)?;
|
||||
e1000e_driver_init(e1000e);
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(1);
|
||||
if initialized {
|
||||
Ok(1)
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
// 用到的e1000e寄存器结构体
|
||||
@ -787,6 +795,7 @@ const E1000E_TXD_CMD_RS: u8 = 1 << 3;
|
||||
|
||||
/// E1000E驱动初始化过程中可能的错误
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum E1000EPciError {
|
||||
// 获取到错误类型的BAR(IO BAR)
|
||||
// An IO BAR was provided rather than a memory BAR.
|
||||
|
@ -6,7 +6,6 @@ use core::{
|
||||
};
|
||||
|
||||
use alloc::{
|
||||
collections::LinkedList,
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
@ -108,7 +107,7 @@ impl VirtIONetDevice {
|
||||
let mac = wire::EthernetAddress::from_bytes(&driver_net.mac_address());
|
||||
debug!("VirtIONetDevice mac: {:?}", mac);
|
||||
let device_inner = VirtIONicDeviceInner::new(driver_net);
|
||||
|
||||
device_inner.inner.lock_irqsave().enable_interrupts();
|
||||
let dev = Arc::new(Self {
|
||||
dev_id,
|
||||
inner: SpinLock::new(InnerVirtIONetDevice {
|
||||
@ -259,7 +258,9 @@ impl Device for VirtIONetDevice {
|
||||
|
||||
impl VirtIODevice for VirtIONetDevice {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -865,12 +866,12 @@ impl VirtIODriver for VirtIONetDriver {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn virtio_id_table(&self) -> LinkedList<VirtioDeviceId> {
|
||||
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_back(id);
|
||||
self.inner().virtio_driver_common.id_table.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ use crate::{
|
||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||
};
|
||||
|
||||
use super::base::block::block_device::BlockDevName;
|
||||
use super::base::device::DevName;
|
||||
|
||||
static mut SCSI_MANAGER: Option<ScsiManager> = None;
|
||||
|
||||
@ -30,7 +30,7 @@ pub struct ScsiManager {
|
||||
|
||||
struct InnerScsiManager {
|
||||
id_bmp: bitmap::StaticBitmap<{ ScsiManager::MAX_DEVICES }>,
|
||||
devname: [Option<BlockDevName>; ScsiManager::MAX_DEVICES],
|
||||
devname: [Option<DevName>; ScsiManager::MAX_DEVICES],
|
||||
}
|
||||
|
||||
impl ScsiManager {
|
||||
@ -49,7 +49,7 @@ impl ScsiManager {
|
||||
self.inner.lock()
|
||||
}
|
||||
|
||||
pub fn alloc_id(&self) -> Option<BlockDevName> {
|
||||
pub fn alloc_id(&self) -> Option<DevName> {
|
||||
let mut inner = self.inner();
|
||||
let idx = inner.id_bmp.first_false_index()?;
|
||||
inner.id_bmp.set(idx, true);
|
||||
@ -59,9 +59,9 @@ impl ScsiManager {
|
||||
}
|
||||
|
||||
/// 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;
|
||||
BlockDevName::new(format!("sd{}", x), id)
|
||||
DevName::new(format!("sd{}", x), id)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
@ -50,6 +50,7 @@ impl Drop for TtyCore {
|
||||
}
|
||||
|
||||
impl TtyCore {
|
||||
#[inline(never)]
|
||||
pub fn new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self> {
|
||||
let name = driver.tty_line_name(index);
|
||||
let device_number = driver
|
||||
@ -76,7 +77,6 @@ impl TtyCore {
|
||||
device_number,
|
||||
privete_fields: SpinLock::new(None),
|
||||
};
|
||||
|
||||
return Arc::new(Self {
|
||||
core,
|
||||
line_discipline: Arc::new(NTtyLinediscipline {
|
||||
|
@ -309,10 +309,16 @@ impl TtyDriver {
|
||||
} else {
|
||||
idx = self.ida.lock().alloc().ok_or(SystemError::EBUSY)?;
|
||||
}
|
||||
|
||||
log::debug!("init_tty_device: create TtyCore");
|
||||
let tty = TtyCore::new(self.self_ref(), idx);
|
||||
|
||||
log::debug!("init_tty_device: to driver_install_tty");
|
||||
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();
|
||||
|
||||
@ -321,18 +327,20 @@ impl TtyDriver {
|
||||
ports[core.index()].setup_internal_tty(Arc::downgrade(&tty));
|
||||
tty.set_port(ports[core.index()].clone());
|
||||
}
|
||||
|
||||
log::debug!("init_tty_device: to ldisc_setup");
|
||||
TtyLdiscManager::ldisc_setup(tty.clone(), tty.core().link())?;
|
||||
|
||||
// 在devfs创建对应的文件
|
||||
|
||||
log::debug!("init_tty_device: to new tty device");
|
||||
let device = TtyDevice::new(
|
||||
core.name().clone(),
|
||||
IdTable::new(self.tty_line_name(idx), Some(*core.device_number())),
|
||||
super::tty_device::TtyType::Tty,
|
||||
);
|
||||
|
||||
log::debug!("init_tty_device: to devfs_register");
|
||||
devfs_register(device.name_ref(), device.clone())?;
|
||||
log::debug!("init_tty_device: to device_register");
|
||||
device_register(device)?;
|
||||
Ok(tty)
|
||||
}
|
||||
@ -473,8 +481,8 @@ pub trait TtyOperation: Sync + Send + Debug {
|
||||
|
||||
fn flush_chars(&self, tty: &TtyCoreData);
|
||||
|
||||
fn put_char(&self, _tty: &TtyCoreData, _ch: u8) -> Result<(), SystemError> {
|
||||
Err(SystemError::ENOSYS)
|
||||
fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> {
|
||||
self.write(tty, &[ch], 1).map(|_| ())
|
||||
}
|
||||
|
||||
fn start(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
|
||||
|
@ -58,6 +58,8 @@ lazy_static! {
|
||||
static ref VC_MANAGER: VirtConsoleManager = VirtConsoleManager::new();
|
||||
}
|
||||
|
||||
kernel_cmdline_param_kv!(CONSOLE_PARAM, console, "");
|
||||
|
||||
/// 获取虚拟终端管理器
|
||||
#[inline]
|
||||
pub fn vc_manager() -> &'static VirtConsoleManager {
|
||||
@ -228,12 +230,29 @@ impl VirtConsoleManager {
|
||||
}
|
||||
|
||||
pub fn setup_default_vc(&self) {
|
||||
// todo: 从内核启动参数中获取
|
||||
for name in Self::DEFAULT_VC_NAMES.iter() {
|
||||
if let Some(vc) = self.lookup_vc_by_tty_name(name) {
|
||||
log::info!("Set default vc with tty device: {}", name);
|
||||
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() {
|
||||
if let Some(vc) = self.lookup_vc_by_tty_name(name) {
|
||||
log::info!("Set default vc with tty device: {}", name);
|
||||
self.set_current_vc(vc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 crate::exception::{irqdesc::IrqReturn, IrqNumber};
|
||||
@ -51,7 +51,7 @@ pub trait VirtIODevice: Device {
|
||||
pub trait VirtIODriver: Driver {
|
||||
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);
|
||||
}
|
||||
@ -60,7 +60,7 @@ int_like!(VirtIODeviceIndex, usize);
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
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
|
||||
@ -75,3 +75,19 @@ impl VirtioDeviceId {
|
||||
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_device_name(format!("virtio{}", virtio_index.data()));
|
||||
|
||||
log::debug!("virtio_device_add: dev: {:?}", dev);
|
||||
// 添加设备到设备管理器
|
||||
device_manager().add_device(dev.clone() as Arc<dyn Device>)?;
|
||||
let r = device_manager()
|
||||
.add_groups(&(dev.clone() as Arc<dyn Device>), &[&VirtIODeviceAttrGroup]);
|
||||
|
||||
log::debug!("virtio_device_add: to setup irq");
|
||||
self.setup_irq(&dev).ok();
|
||||
log::debug!("virtio_device_add: setup irq done");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ use super::virtio_impl::HalImpl;
|
||||
use crate::driver::base::device::bus::Bus;
|
||||
use crate::driver::base::device::{Device, DeviceId};
|
||||
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::pci::pci::{
|
||||
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::virtio::transport::VirtIOTransport;
|
||||
use crate::init::initcall::INITCALL_DEVICE;
|
||||
|
||||
use alloc::string::String;
|
||||
use alloc::sync::Arc;
|
||||
use alloc::vec::Vec;
|
||||
use log::{debug, error, warn};
|
||||
use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
use virtio_drivers::transport::{DeviceType, Transport};
|
||||
|
||||
///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)
|
||||
pub fn virtio_probe() {
|
||||
#[unified_init(INITCALL_DEVICE)]
|
||||
fn virtio_probe() -> Result<(), SystemError> {
|
||||
#[cfg(not(target_arch = "riscv64"))]
|
||||
virtio_probe_pci();
|
||||
virtio_probe_mmio();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -63,6 +70,7 @@ pub(super) fn virtio_device_init(
|
||||
DeviceType::GPU => {
|
||||
warn!("Not support virtio_gpu device for now");
|
||||
}
|
||||
DeviceType::Console => virtio_console(transport, dev_id, dev_parent),
|
||||
DeviceType::Input => {
|
||||
warn!("Not support virtio_input device for now");
|
||||
}
|
||||
|
@ -141,16 +141,21 @@ impl DevFS {
|
||||
.as_any_ref()
|
||||
.downcast_ref::<LockedDevFSInode>()
|
||||
.unwrap();
|
||||
// 在 /dev/char 下创建设备节点
|
||||
dev_char_inode.add_dev(name, device.clone())?;
|
||||
|
||||
// 特殊处理 tty 设备,挂载在 /dev 下
|
||||
if name.starts_with("tty") && name.len() > 3 {
|
||||
dev_root_inode.add_dev(name, device.clone())?;
|
||||
}
|
||||
// ptmx设备
|
||||
if name == "ptmx" {
|
||||
} else if name.starts_with("hvc") && name.len() > 3 {
|
||||
// 特殊处理 hvc 设备,挂载在 /dev 下
|
||||
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());
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
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,
|
||||
namespaces::NsProxy,
|
||||
net::net_core::net_init,
|
||||
@ -45,7 +45,7 @@ fn kernel_init() -> Result<(), SystemError> {
|
||||
crate::driver::disk::ahci::ahci_init()
|
||||
.inspect_err(|e| log::error!("ahci_init failed: {:?}", e))
|
||||
.ok();
|
||||
virtio_probe();
|
||||
|
||||
mount_root_fs().expect("Failed to mount root fs");
|
||||
e1000e_init();
|
||||
net_init().unwrap_or_else(|err| {
|
||||
|
@ -35,6 +35,10 @@ impl SlabAllocator {
|
||||
Ok(nptr) => nptr.as_ptr(),
|
||||
Err(AllocationError::OutOfMemory) => {
|
||||
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);
|
||||
self.zone
|
||||
.refill(layout, leaked_page)
|
||||
|
@ -92,7 +92,8 @@ impl FsStruct {
|
||||
impl Namespace for MntNamespace {
|
||||
fn ns_common_to_ns(ns_common: Arc<NsCommon>) -> Arc<Self> {
|
||||
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_DRIVE="id=disk,file=${QEMU_DISK_IMAGE},if=none"
|
||||
QEMU_ACCELARATE=""
|
||||
QEMU_ARGUMENT=""
|
||||
QEMU_ARGUMENT=" -no-reboot "
|
||||
QEMU_DEVICES=""
|
||||
|
||||
KERNEL_CMDLINE=""
|
||||
|
||||
BIOS_TYPE=""
|
||||
#这个变量为true则使用virtio磁盘
|
||||
VIRTIO_BLK_DEVICE=false
|
||||
VIRTIO_BLK_DEVICE=true
|
||||
# 如果qemu_accel不为空
|
||||
if [ -n "${qemu_accel}" ]; then
|
||||
QEMU_ACCELARATE=" -machine accel=${qemu_accel} "
|
||||
@ -139,9 +142,13 @@ while true;do
|
||||
;;
|
||||
nographic)
|
||||
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_ARGUMENT+=" --nographic "
|
||||
QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf "
|
||||
QEMU_ARGUMENT+="-append ${KERNEL_CMDLINE}"
|
||||
|
||||
;;
|
||||
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 "
|
||||
# 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_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+=" ${QEMU_SHM_OBJECT} "
|
||||
QEMU_ARGUMENT+=" ${QEMU_ACCELARATE} "
|
||||
|
||||
QEMU_ARGUMENT+=" -D ../qemu.log "
|
||||
|
||||
|
||||
# 安装riscv64的uboot
|
||||
|
Reference in New Issue
Block a user