Skip to content

Commit

Permalink
firmware: smccc: Add support for erratum discovery API
Browse files Browse the repository at this point in the history
It is not always possible for the OS to determine if a CPU is affected by
a particular erratum. For example, it may depend on an integration choice
the chip designer made, or whether firmware has enabled some particular
feature.

Add support for the SMCCC 'Errata Management Firmware Interface' that lets
the OS query firmware for this information.

Link: https://developer.arm.com/documentation/den0100/1-0/?lang=en
Signed-off-by: James Morse <james.morse@arm.com>
  • Loading branch information
James Morse authored and intel-lab-lkp committed Mar 30, 2023
1 parent 9d47f2c commit d17afdb
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 0 deletions.
7 changes: 7 additions & 0 deletions arch/arm64/kernel/cpufeature.c
Expand Up @@ -62,6 +62,7 @@

#define pr_fmt(fmt) "CPU features: " fmt

#include <linux/arm_smccc_em.h>
#include <linux/bsearch.h>
#include <linux/cpumask.h>
#include <linux/crash_dump.h>
Expand Down Expand Up @@ -1047,6 +1048,12 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
*/
init_cpu_hwcaps_indirect_list();

/*
* Early erratum workaround may need to be discovered from firmware.
*/
if (IS_ENABLED(CONFIG_ARM_SMCCC_EM))
arm_smccc_em_init();

/*
* Detect and enable early CPU capabilities based on the boot CPU,
* after we have initialised the CPU feature infrastructure.
Expand Down
8 changes: 8 additions & 0 deletions drivers/firmware/smccc/Kconfig
Expand Up @@ -23,3 +23,11 @@ config ARM_SMCCC_SOC_ID
help
Include support for the SoC bus on the ARM SMCCC firmware based
platforms providing some sysfs information about the SoC variant.

config ARM_SMCCC_EM
bool "Errata discovery by ARM SMCCC"
depends on HAVE_ARM_SMCCC_DISCOVERY
default y
help
Include support for querying firmware via SMCCC to determine whether
the CPU is affected by a specific erratum.
1 change: 1 addition & 0 deletions drivers/firmware/smccc/Makefile
Expand Up @@ -2,3 +2,4 @@
#
obj-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smccc.o kvm_guest.o
obj-$(CONFIG_ARM_SMCCC_SOC_ID) += soc_id.o
obj-$(CONFIG_ARM_SMCCC_EM) += em.o
78 changes: 78 additions & 0 deletions drivers/firmware/smccc/em.c
@@ -0,0 +1,78 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Arm Errata Management firmware interface.
*
* This firmware interface advertises support for firmware mitigations for CPU
* errata. It can also be used to discover erratum where the 'configurations
* affected' depends on the integration.
*
* Copyright (C) 2022 ARM Limited
*/

#define pr_fmt(fmt) "arm_smccc_em: " fmt

#include <linux/arm_smccc_em.h>
#include <linux/arm-smccc.h>
#include <linux/errno.h>
#include <linux/printk.h>

#include <asm/alternative.h>

#include <uapi/linux/psci.h>

static u32 supported;

int arm_smccc_em_cpu_features(u32 erratum_id)
{
struct arm_smccc_res res;

if (!READ_ONCE(supported))
return -EOPNOTSUPP;

arm_smccc_1_1_invoke(ARM_SMCCC_EM_CPU_ERRATUM_FEATURES, erratum_id, 0, &res);
switch (res.a0) {
case SMCCC_RET_NOT_SUPPORTED:
return -EOPNOTSUPP;
case SMCCC_EM_RET_INVALID_PARAMTER:
return -EINVAL;
case SMCCC_EM_RET_UNKNOWN:
return -ENOENT;
case SMCCC_EM_RET_HIGHER_EL_MITIGATION:
case SMCCC_EM_RET_NOT_AFFECTED:
case SMCCC_EM_RET_AFFECTED:
return res.a0;
};

return -EIO;
}

int __init arm_smccc_em_init(void)
{
u32 major_ver, minor_ver;
struct arm_smccc_res res;
enum arm_smccc_conduit conduit = arm_smccc_1_1_get_conduit();

if (conduit == SMCCC_CONDUIT_NONE)
return -EOPNOTSUPP;

arm_smccc_1_1_invoke(ARM_SMCCC_EM_VERSION, &res);
if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
return -EOPNOTSUPP;

major_ver = PSCI_VERSION_MAJOR(res.a0);
minor_ver = PSCI_VERSION_MINOR(res.a0);
if (major_ver != 1)
return -EIO;

arm_smccc_1_1_invoke(ARM_SMCCC_EM_FEATURES,
ARM_SMCCC_EM_CPU_ERRATUM_FEATURES, &res);
if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
return -EOPNOTSUPP;

pr_info("SMCCC Errata Management Interface v%d.%d\n",
major_ver, minor_ver);

WRITE_ONCE(supported, 1);

return 0;
}
28 changes: 28 additions & 0 deletions include/linux/arm-smccc.h
Expand Up @@ -182,6 +182,25 @@
ARM_SMCCC_OWNER_STANDARD, \
0x53)

/* Errata Management calls (defined by ARM DEN0100) */
#define ARM_SMCCC_EM_VERSION \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_32, \
ARM_SMCCC_OWNER_STANDARD, \
0xF0)

#define ARM_SMCCC_EM_FEATURES \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_32, \
ARM_SMCCC_OWNER_STANDARD, \
0xF1)

#define ARM_SMCCC_EM_CPU_ERRATUM_FEATURES \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_32, \
ARM_SMCCC_OWNER_STANDARD, \
0xF2)

/*
* Return codes defined in ARM DEN 0070A
* ARM DEN 0070A is now merged/consolidated into ARM DEN 0028 C
Expand All @@ -191,6 +210,15 @@
#define SMCCC_RET_NOT_REQUIRED -2
#define SMCCC_RET_INVALID_PARAMETER -3

/*
* Return codes defined in ARM DEN 0100
*/
#define SMCCC_EM_RET_HIGHER_EL_MITIGATION 3
#define SMCCC_EM_RET_NOT_AFFECTED 2
#define SMCCC_EM_RET_AFFECTED 1
#define SMCCC_EM_RET_INVALID_PARAMTER -2
#define SMCCC_EM_RET_UNKNOWN -3

#ifndef __ASSEMBLY__

#include <linux/linkage.h>
Expand Down
11 changes: 11 additions & 0 deletions include/linux/arm_smccc_em.h
@@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2023 ARM Limited */
#ifndef __LINUX_ARM_SMCCC_EM_H
#define __LINUX_ARM_SMCCC_EM_H

#include <linux/types.h>

int arm_smccc_em_init(void);
int arm_smccc_em_cpu_features(u32 erratum_id);

#endif /* __LINUX_ARM_SMCCC_EM_H */

0 comments on commit d17afdb

Please sign in to comment.