mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-10 03:56:49 +00:00
parent
c2481452f8
commit
a7eb62a47a
@ -1,3 +1,4 @@
|
|||||||
|
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::asm::current::current_pcb,
|
arch::asm::current::current_pcb,
|
||||||
include::bindings::bindings::{
|
include::bindings::bindings::{
|
||||||
@ -6,7 +7,6 @@ use crate::{
|
|||||||
PAGE_2M_SIZE, PAGE_4K_SHIFT, PAGE_4K_SIZE, VM_DONTCOPY, VM_IO,
|
PAGE_2M_SIZE, PAGE_4K_SHIFT, PAGE_4K_SIZE, VM_DONTCOPY, VM_IO,
|
||||||
},
|
},
|
||||||
kdebug, kerror,
|
kdebug, kerror,
|
||||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
|
||||||
};
|
};
|
||||||
use alloc::{boxed::Box, collections::LinkedList, vec::Vec};
|
use alloc::{boxed::Box, collections::LinkedList, vec::Vec};
|
||||||
use core::{mem, ptr::null_mut};
|
use core::{mem, ptr::null_mut};
|
||||||
@ -57,7 +57,7 @@ impl MmioBuddyMemPool {
|
|||||||
/// @param vaddr 虚拟地址
|
/// @param vaddr 虚拟地址
|
||||||
///
|
///
|
||||||
/// @return 创建好的地址区域结构体
|
/// @return 创建好的地址区域结构体
|
||||||
fn __create_region(&self, vaddr: u64) -> Box<MmioBuddyAddrRegion> {
|
fn create_region(&self, vaddr: u64) -> Box<MmioBuddyAddrRegion> {
|
||||||
let mut region: Box<MmioBuddyAddrRegion> = Box::new(MmioBuddyAddrRegion::new());
|
let mut region: Box<MmioBuddyAddrRegion> = Box::new(MmioBuddyAddrRegion::new());
|
||||||
region.vaddr = vaddr;
|
region.vaddr = vaddr;
|
||||||
return region;
|
return region;
|
||||||
@ -74,16 +74,16 @@ impl MmioBuddyMemPool {
|
|||||||
/// @return Ok(i32) 返回0
|
/// @return Ok(i32) 返回0
|
||||||
///
|
///
|
||||||
/// @return Err(i32) 返回错误码
|
/// @return Err(i32) 返回错误码
|
||||||
fn __give_back_block(&self, vaddr: u64, exp: u32) -> Result<i32, i32> {
|
fn give_back_block(&self, vaddr: u64, exp: u32) -> Result<i32, i32> {
|
||||||
// 确保内存对齐,低位都要为0
|
// 确保内存对齐,低位都要为0
|
||||||
if (vaddr & ((1 << exp) - 1)) != 0 {
|
if (vaddr & ((1 << exp) - 1)) != 0 {
|
||||||
return Err(-(EINVAL as i32));
|
return Err(-(EINVAL as i32));
|
||||||
}
|
}
|
||||||
let region: Box<MmioBuddyAddrRegion> = self.__create_region(vaddr);
|
let region: Box<MmioBuddyAddrRegion> = self.create_region(vaddr);
|
||||||
// 加入buddy
|
// 加入buddy
|
||||||
let list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
|
let list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
|
||||||
&mut self.free_regions[__exp2index(exp)].lock();
|
&mut self.free_regions[exp2index(exp)].lock();
|
||||||
self.__buddy_add_region_obj(region, list_guard);
|
self.push_block(region, list_guard);
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,16 +94,16 @@ impl MmioBuddyMemPool {
|
|||||||
/// @param exp 要被分割的地址区域的大小的幂
|
/// @param exp 要被分割的地址区域的大小的幂
|
||||||
///
|
///
|
||||||
/// @param list_guard 【exp-1】对应的链表
|
/// @param list_guard 【exp-1】对应的链表
|
||||||
fn __buddy_split(
|
fn split_block(
|
||||||
&self,
|
&self,
|
||||||
region: Box<MmioBuddyAddrRegion>,
|
region: Box<MmioBuddyAddrRegion>,
|
||||||
exp: u32,
|
exp: u32,
|
||||||
low_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
low_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
||||||
) {
|
) {
|
||||||
let vaddr: u64 = self.__buddy_block_vaddr(region.vaddr, exp - 1);
|
let vaddr: u64 = self.calculate_block_vaddr(region.vaddr, exp - 1);
|
||||||
let new_region: Box<MmioBuddyAddrRegion> = self.__create_region(vaddr);
|
let new_region: Box<MmioBuddyAddrRegion> = self.create_region(vaddr);
|
||||||
self.__buddy_add_region_obj(region, low_list_guard);
|
self.push_block(region, low_list_guard);
|
||||||
self.__buddy_add_region_obj(new_region, low_list_guard);
|
self.push_block(new_region, low_list_guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief 从buddy中申请一块指定大小的内存区域
|
/// @brief 从buddy中申请一块指定大小的内存区域
|
||||||
@ -118,14 +118,14 @@ impl MmioBuddyMemPool {
|
|||||||
/// - 没有满足要求的内存块时,返回ENOFOUND
|
/// - 没有满足要求的内存块时,返回ENOFOUND
|
||||||
/// - 申请的内存块大小超过合法范围,返回WRONGEXP
|
/// - 申请的内存块大小超过合法范围,返回WRONGEXP
|
||||||
/// - 调用函数出错时,返回出错函数对应错误码
|
/// - 调用函数出错时,返回出错函数对应错误码
|
||||||
fn __query_addr_region(
|
fn query_addr_region(
|
||||||
&self,
|
&self,
|
||||||
exp: u32,
|
exp: u32,
|
||||||
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
||||||
) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
|
) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
|
||||||
// 申请范围错误
|
// 申请范围错误
|
||||||
if exp < MMIO_BUDDY_MIN_EXP || exp > MMIO_BUDDY_MAX_EXP {
|
if exp < MMIO_BUDDY_MIN_EXP || exp > MMIO_BUDDY_MAX_EXP {
|
||||||
kdebug!("__query_addr_region: exp wrong");
|
kdebug!("query_addr_region: exp wrong");
|
||||||
return Err(MmioResult::WRONGEXP);
|
return Err(MmioResult::WRONGEXP);
|
||||||
}
|
}
|
||||||
// 没有恰好符合要求的内存块
|
// 没有恰好符合要求的内存块
|
||||||
@ -134,23 +134,21 @@ impl MmioBuddyMemPool {
|
|||||||
// 找到最小符合申请范围的内存块
|
// 找到最小符合申请范围的内存块
|
||||||
// 将大的内存块依次分成小块内存,直到能够满足exp大小,即将exp+1分成两块exp
|
// 将大的内存块依次分成小块内存,直到能够满足exp大小,即将exp+1分成两块exp
|
||||||
for e in exp + 1..MMIO_BUDDY_MAX_EXP + 1 {
|
for e in exp + 1..MMIO_BUDDY_MAX_EXP + 1 {
|
||||||
if self.free_regions[__exp2index(e) as usize].lock().num_free == 0 {
|
if self.free_regions[exp2index(e) as usize].lock().num_free == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for e2 in (exp + 1..e + 1).rev() {
|
for e2 in (exp + 1..e + 1).rev() {
|
||||||
match self
|
match self.pop_block(&mut self.free_regions[exp2index(e2) as usize].lock()) {
|
||||||
.__buddy_pop_region(&mut self.free_regions[__exp2index(e2) as usize].lock())
|
|
||||||
{
|
|
||||||
Ok(region) => {
|
Ok(region) => {
|
||||||
if e2 != exp + 1 {
|
if e2 != exp + 1 {
|
||||||
// 要将分裂后的内存块插入到更小的链表中
|
// 要将分裂后的内存块插入到更小的链表中
|
||||||
let low_list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
|
let low_list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
|
||||||
&mut self.free_regions[__exp2index(e2 - 1) as usize].lock();
|
&mut self.free_regions[exp2index(e2 - 1) as usize].lock();
|
||||||
self.__buddy_split(region, e2, low_list_guard);
|
self.split_block(region, e2, low_list_guard);
|
||||||
} else {
|
} else {
|
||||||
// 由于exp对应的链表list_guard已经被锁住了 不能再加锁
|
// 由于exp对应的链表list_guard已经被锁住了 不能再加锁
|
||||||
// 所以直接将list_guard传入
|
// 所以直接将list_guard传入
|
||||||
self.__buddy_split(region, e2, list_guard);
|
self.split_block(region, e2, list_guard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@ -171,10 +169,10 @@ impl MmioBuddyMemPool {
|
|||||||
for e in MMIO_BUDDY_MIN_EXP..exp {
|
for e in MMIO_BUDDY_MIN_EXP..exp {
|
||||||
if e != exp - 1 {
|
if e != exp - 1 {
|
||||||
let high_list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
|
let high_list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
|
||||||
&mut self.free_regions[__exp2index(exp + 1)].lock();
|
&mut self.free_regions[exp2index(exp + 1)].lock();
|
||||||
match self.__buddy_merge(
|
match self.merge_all_exp(
|
||||||
e,
|
e,
|
||||||
&mut self.free_regions[__exp2index(e) as usize].lock(),
|
&mut self.free_regions[exp2index(e) as usize].lock(),
|
||||||
high_list_guard,
|
high_list_guard,
|
||||||
) {
|
) {
|
||||||
Ok(_) => continue,
|
Ok(_) => continue,
|
||||||
@ -183,9 +181,9 @@ impl MmioBuddyMemPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match self.__buddy_merge(
|
match self.merge_all_exp(
|
||||||
e,
|
e,
|
||||||
&mut self.free_regions[__exp2index(e) as usize].lock(),
|
&mut self.free_regions[exp2index(e) as usize].lock(),
|
||||||
list_guard,
|
list_guard,
|
||||||
) {
|
) {
|
||||||
Ok(_) => continue,
|
Ok(_) => continue,
|
||||||
@ -217,8 +215,8 @@ impl MmioBuddyMemPool {
|
|||||||
exp: u32,
|
exp: u32,
|
||||||
) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
|
) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
|
||||||
let list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
|
let list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
|
||||||
&mut self.free_regions[__exp2index(exp)].lock();
|
&mut self.free_regions[exp2index(exp)].lock();
|
||||||
match self.__query_addr_region(exp, list_guard) {
|
match self.query_addr_region(exp, list_guard) {
|
||||||
Ok(ret) => return Ok(ret),
|
Ok(ret) => return Ok(ret),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
kdebug!("mmio_buddy_query_addr_region failed");
|
kdebug!("mmio_buddy_query_addr_region failed");
|
||||||
@ -231,7 +229,7 @@ impl MmioBuddyMemPool {
|
|||||||
/// @param region 要被添加的地址结构体
|
/// @param region 要被添加的地址结构体
|
||||||
///
|
///
|
||||||
/// @param list_guard 目标链表
|
/// @param list_guard 目标链表
|
||||||
fn __buddy_add_region_obj(
|
fn push_block(
|
||||||
&self,
|
&self,
|
||||||
region: Box<MmioBuddyAddrRegion>,
|
region: Box<MmioBuddyAddrRegion>,
|
||||||
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
||||||
@ -242,7 +240,7 @@ impl MmioBuddyMemPool {
|
|||||||
|
|
||||||
/// @brief 根据地址和内存块大小,计算伙伴块虚拟内存的地址
|
/// @brief 根据地址和内存块大小,计算伙伴块虚拟内存的地址
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn __buddy_block_vaddr(&self, vaddr: u64, exp: u32) -> u64 {
|
fn calculate_block_vaddr(&self, vaddr: u64, exp: u32) -> u64 {
|
||||||
return vaddr ^ (1 << exp);
|
return vaddr ^ (1 << exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +256,7 @@ impl MmioBuddyMemPool {
|
|||||||
/// @return Err(MmioResult)
|
/// @return Err(MmioResult)
|
||||||
/// - 当链表为空,返回ISEMPTY
|
/// - 当链表为空,返回ISEMPTY
|
||||||
/// - 没有找到伙伴块,返回ENOFOUND
|
/// - 没有找到伙伴块,返回ENOFOUND
|
||||||
fn __pop_buddy_block(
|
fn pop_buddy_block(
|
||||||
&self,
|
&self,
|
||||||
vaddr: u64,
|
vaddr: u64,
|
||||||
exp: u32,
|
exp: u32,
|
||||||
@ -268,7 +266,7 @@ impl MmioBuddyMemPool {
|
|||||||
return Err(MmioResult::ISEMPTY);
|
return Err(MmioResult::ISEMPTY);
|
||||||
} else {
|
} else {
|
||||||
//计算伙伴块的地址
|
//计算伙伴块的地址
|
||||||
let buddy_vaddr = self.__buddy_block_vaddr(vaddr, exp);
|
let buddy_vaddr = self.calculate_block_vaddr(vaddr, exp);
|
||||||
|
|
||||||
// element 只会有一个元素
|
// element 只会有一个元素
|
||||||
let mut element: Vec<Box<MmioBuddyAddrRegion>> = list_guard
|
let mut element: Vec<Box<MmioBuddyAddrRegion>> = list_guard
|
||||||
@ -292,7 +290,7 @@ impl MmioBuddyMemPool {
|
|||||||
/// @return Ok(Box<MmioBuddyAddrRegion>) 内存块信息结构体的引用。
|
/// @return Ok(Box<MmioBuddyAddrRegion>) 内存块信息结构体的引用。
|
||||||
///
|
///
|
||||||
/// @return Err(MmioResult) 当链表为空,无法删除时,返回ISEMPTY
|
/// @return Err(MmioResult) 当链表为空,无法删除时,返回ISEMPTY
|
||||||
fn __buddy_pop_region(
|
fn pop_block(
|
||||||
&self,
|
&self,
|
||||||
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
||||||
) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
|
) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
|
||||||
@ -314,9 +312,9 @@ impl MmioBuddyMemPool {
|
|||||||
/// @return Ok(MmioResult) 合并成功返回SUCCESS
|
/// @return Ok(MmioResult) 合并成功返回SUCCESS
|
||||||
/// @return Err(MmioResult)
|
/// @return Err(MmioResult)
|
||||||
/// - 内存块过少,无法合并,返回EINVAL
|
/// - 内存块过少,无法合并,返回EINVAL
|
||||||
/// - __pop_buddy_block调用出错,返回其错误码
|
/// - pop_buddy_block调用出错,返回其错误码
|
||||||
/// - __buddy_merge_blocks调用出错,返回其错误码
|
/// - merge_blocks调用出错,返回其错误码
|
||||||
fn __buddy_merge(
|
fn merge_all_exp(
|
||||||
&self,
|
&self,
|
||||||
exp: u32,
|
exp: u32,
|
||||||
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
||||||
@ -333,7 +331,7 @@ impl MmioBuddyMemPool {
|
|||||||
// 获取内存块
|
// 获取内存块
|
||||||
let vaddr: u64 = list_guard.list.back().unwrap().vaddr;
|
let vaddr: u64 = list_guard.list.back().unwrap().vaddr;
|
||||||
// 获取伙伴内存块
|
// 获取伙伴内存块
|
||||||
match self.__pop_buddy_block(vaddr, exp, list_guard) {
|
match self.pop_buddy_block(vaddr, exp, list_guard) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
@ -343,11 +341,11 @@ impl MmioBuddyMemPool {
|
|||||||
vaddr: region.vaddr,
|
vaddr: region.vaddr,
|
||||||
});
|
});
|
||||||
// 在两块内存都被取出之后才进行合并
|
// 在两块内存都被取出之后才进行合并
|
||||||
match self.__buddy_merge_blocks(region, buddy_region, exp, high_list_guard) {
|
match self.merge_blocks(region, buddy_region, exp, high_list_guard) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// 如果合并失败了要将取出来的元素放回去
|
// 如果合并失败了要将取出来的元素放回去
|
||||||
self.__buddy_add_region_obj(copy_region, list_guard);
|
self.push_block(copy_region, list_guard);
|
||||||
kdebug!("__buddy_merge: __buddy_merge_blocks failed");
|
kdebug!("merge_all_exp: merge_blocks failed");
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
Ok(_) => continue,
|
Ok(_) => continue,
|
||||||
@ -367,7 +365,7 @@ impl MmioBuddyMemPool {
|
|||||||
/// @return Ok(MmioResult) 成功返回SUCCESS
|
/// @return Ok(MmioResult) 成功返回SUCCESS
|
||||||
///
|
///
|
||||||
/// @return Err(MmioResult) 两个内存块不是伙伴块,返回EINVAL
|
/// @return Err(MmioResult) 两个内存块不是伙伴块,返回EINVAL
|
||||||
fn __buddy_merge_blocks(
|
fn merge_blocks(
|
||||||
&self,
|
&self,
|
||||||
region_1: Box<MmioBuddyAddrRegion>,
|
region_1: Box<MmioBuddyAddrRegion>,
|
||||||
region_2: Box<MmioBuddyAddrRegion>,
|
region_2: Box<MmioBuddyAddrRegion>,
|
||||||
@ -375,13 +373,192 @@ impl MmioBuddyMemPool {
|
|||||||
high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
|
||||||
) -> Result<MmioResult, MmioResult> {
|
) -> Result<MmioResult, MmioResult> {
|
||||||
// 判断是否为伙伴块
|
// 判断是否为伙伴块
|
||||||
if region_1.vaddr != self.__buddy_block_vaddr(region_2.vaddr, exp) {
|
if region_1.vaddr != self.calculate_block_vaddr(region_2.vaddr, exp) {
|
||||||
return Err(MmioResult::EINVAL);
|
return Err(MmioResult::EINVAL);
|
||||||
}
|
}
|
||||||
// 将大的块放进下一级链表
|
// 将大的块放进下一级链表
|
||||||
self.__buddy_add_region_obj(region_1, high_list_guard);
|
self.push_block(region_1, high_list_guard);
|
||||||
return Ok(MmioResult::SUCCESS);
|
return Ok(MmioResult::SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief 创建一块mmio区域,并将vma绑定到initial_mm
|
||||||
|
///
|
||||||
|
/// @param size mmio区域的大小(字节)
|
||||||
|
///
|
||||||
|
/// @param vm_flags 要把vma设置成的标志
|
||||||
|
///
|
||||||
|
/// @param res_vaddr 返回值-分配得到的虚拟地址
|
||||||
|
///
|
||||||
|
/// @param res_length 返回值-分配的虚拟地址空间长度
|
||||||
|
///
|
||||||
|
/// @return Ok(i32) 成功返回0
|
||||||
|
///
|
||||||
|
/// @return Err(i32) 失败返回错误码
|
||||||
|
fn create_mmio(
|
||||||
|
&self,
|
||||||
|
size: u32,
|
||||||
|
vm_flags: vm_flags_t,
|
||||||
|
res_vaddr: *mut u64,
|
||||||
|
res_length: *mut u64,
|
||||||
|
) -> Result<i32, i32> {
|
||||||
|
if size > PAGE_1G_SIZE || size == 0 {
|
||||||
|
return Err(-(EPERM as i32));
|
||||||
|
}
|
||||||
|
let mut retval: i32 = 0;
|
||||||
|
// 计算前导0
|
||||||
|
let mut size_exp: u32 = 31 - size.leading_zeros();
|
||||||
|
// 记录最终申请的空间大小
|
||||||
|
let mut new_size: u32 = size;
|
||||||
|
// 对齐要申请的空间大小
|
||||||
|
// 如果要申请的空间大小小于4k,则分配4k
|
||||||
|
if size_exp < PAGE_4K_SHIFT {
|
||||||
|
new_size = PAGE_4K_SIZE;
|
||||||
|
size_exp = PAGE_4K_SHIFT;
|
||||||
|
} else if (new_size & (!(1 << size_exp))) != 0 {
|
||||||
|
// 向左对齐空间大小
|
||||||
|
size_exp += 1;
|
||||||
|
new_size = 1 << size_exp;
|
||||||
|
}
|
||||||
|
match MMIO_POOL.mmio_buddy_query_addr_region(size_exp) {
|
||||||
|
Ok(region) => {
|
||||||
|
unsafe {
|
||||||
|
*res_vaddr = region.vaddr;
|
||||||
|
*res_length = new_size as u64;
|
||||||
|
}
|
||||||
|
// 创建vma
|
||||||
|
let flags: u64 = vm_flags | (VM_IO | VM_DONTCOPY) as u64;
|
||||||
|
let len_4k: u64 = (new_size % PAGE_2M_SIZE) as u64;
|
||||||
|
let len_2m: u64 = new_size as u64 - len_4k;
|
||||||
|
let mut loop_i: u64 = 0;
|
||||||
|
// 先分配2M的vma
|
||||||
|
loop {
|
||||||
|
if loop_i >= len_2m {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let vma: *mut *mut vm_area_struct = null_mut();
|
||||||
|
retval = unsafe {
|
||||||
|
mm_create_vma(
|
||||||
|
&mut initial_mm,
|
||||||
|
region.vaddr + loop_i,
|
||||||
|
PAGE_2M_SIZE.into(),
|
||||||
|
flags,
|
||||||
|
null_mut(),
|
||||||
|
vma,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if retval != 0 {
|
||||||
|
kdebug!(
|
||||||
|
"failed to create mmio 2m vma. pid = {:?}",
|
||||||
|
current_pcb().pid
|
||||||
|
);
|
||||||
|
unsafe {
|
||||||
|
vm_area_del(*vma);
|
||||||
|
vm_area_free(*vma);
|
||||||
|
}
|
||||||
|
return Err(retval);
|
||||||
|
}
|
||||||
|
loop_i += PAGE_2M_SIZE as u64;
|
||||||
|
}
|
||||||
|
// 分配4K的vma
|
||||||
|
loop_i = len_2m;
|
||||||
|
loop {
|
||||||
|
if loop_i >= size as u64 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let vma: *mut *mut vm_area_struct = null_mut();
|
||||||
|
retval = unsafe {
|
||||||
|
mm_create_vma(
|
||||||
|
&mut initial_mm,
|
||||||
|
region.vaddr + loop_i,
|
||||||
|
PAGE_4K_SIZE.into(),
|
||||||
|
flags,
|
||||||
|
null_mut(),
|
||||||
|
vma,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if retval != 0 {
|
||||||
|
kdebug!(
|
||||||
|
"failed to create mmio 4k vma. pid = {:?}",
|
||||||
|
current_pcb().pid
|
||||||
|
);
|
||||||
|
unsafe {
|
||||||
|
vm_area_del(*vma);
|
||||||
|
vm_area_free(*vma);
|
||||||
|
}
|
||||||
|
return Err(retval);
|
||||||
|
}
|
||||||
|
loop_i += PAGE_4K_SIZE as u64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
kdebug!("failed to create mmio vma.pid = {:?}", current_pcb().pid);
|
||||||
|
return Err(-(ENOMEM as i32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief 取消mmio的映射并将地址空间归还到buddy中
|
||||||
|
///
|
||||||
|
/// @param vaddr 起始的虚拟地址
|
||||||
|
///
|
||||||
|
/// @param length 要归还的地址空间的长度
|
||||||
|
///
|
||||||
|
/// @return Ok(i32) 成功返回0
|
||||||
|
///
|
||||||
|
/// @return Err(i32) 失败返回错误码
|
||||||
|
fn release_mmio(&self, vaddr: u64, length: u64) -> Result<i32, i32> {
|
||||||
|
//先将要释放的空间取消映射
|
||||||
|
unsafe {
|
||||||
|
mm_unmap(&mut initial_mm, vaddr, length, false);
|
||||||
|
}
|
||||||
|
let mut loop_i: u64 = 0;
|
||||||
|
loop {
|
||||||
|
if loop_i >= length {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 获取要释放的vma的结构体
|
||||||
|
let vma: *mut vm_area_struct = unsafe { vma_find(&mut initial_mm, vaddr + loop_i) };
|
||||||
|
if vma == null_mut() {
|
||||||
|
kdebug!(
|
||||||
|
"mmio_release failed: vma not found. At address: {:?}, pid = {:?}",
|
||||||
|
vaddr + loop_i,
|
||||||
|
current_pcb().pid
|
||||||
|
);
|
||||||
|
return Err(-(EINVAL as i32));
|
||||||
|
}
|
||||||
|
// 检查vma起始地址是否正确
|
||||||
|
if unsafe { (*vma).vm_start != (vaddr + loop_i) } {
|
||||||
|
kdebug!(
|
||||||
|
"mmio_release failed: addr_start is not equal to current: {:?}. pid = {:?}",
|
||||||
|
vaddr + loop_i,
|
||||||
|
current_pcb().pid
|
||||||
|
);
|
||||||
|
return Err(-(EINVAL as i32));
|
||||||
|
}
|
||||||
|
// 将vma对应空间归还
|
||||||
|
match MMIO_POOL.give_back_block(unsafe { (*vma).vm_start }, unsafe {
|
||||||
|
31 - ((*vma).vm_end - (*vma).vm_start).leading_zeros()
|
||||||
|
}) {
|
||||||
|
Ok(_) => {
|
||||||
|
loop_i += unsafe { (*vma).vm_end - (*vma).vm_start };
|
||||||
|
unsafe {
|
||||||
|
vm_area_del(vma);
|
||||||
|
vm_area_free(vma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
// vma对应空间没有成功归还的话,就不删除vma
|
||||||
|
kdebug!(
|
||||||
|
"mmio_release give_back failed: pid = {:?}",
|
||||||
|
current_pcb().pid
|
||||||
|
);
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief mmio伙伴系统内部的地址区域结构体
|
/// @brief mmio伙伴系统内部的地址区域结构体
|
||||||
@ -433,7 +610,7 @@ pub extern "C" fn __mmio_buddy_init() {
|
|||||||
let cnt_1g_blocks: u32 = ((MMIO_TOP - MMIO_BASE) / PAGE_1G_SIZE as i64) as u32;
|
let cnt_1g_blocks: u32 = ((MMIO_TOP - MMIO_BASE) / PAGE_1G_SIZE as i64) as u32;
|
||||||
let mut vaddr_base: u64 = MMIO_BASE as u64;
|
let mut vaddr_base: u64 = MMIO_BASE as u64;
|
||||||
for _ in 0..cnt_1g_blocks {
|
for _ in 0..cnt_1g_blocks {
|
||||||
match MMIO_POOL.__give_back_block(vaddr_base, PAGE_1G_SHIFT) {
|
match MMIO_POOL.give_back_block(vaddr_base, PAGE_1G_SHIFT) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
vaddr_base += PAGE_1G_SIZE as u64;
|
vaddr_base += PAGE_1G_SIZE as u64;
|
||||||
}
|
}
|
||||||
@ -451,7 +628,7 @@ pub extern "C" fn __mmio_buddy_init() {
|
|||||||
///
|
///
|
||||||
/// @return 内存池数组下标
|
/// @return 内存池数组下标
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn __exp2index(exp: u32) -> usize {
|
fn exp2index(exp: u32) -> usize {
|
||||||
return (exp - 12) as usize;
|
return (exp - 12) as usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,101 +650,11 @@ pub extern "C" fn mmio_create(
|
|||||||
res_vaddr: *mut u64,
|
res_vaddr: *mut u64,
|
||||||
res_length: *mut u64,
|
res_length: *mut u64,
|
||||||
) -> i32 {
|
) -> i32 {
|
||||||
if size > PAGE_1G_SIZE || size == 0 {
|
if let Err(err) = MMIO_POOL.create_mmio(size, vm_flags, res_vaddr, res_length) {
|
||||||
return -(EPERM as i32);
|
return err;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
let mut retval: i32 = 0;
|
|
||||||
// 计算前导0
|
|
||||||
let mut size_exp: u32 = 31 - size.leading_zeros();
|
|
||||||
// 记录最终申请的空间大小
|
|
||||||
let mut new_size: u32 = size;
|
|
||||||
// 对齐要申请的空间大小
|
|
||||||
// 如果要申请的空间大小小于4k,则分配4k
|
|
||||||
if size_exp < PAGE_4K_SHIFT {
|
|
||||||
new_size = PAGE_4K_SIZE;
|
|
||||||
size_exp = PAGE_4K_SHIFT;
|
|
||||||
} else if (new_size & (!(1 << size_exp))) != 0 {
|
|
||||||
// 向左对齐空间大小
|
|
||||||
size_exp += 1;
|
|
||||||
new_size = 1 << size_exp;
|
|
||||||
}
|
|
||||||
match MMIO_POOL.mmio_buddy_query_addr_region(size_exp) {
|
|
||||||
Ok(region) => {
|
|
||||||
unsafe {
|
|
||||||
*res_vaddr = region.vaddr;
|
|
||||||
*res_length = new_size as u64;
|
|
||||||
}
|
|
||||||
// 创建vma
|
|
||||||
let flags: u64 = vm_flags | (VM_IO | VM_DONTCOPY) as u64;
|
|
||||||
let len_4k: u64 = (new_size % PAGE_2M_SIZE) as u64;
|
|
||||||
let len_2m: u64 = new_size as u64 - len_4k;
|
|
||||||
let mut loop_i: u64 = 0;
|
|
||||||
// 先分配2M的vma
|
|
||||||
loop {
|
|
||||||
if loop_i >= len_2m {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
let vma: *mut *mut vm_area_struct = null_mut();
|
|
||||||
retval = unsafe {
|
|
||||||
mm_create_vma(
|
|
||||||
&mut initial_mm,
|
|
||||||
region.vaddr + loop_i,
|
|
||||||
PAGE_2M_SIZE.into(),
|
|
||||||
flags,
|
|
||||||
null_mut(),
|
|
||||||
vma,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if retval != 0 {
|
|
||||||
kdebug!(
|
|
||||||
"failed to create mmio 2m vma. pid = {:?}",
|
|
||||||
current_pcb().pid
|
|
||||||
);
|
|
||||||
unsafe {
|
|
||||||
vm_area_del(*vma);
|
|
||||||
vm_area_free(*vma);
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
loop_i += PAGE_2M_SIZE as u64;
|
|
||||||
}
|
|
||||||
// 分配4K的vma
|
|
||||||
loop_i = len_2m;
|
|
||||||
loop {
|
|
||||||
if loop_i >= size as u64 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
let vma: *mut *mut vm_area_struct = null_mut();
|
|
||||||
retval = unsafe {
|
|
||||||
mm_create_vma(
|
|
||||||
&mut initial_mm,
|
|
||||||
region.vaddr + loop_i,
|
|
||||||
PAGE_4K_SIZE.into(),
|
|
||||||
flags,
|
|
||||||
null_mut(),
|
|
||||||
vma,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if retval != 0 {
|
|
||||||
kdebug!(
|
|
||||||
"failed to create mmio 4k vma. pid = {:?}",
|
|
||||||
current_pcb().pid
|
|
||||||
);
|
|
||||||
unsafe {
|
|
||||||
vm_area_del(*vma);
|
|
||||||
vm_area_free(*vma);
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
loop_i += PAGE_4K_SIZE as u64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
kdebug!("failed to create mmio vma.pid = {:?}", current_pcb().pid);
|
|
||||||
return -(ENOMEM as i32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief 取消mmio的映射并将地址空间归还到buddy中
|
/// @brief 取消mmio的映射并将地址空间归还到buddy中
|
||||||
@ -581,54 +668,9 @@ pub extern "C" fn mmio_create(
|
|||||||
/// @return Err(i32) 失败返回错误码
|
/// @return Err(i32) 失败返回错误码
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn mmio_release(vaddr: u64, length: u64) -> i32 {
|
pub extern "C" fn mmio_release(vaddr: u64, length: u64) -> i32 {
|
||||||
//先将要释放的空间取消映射
|
if let Err(err) = MMIO_POOL.release_mmio(vaddr, length) {
|
||||||
unsafe {
|
return err;
|
||||||
mm_unmap(&mut initial_mm, vaddr, length, false);
|
} else {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
let mut loop_i: u64 = 0;
|
|
||||||
loop {
|
|
||||||
if loop_i >= length {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 获取要释放的vma的结构体
|
|
||||||
let vma: *mut vm_area_struct = unsafe { vma_find(&mut initial_mm, vaddr + loop_i) };
|
|
||||||
if vma == null_mut() {
|
|
||||||
kdebug!(
|
|
||||||
"mmio_release failed: vma not found. At address: {:?}, pid = {:?}",
|
|
||||||
vaddr + loop_i,
|
|
||||||
current_pcb().pid
|
|
||||||
);
|
|
||||||
return -(EINVAL as i32);
|
|
||||||
}
|
|
||||||
// 检查vma起始地址是否正确
|
|
||||||
if unsafe { (*vma).vm_start != (vaddr + loop_i) } {
|
|
||||||
kdebug!(
|
|
||||||
"mmio_release failed: addr_start is not equal to current: {:?}. pid = {:?}",
|
|
||||||
vaddr + loop_i,
|
|
||||||
current_pcb().pid
|
|
||||||
);
|
|
||||||
return -(EINVAL as i32);
|
|
||||||
}
|
|
||||||
// 将vma对应空间归还
|
|
||||||
match MMIO_POOL.__give_back_block(unsafe { (*vma).vm_start }, unsafe {
|
|
||||||
31 - ((*vma).vm_end - (*vma).vm_start).leading_zeros()
|
|
||||||
}) {
|
|
||||||
Ok(_) => {
|
|
||||||
loop_i += unsafe { (*vma).vm_end - (*vma).vm_start };
|
|
||||||
unsafe {
|
|
||||||
vm_area_del(vma);
|
|
||||||
vm_area_free(vma);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
// vma对应空间没有成功归还的话,就不删除vma
|
|
||||||
kdebug!(
|
|
||||||
"mmio_release give_back failed: pid = {:?}",
|
|
||||||
current_pcb().pid
|
|
||||||
);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user