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

Commit d9a1beaa authored by Alexandre Courbot's avatar Alexandre Courbot Committed by Stephen Warren
Browse files

ARM: add basic support for Trusted Foundations



Trusted Foundations is a TrustZone-based secure monitor for ARM that
can be invoked using the same SMC-based API on supported platforms.
This patch adds initial basic support for Trusted Foundations using
the ARM firmware API. Current features are limited to the ability to
boot secondary processors.

Note: The API followed by Trusted Foundations does *not* follow the SMC
calling conventions. It has nothing to do with PSCI neither and is only
relevant to devices that use Trusted Foundations (like most Tegra-based
retail devices).

Signed-off-by: default avatarAlexandre Courbot <acourbot@nvidia.com>
Reviewed-by: default avatarTomasz Figa <t.figa@samsung.com>
Reviewed-by: default avatarStephen Warren <swarren@nvidia.com>
Signed-off-by: default avatarStephen Warren <swarren@nvidia.com>
parent 6ce4eac1
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1053,6 +1053,8 @@ config ARM_TIMER_SP804
	select CLKSRC_MMIO
	select CLKSRC_OF if OF

source "arch/arm/firmware/Kconfig"

source arch/arm/mm/Kconfig

config ARM_NR_BANKS
+1 −0
Original line number Diff line number Diff line
@@ -268,6 +268,7 @@ core-$(CONFIG_KVM_ARM_HOST) += arch/arm/kvm/
core-y				+= arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
core-y				+= arch/arm/net/
core-y				+= arch/arm/crypto/
core-y				+= arch/arm/firmware/
core-y				+= $(machdirs) $(platdirs)

drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
+28 −0
Original line number Diff line number Diff line
config ARCH_SUPPORTS_FIRMWARE
	bool

config ARCH_SUPPORTS_TRUSTED_FOUNDATIONS
	bool
	select ARCH_SUPPORTS_FIRMWARE

menu "Firmware options"
	depends on ARCH_SUPPORTS_FIRMWARE

config TRUSTED_FOUNDATIONS
	bool "Trusted Foundations secure monitor support"
	depends on ARCH_SUPPORTS_TRUSTED_FOUNDATIONS
	help
	  Some devices (including most Tegra-based consumer devices on the
	  market) are booted with the Trusted Foundations secure monitor
	  active, requiring some core operations to be performed by the secure
	  monitor instead of the kernel.

	  This option allows the kernel to invoke the secure monitor whenever
	  required on devices using Trusted Foundations. See
	  arch/arm/include/asm/trusted_foundations.h or the
	  tl,trusted-foundations device tree binding documentation for details
	  on how to use it.

	  Say n if you don't know what this is about.

endmenu
+1 −0
Original line number Diff line number Diff line
obj-$(CONFIG_TRUSTED_FOUNDATIONS)	+= trusted_foundations.o
+81 −0
Original line number Diff line number Diff line
/*
 * Trusted Foundations support for ARM CPUs
 *
 * Copyright (c) 2013, NVIDIA 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; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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.
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/of.h>
#include <asm/firmware.h>
#include <asm/trusted_foundations.h>

#define TF_SET_CPU_BOOT_ADDR_SMC 0xfffff200

static void __naked tf_generic_smc(u32 type, u32 arg1, u32 arg2)
{
	asm volatile(
		".arch_extension	sec\n\t"
		"stmfd	sp!, {r4 - r11, lr}\n\t"
		__asmeq("%0", "r0")
		__asmeq("%1", "r1")
		__asmeq("%2", "r2")
		"mov	r3, #0\n\t"
		"mov	r4, #0\n\t"
		"smc	#0\n\t"
		"ldmfd	sp!, {r4 - r11, pc}"
		:
		: "r" (type), "r" (arg1), "r" (arg2)
		: "memory");
}

static int tf_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
{
	tf_generic_smc(TF_SET_CPU_BOOT_ADDR_SMC, boot_addr, 0);

	return 0;
}

static const struct firmware_ops trusted_foundations_ops = {
	.set_cpu_boot_addr = tf_set_cpu_boot_addr,
};

void register_trusted_foundations(struct trusted_foundations_platform_data *pd)
{
	/*
	 * we are not using version information for now since currently
	 * supported SMCs are compatible with all TF releases
	 */
	register_firmware_ops(&trusted_foundations_ops);
}

void of_register_trusted_foundations(void)
{
	struct device_node *node;
	struct trusted_foundations_platform_data pdata;
	int err;

	node = of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations");
	if (!node)
		return;

	err = of_property_read_u32(node, "tlm,version-major",
				   &pdata.version_major);
	if (err != 0)
		panic("Trusted Foundation: missing version-major property\n");
	err = of_property_read_u32(node, "tlm,version-minor",
				   &pdata.version_minor);
	if (err != 0)
		panic("Trusted Foundation: missing version-minor property\n");
	register_trusted_foundations(&pdata);
}
Loading