| @@ -221,14 +221,48 @@ struct jit_context { · 220 unmodified lines |
| 221 | | 221 | |
| 222 | /* Number of bytes emit_patch() needs to generate instructions */ | 222 | /* Number of bytes emit_patch() needs to generate instructions */ |
| 223 | #define X86_PATCH_SIZE 5 | 223 | #define X86_PATCH_SIZE 5 |
| | 224 | /* Number of bytes that will be skipped on tailcall */ |
| | 225 | #define X86_TAIL_CALL_OFFSET 11 |
| 224 | | 226 | |
| 225 | #define PROLOGUE_SIZE 25 | 227 | static void push_callee_regs(u8 **pprog, bool *callee_regs_used) |
| | 228 | { |
| | 229 | u8 *prog = *pprog; |
| | 230 | int cnt = 0; |
| | 231 | |
| | 232 | if (callee_regs_used[0]) |
| | 233 | EMIT1(0x53); /* push rbx */ |
| | 234 | if (callee_regs_used[1]) |
| | 235 | EMIT2(0x41, 0x55); /* push r13 */ |
| | 236 | if (callee_regs_used[2]) |
| | 237 | EMIT2(0x41, 0x56); /* push r14 */ |
| | 238 | if (callee_regs_used[3]) |
| | 239 | EMIT2(0x41, 0x57); /* push r15 */ |
| | 240 | *pprog = prog; |
| | 241 | } |
| | 242 | |
| | 243 | static void pop_callee_regs(u8 **pprog, bool *callee_regs_used) |
| | 244 | { |
| | 245 | u8 *prog = *pprog; |
| | 246 | int cnt = 0; |
| | 247 | |
| | 248 | if (callee_regs_used[3]) |
| | 249 | EMIT2(0x41, 0x5F); /* pop r15 */ |
| | 250 | if (callee_regs_used[2]) |
| | 251 | EMIT2(0x41, 0x5E); /* pop r14 */ |
| | 252 | if (callee_regs_used[1]) |
| | 253 | EMIT2(0x41, 0x5D); /* pop r13 */ |
| | 254 | if (callee_regs_used[0]) |
| | 255 | EMIT1(0x5B); /* pop rbx */ |
| | 256 | *pprog = prog; |
| | 257 | } |
| 226 | | 258 | |
| 227 | /* | 259 | /* |
| 228 | * Emit x86-64 prologue code for BPF program and check its size. | 260 | * Emit x86-64 prologue code for BPF program. |
| 229 | * bpf_tail_call helper will skip it while jumping into another program | 261 | * bpf_tail_call helper will skip the first X86_TAIL_CALL_OFFSET bytes |
| | 262 | * while jumping to another program |
| 230 | */ | 263 | */ |
| 231 | static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf) | 264 | static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf, |
| | 265 | bool tail_call_reachable, bool is_subprog) |
| 232 | { | 266 | { |
| 233 | u8 *prog = *pprog; | 267 | u8 *prog = *pprog; |
| 234 | int cnt = X86_PATCH_SIZE; | 268 | int cnt = X86_PATCH_SIZE; |
| @@ -238,19 +272,18 @@ static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf) · 3 unmodified lines |
| 238 | */ | 272 | */ |
| 239 | memcpy(prog, ideal_nops[NOP_ATOMIC5], cnt); | 273 | memcpy(prog, ideal_nops[NOP_ATOMIC5], cnt); |
| 240 | prog += cnt; | 274 | prog += cnt; |
| | 275 | if (!ebpf_from_cbpf) { |
| | 276 | if (tail_call_reachable && !is_subprog) |
| | 277 | EMIT2(0x31, 0xC0); /* xor eax, eax */ |
| | 278 | else |
| | 279 | EMIT2(0x66, 0x90); /* nop2 */ |
| | 280 | } |
| 241 | EMIT1(0x55); /* push rbp */ | 281 | EMIT1(0x55); /* push rbp */ |
| 242 | EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */ | 282 | EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */ |
| 243 | /* sub rsp, rounded_stack_depth */ | 283 | /* sub rsp, rounded_stack_depth */ |
| 244 | EMIT3_off32(0x48, 0x81, 0xEC, round_up(stack_depth, 8)); | 284 | EMIT3_off32(0x48, 0x81, 0xEC, round_up(stack_depth, 8)); |
| 245 | EMIT1(0x53); /* push rbx */ | 285 | if (tail_call_reachable) |
| 246 | EMIT2(0x41, 0x55); /* push r13 */ | 286 | EMIT1(0x50); /* push rax */ |
| 247 | EMIT2(0x41, 0x56); /* push r14 */ | | |
| 248 | EMIT2(0x41, 0x57); /* push r15 */ | | |
| 249 | if (!ebpf_from_cbpf) { | | |
| 250 | /* zero init tail_call_cnt */ | | |
| 251 | EMIT2(0x6a, 0x00); | | |
| 252 | BUILD_BUG_ON(cnt != PROLOGUE_SIZE); | | |
| 253 | } | | |
| 254 | *pprog = prog; | 287 | *pprog = prog; |
| 255 | } | 288 | } |
| 256 | | 289 | |
| @@ -314,13 +347,14 @@ static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t, · 57 unmodified lines |
| 314 | mutex_lock(&text_mutex); | 347 | mutex_lock(&text_mutex); |
| 315 | if (memcmp(ip, old_insn, X86_PATCH_SIZE)) | 348 | if (memcmp(ip, old_insn, X86_PATCH_SIZE)) |
| 316 | goto out; | 349 | goto out; |
| | 350 | ret = 1; |
| 317 | if (memcmp(ip, new_insn, X86_PATCH_SIZE)) { | 351 | if (memcmp(ip, new_insn, X86_PATCH_SIZE)) { |
| 318 | if (text_live) | 352 | if (text_live) |
| 319 | text_poke_bp(ip, new_insn, X86_PATCH_SIZE, NULL); | 353 | text_poke_bp(ip, new_insn, X86_PATCH_SIZE, NULL); |
| 320 | else | 354 | else |
| 321 | memcpy(ip, new_insn, X86_PATCH_SIZE); | 355 | memcpy(ip, new_insn, X86_PATCH_SIZE); |
| | 356 | ret = 0; |
| 322 | } | 357 | } |
| 323 | ret = 0; | | |
| 324 | out: | 358 | out: |
| 325 | mutex_unlock(&text_mutex); | 359 | mutex_unlock(&text_mutex); |
| 326 | return ret; | 360 | return ret; |
| @@ -337,6 +371,22 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t, · 10 unmodified lines |
| 337 | return __bpf_arch_text_poke(ip, t, old_addr, new_addr, true); | 371 | return __bpf_arch_text_poke(ip, t, old_addr, new_addr, true); |
| 338 | } | 372 | } |
| 339 | | 373 | |
| | 374 | static int get_pop_bytes(bool *callee_regs_used) |
| | 375 | { |
| | 376 | int bytes = 0; |
| | 377 | |
| | 378 | if (callee_regs_used[3]) |
| | 379 | bytes += 2; |
| | 380 | if (callee_regs_used[2]) |
| | 381 | bytes += 2; |
| | 382 | if (callee_regs_used[1]) |
| | 383 | bytes += 2; |
| | 384 | if (callee_regs_used[0]) |
| | 385 | bytes += 1; |
| | 386 | |
| | 387 | return bytes; |
| | 388 | } |
| | 389 | |
| 340 | /* | 390 | /* |
| 341 | * Generate the following code: | 391 | * Generate the following code: |
| 342 | * | 392 | * |
| @@ -351,12 +401,26 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t, · 8 unmodified lines |
| 351 | * goto *(prog->bpf_func + prologue_size); | 401 | * goto *(prog->bpf_func + prologue_size); |
| 352 | * out: | 402 | * out: |
| 353 | */ | 403 | */ |
| 354 | static void emit_bpf_tail_call_indirect(u8 **pprog) | 404 | static void emit_bpf_tail_call_indirect(u8 **pprog, bool *callee_regs_used, |
| | 405 | u32 stack_depth) |
| 355 | { | 406 | { |
| | 407 | int tcc_off = -4 - round_up(stack_depth, 8); |
| 356 | u8 *prog = *pprog; | 408 | u8 *prog = *pprog; |
| 357 | int label1, label2, label3; | 409 | int pop_bytes = 0; |
| | 410 | int off1 = 49; |
| | 411 | int off2 = 38; |
| | 412 | int off3 = 16; |
| 358 | int cnt = 0; | 413 | int cnt = 0; |
| 359 | | 414 | |
| | 415 | /* count the additional bytes used for popping callee regs from stack |
| | 416 | * that need to be taken into account for each of the offsets that |
| | 417 | * are used for bailing out of the tail call |
| | 418 | */ |
| | 419 | pop_bytes = get_pop_bytes(callee_regs_used); |
| | 420 | off1 += pop_bytes; |
| | 421 | off2 += pop_bytes; |
| | 422 | off3 += pop_bytes; |
| | 423 | |
| 360 | /* | 424 | /* |
| 361 | * rdi - pointer to ctx | 425 | * rdi - pointer to ctx |
| 362 | * rsi - pointer to bpf_array | 426 | * rsi - pointer to bpf_array |
| @@ -370,21 +434,19 @@ static void emit_bpf_tail_call_indirect(u8 **pprog) · 7 unmodified lines |
| 370 | EMIT2(0x89, 0xD2); /* mov edx, edx */ | 434 | EMIT2(0x89, 0xD2); /* mov edx, edx */ |
| 371 | EMIT3(0x39, 0x56, /* cmp dword ptr [rsi + 16], edx */ | 435 | EMIT3(0x39, 0x56, /* cmp dword ptr [rsi + 16], edx */ |
| 372 | offsetof(struct bpf_array, map.max_entries)); | 436 | offsetof(struct bpf_array, map.max_entries)); |
| 373 | #define OFFSET1 (41 + RETPOLINE_RCX_BPF_JIT_SIZE) /* Number of bytes to jump */ | 437 | #define OFFSET1 (off1 + RETPOLINE_RCX_BPF_JIT_SIZE) /* Number of bytes to jump */ |
| 374 | EMIT2(X86_JBE, OFFSET1); /* jbe out */ | 438 | EMIT2(X86_JBE, OFFSET1); /* jbe out */ |
| 375 | label1 = cnt; | | |
| 376 | | 439 | |
| 377 | /* | 440 | /* |
| 378 | * if (tail_call_cnt > MAX_TAIL_CALL_CNT) | 441 | * if (tail_call_cnt > MAX_TAIL_CALL_CNT) |
| 379 | * goto out; | 442 | * goto out; |
| 380 | */ | 443 | */ |
| 381 | EMIT2_off32(0x8B, 0x85, -36 - MAX_BPF_STACK); /* mov eax, dword ptr [rbp - 548] */ | 444 | EMIT2_off32(0x8B, 0x85, tcc_off); /* mov eax, dword ptr [rbp - tcc_off] */ |
| 382 | EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */ | 445 | EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */ |
| 383 | #define OFFSET2 (30 + RETPOLINE_RCX_BPF_JIT_SIZE) | 446 | #define OFFSET2 (off2 + RETPOLINE_RCX_BPF_JIT_SIZE) |
| 384 | EMIT2(X86_JA, OFFSET2); /* ja out */ | 447 | EMIT2(X86_JA, OFFSET2); /* ja out */ |
| 385 | label2 = cnt; | | |
| 386 | EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */ | 448 | EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */ |
| 387 | EMIT2_off32(0x89, 0x85, -36 - MAX_BPF_STACK); /* mov dword ptr [rbp -548], eax */ | 449 | EMIT2_off32(0x89, 0x85, tcc_off); /* mov dword ptr [rbp - tcc_off], eax */ |
| 388 | | 450 | |
| 389 | /* prog = array->ptrs[index]; */ | 451 | /* prog = array->ptrs[index]; */ |
| 390 | EMIT4_off32(0x48, 0x8B, 0x8C, 0xD6, /* mov rcx, [rsi + rdx * 8 + offsetof(...)] */ | 452 | EMIT4_off32(0x48, 0x8B, 0x8C, 0xD6, /* mov rcx, [rsi + rdx * 8 + offsetof(...)] */ |
| @@ -394,48 +456,84 @@ static void emit_bpf_tail_call_indirect(u8 **pprog) · 3 unmodified lines |
| 394 | * if (prog == NULL) | 456 | * if (prog == NULL) |
| 395 | * goto out; | 457 | * goto out; |
| 396 | */ | 458 | */ |
| 397 | EMIT3(0x48, 0x85, 0xC9); /* test rcx,rcx */ | 459 | EMIT3(0x48, 0x85, 0xC9); /* test rcx,rcx */ |
| 398 | #define OFFSET3 (8 + RETPOLINE_RCX_BPF_JIT_SIZE) | 460 | #define OFFSET3 (off3 + RETPOLINE_RCX_BPF_JIT_SIZE) |
| 399 | EMIT2(X86_JE, OFFSET3); /* je out */ | 461 | EMIT2(X86_JE, OFFSET3); /* je out */ |
| 400 | label3 = cnt; | | |
| 401 | | 462 | |
| 402 | /* goto *(prog->bpf_func + prologue_size); */ | 463 | *pprog = prog; |
| | 464 | pop_callee_regs(pprog, callee_regs_used); |
| | 465 | prog = *pprog; |
| | 466 | |
| | 467 | EMIT1(0x58); /* pop rax */ |
| | 468 | EMIT3_off32(0x48, 0x81, 0xC4, /* add rsp, sd */ |
| | 469 | round_up(stack_depth, 8)); |
| | 470 | |
| | 471 | /* goto *(prog->bpf_func + X86_TAIL_CALL_OFFSET); */ |
| 403 | EMIT4(0x48, 0x8B, 0x49, /* mov rcx, qword ptr [rcx + 32] */ | 472 | EMIT4(0x48, 0x8B, 0x49, /* mov rcx, qword ptr [rcx + 32] */ |
| 404 | offsetof(struct bpf_prog, bpf_func)); | 473 | offsetof(struct bpf_prog, bpf_func)); |
| 405 | EMIT4(0x48, 0x83, 0xC1, PROLOGUE_SIZE); /* add rcx, prologue_size */ | 474 | EMIT4(0x48, 0x83, 0xC1, /* add rcx, X86_TAIL_CALL_OFFSET */ |
| 406 | | 475 | X86_TAIL_CALL_OFFSET); |
| 407 | /* | 476 | /* |
| 408 | * Now we're ready to jump into next BPF program | 477 | * Now we're ready to jump into next BPF program |
| 409 | * rdi == ctx (1st arg) | 478 | * rdi == ctx (1st arg) |
| 410 | * rcx == prog->bpf_func + prologue_size | 479 | * rcx == prog->bpf_func + X86_TAIL_CALL_OFFSET |
| 411 | */ | 480 | */ |
| 412 | RETPOLINE_RCX_BPF_JIT(); | 481 | RETPOLINE_RCX_BPF_JIT(); |
| 413 | | 482 | |
| 414 | /* out: */ | 483 | /* out: */ |
| 415 | BUILD_BUG_ON(cnt - label1 != OFFSET1); | | |
| 416 | BUILD_BUG_ON(cnt - label2 != OFFSET2); | | |
| 417 | BUILD_BUG_ON(cnt - label3 != OFFSET3); | | |
| 418 | *pprog = prog; | 484 | *pprog = prog; |
| 419 | } | 485 | } |
| 420 | | 486 | |
| 421 | static void emit_bpf_tail_call_direct(struct bpf_jit_poke_descriptor *poke, | 487 | static void emit_bpf_tail_call_direct(struct bpf_jit_poke_descriptor *poke, |
| 422 | u8 **pprog, int addr, u8 *image) | 488 | u8 **pprog, int addr, u8 *image, |
| | 489 | bool *callee_regs_used, u32 stack_depth) |
| 423 | { | 490 | { |
| | 491 | int tcc_off = -4 - round_up(stack_depth, 8); |
| 424 | u8 *prog = *pprog; | 492 | u8 *prog = *pprog; |
| | 493 | int pop_bytes = 0; |
| | 494 | int off1 = 27; |
| | 495 | int poke_off; |
| 425 | int cnt = 0; | 496 | int cnt = 0; |
| 426 | | 497 | |
| | 498 | /* count the additional bytes used for popping callee regs to stack |
| | 499 | * that need to be taken into account for jump offset that is used for |
| | 500 | * bailing out from of the tail call when limit is reached |
| | 501 | */ |
| | 502 | pop_bytes = get_pop_bytes(callee_regs_used); |
| | 503 | off1 += pop_bytes; |
| | 504 | |
| | 505 | /* |
| | 506 | * total bytes for: |
| | 507 | * - nop5/ jmpq $off |
| | 508 | * - pop callee regs |
| | 509 | * - sub rsp, $val |
| | 510 | * - pop rax |
| | 511 | */ |
| | 512 | poke_off = X86_PATCH_SIZE + pop_bytes + 7 + 1; |
| | 513 | |
| 427 | /* | 514 | /* |
| 428 | * if (tail_call_cnt > MAX_TAIL_CALL_CNT) | 515 | * if (tail_call_cnt > MAX_TAIL_CALL_CNT) |
| 429 | * goto out; | 516 | * goto out; |
| 430 | */ | 517 | */ |
| 431 | EMIT2_off32(0x8B, 0x85, -36 - MAX_BPF_STACK); /* mov eax, dword ptr [rbp - 548] */ | 518 | EMIT2_off32(0x8B, 0x85, tcc_off); /* mov eax, dword ptr [rbp - tcc_off] */ |
| 432 | EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */ | 519 | EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */ |
| 433 | EMIT2(X86_JA, 14); /* ja out */ | 520 | EMIT2(X86_JA, off1); /* ja out */ |
| 434 | EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */ | 521 | EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */ |
| 435 | EMIT2_off32(0x89, 0x85, -36 - MAX_BPF_STACK); /* mov dword ptr [rbp -548], eax */ | 522 | EMIT2_off32(0x89, 0x85, tcc_off); /* mov dword ptr [rbp - tcc_off], eax */ |
| 436 | | 523 | |
| | 524 | poke->tailcall_bypass = image + (addr - poke_off - X86_PATCH_SIZE); |
| | 525 | poke->adj_off = X86_TAIL_CALL_OFFSET; |
| 437 | poke->tailcall_target = image + (addr - X86_PATCH_SIZE); | 526 | poke->tailcall_target = image + (addr - X86_PATCH_SIZE); |
| 438 | poke->adj_off = PROLOGUE_SIZE; | 527 | poke->bypass_addr = (u8 *)poke->tailcall_target + X86_PATCH_SIZE; |
| | 528 | |
| | 529 | emit_jump(&prog, (u8 *)poke->tailcall_target + X86_PATCH_SIZE, |
| | 530 | poke->tailcall_bypass); |
| | 531 | |
| | 532 | *pprog = prog; |
| | 533 | pop_callee_regs(pprog, callee_regs_used); |
| | 534 | prog = *pprog; |
| | 535 | EMIT1(0x58); /* pop rax */ |
| | 536 | EMIT3_off32(0x48, 0x81, 0xC4, round_up(stack_depth, 8)); |
| 439 | | 537 | |
| 440 | memcpy(prog, ideal_nops[NOP_ATOMIC5], X86_PATCH_SIZE); | 538 | memcpy(prog, ideal_nops[NOP_ATOMIC5], X86_PATCH_SIZE); |
| 441 | prog += X86_PATCH_SIZE; | 539 | prog += X86_PATCH_SIZE; |
| @@ -476,6 +574,11 @@ static void bpf_tail_call_direct_fixup(struct bpf_prog *prog) · 34 unmodified lines |
| 476 | (u8 *)target->bpf_func + | 574 | (u8 *)target->bpf_func + |
| 477 | poke->adj_off, false); | 575 | poke->adj_off, false); |
| 478 | BUG_ON(ret < 0); | 576 | BUG_ON(ret < 0); |
| | 577 | ret = __bpf_arch_text_poke(poke->tailcall_bypass, |
| | 578 | BPF_MOD_JUMP, |
| | 579 | (u8 *)poke->tailcall_target + |
| | 580 | X86_PATCH_SIZE, NULL, false); |
| | 581 | BUG_ON(ret < 0); |
| 479 | } | 582 | } |
| 480 | WRITE_ONCE(poke->tailcall_target_stable, true); | 583 | WRITE_ONCE(poke->tailcall_target_stable, true); |
| 481 | mutex_unlock(&array->aux->poke_mutex); | 584 | mutex_unlock(&array->aux->poke_mutex); |
| @@ -654,19 +757,49 @@ static bool ex_handler_bpf(const struct exception_table_entry *x, · 172 unmodified lines |
| 654 | return true; | 757 | return true; |
| 655 | } | 758 | } |
| 656 | | 759 | |
| | 760 | static void detect_reg_usage(struct bpf_insn *insn, int insn_cnt, |
| | 761 | bool *regs_used, bool *tail_call_seen) |
| | 762 | { |
| | 763 | int i; |
| | 764 | |
| | 765 | for (i = 1; i <= insn_cnt; i++, insn++) { |
| | 766 | if (insn->code == (BPF_JMP | BPF_TAIL_CALL)) |
| | 767 | *tail_call_seen = true; |
| | 768 | if (insn->dst_reg == BPF_REG_6 || insn->src_reg == BPF_REG_6) |
| | 769 | regs_used[0] = true; |
| | 770 | if (insn->dst_reg == BPF_REG_7 || insn->src_reg == BPF_REG_7) |
| | 771 | regs_used[1] = true; |
| | 772 | if (insn->dst_reg == BPF_REG_8 || insn->src_reg == BPF_REG_8) |
| | 773 | regs_used[2] = true; |
| | 774 | if (insn->dst_reg == BPF_REG_9 || insn->src_reg == BPF_REG_9) |
| | 775 | regs_used[3] = true; |
| | 776 | } |
| | 777 | } |
| | 778 | |
| 657 | static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, | 779 | static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, |
| 658 | int oldproglen, struct jit_context *ctx) | 780 | int oldproglen, struct jit_context *ctx) |
| 659 | { | 781 | { |
| | 782 | bool tail_call_reachable = bpf_prog->aux->tail_call_reachable; |
| 660 | struct bpf_insn *insn = bpf_prog->insnsi; | 783 | struct bpf_insn *insn = bpf_prog->insnsi; |
| | 784 | bool callee_regs_used[4] = {}; |
| 661 | int insn_cnt = bpf_prog->len; | 785 | int insn_cnt = bpf_prog->len; |
| | 786 | bool tail_call_seen = false; |
| 662 | bool seen_exit = false; | 787 | bool seen_exit = false; |
| 663 | u8 temp[BPF_MAX_INSN_SIZE + BPF_INSN_SAFETY]; | 788 | u8 temp[BPF_MAX_INSN_SIZE + BPF_INSN_SAFETY]; |
| 664 | int i, cnt = 0, excnt = 0; | 789 | int i, cnt = 0, excnt = 0; |
| 665 | int proglen = 0; | 790 | int proglen = 0; |
| 666 | u8 *prog = temp; | 791 | u8 *prog = temp; |
| 667 | | 792 | |
| | 793 | detect_reg_usage(insn, insn_cnt, callee_regs_used, |
| | 794 | &tail_call_seen); |
| | 795 | |
| | 796 | /* tail call's presence in current prog implies it is reachable */ |
| | 797 | tail_call_reachable |= tail_call_seen; |
| | 798 | |
| 668 | emit_prologue(&prog, bpf_prog->aux->stack_depth, | 799 | emit_prologue(&prog, bpf_prog->aux->stack_depth, |
| 669 | bpf_prog_was_classic(bpf_prog)); | 800 | bpf_prog_was_classic(bpf_prog), tail_call_reachable, |
| | 801 | bpf_prog->aux->func_idx != 0); |
| | 802 | push_callee_regs(&prog, callee_regs_used); |
| 670 | addrs[0] = prog - temp; | 803 | addrs[0] = prog - temp; |
| 671 | | 804 | |
| 672 | for (i = 1; i <= insn_cnt; i++, insn++) { | 805 | for (i = 1; i <= insn_cnt; i++, insn++) { |
| @@ -1104,16 +1237,27 @@ xadd: if (is_imm8(insn->off)) · 431 unmodified lines |
| 1104 | /* call */ | 1237 | /* call */ |
| 1105 | case BPF_JMP | BPF_CALL: | 1238 | case BPF_JMP | BPF_CALL: |
| 1106 | func = (u8 *) __bpf_call_base + imm32; | 1239 | func = (u8 *) __bpf_call_base + imm32; |
| 1107 | if (!imm32 || emit_call(&prog, func, image + addrs[i - 1])) | 1240 | if (tail_call_reachable) { |
| 1108 | return -EINVAL; | 1241 | EMIT3_off32(0x48, 0x8B, 0x85, |
| | 1242 | -(bpf_prog->aux->stack_depth + 8)); |
| | 1243 | if (!imm32 || emit_call(&prog, func, image + addrs[i - 1] + 7)) |
| | 1244 | return -EINVAL; |
| | 1245 | } else { |
| | 1246 | if (!imm32 || emit_call(&prog, func, image + addrs[i - 1])) |
| | 1247 | return -EINVAL; |
| | 1248 | } |
| 1109 | break; | 1249 | break; |
| 1110 | | 1250 | |
| 1111 | case BPF_JMP | BPF_TAIL_CALL: | 1251 | case BPF_JMP | BPF_TAIL_CALL: |
| 1112 | if (imm32) | 1252 | if (imm32) |
| 1113 | emit_bpf_tail_call_direct(&bpf_prog->aux->poke_tab[imm32 - 1], | 1253 | emit_bpf_tail_call_direct(&bpf_prog->aux->poke_tab[imm32 - 1], |
| 1114 | &prog, addrs[i], image); | 1254 | &prog, addrs[i], image, |
| | 1255 | callee_regs_used, |
| | 1256 | bpf_prog->aux->stack_depth); |
| 1115 | else | 1257 | else |
| 1116 | emit_bpf_tail_call_indirect(&prog); | 1258 | emit_bpf_tail_call_indirect(&prog, |
| | 1259 | callee_regs_used, |
| | 1260 | bpf_prog->aux->stack_depth); |
| 1117 | break; | 1261 | break; |
| 1118 | | 1262 | |
| 1119 | /* cond jump */ | 1263 | /* cond jump */ |
| @@ -1296,12 +1440,9 @@ emit_jmp: · 176 unmodified lines |
| 1296 | seen_exit = true; | 1440 | seen_exit = true; |
| 1297 | /* Update cleanup_addr */ | 1441 | /* Update cleanup_addr */ |
| 1298 | ctx->cleanup_addr = proglen; | 1442 | ctx->cleanup_addr = proglen; |
| 1299 | if (!bpf_prog_was_classic(bpf_prog)) | 1443 | pop_callee_regs(&prog, callee_regs_used); |
| 1300 | EMIT1(0x5B); /* get rid of tail_call_cnt */ | 1444 | if (tail_call_reachable) |
| 1301 | EMIT2(0x41, 0x5F); /* pop r15 */ | 1445 | EMIT1(0x59); /* pop rcx, get rid of tail_call_cnt */ |
| 1302 | EMIT2(0x41, 0x5E); /* pop r14 */ | | |
| 1303 | EMIT2(0x41, 0x5D); /* pop r13 */ | | |
| 1304 | EMIT1(0x5B); /* pop rbx */ | | |
| 1305 | EMIT1(0xC9); /* leave */ | 1446 | EMIT1(0xC9); /* leave */ |
| 1306 | EMIT1(0xC3); /* ret */ | 1447 | EMIT1(0xC3); /* ret */ |
| 1307 | break; | 1448 | break; |