Recover from spurious faults which don't set the ISV.

The decision of whether the access should have been successful is based
on the address of the fault.

Bug: 127686419
Change-Id: I7252d57c1f1bb7003ebb0f1d7a02918a68296855
diff --git a/src/arch/aarch64/handler.c b/src/arch/aarch64/handler.c
index 0f173ab..7aa3a3e 100644
--- a/src/arch/aarch64/handler.c
+++ b/src/arch/aarch64/handler.c
@@ -516,14 +516,12 @@
  * instruction and data aborts, but not necessarily for other exception reasons.
  */
 static struct vcpu_fault_info fault_info_init(uintreg_t esr,
-					      const struct vcpu *vcpu, int mode,
-					      uint8_t size)
+					      const struct vcpu *vcpu, int mode)
 {
 	uint32_t fsc = esr & 0x3f;
 	struct vcpu_fault_info r;
 
 	r.mode = mode;
-	r.size = size;
 	r.pc = va_init(vcpu->regs.pc);
 
 	/*
@@ -564,27 +562,15 @@
 		return api_wait_for_interrupt(vcpu);
 
 	case 0x24: /* EC = 100100, Data abort. */
-		/*
-		 * Determine the size based on the SAS bits, which are only
-		 * valid if the ISV bit is set. The WnR bit is used to decide
-		 * if it's a read or write.
-		 */
 		info = fault_info_init(
-			esr, vcpu, (esr & (1u << 6)) ? MM_MODE_W : MM_MODE_R,
-			(esr & (1u << 24)) ? (1u << ((esr >> 22) & 0x3)) : 0);
-
-		/* Call the platform-independent handler. */
+			esr, vcpu, (esr & (1u << 6)) ? MM_MODE_W : MM_MODE_R);
 		if (vcpu_handle_page_fault(vcpu, &info)) {
 			return NULL;
 		}
 		break;
 
 	case 0x20: /* EC = 100000, Instruction abort. */
-		/* Determine the size based on the IL bit. */
-		info = fault_info_init(esr, vcpu, MM_MODE_X,
-				       (esr & (1u << 25)) ? 4 : 2);
-
-		/* Call the platform-independent handler. */
+		info = fault_info_init(esr, vcpu, MM_MODE_X);
 		if (vcpu_handle_page_fault(vcpu, &info)) {
 			return NULL;
 		}
diff --git a/src/cpu.c b/src/cpu.c
index c44ef38..0d3e05c 100644
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -198,62 +198,34 @@
 			    struct vcpu_fault_info *f)
 {
 	struct vm *vm = current->vm;
-	ipaddr_t second_addr;
-	bool second;
 	int mode;
 	int mask = f->mode | MM_MODE_INVALID;
-	bool ret = false;
-
-	/* We can't recover if we don't know the size. */
-	if (f->size == 0) {
-		goto exit;
-	}
+	bool resume;
 
 	sl_lock(&vm->lock);
 
 	/*
 	 * Check if this is a legitimate fault, i.e., if the page table doesn't
 	 * allow the access attemped by the VM.
+	 *
+	 * Otherwise, this is a spurious fault, likely because another CPU is
+	 * updating the page table. It is responsible for issuing global TLB
+	 * invalidations while holding the VM lock, so we don't need to do
+	 * anything else to recover from it. (Acquiring/releasing the lock
+	 * ensured that the invalidations have completed.)
 	 */
-	if (!mm_vm_get_mode(&vm->ptable, f->ipaddr, ipa_add(f->ipaddr, 1),
-			    &mode) ||
-	    (mode & mask) != f->mode) {
-		goto exit_unlock;
-	}
+	resume = mm_vm_get_mode(&vm->ptable, f->ipaddr, ipa_add(f->ipaddr, 1),
+				&mode) &&
+		 (mode & mask) == f->mode;
 
-	/*
-	 * Do the same mode check on the second page, if the fault straddles two
-	 * pages.
-	 */
-	second_addr = ipa_add(f->ipaddr, f->size - 1);
-	second = (ipa_addr(f->ipaddr) >> PAGE_BITS) !=
-		 (ipa_addr(second_addr) >> PAGE_BITS);
-	if (second) {
-		if (!mm_vm_get_mode(&vm->ptable, second_addr,
-				    ipa_add(second_addr, 1), &mode) ||
-		    (mode & mask) != f->mode) {
-			goto exit_unlock;
-		}
-	}
-
-	/*
-	 * This is a spurious fault, likely because another CPU is updating the
-	 * page table. It is responsible for issuing global tlb invalidations
-	 * while holding the VM lock, so we don't need to do anything else to
-	 * recover from it. (Acquiring/releasing the lock ensured that the
-	 * invalidations have completed.)
-	 */
-
-	ret = true;
-
-exit_unlock:
 	sl_unlock(&vm->lock);
-exit:
-	if (!ret) {
+
+	if (!resume) {
 		dlog("Stage-2 page fault: pc=0x%x, vmid=%u, vcpu=%u, "
-		     "vaddr=0x%x, ipaddr=0x%x, mode=0x%x, size=%u\n",
+		     "vaddr=0x%x, ipaddr=0x%x, mode=0x%x\n",
 		     f->pc, vm->id, vcpu_index(current), f->vaddr, f->ipaddr,
-		     f->mode, f->size);
+		     f->mode);
 	}
-	return ret;
+
+	return resume;
 }