Skip to content

Commit 4f3b9d7

Browse files
committed
realize paging memory, add kmalloc aligned; todo: realize kmemdump fully
1 parent a4deb10 commit 4f3b9d7

File tree

9 files changed

+331
-24
lines changed

9 files changed

+331
-24
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
<<<<<<< HEAD
12
commit 5c5167c783467a1441565edfd12b130a741e999c
23
Author: Alexeev Bronislav <[email protected]>
34
Date: Sun Aug 24 06:05:27 2025 +0700
45

56
feat: realize paging, add page, frame allocator and change kfree, kmalloc, krealloc
67

8+
=======
9+
>>>>>>> 3fe2ead (realize paging memory, add kmalloc aligned; todo: realize kmemdump fully)
710
commit ffe676bbcd462e3e7d7c8bd82ca1683361ba3bf6
811
Author: Alexeev Bronislav <[email protected]>
912
Date: Sun Aug 24 04:06:51 2025 +0700

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ LDFLAGS = -Ttext 0x1000 --oformat binary
1717

1818
KERNEL_ENTRY = $(BIN_DIR)/bootloader/kernel_entry.o
1919
INTERRUPT_OBJ = $(BIN_DIR)/kernel/cpu/interrupt.o
20+
<<<<<<< HEAD
2021
PAGING_OBJ = $(BIN_DIR)/bootloader/paging.o
22+
=======
23+
PAGING_OBJ = $(BIN_DIR)/kernel/paging_asm.o
24+
>>>>>>> 3fe2ead (realize paging memory, add kmalloc aligned; todo: realize kmemdump fully)
2125

2226
C_SOURCES = $(shell find $(SRC_DIR) -name '*.c')
2327
C_OBJS = $(C_SOURCES:$(SRC_DIR)/%.c=$(BIN_DIR)/%.o)

src/kernel/cpu/paging.c

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
// paging.c
2+
#include "paging.h"
3+
#include "../kklibc/kklibc.h"
4+
#include "isr.h"
5+
#include "../drivers/screen.h"
6+
7+
// Текущий каталог страниц
8+
page_directory_t *current_directory = NULL;
9+
10+
// Внешние функции из assembly
11+
extern void load_page_directory(u32);
12+
extern void enable_paging();
13+
14+
// Инициализация paging
15+
void paging_init() {
16+
kprint("Initializing paging...\n");
17+
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+
}
35+
36+
// Устанавливаем запись в каталоге страниц
37+
current_directory->entries[i].present = 1;
38+
current_directory->entries[i].rw = 1;
39+
current_directory->entries[i].frame = ((u32)table) >> 12;
40+
}
41+
42+
// Переключаемся на новый каталог страниц
43+
switch_page_directory(current_directory);
44+
45+
// Включаем paging
46+
enable_paging();
47+
48+
kprint("Paging enabled\n");
49+
}
50+
51+
// Переключение каталога страниц
52+
void switch_page_directory(page_directory_t *dir) {
53+
current_directory = dir;
54+
load_page_directory((u32)dir);
55+
}
56+
57+
// Получение текущего каталога страниц
58+
page_directory_t *get_current_page_directory() {
59+
return current_directory;
60+
}
61+
62+
// Отображение виртуальной страницы на физическую
63+
void map_page(void *virtual_addr, void *physical_addr, u32 flags) {
64+
u32 virtual = (u32)virtual_addr;
65+
u32 physical = (u32)physical_addr;
66+
67+
u32 pd_index = PAGE_DIRECTORY_INDEX(virtual);
68+
u32 pt_index = PAGE_TABLE_INDEX(virtual);
69+
70+
// Получаем таблицу страниц
71+
page_table_t *table = (page_table_t*)(current_directory->entries[pd_index].frame << 12);
72+
73+
// Устанавливаем запись в таблице страниц
74+
table->entries[pt_index].present = (flags & PAGE_PRESENT) ? 1 : 0;
75+
table->entries[pt_index].rw = (flags & PAGE_WRITABLE) ? 1 : 0;
76+
table->entries[pt_index].user = (flags & PAGE_USER) ? 1 : 0;
77+
table->entries[pt_index].frame = physical >> 12;
78+
79+
// Инвалидируем TLB
80+
asm volatile("invlpg (%0)" : : "r" (virtual_addr));
81+
}
82+
83+
// Удаление отображения страницы
84+
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);
88+
89+
// Получаем таблицу страниц
90+
page_table_t *table = (page_table_t*)(current_directory->entries[pd_index].frame << 12);
91+
92+
// Очищаем запись
93+
table->entries[pt_index].present = 0;
94+
95+
// Инвалидируем TLB
96+
asm volatile("invlpg (%0)" : : "r" (virtual_addr));
97+
}
98+
99+
// Получение физического адреса по виртуальному
100+
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);
104+
105+
// Проверяем наличие страницы
106+
if (!current_directory->entries[pd_index].present) {
107+
return NULL;
108+
}
109+
110+
// Получаем таблицу страниц
111+
page_table_t *table = (page_table_t*)(current_directory->entries[pd_index].frame << 12);
112+
113+
// Проверяем наличие записи в таблице
114+
if (!table->entries[pt_index].present) {
115+
return NULL;
116+
}
117+
118+
// Вычисляем физический адрес
119+
u32 physical = (table->entries[pt_index].frame << 12) + (virtual & 0xFFF);
120+
return (void*)physical;
121+
}
122+
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");
156+
157+
// Зависаем систему при page fault в ядре
158+
asm volatile("hlt");
159+
}

src/kernel/cpu/paging.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// paging.h
2+
#ifndef PAGING_H
3+
#define PAGING_H
4+
5+
#include "../kklibc/ctypes.h"
6+
#include "isr.h"
7+
8+
#define PAGE_SIZE 4096
9+
#define PAGE_DIRECTORY_INDEX(x) ((x) >> 22)
10+
#define PAGE_TABLE_INDEX(x) (((x) >> 12) & 0x3FF)
11+
#define PAGE_GET_PHYS_ADDRESS(x) ((x) & ~0xFFF)
12+
13+
// Флаги для записей в таблицах страниц
14+
#define PAGE_PRESENT 0x1
15+
#define PAGE_WRITABLE 0x2
16+
#define PAGE_USER 0x4
17+
#define PAGE_WRITE_THROUGH 0x8
18+
#define PAGE_CACHE_DISABLE 0x10
19+
#define PAGE_ACCESSED 0x20
20+
#define PAGE_DIRTY 0x40
21+
#define PAGE_GLOBAL 0x100
22+
23+
// Структура записи в каталоге страниц
24+
typedef struct {
25+
u32 present : 1;
26+
u32 rw : 1;
27+
u32 user : 1;
28+
u32 write_through : 1;
29+
u32 cache_disable : 1;
30+
u32 accessed : 1;
31+
u32 reserved : 1;
32+
u32 page_size : 1;
33+
u32 global : 1;
34+
u32 available : 3;
35+
u32 frame : 20;
36+
} page_directory_entry_t;
37+
38+
// Структура записи в таблице страниц
39+
typedef struct {
40+
u32 present : 1;
41+
u32 rw : 1;
42+
u32 user : 1;
43+
u32 write_through : 1;
44+
u32 cache_disable : 1;
45+
u32 accessed : 1;
46+
u32 dirty : 1;
47+
u32 reserved : 1;
48+
u32 global : 1;
49+
u32 available : 3;
50+
u32 frame : 20;
51+
} page_table_entry_t;
52+
53+
// Структура каталога страниц
54+
typedef struct {
55+
page_directory_entry_t entries[1024];
56+
} page_directory_t;
57+
58+
// Структура таблицы страниц
59+
typedef struct {
60+
page_table_entry_t entries[1024];
61+
} page_table_t;
62+
63+
// Функции для работы с paging
64+
void paging_init();
65+
void switch_page_directory(page_directory_t *dir);
66+
page_directory_t *get_current_page_directory();
67+
void map_page(void *virtual_addr, void *physical_addr, u32 flags);
68+
void unmap_page(void *virtual_addr);
69+
void *get_physical_address(void *virtual_addr);
70+
void page_fault_handler(registers_t regs);
71+
72+
#endif

src/kernel/kernel/kernel.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "../drivers/screen.h"
1111
#include "kernel.h"
1212
#include "utils.h"
13+
#include "../cpu/paging.h"
1314
#include "../kklibc/kklibc.h"
1415

1516
int shell_cursor_offset = 0;
@@ -26,7 +27,7 @@ void kmain() {
2627

2728
init_paging();
2829

29-
heap_init();
30+
heap_init();
3031

3132
// Приглашение
3233
kprint("\nKintsugi OS (C) 2025\nRepository: https://github.com/alexeev-prog/KintsugiOS\n");

src/kernel/kernel/utils.c

Lines changed: 2 additions & 2 deletions
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, minimal block size %d\n", meminfo.heap_size, meminfo.heap_start, meminfo.block_size);
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);
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);
@@ -145,7 +145,7 @@ void kmalloc_command(char** args) {
145145
}
146146

147147
int size = strtoint(args[0]);
148-
void* ptr = kmalloc(size);
148+
void* ptr = kmalloc_a(size);
149149

150150
char buf1[32] = "";
151151
hex_to_ascii((int)ptr, buf1);

0 commit comments

Comments
 (0)