Skip to content

Commit 623dfed

Browse files
committed
fix paging
1 parent 46ebda5 commit 623dfed

File tree

7 files changed

+286
-223
lines changed

7 files changed

+286
-223
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
commit 46ebda58fa94ac4712cb208ef8ca8c77e076b48d
2+
Author: Alexeev Bronislav <[email protected]>
3+
Date: Sun Aug 24 23:00:29 2025 +0700
4+
5+
fix paging
6+
17
commit aeeb202e06cc3c249505f348e030cb1363573bdd
28
Author: Alexeev Bronislav <[email protected]>
39
Date: Sun Aug 24 22:47:15 2025 +0700

src/kernel/cpu/paging.c

Lines changed: 96 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,159 +1,147 @@
1-
// paging.c
1+
// [file name]: paging.c
22
#include "paging.h"
33
#include "../kklibc/kklibc.h"
4-
#include "isr.h"
54
#include "../drivers/screen.h"
65

76
// Текущий каталог страниц
8-
page_directory_t *current_directory = NULL;
7+
static page_directory_t *current_directory = NULL;
8+
// Каталог страниц ядра
9+
static page_directory_t *kernel_directory = NULL;
910

10-
// Внешние функции из assembly
11-
extern void load_page_directory(u32);
12-
extern void enable_paging();
11+
// Статистика использования памяти
12+
static u32 used_pages = 0;
13+
static u32 total_pages = 0;
14+
15+
// Временная таблица страниц для идентичного отображения
16+
static page_table_t *identity_table = NULL;
17+
18+
#define PAGING_STRUCTS_START 0x200000
19+
#define KERNEL_PAGE_DIRECTORY_ADDR (PAGING_STRUCTS_START)
20+
#define IDENTITY_PAGE_TABLE_ADDR (PAGING_STRUCTS_START + 0x1000)
1321

14-
// Инициализация paging
1522
void paging_init() {
1623
kprint("Initializing paging...\n");
1724

18-
// Создаем каталог страниц
19-
current_directory = (page_directory_t*)kmalloc_a(sizeof(page_directory_t));
20-
memory_set((u8*)current_directory, 0, sizeof(page_directory_t));
21-
22-
// Создаем таблицы страниц для идентичного отображения первых 4MB
23-
for (u32 i = 0; i < 1024; i++) {
24-
// Каждая запись каталога указывает на таблицу страниц
25-
page_table_t *table = (page_table_t*)kmalloc_a(sizeof(page_table_t));
26-
memory_set((u8*)table, 0, sizeof(page_table_t));
27-
28-
// Заполняем таблицу страниц
29-
for (u32 j = 0; j < 1024; j++) {
30-
u32 frame = (i * 1024 + j) * PAGE_SIZE;
31-
table->entries[j].present = 1;
32-
table->entries[j].rw = 1;
33-
table->entries[j].frame = frame >> 12;
34-
}
25+
// Используем фиксированные адреса для структур paging
26+
kernel_directory = (page_directory_t *)KERNEL_PAGE_DIRECTORY_ADDR;
27+
memory_set((u8 *)kernel_directory, 0, sizeof(page_directory_t));
3528

36-
// Устанавливаем запись в каталоге страниц
37-
current_directory->entries[i].present = 1;
38-
current_directory->entries[i].rw = 1;
39-
current_directory->entries[i].frame = ((u32)table) >> 12;
29+
// Создаем таблицу для идентичного отображения первых 4MB
30+
page_table_t *identity_table = (page_table_t *)IDENTITY_PAGE_TABLE_ADDR;
31+
memory_set((u8 *)identity_table, 0, sizeof(page_table_t));
32+
33+
// Заполняем таблицу идентичного отображения
34+
u32 i;
35+
for (i = 0; i < 1024; i++) {
36+
identity_table->entries[i].present = 1;
37+
identity_table->entries[i].rw = 1;
38+
identity_table->entries[i].frame = i;
4039
}
4140

42-
// Переключаемся на новый каталог страниц
43-
switch_page_directory(current_directory);
41+
// Добавляем таблицу в каталог
42+
kernel_directory->entries[0].present = 1;
43+
kernel_directory->entries[0].rw = 1;
44+
kernel_directory->entries[0].frame = (u32)identity_table >> 12;
45+
46+
// Устанавливаем каталог страниц
47+
current_directory = kernel_directory;
48+
switch_page_directory(kernel_directory);
4449

4550
// Включаем paging
46-
enable_paging();
51+
u32 cr0;
52+
asm volatile("mov %%cr0, %0" : "=r"(cr0));
53+
cr0 |= 0x80000000; // Устанавливаем бит PG
54+
asm volatile("mov %0, %%cr0" :: "r"(cr0));
4755

4856
kprint("Paging enabled\n");
57+
58+
// Инициализируем статистику
59+
total_pages = (HEAP_SIZE + HEAP_START) / PAGE_SIZE;
60+
used_pages = 1024; // Уже использовано для идентичного отображения
4961
}
5062

51-
// Переключение каталога страниц
52-
void switch_page_directory(page_directory_t *dir) {
53-
current_directory = dir;
54-
load_page_directory((u32)dir);
63+
void switch_page_directory(page_directory_t *new_dir) {
64+
current_directory = new_dir;
65+
asm volatile("mov %0, %%cr3" :: "r"(new_dir));
5566
}
5667

57-
// Получение текущего каталога страниц
58-
page_directory_t *get_current_page_directory() {
59-
return current_directory;
68+
page_directory_t *get_kernel_page_directory() {
69+
return kernel_directory;
6070
}
6171

62-
// Отображение виртуальной страницы на физическую
6372
void map_page(void *virtual_addr, void *physical_addr, u32 flags) {
64-
u32 virtual = (u32)virtual_addr;
65-
u32 physical = (u32)physical_addr;
73+
u32 pd_index = PAGE_DIRECTORY_INDEX((u32)virtual_addr);
74+
u32 pt_index = PAGE_TABLE_INDEX((u32)virtual_addr);
6675

67-
u32 pd_index = PAGE_DIRECTORY_INDEX(virtual);
68-
u32 pt_index = PAGE_TABLE_INDEX(virtual);
76+
// Проверяем, существует ли таблица страниц
77+
if (!current_directory->entries[pd_index].present) {
78+
// Создаем новую таблицу страниц
79+
page_table_t *new_table = (page_table_t *)kmalloc_a(sizeof(page_table_t));
80+
memory_set((u8 *)new_table, 0, sizeof(page_table_t));
81+
82+
// Добавляем таблицу в каталог
83+
current_directory->entries[pd_index].present = 1;
84+
current_directory->entries[pd_index].rw = 1;
85+
current_directory->entries[pd_index].frame = (u32)new_table >> 12;
86+
}
6987

70-
// Получаем таблицу страниц
71-
page_table_t *table = (page_table_t*)(current_directory->entries[pd_index].frame << 12);
88+
// Получаем указатель на таблицу страниц
89+
page_table_t *table = (page_table_t *)(current_directory->entries[pd_index].frame << 12);
7290

73-
// Устанавливаем запись в таблице страниц
91+
// Заполняем запись в таблице страниц
7492
table->entries[pt_index].present = (flags & PAGE_PRESENT) ? 1 : 0;
75-
table->entries[pt_index].rw = (flags & PAGE_WRITABLE) ? 1 : 0;
93+
table->entries[pt_index].rw = (flags & PAGE_WRITE) ? 1 : 0;
7694
table->entries[pt_index].user = (flags & PAGE_USER) ? 1 : 0;
77-
table->entries[pt_index].frame = physical >> 12;
95+
table->entries[pt_index].write_through = (flags & PAGE_WRITE_THROUGH) ? 1 : 0;
96+
table->entries[pt_index].cache_disable = (flags & PAGE_CACHE_DISABLE) ? 1 : 0;
97+
table->entries[pt_index].global = (flags & PAGE_GLOBAL) ? 1 : 0;
98+
table->entries[pt_index].frame = (u32)physical_addr >> 12;
99+
100+
// Обновляем статистику
101+
if (table->entries[pt_index].present) {
102+
used_pages++;
103+
}
78104

79-
// Инвалидируем TLB
80-
asm volatile("invlpg (%0)" : : "r" (virtual_addr));
105+
// Принудительно обновляем TLB
106+
asm volatile("invlpg (%0)" :: "r"(virtual_addr));
81107
}
82108

83-
// Удаление отображения страницы
84109
void unmap_page(void *virtual_addr) {
85-
u32 virtual = (u32)virtual_addr;
86-
u32 pd_index = PAGE_DIRECTORY_INDEX(virtual);
87-
u32 pt_index = PAGE_TABLE_INDEX(virtual);
110+
u32 pd_index = PAGE_DIRECTORY_INDEX((u32)virtual_addr);
111+
u32 pt_index = PAGE_TABLE_INDEX((u32)virtual_addr);
88112

89-
// Получаем таблицу страниц
90-
page_table_t *table = (page_table_t*)(current_directory->entries[pd_index].frame << 12);
113+
if (current_directory->entries[pd_index].present) {
114+
page_table_t *table = (page_table_t *)(current_directory->entries[pd_index].frame << 12);
115+
if (table->entries[pt_index].present) {
116+
table->entries[pt_index].present = 0;
117+
used_pages--;
91118

92-
// Очищаем запись
93-
table->entries[pt_index].present = 0;
94-
95-
// Инвалидируем TLB
96-
asm volatile("invlpg (%0)" : : "r" (virtual_addr));
119+
// Принудительно обновляем TLB
120+
asm volatile("invlpg (%0)" :: "r"(virtual_addr));
121+
}
122+
}
97123
}
98124

99-
// Получение физического адреса по виртуальному
100125
void *get_physical_address(void *virtual_addr) {
101-
u32 virtual = (u32)virtual_addr;
102-
u32 pd_index = PAGE_DIRECTORY_INDEX(virtual);
103-
u32 pt_index = PAGE_TABLE_INDEX(virtual);
126+
u32 pd_index = PAGE_DIRECTORY_INDEX((u32)virtual_addr);
127+
u32 pt_index = PAGE_TABLE_INDEX((u32)virtual_addr);
104128

105-
// Проверяем наличие страницы
106129
if (!current_directory->entries[pd_index].present) {
107130
return NULL;
108131
}
109132

110-
// Получаем таблицу страниц
111-
page_table_t *table = (page_table_t*)(current_directory->entries[pd_index].frame << 12);
112-
113-
// Проверяем наличие записи в таблице
133+
page_table_t *table = (page_table_t *)(current_directory->entries[pd_index].frame << 12);
114134
if (!table->entries[pt_index].present) {
115135
return NULL;
116136
}
117137

118-
// Вычисляем физический адрес
119-
u32 physical = (table->entries[pt_index].frame << 12) + (virtual & 0xFFF);
120-
return (void*)physical;
138+
return (void *)(table->entries[pt_index].frame << 12);
121139
}
122140

123-
// Обработчик page fault
124-
void page_fault_handler(registers_t regs) {
125-
u32 faulting_address;
126-
asm volatile("mov %%cr2, %0" : "=r" (faulting_address));
127-
128-
// Проверяем причину page fault
129-
int present = regs.err_code & 0x1;
130-
int rw = regs.err_code & 0x2;
131-
int user = regs.err_code & 0x4;
132-
int reserved = regs.err_code & 0x8;
133-
int id = regs.err_code & 0x10;
134-
135-
kprintf("Page fault at 0x%x, caused by ", faulting_address);
136-
137-
if (present) {
138-
kprint("page protection violation");
139-
} else {
140-
kprint("non-present page");
141-
}
142-
143-
if (rw) {
144-
kprint(" write attempt");
145-
} else {
146-
kprint(" read attempt");
147-
}
148-
149-
if (user) {
150-
kprint(" in user mode");
151-
} else {
152-
kprint(" in kernel mode");
153-
}
154-
155-
kprint("\n");
141+
u32 get_memory_used_pages() {
142+
return used_pages;
143+
}
156144

157-
// Зависаем систему при page fault в ядре
158-
asm volatile("hlt");
145+
u32 get_memory_free_pages() {
146+
return total_pages - used_pages;
159147
}

src/kernel/cpu/paging.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
// paging.h
1+
// [file name]: paging.h
22
#ifndef PAGING_H
33
#define PAGING_H
44

55
#include "../kklibc/ctypes.h"
6-
#include "isr.h"
76

87
#define PAGE_SIZE 4096
9-
#define PAGE_DIRECTORY_INDEX(x) ((x) >> 22)
8+
#define PAGE_DIRECTORY_INDEX(x) (((x) >> 22) & 0x3FF)
109
#define PAGE_TABLE_INDEX(x) (((x) >> 12) & 0x3FF)
11-
#define PAGE_GET_PHYS_ADDRESS(x) ((x) & ~0xFFF)
10+
#define PAGE_GET_PHYS_ADDRESS(x) ((x) & 0xFFFFF000)
1211

13-
// Флаги для записей в таблицах страниц
12+
// Флаги для записей страниц
1413
#define PAGE_PRESENT 0x1
15-
#define PAGE_WRITABLE 0x2
14+
#define PAGE_WRITE 0x2
1615
#define PAGE_USER 0x4
1716
#define PAGE_WRITE_THROUGH 0x8
1817
#define PAGE_CACHE_DISABLE 0x10
@@ -62,11 +61,16 @@ typedef struct {
6261

6362
// Функции для работы с paging
6463
void paging_init();
65-
void switch_page_directory(page_directory_t *dir);
66-
page_directory_t *get_current_page_directory();
64+
void switch_page_directory(page_directory_t *new_dir);
65+
page_directory_t *get_kernel_page_directory();
6766
void map_page(void *virtual_addr, void *physical_addr, u32 flags);
6867
void unmap_page(void *virtual_addr);
6968
void *get_physical_address(void *virtual_addr);
70-
void page_fault_handler(registers_t regs);
69+
u32 get_memory_used_pages();
70+
u32 get_memory_free_pages();
71+
72+
// Функции для выровненного выделения памяти
73+
void *kmalloc_a(u32 size);
74+
void kfree_a(void *ptr);
7175

7276
#endif

src/kernel/kernel/kernel.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ void kmain() {
2525
irq_install();
2626
kprint("IRQ Installed\n");
2727

28-
register_interrupt_handler(14, page_fault_handler);
28+
// register_interrupt_handler(14, page_fault_handler);
29+
paging_init();
2930

3031
heap_init();
3132

src/kernel/kernel/utils.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ void info_command_shell(char** args) {
105105
meminfo_t meminfo = get_meminfo();
106106

107107
kprint("MEMORY\n");
108-
kprintf("HEAP (%d): start at %d (phys: %d), minimal block size %d\n", meminfo.heap_size, meminfo.heap_virtual_start, meminfo.heap_physical_start, meminfo.block_size);
108+
kprintf("HEAP (%d): start at %d, minimal block size %d\n", meminfo.heap_size, meminfo.heap_start, meminfo.block_size);
109109
kprintf("Total used: %d\n", meminfo.total_used);
110110
kprintf("Total free: %d\n", meminfo.total_free);
111111
kprintf("Block count: %d\n", meminfo.block_count);

0 commit comments

Comments
 (0)