アドレス空間
Rev.1を表示中。最新版はこちら。
メモリマップ アドレス空間 +-------------+ 0x00000000 (3GB) | Process空間 | | プロセス毎 | | | | | | | | | | | | | | | | | | | +-------------+ | Kernel空間 | 0xc0000000 (high_memoryまで896MB) | | 物理ページ0以降へ順番にストレートマップされる(LowMem) | | 896MB以降の物理メモリはHighMem。 | | | | | | +-------------+ high_memory (0xf8000000) <== __va(highstart_pfn * PAGE_SIZE) | 8MB hole | オーバラン検出用 +-------------+ VMALLOC_START (約112MB) | vmalloc用 | | | +-------------+ VMALLOC_END +-------------+ PKMAP_BASE (PAGE_SIZE*(LAST_PKMAP + 1) 約4MB) CONFIG_HIGHMEM定義時のみ | | 1025 Page 1つのPageTableにはPTEは1024Entry +-------------+ FIXADDR_BOOT_START +-------------+ FIXADDR_START | : | fixed addr領域 ref to include/asm-i386/fixmap.h +-------------+ FIXADDR_TOP (0xfffff000) +-------------+ 0xffffffff Kernel空間がストレートマップ出来るところまではLowMem(896MB) それ以降はHighMemとなる。 1.5GB メモリ実装時 BIOS-provided physical RAM map: BIOS-e820: 0000000000000000 - 000000000009d000 (usable) BIOS-e820: 000000000009d000 - 00000000000a0000 (reserved) BIOS-e820: 00000000000e0000 - 0000000000100000 (reserved) BIOS-e820: 0000000000100000 - 000000005ffd0000 (usable) BIOS-e820: 000000005ffd0000 - 000000005ffde000 (ACPI data) BIOS-e820: 000000005ffde000 - 0000000060000000 (ACPI NVS) BIOS-e820: 00000000ffb80000 - 0000000100000000 (reserved) (gdb) p max_pfn $2 = 393168 <= 4096かけると0x5ffd0000 (gdb) p max_low_pfn $3 = 229376 <= 896MB LowMemの最後のページ番号 (gdb) p highstart_pfn $9 = 229376 (gdb) p highend_pfn $8 = 393168 (gdb) p/x high_memory $5 = 0xf8000000 ----------------------------- HighMemory カーネル空間(0xc0000000〜)からストレートマップされていないメモリ 896MB以降 ユーザ空間へのページの割り当てはGFP_HIGHUSERで積極的にHighMemoryを使用する。 (malloc()した領域もHIGHMEMからとられているっぽい。) ユーザデータは出来るだけHighMemoryに追い出してLowMemoryを空ける。 カーネルデータはLowMemoryに置かれる(カーネル空間がストレートマップされているため) <== 大規模なシステムだとカーネルデータが大きくなり、LowMemoryのサイズがネックになってくる <== PageCache等のカーネルデータもHighMemoryを使えるみたい カーネルがHighMemoryにアクセスする場合はkmap()を使って 一時的にHighMemoryの指定ページをカーネル空間内にマップする。 # 高速版のkmap_atomic()もある。kmap_atomic()ではマップしている間はsleep禁止。 # kmap()ではsleepしてよい。 # # kmap()でマップしたページは PKMAP_BASEからの4MBの領域のどこかにマップされる。 # kmap_atomic()の場合はtypeによって静的に決定される。 # (fixed address領域のFIX_KMAP_BEGINから始まるエリア) kmap(page) pageがHighMemでなければpage_address()で該当仮想アドレスを返す HighMemならkmap_high()->map_new_virtual()でマップ(PTE設定)してアドレスを返す