bpf_jit.S 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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/frame.h>
  12. /*
  13. * Calling convention :
  14. * rbx : skb pointer (callee saved)
  15. * esi : offset of byte(s) to fetch in skb (can be scratched)
  16. * r10 : copy of skb->data
  17. * r9d : hlen = skb->len - skb->data_len
  18. */
  19. #define SKBDATA %r10
  20. #define SKF_MAX_NEG_OFF $(-0x200000) /* SKF_LL_OFF from filter.h */
  21. #define MAX_BPF_STACK (512 /* from filter.h */ + \
  22. 32 /* space for rbx,r13,r14,r15 */ + \
  23. 8 /* space for skb_copy_bits */)
  24. #define FUNC(name) \
  25. .globl name; \
  26. .type name, @function; \
  27. name:
  28. FUNC(sk_load_word)
  29. test %esi,%esi
  30. js bpf_slow_path_word_neg
  31. FUNC(sk_load_word_positive_offset)
  32. mov %r9d,%eax # hlen
  33. sub %esi,%eax # hlen - offset
  34. cmp $3,%eax
  35. jle bpf_slow_path_word
  36. mov (SKBDATA,%rsi),%eax
  37. bswap %eax /* ntohl() */
  38. ret
  39. FUNC(sk_load_half)
  40. test %esi,%esi
  41. js bpf_slow_path_half_neg
  42. FUNC(sk_load_half_positive_offset)
  43. mov %r9d,%eax
  44. sub %esi,%eax # hlen - offset
  45. cmp $1,%eax
  46. jle bpf_slow_path_half
  47. movzwl (SKBDATA,%rsi),%eax
  48. rol $8,%ax # ntohs()
  49. ret
  50. FUNC(sk_load_byte)
  51. test %esi,%esi
  52. js bpf_slow_path_byte_neg
  53. FUNC(sk_load_byte_positive_offset)
  54. cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte */
  55. jle bpf_slow_path_byte
  56. movzbl (SKBDATA,%rsi),%eax
  57. ret
  58. /* rsi contains offset and can be scratched */
  59. #define bpf_slow_path_common(LEN) \
  60. lea -MAX_BPF_STACK + 32(%rbp), %rdx;\
  61. FRAME_BEGIN; \
  62. mov %rbx, %rdi; /* arg1 == skb */ \
  63. push %r9; \
  64. push SKBDATA; \
  65. /* rsi already has offset */ \
  66. mov $LEN,%ecx; /* len */ \
  67. call skb_copy_bits; \
  68. test %eax,%eax; \
  69. pop SKBDATA; \
  70. pop %r9; \
  71. FRAME_END
  72. bpf_slow_path_word:
  73. bpf_slow_path_common(4)
  74. js bpf_error
  75. mov - MAX_BPF_STACK + 32(%rbp),%eax
  76. bswap %eax
  77. ret
  78. bpf_slow_path_half:
  79. bpf_slow_path_common(2)
  80. js bpf_error
  81. mov - MAX_BPF_STACK + 32(%rbp),%ax
  82. rol $8,%ax
  83. movzwl %ax,%eax
  84. ret
  85. bpf_slow_path_byte:
  86. bpf_slow_path_common(1)
  87. js bpf_error
  88. movzbl - MAX_BPF_STACK + 32(%rbp),%eax
  89. ret
  90. #define sk_negative_common(SIZE) \
  91. FRAME_BEGIN; \
  92. mov %rbx, %rdi; /* arg1 == skb */ \
  93. push %r9; \
  94. push SKBDATA; \
  95. /* rsi already has offset */ \
  96. mov $SIZE,%edx; /* size */ \
  97. call bpf_internal_load_pointer_neg_helper; \
  98. test %rax,%rax; \
  99. pop SKBDATA; \
  100. pop %r9; \
  101. FRAME_END; \
  102. jz bpf_error
  103. bpf_slow_path_word_neg:
  104. cmp SKF_MAX_NEG_OFF, %esi /* test range */
  105. jl bpf_error /* offset lower -> error */
  106. FUNC(sk_load_word_negative_offset)
  107. sk_negative_common(4)
  108. mov (%rax), %eax
  109. bswap %eax
  110. ret
  111. bpf_slow_path_half_neg:
  112. cmp SKF_MAX_NEG_OFF, %esi
  113. jl bpf_error
  114. FUNC(sk_load_half_negative_offset)
  115. sk_negative_common(2)
  116. mov (%rax),%ax
  117. rol $8,%ax
  118. movzwl %ax,%eax
  119. ret
  120. bpf_slow_path_byte_neg:
  121. cmp SKF_MAX_NEG_OFF, %esi
  122. jl bpf_error
  123. FUNC(sk_load_byte_negative_offset)
  124. sk_negative_common(1)
  125. movzbl (%rax), %eax
  126. ret
  127. bpf_error:
  128. # force a return 0 from jit handler
  129. xor %eax,%eax
  130. mov - MAX_BPF_STACK(%rbp),%rbx
  131. mov - MAX_BPF_STACK + 8(%rbp),%r13
  132. mov - MAX_BPF_STACK + 16(%rbp),%r14
  133. mov - MAX_BPF_STACK + 24(%rbp),%r15
  134. leaveq
  135. ret