hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/arch/powerpc/kernel/align.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* align.c - handle alignment exceptions for the Power PC.
23 *
34 * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
....@@ -10,11 +11,6 @@
1011 * Copyright (c) 2005 Benjamin Herrenschmidt, IBM Corp
1112 * <benh@kernel.crashing.org>
1213 * Merge ppc32 and ppc64 implementations
13
- *
14
- * This program is free software; you can redistribute it and/or
15
- * modify it under the terms of the GNU General Public License
16
- * as published by the Free Software Foundation; either version
17
- * 2 of the License, or (at your option) any later version.
1814 */
1915
2016 #include <linux/kernel.h>
....@@ -28,6 +24,7 @@
2824 #include <asm/disassemble.h>
2925 #include <asm/cpu_has_feature.h>
3026 #include <asm/sstep.h>
27
+#include <asm/inst.h>
3128
3229 struct aligninfo {
3330 unsigned char len;
....@@ -108,7 +105,7 @@
108105 * so we don't need the address swizzling.
109106 */
110107 static int emulate_spe(struct pt_regs *regs, unsigned int reg,
111
- unsigned int instr)
108
+ struct ppc_inst ppc_instr)
112109 {
113110 int ret;
114111 union {
....@@ -119,8 +116,9 @@
119116 } data, temp;
120117 unsigned char __user *p, *addr;
121118 unsigned long *evr = &current->thread.evr[reg];
122
- unsigned int nb, flags;
119
+ unsigned int nb, flags, instr;
123120
121
+ instr = ppc_inst_val(ppc_instr);
124122 instr = (instr >> 1) & 0x1f;
125123
126124 /* DAR has the operand effective address */
....@@ -131,8 +129,7 @@
131129
132130 /* Verify the address of the operand */
133131 if (unlikely(user_mode(regs) &&
134
- !access_ok((flags & ST ? VERIFY_WRITE : VERIFY_READ),
135
- addr, nb)))
132
+ !access_ok(addr, nb)))
136133 return -EFAULT;
137134
138135 /* userland only */
....@@ -181,9 +178,11 @@
181178 ret |= __get_user_inatomic(temp.v[1], p++);
182179 ret |= __get_user_inatomic(temp.v[2], p++);
183180 ret |= __get_user_inatomic(temp.v[3], p++);
181
+ fallthrough;
184182 case 4:
185183 ret |= __get_user_inatomic(temp.v[4], p++);
186184 ret |= __get_user_inatomic(temp.v[5], p++);
185
+ fallthrough;
187186 case 2:
188187 ret |= __get_user_inatomic(temp.v[6], p++);
189188 ret |= __get_user_inatomic(temp.v[7], p++);
....@@ -264,9 +263,11 @@
264263 ret |= __put_user_inatomic(data.v[1], p++);
265264 ret |= __put_user_inatomic(data.v[2], p++);
266265 ret |= __put_user_inatomic(data.v[3], p++);
266
+ fallthrough;
267267 case 4:
268268 ret |= __put_user_inatomic(data.v[4], p++);
269269 ret |= __put_user_inatomic(data.v[5], p++);
270
+ fallthrough;
270271 case 2:
271272 ret |= __put_user_inatomic(data.v[6], p++);
272273 ret |= __put_user_inatomic(data.v[7], p++);
....@@ -294,7 +295,7 @@
294295
295296 int fix_alignment(struct pt_regs *regs)
296297 {
297
- unsigned int instr;
298
+ struct ppc_inst instr;
298299 struct instruction_op op;
299300 int r, type;
300301
....@@ -304,18 +305,18 @@
304305 */
305306 CHECK_FULL_REGS(regs);
306307
307
- if (unlikely(__get_user(instr, (unsigned int __user *)regs->nip)))
308
+ if (unlikely(__get_user_instr(instr, (void __user *)regs->nip)))
308309 return -EFAULT;
309310 if ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE)) {
310311 /* We don't handle PPC little-endian any more... */
311312 if (cpu_has_feature(CPU_FTR_PPC_LE))
312313 return -EIO;
313
- instr = swab32(instr);
314
+ instr = ppc_inst_swab(instr);
314315 }
315316
316317 #ifdef CONFIG_SPE
317
- if ((instr >> 26) == 0x4) {
318
- int reg = (instr >> 21) & 0x1f;
318
+ if (ppc_inst_primary_opcode(instr) == 0x4) {
319
+ int reg = (ppc_inst_val(instr) >> 21) & 0x1f;
319320 PPC_WARN_ALIGNMENT(spe, regs);
320321 return emulate_spe(regs, reg, instr);
321322 }
....@@ -332,7 +333,7 @@
332333 * when pasting to a co-processor. Furthermore, paste_last is the
333334 * synchronisation point for preceding copy/paste sequences.
334335 */
335
- if ((instr & 0xfc0006fe) == (PPC_INST_COPY & 0xfc0006fe))
336
+ if ((ppc_inst_val(instr) & 0xfc0006fe) == (PPC_INST_COPY & 0xfc0006fe))
336337 return -EIO;
337338
338339 r = analyse_instr(&op, regs, instr);