merge branch memory-shit into higher-half
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
OBJS = bin/boot.o bin/kernel.o bin/idt.o bin/isr.o bin/screen.o \
|
OBJS = bin/boot.o bin/kernel.o bin/idt.o bin/isr.o bin/screen.o \
|
||||||
bin/utils.o bin/string.o bin/stdio.o bin/disk.o bin/pic.o bin/pit.o \
|
bin/utils.o bin/string.o bin/stdio.o bin/disk.o bin/pic.o bin/pit.o \
|
||||||
bin/keyboard.o bin/paging.o bin/heap.o bin/page_alloc.o bin/page_tables.o \
|
bin/keyboard.o bin/paging.o bin/heap.o bin/page_alloc.o bin/page_tables.o \
|
||||||
bin/fat.o bin/task.o bin/switch.o bin/sys_exit.o bin/gdt.o
|
bin/fat.o bin/task.o bin/switch.o bin/sys_exit.o bin/gdt.o bin/isr-asm.o
|
||||||
|
|
||||||
# Define the compiler and assembler
|
# Define the compiler and assembler
|
||||||
#CC = i686-elf-gcc -D__is_katauos
|
#CC = i686-elf-gcc -D__is_katauos
|
||||||
@@ -16,7 +16,7 @@ CFLAGS = -I./include/ -std=gnu99 -ffreestanding -O0 -Wall -Wextra -m32 -fno-pie
|
|||||||
ASFLAGS = -f elf32
|
ASFLAGS = -f elf32
|
||||||
|
|
||||||
# Define the linker flags
|
# Define the linker flags
|
||||||
LDFLAGS = -m elf_i386 -L$(shell $(CC) -print-libgcc-file-name | xargs dirname)
|
LDFLAGS = -m elf_i386 -L$(shell $(CC) -print-libgcc-file-name | xargs dirname)/32/ -lgcc
|
||||||
LDSCRIPT = link.ld
|
LDSCRIPT = link.ld
|
||||||
|
|
||||||
# Define the output file
|
# Define the output file
|
||||||
@@ -124,6 +124,9 @@ bin/sys_exit.o: src/tasking/sys_exit.asm
|
|||||||
bin/gdt.o: src/kernel/gdt.c
|
bin/gdt.o: src/kernel/gdt.c
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
bin/isr-asm.o: src/kernel/isr.asm
|
||||||
|
$(AS) $(ASFLAGS) $< -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf bin/
|
rm -rf bin/
|
||||||
rm -f $(OUTPUT)
|
rm -f $(OUTPUT)
|
||||||
|
|||||||
+3
-1
@@ -88,7 +88,9 @@ struct tss_entry_struct {
|
|||||||
uint32_t ldt;
|
uint32_t ldt;
|
||||||
uint16_t trap;
|
uint16_t trap;
|
||||||
uint16_t iomap_base;
|
uint16_t iomap_base;
|
||||||
} __packed;
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
extern struct tss_entry_struct tss;
|
||||||
|
|
||||||
struct seg_desc gdt[NR_GDT_ENTRIES];
|
struct seg_desc gdt[NR_GDT_ENTRIES];
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -230,8 +230,10 @@ struct multiboot_color
|
|||||||
struct multiboot_mmap_entry
|
struct multiboot_mmap_entry
|
||||||
{
|
{
|
||||||
multiboot_uint32_t size;
|
multiboot_uint32_t size;
|
||||||
multiboot_uint64_t addr;
|
multiboot_uint32_t addr_low;
|
||||||
multiboot_uint64_t len;
|
multiboot_uint32_t addr_high;
|
||||||
|
multiboot_uint32_t len_low;
|
||||||
|
multiboot_uint32_t len_high;
|
||||||
#define MULTIBOOT_MEMORY_AVAILABLE 1
|
#define MULTIBOOT_MEMORY_AVAILABLE 1
|
||||||
#define MULTIBOOT_MEMORY_RESERVED 2
|
#define MULTIBOOT_MEMORY_RESERVED 2
|
||||||
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
|
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
|
||||||
|
|||||||
@@ -22,10 +22,23 @@
|
|||||||
#define GET_PGDIR(address) ((uint32_t)((address) >> 22) & 0x3FF)
|
#define GET_PGDIR(address) ((uint32_t)((address) >> 22) & 0x3FF)
|
||||||
#define GET_PGTBL(address) ((uint32_t)((address) >> 12) & 0x3FF)
|
#define GET_PGTBL(address) ((uint32_t)((address) >> 12) & 0x3FF)
|
||||||
|
|
||||||
|
#define PAGE_SIZE 0x1000 // 4 КБ
|
||||||
|
|
||||||
|
// Общий размер памяти
|
||||||
|
#define MEMORY_SIZE (0xFFFFFFFF-0xC0000000)
|
||||||
|
|
||||||
|
// Количество страниц
|
||||||
|
#define PAGE_COUNT (MEMORY_SIZE / PAGE_SIZE)
|
||||||
|
|
||||||
|
// Размер битмапа в байтах (округлено вверх)
|
||||||
|
#define BITMAP_SIZE (PAGE_COUNT / 8)
|
||||||
|
|
||||||
extern uint32_t kernel_page_directory[1024] __attribute__((aligned(4096)));
|
extern uint32_t kernel_page_directory[1024] __attribute__((aligned(4096)));
|
||||||
extern uint32_t kernel_page_table[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 user_page_table[1024] __attribute__((aligned(4096)));
|
||||||
|
|
||||||
|
extern uint32_t *kpage_dir;
|
||||||
|
|
||||||
//paging.c
|
//paging.c
|
||||||
void grub_memory_map(unsigned int magic, struct multiboot_info* mbi);
|
void grub_memory_map(unsigned int magic, struct multiboot_info* mbi);
|
||||||
void enablePaging();
|
void enablePaging();
|
||||||
@@ -34,13 +47,17 @@ void paging_init();
|
|||||||
void test_paging();
|
void test_paging();
|
||||||
|
|
||||||
//page_alloc.c
|
//page_alloc.c
|
||||||
|
void set_bit(uint32_t page_index);
|
||||||
|
void clear_bit(uint32_t page_index);
|
||||||
void init_allocator();
|
void init_allocator();
|
||||||
void* alloc_page();
|
void* alloc_page();
|
||||||
void free_page(void* physaddr);
|
void free_page(void* physaddr);
|
||||||
|
|
||||||
//page_tables.c
|
//page_tables.c
|
||||||
void *get_physaddr(void *virtualaddr);
|
void *get_physaddr(void *virtualaddr);
|
||||||
|
uint32_t get_pte(void *virtualaddr);
|
||||||
void map_page(void* physaddr, void* virtualaddr, unsigned int flags);
|
void map_page(void* physaddr, void* virtualaddr, unsigned int flags);
|
||||||
|
void unmap_page(void *virtualaddr);
|
||||||
void map_kernel_page(void* virtualaddr, unsigned int flags);
|
void map_kernel_page(void* virtualaddr, unsigned int flags);
|
||||||
void* setup_user_process(void* user_code_phys, uint32_t* user_stack_top);
|
void* setup_user_process(void* user_code_phys, uint32_t* user_stack_top);
|
||||||
|
|
||||||
|
|||||||
+26
-2
@@ -2,6 +2,8 @@
|
|||||||
#include "../include/string.h"
|
#include "../include/string.h"
|
||||||
#include "../include/paging.h"
|
#include "../include/paging.h"
|
||||||
|
|
||||||
|
struct tss_entry_struct tss;
|
||||||
|
|
||||||
void bss_init()
|
void bss_init()
|
||||||
{
|
{
|
||||||
memset((void *)((int)_edata), 0, KERNEL_BSS_SIZE);
|
memset((void *)((int)_edata), 0, KERNEL_BSS_SIZE);
|
||||||
@@ -29,6 +31,16 @@ void load_gdt(uint32_t gdt_ptr) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void flush_tss(void) {
|
||||||
|
asm volatile (
|
||||||
|
"mov %0, %%ax\n\t"
|
||||||
|
"ltr %%ax\n\t"
|
||||||
|
:
|
||||||
|
: "i" (0x28)
|
||||||
|
: "ax"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static void gdt_set_entry(int num, uint32_t base_addr, uint32_t limit, char loflags, char hiflags)
|
static void gdt_set_entry(int num, uint32_t base_addr, uint32_t limit, char loflags, char hiflags)
|
||||||
{
|
{
|
||||||
num /= sizeof(struct seg_desc);
|
num /= sizeof(struct seg_desc);
|
||||||
@@ -44,6 +56,17 @@ void gdt_init(void)
|
|||||||
{
|
{
|
||||||
uint8_t loflags;
|
uint8_t loflags;
|
||||||
|
|
||||||
|
memset(&tss, 0, sizeof(tss));
|
||||||
|
tss.ss0 = KERNEL_DS;
|
||||||
|
tss.iomap_base = 0xFFFF; // Disable I/O bitmap
|
||||||
|
tss.esp0 = 0xC0010000; /* kernel stack address (firstly defined in boot.asm)*/
|
||||||
|
tss.cs = KERNEL_CS;
|
||||||
|
tss.ds = KERNEL_DS;
|
||||||
|
tss.es = KERNEL_DS;
|
||||||
|
tss.fs = KERNEL_DS;
|
||||||
|
tss.gs = KERNEL_DS;
|
||||||
|
tss.ss = KERNEL_DS;
|
||||||
|
|
||||||
gdt_set_entry(0, 0, 0, 0, 0); /* null descriptor */
|
gdt_set_entry(0, 0, 0, 0, 0); /* null descriptor */
|
||||||
|
|
||||||
loflags = SD_CODE | SD_CD | SD_DPL0 | SD_PRESENT;
|
loflags = SD_CODE | SD_CD | SD_DPL0 | SD_PRESENT;
|
||||||
@@ -56,8 +79,9 @@ void gdt_init(void)
|
|||||||
loflags = SD_DATA | SD_CD | SD_DPL3 | SD_PRESENT;
|
loflags = SD_DATA | SD_CD | SD_DPL3 | SD_PRESENT;
|
||||||
gdt_set_entry(USER_DS, 0, 0xFFFFFFFF, loflags, SD_OPSIZE32 | SD_PAGE4KB);
|
gdt_set_entry(USER_DS, 0, 0xFFFFFFFF, loflags, SD_OPSIZE32 | SD_PAGE4KB);
|
||||||
|
|
||||||
loflags = SD_TSSPRESENT;
|
loflags = 0x89; // P=1, DPL=0, S=0 (system), Type=0x9 (32-bit TSS)
|
||||||
gdt_set_entry(TSS, 0, sizeof(struct tss_entry_struct), loflags, SD_OPSIZE32);
|
gdt_set_entry(TSS, (uint32_t)&tss, sizeof(struct tss_entry_struct) - 1, SD_PRESENT | SD_DPL0 | SD_TSSPRESENT, 0);
|
||||||
|
|
||||||
load_gdt((uint32_t)&gdtr);
|
load_gdt((uint32_t)&gdtr);
|
||||||
|
flush_tss();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
section .text
|
||||||
|
global page_fault_handler
|
||||||
|
extern handle_page_fault ; C function to process the fault
|
||||||
|
|
||||||
|
page_fault_handler:
|
||||||
|
; Save registers to preserve state
|
||||||
|
pushad ; Push EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
push fs
|
||||||
|
push gs
|
||||||
|
|
||||||
|
; Set up kernel data segment
|
||||||
|
mov ax, 0x10 ; Kernel data segment selector (adjust based on your GDT)
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
; Get the faulting address from CR2
|
||||||
|
mov eax, cr2
|
||||||
|
|
||||||
|
; Push parameters for the C function:
|
||||||
|
; - Faulting address (from CR2)
|
||||||
|
; - Error code (at [esp + 48], after pushed registers and segment selectors)
|
||||||
|
push eax ; Push CR2 (faulting address)
|
||||||
|
mov ebx, [esp + 48] ; Get error code (adjust offset based on stack layout)
|
||||||
|
push ebx ; Push error code
|
||||||
|
|
||||||
|
; Call the C handler
|
||||||
|
call handle_page_fault
|
||||||
|
|
||||||
|
; Clean up parameters from stack
|
||||||
|
add esp, 8 ; Remove error code and CR2
|
||||||
|
|
||||||
|
; Restore registers
|
||||||
|
pop gs
|
||||||
|
pop fs
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
popad
|
||||||
|
|
||||||
|
; Remove error code from stack
|
||||||
|
add esp, 4 ; Pop error code
|
||||||
|
|
||||||
|
; Return from interrupt
|
||||||
|
iret ; Restore EIP, CS, EFLAGS (and ESP, SS if privilege change)
|
||||||
+27
-1
@@ -23,6 +23,7 @@ void isr_custom();
|
|||||||
void default_handler();
|
void default_handler();
|
||||||
|
|
||||||
extern void sys_exit_handler();
|
extern void sys_exit_handler();
|
||||||
|
extern void page_fault_handler();
|
||||||
|
|
||||||
void isr_install() {
|
void isr_install() {
|
||||||
idt_set_descriptor(0, (uint32)isr0, 0x8E);
|
idt_set_descriptor(0, (uint32)isr0, 0x8E);
|
||||||
@@ -39,7 +40,7 @@ void isr_install() {
|
|||||||
idt_set_descriptor(11, (uint32)isr11, 0x8E);
|
idt_set_descriptor(11, (uint32)isr11, 0x8E);
|
||||||
idt_set_descriptor(12, (uint32)isr12, 0x8E);
|
idt_set_descriptor(12, (uint32)isr12, 0x8E);
|
||||||
idt_set_descriptor(13, (uint32)isr13, 0x8E);
|
idt_set_descriptor(13, (uint32)isr13, 0x8E);
|
||||||
idt_set_descriptor(14, (uint32)isr14, 0x8E);
|
idt_set_descriptor(14, (uint32)page_fault_handler, 0x8E);
|
||||||
idt_set_descriptor(15, (uint32)isr15, 0x8E);
|
idt_set_descriptor(15, (uint32)isr15, 0x8E);
|
||||||
idt_set_descriptor(16, (uint32)isr16, 0x8E);
|
idt_set_descriptor(16, (uint32)isr16, 0x8E);
|
||||||
idt_set_descriptor(17, (uint32)isr17, 0x8E);
|
idt_set_descriptor(17, (uint32)isr17, 0x8E);
|
||||||
@@ -75,6 +76,31 @@ void default_handler()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "../include/paging.h"
|
||||||
|
|
||||||
|
void handle_page_fault(uint32_t error_code, uint32_t faulting_address)
|
||||||
|
{
|
||||||
|
int present = !(error_code & 0x1); // Bit 0: 0 = not present, 1 = protection violation
|
||||||
|
int write = error_code & 0x2; // Bit 1: 0 = read, 1 = write
|
||||||
|
int user = error_code & 0x4; // Bit 2: 0 = supervisor, 1 = user
|
||||||
|
int reserved = error_code & 0x8; // Bit 3: 0 = no reserved bits, 1 = reserved bits
|
||||||
|
int instruction = error_code & 0x10; // Bit 4: 0 = data, 1 = instruction fetch
|
||||||
|
|
||||||
|
uint32_t pte = get_pte((void*)faulting_address);
|
||||||
|
|
||||||
|
printf("Page fault at address 0x%x\n", faulting_address);
|
||||||
|
printf("Present: %X, Write: %X, User: %X, Reserved: %X, Instruction: %X\n",
|
||||||
|
present, write, user, reserved, instruction);
|
||||||
|
|
||||||
|
printf("PTE: 0x%X (phys: 0x%X, %s, %s)\n", pte, pte & ~0xFFF,
|
||||||
|
(pte & 0x2) ? "writable" : "read-only",
|
||||||
|
(pte & 0x4) ? "user" : "supervisor");
|
||||||
|
|
||||||
|
printf("ERR: 0x%X\n", error_code);
|
||||||
|
|
||||||
|
asm("hlt");
|
||||||
|
}
|
||||||
|
|
||||||
__attribute__((interrupt)) void isr_timer(struct interrupt_frame *frame)
|
__attribute__((interrupt)) void isr_timer(struct interrupt_frame *frame)
|
||||||
{
|
{
|
||||||
pit_init(100);
|
pit_init(100);
|
||||||
|
|||||||
+25
-6
@@ -153,7 +153,13 @@ void kmain(unsigned int magic, unsigned int info)
|
|||||||
printf("bootloader: %s\n", mbi.boot_loader_name);
|
printf("bootloader: %s\n", mbi.boot_loader_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("init_allocator...");
|
||||||
|
init_allocator();
|
||||||
|
printf("done\n");
|
||||||
|
|
||||||
|
printf("grub_memory_map...");
|
||||||
grub_memory_map(magic, &mbi);
|
grub_memory_map(magic, &mbi);
|
||||||
|
printf("done\n");
|
||||||
|
|
||||||
isr_install();
|
isr_install();
|
||||||
pic_remap(0x20, 0x28);
|
pic_remap(0x20, 0x28);
|
||||||
@@ -161,14 +167,27 @@ void kmain(unsigned int magic, unsigned int info)
|
|||||||
|
|
||||||
apply_pic_masks();
|
apply_pic_masks();
|
||||||
|
|
||||||
|
printf("done fucking with pages and memory map!\n");
|
||||||
|
char *test_str;
|
||||||
|
printf("test_str: %X, &test_str %X\n", test_str, &test_str);
|
||||||
|
test_str = alloc_page();
|
||||||
|
printf("test_str: %X, &test_str %X\n", test_str, &test_str);
|
||||||
|
free_page(test_str);
|
||||||
|
|
||||||
|
alloc_page();//TODO: fix this this, because now we MUST allocate a page for checks of successfulness of allocation to pass
|
||||||
|
//the first page is at 0x0 and in check we check by if(!<allocated page>) which returns 0 (false), yeah
|
||||||
|
|
||||||
|
|
||||||
|
//while(1){}
|
||||||
|
|
||||||
//paging_init();
|
//paging_init();
|
||||||
//printf("paging_init done\n");
|
//printf("paging_init done\n");
|
||||||
//test_paging();
|
//test_paging();
|
||||||
init_allocator();
|
|
||||||
heap_init();
|
//heap_init();
|
||||||
printf("after heap_init\n");
|
//printf("after heap_init\n");
|
||||||
__asm__ __volatile__ ("sti");
|
__asm__ __volatile__ ("sti");
|
||||||
//scheduler_init();
|
scheduler_init();
|
||||||
printf("Kernel init sequence completed\n");
|
printf("Kernel init sequence completed\n");
|
||||||
|
|
||||||
char yooo[256] = "heheh";
|
char yooo[256] = "heheh";
|
||||||
@@ -185,8 +204,8 @@ void kmain(unsigned int magic, unsigned int info)
|
|||||||
char temp1[1024] = "rusya_krutoy";
|
char temp1[1024] = "rusya_krutoy";
|
||||||
char temp2[1024] = "katya_tozhe_krutaya";
|
char temp2[1024] = "katya_tozhe_krutaya";
|
||||||
|
|
||||||
huy = heap_alloc(1024);
|
huy = alloc_page();//heap_alloc(1024);
|
||||||
huy2 = heap_alloc(1024);
|
huy2 = alloc_page();//heap_alloc(1024);
|
||||||
|
|
||||||
memcpy(huy, temp1, sizeof(temp1));
|
memcpy(huy, temp1, sizeof(temp1));
|
||||||
memcpy(huy2, temp2, sizeof(temp1));
|
memcpy(huy2, temp2, sizeof(temp1));
|
||||||
|
|||||||
+7
-1
@@ -33,7 +33,7 @@ void heap_init() {
|
|||||||
|
|
||||||
kernel_heap.first = initial_block;
|
kernel_heap.first = initial_block;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
void* heap_alloc(uint32_t size) {
|
void* heap_alloc(uint32_t size) {
|
||||||
// Выравниваем размер до 4 байт
|
// Выравниваем размер до 4 байт
|
||||||
size = (size + 3) & ~3;
|
size = (size + 3) & ~3;
|
||||||
@@ -98,6 +98,12 @@ void* heap_alloc(uint32_t size) {
|
|||||||
// Если что-то пошло не так, возвращаем NULL
|
// Если что-то пошло не так, возвращаем NULL
|
||||||
return (void*)0;
|
return (void*)0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
//TODO: fix it yo
|
||||||
|
void *heap_alloc(uint32_t size)
|
||||||
|
{
|
||||||
|
return alloc_page();
|
||||||
|
}
|
||||||
|
|
||||||
void heap_free(void* ptr) {
|
void heap_free(void* ptr) {
|
||||||
if (!ptr || (uint32_t)ptr < (uint32_t)kernel_heap.start) return;
|
if (!ptr || (uint32_t)ptr < (uint32_t)kernel_heap.start) return;
|
||||||
|
|||||||
+32
-49
@@ -1,52 +1,52 @@
|
|||||||
#include "../include/paging.h"
|
#include "../include/paging.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "../include/stdio.h"
|
#include "../include/stdio.h"
|
||||||
|
#include "../include/string.h"
|
||||||
#define PAGE_SIZE 0x1000 // 4 КБ
|
|
||||||
|
|
||||||
// Общий размер памяти
|
|
||||||
#define MEMORY_SIZE 0x100000000 // 4 ГБ
|
|
||||||
|
|
||||||
// Количество страниц
|
|
||||||
#define PAGE_COUNT (MEMORY_SIZE / PAGE_SIZE) // 1 048 576 страниц
|
|
||||||
|
|
||||||
// Размер битмапа в байтах (округлено вверх)
|
|
||||||
#define BITMAP_SIZE (PAGE_COUNT / 8) // 131 072 байт
|
|
||||||
|
|
||||||
// Битмап для отслеживания страниц
|
// Битмап для отслеживания страниц
|
||||||
// Каждый бит представляет одну страницу: 0 = свободна, 1 = занята
|
// Каждый бит представляет одну страницу: 0 = свободна, 1 = занята
|
||||||
uint8_t page_bitmap[BITMAP_SIZE];
|
uint8_t page_bitmap[BITMAP_SIZE];
|
||||||
|
|
||||||
|
// Установить бит (пометить страницу как занятую)
|
||||||
|
void set_bit(uint32_t page_index) {
|
||||||
|
uint32_t byte_index = page_index / 8; // Номер байта в битовой карте
|
||||||
|
uint8_t bit_offset = page_index % 8; // Смещение бита в байте
|
||||||
|
page_bitmap[byte_index] |= (1 << bit_offset); // Устанавливаем бит
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сбросить бит (пометить страницу как свободную)
|
||||||
|
void clear_bit(uint32_t page_index) {
|
||||||
|
if (page_index >= PAGE_COUNT) {
|
||||||
|
printf("clear_bit: address out of range\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t byte_index = page_index / 8;
|
||||||
|
uint8_t bit_offset = page_index % 8;
|
||||||
|
|
||||||
|
//check if this is needed at all except for debug purposes
|
||||||
|
if(!(page_bitmap[byte_index] & (1 << bit_offset)))
|
||||||
|
{
|
||||||
|
printf("clear_bit: page #0x%X already free\n", page_index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
page_bitmap[byte_index] &= ~(1 << bit_offset); // Сбрасываем бит
|
||||||
|
}
|
||||||
|
|
||||||
// Инициализация аллокатора страниц
|
// Инициализация аллокатора страниц
|
||||||
void init_allocator() {
|
void init_allocator() {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// Помечаем все страницы как свободные (0)
|
memset(page_bitmap, 0x00, BITMAP_SIZE);
|
||||||
for (i = 0; i < BITMAP_SIZE; i++) {
|
|
||||||
page_bitmap[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Резервируем первые 4 МБ для ядра (0x00000000-0x003FFFFF)
|
|
||||||
// Это 1024 страницы или 128 байт битмапа
|
|
||||||
for (i = 0; i < 1024 / 8; i++) {
|
|
||||||
page_bitmap[i] = 0xFF; // Все биты = 1 (занято)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Если вы используете higher-half kernel, то нужно также
|
|
||||||
// зарезервировать соответствующую область в верхней части памяти
|
|
||||||
// Например, если ядро отображено начиная с 0xC0000000 (3 ГБ):
|
|
||||||
uint32_t kernel_higher_start = 0xC0000000 / PAGE_SIZE / 8; // Индекс в битмапе
|
|
||||||
for (i = kernel_higher_start; i < kernel_higher_start + 1024 / 8; i++) {
|
|
||||||
page_bitmap[i] = 0xFF;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* alloc_page() {
|
void* alloc_page() {
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
// Проходим по всему битмапу
|
// Проходим по всему битмапу
|
||||||
for (i = 0; i < BITMAP_SIZE; i++) {
|
for (i = 0; i < BITMAP_SIZE; i++) {
|
||||||
if (page_bitmap[i] != 0xFF) { // Если в этом байте есть свободная страница
|
if (page_bitmap[i] != 0xFF) { // Если в этом байте есть свободная страница
|
||||||
|
//printf("!!!free page at 0x%X!!!\n", i);
|
||||||
for (j = 0; j < 8; j++) {
|
for (j = 0; j < 8; j++) {
|
||||||
if (!(page_bitmap[i] & (1 << j))) { // Если этот бит = 0 (свободен)
|
if (!(page_bitmap[i] & (1 << j))) { // Если этот бит = 0 (свободен)
|
||||||
page_bitmap[i] |= (1 << j); // Помечаем как занятый
|
page_bitmap[i] |= (1 << j); // Помечаем как занятый
|
||||||
@@ -55,7 +55,7 @@ void* alloc_page() {
|
|||||||
uint32_t page_num = i * 8 + j;
|
uint32_t page_num = i * 8 + j;
|
||||||
void* addr = (void*)(page_num * PAGE_SIZE);
|
void* addr = (void*)(page_num * PAGE_SIZE);
|
||||||
|
|
||||||
printf("allocated page at 0x%X (page #0x%X)\n", addr, page_num);
|
//printf("allocated page at 0x%X (page #0x%X)\n", addr, page_num);
|
||||||
|
|
||||||
return (void*)(page_num * PAGE_SIZE);
|
return (void*)(page_num * PAGE_SIZE);
|
||||||
}
|
}
|
||||||
@@ -79,22 +79,5 @@ void free_page(void* physaddr) {
|
|||||||
// Вычисляем номер страницы
|
// Вычисляем номер страницы
|
||||||
uint32_t page_num = addr / PAGE_SIZE;
|
uint32_t page_num = addr / PAGE_SIZE;
|
||||||
|
|
||||||
// Проверка границ
|
clear_bit(page_num);
|
||||||
if (page_num >= PAGE_COUNT) {
|
|
||||||
printf("free_page: address out of range\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Вычисляем индекс байта и бита в битмапе
|
|
||||||
uint32_t byte_idx = page_num / 8;
|
|
||||||
uint32_t bit_idx = page_num % 8;
|
|
||||||
|
|
||||||
// Проверяем, не освобождаем ли уже свободную страницу
|
|
||||||
if (!(page_bitmap[byte_idx] & (1 << bit_idx))) {
|
|
||||||
printf("free_page: page already free\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Освобождаем страницу
|
|
||||||
page_bitmap[byte_idx] &= ~(1 << bit_idx);
|
|
||||||
}
|
}
|
||||||
|
|||||||
+105
-35
@@ -1,17 +1,67 @@
|
|||||||
#include "../include/paging.h"
|
#include "../include/paging.h"
|
||||||
#include <stdint.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;
|
static uint32_t next_user_virt = 0x00400000;
|
||||||
void* setup_user_process(void* user_code_phys, uint32_t* user_stack_top) {
|
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();
|
void* stack_phys = alloc_page();
|
||||||
if (!stack_phys) return 0;
|
if (!stack_phys) return 0;
|
||||||
|
|
||||||
uint32_t code_virt = next_user_virt;
|
uint32_t code_virt = next_user_virt;
|
||||||
uint32_t stack_virt = code_virt + 0x3FF000; // 4 МБ - 4 КБ
|
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(user_code_phys, (void*)code_virt, 0x7);
|
||||||
map_page(stack_phys, (void*)stack_virt, 0x7);
|
map_page(stack_phys, (void*)stack_virt, 0x7);
|
||||||
|
|
||||||
*user_stack_top = stack_virt + 0x1000;
|
// 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 МБ блок
|
next_user_virt += 0x400000; // Следующий 4 МБ блок
|
||||||
return (void*)code_virt;
|
return (void*)code_virt;
|
||||||
}
|
}
|
||||||
@@ -35,40 +85,61 @@ void *get_physaddr(void *virtualaddr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void map_page(void *physaddr, void *virtualaddr, unsigned int flags) {
|
void map_page(void *physaddr, void *virtualaddr, unsigned int flags) {
|
||||||
// Убеждаемся, что адреса выровнены по 4 КБ
|
// Make sure that both addresses are page-aligned.
|
||||||
uint32_t phys = (uint32_t)physaddr & ~0xFFF; // Обнуляем младшие 12 бит
|
if ((unsigned long)physaddr & 0xFFF || (unsigned long)virtualaddr & 0xFFF) {
|
||||||
uint32_t virt = (uint32_t)virtualaddr & ~0xFFF;
|
// Error handling: addresses not page-aligned
|
||||||
|
printf("MAP_PAGE ERROR: address not page-aligned\n");
|
||||||
// Вычисляем индексы
|
return;
|
||||||
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);
|
|
||||||
|
|
||||||
// Устанавливаем отображение
|
unsigned long pdindex = (unsigned long)virtualaddr >> 22;
|
||||||
pt[ptindex] = phys | (flags & 0xFFF) | 0x1; // Флаги + present
|
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");
|
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) {
|
void map_kernel_page(void* virtualaddr, unsigned int flags) {
|
||||||
uint32_t virt = (uint32_t)virtualaddr & ~0xFFF; // Выравниваем по 4 КБ
|
uint32_t virt = (uint32_t)virtualaddr & ~0xFFF; // Выравниваем по 4 КБ
|
||||||
if (virt < 0xC0000000) while(1); // Ошибка: ядро только выше 3 ГБ
|
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 pdindex = virt >> 22; // Индекс в каталоге
|
||||||
uint32_t ptindex = (virt >> 12) & 0x3FF; // Индекс в таблице страниц
|
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();
|
void* new_pt = alloc_page();
|
||||||
if (!new_pt) while(1); // Нет памяти
|
if (!new_pt) while(1); // Нет памяти
|
||||||
|
|
||||||
// Убеждаемся, что адрес выровнен
|
// Убеждаемся, что адрес выровнен
|
||||||
if ((uint32_t)new_pt & 0xFFF) while(1); // Ошибка выравнивания
|
if ((uint32_t)new_pt & 0xFFF) while(1); // Ошибка выравнивания
|
||||||
|
|
||||||
pd[pdindex] = ((uint32_t)new_pt) | 0x3; // Временно записываем в каталог
|
kpage_dir[pdindex] = ((uint32_t)new_pt) | 0x3; // Временно записываем в каталог
|
||||||
asm volatile("invlpg (%0)" : : "r" ((uint32_t)&pd[pdindex]) : "memory"); // Инвалидируем TLB
|
asm volatile("invlpg (%0)" : : "r" ((uint32_t)&kpage_dir[pdindex]) : "memory"); // Инвалидируем TLB
|
||||||
|
|
||||||
|
uint32_t* pt = ((uint32_t*)kpage_dir+0x1000) + (0x400 * pdindex);
|
||||||
|
|
||||||
uint32_t* pt = ((uint32_t*)0xFFC00000) + (0x400 * pdindex);
|
|
||||||
for (int i = 0; i < 1024; i++) {
|
for (int i = 0; i < 1024; i++) {
|
||||||
pt[i] = 0;
|
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();
|
void* phys = alloc_page();
|
||||||
if (!phys) while(1);
|
if (!phys) while(1);
|
||||||
|
|
||||||
|
|||||||
+37
-18
@@ -16,15 +16,12 @@ uint32_t setup_tmp_pgdir(uint32_t magic, uint32_t info)
|
|||||||
struct multiboot_info *mbi;
|
struct multiboot_info *mbi;
|
||||||
|
|
||||||
if(magic != MULTIBOOT_BOOTLOADER_MAGIC) {
|
if(magic != MULTIBOOT_BOOTLOADER_MAGIC) {
|
||||||
/* 4MB of memory assumed */
|
|
||||||
memksize = 4096;
|
memksize = 4096;
|
||||||
} else {
|
} else {
|
||||||
mbi = (struct multiboot_info *)(PAGE_OFFSET + info);
|
mbi = (struct multiboot_info *)(PAGE_OFFSET + info);
|
||||||
if(!(mbi->flags & MULTIBOOT_INFO_MEMORY)) {
|
if(!(mbi->flags & MULTIBOOT_INFO_MEMORY)) {
|
||||||
/* 4MB of memory assumed */
|
|
||||||
memksize = 4096;
|
memksize = 4096;
|
||||||
} else {
|
} else {
|
||||||
/* we need to add the first 1MB to memksize */
|
|
||||||
memksize = (uint32_t)mbi->mem_upper + 1024;
|
memksize = (uint32_t)mbi->mem_upper + 1024;
|
||||||
if(memksize > ((0xFFFFFFFF - PAGE_OFFSET) / 1024)) {
|
if(memksize > ((0xFFFFFFFF - PAGE_OFFSET) / 1024)) {
|
||||||
memksize = (0xFFFFFFFF - PAGE_OFFSET) / 1024;
|
memksize = (0xFFFFFFFF - PAGE_OFFSET) / 1024;
|
||||||
@@ -32,16 +29,10 @@ uint32_t setup_tmp_pgdir(uint32_t magic, uint32_t info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* address becomes PAGE_OFFSET (0xC0000000) plus the size of memory minus the first page */
|
/* Address is PAGE_OFFSET plus memory size minus 4KB */
|
||||||
/* TODO: check if I wrote the comment above correctly*/
|
pagedir_address = PAGE_OFFSET + (memksize * 1024) - 4096;
|
||||||
pagedir_address = PAGE_OFFSET + (memksize * 1024) - memksize;
|
|
||||||
pagedir_address = PAGE_ALIGN(pagedir_address);
|
pagedir_address = PAGE_ALIGN(pagedir_address);
|
||||||
|
|
||||||
/*
|
|
||||||
memory pages:
|
|
||||||
0 -> page directory
|
|
||||||
1 -> page table
|
|
||||||
*/
|
|
||||||
kpage_dir = (uint32_t *)pagedir_address;
|
kpage_dir = (uint32_t *)pagedir_address;
|
||||||
memset(kpage_dir, 0, PAGE_SIZE);
|
memset(kpage_dir, 0, PAGE_SIZE);
|
||||||
|
|
||||||
@@ -49,16 +40,20 @@ uint32_t setup_tmp_pgdir(uint32_t magic, uint32_t info)
|
|||||||
page_table = (uint32_t *)pagedir_address;
|
page_table = (uint32_t *)pagedir_address;
|
||||||
memset(page_table, 0, memksize);
|
memset(page_table, 0, memksize);
|
||||||
|
|
||||||
/* if we have 4MB assumed earlier, the memksize will be 4096 and this loop will run while n < 1024 */
|
|
||||||
/* so basically 4MB is 1024 pages */
|
|
||||||
for(n = 0; n < memksize / sizeof(uint32_t); n++) {
|
for(n = 0; n < memksize / sizeof(uint32_t); n++) {
|
||||||
page_table[n] = (n << PAGE_SHIFT) | PAGE_PRESENT | PAGE_RW;
|
page_table[n] = (n << PAGE_SHIFT) | PAGE_PRESENT | PAGE_RW;
|
||||||
if(!(n % 1024)) {
|
if(!(n % 1024)) {
|
||||||
pd = n / 1024;
|
pd = n / 1024;
|
||||||
kpage_dir[pd] = (uint32_t)(pagedir_address + (PAGE_SIZE * pd) + GDT_BASE) | PAGE_PRESENT | PAGE_RW;
|
uint32_t pt_phys = (uint32_t)page_table - PAGE_OFFSET + (PAGE_SIZE * pd);
|
||||||
kpage_dir[GET_PGDIR(PAGE_OFFSET) + pd] = (uint32_t)(pagedir_address + (PAGE_SIZE * pd) + GDT_BASE) | PAGE_PRESENT | PAGE_RW;
|
kpage_dir[pd] = pt_phys | PAGE_PRESENT | PAGE_RW | PAGE_USER;//TODO: fix, I don't think pd should have DPL3
|
||||||
|
kpage_dir[GET_PGDIR(PAGE_OFFSET) + pd] = pt_phys | PAGE_PRESENT | PAGE_RW | PAGE_USER;//TODO: fix, I don't think pd should have DPL3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t pd_phys = (uint32_t)kpage_dir - PAGE_OFFSET;
|
||||||
|
kpage_dir[1023] = pd_phys | PAGE_PRESENT | PAGE_RW; // Recursive mapping
|
||||||
|
|
||||||
|
|
||||||
return (uint32_t)kpage_dir - PAGE_OFFSET;
|
return (uint32_t)kpage_dir - PAGE_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,16 +74,40 @@ void grub_memory_map(unsigned int magic, struct multiboot_info* mbi)
|
|||||||
(multiboot_memory_map_t*) (mbi->mmap_addr + i);
|
(multiboot_memory_map_t*) (mbi->mmap_addr + i);
|
||||||
|
|
||||||
printf("Start Addr: %x | Length: %x | Size: %x | Type: %x\n",
|
printf("Start Addr: %x | Length: %x | Size: %x | Type: %x\n",
|
||||||
mmmt->addr, mmmt->len, mmmt->size, mmmt->type);
|
mmmt->addr_low, mmmt->len_low, mmmt->size, mmmt->type);
|
||||||
|
|
||||||
if(mmmt->type == MULTIBOOT_MEMORY_AVAILABLE) {
|
if(mmmt->type != MULTIBOOT_MEMORY_AVAILABLE) {
|
||||||
/*
|
/*
|
||||||
* Do something with this memory block!
|
* Do something with this memory block!
|
||||||
* BE WARNED that some of memory shown as availiable is actually
|
* BE WARNED that some of memory shown as availiable is actually
|
||||||
* actively being used by the kernel! You'll need to take that
|
* actively being used by the kernel! You'll need to take that
|
||||||
* into account before writing to memory!
|
* into account before writing to memory!
|
||||||
*/
|
*/
|
||||||
printf("available\n");
|
printf("not available\n");
|
||||||
|
uint32_t size_in_pages = mmmt->len_low / PAGE_SIZE;
|
||||||
|
printf("size_in_pages: 0x%X\n", size_in_pages);
|
||||||
|
|
||||||
|
uint32_t base_page = mmmt->addr_low / PAGE_SIZE;
|
||||||
|
uint32_t page_count = mmmt->len_low / PAGE_SIZE;
|
||||||
|
printf("page_base: %X, page_count: %X\n", base_page, page_count);
|
||||||
|
for (uint32_t j = 0; j < page_count; j++) {
|
||||||
|
set_bit(base_page + j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extern uint32_t _start, _end; // From linker script
|
||||||
|
uint32_t kernel_start_phys = (uint32_t)&_start - 0xC0000000;
|
||||||
|
uint32_t kernel_end_phys = (uint32_t)&_end - 0xC0000000;
|
||||||
|
uint32_t kernel_start_page = kernel_start_phys / PAGE_SIZE;
|
||||||
|
uint32_t kernel_end_page = (kernel_end_phys + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||||
|
printf("Kernel phys range: 0x%X to 0x%X, pages: 0x%X to 0x%X\n",
|
||||||
|
kernel_start_phys, kernel_end_phys, kernel_start_page, kernel_end_page);
|
||||||
|
|
||||||
|
for (uint32_t i = kernel_start_page; i < kernel_end_page; i++) {
|
||||||
|
if (i < BITMAP_SIZE) {
|
||||||
|
set_bit(i);
|
||||||
|
} else {
|
||||||
|
printf("Bitmap overflow at kernel page %u\n", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ sys_exit_handler:
|
|||||||
|
|
||||||
global test_user_function
|
global test_user_function
|
||||||
test_user_function:
|
test_user_function:
|
||||||
mov eax, 0xDEADBEEF
|
mov eax, 0xB00B1E5 ; 0xDEADBEEF
|
||||||
int 0x80
|
int 0x80
|
||||||
jmp $
|
jmp $
|
||||||
|
|
||||||
|
|||||||
+42
-19
@@ -87,7 +87,7 @@ void schedule()
|
|||||||
next = queue;
|
next = queue;
|
||||||
if(next != current)
|
if(next != current)
|
||||||
{
|
{
|
||||||
loadPageDirectory(next->page_directory);
|
//loadPageDirectory(next->page_directory);
|
||||||
switchProcess(next);
|
switchProcess(next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,7 +116,7 @@ void jump_usermode2(void);
|
|||||||
|
|
||||||
void scheduler_init()
|
void scheduler_init()
|
||||||
{
|
{
|
||||||
//jump_usermode2();
|
jump_usermode2();
|
||||||
//we create this task two times because in other case it just won't start
|
//we create this task two times because in other case it just won't start
|
||||||
task_create((EntryPoint)&idle, NULL, 0);
|
task_create((EntryPoint)&idle, NULL, 0);
|
||||||
task_create((EntryPoint)&idle, NULL, 0);
|
task_create((EntryPoint)&idle, NULL, 0);
|
||||||
@@ -127,6 +127,8 @@ void scheduler_init()
|
|||||||
task_create((EntryPoint)&task2, args2, 2);
|
task_create((EntryPoint)&task2, args2, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "../include/string.h"
|
||||||
|
|
||||||
extern void test_user_function(void);
|
extern void test_user_function(void);
|
||||||
void jump_usermode2(void) {
|
void jump_usermode2(void) {
|
||||||
void* code_phys = alloc_page();
|
void* code_phys = alloc_page();
|
||||||
@@ -135,18 +137,25 @@ void jump_usermode2(void) {
|
|||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Временно отображаем code_phys в ядре
|
// Temporarily map code_phys into kernel space
|
||||||
uint32_t kernel_temp_virt = 0xC0100000;
|
uint32_t kernel_temp_virt = 0xC0500000;
|
||||||
map_page(code_phys, (void*)kernel_temp_virt, 0x3); // Present, R/W, Supervisor
|
map_page(code_phys, (void*)kernel_temp_virt, 0x3); // R/W in kernel
|
||||||
|
|
||||||
// Копируем код
|
// Copy user code
|
||||||
uint32_t* src = (uint32_t*)test_user_function;
|
memcpy((void*)kernel_temp_virt, test_user_function, 4096); // Use memcpy
|
||||||
uint32_t* dst = (uint32_t*)kernel_temp_virt;
|
|
||||||
for (int i = 0; i < 1024; i++) {
|
printf("Copied code at 0x%x: 0x%x 0x%x 0x%x\n",
|
||||||
dst[i] = src[i];
|
kernel_temp_virt,
|
||||||
}
|
*(uint32_t*)kernel_temp_virt,
|
||||||
printf("Copied code to 0x%x (virt 0x%x): 0x%x 0x%x 0x%x\n",
|
*(uint32_t*)(kernel_temp_virt + 4),
|
||||||
(uint32_t)code_phys, kernel_temp_virt, dst[0], dst[1], dst[2]);
|
*(uint32_t*)(kernel_temp_virt + 8));
|
||||||
|
|
||||||
|
// Unmap temporary kernel mapping
|
||||||
|
unmap_page((void*)kernel_temp_virt);
|
||||||
|
|
||||||
|
|
||||||
|
printf("Copied code to 0x%x (virt 0x%x)\n",
|
||||||
|
(uint32_t)code_phys, kernel_temp_virt);
|
||||||
|
|
||||||
// Настраиваем Ring 3
|
// Настраиваем Ring 3
|
||||||
uint32_t user_stack_top;
|
uint32_t user_stack_top;
|
||||||
@@ -159,21 +168,35 @@ void jump_usermode2(void) {
|
|||||||
printf("user_code_virt: 0x%x, user_stack_top: 0x%x\n",
|
printf("user_code_virt: 0x%x, user_stack_top: 0x%x\n",
|
||||||
(uint32_t)user_code_virt, user_stack_top);
|
(uint32_t)user_code_virt, user_stack_top);
|
||||||
|
|
||||||
|
//map_page(alloc_page(), (void*)0x400000, 0x7);
|
||||||
|
map_page(alloc_page(), (void*)0x800000, 0x7);
|
||||||
|
|
||||||
|
uint32_t code_pte = get_pte(user_code_virt);
|
||||||
|
printf("Before iret: Code PTE at 0x%x: 0x%x (phys 0x%x, %s, %s)\n",
|
||||||
|
(uint32_t)user_code_virt, code_pte, code_pte & ~0xFFF,
|
||||||
|
(code_pte & 0x2) ? "writable" : "read-only",
|
||||||
|
(code_pte & 0x4) ? "user" : "supervisor");
|
||||||
|
|
||||||
|
// Switch to user mode with interrupts enabled
|
||||||
asm volatile (
|
asm volatile (
|
||||||
|
"pushf\n"
|
||||||
|
"pop %%eax\n"
|
||||||
|
"or $0x200, %%eax\n" // Enable interrupts (IF)
|
||||||
|
"push %%eax\n"
|
||||||
"mov $0x23, %%dx\n"
|
"mov $0x23, %%dx\n"
|
||||||
"mov %%dx, %%ds\n"
|
"mov %%dx, %%ds\n"
|
||||||
"mov %%dx, %%es\n"
|
"mov %%dx, %%es\n"
|
||||||
"mov %%dx, %%fs\n"
|
"mov %%dx, %%fs\n"
|
||||||
"mov %%dx, %%gs\n"
|
"mov %%dx, %%gs\n"
|
||||||
"push $0x23\n"
|
"push $0x23\n" // SS (user data segment)
|
||||||
"push %0\n"
|
"push %0\n" // ESP (user_stack_top)
|
||||||
"pushf\n"
|
"push %%eax\n" // EFLAGS (with IF)
|
||||||
"push $0x1B\n"
|
"push $0x1B\n" // CS (user code segment)
|
||||||
"push %1\n"
|
"push %1\n" // EIP (user_code_virt)
|
||||||
"iret\n"
|
"iret\n"
|
||||||
:
|
:
|
||||||
: "r" (user_stack_top), "r" (user_code_virt)
|
: "r" (user_stack_top), "r" (user_code_virt)
|
||||||
: "dx", "memory"
|
: "dx", "eax", "memory", "cc"
|
||||||
);
|
);
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user