Files
aios/docs/TROUBLESHOOTING.md
2025-07-05 15:00:10 +09:00

6.7 KiB
Raw Permalink Blame History

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

この問題は主にシェル機能とキーボード入力の実装時に発生する。具体的な原因:

  1. ポートI/O競合: PS/2キーボードのポートアクセス0x60, 0x64がbootloaderクレートと競合
  2. メモリアクセス違反: unsafe なポートアクセスがページテーブルの整合性を破壊
  3. 割り込み処理: キーボード割り込みの不適切な処理

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

  1. 基本テスト: スキャンコード表示版でキー入力確認
  2. マッピングテスト: 特定キーa, enter等の動作確認
  3. シェルテスト: コマンド入力・実行の確認

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

  1. 段階的実装

    • 静的表示 → スキャンコード確認 → 完全シェル
  2. デバッグ情報の表示

    • スキャンコードの16進表示
    • ポーリング回数のカウンタ
    • キー受信回数の表示
  3. 安全なポートアクセス

    • options(nomem, nostack, preserves_flags) 使用
    • 適切な遅延の実装
    • エラーハンドリング
  4. テスト環境

    • QEMUの適切な起動オプション
    • フォーカスの確保
    • 段階的な機能テスト