sylveos

Toy Operating System
Log | Files | Refs

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 }