hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/arch/arm64/kernel/armv8_deprecated.c
....@@ -1,9 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2014 ARM Limited
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of the GNU General Public License version 2 as
6
- * published by the Free Software Foundation.
74 */
85
96 #include <linux/cpu.h>
....@@ -62,6 +59,7 @@
6259 static LIST_HEAD(insn_emulation);
6360 static int nr_insn_emulated __initdata;
6461 static DEFINE_RAW_SPINLOCK(insn_emulation_lock);
62
+static DEFINE_MUTEX(insn_emulation_mutex);
6563
6664 static void register_emulation_hooks(struct insn_emulation_ops *ops)
6765 {
....@@ -206,14 +204,14 @@
206204 }
207205
208206 static int emulation_proc_handler(struct ctl_table *table, int write,
209
- void __user *buffer, size_t *lenp,
207
+ void *buffer, size_t *lenp,
210208 loff_t *ppos)
211209 {
212210 int ret = 0;
213
- struct insn_emulation *insn = (struct insn_emulation *) table->data;
211
+ struct insn_emulation *insn = container_of(table->data, struct insn_emulation, current_mode);
214212 enum insn_emulation_mode prev_mode = insn->current_mode;
215213
216
- table->data = &insn->current_mode;
214
+ mutex_lock(&insn_emulation_mutex);
217215 ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
218216
219217 if (ret || !write || prev_mode == insn->current_mode)
....@@ -226,7 +224,7 @@
226224 update_insn_emulation_mode(insn, INSN_UNDEF);
227225 }
228226 ret:
229
- table->data = insn;
227
+ mutex_unlock(&insn_emulation_mutex);
230228 return ret;
231229 }
232230
....@@ -250,7 +248,7 @@
250248 sysctl->maxlen = sizeof(int);
251249
252250 sysctl->procname = insn->ops->name;
253
- sysctl->data = insn;
251
+ sysctl->data = &insn->current_mode;
254252 sysctl->extra1 = &insn->min;
255253 sysctl->extra2 = &insn->max;
256254 sysctl->proc_handler = emulation_proc_handler;
....@@ -280,7 +278,7 @@
280278
281279 #define __user_swpX_asm(data, addr, res, temp, temp2, B) \
282280 do { \
283
- uaccess_enable(); \
281
+ uaccess_enable_privileged(); \
284282 __asm__ __volatile__( \
285283 " mov %w3, %w7\n" \
286284 "0: ldxr"B" %w2, [%4]\n" \
....@@ -305,7 +303,7 @@
305303 "i" (-EFAULT), \
306304 "i" (__SWP_LL_SC_LOOPS) \
307305 : "memory"); \
308
- uaccess_disable(); \
306
+ uaccess_disable_privileged(); \
309307 } while (0)
310308
311309 #define __user_swp_asm(data, addr, res, temp, temp2) \
....@@ -407,7 +405,7 @@
407405
408406 /* Check access in reasonable access range for both SWP and SWPB */
409407 user_ptr = (const void __user *)(unsigned long)(address & ~3);
410
- if (!access_ok(VERIFY_WRITE, user_ptr, 4)) {
408
+ if (!access_ok(user_ptr, 4)) {
411409 pr_debug("SWP{B} emulation: access to 0x%08x not allowed!\n",
412410 address);
413411 goto fault;
....@@ -621,7 +619,8 @@
621619 };
622620
623621 /*
624
- * Invoked as late_initcall, since not needed before init spawned.
622
+ * Invoked as core_initcall, which guarantees that the instruction
623
+ * emulation is ready for userspace.
625624 */
626625 static int __init armv8_deprecated_init(void)
627626 {
....@@ -632,7 +631,7 @@
632631 register_insn_emulation(&cp15_barrier_ops);
633632
634633 if (IS_ENABLED(CONFIG_SETEND_EMULATION)) {
635
- if(system_supports_mixed_endian_el0())
634
+ if (system_supports_mixed_endian_el0())
636635 register_insn_emulation(&setend_ops);
637636 else
638637 pr_info("setend instruction emulation is not supported on this system\n");