summaryrefslogtreecommitdiffstats
path: root/src/kernel
diff options
context:
space:
mode:
authorAdam Muhle <armuhle@us.ibm.com>2013-02-26 08:14:03 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2013-05-08 09:25:51 -0500
commit2deb848cf616c4c815a37988fe2c8c422b885e3e (patch)
tree3058f40318b2094fb5a84453df8edb946f230fa3 /src/kernel
parent8e8dbe99d13d923536353afd96b9b003382b7f2c (diff)
downloadtalos-hostboot-2deb848cf616c4c815a37988fe2c8c422b885e3e.tar.gz
talos-hostboot-2deb848cf616c4c815a37988fe2c8c422b885e3e.zip
IBSCOM error path support
This commit updates IBSCOM to have error path support. It also updates the good-path test cases since there is limited good path support in simics. Full enablement will be done later. Change-Id: I5f9d66165db119473f606303a1026c8c71988785 RTC: 34743 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/3972 Tested-by: Jenkins Server Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Reviewed-by: Douglas R. Gilbert <dgilbert@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/exception.C92
1 files changed, 90 insertions, 2 deletions
diff --git a/src/kernel/exception.C b/src/kernel/exception.C
index c82bfec98..ba2d803b5 100644
--- a/src/kernel/exception.C
+++ b/src/kernel/exception.C
@@ -233,16 +233,104 @@ 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;
+
extern "C"
void kernel_execute_machine_check()
{
task_t* t = TaskManager::getCurrentTask();
- printk("Machine check in %d on %ld:\n"
+
+ //PR (bit 49) = 0 indicates hypervisor mode
+ // Which indicates kernel mode in Hostboot env.
+ if(!(getSRR1() & EXCEPTION_MSR_PR_BIT_MASK))
+ {
+ //Not much we can do to recover in Kernel, just assert
+ printk("Kernel 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());
+ 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());
- kassert(false);
+
+
+ //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;
+
+ uint64_t vaddr = 0;
+ if(rA != 0)
+ {
+ vaddr = t->context.gprs[rA] +
+ t->context.gprs[rB];
+ }
+ 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
+ {
+ printk("kernel_execute_machine_check: Unrecognized memory address(%lx) - ending Task\n",
+ phys);
+ TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED);
+ }
}
extern "C"
OpenPOWER on IntegriCloud