天天看点

optee中的panic函数实现

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中的panic函数实现
optee中的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)
		;
}
           

继续阅读