Simplify trapcode setup by placing a copy of the generic trap handler at

every possible trap address by default. This also makes sure the kernel
notices (and panics at) traps from newer CPUs that the kernel was not
expecting rather than executing gibberish memory.
This commit is contained in:
Nathan Whitehorn 2015-02-09 02:12:38 +00:00
parent 0f638f5385
commit 0eb1bfa5e7

View File

@ -256,6 +256,7 @@ powerpc_init(vm_offset_t fdt, vm_offset_t toc, vm_offset_t ofentry, void *mdp)
vm_offset_t startkernel, endkernel;
void *generictrap;
size_t trap_offset, trapsize;
vm_offset_t trap;
void *kmdp;
char *env;
register_t msr, scratch;
@ -480,20 +481,6 @@ powerpc_init(vm_offset_t fdt, vm_offset_t toc, vm_offset_t ofentry, void *mdp)
bcopy(&rfid_patch,&rfi_patch2,4);
#endif
/*
* Copy a code snippet to restore 32-bit bridge mode
* to the top of every non-generic trap handler
*/
trap_offset += (size_t)&restorebridgesize;
bcopy(&restorebridge, (void *)EXC_RST, trap_offset);
bcopy(&restorebridge, (void *)EXC_DSI, trap_offset);
bcopy(&restorebridge, (void *)EXC_ALI, trap_offset);
bcopy(&restorebridge, (void *)EXC_PGM, trap_offset);
bcopy(&restorebridge, (void *)EXC_MCHK, trap_offset);
bcopy(&restorebridge, (void *)EXC_TRC, trap_offset);
bcopy(&restorebridge, (void *)EXC_BPT, trap_offset);
/*
* Set the common trap entry point to the one that
* knows to restore 32-bit operation on execution.
@ -507,14 +494,35 @@ powerpc_init(vm_offset_t fdt, vm_offset_t toc, vm_offset_t ofentry, void *mdp)
#else /* powerpc64 */
cpu_features |= PPC_FEATURE_64;
generictrap = &trapcode;
/* Set TOC base so that the interrupt code can get at it */
*((void **)TRAP_GENTRAP) = &trapcode2;
*((register_t *)TRAP_TOCBASE) = toc;
#endif
trapsize = (size_t)&trapcodeend - (size_t)&trapcode;
/*
* Copy generic handler into every possible trap. Special cases will get
* different ones in a minute.
*/
for (trap = EXC_RST; trap < EXC_LAST; trap += 0x20)
bcopy(generictrap, (void *)trap, trapsize);
#ifndef __powerpc64__
if (cpu_features & PPC_FEATURE_64) {
/*
* Copy a code snippet to restore 32-bit bridge mode
* to the top of every non-generic trap handler
*/
trap_offset += (size_t)&restorebridgesize;
bcopy(&restorebridge, (void *)EXC_RST, trap_offset);
bcopy(&restorebridge, (void *)EXC_DSI, trap_offset);
bcopy(&restorebridge, (void *)EXC_ALI, trap_offset);
bcopy(&restorebridge, (void *)EXC_PGM, trap_offset);
bcopy(&restorebridge, (void *)EXC_MCHK, trap_offset);
bcopy(&restorebridge, (void *)EXC_TRC, trap_offset);
bcopy(&restorebridge, (void *)EXC_BPT, trap_offset);
}
#endif
bcopy(&rstcode, (void *)(EXC_RST + trap_offset), (size_t)&rstcodeend -
(size_t)&rstcode);
@ -527,31 +535,20 @@ powerpc_init(vm_offset_t fdt, vm_offset_t toc, vm_offset_t ofentry, void *mdp)
(size_t)&dblow);
bcopy(&dblow, (void *)(EXC_BPT + trap_offset), (size_t)&dbend -
(size_t)&dblow);
#else
bcopy(generictrap, (void *)EXC_MCHK, trapsize);
bcopy(generictrap, (void *)EXC_PGM, trapsize);
bcopy(generictrap, (void *)EXC_TRC, trapsize);
bcopy(generictrap, (void *)EXC_BPT, trapsize);
#endif
bcopy(&alitrap, (void *)(EXC_ALI + trap_offset), (size_t)&aliend -
(size_t)&alitrap);
bcopy(&dsitrap, (void *)(EXC_DSI + trap_offset), (size_t)&dsiend -
(size_t)&dsitrap);
bcopy(generictrap, (void *)EXC_ISI, trapsize);
#ifdef __powerpc64__
/* Set TOC base so that the interrupt code can get at it */
*((void **)TRAP_GENTRAP) = &trapcode2;
*((register_t *)TRAP_TOCBASE) = toc;
bcopy(&slbtrap, (void *)EXC_DSE,(size_t)&slbtrapend - (size_t)&slbtrap);
bcopy(&slbtrap, (void *)EXC_ISE,(size_t)&slbtrapend - (size_t)&slbtrap);
#endif
bcopy(generictrap, (void *)EXC_EXI, trapsize);
bcopy(generictrap, (void *)EXC_FPU, trapsize);
bcopy(generictrap, (void *)EXC_DECR, trapsize);
bcopy(generictrap, (void *)EXC_SC, trapsize);
bcopy(generictrap, (void *)EXC_FPA, trapsize);
bcopy(generictrap, (void *)EXC_VEC, trapsize);
bcopy(generictrap, (void *)EXC_PERF, trapsize);
bcopy(generictrap, (void *)EXC_VECAST_G4, trapsize);
bcopy(generictrap, (void *)EXC_VECAST_G5, trapsize);
#ifndef __powerpc64__
#else
/* G2-specific TLB miss helper handlers */
bcopy(&imisstrap, (void *)EXC_IMISS, (size_t)&imisssize);
bcopy(&dlmisstrap, (void *)EXC_DLMISS, (size_t)&dlmisssize);