6.7 KiB
6.7 KiB
Aios Troubleshooting Guide
Common Issues and Solutions
1. Page Table Panic Error (page_table*.rs
)
Problem
QEMUでAiosを実行すると、以下のようなパニックが発生する:
panicked at 'page_table*.rs:105:25'
Root Cause
この問題は主にシェル機能とキーボード入力の実装時に発生する。具体的な原因:
- ポートI/O競合: PS/2キーボードのポートアクセス(0x60, 0x64)がbootloaderクレートと競合
- メモリアクセス違反: unsafe なポートアクセスがページテーブルの整合性を破壊
- 割り込み処理: キーボード割り込みの不適切な処理
Solution Steps
Step 1: 問題の特定
// 危険なポートアクセス例
unsafe fn inb(port: u16) -> u8 {
let result: u8;
core::arch::asm!(
"in al, dx",
out("al") result,
in("dx") port,
);
result
}
Step 2: 安全な実装への移行
// 安全なポートアクセス(遅延付き)
unsafe fn try_inb(port: u16) -> Option<u8> {
// Add delay to avoid rapid polling
for _ in 0..1000 {
core::arch::asm!("nop");
}
let result: u8;
core::arch::asm!(
"in al, dx",
out("al") result,
in("dx") port,
options(nomem, nostack, preserves_flags)
);
Some(result)
}
Step 3: 完全な対策 最終的に、以下の基本的なアプローチで解決:
/// Check if there's data in keyboard buffer
pub fn has_key() -> bool {
unsafe {
let status: u8;
core::arch::asm!(
"in al, 0x64",
out("al") status,
options(nomem, nostack, preserves_flags)
);
(status & 1) != 0
}
}
/// Read raw scancode from keyboard
pub fn read_scancode() -> u8 {
unsafe {
let scancode: u8;
core::arch::asm!(
"in al, 0x60",
out("al") scancode,
options(nomem, nostack, preserves_flags)
);
scancode
}
}
Prevention
options(nomem, nostack, preserves_flags)
を必ず使用- ポーリング頻度を制限(1000サイクル毎など)
- エラーハンドリングの実装
- 段階的テスト(まずデバッグ版で検証)
2. Keyboard Input Not Working
Problem
キーボード入力が QEMU で認識されない問題。
Symptoms
- QEMUは正常に起動する
- 画面表示は正常
- キーを押しても反応しない
- スキャンコードが取得できない
Root Causes
Cause 1: QEMUのフォーカス問題
- QEMUウィンドウにフォーカスがない
- マウスキャプチャが無効
Cause 2: ポーリング頻度の問題
// 問題のあるコード
if counter % 50000 == 0 {
// キーボードチェックの頻度が低すぎ
}
Cause 3: スキャンコードマッピングの不備
// 不完全なマッピング
static SCANCODE_TO_ASCII: [u8; 128] = [
// 配列サイズが127で不一致
];
Solutions
Solution 1: QEMUの正しい起動
# GTK表示でフォーカス確保
qemu-system-x86_64 \
-drive format=raw,file="$BOOT_IMAGE" \
-display gtk
# または、nographic を避ける
qemu-system-x86_64 \
-drive format=raw,file="$BOOT_IMAGE"
Solution 2: 適切なポーリング頻度
loop {
if keyboard_basic::has_key() {
let scancode = keyboard_basic::read_scancode();
// 即座に処理
}
// 軽い遅延のみ
for _ in 0..1000 {
unsafe { core::arch::asm!("nop"); }
}
}
Solution 3: 段階的デバッグ
Phase 1: スキャンコード確認
// デバッグ版でスキャンコードを表示
if keyboard_basic::has_key() {
let scancode = keyboard_basic::read_scancode();
print_hex(scancode); // 16進数で表示
}
Phase 2: キーリリース除外
// キープレスのみ処理(bit 7 = 0)
if (scancode & 0x80) == 0 {
// キープレス処理
}
Phase 3: 完全なマッピング
pub fn scancode_to_char(scancode: u8) -> Option<char> {
match scancode {
0x1E => Some('a'),
0x30 => Some('b'),
// ... 全てのキーをマッピング
0x1C => Some('\n'), // Enter
_ => None,
}
}
Verification Steps
- 基本テスト: スキャンコード表示版でキー入力確認
- マッピングテスト: 特定キー(a, enter等)の動作確認
- シェルテスト: コマンド入力・実行の確認
Working Configuration
最終的に動作した設定:
// keyboard_basic.rs
pub fn has_key() -> bool {
unsafe {
let status: u8;
core::arch::asm!("in al, 0x64", out("al") status, options(nomem, nostack, preserves_flags));
(status & 1) != 0
}
}
// メインループ
loop {
if keyboard_basic::has_key() {
let scancode = keyboard_basic::read_scancode();
if scancode != last_scancode && (scancode & 0x80) == 0 {
if let Some(ch) = keyboard_basic::scancode_to_char(scancode) {
process_char(ch);
}
}
}
// 軽い遅延
for _ in 0..1000 {
unsafe { core::arch::asm!("nop"); }
}
}
3. Build Errors
Type Mismatch in Arrays
// Error: expected array with size 128, found 127
static SCANCODE_TO_ASCII: [u8; 128] = [...]; // 要素が127個
// Solution: 正確な要素数
static SCANCODE_TO_ASCII: [u8; 128] = [
// 128個の要素を確保
0, 27, b'1', ..., 0 // 最後に0で埋める
];
Unused Imports
// Warning: unused import
use core::convert::TryFrom; // 削除
// Warning: unused import
use crate::keyboard; // 使用しない場合は削除
4. QEMU-specific Issues
Display Problems
# 問題: nographic で表示されない
qemu-system-x86_64 -kernel kernel.bin -nographic
# 解決: 標準表示を使用
qemu-system-x86_64 -kernel kernel.bin
Mouse Capture
# QEMUでマウスキャプチャを有効化
Ctrl+Alt+G (toggle mouse capture)
Exit QEMU
# QEMUの終了方法
Ctrl+A, X # または
Alt+F4 # ウィンドウを閉じる
Best Practices
-
段階的実装
- 静的表示 → スキャンコード確認 → 完全シェル
-
デバッグ情報の表示
- スキャンコードの16進表示
- ポーリング回数のカウンタ
- キー受信回数の表示
-
安全なポートアクセス
options(nomem, nostack, preserves_flags)
使用- 適切な遅延の実装
- エラーハンドリング
-
テスト環境
- QEMUの適切な起動オプション
- フォーカスの確保
- 段階的な機能テスト