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,