| .. | .. |
|---|
| 159 | 159 | __sve_free(task); |
|---|
| 160 | 160 | } |
|---|
| 161 | 161 | |
|---|
| 162 | +static void *sve_free_atomic(struct task_struct *task) |
|---|
| 163 | +{ |
|---|
| 164 | + void *sve_state = task->thread.sve_state; |
|---|
| 165 | + |
|---|
| 166 | + WARN_ON(test_tsk_thread_flag(task, TIF_SVE)); |
|---|
| 167 | + |
|---|
| 168 | + task->thread.sve_state = NULL; |
|---|
| 169 | + return sve_state; |
|---|
| 170 | +} |
|---|
| 171 | + |
|---|
| 162 | 172 | /* |
|---|
| 163 | 173 | * TIF_SVE controls whether a task can use SVE without trapping while |
|---|
| 164 | 174 | * in userspace, and also the way a task's FPSIMD/SVE state is stored |
|---|
| .. | .. |
|---|
| 549 | 559 | * non-SVE thread. |
|---|
| 550 | 560 | */ |
|---|
| 551 | 561 | if (task == current) { |
|---|
| 562 | + preempt_disable(); |
|---|
| 552 | 563 | local_bh_disable(); |
|---|
| 553 | 564 | |
|---|
| 554 | 565 | fpsimd_save(); |
|---|
| .. | .. |
|---|
| 559 | 570 | if (test_and_clear_tsk_thread_flag(task, TIF_SVE)) |
|---|
| 560 | 571 | sve_to_fpsimd(task); |
|---|
| 561 | 572 | |
|---|
| 562 | | - if (task == current) |
|---|
| 573 | + if (task == current) { |
|---|
| 563 | 574 | local_bh_enable(); |
|---|
| 575 | + preempt_enable(); |
|---|
| 576 | + } |
|---|
| 564 | 577 | |
|---|
| 565 | 578 | /* |
|---|
| 566 | 579 | * Force reallocation of task SVE state to the correct size |
|---|
| .. | .. |
|---|
| 815 | 828 | |
|---|
| 816 | 829 | sve_alloc(current); |
|---|
| 817 | 830 | |
|---|
| 831 | + preempt_disable(); |
|---|
| 818 | 832 | local_bh_disable(); |
|---|
| 819 | 833 | |
|---|
| 820 | 834 | fpsimd_save(); |
|---|
| .. | .. |
|---|
| 828 | 842 | WARN_ON(1); /* SVE access shouldn't have trapped */ |
|---|
| 829 | 843 | |
|---|
| 830 | 844 | local_bh_enable(); |
|---|
| 845 | + preempt_enable(); |
|---|
| 831 | 846 | } |
|---|
| 832 | 847 | |
|---|
| 833 | 848 | /* |
|---|
| .. | .. |
|---|
| 894 | 909 | void fpsimd_flush_thread(void) |
|---|
| 895 | 910 | { |
|---|
| 896 | 911 | int vl, supported_vl; |
|---|
| 912 | + void *mem = NULL; |
|---|
| 897 | 913 | |
|---|
| 898 | 914 | if (!system_supports_fpsimd()) |
|---|
| 899 | 915 | return; |
|---|
| 900 | 916 | |
|---|
| 917 | + preempt_disable(); |
|---|
| 901 | 918 | local_bh_disable(); |
|---|
| 902 | 919 | |
|---|
| 903 | 920 | memset(¤t->thread.uw.fpsimd_state, 0, |
|---|
| .. | .. |
|---|
| 906 | 923 | |
|---|
| 907 | 924 | if (system_supports_sve()) { |
|---|
| 908 | 925 | clear_thread_flag(TIF_SVE); |
|---|
| 909 | | - sve_free(current); |
|---|
| 926 | + mem = sve_free_atomic(current); |
|---|
| 910 | 927 | |
|---|
| 911 | 928 | /* |
|---|
| 912 | 929 | * Reset the task vector length as required. |
|---|
| .. | .. |
|---|
| 942 | 959 | set_thread_flag(TIF_FOREIGN_FPSTATE); |
|---|
| 943 | 960 | |
|---|
| 944 | 961 | local_bh_enable(); |
|---|
| 962 | + preempt_enable(); |
|---|
| 963 | + kfree(mem); |
|---|
| 945 | 964 | } |
|---|
| 946 | 965 | |
|---|
| 947 | 966 | /* |
|---|
| .. | .. |
|---|
| 953 | 972 | if (!system_supports_fpsimd()) |
|---|
| 954 | 973 | return; |
|---|
| 955 | 974 | |
|---|
| 975 | + preempt_disable(); |
|---|
| 956 | 976 | local_bh_disable(); |
|---|
| 957 | 977 | fpsimd_save(); |
|---|
| 958 | 978 | local_bh_enable(); |
|---|
| 979 | + preempt_enable(); |
|---|
| 959 | 980 | } |
|---|
| 960 | 981 | |
|---|
| 961 | 982 | /* |
|---|
| .. | .. |
|---|
| 1026 | 1047 | return; |
|---|
| 1027 | 1048 | } |
|---|
| 1028 | 1049 | |
|---|
| 1050 | + preempt_disable(); |
|---|
| 1029 | 1051 | local_bh_disable(); |
|---|
| 1030 | 1052 | |
|---|
| 1031 | 1053 | if (test_and_clear_thread_flag(TIF_FOREIGN_FPSTATE)) { |
|---|
| .. | .. |
|---|
| 1034 | 1056 | } |
|---|
| 1035 | 1057 | |
|---|
| 1036 | 1058 | local_bh_enable(); |
|---|
| 1059 | + preempt_enable(); |
|---|
| 1037 | 1060 | } |
|---|
| 1038 | 1061 | |
|---|
| 1039 | 1062 | /* |
|---|
| .. | .. |
|---|
| 1046 | 1069 | if (WARN_ON(!system_supports_fpsimd())) |
|---|
| 1047 | 1070 | return; |
|---|
| 1048 | 1071 | |
|---|
| 1072 | + preempt_disable(); |
|---|
| 1049 | 1073 | local_bh_disable(); |
|---|
| 1050 | 1074 | |
|---|
| 1051 | 1075 | current->thread.uw.fpsimd_state = *state; |
|---|
| .. | .. |
|---|
| 1058 | 1082 | clear_thread_flag(TIF_FOREIGN_FPSTATE); |
|---|
| 1059 | 1083 | |
|---|
| 1060 | 1084 | local_bh_enable(); |
|---|
| 1085 | + preempt_enable(); |
|---|
| 1061 | 1086 | } |
|---|
| 1062 | 1087 | |
|---|
| 1063 | 1088 | /* |
|---|
| .. | .. |
|---|
| 1104 | 1129 | |
|---|
| 1105 | 1130 | BUG_ON(!may_use_simd()); |
|---|
| 1106 | 1131 | |
|---|
| 1132 | + preempt_disable(); |
|---|
| 1107 | 1133 | local_bh_disable(); |
|---|
| 1108 | 1134 | |
|---|
| 1109 | 1135 | __this_cpu_write(kernel_neon_busy, true); |
|---|
| .. | .. |
|---|
| 1117 | 1143 | preempt_disable(); |
|---|
| 1118 | 1144 | |
|---|
| 1119 | 1145 | local_bh_enable(); |
|---|
| 1146 | + preempt_enable(); |
|---|
| 1120 | 1147 | } |
|---|
| 1121 | 1148 | EXPORT_SYMBOL(kernel_neon_begin); |
|---|
| 1122 | 1149 | |
|---|