mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 22:36:48 +00:00
pci重构+pcie支持 (#235)
* pci重构+pcie支持 * pci重构测试完成 * 修正makefile的问题 * 小修改 * 修改函数名字
This commit is contained in:
parent
5c9a63df83
commit
78bf93f02f
27
kernel/src/arch/mod.rs
Normal file
27
kernel/src/arch/mod.rs
Normal file
@ -0,0 +1,27 @@
|
||||
pub mod x86_64;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub use self::x86_64::pci::pci::X86_64PciArch as PciArch;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub use self::x86_64::*; //公开x86_64架构下的函数,使外界接口统一
|
||||
use crate::driver::pci::pci::{BusDeviceFunction, PciError, PciRoot, SegmentGroupNumber};
|
||||
/// TraitPciArch Pci架构相关函数,任何架构都应独立实现trait里的函数
|
||||
pub trait TraitPciArch {
|
||||
/// @brief 读取寄存器值,x86_64架构通过读取两个特定io端口实现
|
||||
/// @param bus_device_function 设备的唯一标识符
|
||||
/// @param offset 寄存器偏移值
|
||||
/// @return 读取到的值
|
||||
fn read_config(bus_device_function: &BusDeviceFunction, offset: u8) -> u32;
|
||||
/// @brief 写入寄存器值,x86_64架构通过读取两个特定io端口实现
|
||||
/// @param bus_device_function 设备的唯一标识符
|
||||
/// @param offset 寄存器偏移值
|
||||
/// @param data 要写入的值
|
||||
fn write_config(bus_device_function: &BusDeviceFunction, offset: u8, data: u32);
|
||||
/// @brief PCI域地址到存储器域地址的转换,x86_64架构为一一对应
|
||||
/// @param address PCI域地址
|
||||
/// @return Result<usize, PciError> 转换结果或出错原因
|
||||
fn address_pci_to_address_memory(address: usize) -> Result<usize, PciError>;
|
||||
/// @brief 获取Segement的root地址,x86_64架构为acpi mcfg表中读取
|
||||
/// @param segement 组id
|
||||
/// @return Result<PciRoot, PciError> 转换结果或出错原因
|
||||
fn ecam_root(segement: SegmentGroupNumber) -> Result<PciRoot, PciError>;
|
||||
}
|
@ -2,7 +2,7 @@ use crate::include::bindings::bindings::{process_control_block, switch_proc};
|
||||
|
||||
use core::sync::atomic::compiler_fence;
|
||||
|
||||
use super::fpu::{fp_state_save, fp_state_restore};
|
||||
use super::fpu::{fp_state_restore, fp_state_save};
|
||||
|
||||
/// @brief 切换进程的上下文(没有切换页表的动作)
|
||||
///
|
||||
|
@ -2,7 +2,8 @@
|
||||
pub mod asm;
|
||||
pub mod context;
|
||||
pub mod cpu;
|
||||
pub mod fpu;
|
||||
pub mod interrupt;
|
||||
pub mod mm;
|
||||
pub mod pci;
|
||||
pub mod sched;
|
||||
pub mod fpu;
|
||||
|
1
kernel/src/arch/x86_64/pci/mod.rs
Normal file
1
kernel/src/arch/x86_64/pci/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod pci;
|
70
kernel/src/arch/x86_64/pci/pci.rs
Normal file
70
kernel/src/arch/x86_64/pci/pci.rs
Normal file
@ -0,0 +1,70 @@
|
||||
use crate::arch::TraitPciArch;
|
||||
use crate::driver::acpi::acpi::mcfg_find_segment;
|
||||
use crate::driver::pci::pci::{
|
||||
BusDeviceFunction, PciError, PciRoot, SegmentGroupNumber, PORT_PCI_CONFIG_ADDRESS,
|
||||
PORT_PCI_CONFIG_DATA,
|
||||
};
|
||||
use crate::include::bindings::bindings::{
|
||||
acpi_get_MCFG, acpi_iter_SDT, acpi_system_description_table_header_t, io_in32, io_out32,
|
||||
};
|
||||
|
||||
use core::ffi::c_void;
|
||||
use core::ptr::NonNull;
|
||||
pub struct X86_64PciArch {}
|
||||
impl TraitPciArch for X86_64PciArch {
|
||||
fn read_config(bus_device_function: &BusDeviceFunction, offset: u8) -> u32 {
|
||||
// 构造pci配置空间地址
|
||||
let address = ((bus_device_function.bus as u32) << 16)
|
||||
| ((bus_device_function.device as u32) << 11)
|
||||
| ((bus_device_function.function as u32 & 7) << 8)
|
||||
| (offset & 0xfc) as u32
|
||||
| (0x80000000);
|
||||
let ret = unsafe {
|
||||
io_out32(PORT_PCI_CONFIG_ADDRESS, address);
|
||||
let temp = io_in32(PORT_PCI_CONFIG_DATA);
|
||||
temp
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
fn write_config(bus_device_function: &BusDeviceFunction, offset: u8, data: u32) {
|
||||
let address = ((bus_device_function.bus as u32) << 16)
|
||||
| ((bus_device_function.device as u32) << 11)
|
||||
| ((bus_device_function.function as u32 & 7) << 8)
|
||||
| (offset & 0xfc) as u32
|
||||
| (0x80000000);
|
||||
unsafe {
|
||||
io_out32(PORT_PCI_CONFIG_ADDRESS, address);
|
||||
// 写入数据
|
||||
io_out32(PORT_PCI_CONFIG_DATA, data);
|
||||
}
|
||||
}
|
||||
|
||||
fn address_pci_to_address_memory(address: usize) -> Result<usize, PciError> {
|
||||
Ok(address)
|
||||
}
|
||||
|
||||
fn ecam_root(segement: SegmentGroupNumber) -> Result<PciRoot, PciError> {
|
||||
let mut data: usize = 0;
|
||||
let data_point = &mut data;
|
||||
unsafe {
|
||||
acpi_iter_SDT(Some(acpi_get_MCFG), data_point as *mut usize as *mut c_void);
|
||||
};
|
||||
//kdebug!("{}",data);
|
||||
//loop{}
|
||||
let head = NonNull::new(data as *mut acpi_system_description_table_header_t).unwrap();
|
||||
let outcome = unsafe { mcfg_find_segment(head).as_ref() };
|
||||
for segmentgroupconfiguration in outcome {
|
||||
if segmentgroupconfiguration.segement_group_number == segement {
|
||||
return Ok(PciRoot {
|
||||
physical_address_base: segmentgroupconfiguration.base_address,
|
||||
mmio_base: None,
|
||||
segement_group_number: segement,
|
||||
bus_begin: segmentgroupconfiguration.bus_begin,
|
||||
bus_end: segmentgroupconfiguration.bus_end,
|
||||
});
|
||||
}
|
||||
}
|
||||
return Err(PciError::SegmentNotFound);
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
kernel_driver_subdirs:=video interrupt usb pci acpi disk keyboard mouse multiboot2 timers hid virtio
|
||||
kernel_driver_subdirs:=video interrupt usb pci acpi disk keyboard mouse multiboot2 timers hid
|
||||
|
||||
ECHO:
|
||||
@echo "$@"
|
||||
|
@ -103,6 +103,22 @@ bool acpi_get_HPET(const struct acpi_system_description_table_header_t *_iter_da
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取MCFG MCFG_description_table
|
||||
*
|
||||
* @param _iter_data 要被迭代的信息的结构体
|
||||
* @param _data 返回的MCFG表的虚拟地址
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool acpi_get_MCFG(const struct acpi_system_description_table_header_t *_iter_data, void *_data)
|
||||
{
|
||||
if (!(_iter_data->Signature[0] == 'M' && _iter_data->Signature[1] == 'C' && _iter_data->Signature[2] == 'F' && _iter_data->Signature[3] == 'G'))
|
||||
return false;
|
||||
*(ul *)_data = (ul)_iter_data;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化acpi模块
|
||||
*
|
||||
|
@ -193,5 +193,14 @@ bool acpi_get_MADT(const struct acpi_system_description_table_header_t *_iter_da
|
||||
*/
|
||||
bool acpi_get_HPET(const struct acpi_system_description_table_header_t *_iter_data, void *_data);
|
||||
|
||||
/**
|
||||
* @brief 获取MCFG MCFG_description_table
|
||||
*
|
||||
* @param _iter_data 要被迭代的信息的结构体
|
||||
* @param _data 返回的MCFG表的虚拟地址
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool acpi_get_MCFG(const struct acpi_system_description_table_header_t *_iter_data, void *_data);
|
||||
// 初始化acpi模块
|
||||
void acpi_init();
|
27
kernel/src/driver/acpi/acpi.rs
Normal file
27
kernel/src/driver/acpi/acpi.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use crate::driver::pci::pci::SegmentGroupNumber;
|
||||
use crate::include::bindings::bindings::acpi_system_description_table_header_t;
|
||||
use core::ptr::{slice_from_raw_parts_mut, NonNull};
|
||||
// MCFG表中的Segement配置部分,开始位置为44+16*n
|
||||
#[repr(C, packed)]
|
||||
pub struct Segement_Configuration_Space {
|
||||
pub base_address: u64,
|
||||
pub segement_group_number: SegmentGroupNumber,
|
||||
pub bus_begin: u8,
|
||||
pub bus_end: u8,
|
||||
pub reverse: u32,
|
||||
}
|
||||
|
||||
/// @brief 获取Segement_Configuration_Space的数量并返回对应数量的Segement_Configuration_Space的切片指针
|
||||
/// @param head acpi_system_description_table_header_t的指针
|
||||
/// @return NonNull<[Segement_Configuration_Space]>
|
||||
pub fn mcfg_find_segment(
|
||||
head: NonNull<acpi_system_description_table_header_t>,
|
||||
) -> NonNull<[Segement_Configuration_Space]> {
|
||||
let table_length = unsafe { (*head.as_ptr()).Length };
|
||||
let number_of_segments = ((table_length - 44) / 16) as u16;
|
||||
NonNull::new(slice_from_raw_parts_mut(
|
||||
(head.as_ptr() as usize + 44) as *mut _,
|
||||
number_of_segments as usize,
|
||||
))
|
||||
.unwrap()
|
||||
}
|
1
kernel/src/driver/acpi/mod.rs
Normal file
1
kernel/src/driver/acpi/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod acpi;
|
@ -1,16 +1,8 @@
|
||||
use alloc::{
|
||||
collections::BTreeMap,
|
||||
sync::Arc
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use core::fmt::Debug;
|
||||
use super::{driver::Driver, Device, DeviceState, IdTable};
|
||||
use crate::libs::spinlock::SpinLock;
|
||||
use super::{
|
||||
driver::Driver,
|
||||
DeviceState,
|
||||
IdTable,
|
||||
Device
|
||||
};
|
||||
use alloc::{collections::BTreeMap, sync::Arc};
|
||||
use core::fmt::Debug;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
/// @brief: 总线状态
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -3,9 +3,7 @@ use core::{any::Any, fmt::Debug};
|
||||
|
||||
/// @brief: Driver error
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
#[derive(PartialEq, Eq)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum DriverError {
|
||||
ProbeError,
|
||||
}
|
||||
|
@ -19,11 +19,7 @@ pub enum DeviceType {
|
||||
}
|
||||
|
||||
/// @brief: 设备标识符类型
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone)]
|
||||
#[derive(Hash)]
|
||||
#[derive(PartialOrd, PartialEq)]
|
||||
#[derive(Ord, Eq)]
|
||||
#[derive(Debug, Clone, Hash, PartialOrd, PartialEq, Ord, Eq)]
|
||||
pub struct IdTable(&'static str, u32);
|
||||
|
||||
/// @brief: 设备标识符操作方法集
|
||||
@ -38,8 +34,7 @@ impl IdTable {
|
||||
}
|
||||
|
||||
/// @brief: 设备当前状态
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum DeviceState {
|
||||
NotInitialized = 0,
|
||||
Initialized = 1,
|
||||
|
@ -1,2 +1,2 @@
|
||||
pub mod device;
|
||||
pub mod platform;
|
||||
pub mod device;
|
@ -1,23 +1,16 @@
|
||||
use alloc::{
|
||||
collections::{BTreeSet, BTreeMap},
|
||||
vec::Vec, sync::Arc
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use core::fmt::Debug;
|
||||
use super::device::{
|
||||
bus::{
|
||||
BusDriver,
|
||||
BusState,
|
||||
BUS_MANAGER,
|
||||
Bus
|
||||
},
|
||||
driver::Driver,
|
||||
IdTable,
|
||||
DeviceError,
|
||||
DeviceState,
|
||||
DeviceType, Device
|
||||
bus::{Bus, BusDriver, BusState, BUS_MANAGER},
|
||||
driver::Driver,
|
||||
Device, DeviceError, DeviceState, DeviceType, IdTable,
|
||||
};
|
||||
use crate::libs::{rwlock::RwLock, mutex::Mutex};
|
||||
use crate::libs::{mutex::Mutex, rwlock::RwLock};
|
||||
use alloc::{
|
||||
collections::{BTreeMap, BTreeSet},
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
use core::fmt::Debug;
|
||||
use lazy_static::lazy_static;
|
||||
use platform_device::PlatformDevice;
|
||||
use platform_driver::PlatformDriver;
|
||||
|
||||
@ -57,7 +50,7 @@ impl CompatibleTable {
|
||||
|
||||
/// @brief: platform总线驱动
|
||||
#[derive(Debug)]
|
||||
pub struct PlatformBusDriver {
|
||||
pub struct PlatformBusDriver {
|
||||
drivers: RwLock<BTreeMap<IdTable, Arc<dyn PlatformDriver>>>, // 总线上所有驱动
|
||||
devices: RwLock<BTreeMap<IdTable, Arc<dyn PlatformDevice>>>, // 总线上所有设备
|
||||
}
|
||||
@ -108,14 +101,17 @@ impl PlatformBusDriver {
|
||||
/// @parameter driver: platform类型驱动,该驱动需要实现PlatformDriver trait
|
||||
/// @return: 注册成功,返回Ok(()),,注册失败,返回BusError类型
|
||||
#[allow(dead_code)]
|
||||
fn register_platform_driver(&mut self, driver: Arc<dyn PlatformDriver>) -> Result<(), DeviceError> {
|
||||
fn register_platform_driver(
|
||||
&mut self,
|
||||
driver: Arc<dyn PlatformDriver>,
|
||||
) -> Result<(), DeviceError> {
|
||||
let id_table = driver.get_id_table();
|
||||
|
||||
let mut drivers = self.drivers.write();
|
||||
// 如果存在同类型的驱动,返回错误
|
||||
if drivers.contains_key(&id_table) {
|
||||
return Err(DeviceError::DriverExists);
|
||||
} else {
|
||||
} else {
|
||||
drivers.insert(id_table.clone(), driver.clone());
|
||||
return Ok(());
|
||||
}
|
||||
@ -135,7 +131,10 @@ impl PlatformBusDriver {
|
||||
/// @parameter driver: platform类型设备,该驱动需要实现PlatformDevice trait
|
||||
/// @return: 注册成功,返回Ok(()),,注册失败,返回BusError类型
|
||||
#[allow(dead_code)]
|
||||
fn register_platform_device(&mut self, device: Arc<dyn PlatformDevice>) -> Result<(), DeviceError> {
|
||||
fn register_platform_device(
|
||||
&mut self,
|
||||
device: Arc<dyn PlatformDevice>,
|
||||
) -> Result<(), DeviceError> {
|
||||
let id_table = device.get_id_table();
|
||||
|
||||
let mut devices = self.devices.write();
|
||||
@ -166,7 +165,10 @@ impl PlatformBusDriver {
|
||||
let devices = self.devices.read();
|
||||
|
||||
for (_dev_id_table, device) in devices.iter() {
|
||||
if device.get_compatible_table().matches(&driver.get_compatible_table()) {
|
||||
if device
|
||||
.get_compatible_table()
|
||||
.matches(&driver.get_compatible_table())
|
||||
{
|
||||
if !device.is_initialized() {
|
||||
// 设备未初始化,调用驱动probe函数
|
||||
match driver.probe(device.clone()) {
|
||||
@ -194,9 +196,12 @@ impl PlatformBusDriver {
|
||||
fn device_match_driver(&self, device: Arc<dyn PlatformDevice>) -> Result<(), DeviceError> {
|
||||
let drivers = self.drivers.read();
|
||||
for (_drv_id_table, driver) in &*drivers {
|
||||
if driver.get_compatible_table().matches(&device.get_compatible_table()) {
|
||||
if driver
|
||||
.get_compatible_table()
|
||||
.matches(&device.get_compatible_table())
|
||||
{
|
||||
match driver.probe(device.clone()) {
|
||||
Ok(_driver) => {
|
||||
Ok(_driver) => {
|
||||
// 将设备状态置为已初始化
|
||||
device.set_state(DeviceState::Initialized);
|
||||
return Ok(());
|
||||
@ -228,10 +233,9 @@ impl BusDriver for PlatformBusDriver {
|
||||
}
|
||||
|
||||
/// @brief: platform总线
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone)]
|
||||
pub struct Platform {
|
||||
state: Arc<Mutex<BusState>>, // 总线状态
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Platform {
|
||||
state: Arc<Mutex<BusState>>, // 总线状态
|
||||
driver: Option<Arc<PlatformBusDriver>>, // 总线驱动
|
||||
}
|
||||
|
||||
@ -266,7 +270,7 @@ impl Platform {
|
||||
match *state {
|
||||
BusState::Initialized => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief: 设置总线状态
|
||||
@ -288,7 +292,7 @@ impl Platform {
|
||||
return *state;
|
||||
}
|
||||
|
||||
/// @brief:
|
||||
/// @brief:
|
||||
/// @parameter: None
|
||||
/// @return: 总线状态
|
||||
#[inline]
|
||||
@ -332,16 +336,26 @@ lazy_static! {
|
||||
/// @return: None
|
||||
#[allow(dead_code)]
|
||||
pub fn platform_bus_init() {
|
||||
BUS_MANAGER.add_bus_driver(BUS_PLATFORM_DRIVER.get_id_table(), BUS_PLATFORM_DRIVER.clone());
|
||||
BUS_MANAGER.add_bus(BUS_PLATFORM_DEVICE.get_id_table(), BUS_PLATFORM_DEVICE.clone());
|
||||
BUS_MANAGER.add_bus_driver(
|
||||
BUS_PLATFORM_DRIVER.get_id_table(),
|
||||
BUS_PLATFORM_DRIVER.clone(),
|
||||
);
|
||||
BUS_MANAGER.add_bus(
|
||||
BUS_PLATFORM_DEVICE.get_id_table(),
|
||||
BUS_PLATFORM_DEVICE.clone(),
|
||||
);
|
||||
BUS_PLATFORM_DEVICE.set_state(BusState::Initialized);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn c_platform_bus_init() {
|
||||
BUS_MANAGER.add_bus_driver(BUS_PLATFORM_DRIVER.get_id_table(), BUS_PLATFORM_DRIVER.clone());
|
||||
BUS_MANAGER.add_bus(BUS_PLATFORM_DEVICE.get_id_table(), BUS_PLATFORM_DEVICE.clone());
|
||||
BUS_MANAGER.add_bus_driver(
|
||||
BUS_PLATFORM_DRIVER.get_id_table(),
|
||||
BUS_PLATFORM_DRIVER.clone(),
|
||||
);
|
||||
BUS_MANAGER.add_bus(
|
||||
BUS_PLATFORM_DEVICE.get_id_table(),
|
||||
BUS_PLATFORM_DEVICE.clone(),
|
||||
);
|
||||
BUS_PLATFORM_DEVICE.set_state(BusState::Initialized);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,12 +1,9 @@
|
||||
use alloc::sync::Arc;
|
||||
use super::{
|
||||
super::device::{
|
||||
Device,
|
||||
DeviceType,
|
||||
DeviceState
|
||||
},
|
||||
CompatibleTable, platform_driver::PlatformDriver
|
||||
super::device::{Device, DeviceState, DeviceType},
|
||||
platform_driver::PlatformDriver,
|
||||
CompatibleTable,
|
||||
};
|
||||
use alloc::sync::Arc;
|
||||
|
||||
/// @brief: 实现该trait的设备实例应挂载在platform总线上,
|
||||
/// 同时应该实现Device trait
|
||||
@ -35,4 +32,3 @@ pub trait PlatformDevice: Device {
|
||||
/// @return: None
|
||||
fn set_driver(&self, driver: Option<Arc<dyn PlatformDriver>>);
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,9 @@
|
||||
use alloc::sync::Arc;
|
||||
use super::{
|
||||
super::device::driver::{
|
||||
Driver,
|
||||
DriverError
|
||||
},
|
||||
super::device::driver::{Driver, DriverError},
|
||||
platform_device::PlatformDevice,
|
||||
CompatibleTable,
|
||||
};
|
||||
use alloc::sync::Arc;
|
||||
|
||||
/// @brief: 实现该trait的设备驱动实例应挂载在platform总线上,
|
||||
/// 同时应该实现Driver trait
|
||||
|
@ -6,10 +6,7 @@ use crate::filesystem::vfs::{
|
||||
};
|
||||
use crate::io::device::BlockDevice;
|
||||
use crate::syscall::SystemError;
|
||||
use crate::{
|
||||
libs::spinlock::SpinLock,
|
||||
time::TimeSpec,
|
||||
};
|
||||
use crate::{libs::spinlock::SpinLock, time::TimeSpec};
|
||||
use alloc::{
|
||||
string::String,
|
||||
sync::{Arc, Weak},
|
||||
|
@ -177,7 +177,6 @@ pub fn get_disks_by_name(name: String) -> Result<Arc<LockedAhciDisk>, SystemErro
|
||||
}
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
return Err(SystemError::ENXIO);
|
||||
|
||||
}
|
||||
|
||||
/// @brief: 通过 ctrl_num 和 port_num 获取 port
|
||||
|
@ -1,2 +1,2 @@
|
||||
pub mod ps2_keyboard;
|
||||
// pub mod ps2_keyboard_inode;
|
||||
// pub mod ps2_keyboard_inode;
|
||||
|
@ -1,3 +1,5 @@
|
||||
pub mod acpi;
|
||||
pub mod base;
|
||||
pub mod disk;
|
||||
pub mod keyboard;
|
||||
pub mod pci;
|
||||
@ -6,4 +8,3 @@ pub mod tty;
|
||||
pub mod uart;
|
||||
pub mod video;
|
||||
pub mod virtio;
|
||||
pub mod base;
|
||||
|
@ -14,7 +14,7 @@ struct List *pci_device_structure_list = NULL;
|
||||
*
|
||||
*/
|
||||
void pci_init();
|
||||
|
||||
void rs_pci_init();
|
||||
// pci设备结构的通用标题字段
|
||||
struct pci_device_structure_header_t
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
arch::interrupt::{cli, sti},
|
||||
include::bindings::bindings::{io_in8, io_out8}, syscall::SystemError,
|
||||
include::bindings::bindings::{io_in8, io_out8},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
pub struct RtcTime {
|
||||
|
@ -1,23 +1,26 @@
|
||||
use core::{ptr::null_mut, sync::atomic::{AtomicBool, Ordering}};
|
||||
use core::{
|
||||
ptr::null_mut,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
exception::softirq::{SoftirqNumber, SoftirqVec, softirq_vectors},
|
||||
exception::softirq::{softirq_vectors, SoftirqNumber, SoftirqVec},
|
||||
include::bindings::bindings::video_refresh_framebuffer,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VideoRefreshFramebuffer{
|
||||
running: AtomicBool
|
||||
pub struct VideoRefreshFramebuffer {
|
||||
running: AtomicBool,
|
||||
}
|
||||
|
||||
impl SoftirqVec for VideoRefreshFramebuffer {
|
||||
fn run(&self) {
|
||||
if self.set_run() == false{
|
||||
if self.set_run() == false {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
unsafe {
|
||||
video_refresh_framebuffer(null_mut());
|
||||
}
|
||||
@ -28,7 +31,7 @@ impl SoftirqVec for VideoRefreshFramebuffer {
|
||||
impl VideoRefreshFramebuffer {
|
||||
pub fn new() -> VideoRefreshFramebuffer {
|
||||
VideoRefreshFramebuffer {
|
||||
running: AtomicBool::new(false)
|
||||
running: AtomicBool::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +0,0 @@
|
||||
all: virtio.o
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
virtio.o: virtio.c
|
||||
$(CC) $(CFLAGS) -c virtio.c -o virtio.o
|
||||
|
@ -1,9 +1,9 @@
|
||||
//! PCI transport for VirtIO.
|
||||
use crate::arch::{PciArch, TraitPciArch};
|
||||
use crate::driver::pci::pci::{
|
||||
capabilities_offset, pci_bar_init, pci_enable_master, CapabilityIterator, DeviceFunction,
|
||||
PciDeviceBar, PciError, PCI_CAP_ID_VNDR,
|
||||
BusDeviceFunction, PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError,
|
||||
PciStandardDeviceBar, PCI_CAP_ID_VNDR,
|
||||
};
|
||||
use crate::include::bindings::bindings::pci_read_config;
|
||||
|
||||
use crate::libs::volatile::{
|
||||
volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly,
|
||||
@ -77,7 +77,7 @@ fn device_type(pci_device_id: u16) -> DeviceType {
|
||||
pub struct PciTransport {
|
||||
device_type: DeviceType,
|
||||
/// The bus, device and function identifier for the VirtIO device.
|
||||
device_function: DeviceFunction,
|
||||
bus_device_function: BusDeviceFunction,
|
||||
/// The common configuration structure within some BAR.
|
||||
common_cfg: NonNull<CommonCfg>,
|
||||
/// The start of the queue notification region within some BAR.
|
||||
@ -93,38 +93,26 @@ impl PciTransport {
|
||||
/// Construct a new PCI VirtIO device driver for the given device function on the given PCI
|
||||
/// root controller.
|
||||
///
|
||||
/// The PCI device must already have had its BARs allocated.
|
||||
pub fn new<H: Hal>(device_function: DeviceFunction) -> Result<Self, VirtioPciError> {
|
||||
let device_vendor = unsafe {
|
||||
let bar_temp = pci_read_config(
|
||||
device_function.bus,
|
||||
device_function.device,
|
||||
device_function.function,
|
||||
0,
|
||||
);
|
||||
bar_temp
|
||||
};
|
||||
let device_id = (device_vendor >> 16) as u16;
|
||||
let vendor_id = device_vendor as u16;
|
||||
if vendor_id != VIRTIO_VENDOR_ID {
|
||||
return Err(VirtioPciError::InvalidVendorId(vendor_id));
|
||||
///
|
||||
pub fn new<H: Hal>(
|
||||
device: &mut PciDeviceStructureGeneralDevice,
|
||||
) -> Result<Self, VirtioPciError> {
|
||||
let header = &device.common_header;
|
||||
let bus_device_function = header.bus_device_function;
|
||||
if header.vendor_id != VIRTIO_VENDOR_ID {
|
||||
return Err(VirtioPciError::InvalidVendorId(header.vendor_id));
|
||||
}
|
||||
let device_type = device_type(device_id);
|
||||
let device_type = device_type(header.device_id);
|
||||
// Find the PCI capabilities we need.
|
||||
let mut common_cfg = None;
|
||||
let mut notify_cfg = None;
|
||||
let mut notify_off_multiplier = 0;
|
||||
let mut isr_cfg = None;
|
||||
let mut device_cfg = None;
|
||||
device.bar_init().unwrap()?;
|
||||
device.enable_master();
|
||||
//device_capability为迭代器,遍历其相当于遍历所有的cap空间
|
||||
let device_capability = CapabilityIterator {
|
||||
device_function: device_function,
|
||||
next_capability_offset: capabilities_offset(device_function),
|
||||
};
|
||||
|
||||
let device_bar = pci_bar_init(device_function)?;
|
||||
pci_enable_master(device_function);
|
||||
for capability in device_capability {
|
||||
for capability in device.capabilities().unwrap() {
|
||||
if capability.id != PCI_CAP_ID_VNDR {
|
||||
continue;
|
||||
}
|
||||
@ -134,33 +122,16 @@ impl PciTransport {
|
||||
continue;
|
||||
}
|
||||
let struct_info = VirtioCapabilityInfo {
|
||||
bar: unsafe {
|
||||
let temp = pci_read_config(
|
||||
device_function.bus,
|
||||
device_function.device,
|
||||
device_function.function,
|
||||
capability.offset + CAP_BAR_OFFSET,
|
||||
);
|
||||
temp as u8
|
||||
},
|
||||
offset: unsafe {
|
||||
let temp = pci_read_config(
|
||||
device_function.bus,
|
||||
device_function.device,
|
||||
device_function.function,
|
||||
capability.offset + CAP_BAR_OFFSET_OFFSET,
|
||||
);
|
||||
temp
|
||||
},
|
||||
length: unsafe {
|
||||
let temp = pci_read_config(
|
||||
device_function.bus,
|
||||
device_function.device,
|
||||
device_function.function,
|
||||
capability.offset + CAP_LENGTH_OFFSET,
|
||||
);
|
||||
temp
|
||||
},
|
||||
bar: PciArch::read_config(&bus_device_function, capability.offset + CAP_BAR_OFFSET)
|
||||
as u8,
|
||||
offset: PciArch::read_config(
|
||||
&bus_device_function,
|
||||
capability.offset + CAP_BAR_OFFSET_OFFSET,
|
||||
),
|
||||
length: PciArch::read_config(
|
||||
&bus_device_function,
|
||||
capability.offset + CAP_LENGTH_OFFSET,
|
||||
),
|
||||
};
|
||||
|
||||
match cfg_type {
|
||||
@ -169,15 +140,10 @@ impl PciTransport {
|
||||
}
|
||||
VIRTIO_PCI_CAP_NOTIFY_CFG if cap_len >= 20 && notify_cfg.is_none() => {
|
||||
notify_cfg = Some(struct_info);
|
||||
notify_off_multiplier = unsafe {
|
||||
let temp = pci_read_config(
|
||||
device_function.bus,
|
||||
device_function.device,
|
||||
device_function.function,
|
||||
capability.offset + CAP_NOTIFY_OFF_MULTIPLIER_OFFSET,
|
||||
);
|
||||
temp
|
||||
};
|
||||
notify_off_multiplier = PciArch::read_config(
|
||||
&bus_device_function,
|
||||
capability.offset + CAP_NOTIFY_OFF_MULTIPLIER_OFFSET,
|
||||
);
|
||||
}
|
||||
VIRTIO_PCI_CAP_ISR_CFG if isr_cfg.is_none() => {
|
||||
isr_cfg = Some(struct_info);
|
||||
@ -190,7 +156,7 @@ impl PciTransport {
|
||||
}
|
||||
|
||||
let common_cfg = get_bar_region::<_>(
|
||||
&device_bar,
|
||||
&device.standard_device_bar,
|
||||
&common_cfg.ok_or(VirtioPciError::MissingCommonConfig)?,
|
||||
)?;
|
||||
|
||||
@ -201,19 +167,22 @@ impl PciTransport {
|
||||
));
|
||||
}
|
||||
//kdebug!("notify.offset={},notify.length={}",notify_cfg.offset,notify_cfg.length);
|
||||
let notify_region = get_bar_region_slice::<_>(&device_bar, ¬ify_cfg)?;
|
||||
let notify_region = get_bar_region_slice::<_>(&device.standard_device_bar, ¬ify_cfg)?;
|
||||
let isr_status = get_bar_region::<_>(
|
||||
&device_bar,
|
||||
&device.standard_device_bar,
|
||||
&isr_cfg.ok_or(VirtioPciError::MissingIsrConfig)?,
|
||||
)?;
|
||||
let config_space = if let Some(device_cfg) = device_cfg {
|
||||
Some(get_bar_region_slice::<_>(&device_bar, &device_cfg)?)
|
||||
Some(get_bar_region_slice::<_>(
|
||||
&device.standard_device_bar,
|
||||
&device_cfg,
|
||||
)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(Self {
|
||||
device_type,
|
||||
device_function,
|
||||
bus_device_function,
|
||||
common_cfg,
|
||||
notify_region,
|
||||
notify_off_multiplier,
|
||||
@ -487,7 +456,7 @@ impl From<PciError> for VirtioPciError {
|
||||
///@param device_bar 存储bar信息的结构体 struct_info 存储cfg空间的位置信息
|
||||
///@return Result<NonNull<T>, VirtioPciError> 成功则返回对应类型的指针,失败则返回Error
|
||||
fn get_bar_region<T>(
|
||||
device_bar: &PciDeviceBar,
|
||||
device_bar: &PciStandardDeviceBar,
|
||||
struct_info: &VirtioCapabilityInfo,
|
||||
) -> Result<NonNull<T>, VirtioPciError> {
|
||||
let bar_info = device_bar.get_bar(struct_info.bar)?;
|
||||
@ -521,7 +490,7 @@ fn get_bar_region<T>(
|
||||
///@param device_bar 存储bar信息的结构体 struct_info 存储cfg空间的位置信息切片的指针
|
||||
///@return Result<NonNull<[T]>, VirtioPciError> 成功则返回对应类型的指针切片,失败则返回Error
|
||||
fn get_bar_region_slice<T>(
|
||||
device_bar: &PciDeviceBar,
|
||||
device_bar: &PciStandardDeviceBar,
|
||||
struct_info: &VirtioCapabilityInfo,
|
||||
) -> Result<NonNull<[T]>, VirtioPciError> {
|
||||
let ptr = get_bar_region::<T>(device_bar, struct_info)?;
|
||||
|
@ -1,46 +0,0 @@
|
||||
#include "virtio.h"
|
||||
#include <common/kprint.h>
|
||||
#include <common/errno.h>
|
||||
#include <driver/pci/pci.h>
|
||||
|
||||
#define MAX_NET_NUM 8 // pci总线上的net设备的最大数量
|
||||
|
||||
// 在pci总线上寻找到net设备控制器的header
|
||||
static struct pci_device_structure_header_t *net_pdevs[MAX_NET_NUM];
|
||||
static int net_pdevs_count = 0;
|
||||
static struct pci_device_structure_header_t *virtio_net_pdev;
|
||||
static int virtio_net_pdev_count = 0;
|
||||
static uint8_t NETWORK_CLASS = 0x2;
|
||||
static uint8_t ETHERNET_SUBCLASS = 0x0;
|
||||
|
||||
/**
|
||||
* @brief 获取virtio-net MMIO映射的虚拟地址
|
||||
* @param virt_addr 外部传入的虚拟地址指针
|
||||
* @return 获取成功,返回0,失败,返回错误码
|
||||
*/
|
||||
uint8_t get_virtio_net_device(uint8_t * bus, uint8_t *device,uint8_t * function)
|
||||
{
|
||||
// 获取所有net-pci设备的列表
|
||||
pci_get_device_structure(NETWORK_CLASS, ETHERNET_SUBCLASS, net_pdevs, &net_pdevs_count);
|
||||
//检测其中的virt-io-net设备
|
||||
for(int i = 0; i < net_pdevs_count;i++) {
|
||||
struct pci_device_structure_general_device_t *dev = net_pdevs[i];
|
||||
if(net_pdevs[i]->Vendor_ID==0x1AF4 && net_pdevs[i]->Device_ID>=0x1000 && net_pdevs[i]->Device_ID<=0x103F && dev->Subsystem_ID==1)
|
||||
{
|
||||
virtio_net_pdev=net_pdevs[i];
|
||||
virtio_net_pdev_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (virtio_net_pdev_count == 0) {
|
||||
kwarn("There is no virtio-net device in this computer!");
|
||||
return NOT_FOUND_DEVICE;
|
||||
}
|
||||
if (virtio_net_pdev->Command==0) {
|
||||
kwarn("The virtio-net device isn't support mmio!");
|
||||
return NOT_SUPPORTE_MMIO;
|
||||
}
|
||||
*bus=virtio_net_pdev->bus;
|
||||
*device=virtio_net_pdev->device;
|
||||
*function=virtio_net_pdev->func;
|
||||
}
|
@ -1,12 +1,5 @@
|
||||
#pragma once
|
||||
#include <common/glib.h>
|
||||
|
||||
#define GET_VIRTADDRESS_SUCCESS 0
|
||||
#define NOT_FOUND_DEVICE 1
|
||||
#define NOT_SUPPORTE_MMIO 2
|
||||
#define GET_VIRTADDRESS_FAILURE 3
|
||||
|
||||
// 获取virtio-net 设备
|
||||
uint8_t get_virtio_net_device(uint8_t * bus, uint8_t *device,uint8_t * function);
|
||||
//寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备后续也可添加)
|
||||
void c_virtio_probe();
|
||||
|
@ -1,53 +1,42 @@
|
||||
use super::transport_pci::PciTransport;
|
||||
use super::virtio_impl::HalImpl;
|
||||
use crate::driver::pci::pci::DeviceFunction;
|
||||
use crate::include::bindings::bindings::get_virtio_net_device;
|
||||
use crate::driver::pci::pci::PciDeviceStructureGeneralDevice;
|
||||
use crate::driver::pci::pci::{
|
||||
get_pci_device_structure_mut, PciDeviceStructure, PCI_DEVICE_LINKEDLIST,
|
||||
};
|
||||
use crate::libs::rwlock::RwLockWriteGuard;
|
||||
use crate::{kdebug, kerror, kwarn};
|
||||
use alloc::{boxed::Box, collections::LinkedList};
|
||||
use virtio_drivers::device::net::VirtIONet;
|
||||
use virtio_drivers::transport::{DeviceType, Transport};
|
||||
const NETWORK_CLASS: u8 = 0x2;
|
||||
const ETHERNET_SUBCLASS: u8 = 0x0;
|
||||
|
||||
//Virtio设备寻找过程中出现的问题
|
||||
enum VirtioError {
|
||||
VirtioNetNotFound,
|
||||
NetDeviceNotFound,
|
||||
}
|
||||
|
||||
///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)(for c)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn c_virtio_probe() {
|
||||
if let Ok(virtio_list) = virtio_device_search() {
|
||||
for device_function in virtio_list {
|
||||
match PciTransport::new::<HalImpl>(*device_function) {
|
||||
Ok(mut transport) => {
|
||||
kdebug!(
|
||||
"Detected virtio PCI device with device type {:?}, features {:#018x}",
|
||||
transport.device_type(),
|
||||
transport.read_device_features(),
|
||||
);
|
||||
virtio_device(transport);
|
||||
}
|
||||
Err(err) => {
|
||||
kerror!("Pci transport create failed because of error: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
kerror!("Error occured when finding virtio device!");
|
||||
}
|
||||
virtio_probe();
|
||||
}
|
||||
|
||||
///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)
|
||||
fn virtio_probe() {
|
||||
if let Ok(virtio_list) = virtio_device_search() {
|
||||
for device_function in virtio_list {
|
||||
match PciTransport::new::<HalImpl>(*device_function) {
|
||||
pub fn virtio_probe() {
|
||||
let mut list = PCI_DEVICE_LINKEDLIST.write();
|
||||
if let Ok(virtio_list) = virtio_device_search(&mut list) {
|
||||
for virtio_device in virtio_list {
|
||||
match PciTransport::new::<HalImpl>(virtio_device) {
|
||||
Ok(mut transport) => {
|
||||
kdebug!(
|
||||
"Detected virtio PCI device with device type {:?}, features {:#018x}",
|
||||
transport.device_type(),
|
||||
transport.read_device_features(),
|
||||
);
|
||||
virtio_device(transport);
|
||||
virtio_device_init(transport);
|
||||
}
|
||||
Err(err) => {
|
||||
kerror!("Pci transport create failed because of error: {}", err);
|
||||
@ -60,7 +49,7 @@ fn virtio_probe() {
|
||||
}
|
||||
|
||||
///@brief 为virtio设备寻找对应的驱动进行初始化
|
||||
fn virtio_device(transport: impl Transport) {
|
||||
fn virtio_device_init(transport: impl Transport) {
|
||||
match transport.device_type() {
|
||||
DeviceType::Block => {
|
||||
kwarn!("Not support virtio_block device for now");
|
||||
@ -131,29 +120,38 @@ fn virtio_net<T: Transport>(transport: T) {
|
||||
}
|
||||
|
||||
/// @brief 寻找所有的virtio设备
|
||||
/// @return Result<LinkedList<Box<DeviceFunction>>,VirtioError> 成功则返回包含所有virtio设备的链表,失败则返回err
|
||||
/// @param list 链表的写锁
|
||||
/// @return Result<LinkedList<&'a mut Pci_Device_Structure_General_Device>, VirtioError> 成功则返回包含所有virtio设备结构体的可变引用的链表,失败则返回err
|
||||
/// 该函数主要是为其他virtio设备预留支持
|
||||
fn virtio_device_search() -> Result<LinkedList<Box<DeviceFunction>>, VirtioError> {
|
||||
let mut virtio_list: LinkedList<Box<DeviceFunction>> = LinkedList::new();
|
||||
let (bus, device, function) = unsafe {
|
||||
let mut bus: u8 = 0;
|
||||
let mut device: u8 = 0;
|
||||
let mut function: u8 = 0;
|
||||
let bus_ptr = &mut bus as *mut u8;
|
||||
let device_ptr = &mut device as *mut u8;
|
||||
let function_ptr = &mut function as *mut u8;
|
||||
get_virtio_net_device(bus_ptr, device_ptr, function_ptr);
|
||||
(bus, device, function)
|
||||
};
|
||||
if bus == 0 && device == 0 && function == 0 {
|
||||
kdebug!("get_virtio_net_device failed");
|
||||
return Err(VirtioError::VirtioNetNotFound);
|
||||
}
|
||||
let device_function = DeviceFunction {
|
||||
bus: bus,
|
||||
device: device,
|
||||
function: function,
|
||||
};
|
||||
virtio_list.push_back(Box::new(device_function));
|
||||
fn virtio_device_search<'a>(
|
||||
list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
|
||||
) -> Result<LinkedList<&'a mut PciDeviceStructureGeneralDevice>, VirtioError> {
|
||||
let mut virtio_list: LinkedList<&mut PciDeviceStructureGeneralDevice> = LinkedList::new();
|
||||
let virtio_net_device = get_virtio_net_device(list)?;
|
||||
virtio_list.push_back(virtio_net_device);
|
||||
Ok(virtio_list)
|
||||
}
|
||||
|
||||
/// @brief 寻找virtio-net设备
|
||||
/// @param list 链表的写锁
|
||||
/// @return Result<&'a mut Pci_Device_Structure_General_Device, VirtioError> 成功则返回virtio设备结构体的可变引用,失败则返回err
|
||||
fn get_virtio_net_device<'a>(
|
||||
list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
|
||||
) -> Result<&'a mut PciDeviceStructureGeneralDevice, VirtioError> {
|
||||
let result = get_pci_device_structure_mut(list, NETWORK_CLASS, ETHERNET_SUBCLASS);
|
||||
if result.is_empty() {
|
||||
return Err(VirtioError::NetDeviceNotFound);
|
||||
}
|
||||
for device in result {
|
||||
let standard_device = device.as_standard_device_mut().unwrap();
|
||||
let header = &standard_device.common_header;
|
||||
if header.vendor_id == 0x1AF4
|
||||
&& header.device_id >= 0x1000
|
||||
&& header.device_id <= 0x103F
|
||||
&& standard_device.subsystem_id == 1
|
||||
{
|
||||
return Ok(standard_device);
|
||||
}
|
||||
}
|
||||
Err(VirtioError::VirtioNetNotFound)
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ use crate::include::bindings::bindings::{
|
||||
alloc_pages, free_pages, memory_management_struct, Page, PAGE_2M_SHIFT, PAGE_2M_SIZE,
|
||||
PAGE_OFFSET, PAGE_SHARED, ZONE_NORMAL,
|
||||
};
|
||||
|
||||
use crate::mm::virt_2_phys;
|
||||
use core::mem::size_of;
|
||||
use core::ptr::NonNull;
|
||||
|
@ -3,11 +3,7 @@ use crate::filesystem::vfs::make_rawdev;
|
||||
use crate::filesystem::vfs::{
|
||||
core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, PollStatus,
|
||||
};
|
||||
use crate::{
|
||||
syscall::SystemError,
|
||||
libs::spinlock::SpinLock,
|
||||
time::TimeSpec,
|
||||
};
|
||||
use crate::{libs::spinlock::SpinLock, syscall::SystemError, time::TimeSpec};
|
||||
use alloc::{
|
||||
string::String,
|
||||
sync::{Arc, Weak},
|
||||
|
@ -3,11 +3,7 @@ use crate::filesystem::vfs::make_rawdev;
|
||||
use crate::filesystem::vfs::{
|
||||
core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, PollStatus,
|
||||
};
|
||||
use crate::{
|
||||
syscall::SystemError,
|
||||
libs::spinlock::SpinLock,
|
||||
time::TimeSpec,
|
||||
};
|
||||
use crate::{libs::spinlock::SpinLock, syscall::SystemError, time::TimeSpec};
|
||||
use alloc::{
|
||||
string::String,
|
||||
sync::{Arc, Weak},
|
||||
|
@ -4,7 +4,8 @@ use alloc::{sync::Arc, vec::Vec};
|
||||
use crate::{
|
||||
io::{device::LBA_SIZE, disk_info::Partition, SeekFrom},
|
||||
kerror,
|
||||
libs::vec_cursor::VecCursor, syscall::SystemError,
|
||||
libs::vec_cursor::VecCursor,
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::fs::{Cluster, FATFileSystem};
|
||||
|
@ -79,7 +79,12 @@ impl FATFile {
|
||||
///
|
||||
/// @return Ok(usize) 成功读取到的字节数
|
||||
/// @return Err(SystemError) 读取时出现错误,返回错误码
|
||||
pub fn read(&self, fs: &Arc<FATFileSystem>, buf: &mut [u8], offset: u64) -> Result<usize, SystemError> {
|
||||
pub fn read(
|
||||
&self,
|
||||
fs: &Arc<FATFileSystem>,
|
||||
buf: &mut [u8],
|
||||
offset: u64,
|
||||
) -> Result<usize, SystemError> {
|
||||
if offset >= self.size() {
|
||||
return Ok(0);
|
||||
}
|
||||
@ -223,7 +228,12 @@ impl FATFile {
|
||||
///
|
||||
/// @return Ok(()) 经过操作后,offset后面具有长度至少为len的空闲空间
|
||||
/// @return Err(SystemError) 处理过程中出现了异常。
|
||||
fn ensure_len(&mut self, fs: &Arc<FATFileSystem>, offset: u64, len: u64) -> Result<(), SystemError> {
|
||||
fn ensure_len(
|
||||
&mut self,
|
||||
fs: &Arc<FATFileSystem>,
|
||||
offset: u64,
|
||||
len: u64,
|
||||
) -> Result<(), SystemError> {
|
||||
// 文件内本身就还有空余的空间
|
||||
if offset + len <= self.size() {
|
||||
return Ok(());
|
||||
@ -545,7 +555,6 @@ impl FATDir {
|
||||
} else {
|
||||
return Err(err_val);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
match r.unwrap() {
|
||||
@ -822,7 +831,11 @@ impl FATDir {
|
||||
///
|
||||
/// @return Ok(FATDirEntry) 目标目录项
|
||||
/// @return Err(SystemError) 底层传上来的错误码
|
||||
pub fn get_dir_entry(&self, fs: Arc<FATFileSystem>, name: &str) -> Result<FATDirEntry, SystemError> {
|
||||
pub fn get_dir_entry(
|
||||
&self,
|
||||
fs: Arc<FATFileSystem>,
|
||||
name: &str,
|
||||
) -> Result<FATDirEntry, SystemError> {
|
||||
if name == "." || name == "/" {
|
||||
return Ok(FATDirEntry::Dir(self.clone()));
|
||||
}
|
||||
@ -1271,7 +1284,11 @@ impl ShortDirEntry {
|
||||
///
|
||||
/// @return Ok(())
|
||||
/// @return Err(SystemError) 错误码
|
||||
pub fn flush(&self, fs: &Arc<FATFileSystem>, disk_bytes_offset: u64) -> Result<(), SystemError> {
|
||||
pub fn flush(
|
||||
&self,
|
||||
fs: &Arc<FATFileSystem>,
|
||||
disk_bytes_offset: u64,
|
||||
) -> Result<(), SystemError> {
|
||||
// 从磁盘读取数据
|
||||
let blk_offset = fs.get_in_block_offset(disk_bytes_offset);
|
||||
let lba = fs.get_lba_from_offset(
|
||||
|
@ -20,8 +20,8 @@ use crate::{
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
vec_cursor::VecCursor,
|
||||
},
|
||||
time::TimeSpec,
|
||||
syscall::SystemError,
|
||||
time::TimeSpec,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@ -1569,7 +1569,8 @@ impl IndexNode for LockedFATInode {
|
||||
dir.check_existence(name, Some(true), guard.fs.upgrade().unwrap())?;
|
||||
|
||||
// 再从磁盘删除
|
||||
let r: Result<(), SystemError> = dir.remove(guard.fs.upgrade().unwrap().clone(), name, true);
|
||||
let r: Result<(), SystemError> =
|
||||
dir.remove(guard.fs.upgrade().unwrap().clone(), name, true);
|
||||
if r.is_ok() {
|
||||
return r;
|
||||
} else {
|
||||
|
@ -14,16 +14,16 @@ use crate::{
|
||||
core::{generate_inode_id, ROOT_INODE},
|
||||
FileType,
|
||||
},
|
||||
include::bindings::bindings::{
|
||||
pid_t, process_find_pcb_by_pid,
|
||||
},
|
||||
include::bindings::bindings::{pid_t, process_find_pcb_by_pid},
|
||||
kerror,
|
||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||
time::TimeSpec, syscall::SystemError,
|
||||
syscall::SystemError,
|
||||
time::TimeSpec,
|
||||
};
|
||||
|
||||
use super::vfs::{
|
||||
file::{FilePrivateData, FileMode}, FileSystem, FsInfo, IndexNode, InodeId, Metadata, PollStatus,
|
||||
file::{FileMode, FilePrivateData},
|
||||
FileSystem, FsInfo, IndexNode, InodeId, Metadata, PollStatus,
|
||||
};
|
||||
|
||||
/// @brief 进程文件类型
|
||||
|
@ -10,7 +10,8 @@ use alloc::{
|
||||
use crate::{
|
||||
filesystem::vfs::{core::generate_inode_id, FileType},
|
||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||
time::TimeSpec, syscall::SystemError,
|
||||
syscall::SystemError,
|
||||
time::TimeSpec,
|
||||
};
|
||||
|
||||
use super::vfs::{
|
||||
|
@ -10,10 +10,7 @@ use ::core::{any::Any, fmt::Debug};
|
||||
|
||||
use alloc::{string::String, sync::Arc, vec::Vec};
|
||||
|
||||
use crate::{
|
||||
time::TimeSpec,
|
||||
syscall::SystemError,
|
||||
};
|
||||
use crate::{syscall::SystemError, time::TimeSpec};
|
||||
|
||||
use self::{core::generate_inode_id, file::FileMode};
|
||||
pub use self::{core::ROOT_INODE, file::FilePrivateData, mount::MountFS};
|
||||
@ -239,7 +236,7 @@ pub trait IndexNode: Any + Sync + Send + Debug {
|
||||
///
|
||||
/// @return 成功 Ok(())
|
||||
/// @return 失败 Err(错误码)
|
||||
fn rmdir(&self, _name: &str) ->Result<(), SystemError>{
|
||||
fn rmdir(&self, _name: &str) -> Result<(), SystemError> {
|
||||
return Err(SystemError::ENOTSUP);
|
||||
}
|
||||
|
||||
|
@ -5,11 +5,9 @@ use alloc::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
libs::spinlock::SpinLock, syscall::SystemError,
|
||||
};
|
||||
use crate::{libs::spinlock::SpinLock, syscall::SystemError};
|
||||
|
||||
use super::{FilePrivateData, FileSystem, FileType, IndexNode, InodeId, file::FileMode};
|
||||
use super::{file::FileMode, FilePrivateData, FileSystem, FileType, IndexNode, InodeId};
|
||||
|
||||
/// @brief 挂载文件系统
|
||||
/// 挂载文件系统的时候,套了MountFS这一层,以实现文件系统的递归挂载
|
||||
@ -166,9 +164,7 @@ impl IndexNode for MountFSInode {
|
||||
buf: &[u8],
|
||||
data: &mut FilePrivateData,
|
||||
) -> Result<usize, SystemError> {
|
||||
return self
|
||||
.inner_inode
|
||||
.write_at(offset, len, buf, data);
|
||||
return self.inner_inode.write_at(offset, len, buf, data);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -1,5 +1,5 @@
|
||||
/// 引入Module
|
||||
use crate::{syscall::SystemError};
|
||||
use crate::syscall::SystemError;
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use core::{any::Any, fmt::Debug};
|
||||
|
||||
@ -45,7 +45,6 @@ pub trait Device: Any + Send + Sync + Debug {
|
||||
fn sync(&self) -> Result<(), SystemError>;
|
||||
|
||||
// TODO: 待实现 open, close
|
||||
|
||||
}
|
||||
|
||||
/// @brief 块设备应该实现的操作
|
||||
@ -58,7 +57,12 @@ pub trait BlockDevice: Any + Send + Sync + Debug {
|
||||
/// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
|
||||
/// 否则返回Err(错误码),其中错误码为负数;
|
||||
/// 如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
|
||||
fn read_at(&self, lba_id_start: BlockId, count: usize, buf: &mut [u8]) -> Result<usize, SystemError>;
|
||||
fn read_at(
|
||||
&self,
|
||||
lba_id_start: BlockId,
|
||||
count: usize,
|
||||
buf: &mut [u8],
|
||||
) -> Result<usize, SystemError>;
|
||||
|
||||
/// @brief: 在块设备中,从第lba_id_start个块开始,把buf中的count个块数据,存放到设备中
|
||||
/// @parameter lba_id_start: 起始块
|
||||
@ -67,7 +71,12 @@ pub trait BlockDevice: Any + Send + Sync + Debug {
|
||||
/// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
|
||||
/// 否则返回Err(错误码),其中错误码为负数;
|
||||
/// 如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
|
||||
fn write_at(&self, lba_id_start: BlockId, count: usize, buf: &[u8]) -> Result<usize, SystemError>;
|
||||
fn write_at(
|
||||
&self,
|
||||
lba_id_start: BlockId,
|
||||
count: usize,
|
||||
buf: &[u8],
|
||||
) -> Result<usize, SystemError>;
|
||||
|
||||
/// @brief: 同步磁盘信息,把所有的dirty数据写回硬盘 - 待实现
|
||||
fn sync(&self) -> Result<(), SystemError>;
|
||||
|
@ -13,9 +13,8 @@ use crate::{
|
||||
},
|
||||
include::bindings::bindings::{
|
||||
pid_t, process_control_block, process_do_exit, process_find_pcb_by_pid, pt_regs,
|
||||
spinlock_t, verify_area, NULL, PF_EXITING,
|
||||
PF_KTHREAD, PF_SIGNALED, PF_WAKEKILL, PROC_INTERRUPTIBLE, USER_CS, USER_DS,
|
||||
USER_MAX_LINEAR_ADDR,
|
||||
spinlock_t, verify_area, NULL, PF_EXITING, PF_KTHREAD, PF_SIGNALED, PF_WAKEKILL,
|
||||
PROC_INTERRUPTIBLE, USER_CS, USER_DS, USER_MAX_LINEAR_ADDR,
|
||||
},
|
||||
ipc::signal_types::{sigset_add, user_sigaction},
|
||||
kBUG, kdebug, kerror, kwarn,
|
||||
@ -29,7 +28,8 @@ use crate::{
|
||||
process::{
|
||||
pid::PidType,
|
||||
process::{process_is_stopped, process_kick, process_wake_up_state},
|
||||
}, syscall::SystemError,
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::signal_types::{
|
||||
@ -698,7 +698,7 @@ fn setup_frame(
|
||||
if err != 0 {
|
||||
// todo: 在这里生成一个sigsegv,然后core dump
|
||||
//临时解决方案:退出当前进程
|
||||
unsafe{
|
||||
unsafe {
|
||||
process_do_exit(1);
|
||||
}
|
||||
}
|
||||
@ -724,8 +724,12 @@ fn setup_frame(
|
||||
// 设置cs和ds寄存器
|
||||
regs.cs = (USER_CS | 0x3) as u64;
|
||||
regs.ds = (USER_DS | 0x3) as u64;
|
||||
|
||||
return if err == 0 { Ok(0) } else { Err(SystemError::EPERM) };
|
||||
|
||||
return if err == 0 {
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(SystemError::EPERM)
|
||||
};
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@ -762,7 +766,11 @@ fn copy_siginfo_to_user(to: *mut siginfo, from: &siginfo) -> Result<i32, SystemE
|
||||
/// @param context 要被设置的目标sigcontext
|
||||
/// @param mask 要被暂存的信号mask标志位
|
||||
/// @param regs 进入信号处理流程前,Restore all要弹出的内核栈栈帧
|
||||
fn setup_sigcontext(context: &mut sigcontext, mask: &sigset_t, regs: &pt_regs) -> Result<i32, SystemError> {
|
||||
fn setup_sigcontext(
|
||||
context: &mut sigcontext,
|
||||
mask: &sigset_t,
|
||||
regs: &pt_regs,
|
||||
) -> Result<i32, SystemError> {
|
||||
let current_thread = current_pcb().thread;
|
||||
|
||||
context.oldmask = *mask;
|
||||
@ -929,19 +937,18 @@ pub extern "C" fn sys_sigaction(regs: &mut pt_regs) -> u64 {
|
||||
}
|
||||
}
|
||||
//return retval as u64;
|
||||
if retval.is_ok(){
|
||||
if retval.is_ok() {
|
||||
return 0;
|
||||
}else{
|
||||
} else {
|
||||
return retval.unwrap_err().to_posix_errno() as u64;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn do_sigaction(
|
||||
sig: SignalNumber,
|
||||
act: Option<&mut sigaction>,
|
||||
old_act: Option<&mut sigaction>,
|
||||
) -> Result<(),SystemError> {
|
||||
) -> Result<(), SystemError> {
|
||||
let pcb = current_pcb();
|
||||
|
||||
// 指向当前信号的action的引用
|
||||
|
@ -665,5 +665,5 @@ pub struct signal_stack {
|
||||
pub sp: *mut c_void,
|
||||
pub flags: u32,
|
||||
pub size: u32,
|
||||
pub fpstate:FpState,
|
||||
pub fpstate: FpState,
|
||||
}
|
||||
|
@ -12,8 +12,6 @@
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
/// 导出x86_64架构相关的代码,命名为arch模块
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[path = "arch/x86_64/mod.rs"]
|
||||
#[macro_use]
|
||||
mod arch;
|
||||
#[macro_use]
|
||||
|
@ -1,9 +1,6 @@
|
||||
#![allow(dead_code)]
|
||||
use super::spinlock::RawSpinlock;
|
||||
use crate::{
|
||||
arch::asm::cmpxchg::try_cmpxchg_q,
|
||||
syscall::SystemError,
|
||||
};
|
||||
use crate::{arch::asm::cmpxchg::try_cmpxchg_q, syscall::SystemError};
|
||||
use core::{fmt::Debug, intrinsics::size_of};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@ -53,7 +50,7 @@ impl LockRef {
|
||||
fn cmpxchg_loop(&mut self, mode: CmpxchgMode) -> Result<i32, i32> {
|
||||
use core::ptr::read_volatile;
|
||||
|
||||
use crate::{arch::cpu::cpu_relax};
|
||||
use crate::arch::cpu::cpu_relax;
|
||||
|
||||
let mut old: LockRef = LockRef::INIT;
|
||||
old.count = unsafe { read_volatile(&self.count) };
|
||||
@ -265,7 +262,7 @@ impl LockRef {
|
||||
let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::DecreaseNotZero);
|
||||
if cmpxchg_result.is_ok() {
|
||||
return Ok(cmpxchg_result.unwrap());
|
||||
} else if cmpxchg_result.unwrap_err() == 1{
|
||||
} else if cmpxchg_result.unwrap_err() == 1 {
|
||||
return Err(SystemError::EPERM);
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,10 @@ use alloc::collections::LinkedList;
|
||||
use crate::{
|
||||
arch::{asm::current::current_pcb, sched::sched},
|
||||
include::bindings::bindings::{
|
||||
pid_t, process_control_block, process_wakeup, PROC_INTERRUPTIBLE, PROC_RUNNING,
|
||||
pid_t, process_control_block, process_wakeup, PROC_INTERRUPTIBLE, PROC_RUNNING,
|
||||
},
|
||||
libs::spinlock::SpinLockGuard, syscall::SystemError,
|
||||
libs::spinlock::SpinLockGuard,
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::spinlock::SpinLock;
|
||||
|
@ -12,13 +12,13 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use core::cmp::Ord;
|
||||
use core::fmt::{self, Debug};
|
||||
use core::cmp::Ordering;
|
||||
use core::ptr;
|
||||
use core::iter::{IntoIterator, FromIterator};
|
||||
use core::fmt::{self, Debug};
|
||||
use core::iter::{FromIterator, IntoIterator};
|
||||
use core::marker;
|
||||
use core::mem;
|
||||
use core::ops::Index;
|
||||
use core::ptr;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
|
||||
@ -234,7 +234,6 @@ impl<K: Ord, V> NodePtr<K, V> {
|
||||
unsafe { (*self.0).right = right }
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
fn parent(&self) -> NodePtr<K, V> {
|
||||
if self.is_null() {
|
||||
@ -421,9 +420,8 @@ where
|
||||
return false;
|
||||
}
|
||||
|
||||
self.iter().all(|(key, value)| {
|
||||
other.get(key).map_or(false, |v| *value == *v)
|
||||
})
|
||||
self.iter()
|
||||
.all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
|
||||
}
|
||||
}
|
||||
|
||||
@ -446,7 +444,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<K: Ord, V> FromIterator<(K, V)> for RBTree<K, V> {
|
||||
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> RBTree<K, V> {
|
||||
let mut tree = RBTree::new();
|
||||
@ -483,7 +480,9 @@ pub struct Keys<'a, K: Ord + 'a, V: 'a> {
|
||||
|
||||
impl<'a, K: Ord, V> Clone for Keys<'a, K, V> {
|
||||
fn clone(&self) -> Keys<'a, K, V> {
|
||||
Keys { inner: self.inner.clone() }
|
||||
Keys {
|
||||
inner: self.inner.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -526,7 +525,9 @@ pub struct Values<'a, K: 'a + Ord, V: 'a> {
|
||||
|
||||
impl<'a, K: Ord, V> Clone for Values<'a, K, V> {
|
||||
fn clone(&self) -> Values<'a, K, V> {
|
||||
Values { inner: self.inner.clone() }
|
||||
Values {
|
||||
inner: self.inner.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -536,7 +537,6 @@ impl<'a, K: Ord + Debug, V: Debug> fmt::Debug for Values<'a, K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a, K: Ord, V> Iterator for Values<'a, K, V> {
|
||||
type Item = &'a V;
|
||||
|
||||
@ -573,7 +573,9 @@ pub struct ValuesMut<'a, K: 'a + Ord, V: 'a> {
|
||||
|
||||
impl<'a, K: Ord, V> Clone for ValuesMut<'a, K, V> {
|
||||
fn clone(&self) -> ValuesMut<'a, K, V> {
|
||||
ValuesMut { inner: self.inner.clone() }
|
||||
ValuesMut {
|
||||
inner: self.inner.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -812,7 +814,6 @@ impl<'a, K: Ord + 'a, V: 'a> DoubleEndedIterator for IterMut<'a, K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<K: Ord, V> IntoIterator for RBTree<K, V> {
|
||||
type Item = (K, V);
|
||||
type IntoIter = IntoIter<K, V>;
|
||||
@ -1387,7 +1388,9 @@ impl<K: Ord, V> RBTree<K, V> {
|
||||
/// Return the value iter mut
|
||||
#[inline]
|
||||
pub fn values_mut(&mut self) -> ValuesMut<K, V> {
|
||||
ValuesMut { inner: self.iter_mut() }
|
||||
ValuesMut {
|
||||
inner: self.iter_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the key and value iter
|
||||
@ -1441,7 +1444,6 @@ mod tests {
|
||||
assert_eq!(*m.get(&2).unwrap(), 6);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_clone() {
|
||||
let mut m = RBTree::new();
|
||||
@ -1788,4 +1790,4 @@ mod tests {
|
||||
assert_eq!(a[&2], "two");
|
||||
assert_eq!(a[&3], "three");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use core::{
|
||||
sync::atomic::{AtomicU32, Ordering},
|
||||
};
|
||||
|
||||
use crate::{syscall::SystemError};
|
||||
use crate::syscall::SystemError;
|
||||
|
||||
///RwLock读写锁
|
||||
|
||||
|
@ -59,10 +59,10 @@ macro_rules! volatile_write_bit {
|
||||
/// queue_driver: Volatile<u64>,
|
||||
/// queue_device: Volatile<u64>,
|
||||
/// }
|
||||
///
|
||||
///
|
||||
/// 对CommonCfg里面的某个寄存器进行读写:
|
||||
/// volwrite!(self.common_cfg, queue_enable, 0);
|
||||
///
|
||||
///
|
||||
/// 这样做不仅使代码的可读性提高了,也避免了对只读寄存器进行写入的误操作
|
||||
|
||||
/// 只读寄存器
|
||||
|
@ -147,6 +147,7 @@ void system_initialize()
|
||||
// ps2_mouse_init();
|
||||
// ata_init();
|
||||
pci_init();
|
||||
rs_pci_init();
|
||||
io_mfence();
|
||||
|
||||
// test_slab();
|
||||
|
@ -4,8 +4,8 @@ use crate::{
|
||||
arch::asm::current::current_pcb,
|
||||
include::bindings::bindings::{
|
||||
initial_mm, mm_create_vma, mm_unmap, vm_area_del, vm_area_free, vm_area_struct, vm_flags_t,
|
||||
vma_find, MMIO_BASE, MMIO_TOP, PAGE_1G_SHIFT, PAGE_1G_SIZE,
|
||||
PAGE_2M_SIZE, PAGE_4K_SHIFT, PAGE_4K_SIZE, VM_DONTCOPY, VM_IO,
|
||||
vma_find, MMIO_BASE, MMIO_TOP, PAGE_1G_SHIFT, PAGE_1G_SIZE, PAGE_2M_SIZE, PAGE_4K_SHIFT,
|
||||
PAGE_4K_SIZE, VM_DONTCOPY, VM_IO,
|
||||
},
|
||||
kdebug, kerror,
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::include::bindings::bindings::{PAGE_OFFSET, process_control_block, mm_struct};
|
||||
use crate::include::bindings::bindings::{mm_struct, process_control_block, PAGE_OFFSET};
|
||||
|
||||
pub mod allocator;
|
||||
pub mod gfp;
|
||||
@ -22,4 +22,4 @@ unsafe impl Send for process_control_block {}
|
||||
unsafe impl Sync for process_control_block {}
|
||||
|
||||
unsafe impl Send for mm_struct {}
|
||||
unsafe impl Sync for mm_struct {}
|
||||
unsafe impl Sync for mm_struct {}
|
||||
|
@ -16,7 +16,8 @@ use crate::{
|
||||
ffi_convert::FFIBind2Rust,
|
||||
refcount::{refcount_inc, RefCount},
|
||||
spinlock::{spin_lock_irqsave, spin_unlock_irqrestore},
|
||||
}, syscall::SystemError,
|
||||
},
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -1,3 +1,4 @@
|
||||
|
||||
use num_traits::{FromPrimitive, ToPrimitive};
|
||||
|
||||
#[repr(i32)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user