HIC ABI 兼容性规范
本文档定义了HIC系统的ABI(Application Binary Interface)兼容性规范,确保二进制兼容性和跨版本稳定性
一、ABI 设计原则
重要: 关于接口分类和官方接口维护原则的详细信息,请参阅: - 接口分类与维护原则
1.1 核心原则
- 类型稳定: 所有公开类型的布局和大小在ABI版本内不变
- 调用约定: 使用标准平台调用约定
- 对齐要求: 遵循平台默认对齐
- 返回值: 所有函数返回统一的错误码类型
- 参数传递: 使用寄存器传递小参数,栈传递大参数
1.2 版本兼容性
| 版本 | 发布日期 | 兼容性 | 变更 |
|---|---|---|---|
| 1.0 | 2026-02-26 | - | 初始版本 |
二、类型定义规范
2.1 基本类型
所有公开类型必须使用固定大小的整数类型:
typedef u8 u8; /* 8位无符号 */
typedef u16 u16; /* 16位无符号 */
typedef u32 u32; /* 32位无符号 */
typedef u64 u64; /* 64位无符号 */
typedef s8 s8; /* 8位有符号 */
typedef s16 s16; /* 16位有符号 */
typedef s32 s32; /* 32位有符号 */
typedef s64 s64; /* 64位有符号 */
ABI保证: 这些类型的大小和符号性永不改变。
2.2 句柄类型
所有句柄类型使用64位无符号整数:
typedef u64 hic_domain_t; /* 域ID */
typedef u64 hic_cap_t; /* 能力句柄 */
typedef u64 hic_thread_t; /* 线程句柄 */
typedef u64 hic_shmem_t; /* 共享内存句柄 */
ABI保证: - 大小永远64位 - 无效值固定为 ~0ULL (0xFFFFFFFFFFFFFFFF) - 值0永远保留用于特殊用途
2.3 枚举类型
枚举类型使用32位有符号整数:
typedef s32 hic_error_t;
enum {
HIC_OK = 0,
HIC_ERR_INVALID_PARAM = 1,
/* ... */
};
ABI保证: - 枚举值永不改变 - 新枚举值可以添加,但不能删除或重命名 - 枚举类型大小固定为32位
2.4 结构体类型
所有公开结构体必须满足:
- 固定大小: 结构体大小在ABI版本内不变
- 固定对齐: 使用默认对齐,不使用packed
- 填充规则: 遵循平台默认填充规则
- 尾随填充: 确保结构体大小是最大对齐的倍数
示例:
typedef struct {
char name[64]; /* 64字节,偏移0 */
u32 api_version_major; /* 4字节,偏移64 */
u32 api_version_minor; /* 4字节,偏移68 */
u32 api_version_patch; /* 4字节,偏移72 */
u32 syscall_num; /* 4字节,偏移76 */
/* 填充到8字节对齐 */
u32 padding1; /* 4字节,偏移80 */
u64 call_count; /* 8字节,偏移88 */
u64 total_time_ns; /* 8字节,偏移96 */
/* 总大小: 104字节 */
} hic_endpoint_info_t;
ABI保证: - 现有字段永不移动或删除 - 新字段只能添加到结构体末尾 - 字段大小永不改变 - 字段对齐永不改变
三、函数调用约定
3.1 x86-64 (System V AMD64 ABI)
| 参数位置 | 寄存器 | 栈 |
|---|---|---|
| 参数1 | RDI | - |
| 参数2 | RSI | - |
| 参数3 | RDX | - |
| 参数4 | RCX | - |
| 参数5 | R8 | - |
| 参数6 | R9 | - |
| 参数7+ | - | 从右到左压栈 |
返回值: - 整数/指针: RAX - 大结构体: 通过隐藏指针(RDI作为第一个参数)
被调用者保存: - RBX, RBP, R12-R15 - 栈指针(RSP) - 对齐栈(16字节对齐)
调用者保存: - RAX, RCX, RDX, RSI, RDI, R8-R11 - XMM0-XMM15
3.2 ARM64 (AAPCS64)
| 参数位置 | 寄存器 | 栈 |
|---|---|---|
| 参数1 | X0 | - |
| 参数2 | X1 | - |
| 参数3 | X2 | - |
| 参数4 | X3 | - |
| 参数5 | X4 | - |
| 参数6 | X5 | - |
| 参数7 | X6 | - |
| 参数8 | X7 | - |
| 参数9+ | - | 从右到左压栈 |
返回值: - 整数/指针: X0 - 大结构体: 通过隐藏指针(X8作为第一个参数)
被调用者保存: - X19-X29 - SP(栈指针) - 16字节栈对齐
调用者保存: - X0-X18 - V0-V31(浮点/向量)
3.3 RISC-V (RV64I)
| 参数位置 | 寄存器 | 栈 |
|---|---|---|
| 参数1 | a0 (x10) | - |
| 参数2 | a1 (x11) | - |
| 参数3 | a2 (x12) | - |
| 参数4 | a3 (x13) | - |
| 参数5 | a4 (x14) | - |
| 参数6 | a5 (x15) | - |
| 参数7 | a6 (x16) | - |
| 参数8 | a7 (x17) | - |
| 参数9+ | - | 从右到左压栈 |
返回值: - 整数/指针: a0 (x10) - 大结构体: 通过隐藏指针(a0作为第一个参数)
被调用者保存: - s0-s11 (x8-x9, x18-x27) - sp (x2) - 16字节栈对齐
调用者保存: - t0-t6 (x5-x7, x28-x31) - a0-a7 (x10-x17)
四、系统调用接口
4.1 系统调用约定
HIC使用统一的系统调用接口,通过 syscall 指令(x86-64)或 svc 指令(ARM64)进入内核。
x86-64系统调用寄存器约定:
RAX: 系统调用号
RDI: 参数1
RSI: 参数2
RDX: 参数3
RCX: 用户空间返回地址(由syscall自动保存)
R11: RFLAGS(由syscall自动保存)
返回值: - 成功: 0(在RAX中) - 失败: 错误码(在RAX中)
4.2 系统调用号映射
| 系统调用号 | 函数 | 参数 | 返回值 |
|---|---|---|---|
| 0 | SYSCALL_IPC_CALL | endpoint_cap, message | hic_error_t |
| 1 | SYSCALL_CAP_TRANSFER | to_domain, cap | hic_error_t |
| 2 | SYSCALL_CAP_DERIVE | parent, sub_rights, out_cap | hic_error_t |
| 3 | SYSCALL_CAP_REVOKE | cap | hic_error_t |
| 4 | SYSCALL_DOMAIN_CREATE | config, out_domain | hic_error_t |
| 5 | SYSCALL_DOMAIN_DESTROY | domain | hic_error_t |
| 6 | SYSCALL_THREAD_CREATE | domain, config, out_thread | hic_error_t |
| 7 | SYSCALL_THREAD_YIELD | - | hic_error_t |
| 8 | SYSCALL_SHMEM_ALLOC | size, flags, out_shmem | hic_error_t |
| 9 | SYSCALL_SHMEM_MAP | shmem, offset, size, out_addr | hic_error_t |
ABI保证: - 系统调用号永不改变 - 参数类型和顺序永不改变 - 返回值类型永不改变
五、内存布局规范
5.1 共享内存布局
共享内存必须满足:
- 对齐: 起始地址至少8字节对齐
- 大小: 必须是页面大小的倍数(4KB)
- 访问权限: 通过能力系统控制
5.2 域内存布局
每个域的内存布局:
+------------------+ 0x00000000
| 代码段 | 只读,可执行
+------------------+
| 只读数据 | 只读
+------------------+
| 数据段 | 读写
+------------------+
| BSS段 | 读写,零初始化
+------------------+
| 栈 | 读写,向下增长
+------------------+
| 堆 | 读写,向上增长
+------------------+
| 共享内存映射 | 读写,能力控制
+------------------+
| MMIO映射 | 读写,能力控制
+------------------+
| 保留 |
+------------------+
ABI保证: - 内存布局顺序永不改变 - 每个段的起始对齐至少8字节 - 栈向下增长,堆向上增长
六、兼容性检查清单
6.1 类型兼容性
- [ ] 所有公开类型的大小固定
- [ ] 所有枚举值固定
- [ ] 所有结构体字段固定
- [ ] 所有对齐要求固定
6.2 函数兼容性
- [ ] 函数签名不变
- [ ] 参数类型不变
- [ ] 返回值类型不变
- [ ] 调用约定不变
6.3 系统调用兼容性
- [ ] 系统调用号不变
- [ ] 参数顺序不变
- [ ] 返回值约定不变
6.4 内存兼容性
- [ ] 共享内存布局不变
- [ ] 域内存布局不变
- [ ] 对齐要求不变
七、版本演进规则
7.1 官方接口的特殊原则
HIC官方接口遵循以下严格原则:
7.1.1 官方接口的向后兼容保证
绝对禁止的操作(官方接口): - ❌ 永不删除任何公开API、函数、结构体字段或枚举值 - ❌ 永不修改任何公开API的签名、参数类型或返回值类型 - ❌ 永不改变任何公开结构体的字段布局或大小 - ❌ 永不废弃任何现有功能
允许的操作(官方接口): - ✅ 只添加新的公开API - ✅ 只添加新的枚举值 - ✅ 只在结构体末尾添加新字段 - ✅ 只添加新的系统调用
7.1.2 官方接口的版本承诺
主版本(Major): - 主版本号增加仅当必须进行破坏性变更 - 破坏性变更包括:删除API、修改签名、改变结构体布局 - 主版本更新极少发生,必须有重大技术理由 - 必须提供完整的迁移路径和文档 - 维护旧版本至少1个发布周期
次版本(Minor): - 次版本号增加用于添加新功能 - 必须保持所有现有API完全兼容 - 不能修改任何现有API - 新增API不能影响现有功能
补丁版本(Patch): - 补丁版本号增加用于bug修复和优化 - 必须保持完全的二进制兼容性 - 不能改变任何公开接口 - 可以包含性能优化和安全修复
7.1.3 官方接口的扩展规则
系统调用扩展: - 系统调用号只能单调递增 - 已分配的系统调用号永不重用 - 系统调用签名永不改变
服务端点扩展: - 端点ID只能单调递增 - 已分配的端点ID永不重用 - 端点功能永不改变
类型扩展: - 可以在结构体末尾添加新字段 - 不能修改或删除现有字段 - 不能改变字段类型或大小
7.2 第三方接口的版本演进
第三方接口的版本管理由各自开发者决定,但必须遵循以下基本规则:
7.2.1 基本要求
- 必须提供版本号(major.minor.patch)
- 必须提供API文档
- 必须明确兼容性声明
7.2.2 版本变更通知
- 主版本变更必须通知所有用户
- 必须提供迁移指南
- 建议维护旧版本一段时间
7.3 主版本更新(破坏性变更)
主版本号增加(例如:1.0 → 2.0)仅当:
- 删除公开API
- 改变公开API签名
- 改变公开结构体布局
- 改变系统调用约定
必须: - 更新所有客户端 - 提供迁移指南 - 维护旧版本至少1个发布周期
注意: 官方接口极少进行主版本更新。
7.4 次版本更新(向后兼容)
次版本号增加(例如:1.0 → 1.1)可以:
- 添加新的公开API
- 添加新的枚举值
- 在结构体末尾添加新字段
- 添加新的系统调用
必须: - 保持所有现有API不变 - 保持二进制兼容性 - 提供新功能的文档 - 保持二进制兼容性 - 提供新功能的文档
7.3 补丁版本更新(修复)
补丁版本号增加(例如:1.0.0 → 1.0.1)可以:
- 修复bug
- 性能优化
- 文档更新
必须: - 不改变任何公开API - 不改变任何公开结构体 - 保持完全的二进制兼容性
八、实现要求
8.1 编译器兼容性
HIC ABI必须与以下编译器兼容:
- GCC: 7.0+
- Clang: 5.0+
- MSVC: 2017+(仅x86-64)
8.2 链接器兼容性
HIC ABI必须与以下链接器兼容:
- GNU ld: 2.26+
- LLVM lld: 6.0+
- gold: 1.12+
8.3 测试要求
所有ABI变更必须通过以下测试:
- 类型大小测试: 验证所有类型的大小
- 对齐测试: 验证所有类型的对齐
- 调用约定测试: 验证函数调用
- 系统调用测试: 验证系统调用接口
- 跨版本测试: 验证不同版本的兼容性
九、参考文档
附录
A. 类型大小表
| 类型 | 大小 | 对齐 | 平台 |
|---|---|---|---|
u8 | 1字节 | 1字节 | 通用 |
u16 | 2字节 | 2字节 | 通用 |
u32 | 4字节 | 4字节 | 通用 |
u64 | 8字节 | 8字节 | 通用 |
hic_domain_t | 8字节 | 8字节 | 通用 |
hic_cap_t | 8字节 | 8字节 | 通用 |
hic_thread_t | 8字节 | 8字节 | 通用 |
hic_shmem_t | 8字节 | 8字节 | 通用 |
hic_error_t | 4字节 | 4字节 | 通用 |
B. 系统调用开销表
| 操作 | 理论开销 | 实际开销 | 方法 |
|---|---|---|---|
| 系统调用 | 20-30ns | ~25ns | syscall/sysret |
| IPC调用 | 20-30ns | ~25ns | 同级函数调用 |
| 能力检查 | ~50ns | ~50ns | 只读查表 |
C. 对齐要求表
| 类型 | x86-64 | ARM64 | RISC-V |
|---|---|---|---|
u8 | 1字节 | 1字节 | 1字节 |
u16 | 2字节 | 2字节 | 2字节 |
u32 | 4字节 | 4字节 | 4字节 |
u64 | 8字节 | 8字节 | 8字节 |
| 指针 | 8字节 | 8字节 | 8字节 |
| 结构体 | 最大对齐 | 最大对齐 | 最大对齐 |