diff --git a/arch/arm64/include/asm/alternative-macros.h b/arch/arm64/include/asm/alternative-macros.h index c8c77f9e36d6..8f69660e7781 100644 --- a/arch/arm64/include/asm/alternative-macros.h +++ b/arch/arm64/include/asm/alternative-macros.h @@ -19,6 +19,7 @@ #error "cpucaps have overflown ARM64_CB_BIT" #endif +#ifndef BUILD_FIPS140_KO #ifndef __ASSEMBLY__ #include @@ -265,4 +266,60 @@ l_yes: #endif /* __ASSEMBLY__ */ +#else + +/* + * The FIPS140 module does not support alternatives patching, as this + * invalidates the HMAC digest of the .text section. However, some alternatives + * are known to be irrelevant so we can tolerate them in the FIPS140 module, as + * they will never be applied in the first place in the use cases that the + * FIPS140 module targets (Android running on a production phone). Any other + * uses of alternatives should be avoided, as it is not safe in the general + * case to simply use the default sequence in one place (the fips module) and + * the alternative sequence everywhere else. + * + * Below is an allowlist of cpucaps that we can ignore, by simply taking the + * safe default instruction sequence. Note that this implies that the FIPS140 + * module is not compatible with VHE, or with pseudo-NMI support. + */ + +#define __ALT_ARM64_HAS_LDAPR 0, +#define __ALT_ARM64_HAS_VIRT_HOST_EXTN 0, +#define __ALT_ARM64_HAS_GIC_PRIO_MASKING 0, +#define __ALT_ARM64_HAS_GIC_PRIO_RELAXED_SYNC 0, + +#define ALTERNATIVE(oldinstr, newinstr, cpucap, ...) \ + _ALTERNATIVE(oldinstr, __ALT_ ## cpucap, #cpucap) + +#define ALTERNATIVE_CB(oldinstr, cpucap, cb) \ + _ALTERNATIVE(oldinstr, __ALT_ ## cpucap, #cpucap) + +#define _ALTERNATIVE(oldinstr, cpucap, cpucap_str) \ + __take_second_arg(cpucap oldinstr, \ + ".err CPU capability " cpucap_str " not supported in fips140 module") + +#ifndef __ASSEMBLY__ + +#include + +static bool cpus_have_cap(unsigned int num); + +/* + * Return 'false' for all capabilities listed above, and use the slow path for + * the remaining ones. This ensures that the FIPS140 module is consistent with + * itself for all capabilities, and with the rest of the kernel at least for the + * ones not listed. + */ +#define __alternative_has_cap(cpucap, altcap) \ + __take_second_arg(altcap false, cpus_have_cap(cpucap)) + +#define alternative_has_cap_likely(cpucap) \ + __alternative_has_cap(cpucap, __ALT_ ## cpucap) + +#define alternative_has_cap_unlikely alternative_has_cap_likely + +#endif /* !__ASSEMBLY__ */ + +#endif /* BUILD_FIPS140_KO */ + #endif /* __ASM_ALTERNATIVE_MACROS_H */