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  }