98 lines
3.1 KiB
Zig
98 lines
3.1 KiB
Zig
//! Platform-independent memory management functions.
|
|
|
|
const std = @import("std");
|
|
|
|
pub const vmm = @import("mem/vmm.zig");
|
|
pub const phys = @import("mem/phys.zig");
|
|
|
|
pub const TranslationLevel = vmm.TranslationLevel;
|
|
|
|
/// A representation for physical address.
|
|
pub const PhysicalAddress = packed struct(u64) {
|
|
raw: u64,
|
|
|
|
/// NULL/zero physical address constant.
|
|
pub const NULL: @This() = .{ .raw = 0 };
|
|
|
|
/// Base address to add to a given `PhysicalAddress` in order to "virtualize" it.
|
|
pub var g_virtualize_base: usize = 0;
|
|
/// Maximum `PhysicalAddress` that can be represented as a virtual address.
|
|
pub var g_virtualize_size: usize = 0;
|
|
|
|
/// Adds an `offset` to this `PhysicalAddress`
|
|
pub fn add(self: @This(), offset: usize) @This() {
|
|
return .{ .raw = self.raw + @as(u64, @intCast(offset)) };
|
|
}
|
|
|
|
/// "Virtualizes" a `PhysicalAddress` by turning it into a virtual address representation of
|
|
/// the memory pointed to by this physical address.
|
|
///
|
|
/// # Panics
|
|
///
|
|
/// Panics if the physical address points to a memory that cannot be represented by a virtual
|
|
/// address.
|
|
pub fn virtualize(self: @This()) usize {
|
|
if (self.raw > g_virtualize_size) {
|
|
@panic("Physical address out of virtualize bounds");
|
|
}
|
|
|
|
return self.raw + g_virtualize_base;
|
|
}
|
|
|
|
/// "De-virtualizes" a previously "virtualized" physical address by mapping it back into its
|
|
/// physical form.
|
|
///
|
|
/// # Panics
|
|
///
|
|
/// Panics if the virtual address provided is outside of virtualizable memory range.
|
|
pub fn from_virtualized(virt: usize) @This() {
|
|
if ((virt < g_virtualize_base) || (virt - g_virtualize_base > g_virtualize_size)) {
|
|
@panic("Invalid virtualized physical address");
|
|
}
|
|
|
|
return .{ .raw = virt - g_virtualize_base };
|
|
}
|
|
};
|
|
|
|
/// Helper function to format a byte quantity into a human-readable size.
|
|
/// Writes its result to the `buffer` provided and returns a pointer to it.
|
|
pub fn format_size(buffer: []u8, size: u64) []const u8 {
|
|
const KIBI: u64 = 1024;
|
|
const MIBI: u64 = KIBI * 1024;
|
|
const GIBI: u64 = MIBI * 1024;
|
|
|
|
const log2: u64 = std.math.log2_int(u64, size);
|
|
const opts: struct { u64, []const u8 } = switch (log2) {
|
|
0...9 => .{ 1, "B" },
|
|
10...19 => .{ KIBI, " KiB" },
|
|
20...29 => .{ MIBI, " MiB" },
|
|
else => .{ GIBI, " GiB" },
|
|
};
|
|
const div: u64 = opts[0];
|
|
const suffix: []const u8 = opts[1];
|
|
const integer = size / div;
|
|
const dot = size >= 1024;
|
|
|
|
const ilen = std.fmt.formatIntBuf(buffer, integer, 10, .lower, .{});
|
|
var len = ilen;
|
|
var flen: usize = 0;
|
|
|
|
if (dot and integer < 100) {
|
|
const fractional = (((size * 1000) / div) % 1000) / 10;
|
|
|
|
if (ilen < buffer.len + 1) {
|
|
buffer[ilen] = '.';
|
|
flen = 1 + std.fmt.formatIntBuf(buffer[ilen + 1 ..], fractional, 10, .lower, .{ .fill = '0', .width = 2 });
|
|
}
|
|
}
|
|
|
|
len += flen;
|
|
|
|
if (len + suffix.len < buffer.len) {
|
|
std.mem.copyForwards(u8, buffer[len..], suffix);
|
|
len += suffix.len;
|
|
}
|
|
|
|
return buffer[0..len];
|
|
}
|