1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/bpf.h> 4 #include <bpf/bpf_helpers.h> 5 #include "../../../include/linux/filter.h" 6 #include "bpf_arena_common.h" 7 #include "bpf_misc.h" 8 9 struct { 10 __uint(type, BPF_MAP_TYPE_ARRAY); 11 __uint(max_entries, 1); 12 __type(key, __u32); 13 __type(value, __u64); 14 } test_map SEC(".maps"); 15 16 struct { 17 __uint(type, BPF_MAP_TYPE_ARENA); 18 __uint(map_flags, BPF_F_MMAPABLE); 19 __uint(max_entries, 1); 20 } arena SEC(".maps"); 21 22 SEC("socket") 23 __log_level(2) 24 __msg(" 0: .......... (b7) r0 = 42") 25 __msg(" 1: 0......... (bf) r1 = r0") 26 __msg(" 2: .1........ (bf) r2 = r1") 27 __msg(" 3: ..2....... (bf) r3 = r2") 28 __msg(" 4: ...3...... (bf) r4 = r3") 29 __msg(" 5: ....4..... (bf) r5 = r4") 30 __msg(" 6: .....5.... (bf) r6 = r5") 31 __msg(" 7: ......6... (bf) r7 = r6") 32 __msg(" 8: .......7.. (bf) r8 = r7") 33 __msg(" 9: ........8. (bf) r9 = r8") 34 __msg("10: .........9 (bf) r0 = r9") 35 __msg("11: 0......... (95) exit") 36 __naked void assign_chain(void) 37 { 38 asm volatile ( 39 "r0 = 42;" 40 "r1 = r0;" 41 "r2 = r1;" 42 "r3 = r2;" 43 "r4 = r3;" 44 "r5 = r4;" 45 "r6 = r5;" 46 "r7 = r6;" 47 "r8 = r7;" 48 "r9 = r8;" 49 "r0 = r9;" 50 "exit;" 51 ::: __clobber_all); 52 } 53 54 SEC("socket") 55 __log_level(2) 56 __msg("0: .......... (b7) r1 = 7") 57 __msg("1: .1........ (07) r1 += 7") 58 __msg("2: .......... (b7) r2 = 7") 59 __msg("3: ..2....... (b7) r3 = 42") 60 __msg("4: ..23...... (0f) r2 += r3") 61 __msg("5: .......... (b7) r0 = 0") 62 __msg("6: 0......... (95) exit") 63 __naked void arithmetics(void) 64 { 65 asm volatile ( 66 "r1 = 7;" 67 "r1 += 7;" 68 "r2 = 7;" 69 "r3 = 42;" 70 "r2 += r3;" 71 "r0 = 0;" 72 "exit;" 73 ::: __clobber_all); 74 } 75 76 #ifdef CAN_USE_BPF_ST 77 SEC("socket") 78 __log_level(2) 79 __msg(" 1: .1........ (07) r1 += -8") 80 __msg(" 2: .1........ (7a) *(u64 *)(r1 +0) = 7") 81 __msg(" 3: .1........ (b7) r2 = 42") 82 __msg(" 4: .12....... (7b) *(u64 *)(r1 +0) = r2") 83 __msg(" 5: .12....... (7b) *(u64 *)(r1 +0) = r2") 84 __msg(" 6: .......... (b7) r0 = 0") 85 __naked void store(void) 86 { 87 asm volatile ( 88 "r1 = r10;" 89 "r1 += -8;" 90 "*(u64 *)(r1 +0) = 7;" 91 "r2 = 42;" 92 "*(u64 *)(r1 +0) = r2;" 93 "*(u64 *)(r1 +0) = r2;" 94 "r0 = 0;" 95 "exit;" 96 ::: __clobber_all); 97 } 98 #endif 99 100 SEC("socket") 101 __log_level(2) 102 __msg("1: ....4..... (07) r4 += -8") 103 __msg("2: ....4..... (79) r5 = *(u64 *)(r4 +0)") 104 __msg("3: ....45.... (07) r4 += -8") 105 __naked void load(void) 106 { 107 asm volatile ( 108 "r4 = r10;" 109 "r4 += -8;" 110 "r5 = *(u64 *)(r4 +0);" 111 "r4 += -8;" 112 "r0 = r5;" 113 "exit;" 114 ::: __clobber_all); 115 } 116 117 SEC("socket") 118 __log_level(2) 119 __msg("0: .1........ (61) r2 = *(u32 *)(r1 +0)") 120 __msg("1: ..2....... (d4) r2 = le64 r2") 121 __msg("2: ..2....... (bf) r0 = r2") 122 __naked void endian(void) 123 { 124 asm volatile ( 125 "r2 = *(u32 *)(r1 +0);" 126 "r2 = le64 r2;" 127 "r0 = r2;" 128 "exit;" 129 ::: __clobber_all); 130 } 131 132 SEC("socket") 133 __log_level(2) 134 __msg(" 8: 0......... (b7) r1 = 1") 135 __msg(" 9: 01........ (db) r1 = atomic64_fetch_add((u64 *)(r0 +0), r1)") 136 __msg("10: 01........ (c3) lock *(u32 *)(r0 +0) += r1") 137 __msg("11: 01........ (db) r1 = atomic64_xchg((u64 *)(r0 +0), r1)") 138 __msg("12: 01........ (bf) r2 = r0") 139 __msg("13: .12....... (bf) r0 = r1") 140 __msg("14: 012....... (db) r0 = atomic64_cmpxchg((u64 *)(r2 +0), r0, r1)") 141 __naked void atomic(void) 142 { 143 asm volatile ( 144 "r2 = r10;" 145 "r2 += -8;" 146 "r1 = 0;" 147 "*(u64 *)(r2 +0) = r1;" 148 "r1 = %[test_map] ll;" 149 "call %[bpf_map_lookup_elem];" 150 "if r0 == 0 goto 1f;" 151 "r1 = 1;" 152 "r1 = atomic_fetch_add((u64 *)(r0 +0), r1);" 153 ".8byte %[add_nofetch];" /* same as "lock *(u32 *)(r0 +0) += r1;" */ 154 "r1 = xchg_64(r0 + 0, r1);" 155 "r2 = r0;" 156 "r0 = r1;" 157 "r0 = cmpxchg_64(r2 + 0, r0, r1);" 158 "1: exit;" 159 : 160 : __imm(bpf_map_lookup_elem), 161 __imm_addr(test_map), 162 __imm_insn(add_nofetch, BPF_ATOMIC_OP(BPF_W, BPF_ADD, BPF_REG_0, BPF_REG_1, 0)) 163 : __clobber_all); 164 } 165 166 #ifdef CAN_USE_LOAD_ACQ_STORE_REL 167 168 SEC("socket") 169 __log_level(2) 170 __msg("2: .12....... (db) store_release((u64 *)(r2 -8), r1)") 171 __msg("3: .......... (bf) r3 = r10") 172 __msg("4: ...3...... (db) r4 = load_acquire((u64 *)(r3 -8))") 173 __naked void atomic_load_acq_store_rel(void) 174 { 175 asm volatile ( 176 "r1 = 42;" 177 "r2 = r10;" 178 ".8byte %[store_release_insn];" /* store_release((u64 *)(r2 - 8), r1); */ 179 "r3 = r10;" 180 ".8byte %[load_acquire_insn];" /* r4 = load_acquire((u64 *)(r3 + 0)); */ 181 "r0 = r4;" 182 "exit;" 183 : 184 : __imm_insn(store_release_insn, 185 BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_2, BPF_REG_1, -8)), 186 __imm_insn(load_acquire_insn, 187 BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_4, BPF_REG_3, -8)) 188 : __clobber_all); 189 } 190 191 #endif /* CAN_USE_LOAD_ACQ_STORE_REL */ 192 193 SEC("socket") 194 __log_level(2) 195 __msg("4: .12....7.. (85) call bpf_trace_printk#6") 196 __msg("5: 0......7.. (0f) r0 += r7") 197 __naked void regular_call(void) 198 { 199 asm volatile ( 200 "r7 = 1;" 201 "r1 = r10;" 202 "r1 += -8;" 203 "r2 = 1;" 204 "call %[bpf_trace_printk];" 205 "r0 += r7;" 206 "exit;" 207 : 208 : __imm(bpf_trace_printk) 209 : __clobber_all); 210 } 211 212 SEC("socket") 213 __log_level(2) 214 __msg("2: 012....... (25) if r1 > 0x7 goto pc+1") 215 __msg("3: ..2....... (bf) r0 = r2") 216 __naked void if1(void) 217 { 218 asm volatile ( 219 "r0 = 1;" 220 "r2 = 2;" 221 "if r1 > 0x7 goto +1;" 222 "r0 = r2;" 223 "exit;" 224 ::: __clobber_all); 225 } 226 227 SEC("socket") 228 __log_level(2) 229 __msg("3: 0123...... (2d) if r1 > r3 goto pc+1") 230 __msg("4: ..2....... (bf) r0 = r2") 231 __naked void if2(void) 232 { 233 asm volatile ( 234 "r0 = 1;" 235 "r2 = 2;" 236 "r3 = 7;" 237 "if r1 > r3 goto +1;" 238 "r0 = r2;" 239 "exit;" 240 ::: __clobber_all); 241 } 242 243 SEC("socket") 244 __log_level(2) 245 __msg("0: .......... (b7) r1 = 0") 246 __msg("1: .1........ (b7) r2 = 7") 247 __msg("2: .12....... (25) if r1 > 0x7 goto pc+4") 248 __msg("3: .12....... (07) r1 += 1") 249 __msg("4: .12....... (27) r2 *= 2") 250 __msg("5: .12....... (05) goto pc+0") 251 __msg("6: .12....... (05) goto pc-5") 252 __msg("7: .......... (b7) r0 = 0") 253 __msg("8: 0......... (95) exit") 254 __naked void loop(void) 255 { 256 asm volatile ( 257 "r1 = 0;" 258 "r2 = 7;" 259 "if r1 > 0x7 goto +4;" 260 "r1 += 1;" 261 "r2 *= 2;" 262 "goto +0;" 263 "goto -5;" 264 "r0 = 0;" 265 "exit;" 266 : 267 : __imm(bpf_trace_printk) 268 : __clobber_all); 269 } 270 271 #ifdef CAN_USE_GOTOL 272 SEC("socket") 273 __log_level(2) 274 __msg("2: .123...... (25) if r1 > 0x7 goto pc+2") 275 __msg("3: ..2....... (bf) r0 = r2") 276 __msg("4: 0......... (06) gotol pc+1") 277 __msg("5: ...3...... (bf) r0 = r3") 278 __msg("6: 0......... (95) exit") 279 __naked void gotol(void) 280 { 281 asm volatile ( 282 "r2 = 42;" 283 "r3 = 24;" 284 "if r1 > 0x7 goto +2;" 285 "r0 = r2;" 286 "gotol +1;" 287 "r0 = r3;" 288 "exit;" 289 : 290 : __imm(bpf_trace_printk) 291 : __clobber_all); 292 } 293 #endif 294 295 SEC("socket") 296 __log_level(2) 297 __msg("0: .......... (b7) r1 = 1") 298 __msg("1: .1........ (e5) may_goto pc+1") 299 __msg("2: .......... (05) goto pc-3") 300 __msg("3: .1........ (bf) r0 = r1") 301 __msg("4: 0......... (95) exit") 302 __naked void may_goto(void) 303 { 304 asm volatile ( 305 "1: r1 = 1;" 306 ".8byte %[may_goto];" 307 "goto 1b;" 308 "r0 = r1;" 309 "exit;" 310 : 311 : __imm(bpf_get_smp_processor_id), 312 __imm_insn(may_goto, BPF_RAW_INSN(BPF_JMP | BPF_JCOND, 0, 0, +1 /* offset */, 0)) 313 : __clobber_all); 314 } 315 316 SEC("socket") 317 __log_level(2) 318 __msg("1: 0......... (18) r2 = 0x7") 319 __msg("3: 0.2....... (0f) r0 += r2") 320 __naked void ldimm64(void) 321 { 322 asm volatile ( 323 "r0 = 0;" 324 "r2 = 0x7 ll;" 325 "r0 += r2;" 326 "exit;" 327 : 328 :: __clobber_all); 329 } 330 331 /* No rules specific for LD_ABS/LD_IND, default behaviour kicks in */ 332 SEC("socket") 333 __log_level(2) 334 __msg("2: 0123456789 (30) r0 = *(u8 *)skb[42]") 335 __msg("3: 012.456789 (0f) r7 += r0") 336 __msg("4: 012.456789 (b7) r3 = 42") 337 __msg("5: 0123456789 (50) r0 = *(u8 *)skb[r3 + 0]") 338 __msg("6: 0......7.. (0f) r7 += r0") 339 __naked void ldabs(void) 340 { 341 asm volatile ( 342 "r6 = r1;" 343 "r7 = 0;" 344 "r0 = *(u8 *)skb[42];" 345 "r7 += r0;" 346 "r3 = 42;" 347 ".8byte %[ld_ind];" /* same as "r0 = *(u8 *)skb[r3];" */ 348 "r7 += r0;" 349 "r0 = r7;" 350 "exit;" 351 : 352 : __imm_insn(ld_ind, BPF_LD_IND(BPF_B, BPF_REG_3, 0)) 353 : __clobber_all); 354 } 355 356 357 #ifdef __BPF_FEATURE_ADDR_SPACE_CAST 358 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid") 359 __log_level(2) 360 __msg(" 6: .12345.... (85) call bpf_arena_alloc_pages") 361 __msg(" 7: 0......... (bf) r1 = addr_space_cast(r0, 0, 1)") 362 __msg(" 8: .1........ (b7) r2 = 42") 363 __naked void addr_space_cast(void) 364 { 365 asm volatile ( 366 "r1 = %[arena] ll;" 367 "r2 = 0;" 368 "r3 = 1;" 369 "r4 = 0;" 370 "r5 = 0;" 371 "call %[bpf_arena_alloc_pages];" 372 "r1 = addr_space_cast(r0, 0, 1);" 373 "r2 = 42;" 374 "*(u64 *)(r1 +0) = r2;" 375 "r0 = 0;" 376 "exit;" 377 : 378 : __imm(bpf_arena_alloc_pages), 379 __imm_addr(arena) 380 : __clobber_all); 381 } 382 #endif 383 384 static __used __naked int aux1(void) 385 { 386 asm volatile ( 387 "r0 = r1;" 388 "r0 += r2;" 389 "exit;" 390 ::: __clobber_all); 391 } 392 393 SEC("socket") 394 __log_level(2) 395 __msg("0: ....45.... (b7) r1 = 1") 396 __msg("1: .1..45.... (b7) r2 = 2") 397 __msg("2: .12.45.... (b7) r3 = 3") 398 /* Conservative liveness for subprog parameters. */ 399 __msg("3: .12345.... (85) call pc+2") 400 __msg("4: .......... (b7) r0 = 0") 401 __msg("5: 0......... (95) exit") 402 __msg("6: .12....... (bf) r0 = r1") 403 __msg("7: 0.2....... (0f) r0 += r2") 404 /* Conservative liveness for subprog return value. */ 405 __msg("8: 0......... (95) exit") 406 __naked void subprog1(void) 407 { 408 asm volatile ( 409 "r1 = 1;" 410 "r2 = 2;" 411 "r3 = 3;" 412 "call aux1;" 413 "r0 = 0;" 414 "exit;" 415 ::: __clobber_all); 416 } 417 418 /* to retain debug info for BTF generation */ 419 void kfunc_root(void) 420 { 421 bpf_arena_alloc_pages(0, 0, 0, 0, 0); 422 } 423 424 char _license[] SEC("license") = "GPL"; 425