optee3.14中的panic、TEE_Panic、panic、panic实现
★★★ 个人博客导读首页—点击此处 ★★★
.
说明:
在默认情况下,本文讲述的都是ARMV8-aarch64架构,optee3.14版本
文章目录
-
-
-
- 1、optee os中的panic函数
- 2、TA中的panic函数
- 3、ldelf中的panic
-
-
1、optee os中的panic函数
在optee os有两种方式调用panic,带参数的和不带参数的,示例如下:
- panic();
- panic(“Written PRIBLOB and read PRIBLOB do not match!”);
对应的这两种中调用,到底层实现
- 无参数的调用: __panic((void *)0)
- 有参数的调用: __panic(s)
(optee_os/core/include/kernel/panic.h)
/* panic() can get a string or no argument */
#define _panic0() __panic((void *)0)
#define _panic1(s) __panic(s)
#define _panic_fn(a, b, name, ...) name
#define panic(...) _panic_fn("", ##__VA_ARGS__, _panic1, _panic0)(__VA_ARGS__)
/* debug disabled => __FILE__, ... and panic message are not built. */
#if defined(CFG_TEE_CORE_DEBUG)
#define __panic(str) __do_panic(__FILE__, __LINE__, __func__, str)
#else
#define __panic(str) __do_panic((void *)0, 0, (void *)0, str)
#endif
__panic
又调用了
__do_panic
,然后我们再看
__do_panic
在底层的实现
- 打印log,无参数的打印"panic",有参数的打印您的参数
- print_kernel_stack()
- while(1)死循环. 所以这也就是为什么,一旦optee os特权默认发生了panic就再也恢复不了了。死循环了还怎么恢复。
(optee_os/core/kernel/panic.c)
void __do_panic(const char *file __maybe_unused,
const int line __maybe_unused,
const char *func __maybe_unused,
const char *msg __maybe_unused)
{
/* disable prehemption */
(void)thread_mask_exceptions(THREAD_EXCP_ALL);
/* TODO: notify other cores */
/* trace: Panic ['panic-string-message' ]at FILE:LINE [<FUNCTION>]" */
if (!file && !func && !msg)
EMSG_RAW("Panic");
else
EMSG_RAW("Panic %s%s%sat %s:%d %s%s%s",
msg ? "'" : "", msg ? msg : "", msg ? "' " : "",
file ? file : "?", file ? line : 0,
func ? "<" : "", func ? func : "", func ? ">" : "");
print_kernel_stack();
/* abort current execution */
while (1)
;
}
2、TA中的panic函数
对于TA,panic的用法也是有两种:
- TEE_Panic(0)
- TEE_Panic(非0)
optee中的panic函数实现
TEE_Panic()是GP定义的一个接口,当然GP也对panic发生的条件做出了要求,这里我们就不细展开讨论
(optee_os/lib/libutee/tee_api_panic.c)
void TEE_Panic(TEE_Result panicCode)
{
_utee_panic(panicCode);
#ifdef __COVERITY__
__coverity_panic__();
#endif
}
(optee_os/lib/libutee/arch/arm/utee_syscalls_a64.S)
FUNC _utee_panic, :
stp x29, x30, [sp, #-16]!
mov x1, sp
bl __utee_panic
/* Not reached */
END_FUNC _utee_panic
#include "utee_syscalls_asm.S"
(optee_os/core/arch/arm/tee/arch_svc_a64.S)
FUNC syscall_panic , :
mov x1, #1 /* panic = true */
mov x2, x0 /* code */
ldr w0, =TEE_ERROR_TARGET_DEAD
ldr x3, [x19, #SC_REC_X0] /* pointer to struct thread_svc_regs */
b tee_svc_sys_return_helper
END_FUNC syscall_panic
(optee_os/core/arch/arm/tee/arch_svc.c)
uint32_t tee_svc_sys_return_helper(uint32_t ret, bool panic,
uint32_t panic_code,
struct thread_svc_regs *regs)
{
if (panic) {
TAMSG_RAW("");
TAMSG_RAW("TA panicked with code 0x%" PRIx32, panic_code);
save_panic_stack(regs);
}
#ifdef ARM32
regs->r1 = panic;
regs->r2 = panic_code;
#endif
#ifdef ARM64
regs->x1 = panic;
regs->x2 = panic_code;
#endif
return ret;
}
3、ldelf中的panic
底层的实现,其实就是回收这个elf(或叫TA,或叫userspace),注意注释
,说明这里不会走到while(true)
(optee_os/ldelf/sys.c)
void __panic(const char *file __maybe_unused, const int line __maybe_unused,
const char *func __maybe_unused)
{
if (!file && !func)
EMSG_RAW("Panic");
else
EMSG_RAW("Panic at %s:%d %s%s%s",
file ? file : "?", file ? line : 0,
func ? "<" : "", func ? func : "", func ? ">" : "");
_ldelf_panic(1);
/*NOTREACHED*/
while (true)
;
}