高通HLOS与TrustZone通信的框架演进(4): MINK微内核与SMCInvoke面向对象的TrustZone通信架构
上一篇:我们已经分析了 QSEECOM 的种种局限。为了解决这些问题,高通设计了全新的 SMCInvoke 框架。本篇将深入 SMCInvoke 的核心——MINK 微内核的 Object-Capability 模型,以及如何将其扩展为跨世界的面向对象通信架构。
1. 从 QSEECOM 到 SMCInvoke:为什么需要重新设计?
前一篇我们详细分析了 QSEECOM 的架构与限制——扁平的请求-响应模型、缺乏对象与能力系统、Client 身份验证不足、共享内存安全风险,以及无法适应 Hypervisor 时代的虚拟化需求。
SMCInvoke 并非简单的 API 升级,而是一次架构层面的范式转变。它的核心思想是:将 HLOS↔TZ 通信建立在面向对象的 Capability 系统之上,使得每一次跨世界调用都具备身份可追溯、权限可控制、接口可定义的安全属性。
SMCInvoke 的理论基础来自 QTEE 中的 MINK 微内核——一个 capability-based 的 IPC 框架。
理解 SMCInvoke,必须先理解 MINK。
2. MINK 微内核简介
MINK(Mini-Kernel)是 QTEE 内部的核心微内核,与传统的宏内核不同,它遵循微内核哲学:
- 内核与域Kernel Domain(特权模式):负责进程、线程、内存管理等最小必要功能
- 用户域User Domain / Process(用户模式):每个 TA 运行在独立的用户态进程中
- 域间通信 通过 Object Invocation 实现,这是 MINK 的核心原语
graph TB
subgraph KD["Kernel Domain(特权模式)"]
MINK["MINK Kernel"]
end
subgraph P1["Process 1(TA-A)"]
O1["Object A1"]
O2["Object A2"]
end
subgraph P2["Process 2(TA-B)"]
O3["Object B1"]
end
subgraph P3["Process 3(TA-C)"]
O4["Object C1"]
end
O1 -- "invoke" --> MINK
MINK -- "dispatch" --> O3
O2 -- "invoke" --> MINK
MINK -- "dispatch" --> O4
O3 -- "invoke" --> MINK
MINK -- "dispatch" --> O2
MINK 多进程 Object Invocation 模型,参考 [4] 80-NH537-4 §3.1-3.5
MINK 类似 L4 或 Mach 的 IPC 机制,但有一个关键区别:消息不发给进程或端口,而是发给具体的 Object。
3. MINK 中的 Object 模型
Object 在 MINK 中是一个简单的 C 结构体:
struct Object {
ObjectInvoke invoke; // 函数指针:对象的 invoke 处理函数
ObjectCxt context; // 上下文指针:传递给 invoke 的第一个参数
};
当一个 Object 被调用时:
int Object_invoke(Object o, ObjectOp op, ObjectArg args[], ObjectCounts k) {
return o.invoke(o.context, op, args, k);
}
参数说明:
op:操作码,标识要调用的方法 ID,由 MINK IDL 自动分配args[]:参数数组,可包含 buffer 参数和 object 参数k:参数计数,通过ObjectCounts_pack(nBufIn, nBufOut, nObjIn, nObjOut)构造
4. MINK 的 IPC 机制与代理链
当 Object 与其调用者位于不同域时,MINK 通过 代理链 实现跨域调用:
graph LR
subgraph "调用者进程"
Caller["Caller"]
OutProxy["Outbound Proxy<br/>(minkIPC)"]
end
subgraph "内核域"
MINK["MINK Kernel"]
InProxy["Inbound Proxy"]
end
subgraph "目标进程"
TargetObj["Target Object"]
end
Caller -- "invoke" --> OutProxy
OutProxy -- "trap 指令" --> MINK
MINK -- "验证 & 调度" --> InProxy
InProxy -- "invoke" --> TargetObj
MINK IPC 代理链:Outbound Proxy → Kernel → Inbound Proxy,参考 [4] 80-NH537-4 §3.5、[2] 80-PF777-58 §5.1.6
调用者进程
→ Outbound Proxy(用户态)
→ trap 指令
→ MINK Kernel(内核域,验证参数)
→ Inbound Proxy(目标进程用户态)
→ Target Object
- Outbound Proxy:所有跨域调用的用户态入口,共享同一个
invoke函数minKIPC,执行 trap 指令 - Inbound Proxy:内核调用用户态进程中的 Object 时,挂起调用线程,唤醒目标进程
- 同域调用:不经过代理,直接调用
这里有三种调用对象:
用户态→内核态(Outbound Proxy):
- 所有 Outbound Proxy 共享同一个 invoke 函数——minkIPC
- minkIPC 执行 trap 指令陷入内核
- 内核验证对象索引和参数后,调用目标 Object 的 invoke 函数
内核态→用户态(Inbound Proxy):
- 内核需要调用用户态进程中的 Object
- Inbound Proxy 挂起调用线程,唤醒目标进程
- 目标进程处理完毕后,唤醒原始调用者
用户态→用户态:
- 链式组合 Outbound + Inbound Proxy,无需特殊代理。
5. Capability(能力)系统
MINK 中的 Object 引用就是 Capability,具有以下安全属性:
| 属性 | 说明 |
|---|---|
| 不可伪造 | 进程只能访问已被授予引用的 Object |
| 即引用即授权 | 持有 Object 引用就拥有调用权 |
| 可传递 | 可通过 invoke 的 Object 参数将引用授予其他域 |
| 不泄漏调用者 | 被调用 Object 无法获知调用者域的属性 |
| 不泄漏被调用者 | 持有引用无法获知 Object 所在进程 |
这比 QSEECOM 中 “任何拥有 /dev/qseecom 权限的进程都可以通信” 的粗粒度控制有了质的提升。
6. 进程模型
MINK 的进程模型有几个重要特征:
- 每个进程有独立的地址空间和对象表——对象表类似于
POSIX的文件描述符表 - 进程是单线程的——没有用户态线程创建 API
- 同步 IPC——调用 invoke 时阻塞,直到被调用方返回
- 进程终止安全:若被调用进程异常终止,invoke 立即返回
Object_ERROR_DEFUNCT
7. SMCInvoke 分层架构全景
7.1 分层架构

SMCInvoke 将 MINK 的 Object Invocation 机制扩展到 HLOS ↔ TZ 跨世界通信场景,并在中间加入了 Hypervisor 层的安全审查。
graph TB
subgraph "HLOS Userspace (System)"
JavaApp["3rd Party Java App"]
MinkSocket["mink-socket-jni.aar"]
end
subgraph "HLOS Userspace (Vendor)"
SMCClient["SMCInvoke Client<br/>(Native App)"]
QSEEComClient["QSEECom Compact Client"]
SSGTZD["SSGTZD Daemon"]
LibMink["libminkdescriptor.so"]
QSEEComCompact["libQSEEComCompact.so"]
end
subgraph "HLOS Kernel"
SMCDrv["SMCInvoke Driver<br/>(/dev/smcinvoke)"]
end
subgraph "EL2 - Hypervisor"
HypRouter["Hyp Invoke Router"]
end
subgraph "Secure World - TZ"
TZRouter["TZ Invoke Router"]
IClientEnv["IClientEnv"]
IAppLoader["IAppLoader"]
TA["Trusted Application"]
end
JavaApp - "AIDL / Socket" --- SSGTZD
SMCClient -- "libminkdescriptor" --- SMCDrv
QSEEComClient -- "libQSEEComCompact" --- SMCDrv
SSGTZD -- "libminkdescriptor" --- SMCDrv
SMCDrv -- "SMC" --- HypRouter
HypRouter -- "验证 & 转发" --- TZRouter
TZRouter -- "调度" --- IClientEnv
IClientEnv -- "open" --- IAppLoader
IAppLoader -- "load" --- TA
图:SMCInvoke 分层架构(参考 [3]80-16234-1 §2、[1]80-PK177-40 § SMCInvoke)
分层列表:
- HLOS Userspace(System):Java App +
mink-socket-jni.aar - HLOS Userspace(Vendor):Native SMCInvoke Client、SSGTZD 守护进程、
libminkdescriptor.so - HLOS Kernel:SMCInvoke Driver(
/dev/smcinvoke) - EL2 Hypervisor:Hyp Invoke Router(验证参数、翻译地址、隔离 VM)
- Secure World:TZ Invoke Router、IClientEnv、IAppLoader、TA
7.2 数据流:一次完整的 Invoke
sequenceDiagram
participant CA as HLOS Client<br/>(Native App)
participant Lib as libminkdescriptor.so
participant Drv as SMCInvoke Driver<br/>(Kernel)
participant Hyp as Hyp Invoke Router<br/>(EL2)
participant TZR as TZ Invoke Router
participant TZObj as TZ Object<br/>(TA)
CA->>Lib: Object_invoke(obj, op, args, counts)
Lib->>Drv: ioctl(SMCINVOKE_IOCTL_INVOKE_REQ)
Drv->>Drv: 构建 SMC 命令记录
Drv->>Hyp: SMC 调用
Hyp->>Hyp: 验证参数、翻译地址
Hyp->>TZR: 转发到 TZ
TZR->>TZR: 验证、翻译、加锁
TZR->>TZObj: 调用目标 Object 的 invoke
TZObj-->>TZR: 返回结果
TZR-->>Hyp: 返回
Hyp-->>Drv: 返回
Drv-->>Lib: ioctl 返回
Lib-->>CA: Object_invoke 返回值
图:SMCInvoke 完整 Invoke 数据流(参考 [3]80-16234-1 §2、[1]80-PK177-40 § SMCInvoke)
7.3 各层职责
| 层次 | 组件 | 核心职责 |
|---|---|---|
| HLOS Userspace | Native Client / Java App | 业务逻辑,调用 MINK Object |
| HLOS Userspace | libminkdescriptor.so | 用户态→内核态的桥接库 |
| HLOS Userspace | SSGTZD | 守护进程,为 Java 层提供 TZ 连接 |
| HLOS Userspace | libQSEEComCompat.so | QSEECom 兼容层,旧客户端迁移用 |
| HLOS Kernel | SMCInvoke Driver | 接收 ioctl,构建 SMC 命令记录 |
| EL2 | Hyp Invoke Router | 验证 SMC 参数、翻译地址、隔离 VM |
| Secure World | TZ Invoke Router | 验证、翻译、加锁,调度到目标 Object |
8. 三类核心对象
8.1 Remote Object(远程对象)
- 归属:TZ 侧
- HLOS 持有:代理引用(Outbound Proxy)
- 用途:HLOS 调用 TZ 侧的服务
- 示例:
IAppLoader、IClientEnv、TA 暴露的app_getAppObject()返回的对象
8.2 Callback Object(回调对象)
- 归属:HLOS 侧
- TZ 持有:代理引用(Inbound Proxy)
- 用途:TZ 主动调用 HLOS 侧的服务,替代 QSEECOM 的 Listener
- 优势:轻量级,不需要注册独立阻塞线程,由 SMCInvoke Driver 的回调机制自动处理
8.3 Memory Object(内存对象)
- 归属:HLOS 侧
- 用途:高效共享大块缓冲区(类似 ION fd 但更安全)
- 特点:TZ 侧直接访问 HLOS 的内存区域,但通过 Object Capability 控制访问范围,不能随意读写任意地址
graph LR
subgraph "HLOS"
CA["Client App"]
CB["Callback Object"]
MO["Memory Object"]
end
subgraph "TZ"
RO["Remote Object<br/>(IAppLoader, TA...)"]
TA["TA"]
end
CA -- "invoke Remote Obj" --> RO
RO -- "invoke Callback Obj" --> CB
MO -- "共享缓冲区" --> TA
TA -- "读写" --> MO
SMCInvoke 三类对象及其归属关系,参考 [3] 80-16234-1 §5、[4] 80-NH537-4 §3.4-3.6
9. SMCInvoke Driver 与 ioctl 接口
SMCInvoke Driver 暴露 /dev/smcinvoke,主要 ioctl 命令:
| IOCTL | 功能 |
|---|---|
SMCINVOKE_IOCTL_INVOKE_REQ |
发起 Object Invoke 请求 |
SMCINVOKE_IOCTL_ACCEPT_REQ |
接受来自 TZ 的回调请求 |
SMCINVOKE_IOCTL_SERVER_REQ |
处理 TZ 发起的回调 |
SMCINVOKE_IOCTL_ACK_LOCAL_OBJ |
确认本地对象引用 |
源码位置:kernel/drivers/soc/qcom/smcinvoke.c
10. Callback Object 取代 Listener 的流程
sequenceDiagram
participant CA as HLOS Client
participant Drv as SMCInvoke Driver
participant TZ as TZ / TA
CA->>Drv: INVOKE_REQ (携带 Callback Obj)
Drv->>TZ: SMC 转发
TZ->>TZ: 处理中...需要 HLOS 服务
TZ->>Drv: 回调 Callback Obj (SMC)
Drv->>CA: ACCEPT_REQ (回调请求)
CA->>CA: 执行回调逻辑
CA->>Drv: SERVER_REQ (回调响应)
Drv->>TZ: SMC 转发回调结果
TZ-->>Drv: 原始 invoke 返回
Drv-->>CA: INVOKE_REQ 返回
Callback Object 取代 Listener 的回调流程,参考 [3] 80-16234-1 §4.5、[1] 80-PK177-40 §SMCInvoke
- HLOS Client 在 invoke TA 时,将一个 Callback Object 作为输入参数传递给 TZ
- TZ 在需要 HLOS 服务时,通过标准的
Object_invoke调用该 Callback Object - SMCInvoke Driver 自动处理回调路由(
ACCEPT_REQ和SERVER_REQioctl) - HLOS 侧执行回调逻辑,结果通过 Driver 返回给 TZ
这种模型比 Listener 更轻量、更易于管理多个并发回调。
11. MINK IDL:接口定义语言
QSEECOM 的最大问题之一是缺少 IDL。MINK IDL 提供轻量级接口描述,自动生成 stub 和 skeleton。
IDL 类型系统:
| 类型分类 | 类型说明 |
|---|---|
| 数值类型 | int8/16/32/64, uint8/16/32/64, float32/64,小端字节序 |
| 缓冲区 | buffer 变长字节序列 |
| 对象引用 | interface MINK Object 引用 |
| 数组 | TYPE[] 固定大小成员的有序集合 |
| 结构体 | struct NAME { ... } 固定大小成员组合 |
| 接口 | interface NAME { method; error; } 定义方法集合 |
IDL 示例:
interface ISMCIEExample : IUnknown {
method sayHello(int32 count, buffer name, buffer out greeting);
method add(int32 a, int32 b, int32 out result);
method getCounter(int32 out value);
error helloFailed;
error addOverflow;
};
Bundling 优化:MINK IDL 自动将多个小型固定大小参数(≤16 字节)打包到一个 buffer 中,减少 invoke 参数数量,降低跨域通信开销。
// 假设方法有 3 个小型输入参数(各 4 字节):
method foo(int32 a, int32 b, int32 c, buffer data);
// 自动 Bundling:
// args[0] = input buffer: {int32 a, int32 b, int32 c} ← 打包在一起
// args[1] = input buffer: data ← 单独传递
12. 一次完整的 SMCInvoke 调用数据流
HLOS Client (Native App)
| Object_invoke(obj, op, args, counts)
v
libminkdescriptor.so
| ioctl(SMCINVOKE_IOCTL_INVOKE_REQ)
v
SMCInvoke Driver (kernel)
| 构建 SMC 命令记录
| SMC 调用
v
Hyp Invoke Router (EL2)
| 验证参数、翻译地址
v
TZ Invoke Router
| 验证、翻译、加锁
| 调用目标 Object 的 invoke
v
TZ Object (TA)
| 处理业务逻辑
| 返回结果
v 原路返回
SMCInvoke 的架构从根本上解决了 QSEECOM 的诸多局限,将通信模型从 “数据通道” 升级为 “面向对象的能力系统”。
→ 下一篇
了解了 SMCInvoke 的架构后,我们需要从开发者和系统集成者的角度进行最终对比:两个框架在接口、安全模型、迁移成本等方面究竟有何具体差异?高通提供了怎样的兼容层来帮助现有 QSEECOM 客户端平滑迁移?下一篇将给出完整的对比表和迁移指南。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)