sylveos

Toy Operating System
Log | Files | Refs

mem.zig (2560B)


      1 pub const BASE_ADDRESS: usize = 0x2000_0000;
      2 
      3 // Forces all outstanding explicit memory transactions to complete before executing
      4 // another **instruction**. Other instructions can execute out of order
      5 inline fn dsb() void {
      6     asm volatile ("mcr p15, 0, %[reg], c7, c10, 4"
      7         :
      8         : [reg] "r" (0),
      9     );
     10 }
     11 // Forces all outstanding explicit memory transactions to complete before executing
     12 // another **memory transaction**. No instruction can execute until this is complete
     13 inline fn dmb() void {
     14     asm volatile ("mcr p15, 0, %[reg], c7, c10, 5"
     15         :
     16         : [reg] "r" (0),
     17     );
     18 }
     19 // Flush Prefetch Buffer
     20 inline fn imb() void {
     21     asm volatile ("mcr p15, 0, %[reg], c7, c5, 4"
     22         :
     23         : [reg] "r" (0),
     24     );
     25 }
     26 
     27 // Prevents the compiler reordering statements
     28 inline fn compiler_barrier() void {
     29     asm volatile ("" ::: .{ .memory = true });
     30 }
     31 
     32 const BarrierKind = enum {
     33     Strict,
     34     Weak,
     35 };
     36 
     37 const Operation = enum {
     38     Read,
     39     Write,
     40     Instruction,
     41     Compiler,
     42 };
     43 
     44 pub inline fn barrier(comptime op: Operation) void {
     45     switch (op) {
     46         .Write => dsb(),
     47         .Read => dmb(),
     48         .Instruction => imb(),
     49         .Compiler => compiler_barrier(),
     50     }
     51 }
     52 
     53 pub inline fn put_u32(address: *allowzero u32, value: u32) void {
     54     asm volatile ("str %[value], [%[address]]"
     55         :
     56         : [value] "r" (value),
     57           [address] "r" (address),
     58     );
     59 }
     60 
     61 pub inline fn put_u32_barrier(
     62     address: *allowzero u32,
     63     value: u32,
     64 ) void {
     65     put_u32(address, value);
     66     barrier(.Write);
     67 }
     68 
     69 pub inline fn get_u32(address: *allowzero u32) u32 {
     70     return asm volatile ("ldr %[result], [%[address]]"
     71         : [result] "=r" (-> u32),
     72         : [address] "r" (address),
     73     );
     74 }
     75 
     76 pub inline fn get_u32_barrier(address: *allowzero u32) u32 {
     77     barrier(.Read);
     78     return get_u32(address);
     79 }
     80 
     81 pub const CriticalSection = struct {
     82     const Self = @This();
     83 
     84     saved_cpsr: u32,
     85 
     86     // TODO; barrier?
     87     pub inline fn enter() Self {
     88         var cpsr: u32 = undefined;
     89 
     90         asm volatile (
     91             \\ mrs %[cpsr], cpsr
     92             \\ cpsid i
     93             : [cpsr] "=r" (cpsr),
     94             :
     95             : .{ .memory = true });
     96 
     97         return .{ .saved_cpsr = cpsr };
     98     }
     99 
    100     pub inline fn exit(self: Self) void {
    101         asm volatile (
    102             \\ msr cpsr_c, %[cpsr]
    103             :
    104             : [cpsr] "r" (self.saved_cpsr),
    105             : .{
    106               .cpsr = true,
    107               .memory = true,
    108             });
    109     }
    110 };
    111 
    112 pub const enter_critical_section = CriticalSection.enter;