Module Name: src Committed By: jmcneill Date: Sat Aug 7 21:21:49 UTC 2021
Modified Files: src/sys/arch/arm/arm: smccc.c smccc.h Log Message: arm: SMCCC: Add return values to smccc_call To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/arm/smccc.c \ src/sys/arch/arm/arm/smccc.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/arm/smccc.c diff -u src/sys/arch/arm/arm/smccc.c:1.1 src/sys/arch/arm/arm/smccc.c:1.2 --- src/sys/arch/arm/arm/smccc.c:1.1 Fri Aug 6 19:38:53 2021 +++ src/sys/arch/arm/arm/smccc.c Sat Aug 7 21:21:49 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: smccc.c,v 1.1 2021/08/06 19:38:53 jmcneill Exp $ */ +/* $NetBSD: smccc.c,v 1.2 2021/08/07 21:21:49 jmcneill Exp $ */ /*- * Copyright (c) 2021 Jared McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: smccc.c,v 1.1 2021/08/06 19:38:53 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: smccc.c,v 1.2 2021/08/07 21:21:49 jmcneill Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -42,7 +42,10 @@ __KERNEL_RCSID(0, "$NetBSD: smccc.c,v 1. #define SMCCC_VERSION 0x80000000 /* True if SMCCC is detected. */ -static bool smccc_present; +static bool smccc_present; + +/* SMCCC conduit (SMC or HVC) */ +static enum psci_conduit smccc_conduit = PSCI_CONDUIT_NONE; /* * smccc_probe -- @@ -58,6 +61,13 @@ smccc_probe(void) } smccc_present = psci_features(SMCCC_VERSION) == PSCI_SUCCESS; + if (smccc_present) { + smccc_conduit = psci_conduit(); + + aprint_debug("SMCCC: Version %#x (%s)\n", + smccc_version(), + smccc_conduit == PSCI_CONDUIT_SMC ? "SMC" : "HVC"); + } } return smccc_present; } @@ -70,7 +80,8 @@ smccc_probe(void) int smccc_version(void) { - return smccc_call(SMCCC_VERSION, 0, 0, 0); + return smccc_call(SMCCC_VERSION, 0, 0, 0, 0, + NULL, NULL, NULL, NULL); } /* @@ -79,11 +90,54 @@ smccc_version(void) * Generic call interface for SMC/HVC calls. */ int -smccc_call(register_t fid, register_t arg1, register_t arg2, register_t arg3) +smccc_call(uint32_t fid, + register_t arg1, register_t arg2, register_t arg3, register_t arg4, + register_t *res0, register_t *res1, register_t *res2, register_t *res3) { + register_t args[5] = { fid, arg1, arg2, arg3, arg4 }; + + register register_t r0 asm ("r0"); + register register_t r1 asm ("r1"); + register register_t r2 asm ("r2"); + register register_t r3 asm ("r3"); + register register_t r4 asm ("r4"); + if (!smccc_present) { return SMCCC_NOT_SUPPORTED; } - return psci_call(fid, arg1, arg2, arg3); + KASSERT(smccc_conduit != PSCI_CONDUIT_NONE); + + r0 = args[0]; + r1 = args[1]; + r2 = args[2]; + r3 = args[3]; + r4 = args[4]; + + if (smccc_conduit == PSCI_CONDUIT_SMC) { + asm volatile ("smc #0" : + "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3) : + "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4) : + "memory"); + } else { + asm volatile ("hvc #0" : + "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3) : + "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4) : + "memory"); + } + + if (res0) { + *res0 = r0; + } + if (res1) { + *res1 = r1; + } + if (res2) { + *res2 = r2; + } + if (res3) { + *res3 = r3; + } + + return r0; } Index: src/sys/arch/arm/arm/smccc.h diff -u src/sys/arch/arm/arm/smccc.h:1.1 src/sys/arch/arm/arm/smccc.h:1.2 --- src/sys/arch/arm/arm/smccc.h:1.1 Fri Aug 6 19:38:53 2021 +++ src/sys/arch/arm/arm/smccc.h Sat Aug 7 21:21:49 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: smccc.h,v 1.1 2021/08/06 19:38:53 jmcneill Exp $ */ +/* $NetBSD: smccc.h,v 1.2 2021/08/07 21:21:49 jmcneill Exp $ */ /*- * Copyright (c) 2021 Jared McNeill <jmcne...@invisible.ca> @@ -50,6 +50,7 @@ int smccc_version(void); /* * Call an SMC/HVC service. */ -int smccc_call(register_t, register_t, register_t, register_t); +int smccc_call(uint32_t, register_t, register_t, register_t, register_t, + register_t *, register_t *, register_t *, register_t *); #endif /* _ARM_SMCCC_H */