VHE: Add EL0 exception handling
Added code to handle SVC's from EL0 partitions. Also added code to abort
on EL0 partition on unexpected errors.
Change-Id: I262b00592819f63ed075759790d59d414ea47a1c
Signed-off-by: Raghu Krishnamurthy <raghu.ncstate@gmail.com>
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 880d07f..9bcce55 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -1064,13 +1064,27 @@
{
struct vcpu *vcpu = current();
struct vcpu_fault_info info;
- struct vcpu *new_vcpu;
+ struct vcpu *new_vcpu = NULL;
uintreg_t ec = GET_ESR_EC(esr);
+ bool is_el0_partition = vcpu->vm->el0_partition;
switch (ec) {
case EC_WFI_WFE:
/* Skip the instruction. */
vcpu->regs.pc += GET_NEXT_PC_INC(esr);
+
+ /*
+ * For EL0 partitions, treat both WFI and WFE the same way so
+ * that FFA_RUN can be called on the partition to resume it. If
+ * we treat WFI using api_wait_for_interrupt, the VCPU will be
+ * in blocked waiting for interrupt but we cannot inject
+ * interrupts into EL0 partitions.
+ */
+ if (is_el0_partition) {
+ api_yield(vcpu, &new_vcpu);
+ return new_vcpu;
+ }
+
/* Check TI bit of ISS, 0 = WFI, 1 = WFE. */
if (esr & 1) {
/* WFE */
@@ -1090,6 +1104,12 @@
if (vcpu_handle_page_fault(vcpu, &info)) {
return NULL;
}
+
+ if (is_el0_partition) {
+ dlog_warning("Data abort on EL0 partition\n");
+ return api_abort(vcpu);
+ }
+
/* Inform the EL1 of the data abort. */
inject_el1_data_abort_exception(vcpu, esr, far);
@@ -1101,13 +1121,25 @@
if (vcpu_handle_page_fault(vcpu, &info)) {
return NULL;
}
+
+ if (is_el0_partition) {
+ dlog_warning("Instruction abort on EL0 partition\n");
+ return api_abort(vcpu);
+ }
+
/* Inform the EL1 of the instruction abort. */
inject_el1_instruction_abort_exception(vcpu, esr, far);
/* Schedule the same VM to continue running. */
return NULL;
-
+ case EC_SVC:
+ CHECK(is_el0_partition);
+ return hvc_handler(vcpu);
case EC_HVC:
+ if (is_el0_partition) {
+ dlog_warning("Unexpected HVC Trap on EL0 partition\n");
+ return api_abort(vcpu);
+ }
return hvc_handler(vcpu);
case EC_SMC: {
@@ -1135,6 +1167,10 @@
break;
}
+ if (is_el0_partition) {
+ return api_abort(vcpu);
+ }
+
/*
* The exception wasn't handled. Inject to the VM to give it chance to
* handle as an unknown exception.