@@ -90,13 +90,79 @@ uint32_t vmem_virt_to_phys(uint32_t virt) {
9090 return phys ;
9191}
9292
93- /* 64-bit wrapper: call 32-bit virt->phys and zero-extend to 64-bit.
94- This is a compatibility helper for subsystems that expect 64-bit DMA addresses.
95- Replace with a true 64-bit page-table walk implementation if/when needed. */
9693uint64_t vmem_virt_to_phys64 (uint64_t virt ) {
97- uint32_t v32 = (uint32_t )virt ;
98- uint32_t p32 = vmem_virt_to_phys (v32 );
99- return (uint64_t )p32 ;
94+ if (current_mode == VMEM_MODE_IDENTITY ) {
95+ return virt ;
96+ }
97+ if (current_mode == VMEM_MODE_OFFSET ) {
98+ if ((int64_t )virt - vmem_offset < 0 ) return 0 ;
99+ uint64_t phys = (uint64_t )((int64_t )virt - vmem_offset );
100+ return phys ;
101+ }
102+
103+ uint64_t cr3 ;
104+ asm volatile ("mov %%cr3, %0" : "=r" (cr3 ));
105+ uint64_t pml4_base = cr3 & 0xFFFFFFFFFFFFF000ULL ;
106+
107+ /* indices */
108+ uint64_t pml4_idx = (virt >> 39 ) & 0x1FFULL ;
109+ uint64_t pdpt_idx = (virt >> 30 ) & 0x1FFULL ;
110+ uint64_t pd_idx = (virt >> 21 ) & 0x1FFULL ;
111+ uint64_t pt_idx = (virt >> 12 ) & 0x1FFULL ;
112+ uint64_t page_off = virt & 0xFFFULL ;
113+
114+ uint64_t read_entry ;
115+ uint64_t entry ;
116+
117+ /* read PML4E */
118+ uint64_t pml4e_phys = pml4_base + (pml4_idx * 8 );
119+ uint64_t pml4e_virt = vmem_phys_to_virt64 (pml4e_phys );
120+ if (pml4e_virt == UINT64_MAX ) return 0 ;
121+ read_entry = * ((volatile uint64_t * )(uintptr_t )pml4e_virt );
122+ entry = read_entry ;
123+ if ((entry & 0x1 ) == 0 ) return 0 ; /* not present */
124+
125+ /* PDPT */
126+ uint64_t pdpt_base = entry & 0xFFFFFFFFFFFFF000ULL ;
127+ uint64_t pdpte_phys = pdpt_base + (pdpt_idx * 8 );
128+ uint64_t pdpte_virt = vmem_phys_to_virt64 (pdpte_phys );
129+ if (pdpte_virt == UINT64_MAX ) return 0 ;
130+ read_entry = * ((volatile uint64_t * )(uintptr_t )pdpte_virt );
131+ entry = read_entry ;
132+ if ((entry & 0x1 ) == 0 ) return 0 ;
133+ /* 1 GiB page? (PS bit) */
134+ if (entry & (1ULL << 7 )) {
135+ uint64_t base = entry & 0xFFFFFC0000000ULL ; /* bits 51:30 */
136+ uint64_t offset = virt & 0x3FFFFFFFULL ; /* lower 30 bits */
137+ return base + offset ;
138+ }
139+
140+ /* PD */
141+ uint64_t pd_base = entry & 0xFFFFFFFFFFFFF000ULL ;
142+ uint64_t pde_phys = pd_base + (pd_idx * 8 );
143+ uint64_t pde_virt = vmem_phys_to_virt64 (pde_phys );
144+ if (pde_virt == UINT64_MAX ) return 0 ;
145+ read_entry = * ((volatile uint64_t * )(uintptr_t )pde_virt );
146+ entry = read_entry ;
147+ if ((entry & 0x1 ) == 0 ) return 0 ;
148+ /* 2 MiB page? (PS bit) */
149+ if (entry & (1ULL << 7 )) {
150+ uint64_t base = entry & 0xFFFFFFFFFFE00000ULL ; /* bits 51:21 */
151+ uint64_t offset = virt & 0x1FFFFFULL ; /* lower 21 bits */
152+ return base + offset ;
153+ }
154+
155+ /* PT */
156+ uint64_t pt_base = entry & 0xFFFFFFFFFFFFF000ULL ;
157+ uint64_t pte_phys = pt_base + (pt_idx * 8 );
158+ uint64_t pte_virt = vmem_phys_to_virt64 (pte_phys );
159+ if (pte_virt == UINT64_MAX ) return 0 ;
160+ read_entry = * ((volatile uint64_t * )(uintptr_t )pte_virt );
161+ entry = read_entry ;
162+ if ((entry & 0x1 ) == 0 ) return 0 ;
163+
164+ uint64_t page_base = entry & 0xFFFFFFFFFFFFF000ULL ;
165+ return page_base + page_off ;
100166}
101167
102168// 物理アドレス→仮想アドレス変換
@@ -131,8 +197,26 @@ uint32_t vmem_phys_to_virt(uint32_t phys) {
131197}
132198
133199uint64_t vmem_phys_to_virt64 (uint64_t phys ) {
200+ /*
201+ * vmem_phys_to_virt works with 32-bit physical addresses and returns
202+ * UINT32_MAX on error. The 64-bit wrapper must translate that error
203+ * into UINT64_MAX so callers (the page-table walker) can detect
204+ * failures reliably. Also fail if the physical address doesn't fit
205+ * in 32-bits because this simple mapper cannot handle >4GiB frames
206+ * without a proper phys->virt64 implementation.
207+ */
208+ if (phys == UINT64_MAX ) {
209+ return UINT64_MAX ;
210+ }
211+ if (phys > UINT32_MAX ) {
212+ /* unsupported: physical address out of 32-bit range */
213+ return UINT64_MAX ;
214+ }
134215 uint32_t p32 = (uint32_t )phys ;
135216 uint32_t v32 = vmem_phys_to_virt (p32 );
217+ if (v32 == UINT32_MAX ) {
218+ return UINT64_MAX ;
219+ }
136220 return (uint64_t )v32 ;
137221}
138222
0 commit comments