aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/Kconfig6
-rw-r--r--drivers/firmware/Makefile3
-rw-r--r--drivers/firmware/arm_sdei.c49
-rw-r--r--drivers/firmware/efi/libstub/Makefile3
-rw-r--r--drivers/firmware/psci/psci.c21
-rw-r--r--drivers/firmware/smccc/Kconfig16
-rw-r--r--drivers/firmware/smccc/Makefile3
-rw-r--r--drivers/firmware/smccc/smccc.c31
8 files changed, 83 insertions, 49 deletions
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 8007d4aa76dc..4843e94713a4 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -295,15 +295,13 @@ config TURRIS_MOX_RWTM
other manufacturing data and also utilize the Entropy Bit Generator
for hardware random number generation.
-config HAVE_ARM_SMCCC
- bool
-
-source "drivers/firmware/psci/Kconfig"
source "drivers/firmware/broadcom/Kconfig"
source "drivers/firmware/google/Kconfig"
source "drivers/firmware/efi/Kconfig"
source "drivers/firmware/imx/Kconfig"
source "drivers/firmware/meson/Kconfig"
+source "drivers/firmware/psci/Kconfig"
+source "drivers/firmware/smccc/Kconfig"
source "drivers/firmware/tegra/Kconfig"
source "drivers/firmware/xilinx/Kconfig"
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index e9fb838af4df..99510be9f5ed 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -23,12 +23,13 @@ obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o
obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o
obj-$(CONFIG_ARM_SCMI_PROTOCOL) += arm_scmi/
-obj-y += psci/
obj-y += broadcom/
obj-y += meson/
obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
obj-$(CONFIG_EFI) += efi/
obj-$(CONFIG_UEFI_CPER) += efi/
obj-y += imx/
+obj-y += psci/
+obj-y += smccc/
obj-y += tegra/
obj-y += xilinx/
diff --git a/drivers/firmware/arm_sdei.c b/drivers/firmware/arm_sdei.c
index 334c8be0c11f..e7e36aab2386 100644
--- a/drivers/firmware/arm_sdei.c
+++ b/drivers/firmware/arm_sdei.c
@@ -429,7 +429,6 @@ int sdei_event_enable(u32 event_num)
return err;
}
-EXPORT_SYMBOL(sdei_event_enable);
static int sdei_api_event_disable(u32 event_num)
{
@@ -471,7 +470,6 @@ int sdei_event_disable(u32 event_num)
return err;
}
-EXPORT_SYMBOL(sdei_event_disable);
static int sdei_api_event_unregister(u32 event_num)
{
@@ -533,7 +531,6 @@ int sdei_event_unregister(u32 event_num)
return err;
}
-EXPORT_SYMBOL(sdei_event_unregister);
/*
* unregister events, but don't destroy them as they are re-registered by
@@ -643,7 +640,6 @@ int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg)
return err;
}
-EXPORT_SYMBOL(sdei_event_register);
static int sdei_reregister_event_llocked(struct sdei_event *event)
{
@@ -1079,26 +1075,9 @@ static struct platform_driver sdei_driver = {
.probe = sdei_probe,
};
-static bool __init sdei_present_dt(void)
-{
- struct device_node *np, *fw_np;
-
- fw_np = of_find_node_by_name(NULL, "firmware");
- if (!fw_np)
- return false;
-
- np = of_find_matching_node(fw_np, sdei_of_match);
- if (!np)
- return false;
- of_node_put(np);
-
- return true;
-}
-
static bool __init sdei_present_acpi(void)
{
acpi_status status;
- struct platform_device *pdev;
struct acpi_table_header *sdei_table_header;
if (acpi_disabled)
@@ -1113,20 +1092,26 @@ static bool __init sdei_present_acpi(void)
if (ACPI_FAILURE(status))
return false;
- pdev = platform_device_register_simple(sdei_driver.driver.name, 0, NULL,
- 0);
- if (IS_ERR(pdev))
- return false;
+ acpi_put_table(sdei_table_header);
return true;
}
static int __init sdei_init(void)
{
- if (sdei_present_dt() || sdei_present_acpi())
- platform_driver_register(&sdei_driver);
+ int ret = platform_driver_register(&sdei_driver);
- return 0;
+ if (!ret && sdei_present_acpi()) {
+ struct platform_device *pdev;
+
+ pdev = platform_device_register_simple(sdei_driver.driver.name,
+ 0, NULL, 0);
+ if (IS_ERR(pdev))
+ pr_info("Failed to register ACPI:SDEI platform device %ld\n",
+ PTR_ERR(pdev));
+ }
+
+ return ret;
}
/*
@@ -1143,6 +1128,14 @@ int sdei_event_handler(struct pt_regs *regs,
mm_segment_t orig_addr_limit;
u32 event_num = arg->event_num;
+ /*
+ * Save restore 'fs'.
+ * The architecture's entry code save/restores 'fs' when taking an
+ * exception from the kernel. This ensures addr_limit isn't inherited
+ * if you interrupted something that allowed the uaccess routines to
+ * access kernel memory.
+ * Do the same here because this doesn't come via the same entry code.
+ */
orig_addr_limit = get_fs();
set_fs(USER_DS);
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 034d71663b1e..cce4a7436052 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -33,6 +33,9 @@ KBUILD_CFLAGS := $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \
$(call cc-option,-fno-addrsig) \
-D__DISABLE_EXPORTS
+# remove SCS flags from all objects in this directory
+KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_SCS), $(KBUILD_CFLAGS))
+
GCOV_PROFILE := n
KASAN_SANITIZE := n
UBSAN_SANITIZE := n
diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
index 2937d44b5df4..92013ecc2d9e 100644
--- a/drivers/firmware/psci/psci.c
+++ b/drivers/firmware/psci/psci.c
@@ -46,25 +46,14 @@
* require cooperation with a Trusted OS driver.
*/
static int resident_cpu = -1;
+struct psci_operations psci_ops;
+static enum arm_smccc_conduit psci_conduit = SMCCC_CONDUIT_NONE;
bool psci_tos_resident_on(int cpu)
{
return cpu == resident_cpu;
}
-struct psci_operations psci_ops = {
- .conduit = SMCCC_CONDUIT_NONE,
- .smccc_version = SMCCC_VERSION_1_0,
-};
-
-enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void)
-{
- if (psci_ops.smccc_version < SMCCC_VERSION_1_1)
- return SMCCC_CONDUIT_NONE;
-
- return psci_ops.conduit;
-}
-
typedef unsigned long (psci_fn)(unsigned long, unsigned long,
unsigned long, unsigned long);
static psci_fn *invoke_psci_fn;
@@ -242,7 +231,7 @@ static void set_conduit(enum arm_smccc_conduit conduit)
WARN(1, "Unexpected PSCI conduit %d\n", conduit);
}
- psci_ops.conduit = conduit;
+ psci_conduit = conduit;
}
static int get_set_conduit_method(struct device_node *np)
@@ -411,8 +400,8 @@ static void __init psci_init_smccc(void)
if (feature != PSCI_RET_NOT_SUPPORTED) {
u32 ret;
ret = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0);
- if (ret == ARM_SMCCC_VERSION_1_1) {
- psci_ops.smccc_version = SMCCC_VERSION_1_1;
+ if (ret >= ARM_SMCCC_VERSION_1_1) {
+ arm_smccc_version_init(ret, psci_conduit);
ver = ret;
}
}
diff --git a/drivers/firmware/smccc/Kconfig b/drivers/firmware/smccc/Kconfig
new file mode 100644
index 000000000000..27b675d76235
--- /dev/null
+++ b/drivers/firmware/smccc/Kconfig
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config HAVE_ARM_SMCCC
+ bool
+ help
+ Include support for the Secure Monitor Call (SMC) and Hypervisor
+ Call (HVC) instructions on Armv7 and above architectures.
+
+config HAVE_ARM_SMCCC_DISCOVERY
+ bool
+ depends on ARM_PSCI_FW
+ default y
+ help
+ SMCCC v1.0 lacked discoverability and hence PSCI v1.0 was updated
+ to add SMCCC discovery mechanism though the PSCI firmware
+ implementation of PSCI_FEATURES(SMCCC_VERSION) which returns
+ success on firmware compliant to SMCCC v1.1 and above.
diff --git a/drivers/firmware/smccc/Makefile b/drivers/firmware/smccc/Makefile
new file mode 100644
index 000000000000..6f369fe3f0b9
--- /dev/null
+++ b/drivers/firmware/smccc/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+obj-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smccc.o
diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c
new file mode 100644
index 000000000000..4e80921ee212
--- /dev/null
+++ b/drivers/firmware/smccc/smccc.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2020 Arm Limited
+ */
+
+#define pr_fmt(fmt) "smccc: " fmt
+
+#include <linux/init.h>
+#include <linux/arm-smccc.h>
+
+static u32 smccc_version = ARM_SMCCC_VERSION_1_0;
+static enum arm_smccc_conduit smccc_conduit = SMCCC_CONDUIT_NONE;
+
+void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit)
+{
+ smccc_version = version;
+ smccc_conduit = conduit;
+}
+
+enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void)
+{
+ if (smccc_version < ARM_SMCCC_VERSION_1_1)
+ return SMCCC_CONDUIT_NONE;
+
+ return smccc_conduit;
+}
+
+u32 arm_smccc_get_version(void)
+{
+ return smccc_version;
+}