Skip to content
This repository was archived by the owner on Jan 14, 2026. It is now read-only.

Commit f522469

Browse files
committed
fix vmem err
1 parent e9cf7bf commit f522469

2 files changed

Lines changed: 91 additions & 7 deletions

File tree

src/include/util/config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#define UEFI_MODE
1010

1111
// 初期化メッセージを表示するかどうか
12-
#define INIT_MSG
12+
// #define INIT_MSG
1313

1414
#ifndef NULL
1515
#define NULL ((void *)0)

src/kernel/mem/vmem.c

Lines changed: 90 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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. */
9693
uint64_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

133199
uint64_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

Comments
 (0)