Add mm module and move memory alignment functions there

This commit is contained in:
Berkus Decker 2020-10-17 22:29:35 +03:00
parent 4083e955d4
commit 4672ddace6
4 changed files with 58 additions and 53 deletions

View File

@ -3,7 +3,7 @@
* Copyright (c) Berkus Decker <berkus+vesper@metta.systems>
*/
use {
super::{align_down, align_up},
crate::mm::{align_down, align_up},
bit_field::BitField,
core::{
convert::{From, Into, TryInto},

View File

@ -346,55 +346,3 @@ pub fn print_layout() {
println!("{}", i);
}
}
/// Align address downwards.
///
/// Returns the greatest x with alignment `align` so that x <= addr.
/// The alignment must be a power of 2.
pub fn align_down(addr: u64, align: u64) -> u64 {
assert!(align.is_power_of_two(), "`align` must be a power of two");
addr & !(align - 1)
}
/// Align address upwards.
///
/// Returns the smallest x with alignment `align` so that x >= addr.
/// The alignment must be a power of 2.
pub fn align_up(addr: u64, align: u64) -> u64 {
assert!(align.is_power_of_two(), "`align` must be a power of two");
let align_mask = align - 1;
if addr & align_mask == 0 {
addr // already aligned
} else {
(addr | align_mask) + 1
}
}
/// Calculate the next possible aligned address without sanity checking the
/// input parameters.
// #[inline]
// fn aligned_addr_unchecked(addr: usize, alignment: usize) -> usize {
// (addr + (alignment - 1)) & !(alignment - 1)
// }
#[cfg(test)]
mod tests {
use super::*;
#[test_case]
pub fn test_align_up() {
// align 1
assert_eq!(align_up(0, 1), 0);
assert_eq!(align_up(1234, 1), 1234);
assert_eq!(align_up(0xffffffffffffffff, 1), 0xffffffffffffffff);
// align 2
assert_eq!(align_up(0, 2), 0);
assert_eq!(align_up(1233, 2), 1234);
assert_eq!(align_up(0xfffffffffffffffe, 2), 0xfffffffffffffffe);
// address 0
assert_eq!(align_up(0, 128), 0);
assert_eq!(align_up(0, 1), 0);
assert_eq!(align_up(0, 2), 0);
assert_eq!(align_up(0, 0x8000000000000000), 0);
}
}

View File

@ -29,6 +29,7 @@ extern crate rlibc; // To enable linking memory intrinsics.
pub mod arch;
pub use arch::*;
mod macros;
mod mm;
mod platform;
#[cfg(feature = "qemu")]
mod qemu;

56
nucleus/src/mm/mod.rs Normal file
View File

@ -0,0 +1,56 @@
/*
* SPDX-License-Identifier: BlueOak-1.0.0
* Copyright (c) Berkus Decker <berkus+vesper@metta.systems>
*/
/// Align address downwards.
///
/// Returns the greatest x with alignment `align` so that x <= addr.
/// The alignment must be a power of 2.
pub fn align_down(addr: u64, align: u64) -> u64 {
assert!(align.is_power_of_two(), "`align` must be a power of two");
addr & !(align - 1)
}
/// Align address upwards.
///
/// Returns the smallest x with alignment `align` so that x >= addr.
/// The alignment must be a power of 2.
pub fn align_up(addr: u64, align: u64) -> u64 {
assert!(align.is_power_of_two(), "`align` must be a power of two");
let align_mask = align - 1;
if addr & align_mask == 0 {
addr // already aligned
} else {
(addr | align_mask) + 1
}
}
/// Calculate the next possible aligned address without sanity checking the
/// input parameters.
#[inline]
fn aligned_addr_unchecked(addr: usize, alignment: usize) -> usize {
(addr + (alignment - 1)) & !(alignment - 1)
}
#[cfg(test)]
mod tests {
use super::*;
#[test_case]
pub fn test_align_up() {
// align 1
assert_eq!(align_up(0, 1), 0);
assert_eq!(align_up(1234, 1), 1234);
assert_eq!(align_up(0xffffffffffffffff, 1), 0xffffffffffffffff);
// align 2
assert_eq!(align_up(0, 2), 0);
assert_eq!(align_up(1233, 2), 1234);
assert_eq!(align_up(0xfffffffffffffffe, 2), 0xfffffffffffffffe);
// address 0
assert_eq!(align_up(0, 128), 0);
assert_eq!(align_up(0, 1), 0);
assert_eq!(align_up(0, 2), 0);
assert_eq!(align_up(0, 0x8000000000000000), 0);
}
}