merge branch memory-shit into higher-half

This commit is contained in:
2025-05-10 15:48:10 +03:00
parent 65f543fa92
commit 767e74976f
14 changed files with 419 additions and 178 deletions
+106 -36
View File
@@ -1,17 +1,67 @@
#include "../include/paging.h"
#include <stdint.h>
#include "../include/string.h"
uint32_t get_pte(void *virtualaddr) {
uint32_t pdindex = (uint32_t)virtualaddr >> 22;
uint32_t ptindex = (uint32_t)virtualaddr >> 12 & 0x3FF;
uint32_t *pd = (uint32_t *)0xFFFFF000;
if (!(pd[pdindex] & 0x1)) {
printf("GET_PTE ERROR: PT not present\n");
return 0;
}
uint32_t *pt = (uint32_t*)(0xFFC00000 + (pdindex << 12));
return pt[ptindex];
}
static uint32_t next_user_virt = 0x00400000;
void* setup_user_process(void* user_code_phys, uint32_t* user_stack_top) {
if ((uint32_t)user_code_phys & 0xFFF) {
printf("SETUP_USER_PROCESS ERROR: user_code_phys not aligned\n");
return 0;
}
void* stack_phys = alloc_page();
if (!stack_phys) return 0;
uint32_t code_virt = next_user_virt;
uint32_t stack_virt = code_virt + 0x3FF000; // 4 МБ - 4 КБ
if (next_user_virt >= 0xC0000000 - 0x400000) {
printf("SETUP_USER_PROCESS ERROR: out of user address space\n");
return 0;
}
unmap_page((void*)code_virt);
unmap_page((void*)stack_virt);
map_page(user_code_phys, (void*)code_virt, 0x7);
map_page(stack_phys, (void*)stack_virt, 0x7);
// Verify mappings
uint32_t code_pte = get_pte((void*)code_virt);
uint32_t stack_pte = get_pte((void*)stack_virt);
uint32_t check_pte = get_pte((void*)0x00400000);
*user_stack_top = stack_virt + 0x1000;
printf("Code PTE at 0x%x: 0x%x (phys 0x%x, %s, %s)\n",
code_virt, code_pte, code_pte & ~0xFFF,
(code_pte & 0x2) ? "writable" : "read-only",
(code_pte & 0x4) ? "user" : "supervisor");
printf("Stack PTE at 0x%x: 0x%x (phys 0x%x, %s, %s)\n",
stack_virt, stack_pte, stack_pte & ~0xFFF,
(stack_pte & 0x2) ? "writable" : "read-only",
(stack_pte & 0x4) ? "user" : "supervisor");
printf("PTE for 0x00400000: 0x%x (phys 0x%x, %s, %s)\n",
check_pte, check_pte & ~0xFFF,
(check_pte & 0x2) ? "writable" : "read-only",
(check_pte & 0x4) ? "user" : "supervisor");
*user_stack_top = stack_virt + 0x1000 -4;//here we place the stack pointer to its top (because the stack is growing down)
next_user_virt += 0x400000; // Следующий 4 МБ блок
return (void*)code_virt;
}
@@ -34,41 +84,62 @@ void *get_physaddr(void *virtualaddr) {
return (void *)((pt[ptindex] & ~0xFFF) + ((unsigned long)virtualaddr & 0xFFF));
}
void map_page(void* physaddr, void* virtualaddr, unsigned int flags) {
// Убеждаемся, что адреса выровнены по 4 КБ
uint32_t phys = (uint32_t)physaddr & ~0xFFF; // Обнуляем младшие 12 бит
uint32_t virt = (uint32_t)virtualaddr & ~0xFFF;
// Вычисляем индексы
uint32_t pdindex = virt >> 22; // Индекс в каталоге страниц
uint32_t ptindex = (virt >> 12) & 0x3FF; // Индекс в таблице страниц
uint32_t *pd = (uint32_t *)0xFFFFF000; // Адрес каталога страниц в виртуальной памяти
// Проверяем, существует ли таблица страниц
if (!(pd[pdindex] & 0x1)) { // Бит 0 — "present"
// Если таблицы нет, создаём новую
void *new_pt = alloc_page();
if (!new_pt) while (1); // Нет памяти
pd[pdindex] = (uint32_t)new_pt | 0x3; // present, writable
// Очищаем новую таблицу
uint32_t *pt = ((uint32_t *)0xFFC00000) + (0x400 * pdindex);
for (int i = 0; i < 1024; i++) {
pt[i] = 0; // Все страницы "не присутствуют"
}
void map_page(void *physaddr, void *virtualaddr, unsigned int flags) {
// Make sure that both addresses are page-aligned.
if ((unsigned long)physaddr & 0xFFF || (unsigned long)virtualaddr & 0xFFF) {
// Error handling: addresses not page-aligned
printf("MAP_PAGE ERROR: address not page-aligned\n");
return;
}
// Получаем адрес таблицы страниц
uint32_t *pt = ((uint32_t *)0xFFC00000) + (0x400 * pdindex);
// Устанавливаем отображение
pt[ptindex] = phys | (flags & 0xFFF) | 0x1; // Флаги + present
unsigned long pdindex = (unsigned long)virtualaddr >> 22;
unsigned long ptindex = (unsigned long)virtualaddr >> 12 & 0x03FF;
// Сбрасываем TLB для этого адреса
unsigned long *pd = (unsigned long *)0xFFFFF000;
// Here you need to check whether the PD entry is present.
// When it is not present, you need to create a new empty PT and
// adjust the PDE accordingly.
if (!(pd[pdindex] & 0x1)) { // If PDE not present
unsigned long *new_pt = alloc_page();
unsigned long *virt_pt = (unsigned long *)(0xC0000000 + new_pt);
memset(virt_pt, 0, 4096);
//pd[pdindex] = (uint32_t)new_pt | 0x3; // Present, R/W
pd[pdindex] = (uint32_t)new_pt | (flags & 0x7); // Add User bit if needed
}
unsigned long *pt = ((unsigned long *)0xFFC00000) + (0x400 * pdindex);
// Here you need to check whether the PT entry is present.
// When it is, then there is already a mapping present. What do you do now?
pt[ptindex] = ((unsigned long)physaddr) | (flags & 0xFFF); // Present
// Now you need to flush the entry in the TLB
// or you might not notice the change.
asm volatile("invlpg (%0)" : : "r" (virtualaddr) : "memory");
}
void unmap_page(void *virtualaddr) {
// Calculate page directory and page table indices
unsigned long pdindex = (unsigned long)virtualaddr >> 22;
unsigned long ptindex = (unsigned long)virtualaddr >> 12 & 0x03FF;
// Get the page directory
unsigned long *pd = (unsigned long *)0xFFFFF000;
if (pd[pdindex] & 0x1) { // Check if the page directory entry is present
// Get the page table
unsigned long *pt = (unsigned long *)(0xFFC00000 + (pdindex << 12));
// Clear the page table entry (remove the mapping)
pt[ptindex] = 0;
// Invalidate the TLB entry for this virtual address
asm volatile("invlpg (%0)" : : "r" (virtualaddr) : "memory");
}
}
void map_kernel_page(void* virtualaddr, unsigned int flags) {
uint32_t virt = (uint32_t)virtualaddr & ~0xFFF; // Выравниваем по 4 КБ
if (virt < 0xC0000000) while(1); // Ошибка: ядро только выше 3 ГБ
@@ -76,27 +147,26 @@ void map_kernel_page(void* virtualaddr, unsigned int flags) {
uint32_t pdindex = virt >> 22; // Индекс в каталоге
uint32_t ptindex = (virt >> 12) & 0x3FF; // Индекс в таблице страниц
uint32_t* pd = (uint32_t*)0xFFFFF000; // Каталог страниц
// Проверяем, существует ли таблица страниц
if (!(pd[pdindex] & 0x1)) {
if (!(kpage_dir[pdindex] & 0x1)) {
void* new_pt = alloc_page();
if (!new_pt) while(1); // Нет памяти
// Убеждаемся, что адрес выровнен
if ((uint32_t)new_pt & 0xFFF) while(1); // Ошибка выравнивания
pd[pdindex] = ((uint32_t)new_pt) | 0x3; // Временно записываем в каталог
asm volatile("invlpg (%0)" : : "r" ((uint32_t)&pd[pdindex]) : "memory"); // Инвалидируем TLB
kpage_dir[pdindex] = ((uint32_t)new_pt) | 0x3; // Временно записываем в каталог
asm volatile("invlpg (%0)" : : "r" ((uint32_t)&kpage_dir[pdindex]) : "memory"); // Инвалидируем TLB
uint32_t* pt = ((uint32_t*)0xFFC00000) + (0x400 * pdindex);
uint32_t* pt = ((uint32_t*)kpage_dir+0x1000) + (0x400 * pdindex);
for (int i = 0; i < 1024; i++) {
pt[i] = 0;
}
}
// Получаем таблицу страниц
uint32_t* pt = ((uint32_t*)0xFFC00000) + (0x400 * pdindex);
uint32_t* pt = ((uint32_t*)kpage_dir+0x1000) + (0x400 * pdindex);
void* phys = alloc_page();
if (!phys) while(1);