Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
- PCG scroll: `cargo test --test vdp_pcg_scroll`
- Foundation WAX ローダ(ホスト): `python3 -m unittest discover -s foundation/tests/wax`。testbench での実行は `tools/llvm-src32/test_toolchain.py` の `test_foundation_wax_loader`
- Foundation シェル(testbench、PCG 画面の比較): `python3 -m unittest discover -s foundation/tests/shell`(`src32_testbench` と Clang が必要)
- Foundation 仮想記憶(`mm` 層。V のある CPU では仮想記憶、`FND_MM=slot` ではスロット): `cd tools/llvm-src32 && python3 -m unittest test_toolchain.ToolchainTests.test_foundation_vm_kernel`。シェルのテストは `python3 -m unittest discover -s foundation/tests/shell` と `FND_MM=slot python3 -m unittest discover -s foundation/tests/shell` の両方。カーネルがユーザーアドレスを直接参照せず `mm_copy_*` を使う契約は MEMORY.md を参照
- Foundation 仮想記憶(`mm` 層。V のある CPU では仮想記憶、`FND_MM=nommu` ではスロット): `cd tools/llvm-src32 && python3 -m unittest test_toolchain.ToolchainTests.test_foundation_vm_kernel`。シェルのテストは `python3 -m unittest discover -s foundation/tests/shell` と `FND_MM=nommu python3 -m unittest discover -s foundation/tests/shell` の両方。カーネルがユーザーアドレスを直接参照せず `mm_copy_*` を使う契約は MEMORY.md を参照
- Foundation CPU 統計(ホスト、カウンタ wrap と user/kernel/idle の帰属): `python3 -m unittest discover -s foundation/tests/cpu`(ホスト C コンパイラが必要)
- Foundation ディスク起動(BIOS → stage1 → FNDBOOT、testbench): `python3 -m unittest discover -s foundation/tests/disk`(`src32_testbench` と Clang が必要)
- FS2 ホストツール: `python3 -m unittest discover -s tools/fs2`
Expand Down
2 changes: 1 addition & 1 deletion doc/foundation_spawn_profile.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ VM では静的バッファ増加分の物理ページも消費する。

- `python -m unittest discover -s foundation/tests/disk_cache -v`: 1 test / 7シナリオ通過。
- `python -m unittest discover -s foundation/tests/shell -v`: VMで24件通過。
- 同じシェルテストを `FND_MM=slot` で実行: 24件通過。
- 同じシェルテストを `FND_MM=nommu` で実行: 24件通過。
- `python -m unittest discover -s foundation/tests/disk -v`: 7件通過(BIOS→stage1→kernel→shellを含む)。
- 計測用イメージの cached/VM、pipeline/VM、cached/slot で両echoの正常終了とR1=42停止を確認。
- `git diff --check` と変更したPythonの `py_compile` 通過。
Expand Down
14 changes: 12 additions & 2 deletions doc/foundation_vm_plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
|---|---|---|
| `mm_hw` | `CPU_FEATURES` に V | ページ表による本物の仮想記憶 |
| `mm_swap` | V なし(新規) | 全プロセスが同じ仮想窓を共有し、切替時にカーネルが像を出し入れする |
| `mm_slot` | V なし(現行) | 物理スロット固定。互換のため当面残す |
| `mm_slot` | V なし(旧) | 物理スロット固定。**2026-10-25 に nommu(アリーナ方式)で置き換えた**(下の「状況」を参照) |

**エミュレーションの限界**: Extension P は「アドレスの許可判定」しかなく、アドレスの変換はできない。U モードの仮想アドレスは常に物理アドレスなので、フォルトで「別の物理ページへ読み替える」ことはできない。したがって実現できる範囲は次のとおり。

Expand Down Expand Up @@ -174,9 +174,19 @@

§7 の手順 3〜4 を実装しました。仕様は `doc/spec_Foundation.md` §5.5、コードは `foundation/kernel/mm.c`/`mm.h` です。

- **mm 層**:`mm_slot` と `mm_vm` は `mm.c` の 2 つの実装で、`mm_init()` が最初の spawn で `CPUID` を見て選びます(`-D FND_MM_SLOT_ONLY` で固定)。カーネルがユーザーの仮想アドレスを直接参照する場所をなくし、`proc_user_range_ok` と `mm_copy_*` に集めました。§8 の確認事項は、ポインタ検証が `proc_user_range_ok`、ユーザーバッファの複写が `ipc.c`・`proc.c`・`blk.c`・`trap.c` の数十か所だったので、そこをすべて置き換えました。
- **mm 層**:`mm_slot`(現在は nommu のアリーナ方式。下の「nommu」参照)と `mm_vm` は `mm.c` の 2 つの実装で、`mm_init()` が最初の spawn で `CPUID` を見て選びます(`-D FND_MM_NOMMU_ONLY` で固定)。カーネルがユーザーの仮想アドレスを直接参照する場所をなくし、`proc_user_range_ok` と `mm_copy_*` に集めました。§8 の確認事項は、ポインタ検証が `proc_user_range_ok`、ユーザーバッファの複写が `ipc.c`・`proc.c`・`blk.c`・`trap.c` の数十か所だったので、そこをすべて置き換えました。
- **決めたこと(§6 の Q)**:Q2 2 段・4 KiB、Q3 領域は使わない、Q4 S は変換しない、Q5 ハードウェア walk、Q7 スワップなし。
- **§10.1 からの変更**:ヒープはページ境界から始め、`mem_grow` はページを足すだけ(領域を使わない)。DMA は `blk_io` だけで、64 KiB のバウンスバッファを使います。
- **仕様案の限界として残したもの**:権限はページ単位です。Foundation のイメージは `--page-align` で W^X を保ちます(`.rodata` の R 専用化は未実装)。MMIO の付与もページ単位で、ページ範囲が届く先の検査を追加しましたが、同じページの別レジスタには触れます。需要ページング、独立 spawn 間の WAL 共有ページ、7 個を超えるプロセスは未実装です。COW と VM 専用の proc_fork は実装済みです(spec_Foundation.md §9.6)。
- **Q9(`sys_info` の能力ビット)**:まだ足していません。`mm_swap` を実装するときに足します。
- **ツールチェーン**:`cpt32_cpu_features()`(`CPUID`)と、`cpt32_mtsr`/`mfsr` で SR `0x40..0x44` が使えます。パイプライン CPU は `CPUID` の暗黙の R1/R2 を interlock しないので、コンパイラは `CPUID` の後に NOP を 3 つ置きます。

## 13. nommu(アリーナ方式)への置き換え(2026-10-25)

V のない CPU の `mm_slot` を、nommu Linux のように**プロセスごとに連続した 1 つのアリーナ**を割り当てる方式に置き換えました。§9 の `mm_swap`(像の出し入れ)は採らず、再配置可能な実行形式で「同じアドレスにリンクされたアプリを同時に動かせない」を解決します。仕様は `doc/spec_Foundation.md` §5.2、画像形式は `doc/spec_WAX_v3.md` §3.1 です。

- 4 KiB ページのビットマップ(`[0x400000, RAM 末尾)`、最大 256 MiB)から、プロセスの全ブロック・WAL・スタック・ヒープ分の連続ページを first fit で取ります。固定アドレスの画像(v2 や `--protected`)は、その範囲を要求して取れなければ `FND_E_ADDRESS_CONFLICT` です。
- Foundation の全プログラムは `--pie`(再配置可能な WAX v3)です。カーネルは試しの基底で配置を計画してから確保し、`wax_rebase` で本番の基底に動かして、relocation table を適用します。
- `mem_grow` は nommu の `brk` と同じで、アリーナを動かせません。ヒープがアリーナの末尾にあり、上のページが空いているときだけ伸びます。大きなヒープが要る画像は `--heap-hint` で最初に求めます。
- 保護は Extension P の 8 領域(MPU)で、切替は従来どおりです。物理メモリを共有しない保証(ゼロ化・プール)もスロットのときと同じです。
- 残る制約:断片化は圧縮(アリーナの移動)で解消できません。プロセスは 7 個までのままです(スロットの数ではなくなったので、増やせます)。
37 changes: 34 additions & 3 deletions doc/ja/spec_WAX_v3.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ translation_of: ../spec_WAX_v3.md
---
# WAX/WAL v3 — CPU 保護とライブラリシンボル

Revision 3.0、2026-10-21。状態: **仕様策定済み・Foundation カーネルが読み込み可能**。
Revision 3.1、2026-10-25。状態: **仕様策定済み・Foundation カーネルが読み込み可能**。
v3 のバイナリ形式と基本 OS ローダー契約を定義します。
「必須」「禁止」は規範要件です。[英語版](../spec_WAX_v3.md)。

Expand Down Expand Up @@ -55,7 +55,7 @@ header は固定 160 byte。空 table でも entry_size は規定値です。
| 4 | 2 | version = 3 |
| 6 | 2 | type: 1 WAX、2 WAL |
| 8 | 2 | arch = 1 (SRC32) |
| 10 | 2 | flags: bit0 DEBUG_PRESENT、bit1 PROTECTED、他は 0 |
| 10 | 2 | flags: bit0 DEBUG_PRESENT、bit1 PROTECTED、bit2 RELOCATABLE(§3.1)、他は 0 |
| 12 | 4 | header_size = 160 |
| 16 | 4 | file_size = 実ファイル長 |
| 20 | 4 | call_abi = 1(§6) |
Expand Down Expand Up @@ -85,7 +85,10 @@ header は固定 160 byte。空 table でも entry_size は規定値です。
| 116 | 4 | os_min_minor |
| 120 | 4 | debug_offset: 不在なら 0 |
| 124 | 4 | debug_size: 不在なら 0 |
| 128 | 32 | reserved |
| 128 | 4 | reloc_table_offset: ファイル先頭からの位置。RELOCATABLE のときだけ非ゼロ |
| 132 | 4 | reloc_count: RELOCATABLE のときだけ非ゼロ |
| 136 | 4 | heap_hint: プログラムが求めるヒープの byte 数(8 の倍数)。無ければ 0。RELOCATABLE のときだけ指定可 |
| 140 | 20 | reserved |

header、各 table、string table、非空 payload、debug のファイル範囲は
相互に重ならず、file_size 内に収まる必要があります。開始 offset はすべて 4 の倍数。
Expand Down Expand Up @@ -139,6 +142,34 @@ WAX entry は 4-byte 整列、先頭命令 4 byte 全体が初期化済み RX
stack top/size は非ゼロの 8 の倍数、減算で underflow せず、image 予約範囲と重複不可。
OS はスタック全体をゼロ化します。WAL の stack/entry フィールドはすべて 0 です。

### 3.1 再配置可能な実行形式

flags の RELOCATABLE を立てた WAX は、nommu システムの FLAT 形式のように、
どのアドレスにでも読み込めます。`base_addr`、block の address、entry、スタックは
**リンク時**の配置で、ローダーは最大 alignment の倍数で、すべての範囲が RAM に収まる
`delta` を選び、image 全体を `base_addr + delta` に置いて relocation table を適用します。
再配置可能にできるのは WAX だけです(WAL は構造上すでに位置独立)。

relocation table は `reloc_table_offset` にある u32 を `reloc_count` 個並べたもので、
address の厳密な昇順です。各エントリは上位 30 bit がリンク時アドレス(4 byte 整列)、
下位 2 bit が種類です。

| 種類 | 意味 |
|---:|---|
| 0 | R/RW block にある 32 bit big-endian のデータ語。`delta` を足す |
| 1 | RX block にある `LDIH rd, hi` とそれに続く `LDIL rd, lo`(rd は同じ)。`hi:lo` の 32 bit 値はリンク時アドレスで、`delta` を足して両方の即値を書き直す |

それ以外の種類は予約で、拒否します。各エントリは、対応する権限の block の
初期化済み領域に完全に収まらなければなりません。entry や image-relative offset、
import slot は配置後の origin からの相対なので、エントリは要りません。
再配置はプロセスの実行前、スタックのゼロ化より前に行います。

再配置可能な WAX のスタックは最下位の block の直下にあり(`user_stack_top == base_addr`)、
予約範囲 `[base_addr - user_stack_size, 最上位 block の終端)` は 1 つの連続領域として
まとめて動きます。ローダーは初期の `R30` に配置後の origin(`base_addr + delta`)を入れ、
位置独立な開始コードが image を見つけられるようにします。ローダーは最上位 block の上に
ヒープ用のゼロ化メモリを足してよい(`heap_hint` を参照)。それは image には含まれません。

## 4. 依存とシンボル

### 4.1 Dependency entry(16 byte)
Expand Down
Loading
Loading