huawei-mrd-kernel/drivers/tzdriver/cfc.h

159 lines
4.5 KiB
C
Raw Normal View History

#ifndef TZDRIVER_CFC_H
#define TZDRIVER_CFC_H
#define CFC_MARK_SYM(name) __cfc_mark_##name
#define CFC_SEND_DATA_START_SYM(name) __cfc_send_##name##_start
#define CFC_SEND_DATA_STOP_SYM(name) __cfc_send_##name##_stop
#define CFC_FUNC_ENTRY_SYM(func) __cfc_enter_##func
#define CFC_RETURN_SUCC_SYM(func, extra) __cfc_ret_##func##_succ##extra
#define CFC_RETURN_FAIL_SYM(func, extra) __cfc_ret_##func##_fail##extra
#ifndef CFC_GENRULES
#include <linux/spinlock.h>
#ifdef CONFIG_TEE_CFC
#define STRINGX(x) #x
#define STRING(x) STRINGX(x)
extern void cfc_enable_coresight(void);
extern void cfc_disable_coresight(void);
extern void cfc_prepare_clk_pm(void);
extern void cfc_unprepare_pm_clk(void);
extern spinlock_t cfc_coresight_spinlock;
extern unsigned int *cfc_seqlock;
extern bool cfc_is_enabled;
#define ___CFC_SEND_DATA(name, data) \
asm volatile(".pushsection .cfc.entries.text, \"ax\"\n" \
".global " STRING(CFC_SEND_DATA_START_SYM(name)) "\n" \
".global " STRING(CFC_SEND_DATA_STOP_SYM(name)) "\n" \
"1:\n" \
"isb\n" \
STRING(CFC_SEND_DATA_START_SYM(name)) ":\n" \
"isb\n" \
"msr contextidr_el1, %0\n" \
"isb\n" \
STRING(CFC_SEND_DATA_STOP_SYM(name)) ":\n" \
"msr contextidr_el1, %1\n" \
"b 2f\n" \
".popsection\n" \
"b 1b\n" \
"2: \n" \
::"r"(data), "r"(current->pid):)
#define ___CFC_MARK(symname) \
asm volatile(".pushsection .cfc.entries.text, \"ax\"\n" \
".type " STRING(symname) ", @function\n" \
".global " STRING(symname) "\n" \
STRING(symname)":\n" \
"1:\n" \
"b 2f\n" \
".popsection\n" \
"b 1b\n" \
"2: \n" \
)
/* 1.8G */
#define CFC_SEQLOCK_MAX_LOOP 1800000000
#define __CFC_SEQLOCK_BEGIN \
do { \
uint32_t old_seqlock; \
unsigned int __cfc_counter = CFC_SEQLOCK_MAX_LOOP; \
do
#define __CFC_SEQLOCK_END \
while(__cfc_counter && ((old_seqlock % 2) || (old_seqlock != READ_ONCE(*cfc_seqlock))));\
} while (0)
#define __CFC_WRAPPER(content) \
__CFC_SEQLOCK_BEGIN { \
unsigned long __cfc_flags; \
if (!cfc_is_enabled) \
break; \
while ((__cfc_counter && (old_seqlock = READ_ONCE(*cfc_seqlock)) % 2))\
__cfc_counter--; \
get_cpu(); \
spin_lock_irqsave(&cfc_coresight_spinlock, __cfc_flags); \
if (__cfc_counter && ((old_seqlock = READ_ONCE(*cfc_seqlock)) % 2)) { \
spin_unlock_irqrestore(&cfc_coresight_spinlock, __cfc_flags); \
put_cpu(); \
continue; \
} \
cfc_enable_coresight(); \
content; \
cfc_disable_coresight(); \
spin_unlock_irqrestore(&cfc_coresight_spinlock, __cfc_flags); \
put_cpu(); \
} __CFC_SEQLOCK_END
#define __CFC_MARK(symname) __CFC_WRAPPER(___CFC_MARK(symname))
#define __CFC_SEND_DATA(name, data) __CFC_WRAPPER(___CFC_SEND_DATA(name, data))
#else
#define __CFC_MARK(symname) do { } while(0)
#define __CFC_SEND_DATA(symname, data) do { } while (0)
#define cfc_is_enabled false
#define cfc_prepare_clk_pm(ARG) do {} while(0)
#define cfc_unprepare_pm_clk(ARG) do {} while(0)
#endif
/* for linux kernel */
#define CFC_MARK(name) __CFC_MARK(CFC_MARK_SYM(name))
#define CFC_SEND_DATA(name, data) __CFC_SEND_DATA(name, data)
#define __CFC_RETURN(symname, val) \
do { \
__CFC_MARK(symname); \
return val; \
} while(0)
#define __CFC_RETURN_UNPREPARE_PM_CLK(symname, val) \
do { \
__CFC_MARK(symname); \
cfc_unprepare_pm_clk(); \
return val; \
} while(0)
#define CFC_FUNC_ENTRY(func) \
__CFC_MARK(CFC_FUNC_ENTRY_SYM(func))
#define CFC_RETURN_SUCC(func, extra, val) \
__CFC_RETURN(CFC_RETURN_SUCC_SYM(func, extra), val)
#define CFC_RETURN_FAIL(func, extra, val) \
__CFC_RETURN(CFC_RETURN_FAIL_SYM(func, extra), val)
#define CFC_RETURN_SUCC_WITH_PMCLK(func, extra, val) \
__CFC_RETURN_UNPREPARE_PM_CLK(CFC_RETURN_SUCC_SYM(func, extra), val)
#define CFC_RETURN_FAIL_WITH_PMCLK(func, extra, val) \
__CFC_RETURN_UNPREPARE_PM_CLK(CFC_RETURN_FAIL_SYM(func, extra), val)
#define CFC_RETURN(func, extra, val) \
do { \
if (val) \
CFC_RETURN_FAIL(func, extra, val); \
CFC_RETURN_SUCC(func, extra, val); \
} while (0)
#define CFC_RETURN_PMCLK(func, extra, val) \
do { \
if (val) \
CFC_RETURN_FAIL_WITH_PMCLK(func, extra, val); \
CFC_RETURN_SUCC_WITH_PMCLK(func, extra, val); \
} while (0)
#define CFC_RETURN_PMCLK_ON_COND(func, extra, val, cond) \
do { \
if (cond) \
CFC_RETURN_PMCLK(func, extra, val); \
return val; \
} while (0)
#endif
#endif