summaryrefslogtreecommitdiff
path: root/src/arch/arm64/include
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2014-09-17 01:16:20 -0500
committerPatrick Georgi <pgeorgi@google.com>2015-03-28 07:05:37 +0100
commitb241f57de543a5837ed12889dd1cc417de705967 (patch)
tree89be782ddb446166b9d84c4be256e6a011d2b9d1 /src/arch/arm64/include
parente702be692b438843c94a8dcd314f0891f2743224 (diff)
arm64: add smc layer to secmon
In order to process PSCI commands SMC instructions need to be serviced. Provide a simple way for users of SMC to register their handlers by function. The SMC layer hooks into the exception processing, however it only processes AARCH64 SMC calls. All others are ignored. BUG=chrome-os-partner:32112 BRANCH=None TEST=Added nop smc call to depthcharge. SMC handled and continue booting to kernel. Change-Id: I378f13c29220ff9f37040f094bf9cfb69259af0c Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: 76d2febc50397348b68d38532b8f37e2b3cf6a30 Original-Change-Id: Ieaa29fa883b9f9d55fc62ba92a1d45452296efa4 Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/218846 Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org> Original-Commit-Queue: Furquan Shaikh <furquan@chromium.org> Original-Tested-by: Furquan Shaikh <furquan@chromium.org> Reviewed-on: http://review.coreboot.org/9092 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/arch/arm64/include')
-rw-r--r--src/arch/arm64/include/arch/smc.h122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/arch/arm64/include/arch/smc.h b/src/arch/arm64/include/arch/smc.h
new file mode 100644
index 0000000000..288459e6ba
--- /dev/null
+++ b/src/arch/arm64/include/arch/smc.h
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#ifndef __ARCH_SMC_H__
+#define __ARCH_SMC_H__
+
+#include <stdint.h>
+
+enum {
+ FUNC_ID_CALL_TYPE_SHIFT = 31,
+ FUNC_ID_CALL_TYPE_MASK = (1 << FUNC_ID_CALL_TYPE_SHIFT),
+ FUNC_ID_FASTCALL = (1 << FUNC_ID_CALL_TYPE_SHIFT),
+ FUNC_ID_STDCALL = (0 << FUNC_ID_CALL_TYPE_SHIFT),
+
+ FUNC_ID_CALL_CONVENTION_SHIFT = 30,
+ FUNC_ID_CALL_CONVENTION_MASK = (1 << FUNC_ID_CALL_CONVENTION_SHIFT),
+ FUNC_ID_SMC32 = (0 << FUNC_ID_CALL_CONVENTION_SHIFT),
+ FUNC_ID_SMC64 = (1 << FUNC_ID_CALL_CONVENTION_SHIFT),
+
+ FUNC_ID_ENTITY_SHIFT = 24,
+ FUNC_ID_ENTITY_MASK = (0x3f << FUNC_ID_ENTITY_SHIFT),
+
+ FUNC_ID_FUNC_NUMBER_SHIFT = 0,
+ FUNC_ID_FUNC_NUMBER_MASK = (0xffff << FUNC_ID_FUNC_NUMBER_SHIFT),
+
+ FUNC_ID_MASK = FUNC_ID_CALL_TYPE_MASK | FUNC_ID_CALL_CONVENTION_MASK |
+ FUNC_ID_ENTITY_MASK | FUNC_ID_FUNC_NUMBER_MASK,
+
+ SMC_NUM_ARGS = 8, /* The last is optional hypervisor id. */
+ SMC_NUM_RESULTS = 4,
+
+ SMC_UNKNOWN_FUNC = 0xffffffff,
+};
+
+#define SMC_FUNC(entity, number, call_convention, call_type) \
+ ((call_type) | (call_convention) | \
+ ((entity) << FUNC_ID_ENTITY_SHIFT) | (number))
+
+#define SMC_FUNC_FAST(entity, number, call_convention) \
+ SMC_FUNC((entity), (number), (call_convention), FUNC_ID_FASTCALL)
+
+#define SMC_FUNC_FAST32(entity, number) \
+ SMC_FUNC_FAST((entity), (number), FUNC_ID_SMC32)
+
+#define SMC_FUNC_FAST64(entity, number) \
+ SMC_FUNC_FAST((entity), (number), FUNC_ID_SMC64)
+
+struct smc_call {
+ uint64_t args[SMC_NUM_ARGS];
+ uint64_t results[SMC_NUM_RESULTS];
+};
+
+/* SMC immediate value needs to be 0. */
+/* Check mod AARCHx mode against calling convention. */
+
+static inline uint64_t smc64_arg(const struct smc_call *smc, unsigned i)
+{
+ return smc->args[i];
+}
+
+static inline uint32_t smc32_arg(const struct smc_call *smc, unsigned i)
+{
+ return smc64_arg(smc, i);
+}
+
+static inline void smc64_result(struct smc_call *smc, unsigned i, uint64_t v)
+{
+ smc->results[i] = v;
+}
+
+static inline void smc32_result(struct smc_call *smc, unsigned i, uint32_t v)
+{
+ uint64_t v64 = v;
+ smc64_result(smc, i, v64);
+}
+
+static inline void smc32_return(struct smc_call *smc, int32_t v)
+{
+ smc32_result(smc, 0, v);
+}
+
+static inline uint32_t smc_hypervisor_id(const struct smc_call *smc)
+{
+ /* Set in W7 */
+ return smc32_arg(smc, 7);
+}
+
+static inline uint32_t smc_session_id(const struct smc_call *smc)
+{
+ /* Set in W6 */
+ return smc32_arg(smc, 6);
+}
+
+static inline uint32_t smc_function_id(const struct smc_call *smc)
+{
+ /* Function ID in W0. */
+ return smc32_arg(smc, 0) & FUNC_ID_MASK;
+}
+
+/* Initialize the SMC layer. */
+void smc_init(void);
+
+/* Register a handler for a given function range, inclusive. */
+int smc_register_range(uint32_t min, uint32_t max, int (*)(struct smc_call *));
+
+#endif /* __ARCH_SMC_H__ */