Home | History | Annotate | Line # | Download | only in powerpc
      1 /*	$NetBSD: trap.c,v 1.168 2026/01/09 22:54:34 jmcneill Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
      5  * Copyright (C) 1995, 1996 TooLs GmbH.
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *	This product includes software developed by TooLs GmbH.
     19  * 4. The name of TooLs GmbH may not be used to endorse or promote products
     20  *    derived from this software without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
     23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 #define	__UFETCHSTORE_PRIVATE
     35 #define	__UCAS_PRIVATE
     36 
     37 #include <sys/cdefs.h>
     38 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.168 2026/01/09 22:54:34 jmcneill Exp $");
     39 
     40 #ifdef _KERNEL_OPT
     41 #include "opt_altivec.h"
     42 #include "opt_ddb.h"
     43 #include "opt_ppcarch.h"
     44 #endif
     45 
     46 #include <sys/param.h>
     47 
     48 #include <sys/proc.h>
     49 #include <sys/ras.h>
     50 #include <sys/reboot.h>
     51 #include <sys/systm.h>
     52 #include <sys/kauth.h>
     53 #include <sys/cpu.h>
     54 
     55 #include <uvm/uvm_extern.h>
     56 
     57 #include <dev/cons.h>
     58 
     59 #include <powerpc/altivec.h>
     60 #include <powerpc/db_machdep.h>
     61 #include <powerpc/fpu.h>
     62 #include <powerpc/frame.h>
     63 #include <powerpc/instr.h>
     64 #include <powerpc/pcb.h>
     65 #include <powerpc/pmap.h>
     66 #include <powerpc/trap.h>
     67 #include <powerpc/userret.h>
     68 
     69 #include <powerpc/spr.h>
     70 #include <powerpc/oea/spr.h>
     71 
     72 static int emulate_privileged(struct lwp *, struct trapframe *);
     73 static int fix_unaligned(struct lwp *, struct trapframe *);
     74 #ifdef PPC_IBMESPRESSO
     75 static int fix_stwcx(struct lwp *, struct trapframe *);
     76 #endif
     77 static inline vaddr_t setusr(vaddr_t, size_t *);
     78 static inline void unsetusr(void);
     79 
     80 void trap(struct trapframe *);	/* Called from locore / trap_subr */
     81 /* Why are these not defined in a header? */
     82 int badaddr(void *, size_t);
     83 int badaddr_read(void *, size_t, int *);
     84 
     85 struct dsi_info {
     86     uint16_t indicator;
     87     uint16_t flags;
     88 };
     89 
     90 static const struct dsi_info* get_dsi_info(register_t);
     91 
     92 void
     93 trap(struct trapframe *tf)
     94 {
     95 	struct cpu_info * const ci = curcpu();
     96 	struct lwp * const l = curlwp;
     97 	struct proc * const p = l->l_proc;
     98 	struct pcb * const pcb = curpcb;
     99 	struct vm_map *map;
    100 	ksiginfo_t ksi;
    101 	const bool usertrap = (tf->tf_srr1 & PSL_PR);
    102 	int type = tf->tf_exc;
    103 	int ftype, rv;
    104 
    105 	ci->ci_ev_traps.ev_count++;
    106 
    107 	KASSERTMSG(!usertrap || tf == l->l_md.md_utf,
    108 	    "trap: tf=%p is invalid: trapframe(%p)=%p", tf, l, l->l_md.md_utf);
    109 
    110 	if (usertrap) {
    111 		type |= EXC_USER;
    112 #ifdef DIAGNOSTIC
    113 		if (l == NULL || p == NULL)
    114 			panic("trap: user trap %d with lwp = %p, proc = %p",
    115 			    type, l, p);
    116 #endif
    117 	}
    118 
    119 	ci->ci_data.cpu_ntrap++;
    120 
    121 	switch (type) {
    122 	case EXC_RUNMODETRC|EXC_USER:
    123 		/* FALLTHROUGH */
    124 	case EXC_TRC|EXC_USER:
    125 		tf->tf_srr1 &= ~PSL_SE;
    126 		if (p->p_raslist == NULL ||
    127 		    ras_lookup(p, (void *)tf->tf_srr0) == (void *) -1) {
    128 			KSI_INIT_TRAP(&ksi);
    129 			ksi.ksi_signo = SIGTRAP;
    130 			ksi.ksi_trap = EXC_TRC;
    131 			ksi.ksi_addr = (void *)tf->tf_srr0;
    132 			ksi.ksi_code = TRAP_TRACE;
    133 			(*p->p_emul->e_trapsignal)(l, &ksi);
    134 		}
    135 		break;
    136 	case EXC_DSI: {
    137 		struct faultbuf * const fb = pcb->pcb_onfault;
    138 		vaddr_t va = tf->tf_dar;
    139 
    140 		ci->ci_ev_kdsi.ev_count++;
    141 
    142 		if ((va >> ADDR_SR_SHFT) == pcb->pcb_kmapsr) {
    143 			va &= ADDR_PIDX | ADDR_POFF;
    144 			va |= pcb->pcb_umapsr << ADDR_SR_SHFT;
    145 			map = &p->p_vmspace->vm_map;
    146 		}
    147 #if defined(DIAGNOSTIC) && !defined(PPC_OEA64)
    148 		else if (__predict_false((va >> ADDR_SR_SHFT) == USER_SR)) {
    149 			printf("trap: kernel %s DSI trap @ %#lx by %#lx"
    150 			    " (DSISR %#x): USER_SR unset\n",
    151 			    (tf->tf_dsisr & DSISR_STORE)
    152 				? "write" : "read",
    153 			    va, tf->tf_srr0, tf->tf_dsisr);
    154 			goto brain_damage2;
    155 		}
    156 #endif
    157 		else {
    158 			map = kernel_map;
    159 		}
    160 
    161 #ifdef PPC_OEA64
    162 		if ((tf->tf_dsisr & DSISR_NOTFOUND) &&
    163 		    vm_map_pmap(map)->pm_ste_evictions > 0 &&
    164 		    pmap_ste_spill(vm_map_pmap(map), trunc_page(va), false))
    165 			return;
    166 #endif
    167 		if ((tf->tf_dsisr & DSISR_NOTFOUND) &&
    168 		    vm_map_pmap(map)->pm_evictions > 0 &&
    169 		    pmap_pte_spill(vm_map_pmap(map), trunc_page(va), false))
    170 			return;
    171 
    172 		/*
    173 		 * Only query UVM if no interrupts are active.
    174 		 */
    175 		if (ci->ci_idepth < 0) {
    176 			if (tf->tf_dsisr & DSISR_STORE)
    177 				ftype = VM_PROT_WRITE;
    178 			else
    179 				ftype = VM_PROT_READ;
    180 
    181 			pcb->pcb_onfault = NULL;
    182 			rv = uvm_fault(map, trunc_page(va), ftype);
    183 			pcb->pcb_onfault = fb;
    184 
    185 			if (map != kernel_map) {
    186 				/*
    187 				 * Record any stack growth...
    188 				 */
    189 				if (rv == 0)
    190 					uvm_grow(p, trunc_page(va));
    191 			}
    192 			if (rv == 0)
    193 				return;
    194 			if (rv == EACCES)
    195 				rv = EFAULT;
    196 		} else {
    197 			/*
    198 			 * Note that this implies that access to the USER
    199 			 * segment is not allowed in interrupt context.
    200 			 */
    201 			rv = EFAULT;
    202 		}
    203 		if (fb != NULL) {
    204 			tf->tf_srr0 = fb->fb_pc;
    205 			tf->tf_cr = fb->fb_cr;
    206 			tf->tf_fixreg[1] = fb->fb_sp;
    207 			tf->tf_fixreg[2] = fb->fb_r2;
    208 			tf->tf_fixreg[3] = rv;
    209 			memcpy(&tf->tf_fixreg[13], fb->fb_fixreg,
    210 			    sizeof(fb->fb_fixreg));
    211 			return;
    212 		}
    213 		printf("trap: kernel %s DSI trap @ %#lx by %#lx (DSISR %#x, err"
    214 		    "=%d), lr %#lx\n", (tf->tf_dsisr & DSISR_STORE) ? "write" : "read",
    215 		    va, tf->tf_srr0, tf->tf_dsisr, rv, tf->tf_lr);
    216 		goto brain_damage2;
    217 	}
    218 	case EXC_DSI|EXC_USER:
    219 		ci->ci_ev_udsi.ev_count++;
    220 		if (tf->tf_dsisr & DSISR_STORE)
    221 			ftype = VM_PROT_WRITE;
    222 		else
    223 			ftype = VM_PROT_READ;
    224 
    225 		/*
    226 		 * Try to spill an evicted pte into the page table
    227 		 * if this wasn't a protection fault and the pmap
    228 		 * has some evicted pte's.
    229 		 */
    230 		map = &p->p_vmspace->vm_map;
    231 #ifdef PPC_OEA64
    232 		if ((tf->tf_dsisr & DSISR_NOTFOUND) &&
    233 		    vm_map_pmap(map)->pm_ste_evictions > 0 &&
    234 		    pmap_ste_spill(vm_map_pmap(map), trunc_page(tf->tf_dar),
    235 				   false)) {
    236 			break;
    237 		}
    238 #endif
    239 
    240 		if ((tf->tf_dsisr & DSISR_NOTFOUND) &&
    241 		    vm_map_pmap(map)->pm_evictions > 0 &&
    242 		    pmap_pte_spill(vm_map_pmap(map), trunc_page(tf->tf_dar),
    243 				   false)) {
    244 			break;
    245 		}
    246 
    247 		KASSERT(pcb->pcb_onfault == NULL);
    248 		rv = uvm_fault(map, trunc_page(tf->tf_dar), ftype);
    249 		if (rv == 0) {
    250 			/*
    251 			 * Record any stack growth...
    252 			 */
    253 			uvm_grow(p, trunc_page(tf->tf_dar));
    254 			break;
    255 		}
    256 		ci->ci_ev_udsi_fatal.ev_count++;
    257 		if (cpu_printfataltraps
    258 		    && (p->p_slflag & PSL_TRACED) == 0
    259 		    && !sigismember(&p->p_sigctx.ps_sigcatch, SIGSEGV)) {
    260 			printf("trap: pid %d.%d (%s): user %s DSI trap @ %#lx "
    261 			    "by %#lx (DSISR %#x, err=%d)\n",
    262 			    p->p_pid, l->l_lid, p->p_comm,
    263 			    (tf->tf_dsisr & DSISR_STORE) ? "write" : "read",
    264 			    tf->tf_dar, tf->tf_srr0, tf->tf_dsisr, rv);
    265 		}
    266 		KSI_INIT_TRAP(&ksi);
    267 		ksi.ksi_trap = EXC_DSI;
    268 		ksi.ksi_addr = (void *)tf->tf_dar;
    269 vm_signal:
    270 		switch (rv) {
    271 		case EINVAL:
    272 			ksi.ksi_signo = SIGBUS;
    273 			ksi.ksi_code = BUS_ADRERR;
    274 			break;
    275 		case EACCES:
    276 			ksi.ksi_signo = SIGSEGV;
    277 			ksi.ksi_code = SEGV_ACCERR;
    278 			break;
    279 		case ENOMEM:
    280 			ksi.ksi_signo = SIGKILL;
    281 			printf("UVM: pid %d.%d (%s), uid %d killed: "
    282 			       "out of swap\n", p->p_pid, l->l_lid, p->p_comm,
    283 			       l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1);
    284 			break;
    285 		default:
    286 			ksi.ksi_signo = SIGSEGV;
    287 			ksi.ksi_code = SEGV_MAPERR;
    288 			break;
    289 		}
    290 		(*p->p_emul->e_trapsignal)(l, &ksi);
    291 		break;
    292 
    293 	case EXC_ISI:
    294 		ci->ci_ev_kisi.ev_count++;
    295 
    296 		printf("trap: kernel ISI by %#lx (SRR1 %#lx), lr: %#lx\n",
    297 		    tf->tf_srr0, tf->tf_srr1, tf->tf_lr);
    298 		goto brain_damage2;
    299 
    300 	case EXC_ISI|EXC_USER:
    301 		ci->ci_ev_isi.ev_count++;
    302 
    303 		/*
    304 		 * Try to spill an evicted pte into the page table
    305 		 * if this wasn't a protection fault and the pmap
    306 		 * has some evicted pte's.
    307 		 */
    308 		map = &p->p_vmspace->vm_map;
    309 #ifdef PPC_OEA64
    310 		if (vm_map_pmap(map)->pm_ste_evictions > 0 &&
    311 		    pmap_ste_spill(vm_map_pmap(map), trunc_page(tf->tf_srr0),
    312 				   true)) {
    313 			break;
    314 		}
    315 #endif
    316 
    317 		if (vm_map_pmap(map)->pm_evictions > 0 &&
    318 		    pmap_pte_spill(vm_map_pmap(map), trunc_page(tf->tf_srr0),
    319 				   true)) {
    320 			break;
    321 		}
    322 
    323 		ftype = VM_PROT_EXECUTE;
    324 		KASSERT(pcb->pcb_onfault == NULL);
    325 		rv = uvm_fault(map, trunc_page(tf->tf_srr0), ftype);
    326 		if (rv == 0) {
    327 			break;
    328 		}
    329 		ci->ci_ev_isi_fatal.ev_count++;
    330 		if (cpu_printfataltraps
    331 		    && (p->p_slflag & PSL_TRACED) == 0
    332 		    && !sigismember(&p->p_sigctx.ps_sigcatch, SIGSEGV)) {
    333 			printf("trap: pid %d.%d (%s): user ISI trap @ %#lx "
    334 			    "(SRR1=%#lx)\n", p->p_pid, l->l_lid, p->p_comm,
    335 			    tf->tf_srr0, tf->tf_srr1);
    336 		}
    337 		KSI_INIT_TRAP(&ksi);
    338 		ksi.ksi_trap = EXC_ISI;
    339 		ksi.ksi_addr = (void *)tf->tf_srr0;
    340 		goto vm_signal;
    341 
    342 	case EXC_FPU|EXC_USER:
    343 		ci->ci_ev_fpu.ev_count++;
    344 		fpu_load();
    345 		break;
    346 
    347 	case EXC_AST|EXC_USER:
    348 		cpu_ast(l, ci);
    349 		break;
    350 
    351 	case EXC_ALI|EXC_USER:
    352 		ci->ci_ev_ali.ev_count++;
    353 		if (fix_unaligned(l, tf) != 0) {
    354 			ci->ci_ev_ali_fatal.ev_count++;
    355 			if (cpu_printfataltraps
    356 			    && (p->p_slflag & PSL_TRACED) == 0
    357 			    && !sigismember(&p->p_sigctx.ps_sigcatch, SIGBUS)) {
    358 				printf("trap: pid %d.%d (%s): user ALI trap @ "
    359 				    "%#lx by %#lx (DSISR %#x)\n",
    360 				    p->p_pid, l->l_lid, p->p_comm,
    361 				    tf->tf_dar, tf->tf_srr0, tf->tf_dsisr);
    362 			}
    363 			KSI_INIT_TRAP(&ksi);
    364 			ksi.ksi_signo = SIGBUS;
    365 			ksi.ksi_trap = EXC_ALI;
    366 			ksi.ksi_addr = (void *)tf->tf_dar;
    367 			ksi.ksi_code = BUS_ADRALN;
    368 			(*p->p_emul->e_trapsignal)(l, &ksi);
    369 		} else
    370 			tf->tf_srr0 += 4;
    371 		break;
    372 
    373 	case EXC_PERF|EXC_USER:
    374 		/* Not really, but needed due to how trap_subr.S works */
    375 	case EXC_VEC|EXC_USER:
    376 		ci->ci_ev_vec.ev_count++;
    377 #ifdef ALTIVEC
    378 		vec_load();
    379 		break;
    380 #else
    381 		if (cpu_printfataltraps
    382 		    && (p->p_slflag & PSL_TRACED) == 0
    383 		    && !sigismember(&p->p_sigctx.ps_sigcatch, SIGILL)) {
    384 			printf("trap: pid %d.%d (%s): user VEC trap @ %#lx "
    385 			    "(SRR1=%#lx)\n",
    386 			    p->p_pid, l->l_lid, p->p_comm,
    387 			    tf->tf_srr0, tf->tf_srr1);
    388 		}
    389 		KSI_INIT_TRAP(&ksi);
    390 		ksi.ksi_signo = SIGILL;
    391 		ksi.ksi_trap = EXC_PGM;
    392 		ksi.ksi_addr = (void *)tf->tf_srr0;
    393 		ksi.ksi_code = ILL_ILLOPC;
    394 		(*p->p_emul->e_trapsignal)(l, &ksi);
    395 		break;
    396 #endif
    397 	case EXC_MCHK|EXC_USER:
    398 		ci->ci_ev_umchk.ev_count++;
    399 		if (cpu_printfataltraps
    400 		    && (p->p_slflag & PSL_TRACED) == 0
    401 		    && !sigismember(&p->p_sigctx.ps_sigcatch, SIGBUS)) {
    402 			printf("trap: pid %d (%s): user MCHK trap @ %#lx "
    403 			    "(SRR1=%#lx)\n",
    404 			    p->p_pid, p->p_comm, tf->tf_srr0, tf->tf_srr1);
    405 		}
    406 		KSI_INIT_TRAP(&ksi);
    407 		ksi.ksi_signo = SIGBUS;
    408 		ksi.ksi_trap = EXC_MCHK;
    409 		ksi.ksi_addr = (void *)tf->tf_srr0;
    410 		ksi.ksi_code = BUS_OBJERR;
    411 		(*p->p_emul->e_trapsignal)(l, &ksi);
    412 		break;
    413 
    414 	case EXC_PGM|EXC_USER:
    415 		ci->ci_ev_pgm.ev_count++;
    416 		if (tf->tf_srr1 & 0x00020000) {	/* Bit 14 is set if trap */
    417 			if (p->p_raslist == NULL ||
    418 			    ras_lookup(p, (void *)tf->tf_srr0) == (void *) -1) {
    419 				KSI_INIT_TRAP(&ksi);
    420 				ksi.ksi_signo = SIGTRAP;
    421 				ksi.ksi_trap = EXC_PGM;
    422 				ksi.ksi_addr = (void *)tf->tf_srr0;
    423 				ksi.ksi_code = TRAP_BRKPT;
    424 				(*p->p_emul->e_trapsignal)(l, &ksi);
    425 			} else {
    426 				/* skip the trap instruction */
    427 				tf->tf_srr0 += 4;
    428 			}
    429 		} else {
    430 			KSI_INIT_TRAP(&ksi);
    431 			ksi.ksi_signo = SIGILL;
    432 			ksi.ksi_trap = EXC_PGM;
    433 			ksi.ksi_addr = (void *)tf->tf_srr0;
    434 			if (tf->tf_srr1 & 0x100000) {
    435 				ksi.ksi_signo = SIGFPE;
    436 				ksi.ksi_code = fpu_get_fault_code();
    437 			} else if (tf->tf_srr1 & 0x40000) {
    438 				if (emulate_privileged(l, tf)) {
    439 					tf->tf_srr0 += 4;
    440 					break;
    441 				}
    442 				ksi.ksi_code = ILL_PRVOPC;
    443 			} else {
    444 #ifdef PPC_IBMESPRESSO
    445 				if (fix_stwcx(l, tf)) {
    446 					tf->tf_srr0 += 4;
    447 					break;
    448 				}
    449 #endif
    450 				ksi.ksi_code = ILL_ILLOPC;
    451 			}
    452 			if (cpu_printfataltraps
    453 			    && (p->p_slflag & PSL_TRACED) == 0
    454 			    && !sigismember(&p->p_sigctx.ps_sigcatch,
    455 				    ksi.ksi_signo)) {
    456 				printf("trap: pid %d.%d (%s): user PGM trap @"
    457 				    " %#lx (SRR1=%#lx)\n", p->p_pid, l->l_lid,
    458 				    p->p_comm, tf->tf_srr0, tf->tf_srr1);
    459 			}
    460 			(*p->p_emul->e_trapsignal)(l, &ksi);
    461 		}
    462 		break;
    463 
    464 	case EXC_MCHK: {
    465 		struct faultbuf *fb;
    466 
    467 		if ((fb = pcb->pcb_onfault) != NULL) {
    468 			tf->tf_srr0 = fb->fb_pc;
    469 			tf->tf_fixreg[1] = fb->fb_sp;
    470 			tf->tf_fixreg[2] = fb->fb_r2;
    471 			tf->tf_fixreg[3] = EFAULT;
    472 			tf->tf_cr = fb->fb_cr;
    473 			memcpy(&tf->tf_fixreg[13], fb->fb_fixreg,
    474 			    sizeof(fb->fb_fixreg));
    475 			return;
    476 		}
    477 		printf("trap: pid %d.%d (%s): kernel MCHK trap @"
    478 		    " %#lx (SRR1=%#lx)\n", p->p_pid, l->l_lid,
    479 		    p->p_comm, tf->tf_srr0, tf->tf_srr1);
    480 		goto brain_damage2;
    481 	}
    482 	case EXC_ALI:
    483 		printf("trap: pid %d.%d (%s): kernel ALI trap @ %#lx by %#lx "
    484 		    "(DSISR %#x)\n", p->p_pid, l->l_lid, p->p_comm,
    485 		    tf->tf_dar, tf->tf_srr0, tf->tf_dsisr);
    486 		goto brain_damage2;
    487 	case EXC_PGM:
    488 		printf("trap: pid %d.%d (%s): kernel PGM trap @"
    489 		    " %#lx (SRR1=%#lx)\n", p->p_pid, l->l_lid,
    490 		    p->p_comm, tf->tf_srr0, tf->tf_srr1);
    491 		goto brain_damage2;
    492 
    493 	default:
    494 		printf("trap type %x at %lx\n", type, tf->tf_srr0);
    495 brain_damage2:
    496 #if defined(DDB) && 0 /* XXX */
    497 		if (kdb_trap(type, tf))
    498 			return;
    499 #endif
    500 #ifdef TRAP_PANICWAIT
    501 		printf("Press a key to panic.\n");
    502 		cnpollc(true);
    503 		cngetc();
    504 		cnpollc(false);
    505 #endif
    506 		panic("trap");
    507 	}
    508 	userret(l, tf);
    509 }
    510 
    511 #ifdef _LP64
    512 static inline vaddr_t
    513 setusr(vaddr_t uva, size_t *len_p)
    514 {
    515 	*len_p = SEGMENT_LENGTH - (uva & ~SEGMENT_MASK);
    516 	return pmap_setusr(uva) + (uva & ~SEGMENT_MASK);
    517 }
    518 static void
    519 unsetusr(void)
    520 {
    521 	pmap_unsetusr();
    522 }
    523 #else
    524 static inline vaddr_t
    525 setusr(vaddr_t uva, size_t *len_p)
    526 {
    527 	struct pcb *pcb = curpcb;
    528 	vaddr_t p;
    529 	KASSERT(pcb != NULL);
    530 	KASSERT(pcb->pcb_kmapsr == 0);
    531 	pcb->pcb_kmapsr = USER_SR;
    532 	pcb->pcb_umapsr = uva >> ADDR_SR_SHFT;
    533 	*len_p = SEGMENT_LENGTH - (uva & ~SEGMENT_MASK);
    534 	p = (USER_SR << ADDR_SR_SHFT) + (uva & ~SEGMENT_MASK);
    535 	__asm volatile ("isync; mtsr %0,%1; isync"
    536 	    ::	"n"(USER_SR), "r"(pcb->pcb_pm->pm_sr[pcb->pcb_umapsr]));
    537 	return p;
    538 }
    539 
    540 static void
    541 unsetusr(void)
    542 {
    543 	curpcb->pcb_kmapsr = 0;
    544 	__asm volatile ("isync; mtsr %0,%1; isync"
    545 	    ::	"n"(USER_SR), "r"(EMPTY_SEGMENT));
    546 }
    547 #endif
    548 
    549 #define	UFETCH(sz)							\
    550 int									\
    551 _ufetch_ ## sz(const uint ## sz ## _t *uaddr, uint ## sz ## _t *valp)	\
    552 {									\
    553 	struct faultbuf env;						\
    554 	vaddr_t p;							\
    555 	size_t seglen;							\
    556 	int rv;								\
    557 									\
    558 	if ((rv = setfault(&env)) != 0) {				\
    559 		goto out;						\
    560 	}								\
    561 	p = setusr((vaddr_t)uaddr, &seglen);				\
    562 	*valp = *(const volatile uint ## sz ## _t *)p;			\
    563  out:									\
    564 	unsetusr();							\
    565 	curpcb->pcb_onfault = 0;					\
    566 	return rv;							\
    567 }
    568 
    569 UFETCH(8)
    570 UFETCH(16)
    571 UFETCH(32)
    572 #ifdef _LP64
    573 UFETCH(64)
    574 #endif
    575 
    576 #undef UFETCH
    577 
    578 #define	USTORE(sz)							\
    579 int									\
    580 _ustore_ ## sz(uint ## sz ## _t *uaddr, uint ## sz ## _t val)		\
    581 {									\
    582 	struct faultbuf env;						\
    583 	vaddr_t p;							\
    584 	size_t seglen;							\
    585 	int rv;								\
    586 									\
    587 	if ((rv = setfault(&env)) != 0) {				\
    588 		goto out;						\
    589 	}								\
    590 	p = setusr((vaddr_t)uaddr, &seglen);				\
    591 	*(volatile uint ## sz ## _t *)p = val;				\
    592  out:									\
    593 	unsetusr();							\
    594 	curpcb->pcb_onfault = 0;					\
    595 	return rv;							\
    596 }
    597 
    598 USTORE(8)
    599 USTORE(16)
    600 USTORE(32)
    601 #ifdef _LP64
    602 USTORE(64)
    603 #endif
    604 
    605 #undef USTORE
    606 
    607 int
    608 copyin(const void *udaddr, void *kaddr, size_t len)
    609 {
    610 	vaddr_t uva = (vaddr_t) udaddr;
    611 	char *kp = kaddr;
    612 	struct faultbuf env;
    613 	int rv;
    614 
    615 	if ((rv = setfault(&env)) != 0) {
    616 		unsetusr();
    617 		goto out;
    618 	}
    619 
    620 	while (len > 0) {
    621 		size_t seglen;
    622 		vaddr_t p = setusr(uva, &seglen);
    623 		if (seglen > len)
    624 			seglen = len;
    625 		memcpy(kp, (const char *) p, seglen);
    626 		uva += seglen;
    627 		kp += seglen;
    628 		len -= seglen;
    629 		unsetusr();
    630 	}
    631 
    632   out:
    633 	curpcb->pcb_onfault = 0;
    634 	return rv;
    635 }
    636 
    637 int
    638 copyout(const void *kaddr, void *udaddr, size_t len)
    639 {
    640 	const char *kp = kaddr;
    641 	vaddr_t uva = (vaddr_t) udaddr;
    642 	struct faultbuf env;
    643 	int rv;
    644 
    645 	if ((rv = setfault(&env)) != 0) {
    646 		unsetusr();
    647 		goto out;
    648 	}
    649 
    650 	while (len > 0) {
    651 		size_t seglen;
    652 		vaddr_t p = setusr(uva, &seglen);
    653 		if (seglen > len)
    654 			seglen = len;
    655 		memcpy((char *)p, kp, seglen);
    656 		uva += seglen;
    657 		kp += seglen;
    658 		len -= seglen;
    659 		unsetusr();
    660 	}
    661 
    662   out:
    663 	curpcb->pcb_onfault = 0;
    664 	return rv;
    665 }
    666 
    667 /*
    668  * kcopy(const void *src, void *dst, size_t len);
    669  *
    670  * Copy len bytes from src to dst, aborting if we encounter a fatal
    671  * page fault.
    672  *
    673  * kcopy() _must_ save and restore the old fault handler since it is
    674  * called by uiomove(), which may be in the path of servicing a non-fatal
    675  * page fault.
    676  */
    677 int
    678 kcopy(const void *src, void *dst, size_t len)
    679 {
    680 	struct faultbuf env, *oldfault;
    681 	int rv;
    682 
    683 	oldfault = curpcb->pcb_onfault;
    684 
    685 	if ((rv = setfault(&env)) == 0)
    686 		memcpy(dst, src, len);
    687 
    688 	curpcb->pcb_onfault = oldfault;
    689 	return rv;
    690 }
    691 
    692 #if 0 /* XXX CPU configuration spaghetti */
    693 int
    694 _ucas_32(volatile uint32_t *uptr, uint32_t old, uint32_t new, uint32_t *ret)
    695 {
    696 	extern int do_ucas_32(volatile int32_t *, int32_t, int32_t, int32_t *);
    697 	vaddr_t uva = (vaddr_t)uptr;
    698 	vaddr_t p;
    699 	struct faultbuf env;
    700 	size_t seglen;
    701 	int rv;
    702 
    703 	if ((rv = setfault(&env)) != 0) {
    704 		unsetusr();
    705 		goto out;
    706 	}
    707 	p = setusr(uva, &seglen);
    708 	KASSERT(seglen >= sizeof(*uptr));
    709 	do_ucas_32((void *)p, old, new, ret);
    710 	unsetusr();
    711 
    712 out:
    713 	curpcb->pcb_onfault = 0;
    714 	return rv;
    715 }
    716 #endif
    717 
    718 int
    719 badaddr(void *addr, size_t size)
    720 {
    721 	return badaddr_read(addr, size, NULL);
    722 }
    723 
    724 int
    725 badaddr_read(void *addr, size_t size, int *rptr)
    726 {
    727 	struct faultbuf env;
    728 	int x;
    729 
    730 	/* Get rid of any stale machine checks that have been waiting.  */
    731 	__asm volatile ("sync; isync");
    732 
    733 	if (setfault(&env)) {
    734 		curpcb->pcb_onfault = 0;
    735 		__asm volatile ("sync");
    736 		return 1;
    737 	}
    738 
    739 	__asm volatile ("sync");
    740 
    741 	switch (size) {
    742 	case 1:
    743 		x = *(volatile int8_t *)addr;
    744 		break;
    745 	case 2:
    746 		x = *(volatile int16_t *)addr;
    747 		break;
    748 	case 4:
    749 		x = *(volatile int32_t *)addr;
    750 		break;
    751 	default:
    752 		panic("badaddr: invalid size (%lu)", (u_long) size);
    753 	}
    754 
    755 	/* Make sure we took the machine check, if we caused one. */
    756 	__asm volatile ("sync; isync");
    757 
    758 	curpcb->pcb_onfault = 0;
    759 	__asm volatile ("sync");	/* To be sure. */
    760 
    761 	/* Use the value to avoid reorder. */
    762 	if (rptr)
    763 		*rptr = x;
    764 
    765 	return 0;
    766 }
    767 
    768 /*
    769  * For now, this only deals with the particular unaligned access case
    770  * that gcc tends to generate.  Eventually it should handle all of the
    771  * possibilities that can happen on a 32-bit PowerPC in big-endian mode.
    772  */
    773 
    774 static int
    775 fix_unaligned(struct lwp *l, struct trapframe *tf)
    776 {
    777 	const struct dsi_info* dsi = get_dsi_info(tf->tf_dsisr);
    778 
    779 	if ( !dsi )
    780 	    return -1;
    781 
    782 	switch (dsi->indicator) {
    783 	case EXC_ALI_DCBZ:
    784 		{
    785 			/*
    786 			 * The DCBZ (Data Cache Block Zero) instruction
    787 			 * gives an alignment fault if used on non-cacheable
    788 			 * memory.  We handle the fault mainly for the
    789 			 * case when we are running with the cache disabled
    790 			 * for debugging.
    791 			 */
    792 			static char zeroes[MAXCACHELINESIZE];
    793 			int error;
    794 			error = copyout(zeroes,
    795 			    (void *)(tf->tf_dar & -curcpu()->ci_ci.dcache_line_size),
    796 			    curcpu()->ci_ci.dcache_line_size);
    797 			if (error)
    798 				return -1;
    799 			return 0;
    800 		}
    801 		break;
    802 
    803 	case EXC_ALI_LFD:
    804 	case EXC_ALI_LFDU:
    805 	case EXC_ALI_LDFX:
    806 	case EXC_ALI_LFDUX:
    807 		{
    808 			struct pcb * const pcb = lwp_getpcb(l);
    809 			const int reg = EXC_ALI_RST(tf->tf_dsisr);
    810 			const int a_reg = EXC_ALI_RA(tf->tf_dsisr);
    811 			uint64_t * const fpreg = &pcb->pcb_fpu.fpreg[reg];
    812 			register_t* a_reg_addr = &tf->tf_fixreg[a_reg];
    813 
    814 			/*
    815 			 * Juggle the FPU to ensure that we've initialized
    816 			 * the FPRs, and that their current state is in
    817 			 * the PCB.
    818 			 */
    819 
    820 			KASSERT(l == curlwp);
    821 			if (!fpu_used_p(l)) {
    822 				memset(&pcb->pcb_fpu, 0, sizeof(pcb->pcb_fpu));
    823 				fpu_mark_used(l);
    824 			} else {
    825 				fpu_save(l);
    826 			}
    827 
    828 			if (copyin((void *)tf->tf_dar, fpreg,
    829 				   sizeof(double)) != 0)
    830 				return -1;
    831 
    832 			if (dsi->flags & DSI_OP_INDEXED) {
    833 			    /* do nothing */
    834 			}
    835 
    836 			if (dsi->flags & DSI_OP_UPDATE) {
    837 			    /* this is valid for 601, but to simplify logic don't pass for any */
    838 			    if (a_reg == 0)
    839 				return -1;
    840 			    else
    841 				*a_reg_addr = tf->tf_dar;
    842 			}
    843 
    844 			fpu_load();
    845 			return 0;
    846 		}
    847 		break;
    848 
    849 	case EXC_ALI_STFD:
    850 	case EXC_ALI_STFDU:
    851 	case EXC_ALI_STFDX:
    852 	case EXC_ALI_STFDUX:
    853 		{
    854 			struct pcb * const pcb = lwp_getpcb(l);
    855 			const int reg = EXC_ALI_RST(tf->tf_dsisr);
    856 			const int a_reg = EXC_ALI_RA(tf->tf_dsisr);
    857 			uint64_t * const fpreg = &pcb->pcb_fpu.fpreg[reg];
    858 			register_t* a_reg_addr = &tf->tf_fixreg[a_reg];
    859 
    860 			/*
    861 			 * Juggle the FPU to ensure that we've initialized
    862 			 * the FPRs, and that their current state is in
    863 			 * the PCB.
    864 			 */
    865 
    866 			KASSERT(l == curlwp);
    867 			if (!fpu_used_p(l)) {
    868 				memset(&pcb->pcb_fpu, 0, sizeof(pcb->pcb_fpu));
    869 				fpu_mark_used(l);
    870 			} else {
    871 				fpu_save(l);
    872 			}
    873 
    874 			if (copyout(fpreg, (void *)tf->tf_dar,
    875 				    sizeof(double)) != 0)
    876 				return -1;
    877 
    878 			if (dsi->flags & DSI_OP_INDEXED) {
    879 			    /* do nothing */
    880 			}
    881 
    882 			if (dsi->flags & DSI_OP_UPDATE) {
    883 			    /* this is valid for 601, but to simplify logic don't pass for any */
    884 			    if (a_reg == 0)
    885 				return -1;
    886 			    else
    887 				*a_reg_addr = tf->tf_dar;
    888 			}
    889 
    890 			fpu_load();
    891 			return 0;
    892 		}
    893 		break;
    894 
    895 	case EXC_ALI_LHZ:
    896 	case EXC_ALI_LHZU:
    897 	case EXC_ALI_LHZX:
    898 	case EXC_ALI_LHZUX:
    899 	case EXC_ALI_LHA:
    900 	case EXC_ALI_LHAU:
    901 	case EXC_ALI_LHAX:
    902 	case EXC_ALI_LHAUX:
    903 	case EXC_ALI_LHBRX:
    904 		{
    905 		    const register_t ea_addr = tf->tf_dar;
    906 		    const unsigned int t_reg = EXC_ALI_RST(tf->tf_dsisr);
    907 		    const unsigned int a_reg = EXC_ALI_RA(tf->tf_dsisr);
    908 		    register_t* t_reg_addr = &tf->tf_fixreg[t_reg];
    909 		    register_t* a_reg_addr = &tf->tf_fixreg[a_reg];
    910 
    911 		    /* load into lower 2 bytes of reg */
    912 		    if (copyin((void *)ea_addr,
    913 			       t_reg_addr+2,
    914 			       sizeof(uint16_t)) != 0)
    915 			return -1;
    916 
    917 		    if (dsi->flags & DSI_OP_UPDATE) {
    918 			/* this is valid for 601, but to simplify logic don't pass for any */
    919 			if (a_reg == 0)
    920 			    return -1;
    921 			else
    922 			    *a_reg_addr = ea_addr;
    923 		    }
    924 
    925 		    if (dsi->flags & DSI_OP_INDEXED) {
    926 			/* do nothing , indexed address already in ea */
    927 		    }
    928 
    929 		    if (dsi->flags & DSI_OP_ZERO) {
    930 			/* clear upper 2 bytes */
    931 			*t_reg_addr &= 0x0000ffff;
    932 		    } else if (dsi->flags & DSI_OP_ALGEBRAIC) {
    933 			/* sign extend upper 2 bytes */
    934 			if (*t_reg_addr & 0x00008000)
    935 			    *t_reg_addr |= 0xffff0000;
    936 			else
    937 			    *t_reg_addr &= 0x0000ffff;
    938 		    }
    939 
    940 		    if (dsi->flags & DSI_OP_REVERSED) {
    941 			/* reverse lower 2 bytes */
    942 			uint32_t temp = *t_reg_addr;
    943 
    944 			*t_reg_addr = ((temp & 0x000000ff) << 8 ) |
    945 			              ((temp & 0x0000ff00) >> 8 );
    946 		    }
    947 		    return 0;
    948 		}
    949 		break;
    950 
    951 	case EXC_ALI_STH:
    952 	case EXC_ALI_STHU:
    953 	case EXC_ALI_STHX:
    954 	case EXC_ALI_STHUX:
    955 	case EXC_ALI_STHBRX:
    956 		{
    957 		    const register_t ea_addr = tf->tf_dar;
    958 		    const unsigned int s_reg = EXC_ALI_RST(tf->tf_dsisr);
    959 		    const unsigned int a_reg = EXC_ALI_RA(tf->tf_dsisr);
    960 		    register_t* s_reg_addr = &tf->tf_fixreg[s_reg];
    961 		    register_t* a_reg_addr = &tf->tf_fixreg[a_reg];
    962 
    963 		    /* byte-reversed write out of lower 2 bytes */
    964 		    if (dsi->flags & DSI_OP_REVERSED) {
    965 			uint16_t tmp = *s_reg_addr & 0xffff;
    966 			tmp = bswap16(tmp);
    967 
    968 			if (copyout(&tmp,
    969 				    (void *)ea_addr,
    970 				    sizeof(uint16_t)) != 0)
    971 			    return -1;
    972 		    }
    973 		    /* write out lower 2 bytes */
    974 		    else if (copyout(s_reg_addr+2,
    975 				     (void *)ea_addr,
    976 				     sizeof(uint16_t)) != 0) {
    977 			return -1;
    978 		    }
    979 
    980 		    if (dsi->flags & DSI_OP_INDEXED) {
    981 			/* do nothing, indexed address already in ea */
    982 		    }
    983 
    984 		    if (dsi->flags & DSI_OP_UPDATE) {
    985 			/* this is valid for 601, but to simplify logic don't pass for any */
    986 			if (a_reg == 0)
    987 			    return -1;
    988 			else
    989 			    *a_reg_addr = ea_addr;
    990 		    }
    991 
    992 		    return 0;
    993 		}
    994 		break;
    995 
    996 	case EXC_ALI_LWARX_LWZ:
    997 	case EXC_ALI_LWZU:
    998 	case EXC_ALI_LWZX:
    999 	case EXC_ALI_LWZUX:
   1000 	case EXC_ALI_LWBRX:
   1001 		{
   1002 		    const register_t ea_addr = tf->tf_dar;
   1003 		    const unsigned int t_reg = EXC_ALI_RST(tf->tf_dsisr);
   1004 		    const unsigned int a_reg = EXC_ALI_RA(tf->tf_dsisr);
   1005 		    register_t* t_reg_addr = &tf->tf_fixreg[t_reg];
   1006 		    register_t* a_reg_addr = &tf->tf_fixreg[a_reg];
   1007 
   1008 		    if (copyin((void *)ea_addr,
   1009 			       t_reg_addr,
   1010 			       sizeof(uint32_t)) != 0)
   1011 			return -1;
   1012 
   1013 		    if (dsi->flags & DSI_OP_UPDATE) {
   1014 			/* this is valid for 601, but to simplify logic don't pass for any */
   1015 			if (a_reg == 0)
   1016 			    return -1;
   1017 			else
   1018 			    *a_reg_addr = ea_addr;
   1019 		    }
   1020 
   1021 		    if (dsi->flags & DSI_OP_INDEXED) {
   1022 			/* do nothing , indexed address already in ea */
   1023 		    }
   1024 
   1025 		    if (dsi->flags & DSI_OP_ZERO) {
   1026 			/* XXX - 64bit clear upper word */
   1027 		    }
   1028 
   1029 		    if (dsi->flags & DSI_OP_REVERSED) {
   1030 			/* reverse  bytes */
   1031 			register_t temp = bswap32(*t_reg_addr);
   1032 			*t_reg_addr = temp;
   1033 		    }
   1034 
   1035 		    return 0;
   1036 		}
   1037 		break;
   1038 
   1039 	case EXC_ALI_STW:
   1040 	case EXC_ALI_STWU:
   1041 	case EXC_ALI_STWX:
   1042 	case EXC_ALI_STWUX:
   1043 	case EXC_ALI_STWBRX:
   1044 		{
   1045 		    const register_t ea_addr = tf->tf_dar;
   1046 		    const unsigned int s_reg = EXC_ALI_RST(tf->tf_dsisr);
   1047 		    const unsigned int a_reg = EXC_ALI_RA(tf->tf_dsisr);
   1048 		    register_t* s_reg_addr = &tf->tf_fixreg[s_reg];
   1049 		    register_t* a_reg_addr = &tf->tf_fixreg[a_reg];
   1050 
   1051 		    if (dsi->flags & DSI_OP_REVERSED) {
   1052 			/* byte-reversed write out */
   1053 			register_t temp = bswap32(*s_reg_addr);
   1054 
   1055 			if (copyout(&temp,
   1056 				    (void *)ea_addr,
   1057 				    sizeof(uint32_t)) != 0)
   1058 			    return -1;
   1059 		    }
   1060 		    /* write out word */
   1061 		    else if (copyout(s_reg_addr,
   1062 				     (void *)ea_addr,
   1063 				     sizeof(uint32_t)) != 0)
   1064 			return -1;
   1065 
   1066 		    if (dsi->flags & DSI_OP_INDEXED) {
   1067 			/* do nothing, indexed address already in ea */
   1068 		    }
   1069 
   1070 		    if (dsi->flags & DSI_OP_UPDATE) {
   1071 			/* this is valid for 601, but to simplify logic don't pass for any */
   1072 			if (a_reg == 0)
   1073 			    return -1;
   1074 			else
   1075 			    *a_reg_addr = ea_addr;
   1076 		    }
   1077 
   1078 		    return 0;
   1079 		}
   1080 		break;
   1081 	}
   1082 
   1083 	return -1;
   1084 }
   1085 
   1086 static int
   1087 emulate_privileged(struct lwp *l, struct trapframe *tf)
   1088 {
   1089 	uint32_t opcode;
   1090 
   1091 	if (copyin((void *)tf->tf_srr0, &opcode, sizeof(opcode)) != 0)
   1092 		return 0;
   1093 
   1094 	if (OPC_MFSPR_P(opcode, SPR_PVR)) {
   1095 		__asm ("mfpvr %0" : "=r"(tf->tf_fixreg[OPC_MFSPR_REG(opcode)]));
   1096 		return 1;
   1097 	}
   1098 
   1099 	return emulate_mxmsr(l, tf, opcode);
   1100 }
   1101 
   1102 int
   1103 copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
   1104 {
   1105 	vaddr_t uva = (vaddr_t) udaddr;
   1106 	char *kp = kaddr;
   1107 	struct faultbuf env;
   1108 	int rv;
   1109 
   1110 	if ((rv = setfault(&env)) != 0) {
   1111 		unsetusr();
   1112 		goto out2;
   1113 	}
   1114 
   1115 	while (len > 0) {
   1116 		size_t seglen;
   1117 		vaddr_t p = setusr(uva, &seglen);
   1118 		if (seglen > len)
   1119 			seglen = len;
   1120 		len -= seglen;
   1121 		uva += seglen;
   1122 		for (; seglen-- > 0; p++) {
   1123 			if ((*kp++ = *(char *)p) == 0) {
   1124 				unsetusr();
   1125 				goto out;
   1126 			}
   1127 		}
   1128 		unsetusr();
   1129 	}
   1130 	rv = ENAMETOOLONG;
   1131 
   1132  out:
   1133 	if (done != NULL)
   1134 		*done = kp - (char *) kaddr;
   1135  out2:
   1136 	curpcb->pcb_onfault = 0;
   1137 	return rv;
   1138 }
   1139 
   1140 
   1141 int
   1142 copyoutstr(const void *kaddr, void *udaddr, size_t len, size_t *done)
   1143 {
   1144 	const char *kp = kaddr;
   1145 	vaddr_t uva = (vaddr_t) udaddr;
   1146 	struct faultbuf env;
   1147 	int rv;
   1148 
   1149 	if ((rv = setfault(&env)) != 0) {
   1150 		unsetusr();
   1151 		goto out2;
   1152 	}
   1153 
   1154 	while (len > 0) {
   1155 		size_t seglen;
   1156 		vaddr_t p = setusr(uva, &seglen);
   1157 		if (seglen > len)
   1158 			seglen = len;
   1159 		len -= seglen;
   1160 		uva += seglen;
   1161 		for (; seglen-- > 0; p++) {
   1162 			if ((*(char *)p = *kp++) == 0) {
   1163 				unsetusr();
   1164 				goto out;
   1165 			}
   1166 		}
   1167 		unsetusr();
   1168 	}
   1169 	rv = ENAMETOOLONG;
   1170 
   1171  out:
   1172 	if (done != NULL)
   1173 		*done = kp - (const char*)kaddr;
   1174  out2:
   1175 	curpcb->pcb_onfault = 0;
   1176 	return rv;
   1177 }
   1178 
   1179 const struct dsi_info*
   1180 get_dsi_info(register_t dsisr)
   1181 {
   1182     static const struct dsi_info dsi[] =
   1183 	{
   1184 	    /* data cache block zero */
   1185 	    {EXC_ALI_DCBZ, 0},
   1186 
   1187 	    /* load halfwords */
   1188 	    {EXC_ALI_LHZ,   DSI_OP_ZERO},
   1189 	    {EXC_ALI_LHZU,  DSI_OP_ZERO|DSI_OP_UPDATE},
   1190 	    {EXC_ALI_LHZX,  DSI_OP_ZERO|DSI_OP_INDEXED},
   1191 	    {EXC_ALI_LHZUX, DSI_OP_ZERO|DSI_OP_UPDATE|DSI_OP_INDEXED},
   1192 	    {EXC_ALI_LHA,   DSI_OP_ALGEBRAIC},
   1193 	    {EXC_ALI_LHAU,  DSI_OP_ALGEBRAIC|DSI_OP_UPDATE},
   1194 	    {EXC_ALI_LHAX,  DSI_OP_ALGEBRAIC|DSI_OP_INDEXED},
   1195 	    {EXC_ALI_LHAUX, DSI_OP_ALGEBRAIC|DSI_OP_UPDATE|DSI_OP_INDEXED},
   1196 
   1197 	    /* store halfwords */
   1198 	    {EXC_ALI_STH,   0},
   1199 	    {EXC_ALI_STHU,  DSI_OP_UPDATE},
   1200 	    {EXC_ALI_STHX,  DSI_OP_INDEXED},
   1201 	    {EXC_ALI_STHUX, DSI_OP_UPDATE|DSI_OP_INDEXED},
   1202 
   1203 	    /* load words */
   1204 	    {EXC_ALI_LWARX_LWZ, DSI_OP_ZERO},
   1205 	    {EXC_ALI_LWZU,      DSI_OP_ZERO|DSI_OP_UPDATE},
   1206 	    {EXC_ALI_LWZX,      DSI_OP_ZERO|DSI_OP_INDEXED},
   1207 	    {EXC_ALI_LWZUX,     DSI_OP_ZERO|DSI_OP_UPDATE|DSI_OP_INDEXED},
   1208 
   1209 	    /* store words */
   1210 	    {EXC_ALI_STW,   0},
   1211 	    {EXC_ALI_STWU,  DSI_OP_UPDATE},
   1212 	    {EXC_ALI_STWX,  DSI_OP_INDEXED},
   1213 	    {EXC_ALI_STWUX, DSI_OP_UPDATE|DSI_OP_INDEXED},
   1214 
   1215 	    /* load byte-reversed */
   1216 	    {EXC_ALI_LHBRX, DSI_OP_REVERSED|DSI_OP_INDEXED|DSI_OP_ZERO},
   1217 	    {EXC_ALI_LWBRX, DSI_OP_REVERSED|DSI_OP_INDEXED},
   1218 
   1219 	    /* store byte-reversed */
   1220 	    {EXC_ALI_STHBRX, DSI_OP_REVERSED|DSI_OP_INDEXED},
   1221 	    {EXC_ALI_STWBRX, DSI_OP_REVERSED|DSI_OP_INDEXED},
   1222 
   1223 	    /* load float double-precision */
   1224 	    {EXC_ALI_LFD,   0},
   1225 	    {EXC_ALI_LFDU,  DSI_OP_UPDATE},
   1226 	    {EXC_ALI_LDFX,  DSI_OP_INDEXED},
   1227 	    {EXC_ALI_LFDUX, DSI_OP_UPDATE|DSI_OP_INDEXED},
   1228 
   1229 	    /* store float double precision */
   1230 	    {EXC_ALI_STFD,   0},
   1231 	    {EXC_ALI_STFDU,  DSI_OP_UPDATE},
   1232 	    {EXC_ALI_STFDX,  DSI_OP_INDEXED},
   1233 	    {EXC_ALI_STFDUX, DSI_OP_UPDATE|DSI_OP_INDEXED},
   1234 
   1235 	    /* XXX - ones below here not yet implemented in fix_unaligned() */
   1236 	    /* load float single precision */
   1237 	    {EXC_ALI_LFS,   0},
   1238 	    {EXC_ALI_LFSU,  DSI_OP_UPDATE},
   1239 	    {EXC_ALI_LSFX,  DSI_OP_INDEXED},
   1240 	    {EXC_ALI_LFSUX, DSI_OP_UPDATE|DSI_OP_INDEXED},
   1241 
   1242 	    /* store float single precision */
   1243 	    {EXC_ALI_STFS,   0},
   1244 	    {EXC_ALI_STFSU,  DSI_OP_UPDATE},
   1245 	    {EXC_ALI_STFSX,  DSI_OP_INDEXED},
   1246 	    {EXC_ALI_STFSUX, DSI_OP_UPDATE|DSI_OP_INDEXED},
   1247 
   1248 	    /* multiple */
   1249 	    {EXC_ALI_LMW,  0},
   1250 	    {EXC_ALI_STMW, 0},
   1251 
   1252 	    /* load & store string */
   1253 	    {EXC_ALI_LSWI, 0},
   1254 	    {EXC_ALI_LSWX, DSI_OP_INDEXED},
   1255 	    {EXC_ALI_STSWI, 0},
   1256 	    {EXC_ALI_STSWX, DSI_OP_INDEXED},
   1257 
   1258 	    /* get/send word from external */
   1259 	    {EXC_ALI_ECIWX, DSI_OP_INDEXED},
   1260 	    {EXC_ALI_ECOWX, DSI_OP_INDEXED},
   1261 
   1262 	    /* store float as integer word */
   1263 	    {EXC_ALI_STFIWX, 0},
   1264 
   1265 	    /* store conditional */
   1266 	    {EXC_ALI_LDARX, DSI_OP_INDEXED}, /* stdcx */
   1267 	    {EXC_ALI_STDCX, DSI_OP_INDEXED},
   1268 	    {EXC_ALI_STWCX, DSI_OP_INDEXED},  /* lwarx */
   1269 
   1270 #ifdef PPC_OEA64
   1271 	    /* 64 bit, load word algebriac */
   1272 	    {EXC_ALI_LWAX,  DSI_OP_ALGEBRAIC|DSI_OP_INDEXED},
   1273 	    {EXC_ALI_LWAUX, DSI_OP_ALGEBRAIC|DSI_OP_UPDATE|DSI_OP_INDEXED},
   1274 
   1275 	    /* 64 bit load doubleword */
   1276 	    {EXC_ALI_LD_LDU_LWA, 0},
   1277 	    {EXC_ALI_LDX,        DSI_OP_INDEXED},
   1278 	    {EXC_ALI_LDUX,       DSI_OP_UPDATE|DSI_OP_INDEXED},
   1279 
   1280 	    /* 64 bit store double word */
   1281 	    {EXC_ALI_STD_STDU, 0},
   1282 	    {EXC_ALI_STDX,     DSI_OP_INDEXED},
   1283 	    {EXC_ALI_STDUX,    DSI_OP_UPDATE|DSI_OP_INDEXED},
   1284 #endif
   1285 	};
   1286 
   1287     int num_elems = sizeof(dsi)/sizeof(dsi[0]);
   1288     int indicator = EXC_ALI_OPCODE_INDICATOR(dsisr);
   1289     int i;
   1290 
   1291     for (i = 0 ; i < num_elems; i++) {
   1292 	if (indicator == dsi[i].indicator){
   1293 	    return &dsi[i];
   1294 	}
   1295     }
   1296     return 0;
   1297 }
   1298 
   1299 #ifdef PPC_IBMESPRESSO
   1300 static int
   1301 fix_stwcx(struct lwp *l, struct trapframe *tf)
   1302 {
   1303 	struct faultbuf env;
   1304 	union instr instr;
   1305 	vaddr_t uva, p;
   1306 	size_t len;
   1307 	uint32_t cr;
   1308 
   1309 	if (copyin((void *)tf->tf_srr0, &instr.i_int, sizeof(instr)) != 0) {
   1310 		printf("trap: copyin of 0x%08lx failed\n", tf->tf_srr0);
   1311 		return 0;
   1312 	}
   1313 
   1314 	if (instr.i_any.i_opcd != OPC_integer_31 ||
   1315 	    instr.i_x.i_xo != OPC31_STWCX) {
   1316 		return 0;
   1317 	}
   1318 	KASSERT(instr.i_x.i_rc == 0);
   1319 
   1320 	if (setfault(&env) != 0) {
   1321 		unsetusr();
   1322 		curpcb->pcb_onfault = 0;
   1323 		printf("trap: stwcx. emulate failed\n");
   1324 		return 0;
   1325 	}
   1326 
   1327 	uva = (instr.i_x.i_ra ? tf->tf_ureg.r_fixreg[instr.i_x.i_ra] : 0) +
   1328 	      tf->tf_ureg.r_fixreg[instr.i_x.i_rb];
   1329 	p = setusr(uva, &len);
   1330 
   1331 	asm volatile(
   1332 	    "dcbst	0, %1		\n"
   1333 	    "stwcx.	%2, 0, %1	\n"
   1334 	    "mfcr	%0		\n"
   1335 	    : "=r" (cr)
   1336 	    : "r" (p),
   1337 	      "r" (tf->tf_ureg.r_fixreg[instr.i_x.i_rs])
   1338 	    : "cr0", "memory"
   1339 	);
   1340 
   1341 	tf->tf_ureg.r_cr &= ~0xf0000000;
   1342 	tf->tf_ureg.r_cr |= (cr & 0xf0000000);
   1343 
   1344 	unsetusr();
   1345 	curpcb->pcb_onfault = 0;
   1346 	return 1;
   1347 }
   1348 #endif
   1349