Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8b9c550e authored by Alex Elder's avatar Alex Elder Committed by Matt Porter
Browse files

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: default avatarAlex Elder <elder@linaro.org>
Reviewed-by: default avatarTim Kryger <tim.kryger@linaro.org>
Reviewed-by: default avatarMarkus Mayer <markus.mayer@linaro.org>
Reviewed-by: default avatarMatt Porter <mporter@linaro.org>
Signed-off-by: default avatarMatt Porter <mporter@linaro.org>
parent d5c627b5
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -20,9 +20,10 @@ obj-$(CONFIG_ARCH_BCM_21664) += board_bcm21664.o
obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona.o

# Support for secure monitor traps
obj-$(CONFIG_ARCH_BCM_MOBILE_SMC) += bcm_kona_smc.o bcm_kona_smc_asm.o
plus_sec := $(call as-instr,.arch_extension sec,+sec)
AFLAGS_bcm_kona_smc_asm.o	:=-Wa,-march=armv7-a$(plus_sec)
obj-$(CONFIG_ARCH_BCM_MOBILE_SMC) += bcm_kona_smc.o
ifeq ($(call as-instr,.arch_extension sec,as_has_sec),as_has_sec)
CFLAGS_bcm_kona_smc.o		+= -Wa,-march=armv7-a+sec -DREQUIRES_SEC
endif

# BCM2835
obj-$(CONFIG_ARCH_BCM2835)	+= board_bcm2835.o
+45 −1
Original line number Diff line number Diff line
@@ -76,6 +76,50 @@ int __init bcm_kona_smc_init(void)
	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 */
static void __bcm_kona_smc(void *info)
{
@@ -95,7 +139,7 @@ static void __bcm_kona_smc(void *info)
	flush_cache_all();

	/* 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,
+0 −6
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@
#define SEC_ROM_RET_OK			0x00000001
#define SEC_EXIT_NORMAL			0x1

#ifndef	__ASSEMBLY__
extern int __init bcm_kona_smc_init(void);

extern unsigned bcm_kona_smc(unsigned service_id,
@@ -30,9 +29,4 @@ extern unsigned bcm_kona_smc(unsigned service_id,
			     unsigned arg2,
			     unsigned arg3);

extern int bcm_kona_smc_asm(u32 service_id,
			    u32 buffer_addr);

#endif	/* __ASSEMBLY__ */

#endif /* BCM_KONA_SMC_H */
+0 −41
Original line number Diff line number Diff line
/*
 * 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)