mem/heap: use libyalloc instead of linked_list_allocator in kernel
This commit is contained in:
parent
3383d0350c
commit
8eb5d2ecf1
409
Cargo.lock
generated
409
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -47,8 +47,6 @@ const_assert_eq!(KERNEL_L1_INDEX, 1);
|
|||||||
// 2MiB max
|
// 2MiB max
|
||||||
const EARLY_MAPPING_L2I: usize = KERNEL_END_L2_INDEX + 1;
|
const EARLY_MAPPING_L2I: usize = KERNEL_END_L2_INDEX + 1;
|
||||||
// 1GiB max
|
// 1GiB max
|
||||||
const HEAP_MAPPING_L1I: usize = KERNEL_L1_INDEX + 1;
|
|
||||||
// 1GiB max
|
|
||||||
const DEVICE_MAPPING_L1I: usize = KERNEL_L1_INDEX + 2;
|
const DEVICE_MAPPING_L1I: usize = KERNEL_L1_INDEX + 2;
|
||||||
const DEVICE_MAPPING_L3_COUNT: usize = 4;
|
const DEVICE_MAPPING_L3_COUNT: usize = 4;
|
||||||
// 16GiB max
|
// 16GiB max
|
||||||
@ -59,9 +57,6 @@ pub const RAM_MAPPING_L1_COUNT: usize = 16;
|
|||||||
const EARLY_MAPPING_OFFSET: usize =
|
const EARLY_MAPPING_OFFSET: usize =
|
||||||
MAPPING_OFFSET | (KERNEL_L1_INDEX * L1::SIZE) | (EARLY_MAPPING_L2I * L2::SIZE);
|
MAPPING_OFFSET | (KERNEL_L1_INDEX * L1::SIZE) | (EARLY_MAPPING_L2I * L2::SIZE);
|
||||||
static mut EARLY_MAPPING_L3: PageTable<L3> = PageTable::zeroed();
|
static mut EARLY_MAPPING_L3: PageTable<L3> = PageTable::zeroed();
|
||||||
// 1GiB for heap mapping
|
|
||||||
pub const HEAP_MAPPING_OFFSET: usize = MAPPING_OFFSET | (HEAP_MAPPING_L1I * L1::SIZE);
|
|
||||||
pub static mut HEAP_MAPPING_L2: PageTable<L2> = PageTable::zeroed();
|
|
||||||
// 1GiB for device MMIO mapping
|
// 1GiB for device MMIO mapping
|
||||||
const DEVICE_MAPPING_OFFSET: usize = MAPPING_OFFSET | (DEVICE_MAPPING_L1I * L1::SIZE);
|
const DEVICE_MAPPING_OFFSET: usize = MAPPING_OFFSET | (DEVICE_MAPPING_L1I * L1::SIZE);
|
||||||
static mut DEVICE_MAPPING_L2: PageTable<L2> = PageTable::zeroed();
|
static mut DEVICE_MAPPING_L2: PageTable<L2> = PageTable::zeroed();
|
||||||
@ -232,18 +227,6 @@ pub unsafe fn map_ram_l1(index: usize) {
|
|||||||
((index * L1::SIZE) as u64) | ram_block_flags().bits();
|
((index * L1::SIZE) as u64) | ram_block_flags().bits();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// Only meant to be used by the architecture initialization functions.
|
|
||||||
pub unsafe fn map_heap_l2(index: usize, page: PhysicalAddress) {
|
|
||||||
if index >= 512 {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
assert!(!HEAP_MAPPING_L2[index].is_present());
|
|
||||||
// TODO UXN, PXN
|
|
||||||
HEAP_MAPPING_L2[index] = PageEntry::normal_block(page, PageAttributes::empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Device mappings
|
// Device mappings
|
||||||
unsafe fn map_device_memory_l3(
|
unsafe fn map_device_memory_l3(
|
||||||
base: PhysicalAddress,
|
base: PhysicalAddress,
|
||||||
@ -394,7 +377,6 @@ pub unsafe fn init_fixed_tables() {
|
|||||||
// TODO this could be built in compile-time too?
|
// TODO this could be built in compile-time too?
|
||||||
let early_mapping_l3_phys = addr_of!(EARLY_MAPPING_L3) as usize - KERNEL_VIRT_OFFSET;
|
let early_mapping_l3_phys = addr_of!(EARLY_MAPPING_L3) as usize - KERNEL_VIRT_OFFSET;
|
||||||
let device_mapping_l2_phys = addr_of!(DEVICE_MAPPING_L2) as usize - KERNEL_VIRT_OFFSET;
|
let device_mapping_l2_phys = addr_of!(DEVICE_MAPPING_L2) as usize - KERNEL_VIRT_OFFSET;
|
||||||
let heap_mapping_l2_phys = addr_of!(HEAP_MAPPING_L2) as usize - KERNEL_VIRT_OFFSET;
|
|
||||||
|
|
||||||
for i in 0..DEVICE_MAPPING_L3_COUNT {
|
for i in 0..DEVICE_MAPPING_L3_COUNT {
|
||||||
let device_mapping_l3_phys = PhysicalAddress::from_raw(
|
let device_mapping_l3_phys = PhysicalAddress::from_raw(
|
||||||
@ -407,10 +389,6 @@ pub unsafe fn init_fixed_tables() {
|
|||||||
KERNEL_TABLES.l2.data[EARLY_MAPPING_L2I] =
|
KERNEL_TABLES.l2.data[EARLY_MAPPING_L2I] =
|
||||||
(early_mapping_l3_phys as u64) | kernel_table_flags().bits();
|
(early_mapping_l3_phys as u64) | kernel_table_flags().bits();
|
||||||
|
|
||||||
assert_eq!(KERNEL_TABLES.l1.data[HEAP_MAPPING_L1I], 0);
|
|
||||||
KERNEL_TABLES.l1.data[HEAP_MAPPING_L1I] =
|
|
||||||
(heap_mapping_l2_phys as u64) | kernel_table_flags().bits();
|
|
||||||
|
|
||||||
assert_eq!(KERNEL_TABLES.l1.data[DEVICE_MAPPING_L1I], 0);
|
assert_eq!(KERNEL_TABLES.l1.data[DEVICE_MAPPING_L1I], 0);
|
||||||
KERNEL_TABLES.l1.data[DEVICE_MAPPING_L1I] =
|
KERNEL_TABLES.l1.data[DEVICE_MAPPING_L1I] =
|
||||||
(device_mapping_l2_phys as u64) | kernel_table_flags().bits();
|
(device_mapping_l2_phys as u64) | kernel_table_flags().bits();
|
||||||
|
@ -44,7 +44,6 @@ const_assert_eq!(KERNEL_L1_INDEX, 0);
|
|||||||
|
|
||||||
// Mapped at boot
|
// Mapped at boot
|
||||||
const EARLY_MAPPING_L2I: usize = KERNEL_START_L2_INDEX - 1;
|
const EARLY_MAPPING_L2I: usize = KERNEL_START_L2_INDEX - 1;
|
||||||
const HEAP_MAPPING_L1I: usize = KERNEL_L1_INDEX + 1;
|
|
||||||
const DEVICE_MAPPING_L1I: usize = KERNEL_L1_INDEX + 2;
|
const DEVICE_MAPPING_L1I: usize = KERNEL_L1_INDEX + 2;
|
||||||
const RAM_MAPPING_L0I: usize = KERNEL_L0_INDEX - 1;
|
const RAM_MAPPING_L0I: usize = KERNEL_L0_INDEX - 1;
|
||||||
|
|
||||||
@ -60,10 +59,6 @@ const EARLY_MAPPING_OFFSET: usize = CANONICAL_ADDRESS_MASK
|
|||||||
| (KERNEL_L1_INDEX * L1::SIZE)
|
| (KERNEL_L1_INDEX * L1::SIZE)
|
||||||
| (EARLY_MAPPING_L2I * L2::SIZE);
|
| (EARLY_MAPPING_L2I * L2::SIZE);
|
||||||
static mut EARLY_MAPPING_L3: PageTable<L3> = PageTable::zeroed();
|
static mut EARLY_MAPPING_L3: PageTable<L3> = PageTable::zeroed();
|
||||||
// 1GiB for heap mapping
|
|
||||||
pub const HEAP_MAPPING_OFFSET: usize =
|
|
||||||
CANONICAL_ADDRESS_MASK | (KERNEL_L0_INDEX * L0::SIZE) | (HEAP_MAPPING_L1I * L1::SIZE);
|
|
||||||
pub(super) static mut HEAP_MAPPING_L2: PageTable<L2> = PageTable::zeroed();
|
|
||||||
// 1GiB for device MMIO mapping
|
// 1GiB for device MMIO mapping
|
||||||
const DEVICE_MAPPING_OFFSET: usize =
|
const DEVICE_MAPPING_OFFSET: usize =
|
||||||
CANONICAL_ADDRESS_MASK | (KERNEL_L0_INDEX * L0::SIZE) | (DEVICE_MAPPING_L1I * L1::SIZE);
|
CANONICAL_ADDRESS_MASK | (KERNEL_L0_INDEX * L0::SIZE) | (DEVICE_MAPPING_L1I * L1::SIZE);
|
||||||
@ -269,23 +264,6 @@ unsafe fn unmap_device_memory(map: &RawDeviceMemoryMapping<KernelTableManagerImp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// Only meant to be called from memory initialization routines.
|
|
||||||
pub unsafe fn map_heap_block(index: usize, page: PhysicalAddress) {
|
|
||||||
if !page.is_page_aligned_for::<L2>() {
|
|
||||||
panic!("Attempted to map a misaligned 2MiB page");
|
|
||||||
}
|
|
||||||
assert!(index < 512);
|
|
||||||
|
|
||||||
if HEAP_MAPPING_L2[index].is_present() {
|
|
||||||
panic!("Page is already mappged: {:#x}", page);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO NX
|
|
||||||
HEAP_MAPPING_L2[index] = PageEntry::<L2>::block(page, PageAttributes::WRITABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Memory mapping which may be used for performing early kernel initialization
|
/// Memory mapping which may be used for performing early kernel initialization
|
||||||
pub struct EarlyMapping<'a, T: ?Sized> {
|
pub struct EarlyMapping<'a, T: ?Sized> {
|
||||||
value: &'a mut T,
|
value: &'a mut T,
|
||||||
@ -371,7 +349,7 @@ pub fn clone_kernel_tables(dst: &mut PageTable<L0>) {
|
|||||||
/// * 0xFFFFFF8000000000 .. 0xFFFFFF8000200000 : ---
|
/// * 0xFFFFFF8000000000 .. 0xFFFFFF8000200000 : ---
|
||||||
/// * 0xFFFFFF8000200000 .. 0xFFFFFF8000400000 : EARLY_MAPPING_L3
|
/// * 0xFFFFFF8000200000 .. 0xFFFFFF8000400000 : EARLY_MAPPING_L3
|
||||||
/// * 0xFFFFFF8000400000 .. ... : KERNEL_TABLES.kernel_l3s
|
/// * 0xFFFFFF8000400000 .. ... : KERNEL_TABLES.kernel_l3s
|
||||||
/// * 0xFFFFFF8040000000 .. 0xFFFFFF8080000000 : HEAP_MAPPING_L2
|
/// * 0xFFFFFF8040000000 .. 0xFFFFFF8080000000 : ---
|
||||||
/// * 0xFFFFFF8080000000 .. 0xFFFFFF8100000000 : DEVICE_MAPPING_L2
|
/// * 0xFFFFFF8080000000 .. 0xFFFFFF8100000000 : DEVICE_MAPPING_L2
|
||||||
/// * 0xFFFFFF8080000000 .. 0xFFFFFF8080800000 : DEVICE_MAPPING_L3S
|
/// * 0xFFFFFF8080000000 .. 0xFFFFFF8080800000 : DEVICE_MAPPING_L3S
|
||||||
/// * 0xFFFFFF8080800000 .. 0xFFFFFF8100000000 : ...
|
/// * 0xFFFFFF8080800000 .. 0xFFFFFF8100000000 : ...
|
||||||
@ -383,7 +361,6 @@ pub unsafe fn init_fixed_tables() {
|
|||||||
// TODO this could be built in compile-time too?
|
// TODO this could be built in compile-time too?
|
||||||
let early_mapping_l3_phys = addr_of!(EARLY_MAPPING_L3) as usize - KERNEL_VIRT_OFFSET;
|
let early_mapping_l3_phys = addr_of!(EARLY_MAPPING_L3) as usize - KERNEL_VIRT_OFFSET;
|
||||||
let device_mapping_l2_phys = addr_of!(DEVICE_MAPPING_L2) as usize - KERNEL_VIRT_OFFSET;
|
let device_mapping_l2_phys = addr_of!(DEVICE_MAPPING_L2) as usize - KERNEL_VIRT_OFFSET;
|
||||||
let heap_mapping_l2_phys = addr_of!(HEAP_MAPPING_L2) as usize - KERNEL_VIRT_OFFSET;
|
|
||||||
let ram_mapping_l1_phys = addr_of!(RAM_MAPPING_L1) as usize - KERNEL_VIRT_OFFSET;
|
let ram_mapping_l1_phys = addr_of!(RAM_MAPPING_L1) as usize - KERNEL_VIRT_OFFSET;
|
||||||
|
|
||||||
for i in 0..DEVICE_MAPPING_L3_COUNT {
|
for i in 0..DEVICE_MAPPING_L3_COUNT {
|
||||||
@ -397,9 +374,6 @@ pub unsafe fn init_fixed_tables() {
|
|||||||
KERNEL_TABLES.kernel_l2.data[EARLY_MAPPING_L2I] = (early_mapping_l3_phys as u64)
|
KERNEL_TABLES.kernel_l2.data[EARLY_MAPPING_L2I] = (early_mapping_l3_phys as u64)
|
||||||
| (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits();
|
| (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits();
|
||||||
|
|
||||||
assert_eq!(KERNEL_TABLES.kernel_l1.data[HEAP_MAPPING_L1I], 0);
|
|
||||||
KERNEL_TABLES.kernel_l1.data[HEAP_MAPPING_L1I] =
|
|
||||||
(heap_mapping_l2_phys as u64) | (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits();
|
|
||||||
assert_eq!(KERNEL_TABLES.kernel_l1.data[DEVICE_MAPPING_L1I], 0);
|
assert_eq!(KERNEL_TABLES.kernel_l1.data[DEVICE_MAPPING_L1I], 0);
|
||||||
KERNEL_TABLES.kernel_l1.data[DEVICE_MAPPING_L1I] = (device_mapping_l2_phys as u64)
|
KERNEL_TABLES.kernel_l1.data[DEVICE_MAPPING_L1I] = (device_mapping_l2_phys as u64)
|
||||||
| (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits();
|
| (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits();
|
||||||
|
@ -12,5 +12,6 @@ libk-util = { path = "../libk-util" }
|
|||||||
libk-mm-interface = { path = "interface" }
|
libk-mm-interface = { path = "interface" }
|
||||||
vmalloc = { path = "../../lib/vmalloc" }
|
vmalloc = { path = "../../lib/vmalloc" }
|
||||||
|
|
||||||
linked_list_allocator = "0.10.5"
|
libyalloc = { path = "../../../lib/libyalloc", default-features = false, features = ["dep-of-kernel"] }
|
||||||
|
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
|
@ -1,41 +1,58 @@
|
|||||||
//! Kernel's global heap allocator
|
//! Kernel's global heap allocator
|
||||||
use core::{
|
use core::{
|
||||||
alloc::{GlobalAlloc, Layout},
|
alloc::{GlobalAlloc, Layout},
|
||||||
ops::Range,
|
|
||||||
ptr::{null_mut, NonNull},
|
ptr::{null_mut, NonNull},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use kernel_arch::KernelTableManagerImpl;
|
||||||
|
use libk_mm_interface::address::PhysicalAddress;
|
||||||
use libk_util::sync::IrqSafeSpinlock;
|
use libk_util::sync::IrqSafeSpinlock;
|
||||||
use linked_list_allocator::Heap;
|
use libyalloc::{allocator::BucketAllocator, sys::PageProvider};
|
||||||
|
|
||||||
|
use crate::{address::Virtualize, phys, L3_PAGE_SIZE};
|
||||||
|
|
||||||
|
// TODO limits?
|
||||||
|
|
||||||
|
struct KernelPageProvider;
|
||||||
|
|
||||||
|
impl PageProvider for KernelPageProvider {
|
||||||
|
fn unmap_pages(address: NonNull<u8>, count: usize) {
|
||||||
|
log::trace!("Release {}K of heap", count * 4);
|
||||||
|
let phys = PhysicalAddress::from_virtualized(address.as_ptr().addr());
|
||||||
|
for i in 0..count {
|
||||||
|
unsafe {
|
||||||
|
phys::free_page(phys.add(i * L3_PAGE_SIZE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_pages(count: usize) -> Option<NonNull<u8>> {
|
||||||
|
log::trace!("Grow heap by {}K", count * 4);
|
||||||
|
let phys = phys::alloc_pages_contiguous(count).ok()?;
|
||||||
|
let virt = phys.raw_virtualize::<KernelTableManagerImpl>();
|
||||||
|
Some(unsafe { NonNull::new_unchecked(virt as *mut u8) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Kernel heap manager
|
/// Kernel heap manager
|
||||||
pub struct KernelAllocator {
|
pub struct KernelAllocator {
|
||||||
inner: IrqSafeSpinlock<Heap>,
|
inner: IrqSafeSpinlock<BucketAllocator<KernelPageProvider>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KernelAllocator {
|
impl KernelAllocator {
|
||||||
const fn empty() -> Self {
|
const fn empty() -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: IrqSafeSpinlock::new(Heap::empty()),
|
inner: IrqSafeSpinlock::new(BucketAllocator::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn init(&self, base: usize, size: usize) {
|
|
||||||
self.inner.lock().init(base as _, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn range(&self) -> Range<usize> {
|
|
||||||
let lock = self.inner.lock();
|
|
||||||
lock.bottom() as usize..lock.top() as usize
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl GlobalAlloc for KernelAllocator {
|
unsafe impl GlobalAlloc for KernelAllocator {
|
||||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||||
match self.inner.lock().allocate_first_fit(layout) {
|
match self.inner.lock().allocate(layout) {
|
||||||
Ok(v) => v.as_ptr(),
|
Some(p) => p.as_ptr(),
|
||||||
Err(e) => {
|
None => {
|
||||||
log::error!("Failed to allocate {:?}: {:?}", layout, e);
|
log::error!("Failed to allocate {:?}", layout);
|
||||||
null_mut()
|
null_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,24 +60,10 @@ unsafe impl GlobalAlloc for KernelAllocator {
|
|||||||
|
|
||||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||||
let ptr = NonNull::new(ptr).unwrap();
|
let ptr = NonNull::new(ptr).unwrap();
|
||||||
self.inner.lock().deallocate(ptr, layout)
|
self.inner.lock().free(ptr, layout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Kernel's global allocator
|
/// Kernel's global allocator
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
pub static GLOBAL_HEAP: KernelAllocator = KernelAllocator::empty();
|
pub static GLOBAL_HEAP: KernelAllocator = KernelAllocator::empty();
|
||||||
|
|
||||||
/// Sets up kernel's global heap with given memory range.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// The caller must ensure the range is valid and mapped virtual memory.
|
|
||||||
pub unsafe fn init_heap(heap_base: usize, heap_size: usize) {
|
|
||||||
GLOBAL_HEAP.init(heap_base, heap_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the heap address range
|
|
||||||
pub fn heap_range() -> Range<usize> {
|
|
||||||
GLOBAL_HEAP.range()
|
|
||||||
}
|
|
||||||
|
65
kernel/modules/test_mod/Cargo.lock
generated
65
kernel/modules/test_mod/Cargo.lock
generated
@ -48,12 +48,6 @@ dependencies = [
|
|||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
@ -90,6 +84,12 @@ dependencies = [
|
|||||||
"syn 2.0.53",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.99"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -255,6 +255,12 @@ dependencies = [
|
|||||||
"yggdrasil-abi",
|
"yggdrasil-abi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.155"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libk"
|
name = "libk"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -294,7 +300,7 @@ dependencies = [
|
|||||||
"kernel-arch",
|
"kernel-arch",
|
||||||
"libk-mm-interface",
|
"libk-mm-interface",
|
||||||
"libk-util",
|
"libk-util",
|
||||||
"linked_list_allocator",
|
"libyalloc",
|
||||||
"log",
|
"log",
|
||||||
"vmalloc",
|
"vmalloc",
|
||||||
"yggdrasil-abi",
|
"yggdrasil-abi",
|
||||||
@ -323,22 +329,11 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linked_list_allocator"
|
name = "libyalloc"
|
||||||
version = "0.10.5"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"spinning_top",
|
"libc",
|
||||||
]
|
"yggdrasil-rt",
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lock_api"
|
|
||||||
version = "0.4.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"scopeguard",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -416,12 +411,6 @@ version = "1.0.17"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
|
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scopeguard"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.197"
|
version = "1.0.197"
|
||||||
@ -453,15 +442,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "spinning_top"
|
|
||||||
version = "0.2.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0"
|
|
||||||
dependencies = [
|
|
||||||
"lock_api",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -554,6 +534,17 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yggdrasil-rt"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"abi-generator",
|
||||||
|
"abi-lib",
|
||||||
|
"cc",
|
||||||
|
"prettyplease",
|
||||||
|
"yggdrasil-abi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.7.32"
|
version = "0.7.32"
|
||||||
|
@ -12,19 +12,18 @@ use device_tree::dt::{DevTreeIndexPropExt, DevTreeNodeInfo, DeviceTree, FdtMemor
|
|||||||
use git_version::git_version;
|
use git_version::git_version;
|
||||||
use kernel_arch_aarch64::{
|
use kernel_arch_aarch64::{
|
||||||
mem::{
|
mem::{
|
||||||
table::{L1, L2, L3},
|
table::{L1, L3},
|
||||||
EarlyMapping, HEAP_MAPPING_OFFSET, MEMORY_LIMIT, RAM_MAPPING_L1_COUNT,
|
EarlyMapping, MEMORY_LIMIT, RAM_MAPPING_L1_COUNT,
|
||||||
},
|
},
|
||||||
ArchitectureImpl, PerCpuData,
|
ArchitectureImpl, PerCpuData,
|
||||||
};
|
};
|
||||||
use libk::{arch::Cpu, device::external_interrupt_controller};
|
use libk::{arch::Cpu, device::external_interrupt_controller};
|
||||||
use libk_mm::{
|
use libk_mm::{
|
||||||
address::{FromRaw, IntoRaw, PhysicalAddress},
|
address::{FromRaw, IntoRaw, PhysicalAddress},
|
||||||
heap,
|
|
||||||
phys::PhysicalMemoryRegion,
|
phys::PhysicalMemoryRegion,
|
||||||
phys::{self, reserved::reserve_region},
|
phys::{self, reserved::reserve_region},
|
||||||
pointer::PhysicalRef,
|
pointer::PhysicalRef,
|
||||||
table::{EntryLevel, EntryLevelExt},
|
table::EntryLevelExt,
|
||||||
};
|
};
|
||||||
use libk_util::OneTimeInit;
|
use libk_util::OneTimeInit;
|
||||||
use tock_registers::interfaces::Writeable;
|
use tock_registers::interfaces::Writeable;
|
||||||
@ -151,9 +150,6 @@ impl AArch64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn init_memory_management(&'static self, dtb: PhysicalAddress) -> Result<(), Error> {
|
unsafe fn init_memory_management(&'static self, dtb: PhysicalAddress) -> Result<(), Error> {
|
||||||
// 16x2MiB
|
|
||||||
const HEAP_PAGES: usize = 16;
|
|
||||||
|
|
||||||
// Initialize the runtime mappings
|
// Initialize the runtime mappings
|
||||||
kernel_arch_aarch64::mem::init_fixed_tables();
|
kernel_arch_aarch64::mem::init_fixed_tables();
|
||||||
|
|
||||||
@ -197,14 +193,6 @@ impl AArch64 {
|
|||||||
|
|
||||||
phys::init_from_iter(regions, Self::map_physical_memory)?;
|
phys::init_from_iter(regions, Self::map_physical_memory)?;
|
||||||
|
|
||||||
// Setup the heap
|
|
||||||
for i in 0..HEAP_PAGES {
|
|
||||||
let l2_page = phys::alloc_2m_page()?;
|
|
||||||
kernel_arch_aarch64::mem::map_heap_l2(i, l2_page);
|
|
||||||
}
|
|
||||||
|
|
||||||
heap::init_heap(HEAP_MAPPING_OFFSET, HEAP_PAGES * L2::SIZE);
|
|
||||||
|
|
||||||
// EarlyMapping for DTB no longer needed, it lives in physical memory and can be obtained
|
// EarlyMapping for DTB no longer needed, it lives in physical memory and can be obtained
|
||||||
// through PhysicalRef
|
// through PhysicalRef
|
||||||
let dtb_slice: PhysicalRef<'static, [u8]> = PhysicalRef::map_slice(dtb, dtb_size);
|
let dtb_slice: PhysicalRef<'static, [u8]> = PhysicalRef::map_slice(dtb, dtb_size);
|
||||||
|
@ -8,9 +8,9 @@ use device_api::{interrupt::Irq, Device};
|
|||||||
use git_version::git_version;
|
use git_version::git_version;
|
||||||
use kernel_arch_x86_64::{
|
use kernel_arch_x86_64::{
|
||||||
mem::{
|
mem::{
|
||||||
init_fixed_tables, map_heap_block,
|
init_fixed_tables,
|
||||||
table::{PageAttributes, PageEntry, PageTable, L1, L2, L3},
|
table::{PageAttributes, PageEntry, PageTable, L1, L2, L3},
|
||||||
EarlyMapping, HEAP_MAPPING_OFFSET, MEMORY_LIMIT, RAM_MAPPING_L1,
|
EarlyMapping, MEMORY_LIMIT, RAM_MAPPING_L1,
|
||||||
},
|
},
|
||||||
PerCpuData,
|
PerCpuData,
|
||||||
};
|
};
|
||||||
@ -19,7 +19,6 @@ use libk::{arch::Cpu, device::register_external_interrupt_controller};
|
|||||||
use libk_device::register_monotonic_timestamp_provider;
|
use libk_device::register_monotonic_timestamp_provider;
|
||||||
use libk_mm::{
|
use libk_mm::{
|
||||||
address::{FromRaw, IntoRaw, PhysicalAddress, Virtualize},
|
address::{FromRaw, IntoRaw, PhysicalAddress, Virtualize},
|
||||||
heap,
|
|
||||||
phys::{self, reserved::reserve_region, PhysicalMemoryRegion},
|
phys::{self, reserved::reserve_region, PhysicalMemoryRegion},
|
||||||
table::{EntryLevel, EntryLevelExt},
|
table::{EntryLevel, EntryLevelExt},
|
||||||
};
|
};
|
||||||
@ -241,8 +240,6 @@ impl X86_64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn init_memory_management(&self) -> Result<(), Error> {
|
unsafe fn init_memory_management(&self) -> Result<(), Error> {
|
||||||
const HEAP_PAGES: usize = 16;
|
|
||||||
|
|
||||||
init_fixed_tables();
|
init_fixed_tables();
|
||||||
|
|
||||||
// Reserve lower 4MiB just in case
|
// Reserve lower 4MiB just in case
|
||||||
@ -258,16 +255,6 @@ impl X86_64 {
|
|||||||
&BootData::YBoot(data) => Self::init_physical_memory_from_yboot(data)?,
|
&BootData::YBoot(data) => Self::init_physical_memory_from_yboot(data)?,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup heap
|
|
||||||
for i in 0..HEAP_PAGES {
|
|
||||||
// Allocate in 2MiB chunks
|
|
||||||
let l2_page = phys::alloc_2m_page()?;
|
|
||||||
|
|
||||||
map_heap_block(i, l2_page);
|
|
||||||
}
|
|
||||||
|
|
||||||
heap::init_heap(HEAP_MAPPING_OFFSET, HEAP_PAGES * L2::SIZE);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,6 @@
|
|||||||
use arch::Platform;
|
use arch::Platform;
|
||||||
use kernel_arch::{Architecture, ArchitectureImpl};
|
use kernel_arch::{Architecture, ArchitectureImpl};
|
||||||
use libk::arch::Cpu;
|
use libk::arch::Cpu;
|
||||||
use libk_mm::heap;
|
|
||||||
use libk_util::sync::SpinFence;
|
use libk_util::sync::SpinFence;
|
||||||
|
|
||||||
use crate::{arch::PLATFORM, fs::sysfs, task::spawn_kernel_closure};
|
use crate::{arch::PLATFORM, fs::sysfs, task::spawn_kernel_closure};
|
||||||
@ -93,8 +92,6 @@ pub fn kernel_secondary_main() -> ! {
|
|||||||
pub fn kernel_main() -> ! {
|
pub fn kernel_main() -> ! {
|
||||||
libk::panic::set_handler(panic::panic_handler);
|
libk::panic::set_handler(panic::panic_handler);
|
||||||
|
|
||||||
debugln!("Heap: {:#x?}", heap::heap_range());
|
|
||||||
|
|
||||||
// Setup the sysfs
|
// Setup the sysfs
|
||||||
sysfs::init();
|
sysfs::init();
|
||||||
fs::add_pseudo_devices().unwrap();
|
fs::add_pseudo_devices().unwrap();
|
||||||
|
@ -17,7 +17,9 @@ libc = { version = "0.2.140", default-features = false }
|
|||||||
yggdrasil-rt = { path = "../runtime", default-features = false }
|
yggdrasil-rt = { path = "../runtime", default-features = false }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = ["global"]
|
||||||
|
global = []
|
||||||
|
dep-of-kernel = []
|
||||||
rustc-dep-of-std = [
|
rustc-dep-of-std = [
|
||||||
"core",
|
"core",
|
||||||
"compiler_builtins",
|
"compiler_builtins",
|
||||||
|
@ -2,33 +2,34 @@ use core::{alloc::Layout, ops::Index, ptr::NonNull};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bucket::Bucket,
|
bucket::Bucket,
|
||||||
util::{self, Assert, IsTrue},
|
sys::{self, PageProvider},
|
||||||
|
util::{Assert, IsTrue},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BucketList<const N: usize, const M: usize>
|
struct BucketList<P: PageProvider, const N: usize, const M: usize>
|
||||||
where
|
where
|
||||||
[u64; M / 64]: Sized,
|
[u64; M / 64]: Sized,
|
||||||
Assert<{ M % 64 == 0 }>: IsTrue,
|
Assert<{ M % 64 == 0 }>: IsTrue,
|
||||||
{
|
{
|
||||||
head: Option<NonNull<Bucket<N, M>>>,
|
head: Option<NonNull<Bucket<P, N, M>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BucketAllocator {
|
pub struct BucketAllocator<P: PageProvider> {
|
||||||
// 1024x64 = 16 pages
|
// 1024x64 = 16 pages
|
||||||
buckets_1024: BucketList<1024, 64>,
|
buckets_1024: BucketList<P, 1024, 64>,
|
||||||
// 512x64 = 8 pages
|
// 512x64 = 8 pages
|
||||||
buckets_512: BucketList<512, 64>,
|
buckets_512: BucketList<P, 512, 64>,
|
||||||
// 256x128 = 8 pages
|
// 256x128 = 8 pages
|
||||||
buckets_256: BucketList<256, 128>,
|
buckets_256: BucketList<P, 256, 128>,
|
||||||
// 128x128 = 4 pages
|
// 128x128 = 4 pages
|
||||||
buckets_128: BucketList<128, 128>,
|
buckets_128: BucketList<P, 128, 128>,
|
||||||
// 64x128 = 2 pages
|
// 64x128 = 2 pages
|
||||||
buckets_64: BucketList<128, 128>,
|
buckets_64: BucketList<P, 128, 128>,
|
||||||
// 32x256 = 2 pages
|
// 32x256 = 2 pages
|
||||||
buckets_32: BucketList<128, 128>,
|
buckets_32: BucketList<P, 128, 128>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize, const M: usize> BucketList<N, M>
|
impl<P: PageProvider, const N: usize, const M: usize> BucketList<P, N, M>
|
||||||
where
|
where
|
||||||
[u64; M / 64]: Sized,
|
[u64; M / 64]: Sized,
|
||||||
Assert<{ M % 64 == 0 }>: IsTrue,
|
Assert<{ M % 64 == 0 }>: IsTrue,
|
||||||
@ -75,12 +76,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize, const M: usize> Index<usize> for BucketList<N, M>
|
impl<P: PageProvider, const N: usize, const M: usize> Index<usize> for BucketList<P, N, M>
|
||||||
where
|
where
|
||||||
[u64; M / 64]: Sized,
|
[u64; M / 64]: Sized,
|
||||||
Assert<{ M % 64 == 0 }>: IsTrue,
|
Assert<{ M % 64 == 0 }>: IsTrue,
|
||||||
{
|
{
|
||||||
type Output = Bucket<N, M>;
|
type Output = Bucket<P, N, M>;
|
||||||
|
|
||||||
fn index(&self, index: usize) -> &Self::Output {
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
let mut current = 0;
|
let mut current = 0;
|
||||||
@ -100,7 +101,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BucketAllocator {
|
impl<P: PageProvider> BucketAllocator<P> {
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
buckets_1024: BucketList::new(),
|
buckets_1024: BucketList::new(),
|
||||||
@ -116,14 +117,13 @@ impl BucketAllocator {
|
|||||||
let aligned = layout.pad_to_align();
|
let aligned = layout.pad_to_align();
|
||||||
|
|
||||||
match aligned.size() {
|
match aligned.size() {
|
||||||
0 => todo!(),
|
|
||||||
..=32 => self.buckets_32.allocate(),
|
..=32 => self.buckets_32.allocate(),
|
||||||
..=64 => self.buckets_64.allocate(),
|
..=64 => self.buckets_64.allocate(),
|
||||||
..=128 => self.buckets_128.allocate(),
|
..=128 => self.buckets_128.allocate(),
|
||||||
..=256 => self.buckets_256.allocate(),
|
..=256 => self.buckets_256.allocate(),
|
||||||
..=512 => self.buckets_512.allocate(),
|
..=512 => self.buckets_512.allocate(),
|
||||||
..=1024 => self.buckets_1024.allocate(),
|
..=1024 => self.buckets_1024.allocate(),
|
||||||
size => util::map_pages((size + util::PAGE_SIZE - 1) / util::PAGE_SIZE),
|
size => P::map_pages((size + sys::PAGE_SIZE - 1) / sys::PAGE_SIZE),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +131,6 @@ impl BucketAllocator {
|
|||||||
let aligned = layout.pad_to_align();
|
let aligned = layout.pad_to_align();
|
||||||
|
|
||||||
match aligned.size() {
|
match aligned.size() {
|
||||||
0 => todo!(),
|
|
||||||
..=32 => self.buckets_32.free(ptr),
|
..=32 => self.buckets_32.free(ptr),
|
||||||
..=64 => self.buckets_64.free(ptr),
|
..=64 => self.buckets_64.free(ptr),
|
||||||
..=128 => self.buckets_128.free(ptr),
|
..=128 => self.buckets_128.free(ptr),
|
||||||
@ -139,8 +138,8 @@ impl BucketAllocator {
|
|||||||
..=512 => self.buckets_512.free(ptr),
|
..=512 => self.buckets_512.free(ptr),
|
||||||
..=1024 => self.buckets_1024.free(ptr),
|
..=1024 => self.buckets_1024.free(ptr),
|
||||||
size => {
|
size => {
|
||||||
assert_eq!(usize::from(ptr.addr()) % util::PAGE_SIZE, 0);
|
assert_eq!(usize::from(ptr.addr()) % sys::PAGE_SIZE, 0);
|
||||||
util::unmap_pages(ptr, (size + util::PAGE_SIZE - 1) / util::PAGE_SIZE);
|
P::unmap_pages(ptr, (size + sys::PAGE_SIZE - 1) / sys::PAGE_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -151,10 +150,11 @@ mod tests {
|
|||||||
use core::{alloc::Layout, ptr::NonNull};
|
use core::{alloc::Layout, ptr::NonNull};
|
||||||
|
|
||||||
use super::{BucketAllocator, BucketList};
|
use super::{BucketAllocator, BucketList};
|
||||||
|
use crate::sys::OsPageProvider;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn single_list_allocation() {
|
fn single_list_allocation() {
|
||||||
let mut list = BucketList::<32, 64>::new();
|
let mut list = BucketList::<OsPageProvider, 32, 64>::new();
|
||||||
let mut vec = vec![];
|
let mut vec = vec![];
|
||||||
|
|
||||||
for _ in 0..4 * 64 + 3 {
|
for _ in 0..4 * 64 + 3 {
|
||||||
@ -173,7 +173,7 @@ mod tests {
|
|||||||
fn multi_list_allocation() {
|
fn multi_list_allocation() {
|
||||||
const SIZES: &[usize] = &[1, 3, 7, 15, 16, 24, 33, 65, 126, 255, 500, 1000];
|
const SIZES: &[usize] = &[1, 3, 7, 15, 16, 24, 33, 65, 126, 255, 500, 1000];
|
||||||
|
|
||||||
let mut allocator = BucketAllocator::new();
|
let mut allocator = BucketAllocator::<OsPageProvider>::new();
|
||||||
let mut vec = vec![];
|
let mut vec = vec![];
|
||||||
|
|
||||||
for _ in 0..65 {
|
for _ in 0..65 {
|
||||||
@ -199,7 +199,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn double_free() {
|
fn double_free() {
|
||||||
let mut allocator = BucketAllocator::new();
|
let mut allocator = BucketAllocator::<OsPageProvider>::new();
|
||||||
let layout = Layout::from_size_align(63, 32).unwrap();
|
let layout = Layout::from_size_align(63, 32).unwrap();
|
||||||
let ptr = allocator.allocate(layout).unwrap();
|
let ptr = allocator.allocate(layout).unwrap();
|
||||||
|
|
||||||
@ -213,7 +213,7 @@ mod tests {
|
|||||||
fn large_alloc() {
|
fn large_alloc() {
|
||||||
const SIZES: &[usize] = &[2000, 2048, 4000, 4096, 8192];
|
const SIZES: &[usize] = &[2000, 2048, 4000, 4096, 8192];
|
||||||
|
|
||||||
let mut allocator = BucketAllocator::new();
|
let mut allocator = BucketAllocator::<OsPageProvider>::new();
|
||||||
let mut vec = vec![];
|
let mut vec = vec![];
|
||||||
|
|
||||||
for &size in SIZES {
|
for &size in SIZES {
|
||||||
|
@ -3,9 +3,12 @@ use core::{
|
|||||||
ptr::NonNull,
|
ptr::NonNull,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::util::{self, Assert, IsTrue, NonNullExt};
|
use crate::{
|
||||||
|
sys::PageProvider,
|
||||||
|
util::{Assert, IsTrue, NonNullExt},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct Bucket<const N: usize, const M: usize>
|
pub struct Bucket<P: PageProvider, const N: usize, const M: usize>
|
||||||
where
|
where
|
||||||
[u64; M / 64]: Sized,
|
[u64; M / 64]: Sized,
|
||||||
Assert<{ M % 64 == 0 }>: IsTrue,
|
Assert<{ M % 64 == 0 }>: IsTrue,
|
||||||
@ -13,10 +16,10 @@ where
|
|||||||
pub(crate) data: NonNull<u8>,
|
pub(crate) data: NonNull<u8>,
|
||||||
bitmap: [u64; M / 64],
|
bitmap: [u64; M / 64],
|
||||||
allocated_count: usize,
|
allocated_count: usize,
|
||||||
pub(crate) next: Option<NonNull<Bucket<N, M>>>,
|
pub(crate) next: Option<NonNull<Bucket<P, N, M>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize, const M: usize> Bucket<N, M>
|
impl<P: PageProvider, const N: usize, const M: usize> Bucket<P, N, M>
|
||||||
where
|
where
|
||||||
[u64; M / 64]: Sized,
|
[u64; M / 64]: Sized,
|
||||||
Assert<{ M % 64 == 0 }>: IsTrue,
|
Assert<{ M % 64 == 0 }>: IsTrue,
|
||||||
@ -25,8 +28,8 @@ where
|
|||||||
let data_page_count = (M * N + 0xFFF) / 0x1000;
|
let data_page_count = (M * N + 0xFFF) / 0x1000;
|
||||||
let info_page_count = (size_of::<Self>() + 0xFFF) / 0x1000;
|
let info_page_count = (size_of::<Self>() + 0xFFF) / 0x1000;
|
||||||
|
|
||||||
let data = util::map_pages(data_page_count)?;
|
let data = P::map_pages(data_page_count)?;
|
||||||
let info = util::map_pages(info_page_count)?;
|
let info = P::map_pages(info_page_count)?;
|
||||||
|
|
||||||
let bucket = unsafe { info.cast::<MaybeUninit<Self>>().as_mut() };
|
let bucket = unsafe { info.cast::<MaybeUninit<Self>>().as_mut() };
|
||||||
let bucket = bucket.write(Self {
|
let bucket = bucket.write(Self {
|
||||||
@ -85,11 +88,27 @@ where
|
|||||||
mod tests {
|
mod tests {
|
||||||
use core::ptr::NonNull;
|
use core::ptr::NonNull;
|
||||||
|
|
||||||
use crate::{bucket::Bucket, util::NonNullExt};
|
use crate::{
|
||||||
|
bucket::Bucket,
|
||||||
|
sys::{self, PageProvider},
|
||||||
|
util::NonNullExt,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct DummyPageProvider;
|
||||||
|
|
||||||
|
impl PageProvider for DummyPageProvider {
|
||||||
|
fn map_pages(count: usize) -> Option<NonNull<u8>> {
|
||||||
|
let v = vec![0u8; count * sys::PAGE_SIZE];
|
||||||
|
let p = NonNull::from(&mut v.leak()[0]);
|
||||||
|
Some(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unmap_pages(_address: NonNull<u8>, _count: usize) {}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bucket_creation() {
|
fn bucket_creation() {
|
||||||
let mut bucket = Bucket::<32, 64>::new().unwrap();
|
let mut bucket = Bucket::<DummyPageProvider, 32, 64>::new().unwrap();
|
||||||
let bucket = unsafe { bucket.as_mut() };
|
let bucket = unsafe { bucket.as_mut() };
|
||||||
assert_eq!(bucket.allocated_count, 0);
|
assert_eq!(bucket.allocated_count, 0);
|
||||||
assert_eq!(bucket.next, None);
|
assert_eq!(bucket.next, None);
|
||||||
@ -97,7 +116,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bucket_allocation() {
|
fn bucket_allocation() {
|
||||||
let mut bucket = Bucket::<32, 64>::new().unwrap();
|
let mut bucket = Bucket::<DummyPageProvider, 32, 64>::new().unwrap();
|
||||||
let bucket = unsafe { bucket.as_mut() };
|
let bucket = unsafe { bucket.as_mut() };
|
||||||
let mut vec = vec![];
|
let mut vec = vec![];
|
||||||
|
|
||||||
@ -132,8 +151,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn free_outside_of_bucket() {
|
fn free_outside_of_bucket() {
|
||||||
let mut bucket0 = Bucket::<32, 64>::new().unwrap();
|
let mut bucket0 = Bucket::<DummyPageProvider, 32, 64>::new().unwrap();
|
||||||
let mut bucket1 = Bucket::<64, 64>::new().unwrap();
|
let mut bucket1 = Bucket::<DummyPageProvider, 64, 64>::new().unwrap();
|
||||||
let bucket0 = unsafe { bucket0.as_mut() };
|
let bucket0 = unsafe { bucket0.as_mut() };
|
||||||
let bucket1 = unsafe { bucket1.as_mut() };
|
let bucket1 = unsafe { bucket1.as_mut() };
|
||||||
|
|
||||||
@ -150,7 +169,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn double_free() {
|
fn double_free() {
|
||||||
let mut bucket0 = Bucket::<32, 64>::new().unwrap();
|
let mut bucket0 = Bucket::<DummyPageProvider, 32, 64>::new().unwrap();
|
||||||
let bucket0 = unsafe { bucket0.as_mut() };
|
let bucket0 = unsafe { bucket0.as_mut() };
|
||||||
|
|
||||||
let ptr = bucket0.allocate().unwrap();
|
let ptr = bucket0.allocate().unwrap();
|
||||||
|
@ -3,7 +3,7 @@ use core::{
|
|||||||
ptr::{null_mut, NonNull},
|
ptr::{null_mut, NonNull},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{allocator::BucketAllocator, util::Spinlock};
|
use crate::{allocator::BucketAllocator, sys::OsPageProvider, util::Spinlock};
|
||||||
|
|
||||||
pub struct GlobalAllocator;
|
pub struct GlobalAllocator;
|
||||||
|
|
||||||
@ -37,4 +37,5 @@ unsafe impl Allocator for GlobalAllocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLOBAL_ALLOCATOR: Spinlock<BucketAllocator> = Spinlock::new(BucketAllocator::new());
|
static GLOBAL_ALLOCATOR: Spinlock<BucketAllocator<OsPageProvider>> =
|
||||||
|
Spinlock::new(BucketAllocator::new());
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
allocator_api
|
allocator_api
|
||||||
)]
|
)]
|
||||||
#![cfg_attr(not(test), no_std)]
|
#![cfg_attr(not(test), no_std)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features, unexpected_cfgs)]
|
||||||
#![deny(fuzzy_provenance_casts, lossy_provenance_casts)]
|
#![deny(fuzzy_provenance_casts, lossy_provenance_casts)]
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -16,5 +16,8 @@ extern crate test;
|
|||||||
|
|
||||||
pub mod allocator;
|
pub mod allocator;
|
||||||
mod bucket;
|
mod bucket;
|
||||||
pub mod global;
|
pub mod sys;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "global", rust_analyzer))]
|
||||||
|
pub mod global;
|
||||||
|
57
lib/libyalloc/src/sys.rs
Normal file
57
lib/libyalloc/src/sys.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
use core::ptr::NonNull;
|
||||||
|
|
||||||
|
pub const PAGE_SIZE: usize = 0x1000;
|
||||||
|
|
||||||
|
pub trait PageProvider {
|
||||||
|
fn map_pages(count: usize) -> Option<NonNull<u8>>;
|
||||||
|
fn unmap_pages(address: NonNull<u8>, count: usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "dep-of-kernel"))]
|
||||||
|
pub struct OsPageProvider;
|
||||||
|
|
||||||
|
#[cfg(any(all(unix, not(feature = "dep-of-kernel")), rust_analyzer))]
|
||||||
|
impl PageProvider for OsPageProvider {
|
||||||
|
fn map_pages(count: usize) -> Option<NonNull<u8>> {
|
||||||
|
use core::ptr::null_mut;
|
||||||
|
|
||||||
|
let address = unsafe {
|
||||||
|
libc::mmap(
|
||||||
|
null_mut(),
|
||||||
|
count * PAGE_SIZE,
|
||||||
|
libc::PROT_READ | libc::PROT_WRITE,
|
||||||
|
libc::MAP_ANONYMOUS | libc::MAP_PRIVATE,
|
||||||
|
-1,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
NonNull::new(address as *mut u8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unmap_pages(address: NonNull<u8>, count: usize) {
|
||||||
|
unsafe {
|
||||||
|
libc::munmap(address.as_ptr() as _, count * PAGE_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(all(not(unix), not(feature = "dep-of-kernel")), rust_analyzer))]
|
||||||
|
impl PageProvider for OsPageProvider {
|
||||||
|
fn map_pages(count: usize) -> Option<NonNull<u8>> {
|
||||||
|
use yggdrasil_rt::mem::MappingSource;
|
||||||
|
|
||||||
|
let address = unsafe {
|
||||||
|
yggdrasil_rt::sys::map_memory(None, count * PAGE_SIZE, &MappingSource::Anonymous)
|
||||||
|
}
|
||||||
|
.ok()?;
|
||||||
|
|
||||||
|
NonNull::new(core::ptr::from_exposed_addr_mut(address))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unmap_pages(address: NonNull<u8>, count: usize) {
|
||||||
|
unsafe {
|
||||||
|
yggdrasil_rt::sys::unmap_memory(address.addr().into(), count * PAGE_SIZE).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,12 @@
|
|||||||
|
use core::ptr::NonNull;
|
||||||
|
|
||||||
|
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
|
||||||
use core::{
|
use core::{
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
ptr::NonNull,
|
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const PAGE_SIZE: usize = 0x1000;
|
|
||||||
|
|
||||||
pub enum Assert<const T: bool> {}
|
pub enum Assert<const T: bool> {}
|
||||||
pub trait IsTrue {}
|
pub trait IsTrue {}
|
||||||
impl IsTrue for Assert<true> {}
|
impl IsTrue for Assert<true> {}
|
||||||
@ -21,60 +21,18 @@ impl<T> NonNullExt<T> for NonNull<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
|
||||||
pub struct Spinlock<T: ?Sized> {
|
pub struct Spinlock<T: ?Sized> {
|
||||||
state: AtomicBool,
|
state: AtomicBool,
|
||||||
data: UnsafeCell<T>,
|
data: UnsafeCell<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
|
||||||
pub struct SpinlockGuard<'a, T: ?Sized> {
|
pub struct SpinlockGuard<'a, T: ?Sized> {
|
||||||
lock: &'a Spinlock<T>,
|
lock: &'a Spinlock<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_pages(count: usize) -> Option<NonNull<u8>> {
|
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
|
||||||
#[cfg(unix)]
|
|
||||||
{
|
|
||||||
use core::ptr::null_mut;
|
|
||||||
|
|
||||||
let address = unsafe {
|
|
||||||
libc::mmap(
|
|
||||||
null_mut(),
|
|
||||||
count * PAGE_SIZE,
|
|
||||||
libc::PROT_READ | libc::PROT_WRITE,
|
|
||||||
libc::MAP_ANONYMOUS | libc::MAP_PRIVATE,
|
|
||||||
-1,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
NonNull::new(address as *mut u8)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
|
||||||
{
|
|
||||||
use yggdrasil_rt::mem::MappingSource;
|
|
||||||
|
|
||||||
let address = unsafe {
|
|
||||||
yggdrasil_rt::sys::map_memory(None, count * PAGE_SIZE, &MappingSource::Anonymous)
|
|
||||||
}
|
|
||||||
.ok()?;
|
|
||||||
|
|
||||||
NonNull::new(core::ptr::from_exposed_addr_mut(address))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unmap_pages(address: NonNull<u8>, count: usize) {
|
|
||||||
#[cfg(unix)]
|
|
||||||
unsafe {
|
|
||||||
libc::munmap(address.as_ptr() as _, count * PAGE_SIZE);
|
|
||||||
}
|
|
||||||
#[cfg(not(unix))]
|
|
||||||
{
|
|
||||||
unsafe {
|
|
||||||
yggdrasil_rt::sys::unmap_memory(address.addr().into(), count * PAGE_SIZE).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ?Sized> Spinlock<T> {
|
impl<T: ?Sized> Spinlock<T> {
|
||||||
pub const fn new(value: T) -> Self
|
pub const fn new(value: T) -> Self
|
||||||
where
|
where
|
||||||
@ -100,6 +58,7 @@ impl<T: ?Sized> Spinlock<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
|
||||||
impl<'a, T: ?Sized> Deref for SpinlockGuard<'a, T> {
|
impl<'a, T: ?Sized> Deref for SpinlockGuard<'a, T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
@ -108,16 +67,19 @@ impl<'a, T: ?Sized> Deref for SpinlockGuard<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
|
||||||
impl<'a, T: ?Sized> DerefMut for SpinlockGuard<'a, T> {
|
impl<'a, T: ?Sized> DerefMut for SpinlockGuard<'a, T> {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
unsafe { &mut *self.lock.data.get() }
|
unsafe { &mut *self.lock.data.get() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
|
||||||
impl<'a, T: ?Sized> Drop for SpinlockGuard<'a, T> {
|
impl<'a, T: ?Sized> Drop for SpinlockGuard<'a, T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.lock.state.store(false, Ordering::Release);
|
self.lock.state.store(false, Ordering::Release);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
|
||||||
unsafe impl<T: ?Sized> Sync for Spinlock<T> {}
|
unsafe impl<T: ?Sized> Sync for Spinlock<T> {}
|
||||||
|
@ -57,7 +57,7 @@ fn build_uefi_image(
|
|||||||
"if=/dev/zero",
|
"if=/dev/zero",
|
||||||
&format!("of={}", image_path.display()),
|
&format!("of={}", image_path.display()),
|
||||||
"bs=1M",
|
"bs=1M",
|
||||||
"count=256",
|
"count=512",
|
||||||
],
|
],
|
||||||
false,
|
false,
|
||||||
)?;
|
)?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user