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>
This commit is contained in:
parent
d5c627b575
commit
8b9c550e37
@ -20,9 +20,10 @@ obj-$(CONFIG_ARCH_BCM_21664) += board_bcm21664.o
|
|||||||
obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona.o
|
obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona.o
|
||||||
|
|
||||||
# Support for secure monitor traps
|
# Support for secure monitor traps
|
||||||
obj-$(CONFIG_ARCH_BCM_MOBILE_SMC) += bcm_kona_smc.o bcm_kona_smc_asm.o
|
obj-$(CONFIG_ARCH_BCM_MOBILE_SMC) += bcm_kona_smc.o
|
||||||
plus_sec := $(call as-instr,.arch_extension sec,+sec)
|
ifeq ($(call as-instr,.arch_extension sec,as_has_sec),as_has_sec)
|
||||||
AFLAGS_bcm_kona_smc_asm.o :=-Wa,-march=armv7-a$(plus_sec)
|
CFLAGS_bcm_kona_smc.o += -Wa,-march=armv7-a+sec -DREQUIRES_SEC
|
||||||
|
endif
|
||||||
|
|
||||||
# BCM2835
|
# BCM2835
|
||||||
obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o
|
obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o
|
||||||
|
@ -76,6 +76,50 @@ int __init bcm_kona_smc_init(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since interrupts are disabled in the open mode, we must keep
|
||||||
|
* interrupts disabled in secure mode by setting R5=0x3. If interrupts
|
||||||
|
* are enabled in open mode, we can set R5=0x0 to allow interrupts in
|
||||||
|
* secure mode. If we did this, the secure monitor would return back
|
||||||
|
* control to the open mode to handle the interrupt prior to completing
|
||||||
|
* the secure service. If this happened, R12 would not be
|
||||||
|
* SEC_EXIT_NORMAL and we would need to call SMC again after resetting
|
||||||
|
* R5 (it gets clobbered by the secure monitor) and setting R4 to
|
||||||
|
* SSAPI_RET_FROM_INT_SERV to indicate that we want the secure monitor
|
||||||
|
* to finish up the previous uncompleted secure service.
|
||||||
|
*/
|
||||||
|
static int bcm_kona_do_smc(u32 service_id, u32 buffer_phys)
|
||||||
|
{
|
||||||
|
register u32 ip asm("ip"); /* Also called r12 */
|
||||||
|
register u32 r0 asm("r0");
|
||||||
|
register u32 r4 asm("r4");
|
||||||
|
register u32 r5 asm("r5");
|
||||||
|
register u32 r6 asm("r6");
|
||||||
|
|
||||||
|
r4 = service_id;
|
||||||
|
r5 = 0x3; /* Keep IRQ and FIQ off in SM */
|
||||||
|
r6 = buffer_phys;
|
||||||
|
|
||||||
|
asm volatile (
|
||||||
|
/* Make sure we got the registers we want */
|
||||||
|
__asmeq("%0", "ip")
|
||||||
|
__asmeq("%1", "r0")
|
||||||
|
__asmeq("%2", "r4")
|
||||||
|
__asmeq("%3", "r5")
|
||||||
|
__asmeq("%4", "r6")
|
||||||
|
#ifdef REQUIRES_SEC
|
||||||
|
".arch_extension sec\n"
|
||||||
|
#endif
|
||||||
|
" smc #0\n"
|
||||||
|
: "=r" (ip), "=r" (r0)
|
||||||
|
: "r" (r4), "r" (r5), "r" (r6)
|
||||||
|
: "r1", "r2", "r3", "r7", "lr");
|
||||||
|
|
||||||
|
BUG_ON(ip != SEC_EXIT_NORMAL);
|
||||||
|
|
||||||
|
return r0;
|
||||||
|
}
|
||||||
|
|
||||||
/* __bcm_kona_smc() should only run on CPU 0, with pre-emption disabled */
|
/* __bcm_kona_smc() should only run on CPU 0, with pre-emption disabled */
|
||||||
static void __bcm_kona_smc(void *info)
|
static void __bcm_kona_smc(void *info)
|
||||||
{
|
{
|
||||||
@ -95,7 +139,7 @@ static void __bcm_kona_smc(void *info)
|
|||||||
flush_cache_all();
|
flush_cache_all();
|
||||||
|
|
||||||
/* Trap into Secure Monitor and record the request result */
|
/* Trap into Secure Monitor and record the request result */
|
||||||
data->result = bcm_kona_smc_asm(data->service_id, bcm_smc_buffer_phys);
|
data->result = bcm_kona_do_smc(data->service_id, bcm_smc_buffer_phys);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1,
|
unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1,
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#define SEC_ROM_RET_OK 0x00000001
|
#define SEC_ROM_RET_OK 0x00000001
|
||||||
#define SEC_EXIT_NORMAL 0x1
|
#define SEC_EXIT_NORMAL 0x1
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
|
||||||
extern int __init bcm_kona_smc_init(void);
|
extern int __init bcm_kona_smc_init(void);
|
||||||
|
|
||||||
extern unsigned bcm_kona_smc(unsigned service_id,
|
extern unsigned bcm_kona_smc(unsigned service_id,
|
||||||
@ -30,9 +29,4 @@ extern unsigned bcm_kona_smc(unsigned service_id,
|
|||||||
unsigned arg2,
|
unsigned arg2,
|
||||||
unsigned arg3);
|
unsigned arg3);
|
||||||
|
|
||||||
extern int bcm_kona_smc_asm(u32 service_id,
|
|
||||||
u32 buffer_addr);
|
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
|
||||||
|
|
||||||
#endif /* BCM_KONA_SMC_H */
|
#endif /* BCM_KONA_SMC_H */
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Broadcom Corporation
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
|
||||||
* kind, whether express or implied; without even the implied warranty
|
|
||||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/linkage.h>
|
|
||||||
#include "bcm_kona_smc.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* int bcm_kona_smc_asm(u32 service_id, u32 buffer_addr)
|
|
||||||
*/
|
|
||||||
|
|
||||||
ENTRY(bcm_kona_smc_asm)
|
|
||||||
stmfd sp!, {r4-r12, lr}
|
|
||||||
mov r4, r0 @ service_id
|
|
||||||
mov r5, #3 @ Keep IRQ and FIQ off in SM
|
|
||||||
/*
|
|
||||||
* Since interrupts are disabled in the open mode, we must keep
|
|
||||||
* interrupts disabled in secure mode by setting R5=0x3. If interrupts
|
|
||||||
* are enabled in open mode, we can set R5=0x0 to allow interrupts in
|
|
||||||
* secure mode. If we did this, the secure monitor would return back
|
|
||||||
* control to the open mode to handle the interrupt prior to completing
|
|
||||||
* the secure service. If this happened, R12 would not be
|
|
||||||
* SEC_EXIT_NORMAL and we would need to call SMC again after resetting
|
|
||||||
* R5 (it gets clobbered by the secure monitor) and setting R4 to
|
|
||||||
* SSAPI_RET_FROM_INT_SERV to indicate that we want the secure monitor
|
|
||||||
* to finish up the previous uncompleted secure service.
|
|
||||||
*/
|
|
||||||
mov r6, r1 @ buffer_addr
|
|
||||||
smc #0
|
|
||||||
/* Check r12 for SEC_EXIT_NORMAL here if interrupts are enabled */
|
|
||||||
ldmfd sp!, {r4-r12, pc}
|
|
||||||
ENDPROC(bcm_kona_smc_asm)
|
|
Loading…
Reference in New Issue
Block a user