天天看點

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

繼續閱讀