64 位元 CPU 上的 ILP32
32 位元指標,加上完整的 64 位元指令集:記憶體最多少 30%,代價是慢幾個百分點。 我們的第一個架構是 AArch64,給已經不支援 32 位元 Arm 的新核心上的嵌入式 Linux 使用。
什麼是 ILP32?
ILP32 程式是 64 位元程式:用的是 64 位元的指令和暫存器,只是記憶體位址(指標)只用 4 bytes 存,不用 8 bytes。
位址變短,資料就變小,程式用的記憶體也跟著變少。代價是每個程式最多只能用 4 GB 記憶體,這對路由器和小板子來說已經足夠。
名稱的意思是 int、long 和指標都是 32 位元;一般的 64 位元 Linux 則是 LP64,long 和指標是 64 位元。
| 32 位元 Arm(armhf) | 一般 64 位元(LP64) | ILP32 | |
|---|---|---|---|
| 指令與暫存器 | 32 位元 | 64 位元 | 64 位元 |
| 位址(指標) | 4 bytes | 8 bytes | 4 bytes |
| 記憶體用量 | 少 | 多 | 少 |
| 新的 Arm 核心能跑嗎 | 不能 | 能 | 能 |
| 每個程式可用記憶體 | 4 GB | 遠大於 4 GB | 4 GB |
為什麼要 ILP32?
嵌入式設備的記憶體預算很緊,常見只有 128–512 MB,DRAM 又一直漲價。過去在 Arm 上省記憶體的選擇是 32 位元 Arm(armhf), 但新的核心(Cortex-A715/A720、Cortex-A520、Cortex-X3 以及之後的核心)已經不能執行 AArch32 程式。 ILP32 保留了省記憶體的好處,又能在這些只支援 AArch64 的核心上執行。
- 指標和資料結構變小:記憶體用得少,快取用得更有效率。
- 保留完整的 64 位元指令集和暫存器(AArch64 有 31 個通用暫存器)。
- kernel 仍是 64 位元,ILP32 和 LP64 程式可以同時執行。
- 64 位元的
time_t:沒有 2038 年問題。
取捨:同樣的編譯方式下,ILP32 比 LP64 慢幾個百分點,部分原因是 32 位元指標的位址運算必須在 4 GiB 回繞, 編譯器有時得多加指令。詳見效能數據。這也不是只有 Arm 的想法:Linux 從 2012 年起就有 x86-64 的 x32, Apple 從 2018 年起在 Apple Watch 上用 arm64_32,RISC-V 的 psABI 也列有實驗性的 RV64ILP32 ABI(架構)。
困境
在 AArch64 上,上游的支援一直在退場:Linux 的 ILP32 ABI 從未合併,glibc 也沒有合併它的 port,GCC 15 把
-mabi=ilp32 列為淘汰,Arm 也從 AArch64 的 ABI 文件中移除了 ILP32。我們把整套元件維持在可用的狀態並一起測試:
kernel、C 函式庫、編譯器、ILP32Wrt 與 Debian 套件,全部使用 64 位元的 time_t。
我們提供什麼
實測
| OpenWrt One(有負載) | LP64 | ILP32 | 差異 |
|---|---|---|---|
| 使用者空間記憶體(PSS) | 38.3 MB | 28.9 MB | -24.6% |
| 可用記憶體 | 863.6 MB | 872.2 MB | +8.6 MB |
| 速度(四項計時,用 GCC 編譯) | 慢 2–11% | ||
同一份原始碼、同樣的套件與 kernel 設定,都用 GCC 14.3 編譯,只差使用者空間的 ABI。 完整結果與量測方法。
現況
- 已在 QEMU(Cortex-A35/A53,以及支援 PAC、BTI、SVE 的
-cpu max)和實機上測試: OpenWrt One 和 Raspberry Pi 3 B+(ILP32Wrt);Raspberry Pi 3 B+、ESPRESSObin、一塊 Cortex-A72 板子和一塊 Cortex-A35 板子(Debian 13)。 - GCC 不支援 ILP32 的返回位址簽章(
pac-ret),加上我們 patch 的 clang 22 可以。 - 尚未移植:LLVM 的 runtime(compiler-rt、libunwind、libc++),以及 Java、Node.js 等語言 runtime。
參與
歡迎到 Discussions 提問、分享想法和你自己板子的測試結果。任何人都可以用自己的名義
把我們的 patch 送進上游(請保留原本的 Signed-off-by),也歡迎有人擔任維護者,包括新的架構。
聯絡:[email protected]。