github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/asm/load_store.go (about)

     1  package asm
     2  
     3  //go:generate go run golang.org/x/tools/cmd/stringer@latest -output load_store_string.go -type=Mode,Size
     4  
     5  // Mode for load and store operations
     6  //
     7  //	msb      lsb
     8  //	+---+--+---+
     9  //	|MDE|sz|cls|
    10  //	+---+--+---+
    11  type Mode uint8
    12  
    13  const modeMask OpCode = 0xe0
    14  
    15  const (
    16  	// InvalidMode is returned by getters when invoked
    17  	// on non load / store OpCodes
    18  	InvalidMode Mode = 0xff
    19  	// ImmMode - immediate value
    20  	ImmMode Mode = 0x00
    21  	// AbsMode - immediate value + offset
    22  	AbsMode Mode = 0x20
    23  	// IndMode - indirect (imm+src)
    24  	IndMode Mode = 0x40
    25  	// MemMode - load from memory
    26  	MemMode Mode = 0x60
    27  	// MemSXMode - load from memory, sign extension
    28  	MemSXMode Mode = 0x80
    29  	// XAddMode - add atomically across processors.
    30  	XAddMode Mode = 0xc0
    31  )
    32  
    33  // Size of load and store operations
    34  //
    35  //	msb      lsb
    36  //	+---+--+---+
    37  //	|mde|SZ|cls|
    38  //	+---+--+---+
    39  type Size uint8
    40  
    41  const sizeMask OpCode = 0x18
    42  
    43  const (
    44  	// InvalidSize is returned by getters when invoked
    45  	// on non load / store OpCodes
    46  	InvalidSize Size = 0xff
    47  	// DWord - double word; 64 bits
    48  	DWord Size = 0x18
    49  	// Word - word; 32 bits
    50  	Word Size = 0x00
    51  	// Half - half-word; 16 bits
    52  	Half Size = 0x08
    53  	// Byte - byte; 8 bits
    54  	Byte Size = 0x10
    55  )
    56  
    57  // Sizeof returns the size in bytes.
    58  func (s Size) Sizeof() int {
    59  	switch s {
    60  	case DWord:
    61  		return 8
    62  	case Word:
    63  		return 4
    64  	case Half:
    65  		return 2
    66  	case Byte:
    67  		return 1
    68  	default:
    69  		return -1
    70  	}
    71  }
    72  
    73  // LoadMemOp returns the OpCode to load a value of given size from memory.
    74  func LoadMemOp(size Size) OpCode {
    75  	return OpCode(LdXClass).SetMode(MemMode).SetSize(size)
    76  }
    77  
    78  // LoadMemSXOp returns the OpCode to load a value of given size from memory sign extended.
    79  func LoadMemSXOp(size Size) OpCode {
    80  	return OpCode(LdXClass).SetMode(MemSXMode).SetSize(size)
    81  }
    82  
    83  // LoadMem emits `dst = *(size *)(src + offset)`.
    84  func LoadMem(dst, src Register, offset int16, size Size) Instruction {
    85  	return Instruction{
    86  		OpCode: LoadMemOp(size),
    87  		Dst:    dst,
    88  		Src:    src,
    89  		Offset: offset,
    90  	}
    91  }
    92  
    93  // LoadMemSX emits `dst = *(size *)(src + offset)` but sign extends dst.
    94  func LoadMemSX(dst, src Register, offset int16, size Size) Instruction {
    95  	if size == DWord {
    96  		return Instruction{OpCode: InvalidOpCode}
    97  	}
    98  
    99  	return Instruction{
   100  		OpCode: LoadMemSXOp(size),
   101  		Dst:    dst,
   102  		Src:    src,
   103  		Offset: offset,
   104  	}
   105  }
   106  
   107  // LoadImmOp returns the OpCode to load an immediate of given size.
   108  //
   109  // As of kernel 4.20, only DWord size is accepted.
   110  func LoadImmOp(size Size) OpCode {
   111  	return OpCode(LdClass).SetMode(ImmMode).SetSize(size)
   112  }
   113  
   114  // LoadImm emits `dst = (size)value`.
   115  //
   116  // As of kernel 4.20, only DWord size is accepted.
   117  func LoadImm(dst Register, value int64, size Size) Instruction {
   118  	return Instruction{
   119  		OpCode:   LoadImmOp(size),
   120  		Dst:      dst,
   121  		Constant: value,
   122  	}
   123  }
   124  
   125  // LoadMapPtr stores a pointer to a map in dst.
   126  func LoadMapPtr(dst Register, fd int) Instruction {
   127  	if fd < 0 {
   128  		return Instruction{OpCode: InvalidOpCode}
   129  	}
   130  
   131  	return Instruction{
   132  		OpCode:   LoadImmOp(DWord),
   133  		Dst:      dst,
   134  		Src:      PseudoMapFD,
   135  		Constant: int64(uint32(fd)),
   136  	}
   137  }
   138  
   139  // LoadMapValue stores a pointer to the value at a certain offset of a map.
   140  func LoadMapValue(dst Register, fd int, offset uint32) Instruction {
   141  	if fd < 0 {
   142  		return Instruction{OpCode: InvalidOpCode}
   143  	}
   144  
   145  	fdAndOffset := (uint64(offset) << 32) | uint64(uint32(fd))
   146  	return Instruction{
   147  		OpCode:   LoadImmOp(DWord),
   148  		Dst:      dst,
   149  		Src:      PseudoMapValue,
   150  		Constant: int64(fdAndOffset),
   151  	}
   152  }
   153  
   154  // LoadIndOp returns the OpCode for loading a value of given size from an sk_buff.
   155  func LoadIndOp(size Size) OpCode {
   156  	return OpCode(LdClass).SetMode(IndMode).SetSize(size)
   157  }
   158  
   159  // LoadInd emits `dst = ntoh(*(size *)(((sk_buff *)R6)->data + src + offset))`.
   160  func LoadInd(dst, src Register, offset int32, size Size) Instruction {
   161  	return Instruction{
   162  		OpCode:   LoadIndOp(size),
   163  		Dst:      dst,
   164  		Src:      src,
   165  		Constant: int64(offset),
   166  	}
   167  }
   168  
   169  // LoadAbsOp returns the OpCode for loading a value of given size from an sk_buff.
   170  func LoadAbsOp(size Size) OpCode {
   171  	return OpCode(LdClass).SetMode(AbsMode).SetSize(size)
   172  }
   173  
   174  // LoadAbs emits `r0 = ntoh(*(size *)(((sk_buff *)R6)->data + offset))`.
   175  func LoadAbs(offset int32, size Size) Instruction {
   176  	return Instruction{
   177  		OpCode:   LoadAbsOp(size),
   178  		Dst:      R0,
   179  		Constant: int64(offset),
   180  	}
   181  }
   182  
   183  // StoreMemOp returns the OpCode for storing a register of given size in memory.
   184  func StoreMemOp(size Size) OpCode {
   185  	return OpCode(StXClass).SetMode(MemMode).SetSize(size)
   186  }
   187  
   188  // StoreMem emits `*(size *)(dst + offset) = src`
   189  func StoreMem(dst Register, offset int16, src Register, size Size) Instruction {
   190  	return Instruction{
   191  		OpCode: StoreMemOp(size),
   192  		Dst:    dst,
   193  		Src:    src,
   194  		Offset: offset,
   195  	}
   196  }
   197  
   198  // StoreImmOp returns the OpCode for storing an immediate of given size in memory.
   199  func StoreImmOp(size Size) OpCode {
   200  	return OpCode(StClass).SetMode(MemMode).SetSize(size)
   201  }
   202  
   203  // StoreImm emits `*(size *)(dst + offset) = value`.
   204  func StoreImm(dst Register, offset int16, value int64, size Size) Instruction {
   205  	return Instruction{
   206  		OpCode:   StoreImmOp(size),
   207  		Dst:      dst,
   208  		Offset:   offset,
   209  		Constant: value,
   210  	}
   211  }
   212  
   213  // StoreXAddOp returns the OpCode to atomically add a register to a value in memory.
   214  func StoreXAddOp(size Size) OpCode {
   215  	return OpCode(StXClass).SetMode(XAddMode).SetSize(size)
   216  }
   217  
   218  // StoreXAdd atomically adds src to *dst.
   219  func StoreXAdd(dst, src Register, size Size) Instruction {
   220  	return Instruction{
   221  		OpCode: StoreXAddOp(size),
   222  		Dst:    dst,
   223  		Src:    src,
   224  	}
   225  }