Lines Matching +full:sw +full:- +full:exception
1 // SPDX-License-Identifier: GPL-2.0
3 * Architecture-specific unaligned trap handling.
5 * Copyright (C) 1999-2002, 2004 Hewlett-Packard Co
7 * David Mosberger-Tang <davidm@hpl.hp.com>
9 * 2002/12/09 Fix rotating register handling (off-by-1 error, missing fr-rotation). Fix
10 * get_rse_reg() to not leak kernel bits to user-level (reading an out-of-frame
28 #include <asm/exception.h>
69 * For M-unit:
72 * --------|------|---------|
73 * [40-37] | [36] | [35:30] |
74 * --------|------|---------|
76 * --------------------------
80 * checking the m-bit until later in the load/store emulation.
86 * Table C-28 Integer Load/Store
108 * Table C-29 Integer Load +Reg
110 * we use the ld->m (bit [36:36]) field to determine whether or not we have
115 * Table C-30 Integer Load/Store +Imm
137 * Table C-32 Floating-point Load/Store
150 * Table C-33 Floating-point Load +Reg
152 * we use the ld->m (bit [36:36]) field to determine whether or not we have
157 * Table C-34 Floating-point Load/Store +Imm
194 * A 2-byte value should be enough to hold any kind of offset
197 * simply use RSW instead of RPT or vice-versa.
200 #define RPO(x) ((size_t) &((struct pt_regs *)0)->x)
201 #define RSO(x) ((size_t) &((struct switch_stack *)0)->x)
213 0, /* r0 is read-only : WE SHOULD NEVER GET THIS */
271 /* Invalidate ALAT entry for floating-point register REGNO. */
303 reg -= sor; in rotate_reg()
310 struct switch_stack *sw = (struct switch_stack *) regs - 1; in set_rse_reg() local
315 long sof = (regs->cr_ifs) & 0x7f; in set_rse_reg()
316 long sor = 8 * ((regs->cr_ifs >> 14) & 0xf); in set_rse_reg()
317 long rrb_gr = (regs->cr_ifs >> 18) & 0x7f; in set_rse_reg()
318 long ridx = r1 - 32; in set_rse_reg()
329 DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n", in set_rse_reg()
330 r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx); in set_rse_reg()
332 on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore); in set_rse_reg()
333 addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + ridx); in set_rse_reg()
337 if ((unsigned long) rnat_addr >= sw->ar_bspstore) in set_rse_reg()
338 rnat_addr = &sw->ar_rnat; in set_rse_reg()
354 bspstore = (unsigned long *)regs->ar_bspstore; in set_rse_reg()
356 bsp = ia64_rse_skip_regs(ubs_end, -sof); in set_rse_reg()
361 ia64_poke(current, sw, (unsigned long) ubs_end, (unsigned long) addr, val); in set_rse_reg()
365 ia64_peek(current, sw, (unsigned long) ubs_end, (unsigned long) rnat_addr, &rnats); in set_rse_reg()
374 ia64_poke(current, sw, (unsigned long) ubs_end, (unsigned long) rnat_addr, rnats); in set_rse_reg()
383 struct switch_stack *sw = (struct switch_stack *) regs - 1; in get_rse_reg() local
388 long sof = (regs->cr_ifs) & 0x7f; in get_rse_reg()
389 long sor = 8 * ((regs->cr_ifs >> 14) & 0xf); in get_rse_reg()
390 long rrb_gr = (regs->cr_ifs >> 18) & 0x7f; in get_rse_reg()
391 long ridx = r1 - 32; in get_rse_reg()
394 /* read of out-of-frame register returns an undefined value; 0 in our case. */ in get_rse_reg()
402 DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n", in get_rse_reg()
403 r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx); in get_rse_reg()
405 on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore); in get_rse_reg()
406 addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + ridx); in get_rse_reg()
412 if ((unsigned long) rnat_addr >= sw->ar_bspstore) in get_rse_reg()
413 rnat_addr = &sw->ar_rnat; in get_rse_reg()
425 bspstore = (unsigned long *)regs->ar_bspstore; in get_rse_reg()
427 bsp = ia64_rse_skip_regs(ubs_end, -sof); in get_rse_reg()
432 ia64_peek(current, sw, (unsigned long) ubs_end, (unsigned long) addr, val); in get_rse_reg()
440 ia64_peek(current, sw, (unsigned long) ubs_end, (unsigned long) rnat_addr, &rnats); in get_rse_reg()
456 struct switch_stack *sw = (struct switch_stack *) regs - 1; in setreg() local
470 * Using r0 as a target raises a General Exception fault which has higher priority in setreg()
475 * Now look at registers in [0-31] range and init correct UNAT in setreg()
478 addr = (unsigned long)sw; in setreg()
479 unat = &sw->ar_unat; in setreg()
482 unat = &sw->caller_unat; in setreg()
485 addr, unat==&sw->ar_unat ? "yes":"no", GR_OFFS(regnum)); in setreg()
496 * UNAT bit_pos = GR[r3]{8:3} form EAS-2.4 in setreg()
510 * range from 32-127, result is in the range from 0-95.
515 unsigned long rrb_fr = (regs->cr_ifs >> 25) & 0x7f; in fph_index()
516 return rotate_reg(96, rrb_fr, (regnum - IA64_FIRST_ROTATING_FR)); in fph_index()
522 struct switch_stack *sw = (struct switch_stack *)regs - 1; in setfpreg() local
526 * From EAS-2.5: FPDisableFault has higher priority than Unaligned in setfpreg()
528 * To update f32-f127, there are three choices: in setfpreg()
530 * (1) save f32-f127 to thread.fph and update the values there in setfpreg()
538 current->thread.fph[fph_index(regs, regnum)] = *fpval; in setfpreg()
544 addr = (unsigned long)sw; in setfpreg()
560 regs->cr_ipsr |= IA64_PSR_MFL; in setfpreg()
583 struct switch_stack *sw = (struct switch_stack *) regs - 1; in getfpreg() local
587 * From EAS-2.5: FPDisableFault has higher priority than in getfpreg()
592 * to current->thread.fph to get access to it. See discussion in setfpreg() in getfpreg()
597 *fpval = current->thread.fph[fph_index(regs, regnum)]; in getfpreg()
614 addr = FR_IN_SW(regnum) ? (unsigned long)sw in getfpreg()
630 struct switch_stack *sw = (struct switch_stack *) regs - 1; in getreg() local
639 * take care of r0 (read-only always evaluate to 0) in getreg()
649 * Now look at registers in [0-31] range and init correct UNAT in getreg()
652 addr = (unsigned long)sw; in getreg()
653 unat = &sw->ar_unat; in getreg()
656 unat = &sw->caller_unat; in getreg()
744 * propagate Nat r2 -> r3 in emulate_load_updates()
790 return -1; in emulate_load_int()
792 /* this assumes little-endian byte-order: */ in emulate_load_int()
794 return -1; in emulate_load_int()
807 * - acquire semantics would have been used, so force fence instead. in emulate_load_int()
810 * - if we get to this handler, it's because the entry was not in the ALAT. in emulate_load_int()
814 * - same as previous one in emulate_load_int()
817 * - same as above for c.clr part. The load needs to have acquire semantics. So in emulate_load_int()
821 * - suppose ldX.a r1=[r3]. If we get to the unaligned trap it's because the in emulate_load_int()
865 * - ld.c.*, if the entry is not present a normal load is executed in emulate_load_int()
866 * - chk.a.*, if the entry is not present, execution jumps to recovery code in emulate_load_int()
917 return -1; in emulate_store_int()
920 /* this assumes little-endian byte-order: */ in emulate_store_int()
922 return -1; in emulate_store_int()
953 * to do the complete flush :-<< in emulate_store_int()
1067 * This assumes little-endian byte-order. Note that there is no "ldfpe" in emulate_load_floatpair()
1072 return -1; in emulate_load_floatpair()
1174 return -1; in emulate_load_float()
1267 return -1; in emulate_store_float()
1299 * to do the complete flush :-<< in emulate_store_float()
1324 int ret = -1; in ia64_handle_unaligned()
1327 if (ia64_psr(regs)->be) { in ia64_handle_unaligned()
1328 /* we don't support big-endian accesses */ in ia64_handle_unaligned()
1329 if (die_if_kernel("big-endian unaligned accesses are not supported", regs, 0)) in ia64_handle_unaligned()
1335 * Treat kernel accesses for which there is an exception handler entry the same as in ia64_handle_unaligned()
1336 * user-level unaligned accesses. Otherwise, a clever program could trick this in ia64_handle_unaligned()
1340 eh = search_exception_tables(regs->cr_iip + ia64_psr(regs)->ri); in ia64_handle_unaligned()
1342 if ((current->thread.flags & IA64_THREAD_UAC_SIGBUS) != 0) in ia64_handle_unaligned()
1346 !(current->thread.flags & IA64_THREAD_UAC_NOPRINT) && in ia64_handle_unaligned()
1353 "ip=0x%016lx\n\r", current->comm, in ia64_handle_unaligned()
1355 ifa, regs->cr_iip + ipsr->ri); in ia64_handle_unaligned()
1365 buf[len-1] = '\0'; /* drop '\r' */ in ia64_handle_unaligned()
1371 "unaligned exception which required\n" in ia64_handle_unaligned()
1374 "Unaligned exception warnings have " in ia64_handle_unaligned()
1377 "echo 0 > /proc/sys/kernel/ignore-" in ia64_handle_unaligned()
1378 "unaligned-usertrap to re-enable\n", in ia64_handle_unaligned()
1379 current->comm, task_pid_nr(current)); in ia64_handle_unaligned()
1385 ifa, regs->cr_iip + ipsr->ri); in ia64_handle_unaligned()
1393 regs->cr_iip, ifa, regs->cr_ipsr, ipsr->ri, ipsr->it); in ia64_handle_unaligned()
1395 if (emulate_load(bundle, regs->cr_iip, 16, kernel_mode)) in ia64_handle_unaligned()
1401 switch (ipsr->ri) { in ia64_handle_unaligned()
1422 * - ldX.spill in ia64_handle_unaligned()
1423 * - stX.spill in ia64_handle_unaligned()
1425 * - ld16 in ia64_handle_unaligned()
1426 * - st16 in ia64_handle_unaligned()
1431 * - cmpxchg in ia64_handle_unaligned()
1432 * - fetchadd in ia64_handle_unaligned()
1433 * - xchg in ia64_handle_unaligned()
1438 * - ldX.sZ in ia64_handle_unaligned()
1441 * --------------------------------------------------------------------------------- in ia64_handle_unaligned()
1468 regs->cr_ipsr |= IA64_PSR_ED; in ia64_handle_unaligned()
1532 if (ipsr->ri == 2) in ia64_handle_unaligned()
1538 regs->cr_iip += 16; in ia64_handle_unaligned()
1539 ipsr->ri = (ipsr->ri + 1) & 0x3; in ia64_handle_unaligned()
1541 DPRINT("ipsr->ri=%d iip=%lx\n", ipsr->ri, regs->cr_iip); in ia64_handle_unaligned()