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)
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)
;
}