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

Commit 5d1897c

Browse files
committed
upd paging logic
1 parent edb3f8c commit 5d1897c

6 files changed

Lines changed: 78 additions & 19 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/include/mem/paging.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
void paging_init_identity(uint32_t map_mb);
55
void paging_enable(void);
66

7+
#include <stddef.h>
8+
79
#define PAGING_PRESENT 0x1
810
#define PAGING_RW 0x2
911
#define PAGING_USER 0x4
1012

1113
void *alloc_page_table(void);
1214
int map_page(uint32_t phys, uint32_t virt, uint32_t flags);
1315
int unmap_page(uint32_t virt);
16+
int map_range(uint32_t phys_start, uint32_t virt_start, size_t size, uint32_t flags);
17+
void page_fault_handler_ex(uint32_t vec, uint32_t error_code, uint32_t eip);
1418

1519
#endif /* _MEM_PAGING_H */

src/kernel/interrupt/idt.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ void irq_handler_c(uint32_t vec) {
8484
}
8585

8686
extern void page_fault_handler(uint32_t vec);
87+
extern void page_fault_handler_ex(uint32_t vec, uint32_t error_code, uint32_t eip);
8788

8889
void irq_exception_c(uint32_t vec) {
8990
if (vec == 14) {
@@ -95,6 +96,20 @@ void irq_exception_c(uint32_t vec) {
9596
}
9697
}
9798

99+
/**
100+
* @fn irq_exception_ex
101+
* @brief 例外発生時の拡張ハンドラ
102+
*/
103+
void irq_exception_ex(uint32_t vec, uint32_t error_code) {
104+
if (vec == 14) {
105+
// C言語からEIPを正確に取得するのは難しいため、ここでは0を渡す
106+
page_fault_handler_ex(vec, error_code, 0);
107+
} else {
108+
printk("exception ex vec=%u err=0x%x\n", (unsigned)vec, (unsigned)error_code);
109+
while (1) {}
110+
}
111+
}
112+
98113
/**
99114
* @fn idt_init
100115
* @brief IDTを初期化する

src/kernel/interrupt/irq.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
#include <config.h>
1+
#include <config.h>
22

3-
/**
4-
* @fn irq_save
5-
* Save EFLAGS and disable interrupts.
6-
*/
7-
uint32_t irq_save(void) {
3+
/**
4+
* @fn irq_save
5+
* Save EFLAGS and disable interrupts.
6+
*/
7+
uint32_t irq_save(void) {
88
uint32_t flags;
99
asm volatile(
1010
"pushf\n\t"
@@ -15,18 +15,18 @@
1515
);
1616
asm volatile("cli" ::: "memory");
1717
return flags;
18-
}
18+
}
1919

20-
/**
21-
* @fn irq_restore
22-
* Restore EFLAGS.
23-
*/
24-
void irq_restore(uint32_t flags) {
20+
/**
21+
* @fn irq_restore
22+
* Restore EFLAGS.
23+
*/
24+
void irq_restore(uint32_t flags) {
2525
asm volatile(
2626
"push %0\n\t"
2727
"popf\n\t"
2828
:
2929
: "r" (flags)
3030
: "memory"
3131
);
32-
}
32+
}

src/kernel/interrupt/irq_stubs.asm

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,24 @@ isr_stub_table:
55

66
extern irq_handler_c
77
extern irq_exception_c
8+
extern irq_exception_ex
89

9-
global isr32
10-
isr32:
10+
; Exception with error code: isr14
1111
global isr14
1212
isr14:
1313
pusha
14-
push dword 14
15-
call irq_exception_c
16-
add esp, 4
14+
; error code is located just above the pushed registers (pusha pushes 8 regs = 32 bytes)
15+
mov eax, [esp + 32]
16+
push eax ; push error_code
17+
push dword 14 ; push vector
18+
call irq_exception_ex
19+
add esp, 8
1720
popa
1821
iretd
1922

23+
; IRQ handlers 32-47
24+
global isr32
25+
isr32:
2026
pusha
2127
push dword 32
2228
call irq_handler_c

src/kernel/mem/paging.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,18 @@ int unmap_page(uint32_t virt) {
6868
if ((pt[pt_idx] & PAGING_PRESENT) == 0) return -1;
6969
pt[pt_idx] = 0;
7070
invlpg((void *)virt);
71+
72+
/* check if the page table became empty -> free it and clear PDE */
73+
int empty = 1;
74+
for (int i = 0; i < 1024; ++i) {
75+
if (pt[i] & PAGING_PRESENT) { empty = 0; break; }
76+
}
77+
if (empty) {
78+
uint32_t pt_phys = (uint32_t)pt; /* current identity mapping */
79+
page_directory[pd_idx] = 0x00000000;
80+
free_frame((void *)pt_phys);
81+
}
82+
7183
return 0;
7284
}
7385

@@ -93,6 +105,28 @@ void paging_init_identity(uint32_t map_mb) {
93105
printk("paging: identity map initialized for %u MB (pages=%u)\n", (unsigned)map_mb, (unsigned)pages);
94106
}
95107

108+
/**
109+
* @fn map_range
110+
* @brief 指定範囲を連続ページとしてマップする
111+
*/
112+
int map_range(uint32_t phys_start, uint32_t virt_start, size_t size, uint32_t flags) {
113+
if (phys_start % 0x1000 || virt_start % 0x1000) return -1;
114+
uint32_t pages = (size + 0xFFF) / 0x1000;
115+
for (uint32_t i = 0; i < pages; ++i) {
116+
if (map_page(phys_start + i * 0x1000, virt_start + i * 0x1000, flags) != 0) {
117+
return -1;
118+
}
119+
}
120+
return 0;
121+
}
122+
123+
void page_fault_handler_ex(uint32_t vec, uint32_t error_code, uint32_t eip) {
124+
uint32_t fault_addr;
125+
asm volatile ("mov %%cr2, %0" : "=r" (fault_addr));
126+
printk("PAGE FAULT: vec=%u err=0x%x eip=0x%x cr2=0x%x\n", (unsigned)vec, (unsigned)error_code, (unsigned)eip, (unsigned)fault_addr);
127+
while (1) {}
128+
}
129+
96130
/**
97131
* @fn paging_enable
98132
* @brief ページングを有効化

0 commit comments

Comments
 (0)