22#include <stdint.h>
33#include <mem/paging.h>
44#include <mem/map.h>
5+ #include <mem/vmem.h>
56#include <stddef.h>
67#include <console.h>
78#include <interrupt/irq.h>
@@ -20,10 +21,15 @@ static inline void invlpg(void *addr) {
2021void * alloc_page_table (void ) {
2122 void * frame = alloc_frame ();
2223 if (!frame ) return NULL ;
23- // ページテーブルをゼロクリア
24- uint32_t * tbl = (uint32_t * )frame ;
24+ // alloc_frame() は物理フレームの物理アドレスを返す実装の可能性がある。
25+ // 実行環境によらず仮想ポインタを得るため vmem_phys_to_virt を用いる。
26+ uint32_t phys = (uint32_t )(uintptr_t )frame ;
27+ uint32_t virt = vmem_phys_to_virt (phys );
28+ if (virt == 0 ) return NULL ;
29+ uint32_t * tbl = (uint32_t * ) (uintptr_t ) virt ;
2530 for (size_t i = 0 ; i < 1024 ; ++ i ) tbl [i ] = 0 ;
26- return frame ;
31+ // return the virtual pointer for convenience to callers
32+ return (void * )(uintptr_t )virt ;
2733}
2834
2935/**
@@ -39,12 +45,15 @@ int map_page(uint32_t phys, uint32_t virt, uint32_t flags) {
3945 uint32_t pde = page_directory [pd_idx ];
4046 uint32_t * pt ;
4147 if ((pde & PAGING_PRESENT ) == 0 ) {
42- void * new_pt = alloc_page_table ();
43- if (!new_pt ) return -1 ;
44- page_directory [pd_idx ] = ((uint32_t )new_pt ) | (PAGING_PRESENT | PAGING_RW );
45- pt = (uint32_t * )new_pt ;
48+ void * new_pt_virt = alloc_page_table ();
49+ if (!new_pt_virt ) return -1 ;
50+ uint32_t new_pt_phys = vmem_virt_to_phys ((uint32_t )(uintptr_t )new_pt_virt );
51+ page_directory [pd_idx ] = (new_pt_phys & 0xFFFFF000 ) | (PAGING_PRESENT | PAGING_RW );
52+ pt = (uint32_t * )new_pt_virt ;
4653 } else {
47- pt = (uint32_t * )(pde & 0xFFFFF000 );
54+ uint32_t pt_phys = pde & 0xFFFFF000 ;
55+ uint32_t pt_virt = vmem_phys_to_virt (pt_phys );
56+ pt = (uint32_t * )(uintptr_t )pt_virt ;
4857 }
4958
5059 pt [pt_idx ] = (phys & 0xFFFFF000 ) | (flags & 0xFFF );
@@ -64,7 +73,9 @@ int unmap_page(uint32_t virt) {
6473
6574 uint32_t pde = page_directory [pd_idx ];
6675 if ((pde & PAGING_PRESENT ) == 0 ) return -1 ;
67- uint32_t * pt = (uint32_t * )(pde & 0xFFFFF000 );
76+ uint32_t pt_phys = pde & 0xFFFFF000 ;
77+ uint32_t pt_virt = vmem_phys_to_virt (pt_phys );
78+ uint32_t * pt = (uint32_t * )(uintptr_t )pt_virt ;
6879 if ((pt [pt_idx ] & PAGING_PRESENT ) == 0 ) return -1 ;
6980 pt [pt_idx ] = 0 ;
7081 invlpg ((void * )virt );
@@ -75,9 +86,9 @@ int unmap_page(uint32_t virt) {
7586 if (pt [i ] & PAGING_PRESENT ) { empty = 0 ; break ; }
7687 }
7788 if (empty ) {
78- uint32_t pt_phys = ( uint32_t )pt ; /* current identity mapping */
89+ uint32_t pt_phys = vmem_virt_to_phys (( uint32_t )( uintptr_t ) pt );
7990 page_directory [pd_idx ] = 0x00000000 ;
80- free_frame ((void * )pt_phys );
91+ free_frame ((void * )( uintptr_t ) pt_phys );
8192 }
8293
8394 return 0 ;
@@ -96,8 +107,9 @@ void paging_init_identity(uint32_t map_mb) {
96107 first_table [i ] = (i * 0x1000 ) | 3u ; // present + rw
97108 }
98109
99- // ディレクトリエントリ0はfirst_tableを指す
100- page_directory [0 ] = ((uint32_t )first_table ) | 3u ;
110+ // ディレクトリエントリ0はfirst_tableを指す。first_tableは静的で既に仮想アドレスとしてアクセス可能だが、PDEには物理アドレスを置く必要がある。
111+ uint32_t first_table_phys = vmem_virt_to_phys ((uint32_t )(uintptr_t )first_table );
112+ page_directory [0 ] = (first_table_phys & 0xFFFFF000 ) | 3u ;
101113
102114 // 残りのPDEをnot presentにする
103115 for (uint32_t i = 1 ; i < 1024 ; ++ i ) page_directory [i ] = 0x00000000 ;
@@ -133,7 +145,8 @@ void page_fault_handler_ex(uint32_t vec, uint32_t error_code, uint32_t eip) {
133145 */
134146void paging_enable (void ) {
135147 // CR3をロード
136- asm volatile ("mov %%eax, %%cr3" :: "a" ((uint32_t )page_directory ));
148+ uint32_t pd_phys = vmem_virt_to_phys ((uint32_t )(uintptr_t )page_directory );
149+ asm volatile ("mov %%eax, %%cr3" :: "a" (pd_phys ));
137150 // CR0のPGビットを有効化
138151 uint32_t cr0 ;
139152 asm volatile ("mov %%cr0, %%eax" : "=a" (cr0 ));
0 commit comments