Implement SMCCC 1.2 for calling, returning 8 registers.

Bug: 141469322
Change-Id: I0b69d03591fa09739492c751bd95fbd28a9118e1
diff --git a/driver/linux b/driver/linux
index d426b6c..a989330 160000
--- a/driver/linux
+++ b/driver/linux
@@ -1 +1 @@
-Subproject commit d426b6cb6d2bdde5b7d6c140141f739378d2ca95
+Subproject commit a9893306ccd532c8ac0f568b60cc55489f493b2c
diff --git a/src/arch/aarch64/hftest/hf_call.c b/src/arch/aarch64/hftest/hf_call.c
index c31aab9..ee591f1 100644
--- a/src/arch/aarch64/hftest/hf_call.c
+++ b/src/arch/aarch64/hftest/hf_call.c
@@ -27,7 +27,10 @@
 	__asm__ volatile(
 		"hvc #0"
 		: /* Output registers, also used as inputs ('+' constraint). */
-		"+r"(r0), "+r"(r1), "+r"(r2), "+r"(r3));
+		"+r"(r0), "+r"(r1), "+r"(r2), "+r"(r3)
+		:
+		: /* Clobber registers. */
+		"x4", "x5", "x6", "x7");
 
 	return r0;
 }
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 2406768..39bf58c 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -51,6 +51,11 @@
 #define GET_NEXT_PC_INC(esr) (((esr) & (1u << 25)) ? 4 : 2)
 
 /**
+ * The Client ID field within X7 for an SMC64 call.
+ */
+#define CLIENT_ID_MASK UINT64_C(0xffff)
+
+/**
  * Returns a reference to the currently executing vCPU.
  */
 static struct vcpu *current(void)
@@ -272,11 +277,25 @@
 	uint32_t func = vcpu->regs.r[0];
 	/* TODO(b/132421503): obtain vmid according to new scheme. */
 	uint32_t client_id = vcpu->vm->id;
+	/*
+	 * Set the Client ID but keep the existing Secure OS ID and anything
+	 * else (currently unspecified) that the client may have passed in the
+	 * upper bits.
+	 */
+	uintreg_t arg7 = client_id | (vcpu->regs.r[7] & ~CLIENT_ID_MASK);
 
 	if (smc_check_client_privileges(vcpu)) {
 		*ret = smc_forward(func, vcpu->regs.r[1], vcpu->regs.r[2],
 				   vcpu->regs.r[3], vcpu->regs.r[4],
-				   vcpu->regs.r[5], vcpu->regs.r[6], client_id);
+				   vcpu->regs.r[5], vcpu->regs.r[6], arg7);
+		/*
+		 * Preserve the value passed by the caller, rather than the
+		 * client_id we generated. Note that this would also overwrite
+		 * any return value that may be in x7, but the SMCs that we are
+		 * forwarding are legacy calls from before SMCCC 1.2 so won't
+		 * have more than 4 return values anyway.
+		 */
+		ret->res7 = vcpu->regs.r[7];
 		return true;
 	}
 
@@ -284,10 +303,16 @@
 }
 
 static bool spci_handler(uintreg_t func, uintreg_t arg1, uintreg_t arg2,
-			 uintreg_t arg3, uintreg_t *ret, struct vcpu **next)
+			 uintreg_t arg3, uintreg_t arg4, uintreg_t arg5,
+			 uintreg_t arg6, uintreg_t arg7, uintreg_t *ret,
+			 struct vcpu **next)
 {
 	(void)arg2;
 	(void)arg3;
+	(void)arg4;
+	(void)arg5;
+	(void)arg6;
+	(void)arg7;
 
 	switch (func & ~SMCCC_CONVENTION_MASK) {
 	case SPCI_VERSION_32:
@@ -368,6 +393,10 @@
 	uintreg_t arg1 = vcpu->regs.r[1];
 	uintreg_t arg2 = vcpu->regs.r[2];
 	uintreg_t arg3 = vcpu->regs.r[3];
+	uintreg_t arg4 = vcpu->regs.r[4];
+	uintreg_t arg5 = vcpu->regs.r[5];
+	uintreg_t arg6 = vcpu->regs.r[6];
+	uintreg_t arg7 = vcpu->regs.r[7];
 	struct vcpu *next = NULL;
 
 	if (psci_handler(vcpu, func, arg1, arg2, arg3, &vcpu->regs.r[0],
@@ -375,7 +404,8 @@
 		return next;
 	}
 
-	if (spci_handler(func, arg1, arg2, arg3, &vcpu->regs.r[0], &next)) {
+	if (spci_handler(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
+			 &vcpu->regs.r[0], &next)) {
 		update_vi(next);
 		return next;
 	}
diff --git a/src/arch/aarch64/smc.c b/src/arch/aarch64/smc.c
index 2b4bb09..34a8847 100644
--- a/src/arch/aarch64/smc.c
+++ b/src/arch/aarch64/smc.c
@@ -37,7 +37,14 @@
 		"+r"(r0), "+r"(r1), "+r"(r2), "+r"(r3), "+r"(r4), "+r"(r5),
 		"+r"(r6), "+r"(r7));
 
-	return (smc_res_t){.res0 = r0, .res1 = r1, .res2 = r2, .res3 = r3};
+	return (smc_res_t){.res0 = r0,
+			   .res1 = r1,
+			   .res2 = r2,
+			   .res3 = r3,
+			   .res4 = r4,
+			   .res5 = r5,
+			   .res6 = r6,
+			   .res7 = r7};
 }
 
 smc_res_t smc32(uint32_t func, uint32_t arg0, uint32_t arg1, uint32_t arg2,
diff --git a/src/arch/aarch64/smc.h b/src/arch/aarch64/smc.h
index 93847fa..5e04f26 100644
--- a/src/arch/aarch64/smc.h
+++ b/src/arch/aarch64/smc.h
@@ -52,6 +52,10 @@
 	uint64_t res1;
 	uint64_t res2;
 	uint64_t res3;
+	uint64_t res4;
+	uint64_t res5;
+	uint64_t res6;
+	uint64_t res7;
 } smc_res_t;
 
 smc_res_t smc32(uint32_t func, uint32_t arg0, uint32_t arg1, uint32_t arg2,