bpf_jit.S 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /* bpf_jit.S : BPF JIT helper functions
  2. *
  3. * Copyright (C) 2011 Eric Dumazet (eric.dumazet@gmail.com)
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation; version 2
  8. * of the License.
  9. */
  10. #include <linux/linkage.h>
  11. #include <asm/dwarf2.h>
  12. /*
  13. * Calling convention :
  14. * rdi : skb pointer
  15. * esi : offset of byte(s) to fetch in skb (can be scratched)
  16. * r8 : copy of skb->data
  17. * r9d : hlen = skb->len - skb->data_len
  18. */
  19. #define SKBDATA %r8
  20. #define SKF_MAX_NEG_OFF $(-0x200000) /* SKF_LL_OFF from filter.h */
  21. sk_load_word:
  22. .globl sk_load_word
  23. test %esi,%esi
  24. js bpf_slow_path_word_neg
  25. sk_load_word_positive_offset:
  26. .globl sk_load_word_positive_offset
  27. mov %r9d,%eax # hlen
  28. sub %esi,%eax # hlen - offset
  29. cmp $3,%eax
  30. jle bpf_slow_path_word
  31. mov (SKBDATA,%rsi),%eax
  32. bswap %eax /* ntohl() */
  33. ret
  34. sk_load_half:
  35. .globl sk_load_half
  36. test %esi,%esi
  37. js bpf_slow_path_half_neg
  38. sk_load_half_positive_offset:
  39. .globl sk_load_half_positive_offset
  40. mov %r9d,%eax
  41. sub %esi,%eax # hlen - offset
  42. cmp $1,%eax
  43. jle bpf_slow_path_half
  44. movzwl (SKBDATA,%rsi),%eax
  45. rol $8,%ax # ntohs()
  46. ret
  47. sk_load_byte:
  48. .globl sk_load_byte
  49. test %esi,%esi
  50. js bpf_slow_path_byte_neg
  51. sk_load_byte_positive_offset:
  52. .globl sk_load_byte_positive_offset
  53. cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte */
  54. jle bpf_slow_path_byte
  55. movzbl (SKBDATA,%rsi),%eax
  56. ret
  57. /**
  58. * sk_load_byte_msh - BPF_S_LDX_B_MSH helper
  59. *
  60. * Implements BPF_S_LDX_B_MSH : ldxb 4*([offset]&0xf)
  61. * Must preserve A accumulator (%eax)
  62. * Inputs : %esi is the offset value
  63. */
  64. sk_load_byte_msh:
  65. .globl sk_load_byte_msh
  66. test %esi,%esi
  67. js bpf_slow_path_byte_msh_neg
  68. sk_load_byte_msh_positive_offset:
  69. .globl sk_load_byte_msh_positive_offset
  70. cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte_msh */
  71. jle bpf_slow_path_byte_msh
  72. movzbl (SKBDATA,%rsi),%ebx
  73. and $15,%bl
  74. shl $2,%bl
  75. ret
  76. /* rsi contains offset and can be scratched */
  77. #define bpf_slow_path_common(LEN) \
  78. push %rdi; /* save skb */ \
  79. push %r9; \
  80. push SKBDATA; \
  81. /* rsi already has offset */ \
  82. mov $LEN,%ecx; /* len */ \
  83. lea -12(%rbp),%rdx; \
  84. call skb_copy_bits; \
  85. test %eax,%eax; \
  86. pop SKBDATA; \
  87. pop %r9; \
  88. pop %rdi
  89. bpf_slow_path_word:
  90. bpf_slow_path_common(4)
  91. js bpf_error
  92. mov -12(%rbp),%eax
  93. bswap %eax
  94. ret
  95. bpf_slow_path_half:
  96. bpf_slow_path_common(2)
  97. js bpf_error
  98. mov -12(%rbp),%ax
  99. rol $8,%ax
  100. movzwl %ax,%eax
  101. ret
  102. bpf_slow_path_byte:
  103. bpf_slow_path_common(1)
  104. js bpf_error
  105. movzbl -12(%rbp),%eax
  106. ret
  107. bpf_slow_path_byte_msh:
  108. xchg %eax,%ebx /* dont lose A , X is about to be scratched */
  109. bpf_slow_path_common(1)
  110. js bpf_error
  111. movzbl -12(%rbp),%eax
  112. and $15,%al
  113. shl $2,%al
  114. xchg %eax,%ebx
  115. ret
  116. #define sk_negative_common(SIZE) \
  117. push %rdi; /* save skb */ \
  118. push %r9; \
  119. push SKBDATA; \
  120. /* rsi already has offset */ \
  121. mov $SIZE,%edx; /* size */ \
  122. call bpf_internal_load_pointer_neg_helper; \
  123. test %rax,%rax; \
  124. pop SKBDATA; \
  125. pop %r9; \
  126. pop %rdi; \
  127. jz bpf_error
  128. bpf_slow_path_word_neg:
  129. cmp SKF_MAX_NEG_OFF, %esi /* test range */
  130. jl bpf_error /* offset lower -> error */
  131. sk_load_word_negative_offset:
  132. .globl sk_load_word_negative_offset
  133. sk_negative_common(4)
  134. mov (%rax), %eax
  135. bswap %eax
  136. ret
  137. bpf_slow_path_half_neg:
  138. cmp SKF_MAX_NEG_OFF, %esi
  139. jl bpf_error
  140. sk_load_half_negative_offset:
  141. .globl sk_load_half_negative_offset
  142. sk_negative_common(2)
  143. mov (%rax),%ax
  144. rol $8,%ax
  145. movzwl %ax,%eax
  146. ret
  147. bpf_slow_path_byte_neg:
  148. cmp SKF_MAX_NEG_OFF, %esi
  149. jl bpf_error
  150. sk_load_byte_negative_offset:
  151. .globl sk_load_byte_negative_offset
  152. sk_negative_common(1)
  153. movzbl (%rax), %eax
  154. ret
  155. bpf_slow_path_byte_msh_neg:
  156. cmp SKF_MAX_NEG_OFF, %esi
  157. jl bpf_error
  158. sk_load_byte_msh_negative_offset:
  159. .globl sk_load_byte_msh_negative_offset
  160. xchg %eax,%ebx /* dont lose A , X is about to be scratched */
  161. sk_negative_common(1)
  162. movzbl (%rax),%eax
  163. and $15,%al
  164. shl $2,%al
  165. xchg %eax,%ebx
  166. ret
  167. bpf_error:
  168. # force a return 0 from jit handler
  169. xor %eax,%eax
  170. mov -8(%rbp),%rbx
  171. leaveq
  172. ret