Commit 35ef4b70 authored by Richard Henderson's avatar Richard Henderson

[ALPHA] Streamline opDEC_check and the actual fixup bits in do_entIF.

parent afbd3007
......@@ -15,6 +15,7 @@
#include <linux/delay.h>
#include <linux/smp_lock.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/gentrap.h>
#include <asm/uaccess.h>
......@@ -25,35 +26,37 @@
#include "proto.h"
/* data/code implementing a work-around for some SRMs which
mishandle opDEC faults
*/
static int opDEC_testing = 0;
static int opDEC_fix = 0;
static int opDEC_checked = 0;
static unsigned long opDEC_test_pc = 0;
/* Work-around for some SRMs which mishandle opDEC faults. */
static void
static int opDEC_fix;
static void __init
opDEC_check(void)
{
unsigned long test_pc;
if (opDEC_checked) return;
lock_kernel();
opDEC_testing = 1;
__asm__ __volatile__(
" br %0,1f\n"
"1: addq %0,8,%0\n"
" stq %0,%1\n"
__asm__ __volatile__ (
/* Load the address of... */
" br $16, 1f\n"
/* A stub instruction fault handler. Just add 4 to the
pc and continue. */
" ldq $16, 8($sp)\n"
" addq $16, 4, $16\n"
" stq $16, 8($sp)\n"
" call_pal %[rti]\n"
/* Install the instruction fault handler. */
"1: lda $17, 3\n"
" call_pal %[wrent]\n"
/* With that in place, the fault from the round-to-minf fp
insn will arrive either at the "lda 4" insn (bad) or one
past that (good). This places the correct fixup in %0. */
" lda %[fix], 0\n"
" cvttq/svm $f31,$f31\n"
: "=&r"(test_pc), "=m"(opDEC_test_pc)
: );
" lda %[fix], 4"
: [fix] "=r" (opDEC_fix)
: [rti] "n" (PAL_rti), [wrent] "n" (PAL_wrent)
: "$0", "$1", "$16", "$17", "$22", "$23", "$24", "$25");
opDEC_testing = 0;
opDEC_checked = 1;
unlock_kernel();
if (opDEC_fix)
printk("opDEC fixup enabled.\n");
}
void
......@@ -244,7 +247,7 @@ do_entIF(unsigned long type, struct pt_regs *regs)
siginfo_t info;
int signo, code;
if (!opDEC_testing || type != 4) {
if (regs->ps == 0) {
if (type == 1) {
const unsigned int *data
= (const unsigned int *) regs->pc;
......@@ -359,14 +362,6 @@ do_entIF(unsigned long type, struct pt_regs *regs)
fault during the boot sequence and testing if
we get the correct PC. If not, we set a flag
to correct it every time through. */
if (opDEC_testing) {
if (regs->pc == opDEC_test_pc) {
opDEC_fix = 4;
regs->pc += 4;
printk("opDEC fixup enabled.\n");
}
return;
}
regs->pc += opDEC_fix;
/* EV4 does not implement anything except normal
......@@ -1083,22 +1078,22 @@ do_entUnaUser(void * va, unsigned long opcode,
return;
}
void
void __init
trap_init(void)
{
/* Tell PAL-code what global pointer we want in the kernel. */
register unsigned long gptr __asm__("$29");
wrkgp(gptr);
/* Hack for Multia (UDB) and JENSEN: some of their SRMs have
a bug in the handling of the opDEC fault. Fix it up if so. */
if (implver() == IMPLVER_EV4)
opDEC_check();
wrent(entArith, 1);
wrent(entMM, 2);
wrent(entIF, 3);
wrent(entUna, 4);
wrent(entSys, 5);
wrent(entDbg, 6);
/* Hack for Multia (UDB) and JENSEN: some of their SRMs have
a bug in the handling of the opDEC fault. Fix it up if so. */
if (implver() == IMPLVER_EV4)
opDEC_check();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment