diff options
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | arch/x86/net/bpf_jit_comp32.c | 284 | ||||
-rw-r--r-- | include/net/xdp_sock.h | 5 | ||||
-rw-r--r-- | include/uapi/linux/bpf.h | 1 | ||||
-rw-r--r-- | kernel/bpf/btf.c | 12 | ||||
-rw-r--r-- | kernel/bpf/core.c | 4 | ||||
-rw-r--r-- | net/core/filter.c | 2 | ||||
-rw-r--r-- | net/xdp/xdp_umem.c | 21 | ||||
-rw-r--r-- | net/xdp/xdp_umem.h | 1 | ||||
-rw-r--r-- | net/xdp/xsk.c | 87 | ||||
-rw-r--r-- | net/xdp/xsk_queue.h | 2 | ||||
-rw-r--r-- | samples/bpf/xdp_redirect_user.c | 2 | ||||
-rw-r--r-- | tools/bpf/bpftool/cgroup.c | 6 | ||||
-rw-r--r-- | tools/include/uapi/linux/bpf.h | 1 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/progs/test_lwt_seg6local.c | 12 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/verifier/basic_instr.c | 85 |
16 files changed, 230 insertions, 296 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 3c4d72755127..54691cc484da 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -17274,6 +17274,7 @@ N: xdp | |||
17274 | XDP SOCKETS (AF_XDP) | 17274 | XDP SOCKETS (AF_XDP) |
17275 | M: Björn Töpel <bjorn.topel@intel.com> | 17275 | M: Björn Töpel <bjorn.topel@intel.com> |
17276 | M: Magnus Karlsson <magnus.karlsson@intel.com> | 17276 | M: Magnus Karlsson <magnus.karlsson@intel.com> |
17277 | R: Jonathan Lemon <jonathan.lemon@gmail.com> | ||
17277 | L: netdev@vger.kernel.org | 17278 | L: netdev@vger.kernel.org |
17278 | L: bpf@vger.kernel.org | 17279 | L: bpf@vger.kernel.org |
17279 | S: Maintained | 17280 | S: Maintained |
diff --git a/arch/x86/net/bpf_jit_comp32.c b/arch/x86/net/bpf_jit_comp32.c index b29e82f190c7..1d12d2174085 100644 --- a/arch/x86/net/bpf_jit_comp32.c +++ b/arch/x86/net/bpf_jit_comp32.c | |||
@@ -724,9 +724,6 @@ static inline void emit_ia32_lsh_r64(const u8 dst[], const u8 src[], | |||
724 | { | 724 | { |
725 | u8 *prog = *pprog; | 725 | u8 *prog = *pprog; |
726 | int cnt = 0; | 726 | int cnt = 0; |
727 | static int jmp_label1 = -1; | ||
728 | static int jmp_label2 = -1; | ||
729 | static int jmp_label3 = -1; | ||
730 | u8 dreg_lo = dstk ? IA32_EAX : dst_lo; | 727 | u8 dreg_lo = dstk ? IA32_EAX : dst_lo; |
731 | u8 dreg_hi = dstk ? IA32_EDX : dst_hi; | 728 | u8 dreg_hi = dstk ? IA32_EDX : dst_hi; |
732 | 729 | ||
@@ -745,79 +742,23 @@ static inline void emit_ia32_lsh_r64(const u8 dst[], const u8 src[], | |||
745 | /* mov ecx,src_lo */ | 742 | /* mov ecx,src_lo */ |
746 | EMIT2(0x8B, add_2reg(0xC0, src_lo, IA32_ECX)); | 743 | EMIT2(0x8B, add_2reg(0xC0, src_lo, IA32_ECX)); |
747 | 744 | ||
748 | /* cmp ecx,32 */ | 745 | /* shld dreg_hi,dreg_lo,cl */ |
749 | EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32); | 746 | EMIT3(0x0F, 0xA5, add_2reg(0xC0, dreg_hi, dreg_lo)); |
750 | /* Jumps when >= 32 */ | ||
751 | if (is_imm8(jmp_label(jmp_label1, 2))) | ||
752 | EMIT2(IA32_JAE, jmp_label(jmp_label1, 2)); | ||
753 | else | ||
754 | EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label1, 6)); | ||
755 | |||
756 | /* < 32 */ | ||
757 | /* shl dreg_hi,cl */ | ||
758 | EMIT2(0xD3, add_1reg(0xE0, dreg_hi)); | ||
759 | /* mov ebx,dreg_lo */ | ||
760 | EMIT2(0x8B, add_2reg(0xC0, dreg_lo, IA32_EBX)); | ||
761 | /* shl dreg_lo,cl */ | 747 | /* shl dreg_lo,cl */ |
762 | EMIT2(0xD3, add_1reg(0xE0, dreg_lo)); | 748 | EMIT2(0xD3, add_1reg(0xE0, dreg_lo)); |
763 | 749 | ||
764 | /* IA32_ECX = -IA32_ECX + 32 */ | 750 | /* if ecx >= 32, mov dreg_lo into dreg_hi and clear dreg_lo */ |
765 | /* neg ecx */ | ||
766 | EMIT2(0xF7, add_1reg(0xD8, IA32_ECX)); | ||
767 | /* add ecx,32 */ | ||
768 | EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32); | ||
769 | 751 | ||
770 | /* shr ebx,cl */ | 752 | /* cmp ecx,32 */ |
771 | EMIT2(0xD3, add_1reg(0xE8, IA32_EBX)); | 753 | EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32); |
772 | /* or dreg_hi,ebx */ | 754 | /* skip the next two instructions (4 bytes) when < 32 */ |
773 | EMIT2(0x09, add_2reg(0xC0, dreg_hi, IA32_EBX)); | 755 | EMIT2(IA32_JB, 4); |
774 | |||
775 | /* goto out; */ | ||
776 | if (is_imm8(jmp_label(jmp_label3, 2))) | ||
777 | EMIT2(0xEB, jmp_label(jmp_label3, 2)); | ||
778 | else | ||
779 | EMIT1_off32(0xE9, jmp_label(jmp_label3, 5)); | ||
780 | |||
781 | /* >= 32 */ | ||
782 | if (jmp_label1 == -1) | ||
783 | jmp_label1 = cnt; | ||
784 | |||
785 | /* cmp ecx,64 */ | ||
786 | EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 64); | ||
787 | /* Jumps when >= 64 */ | ||
788 | if (is_imm8(jmp_label(jmp_label2, 2))) | ||
789 | EMIT2(IA32_JAE, jmp_label(jmp_label2, 2)); | ||
790 | else | ||
791 | EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label2, 6)); | ||
792 | 756 | ||
793 | /* >= 32 && < 64 */ | ||
794 | /* sub ecx,32 */ | ||
795 | EMIT3(0x83, add_1reg(0xE8, IA32_ECX), 32); | ||
796 | /* shl dreg_lo,cl */ | ||
797 | EMIT2(0xD3, add_1reg(0xE0, dreg_lo)); | ||
798 | /* mov dreg_hi,dreg_lo */ | 757 | /* mov dreg_hi,dreg_lo */ |
799 | EMIT2(0x89, add_2reg(0xC0, dreg_hi, dreg_lo)); | 758 | EMIT2(0x89, add_2reg(0xC0, dreg_hi, dreg_lo)); |
800 | |||
801 | /* xor dreg_lo,dreg_lo */ | 759 | /* xor dreg_lo,dreg_lo */ |
802 | EMIT2(0x33, add_2reg(0xC0, dreg_lo, dreg_lo)); | 760 | EMIT2(0x33, add_2reg(0xC0, dreg_lo, dreg_lo)); |
803 | 761 | ||
804 | /* goto out; */ | ||
805 | if (is_imm8(jmp_label(jmp_label3, 2))) | ||
806 | EMIT2(0xEB, jmp_label(jmp_label3, 2)); | ||
807 | else | ||
808 | EMIT1_off32(0xE9, jmp_label(jmp_label3, 5)); | ||
809 | |||
810 | /* >= 64 */ | ||
811 | if (jmp_label2 == -1) | ||
812 | jmp_label2 = cnt; | ||
813 | /* xor dreg_lo,dreg_lo */ | ||
814 | EMIT2(0x33, add_2reg(0xC0, dreg_lo, dreg_lo)); | ||
815 | /* xor dreg_hi,dreg_hi */ | ||
816 | EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); | ||
817 | |||
818 | if (jmp_label3 == -1) | ||
819 | jmp_label3 = cnt; | ||
820 | |||
821 | if (dstk) { | 762 | if (dstk) { |
822 | /* mov dword ptr [ebp+off],dreg_lo */ | 763 | /* mov dword ptr [ebp+off],dreg_lo */ |
823 | EMIT3(0x89, add_2reg(0x40, IA32_EBP, dreg_lo), | 764 | EMIT3(0x89, add_2reg(0x40, IA32_EBP, dreg_lo), |
@@ -836,9 +777,6 @@ static inline void emit_ia32_arsh_r64(const u8 dst[], const u8 src[], | |||
836 | { | 777 | { |
837 | u8 *prog = *pprog; | 778 | u8 *prog = *pprog; |
838 | int cnt = 0; | 779 | int cnt = 0; |
839 | static int jmp_label1 = -1; | ||
840 | static int jmp_label2 = -1; | ||
841 | static int jmp_label3 = -1; | ||
842 | u8 dreg_lo = dstk ? IA32_EAX : dst_lo; | 780 | u8 dreg_lo = dstk ? IA32_EAX : dst_lo; |
843 | u8 dreg_hi = dstk ? IA32_EDX : dst_hi; | 781 | u8 dreg_hi = dstk ? IA32_EDX : dst_hi; |
844 | 782 | ||
@@ -857,79 +795,23 @@ static inline void emit_ia32_arsh_r64(const u8 dst[], const u8 src[], | |||
857 | /* mov ecx,src_lo */ | 795 | /* mov ecx,src_lo */ |
858 | EMIT2(0x8B, add_2reg(0xC0, src_lo, IA32_ECX)); | 796 | EMIT2(0x8B, add_2reg(0xC0, src_lo, IA32_ECX)); |
859 | 797 | ||
860 | /* cmp ecx,32 */ | 798 | /* shrd dreg_lo,dreg_hi,cl */ |
861 | EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32); | 799 | EMIT3(0x0F, 0xAD, add_2reg(0xC0, dreg_lo, dreg_hi)); |
862 | /* Jumps when >= 32 */ | 800 | /* sar dreg_hi,cl */ |
863 | if (is_imm8(jmp_label(jmp_label1, 2))) | ||
864 | EMIT2(IA32_JAE, jmp_label(jmp_label1, 2)); | ||
865 | else | ||
866 | EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label1, 6)); | ||
867 | |||
868 | /* < 32 */ | ||
869 | /* lshr dreg_lo,cl */ | ||
870 | EMIT2(0xD3, add_1reg(0xE8, dreg_lo)); | ||
871 | /* mov ebx,dreg_hi */ | ||
872 | EMIT2(0x8B, add_2reg(0xC0, dreg_hi, IA32_EBX)); | ||
873 | /* ashr dreg_hi,cl */ | ||
874 | EMIT2(0xD3, add_1reg(0xF8, dreg_hi)); | 801 | EMIT2(0xD3, add_1reg(0xF8, dreg_hi)); |
875 | 802 | ||
876 | /* IA32_ECX = -IA32_ECX + 32 */ | 803 | /* if ecx >= 32, mov dreg_hi to dreg_lo and set/clear dreg_hi depending on sign */ |
877 | /* neg ecx */ | ||
878 | EMIT2(0xF7, add_1reg(0xD8, IA32_ECX)); | ||
879 | /* add ecx,32 */ | ||
880 | EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32); | ||
881 | |||
882 | /* shl ebx,cl */ | ||
883 | EMIT2(0xD3, add_1reg(0xE0, IA32_EBX)); | ||
884 | /* or dreg_lo,ebx */ | ||
885 | EMIT2(0x09, add_2reg(0xC0, dreg_lo, IA32_EBX)); | ||
886 | 804 | ||
887 | /* goto out; */ | 805 | /* cmp ecx,32 */ |
888 | if (is_imm8(jmp_label(jmp_label3, 2))) | 806 | EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32); |
889 | EMIT2(0xEB, jmp_label(jmp_label3, 2)); | 807 | /* skip the next two instructions (5 bytes) when < 32 */ |
890 | else | 808 | EMIT2(IA32_JB, 5); |
891 | EMIT1_off32(0xE9, jmp_label(jmp_label3, 5)); | ||
892 | |||
893 | /* >= 32 */ | ||
894 | if (jmp_label1 == -1) | ||
895 | jmp_label1 = cnt; | ||
896 | |||
897 | /* cmp ecx,64 */ | ||
898 | EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 64); | ||
899 | /* Jumps when >= 64 */ | ||
900 | if (is_imm8(jmp_label(jmp_label2, 2))) | ||
901 | EMIT2(IA32_JAE, jmp_label(jmp_label2, 2)); | ||
902 | else | ||
903 | EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label2, 6)); | ||
904 | 809 | ||
905 | /* >= 32 && < 64 */ | ||
906 | /* sub ecx,32 */ | ||
907 | EMIT3(0x83, add_1reg(0xE8, IA32_ECX), 32); | ||
908 | /* ashr dreg_hi,cl */ | ||
909 | EMIT2(0xD3, add_1reg(0xF8, dreg_hi)); | ||
910 | /* mov dreg_lo,dreg_hi */ | 810 | /* mov dreg_lo,dreg_hi */ |
911 | EMIT2(0x89, add_2reg(0xC0, dreg_lo, dreg_hi)); | 811 | EMIT2(0x89, add_2reg(0xC0, dreg_lo, dreg_hi)); |
912 | 812 | /* sar dreg_hi,31 */ | |
913 | /* ashr dreg_hi,imm8 */ | ||
914 | EMIT3(0xC1, add_1reg(0xF8, dreg_hi), 31); | 813 | EMIT3(0xC1, add_1reg(0xF8, dreg_hi), 31); |
915 | 814 | ||
916 | /* goto out; */ | ||
917 | if (is_imm8(jmp_label(jmp_label3, 2))) | ||
918 | EMIT2(0xEB, jmp_label(jmp_label3, 2)); | ||
919 | else | ||
920 | EMIT1_off32(0xE9, jmp_label(jmp_label3, 5)); | ||
921 | |||
922 | /* >= 64 */ | ||
923 | if (jmp_label2 == -1) | ||
924 | jmp_label2 = cnt; | ||
925 | /* ashr dreg_hi,imm8 */ | ||
926 | EMIT3(0xC1, add_1reg(0xF8, dreg_hi), 31); | ||
927 | /* mov dreg_lo,dreg_hi */ | ||
928 | EMIT2(0x89, add_2reg(0xC0, dreg_lo, dreg_hi)); | ||
929 | |||
930 | if (jmp_label3 == -1) | ||
931 | jmp_label3 = cnt; | ||
932 | |||
933 | if (dstk) { | 815 | if (dstk) { |
934 | /* mov dword ptr [ebp+off],dreg_lo */ | 816 | /* mov dword ptr [ebp+off],dreg_lo */ |
935 | EMIT3(0x89, add_2reg(0x40, IA32_EBP, dreg_lo), | 817 | EMIT3(0x89, add_2reg(0x40, IA32_EBP, dreg_lo), |
@@ -948,9 +830,6 @@ static inline void emit_ia32_rsh_r64(const u8 dst[], const u8 src[], bool dstk, | |||
948 | { | 830 | { |
949 | u8 *prog = *pprog; | 831 | u8 *prog = *pprog; |
950 | int cnt = 0; | 832 | int cnt = 0; |
951 | static int jmp_label1 = -1; | ||
952 | static int jmp_label2 = -1; | ||
953 | static int jmp_label3 = -1; | ||
954 | u8 dreg_lo = dstk ? IA32_EAX : dst_lo; | 833 | u8 dreg_lo = dstk ? IA32_EAX : dst_lo; |
955 | u8 dreg_hi = dstk ? IA32_EDX : dst_hi; | 834 | u8 dreg_hi = dstk ? IA32_EDX : dst_hi; |
956 | 835 | ||
@@ -969,77 +848,23 @@ static inline void emit_ia32_rsh_r64(const u8 dst[], const u8 src[], bool dstk, | |||
969 | /* mov ecx,src_lo */ | 848 | /* mov ecx,src_lo */ |
970 | EMIT2(0x8B, add_2reg(0xC0, src_lo, IA32_ECX)); | 849 | EMIT2(0x8B, add_2reg(0xC0, src_lo, IA32_ECX)); |
971 | 850 | ||
972 | /* cmp ecx,32 */ | 851 | /* shrd dreg_lo,dreg_hi,cl */ |
973 | EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32); | 852 | EMIT3(0x0F, 0xAD, add_2reg(0xC0, dreg_lo, dreg_hi)); |
974 | /* Jumps when >= 32 */ | ||
975 | if (is_imm8(jmp_label(jmp_label1, 2))) | ||
976 | EMIT2(IA32_JAE, jmp_label(jmp_label1, 2)); | ||
977 | else | ||
978 | EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label1, 6)); | ||
979 | |||
980 | /* < 32 */ | ||
981 | /* lshr dreg_lo,cl */ | ||
982 | EMIT2(0xD3, add_1reg(0xE8, dreg_lo)); | ||
983 | /* mov ebx,dreg_hi */ | ||
984 | EMIT2(0x8B, add_2reg(0xC0, dreg_hi, IA32_EBX)); | ||
985 | /* shr dreg_hi,cl */ | 853 | /* shr dreg_hi,cl */ |
986 | EMIT2(0xD3, add_1reg(0xE8, dreg_hi)); | 854 | EMIT2(0xD3, add_1reg(0xE8, dreg_hi)); |
987 | 855 | ||
988 | /* IA32_ECX = -IA32_ECX + 32 */ | 856 | /* if ecx >= 32, mov dreg_hi to dreg_lo and clear dreg_hi */ |
989 | /* neg ecx */ | ||
990 | EMIT2(0xF7, add_1reg(0xD8, IA32_ECX)); | ||
991 | /* add ecx,32 */ | ||
992 | EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32); | ||
993 | |||
994 | /* shl ebx,cl */ | ||
995 | EMIT2(0xD3, add_1reg(0xE0, IA32_EBX)); | ||
996 | /* or dreg_lo,ebx */ | ||
997 | EMIT2(0x09, add_2reg(0xC0, dreg_lo, IA32_EBX)); | ||
998 | |||
999 | /* goto out; */ | ||
1000 | if (is_imm8(jmp_label(jmp_label3, 2))) | ||
1001 | EMIT2(0xEB, jmp_label(jmp_label3, 2)); | ||
1002 | else | ||
1003 | EMIT1_off32(0xE9, jmp_label(jmp_label3, 5)); | ||
1004 | 857 | ||
1005 | /* >= 32 */ | 858 | /* cmp ecx,32 */ |
1006 | if (jmp_label1 == -1) | 859 | EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 32); |
1007 | jmp_label1 = cnt; | 860 | /* skip the next two instructions (4 bytes) when < 32 */ |
1008 | /* cmp ecx,64 */ | 861 | EMIT2(IA32_JB, 4); |
1009 | EMIT3(0x83, add_1reg(0xF8, IA32_ECX), 64); | ||
1010 | /* Jumps when >= 64 */ | ||
1011 | if (is_imm8(jmp_label(jmp_label2, 2))) | ||
1012 | EMIT2(IA32_JAE, jmp_label(jmp_label2, 2)); | ||
1013 | else | ||
1014 | EMIT2_off32(0x0F, IA32_JAE + 0x10, jmp_label(jmp_label2, 6)); | ||
1015 | 862 | ||
1016 | /* >= 32 && < 64 */ | ||
1017 | /* sub ecx,32 */ | ||
1018 | EMIT3(0x83, add_1reg(0xE8, IA32_ECX), 32); | ||
1019 | /* shr dreg_hi,cl */ | ||
1020 | EMIT2(0xD3, add_1reg(0xE8, dreg_hi)); | ||
1021 | /* mov dreg_lo,dreg_hi */ | 863 | /* mov dreg_lo,dreg_hi */ |
1022 | EMIT2(0x89, add_2reg(0xC0, dreg_lo, dreg_hi)); | 864 | EMIT2(0x89, add_2reg(0xC0, dreg_lo, dreg_hi)); |
1023 | /* xor dreg_hi,dreg_hi */ | 865 | /* xor dreg_hi,dreg_hi */ |
1024 | EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); | 866 | EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); |
1025 | 867 | ||
1026 | /* goto out; */ | ||
1027 | if (is_imm8(jmp_label(jmp_label3, 2))) | ||
1028 | EMIT2(0xEB, jmp_label(jmp_label3, 2)); | ||
1029 | else | ||
1030 | EMIT1_off32(0xE9, jmp_label(jmp_label3, 5)); | ||
1031 | |||
1032 | /* >= 64 */ | ||
1033 | if (jmp_label2 == -1) | ||
1034 | jmp_label2 = cnt; | ||
1035 | /* xor dreg_lo,dreg_lo */ | ||
1036 | EMIT2(0x33, add_2reg(0xC0, dreg_lo, dreg_lo)); | ||
1037 | /* xor dreg_hi,dreg_hi */ | ||
1038 | EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); | ||
1039 | |||
1040 | if (jmp_label3 == -1) | ||
1041 | jmp_label3 = cnt; | ||
1042 | |||
1043 | if (dstk) { | 868 | if (dstk) { |
1044 | /* mov dword ptr [ebp+off],dreg_lo */ | 869 | /* mov dword ptr [ebp+off],dreg_lo */ |
1045 | EMIT3(0x89, add_2reg(0x40, IA32_EBP, dreg_lo), | 870 | EMIT3(0x89, add_2reg(0x40, IA32_EBP, dreg_lo), |
@@ -1069,27 +894,10 @@ static inline void emit_ia32_lsh_i64(const u8 dst[], const u32 val, | |||
1069 | } | 894 | } |
1070 | /* Do LSH operation */ | 895 | /* Do LSH operation */ |
1071 | if (val < 32) { | 896 | if (val < 32) { |
1072 | /* shl dreg_hi,imm8 */ | 897 | /* shld dreg_hi,dreg_lo,imm8 */ |
1073 | EMIT3(0xC1, add_1reg(0xE0, dreg_hi), val); | 898 | EMIT4(0x0F, 0xA4, add_2reg(0xC0, dreg_hi, dreg_lo), val); |
1074 | /* mov ebx,dreg_lo */ | ||
1075 | EMIT2(0x8B, add_2reg(0xC0, dreg_lo, IA32_EBX)); | ||
1076 | /* shl dreg_lo,imm8 */ | 899 | /* shl dreg_lo,imm8 */ |
1077 | EMIT3(0xC1, add_1reg(0xE0, dreg_lo), val); | 900 | EMIT3(0xC1, add_1reg(0xE0, dreg_lo), val); |
1078 | |||
1079 | /* IA32_ECX = 32 - val */ | ||
1080 | /* mov ecx,val */ | ||
1081 | EMIT2(0xB1, val); | ||
1082 | /* movzx ecx,ecx */ | ||
1083 | EMIT3(0x0F, 0xB6, add_2reg(0xC0, IA32_ECX, IA32_ECX)); | ||
1084 | /* neg ecx */ | ||
1085 | EMIT2(0xF7, add_1reg(0xD8, IA32_ECX)); | ||
1086 | /* add ecx,32 */ | ||
1087 | EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32); | ||
1088 | |||
1089 | /* shr ebx,cl */ | ||
1090 | EMIT2(0xD3, add_1reg(0xE8, IA32_EBX)); | ||
1091 | /* or dreg_hi,ebx */ | ||
1092 | EMIT2(0x09, add_2reg(0xC0, dreg_hi, IA32_EBX)); | ||
1093 | } else if (val >= 32 && val < 64) { | 901 | } else if (val >= 32 && val < 64) { |
1094 | u32 value = val - 32; | 902 | u32 value = val - 32; |
1095 | 903 | ||
@@ -1135,27 +943,10 @@ static inline void emit_ia32_rsh_i64(const u8 dst[], const u32 val, | |||
1135 | 943 | ||
1136 | /* Do RSH operation */ | 944 | /* Do RSH operation */ |
1137 | if (val < 32) { | 945 | if (val < 32) { |
1138 | /* shr dreg_lo,imm8 */ | 946 | /* shrd dreg_lo,dreg_hi,imm8 */ |
1139 | EMIT3(0xC1, add_1reg(0xE8, dreg_lo), val); | 947 | EMIT4(0x0F, 0xAC, add_2reg(0xC0, dreg_lo, dreg_hi), val); |
1140 | /* mov ebx,dreg_hi */ | ||
1141 | EMIT2(0x8B, add_2reg(0xC0, dreg_hi, IA32_EBX)); | ||
1142 | /* shr dreg_hi,imm8 */ | 948 | /* shr dreg_hi,imm8 */ |
1143 | EMIT3(0xC1, add_1reg(0xE8, dreg_hi), val); | 949 | EMIT3(0xC1, add_1reg(0xE8, dreg_hi), val); |
1144 | |||
1145 | /* IA32_ECX = 32 - val */ | ||
1146 | /* mov ecx,val */ | ||
1147 | EMIT2(0xB1, val); | ||
1148 | /* movzx ecx,ecx */ | ||
1149 | EMIT3(0x0F, 0xB6, add_2reg(0xC0, IA32_ECX, IA32_ECX)); | ||
1150 | /* neg ecx */ | ||
1151 | EMIT2(0xF7, add_1reg(0xD8, IA32_ECX)); | ||
1152 | /* add ecx,32 */ | ||
1153 | EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32); | ||
1154 | |||
1155 | /* shl ebx,cl */ | ||
1156 | EMIT2(0xD3, add_1reg(0xE0, IA32_EBX)); | ||
1157 | /* or dreg_lo,ebx */ | ||
1158 | EMIT2(0x09, add_2reg(0xC0, dreg_lo, IA32_EBX)); | ||
1159 | } else if (val >= 32 && val < 64) { | 950 | } else if (val >= 32 && val < 64) { |
1160 | u32 value = val - 32; | 951 | u32 value = val - 32; |
1161 | 952 | ||
@@ -1200,27 +991,10 @@ static inline void emit_ia32_arsh_i64(const u8 dst[], const u32 val, | |||
1200 | } | 991 | } |
1201 | /* Do RSH operation */ | 992 | /* Do RSH operation */ |
1202 | if (val < 32) { | 993 | if (val < 32) { |
1203 | /* shr dreg_lo,imm8 */ | 994 | /* shrd dreg_lo,dreg_hi,imm8 */ |
1204 | EMIT3(0xC1, add_1reg(0xE8, dreg_lo), val); | 995 | EMIT4(0x0F, 0xAC, add_2reg(0xC0, dreg_lo, dreg_hi), val); |
1205 | /* mov ebx,dreg_hi */ | ||
1206 | EMIT2(0x8B, add_2reg(0xC0, dreg_hi, IA32_EBX)); | ||
1207 | /* ashr dreg_hi,imm8 */ | 996 | /* ashr dreg_hi,imm8 */ |
1208 | EMIT3(0xC1, add_1reg(0xF8, dreg_hi), val); | 997 | EMIT3(0xC1, add_1reg(0xF8, dreg_hi), val); |
1209 | |||
1210 | /* IA32_ECX = 32 - val */ | ||
1211 | /* mov ecx,val */ | ||
1212 | EMIT2(0xB1, val); | ||
1213 | /* movzx ecx,ecx */ | ||
1214 | EMIT3(0x0F, 0xB6, add_2reg(0xC0, IA32_ECX, IA32_ECX)); | ||
1215 | /* neg ecx */ | ||
1216 | EMIT2(0xF7, add_1reg(0xD8, IA32_ECX)); | ||
1217 | /* add ecx,32 */ | ||
1218 | EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32); | ||
1219 | |||
1220 | /* shl ebx,cl */ | ||
1221 | EMIT2(0xD3, add_1reg(0xE0, IA32_EBX)); | ||
1222 | /* or dreg_lo,ebx */ | ||
1223 | EMIT2(0x09, add_2reg(0xC0, dreg_lo, IA32_EBX)); | ||
1224 | } else if (val >= 32 && val < 64) { | 998 | } else if (val >= 32 && val < 64) { |
1225 | u32 value = val - 32; | 999 | u32 value = val - 32; |
1226 | 1000 | ||
diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h index d074b6d60f8a..7da155164947 100644 --- a/include/net/xdp_sock.h +++ b/include/net/xdp_sock.h | |||
@@ -61,6 +61,11 @@ struct xdp_sock { | |||
61 | struct xsk_queue *tx ____cacheline_aligned_in_smp; | 61 | struct xsk_queue *tx ____cacheline_aligned_in_smp; |
62 | struct list_head list; | 62 | struct list_head list; |
63 | bool zc; | 63 | bool zc; |
64 | enum { | ||
65 | XSK_READY = 0, | ||
66 | XSK_BOUND, | ||
67 | XSK_UNBOUND, | ||
68 | } state; | ||
64 | /* Protects multiple processes in the control path */ | 69 | /* Protects multiple processes in the control path */ |
65 | struct mutex mutex; | 70 | struct mutex mutex; |
66 | /* Mutual exclusion of NAPI TX thread and sendmsg error paths | 71 | /* Mutual exclusion of NAPI TX thread and sendmsg error paths |
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index a8b823c30b43..29a5bc3d5c66 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h | |||
@@ -3143,6 +3143,7 @@ struct bpf_prog_info { | |||
3143 | char name[BPF_OBJ_NAME_LEN]; | 3143 | char name[BPF_OBJ_NAME_LEN]; |
3144 | __u32 ifindex; | 3144 | __u32 ifindex; |
3145 | __u32 gpl_compatible:1; | 3145 | __u32 gpl_compatible:1; |
3146 | __u32 :31; /* alignment pad */ | ||
3146 | __u64 netns_dev; | 3147 | __u64 netns_dev; |
3147 | __u64 netns_ino; | 3148 | __u64 netns_ino; |
3148 | __u32 nr_jited_ksyms; | 3149 | __u32 nr_jited_ksyms; |
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index cad09858a5f2..546ebee39e2a 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c | |||
@@ -1928,8 +1928,8 @@ static int btf_array_resolve(struct btf_verifier_env *env, | |||
1928 | /* Check array->index_type */ | 1928 | /* Check array->index_type */ |
1929 | index_type_id = array->index_type; | 1929 | index_type_id = array->index_type; |
1930 | index_type = btf_type_by_id(btf, index_type_id); | 1930 | index_type = btf_type_by_id(btf, index_type_id); |
1931 | if (btf_type_is_resolve_source_only(index_type) || | 1931 | if (btf_type_nosize_or_null(index_type) || |
1932 | btf_type_nosize_or_null(index_type)) { | 1932 | btf_type_is_resolve_source_only(index_type)) { |
1933 | btf_verifier_log_type(env, v->t, "Invalid index"); | 1933 | btf_verifier_log_type(env, v->t, "Invalid index"); |
1934 | return -EINVAL; | 1934 | return -EINVAL; |
1935 | } | 1935 | } |
@@ -1948,8 +1948,8 @@ static int btf_array_resolve(struct btf_verifier_env *env, | |||
1948 | /* Check array->type */ | 1948 | /* Check array->type */ |
1949 | elem_type_id = array->type; | 1949 | elem_type_id = array->type; |
1950 | elem_type = btf_type_by_id(btf, elem_type_id); | 1950 | elem_type = btf_type_by_id(btf, elem_type_id); |
1951 | if (btf_type_is_resolve_source_only(elem_type) || | 1951 | if (btf_type_nosize_or_null(elem_type) || |
1952 | btf_type_nosize_or_null(elem_type)) { | 1952 | btf_type_is_resolve_source_only(elem_type)) { |
1953 | btf_verifier_log_type(env, v->t, | 1953 | btf_verifier_log_type(env, v->t, |
1954 | "Invalid elem"); | 1954 | "Invalid elem"); |
1955 | return -EINVAL; | 1955 | return -EINVAL; |
@@ -2170,8 +2170,8 @@ static int btf_struct_resolve(struct btf_verifier_env *env, | |||
2170 | const struct btf_type *member_type = btf_type_by_id(env->btf, | 2170 | const struct btf_type *member_type = btf_type_by_id(env->btf, |
2171 | member_type_id); | 2171 | member_type_id); |
2172 | 2172 | ||
2173 | if (btf_type_is_resolve_source_only(member_type) || | 2173 | if (btf_type_nosize_or_null(member_type) || |
2174 | btf_type_nosize_or_null(member_type)) { | 2174 | btf_type_is_resolve_source_only(member_type)) { |
2175 | btf_verifier_log_member(env, v->t, member, | 2175 | btf_verifier_log_member(env, v->t, member, |
2176 | "Invalid member"); | 2176 | "Invalid member"); |
2177 | return -EINVAL; | 2177 | return -EINVAL; |
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 080e2bb644cc..f2148db91439 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c | |||
@@ -1364,10 +1364,10 @@ select_insn: | |||
1364 | insn++; | 1364 | insn++; |
1365 | CONT; | 1365 | CONT; |
1366 | ALU_ARSH_X: | 1366 | ALU_ARSH_X: |
1367 | DST = (u64) (u32) ((*(s32 *) &DST) >> SRC); | 1367 | DST = (u64) (u32) (((s32) DST) >> SRC); |
1368 | CONT; | 1368 | CONT; |
1369 | ALU_ARSH_K: | 1369 | ALU_ARSH_K: |
1370 | DST = (u64) (u32) ((*(s32 *) &DST) >> IMM); | 1370 | DST = (u64) (u32) (((s32) DST) >> IMM); |
1371 | CONT; | 1371 | CONT; |
1372 | ALU64_ARSH_X: | 1372 | ALU64_ARSH_X: |
1373 | (*(s64 *) &DST) >>= SRC; | 1373 | (*(s64 *) &DST) >>= SRC; |
diff --git a/net/core/filter.c b/net/core/filter.c index f615e42cf4ef..3fdf1b21be36 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -4737,7 +4737,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params, | |||
4737 | return -ENODEV; | 4737 | return -ENODEV; |
4738 | 4738 | ||
4739 | idev = __in6_dev_get_safely(dev); | 4739 | idev = __in6_dev_get_safely(dev); |
4740 | if (unlikely(!idev || !net->ipv6.devconf_all->forwarding)) | 4740 | if (unlikely(!idev || !idev->cnf.forwarding)) |
4741 | return BPF_FIB_LKUP_RET_FWD_DISABLED; | 4741 | return BPF_FIB_LKUP_RET_FWD_DISABLED; |
4742 | 4742 | ||
4743 | if (flags & BPF_FIB_LOOKUP_OUTPUT) { | 4743 | if (flags & BPF_FIB_LOOKUP_OUTPUT) { |
diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c index 9c6de4f114f8..20c91f02d3d8 100644 --- a/net/xdp/xdp_umem.c +++ b/net/xdp/xdp_umem.c | |||
@@ -105,6 +105,9 @@ int xdp_umem_assign_dev(struct xdp_umem *umem, struct net_device *dev, | |||
105 | 105 | ||
106 | umem->dev = dev; | 106 | umem->dev = dev; |
107 | umem->queue_id = queue_id; | 107 | umem->queue_id = queue_id; |
108 | |||
109 | dev_hold(dev); | ||
110 | |||
108 | if (force_copy) | 111 | if (force_copy) |
109 | /* For copy-mode, we are done. */ | 112 | /* For copy-mode, we are done. */ |
110 | goto out_rtnl_unlock; | 113 | goto out_rtnl_unlock; |
@@ -124,7 +127,6 @@ int xdp_umem_assign_dev(struct xdp_umem *umem, struct net_device *dev, | |||
124 | goto err_unreg_umem; | 127 | goto err_unreg_umem; |
125 | rtnl_unlock(); | 128 | rtnl_unlock(); |
126 | 129 | ||
127 | dev_hold(dev); | ||
128 | umem->zc = true; | 130 | umem->zc = true; |
129 | return 0; | 131 | return 0; |
130 | 132 | ||
@@ -138,11 +140,13 @@ out_rtnl_unlock: | |||
138 | return err; | 140 | return err; |
139 | } | 141 | } |
140 | 142 | ||
141 | static void xdp_umem_clear_dev(struct xdp_umem *umem) | 143 | void xdp_umem_clear_dev(struct xdp_umem *umem) |
142 | { | 144 | { |
143 | struct netdev_bpf bpf; | 145 | struct netdev_bpf bpf; |
144 | int err; | 146 | int err; |
145 | 147 | ||
148 | ASSERT_RTNL(); | ||
149 | |||
146 | if (!umem->dev) | 150 | if (!umem->dev) |
147 | return; | 151 | return; |
148 | 152 | ||
@@ -151,22 +155,17 @@ static void xdp_umem_clear_dev(struct xdp_umem *umem) | |||
151 | bpf.xsk.umem = NULL; | 155 | bpf.xsk.umem = NULL; |
152 | bpf.xsk.queue_id = umem->queue_id; | 156 | bpf.xsk.queue_id = umem->queue_id; |
153 | 157 | ||
154 | rtnl_lock(); | ||
155 | err = umem->dev->netdev_ops->ndo_bpf(umem->dev, &bpf); | 158 | err = umem->dev->netdev_ops->ndo_bpf(umem->dev, &bpf); |
156 | rtnl_unlock(); | ||
157 | 159 | ||
158 | if (err) | 160 | if (err) |
159 | WARN(1, "failed to disable umem!\n"); | 161 | WARN(1, "failed to disable umem!\n"); |
160 | } | 162 | } |
161 | 163 | ||
162 | rtnl_lock(); | ||
163 | xdp_clear_umem_at_qid(umem->dev, umem->queue_id); | 164 | xdp_clear_umem_at_qid(umem->dev, umem->queue_id); |
164 | rtnl_unlock(); | ||
165 | 165 | ||
166 | if (umem->zc) { | 166 | dev_put(umem->dev); |
167 | dev_put(umem->dev); | 167 | umem->dev = NULL; |
168 | umem->zc = false; | 168 | umem->zc = false; |
169 | } | ||
170 | } | 169 | } |
171 | 170 | ||
172 | static void xdp_umem_unpin_pages(struct xdp_umem *umem) | 171 | static void xdp_umem_unpin_pages(struct xdp_umem *umem) |
@@ -194,7 +193,9 @@ static void xdp_umem_unaccount_pages(struct xdp_umem *umem) | |||
194 | 193 | ||
195 | static void xdp_umem_release(struct xdp_umem *umem) | 194 | static void xdp_umem_release(struct xdp_umem *umem) |
196 | { | 195 | { |
196 | rtnl_lock(); | ||
197 | xdp_umem_clear_dev(umem); | 197 | xdp_umem_clear_dev(umem); |
198 | rtnl_unlock(); | ||
198 | 199 | ||
199 | ida_simple_remove(&umem_ida, umem->id); | 200 | ida_simple_remove(&umem_ida, umem->id); |
200 | 201 | ||
diff --git a/net/xdp/xdp_umem.h b/net/xdp/xdp_umem.h index 27603227601b..a63a9fb251f5 100644 --- a/net/xdp/xdp_umem.h +++ b/net/xdp/xdp_umem.h | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | int xdp_umem_assign_dev(struct xdp_umem *umem, struct net_device *dev, | 11 | int xdp_umem_assign_dev(struct xdp_umem *umem, struct net_device *dev, |
12 | u16 queue_id, u16 flags); | 12 | u16 queue_id, u16 flags); |
13 | void xdp_umem_clear_dev(struct xdp_umem *umem); | ||
13 | bool xdp_umem_validate_queues(struct xdp_umem *umem); | 14 | bool xdp_umem_validate_queues(struct xdp_umem *umem); |
14 | void xdp_get_umem(struct xdp_umem *umem); | 15 | void xdp_get_umem(struct xdp_umem *umem); |
15 | void xdp_put_umem(struct xdp_umem *umem); | 16 | void xdp_put_umem(struct xdp_umem *umem); |
diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index a14e8864e4fa..f53a6ef7c155 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c | |||
@@ -335,6 +335,22 @@ static int xsk_init_queue(u32 entries, struct xsk_queue **queue, | |||
335 | return 0; | 335 | return 0; |
336 | } | 336 | } |
337 | 337 | ||
338 | static void xsk_unbind_dev(struct xdp_sock *xs) | ||
339 | { | ||
340 | struct net_device *dev = xs->dev; | ||
341 | |||
342 | if (!dev || xs->state != XSK_BOUND) | ||
343 | return; | ||
344 | |||
345 | xs->state = XSK_UNBOUND; | ||
346 | |||
347 | /* Wait for driver to stop using the xdp socket. */ | ||
348 | xdp_del_sk_umem(xs->umem, xs); | ||
349 | xs->dev = NULL; | ||
350 | synchronize_net(); | ||
351 | dev_put(dev); | ||
352 | } | ||
353 | |||
338 | static int xsk_release(struct socket *sock) | 354 | static int xsk_release(struct socket *sock) |
339 | { | 355 | { |
340 | struct sock *sk = sock->sk; | 356 | struct sock *sk = sock->sk; |
@@ -354,15 +370,7 @@ static int xsk_release(struct socket *sock) | |||
354 | sock_prot_inuse_add(net, sk->sk_prot, -1); | 370 | sock_prot_inuse_add(net, sk->sk_prot, -1); |
355 | local_bh_enable(); | 371 | local_bh_enable(); |
356 | 372 | ||
357 | if (xs->dev) { | 373 | xsk_unbind_dev(xs); |
358 | struct net_device *dev = xs->dev; | ||
359 | |||
360 | /* Wait for driver to stop using the xdp socket. */ | ||
361 | xdp_del_sk_umem(xs->umem, xs); | ||
362 | xs->dev = NULL; | ||
363 | synchronize_net(); | ||
364 | dev_put(dev); | ||
365 | } | ||
366 | 374 | ||
367 | xskq_destroy(xs->rx); | 375 | xskq_destroy(xs->rx); |
368 | xskq_destroy(xs->tx); | 376 | xskq_destroy(xs->tx); |
@@ -412,7 +420,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len) | |||
412 | return -EINVAL; | 420 | return -EINVAL; |
413 | 421 | ||
414 | mutex_lock(&xs->mutex); | 422 | mutex_lock(&xs->mutex); |
415 | if (xs->dev) { | 423 | if (xs->state != XSK_READY) { |
416 | err = -EBUSY; | 424 | err = -EBUSY; |
417 | goto out_release; | 425 | goto out_release; |
418 | } | 426 | } |
@@ -492,6 +500,8 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len) | |||
492 | out_unlock: | 500 | out_unlock: |
493 | if (err) | 501 | if (err) |
494 | dev_put(dev); | 502 | dev_put(dev); |
503 | else | ||
504 | xs->state = XSK_BOUND; | ||
495 | out_release: | 505 | out_release: |
496 | mutex_unlock(&xs->mutex); | 506 | mutex_unlock(&xs->mutex); |
497 | return err; | 507 | return err; |
@@ -520,6 +530,10 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname, | |||
520 | return -EFAULT; | 530 | return -EFAULT; |
521 | 531 | ||
522 | mutex_lock(&xs->mutex); | 532 | mutex_lock(&xs->mutex); |
533 | if (xs->state != XSK_READY) { | ||
534 | mutex_unlock(&xs->mutex); | ||
535 | return -EBUSY; | ||
536 | } | ||
523 | q = (optname == XDP_TX_RING) ? &xs->tx : &xs->rx; | 537 | q = (optname == XDP_TX_RING) ? &xs->tx : &xs->rx; |
524 | err = xsk_init_queue(entries, q, false); | 538 | err = xsk_init_queue(entries, q, false); |
525 | mutex_unlock(&xs->mutex); | 539 | mutex_unlock(&xs->mutex); |
@@ -534,7 +548,7 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname, | |||
534 | return -EFAULT; | 548 | return -EFAULT; |
535 | 549 | ||
536 | mutex_lock(&xs->mutex); | 550 | mutex_lock(&xs->mutex); |
537 | if (xs->umem) { | 551 | if (xs->state != XSK_READY || xs->umem) { |
538 | mutex_unlock(&xs->mutex); | 552 | mutex_unlock(&xs->mutex); |
539 | return -EBUSY; | 553 | return -EBUSY; |
540 | } | 554 | } |
@@ -561,6 +575,10 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname, | |||
561 | return -EFAULT; | 575 | return -EFAULT; |
562 | 576 | ||
563 | mutex_lock(&xs->mutex); | 577 | mutex_lock(&xs->mutex); |
578 | if (xs->state != XSK_READY) { | ||
579 | mutex_unlock(&xs->mutex); | ||
580 | return -EBUSY; | ||
581 | } | ||
564 | if (!xs->umem) { | 582 | if (!xs->umem) { |
565 | mutex_unlock(&xs->mutex); | 583 | mutex_unlock(&xs->mutex); |
566 | return -EINVAL; | 584 | return -EINVAL; |
@@ -662,6 +680,9 @@ static int xsk_mmap(struct file *file, struct socket *sock, | |||
662 | unsigned long pfn; | 680 | unsigned long pfn; |
663 | struct page *qpg; | 681 | struct page *qpg; |
664 | 682 | ||
683 | if (xs->state != XSK_READY) | ||
684 | return -EBUSY; | ||
685 | |||
665 | if (offset == XDP_PGOFF_RX_RING) { | 686 | if (offset == XDP_PGOFF_RX_RING) { |
666 | q = READ_ONCE(xs->rx); | 687 | q = READ_ONCE(xs->rx); |
667 | } else if (offset == XDP_PGOFF_TX_RING) { | 688 | } else if (offset == XDP_PGOFF_TX_RING) { |
@@ -693,6 +714,38 @@ static int xsk_mmap(struct file *file, struct socket *sock, | |||
693 | size, vma->vm_page_prot); | 714 | size, vma->vm_page_prot); |
694 | } | 715 | } |
695 | 716 | ||
717 | static int xsk_notifier(struct notifier_block *this, | ||
718 | unsigned long msg, void *ptr) | ||
719 | { | ||
720 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | ||
721 | struct net *net = dev_net(dev); | ||
722 | struct sock *sk; | ||
723 | |||
724 | switch (msg) { | ||
725 | case NETDEV_UNREGISTER: | ||
726 | mutex_lock(&net->xdp.lock); | ||
727 | sk_for_each(sk, &net->xdp.list) { | ||
728 | struct xdp_sock *xs = xdp_sk(sk); | ||
729 | |||
730 | mutex_lock(&xs->mutex); | ||
731 | if (xs->dev == dev) { | ||
732 | sk->sk_err = ENETDOWN; | ||
733 | if (!sock_flag(sk, SOCK_DEAD)) | ||
734 | sk->sk_error_report(sk); | ||
735 | |||
736 | xsk_unbind_dev(xs); | ||
737 | |||
738 | /* Clear device references in umem. */ | ||
739 | xdp_umem_clear_dev(xs->umem); | ||
740 | } | ||
741 | mutex_unlock(&xs->mutex); | ||
742 | } | ||
743 | mutex_unlock(&net->xdp.lock); | ||
744 | break; | ||
745 | } | ||
746 | return NOTIFY_DONE; | ||
747 | } | ||
748 | |||
696 | static struct proto xsk_proto = { | 749 | static struct proto xsk_proto = { |
697 | .name = "XDP", | 750 | .name = "XDP", |
698 | .owner = THIS_MODULE, | 751 | .owner = THIS_MODULE, |
@@ -764,6 +817,7 @@ static int xsk_create(struct net *net, struct socket *sock, int protocol, | |||
764 | sock_set_flag(sk, SOCK_RCU_FREE); | 817 | sock_set_flag(sk, SOCK_RCU_FREE); |
765 | 818 | ||
766 | xs = xdp_sk(sk); | 819 | xs = xdp_sk(sk); |
820 | xs->state = XSK_READY; | ||
767 | mutex_init(&xs->mutex); | 821 | mutex_init(&xs->mutex); |
768 | spin_lock_init(&xs->tx_completion_lock); | 822 | spin_lock_init(&xs->tx_completion_lock); |
769 | 823 | ||
@@ -784,6 +838,10 @@ static const struct net_proto_family xsk_family_ops = { | |||
784 | .owner = THIS_MODULE, | 838 | .owner = THIS_MODULE, |
785 | }; | 839 | }; |
786 | 840 | ||
841 | static struct notifier_block xsk_netdev_notifier = { | ||
842 | .notifier_call = xsk_notifier, | ||
843 | }; | ||
844 | |||
787 | static int __net_init xsk_net_init(struct net *net) | 845 | static int __net_init xsk_net_init(struct net *net) |
788 | { | 846 | { |
789 | mutex_init(&net->xdp.lock); | 847 | mutex_init(&net->xdp.lock); |
@@ -816,8 +874,15 @@ static int __init xsk_init(void) | |||
816 | err = register_pernet_subsys(&xsk_net_ops); | 874 | err = register_pernet_subsys(&xsk_net_ops); |
817 | if (err) | 875 | if (err) |
818 | goto out_sk; | 876 | goto out_sk; |
877 | |||
878 | err = register_netdevice_notifier(&xsk_netdev_notifier); | ||
879 | if (err) | ||
880 | goto out_pernet; | ||
881 | |||
819 | return 0; | 882 | return 0; |
820 | 883 | ||
884 | out_pernet: | ||
885 | unregister_pernet_subsys(&xsk_net_ops); | ||
821 | out_sk: | 886 | out_sk: |
822 | sock_unregister(PF_XDP); | 887 | sock_unregister(PF_XDP); |
823 | out_proto: | 888 | out_proto: |
diff --git a/net/xdp/xsk_queue.h b/net/xdp/xsk_queue.h index 88b9ae24658d..cba4a640d5e8 100644 --- a/net/xdp/xsk_queue.h +++ b/net/xdp/xsk_queue.h | |||
@@ -288,7 +288,7 @@ static inline void xskq_produce_flush_desc(struct xsk_queue *q) | |||
288 | /* Order producer and data */ | 288 | /* Order producer and data */ |
289 | smp_wmb(); /* B, matches C */ | 289 | smp_wmb(); /* B, matches C */ |
290 | 290 | ||
291 | q->prod_tail = q->prod_head, | 291 | q->prod_tail = q->prod_head; |
292 | WRITE_ONCE(q->ring->producer, q->prod_tail); | 292 | WRITE_ONCE(q->ring->producer, q->prod_tail); |
293 | } | 293 | } |
294 | 294 | ||
diff --git a/samples/bpf/xdp_redirect_user.c b/samples/bpf/xdp_redirect_user.c index 09747bee6668..003c0c6e38c5 100644 --- a/samples/bpf/xdp_redirect_user.c +++ b/samples/bpf/xdp_redirect_user.c | |||
@@ -189,7 +189,7 @@ int main(int argc, char **argv) | |||
189 | } | 189 | } |
190 | 190 | ||
191 | memset(&info, 0, sizeof(info)); | 191 | memset(&info, 0, sizeof(info)); |
192 | ret = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len); | 192 | ret = bpf_obj_get_info_by_fd(dummy_prog_fd, &info, &info_len); |
193 | if (ret) { | 193 | if (ret) { |
194 | printf("can't get prog info - %s\n", strerror(errno)); | 194 | printf("can't get prog info - %s\n", strerror(errno)); |
195 | return ret; | 195 | return ret; |
diff --git a/tools/bpf/bpftool/cgroup.c b/tools/bpf/bpftool/cgroup.c index 73ec8ea33fb4..a13fb7265d1a 100644 --- a/tools/bpf/bpftool/cgroup.c +++ b/tools/bpf/bpftool/cgroup.c | |||
@@ -168,7 +168,7 @@ static int do_show(int argc, char **argv) | |||
168 | 168 | ||
169 | cgroup_fd = open(argv[0], O_RDONLY); | 169 | cgroup_fd = open(argv[0], O_RDONLY); |
170 | if (cgroup_fd < 0) { | 170 | if (cgroup_fd < 0) { |
171 | p_err("can't open cgroup %s", argv[1]); | 171 | p_err("can't open cgroup %s", argv[0]); |
172 | goto exit; | 172 | goto exit; |
173 | } | 173 | } |
174 | 174 | ||
@@ -356,7 +356,7 @@ static int do_attach(int argc, char **argv) | |||
356 | 356 | ||
357 | cgroup_fd = open(argv[0], O_RDONLY); | 357 | cgroup_fd = open(argv[0], O_RDONLY); |
358 | if (cgroup_fd < 0) { | 358 | if (cgroup_fd < 0) { |
359 | p_err("can't open cgroup %s", argv[1]); | 359 | p_err("can't open cgroup %s", argv[0]); |
360 | goto exit; | 360 | goto exit; |
361 | } | 361 | } |
362 | 362 | ||
@@ -414,7 +414,7 @@ static int do_detach(int argc, char **argv) | |||
414 | 414 | ||
415 | cgroup_fd = open(argv[0], O_RDONLY); | 415 | cgroup_fd = open(argv[0], O_RDONLY); |
416 | if (cgroup_fd < 0) { | 416 | if (cgroup_fd < 0) { |
417 | p_err("can't open cgroup %s", argv[1]); | 417 | p_err("can't open cgroup %s", argv[0]); |
418 | goto exit; | 418 | goto exit; |
419 | } | 419 | } |
420 | 420 | ||
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index a8b823c30b43..29a5bc3d5c66 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h | |||
@@ -3143,6 +3143,7 @@ struct bpf_prog_info { | |||
3143 | char name[BPF_OBJ_NAME_LEN]; | 3143 | char name[BPF_OBJ_NAME_LEN]; |
3144 | __u32 ifindex; | 3144 | __u32 ifindex; |
3145 | __u32 gpl_compatible:1; | 3145 | __u32 gpl_compatible:1; |
3146 | __u32 :31; /* alignment pad */ | ||
3146 | __u64 netns_dev; | 3147 | __u64 netns_dev; |
3147 | __u64 netns_ino; | 3148 | __u64 netns_ino; |
3148 | __u32 nr_jited_ksyms; | 3149 | __u32 nr_jited_ksyms; |
diff --git a/tools/testing/selftests/bpf/progs/test_lwt_seg6local.c b/tools/testing/selftests/bpf/progs/test_lwt_seg6local.c index 0575751bc1bc..e2f6ed0a583d 100644 --- a/tools/testing/selftests/bpf/progs/test_lwt_seg6local.c +++ b/tools/testing/selftests/bpf/progs/test_lwt_seg6local.c | |||
@@ -61,7 +61,7 @@ struct sr6_tlv_t { | |||
61 | unsigned char value[0]; | 61 | unsigned char value[0]; |
62 | } BPF_PACKET_HEADER; | 62 | } BPF_PACKET_HEADER; |
63 | 63 | ||
64 | __attribute__((always_inline)) struct ip6_srh_t *get_srh(struct __sk_buff *skb) | 64 | static __always_inline struct ip6_srh_t *get_srh(struct __sk_buff *skb) |
65 | { | 65 | { |
66 | void *cursor, *data_end; | 66 | void *cursor, *data_end; |
67 | struct ip6_srh_t *srh; | 67 | struct ip6_srh_t *srh; |
@@ -95,7 +95,7 @@ __attribute__((always_inline)) struct ip6_srh_t *get_srh(struct __sk_buff *skb) | |||
95 | return srh; | 95 | return srh; |
96 | } | 96 | } |
97 | 97 | ||
98 | __attribute__((always_inline)) | 98 | static __always_inline |
99 | int update_tlv_pad(struct __sk_buff *skb, uint32_t new_pad, | 99 | int update_tlv_pad(struct __sk_buff *skb, uint32_t new_pad, |
100 | uint32_t old_pad, uint32_t pad_off) | 100 | uint32_t old_pad, uint32_t pad_off) |
101 | { | 101 | { |
@@ -125,7 +125,7 @@ int update_tlv_pad(struct __sk_buff *skb, uint32_t new_pad, | |||
125 | return 0; | 125 | return 0; |
126 | } | 126 | } |
127 | 127 | ||
128 | __attribute__((always_inline)) | 128 | static __always_inline |
129 | int is_valid_tlv_boundary(struct __sk_buff *skb, struct ip6_srh_t *srh, | 129 | int is_valid_tlv_boundary(struct __sk_buff *skb, struct ip6_srh_t *srh, |
130 | uint32_t *tlv_off, uint32_t *pad_size, | 130 | uint32_t *tlv_off, uint32_t *pad_size, |
131 | uint32_t *pad_off) | 131 | uint32_t *pad_off) |
@@ -184,7 +184,7 @@ int is_valid_tlv_boundary(struct __sk_buff *skb, struct ip6_srh_t *srh, | |||
184 | return 0; | 184 | return 0; |
185 | } | 185 | } |
186 | 186 | ||
187 | __attribute__((always_inline)) | 187 | static __always_inline |
188 | int add_tlv(struct __sk_buff *skb, struct ip6_srh_t *srh, uint32_t tlv_off, | 188 | int add_tlv(struct __sk_buff *skb, struct ip6_srh_t *srh, uint32_t tlv_off, |
189 | struct sr6_tlv_t *itlv, uint8_t tlv_size) | 189 | struct sr6_tlv_t *itlv, uint8_t tlv_size) |
190 | { | 190 | { |
@@ -228,7 +228,7 @@ int add_tlv(struct __sk_buff *skb, struct ip6_srh_t *srh, uint32_t tlv_off, | |||
228 | return update_tlv_pad(skb, new_pad, pad_size, pad_off); | 228 | return update_tlv_pad(skb, new_pad, pad_size, pad_off); |
229 | } | 229 | } |
230 | 230 | ||
231 | __attribute__((always_inline)) | 231 | static __always_inline |
232 | int delete_tlv(struct __sk_buff *skb, struct ip6_srh_t *srh, | 232 | int delete_tlv(struct __sk_buff *skb, struct ip6_srh_t *srh, |
233 | uint32_t tlv_off) | 233 | uint32_t tlv_off) |
234 | { | 234 | { |
@@ -266,7 +266,7 @@ int delete_tlv(struct __sk_buff *skb, struct ip6_srh_t *srh, | |||
266 | return update_tlv_pad(skb, new_pad, pad_size, pad_off); | 266 | return update_tlv_pad(skb, new_pad, pad_size, pad_off); |
267 | } | 267 | } |
268 | 268 | ||
269 | __attribute__((always_inline)) | 269 | static __always_inline |
270 | int has_egr_tlv(struct __sk_buff *skb, struct ip6_srh_t *srh) | 270 | int has_egr_tlv(struct __sk_buff *skb, struct ip6_srh_t *srh) |
271 | { | 271 | { |
272 | int tlv_offset = sizeof(struct ip6_t) + sizeof(struct ip6_srh_t) + | 272 | int tlv_offset = sizeof(struct ip6_t) + sizeof(struct ip6_srh_t) + |
diff --git a/tools/testing/selftests/bpf/verifier/basic_instr.c b/tools/testing/selftests/bpf/verifier/basic_instr.c index ed91a7b9a456..071dbc889e8c 100644 --- a/tools/testing/selftests/bpf/verifier/basic_instr.c +++ b/tools/testing/selftests/bpf/verifier/basic_instr.c | |||
@@ -91,6 +91,91 @@ | |||
91 | .result = ACCEPT, | 91 | .result = ACCEPT, |
92 | }, | 92 | }, |
93 | { | 93 | { |
94 | "lsh64 by 0 imm", | ||
95 | .insns = { | ||
96 | BPF_LD_IMM64(BPF_REG_0, 1), | ||
97 | BPF_LD_IMM64(BPF_REG_1, 1), | ||
98 | BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 0), | ||
99 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1), | ||
100 | BPF_MOV64_IMM(BPF_REG_0, 2), | ||
101 | BPF_EXIT_INSN(), | ||
102 | }, | ||
103 | .result = ACCEPT, | ||
104 | .retval = 1, | ||
105 | }, | ||
106 | { | ||
107 | "rsh64 by 0 imm", | ||
108 | .insns = { | ||
109 | BPF_LD_IMM64(BPF_REG_0, 1), | ||
110 | BPF_LD_IMM64(BPF_REG_1, 0x100000000LL), | ||
111 | BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1), | ||
112 | BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 0), | ||
113 | BPF_JMP_REG(BPF_JEQ, BPF_REG_1, BPF_REG_2, 1), | ||
114 | BPF_MOV64_IMM(BPF_REG_0, 2), | ||
115 | BPF_EXIT_INSN(), | ||
116 | }, | ||
117 | .result = ACCEPT, | ||
118 | .retval = 1, | ||
119 | }, | ||
120 | { | ||
121 | "arsh64 by 0 imm", | ||
122 | .insns = { | ||
123 | BPF_LD_IMM64(BPF_REG_0, 1), | ||
124 | BPF_LD_IMM64(BPF_REG_1, 0x100000000LL), | ||
125 | BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1), | ||
126 | BPF_ALU64_IMM(BPF_ARSH, BPF_REG_1, 0), | ||
127 | BPF_JMP_REG(BPF_JEQ, BPF_REG_1, BPF_REG_2, 1), | ||
128 | BPF_MOV64_IMM(BPF_REG_0, 2), | ||
129 | BPF_EXIT_INSN(), | ||
130 | }, | ||
131 | .result = ACCEPT, | ||
132 | .retval = 1, | ||
133 | }, | ||
134 | { | ||
135 | "lsh64 by 0 reg", | ||
136 | .insns = { | ||
137 | BPF_LD_IMM64(BPF_REG_0, 1), | ||
138 | BPF_LD_IMM64(BPF_REG_1, 1), | ||
139 | BPF_LD_IMM64(BPF_REG_2, 0), | ||
140 | BPF_ALU64_REG(BPF_LSH, BPF_REG_1, BPF_REG_2), | ||
141 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1), | ||
142 | BPF_MOV64_IMM(BPF_REG_0, 2), | ||
143 | BPF_EXIT_INSN(), | ||
144 | }, | ||
145 | .result = ACCEPT, | ||
146 | .retval = 1, | ||
147 | }, | ||
148 | { | ||
149 | "rsh64 by 0 reg", | ||
150 | .insns = { | ||
151 | BPF_LD_IMM64(BPF_REG_0, 1), | ||
152 | BPF_LD_IMM64(BPF_REG_1, 0x100000000LL), | ||
153 | BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1), | ||
154 | BPF_LD_IMM64(BPF_REG_3, 0), | ||
155 | BPF_ALU64_REG(BPF_RSH, BPF_REG_1, BPF_REG_3), | ||
156 | BPF_JMP_REG(BPF_JEQ, BPF_REG_1, BPF_REG_2, 1), | ||
157 | BPF_MOV64_IMM(BPF_REG_0, 2), | ||
158 | BPF_EXIT_INSN(), | ||
159 | }, | ||
160 | .result = ACCEPT, | ||
161 | .retval = 1, | ||
162 | }, | ||
163 | { | ||
164 | "arsh64 by 0 reg", | ||
165 | .insns = { | ||
166 | BPF_LD_IMM64(BPF_REG_0, 1), | ||
167 | BPF_LD_IMM64(BPF_REG_1, 0x100000000LL), | ||
168 | BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1), | ||
169 | BPF_LD_IMM64(BPF_REG_3, 0), | ||
170 | BPF_ALU64_REG(BPF_ARSH, BPF_REG_1, BPF_REG_3), | ||
171 | BPF_JMP_REG(BPF_JEQ, BPF_REG_1, BPF_REG_2, 1), | ||
172 | BPF_MOV64_IMM(BPF_REG_0, 2), | ||
173 | BPF_EXIT_INSN(), | ||
174 | }, | ||
175 | .result = ACCEPT, | ||
176 | .retval = 1, | ||
177 | }, | ||
178 | { | ||
94 | "invalid 64-bit BPF_END", | 179 | "invalid 64-bit BPF_END", |
95 | .insns = { | 180 | .insns = { |
96 | BPF_MOV32_IMM(BPF_REG_0, 0), | 181 | BPF_MOV32_IMM(BPF_REG_0, 0), |