aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAlex Elder <elder@linaro.org>2014-04-21 17:53:09 -0400
committerMatt Porter <mporter@linaro.org>2014-04-25 08:51:36 -0400
commit8b9c550e37ff4e4d0de2890a835f44a7813e3423 (patch)
tree07e846ee9fb1c09b820e67825558d6e107440044 /arch
parentd5c627b5751ed44c0eff6c12e658097edf6338de (diff)
ARM: bcm: use inline assembly for "smc" request
Move the code that implements the "smc" call into a C function that uses inline assembly. This allows us to make that function private, and enables us to get rid of "arch/arm/mach-bcm/bcm_kona_smc_asm.S". Rename what had been the "buffer_addr" argument to be "buffer_phys" so it's consistent with other usage in this file. Since it's now easy to do, verify that r12 contains SEC_EXIT_NORMAL upon completion of the SMC. There really isn't a good way to handle the abnormal completion of a secure monitor request. Since "bcm_kona_smc.h" is now only included from C files, eliminate the #ifndef __ASSEMBLY__. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Tim Kryger <tim.kryger@linaro.org> Reviewed-by: Markus Mayer <markus.mayer@linaro.org> Reviewed-by: Matt Porter <mporter@linaro.org> Signed-off-by: Matt Porter <mporter@linaro.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-bcm/Makefile7
-rw-r--r--arch/arm/mach-bcm/bcm_kona_smc.c46
-rw-r--r--arch/arm/mach-bcm/bcm_kona_smc.h6
-rw-r--r--arch/arm/mach-bcm/bcm_kona_smc_asm.S41
4 files changed, 49 insertions, 51 deletions
diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile
index 51549814f7cd..d5b60feda8ad 100644
--- a/arch/arm/mach-bcm/Makefile
+++ b/arch/arm/mach-bcm/Makefile
@@ -20,9 +20,10 @@ obj-$(CONFIG_ARCH_BCM_21664) += board_bcm21664.o
20obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona.o 20obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona.o
21 21
22# Support for secure monitor traps 22# Support for secure monitor traps
23obj-$(CONFIG_ARCH_BCM_MOBILE_SMC) += bcm_kona_smc.o bcm_kona_smc_asm.o 23obj-$(CONFIG_ARCH_BCM_MOBILE_SMC) += bcm_kona_smc.o
24plus_sec := $(call as-instr,.arch_extension sec,+sec) 24ifeq ($(call as-instr,.arch_extension sec,as_has_sec),as_has_sec)
25AFLAGS_bcm_kona_smc_asm.o :=-Wa,-march=armv7-a$(plus_sec) 25CFLAGS_bcm_kona_smc.o += -Wa,-march=armv7-a+sec -DREQUIRES_SEC
26endif
26 27
27# BCM2835 28# BCM2835
28obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o 29obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o
diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c
index 6fdcf96ca54e..cc81c86f24b5 100644
--- a/arch/arm/mach-bcm/bcm_kona_smc.c
+++ b/arch/arm/mach-bcm/bcm_kona_smc.c
@@ -76,6 +76,50 @@ int __init bcm_kona_smc_init(void)
76 return 0; 76 return 0;
77} 77}
78 78
79/*
80 * Since interrupts are disabled in the open mode, we must keep
81 * interrupts disabled in secure mode by setting R5=0x3. If interrupts
82 * are enabled in open mode, we can set R5=0x0 to allow interrupts in
83 * secure mode. If we did this, the secure monitor would return back
84 * control to the open mode to handle the interrupt prior to completing
85 * the secure service. If this happened, R12 would not be
86 * SEC_EXIT_NORMAL and we would need to call SMC again after resetting
87 * R5 (it gets clobbered by the secure monitor) and setting R4 to
88 * SSAPI_RET_FROM_INT_SERV to indicate that we want the secure monitor
89 * to finish up the previous uncompleted secure service.
90 */
91static int bcm_kona_do_smc(u32 service_id, u32 buffer_phys)
92{
93 register u32 ip asm("ip"); /* Also called r12 */
94 register u32 r0 asm("r0");
95 register u32 r4 asm("r4");
96 register u32 r5 asm("r5");
97 register u32 r6 asm("r6");
98
99 r4 = service_id;
100 r5 = 0x3; /* Keep IRQ and FIQ off in SM */
101 r6 = buffer_phys;
102
103 asm volatile (
104 /* Make sure we got the registers we want */
105 __asmeq("%0", "ip")
106 __asmeq("%1", "r0")
107 __asmeq("%2", "r4")
108 __asmeq("%3", "r5")
109 __asmeq("%4", "r6")
110#ifdef REQUIRES_SEC
111 ".arch_extension sec\n"
112#endif
113 " smc #0\n"
114 : "=r" (ip), "=r" (r0)
115 : "r" (r4), "r" (r5), "r" (r6)
116 : "r1", "r2", "r3", "r7", "lr");
117
118 BUG_ON(ip != SEC_EXIT_NORMAL);
119
120 return r0;
121}
122
79/* __bcm_kona_smc() should only run on CPU 0, with pre-emption disabled */ 123/* __bcm_kona_smc() should only run on CPU 0, with pre-emption disabled */
80static void __bcm_kona_smc(void *info) 124static void __bcm_kona_smc(void *info)
81{ 125{
@@ -95,7 +139,7 @@ static void __bcm_kona_smc(void *info)
95 flush_cache_all(); 139 flush_cache_all();
96 140
97 /* Trap into Secure Monitor and record the request result */ 141 /* Trap into Secure Monitor and record the request result */
98 data->result = bcm_kona_smc_asm(data->service_id, bcm_smc_buffer_phys); 142 data->result = bcm_kona_do_smc(data->service_id, bcm_smc_buffer_phys);
99} 143}
100 144
101unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1, 145unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1,
diff --git a/arch/arm/mach-bcm/bcm_kona_smc.h b/arch/arm/mach-bcm/bcm_kona_smc.h
index 629e64a89982..2e29ec67e414 100644
--- a/arch/arm/mach-bcm/bcm_kona_smc.h
+++ b/arch/arm/mach-bcm/bcm_kona_smc.h
@@ -21,7 +21,6 @@
21#define SEC_ROM_RET_OK 0x00000001 21#define SEC_ROM_RET_OK 0x00000001
22#define SEC_EXIT_NORMAL 0x1 22#define SEC_EXIT_NORMAL 0x1
23 23
24#ifndef __ASSEMBLY__
25extern int __init bcm_kona_smc_init(void); 24extern int __init bcm_kona_smc_init(void);
26 25
27extern unsigned bcm_kona_smc(unsigned service_id, 26extern unsigned bcm_kona_smc(unsigned service_id,
@@ -30,9 +29,4 @@ extern unsigned bcm_kona_smc(unsigned service_id,
30 unsigned arg2, 29 unsigned arg2,
31 unsigned arg3); 30 unsigned arg3);
32 31
33extern int bcm_kona_smc_asm(u32 service_id,
34 u32 buffer_addr);
35
36#endif /* __ASSEMBLY__ */
37
38#endif /* BCM_KONA_SMC_H */ 32#endif /* BCM_KONA_SMC_H */
diff --git a/arch/arm/mach-bcm/bcm_kona_smc_asm.S b/arch/arm/mach-bcm/bcm_kona_smc_asm.S
deleted file mode 100644
index a1608480d60d..000000000000
--- a/arch/arm/mach-bcm/bcm_kona_smc_asm.S
+++ /dev/null
@@ -1,41 +0,0 @@
1/*
2 * Copyright (C) 2013 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
7 *
8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9 * kind, whether express or implied; without even the implied warranty
10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/linkage.h>
15#include "bcm_kona_smc.h"
16
17/*
18 * int bcm_kona_smc_asm(u32 service_id, u32 buffer_addr)
19 */
20
21ENTRY(bcm_kona_smc_asm)
22 stmfd sp!, {r4-r12, lr}
23 mov r4, r0 @ service_id
24 mov r5, #3 @ Keep IRQ and FIQ off in SM
25 /*
26 * Since interrupts are disabled in the open mode, we must keep
27 * interrupts disabled in secure mode by setting R5=0x3. If interrupts
28 * are enabled in open mode, we can set R5=0x0 to allow interrupts in
29 * secure mode. If we did this, the secure monitor would return back
30 * control to the open mode to handle the interrupt prior to completing
31 * the secure service. If this happened, R12 would not be
32 * SEC_EXIT_NORMAL and we would need to call SMC again after resetting
33 * R5 (it gets clobbered by the secure monitor) and setting R4 to
34 * SSAPI_RET_FROM_INT_SERV to indicate that we want the secure monitor
35 * to finish up the previous uncompleted secure service.
36 */
37 mov r6, r1 @ buffer_addr
38 smc #0
39 /* Check r12 for SEC_EXIT_NORMAL here if interrupts are enabled */
40 ldmfd sp!, {r4-r12, pc}
41ENDPROC(bcm_kona_smc_asm)