1*7e75ca54SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2*7e75ca54SJens Wiklander /*
3*7e75ca54SJens Wiklander * Copyright (c) 2022, Linaro Limited
4*7e75ca54SJens Wiklander */
5*7e75ca54SJens Wiklander
6*7e75ca54SJens Wiklander #include <compiler.h>
7*7e75ca54SJens Wiklander #include <fault_mitigation.h>
8*7e75ca54SJens Wiklander
9*7e75ca54SJens Wiklander #ifndef __KERNEL__
10*7e75ca54SJens Wiklander struct ftmn_func_arg *__ftmn_global_func_arg;
11*7e75ca54SJens Wiklander #endif
12*7e75ca54SJens Wiklander
13*7e75ca54SJens Wiklander /*
14*7e75ca54SJens Wiklander * These functions can be implemented in assembly if needed. They would
15*7e75ca54SJens Wiklander * provide the same API but an implementation more resilient to fault
16*7e75ca54SJens Wiklander * injections.
17*7e75ca54SJens Wiklander *
18*7e75ca54SJens Wiklander * For now there is no need since it's enough with the single redundancy
19*7e75ca54SJens Wiklander * provided just by having these function implemented separately from where
20*7e75ca54SJens Wiklander * they are used.
21*7e75ca54SJens Wiklander */
22*7e75ca54SJens Wiklander
___ftmn_return_res(struct ftmn_check * check,unsigned long steps,unsigned long res)23*7e75ca54SJens Wiklander unsigned long __weak ___ftmn_return_res(struct ftmn_check *check,
24*7e75ca54SJens Wiklander unsigned long steps, unsigned long res)
25*7e75ca54SJens Wiklander {
26*7e75ca54SJens Wiklander if (check->steps != steps)
27*7e75ca54SJens Wiklander FTMN_PANIC();
28*7e75ca54SJens Wiklander if ((check->res ^ FTMN_DEFAULT_HASH) != res)
29*7e75ca54SJens Wiklander FTMN_PANIC();
30*7e75ca54SJens Wiklander return res;
31*7e75ca54SJens Wiklander }
32*7e75ca54SJens Wiklander
___ftmn_expect_state(struct ftmn_check * check,enum ftmn_incr incr,unsigned long steps,unsigned long res)33*7e75ca54SJens Wiklander void __weak ___ftmn_expect_state(struct ftmn_check *check, enum ftmn_incr incr,
34*7e75ca54SJens Wiklander unsigned long steps, unsigned long res)
35*7e75ca54SJens Wiklander {
36*7e75ca54SJens Wiklander if ((check->res ^ FTMN_DEFAULT_HASH) != res)
37*7e75ca54SJens Wiklander FTMN_PANIC();
38*7e75ca54SJens Wiklander if (check->steps != steps)
39*7e75ca54SJens Wiklander FTMN_PANIC();
40*7e75ca54SJens Wiklander check->steps += incr;
41*7e75ca54SJens Wiklander }
42*7e75ca54SJens Wiklander
___ftmn_callee_done(struct ftmn_func_arg * arg,unsigned long my_hash,unsigned long res)43*7e75ca54SJens Wiklander void __weak ___ftmn_callee_done(struct ftmn_func_arg *arg,
44*7e75ca54SJens Wiklander unsigned long my_hash,
45*7e75ca54SJens Wiklander unsigned long res)
46*7e75ca54SJens Wiklander {
47*7e75ca54SJens Wiklander arg->hash ^= my_hash;
48*7e75ca54SJens Wiklander arg->res = arg->hash ^ res;
49*7e75ca54SJens Wiklander }
50*7e75ca54SJens Wiklander
___ftmn_callee_done_not_zero(struct ftmn_func_arg * arg,unsigned long my_hash,unsigned long res)51*7e75ca54SJens Wiklander void __weak ___ftmn_callee_done_not_zero(struct ftmn_func_arg *arg,
52*7e75ca54SJens Wiklander unsigned long my_hash,
53*7e75ca54SJens Wiklander unsigned long res)
54*7e75ca54SJens Wiklander {
55*7e75ca54SJens Wiklander if (res == 0)
56*7e75ca54SJens Wiklander FTMN_PANIC();
57*7e75ca54SJens Wiklander arg->hash ^= my_hash;
58*7e75ca54SJens Wiklander arg->res = arg->hash ^ res;
59*7e75ca54SJens Wiklander }
60*7e75ca54SJens Wiklander
___ftmn_callee_done_memcmp(struct ftmn_func_arg * arg,unsigned long my_hash,int res,ftmn_memcmp_t my_memcmp,const void * p1,const void * p2,size_t nb)61*7e75ca54SJens Wiklander void __weak ___ftmn_callee_done_memcmp(struct ftmn_func_arg *arg,
62*7e75ca54SJens Wiklander unsigned long my_hash, int res,
63*7e75ca54SJens Wiklander ftmn_memcmp_t my_memcmp,
64*7e75ca54SJens Wiklander const void *p1, const void *p2,
65*7e75ca54SJens Wiklander size_t nb)
66*7e75ca54SJens Wiklander {
67*7e75ca54SJens Wiklander int res2 = 0;
68*7e75ca54SJens Wiklander
69*7e75ca54SJens Wiklander if (!nb)
70*7e75ca54SJens Wiklander FTMN_PANIC();
71*7e75ca54SJens Wiklander
72*7e75ca54SJens Wiklander res2 = my_memcmp(p1, p2, nb);
73*7e75ca54SJens Wiklander if (res2 != res)
74*7e75ca54SJens Wiklander FTMN_PANIC();
75*7e75ca54SJens Wiklander
76*7e75ca54SJens Wiklander arg->hash ^= my_hash;
77*7e75ca54SJens Wiklander arg->res = arg->hash ^ res;
78*7e75ca54SJens Wiklander }
79*7e75ca54SJens Wiklander
___ftmn_callee_done_check(struct ftmn_func_arg * arg,unsigned long my_hash,struct ftmn_check * check,enum ftmn_incr incr,unsigned long steps,unsigned long res)80*7e75ca54SJens Wiklander void __weak ___ftmn_callee_done_check(struct ftmn_func_arg *arg,
81*7e75ca54SJens Wiklander unsigned long my_hash,
82*7e75ca54SJens Wiklander struct ftmn_check *check,
83*7e75ca54SJens Wiklander enum ftmn_incr incr, unsigned long steps,
84*7e75ca54SJens Wiklander unsigned long res)
85*7e75ca54SJens Wiklander {
86*7e75ca54SJens Wiklander if ((check->res ^ FTMN_DEFAULT_HASH) != res)
87*7e75ca54SJens Wiklander FTMN_PANIC();
88*7e75ca54SJens Wiklander if (check->steps != steps)
89*7e75ca54SJens Wiklander FTMN_PANIC();
90*7e75ca54SJens Wiklander
91*7e75ca54SJens Wiklander check->steps += incr;
92*7e75ca54SJens Wiklander if (arg) {
93*7e75ca54SJens Wiklander arg->hash ^= my_hash;
94*7e75ca54SJens Wiklander arg->res = check->res ^ FTMN_DEFAULT_HASH ^ arg->hash;
95*7e75ca54SJens Wiklander }
96*7e75ca54SJens Wiklander
97*7e75ca54SJens Wiklander }
98*7e75ca54SJens Wiklander
___ftmn_callee_update_not_zero(struct ftmn_func_arg * arg,unsigned long res)99*7e75ca54SJens Wiklander void ___ftmn_callee_update_not_zero(struct ftmn_func_arg *arg,
100*7e75ca54SJens Wiklander unsigned long res)
101*7e75ca54SJens Wiklander {
102*7e75ca54SJens Wiklander if (!res)
103*7e75ca54SJens Wiklander FTMN_PANIC();
104*7e75ca54SJens Wiklander arg->res = arg->hash ^ res;
105*7e75ca54SJens Wiklander }
106*7e75ca54SJens Wiklander
107*7e75ca54SJens Wiklander
___ftmn_copy_linked_call_res(struct ftmn_check * check,enum ftmn_incr incr,struct ftmn_func_arg * arg,unsigned long res)108*7e75ca54SJens Wiklander void __weak ___ftmn_copy_linked_call_res(struct ftmn_check *check,
109*7e75ca54SJens Wiklander enum ftmn_incr incr,
110*7e75ca54SJens Wiklander struct ftmn_func_arg *arg,
111*7e75ca54SJens Wiklander unsigned long res)
112*7e75ca54SJens Wiklander {
113*7e75ca54SJens Wiklander if ((arg->res ^ arg->hash) != res)
114*7e75ca54SJens Wiklander FTMN_PANIC();
115*7e75ca54SJens Wiklander check->res = res ^ FTMN_DEFAULT_HASH;
116*7e75ca54SJens Wiklander check->steps += incr;
117*7e75ca54SJens Wiklander }
118*7e75ca54SJens Wiklander
___ftmn_set_check_res(struct ftmn_check * check,enum ftmn_incr incr,unsigned long res)119*7e75ca54SJens Wiklander void __weak ___ftmn_set_check_res(struct ftmn_check *check, enum ftmn_incr incr,
120*7e75ca54SJens Wiklander unsigned long res)
121*7e75ca54SJens Wiklander {
122*7e75ca54SJens Wiklander check->steps += incr;
123*7e75ca54SJens Wiklander check->res = res ^ FTMN_DEFAULT_HASH;
124*7e75ca54SJens Wiklander }
125*7e75ca54SJens Wiklander
___ftmn_set_check_res_not_zero(struct ftmn_check * check,enum ftmn_incr incr,unsigned long res)126*7e75ca54SJens Wiklander void __weak ___ftmn_set_check_res_not_zero(struct ftmn_check *check,
127*7e75ca54SJens Wiklander enum ftmn_incr incr,
128*7e75ca54SJens Wiklander unsigned long res)
129*7e75ca54SJens Wiklander {
130*7e75ca54SJens Wiklander if (!res)
131*7e75ca54SJens Wiklander FTMN_PANIC();
132*7e75ca54SJens Wiklander check->steps += incr;
133*7e75ca54SJens Wiklander check->res = res ^ FTMN_DEFAULT_HASH;
134*7e75ca54SJens Wiklander }
135*7e75ca54SJens Wiklander
___ftmn_set_check_res_memcmp(struct ftmn_check * check,enum ftmn_incr incr,int res,ftmn_memcmp_t my_memcmp,const void * p1,const void * p2,size_t nb)136*7e75ca54SJens Wiklander void __weak ___ftmn_set_check_res_memcmp(struct ftmn_check *check,
137*7e75ca54SJens Wiklander enum ftmn_incr incr, int res,
138*7e75ca54SJens Wiklander ftmn_memcmp_t my_memcmp,
139*7e75ca54SJens Wiklander const void *p1, const void *p2,
140*7e75ca54SJens Wiklander size_t nb)
141*7e75ca54SJens Wiklander {
142*7e75ca54SJens Wiklander int res2 = 0;
143*7e75ca54SJens Wiklander
144*7e75ca54SJens Wiklander if (!nb)
145*7e75ca54SJens Wiklander FTMN_PANIC();
146*7e75ca54SJens Wiklander
147*7e75ca54SJens Wiklander res2 = my_memcmp(p1, p2, nb);
148*7e75ca54SJens Wiklander if (res2 != res)
149*7e75ca54SJens Wiklander FTMN_PANIC();
150*7e75ca54SJens Wiklander
151*7e75ca54SJens Wiklander check->steps += incr;
152*7e75ca54SJens Wiklander check->res = FTMN_DEFAULT_HASH ^ res;
153*7e75ca54SJens Wiklander }
154