pt.zig (4259B)
1 const std = @import("std"); 2 3 const procmap = @import("./procmap.zig"); 4 const pinned = @import("./pinned.zig"); 5 const mmu = @import("./mmu.zig"); 6 const mem = @import("./mem.zig"); 7 8 pub const Error = error{ 9 InvalidPageCount, 10 MmuEnabled, 11 MmuDisabled, 12 } || std.mem.Allocator.Error; 13 14 pub const fault_page: mmu.FirstLevelDescriptor = .{ .ty = .Fault, .descriptor = .{ .fault = .{} } }; 15 16 pub fn init(alloc: std.mem.Allocator, count: u16) Error![]mmu.FirstLevelDescriptor { 17 if (count != 4096) return Error.InvalidPageCount; 18 19 const page_table = try alloc.alignedAlloc( 20 mmu.FirstLevelDescriptor, 21 std.mem.Alignment.fromByteUnits(1 << 5), 22 count, 23 ); 24 25 @memset(page_table, fault_page); 26 mmu.sync_pte(); 27 28 return page_table; 29 } 30 31 pub fn dupe(alloc: std.mem.Allocator, pt: []mmu.FirstLevelDescriptor) Error![]mmu.FirstLevelDescriptor { 32 const page_table = try alloc.alignedAlloc( 33 mmu.FirstLevelDescriptor, 34 std.mem.Alignment.fromByteUnits(1 << 5), 35 pt.len, 36 ); 37 @memcpy(page_table, pt); 38 mmu.sync_pte(); 39 40 return page_table; 41 } 42 43 pub fn pt_switch(pt: []mmu.FirstLevelDescriptor, pid: u24, asid: u8) Error!void { 44 mmu.set_context_ttbr0(.{ .asid = asid, .pid = pid }, .{ 45 .translation_table_base = @truncate(@intFromPtr(pt.ptr) >> 5), 46 }); 47 } 48 49 pub fn set(pt: []mmu.FirstLevelDescriptor, va: u32, pa: u32, attr: pinned.PinnedAttribute) Error!*mmu.FirstLevelDescriptor { 50 const index = va >> 20; 51 52 const mem_attr: mmu.LockdownAttributesRegister.PageTableEncodingManual = @bitCast(@intFromEnum(attr.mem_attributes)); 53 54 pt[index] = .{ 55 .ty = .Section, 56 .descriptor = .{ 57 .section = .{ 58 .not_global = if (attr.scope == .Global) false else true, 59 .ap = attr.permission, 60 .apx = @enumFromInt(0), 61 .domain = attr.domain, 62 .never_execute = false, 63 .b = mem_attr.b, 64 .c = mem_attr.c, 65 .tex = mem_attr.tex, 66 .shared = false, 67 // Get top 12 bits of PA 68 .section_base_address = @truncate(pa >> 20), 69 }, 70 }, 71 }; 72 73 mmu.sync_pte(); 74 75 return &pt[index]; 76 } 77 78 pub fn remove(pt: []mmu.FirstLevelDescriptor, va: u32) !void { 79 const index = va >> 20; 80 81 pt[index].ty = .Fault; 82 83 mmu.sync_pte(); 84 } 85 86 pub fn get(pt: []mmu.FirstLevelDescriptor, va: u32) !?*mmu.FirstLevelDescriptor { 87 const index = va >> 20; 88 const page = &pt[index]; 89 90 if (page.ty == .Fault) return null; 91 92 return page; 93 } 94 95 pub fn translate(pt: []mmu.FirstLevelDescriptor, va: u32) ?u32 { 96 const index = va >> 20; 97 const page = pt[index]; 98 99 // Not dealing with with coarse/fault 100 if (page.ty != .Section) return null; 101 const section = page.descriptor.section; 102 // Not dealing with super sections 103 if (section.is_supersection) return null; 104 105 // Top 12 bits of address 106 const base = @as(u32, section.section_base_address) << 20; 107 108 // Probably correct 109 return base | (va & 0x000F_FFFF); 110 } 111 112 pub fn check_entry(va: u32) void { 113 const index = va >> 20; 114 115 const ttbr0 = mmu.TranslationTableBaseRegister0.get(); 116 const ttb: [*]mmu.FirstLevelDescriptor = @ptrFromInt(@as(u32, ttbr0.translation_table_base) << 5); 117 118 const entry = ttb[index].descriptor.section; 119 @import("devices/mini-uart.zig").print( 120 \\index = {} 121 \\va = 0x{X} 122 \\pa = 0b{b} / 0x{X} 123 \\0b{b} = nG 124 \\0b{b} = S 125 \\0b{b} = APX 126 \\0b{b} = TEX 127 \\0b{b} = AP 128 \\0b{b} = IMP 129 \\0b{b} = domain 130 \\0b{b} = XN 131 \\0b{b} = C 132 \\0b{b} = B 133 \\0b{b} = tag 134 \\ 135 \\ 136 , .{ 137 index, 138 va, 139 entry.section_base_address, 140 entry.section_base_address, 141 if (entry.not_global) @as(u1, 1) else @as(u1, 0), 142 if (entry.shared) @as(u1, 1) else @as(u1, 0), 143 @intFromEnum(entry.apx), 144 entry.tex, 145 @intFromEnum(entry.ap), 146 entry._implementation_9, 147 entry.domain, 148 if (entry.never_execute) @as(u1, 1) else @as(u1, 0), 149 entry.c, 150 entry.b, 151 @intFromEnum(ttb[index].ty), 152 }); 153 }