ppc64: handle exception 0x1500 (soft patch)
This change adds a hypervisor trap handler for exception 0x1500 (soft patch), normalizing all VSX registers and returning. This avoids a kernel panic due to unknown exception. Change made with the collaboration of leonardo.bianconi_eldorado.org.br, that found out that this is a hypervisor exception and not a supervisor one, and fixed this in the code. Reviewed by: jhibbits, sbruno Differential Revision: https://reviews.freebsd.org/D17806
This commit is contained in:
parent
13b1c7a3a5
commit
38e00d542b
@ -366,6 +366,7 @@ aim_cpu_init(vm_offset_t toc)
|
||||
bcopy(&hypertrapcode, (void *)(EXC_HEA + trap_offset), trapsize);
|
||||
bcopy(&hypertrapcode, (void *)(EXC_HMI + trap_offset), trapsize);
|
||||
bcopy(&hypertrapcode, (void *)(EXC_HVI + trap_offset), trapsize);
|
||||
bcopy(&hypertrapcode, (void *)(EXC_SOFT_PATCH + trap_offset), trapsize);
|
||||
#endif
|
||||
|
||||
bcopy(&rstcode, (void *)(EXC_RST + trap_offset), (size_t)&rstcodeend -
|
||||
|
@ -103,6 +103,9 @@
|
||||
#define EXC_SPFPD 0x2f30 /* SPE Floating-point Data */
|
||||
#define EXC_SPFPR 0x2f40 /* SPE Floating-point Round */
|
||||
|
||||
/* POWER8 */
|
||||
#define EXC_SOFT_PATCH 0x1500 /* POWER8 Soft Patch Exception */
|
||||
|
||||
#define EXC_LAST 0x2f00 /* Last possible exception vector */
|
||||
|
||||
#define EXC_AST 0x3000 /* Fake AST vector */
|
||||
|
@ -255,6 +255,7 @@ db_backtrace(struct thread *td, db_addr_t fp, int count)
|
||||
case EXC_DECR: trapstr = "DECR"; break;
|
||||
case EXC_PERF: trapstr = "PERF"; break;
|
||||
case EXC_VSX: trapstr = "VSX"; break;
|
||||
case EXC_SOFT_PATCH: trapstr = "SOFT_PATCH"; break;
|
||||
default: trapstr = NULL; break;
|
||||
}
|
||||
if (trapstr != NULL) {
|
||||
|
@ -95,6 +95,7 @@ static void syscall(struct trapframe *frame);
|
||||
void handle_kernel_slb_spill(int, register_t, register_t);
|
||||
static int handle_user_slb_spill(pmap_t pm, vm_offset_t addr);
|
||||
extern int n_slbs;
|
||||
static void normalize_inputs(void);
|
||||
#endif
|
||||
|
||||
extern vm_offset_t __startkernel;
|
||||
@ -147,6 +148,7 @@ static struct powerpc_exception powerpc_exceptions[] = {
|
||||
{ EXC_VECAST_G4, "altivec assist" },
|
||||
{ EXC_THRM, "thermal management" },
|
||||
{ EXC_RUNMODETRC, "run mode/trace" },
|
||||
{ EXC_SOFT_PATCH, "soft patch exception" },
|
||||
{ EXC_LAST, NULL }
|
||||
};
|
||||
|
||||
@ -382,6 +384,17 @@ trap(struct trapframe *frame)
|
||||
ucode = BUS_OBJERR;
|
||||
break;
|
||||
|
||||
#if defined(__powerpc64__) && defined(AIM)
|
||||
case EXC_SOFT_PATCH:
|
||||
/*
|
||||
* Point to the instruction that generated the exception to execute it again,
|
||||
* and normalize the register values.
|
||||
*/
|
||||
frame->srr0 -= 4;
|
||||
normalize_inputs();
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
trap_fatal(frame);
|
||||
}
|
||||
@ -909,6 +922,49 @@ fix_unaligned(struct thread *td, struct trapframe *frame)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#if defined(__powerpc64__) && defined(AIM)
|
||||
#define MSKNSHL(x, m, n) "(((" #x ") & " #m ") << " #n ")"
|
||||
#define MSKNSHR(x, m, n) "(((" #x ") & " #m ") >> " #n ")"
|
||||
|
||||
/* xvcpsgndp instruction, built in opcode format.
|
||||
* This can be changed to use mnemonic after a toolchain update.
|
||||
*/
|
||||
#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) ")")
|
||||
|
||||
/* Macros to normalize 1 or 10 VSX registers */
|
||||
#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)
|
||||
{
|
||||
unsigned long msr;
|
||||
|
||||
/* enable VSX */
|
||||
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);
|
||||
|
||||
/* restore MSR */
|
||||
mtmsr(msr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef KDB
|
||||
int
|
||||
db_trap_glue(struct trapframe *frame)
|
||||
|
Loading…
Reference in New Issue
Block a user