github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/dma/dma.go (about) 1 // First-fit memory allocator for DMA buffers 2 // https://github.com/usbarmory/tamago 3 // 4 // Copyright (c) WithSecure Corporation 5 // https://foundry.withsecure.com 6 // 7 // Use of this source code is governed by the license 8 // that can be found in the LICENSE file. 9 10 // Package dma provides primitives for direct memory allocation and alignment, 11 // it is primarily used in bare metal device driver operation to avoid passing 12 // Go pointers for DMA purposes. 13 // 14 // This package is only meant to be used with `GOOS=tamago` as supported by the 15 // TamaGo framework for bare metal Go on ARM/RISC-V SoCs, see 16 // https://github.com/usbarmory/tamago. 17 package dma 18 19 import ( 20 "fmt" 21 "runtime" 22 ) 23 24 // NewRegion initializes a memory region for DMA buffer allocation. 25 // 26 // To avoid unforseen consequences the caller must ensure that allocated 27 // regions do not overlap among themselves or with the global one (see Init()). 28 // 29 // To allow allocation of DMA buffers within Go runtime memory the unsafe flag 30 // must be set. 31 func NewRegion(addr uint, size int, unsafe bool) (r *Region, err error) { 32 start := uint(addr) 33 end := uint(start) + uint(size) 34 35 // returns uint32/uint64 depending on platform 36 rs, re := runtime.MemRegion() 37 ramStart := uint(rs) 38 ramEnd := uint(re) 39 40 if !unsafe && 41 (ramStart >= start && ramStart < end || 42 ramEnd > start && ramEnd < end || 43 start >= ramStart && end < ramEnd) { 44 return nil, fmt.Errorf("DMA within Go runtime memory (%#x-%#x) is not allowed", ramStart, ramEnd) 45 } 46 47 r = &Region{} 48 r.Init(start, uint(size)) 49 50 return 51 } 52 53 // Init initializes the global memory region for DMA buffer allocation, used 54 // throughout the tamago package for all DMA allocations. 55 // 56 // Additional DMA regions for application use can be allocated through 57 // NewRegion(). 58 func Init(start uint, size int) (err error) { 59 dma, err = NewRegion(start, size, false) 60 return 61 } 62 63 // Reserve is the equivalent of Region.Reserve() on the global DMA region. 64 func Reserve(size int, align int) (addr uint, buf []byte) { 65 return dma.Reserve(size, align) 66 } 67 68 // Reserved is the equivalent of Region.Reserved() on the global DMA region. 69 func Reserved(buf []byte) (res bool, addr uint) { 70 return dma.Reserved(buf) 71 } 72 73 // Alloc is the equivalent of Region.Alloc() on the global DMA region. 74 func Alloc(buf []byte, align int) (addr uint) { 75 return dma.Alloc(buf, align) 76 } 77 78 // Read is the equivalent of Region.Read() on the global DMA region. 79 func Read(addr uint, off int, buf []byte) { 80 dma.Read(addr, off, buf) 81 } 82 83 // Write is the equivalent of Region.Write() on the global DMA region. 84 func Write(addr uint, off int, buf []byte) { 85 dma.Write(addr, off, buf) 86 } 87 88 // Free is the equivalent of Region.Free() on the global DMA region. 89 func Free(addr uint) { 90 dma.Free(addr) 91 } 92 93 // Release is the equivalent of Region.Release() on the global DMA region. 94 func Release(addr uint) { 95 dma.Release(addr) 96 }