bpf_jit.S 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * BPF Jit compiler for s390, help functions.
  3. *
  4. * Copyright IBM Corp. 2012,2015
  5. *
  6. * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  7. * Michael Holzheu <holzheu@linux.vnet.ibm.com>
  8. */
  9. #include <linux/linkage.h>
  10. #include <asm/nospec-insn.h>
  11. #include "bpf_jit.h"
  12. /*
  13. * Calling convention:
  14. * registers %r7-%r10, %r11,%r13, and %r15 are call saved
  15. *
  16. * Input (64 bit):
  17. * %r3 (%b2) = offset into skb data
  18. * %r6 (%b5) = return address
  19. * %r7 (%b6) = skb pointer
  20. * %r12 = skb data pointer
  21. *
  22. * Output:
  23. * %r14= %b0 = return value (read skb value)
  24. *
  25. * Work registers: %r2,%r4,%r5,%r14
  26. *
  27. * skb_copy_bits takes 4 parameters:
  28. * %r2 = skb pointer
  29. * %r3 = offset into skb data
  30. * %r4 = pointer to temp buffer
  31. * %r5 = length to copy
  32. * Return value in %r2: 0 = ok
  33. *
  34. * bpf_internal_load_pointer_neg_helper takes 3 parameters:
  35. * %r2 = skb pointer
  36. * %r3 = offset into data
  37. * %r4 = length to copy
  38. * Return value in %r2: Pointer to data
  39. */
  40. #define SKF_MAX_NEG_OFF -0x200000 /* SKF_LL_OFF from filter.h */
  41. /*
  42. * Load SIZE bytes from SKB
  43. */
  44. #define sk_load_common(NAME, SIZE, LOAD) \
  45. ENTRY(sk_load_##NAME); \
  46. ltgr %r3,%r3; /* Is offset negative? */ \
  47. jl sk_load_##NAME##_slow_neg; \
  48. ENTRY(sk_load_##NAME##_pos); \
  49. aghi %r3,SIZE; /* Offset + SIZE */ \
  50. clg %r3,STK_OFF_HLEN(%r15); /* Offset + SIZE > hlen? */ \
  51. jh sk_load_##NAME##_slow; \
  52. LOAD %r14,-SIZE(%r3,%r12); /* Get data from skb */ \
  53. B_EX OFF_OK,%r6; /* Return */ \
  54. \
  55. sk_load_##NAME##_slow:; \
  56. lgr %r2,%r7; /* Arg1 = skb pointer */ \
  57. aghi %r3,-SIZE; /* Arg2 = offset */ \
  58. la %r4,STK_OFF_TMP(%r15); /* Arg3 = temp bufffer */ \
  59. lghi %r5,SIZE; /* Arg4 = size */ \
  60. brasl %r14,skb_copy_bits; /* Get data from skb */ \
  61. LOAD %r14,STK_OFF_TMP(%r15); /* Load from temp bufffer */ \
  62. ltgr %r2,%r2; /* Set cc to (%r2 != 0) */ \
  63. BR_EX %r6; /* Return */
  64. sk_load_common(word, 4, llgf) /* r14 = *(u32 *) (skb->data+offset) */
  65. sk_load_common(half, 2, llgh) /* r14 = *(u16 *) (skb->data+offset) */
  66. GEN_BR_THUNK %r6
  67. GEN_B_THUNK OFF_OK,%r6
  68. /*
  69. * Load 1 byte from SKB (optimized version)
  70. */
  71. /* r14 = *(u8 *) (skb->data+offset) */
  72. ENTRY(sk_load_byte)
  73. ltgr %r3,%r3 # Is offset negative?
  74. jl sk_load_byte_slow_neg
  75. ENTRY(sk_load_byte_pos)
  76. clg %r3,STK_OFF_HLEN(%r15) # Offset >= hlen?
  77. jnl sk_load_byte_slow
  78. llgc %r14,0(%r3,%r12) # Get byte from skb
  79. B_EX OFF_OK,%r6 # Return OK
  80. sk_load_byte_slow:
  81. lgr %r2,%r7 # Arg1 = skb pointer
  82. # Arg2 = offset
  83. la %r4,STK_OFF_TMP(%r15) # Arg3 = pointer to temp buffer
  84. lghi %r5,1 # Arg4 = size (1 byte)
  85. brasl %r14,skb_copy_bits # Get data from skb
  86. llgc %r14,STK_OFF_TMP(%r15) # Load result from temp buffer
  87. ltgr %r2,%r2 # Set cc to (%r2 != 0)
  88. BR_EX %r6 # Return cc
  89. #define sk_negative_common(NAME, SIZE, LOAD) \
  90. sk_load_##NAME##_slow_neg:; \
  91. cgfi %r3,SKF_MAX_NEG_OFF; \
  92. jl bpf_error; \
  93. lgr %r2,%r7; /* Arg1 = skb pointer */ \
  94. /* Arg2 = offset */ \
  95. lghi %r4,SIZE; /* Arg3 = size */ \
  96. brasl %r14,bpf_internal_load_pointer_neg_helper; \
  97. ltgr %r2,%r2; \
  98. jz bpf_error; \
  99. LOAD %r14,0(%r2); /* Get data from pointer */ \
  100. xr %r3,%r3; /* Set cc to zero */ \
  101. BR_EX %r6; /* Return cc */
  102. sk_negative_common(word, 4, llgf)
  103. sk_negative_common(half, 2, llgh)
  104. sk_negative_common(byte, 1, llgc)
  105. bpf_error:
  106. # force a return 0 from jit handler
  107. ltgr %r15,%r15 # Set condition code
  108. BR_EX %r6