github.com/eh-steve/goloader@v0.0.0-20240111193454-90ff3cfdae39/mmap/mmap_linux_arm64.go (about) 1 //go:build linux && arm64 2 // +build linux,arm64 3 4 package mmap 5 6 import ( 7 "os" 8 "syscall" 9 ) 10 11 func clearInstructionCacheLine(addr uintptr) 12 13 func clearDataCacheLine(addr uintptr) 14 15 func read_CTR_ELO_Register() (regval uint32) 16 17 func dataSyncBarrierInnerShareableDomain() 18 19 func instructionSyncBarrier() 20 21 const CTR_IDC_BIT = 28 22 const CTR_DIC_BIT = 29 23 24 var cacheInfo uint32 // Copy of cache type register contents 25 26 var iCacheLineSize uint32 27 var dCacheLineSize uint32 28 29 func alignAddress(addr, alignment uintptr) uintptr { 30 return addr &^ (alignment - 1) 31 } 32 33 // Inspired by gcc's __aarch64_sync_cache_range() 34 func aarch64SyncInstructionCacheRange(start uintptr, end uintptr) { 35 if cacheInfo == 0 { 36 cacheInfo = read_CTR_ELO_Register() 37 } 38 iCacheLineSize = 4 << (cacheInfo & 0xF) 39 dCacheLineSize = 4 << ((cacheInfo >> 16) & 0xF) 40 41 if (cacheInfo & (CTR_IDC_BIT << 0x1)) == 0 { 42 start = alignAddress(start, uintptr(dCacheLineSize)) 43 for addr := start; addr < end; addr += uintptr(dCacheLineSize) { 44 clearDataCacheLine(addr) 45 } 46 } 47 dataSyncBarrierInnerShareableDomain() 48 49 if (cacheInfo & (CTR_DIC_BIT << 0x1)) == 0 { 50 start = alignAddress(start, uintptr(iCacheLineSize)) 51 for addr := start; addr < end; addr += uintptr(iCacheLineSize) { 52 clearInstructionCacheLine(addr) 53 } 54 } 55 dataSyncBarrierInnerShareableDomain() 56 instructionSyncBarrier() 57 } 58 59 func MakeThreadJITCodeExecutable(ptr uintptr, len int) { 60 aarch64SyncInstructionCacheRange(ptr, ptr+uintptr(len)) 61 } 62 63 func Mmap(size int) ([]byte, error) { 64 return AcquireMapping(size, mmapCode) 65 } 66 67 func MmapData(size int) ([]byte, error) { 68 return AcquireMapping(size, mmapData) 69 } 70 71 func mmapCode(size int, addr uintptr) ([]byte, error) { 72 fixed := 0 73 if addr != 0 { 74 fixed = syscall.MAP_FIXED 75 } 76 data, err := mapper.Mmap( 77 addr, 78 0, 79 0, 80 size, 81 syscall.PROT_READ|syscall.PROT_WRITE|syscall.PROT_EXEC, 82 syscall.MAP_PRIVATE|syscall.MAP_ANON|fixed) 83 if err != nil { 84 err = os.NewSyscallError("syscall.Mmap", err) 85 } 86 return data, err 87 } 88 89 func mmapData(size int, addr uintptr) ([]byte, error) { 90 fixed := 0 91 if addr != 0 { 92 fixed = syscall.MAP_FIXED 93 } 94 data, err := mapper.Mmap( 95 addr, 96 0, 97 0, 98 size, 99 syscall.PROT_READ|syscall.PROT_WRITE, 100 syscall.MAP_PRIVATE|syscall.MAP_ANON|fixed) 101 if err != nil { 102 err = os.NewSyscallError("syscall.Mmap", err) 103 } 104 return data, err 105 } 106 107 func Munmap(b []byte) (err error) { 108 err = mapper.Munmap(b) 109 if err != nil { 110 err = os.NewSyscallError("syscall.Munmap", err) 111 } 112 return 113 }