#endif
}
-#if 0
/* Inject a virtual Abort/SError into the guest. */
static void inject_vabt_exception(struct cpu_user_regs *regs)
{
current->arch.hcr_el2 |= HCR_VA;
WRITE_SYSREG(current->arch.hcr_el2, HCR_EL2);
}
-#endif
+
+/*
+ * SError exception handler. We only handle the following 3 types of SErrors:
+ * 1) Guest-generated SError and had been delivered in EL1 and then
+ * been forwarded to EL2.
+ * 2) Guest-generated SError but hadn't been delivered in EL1 before
+ * trapping to EL2. This SError would be caught in EL2 as soon as
+ * we just unmasked the PSTATE.A bit.
+ * 3) Hypervisor generated native SError, that would be a bug.
+ *
+ * A true parameter "guest" means that the SError is type#1 or type#2.
+ */
+static void __do_trap_serror(struct cpu_user_regs *regs, bool guest)
+{
+ /*
+ * Only "DIVERSE" option needs to distinguish the guest-generated SErrors
+ * from hypervisor SErrors.
+ */
+ if ( serrors_op == SERRORS_DIVERSE )
+ {
+ /* Forward the type#1 and type#2 SErrors to guests. */
+ if ( guest )
+ return inject_vabt_exception(regs);
+
+ /* Type#3 SErrors will panic the whole system */
+ goto crash_system;
+ }
+
+ /*
+ * The "FORWARD" option will forward all SErrors to the guests, except
+ * idle domain generated SErrors.
+ */
+ if ( serrors_op == SERRORS_FORWARD )
+ {
+ /*
+ * Because the idle domain doesn't have the ability to handle the
+ * SErrors, we have to crash the whole system while we get a SError
+ * generated by idle domain.
+ */
+ if ( is_idle_vcpu(current) )
+ goto crash_system;
+
+ return inject_vabt_exception(regs);
+ }
+
+crash_system:
+ /* Three possibilities to crash the whole system:
+ * 1) "DIVERSE" option with Hypervisor generated SErrors.
+ * 2) "FORWARD" option with Idle Domain generated SErrors.
+ * 3) "PANIC" option with all SErrors.
+ */
+ do_unexpected_trap("SError", regs);
+}
struct reg_ctxt {
/* Guest-side state */
domain_crash_synchronous();
}
+asmlinkage void do_trap_hyp_serror(struct cpu_user_regs *regs)
+{
+ enter_hypervisor_head(regs);
+
+ __do_trap_serror(regs, VABORT_GEN_BY_GUEST(regs));
+}
+
+asmlinkage void do_trap_guest_serror(struct cpu_user_regs *regs)
+{
+ enter_hypervisor_head(regs);
+
+ __do_trap_serror(regs, true);
+}
+
asmlinkage void do_trap_irq(struct cpu_user_regs *regs)
{
enter_hypervisor_head(regs);