bpf_jit_64.S 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /* bpf_jit.S: Packet/header access helper functions
  2. * for PPC64 BPF compiler.
  3. *
  4. * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; version 2
  9. * of the License.
  10. */
  11. #include <asm/ppc_asm.h>
  12. #include "bpf_jit.h"
  13. /*
  14. * All of these routines are called directly from generated code,
  15. * whose register usage is:
  16. *
  17. * r3 skb
  18. * r4,r5 A,X
  19. * r6 *** address parameter to helper ***
  20. * r7-r10 scratch
  21. * r14 skb->data
  22. * r15 skb headlen
  23. * r16-31 M[]
  24. */
  25. /*
  26. * To consider: These helpers are so small it could be better to just
  27. * generate them inline. Inline code can do the simple headlen check
  28. * then branch directly to slow_path_XXX if required. (In fact, could
  29. * load a spare GPR with the address of slow_path_generic and pass size
  30. * as an argument, making the call site a mtlr, li and bllr.)
  31. *
  32. * Technically, the "is addr < 0" check is unnecessary & slowing down
  33. * the ABS path, as it's statically checked on generation.
  34. */
  35. .globl sk_load_word
  36. sk_load_word:
  37. cmpdi r_addr, 0
  38. blt bpf_error
  39. /* Are we accessing past headlen? */
  40. subi r_scratch1, r_HL, 4
  41. cmpd r_scratch1, r_addr
  42. blt bpf_slow_path_word
  43. /* Nope, just hitting the header. cr0 here is eq or gt! */
  44. lwzx r_A, r_D, r_addr
  45. /* When big endian we don't need to byteswap. */
  46. blr /* Return success, cr0 != LT */
  47. .globl sk_load_half
  48. sk_load_half:
  49. cmpdi r_addr, 0
  50. blt bpf_error
  51. subi r_scratch1, r_HL, 2
  52. cmpd r_scratch1, r_addr
  53. blt bpf_slow_path_half
  54. lhzx r_A, r_D, r_addr
  55. blr
  56. .globl sk_load_byte
  57. sk_load_byte:
  58. cmpdi r_addr, 0
  59. blt bpf_error
  60. cmpd r_HL, r_addr
  61. ble bpf_slow_path_byte
  62. lbzx r_A, r_D, r_addr
  63. blr
  64. /*
  65. * BPF_S_LDX_B_MSH: ldxb 4*([offset]&0xf)
  66. * r_addr is the offset value, already known positive
  67. */
  68. .globl sk_load_byte_msh
  69. sk_load_byte_msh:
  70. cmpd r_HL, r_addr
  71. ble bpf_slow_path_byte_msh
  72. lbzx r_X, r_D, r_addr
  73. rlwinm r_X, r_X, 2, 32-4-2, 31-2
  74. blr
  75. bpf_error:
  76. /* Entered with cr0 = lt */
  77. li r3, 0
  78. /* Generated code will 'blt epilogue', returning 0. */
  79. blr
  80. /* Call out to skb_copy_bits:
  81. * We'll need to back up our volatile regs first; we have
  82. * local variable space at r1+(BPF_PPC_STACK_BASIC).
  83. * Allocate a new stack frame here to remain ABI-compliant in
  84. * stashing LR.
  85. */
  86. #define bpf_slow_path_common(SIZE) \
  87. mflr r0; \
  88. std r0, 16(r1); \
  89. /* R3 goes in parameter space of caller's frame */ \
  90. std r_skb, (BPF_PPC_STACKFRAME+48)(r1); \
  91. std r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1); \
  92. std r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1); \
  93. addi r5, r1, BPF_PPC_STACK_BASIC+(2*8); \
  94. stdu r1, -BPF_PPC_SLOWPATH_FRAME(r1); \
  95. /* R3 = r_skb, as passed */ \
  96. mr r4, r_addr; \
  97. li r6, SIZE; \
  98. bl skb_copy_bits; \
  99. /* R3 = 0 on success */ \
  100. addi r1, r1, BPF_PPC_SLOWPATH_FRAME; \
  101. ld r0, 16(r1); \
  102. ld r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1); \
  103. ld r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1); \
  104. mtlr r0; \
  105. cmpdi r3, 0; \
  106. blt bpf_error; /* cr0 = LT */ \
  107. ld r_skb, (BPF_PPC_STACKFRAME+48)(r1); \
  108. /* Great success! */
  109. bpf_slow_path_word:
  110. bpf_slow_path_common(4)
  111. /* Data value is on stack, and cr0 != LT */
  112. lwz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
  113. blr
  114. bpf_slow_path_half:
  115. bpf_slow_path_common(2)
  116. lhz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
  117. blr
  118. bpf_slow_path_byte:
  119. bpf_slow_path_common(1)
  120. lbz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
  121. blr
  122. bpf_slow_path_byte_msh:
  123. bpf_slow_path_common(1)
  124. lbz r_X, BPF_PPC_STACK_BASIC+(2*8)(r1)
  125. rlwinm r_X, r_X, 2, 32-4-2, 31-2
  126. blr