//! 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]; }