2019-11-02 01:22:10 +00:00
const std = @import ( " std " ) ;
const expectEqual = std . testing . expectEqual ;
2019-11-02 02:00:49 +00:00
const log = @import ( " log.zig " ) ;
2019-05-23 17:50:37 +01:00
2020-05-14 17:34:50 +01:00
pub const Module = struct {
/// The region of memory occupied by the module
region : Range ,
/// The module's name
name : [ ] const u8 ,
} ;
pub const Map = struct {
/// The virtual range to reserve
virtual : Range ,
/// The physical range to map to, if any
physical : ? Range ,
} ;
/// A range of memory
pub const Range = struct {
/// The start of the range, inclusive
start : usize ,
/// The end of the range, exclusive
end : usize ,
} ;
2019-05-23 17:50:37 +01:00
pub const MemProfile = struct {
2019-09-09 23:38:06 +01:00
/// The virtual end address of the kernel code.
2019-05-23 17:50:37 +01:00
vaddr_end : [ * ] u8 ,
2019-09-09 23:38:06 +01:00
/// The virtual end address of the kernel code.
2019-05-23 17:50:37 +01:00
vaddr_start : [ * ] u8 ,
2019-09-09 23:38:06 +01:00
/// The physical end address of the kernel code.
2019-05-23 17:50:37 +01:00
physaddr_end : [ * ] u8 ,
2019-09-09 23:38:06 +01:00
/// The physical start address of the kernel code.
2019-05-23 17:50:37 +01:00
physaddr_start : [ * ] u8 ,
2019-09-09 23:38:06 +01:00
/// The amount of memory in the system, in kilobytes.
2020-05-12 14:08:29 +01:00
mem_kb : usize ,
2019-09-09 23:38:06 +01:00
2020-05-14 17:34:50 +01:00
/// The modules loaded into memory at boot.
modules : [ ] Module ,
2019-11-02 01:22:10 +00:00
2020-05-14 17:34:50 +01:00
/// The virtual regions of reserved memory. Should not include what is tracked by the vaddr_* fields but should include the regions occupied by the modules. These are reserved and mapped by the VMM
virtual_reserved : [ ] Map ,
2019-11-02 01:22:10 +00:00
2020-05-14 17:34:50 +01:00
/// The phsyical regions of reserved memory. Should not include what is tracked by the physaddr_* fields but should include the regions occupied by the modules. These are reserved by the PMM
physical_reserved : [ ] Range ,
2019-11-02 01:22:10 +00:00
2020-05-14 17:34:50 +01:00
/// The allocator to use before a heap can be set up.
fixed_allocator : std . heap . FixedBufferAllocator ,
} ;
2019-11-02 01:22:10 +00:00
/// The size of the fixed allocator used before the heap is set up. Set to 1MiB.
2020-05-14 17:34:50 +01:00
pub const FIXED_ALLOC_SIZE : usize = 1024 * 1024 ;
2019-05-23 17:50:37 +01:00
2019-11-02 01:22:10 +00:00
/// The kernel's virtual address offset. It's assigned in the init function and this file's tests.
/// We can't just use KERNEL_ADDR_OFFSET since using externs in the virtToPhys test is broken in
/// release-safe. This is a workaround until that is fixed.
2020-05-14 17:34:50 +01:00
pub var ADDR_OFFSET : usize = undefined ;
2019-11-02 01:22:10 +00:00
///
/// Convert a virtual address to its physical counterpart by subtracting the kernel virtual offset from the virtual address.
///
/// Arguments:
/// IN virt: var - The virtual address to covert. Either an integer or pointer.
///
2020-01-01 19:12:36 +00:00
/// Return: @TypeOf(virt)
2019-11-02 01:22:10 +00:00
/// The physical address.
///
2020-01-09 16:16:51 +00:00
pub fn virtToPhys ( virt : var ) @TypeOf ( virt ) {
2020-01-01 19:12:36 +00:00
const T = @TypeOf ( virt ) ;
2020-04-12 22:26:34 +01:00
return switch ( @typeInfo ( T ) ) {
2019-11-02 01:22:10 +00:00
. Pointer = > @intToPtr ( T , @ptrToInt ( virt ) - ADDR_OFFSET ) ,
. Int = > virt - ADDR_OFFSET ,
else = > @compileError ( " Only pointers and integers are supported " ) ,
} ;
}
///
/// Convert a physical address to its virtual counterpart by adding the kernel virtual offset to the physical address.
///
/// Arguments:
/// IN phys: var - The physical address to covert. Either an integer or pointer.
///
2020-01-01 19:12:36 +00:00
/// Return: @TypeOf(virt)
2019-11-02 01:22:10 +00:00
/// The virtual address.
///
2020-01-09 16:16:51 +00:00
pub fn physToVirt ( phys : var ) @TypeOf ( phys ) {
2020-01-01 19:12:36 +00:00
const T = @TypeOf ( phys ) ;
2020-04-12 22:26:34 +01:00
return switch ( @typeInfo ( T ) ) {
2019-11-02 01:22:10 +00:00
. Pointer = > @intToPtr ( T , @ptrToInt ( phys ) + ADDR_OFFSET ) ,
. Int = > phys + ADDR_OFFSET ,
else = > @compileError ( " Only pointers and integers are supported " ) ,
} ;
}
test " physToVirt " {
ADDR_OFFSET = 0xC0000000 ;
const offset : usize = ADDR_OFFSET ;
2019-11-10 12:35:08 +00:00
expectEqual ( physToVirt ( @as ( usize , 0 ) ) , offset + 0 ) ;
expectEqual ( physToVirt ( @as ( usize , 123 ) ) , offset + 123 ) ;
2020-01-01 19:12:36 +00:00
expectEqual ( @ptrToInt ( physToVirt ( @intToPtr ( * align ( 1 ) usize , 123 ) ) ) , offset + 123 ) ;
2019-11-02 01:22:10 +00:00
}
test " virtToPhys " {
ADDR_OFFSET = 0xC0000000 ;
const offset : usize = ADDR_OFFSET ;
expectEqual ( virtToPhys ( offset + 0 ) , 0 ) ;
expectEqual ( virtToPhys ( offset + 123 ) , 123 ) ;
2020-01-01 19:12:36 +00:00
expectEqual ( @ptrToInt ( virtToPhys ( @intToPtr ( * align ( 1 ) usize , offset + 123 ) ) ) , 123 ) ;
2019-11-02 01:22:10 +00:00
}