github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/internal/reg/reg32.go (about)

     1  // https://github.com/f-secure-foundry/tamago
     2  //
     3  // Copyright (c) F-Secure Corporation
     4  // https://foundry.f-secure.com
     5  //
     6  // Use of this source code is governed by the license
     7  // that can be found in the LICENSE file.
     8  
     9  // Package reg provides primitives for retrieving and modifying hardware
    10  // registers.
    11  //
    12  // This package is only meant to be used with `GOOS=tamago GOARCH=arm` as
    13  // supported by the TamaGo framework for bare metal Go on ARM SoCs, see
    14  // https://github.com/f-secure-foundry/tamago.
    15  package reg
    16  
    17  import (
    18  	"runtime"
    19  	"sync/atomic"
    20  	"time"
    21  	"unsafe"
    22  )
    23  
    24  func Get(addr uint32, pos int, mask int) uint32 {
    25  	reg := (*uint32)(unsafe.Pointer(uintptr(addr)))
    26  	r := atomic.LoadUint32(reg)
    27  
    28  	return uint32((int(r) >> pos) & mask)
    29  }
    30  
    31  func Set(addr uint32, pos int) {
    32  	reg := (*uint32)(unsafe.Pointer(uintptr(addr)))
    33  
    34  	r := atomic.LoadUint32(reg)
    35  	r |= (1 << pos)
    36  
    37  	atomic.StoreUint32(reg, r)
    38  }
    39  
    40  func Clear(addr uint32, pos int) {
    41  	reg := (*uint32)(unsafe.Pointer(uintptr(addr)))
    42  
    43  	r := atomic.LoadUint32(reg)
    44  	r &= ^(1 << pos)
    45  
    46  	atomic.StoreUint32(reg, r)
    47  }
    48  
    49  func SetN(addr uint32, pos int, mask int, val uint32) {
    50  	reg := (*uint32)(unsafe.Pointer(uintptr(addr)))
    51  
    52  	r := atomic.LoadUint32(reg)
    53  	r = (r & (^(uint32(mask) << pos))) | (val << pos)
    54  
    55  	atomic.StoreUint32(reg, r)
    56  }
    57  
    58  func ClearN(addr uint32, pos int, mask int) {
    59  	reg := (*uint32)(unsafe.Pointer(uintptr(addr)))
    60  
    61  	r := atomic.LoadUint32(reg)
    62  	r &= ^(uint32(mask) << pos)
    63  
    64  	atomic.StoreUint32(reg, r)
    65  }
    66  
    67  // defined in reg32.s
    68  func Move(dst uint32, src uint32)
    69  
    70  func Read(addr uint32) uint32 {
    71  	reg := (*uint32)(unsafe.Pointer(uintptr(addr)))
    72  	return atomic.LoadUint32(reg)
    73  }
    74  
    75  func Write(addr uint32, val uint32) {
    76  	reg := (*uint32)(unsafe.Pointer(uintptr(addr)))
    77  	atomic.StoreUint32(reg, val)
    78  }
    79  
    80  func WriteBack(addr uint32) {
    81  	reg := (*uint32)(unsafe.Pointer(uintptr(addr)))
    82  
    83  	r := atomic.LoadUint32(reg)
    84  	r |= r
    85  
    86  	atomic.StoreUint32(reg, r)
    87  }
    88  
    89  func Or(addr uint32, val uint32) {
    90  	reg := (*uint32)(unsafe.Pointer(uintptr(addr)))
    91  
    92  	r := atomic.LoadUint32(reg)
    93  	r |= val
    94  
    95  	atomic.StoreUint32(reg, r)
    96  }
    97  
    98  // Wait waits for a specific register bit to match a value. This function
    99  // cannot be used before runtime initialization with `GOOS=tamago`.
   100  func Wait(addr uint32, pos int, mask int, val uint32) {
   101  	for Get(addr, pos, mask) != val {
   102  		// tamago is single-threaded, give other goroutines a chance
   103  		runtime.Gosched()
   104  	}
   105  }
   106  
   107  // WaitFor waits, until a timeout expires, for a specific register bit to match
   108  // a value. The return boolean indicates whether the wait condition was checked
   109  // (true) or if it timed out (false). This function cannot be used before
   110  // runtime initialization.
   111  func WaitFor(timeout time.Duration, addr uint32, pos int, mask int, val uint32) bool {
   112  	start := time.Now()
   113  
   114  	for Get(addr, pos, mask) != val {
   115  		// tamago is single-threaded, give other goroutines a chance
   116  		runtime.Gosched()
   117  
   118  		if time.Since(start) >= timeout {
   119  			return false
   120  		}
   121  	}
   122  
   123  	return true
   124  }
   125  
   126  // WaitSignal waits, until a channel is closed, for a specific register bit to
   127  // match a value. The return boolean indicates whether the wait condition was
   128  // checked (true) or cancelled (false). This function cannot be used before
   129  // runtime initialization.
   130  func WaitSignal(done chan bool, addr uint32, pos int, mask int, val uint32) bool {
   131  	for Get(addr, pos, mask) != val {
   132  		// tamago is single-threaded, give other goroutines a chance
   133  		runtime.Gosched()
   134  
   135  		select {
   136  		case <-done:
   137  			return false
   138  		default:
   139  		}
   140  	}
   141  
   142  	return true
   143  }