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

Commit 573118f

Browse files
committed
fix memory safe
1 parent b3935da commit 573118f

3 files changed

Lines changed: 96 additions & 64 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 39 ; 読み込むセクタの数
2+
SECTOR_COUNT EQU 40 ; 読み込むセクタの数
33
START_SECTOR EQU 2 ; 開始するセクタ番号
44
CYLINDER_NUM EQU 0 ; シリンダ番号
55
HEAD_NUM EQU 0 ; ヘッド番号

src/kernel/mem/paging.c

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@
33
#include <mem/paging.h>
44
#include <mem/map.h>
55
#include <stddef.h>
6+
7+
/* helpers: in current identity-map boot situation, phys==virt, so these are identity
8+
* conversions. If kernel later runs with higher-half mapping, update these helpers
9+
* to translate between physical and kernel virtual addresses accordingly.
10+
*/
11+
static inline void *phys_to_virt(uint32_t phys) {
12+
return (void *)phys;
13+
}
14+
static inline uint32_t virt_to_phys(void *virt) {
15+
return (uint32_t)virt;
16+
}
617
#include <console.h>
718
#include <interrupt/irq.h>
819

@@ -64,20 +75,43 @@ int unmap_page(uint32_t virt) {
6475

6576
// 指定されたMB数分のメモリを同一マッピングで初期化する
6677
void paging_init_identity(uint32_t map_mb) {
78+
/* map_mb MB (rounded up to full pages) as identity mapping */
6779
uint32_t pages = ((map_mb * 1024u * 1024u) + 0xFFF) / 0x1000;
80+
uint32_t pages_remaining = pages;
6881

69-
// 最初のテーブル: 最初の4MBを同一マッピング(1024エントリ)
70-
for (uint32_t i = 0; i < 1024; ++i) {
71-
first_table[i] = (i * 0x1000) | 3u; // present + rw
72-
}
82+
/* number of page tables needed (1024 entries per table -> 4MB each) */
83+
uint32_t needed_pt = (pages + 1023) / 1024;
7384

74-
// ディレクトリエントリ0はfirst_tableを指す
75-
page_directory[0] = ((uint32_t)first_table) | 3u;
85+
/* initialize page directory to not present */
86+
for (uint32_t i = 0; i < 1024; ++i) page_directory[i] = 0x00000000;
7687

77-
// 残りのPDEをnot presentにする
78-
for (uint32_t i = 1; i < 1024; ++i) page_directory[i] = 0x00000000;
88+
for (uint32_t pt_index = 0; pt_index < needed_pt; ++pt_index) {
89+
/* use first_table for pt_index==0 for static allocation */
90+
uint32_t *pt = NULL;
91+
if (pt_index == 0) {
92+
pt = first_table;
93+
} else {
94+
void *alloc = alloc_page_table();
95+
if (!alloc) {
96+
printk("paging: failed to alloc page table for pt_index=%u\n", (unsigned)pt_index);
97+
break;
98+
}
99+
pt = (uint32_t *)alloc;
100+
}
101+
102+
/* fill table entries for this PT */
103+
for (uint32_t i = 0; i < 1024 && pages_remaining > 0; ++i, --pages_remaining) {
104+
uint32_t phys = (pt_index * 1024u + i) * 0x1000u;
105+
pt[i] = (phys & 0xFFFFF000u) | (PAGING_PRESENT | PAGING_RW);
106+
}
107+
108+
/* write PDE: PDE must contain physical address of pt */
109+
uint32_t pt_phys = virt_to_phys((void *)pt);
110+
page_directory[pt_index] = (pt_phys & 0xFFFFF000u) | (PAGING_PRESENT | PAGING_RW);
111+
}
79112

80-
printk("paging: identity map initialized for %u MB (pages=%u)\n", (unsigned)map_mb, (unsigned)pages);
113+
printk("paging: identity map initialized for %u MB (pages=%u, tables=%u)\n",
114+
(unsigned)map_mb, (unsigned)pages, (unsigned)needed_pt);
81115
}
82116

83117
// ページング機能を有効化する

src/kernel/tests/paging_test.c

Lines changed: 52 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,58 +4,56 @@
44
#include <mem/map.h>
55

66
void paging_test(void) {
7-
printk("[PAGING TEST] start\n");
8-
9-
/* Set up a small identity mapping for low memory so kernel stays accessible */
10-
paging_init_identity(1); /* map first 1 MB */
11-
printk("[PAGING TEST] identity map (1MB) set\n");
12-
13-
/* Allocate a physical frame to map */
14-
void *frame = alloc_frame();
15-
if (!frame) {
16-
printk("[PAGING TEST] alloc_frame failed\n");
17-
return;
18-
}
19-
uint32_t phys = (uint32_t)frame;
20-
printk("[PAGING TEST] allocated phys frame=0x%x\n", (unsigned)phys);
21-
22-
/* choose a virtual address likely unmapped (above identity region) */
23-
uint32_t virt = 0x4000000; /* 64MB */
24-
25-
/* map the page (present + rw) */
26-
if (map_page(phys, virt, PAGING_PRESENT | PAGING_RW) != 0) {
27-
printk("[PAGING TEST] map_page failed\n");
28-
return;
29-
}
30-
printk("[PAGING TEST] mapped phys 0x%x -> virt 0x%x\n", (unsigned)phys, (unsigned)virt);
31-
32-
/* enable paging */
33-
paging_enable();
34-
printk("[PAGING TEST] paging enabled\n");
35-
36-
/* Access the newly mapped virtual address */
37-
volatile uint32_t *p = (uint32_t *)virt;
38-
*p = 0xdeadbeef;
39-
uint32_t v = *p;
40-
printk("[PAGING TEST] write/read virt 0x%x -> 0x%x\n", (unsigned)virt, (unsigned)v);
41-
42-
/* unmap the page (do not access after this to avoid page fault) */
43-
if (unmap_page(virt) == 0) {
44-
printk("[PAGING TEST] unmapped virt 0x%x\n", (unsigned)virt);
45-
} else {
46-
printk("[PAGING TEST] unmap_page failed for 0x%x\n", (unsigned)virt);
47-
}
48-
49-
/* remap the same physical frame to a different virtual address and verify */
50-
uint32_t virt2 = 0x4100000; /* 65MB */
51-
if (map_page(phys, virt2, PAGING_PRESENT | PAGING_RW) != 0) {
52-
printk("[PAGING TEST] remap failed\n");
53-
return;
54-
}
55-
printk("[PAGING TEST] remapped phys 0x%x -> virt 0x%x\n", (unsigned)phys, (unsigned)virt2);
56-
volatile uint32_t *p2 = (uint32_t *)virt2;
57-
uint32_t v2 = *p2; /* should reflect previous write if caching coherent */
58-
printk("[PAGING TEST] read virt2 0x%x -> 0x%x\n", (unsigned)virt2, (unsigned)v2);
59-
60-
printk("[PAGING TEST] done\n");
7+
// カーネルがアクセス可能なように低メモリをアイデンティティマッピング
8+
paging_init_identity(1); // 最初の1MBをマップ
9+
printk("identity map (1MB) set\n");
10+
11+
// マッピングする物理フレームを確保
12+
void *frame = alloc_frame();
13+
if (!frame) {
14+
printk("alloc_frame failed\n");
15+
return;
16+
}
17+
uint32_t phys = (uint32_t)frame;
18+
printk("allocated phys frame=0x%x\n", (unsigned)phys);
19+
20+
// アイデンティティ領域の上に未マップと思われる仮想アドレスを選択
21+
uint32_t virt = 0x4000000; // 64MB
22+
23+
// ページをマップ(present + rw)
24+
if (map_page(phys, virt, PAGING_PRESENT | PAGING_RW) != 0) {
25+
printk("map_page failed\n");
26+
return;
27+
}
28+
printk("mapped phys 0x%x -> virt 0x%x\n", (unsigned)phys, (unsigned)virt);
29+
30+
// ページングを有効化
31+
paging_enable();
32+
printk("paging enabled\n");
33+
34+
// 新たにマップした仮想アドレスへアクセス
35+
volatile uint32_t *p = (uint32_t *)virt;
36+
*p = 0xdeadbeef;
37+
uint32_t v = *p;
38+
printk("write/read virt 0x%x -> 0x%x\n", (unsigned)virt, (unsigned)v);
39+
40+
// ページのアンマップ(この後アクセスするとページフォルトになるので注意)
41+
if (unmap_page(virt) == 0) {
42+
printk("unmapped virt 0x%x\n", (unsigned)virt);
43+
} else {
44+
printk("unmap_page failed for 0x%x\n", (unsigned)virt);
45+
}
46+
47+
// 同じ物理フレームを別の仮想アドレスに再マップし、値を確認
48+
uint32_t virt2 = 0x4100000; // 65MB
49+
if (map_page(phys, virt2, PAGING_PRESENT | PAGING_RW) != 0) {
50+
printk("remap failed\n");
51+
return;
52+
}
53+
printk("remapped phys 0x%x -> virt 0x%x\n", (unsigned)phys, (unsigned)virt2);
54+
volatile uint32_t *p2 = (uint32_t *)virt2;
55+
uint32_t v2 = *p2; // キャッシュが一貫していれば前回の書き込みが反映されているはず
56+
printk("read virt2 0x%x -> 0x%x\n", (unsigned)virt2, (unsigned)v2);
57+
58+
printk("done\n");
6159
}

0 commit comments

Comments
 (0)