forked from lolo859/vystem
72 lines
3.5 KiB
C
72 lines
3.5 KiB
C
// SPDX-License-Identifier: MPL-2.0
|
|
#include "memory/pba.h"
|
|
#include "memory/pez/pez.h"
|
|
#include "kernel/log.h"
|
|
SH_STATUS sh_pba_init(sh_pba_PAGE_BLOCK_ALLOCATOR *pba,sh_page_VIRTUAL_ADDRESS start_va,sh_uint64 area_pages_amount,sh_uint64 block_pages) {
|
|
if (pba==SH_NULLPTR) {
|
|
return SH_STATUS_INVALID_PARAMETER;
|
|
}
|
|
if (area_pages_amount%block_pages!=0) {
|
|
return SH_STATUS_INVALID_PARAMETER;
|
|
}
|
|
if (start_va%(SH_PAGE_SIZE*block_pages)!=0) {
|
|
return SH_STATUS_INVALID_PARAMETER;
|
|
}
|
|
pba->start_va=start_va;
|
|
pba->block_pages=block_pages;
|
|
pba->block_count=0;
|
|
pba->total_pages=area_pages_amount;
|
|
pba->max_blocks=area_pages_amount/block_pages;
|
|
return SH_STATUS_SUCCESS;
|
|
}
|
|
SH_STATUS sh_pba_alloc(sh_pba_PAGE_BLOCK_ALLOCATOR *pba,sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADDRESS *ptr) {
|
|
if (pba==SH_NULLPTR || ptr==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER;
|
|
if (pba->block_count==pba->max_blocks) return SH_STATUS_PBA_FULL;
|
|
if (!sh_pez_is_available()) {
|
|
sh_page_PHYSICAL_ADDRESS block_pa;
|
|
SH_STATUS status=sh_page_search_physical_contiguous_block_na(pba->block_pages,&block_pa);
|
|
if (sh_status_error(status)) return status;
|
|
sh_page_VIRTUAL_ADDRESS temp_ptr=pba->start_va+pba->block_count*pba->block_pages*SH_PAGE_SIZE;
|
|
status=sh_page_is_va_range_mapped_ptp(ptp,temp_ptr,pba->block_pages*SH_PAGE_SIZE);
|
|
if (status==SH_STATUS_VA_FULLY_MAPPED || status==SH_STATUS_VA_PARTIALLY_MAPPED) {
|
|
return status;
|
|
} else if (sh_status_error(status)) {
|
|
return status;
|
|
} else if (status!=SH_STATUS_VA_NOT_MAPPED) {
|
|
return status;
|
|
}
|
|
status=sh_page_set_pages_range_bitmap((sh_uint8*)sh_page_get_physical_bitmap_ptr(),sh_page_get_physical_memory_amount_pages(),block_pa/SH_PAGE_SIZE,pba->block_pages,SH_TRUE);
|
|
if (sh_status_error(status)) return status;
|
|
status=sh_page_map_contiguous_pages_range_ptp(ptp,temp_ptr,block_pa,SH_PAGE_RW | SH_PAGE_NX | SH_PAGE_PRESENT,pba->block_pages*SH_PAGE_SIZE);
|
|
if (sh_status_error(status)) {
|
|
SH_STATUS status2=sh_page_set_pages_range_bitmap((sh_uint8*)sh_page_get_physical_bitmap_ptr(),sh_page_get_physical_memory_amount_pages(),block_pa/SH_PAGE_SIZE,pba->block_pages,SH_FALSE);
|
|
if (sh_status_error(status2)) return status2;
|
|
return status;
|
|
}
|
|
*ptr=temp_ptr;
|
|
} else {
|
|
if (sh_pez_get_reference_phys_plane()==SH_NULLPTR) return SH_STATUS_ERROR_PEZ_INITIALIZED;
|
|
sh_page_PHYSICAL_ADDRESS block_pa;
|
|
SH_STATUS status=sh_pez_alloc_physical_pages(sh_pez_get_reference_phys_plane(),(sh_uint32)pba->block_pages,&block_pa);
|
|
if (sh_status_error(status)) return status;
|
|
sh_page_VIRTUAL_ADDRESS temp_ptr=pba->start_va+pba->block_count*pba->block_pages*SH_PAGE_SIZE;
|
|
status=sh_page_is_va_range_mapped_ptp(ptp,temp_ptr,pba->block_pages*SH_PAGE_SIZE);
|
|
if (status==SH_STATUS_VA_FULLY_MAPPED || status==SH_STATUS_VA_PARTIALLY_MAPPED) {
|
|
return status;
|
|
} else if (sh_status_error(status)) {
|
|
return status;
|
|
} else if (status!=SH_STATUS_VA_NOT_MAPPED) {
|
|
return status;
|
|
}
|
|
status=sh_page_map_contiguous_pages_range_ptp(ptp,temp_ptr,block_pa,SH_PAGE_RW | SH_PAGE_NX | SH_PAGE_PRESENT,pba->block_pages*SH_PAGE_SIZE);
|
|
if (sh_status_error(status)) {
|
|
SH_STATUS status2=sh_page_set_pages_range_bitmap((sh_uint8*)sh_page_get_physical_bitmap_ptr(),sh_page_get_physical_memory_amount_pages(),block_pa/SH_PAGE_SIZE,pba->block_pages,SH_FALSE);
|
|
if (sh_status_error(status2)) return status2;
|
|
return status;
|
|
}
|
|
*ptr=temp_ptr;
|
|
}
|
|
pba->block_count++;
|
|
return SH_STATUS_SUCCESS;
|
|
}
|