memory allocator
This commit is contained in:
56
nel_os_bootloader/qemu.log
Normal file
56
nel_os_bootloader/qemu.log
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
CPU Reset (CPU 0)
|
||||||
|
EAX=00000000 EBX=00000000 ECX=00000000 EDX=00000000
|
||||||
|
ESI=00000000 EDI=00000000 EBP=00000000 ESP=00000000
|
||||||
|
EIP=00000000 EFL=00000000 [-------] CPL=0 II=0 A20=0 SMM=0 HLT=0
|
||||||
|
ES =0000 00000000 00000000 00000000
|
||||||
|
CS =0000 00000000 00000000 00000000
|
||||||
|
SS =0000 00000000 00000000 00000000
|
||||||
|
DS =0000 00000000 00000000 00000000
|
||||||
|
FS =0000 00000000 00000000 00000000
|
||||||
|
GS =0000 00000000 00000000 00000000
|
||||||
|
LDT=0000 00000000 00000000 00000000
|
||||||
|
TR =0000 00000000 00000000 00000000
|
||||||
|
GDT= 00000000 00000000
|
||||||
|
IDT= 00000000 00000000
|
||||||
|
CR0=00000000 CR2=00000000 CR3=00000000 CR4=00000000
|
||||||
|
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
|
||||||
|
DR6=0000000000000000 DR7=0000000000000000
|
||||||
|
CCS=00000000 CCD=00000000 CCO=DYNAMIC
|
||||||
|
EFER=0000000000000000
|
||||||
|
FCW=0000 FSW=0000 [ST=0] FTW=ff MXCSR=00000000
|
||||||
|
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
|
||||||
|
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
|
||||||
|
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
|
||||||
|
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
|
||||||
|
XMM00=0000000000000000 0000000000000000 XMM01=0000000000000000 0000000000000000
|
||||||
|
XMM02=0000000000000000 0000000000000000 XMM03=0000000000000000 0000000000000000
|
||||||
|
XMM04=0000000000000000 0000000000000000 XMM05=0000000000000000 0000000000000000
|
||||||
|
XMM06=0000000000000000 0000000000000000 XMM07=0000000000000000 0000000000000000
|
||||||
|
CPU Reset (CPU 0)
|
||||||
|
EAX=00000000 EBX=00000000 ECX=00000000 EDX=00060fb1
|
||||||
|
ESI=00000000 EDI=00000000 EBP=00000000 ESP=00000000
|
||||||
|
EIP=0000fff0 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
|
||||||
|
ES =0000 00000000 0000ffff 00009300
|
||||||
|
CS =f000 ffff0000 0000ffff 00009b00
|
||||||
|
SS =0000 00000000 0000ffff 00009300
|
||||||
|
DS =0000 00000000 0000ffff 00009300
|
||||||
|
FS =0000 00000000 0000ffff 00009300
|
||||||
|
GS =0000 00000000 0000ffff 00009300
|
||||||
|
LDT=0000 00000000 0000ffff 00008200
|
||||||
|
TR =0000 00000000 0000ffff 00008b00
|
||||||
|
GDT= 00000000 0000ffff
|
||||||
|
IDT= 00000000 0000ffff
|
||||||
|
CR0=60000010 CR2=00000000 CR3=00000000 CR4=00000000
|
||||||
|
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
|
||||||
|
DR6=00000000ffff0ff0 DR7=0000000000000400
|
||||||
|
CCS=00000000 CCD=00000000 CCO=DYNAMIC
|
||||||
|
EFER=0000000000000000
|
||||||
|
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
|
||||||
|
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
|
||||||
|
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
|
||||||
|
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
|
||||||
|
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
|
||||||
|
XMM00=0000000000000000 0000000000000000 XMM01=0000000000000000 0000000000000000
|
||||||
|
XMM02=0000000000000000 0000000000000000 XMM03=0000000000000000 0000000000000000
|
||||||
|
XMM04=0000000000000000 0000000000000000 XMM05=0000000000000000 0000000000000000
|
||||||
|
XMM06=0000000000000000 0000000000000000 XMM07=0000000000000000 0000000000000000
|
@ -1,6 +1,8 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
pub mod allocator;
|
pub mod allocator;
|
||||||
pub mod constant;
|
pub mod constant;
|
||||||
pub mod logging;
|
pub mod logging;
|
||||||
@ -8,6 +10,8 @@ pub mod memory;
|
|||||||
pub mod paging;
|
pub mod paging;
|
||||||
pub mod serial;
|
pub mod serial;
|
||||||
|
|
||||||
|
use alloc::vec;
|
||||||
|
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
use core::ptr::addr_of;
|
use core::ptr::addr_of;
|
||||||
@ -17,7 +21,6 @@ use x86_64::{structures::paging::OffsetPageTable, VirtAddr};
|
|||||||
use crate::{
|
use crate::{
|
||||||
constant::{BANNER, KERNEL_STACK_SIZE, PKG_VERSION},
|
constant::{BANNER, KERNEL_STACK_SIZE, PKG_VERSION},
|
||||||
memory::BitmapMemoryTable,
|
memory::BitmapMemoryTable,
|
||||||
paging::get_active_level_4_table,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[repr(C, align(16))]
|
#[repr(C, align(16))]
|
||||||
@ -107,5 +110,9 @@ pub extern "sysv64" fn main(usable_memory: &nel_os_common::memory::UsableMemory)
|
|||||||
|
|
||||||
allocator::init_heap(&mut mapper, &mut bitmap_table).unwrap();
|
allocator::init_heap(&mut mapper, &mut bitmap_table).unwrap();
|
||||||
|
|
||||||
|
let mut test_vec = vec![1, 2, 3, 4, 9];
|
||||||
|
test_vec.push(10);
|
||||||
|
info!("Vector test: {:?}", test_vec);
|
||||||
|
|
||||||
hlt_loop();
|
hlt_loop();
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ pub fn init_page_table(frame_allocator: &mut impl FrameAllocator<Size4KiB>) -> *
|
|||||||
let (lv4_frame, lv4_table) = new_page_table(frame_allocator);
|
let (lv4_frame, lv4_table) = new_page_table(frame_allocator);
|
||||||
let (lv3_frame, lv3_table) = new_page_table(frame_allocator);
|
let (lv3_frame, lv3_table) = new_page_table(frame_allocator);
|
||||||
|
|
||||||
let base_flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::GLOBAL;
|
let base_flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::ACCESSED;
|
||||||
|
|
||||||
let lv4: &mut PageTable = unsafe { &mut *lv4_table };
|
let lv4: &mut PageTable = unsafe { &mut *lv4_table };
|
||||||
|
|
||||||
|
97
nel_os_kernel/triple_fault_fix.md
Normal file
97
nel_os_kernel/triple_fault_fix.md
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
# Triple Fault 修正内容
|
||||||
|
|
||||||
|
## 問題の概要
|
||||||
|
`paging::initialize()`関数を実行するとQEMUがトリプルフォルトで落ちる問題が発生していました。
|
||||||
|
|
||||||
|
## 原因
|
||||||
|
1. **カーネルの仮想アドレスを物理アドレスとして使用**
|
||||||
|
- 静的変数のページテーブルのアドレスをそのまま物理アドレスとして扱っていた
|
||||||
|
- カーネルは0x100000付近の仮想アドレスで動作しているが、これは物理アドレスではない
|
||||||
|
|
||||||
|
2. **物理アドレス0x0の使用**
|
||||||
|
- ビットマップメモリアロケータが最初の1MBを予約していなかった
|
||||||
|
- 物理アドレス0x0にページテーブルを配置しようとしてトリプルフォルト
|
||||||
|
|
||||||
|
3. **不十分なメモリマッピング範囲**
|
||||||
|
- 最初は4GBまでしかマッピングしていなかった
|
||||||
|
- ヒープが5GB付近に配置されたためページフォルトが発生
|
||||||
|
|
||||||
|
## 修正内容
|
||||||
|
|
||||||
|
### 1. ビットマップメモリアロケータの修正 (memory.rs)
|
||||||
|
```rust
|
||||||
|
// 最初の1MB(256ページ)を予約
|
||||||
|
const RESERVED_PAGES: usize = 256; // 1MB / 4KB
|
||||||
|
|
||||||
|
let mut table = Self {
|
||||||
|
used_map,
|
||||||
|
start: RESERVED_PAGES, // 0ではなく256から開始
|
||||||
|
end: usize::MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 最初の1MBを明示的に予約済みとしてマーク
|
||||||
|
for i in 0..RESERVED_PAGES {
|
||||||
|
table.set_frame(i, false);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. ページテーブル初期化の修正 (paging.rs)
|
||||||
|
```rust
|
||||||
|
// 静的変数を削除し、動的に物理メモリを確保
|
||||||
|
pub unsafe fn initialize(bitmap_table: &mut BitmapMemoryTable) -> PhysFrame {
|
||||||
|
let new_frame = unsafe { initialize_identity_mapping(bitmap_table) };
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn initialize_identity_mapping(bitmap_table: &mut BitmapMemoryTable) -> PhysFrame {
|
||||||
|
// 物理フレームを動的に確保
|
||||||
|
let pml4_frame = bitmap_table.allocate_frame().expect("Failed to allocate PML4 frame");
|
||||||
|
let pml4_addr = pml4_frame.start_address().as_u64();
|
||||||
|
let pml4_table = unsafe { &mut *(pml4_addr as *mut PageTable) };
|
||||||
|
*pml4_table = PageTable::new();
|
||||||
|
|
||||||
|
// PDPテーブルも同様に確保
|
||||||
|
let pdp_frame = bitmap_table.allocate_frame().expect("Failed to allocate PDP frame");
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. メモリマッピング範囲の拡張
|
||||||
|
```rust
|
||||||
|
// 4GBから64GBへ拡張
|
||||||
|
// Create identity mapping for first 64GB (64 PDP entries, each covering 1GB)
|
||||||
|
for i in 0..64 {
|
||||||
|
// 各1GBエントリに対してページディレクトリを作成
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. main.rsの修正
|
||||||
|
```rust
|
||||||
|
// bitmap_tableをpaging::initialize()に渡す
|
||||||
|
let mut mapper = {
|
||||||
|
unsafe { paging::initialize(&mut bitmap_table) };
|
||||||
|
let lv4_table = get_active_level_4_table();
|
||||||
|
unsafe { OffsetPageTable::new(lv4_table, VirtAddr::new(0x0)) }
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. unsafe操作の適切な処理
|
||||||
|
```rust
|
||||||
|
// unsafe操作をunsafeブロックで囲む
|
||||||
|
let new_frame = unsafe { initialize_identity_mapping(bitmap_table) };
|
||||||
|
|
||||||
|
// raw constを使用してmutable staticへの参照を作成
|
||||||
|
PML4_TABLE[0].set_frame(phys_frame(&raw const PDP_TABLE), flags);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 結果
|
||||||
|
- 物理メモリアロケータが正しく0x208000から物理フレームを割り当てるようになった
|
||||||
|
- 64GBまでの恒等マッピングにより、5GB付近のヒープアクセスも成功
|
||||||
|
- トリプルフォルトが解消され、カーネルが正常に動作するようになった
|
||||||
|
|
||||||
|
## 学んだこと
|
||||||
|
1. カーネルの仮想アドレスと物理アドレスを区別することの重要性
|
||||||
|
2. 低位メモリ(0-1MB)は予約領域として扱うべき
|
||||||
|
3. ページテーブルのマッピング範囲は使用するメモリ全体をカバーする必要がある
|
||||||
|
4. UEFIは恒等マッピングを提供しているため、物理アドレスへの直接アクセスが可能
|
Reference in New Issue
Block a user