summaryrefslogtreecommitdiffstats
path: root/src/kernel/exception.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/exception.C')
-rw-r--r--src/kernel/exception.C82
1 files changed, 15 insertions, 67 deletions
diff --git a/src/kernel/exception.C b/src/kernel/exception.C
index ba2d803b5..47d8a3c01 100644
--- a/src/kernel/exception.C
+++ b/src/kernel/exception.C
@@ -31,6 +31,7 @@
#include <kernel/intmsghandler.H>
#include <errno.h>
#include <kernel/vmmmgr.H>
+#include <kernel/machchk.H>
namespace ExceptionHandles
{
@@ -235,12 +236,7 @@ void kernel_execute_softpatch()
const uint64_t EXCEPTION_MSR_PR_BIT_MASK = 0x0000000000004000;
const uint64_t EXCEPTION_SRR1_LOADSTORE_ERR = 0x0000000000200000;
-const uint64_t EXCEPTION_DSISR_LDX_UE_INTERRUPT = 0x0000000000008000;
-const uint32_t EXCEPTION_LDX_INSTR_MASK = 0xFC0007FE;
-const uint32_t EXCEPTION_LDX_INSTR = 0x7C00002A;
-const uint32_t EXCEPTION_RA_MASK = 0x001F0000;
-const uint32_t EXCEPTION_RB_MASK = 0x0000F800;
-const uint32_t EXCEPTION_RT_MASK = 0x03E00000;
+const uint64_t EXCEPTION_DSISR_LD_UE_INTERRUPT = 0x0000000000008000;
extern "C"
void kernel_execute_machine_check()
@@ -260,75 +256,27 @@ void kernel_execute_machine_check()
kassert(false);
}
- //User Space MC
- printk("User Space Machine check in %d on %ld:\n"
- "\tSRR0 = %lx, SRR1 = %lx\n"
- "\tDSISR = %lx, DAR = %lx\n",
- t->tid, getPIR(),
- getSRR0(), getSRR1(), getDSISR(), getDAR());
-
-
- //Determine if this Machine Check was triggered by a SUE on
- //CI (Cache Inhibited) Load.
- if(!((getSRR1() & EXCEPTION_SRR1_LOADSTORE_ERR) &&
- (getDSISR() & EXCEPTION_DSISR_LDX_UE_INTERRUPT)))
- {
- //SUE not caused by CI Load, unhandled exception.
- TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED);
- }
-
- //Get instruction that caused the SUE
- uint64_t phys_addr = VmmManager::findKernelAddress(
- reinterpret_cast<uint64_t>(t->context.nip));
-
- sync();
- uint32_t* instruction = reinterpret_cast<uint32_t*>(phys_addr);
-
- if(!((*instruction & EXCEPTION_LDX_INSTR_MASK) ==
- EXCEPTION_LDX_INSTR))
- {
- //Not an LDX instruction, unhandled exception
- printk("kernel_execute_machine_check: Instruction 0x%.8x not an LDX instruction. Ending task\n", *instruction);
- TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED);
-
- }
-
- //Compute the accessed address
- uint32_t rA = (*instruction & EXCEPTION_RA_MASK) >> 16;
- uint32_t rB = (*instruction & EXCEPTION_RB_MASK) >> 11;
+ bool handled = false;
- uint64_t vaddr = 0;
- if(rA != 0)
+ // SUE on load instruction.
+ if ((getSRR1() & EXCEPTION_SRR1_LOADSTORE_ERR) &&
+ (getDSISR() & EXCEPTION_DSISR_LD_UE_INTERRUPT))
{
- vaddr = t->context.gprs[rA] +
- t->context.gprs[rB];
+ handled = Kernel::MachineCheck::handleLoadUE(t);
}
else
{
- vaddr = t->context.gprs[rB];
- }
- uint64_t phys = VmmManager::findPhysicalAddress(vaddr);
-
- //Check if address is in IBSCOM MMIO Range.
- if( (phys >= MMIO_IBSCOM_START) &&
- (phys <= MMIO_IBSCOM_END) )
- {
- //Read occured during IBSCOM read. Indicate error to caller
- //by setting known pattern (ascii SCOMFAIL) in rT
- uint32_t rT = (*instruction & EXCEPTION_RT_MASK) >> 21;
-
- //set rT = MMIO_IBSCOM_UE_DETECTED
- t->context.gprs[rT] = MMIO_IBSCOM_UE_DETECTED;
- //Advance to next instruction
- uint32_t* nextInst = reinterpret_cast<uint32_t*>(t->context.nip);
- nextInst++;
- t->context.nip = reinterpret_cast<void*>(nextInst);
}
- else
+
+ if (!handled)
{
- printk("kernel_execute_machine_check: Unrecognized memory address(%lx) - ending Task\n",
- phys);
+ //User Space MC
+ printk("User Space Machine check in %d on %ld:\n"
+ "\tSRR0 = %lx, SRR1 = %lx\n"
+ "\tDSISR = %lx, DAR = %lx\n",
+ t->tid, getPIR(),
+ getSRR0(), getSRR1(), getDSISR(), getDAR());
TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED);
}
}
OpenPOWER on IntegriCloud