tasking, mm: remove unused functions and page_directory field from the Task struct

This commit is contained in:
2025-06-01 14:04:49 +03:00
parent 5f87e55067
commit d1ac41deeb
7 changed files with 10 additions and 642 deletions
+1 -9
View File
@@ -31,10 +31,6 @@
// Размер битмапа в байтах (округлено вверх)
#define BITMAP_SIZE (PAGE_COUNT / 8)
extern uint32_t kernel_page_directory[1024] __attribute__((aligned(4096)));
extern uint32_t kernel_page_table[1024] __attribute__((aligned(4096)));
extern uint32_t user_page_table[1024] __attribute__((aligned(4096)));
extern uint32_t *kpage_dir;
//paging.c
@@ -42,9 +38,7 @@ void grub_memory_map(unsigned int magic, struct multiboot_info* mbi);
uint32_t* get_page_dir();
void set_page_dir(uint32_t new_page_dir);
uint32_t phys_to_virt(uint32_t phys);
uint32_t create_page_dir();
void enablePaging();
void loadPageDirectory(uint32_t* page_directory);
uint32_t* create_page_dir();
//page_alloc.c
void set_bit(uint32_t page_index);
@@ -59,7 +53,5 @@ uint32_t get_pte(void *virtualaddr);
void map_page(void* physaddr, void* virtualaddr, unsigned int flags);
void unmap_page(void *virtualaddr);
int map_page_in_directory(uint32_t* pd_virt_addr, void* phys_addr, void* virt_addr, uint32_t flags);
void map_kernel_page(void* virtualaddr, unsigned int flags);
void* setup_user_process(uint32_t* pd, void* user_code_phys, uint32_t* user_stack_top);
#endif
-1
View File
@@ -58,7 +58,6 @@ typedef struct Process
TrapFrame* tf; // Trap frame (только для ring 3)
uint32_t ring; // Уровень привилегий (0 или 3)
struct Process* next; // Следующий процесс
uint32_t* page_directory; // Директория страниц
} Process;
Process* task_create(uint32_t func, void** args, uint32_t arg_count, uint32_t ring, uint32_t* pagedir);
-91
View File
@@ -17,60 +17,6 @@ uint32_t get_pte(void *virtualaddr) {
return pt[ptindex];
}
static uint32_t next_user_virt = 0x00400000;
void* setup_user_process(uint32_t* pd, 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_in_directory(pd, user_code_phys, (void*)code_virt, 0x7);
map_page_in_directory(pd, 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);
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;
}
void free_user_process(void* code_phys, void* stack_phys) {
free_page(code_phys);
free_page(stack_phys);
}
void *get_physaddr(void *virtualaddr) {
unsigned long pdindex = (unsigned long)virtualaddr >> 22;
unsigned long ptindex = (unsigned long)virtualaddr >> 12 & 0x03FF;
@@ -194,40 +140,3 @@ int map_page_in_directory(uint32_t* pd_virt_addr, void* phys_addr, void* virt_ad
return 0; // Success
}
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; // Индекс в таблице страниц
// Проверяем, существует ли таблица страниц
if (!(kpage_dir[pdindex] & 0x1)) {
void* new_pt = alloc_page();
if (!new_pt) while(1); // Нет памяти
// Убеждаемся, что адрес выровнен
if ((uint32_t)new_pt & 0xFFF) while(1); // Ошибка выравнивания
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*)kpage_dir+0x1000) + (0x400 * pdindex);
for (int i = 0; i < 1024; i++) {
pt[i] = 0;
}
}
// Получаем таблицу страниц
uint32_t* pt = ((uint32_t*)kpage_dir+0x1000) + (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");
}
+2 -31
View File
@@ -2,10 +2,6 @@
#include <stdint.h>
#include "../include/string.h"
uint32_t kernel_page_directory[1024] __attribute__((aligned(4096)));
uint32_t kernel_page_table[1024] __attribute__((aligned(4096)));
uint32_t user_page_table[1024] __attribute__((aligned(4096)));
uint32_t *kpage_dir;
uint32_t setup_tmp_pgdir(uint32_t magic, uint32_t info)
@@ -128,7 +124,7 @@ uint32_t phys_to_virt(uint32_t phys)
return phys+0xC0000000;
}
uint32_t create_page_dir()
uint32_t* create_page_dir()
{
void* ppp = alloc_page();
memset(ppp, 0, 0x1000);
@@ -148,30 +144,5 @@ uint32_t create_page_dir()
new_pd[1023] = (uint32_t)ppp | 0x03; // Present + Read/Write
return (uint32_t)new_pd;
}
void enablePaging() {
asm volatile (
"mov %%cr0, %%eax\n"
"or $0x80000000, %%eax\n"
"mov %%eax, %%cr0\n"
"jmp 1f\n"
"1:\n"
"mov %%cr3, %%eax\n" // Перезагрузка CR3 для сброса TLB
"mov %%eax, %%cr3\n"
"nop\n"
:
:
: "eax", "memory"
);
}
void loadPageDirectory(uint32_t* page_directory) {
asm volatile (
"mov %0, %%cr3\n" // Загружаем физический адрес каталога страниц в CR3
: // Нет выходных операндов
: "r" (page_directory) // Входной операнд — адрес каталога
: // Нет изменяемых регистров
);
return new_pd;
}
-503
View File
@@ -1,503 +0,0 @@
#include "../include/paging.h"
#include <stdint.h>
#include "../include/stdio.h"
void enablePaging() {
asm volatile (
"mov %%cr0, %%eax\n"
"or $0x80000000, %%eax\n"
"mov %%eax, %%cr0\n"
"jmp 1f\n"
"1:\n"
"mov %%cr3, %%eax\n" // Перезагрузка CR3 для сброса TLB
"mov %%eax, %%cr3\n"
"nop\n"
:
:
: "eax", "memory"
);
}
void loadPageDirectory(uint32_t* page_directory) {
asm volatile (
"mov %0, %%cr3\n" // Загружаем физический адрес каталога страниц в CR3
: // Нет выходных операндов
: "r" (page_directory) // Входной операнд — адрес каталога
: // Нет изменяемых регистров
);
}
uint32_t kernel_page_directory[1024] __attribute__((aligned(4096)));
uint32_t kernel_page_table[1024] __attribute__((aligned(4096)));
// 16 МБ = 16 * 1024 * 1024 байт = 4096 страниц (по 4 КБ)
// 4096 бит = 512 байт
uint8_t page_bitmap[512]; // 1 бит на страницу
/**
page_bitmap — массив, где каждый бит соответствует странице (0 = свободна, 1 = занята).
init_allocator помечает первые 4 МБ как занятые (там ядро).
alloc_page ищет первый свободный бит и возвращает адрес страницы.
free_page освобождает страницу, сбрасывая бит.
**/
void init_allocator() {
int i;
// Помечаем все страницы как свободные (0)
for (i = 0; i < 512; i++) {
page_bitmap[i] = 0;
}
// Первые 4 МБ уже заняты ядром (0x000000000x003FFFFF)
for (i = 0; i < 1024 / 8; i++) { // 1024 страницы = 128 байт
page_bitmap[i] = 0xFF; // Все биты = 1 (занято)
}
}
// Выделяем свободную страницу
void* alloc_page() {
// printf("alloc_page called\n");
int i, j;
for (i = 0; i < 512; i++) {
if (page_bitmap[i] != 0xFF) {
for (j = 0; j < 8; j++) {
if (!(page_bitmap[i] & (1 << j))) {
page_bitmap[i] |= (1 << j);
return (void*)(((i * 8) + j) * 0x1000);
}
}
}
}
printf("no bitches? no free pages?\n");
return (void*)0; // Нет свободных страниц
}
void test_paging() {
uint32_t* pd = (uint32_t*)0xFFFFF000;
uint32_t expected = (uint32_t)kernel_page_table | 0x3;
// Игнорируем дополнительные флаги, проверяем только базовый адрес и present
if ((pd[0] & ~0xFFF) == (expected & ~0xFFF)) {
// Успех
} else {
printf("RECURSION BROKEN!!\n");
printf("pd[0] = 0x%X\n");
printf("(uint32_t)first_page_table | 0x3 = %X", (uint32_t)kernel_page_table | 0x3);
while (1); // Рекурсия сломана
}
}
// Освобождаем страницу
void free_page(void *physaddr) {
uint32_t page_num = (uint32_t)physaddr / 0x1000;
uint32_t byte_idx = page_num / 8;
uint32_t bit_idx = page_num % 8;
page_bitmap[byte_idx] &= ~(1 << bit_idx); // Сбрасываем бит
}
/**
Теперь первые 4 МБ физической памяти отображаются на виртуальный адрес 0xC0000000 (3 ГБ), а не на 0x00000000.
Это оставляет нижние 3 ГБ (0x000000000xBFFFFFFF) свободными для пользовательских процессов.
**/
void paging_init()
{
int i;
// Проверяем физические адреса
uint32_t pd_phys = (uint32_t)kernel_page_directory;
uint32_t pt_phys = (uint32_t)kernel_page_table;
if (pd_phys & 0xFFF || pt_phys & 0xFFF) {
while (1); // Ошибка выравнивания
}
// Заполняем каталог страниц
for (i = 0; i < 1024; i++) {
kernel_page_directory[i] = 0x00000002; // not present
}
// Identity mapping для 0x000000000x003FFFFF
for (i = 0; i < 1024; i++) {
kernel_page_table[i] = (i * 0x1000) | 0x3; // supervisor, present
}
kernel_page_directory[0] = pt_phys | 0x3;
// Рекурсивное отображение
kernel_page_directory[1023] = pd_phys | 0x3;
// Проверяем перед загрузкой
if (kernel_page_directory[0] != (pt_phys | 0x3) ||
kernel_page_directory[1023] != (pd_phys | 0x3)) {
printf("OSHIBKA ZAPISI BLYA\n");
while (1); // Ошибка записи
}
loadPageDirectory(kernel_page_directory);
enablePaging();
}
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));
}
/**
Проверяем, существует ли таблица страниц (бит present в записи каталога).
Используем invlpg (inline assembly) для сброса TLB, чтобы процессор увидел изменения.
Пока вместо выделения новой таблицы страниц я добавил бесконечный цикл (while(1)). Позже мы заменим это аллокатором.
**/
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");
}
//map_kernel_page((void*)0xC0100000, 0x2); — отобразит страницу в ядре.
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); // Нет памяти
// Убеждаемся, что адрес выровнен (опционально, если alloc_page() не гарантирует)
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");
}
// Структура заголовка блока памяти
typedef struct Block {
uint32_t size; // Размер блока (в байтах, включая заголовок)
uint32_t is_free; // 1 = свободен, 0 = занят
struct Block* next; // Указатель на следующий блок
} Block;
// Структура для управления кучей
typedef struct {
void* start; // Начало кучи
uint32_t size; // Текущий размер кучи в байтах
Block* first; // Первый блок в куче
} Heap;
Heap kernel_heap;
void heap_init() {
kernel_heap.start = (void*)0xD0000000; // Начало кучи в ядре
kernel_heap.size = 0x1000; // Начальный размер — 1 страница (4 КБ)
printf("before map_kernel_page\n");
// Отображаем первую страницу
map_kernel_page(kernel_heap.start, 0x2); // writable, supervisor
printf("after map_kernel_page\n");
// Создаём первый блок, который занимает всю страницу
Block* initial_block = (Block*)kernel_heap.start;
initial_block->size = 0x1000 - sizeof(Block); // Размер без учёта заголовка
initial_block->is_free = 1; // Свободен
initial_block->next = (Block*)0; // Пока нет следующего
kernel_heap.first = initial_block;
}
// Выделение памяти из кучи
//Ищет свободный блок подходящего размера. Если блок большой, делит его.
//Если свободных блоков нет, добавляет страницу.
void* heap_alloc(uint32_t size) {
// Выравниваем размер до 4 байт
size = (size + 3) & ~3;
Block* current = kernel_heap.first;
Block* prev = (Block*)0;
// Ищем подходящий свободный блок
while (current) {
if (current->is_free && current->size >= size) {
if (current->size >= size + sizeof(Block) + 4) {
Block* new_block = (Block*)((uint32_t)current + sizeof(Block) + size);
new_block->size = current->size - size - sizeof(Block);
new_block->is_free = 1;
new_block->next = current->next;
current->size = size;
current->next = new_block;
}
current->is_free = 0;
return (void*)((uint32_t)current + sizeof(Block));
}
prev = current;
current = current->next;
}
// Нет подходящего блока — выделяем нужное количество страниц
uint32_t total_size = size + sizeof(Block); // Размер с заголовком
uint32_t pages_needed = (total_size + 0xFFF) / 0x1000; // Округляем вверх до страниц
uint32_t alloc_size = pages_needed * 0x1000; // Сколько байт выделяем
void* new_page = (void*)((uint32_t)kernel_heap.start + kernel_heap.size);
for (uint32_t i = 0; i < pages_needed; i++) {
map_kernel_page((void*)((uint32_t)new_page + i * 0x1000), 0x2);
}
kernel_heap.size += alloc_size;
Block* new_block = (Block*)new_page;
new_block->size = alloc_size - sizeof(Block);
new_block->is_free = 1;
new_block->next = (Block*)0;
if (prev) prev->next = new_block;
if (!kernel_heap.first) kernel_heap.first = new_block;
// Теперь current указывает на новый блок, продолжаем цикл
current = new_block;
if (current->size >= size) {
if (current->size >= size + sizeof(Block) + 4) {
Block* split_block = (Block*)((uint32_t)current + sizeof(Block) + size);
split_block->size = current->size - size - sizeof(Block);
split_block->is_free = 1;
split_block->next = current->next;
current->size = size;
current->next = split_block;
}
current->is_free = 0;
return (void*)((uint32_t)current + sizeof(Block));
}
// Если что-то пошло не так, возвращаем NULL
return (void*)0;
}
// Освобождение памяти
//Помечает блок как свободный и пытается объединить его с соседними свободными блоками,
//чтобы уменьшить фрагментацию.
void heap_free(void* ptr) {
if (!ptr || (uint32_t)ptr < (uint32_t)kernel_heap.start) return;
// Находим блок по указателю (указатель указывает после заголовка)
Block* block = (Block*)((uint32_t)ptr - sizeof(Block));
block->is_free = 1;
// Слияние с предыдущим блоком, если он свободен
Block* current = kernel_heap.first;
Block* prev = (Block*)0;
while (current && current != block) {
prev = current;
current = current->next;
}
if (prev && prev->is_free) {
prev->size += sizeof(Block) + block->size;
prev->next = block->next;
block = prev;
}
// Слияние с следующим блоком, если он свободен
if (block->next && block->next->is_free) {
block->size += sizeof(Block) + block->next->size;
block->next = block->next->next;
}
}
// Функция проверки страниц
void test_pages() {
// Тест 1: Проверка ядра
void* kernel_addr = (void*)0xC0100000;
map_kernel_page(kernel_addr, 0x2); // writable, supervisor
// Записываем значение в страницу
uint32_t* kernel_ptr = (uint32_t*)kernel_addr;
*kernel_ptr = 0xDEADBEEF;
// Проверяем, что значение записалось
if (*kernel_ptr == 0xDEADBEEF) {
// Успех! (в реальной ОС тут можно вывести сообщение через UART или VGA)
} else {
while (1); // Ошибка
}
/*
// Тест 2: Проверка пользовательского процесса
Process* proc = create_process(1); // Создаём процесс
void* user_addr = (void*)0x1000;
map_user_page(proc, user_addr, 0x6); // writable, user
// Переключаемся на процесс
switch_to_process(proc);
// Записываем значение
uint32_t* user_ptr = (uint32_t*)user_addr;
*user_ptr = 0xCAFEBABE;
// Проверяем
if (*user_ptr == 0xCAFEBABE) {
// Успех!
} else {
while (1); // Ошибка
}
// Возвращаемся в ядро
switch_to_process((Process*)0); // Предполагаем, что 0 вернёт нас к kernel_page_directory
*/
// Тест 3: Проверка кучи
heap_init();
void* heap_ptr1 = heap_alloc(16);
uint32_t* heap_data1 = (uint32_t*)heap_ptr1;
*heap_data1 = 0x12345678;
void* heap_ptr2 = heap_alloc(200);
uint32_t* heap_data2 = (uint32_t*)heap_ptr2;
*heap_data2 = 0x87654321;
heap_free(heap_ptr1);
void* heap_ptr3 = heap_alloc(12); // Должно взять место ptr1
if (*heap_data1 == 0x12345678 && *heap_data2 == 0x87654321 &&
heap_ptr3 == heap_ptr1) {
// Успех!
} else {
while (1); // Ошибка
}
}
/**
0xD0000000: Произвольный адрес в ядре (выше 0xC0000000), выбран для кучи, чтобы не пересекаться с другими данными.
0xFFFFF000: Виртуальный адрес каталога страниц благодаря рекурсивному отображению (последняя запись указывает на себя).
0xFFC00000: Начало области, где лежат все таблицы страниц, доступные через рекурсию.
**/
/**
Dalshe idyot to chto napisal grok dlya processov v buduschem
**/
/*
// Структура для процесса
typedef struct {
uint32_t page_directory[1024] __attribute__((aligned(4096))); // Каталог страниц процесса
uint32_t pid; // ID процесса (для примера)
} Process;
// Создание нового процесса
//Создаёт новый каталог страниц для процесса, копируя ядро (768–1023 записи) и оставляя нижние 3 ГБ пустыми.
Process* create_process(uint32_t pid) {
Process* proc = (Process*)alloc_page(); // Выделяем страницу под структуру
if (!proc) return (Process*)0; // Нет памяти
int i;
// Копируем каталог ядра в каталог процесса
for (i = 0; i < 1024; i++) {
proc->page_directory[i] = kernel_page_directory[i];
}
// Нижние 3 ГБ (0-767) изначально пустые
for (i = 0; i < 768; i++) {
proc->page_directory[i] = 0x00000002; // not present
}
proc->pid = pid;
return proc;
}
// Переключение на процесс
//Переключает процессор на каталог страниц процесса.
void switch_to_process(Process* proc) {
loadPageDirectory(proc->page_directory);
}
//Выделяет страницу в пользовательском пространстве (ниже 0xC0000000) с флагами user-level (бит 2 = 1).
void map_user_page(Process* proc, void* virtualaddr, unsigned int flags) {
uint32_t virt = (uint32_t)virtualaddr & ~0xFFF;
if (virt >= 0xC0000000) while(1); // Ошибка: пользователь не может трогать ядро!
uint32_t pdindex = virt >> 22;
uint32_t ptindex = (virt >> 12) & 0x3FF;
// Проверяем, есть ли таблица страниц
if (!(proc->page_directory[pdindex] & 0x1)) {
void* new_pt = alloc_page();
if (!new_pt) while(1); // Нет памяти
// Новая таблица: user, writable, present (0x7 = 111b)
proc->page_directory[pdindex] = ((uint32_t)new_pt) | 0x7;
// Очищаем таблицу
uint32_t* pt = (uint32_t*)new_pt;
for (int i = 0; i < 1024; i++) {
pt[i] = 0; // Все страницы "не присутствуют"
}
}
// Получаем таблицу страниц
uint32_t* pt = (uint32_t*)(proc->page_directory[pdindex] & ~0xFFF);
void* phys = alloc_page();
if (!phys) while(1); // Нет памяти
// Отображаем страницу: user, flags, present
pt[ptindex] = (uint32_t)phys | (flags & 0xFFF) | 0x5; // 0x5 = 101b (present, user)
// Сбрасываем TLB
asm volatile("invlpg (%0)" : : "r" (virtualaddr) : "memory");
}
// Пример использования
void test_process() {
Process* proc = create_process(1); // Создаём процесс с PID 1
map_user_page(proc, (void*)0x1000, 0x6); // Отображаем страницу на 0x1000 (writable, user)
switch_to_process(proc); // Переключаемся на процесс
}
*/
+1 -1
View File
@@ -32,7 +32,7 @@ switchProcess:
mov esp, [edx + 4] ; esp = next_process_ptr->kesp
mov [current], edx ; current = next_process_ptr
mov eax, [edx + 40]
mov eax, [edx + 12]
sub eax, 0xC0000000
mov cr3, eax
+6 -6
View File
@@ -56,7 +56,7 @@ Process* task_create(uint32_t func, void** args, uint32_t arg_count, uint32_t ri
p->tf->eflags = FL_IF;
p->tf->eip = (uint32_t)func;
p->page_directory = pagedir;//(uint32_t*)create_page_dir();
p->pagedir = pagedir;//(uint32_t*)create_page_dir();
if(ring == 3)
{
@@ -65,7 +65,7 @@ Process* task_create(uint32_t func, void** args, uint32_t arg_count, uint32_t ri
uint32_t user_stack_virtual_top = 0xBFFFF000 - ((p->pid -1) * (USTACKSIZE + 4096)); // Уникальный верх стека для каждого процесса
uint32_t user_stack_virtual_base = user_stack_virtual_top - USTACKSIZE;
map_page_in_directory(p->page_directory, user_stack_physical, (void*)user_stack_virtual_base, PAGE_PRESENT | PAGE_RW | PAGE_USER); // Флаги 0x7
map_page_in_directory(p->pagedir, user_stack_physical, (void*)user_stack_virtual_base, PAGE_PRESENT | PAGE_RW | PAGE_USER); // Флаги 0x7
p->tf->usermode_esp = user_stack_virtual_top;
@@ -193,12 +193,12 @@ void jump_usermode2(void) {
printf("Copied code to 0x%x (virt 0x%x)\n",
(uint32_t)code_phys, kernel_temp_virt);
uint32_t* proc_pd = (uint32_t*)create_page_dir();
uint32_t* proc2_pd = (uint32_t*)create_page_dir();
uint32_t* proc_pd = create_page_dir();
uint32_t* proc2_pd = create_page_dir();
Process* p_task1 = task_create(0x400000, NULL, 0, 3, proc_pd);
Process* p_task2 = task_create(0x400000, NULL, 0, 3, proc2_pd);
if (map_page_in_directory(p_task1->page_directory,
if (map_page_in_directory(p_task1->pagedir,
code_phys,
(void*)0x400000,
PAGE_PRESENT | PAGE_RW | PAGE_USER) != 0) { // PAGE_USER is critical, PAGE_RW for now, can be R-X
@@ -208,7 +208,7 @@ void jump_usermode2(void) {
return;
}
if (map_page_in_directory(p_task2->page_directory,
if (map_page_in_directory(p_task2->pagedir,
second_code_phys,
(void*)0x400000,
PAGE_PRESENT | PAGE_RW | PAGE_USER) != 0) { // PAGE_USER is critical, PAGE_RW for now, can be R-X