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
10 changes: 8 additions & 2 deletions doc/spec_Foundation.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,8 @@ S モードの R30 は、常にスタブのアドレスでなければなりま
- 2 = CPU 統計。16 bytes のヘッダ(`elapsed_cycles`、`kernel_cycles`、`idle_cycles`、`clock_hz`)に、プロセスごとの 8 bytes(`pid`、`user_cycles`)が続きます。すべて u32、カウンタは 2^32 で wrap します。レコード順は sel 1 と同じで、終了記録も含み、再利用時は新 PID のカウンタを 0 にします。PeC timer ch1 を IRQ なしの 48 MHz free-running clock としてカーネルが予約します。スケジューラの起動時から計測し、HALT 中の経過も idle に含みます。使用率はスナップショット間の符号なし差分で計算し、間隔は約89秒未満とします。
- `kernel_cycles` は C の trap ハンドラ入口から scheduler 終了までの概算です。アセンブリの context save/restore と C 計測関数の境界外の命令は、前後の user/idle に含まれます。厳密な OS オーバーヘッドとは一致しません。`user_cycles` はプロセスの全スレッドの合計、syscall 処理時間は kernel 側です。ch1 による計測自体の実行コストもあります。
- 3 = `fnd_meminfo`(16 bytes)。順に `ram_bytes`、`vram_bytes`、`pcmram_bytes`、予約(0)。ハードウェアの実装容量で、BMC のメモリ容量レジスタ([BMC §1.5](spec_BMC_DMAC.md))の値です。`ram_bytes` は sel 0 と同じ(容量不明なら 16 MiB)。`vram_bytes` と `pcmram_bytes` は BMC の値そのままで、0 は容量不明を表します
- 4 = 呼び出したプロセス自身の `pid` と `parent`(8 bytes、u32 が 2 つ)。POSIX の `getpid`/`getppid` 用
- 5 = PROCESS ハンドルの pid。ハンドル番号を `buf` に渡し(メモリは使わない。`cap` は無視)、結果が pid です。ハンドルが PROCESS でなければ `FND_E_BAD_HANDLE`。`proc_fork` や `proc_spawn` が返したハンドルから子の pid を知るのに使う
- その他は `FND_E_BAD_ARG`

### 9.1 ケーパビリティ
Expand Down Expand Up @@ -396,13 +398,15 @@ S モードの R30 は、常にスタブのアドレスでなければなりま
| Off | 名前 | 意味 |
|---:|---|---|
| 0 | magic | `0x464E4453`(`FNDS`) |
| 4 | version | 1 |
| 4 | version | 2(1 は env_count、env_off を欠く。読み手は 0 として扱う) |
| 8 | size | ブロック全体の byte 数 |
| 12 | argc | 引数の数 |
| 16 | argv_off | argc 個の u32 オフセットの配列(ブロック先頭から) |
| 20 | cwd_off | カレントディレクトリ(絶対パス)の位置 |
| 24 | role_count | 役割表の件数 |
| 28 | roles_off | `(role, handle)` の組の配列 |
| 32 | env_count | 環境変数の数(version 2) |
| 36 | env_off | env_count 個の u32 オフセットの配列。指す先は `NAME=value`(version 2) |

- 文字列は NUL で終わります。
- role の値:1 `STDIN`、2 `STDOUT`、3 `STDERR`、4 `FS`(fs への CHANNEL)、5 `CONSOLE`。
Expand All @@ -423,7 +427,7 @@ CPU が Extension V を報告するとき(`CPU_FEATURES` bit 9)、カーネ
- **`blk_io`**(§10.4):DMA は変換されないので、転送はカーネルのバッファを経由し、完了後に複写します。
- **フォールトと COW**:`proc_fork`(§9.6)で共有した書き込み可能ページは、PTE の W を落として SW bit 9(COW)を立てます(SW bit 8 は所有フレーム)。書き込み保護フォールト `0x8006000A` が COW ページを指す場合、共有中なら新しいフレームへ 4 KiB をコピーし、最後の所有者ならコピーせず W を復元します。TLB を消去して同じ EPC の命令を再実行します。真の読み取り専用ページや未マップページへのアクセス、COW 解決のメモリ不足を含む、ほかの U モードフォールトはプロセスを終了します。終了コードは CAUSE です。需要ページングはないので、ページは `proc_spawn` と `mem_grow` が先にすべてマップします。
- **`sys_info`**:sel 0 の `free_bytes` は未使用の物理フレームの合計、sel 1 のプロセスごとのメモリはマップされた所有フレーム(ページ表を除く)の合計です。共有フレームは各プロセスの値に含まれるため、プロセスの値の合計は物理使用量と一致しません。
- **限界**:プロセスは 7 個、スレッドは 8 個までのままです(§9)。
- **限界**:プロセスは 10 個、スレッドは 16 個までです。pipe サービスが 1 つ使います。

### 9.4 終了と後始末

Expand Down Expand Up @@ -602,6 +606,8 @@ stage1 は、`kernel_load` = `0x00010000`、`kernel_size` ≤ `0xE0000`(§5.1

カーネルは同梱モジュールを表の順に spawn します。各モジュールには、argv = [name]、cwd = `/`、役割表なしの起動ブロックを与えます。表の最後は init でなければなりません。すべて spawn し終えたら、staging 領域を解放します。

標準の構成は console、disk、fs、pipe([API §9.5](spec_Foundation_API.md))、init の順です。

## 12. C からの利用

- ABI ヘッダ `foundation/include/foundation/{abi.h,errors.h,ipc.h}` に、本書の番号と構造体を定義します。
Expand Down
31 changes: 25 additions & 6 deletions doc/spec_Foundation_API.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Revision 0.1、2026-10-24。Status: **ドラフト(主要な設計判断は確
|---|---|
| プロトコル | [Foundation §8](spec_Foundation.md) の IPC(`fnd_msg`、`ipc_call`、ハンドル転送)の上に載る、サービスとクライアントの約束 |
| サービス | fs(`svc_lookup("fs")`)、console(`svc_lookup("console")`)、デバイスサービス |
| ライブラリ | libfnd(`foundation/lib/fnd`、C11、WAL `fnd` 1.2 または静的リンク) |
| ライブラリ | libfnd(`foundation/lib/fnd`、C11、WAL `fnd` 1.3 または静的リンク) |
| ヘッダ | `foundation/include/foundation/{fnd.h,api.h}`。`api.h` は本書の番号と構造体、`fnd.h` は libfnd の関数 |

本書が定めないもの:
Expand Down Expand Up @@ -45,6 +45,7 @@ Revision 0.1、2026-10-24。Status: **ドラフト(主要な設計判断は確
| `0x0100–0x01FF` | fs セッション操作(§6) |
| `0x0200–0x02FF` | ディレクトリ操作(§7) |
| `0x0300–0x03FF` | デバイスサービスの操作(§9) |
| `0x0400–0x04FF` | pipe サービスの操作(§9.5) |
| `0x1000–0x10FF` | コンソール操作(§8) |
| `0x1100–0x11FF` | VDPビットマップ/CLUT操作(§9.1) |
| `0x1200–0x12FF` | SGC 状態・出力GP・リセット操作(§9.3) |
Expand Down Expand Up @@ -80,7 +81,7 @@ Revision 0.1、2026-10-24。Status: **ドラフト(主要な設計判断は確
| オブジェクト | 作る操作 | 使える操作 |
|---|---|---|
| fs セッション | `svc_lookup("fs")`、`FS_SESSION_NEW` | §6 |
| ストリーム | `FS_OPEN`、`DEV_OPEN`(ファイル、コンソール、デバイス) | §5。コンソールなら §8 も |
| ストリーム | `FS_OPEN`、`DEV_OPEN`(ファイル、コンソール、デバイス)、`PIPE_OPEN`(pipe の両端) | §5。コンソールなら §8 も |
| ディレクトリ | `FS_DIR_OPEN` | §7 |

- 開いたファイル 1 つが 1 つの CHANNEL です。libfnd のファイルハンドルは、カーネルのハンドル番号そのものです(実装案 §4.4 の「別の名前空間」という案は採らない)。
Expand Down Expand Up @@ -454,13 +455,28 @@ C API は `<foundation/sgc.h>` の `fnd_sgc_get_status`、`fnd_sgc_set_output`
- `ST_STAT` は DEVICE、上表の mode、UID 0、size 0 を返します。乱数デバイスの flags は READ_ONLY、UART は 0 です。`ST_SYNC` は成功する no-op、seek/truncate/その他の操作は UNSUPPORTED。権限のない read/write は ACCESS です。ユーザーバッファは IPC の検証後に `mm_copy_*` でコピーします。
- C アプリは既存の `fnd_file_open`、`fnd_read`、`fnd_write`、`fnd_close` を使えます。たとえば `fnd_file_open("/dev/prng", FND_OPEN_READ, FND_MODE_DEFAULT, &h)` で開いて任意長を読み出せます。

### 9.5 pipe サービス `pipe`

名前なしの pipe(POSIX の `pipe(2)`)のためのサービスです。`svc_lookup("pipe")` で得た CHANNEL は `PIPE_OPEN` だけを受け付けます。pipe の両端は、サービスの PORT から作った CHANNEL 1 本ずつで、badge で端を区別します。端のハンドルは `dup`・`XFER_HANDLE`・`proc_fork` で増やせます。端の最後のハンドルが閉じる(`CLIENT_GONE`)と、その端が閉じたことになります。

| op | 名前 | 要求 | 応答 |
|---|---|---|---|
| `0x0400` | `PIPE_OPEN` | `a0` = 0: 新しい pipe を作る。1: `a1` = pipe の id の書き端を付ける | `a0` = pipe の id、`a3` = 端のストリーム(`XFER_HANDLE`)。作る呼び出しは読み端を返す |

- 書き端は pipe ごとに 1 回だけ付けられます(付け済みなら `FND_E_NOT_FOUND`)。読み端と書き端の両方が閉じると pipe は消えます。
- 端のストリームは §5 のうち `ST_READ`(読み端)、`ST_WRITE`(書き端)、`ST_STAT`(`type` = 5 PIPE)、`ST_SYNC`(何もしない)を受け付けます。`ST_SEEK` と `ST_TRUNCATE` は `FND_E_UNSUPPORTED`、向きが違う端への読み書きは `FND_E_ACCESS` です。
- `ST_READ` はデータが届くまで待ち、届いた分(最大 `a0`)を返します。書き端がすべて閉じていてデータがなければ、長さ 0(EOF)を返します。
- `ST_WRITE`(4096 bytes まで)は、全体が入る空きができるまで待ち、まとめて書きます(原子的)。読み端がすべて閉じていれば `FND_E_PEER_GONE` です。待っている要求は端が閉じたときに答えます。
- 容量は 1 つの pipe につき 4096 bytes、同時に待てる要求は 32 件、pipe は 32 本です。超えると `FND_E_LIMIT` です。
- サービスはどのバックエンドでも起動します。ただし `fork` で端を共有できるのは VM だけです(`proc_fork` が VM 専用のため)。

## 10. 構造体

### 10.1 `fnd_stat`(64 bytes)

| Off | 名前 | 意味 |
|---:|---|---|
| 0 | `type` | 1 FILE、2 DIR、3 DEVICE、4 CONSOLE |
| 0 | `type` | 1 FILE、2 DIR、3 DEVICE、4 CONSOLE、5 PIPE |
| 4 | `mode` | FS2 §8 の mode |
| 8 | `uid` | 所有者 |
| 12 | `flags` | bit 0 `READ_ONLY`(mount か媒体が書き込み禁止)、bit 1 `SEEKABLE`。その他は 0 |
Expand Down Expand Up @@ -602,7 +618,8 @@ typedef struct {
const char *const *argv; /* argv[0] を含む */
const char *cwd; /* NULL なら現在の cwd */
fnd_handle std_in, std_out, std_err; /* 0 なら自分のものを渡す */
uint32_t flags; /* 予約。0 */
uint32_t flags; /* FND_EXEC_KEEP_ARGV0(1): argv[0] を置き換えずそのまま渡す。他は予約。0 */
const char *const *envp; /* NULL 終端の "NAME=value"。NULL なら空の環境 */
} fnd_exec_t;

fnd_status fnd_proc_exec(const char *path, const fnd_exec_t *ex, fnd_handle *proc);
Expand All @@ -613,9 +630,11 @@ fnd_status fnd_proc_kill(fnd_handle proc);

`fnd_proc_fork()` は WAL `fnd` 1.2 の追加 API です。カーネルの `proc_fork` を呼び、親に子の PROCESS ハンドル、子に 0、失敗時に負のエラーを返します。VM・単一スレッドなどの制約は [カーネル仕様 §9.6](spec_Foundation.md) を参照してください。ハンドルが指すファイル位置・fs セッション・cwd などのサービス側状態は親子で共有します。

環境変数は `WAL fnd 1.3` で加わりました。`fnd_envc()` と `fnd_env(i)` が、起動ブロック([Foundation §9.3](spec_Foundation.md)、version 2)の環境を返します。子へは `fnd_exec_t.envp` で渡し、`fork` した子は環境をメモリごと引き継ぎます。環境と引数は合わせて起動ブロックの 4096 bytes に収まらなければならず、環境は 128 件までです。

`fnd_proc_exec` は次の手順で起動します。

1. `path` を `EXEC` で開き(X 権限の検査)、全体を `fnd_mem_alloc` の領域に読み込んで閉じる。大きさの上限は `FND_EXEC_IMAGE_MAX`(1 MiB)で、超えれば `FND_E_LIMIT`。
1. `path` を `EXEC` で開き(X 権限の検査)、全体を `fnd_mem_alloc` の領域に読み込んで閉じる。大きさの上限は `FND_EXEC_IMAGE_MAX`(1.5 MiB。カーネルの `FND_SPAWN_IMAGE_MAX` も同じ)で、超えれば `FND_E_LIMIT`。
2. `FS_SESSION_NEW` で子のための fs セッションを作る。
3. 起動ブロックを作る。cwd は `ex->cwd`、なければ `fnd_cwd_get` の値。役割表は 1 `STDIN`、2 `STDOUT`、3 `STDERR`、4 `FS`、5 `CONSOLE` で、`handles` にこの順に並べる(CONSOLE の役割がなければ 5 は省く)。
4. イメージが依存を持つ WAX v3 なら、依存する WAL を集める([Foundation §9.5](spec_Foundation.md))。依存表の各 `(library_id, abi_major)` について `/lib/<library_id>.<abi_major>.wal` を `EXEC` で開いて読み込み、その WAL の依存表も同じようにたどる。同じ ID と major は 1 回だけ読む。ファイルがなければ `FND_E_DEPENDENCY`、合計が WAX を含めて 8 個を超えれば `FND_E_LIMIT` で、起動しない。WAL の中身の検証と minor の確認はカーネルが行う。
Expand Down Expand Up @@ -695,7 +714,7 @@ init は、各サービスの起動後にシェルなどのアプリを起動す
| UID の認証 | v1 は全セッション UID 0。カーネル ABI に資格情報を加えてから、`FS_SESSION_NEW` で UID を下げる操作などを定める |
| `DEV_OPEN` の呼び出し元の確認 | v1 では確認できない(§9)。カーネル ABI でサービスにケーパビリティ付きの CHANNEL を渡す方法を決めてから閉じる |
| 時刻の取得 | FS2 §7 の「一貫した時計のスナップショット」が未定義。libfnd の `fnd_time_now` はそれを待つ |
| 大きいイメージの起動 | `FND_EXEC_IMAGE_MAX` は 1 MiB。親のスロットより大きい子は、fs がカーネルへ直接渡す方式(将来)まで起動できない |
| 大きいイメージの起動 | `FND_EXEC_IMAGE_MAX` は 1.5 MiB。親のスロットより大きい子は、fs がカーネルへ直接渡す方式(将来)まで起動できない |
| WAL の一覧 | **決定(2026-10-22)**:`/lib/<image_id>.<abi_major>.wal` に置き、`fnd_proc_exec` が依存をたどって読み、`proc_spawn` の `libs` で渡す(§11.6、[Foundation §9.2・§9.5](spec_Foundation.md)) |
| sol のライブラリ | `sol/foundation/libfnd.sol` と `tools/solc/build_foundation.py` でC操作を利用可能。`examples/foundation-sol` は実FS2で5001 bytesのwrite/read/close、65件の列挙、rewind、ENDと資源解放、子の起動/待機を検証する |
| 64-bit 整数 | `tools/llvm-src32` での `int64_t` の対応を実装時に確認する。使えなければ、libfnd の 64-bit 引数を上位・下位の組に置き換える |
Loading
Loading