修改mmio-buddy代码结构和函数名 (#184)

* 修改mmio-buddy结构和函数名
This commit is contained in:
houmkh 2023-03-06 11:21:29 +08:00 committed by GitHub
parent c2481452f8
commit a7eb62a47a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,3 +1,4 @@
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
use crate::{
arch::asm::current::current_pcb,
include::bindings::bindings::{
@ -6,7 +7,6 @@ use crate::{
PAGE_2M_SIZE, PAGE_4K_SHIFT, PAGE_4K_SIZE, VM_DONTCOPY, VM_IO,
},
kdebug, kerror,
libs::spinlock::{SpinLock, SpinLockGuard},
};
use alloc::{boxed::Box, collections::LinkedList, vec::Vec};
use core::{mem, ptr::null_mut};
@ -57,7 +57,7 @@ impl MmioBuddyMemPool {
/// @param vaddr 虚拟地址
///
/// @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());
region.vaddr = vaddr;
return region;
@ -74,16 +74,16 @@ impl MmioBuddyMemPool {
/// @return Ok(i32) 返回0
///
/// @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
if (vaddr & ((1 << exp) - 1)) != 0 {
return Err(-(EINVAL as i32));
}
let region: Box<MmioBuddyAddrRegion> = self.__create_region(vaddr);
let region: Box<MmioBuddyAddrRegion> = self.create_region(vaddr);
// 加入buddy
let list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
&mut self.free_regions[__exp2index(exp)].lock();
self.__buddy_add_region_obj(region, list_guard);
&mut self.free_regions[exp2index(exp)].lock();
self.push_block(region, list_guard);
return Ok(0);
}
@ -94,16 +94,16 @@ impl MmioBuddyMemPool {
/// @param exp 要被分割的地址区域的大小的幂
///
/// @param list_guard 【exp-1】对应的链表
fn __buddy_split(
fn split_block(
&self,
region: Box<MmioBuddyAddrRegion>,
exp: u32,
low_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
) {
let vaddr: u64 = self.__buddy_block_vaddr(region.vaddr, exp - 1);
let new_region: Box<MmioBuddyAddrRegion> = self.__create_region(vaddr);
self.__buddy_add_region_obj(region, low_list_guard);
self.__buddy_add_region_obj(new_region, low_list_guard);
let vaddr: u64 = self.calculate_block_vaddr(region.vaddr, exp - 1);
let new_region: Box<MmioBuddyAddrRegion> = self.create_region(vaddr);
self.push_block(region, low_list_guard);
self.push_block(new_region, low_list_guard);
}
/// @brief 从buddy中申请一块指定大小的内存区域
@ -118,14 +118,14 @@ impl MmioBuddyMemPool {
/// - 没有满足要求的内存块时返回ENOFOUND
/// - 申请的内存块大小超过合法范围返回WRONGEXP
/// - 调用函数出错时,返回出错函数对应错误码
fn __query_addr_region(
fn query_addr_region(
&self,
exp: u32,
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
// 申请范围错误
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);
}
// 没有恰好符合要求的内存块
@ -134,23 +134,21 @@ impl MmioBuddyMemPool {
// 找到最小符合申请范围的内存块
// 将大的内存块依次分成小块内存直到能够满足exp大小即将exp+1分成两块exp
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;
}
for e2 in (exp + 1..e + 1).rev() {
match self
.__buddy_pop_region(&mut self.free_regions[__exp2index(e2) as usize].lock())
{
match self.pop_block(&mut self.free_regions[exp2index(e2) as usize].lock()) {
Ok(region) => {
if e2 != exp + 1 {
// 要将分裂后的内存块插入到更小的链表中
let low_list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
&mut self.free_regions[__exp2index(e2 - 1) as usize].lock();
self.__buddy_split(region, e2, low_list_guard);
&mut self.free_regions[exp2index(e2 - 1) as usize].lock();
self.split_block(region, e2, low_list_guard);
} else {
// 由于exp对应的链表list_guard已经被锁住了 不能再加锁
// 所以直接将list_guard传入
self.__buddy_split(region, e2, list_guard);
self.split_block(region, e2, list_guard);
}
}
Err(err) => {
@ -171,10 +169,10 @@ impl MmioBuddyMemPool {
for e in MMIO_BUDDY_MIN_EXP..exp {
if e != exp - 1 {
let high_list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
&mut self.free_regions[__exp2index(exp + 1)].lock();
match self.__buddy_merge(
&mut self.free_regions[exp2index(exp + 1)].lock();
match self.merge_all_exp(
e,
&mut self.free_regions[__exp2index(e) as usize].lock(),
&mut self.free_regions[exp2index(e) as usize].lock(),
high_list_guard,
) {
Ok(_) => continue,
@ -183,9 +181,9 @@ impl MmioBuddyMemPool {
}
}
} else {
match self.__buddy_merge(
match self.merge_all_exp(
e,
&mut self.free_regions[__exp2index(e) as usize].lock(),
&mut self.free_regions[exp2index(e) as usize].lock(),
list_guard,
) {
Ok(_) => continue,
@ -217,8 +215,8 @@ impl MmioBuddyMemPool {
exp: u32,
) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
let list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
&mut self.free_regions[__exp2index(exp)].lock();
match self.__query_addr_region(exp, list_guard) {
&mut self.free_regions[exp2index(exp)].lock();
match self.query_addr_region(exp, list_guard) {
Ok(ret) => return Ok(ret),
Err(err) => {
kdebug!("mmio_buddy_query_addr_region failed");
@ -231,7 +229,7 @@ impl MmioBuddyMemPool {
/// @param region 要被添加的地址结构体
///
/// @param list_guard 目标链表
fn __buddy_add_region_obj(
fn push_block(
&self,
region: Box<MmioBuddyAddrRegion>,
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
@ -242,7 +240,7 @@ impl MmioBuddyMemPool {
/// @brief 根据地址和内存块大小,计算伙伴块虚拟内存的地址
#[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);
}
@ -258,7 +256,7 @@ impl MmioBuddyMemPool {
/// @return Err(MmioResult)
/// - 当链表为空返回ISEMPTY
/// - 没有找到伙伴块返回ENOFOUND
fn __pop_buddy_block(
fn pop_buddy_block(
&self,
vaddr: u64,
exp: u32,
@ -268,7 +266,7 @@ impl MmioBuddyMemPool {
return Err(MmioResult::ISEMPTY);
} else {
//计算伙伴块的地址
let buddy_vaddr = self.__buddy_block_vaddr(vaddr, exp);
let buddy_vaddr = self.calculate_block_vaddr(vaddr, exp);
// element 只会有一个元素
let mut element: Vec<Box<MmioBuddyAddrRegion>> = list_guard
@ -292,7 +290,7 @@ impl MmioBuddyMemPool {
/// @return Ok(Box<MmioBuddyAddrRegion>) 内存块信息结构体的引用。
///
/// @return Err(MmioResult) 当链表为空无法删除时返回ISEMPTY
fn __buddy_pop_region(
fn pop_block(
&self,
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> {
@ -314,9 +312,9 @@ impl MmioBuddyMemPool {
/// @return Ok(MmioResult) 合并成功返回SUCCESS
/// @return Err(MmioResult)
/// - 内存块过少无法合并返回EINVAL
/// - __pop_buddy_block调用出错返回其错误码
/// - __buddy_merge_blocks调用出错返回其错误码
fn __buddy_merge(
/// - pop_buddy_block调用出错返回其错误码
/// - merge_blocks调用出错返回其错误码
fn merge_all_exp(
&self,
exp: u32,
list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
@ -333,7 +331,7 @@ impl MmioBuddyMemPool {
// 获取内存块
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) => {
return Err(err);
}
@ -343,11 +341,11 @@ impl MmioBuddyMemPool {
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) => {
// 如果合并失败了要将取出来的元素放回去
self.__buddy_add_region_obj(copy_region, list_guard);
kdebug!("__buddy_merge: __buddy_merge_blocks failed");
self.push_block(copy_region, list_guard);
kdebug!("merge_all_exp: merge_blocks failed");
return Err(err);
}
Ok(_) => continue,
@ -367,7 +365,7 @@ impl MmioBuddyMemPool {
/// @return Ok(MmioResult) 成功返回SUCCESS
///
/// @return Err(MmioResult) 两个内存块不是伙伴块,返回EINVAL
fn __buddy_merge_blocks(
fn merge_blocks(
&self,
region_1: Box<MmioBuddyAddrRegion>,
region_2: Box<MmioBuddyAddrRegion>,
@ -375,106 +373,36 @@ impl MmioBuddyMemPool {
high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
) -> 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);
}
// 将大的块放进下一级链表
self.__buddy_add_region_obj(region_1, high_list_guard);
self.push_block(region_1, high_list_guard);
return Ok(MmioResult::SUCCESS);
}
}
/// @brief mmio伙伴系统内部的地址区域结构体
pub struct MmioBuddyAddrRegion {
vaddr: u64,
}
impl MmioBuddyAddrRegion {
pub fn new() -> Self {
return MmioBuddyAddrRegion {
..Default::default()
};
}
}
impl Default for MmioBuddyAddrRegion {
fn default() -> Self {
MmioBuddyAddrRegion {
vaddr: Default::default(),
}
}
}
/// @brief 空闲页数组结构体
pub struct MmioFreeRegionList {
/// 存储mmio_buddy的地址链表
list: LinkedList<Box<MmioBuddyAddrRegion>>,
/// 空闲块的数量
num_free: i64,
}
impl MmioFreeRegionList {
fn new() -> Self {
return MmioFreeRegionList {
..Default::default()
};
}
}
impl Default for MmioFreeRegionList {
fn default() -> Self {
MmioFreeRegionList {
list: Default::default(),
num_free: 0,
}
}
}
/// @brief 初始化mmio的伙伴系统
#[no_mangle]
pub extern "C" fn __mmio_buddy_init() {
// 创建一堆1GB的地址块
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;
for _ in 0..cnt_1g_blocks {
match MMIO_POOL.__give_back_block(vaddr_base, PAGE_1G_SHIFT) {
Ok(_) => {
vaddr_base += PAGE_1G_SIZE as u64;
}
Err(_) => {
kerror!("__mmio_buddy_init failed");
return;
}
}
}
}
/// @brief 将内存对象大小的幂转换成内存池中的数组的下标
///
/// @param exp内存大小
///
/// @return 内存池数组下标
#[inline(always)]
fn __exp2index(exp: u32) -> usize {
return (exp - 12) as usize;
}
/// @brief 创建一块mmio区域并将vma绑定到initial_mm
///
/// @param size mmio区域的大小字节
///
/// @param vm_flags 要把vma设置成的标志
///
/// @param res_vaddr 返回值-分配得到的虚拟地址
///
/// @param res_length 返回值-分配的虚拟地址空间长度
///
/// @return int 错误码
#[no_mangle]
pub extern "C" fn mmio_create(
/// @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,
) -> i32 {
) -> Result<i32, i32> {
if size > PAGE_1G_SIZE || size == 0 {
return -(EPERM as i32);
return Err(-(EPERM as i32));
}
let mut retval: i32 = 0;
// 计算前导0
@ -527,7 +455,7 @@ pub extern "C" fn mmio_create(
vm_area_del(*vma);
vm_area_free(*vma);
}
return retval;
return Err(retval);
}
loop_i += PAGE_2M_SIZE as u64;
}
@ -557,30 +485,29 @@ pub extern "C" fn mmio_create(
vm_area_del(*vma);
vm_area_free(*vma);
}
return retval;
return Err(retval);
}
loop_i += PAGE_4K_SIZE as u64;
}
}
Err(_) => {
kdebug!("failed to create mmio vma.pid = {:?}", current_pcb().pid);
return -(ENOMEM as i32);
return Err(-(ENOMEM as i32));
}
}
return retval;
}
return Ok(retval);
}
/// @brief 取消mmio的映射并将地址空间归还到buddy中
///
/// @param vaddr 起始的虚拟地址
///
/// @param length 要归还的地址空间的长度
///
/// @return Ok(i32) 成功返回0
///
/// @return Err(i32) 失败返回错误码
#[no_mangle]
pub extern "C" fn mmio_release(vaddr: u64, length: u64) -> i32 {
/// @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);
@ -598,7 +525,7 @@ pub extern "C" fn mmio_release(vaddr: u64, length: u64) -> i32 {
vaddr + loop_i,
current_pcb().pid
);
return -(EINVAL as i32);
return Err(-(EINVAL as i32));
}
// 检查vma起始地址是否正确
if unsafe { (*vma).vm_start != (vaddr + loop_i) } {
@ -607,10 +534,10 @@ pub extern "C" fn mmio_release(vaddr: u64, length: u64) -> i32 {
vaddr + loop_i,
current_pcb().pid
);
return -(EINVAL as i32);
return Err(-(EINVAL as i32));
}
// 将vma对应空间归还
match MMIO_POOL.__give_back_block(unsafe { (*vma).vm_start }, unsafe {
match MMIO_POOL.give_back_block(unsafe { (*vma).vm_start }, unsafe {
31 - ((*vma).vm_end - (*vma).vm_start).leading_zeros()
}) {
Ok(_) => {
@ -626,9 +553,124 @@ pub extern "C" fn mmio_release(vaddr: u64, length: u64) -> i32 {
"mmio_release give_back failed: pid = {:?}",
current_pcb().pid
);
return err;
return Err(err);
}
}
}
return 0;
return Ok(0);
}
}
/// @brief mmio伙伴系统内部的地址区域结构体
pub struct MmioBuddyAddrRegion {
vaddr: u64,
}
impl MmioBuddyAddrRegion {
pub fn new() -> Self {
return MmioBuddyAddrRegion {
..Default::default()
};
}
}
impl Default for MmioBuddyAddrRegion {
fn default() -> Self {
MmioBuddyAddrRegion {
vaddr: Default::default(),
}
}
}
/// @brief 空闲页数组结构体
pub struct MmioFreeRegionList {
/// 存储mmio_buddy的地址链表
list: LinkedList<Box<MmioBuddyAddrRegion>>,
/// 空闲块的数量
num_free: i64,
}
impl MmioFreeRegionList {
fn new() -> Self {
return MmioFreeRegionList {
..Default::default()
};
}
}
impl Default for MmioFreeRegionList {
fn default() -> Self {
MmioFreeRegionList {
list: Default::default(),
num_free: 0,
}
}
}
/// @brief 初始化mmio的伙伴系统
#[no_mangle]
pub extern "C" fn __mmio_buddy_init() {
// 创建一堆1GB的地址块
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;
for _ in 0..cnt_1g_blocks {
match MMIO_POOL.give_back_block(vaddr_base, PAGE_1G_SHIFT) {
Ok(_) => {
vaddr_base += PAGE_1G_SIZE as u64;
}
Err(_) => {
kerror!("__mmio_buddy_init failed");
return;
}
}
}
}
/// @brief 将内存对象大小的幂转换成内存池中的数组的下标
///
/// @param exp内存大小
///
/// @return 内存池数组下标
#[inline(always)]
fn exp2index(exp: u32) -> usize {
return (exp - 12) as usize;
}
/// @brief 创建一块mmio区域并将vma绑定到initial_mm
///
/// @param size mmio区域的大小字节
///
/// @param vm_flags 要把vma设置成的标志
///
/// @param res_vaddr 返回值-分配得到的虚拟地址
///
/// @param res_length 返回值-分配的虚拟地址空间长度
///
/// @return int 错误码
#[no_mangle]
pub extern "C" fn mmio_create(
size: u32,
vm_flags: vm_flags_t,
res_vaddr: *mut u64,
res_length: *mut u64,
) -> i32 {
if let Err(err) = MMIO_POOL.create_mmio(size, vm_flags, res_vaddr, res_length) {
return err;
} else {
return 0;
}
}
/// @brief 取消mmio的映射并将地址空间归还到buddy中
///
/// @param vaddr 起始的虚拟地址
///
/// @param length 要归还的地址空间的长度
///
/// @return Ok(i32) 成功返回0
///
/// @return Err(i32) 失败返回错误码
#[no_mangle]
pub extern "C" fn mmio_release(vaddr: u64, length: u64) -> i32 {
if let Err(err) = MMIO_POOL.release_mmio(vaddr, length) {
return err;
} else {
return 0;
}
}