요청하는 쪽과 처리하는 쪽을 함께 봅니다
Linux v6.18.37의 TEE/OP-TEE 드라이버, TF-A LTS 2.14.3의 opteed, OP-TEE OS 4.10.0을 연결합니다. 먼저 전통적인 SMC ABI 경로를 설명한 뒤 FF-A 차이를 구분합니다. TEE는 보안 실행 환경이라는 범주이고 OP-TEE는 그 구현 중 하나입니다.
- 사용자 프로그램과 TEE Client API
라이브러리가 /dev/tee*에 세션 열기·명령 실행 ioctl을 요청합니다.
ioctl 시스템 호출
- Linux TEE core와 OP-TEE 드라이버
사용자 인자와 공유 메모리 참조를 검사하고 optee_msg_arg를 준비합니다.
SMC ABI 호출
- TF-A의 opteed
현재 CPU의 비보안 context를 보존하고 OP-TEE의 보안 context로 전환합니다.
Secure World 실행
- OP-TEE와 TA
메시지와 세션·메모리 권한을 확인한 뒤 Trusted Application의 명령을 실행합니다.
결과 또는 중간 RPC를 호출한 쪽으로 반환
- Linux와 사용자 프로그램
중간 RPC면 처리 후 재진입하고, 최종 결과면 사용자에게 돌려줍니다.
화살표는 요청과 실행 전환의 방향입니다. TA가 Linux 프로세스 안에서 실행되거나 CPU를 새로 켠다는 뜻은 아닙니다. Linux 커널 내부 TEE 사용자는 사용자 공간 단계를 거치지 않을 수도 있습니다.
서비스 번호와 TA 명령 번호는 다릅니다
v6.18.37 · drivers/tee/optee/call.c · 538–546행
msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND;
msg_arg->func = arg->func;
msg_arg->session = arg->session;
msg_arg->cancel_id = arg->cancel_id;
rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params,
param);
if (rc)
goto out;| 코드에서 볼 부분 | 이 줄이 하는 일과 다음 단계에 미치는 영향 |
|---|---|
msg_arg->cmd | OP-TEE 메시지 수준에서 “TA 명령 실행”이라는 작업 종류를 정합니다. |
msg_arg->func | 해당 TA가 해석할 명령 번호입니다. PSCI나 SMC function ID가 아닙니다. |
msg_arg->session | 이미 연 세션을 식별합니다. 커널과 OP-TEE 모두 세션 수명과 유효성을 확인합니다. |
msg_arg->cancel_id | 진행 중인 요청을 취소할 때 대응시킬 식별자입니다. |
to_msg_param | Linux의 매개변수를 OP-TEE 메시지 표현으로 변환합니다. 단순 정수 인자와 메모리 참조를 구분합니다. |
| 전달 위치 | 내용 | 해석하는 쪽 |
|---|---|---|
| a0 / x0 | OPTEE_SMC_CALL_WITH_ARG | SMC 서비스와 호출 형태를 선택합니다. |
| a1 / x1 | 메시지 물리 주소의 상위 32비트 | OP-TEE SMC ABI가 a2와 결합합니다. |
| a2 / x2 | 메시지 물리 주소의 하위 32비트 | AArch64라고 x1 하나에 포인터 전체를 넣는 규칙으로 바꾸지 않습니다. |
| 공유 메모리의 optee_msg_arg | cmd, session, func, ret, params 등 | OP-TEE가 메시지의 작업과 인자를 해석합니다. |
이 표는 CALL_WITH_ARG 계열의 물리 주소 전달 예입니다. CALL_WITH_REGD_ARG의 a1:a2는 등록된 공유 메모리 cookie이고 a3는 offset이므로 같은 뜻으로 읽으면 안 됩니다.
v6.18.37 드라이버는 협상한 기능과 공유 메모리 종류에 따라 CALL_WITH_ARG, CALL_WITH_RPC_ARG, CALL_WITH_REGD_ARG를 고릅니다. 기존 글에 “항상 물리 포인터를 넘긴다”는 설명만 있으면 이 차이를 보충해야 합니다. SMC 호출 형태 선택 · 레지스터별 ABI 정의
한 번의 요청이 여러 번의 SMC 왕복으로 이어질 수 있습니다
v6.18.37 · drivers/tee/optee/smc_abi.c · 932–956행
trace_optee_invoke_fn_begin(¶m);
optee->smc.invoke_fn(param.a0, param.a1, param.a2, param.a3,
param.a4, param.a5, param.a6, param.a7,
&res);
trace_optee_invoke_fn_end(¶m, &res);
if (res.a0 == OPTEE_SMC_RETURN_ETHREAD_LIMIT) {
/*
* Out of threads in secure world, wait for a thread
* become available.
*/
optee_cq_wait_for_completion(&optee->call_queue, &w);
} else if (OPTEE_SMC_RETURN_IS_RPC(res.a0)) {
cond_resched();
param.a0 = res.a0;
param.a1 = res.a1;
param.a2 = res.a2;
param.a3 = res.a3;
optee_handle_rpc(ctx, rpc_arg, ¶m, &call_ctx);
} else {
rc = res.a0;
break;
}
}| 코드에서 볼 부분 | 이 줄이 하는 일과 다음 단계에 미치는 영향 |
|---|---|
optee->smc.invoke_fn(...) | 현재 param의 레지스터 인자로 보안 쪽을 호출합니다. |
OPTEE_SMC_RETURN_ETHREAD_LIMIT | 보안 쪽 실행 스레드가 부족하면 대기합니다. TA의 최종 실행 결과를 받은 것이 아닙니다. |
OPTEE_SMC_RETURN_IS_RPC(res.a0) | 보안 요청이 완료된 것이 아니라 일반 영역의 도움이 필요한 중간 반환인지 구분합니다. |
param.a0~a3 = res.a0~a3 | RPC 종류와 필요한 반환 정보를 다음 처리로 전달합니다. |
optee_handle_rpc | 커널이 처리할 요청은 직접 처리하고, 사용자 공간 작업은 supplicant 경로에 전달합니다. 이후 RETURN_FROM_RPC를 사용해 보안 작업을 이어갑니다. |
그 밖의 반환에서 break | 호출을 끝낼 반환 코드라면 반복을 마칩니다. rc = res.a0와 메시지 안의 TA 결과는 구분해야 합니다. |
- OP-TEE의 실행 중인 요청
예를 들어 TA 파일 읽기 등 일반 영역의 서비스가 필요해집니다.
RPC 이유와 재개 정보를 반환
- Linux OP-TEE 드라이버
RPC를 분류합니다. 사용자 공간이 처리할 요청은 supplicant 대기열로 전달합니다.
tee-supplicant가 요청을 받아 처리
- tee-supplicant
파일 서비스 등의 결과를 공유 메모리와 응답으로 돌려줍니다.
드라이버가 RETURN_FROM_RPC로 재진입
- OP-TEE의 중단된 작업
저장한 실행 상태를 이어가고 반환받은 데이터와 크기를 검증합니다.
완료되면 최종 결과 반환
RPC는 OP-TEE가 Linux 안의 임의 함수를 직접 호출하는 뜻이 아닙니다. 정해진 메시지와 ioctl·공유 메모리를 통해 작업을 요청합니다. 모든 RPC가 tee-supplicant까지 가는 것도 아닙니다.
공유 메모리는 비보안 쪽이 바꿀 수 있으므로 “응답이 왔다”와 “신뢰할 수 있다”를 같은 뜻으로 보지 않습니다. OP-TEE는 크기·범위·세션 등의 조건을 검증해야 합니다. 커널의 RPC 분류 · supplicant 요청과 응답 · OP-TEE 메시지 처리
실패 코드도 세 층으로 나눕니다
| 결과 | 예 | 확인할 곳 |
|---|---|---|
| Linux ioctl의 오류 | 유효하지 않은 사용자 버퍼·세션, 복사 실패 | 시스템 호출 반환값과 errno |
| SMC/FF-A 전달 및 실행 제어 결과 | 알 수 없는 호출, 잘못된 주소, 스레드 부족, RPC | SMC res.a0 또는 해당 FF-A 응답 |
| OP-TEE/TA의 처리 결과 | 메시지의 ret와 ret_origin | 드라이버가 사용자 인자로 복사하는 결과 필드 |
OPTEE_SMC_RETURN_OK는 메시지 처리가 끝났다는 의미이며 TA 명령 자체의 성공까지 모두 보장하지 않습니다. 메시지의 ret와 오류가 발생한 층을 나타내는 ret_origin도 확인해야 합니다. 메시지 결과를 사용자 인자로 되돌리는 코드
FF-A 구성에서는 같은 메시지를 다른 방식으로 전달합니다
Linux v6.18.37에는 SMC ABI 구현뿐 아니라 ffa_abi.c도 있습니다. FF-A 구성은 파티션 식별자, FF-A 메시지와 메모리 공유 핸들을 사용합니다. 이 경로에 CALL_WITH_ARG의 x1:x2 물리 주소 표를 그대로 적용하면 틀립니다.
OP-TEE 메시지의 cmd·session·params라는 상위 의미는 함께 읽을 수 있지만, Secure World로 들어가는 중간 구성 요소와 메모리 등록·공유 방법은 선택한 FF-A/SPMC 배치에 맞춰 확인해야 합니다. 전통적인 opteed dispatcher가 반드시 같은 위치에 있다고 가정하지 않습니다. FF-A 전송 구현
기준 소스와 확인 범위
각 코드의 링크는 위 버전의 고정 커밋을 가리킵니다. 프로젝트별 버전을 함께 명시한 것은 비교 기준이며, 이 조합을 특정 보드에서 빌드·부팅해 호환성을 검증했다는 뜻은 아닙니다. 코드는 표시한 범위의 실제 원문이며, 설명 표는 그 범위의 동작을 묶어서 읽도록 작성했습니다.