在Sysfs中引入ACPI Firmware (#405)

- bugfix: multiboot2启动的信息因为没及时转存导致后面无法从其中进行查询的bug
- feature: 把acpi表、acpi bus加入sysfs
This commit is contained in:
LoGin 2023-10-22 22:00:16 +08:00 committed by GitHub
parent 01bd5258cf
commit 7eda31b2f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 1044 additions and 204 deletions

View File

@ -31,7 +31,7 @@ elf = { version = "0.7.2", default-features = false }
memoffset = "0.9.0"
atomic_enum = "0.2.0"
raw-cpuid = "11.0.1"
acpi = "5.0.0"
acpi = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/acpi-rs.git", rev = "fb69243dcf" }
intertrait = { path = "src/libs/intertrait" }
linkme = "0.2"
ida = { path = "src/libs/ida" }
@ -51,4 +51,3 @@ features = ["spin_no_std"]
[profile.release]
debug = false

View File

@ -181,7 +181,7 @@ void acpi_init()
// 申请mmio空间
uint64_t size = 0;
mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_rsdt_virt_addr_base, &size);
rs_mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_rsdt_virt_addr_base, &size);
// 映射rsdt表
paddr = (uint64_t)rsdt_phys_base;
@ -200,7 +200,7 @@ void acpi_init()
printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num);
// 申请mmio空间
mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_description_header_base, &size);
rs_mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_description_header_base, &size);
// 映射所有的Entry的物理地址
acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK;
@ -220,7 +220,7 @@ void acpi_init()
kdebug("rsdpv1->RsdtAddress=%#018lx", rsdpv1->RsdtAddress);
// 申请mmio空间
uint64_t size = 0;
mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_rsdt_virt_addr_base, &size);
rs_mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_rsdt_virt_addr_base, &size);
// acpi_rsdt_virt_addr_base = 0xffffb00000000000UL;
kdebug("ACPI: mmio created. acpi_rsdt_virt_addr_base = %#018lx,size= %#010lx", acpi_rsdt_virt_addr_base, size);
@ -243,7 +243,7 @@ void acpi_init()
printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num);
// 申请mmio空间
mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_description_header_base, &size);
rs_mmio_create(PAGE_2M_SIZE, VM_IO | VM_DONTCOPY, &acpi_description_header_base, &size);
// 映射所有的Entry的物理地址
acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK;

View File

@ -1,7 +1,17 @@
use alloc::sync::Arc;
use alloc::{
string::{String, ToString},
sync::{Arc, Weak},
};
use crate::{
driver::base::device::{driver::Driver, Device},
driver::base::{
device::{
bus::{bus_manager, Bus},
driver::Driver,
Device,
},
subsys::SubSysPrivate,
},
syscall::SystemError,
};
@ -20,4 +30,98 @@ impl AcpiManager {
return Ok(false);
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1286
pub(super) fn bus_init(&self) -> Result<(), SystemError> {
self.acpi_sysfs_init()?;
let acpi_bus = AcpiBus::new();
bus_manager()
.register(acpi_bus as Arc<dyn Bus>)
.expect("acpi_bus register failed");
return Ok(());
}
}
/// ACPI总线
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1072
#[derive(Debug)]
pub(super) struct AcpiBus {
private: SubSysPrivate,
}
impl AcpiBus {
pub fn new() -> Arc<Self> {
let default_weak: Weak<Self> = Weak::new();
let bus = Arc::new(Self {
private: SubSysPrivate::new("acpi".to_string(), default_weak, &[]),
});
bus.subsystem()
.set_bus(Arc::downgrade(&(bus.clone() as Arc<dyn Bus>)));
return bus;
}
}
impl Bus for AcpiBus {
fn name(&self) -> String {
return self.private.subsys().as_kobject().name();
}
fn dev_name(&self) -> String {
self.name()
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1056
fn remove(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
todo!("acpi_bus: remove")
}
fn shutdown(&self, _device: &Arc<dyn Device>) {
return;
}
fn resume(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
return Ok(());
}
/// 通过acpi来匹配驱动
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1005
fn match_device(
&self,
_device: &Arc<dyn Device>,
_driver: &Arc<dyn Driver>,
) -> Result<bool, SystemError> {
// todo: 通过acpi来匹配驱动
return Ok(false);
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1019
fn probe(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
todo!("acpi_bus: probe")
}
fn subsystem(&self) -> &SubSysPrivate {
return &self.private;
}
}
/// Acpi设备应当实现的trait
///
/// 所有的实现了 AcpiDevice trait的结构体都应该在结构体上方标注`#[cast_to([sync] AcpiDevice)]
///
/// todo: 仿照linux的acpi_device去设计这个trait
///
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/acpi/acpi_bus.h#364
pub trait AcpiDevice: Device {}
/// Acpi驱动应当实现的trait
///
/// 所有的实现了 AcpiDriver trait的结构体都应该在结构体上方标注`#[cast_to([sync] AcpiDriver)]
///
/// todo: 仿照linux的acpi_driver去设计这个trait
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/include/acpi/acpi_bus.h#163
pub trait AcpiDriver: Driver {}

View File

@ -4,7 +4,7 @@ use crate::{
mm::{MemoryManagementArch, VirtAddr},
};
use super::AcpiManager;
use super::acpi_manager;
static mut RSDP_TMP_BOX: Option<AlignedBox<[u8; 4096], 4096>> = None;
@ -20,5 +20,7 @@ unsafe extern "C" fn rs_acpi_init(rsdp_vaddr: u64) {
))
.unwrap();
AcpiManager::init(rsdp_paddr);
acpi_manager()
.init(rsdp_paddr)
.expect("rs_acpi_init(): failed to init acpi");
}

View File

@ -1,56 +1,90 @@
use core::{fmt::Debug, ptr::NonNull};
use acpi::AcpiHandler;
use alloc::{string::ToString, sync::Arc};
use crate::{
driver::base::firmware::sys_firmware_kset,
kinfo,
libs::{
align::{page_align_down, page_align_up},
once::Once,
},
libs::align::{page_align_down, page_align_up},
mm::{
mmio_buddy::{mmio_pool, MMIOSpaceGuard},
PhysAddr, VirtAddr,
},
syscall::SystemError,
};
use super::base::kset::KSet;
extern crate acpi;
pub mod bus;
mod c_adapter;
pub mod glue;
pub mod old;
extern crate acpi;
mod sysfs;
static mut __ACPI_TABLE: Option<acpi::AcpiTables<AcpiHandlerImpl>> = None;
/// `/sys/firmware/acpi`的kset
static mut ACPI_KSET_INSTANCE: Option<Arc<KSet>> = None;
#[inline(always)]
pub fn acpi_manager() -> &'static AcpiManager {
&AcpiManager
}
#[inline(always)]
pub fn acpi_kset() -> Arc<KSet> {
unsafe { ACPI_KSET_INSTANCE.clone().unwrap() }
}
#[derive(Debug)]
pub struct AcpiManager;
impl AcpiManager {
pub fn init(rsdp_paddr: PhysAddr) {
static INIT: Once = Once::new();
INIT.call_once(|| {
/// 初始化ACPI
///
/// ## 参数
///
/// - `rsdp_paddr`: RSDP的物理地址
///
///
/// ## 参考资料
///
/// https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1390
pub fn init(&self, rsdp_paddr: PhysAddr) -> Result<(), SystemError> {
kinfo!("Initializing Acpi Manager...");
// 初始化`/sys/firmware/acpi`的kset
let kset = KSet::new("acpi".to_string());
kset.register(Some(sys_firmware_kset()))?;
unsafe {
ACPI_KSET_INSTANCE = Some(kset.clone());
}
self.map_tables(rsdp_paddr)?;
self.bus_init()?;
kinfo!("Acpi Manager initialized.");
return Ok(());
}
fn map_tables(&self, rsdp_paddr: PhysAddr) -> Result<(), SystemError> {
let acpi_table: acpi::AcpiTables<AcpiHandlerImpl> =
unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr.data()) }
.unwrap_or_else(|e| {
panic!("acpi_init(): failed to parse acpi tables, error: {:?}", e)
});
unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr.data()) }.map_err(
|e| {
kerror!("acpi_init(): failed to parse acpi tables, error: {:?}", e);
SystemError::ENOMEM
},
)?;
unsafe {
__ACPI_TABLE = Some(acpi_table);
}
kinfo!("Acpi Manager initialized.");
});
return Ok(());
}
#[allow(dead_code)]
pub fn tables() -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> {
pub fn tables(&self) -> Option<&'static acpi::AcpiTables<AcpiHandlerImpl>> {
unsafe { __ACPI_TABLE.as_ref() }
}
}

View File

@ -0,0 +1,510 @@
use acpi::sdt::SdtHeader;
use alloc::{
string::{String, ToString},
sync::Arc,
vec::Vec,
};
use crate::{
driver::{
acpi::acpi_manager,
base::{kobject::KObject, kset::KSet},
},
filesystem::{
sysfs::{file::sysfs_emit_str, sysfs_instance, Attribute, BinAttribute, SysFSOpsSupport},
vfs::syscall::ModeType,
},
libs::rwlock::RwLock,
syscall::SystemError,
};
use super::{acpi_kset, AcpiManager};
static mut __HOTPLUG_KSET_INSTANCE: Option<Arc<KSet>> = None;
static mut __ACPI_TABLES_KSET_INSTANCE: Option<Arc<KSet>> = None;
static mut __ACPI_TABLES_DATA_KSET_INSTANCE: Option<Arc<KSet>> = None;
static mut __ACPI_TABLES_DYNAMIC_KSET_INSTANCE: Option<Arc<KSet>> = None;
static mut __ACPI_TABLE_ATTR_LIST: Option<RwLock<Vec<Arc<AttrAcpiTable>>>> = None;
const ACPI_MAX_TABLE_INSTANCES: usize = 999;
#[inline(always)]
#[allow(dead_code)]
pub fn hotplug_kset() -> Arc<KSet> {
unsafe { __HOTPLUG_KSET_INSTANCE.clone().unwrap() }
}
#[inline(always)]
pub fn acpi_tables_kset() -> Arc<KSet> {
unsafe { __ACPI_TABLES_KSET_INSTANCE.clone().unwrap() }
}
#[inline(always)]
#[allow(dead_code)]
pub fn acpi_tables_data_kset() -> Arc<KSet> {
unsafe { __ACPI_TABLES_DATA_KSET_INSTANCE.clone().unwrap() }
}
#[inline(always)]
#[allow(dead_code)]
pub fn acpi_tables_dynamic_kset() -> Arc<KSet> {
unsafe { __ACPI_TABLES_DYNAMIC_KSET_INSTANCE.clone().unwrap() }
}
#[inline(always)]
fn acpi_table_attr_list() -> &'static RwLock<Vec<Arc<AttrAcpiTable>>> {
unsafe {
return __ACPI_TABLE_ATTR_LIST.as_ref().unwrap();
}
}
impl AcpiManager {
pub(super) fn acpi_sysfs_init(&self) -> Result<(), SystemError> {
unsafe {
__ACPI_TABLE_ATTR_LIST = Some(RwLock::new(Vec::new()));
}
self.acpi_tables_sysfs_init()?;
let hotplug_kset = KSet::new("hotplug".to_string());
hotplug_kset.register(Some(acpi_kset()))?;
unsafe {
__HOTPLUG_KSET_INSTANCE = Some(hotplug_kset.clone());
}
let hotplug_kobj = hotplug_kset as Arc<dyn KObject>;
sysfs_instance().create_file(&hotplug_kobj, &AttrForceRemove)?;
return Ok(());
}
/// 在 sysfs 中创建 ACPI 表目录
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/sysfs.c?fi=acpi_sysfs_init#488
fn acpi_tables_sysfs_init(&self) -> Result<(), SystemError> {
// 创建 `/sys/firmware/acpi/tables` 目录
let acpi_tables_kset = KSet::new("tables".to_string());
acpi_tables_kset.register(Some(acpi_kset()))?;
unsafe {
__ACPI_TABLES_KSET_INSTANCE = Some(acpi_tables_kset.clone());
}
// 创建 `/sys/firmware/acpi/tables/data` 目录
let acpi_tables_data_kset = KSet::new("data".to_string());
acpi_tables_data_kset.register(Some(acpi_tables_kset.clone()))?;
unsafe {
__ACPI_TABLES_DATA_KSET_INSTANCE = Some(acpi_tables_data_kset);
}
// 创建 `/sys/firmware/acpi/tables/dynamic` 目录
let acpi_tables_dynamic_kset = KSet::new("dynamic".to_string());
acpi_tables_dynamic_kset.register(Some(acpi_tables_kset.clone()))?;
unsafe {
__ACPI_TABLES_DYNAMIC_KSET_INSTANCE = Some(acpi_tables_dynamic_kset);
}
// todo: get acpi tables.
let tables = self.tables().unwrap();
let headers = tables.headers();
for header in headers {
kdebug!("ACPI header: {:?}", header);
let attr = AttrAcpiTable::new(&header)?;
acpi_table_attr_list().write().push(attr);
self.acpi_table_data_init(&header)?;
}
return Ok(());
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/sysfs.c?fi=acpi_sysfs_init#469
fn acpi_table_data_init(&self, _header: &SdtHeader) -> Result<(), SystemError> {
// todo!("AcpiManager::acpi_table_data_init()")
return Ok(());
}
}
#[derive(Debug)]
struct AttrForceRemove;
impl Attribute for AttrForceRemove {
fn name(&self) -> &str {
"force_remove"
}
fn mode(&self) -> ModeType {
return ModeType::from_bits_truncate(0o444);
}
fn support(&self) -> SysFSOpsSupport {
return SysFSOpsSupport::SHOW;
}
fn show(&self, _kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
return sysfs_emit_str(buf, "0\n");
}
}
/// ACPI 表在 sysfs 中的属性
#[derive(Debug)]
struct AttrAcpiTable {
name: String,
filename: String,
instance: isize,
size: usize,
}
impl AttrAcpiTable {
pub fn new(header: &SdtHeader) -> Result<Arc<Self>, SystemError> {
let mut r = Self {
name: header.signature.to_string(),
filename: "".to_string(),
instance: 0,
size: header.length as usize,
};
for attr in acpi_table_attr_list().read().iter() {
if attr.name == r.name {
r.instance = attr.instance;
}
}
// 将当前实例的序号加1
r.instance += 1;
if r.instance > ACPI_MAX_TABLE_INSTANCES as isize {
kwarn!("too many table instances. name: {}", r.name);
return Err(SystemError::ERANGE);
}
let mut has_multiple_instances: bool = false;
let mut tmpcnt = 0;
for h in acpi_manager().tables().unwrap().headers() {
if h.signature == header.signature {
tmpcnt += 1;
if tmpcnt > 1 {
has_multiple_instances = true;
break;
}
}
}
if r.instance > 1 || (r.instance == 1 && has_multiple_instances) {
r.filename = format!("{}{}", r.name, r.instance);
} else {
r.filename = r.name.clone();
}
let result = Arc::new(r);
sysfs_instance().create_bin_file(
&(acpi_tables_kset() as Arc<dyn KObject>),
&(result.clone() as Arc<dyn BinAttribute>),
)?;
return Ok(result);
}
}
impl Attribute for AttrAcpiTable {
fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn name(&self) -> &str {
return &self.filename;
}
fn mode(&self) -> ModeType {
return ModeType::from_bits_truncate(0o400);
}
fn support(&self) -> SysFSOpsSupport {
return SysFSOpsSupport::empty();
}
}
impl BinAttribute for AttrAcpiTable {
fn support_battr(&self) -> SysFSOpsSupport {
return SysFSOpsSupport::READ;
}
fn write(
&self,
_kobj: Arc<dyn KObject>,
_buf: &[u8],
_offset: usize,
) -> Result<usize, SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
/// 展示 ACPI 表的内容
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/acpi/sysfs.c?fi=acpi_sysfs_init#320
fn read(
&self,
_kobj: Arc<dyn KObject>,
buf: &mut [u8],
offset: usize,
) -> Result<usize, SystemError> {
macro_rules! copy_data {
($table:expr) => {
let from = unsafe {
core::slice::from_raw_parts(
$table.virtual_start().as_ptr() as *const u8,
$table.region_length(),
)
};
if offset >= from.len() {
return Ok(0);
}
let mut count = buf.len();
if count > from.len() - offset {
count = from.len() - offset;
}
buf[0..count].copy_from_slice(&from[offset..offset + count]);
return Ok(count);
};
}
macro_rules! define_struct {
($name:ident) => {
#[repr(transparent)]
#[allow(non_snake_case)]
#[allow(non_camel_case_types)]
struct $name {
header: SdtHeader,
}
unsafe impl acpi::AcpiTable for $name {
const SIGNATURE: acpi::sdt::Signature = acpi::sdt::Signature::$name;
fn header(&self) -> &acpi::sdt::SdtHeader {
return &self.header;
}
}
};
}
macro_rules! handle {
($name: ident, $tables: expr) => {
define_struct!($name);
let table = $tables.find_entire_table::<$name>().map_err(|e| {
kwarn!(
"AttrAcpiTable::read(): failed to find table. name: {}, error: {:?}",
self.name,
e
);
SystemError::ENODEV
})?;
copy_data!(table);
};
}
let tables = acpi_manager().tables().unwrap();
match self.name.as_str() {
"RSDT" => {
handle!(RSDT, tables);
}
"XSDT" => {
handle!(XSDT, tables);
}
"FACP" => {
handle!(FADT, tables);
}
"HPET" => {
handle!(HPET, tables);
}
"APIC" => {
handle!(MADT, tables);
}
"MCFG" => {
handle!(MCFG, tables);
}
"SSDT" => {
handle!(SSDT, tables);
}
"BERT" => {
handle!(BERT, tables);
}
"BGRT" => {
handle!(BGRT, tables);
}
"CPEP" => {
handle!(CPEP, tables);
}
"DSDT" => {
handle!(DSDT, tables);
}
"ECDT" => {
handle!(ECDT, tables);
}
"EINJ" => {
handle!(EINJ, tables);
}
"ERST" => {
handle!(ERST, tables);
}
"FACS" => {
handle!(FACS, tables);
}
"FPDT" => {
handle!(FPDT, tables);
}
"GTDT" => {
handle!(GTDT, tables);
}
"HEST" => {
handle!(HEST, tables);
}
"MSCT" => {
handle!(MSCT, tables);
}
"MPST" => {
handle!(MPST, tables);
}
"NFIT" => {
handle!(NFIT, tables);
}
"PCCT" => {
handle!(PCCT, tables);
}
"PHAT" => {
handle!(PHAT, tables);
}
"PMTT" => {
handle!(PMTT, tables);
}
"PSDT" => {
handle!(PSDT, tables);
}
"RASF" => {
handle!(RASF, tables);
}
"SBST" => {
handle!(SBST, tables);
}
"SDEV" => {
handle!(SDEV, tables);
}
"SLIT" => {
handle!(SLIT, tables);
}
"SRAT" => {
handle!(SRAT, tables);
}
"AEST" => {
handle!(AEST, tables);
}
"BDAT" => {
handle!(BDAT, tables);
}
"CDIT" => {
handle!(CDIT, tables);
}
"CEDT" => {
handle!(CEDT, tables);
}
"CRAT" => {
handle!(CRAT, tables);
}
"CSRT" => {
handle!(CSRT, tables);
}
"DBGP" => {
handle!(DBGP, tables);
}
"DBG2" => {
handle!(DBG2, tables);
}
"DMAR" => {
handle!(DMAR, tables);
}
"DRTM" => {
handle!(DRTM, tables);
}
"ETDT" => {
handle!(ETDT, tables);
}
"IBFT" => {
handle!(IBFT, tables);
}
"IORT" => {
handle!(IORT, tables);
}
"IVRS" => {
handle!(IVRS, tables);
}
"LPIT" => {
handle!(LPIT, tables);
}
"MCHI" => {
handle!(MCHI, tables);
}
"MPAM" => {
handle!(MPAM, tables);
}
"MSDM" => {
handle!(MSDM, tables);
}
"PRMT" => {
handle!(PRMT, tables);
}
"RGRT" => {
handle!(RGRT, tables);
}
"SDEI" => {
handle!(SDEI, tables);
}
"SLIC" => {
handle!(SLIC, tables);
}
"SPCR" => {
handle!(SPCR, tables);
}
"SPMI" => {
handle!(SPMI, tables);
}
"STAO" => {
handle!(STAO, tables);
}
"SVKL" => {
handle!(SVKL, tables);
}
"TCPA" => {
handle!(TCPA, tables);
}
"TPM2" => {
handle!(TPM2, tables);
}
"UEFI" => {
handle!(UEFI, tables);
}
"WAET" => {
handle!(WAET, tables);
}
"WDAT" => {
handle!(WDAT, tables);
}
"WDRT" => {
handle!(WDRT, tables);
}
"WPBT" => {
handle!(WPBT, tables);
}
"WSMT" => {
handle!(WSMT, tables);
}
"XENV" => {
handle!(XENV, tables);
}
_ => {
kerror!("AttrAcpiTable::read(): unknown table. name: {}", self.name);
return Err(SystemError::ENODEV);
}
};
}
fn size(&self) -> usize {
return self.size;
}
}

View File

@ -97,6 +97,7 @@ impl From<BusState> for DeviceState {
/// https://opengrok.ringotek.cn/xref/linux-6.1.9/include/linux/device/bus.h#84
pub trait Bus: Debug + Send + Sync {
fn name(&self) -> String;
/// Used for subsystems to enumerate devices like ("foo%u", dev->id).
fn dev_name(&self) -> String;
fn root_device(&self) -> Option<Arc<dyn Device>> {
None

View File

@ -161,6 +161,20 @@ impl SysFSOps for KObjectSysFSOps {
pub struct KObjectManager;
impl KObjectManager {
#[allow(dead_code)]
pub fn init_and_add_kobj(
kobj: Arc<dyn KObject>,
join_kset: Option<Arc<KSet>>,
) -> Result<(), SystemError> {
Self::kobj_init(&kobj);
Self::add_kobj(kobj, join_kset)
}
#[allow(dead_code)]
pub fn kobj_init(kobj: &Arc<dyn KObject>) {
kobj.set_kobj_type(Some(&DynamicKObjKType));
}
pub fn add_kobj(
kobj: Arc<dyn KObject>,
join_kset: Option<Arc<KSet>>,
@ -212,3 +226,21 @@ impl KObjectManager {
return Ok(());
}
}
/// 动态创建的kobject对象的ktype
#[derive(Debug)]
pub struct DynamicKObjKType;
impl KObjType for DynamicKObjKType {
fn release(&self, kobj: Arc<dyn KObject>) {
kdebug!("DynamicKObjKType::release() kobj:{:?}", kobj.name());
}
fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
Some(&KObjectSysFSOps)
}
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
None
}
}

View File

@ -7,16 +7,13 @@ use alloc::{
use core::hash::Hash;
use crate::{
filesystem::{
kernfs::KernFSInode,
sysfs::{AttributeGroup, SysFSOps},
},
filesystem::kernfs::KernFSInode,
libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
syscall::SystemError,
};
use super::kobject::{
KObjType, KObject, KObjectManager, KObjectState, KObjectSysFSOps, LockedKObjectState,
DynamicKObjKType, KObjType, KObject, KObjectManager, KObjectState, LockedKObjectState,
};
#[derive(Debug)]
@ -164,11 +161,11 @@ impl KObject for KSet {
}
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
Some(&KSetKObjType)
self.inner.read().ktype
}
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
todo!("KSet::set_kobj_type")
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
self.inner.write().ktype = ktype;
}
fn kset(&self) -> Option<Arc<KSet>> {
@ -208,6 +205,7 @@ impl KSetParentData {
struct InnerKSet {
kern_inode: Option<Arc<KernFSInode>>,
name: String,
ktype: Option<&'static dyn KObjType>,
}
impl InnerKSet {
@ -215,19 +213,7 @@ impl InnerKSet {
Self {
kern_inode: None,
name,
ktype: Some(&DynamicKObjKType),
}
}
}
#[derive(Debug)]
pub struct KSetKObjType;
impl KObjType for KSetKObjType {
fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
Some(&KObjectSysFSOps)
}
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
None
}
}

View File

@ -2,25 +2,40 @@
#include <common/glib.h>
#include <common/kprint.h>
uintptr_t multiboot2_boot_info_addr;
unsigned int multiboot2_magic;
// uintptr_t multiboot2_boot_info_addr;
// unsigned int multiboot2_magic;
unsigned int multiboot2_boot_info_size;
bool multiboot2_init(void)
#define MBI_RAW_MAX_SIZE 409600
// 由于启动时传递的mb2 info所在的地址,在内存管理初始化之后会被覆盖,所以需要将其拷贝到一个固定的位置
static uint8_t mbi_raw[MBI_RAW_MAX_SIZE] = {0};
bool multiboot2_init(uint64_t mb2_info_paddr, uint32_t mb2_magic)
{
uintptr_t *addr = (uintptr_t *)multiboot2_boot_info_addr;
if (multiboot2_magic != MULTIBOOT2_BOOTLOADER_MAGIC)
uint64_t vaddr = phys_2_virt(mb2_info_paddr);
if (mb2_magic != MULTIBOOT2_BOOTLOADER_MAGIC)
return false;
// addr+0 处保存了大小
multiboot2_boot_info_size = *(unsigned int *)addr;
// vaddr+0 处保存了大小
multiboot2_boot_info_size = *(uint32_t *)vaddr;
if (multiboot2_boot_info_size > MBI_RAW_MAX_SIZE)
return false;
memcpy((void *)mbi_raw, (void *)vaddr, multiboot2_boot_info_size);
return true;
}
void multiboot2_iter(bool (*_fun)(const struct iter_data_t *, void *, unsigned int *),
void *data, unsigned int *count)
{
// kdebug("multiboot2_boot_info_addr=%#018lx", multiboot2_boot_info_addr);
uintptr_t addr = multiboot2_boot_info_addr;
// uintptr_t addr = multiboot2_boot_info_addr;
// for(int i=0;i<8192;i++)
// {
// mbi_raw[i] = ((uint8_t *)multiboot2_boot_info_addr)[i];
// }
uint8_t * addr = mbi_raw;
// 接下来的第8字节开始为 tag 信息
struct iter_data_t *tag = (struct iter_data_t *)((void *)addr + 8);
for (; tag->type != MULTIBOOT_TAG_TYPE_END;

View File

@ -26,9 +26,6 @@
* @brief MULTIBOOT2
*/
extern unsigned int multiboot2_magic;
extern uintptr_t multiboot2_boot_info_addr;
/* How many bytes from the start of the file we search for the header. */
static const unsigned int MULTIBOOT_SEARCH = 32768;
static const unsigned int MULTIBOOT_HEADER_ALIGN = 8;
@ -416,7 +413,7 @@ struct iter_data_t
* @return true
* @return false
*/
static bool multiboot2_init(void);
bool multiboot2_init(uint64_t mb2_info_paddr, uint32_t mb2_magic);
/**
* @brief

View File

@ -439,7 +439,7 @@ impl KernFSInode {
return Err(SystemError::ENOTDIR);
}
return self.inner_create(name, KernInodeType::Dir, mode, private_data, callback);
return self.inner_create(name, KernInodeType::Dir, mode, 0, private_data, callback);
}
/// 在当前inode下增加文件
@ -448,9 +448,11 @@ impl KernFSInode {
///
/// - `name`:文件名称
/// - `mode`:文件权限
/// - `size`:文件大小(如果不指定则默认为4096)
/// - `private_data`:文件私有数据
/// - `callback`:文件回调函数
///
///
/// ## 返回值
///
/// - 成功文件inode
@ -461,6 +463,7 @@ impl KernFSInode {
&self,
name: String,
mode: ModeType,
size: Option<usize>,
private_data: Option<KernInodePrivateData>,
callback: Option<&'static dyn KernFSCallback>,
) -> Result<Arc<KernFSInode>, SystemError> {
@ -468,7 +471,15 @@ impl KernFSInode {
return Err(SystemError::ENOTDIR);
}
return self.inner_create(name, KernInodeType::File, mode, private_data, callback);
let size = size.unwrap_or(4096);
return self.inner_create(
name,
KernInodeType::File,
mode,
size,
private_data,
callback,
);
}
fn inner_create(
@ -476,21 +487,19 @@ impl KernFSInode {
name: String,
file_type: KernInodeType,
mode: ModeType,
mut size: usize,
private_data: Option<KernInodePrivateData>,
callback: Option<&'static dyn KernFSCallback>,
) -> Result<Arc<KernFSInode>, SystemError> {
let size;
match file_type {
KernInodeType::Dir | KernInodeType::SymLink => {
size = 0;
}
KernInodeType::File => {
size = 4096;
}
_ => {}
}
let metadata = Metadata {
size,
size: size as i64,
mode,
uid: 0,
gid: 0,
@ -570,6 +579,7 @@ impl KernFSInode {
name,
KernInodeType::SymLink,
ModeType::S_IFLNK | ModeType::from_bits_truncate(0o777),
0,
None,
None,
)?;

View File

@ -19,23 +19,36 @@ use crate::{
syscall::SystemError,
};
use super::{Attribute, SysFS, SysFSKernPrivateData};
use super::{Attribute, BinAttribute, SysFS, SysFSKernPrivateData};
#[derive(Debug)]
pub struct SysKernFilePriv {
attribute: Option<&'static dyn Attribute>,
/// bin attribute和attribute二选一只能有一个为Some
bin_attribute: Option<Arc<dyn BinAttribute>>,
/// 当前文件对应的kobject
kobj: Weak<dyn KObject>,
// todo: 增加bin attribute,它和attribute二选一只能有一个为Some
}
impl SysKernFilePriv {
pub fn new(kobj: &Arc<dyn KObject>, attribute: Option<&'static dyn Attribute>) -> Self {
if attribute.is_none() {
panic!("attribute can't be None");
pub fn new(
kobj: &Arc<dyn KObject>,
attribute: Option<&'static dyn Attribute>,
bin_attribute: Option<Arc<dyn BinAttribute>>,
) -> Self {
if attribute.is_none() && bin_attribute.is_none() {
panic!("attribute and bin_attribute can't be both None");
}
if attribute.is_some() && bin_attribute.is_some() {
panic!("attribute and bin_attribute can't be both Some");
}
let kobj = Arc::downgrade(kobj);
return Self { kobj, attribute };
return Self {
kobj,
attribute,
bin_attribute,
};
}
#[allow(dead_code)]
@ -44,18 +57,41 @@ impl SysKernFilePriv {
self.attribute
}
pub fn callback_read(&self, buf: &mut [u8]) -> Result<usize, SystemError> {
let attribute = self.attribute.ok_or(SystemError::EINVAL)?;
pub fn callback_read(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
if let Some(attribute) = self.attribute {
// 当前文件所指向的kobject已经被释放
let kobj = self.kobj.upgrade().expect("kobj is None");
return attribute.show(kobj, buf);
let len = attribute.show(kobj, buf)?;
if offset > 0 {
if len <= offset {
return Ok(0);
}
let len = len - offset;
buf.copy_within(offset..offset + len, 0);
buf[len] = 0;
}
return Ok(len);
} else if let Some(bin_attribute) = self.bin_attribute.as_ref() {
// 当前文件所指向的kobject已经被释放
let kobj = self.kobj.upgrade().expect("kobj is None");
return bin_attribute.read(kobj, buf, offset);
} else {
panic!("attribute and bin_attribute can't be both None");
}
}
pub fn callback_write(&self, buf: &[u8]) -> Result<usize, SystemError> {
let attribute = self.attribute.ok_or(SystemError::EINVAL)?;
pub fn callback_write(&self, buf: &[u8], offset: usize) -> Result<usize, SystemError> {
if let Some(attribute) = self.attribute {
// 当前文件所指向的kobject已经被释放
let kobj = self.kobj.upgrade().expect("kobj is None");
return attribute.store(kobj, buf);
} else if let Some(bin_attribute) = self.bin_attribute.as_ref() {
// 当前文件所指向的kobject已经被释放
let kobj = self.kobj.upgrade().expect("kobj is None");
return bin_attribute.write(kobj, buf, offset);
} else {
panic!("attribute and bin_attribute can't be both None");
}
}
}
@ -115,10 +151,11 @@ impl SysFS {
kern_callback = &PreallocKFOpsEmpty;
}
let sys_priv = SysFSKernPrivateData::File(SysKernFilePriv::new(&kobj, Some(attr)));
let sys_priv = SysFSKernPrivateData::File(SysKernFilePriv::new(&kobj, Some(attr), None));
let r = parent.add_file(
attr.name().to_string(),
mode.bitand(ModeType::from_bits_truncate(0o777)),
Some(4096),
Some(KernInodePrivateData::SysFS(sys_priv)),
Some(kern_callback),
);
@ -155,6 +192,95 @@ impl SysFS {
}
}
}
/// 在sysfs中为指定的kobject创建一个动态申请的bin属性文件
///
/// ## 参数
///
/// - `kobj` 要创建属性文件的kobject
/// - `attr` 属性
///
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/file.c#558
pub fn create_bin_file(
&self,
kobj: &Arc<dyn KObject>,
attr: &Arc<dyn BinAttribute>,
) -> Result<(), SystemError> {
let inode = kobj.inode().ok_or(SystemError::EINVAL)?;
return self.add_bin_file_with_mode(&inode, attr, attr.mode());
}
/// 在sysfs中删除某个kobject的bin属性文件
///
/// 如果属性文件不存在,则发出一个警告
#[allow(dead_code)]
pub fn remove_bin_file(&self, kobj: &Arc<dyn KObject>, attr: &Arc<dyn BinAttribute>) {
let parent = kobj.inode();
if let Some(parent) = parent {
let r = parent.remove(attr.name());
if unlikely(r.is_err()) {
kwarn!(
"failed to remove file '{}' from '{}'",
attr.name(),
kobj.name()
);
}
}
}
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/file.c#304
pub(super) fn add_bin_file_with_mode(
&self,
parent: &Arc<KernFSInode>,
attr: &Arc<dyn BinAttribute>,
mode: ModeType,
) -> Result<(), SystemError> {
let x = parent.private_data_mut();
let kobj: Arc<dyn KObject>;
if let Some(KernInodePrivateData::SysFS(SysFSKernPrivateData::Dir(dt))) = x.as_ref() {
kobj = dt.kobj().unwrap();
} else {
drop(x);
let path = self.kernfs_path(parent);
panic!("parent '{path}' is not a dir");
}
drop(x);
let kern_callback: &'static dyn KernFSCallback;
let bin_support = attr.support_battr();
if bin_support.contains(SysFSOpsSupport::READ)
&& bin_support.contains(SysFSOpsSupport::WRITE)
{
kern_callback = &PreallocKFOpsRW;
} else if bin_support.contains(SysFSOpsSupport::READ) {
kern_callback = &PreallocKFOpsReadOnly;
} else if bin_support.contains(SysFSOpsSupport::WRITE) {
kern_callback = &PreallocKFOpsWriteOnly;
} else {
kern_callback = &PreallocKFOpsEmpty;
}
let sys_priv =
SysFSKernPrivateData::File(SysKernFilePriv::new(&kobj, None, Some(attr.clone())));
let r = parent.add_file(
attr.name().to_string(),
mode.bitand(ModeType::from_bits_truncate(0o777)),
Some(attr.size()),
Some(KernInodePrivateData::SysFS(sys_priv)),
Some(kern_callback),
);
if let Err(e) = r {
if e == SystemError::EEXIST {
self.warn_duplicate(parent, attr.name());
}
return Err(e);
}
return Ok(());
}
}
#[derive(Debug)]

View File

@ -69,15 +69,8 @@ impl SysFSKernPrivateData {
pub fn callback_read(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
match self {
SysFSKernPrivateData::File(file) => {
let len = file.callback_read(buf)?;
if offset > 0 {
if len <= offset {
return Ok(0);
}
let len = len - offset;
buf.copy_within(offset..offset + len, 0);
buf[len] = 0;
}
let len = file.callback_read(buf, offset)?;
return Ok(len);
}
_ => {
@ -87,10 +80,10 @@ impl SysFSKernPrivateData {
}
#[inline(always)]
pub fn callback_write(&self, buf: &[u8], _offset: usize) -> Result<usize, SystemError> {
pub fn callback_write(&self, buf: &[u8], offset: usize) -> Result<usize, SystemError> {
match self {
SysFSKernPrivateData::File(file) => {
return file.callback_write(buf);
return file.callback_write(buf, offset);
}
_ => {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
@ -114,7 +107,7 @@ pub trait AttributeGroup: Debug + Send + Sync {
///
/// 如果返回Some则使用返回的权限。
/// 如果要标识属性不可见则返回Some(ModeType::empty())
fn is_visible(&self, kobj: Arc<dyn KObject>, attr: &dyn Attribute) -> Option<ModeType>;
fn is_visible(&self, kobj: Arc<dyn KObject>, attr: &'static dyn Attribute) -> Option<ModeType>;
}
/// sysfs文件的属性
@ -133,12 +126,40 @@ pub trait Attribute: Debug + Send + Sync {
}
}
pub trait BinAttribute: Attribute {
fn support_battr(&self) -> SysFSOpsSupport;
fn write(
&self,
_kobj: Arc<dyn KObject>,
_buf: &[u8],
_offset: usize,
) -> Result<usize, SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn read(
&self,
_kobj: Arc<dyn KObject>,
_buf: &mut [u8],
_offset: usize,
) -> Result<usize, SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
fn size(&self) -> usize;
}
pub trait SysFSOps: Debug {
/// 获取当前文件的支持的操作
fn support(&self, attr: &dyn Attribute) -> SysFSOpsSupport {
return attr.support();
}
fn support_battr(&self, attr: &Arc<dyn BinAttribute>) -> SysFSOpsSupport {
return attr.support();
}
fn show(
&self,
kobj: Arc<dyn KObject>,
@ -156,8 +177,12 @@ pub trait SysFSOps: Debug {
bitflags! {
pub struct SysFSOpsSupport: u8{
// === for attribute ===
const SHOW = 1 << 0;
const STORE = 1 << 1;
// === for bin attribute ===
const READ = 1 << 2;
const WRITE = 1 << 3;
}
}

View File

@ -693,7 +693,7 @@ impl Syscall {
kstat.rdev = metadata.raw_dev as i64;
kstat.mode = metadata.mode;
match file.lock().file_type() {
FileType::File => kstat.mode.insert(ModeType::S_IFMT),
FileType::File => kstat.mode.insert(ModeType::S_IFREG),
FileType::Dir => kstat.mode.insert(ModeType::S_IFDIR),
FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK),
FileType::CharDevice => kstat.mode.insert(ModeType::S_IFCHR),

View File

@ -71,7 +71,6 @@ void reload_idt()
void system_initialize()
{
rs_init_before_mem_init();
// 重新加载gdt和idt
ul tss_item_addr = (ul)phys_2_virt(0x7c00);
@ -88,7 +87,6 @@ void system_initialize()
// 初始化内存管理单元
// mm_init();
rs_mm_init();
// 内存管理单元初始化完毕后,需要立即重新初始化显示驱动。
// 原因是系统启动初期framebuffer被映射到48M地址处
// mm初始化完毕后若不重新初始化显示驱动将会导致错误的数据写入内存从而造成其他模块崩溃
@ -101,6 +99,9 @@ void system_initialize()
rs_init_intertrait();
// kinfo("vaddr:%#018lx", video_frame_buffer_info.vaddr);
io_mfence();
vfs_init();
rs_driver_init();
acpi_init();
io_mfence();
@ -124,9 +125,7 @@ void system_initialize()
rs_jiffies_init();
io_mfence();
vfs_init();
rs_driver_init();
rs_kthread_init();
io_mfence();
@ -183,8 +182,7 @@ void Start_Kernel(void)
mb2_info &= 0xffffffff;
mb2_magic &= 0xffffffff;
multiboot2_magic = (uint)mb2_magic;
multiboot2_boot_info_addr = mb2_info + PAGE_OFFSET;
multiboot2_init(mb2_info, mb2_magic);
io_mfence();
system_initialize();
io_mfence();

View File

@ -7,7 +7,7 @@ use hashbrown::HashMap;
use crate::{
arch::mm::LowAddressRemapping,
include::bindings::bindings::{gfp_t, PAGE_U_S},
include::bindings::bindings::{gfp_t, vm_flags_t, PAGE_U_S},
kerror,
libs::{align::page_align_up, spinlock::SpinLock},
mm::MMArch,
@ -15,8 +15,8 @@ use crate::{
};
use super::{
allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, no_init::pseudo_map_phys,
page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, mmio_buddy::mmio_pool,
no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
};
lazy_static! {
@ -125,3 +125,50 @@ pub unsafe extern "C" fn rs_unmap_at_low_addr() -> usize {
LowAddressRemapping::unmap_at_low_address(true);
return 0;
}
/// @brief 创建一块mmio区域并将vma绑定到initial_mm
///
/// @param size mmio区域的大小字节
///
/// @param vm_flags 要把vma设置成的标志
///
/// @param res_vaddr 返回值-分配得到的虚拟地址
///
/// @param res_length 返回值-分配的虚拟地址空间长度
///
/// @return int 错误码
#[no_mangle]
unsafe extern "C" fn rs_mmio_create(
size: u32,
_vm_flags: vm_flags_t,
res_vaddr: *mut u64,
res_length: *mut u64,
) -> i32 {
// kdebug!("mmio_create");
let r = mmio_pool().create_mmio(size as usize);
if r.is_err() {
return r.unwrap_err().to_posix_errno();
}
let space_guard = r.unwrap();
*res_vaddr = space_guard.vaddr().data() as u64;
*res_length = space_guard.size() as u64;
// 由于space_guard drop的时候会自动释放内存所以这里要忽略它的释放
core::mem::forget(space_guard);
return 0;
}
/// @brief 取消mmio的映射并将地址空间归还到buddy中
///
/// @param vaddr 起始的虚拟地址
///
/// @param length 要归还的地址空间的长度
///
/// @return Ok(i32) 成功返回0
///
/// @return Err(i32) 失败返回错误码
#[no_mangle]
pub unsafe extern "C" fn rs_mmio_release(vaddr: u64, length: u64) -> i32 {
return mmio_pool()
.release_mmio(VirtAddr::new(vaddr as usize), length as usize)
.unwrap_or_else(|err| err.to_posix_errno());
}

View File

@ -1,5 +1,5 @@
#pragma once
#include "mm.h"
extern void mmio_create(uint32_t size, uint64_t vm_flagsu, uint64_t* res_vaddr, uint64_t* res_length);
extern int mmio_release(int vaddr, int length);
extern int rs_mmio_create(uint32_t size, uint64_t vm_flags, uint64_t* res_vaddr, uint64_t* res_length);
extern int rs_mmio_release(uint64_t vaddr, uint64_t length);

View File

@ -3,7 +3,7 @@ use crate::mm::kernel_mapper::KernelMapper;
use crate::process::ProcessManager;
use crate::syscall::SystemError;
use crate::{
include::bindings::bindings::{vm_flags_t, PAGE_1G_SHIFT, PAGE_4K_SHIFT, PAGE_4K_SIZE},
include::bindings::bindings::{PAGE_1G_SHIFT, PAGE_4K_SHIFT, PAGE_4K_SIZE},
kdebug,
mm::{MMArch, MemoryManagementArch},
};
@ -520,7 +520,7 @@ impl MmioBuddyMemPool {
/// @return Ok(i32) 成功返回0
///
/// @return Err(SystemError) 失败返回错误码
fn release_mmio(&self, vaddr: VirtAddr, length: usize) -> Result<i32, SystemError> {
pub fn release_mmio(&self, vaddr: VirtAddr, length: usize) -> Result<i32, SystemError> {
assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
assert!(length & (MMArch::PAGE_SIZE - 1) == 0);
if vaddr < self.pool_start_addr
@ -707,49 +707,3 @@ pub fn mmio_init() {
kinfo!("MMIO buddy memory pool init done");
}
/// @brief 创建一块mmio区域并将vma绑定到initial_mm
///
/// @param size mmio区域的大小字节
///
/// @param vm_flags 要把vma设置成的标志
///
/// @param res_vaddr 返回值-分配得到的虚拟地址
///
/// @param res_length 返回值-分配的虚拟地址空间长度
///
/// @return int 错误码
#[no_mangle]
pub unsafe extern "C" fn mmio_create(
size: u32,
_vm_flags: vm_flags_t,
res_vaddr: *mut u64,
res_length: *mut u64,
) -> i32 {
// kdebug!("mmio_create");
let r = mmio_pool().create_mmio(size as usize);
if r.is_err() {
return r.unwrap_err().to_posix_errno();
}
let space_guard = r.unwrap();
*res_vaddr = space_guard.vaddr().data() as u64;
*res_length = space_guard.size() as u64;
// 由于space_guard drop的时候会自动释放内存所以这里要忽略它的释放
core::mem::forget(space_guard);
return 0;
}
/// @brief 取消mmio的映射并将地址空间归还到buddy中
///
/// @param vaddr 起始的虚拟地址
///
/// @param length 要归还的地址空间的长度
///
/// @return Ok(i32) 成功返回0
///
/// @return Err(i32) 失败返回错误码
#[no_mangle]
pub unsafe extern "C" fn mmio_release(vaddr: u64, length: u64) -> i32 {
return mmio_pool()
.release_mmio(VirtAddr::new(vaddr as usize), length as usize)
.unwrap_or_else(|err| err.to_posix_errno());
}