mm: put all code into separate files
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
#include "../include/paging.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void *get_physaddr(void *virtualaddr) {
|
||||
unsigned long pdindex = (unsigned long)virtualaddr >> 22;
|
||||
unsigned long ptindex = (unsigned long)virtualaddr >> 12 & 0x03FF;
|
||||
|
||||
unsigned long *pd = (unsigned long *)0xFFFFF000;
|
||||
// Here you need to check whether the PD entry is present.
|
||||
|
||||
unsigned long *pt = ((unsigned long *)0xFFC00000) + (0x400 * pdindex);
|
||||
// Here you need to check whether the PT entry is present.
|
||||
|
||||
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; // Все страницы "не присутствуют"
|
||||
}
|
||||
}
|
||||
|
||||
// Получаем адрес таблицы страниц
|
||||
uint32_t *pt = ((uint32_t *)0xFFC00000) + (0x400 * pdindex);
|
||||
|
||||
// Устанавливаем отображение
|
||||
pt[ptindex] = phys | (flags & 0xFFF) | 0x1; // Флаги + present
|
||||
|
||||
// Сбрасываем TLB для этого адреса
|
||||
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 ГБ
|
||||
|
||||
uint32_t pdindex = virt >> 22; // Индекс в каталоге
|
||||
uint32_t ptindex = (virt >> 12) & 0x3FF; // Индекс в таблице страниц
|
||||
|
||||
uint32_t* pd = (uint32_t*)0xFFFFF000; // Каталог страниц
|
||||
|
||||
// Проверяем, существует ли таблица страниц
|
||||
if (!(pd[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
|
||||
|
||||
uint32_t* pt = ((uint32_t*)0xFFC00000) + (0x400 * pdindex);
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
pt[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Получаем таблицу страниц
|
||||
uint32_t* pt = ((uint32_t*)0xFFC00000) + (0x400 * pdindex);
|
||||
void* phys = alloc_page();
|
||||
if (!phys) while(1);
|
||||
|
||||
// Проверяем, не занята ли страница
|
||||
if (pt[ptindex] & 0x1) while(1); // Ошибка: страница уже отображена
|
||||
|
||||
pt[ptindex] = (uint32_t)phys | (flags & 0xFFF) | 0x1; // supervisor, present
|
||||
asm volatile("invlpg (%0)" : : "r" (virtualaddr) : "memory");
|
||||
}
|
||||
Reference in New Issue
Block a user