#include <sys/param.h>
#include <sys/kdb.h>
#include <sys/proc.h>
#include <sys/ktr.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/ptrace.h>
#include <sys/reboot.h>
#include <sys/syscall.h>
#include <sys/sysent.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/uio.h>
#include <sys/signalvar.h>
#include <sys/vmmeter.h>
#include <security/audit/audit.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
#include <vm/vm_param.h>
#include <vm/vm_kern.h>
#include <vm/vm_map.h>
#include <vm/vm_page.h>
#include <machine/_inttypes.h>
#include <machine/altivec.h>
#include <machine/cpu.h>
#include <machine/db_machdep.h>
#include <machine/fpu.h>
#include <machine/frame.h>
#include <machine/pcb.h>
#include <machine/psl.h>
#include <machine/slb.h>
#include <machine/spr.h>
#include <machine/sr.h>
#include <machine/trap.h>
#define FAULTBUF_LR 21
#define FAULTBUF_R1 1
#define FAULTBUF_R2 2
#define FAULTBUF_CR 22
#define FAULTBUF_R14 3
#define MOREARGS(sp) ((caddr_t)((uintptr_t)(sp) + \
sizeof(struct callframe) - 3*sizeof(register_t)))
static void trap_fatal(struct trapframe *frame);
static void printtrap(u_int vector, struct trapframe *frame, int isfatal,
int user);
static bool trap_pfault(struct trapframe *frame, bool user, int *signo,
int *ucode);
static int fix_unaligned(struct thread *td, struct trapframe *frame);
static int handle_onfault(struct trapframe *frame);
static void syscall(struct trapframe *frame);
#if defined(__powerpc64__) && defined(AIM)
static void normalize_inputs(void);
#endif
extern vm_offset_t __startkernel;
extern int copy_fault(void);
extern int fusufault(void);
#ifdef KDB
int db_trap_glue(struct trapframe *);
#endif
struct powerpc_exception {
u_int vector;
char *name;
};
#ifdef KDTRACE_HOOKS
#include <sys/dtrace_bsd.h>
int (*dtrace_invop_jump_addr)(struct trapframe *);
#endif
static struct powerpc_exception powerpc_exceptions[] = {
{ EXC_CRIT, "critical input" },
{ EXC_RST, "system reset" },
{ EXC_MCHK, "machine check" },
{ EXC_DSI, "data storage interrupt" },
{ EXC_DSE, "data segment exception" },
{ EXC_ISI, "instruction storage interrupt" },
{ EXC_ISE, "instruction segment exception" },
{ EXC_EXI, "external interrupt" },
{ EXC_ALI, "alignment" },
{ EXC_PGM, "program" },
{ EXC_HEA, "hypervisor emulation assistance" },
{ EXC_FPU, "floating-point unavailable" },
{ EXC_APU, "auxiliary proc unavailable" },
{ EXC_DECR, "decrementer" },
{ EXC_FIT, "fixed-interval timer" },
{ EXC_WDOG, "watchdog timer" },
{ EXC_SC, "system call" },
{ EXC_TRC, "trace" },
{ EXC_FPA, "floating-point assist" },
{ EXC_DEBUG, "debug" },
{ EXC_PERF, "performance monitoring" },
{ EXC_VEC, "altivec unavailable" },
{ EXC_VSX, "vsx unavailable" },
{ EXC_FAC, "facility unavailable" },
{ EXC_HFAC, "hypervisor facility unavailable" },
{ EXC_ITMISS, "instruction tlb miss" },
{ EXC_DLMISS, "data load tlb miss" },
{ EXC_DSMISS, "data store tlb miss" },
{ EXC_BPT, "instruction breakpoint" },
{ EXC_SMI, "system management" },
{ EXC_VECAST_G4, "altivec assist" },
{ EXC_THRM, "thermal management" },
{ EXC_RUNMODETRC, "run mode/trace" },
{ EXC_SOFT_PATCH, "soft patch exception" },
{ EXC_HVI, "hypervisor virtualization" },
{ EXC_LAST, NULL }
};
static int uprintf_signal;
SYSCTL_INT(_machdep, OID_AUTO, uprintf_signal, CTLFLAG_RWTUN,
&uprintf_signal, 0,
"Print debugging information on trap signal to ctty");
#define ESR_BITMASK \
"\20" \
"\040b0\037b1\036b2\035b3\034PIL\033PRR\032PTR\031FP" \
"\030ST\027b9\026DLK\025ILK\024b12\023b13\022BO\021PIE" \
"\020b16\017b17\016b18\015b19\014b20\013b21\012b22\011b23" \
"\010SPE\007EPID\006b26\005b27\004b28\003b29\002b30\001b31"
#define MCSR_BITMASK \
"\20" \
"\040MCP\037ICERR\036DCERR\035TLBPERR\034L2MMU_MHIT\033b5\032b6\031b7" \
"\030b8\027b9\026b10\025NMI\024MAV\023MEA\022b14\021IF" \
"\020LD\017ST\016LDG\015b19\014b20\013b21\012b22\011b23" \
"\010b24\007b25\006b26\005b27\004b28\003b29\002TLBSYNC\001BSL2_ERR"
#define MSSSR_BITMASK \
"\20" \
"\040b0\037b1\036b2\035b3\034b4\033b5\032b6\031b7" \
"\030b8\027b9\026b10\025b11\024b12\023L2TAG\022L2DAT\021L3TAG" \
"\020L3DAT\017APE\016DPE\015TEA\014b20\013b21\012b22\011b23" \
"\010b24\007b25\006b26\005b27\004b28\003b29\002b30\001b31"
static const char *
trapname(u_int vector)
{
struct powerpc_exception *pe;
for (pe = powerpc_exceptions; pe->vector != EXC_LAST; pe++) {
if (pe->vector == vector)
return (pe->name);
}
return ("unknown");
}
static inline bool
frame_is_trap_inst(struct trapframe *frame)
{
#ifdef AIM
return (frame->exc == EXC_PGM && frame->srr1 & EXC_PGM_TRAP);
#else
return ((frame->cpu.booke.esr & ESR_PTR) != 0);
#endif
}
void
trap(struct trapframe *frame)
{
struct thread *td;
struct proc *p;
#ifdef KDTRACE_HOOKS
uint32_t inst;
#endif
int sig, type, user;
u_int ucode;
ksiginfo_t ksi;
register_t addr, fscr;
VM_CNT_INC(v_trap);
#ifdef KDB
if (kdb_active) {
kdb_reenter();
return;
}
#endif
td = curthread;
p = td->td_proc;
type = ucode = frame->exc;
sig = 0;
user = frame->srr1 & PSL_PR;
addr = 0;
CTR3(KTR_TRAP, "trap: %s type=%s (%s)", td->td_name,
trapname(type), user ? "user" : "kernel");
#ifdef KDTRACE_HOOKS
if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type) != 0)
return;
#endif
if (user) {
td->td_pticks = 0;
td->td_frame = frame;
addr = frame->srr0;
if (td->td_cowgen != atomic_load_int(&p->p_cowgen))
thread_cow_update(td);
switch (type) {
case EXC_RUNMODETRC:
case EXC_TRC:
frame->srr1 &= ~PSL_SE;
sig = SIGTRAP;
ucode = TRAP_TRACE;
break;
#if defined(__powerpc64__) && defined(AIM)
case EXC_DSE:
addr = frame->dar;
case EXC_ISE:
if (radix_mmu ||
handle_user_slb_spill(&p->p_vmspace->vm_pmap,
addr) != 0){
sig = SIGSEGV;
ucode = SEGV_MAPERR;
}
break;
#endif
case EXC_DSI:
addr = frame->dar;
case EXC_ISI:
if (trap_pfault(frame, true, &sig, &ucode))
sig = 0;
break;
case EXC_SC:
syscall(frame);
break;
case EXC_FPU:
KASSERT((td->td_pcb->pcb_flags & PCB_FPU) != PCB_FPU,
("FPU already enabled for thread"));
enable_fpu(td);
break;
case EXC_VEC:
KASSERT((td->td_pcb->pcb_flags & PCB_VEC) != PCB_VEC,
("Altivec already enabled for thread"));
enable_vec(td);
break;
case EXC_VSX:
KASSERT((td->td_pcb->pcb_flags & PCB_VSX) != PCB_VSX,
("VSX already enabled for thread"));
if (!(td->td_pcb->pcb_flags & PCB_VEC))
enable_vec(td);
if (td->td_pcb->pcb_flags & PCB_FPU)
save_fpu(td);
td->td_pcb->pcb_flags |= PCB_VSX;
enable_fpu(td);
break;
case EXC_FAC:
fscr = mfspr(SPR_FSCR);
switch (fscr & FSCR_IC_MASK) {
case FSCR_IC_HTM:
CTR0(KTR_TRAP,
"Hardware Transactional Memory subsystem disabled");
sig = SIGILL;
ucode = ILL_ILLOPC;
break;
case FSCR_IC_DSCR:
td->td_pcb->pcb_flags |= PCB_CFSCR | PCB_CDSCR;
fscr |= FSCR_DSCR;
mtspr(SPR_DSCR, 0);
break;
case FSCR_IC_EBB:
td->td_pcb->pcb_flags |= PCB_CFSCR;
fscr |= FSCR_EBB;
mtspr(SPR_EBBHR, 0);
mtspr(SPR_EBBRR, 0);
mtspr(SPR_BESCR, 0);
break;
case FSCR_IC_TAR:
td->td_pcb->pcb_flags |= PCB_CFSCR;
fscr |= FSCR_TAR;
mtspr(SPR_TAR, 0);
break;
case FSCR_IC_LM:
td->td_pcb->pcb_flags |= PCB_CFSCR;
fscr |= FSCR_LM;
mtspr(SPR_LMRR, 0);
mtspr(SPR_LMSER, 0);
break;
default:
sig = SIGILL;
ucode = ILL_ILLOPC;
}
mtspr(SPR_FSCR, fscr & ~FSCR_IC_MASK);
break;
case EXC_HEA:
case EXC_HFAC:
sig = SIGILL;
ucode = ILL_ILLOPC;
break;
case EXC_VECAST_E:
case EXC_VECAST_G4:
case EXC_VECAST_G5:
save_vec(td);
td->td_pcb->pcb_vec.vscr |= ALTIVEC_VSCR_NJ;
enable_vec(td);
break;
case EXC_ALI:
if (fix_unaligned(td, frame) != 0) {
sig = SIGBUS;
ucode = BUS_ADRALN;
addr = frame->dar;
}
else
frame->srr0 += 4;
break;
case EXC_DEBUG:
mtspr(SPR_DBSR, mfspr(SPR_DBSR));
frame->srr1 &= ~PSL_DE;
frame->cpu.booke.dbcr0 &= ~(DBCR0_IDM | DBCR0_IC);
sig = SIGTRAP;
ucode = TRAP_TRACE;
break;
case EXC_PGM:
if (frame_is_trap_inst(frame)) {
#ifdef KDTRACE_HOOKS
inst = fuword32((const void *)frame->srr0);
if (inst == 0x0FFFDDDD &&
dtrace_pid_probe_ptr != NULL) {
(*dtrace_pid_probe_ptr)(frame);
break;
}
#endif
sig = SIGTRAP;
ucode = TRAP_BRKPT;
break;
}
if ((frame->srr1 & EXC_PGM_FPENABLED) &&
(td->td_pcb->pcb_flags & PCB_FPU))
sig = SIGFPE;
else
sig = ppc_instr_emulate(frame, td);
if (sig == SIGILL) {
if (frame->srr1 & EXC_PGM_PRIV)
ucode = ILL_PRVOPC;
else if (frame->srr1 & EXC_PGM_ILLEGAL)
ucode = ILL_ILLOPC;
} else if (sig == SIGFPE) {
ucode = get_fpu_exception(td);
}
break;
case EXC_MCHK:
sig = cpu_machine_check(td, frame, &ucode);
printtrap(frame->exc, frame, 0, (frame->srr1 & PSL_PR));
break;
#if defined(__powerpc64__) && defined(AIM)
case EXC_SOFT_PATCH:
frame->srr0 -= 4;
normalize_inputs();
break;
#endif
default:
trap_fatal(frame);
}
} else {
KASSERT(cold || td->td_ucred != NULL,
("kernel trap doesn't have ucred"));
switch (type) {
case EXC_PGM:
#ifdef KDTRACE_HOOKS
if (frame_is_trap_inst(frame)) {
if (*(uint32_t *)frame->srr0 == EXC_DTRACE) {
if (dtrace_invop_jump_addr != NULL) {
dtrace_invop_jump_addr(frame);
return;
}
}
}
#endif
#ifdef KDB
if (db_trap_glue(frame))
return;
#endif
break;
#if defined(__powerpc64__) && defined(AIM)
case EXC_DSE:
if (radix_mmu)
break;
if (td->td_pcb->pcb_cpu.aim.usr_vsid != 0 &&
(frame->dar & SEGMENT_MASK) == USER_ADDR) {
__asm __volatile ("slbmte %0, %1" ::
"r"(td->td_pcb->pcb_cpu.aim.usr_vsid),
"r"(USER_SLB_SLBE));
return;
}
break;
#endif
case EXC_DSI:
if (trap_pfault(frame, false, NULL, NULL))
return;
break;
case EXC_MCHK:
if (handle_onfault(frame))
return;
break;
default:
break;
}
trap_fatal(frame);
}
if (sig != 0) {
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = sig;
ksi.ksi_code = (int) ucode;
ksi.ksi_addr = (void *)addr;
ksi.ksi_trapno = type;
if (uprintf_signal) {
uprintf("pid %d comm %s: signal %d code %d type 0x%x "
"addr 0x%lx r1 0x%lx srr0 0x%lx srr1 0x%lx\n",
p->p_pid, p->p_comm, sig, ucode, type,
(u_long)addr, (u_long)frame->fixreg[1],
(u_long)frame->srr0, (u_long)frame->srr1);
}
trapsignal(td, &ksi);
}
userret(td, frame);
}
static void
trap_fatal(struct trapframe *frame)
{
#ifdef KDB
bool handled;
#endif
printtrap(frame->exc, frame, 1, (frame->srr1 & PSL_PR));
#ifdef KDB
if (debugger_on_trap) {
kdb_why = KDB_WHY_TRAP;
handled = kdb_trap(frame->exc, 0, frame);
kdb_why = KDB_WHY_UNSET;
if (handled)
return;
}
#endif
panic("%s trap", trapname(frame->exc));
}
static void
cpu_printtrap(u_int vector, struct trapframe *frame, int isfatal, int user)
{
#ifdef AIM
uint16_t ver;
switch (vector) {
case EXC_MCHK:
ver = mfpvr() >> 16;
if (MPC745X_P(ver))
printf(" msssr0 = 0x%b\n",
(int)mfspr(SPR_MSSSR0), MSSSR_BITMASK);
case EXC_DSE:
case EXC_DSI:
case EXC_DTMISS:
printf(" dsisr = 0x%lx\n",
(u_long)frame->cpu.aim.dsisr);
break;
}
#elif defined(BOOKE)
vm_paddr_t pa;
switch (vector) {
case EXC_MCHK:
pa = mfspr(SPR_MCARU);
pa = (pa << 32) | (u_register_t)mfspr(SPR_MCAR);
printf(" mcsr = 0x%b\n",
(int)mfspr(SPR_MCSR), MCSR_BITMASK);
printf(" mcar = 0x%jx\n", (uintmax_t)pa);
}
printf(" esr = 0x%b\n",
(int)frame->cpu.booke.esr, ESR_BITMASK);
#endif
}
static void
printtrap(u_int vector, struct trapframe *frame, int isfatal, int user)
{
printf("\n");
printf("%s %s trap:\n", isfatal ? "fatal" : "handled",
user ? "user" : "kernel");
printf("\n");
printf(" exception = 0x%x (%s)\n", vector, trapname(vector));
switch (vector) {
case EXC_DSE:
case EXC_DSI:
case EXC_DTMISS:
case EXC_ALI:
case EXC_MCHK:
printf(" virtual address = 0x%" PRIxPTR "\n", frame->dar);
break;
case EXC_ISE:
case EXC_ISI:
case EXC_ITMISS:
printf(" virtual address = 0x%" PRIxPTR "\n", frame->srr0);
break;
}
cpu_printtrap(vector, frame, isfatal, user);
printf(" srr0 = 0x%" PRIxPTR " (0x%" PRIxPTR ")\n",
frame->srr0, frame->srr0 - (register_t)(__startkernel - KERNBASE));
printf(" srr1 = 0x%lx\n", (u_long)frame->srr1);
printf(" current msr = 0x%" PRIxPTR "\n", mfmsr());
printf(" lr = 0x%" PRIxPTR " (0x%" PRIxPTR ")\n",
frame->lr, frame->lr - (register_t)(__startkernel - KERNBASE));
printf(" frame = %p\n", frame);
printf(" curthread = %p\n", curthread);
if (curthread != NULL)
printf(" pid = %d, comm = %s\n",
curthread->td_proc->p_pid, curthread->td_name);
printf("\n");
}
static int
handle_onfault(struct trapframe *frame)
{
struct thread *td;
jmp_buf *fb;
td = curthread;
#if defined(__powerpc64__) || defined(BOOKE)
uintptr_t dispatch = (uintptr_t)td->td_pcb->pcb_onfault;
if (dispatch == 0)
return (0);
switch (dispatch) {
case COPYFAULT:
frame->srr0 = (uintptr_t)copy_fault;
return (1);
case FUSUFAULT:
frame->srr0 = (uintptr_t)fusufault;
return (1);
default:
break;
}
#endif
fb = td->td_pcb->pcb_onfault;
if (fb != NULL) {
frame->srr0 = (*fb)->_jb[FAULTBUF_LR];
frame->fixreg[1] = (*fb)->_jb[FAULTBUF_R1];
frame->fixreg[2] = (*fb)->_jb[FAULTBUF_R2];
frame->fixreg[3] = 1;
frame->cr = (*fb)->_jb[FAULTBUF_CR];
bcopy(&(*fb)->_jb[FAULTBUF_R14], &frame->fixreg[14],
18 * sizeof(register_t));
td->td_pcb->pcb_onfault = NULL;
return (1);
}
return (0);
}
int
cpu_fetch_syscall_args(struct thread *td)
{
struct proc *p;
struct trapframe *frame;
struct syscall_args *sa;
caddr_t params;
size_t argsz;
int error, n, narg, i;
p = td->td_proc;
frame = td->td_frame;
sa = &td->td_sa;
sa->code = frame->fixreg[0];
sa->original_code = sa->code;
params = (caddr_t)(frame->fixreg + FIRSTARG);
n = NARGREG;
if (sa->code == SYS_syscall) {
sa->code = *(register_t *) params;
params += sizeof(register_t);
n -= 1;
} else if (sa->code == SYS___syscall) {
if (SV_PROC_FLAG(p, SV_ILP32)) {
params += sizeof(register_t);
sa->code = *(register_t *) params;
params += sizeof(register_t);
n -= 2;
} else {
sa->code = *(register_t *) params;
params += sizeof(register_t);
n -= 1;
}
}
if (sa->code >= p->p_sysent->sv_size)
sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
narg = sa->callp->sy_narg;
if (SV_PROC_FLAG(p, SV_ILP32)) {
argsz = sizeof(uint32_t);
for (i = 0; i < n; i++)
sa->args[i] = ((u_register_t *)(params))[i] &
0xffffffff;
} else {
argsz = sizeof(uint64_t);
for (i = 0; i < n; i++)
sa->args[i] = ((u_register_t *)(params))[i];
}
if (narg > n)
error = copyin(MOREARGS(frame->fixreg[1]), sa->args + n,
(narg - n) * argsz);
else
error = 0;
#ifdef __powerpc64__
if (SV_PROC_FLAG(p, SV_ILP32) && narg > n) {
for (i = narg; i >= n; i--)
sa->args[i] = ((uint32_t *)(&sa->args[n]))[i-n];
}
#endif
if (error == 0) {
td->td_retval[0] = 0;
td->td_retval[1] = frame->fixreg[FIRSTARG + 1];
}
return (error);
}
#include "../../kern/subr_syscall.c"
void
syscall(struct trapframe *frame)
{
struct thread *td;
td = curthread;
td->td_frame = frame;
#if defined(__powerpc64__) && defined(AIM)
if (td->td_pcb->pcb_cpu.aim.usr_vsid != 0)
__asm __volatile ("slbmte %0, %1; isync" ::
"r"(td->td_pcb->pcb_cpu.aim.usr_vsid), "r"(USER_SLB_SLBE));
#endif
syscallenter(td);
syscallret(td);
}
static bool
trap_pfault(struct trapframe *frame, bool user, int *signo, int *ucode)
{
vm_offset_t eva;
struct thread *td;
struct proc *p;
vm_map_t map;
vm_prot_t ftype;
int rv, is_user;
td = curthread;
p = td->td_proc;
if (frame->exc == EXC_ISI) {
eva = frame->srr0;
ftype = VM_PROT_EXECUTE;
if (frame->srr1 & SRR1_ISI_PFAULT)
ftype |= VM_PROT_READ;
} else {
eva = frame->dar;
#ifdef BOOKE
if (frame->cpu.booke.esr & ESR_ST)
#else
if (frame->cpu.aim.dsisr & DSISR_STORE)
#endif
ftype = VM_PROT_WRITE;
else
ftype = VM_PROT_READ;
}
#if defined(__powerpc64__) && defined(AIM)
if (radix_mmu && pmap_nofault(&p->p_vmspace->vm_pmap, eva, ftype) == 0)
return (true);
#endif
if (__predict_true((td->td_pflags & TDP_NOFAULTING) == 0)) {
if (td->td_critnest != 0 ||
WITNESS_CHECK(WARN_SLEEPOK | WARN_GIANTOK, NULL,
"Kernel page fault") != 0) {
trap_fatal(frame);
return (false);
}
}
if (user) {
KASSERT(p->p_vmspace != NULL, ("trap_pfault: vmspace NULL"));
map = &p->p_vmspace->vm_map;
} else {
rv = pmap_decode_kernel_ptr(eva, &is_user, &eva);
if (rv != 0)
return (false);
if (is_user)
map = &p->p_vmspace->vm_map;
else
map = kernel_map;
}
rv = vm_fault_trap(map, eva, ftype, VM_FAULT_NORMAL, signo, ucode);
if (rv == KERN_SUCCESS)
return (true);
if (!user && handle_onfault(frame))
return (true);
return (false);
}
static int
fix_unaligned(struct thread *td, struct trapframe *frame)
{
struct thread *fputhread;
#ifdef BOOKE
uint32_t inst;
#endif
int indicator, reg;
double *fpr;
#ifdef BOOKE
indicator = (frame->cpu.booke.esr & ESR_ST) ? EXC_ALI_STFD : EXC_ALI_LFD;
#else
indicator = EXC_ALI_OPCODE_INDICATOR(frame->cpu.aim.dsisr);
#endif
switch (indicator) {
case EXC_ALI_LFD:
case EXC_ALI_STFD:
#ifdef BOOKE
if (copyin((void *)frame->srr0, &inst, sizeof(inst)) != 0)
return (-1);
reg = EXC_ALI_INST_RST(inst);
#else
reg = EXC_ALI_RST(frame->cpu.aim.dsisr);
#endif
fpr = &td->td_pcb->pcb_fpu.fpr[reg].fpr;
fputhread = PCPU_GET(fputhread);
if (fputhread != td) {
if (fputhread)
save_fpu(fputhread);
enable_fpu(td);
}
save_fpu(td);
if (indicator == EXC_ALI_LFD) {
if (copyin((void *)frame->dar, fpr,
sizeof(double)) != 0)
return (-1);
enable_fpu(td);
} else {
if (copyout(fpr, (void *)frame->dar,
sizeof(double)) != 0)
return (-1);
}
return (0);
break;
}
return (-1);
}
#if defined(__powerpc64__) && defined(AIM)
#define MSKNSHL(x, m, n) "(((" #x ") & " #m ") << " #n ")"
#define MSKNSHR(x, m, n) "(((" #x ") & " #m ") >> " #n ")"
#define XVCPSGNDP(xt, xa, xb) \
__asm __volatile(".long (" \
MSKNSHL(60, 0x3f, 26) " | " \
MSKNSHL(xt, 0x1f, 21) " | " \
MSKNSHL(xa, 0x1f, 16) " | " \
MSKNSHL(xb, 0x1f, 11) " | " \
MSKNSHL(240, 0xff, 3) " | " \
MSKNSHR(xa, 0x20, 3) " | " \
MSKNSHR(xa, 0x20, 4) " | " \
MSKNSHR(xa, 0x20, 5) ")")
#define NORM(x) XVCPSGNDP(x, x, x)
#define NORM10(x) \
NORM(x ## 0); NORM(x ## 1); NORM(x ## 2); NORM(x ## 3); NORM(x ## 4); \
NORM(x ## 5); NORM(x ## 6); NORM(x ## 7); NORM(x ## 8); NORM(x ## 9)
static void
normalize_inputs(void)
{
register_t msr;
msr = mfmsr();
mtmsr(msr | PSL_VSX);
NORM(0); NORM(1); NORM(2); NORM(3); NORM(4);
NORM(5); NORM(6); NORM(7); NORM(8); NORM(9);
NORM10(1); NORM10(2); NORM10(3); NORM10(4); NORM10(5);
NORM(60); NORM(61); NORM(62); NORM(63);
mtmsr(msr);
}
#endif
#ifdef KDB
int
db_trap_glue(struct trapframe *frame)
{
if (!(frame->srr1 & PSL_PR)
&& (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC
|| frame_is_trap_inst(frame)
|| frame->exc == EXC_BPT
|| frame->exc == EXC_DEBUG
|| frame->exc == EXC_DSI)) {
int type = frame->exc;
if (*(uint32_t *)frame->srr0 == EXC_DTRACE)
return (0);
if (frame_is_trap_inst(frame)) {
type = T_BREAKPOINT;
}
return (kdb_trap(type, 0, frame));
}
return (0);
}
#endif