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

Commit 7376235

Browse files
committed
add vmem
1 parent 5d1897c commit 7376235

7 files changed

Lines changed: 94 additions & 15 deletions

File tree

src/boot/config.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
KERNEL_OFFSET EQU 0x10000 ; カーネルをロードするアドレス
2-
SECTOR_COUNT EQU 40 ; 読み込むセクタの数
2+
SECTOR_COUNT EQU 42 ; 読み込むセクタの数
33
START_SECTOR EQU 2 ; 開始するセクタ番号
44
CYLINDER_NUM EQU 0 ; シリンダ番号
55
HEAD_NUM EQU 0 ; ヘッド番号

src/include/mem/vmem.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#ifndef _MEM_VMEM_H
2+
#define _MEM_VMEM_H
3+
4+
#include <stdint.h>
5+
6+
uint32_t vmem_virt_to_phys(uint32_t virt);
7+
uint32_t vmem_phys_to_virt(uint32_t phys);
8+
void vmem_set_offset(int32_t offset);
9+
void vmem_reset(void);
10+
11+
#endif /* _MEM_VMEM_H */

src/include/tests/define.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#define GDT_TEST
1818
// ページングのテスト
1919
#define PAGING_TEST
20+
// 仮想メモリのテスト
21+
#define VMEM_TEST
2022

2123
/* -------- 宣言 -------- */
2224
#ifdef MEM_TEST
@@ -43,6 +45,10 @@ void gdt_test();
4345
void paging_test();
4446
#endif /* PAGING_TEST */
4547

48+
#ifdef VMEM_TEST
49+
void vmem_test();
50+
#endif /* VMEM_TEST */
51+
4652
#endif /* TEST_TRUE */
4753

4854
#endif /* _TESTS_CONFIG_H */

src/kernel/mem/paging.c

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
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) {
2021
void *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
*/
134146
void 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));

src/kernel/mem/vmem.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include <stdint.h>
2+
#include <mem/vmem.h>
3+
4+
static int32_t vmem_offset = 0;
5+
6+
uint32_t vmem_virt_to_phys(uint32_t virt) {
7+
if (vmem_offset == 0) return virt;
8+
if ((int32_t)virt - vmem_offset < 0) return 0;
9+
return (uint32_t)((int32_t)virt - vmem_offset);
10+
}
11+
12+
uint32_t vmem_phys_to_virt(uint32_t phys) {
13+
if (vmem_offset == 0) return phys;
14+
return (uint32_t)((int32_t)phys + vmem_offset);
15+
}
16+
17+
void vmem_set_offset(int32_t offset) {
18+
vmem_offset = offset;
19+
}
20+
21+
void vmem_reset(void) {
22+
vmem_offset = 0;
23+
}

src/kernel/tests/run.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,9 @@ void run_test() {
4141
printk("> PAGING TEST\n");
4242
paging_test();
4343
#endif
44+
45+
#ifdef VMEM_TEST
46+
printk("> VMEM TEST\n");
47+
vmem_test();
48+
#endif
4449
}

src/kernel/tests/vmem_test.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <config.h>
2+
#include <console.h>
3+
#include <mem/vmem.h>
4+
#include <mem/map.h>
5+
#include <tests/define.h>
6+
7+
void vmem_test(void) {
8+
printk("default identity check\n");
9+
uint32_t p = 0x1000;
10+
uint32_t v = vmem_phys_to_virt(p);
11+
uint32_t p2 = vmem_virt_to_phys(v);
12+
printk("phys=0x%x -> virt=0x%x -> phys=0x%x\n", (unsigned)p, (unsigned)v, (unsigned)p2);
13+
14+
printk("offset mode check\n");
15+
vmem_set_offset(0xC0000000); // example kernel-high offset
16+
uint32_t v_off = vmem_phys_to_virt(p);
17+
uint32_t p_off = vmem_virt_to_phys(v_off);
18+
printk("phys=0x%x -> virt=0x%x -> phys=0x%x\n", (unsigned)p, (unsigned)v_off, (unsigned)p_off);
19+
20+
vmem_reset();
21+
}

0 commit comments

Comments
 (0)