Skip to main content

atmos/kernel/
syscall.rs

1//! syscall.rs - System Call Dispatcher (EL0 → EL1)
2//!
3//! SVC #0 命令によるシステムコールを処理します。
4//! レジスタ規約: x8 = システムコール番号, x0〜x5 = 引数, x0 = 戻り値
5//!
6//! # 安定性ポリシー
7//!
8//! アプリケーション (EL0) がどんな引数でシステムコールを発行しても、
9//! カーネルはパニック・クラッシュしてはならない。
10//! - ユーザポインタは必ず [`crate::kernel::usercopy`] の検証関数を通すこと
11//! - 不正な引数はエラー値 (`usize::MAX` または 0) を返して拒否すること
12//! - カーネル内で `unwrap()` / 添字アクセスによるパニックを起こさないこと
13#![allow(dead_code)]
14// EL0 境界モジュール: パニックにつながる操作を deny で強制排除
15#![deny(
16    clippy::unwrap_used,
17    clippy::expect_used,
18    clippy::panic,
19    clippy::indexing_slicing
20)]
21
22/// システムコール番号の定義
23/// プロセスがCPUを自発的に譲渡します。
24pub const SYS_YIELD: usize = 0;
25/// プロセスを終了します。
26pub const SYS_EXIT: usize = 1;
27/// デバッグメッセージを出力します。
28pub const SYS_PRINT: usize = 2;
29/// ファイルを読み込みます。
30pub const SYS_READ_FILE: usize = 3;
31/// ファイルを書き込みます。
32pub const SYS_WRITE_FILE: usize = 4;
33// --- EL0 GUI ウィンドウ ABI (Phase 4) ---
34/// GUIウィンドウを生成します。
35pub const SYS_WIN_CREATE: usize = 5;
36/// GUIウィンドウへビットマップ転送を行います。
37pub const SYS_WIN_BLIT: usize = 6;
38/// GUIウィンドウのイベントをポーリングします。
39pub const SYS_WIN_POLL: usize = 7;
40/// GUIウィンドウを閉じます。
41pub const SYS_WIN_CLOSE: usize = 8;
42
43/// Rustレベルのシステムコールディスパッチャ。
44/// `vector.S` の `svc_handler_entry` から呼び出されます。
45/// 引数はトラップフレームのレジスタ値として渡されます。
46///
47/// # 引数
48/// * `x0` - 第1引数 (システムコールにより内容が異なります)
49/// * `x1` - 第2引数 (システムコールにより内容が異なります)
50/// * `_x2` - 第3引数 (システムコールにより内容が異なります。未使用)
51/// * `syscall_nr` - システムコール番号
52///
53/// # 戻り値
54/// システムコールの戻り値 (x0 レジスタに設定されます)。
55#[no_mangle]
56pub extern "C" fn rust_svc_handler(
57    x0: usize,
58    x1: usize,
59    _x2: usize,
60    syscall_nr: usize, // x3
61) -> usize {
62    match syscall_nr {
63        SYS_YIELD => {
64            // CPUを他のプロセスに譲る
65            crate::kernel::scheduler::yield_now();
66            0
67        }
68        SYS_EXIT => {
69            // プロセスを終了する
70            crate::info!("[SYS] Process exiting (exit code={})", x0);
71            crate::kernel::scheduler::exit();
72            // exit() は ! 型なのでここには到達しない
73        }
74        SYS_PRINT => {
75            // デバッグ出力: x0 = 文字列ポインタ, x1 = 長さ
76            // 事前条件: ポインタがユーザー RAM 領域内・UTF-8・4096 バイト未満
77            match crate::kernel::usercopy::user_str(x0, x1, 4095) {
78                Some(s) => crate::println!("[USER ] {}", s),
79                None => crate::error!("[SYS] sys_print: rejected (ptr=0x{:x}, len={})", x0, x1),
80            }
81            0
82        }
83        SYS_WIN_CREATE => crate::kernel::user_win::sys_win_create(x0),
84        SYS_WIN_BLIT => crate::kernel::user_win::sys_win_blit(x0, x1),
85        SYS_WIN_POLL => crate::kernel::user_win::sys_win_poll(x0, x1),
86        SYS_WIN_CLOSE => crate::kernel::user_win::sys_win_close(x0),
87        SYS_READ_FILE => {
88            // ファイル読み取り: x0 = パスポインタ, x1 = パス長, x2 = バッファポインタ
89            // 将来実装
90            crate::warn!("[SYS] sys_read_file (not yet implemented)");
91            usize::MAX // エラー
92        }
93        SYS_WRITE_FILE => {
94            // ファイル書き込み: x0 = パスポインタ, x1 = パス長, x2 = データポインタ
95            // 将来実装
96            crate::warn!("[SYS] sys_write_file (not yet implemented)");
97            usize::MAX // エラー
98        }
99        _ => {
100            crate::error!(
101                "[SYS] Unknown syscall number {} (x0=0x{:x})",
102                syscall_nr,
103                x0
104            );
105            usize::MAX // エラー
106        }
107    }
108}
109
110/// EL0 (ユーザー空間) からの Data Abort (ページフォルト等) を処理します。
111/// 不正なメモリアクセスを行ったユーザープロセスに対して警告を出力した上で、
112/// 対象プロセスを終了させます。
113///
114/// # 引数
115/// * `far` - 例外発生アドレス (FAR_EL1)
116/// * `esr` - 例外シンドロームレジスタ (ESR_EL1)
117#[no_mangle]
118pub extern "C" fn rust_data_abort_handler(far: usize, esr: usize) {
119    let dfsc = esr & 0x3F; // Data Fault Status Code
120    let wnr = (esr >> 6) & 1; // Write not Read
121
122    crate::error!("[SYS] === DATA ABORT from EL0 ===");
123    crate::error!("[SYS]   FAR_EL1 (fault address): 0x{:016x}", far);
124    crate::error!("[SYS]   ESR_EL1: 0x{:08x}", esr);
125    crate::error!(
126        "[SYS]   DFSC: 0x{:02x}, WnR: {} ({})",
127        dfsc,
128        wnr,
129        if wnr == 1 { "Write" } else { "Read" }
130    );
131
132    if far >= 0x3C00_0000 {
133        crate::error!("[SYS]   -> MMIO region access violation! Killing process.");
134    } else {
135        crate::error!("[SYS]   -> Memory access violation! Killing process.");
136    }
137
138    // 不正アクセスしたプロセスを終了させる
139    crate::kernel::scheduler::exit();
140}
141
142/// EL1(特権モード)動作中の同期例外(カーネルパニック等)をデバッグ出力し、CPUを無限ループ(ハングアップ)させます。
143///
144/// # 引数
145/// * `far` - 例外発生アドレス (FAR_EL1)
146/// * `esr` - 例外シンドロームレジスタ (ESR_EL1)
147/// * `tf` - 退避されたトラップフレームのアドレス
148///
149/// # Safety
150/// `tf` は `vector.S` が構築したトラップフレーム (x0-x30, elr_el1, spsr_el1 の 34 要素以上) を
151/// 正しく指していなければなりません。それ以外の場所から呼び出さないでください。
152#[no_mangle]
153pub unsafe extern "C" fn rust_el1_sync_handler(far: usize, esr: usize, tf: *const usize) {
154    let ec = (esr >> 26) & 0x3F;
155    let iss = esr & 0x1FFFFFF;
156
157    crate::println!("==================================================");
158    crate::println!("!!! KERNEL PANIC: EL1 Synchronous Exception !!!");
159    crate::println!("==================================================");
160    crate::println!("  FAR_EL1 (fault address):  0x{:016x}", far);
161    crate::println!(
162        "  ESR_EL1 (exception reg):  0x{:08x} (EC: 0x{:02x}, ISS: 0x{:06x})",
163        esr,
164        ec,
165        iss
166    );
167
168    // vector.Sの退避順: x0-x30 (31個), elr_el1, spsr_el1
169    // レジスタインデックス: elr=32, spsr=33
170    let elr = *tf.add(32);
171    let spsr = *tf.add(33);
172    crate::println!("  ELR_EL1 (Exception PC):   0x{:016x}", elr);
173    crate::println!("  SPSR_EL1 (saved state):   0x{:08x}", spsr);
174
175    // 汎用レジスタの出力
176    crate::println!("  Registers:");
177    for i in 0..16 {
178        let val1 = *tf.add(i);
179        let val2 = *tf.add(i + 16);
180        if i + 16 < 31 {
181            crate::println!(
182                "    x{:02}: 0x{:016x}    x{:02}: 0x{:016x}",
183                i,
184                val1,
185                i + 16,
186                val2
187            );
188        } else {
189            crate::println!("    x{:02}: 0x{:016x}", i, val1);
190        }
191    }
192
193    loop {
194        unsafe {
195            core::arch::asm!("wfe");
196        }
197    }
198}