diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2209cb3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +* +!*.* +!*/ + +!Makefile + +build/* + +test.* + +!.vscode/ +!.vscode/*.* +.vscode/c_cpp_properties.json +.vscode/settings.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..af220ad --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(linux) bochs floppy", + "type": "f5anything", + "request": "launch", + "command": "bochs -q -f ./bochs.linux.conf", + "preLaunchTask": "make_floppy" + }, + { + "name": "(win) bochs floppy", + "type": "f5anything", + "request": "launch", + "command": "& \"${env:BOCHS_PATH}\\bochs\"-q -f ./bochs.win.conf", + "preLaunchTask": "make_floppy" + }, + { + "name": "(win_dbg) bochs floppy", + "type": "f5anything", + "request": "launch", + "command": "& \"${env:BOCHS_PATH}\\bochsdbg\" -q -f ./bochsdbg.win.conf", + "preLaunchTask": "make_floppy" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..a85305a --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,10 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "make_floppy", + "type": "shell", + "command": "./build_" + } + ] +} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..361aeae --- /dev/null +++ b/Makefile @@ -0,0 +1,206 @@ +SOURCE_DIR = ./src +BUILD_DIR = ./build + +BOOTLOADER_SOURCE_DIR = $(SOURCE_DIR)/bootloader +KERNEL_SOURCE_DIR = $(SOURCE_DIR)/kernel +LIBC_SOURCE_DIR = $(SOURCE_DIR)/libc + +BOOTLOADER_BUILD_DIR = $(BUILD_DIR)/bootloader +KERNEL_BUILD_DIR = $(BUILD_DIR)/kernel +LIBC_BUILD_DIR = $(BUILD_DIR)/libc + +BOOTLOADER_ASM = $(BOOTLOADER_SOURCE_DIR)/boot.asm +KERNEL_C = $(KERNEL_SOURCE_DIR)/kernel.c +KERNEL_ENTRY_ASM = $(KERNEL_SOURCE_DIR)/kernel_entry.asm + +TRAMP_WC_O = $(KERNEL_BUILD_DIR)/sys/context/tramplinsWContext.o + +BOOTLOADER_BIN = $(BOOTLOADER_BUILD_DIR)/bootloader.bin +KERNEL_O = $(KERNEL_BUILD_DIR)/kernel.o +KERNEL_ENTRY_O = $(KERNEL_BUILD_DIR)/kernel_entry.o +KERNEL_TMP = $(KERNEL_BUILD_DIR)/kernel.tmp +KERNEL_BIN = $(KERNEL_BUILD_DIR)/kernel.bin + +FLOPPY_IMG = $(BUILD_DIR)/floppy.img + +KERNEL_ENTRY_ADDRESS = 0x20200 +# 0xC0020200 +# 0x20200 + +ifeq ($(OS), Windows_NT) + ASM = ${NASM_PATH}\nasm + DD = ${CYGWIN_PATH}\bin\dd + GCC = gcc -fno-leading-underscore + MCOPY = + MKFS = + LD = ld + LD_M_OPT = i386pe + OBJCOPY = objcopy + OD = ${CYGWIN_PATH}\bin\od + OD_OPT = -t x1 -A n + RM = +else + UNAME_S := $(shell uname -s) + ifeq ($(UNAME_S), Linux) + ASM = nasm + GCC = gcc + DD = dd + MCOPY = mcopy + MKFS = mkfs + LD = ld + OBJCOPY = objcopy + OD = od + OD_OPT = -t x1 -A n + RM = rm + endif +endif + +$(info init..) + +.PHONY: clean_boot floppy kernel bootloader + +floppy: bootloader kernel $(FLOPPY_IMG) +kernel: $(KERNEL_BIN) +bootloader: $(BOOTLOADER_BIN) + +$(BUILD_DIR)/pm/io/print_d2vm.o: $(SOURCE_DIR)/pm/io/print_d2vm.asm + $(info [MAKE] building: $@) + $(ASM) -f elf $< -o $@ + +$(TRAMP_WC_O): $(KERNEL_SOURCE_DIR)/sys/context/tramplinsWContext.asm + $(info [MAKE] building: $@) + $(ASM) -f elf $< -o $@ + +$(KERNEL_BUILD_DIR)/sys/paging/paging.asm.o: $(KERNEL_SOURCE_DIR)/sys/paging/paging.asm + $(info [MAKE] building: $@) + $(ASM) -f elf $< -o $@ + +$(KERNEL_BUILD_DIR)/sys/process/exec.asm.o: $(KERNEL_SOURCE_DIR)/sys/process/exec.asm + $(info [MAKE] building: $@) + $(ASM) -f elf $< -o $@ + +$(KERNEL_BUILD_DIR)/sync/sync.asm.o: $(KERNEL_SOURCE_DIR)/sync/sync.asm $(KERNEL_SOURCE_DIR)/sync/sync.h + $(info [MAKE] building: $@) + $(ASM) -f elf $< -o $@ + +$(KERNEL_BUILD_DIR)/sys/pic/pic.o: $(KERNEL_SOURCE_DIR)/sys/pic/pic.c \ + $(KERNEL_SOURCE_DIR)/sys/pic/pic.h + $(info [MAKE] building: $@) + $(GCC) -Wall -m32 -mno-sse -fno-pie -ffreestanding -nostdlib -fno-stack-protector -c $< -o $@ + +$(KERNEL_BUILD_DIR)/sys/io/printf.o: $(KERNEL_SOURCE_DIR)/sys/io/printf.c \ + $(KERNEL_SOURCE_DIR)/sys/io/printf.h $(KERNEL_SOURCE_DIR)/sync/sync.h + $(info [MAKE] building: $@) + $(GCC) -Wall -m32 -mno-sse -fno-pie -ffreestanding -nostdlib -fno-stack-protector -c $< -o $@ + +$(KERNEL_BUILD_DIR)/sys/memory/mem_utils.o: $(KERNEL_SOURCE_DIR)/sys/memory/mem_utils.c \ + $(KERNEL_SOURCE_DIR)/sys/memory/mem_utils.h + $(info [MAKE] building: $@) + $(GCC) -Wall -m32 -mno-sse -fno-pie -ffreestanding -nostdlib -fno-stack-protector -c $< -o $@ + +$(KERNEL_BUILD_DIR)/sys/memory/alloc.o: $(KERNEL_SOURCE_DIR)/sys/memory/alloc.c \ + $(KERNEL_SOURCE_DIR)/sys/memory/alloc.h $(KERNEL_SOURCE_DIR)/sys/paging/paging.h \ + $(KERNEL_SOURCE_DIR)/sys/io/io.h $(KERNEL_SOURCE_DIR)/sys/io/printf.h \ + $(KERNEL_SOURCE_DIR)/misc/list.h + $(info [MAKE] building: $@) + $(GCC) -Wall -m32 -mno-sse -fno-pie -ffreestanding -nostdlib -fno-stack-protector -c $< -o $@ + +$(KERNEL_BUILD_DIR)/sys/context/exp.o: $(KERNEL_SOURCE_DIR)/sys/context/experiment.asm + $(info [MAKE] building: $@) + $(ASM) -f elf $< -o $@ + +$(KERNEL_BUILD_DIR)/sys/paging/paging.o: $(KERNEL_SOURCE_DIR)/sys/paging/paging.c \ + $(KERNEL_SOURCE_DIR)/sys/paging/paging.h $(KERNEL_SOURCE_DIR)/sys/memory/alloc.h \ + $(KERNEL_SOURCE_DIR)/sys/paging/pdt.h $(KERNEL_SOURCE_DIR)/sys/paging/pt.h \ + $(KERNEL_SOURCE_DIR)/sys/io/io.h $(KERNEL_SOURCE_DIR)/sys/io/printf.h + $(info [MAKE] building: $@) + $(GCC) -Wall -m32 -mno-sse -fno-pie -ffreestanding -nostdlib -fno-stack-protector -c $< -o $@ + +$(KERNEL_BUILD_DIR)/misc/list.o: $(KERNEL_SOURCE_DIR)/misc/list.c \ + $(KERNEL_SOURCE_DIR)/misc/list.h $(KERNEL_SOURCE_DIR)/sys/memory/alloc.h + $(info [MAKE] building: $@) + $(GCC) -Wall -m32 -mno-sse -fno-pie -ffreestanding -nostdlib -fno-stack-protector -c $< -o $@ + +$(KERNEL_BUILD_DIR)/sys/process/process.o: $(KERNEL_SOURCE_DIR)/sys/process/process.c \ + $(KERNEL_SOURCE_DIR)/sys/process/process.h $(KERNEL_SOURCE_DIR)/sys/paging/paging.h \ + $(KERNEL_SOURCE_DIR)/sys/io/io.h $(KERNEL_SOURCE_DIR)/sys/io/printf.h + $(info [MAKE] building: $@) + $(GCC) -Wall -m32 -mno-sse -fno-pie -ffreestanding -nostdlib -fno-stack-protector -c $< -o $@ + +$(KERNEL_BUILD_DIR)/sys/process/scheduler.o: $(KERNEL_SOURCE_DIR)/sys/process/scheduler.c \ + $(KERNEL_SOURCE_DIR)/sys/process/scheduler.h $(KERNEL_SOURCE_DIR)/misc/list.h \ + $(KERNEL_SOURCE_DIR)/sys/memory/alloc.h $(KERNEL_SOURCE_DIR)/sys/context/context.h \ + $(KERNEL_SOURCE_DIR)/sys/process/process.h $(KERNEL_SOURCE_DIR)/sys/paging/paging.h \ + $(LIBC_SOURCE_DIR)/io/console.h + $(info [MAKE] building: $@) + $(GCC) -Wall -m32 -mno-sse -fno-pie -ffreestanding -nostdlib -fno-stack-protector -c $< -o $@ + +$(KERNEL_BUILD_DIR)/sys/interruption.o: $(KERNEL_SOURCE_DIR)/sys/interruption.c \ + $(KERNEL_SOURCE_DIR)/sys/interruption.h $(KERNEL_SOURCE_DIR)/sys/tramplins.hpp \ + $(KERNEL_SOURCE_DIR)/sys/context/tramplinsWContext.asm \ + $(KERNEL_SOURCE_DIR)/sys/context/context.h $(KERNEL_SOURCE_DIR)/sys/io/io.h $(KERNEL_SOURCE_DIR)/sys/io/printf.h \ + $(KERNEL_SOURCE_DIR)/sys/memory/memory.h $(KERNEL_SOURCE_DIR)/sys/paging/paging.h $(KERNEL_SOURCE_DIR)/sys/pic/pic.h \ + $(KERNEL_SOURCE_DIR)/sys/process/scheduler.h $(KERNEL_SOURCE_DIR)/sync/sync.h + $(info [MAKE] building: $@) + $(GCC) -Wall -m32 -mno-sse -fno-pie -ffreestanding -nostdlib -fno-stack-protector -c $< -o $@ + +$(LIBC_BUILD_DIR)/io/console.o: $(LIBC_SOURCE_DIR)/io/console.c $(LIBC_SOURCE_DIR)/io/console.h \ + $(KERNEL_SOURCE_DIR)/sys/io/io.h $(KERNEL_SOURCE_DIR)/sys/memory/alloc.h + $(info [MAKE] building: $@) + $(GCC) -Wall -m32 -mno-sse -fno-pie -ffreestanding -nostdlib -fno-stack-protector -c $< -o $@ + +$(LIBC_BUILD_DIR)/io/printer.o: $(LIBC_SOURCE_DIR)/io/printer.c $(LIBC_SOURCE_DIR)/io/printer.h \ + $(KERNEL_SOURCE_DIR)/sys/io/io.h $(KERNEL_SOURCE_DIR)/sys/memory/alloc.h + $(info [MAKE] building: $@) + $(GCC) -Wall -m32 -mno-sse -fno-pie -ffreestanding -nostdlib -fno-stack-protector -c $< -o $@ + +$(KERNEL_O): $(KERNEL_C) $(KERNEL_SOURCE_DIR)/sys/io/io.h $(KERNEL_SOURCE_DIR)/sys/io/printf.h \ + $(KERNEL_SOURCE_DIR)/sys/memory/memory.h $(KERNEL_SOURCE_DIR)/sys/interruption.h \ + $(KERNEL_SOURCE_DIR)/sys/pic/pic.h $(KERNEL_SOURCE_DIR)/sys/paging/paging.h \ + $(KERNEL_SOURCE_DIR)/sys/process/scheduler.h $(LIBC_SOURCE_DIR)/io/printer.h + $(info [MAKE] building: $@) + $(GCC) -Wall -m32 -mno-sse -fno-pie -ffreestanding -nostdlib -fno-stack-protector -c $< -o $@ +# -m32 + +$(KERNEL_ENTRY_O): $(KERNEL_ENTRY_ASM) + $(info [MAKE] building: $@) + $(ASM) -f elf $< -o $@ + +$(KERNEL_BIN): $(KERNEL_ENTRY_O) $(KERNEL_O) \ + $(KERNEL_BUILD_DIR)/sys/io/printf.o $(BUILD_DIR)/pm/io/print_d2vm.o $(KERNEL_BUILD_DIR)/sys/memory/alloc.o \ + $(KERNEL_BUILD_DIR)/sys/interruption.o $(KERNEL_BUILD_DIR)/sys/memory/mem_utils.o $(KERNEL_BUILD_DIR)/sys/pic/pic.o \ + $(TRAMP_WC_O) $(KERNEL_BUILD_DIR)/sys/context/exp.o \ + $(KERNEL_BUILD_DIR)/sys/paging/paging.asm.o $(KERNEL_BUILD_DIR)/sys/paging/paging.o $(KERNEL_BUILD_DIR)/misc/list.o \ + $(KERNEL_BUILD_DIR)/sys/process/process.o $(KERNEL_BUILD_DIR)/sys/process/scheduler.o \ + $(KERNEL_BUILD_DIR)/sys/process/exec.asm.o $(KERNEL_BUILD_DIR)/sync/sync.asm.o $(LIBC_BUILD_DIR)/io/console.o \ + $(LIBC_BUILD_DIR)/io/printer.o + $(info [MAKE] building: $@) + $(LD) -m i386pe -Ttext $(KERNEL_ENTRY_ADDRESS) $^ -o $(KERNEL_TMP) +# $(LD) -m i386pe -T $(KERNEL_SOURCE_DIR)/link.ld $^ -o $(KERNEL_TMP) +# $(KERNEL_TMP) + $(OBJCOPY) -I pe-i386 -O binary $(KERNEL_TMP) $@ + +$(BOOTLOADER_BIN): $(BOOTLOADER_ASM) $(SOURCE_DIR)/rm/io/print.asm \ + $(SOURCE_DIR)/bootloader/read_floppy_disk.asm $(SOURCE_DIR)/pm/switch2pm.asm \ + $(SOURCE_DIR)/pm/gdt.asm $(SOURCE_DIR)/pm/io/print_d2vm.asm + $(info [MAKE] building: $@) + $(ASM) -fbin $< -o $@ + $(OD) $(OD_OPT) $@ + +$(FLOPPY_IMG): $(BOOTLOADER_BIN) $(KERNEL_BIN) + $(info [MAKE] building: $@) + $(DD) bs=512 count=2880 if=/dev/zero of=$@ +# $(MKFS) -t fat -F 12 -n "UNOS" $@ + $(DD) conv=notrunc if=$< of=$@ +# $(MCOPY) -i $@ $(word 2,$^) "::kernel.bin" + $(DD) conv=notrunc seek=1 if=$(word 2,$^) of=$@ + +clean_boot: + $(info [MAKE] do $@:) + $(RM) -f $(FLOPPY_IMG) + $(RM) -f $(KERNEL_ENTRY_O) + $(RM) -f $(KERNEL_O) + $(RM) -f $(KERNEL_TMP) + $(RM) -f $(KERNEL_BIN) + $(RM) -f $(BOOTLOADER_BIN) + $(RM) -f $(BOOTLOADER_BIN) diff --git a/bochs.linux.conf b/bochs.linux.conf new file mode 100644 index 0000000..768f329 --- /dev/null +++ b/bochs.linux.conf @@ -0,0 +1,8 @@ +plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true +config_interface: textconfig +display_library: x, options="gui_debug" +memory: host=2048, guest=4096 +boot: floppy +floppy_bootsig_check: disabled=0 +floppya: type=1_44, 1_44="./build/floppy.img", status=inserted, write_protected=0 +magic_break: enabled=1 diff --git a/bochs.win.conf b/bochs.win.conf new file mode 100644 index 0000000..b5ce8d7 --- /dev/null +++ b/bochs.win.conf @@ -0,0 +1,8 @@ +plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true +config_interface: win32config +display_library: win32 +memory: host=2048, guest=4096 +boot: floppy +floppy_bootsig_check: disabled=0 +floppya: type=1_44, 1_44="./build/floppy.img", status=inserted, write_protected=0 +magic_break: enabled=1 diff --git a/bochsdbg.win.conf b/bochsdbg.win.conf new file mode 100644 index 0000000..8b6b602 --- /dev/null +++ b/bochsdbg.win.conf @@ -0,0 +1,8 @@ +plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true +config_interface: win32config +display_library: win32, options="gui_debug" +memory: host=2048, guest=4096 +boot: floppy +floppy_bootsig_check: disabled=0 +floppya: type=1_44, 1_44="./build/floppy.img", status=inserted, write_protected=0 +magic_break: enabled=1 diff --git a/bx_enh_dbg.ini b/bx_enh_dbg.ini new file mode 100644 index 0000000..0d0a5e1 --- /dev/null +++ b/bx_enh_dbg.ini @@ -0,0 +1,26 @@ +# bx_enh_dbg_ini +SeeReg[0] = TRUE +SeeReg[1] = TRUE +SeeReg[2] = TRUE +SeeReg[3] = TRUE +SeeReg[4] = FALSE +SeeReg[5] = FALSE +SeeReg[6] = TRUE +SeeReg[7] = FALSE +SingleCPU = FALSE +ShowIOWindows = TRUE +ShowButtons = TRUE +SeeRegColors = TRUE +ignoreNxtT = TRUE +ignSSDisasm = TRUE +UprCase = 0 +DumpInAsciiMode = 3 +isLittleEndian = TRUE +DefaultAsmLines = 512 +DumpWSIndex = 0 +DockOrder = 0x123 +ListWidthPix[0] = 381 +ListWidthPix[1] = 468 +ListWidthPix[2] = 466 +MainWindow = 0, 0, 878, 500 +FontName = Normal diff --git a/src/bootloader/boot.asm b/src/bootloader/boot.asm new file mode 100644 index 0000000..6e4e6be --- /dev/null +++ b/src/bootloader/boot.asm @@ -0,0 +1,66 @@ +[BITS 16] + +KERNEL_OFFSET_ES equ 0x2000 +KERNEL_OFFSET_BX equ 0 + +main: + xor ax, ax + mov es, ax + + cli + mov ss, ax + mov sp, 0x7c00 + mov ax, 0x7c0 + mov ds, ax + mov bp, 0x7c00 + + mov si, os_boot_msg + call print + + mov ax, KERNEL_OFFSET_ES + mov es, ax + mov bx, KERNEL_OFFSET_BX + call disk_load + + ;mov si, KERNEL_OFFSET_ES + ;xor cx, cx + ;mov al, dh + ;mov cx, 0x200 + ;mul cx + ;mov cx, ax + ;add cx, 0 + ;xor ah, ah + ;call accumulate + + ;mov si, sum + ;call print ; TODO: implement print_hex, source=? + + call switch_to_pm + + jmp $ + +%ifndef PRINT + %include "./src/rm/io/print.asm" +%endif + +;%ifndef PRINT_HEX +; %include "./src/rm/io/print_hex.asm" +;%endif + +%ifndef READ_FLOPPY_DISK + %include "./src/bootloader/read_floppy_disk.asm" +%endif + +;%ifndef ACCUMULATE_SUM +; %include "./src/rm/misc/accumulate_sum.asm" +;%endif + +os_boot_msg: + DB 'Hello world!', 0x0d, 0x0a, 0 + +%ifndef SWITCH_TO_PM + %include "./src/pm/switch2pm.asm" +%endif + +times 510-($-$$) DB 0 +dw 0xaa55 \ No newline at end of file diff --git a/src/bootloader/read_floppy_disk.asm b/src/bootloader/read_floppy_disk.asm new file mode 100644 index 0000000..a7ff0c0 --- /dev/null +++ b/src/bootloader/read_floppy_disk.asm @@ -0,0 +1,55 @@ +%ifndef READ_AFLOPPY_DISKS + %define READ_AFLOPPY_DISKS +%endif + +[BITS 16] + +disk_load: + mov di, 0x0 + + mov ch, 0x00 ; select cylinder 0 + mov dh, 0x00 ; select head 0 + mov cl, 0x01 ; select sector 1 (512B each sector, so it follows out boot sector) + ; now read w/bootloader + +loop_load: + mov ah, 0x02 ; 0x2 - read sectors from drive + mov al, 1 ; read DH sector + int 0x13 + jc disk_error + + mov ax, es + add ax, 0x20 + mov es, ax + + add cl, 0x1 + + cmp cl, 0x13 + jl continue + + and cx, 0xffc0 + add cl, 1 + + xor dh, 0x1 + jne continue + + add ch, 1 + +continue: + add di, 0x1 + cmp di, 768 + + jne loop_load + ret + +disk_error: + mov si, disk_error_msg + call print + jmp $ + +%ifndef PRINT + %include "./src/misc/print.asm" +%endif + +disk_error_msg: + DB 'Disk read error!', 0x0d, 0x0a, 0 \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c new file mode 100644 index 0000000..4d55dac --- /dev/null +++ b/src/kernel/kernel.c @@ -0,0 +1,238 @@ +extern void asm_print_d2vm(char* src); +extern void experiment(); + +#include "./sys/io/io.h" +#include "./sys/memory/memory.h" +#include "./sys/interruption.h" +#include "./sys/pic/pic.h" +#include "./sys/paging/paging.h" +#include "./sys/process/scheduler.h" +#include "../libc/io/printer.h" + +// compare [first, first_end) and second (until '\0') + +void str_reverse(char* str_start, char* str_end) { + int len = (str_end - str_start + 1) / 2; + for (int i = 0; i < len; ++i) + { + char buf = *(str_start + i); + *(str_start + i) = *(str_end - i); + *(str_end - i) = buf; + } +} + +void task1(int i, int j, int k) +{ + static unsigned int counter = 0u; + print("Hello from process #1 : %d %d %d;\n", i, j, k); + int* temp = os_malloc(sizeof(int) * 100); + temp[5] = 5; + // asm("xchgw %bx, %bx"); + while(counter < 200000) + { + if (!(counter % 10)) + { + print("1\n"); + } + print("1 "); + ++counter; + } + print("\nEnd of the proc #1, counter=%d\n", counter); + asm("xchgw %bx, %bx"); +} + +void task2(int i, int j, int k, int l) +{ + static unsigned int counter = 0u; + print("Hello from process #2 : %d %d %d %d;\n", i, j, k, l); + int* temp = os_malloc(sizeof(int) * 150); + temp[126] = 16; + // asm("xchgw %bx, %bx"); + while(counter < 200000) + { + if (!(counter % 10)) + { + print("2\n"); + } + print("2 "); + ++counter; + } + print("\nEnd of the proc #2, counter=%d\n", counter); + asm("xchgw %bx, %bx"); +} + +void task3(int i, int j) +{ + static unsigned int counter = 0u; + print("Hello from process #%d : %d %d;\n", i, i, j); + int* temp = os_malloc(sizeof(int) * 77); + temp[126] = 16; + // asm("xchgw %bx, %bx"); + while(counter < 200000) + { + if (!(counter % 10)) + { + print("%d\n", i); + } + print("%d ", i); + ++counter; + } + print("\nEnd of the proc #%d, counter=%d\n", i, counter); + asm("xchgw %bx, %bx"); +} + +void entry_point() +{ + init_printer(); + printf( " %b %d_RED!hello world!\n", 20, 0x80000000); + // ||||||||||||| + asm_print_d2vm("Hello from C!"); + + // non-PSE + /* ppdt actual_pdt = markup_pdt(); + if (!actual_pdt) + { + printf("PDT initialization finished bad!\n"); + asm("xchgw %bx, %bx"); + 1/0; // YEAH + } + else + { + printf("PDT on %x\n", actual_pdt); + } + load_page_directory(actual_pdt); + enable_paging(); */ + + // PSE + ppdtx actual_pdt = create_pdt_pse(); + + if (!actual_pdt) + { + printf("PDT initialization finished bad!\n"); + asm("xchgw %bx, %bx"); + 1/0; // YEAH + } + else + { + printf("PDT on %x\n", actual_pdt); + } + load_page_directory(actual_pdt); + enable_paging_pse(); + jmp_to_higher_half(); + + fix_heap_to_higher_half(); + InterruptDescriptor32* pidt = init_idt(0xC0000000); + reg_idtd(pidt); + setup_pic(); + // GDT move here + // ... + unfix_heap_to_higher_half(); + + actual_pdt = (ppdtx)((ptr_t)actual_pdt + 0xC0000000); + for(unsigned int i = 0; i < 64; ++i) + { + if (!actual_pdt->pages[i].present) break; + actual_pdt->pages[i].present = 0; + invalidate_page((void*)((ptr_t)actual_pdt->pages[i].frame_address >> 22)); + } + // GDT does not move, so + actual_pdt->pages[0ul].present = 1; + invalidate_page((void*)((ptr_t)actual_pdt->pages[0u].frame_address >> 22)); + + fix_heap_to_N(0x200000); + + // lab №7, #1 + // experiment(); + + //----------------------------------------------------------------------- TEST ZONE : C_MALLOC, C_DELETE + // int* temp = c_malloc(sizeof(int) * 10); + // int* temp1 = c_malloc(sizeof(int) * 20); + // int* temp2 = c_malloc(sizeof(int) * 10); + // int* temp3 = c_malloc(sizeof(int) * 10); + // int* temp4 = c_malloc(sizeof(int) * 10); + // int* temp5 = c_malloc(sizeof(int) * 30); + // int* temp6 = c_malloc(sizeof(int) * 20); + // c_delete(temp, sizeof(int) * 10); + // c_delete(temp1, sizeof(int) * 20); + // c_delete(temp2, sizeof(int) * 10); + // int* temp7 = c_malloc(sizeof(int) * 30); + // c_delete(temp3, sizeof(int) * 10); + // int* temp8 = c_malloc(sizeof(int) * 20); + // asm("xchgw %bx, %bx"); + //----------------------------------------------------------------------- + + //----------------------------------------------------------------------- TEST ZONE : PROCESSES + reg_os(); + add_task((ptr_t*)task1, ARBITRARY, "Process #1", 0, 0, 40, 14, 3u, 1, 228, 322); + add_task((ptr_t*)task2, ARBITRARY, "Process #2", 40, 0, 40, 11, 4u, 2, 10, 15, 20); + add_task((ptr_t*)task3, ARBITRARY, "Process #3", 0, 14, 40, 11, 2u, 3, 228); + // add_task((ptr_t*)task3, ARBITRARY, "Process #4", 40, 11, 40, 14, 2u, 4, 322); + reg_os(); + //----------------------------------------------------------------------- + + //----------------------------------------------------------------------- TEST ZONE : PAGING, KERNEL_KMALLOC + // asm("xchgw %bx, %bx"); + // int* temp = malloc(sizeof(int) * 100); + // if (!temp) + // { + // printf("Bad allocation\n"); + // asm("xchgw %bx, %bx"); + // } + // else + // { + // asm("xchgw %bx, %bx"); + // printf("Temp on %x\n", temp); + // for(ptr_t i = 0u; i < 100; ++i) + // { + // *temp = 0x1; + // } + // } + + // int* temp2 = malloc(sizeof(int) * 0x10000000); + // temp2 = malloc(sizeof(int) * 0x10000000); + // temp2 = malloc(sizeof(int) * 0x100000); + // if (!temp2) + // { + // printf("Bad allocation\n"); + // asm("xchgw %bx, %bx"); + // } + // else + // { + // printf("Temp on %x\n", temp2); + // for(ptr_t i = 0u; i < 0x100000; ++i) + // { + // *temp2 = 0x10 + i; + // } + // } + + // int* temp3 = malloc(sizeof(int) * 0x1000); + // if (!temp3) + // { + // printf("Bad allocation\n"); + // asm("xchgw %bx, %bx"); + // } + // else + // { + // printf("Temp on %x\n", temp3); + // for(ptr_t i = 0u; i < 0x1000; ++i) + // { + // printf("%d ", temp3[i]); + // } + // printf("\n"); + // } + //----------------------------------------------------------------------- + + asm("sti"); + // while(1) { + // printf("*"); + // } + + + // printf("%X", -192); + + // printf(str, num); + // printf("%d", 1/0); // 0x0 + + // asm("sti"); + while (1) { print("INT FROM MAIN\n"); asm("hlt"); } +} \ No newline at end of file diff --git a/src/kernel/kernel_entry.asm b/src/kernel/kernel_entry.asm new file mode 100644 index 0000000..5241307 --- /dev/null +++ b/src/kernel/kernel_entry.asm @@ -0,0 +1,6 @@ +[BITS 32] + +[extern entry_point] + +call entry_point +jmp $ \ No newline at end of file diff --git a/src/kernel/link.ld b/src/kernel/link.ld new file mode 100644 index 0000000..4fde54e --- /dev/null +++ b/src/kernel/link.ld @@ -0,0 +1,35 @@ +ENTRY(loader) +/* the name of the entry symbol */ + +. = 0xC0100000 +/* the code should be relocated to 3GB + 1MB */ +/* align at 4 KB and load at 1 MB */ + +.text ALIGN (0x1000) : AT(ADDR(.text) - 0xC0000000) +{ + *(.text) + /* all text sections from all files */ +} +/* align at 4 KB and load at 1 MB + . */ + +.rodata ALIGN (0x1000) : AT(ADDR(.text) - 0xC0000000) +{ + *(.rodata*) + /* all read-only data sections from all files */ +} +/* align at 4 KB and load at 1 MB + . */ + +.data ALIGN (0x1000) : AT(ADDR(.text) - 0xC0000000) +{ + *(.data) + /* all data sections from all files */ +} +/* align at 4 KB and load at 1 MB + . */ + +.bss ALIGN (0x1000) : AT(ADDR(.text) - 0xC0000000) +{ + *(COMMON) + /* all COMMON sections from all files */ + *(.bss) + /* all bss sections from all files */ +} \ No newline at end of file diff --git a/src/kernel/misc/list.c b/src/kernel/misc/list.c new file mode 100644 index 0000000..7c9ad61 --- /dev/null +++ b/src/kernel/misc/list.c @@ -0,0 +1,83 @@ +#include "./list.h" +#include "../sys/memory/alloc.h" + +node* find_tail(node* root) +{ + while(root && root->next) { root = root->next; } + return root; +} + +node* find_n(node* root, unsigned int n) +{ + while(root && root->next && n > 0) { root = root->next; --n; } + return root; +} + +node* add_head(node* root, uint32_t data) +{ + node* new_node = os_malloc(sizeof(node)); + new_node->data = data; + new_node->data2 = 0; + new_node->data3 = 0; + new_node->next = root; + return new_node; +} + +node* add_tail(node* root, uint32_t data) +{ + node* tail = find_tail(root); + node* new_node = os_malloc(sizeof(node)); + new_node->data = data; + new_node->data2 = 0; + new_node->data3 = 0; + new_node->next = nullptr; + if (tail == nullptr) return new_node; + tail->next = new_node; + return tail; +} + +node* add_after_n(node* root, uint32_t data, unsigned int n) +{ + node* prev = find_n(root, n); + node* new_node = os_malloc(sizeof(node)); + new_node->data = data; + new_node->data2 = 0; + new_node->data3 = 0; + new_node->next = nullptr; + if (prev == nullptr) return new_node; + if (prev->next) new_node->next = prev->next; + prev->next = new_node; + return root; +} + +node* remove_head(node* root) +{ + if (root == nullptr || root->next == nullptr) return nullptr; + node* ret = root->next; + root->next = nullptr; + return ret; +} + +node* remove_tail(node* root) +{ + node* cur = root; + while(cur && cur->next && cur->next->next) { cur = cur->next; } + if (cur == nullptr || cur->next == nullptr) return nullptr; + cur->next = nullptr; + return root; +} + +node* remove_n(node* root, unsigned int n) +{ + if (root == nullptr || root->next == nullptr) return nullptr; + if (n == 0) return remove_head(root); + node* prev = find_n(root, n - 1); + if (prev->next == nullptr) return remove_n(root, n - 2); + if (prev->next->next == nullptr) + { + prev->next = nullptr; + return root; + } + prev->next == prev->next->next; + return root; +} \ No newline at end of file diff --git a/src/kernel/misc/list.h b/src/kernel/misc/list.h new file mode 100644 index 0000000..45fa5cd --- /dev/null +++ b/src/kernel/misc/list.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +#pragma pack(push, 1) +typedef struct node_struct +{ + uint32_t data; + uint32_t data2; + uint32_t data3; + struct node_struct* next; + +} node, *pnode; +#pragma pack(pop) + + +node* find_tail(node* root); +node* find_n(node* root, unsigned int n); +node* add_head(node* root, uint32_t data); +node* add_tail(node* root, uint32_t data); +node* add_after_n(node* root, uint32_t data, unsigned int n); +node* remove_head(node* root); +node* remove_tail(node* root); +node* remove_n(node* root, unsigned int n); \ No newline at end of file diff --git a/src/kernel/sync/sync.asm b/src/kernel/sync/sync.asm new file mode 100644 index 0000000..674539e --- /dev/null +++ b/src/kernel/sync/sync.asm @@ -0,0 +1,98 @@ +[BITS 32] + +[EXTERN lock_32_irq] +[EXTERN lock_32] +[EXTERN unlock_32_irq] +[EXTERN unlock_32] + +lock_32_irq: + cli + push ebp + mov ebp, esp + push eax + push ebx + push ecx + mov ebx, 0x1 + ; xchg bx, bx + ; lea ecx, [ebp + 8] + mov ecx, dword [ebp + 8] +.start_lock: + xor eax, eax + lock cmpxchg dword [ecx], ebx + cmp eax, 0x0 + jne .start_lock + +locked_32_irq: + pop ecx + pop ebx + pop eax + mov esp, ebp + pop ebp + ret + +lock_32: + push ebp + mov ebp, esp + push eax + push ebx + push ecx + mov ebx, 0x1 + ; xchg bx, bx + ; lea ecx, [ebp + 8] + mov ecx, dword [ebp + 8] +.start_lock: + xor eax, eax + lock cmpxchg dword [ecx], ebx + cmp eax, 0x0 + jne .start_lock + +locked_32: + pop ecx + pop ebx + pop eax + mov esp, ebp + pop ebp + ret + +unlock_32_irq: + push ebp + mov ebp, esp + push eax + push ebx + ; xchg bx, bx + ; lea eax, [ebp + 8] + mov ebx, dword [ebp + 8] +.start_unlock: + mov eax, dword [ebx] + lock xor dword [ebx], eax + cmp eax, 0x0 + je .start_unlock + +unlocked_32_irq: + pop ebx + pop eax + mov esp, ebp + pop ebp + sti + ret + +unlock_32: + push ebp + mov ebp, esp + push eax + push ebx + ; xchg bx, bx + ; lea eax, [ebp + 8] + mov ebx, dword [ebp + 8] +.start_unlock: + mov eax, dword [ebx] + lock xor dword [ebx], eax + cmp eax, 0x0 + je .start_unlock + +unlocked_32: + pop ebx + pop eax + mov esp, ebp + pop ebp + ret \ No newline at end of file diff --git a/src/kernel/sync/sync.h b/src/kernel/sync/sync.h new file mode 100644 index 0000000..4a1e53e --- /dev/null +++ b/src/kernel/sync/sync.h @@ -0,0 +1,8 @@ +#pragma once + +typedef int mutex; + +extern void lock_32_irq(mutex* lock); +extern void lock_32(mutex* lock); +extern void unlock_32_irq(mutex* lock); +extern void unlock_32(mutex* lock); \ No newline at end of file diff --git a/src/kernel/sys/context/context.h b/src/kernel/sys/context/context.h new file mode 100644 index 0000000..093c754 --- /dev/null +++ b/src/kernel/sys/context/context.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include "../io/io.h" + +typedef struct +{ + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t esp; + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + uint16_t gs; + uint16_t padding_1; + uint16_t fs; + uint16_t padding_2; + uint16_t es; + uint16_t padding_3; + uint16_t ds; + uint16_t padding_4; + uint32_t vector; + uint32_t error_code; + uint32_t eip; + uint16_t cs; + uint16_t padding_5; + uint32_t eflags; + uint32_t esp_before; + uint16_t ss; + uint16_t padding_6; + +} context; + +typedef struct +{ + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t esp_on_handling; + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + uint16_t gs; + uint16_t padding_1; + uint16_t fs; + uint16_t padding_2; + uint16_t es; + uint16_t padding_3; + uint16_t ds; + uint16_t padding_4; + uint32_t vector; + uint32_t error_code; + uint32_t eip; + uint16_t cs; + uint16_t padding_5; + +} crop_context; diff --git a/src/kernel/sys/context/experiment.asm b/src/kernel/sys/context/experiment.asm new file mode 100644 index 0000000..790e2e9 --- /dev/null +++ b/src/kernel/sys/context/experiment.asm @@ -0,0 +1,23 @@ +[BITS 32] + +[GLOBAL experiment] + +experiment: + push ebp + mov ebp, esp + pusha + + ; xchg bx, bx + mov eax, 1 + mov ecx, 2 + mov edx, 3 + mov ebx, 4 + mov esi, 5 + mov edi, 6 + mov ebp, 7 + int 42 + + popa + mov esp, ebp + pop ebp + ret \ No newline at end of file diff --git a/src/kernel/sys/context/gen_asm_context.py b/src/kernel/sys/context/gen_asm_context.py new file mode 100644 index 0000000..30166b2 --- /dev/null +++ b/src/kernel/sys/context/gen_asm_context.py @@ -0,0 +1,28 @@ +exceptions_with_error_code = {8, 10, 11, 12, 13, 14, 17, 21, 29, 30} + +with open("./src/kernel/sys/context/tramplinsWContext.asm", "w") as f: + + + wr = f.write + wr("[BITS 32]\n\n") + + for i in range(0, 256): + wr(f"[GLOBAL tramplin_{str(hex(i))[2:]}]\n") + + wr(''' +collect_context: + push ds + push es + push fs + push gs + pusha +''') + + wr("\n\n") + for i in range(0, 256): + wr(f"tramplin_{str(hex(i))[2:]}:\n") + if i not in exceptions_with_error_code: + wr("\tpush 0x0\n") + wr(f"\tpush 0x{str(hex(i))[2:]}\n") + wr("\tjmp collect_context") + wr("\n\n") \ No newline at end of file diff --git a/src/kernel/sys/context/tramplinsWContext.asm b/src/kernel/sys/context/tramplinsWContext.asm new file mode 100644 index 0000000..49ba201 --- /dev/null +++ b/src/kernel/sys/context/tramplinsWContext.asm @@ -0,0 +1,1556 @@ +[BITS 32] + +[GLOBAL tramplin_0] +[GLOBAL tramplin_1] +[GLOBAL tramplin_2] +[GLOBAL tramplin_3] +[GLOBAL tramplin_4] +[GLOBAL tramplin_5] +[GLOBAL tramplin_6] +[GLOBAL tramplin_7] +[GLOBAL tramplin_8] +[GLOBAL tramplin_9] +[GLOBAL tramplin_a] +[GLOBAL tramplin_b] +[GLOBAL tramplin_c] +[GLOBAL tramplin_d] +[GLOBAL tramplin_e] +[GLOBAL tramplin_f] +[GLOBAL tramplin_10] +[GLOBAL tramplin_11] +[GLOBAL tramplin_12] +[GLOBAL tramplin_13] +[GLOBAL tramplin_14] +[GLOBAL tramplin_15] +[GLOBAL tramplin_16] +[GLOBAL tramplin_17] +[GLOBAL tramplin_18] +[GLOBAL tramplin_19] +[GLOBAL tramplin_1a] +[GLOBAL tramplin_1b] +[GLOBAL tramplin_1c] +[GLOBAL tramplin_1d] +[GLOBAL tramplin_1e] +[GLOBAL tramplin_1f] +[GLOBAL tramplin_20] +[GLOBAL tramplin_21] +[GLOBAL tramplin_22] +[GLOBAL tramplin_23] +[GLOBAL tramplin_24] +[GLOBAL tramplin_25] +[GLOBAL tramplin_26] +[GLOBAL tramplin_27] +[GLOBAL tramplin_28] +[GLOBAL tramplin_29] +[GLOBAL tramplin_2a] +[GLOBAL tramplin_2b] +[GLOBAL tramplin_2c] +[GLOBAL tramplin_2d] +[GLOBAL tramplin_2e] +[GLOBAL tramplin_2f] +[GLOBAL tramplin_30] +[GLOBAL tramplin_31] +[GLOBAL tramplin_32] +[GLOBAL tramplin_33] +[GLOBAL tramplin_34] +[GLOBAL tramplin_35] +[GLOBAL tramplin_36] +[GLOBAL tramplin_37] +[GLOBAL tramplin_38] +[GLOBAL tramplin_39] +[GLOBAL tramplin_3a] +[GLOBAL tramplin_3b] +[GLOBAL tramplin_3c] +[GLOBAL tramplin_3d] +[GLOBAL tramplin_3e] +[GLOBAL tramplin_3f] +[GLOBAL tramplin_40] +[GLOBAL tramplin_41] +[GLOBAL tramplin_42] +[GLOBAL tramplin_43] +[GLOBAL tramplin_44] +[GLOBAL tramplin_45] +[GLOBAL tramplin_46] +[GLOBAL tramplin_47] +[GLOBAL tramplin_48] +[GLOBAL tramplin_49] +[GLOBAL tramplin_4a] +[GLOBAL tramplin_4b] +[GLOBAL tramplin_4c] +[GLOBAL tramplin_4d] +[GLOBAL tramplin_4e] +[GLOBAL tramplin_4f] +[GLOBAL tramplin_50] +[GLOBAL tramplin_51] +[GLOBAL tramplin_52] +[GLOBAL tramplin_53] +[GLOBAL tramplin_54] +[GLOBAL tramplin_55] +[GLOBAL tramplin_56] +[GLOBAL tramplin_57] +[GLOBAL tramplin_58] +[GLOBAL tramplin_59] +[GLOBAL tramplin_5a] +[GLOBAL tramplin_5b] +[GLOBAL tramplin_5c] +[GLOBAL tramplin_5d] +[GLOBAL tramplin_5e] +[GLOBAL tramplin_5f] +[GLOBAL tramplin_60] +[GLOBAL tramplin_61] +[GLOBAL tramplin_62] +[GLOBAL tramplin_63] +[GLOBAL tramplin_64] +[GLOBAL tramplin_65] +[GLOBAL tramplin_66] +[GLOBAL tramplin_67] +[GLOBAL tramplin_68] +[GLOBAL tramplin_69] +[GLOBAL tramplin_6a] +[GLOBAL tramplin_6b] +[GLOBAL tramplin_6c] +[GLOBAL tramplin_6d] +[GLOBAL tramplin_6e] +[GLOBAL tramplin_6f] +[GLOBAL tramplin_70] +[GLOBAL tramplin_71] +[GLOBAL tramplin_72] +[GLOBAL tramplin_73] +[GLOBAL tramplin_74] +[GLOBAL tramplin_75] +[GLOBAL tramplin_76] +[GLOBAL tramplin_77] +[GLOBAL tramplin_78] +[GLOBAL tramplin_79] +[GLOBAL tramplin_7a] +[GLOBAL tramplin_7b] +[GLOBAL tramplin_7c] +[GLOBAL tramplin_7d] +[GLOBAL tramplin_7e] +[GLOBAL tramplin_7f] +[GLOBAL tramplin_80] +[GLOBAL tramplin_81] +[GLOBAL tramplin_82] +[GLOBAL tramplin_83] +[GLOBAL tramplin_84] +[GLOBAL tramplin_85] +[GLOBAL tramplin_86] +[GLOBAL tramplin_87] +[GLOBAL tramplin_88] +[GLOBAL tramplin_89] +[GLOBAL tramplin_8a] +[GLOBAL tramplin_8b] +[GLOBAL tramplin_8c] +[GLOBAL tramplin_8d] +[GLOBAL tramplin_8e] +[GLOBAL tramplin_8f] +[GLOBAL tramplin_90] +[GLOBAL tramplin_91] +[GLOBAL tramplin_92] +[GLOBAL tramplin_93] +[GLOBAL tramplin_94] +[GLOBAL tramplin_95] +[GLOBAL tramplin_96] +[GLOBAL tramplin_97] +[GLOBAL tramplin_98] +[GLOBAL tramplin_99] +[GLOBAL tramplin_9a] +[GLOBAL tramplin_9b] +[GLOBAL tramplin_9c] +[GLOBAL tramplin_9d] +[GLOBAL tramplin_9e] +[GLOBAL tramplin_9f] +[GLOBAL tramplin_a0] +[GLOBAL tramplin_a1] +[GLOBAL tramplin_a2] +[GLOBAL tramplin_a3] +[GLOBAL tramplin_a4] +[GLOBAL tramplin_a5] +[GLOBAL tramplin_a6] +[GLOBAL tramplin_a7] +[GLOBAL tramplin_a8] +[GLOBAL tramplin_a9] +[GLOBAL tramplin_aa] +[GLOBAL tramplin_ab] +[GLOBAL tramplin_ac] +[GLOBAL tramplin_ad] +[GLOBAL tramplin_ae] +[GLOBAL tramplin_af] +[GLOBAL tramplin_b0] +[GLOBAL tramplin_b1] +[GLOBAL tramplin_b2] +[GLOBAL tramplin_b3] +[GLOBAL tramplin_b4] +[GLOBAL tramplin_b5] +[GLOBAL tramplin_b6] +[GLOBAL tramplin_b7] +[GLOBAL tramplin_b8] +[GLOBAL tramplin_b9] +[GLOBAL tramplin_ba] +[GLOBAL tramplin_bb] +[GLOBAL tramplin_bc] +[GLOBAL tramplin_bd] +[GLOBAL tramplin_be] +[GLOBAL tramplin_bf] +[GLOBAL tramplin_c0] +[GLOBAL tramplin_c1] +[GLOBAL tramplin_c2] +[GLOBAL tramplin_c3] +[GLOBAL tramplin_c4] +[GLOBAL tramplin_c5] +[GLOBAL tramplin_c6] +[GLOBAL tramplin_c7] +[GLOBAL tramplin_c8] +[GLOBAL tramplin_c9] +[GLOBAL tramplin_ca] +[GLOBAL tramplin_cb] +[GLOBAL tramplin_cc] +[GLOBAL tramplin_cd] +[GLOBAL tramplin_ce] +[GLOBAL tramplin_cf] +[GLOBAL tramplin_d0] +[GLOBAL tramplin_d1] +[GLOBAL tramplin_d2] +[GLOBAL tramplin_d3] +[GLOBAL tramplin_d4] +[GLOBAL tramplin_d5] +[GLOBAL tramplin_d6] +[GLOBAL tramplin_d7] +[GLOBAL tramplin_d8] +[GLOBAL tramplin_d9] +[GLOBAL tramplin_da] +[GLOBAL tramplin_db] +[GLOBAL tramplin_dc] +[GLOBAL tramplin_dd] +[GLOBAL tramplin_de] +[GLOBAL tramplin_df] +[GLOBAL tramplin_e0] +[GLOBAL tramplin_e1] +[GLOBAL tramplin_e2] +[GLOBAL tramplin_e3] +[GLOBAL tramplin_e4] +[GLOBAL tramplin_e5] +[GLOBAL tramplin_e6] +[GLOBAL tramplin_e7] +[GLOBAL tramplin_e8] +[GLOBAL tramplin_e9] +[GLOBAL tramplin_ea] +[GLOBAL tramplin_eb] +[GLOBAL tramplin_ec] +[GLOBAL tramplin_ed] +[GLOBAL tramplin_ee] +[GLOBAL tramplin_ef] +[GLOBAL tramplin_f0] +[GLOBAL tramplin_f1] +[GLOBAL tramplin_f2] +[GLOBAL tramplin_f3] +[GLOBAL tramplin_f4] +[GLOBAL tramplin_f5] +[GLOBAL tramplin_f6] +[GLOBAL tramplin_f7] +[GLOBAL tramplin_f8] +[GLOBAL tramplin_f9] +[GLOBAL tramplin_fa] +[GLOBAL tramplin_fb] +[GLOBAL tramplin_fc] +[GLOBAL tramplin_fd] +[GLOBAL tramplin_fe] +[GLOBAL tramplin_ff] + +[EXTERN interrupt_handler] + +collect_context: + push ds + push es + push fs + push gs + pusha + push esp + + mov eax, 0x10 + mov ds, eax + mov es, eax + + call interrupt_handler + + pop esp + popa + pop gs + pop fs + pop es + pop ds + + add esp, 8 + + iretd + +tramplin_0: + push 0x0 + push 0x0 + jmp collect_context + +tramplin_1: + push 0x0 + push 0x1 + jmp collect_context + +tramplin_2: + push 0x0 + push 0x2 + jmp collect_context + +tramplin_3: + push 0x0 + push 0x3 + jmp collect_context + +tramplin_4: + push 0x0 + push 0x4 + jmp collect_context + +tramplin_5: + push 0x0 + push 0x5 + jmp collect_context + +tramplin_6: + push 0x0 + push 0x6 + jmp collect_context + +tramplin_7: + push 0x0 + push 0x7 + jmp collect_context + +tramplin_8: + push 0x8 + jmp collect_context + +tramplin_9: + push 0x0 + push 0x9 + jmp collect_context + +tramplin_a: + push 0xa + jmp collect_context + +tramplin_b: + push 0xb + jmp collect_context + +tramplin_c: + push 0xc + jmp collect_context + +tramplin_d: + push 0xd + jmp collect_context + +tramplin_e: + push 0xe + jmp collect_context + +tramplin_f: + push 0x0 + push 0xf + jmp collect_context + +tramplin_10: + push 0x0 + push 0x10 + jmp collect_context + +tramplin_11: + push 0x11 + jmp collect_context + +tramplin_12: + push 0x0 + push 0x12 + jmp collect_context + +tramplin_13: + push 0x0 + push 0x13 + jmp collect_context + +tramplin_14: + push 0x0 + push 0x14 + jmp collect_context + +tramplin_15: + push 0x15 + jmp collect_context + +tramplin_16: + push 0x0 + push 0x16 + jmp collect_context + +tramplin_17: + push 0x0 + push 0x17 + jmp collect_context + +tramplin_18: + push 0x0 + push 0x18 + jmp collect_context + +tramplin_19: + push 0x0 + push 0x19 + jmp collect_context + +tramplin_1a: + push 0x0 + push 0x1a + jmp collect_context + +tramplin_1b: + push 0x0 + push 0x1b + jmp collect_context + +tramplin_1c: + push 0x0 + push 0x1c + jmp collect_context + +tramplin_1d: + push 0x1d + jmp collect_context + +tramplin_1e: + push 0x1e + jmp collect_context + +tramplin_1f: + push 0x0 + push 0x1f + jmp collect_context + +tramplin_20: + push 0x0 + push 0x20 + jmp collect_context + +tramplin_21: + push 0x0 + push 0x21 + jmp collect_context + +tramplin_22: + push 0x0 + push 0x22 + jmp collect_context + +tramplin_23: + push 0x0 + push 0x23 + jmp collect_context + +tramplin_24: + push 0x0 + push 0x24 + jmp collect_context + +tramplin_25: + push 0x0 + push 0x25 + jmp collect_context + +tramplin_26: + push 0x0 + push 0x26 + jmp collect_context + +tramplin_27: + push 0x0 + push 0x27 + jmp collect_context + +tramplin_28: + push 0x0 + push 0x28 + jmp collect_context + +tramplin_29: + push 0x0 + push 0x29 + jmp collect_context + +tramplin_2a: + push 0x0 + push 0x2a + jmp collect_context + +tramplin_2b: + push 0x0 + push 0x2b + jmp collect_context + +tramplin_2c: + push 0x0 + push 0x2c + jmp collect_context + +tramplin_2d: + push 0x0 + push 0x2d + jmp collect_context + +tramplin_2e: + push 0x0 + push 0x2e + jmp collect_context + +tramplin_2f: + push 0x0 + push 0x2f + jmp collect_context + +tramplin_30: + push 0x0 + push 0x30 + jmp collect_context + +tramplin_31: + push 0x0 + push 0x31 + jmp collect_context + +tramplin_32: + push 0x0 + push 0x32 + jmp collect_context + +tramplin_33: + push 0x0 + push 0x33 + jmp collect_context + +tramplin_34: + push 0x0 + push 0x34 + jmp collect_context + +tramplin_35: + push 0x0 + push 0x35 + jmp collect_context + +tramplin_36: + push 0x0 + push 0x36 + jmp collect_context + +tramplin_37: + push 0x0 + push 0x37 + jmp collect_context + +tramplin_38: + push 0x0 + push 0x38 + jmp collect_context + +tramplin_39: + push 0x0 + push 0x39 + jmp collect_context + +tramplin_3a: + push 0x0 + push 0x3a + jmp collect_context + +tramplin_3b: + push 0x0 + push 0x3b + jmp collect_context + +tramplin_3c: + push 0x0 + push 0x3c + jmp collect_context + +tramplin_3d: + push 0x0 + push 0x3d + jmp collect_context + +tramplin_3e: + push 0x0 + push 0x3e + jmp collect_context + +tramplin_3f: + push 0x0 + push 0x3f + jmp collect_context + +tramplin_40: + push 0x0 + push 0x40 + jmp collect_context + +tramplin_41: + push 0x0 + push 0x41 + jmp collect_context + +tramplin_42: + push 0x0 + push 0x42 + jmp collect_context + +tramplin_43: + push 0x0 + push 0x43 + jmp collect_context + +tramplin_44: + push 0x0 + push 0x44 + jmp collect_context + +tramplin_45: + push 0x0 + push 0x45 + jmp collect_context + +tramplin_46: + push 0x0 + push 0x46 + jmp collect_context + +tramplin_47: + push 0x0 + push 0x47 + jmp collect_context + +tramplin_48: + push 0x0 + push 0x48 + jmp collect_context + +tramplin_49: + push 0x0 + push 0x49 + jmp collect_context + +tramplin_4a: + push 0x0 + push 0x4a + jmp collect_context + +tramplin_4b: + push 0x0 + push 0x4b + jmp collect_context + +tramplin_4c: + push 0x0 + push 0x4c + jmp collect_context + +tramplin_4d: + push 0x0 + push 0x4d + jmp collect_context + +tramplin_4e: + push 0x0 + push 0x4e + jmp collect_context + +tramplin_4f: + push 0x0 + push 0x4f + jmp collect_context + +tramplin_50: + push 0x0 + push 0x50 + jmp collect_context + +tramplin_51: + push 0x0 + push 0x51 + jmp collect_context + +tramplin_52: + push 0x0 + push 0x52 + jmp collect_context + +tramplin_53: + push 0x0 + push 0x53 + jmp collect_context + +tramplin_54: + push 0x0 + push 0x54 + jmp collect_context + +tramplin_55: + push 0x0 + push 0x55 + jmp collect_context + +tramplin_56: + push 0x0 + push 0x56 + jmp collect_context + +tramplin_57: + push 0x0 + push 0x57 + jmp collect_context + +tramplin_58: + push 0x0 + push 0x58 + jmp collect_context + +tramplin_59: + push 0x0 + push 0x59 + jmp collect_context + +tramplin_5a: + push 0x0 + push 0x5a + jmp collect_context + +tramplin_5b: + push 0x0 + push 0x5b + jmp collect_context + +tramplin_5c: + push 0x0 + push 0x5c + jmp collect_context + +tramplin_5d: + push 0x0 + push 0x5d + jmp collect_context + +tramplin_5e: + push 0x0 + push 0x5e + jmp collect_context + +tramplin_5f: + push 0x0 + push 0x5f + jmp collect_context + +tramplin_60: + push 0x0 + push 0x60 + jmp collect_context + +tramplin_61: + push 0x0 + push 0x61 + jmp collect_context + +tramplin_62: + push 0x0 + push 0x62 + jmp collect_context + +tramplin_63: + push 0x0 + push 0x63 + jmp collect_context + +tramplin_64: + push 0x0 + push 0x64 + jmp collect_context + +tramplin_65: + push 0x0 + push 0x65 + jmp collect_context + +tramplin_66: + push 0x0 + push 0x66 + jmp collect_context + +tramplin_67: + push 0x0 + push 0x67 + jmp collect_context + +tramplin_68: + push 0x0 + push 0x68 + jmp collect_context + +tramplin_69: + push 0x0 + push 0x69 + jmp collect_context + +tramplin_6a: + push 0x0 + push 0x6a + jmp collect_context + +tramplin_6b: + push 0x0 + push 0x6b + jmp collect_context + +tramplin_6c: + push 0x0 + push 0x6c + jmp collect_context + +tramplin_6d: + push 0x0 + push 0x6d + jmp collect_context + +tramplin_6e: + push 0x0 + push 0x6e + jmp collect_context + +tramplin_6f: + push 0x0 + push 0x6f + jmp collect_context + +tramplin_70: + push 0x0 + push 0x70 + jmp collect_context + +tramplin_71: + push 0x0 + push 0x71 + jmp collect_context + +tramplin_72: + push 0x0 + push 0x72 + jmp collect_context + +tramplin_73: + push 0x0 + push 0x73 + jmp collect_context + +tramplin_74: + push 0x0 + push 0x74 + jmp collect_context + +tramplin_75: + push 0x0 + push 0x75 + jmp collect_context + +tramplin_76: + push 0x0 + push 0x76 + jmp collect_context + +tramplin_77: + push 0x0 + push 0x77 + jmp collect_context + +tramplin_78: + push 0x0 + push 0x78 + jmp collect_context + +tramplin_79: + push 0x0 + push 0x79 + jmp collect_context + +tramplin_7a: + push 0x0 + push 0x7a + jmp collect_context + +tramplin_7b: + push 0x0 + push 0x7b + jmp collect_context + +tramplin_7c: + push 0x0 + push 0x7c + jmp collect_context + +tramplin_7d: + push 0x0 + push 0x7d + jmp collect_context + +tramplin_7e: + push 0x0 + push 0x7e + jmp collect_context + +tramplin_7f: + push 0x0 + push 0x7f + jmp collect_context + +tramplin_80: + push 0x0 + push 0x80 + jmp collect_context + +tramplin_81: + push 0x0 + push 0x81 + jmp collect_context + +tramplin_82: + push 0x0 + push 0x82 + jmp collect_context + +tramplin_83: + push 0x0 + push 0x83 + jmp collect_context + +tramplin_84: + push 0x0 + push 0x84 + jmp collect_context + +tramplin_85: + push 0x0 + push 0x85 + jmp collect_context + +tramplin_86: + push 0x0 + push 0x86 + jmp collect_context + +tramplin_87: + push 0x0 + push 0x87 + jmp collect_context + +tramplin_88: + push 0x0 + push 0x88 + jmp collect_context + +tramplin_89: + push 0x0 + push 0x89 + jmp collect_context + +tramplin_8a: + push 0x0 + push 0x8a + jmp collect_context + +tramplin_8b: + push 0x0 + push 0x8b + jmp collect_context + +tramplin_8c: + push 0x0 + push 0x8c + jmp collect_context + +tramplin_8d: + push 0x0 + push 0x8d + jmp collect_context + +tramplin_8e: + push 0x0 + push 0x8e + jmp collect_context + +tramplin_8f: + push 0x0 + push 0x8f + jmp collect_context + +tramplin_90: + push 0x0 + push 0x90 + jmp collect_context + +tramplin_91: + push 0x0 + push 0x91 + jmp collect_context + +tramplin_92: + push 0x0 + push 0x92 + jmp collect_context + +tramplin_93: + push 0x0 + push 0x93 + jmp collect_context + +tramplin_94: + push 0x0 + push 0x94 + jmp collect_context + +tramplin_95: + push 0x0 + push 0x95 + jmp collect_context + +tramplin_96: + push 0x0 + push 0x96 + jmp collect_context + +tramplin_97: + push 0x0 + push 0x97 + jmp collect_context + +tramplin_98: + push 0x0 + push 0x98 + jmp collect_context + +tramplin_99: + push 0x0 + push 0x99 + jmp collect_context + +tramplin_9a: + push 0x0 + push 0x9a + jmp collect_context + +tramplin_9b: + push 0x0 + push 0x9b + jmp collect_context + +tramplin_9c: + push 0x0 + push 0x9c + jmp collect_context + +tramplin_9d: + push 0x0 + push 0x9d + jmp collect_context + +tramplin_9e: + push 0x0 + push 0x9e + jmp collect_context + +tramplin_9f: + push 0x0 + push 0x9f + jmp collect_context + +tramplin_a0: + push 0x0 + push 0xa0 + jmp collect_context + +tramplin_a1: + push 0x0 + push 0xa1 + jmp collect_context + +tramplin_a2: + push 0x0 + push 0xa2 + jmp collect_context + +tramplin_a3: + push 0x0 + push 0xa3 + jmp collect_context + +tramplin_a4: + push 0x0 + push 0xa4 + jmp collect_context + +tramplin_a5: + push 0x0 + push 0xa5 + jmp collect_context + +tramplin_a6: + push 0x0 + push 0xa6 + jmp collect_context + +tramplin_a7: + push 0x0 + push 0xa7 + jmp collect_context + +tramplin_a8: + push 0x0 + push 0xa8 + jmp collect_context + +tramplin_a9: + push 0x0 + push 0xa9 + jmp collect_context + +tramplin_aa: + push 0x0 + push 0xaa + jmp collect_context + +tramplin_ab: + push 0x0 + push 0xab + jmp collect_context + +tramplin_ac: + push 0x0 + push 0xac + jmp collect_context + +tramplin_ad: + push 0x0 + push 0xad + jmp collect_context + +tramplin_ae: + push 0x0 + push 0xae + jmp collect_context + +tramplin_af: + push 0x0 + push 0xaf + jmp collect_context + +tramplin_b0: + push 0x0 + push 0xb0 + jmp collect_context + +tramplin_b1: + push 0x0 + push 0xb1 + jmp collect_context + +tramplin_b2: + push 0x0 + push 0xb2 + jmp collect_context + +tramplin_b3: + push 0x0 + push 0xb3 + jmp collect_context + +tramplin_b4: + push 0x0 + push 0xb4 + jmp collect_context + +tramplin_b5: + push 0x0 + push 0xb5 + jmp collect_context + +tramplin_b6: + push 0x0 + push 0xb6 + jmp collect_context + +tramplin_b7: + push 0x0 + push 0xb7 + jmp collect_context + +tramplin_b8: + push 0x0 + push 0xb8 + jmp collect_context + +tramplin_b9: + push 0x0 + push 0xb9 + jmp collect_context + +tramplin_ba: + push 0x0 + push 0xba + jmp collect_context + +tramplin_bb: + push 0x0 + push 0xbb + jmp collect_context + +tramplin_bc: + push 0x0 + push 0xbc + jmp collect_context + +tramplin_bd: + push 0x0 + push 0xbd + jmp collect_context + +tramplin_be: + push 0x0 + push 0xbe + jmp collect_context + +tramplin_bf: + push 0x0 + push 0xbf + jmp collect_context + +tramplin_c0: + push 0x0 + push 0xc0 + jmp collect_context + +tramplin_c1: + push 0x0 + push 0xc1 + jmp collect_context + +tramplin_c2: + push 0x0 + push 0xc2 + jmp collect_context + +tramplin_c3: + push 0x0 + push 0xc3 + jmp collect_context + +tramplin_c4: + push 0x0 + push 0xc4 + jmp collect_context + +tramplin_c5: + push 0x0 + push 0xc5 + jmp collect_context + +tramplin_c6: + push 0x0 + push 0xc6 + jmp collect_context + +tramplin_c7: + push 0x0 + push 0xc7 + jmp collect_context + +tramplin_c8: + push 0x0 + push 0xc8 + jmp collect_context + +tramplin_c9: + push 0x0 + push 0xc9 + jmp collect_context + +tramplin_ca: + push 0x0 + push 0xca + jmp collect_context + +tramplin_cb: + push 0x0 + push 0xcb + jmp collect_context + +tramplin_cc: + push 0x0 + push 0xcc + jmp collect_context + +tramplin_cd: + push 0x0 + push 0xcd + jmp collect_context + +tramplin_ce: + push 0x0 + push 0xce + jmp collect_context + +tramplin_cf: + push 0x0 + push 0xcf + jmp collect_context + +tramplin_d0: + push 0x0 + push 0xd0 + jmp collect_context + +tramplin_d1: + push 0x0 + push 0xd1 + jmp collect_context + +tramplin_d2: + push 0x0 + push 0xd2 + jmp collect_context + +tramplin_d3: + push 0x0 + push 0xd3 + jmp collect_context + +tramplin_d4: + push 0x0 + push 0xd4 + jmp collect_context + +tramplin_d5: + push 0x0 + push 0xd5 + jmp collect_context + +tramplin_d6: + push 0x0 + push 0xd6 + jmp collect_context + +tramplin_d7: + push 0x0 + push 0xd7 + jmp collect_context + +tramplin_d8: + push 0x0 + push 0xd8 + jmp collect_context + +tramplin_d9: + push 0x0 + push 0xd9 + jmp collect_context + +tramplin_da: + push 0x0 + push 0xda + jmp collect_context + +tramplin_db: + push 0x0 + push 0xdb + jmp collect_context + +tramplin_dc: + push 0x0 + push 0xdc + jmp collect_context + +tramplin_dd: + push 0x0 + push 0xdd + jmp collect_context + +tramplin_de: + push 0x0 + push 0xde + jmp collect_context + +tramplin_df: + push 0x0 + push 0xdf + jmp collect_context + +tramplin_e0: + push 0x0 + push 0xe0 + jmp collect_context + +tramplin_e1: + push 0x0 + push 0xe1 + jmp collect_context + +tramplin_e2: + push 0x0 + push 0xe2 + jmp collect_context + +tramplin_e3: + push 0x0 + push 0xe3 + jmp collect_context + +tramplin_e4: + push 0x0 + push 0xe4 + jmp collect_context + +tramplin_e5: + push 0x0 + push 0xe5 + jmp collect_context + +tramplin_e6: + push 0x0 + push 0xe6 + jmp collect_context + +tramplin_e7: + push 0x0 + push 0xe7 + jmp collect_context + +tramplin_e8: + push 0x0 + push 0xe8 + jmp collect_context + +tramplin_e9: + push 0x0 + push 0xe9 + jmp collect_context + +tramplin_ea: + push 0x0 + push 0xea + jmp collect_context + +tramplin_eb: + push 0x0 + push 0xeb + jmp collect_context + +tramplin_ec: + push 0x0 + push 0xec + jmp collect_context + +tramplin_ed: + push 0x0 + push 0xed + jmp collect_context + +tramplin_ee: + push 0x0 + push 0xee + jmp collect_context + +tramplin_ef: + push 0x0 + push 0xef + jmp collect_context + +tramplin_f0: + push 0x0 + push 0xf0 + jmp collect_context + +tramplin_f1: + push 0x0 + push 0xf1 + jmp collect_context + +tramplin_f2: + push 0x0 + push 0xf2 + jmp collect_context + +tramplin_f3: + push 0x0 + push 0xf3 + jmp collect_context + +tramplin_f4: + push 0x0 + push 0xf4 + jmp collect_context + +tramplin_f5: + push 0x0 + push 0xf5 + jmp collect_context + +tramplin_f6: + push 0x0 + push 0xf6 + jmp collect_context + +tramplin_f7: + push 0x0 + push 0xf7 + jmp collect_context + +tramplin_f8: + push 0x0 + push 0xf8 + jmp collect_context + +tramplin_f9: + push 0x0 + push 0xf9 + jmp collect_context + +tramplin_fa: + push 0x0 + push 0xfa + jmp collect_context + +tramplin_fb: + push 0x0 + push 0xfb + jmp collect_context + +tramplin_fc: + push 0x0 + push 0xfc + jmp collect_context + +tramplin_fd: + push 0x0 + push 0xfd + jmp collect_context + +tramplin_fe: + push 0x0 + push 0xfe + jmp collect_context + +tramplin_ff: + push 0x0 + push 0xff + jmp collect_context + diff --git a/src/kernel/sys/gen_tramplins.py b/src/kernel/sys/gen_tramplins.py new file mode 100644 index 0000000..16b5cc1 --- /dev/null +++ b/src/kernel/sys/gen_tramplins.py @@ -0,0 +1,15 @@ +import os + +root = os.getcwd() + '/src/kernel/sys' + +with open(root + '/tramplins.hpp.template','r') as ff, open(root + '/tramplins.hpp','w') as sf: + for line in ff: + sf.write(line) + all_tramplins = '' + indent = '\n\t\t\t\t\t' + for i in range(255): + sf.write('__gen_tramplin(%s)\n' % hex(i).split('x')[-1]) + all_tramplins += 'tramplin_%s,%s' % (hex(i).split('x')[-1], indent if (i + 1) % 8 == 0 else ' ') + sf.write('__gen_tramplin(ff)\n') + all_tramplins += 'tramplin_ff' + sf.write('__gen_tramplins(%s)\n' % all_tramplins) \ No newline at end of file diff --git a/src/kernel/sys/idt.h b/src/kernel/sys/idt.h new file mode 100644 index 0000000..c834ddd --- /dev/null +++ b/src/kernel/sys/idt.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#pragma pack(push, 1) +typedef struct { + uint16_t offset_1; // offset bits 0..15 + uint16_t selector; // a code segment selector in GDT or LDT + uint8_t zero; // unused, set to 0 + uint8_t gate_type; // gate type, dpl, and p fields + uint16_t offset_2; // offset bits 16..31 +} InterruptDescriptor32; +#pragma pack(pop) \ No newline at end of file diff --git a/src/kernel/sys/interruption.c b/src/kernel/sys/interruption.c new file mode 100644 index 0000000..7abcf6a --- /dev/null +++ b/src/kernel/sys/interruption.c @@ -0,0 +1,390 @@ +#include "./interruption.h" +#include "./paging/paging.h" +#include "./process/scheduler.h" +#include "../sync/sync.h" +#include "../../libc/io/printer.h" + +void kernel_panic(char* str, int type) +{ + init_printer(); + printf(str, type); + while (1); +} + +void panic_handler(int vector) +{ + kernel_panic("unhandled interrupt %x", vector); +} + +InterruptDescriptor32* init_idt(ptr_t shift) +{ + InterruptDescriptor32* idt = (InterruptDescriptor32*)kernel_calloc(sizeof(InterruptDescriptor32) * 256u, 12u); + if (idt == nullptr) + { + printf("[EXC] register_handlers(): not enough memory!"); + } + + for (int i = 0; i < 256; ++i) + { + if (i < 32) + { + idt[i].gate_type = 0x8F; + } + else + { + idt[i].gate_type = 0x8E; + } + idt[i].offset_1 = (uint16_t) ((ptr_t)tramplins[i] + shift); // lower bits + idt[i].offset_2 = (uint16_t) (((ptr_t)tramplins[i] + shift) >> 16); // upper bits + idt[i].selector = 0b1000; + } + + return idt; +} + +void reg_idtd(InterruptDescriptor32* idt) +{ + IDTD idtd; + idtd.IDT_size = sizeof(InterruptDescriptor32) * 256 - 1; + idtd.linear_addr_IDT = (uint32_t)(idt); + + asm("lidt %0" :: "m"(idtd)); +} + +void timer_interrupt(context* ctx); +void page_fault(context* ctx); +void page_fault_pse(context* ctx); +void default_panic_handler(context* ctx); + +void interrupt_handler(context* ctx) { + switch (ctx->vector) { + case 0x20: + { + timer_interrupt(ctx); + outb(0x20, 0x20); + break; + } + case 0xe: + { + // page_fault(ctx); // non-PSE + page_fault_pse(ctx); // PSE + break; + } + default: + { + default_panic_handler(ctx); + break; + } + } +} + +void timer_interrupt(context* ctx) { + static int counter = 0u; + // printf("\n%d ", counter); + lock_32_irq(&lock_scheduler); + if (counter == 100) + { + counter = 0u; + int printf_was_locked = 0; + int cprint_was_locked = 0; + if (lock_printf) + { + printf("[SWITCH TO NEXT] PRINTF WAS LOCKED\n"); + unlock_32(&lock_printf); + printf_was_locked = 1; + } + if (lock_cprint) + { + printf("[SWITCH TO NEXT] CPRINT WAS LOCKED\n"); + unlock_32(&lock_cprint); + cprint_was_locked = 1; + } + // unsigned int current_eflags; + // asm("pushf\n\t" + // "pop %0" + // : "=g"(current_eflags) + // : + // : "memory" + // ); + // printf("T[INFO] Interrupt %x, interrupted process context:\n" + // " EAX = %x ECX = %x EDX = %x EBX = %x\n" + // " ESP = %x EBP = %x ESI = %x EDI = %x\n" + // " DS = %x ES = %x FS = %x GS = %x\n" + // " CS = %x SS = %x EIP = %x\n" + // " EFLAGS (interrupted) = %x " "EFLAGS (current) = %x\n" + // " error code = %x\n", + // ctx->vector, + // ctx->eax, ctx->ecx, ctx->edx, ctx->ebx, + // ctx->esp, ctx->ebp, ctx->esi, ctx->edi, + // ctx->ds, ctx->es, ctx->fs, ctx->gs, + // ctx->cs, ctx->ss, ctx->eip, + // ctx->eflags, current_eflags, + // ctx->error_code); + // asm("xchgw %bx, %bx"); + int lockword = switch_to_next(ctx, (!!printf_was_locked << 0) | (!!cprint_was_locked << 1)); + if (lockword & (1u << 0)) lock_32(&lock_printf); + if (lockword & (1u << 1)) lock_32(&lock_cprint); + // asm("xchgw %bx, %bx"); + } + else + { + unlock_32_irq(&lock_scheduler); + } + ++counter; +} + +void page_fault(context* ctx) +{ + // init_printer(); + // printf("[PAGE FAULT HANDLING] START\n"); + unsigned int ec = ctx->error_code; + if (!(ec & 1)) + { + ptr_t* cr2 = nullptr; + ppdt cr3 = nullptr; + get_cr2_and_cr3(&cr2, &cr3); + // printf("[PAGE FAULT HANDLING] CAUSE-ADDRESS %x\n", cr2); + unsigned int idx1 = 0u; + unsigned int idx2 = 0u; + ppt cur_pt = nullptr; + ppte cur_ppte = nullptr; + do + { + // printf("[PAGE FAULT HANDLING] FOUND PDT (PDT IDX : %d)\n", idx1); + pde cur_pde = cr3->pages[idx1]; + // printf("ACTUAL PDT: %x\nIT's PT: %x\nIT's PT << 12u: %x\n", cr3, cur_pde.page_table, (cur_pde.page_table << 12)); + // printf( "uint32_t present : %x\n" + // "uint32_t rw : %x\n" + // "uint32_t us : %x\n" + // // "uint32_t pwt : %x\n" + // // "uint32_t pcd : %x\n" + // // "uint32_t a : %x\n" + // // "uint32_t ignored1 : %x\n" + // // "uint32_t ps : %x\n" + // // "uint32_t ignored2 : %x\n" + // "uint32_t page_table << 12: %x\n", + // cur_pde.present, cur_pde.rw, cur_pde.us, /* cur_pde.pwt, + // cur_pde.pcd, cur_pde.a, cur_pde.ignored1, cur_pde.ps, + // cur_pde.ignored2, */(cur_pde.page_table << 12)); + if (!cur_pde.present) + { + cr3->pages[idx1].present = 1; + // printf( "[UPDATE] uint32_t present : %x\n", cr3->pages[idx1].present); + } + cur_pt = (ppt)(cr3->pages[idx1].page_table << 12); + idx2 = 0u; + while(idx2 < 1023u && !((cur_pt->pages[idx2].page_frame << 12) <= (ptr_t)cr2 && + (cur_pt->pages[idx2 + 1].page_frame << 12) > (ptr_t)cr2)) { ++idx2; } + if (idx2 < 1023u || (idx2 == 1023u && (cur_pt->pages[idx2].page_frame << 12) >= (ptr_t)cr2)) + { + // if ((idx2 == 1023u && (cur_pt->pages[idx2].page_frame << 12) >= (ptr_t)cr2)) printf("--------------------EGDE CASE--------------------\n"); + cur_ppte = &cur_pt->pages[idx2]; + } + else + { + ++idx1; + if (idx1 >= 1024u) + { + printf("[PAGE FAULT HANDLING] PDT NOT FOUND (PDT IDX : %d)\n", idx1); + asm("xchgw %bx, %bx"); + return; + } + } + } while(!cur_ppte); + // printf("PDE IDX: %d\n", idx1); + // printf("PTE IDX: %d\n", idx2); + // printf("FOUND PTE: %x\n", cur_ppte); + // printf( "uint32_t present : %x\n" + // "uint32_t rw : %x\n" + // "uint32_t us : %x\n" + // // "uint32_t pwt : %x\n" + // // "uint32_t pcd : %x\n" + // // "uint32_t a : %x\n" + // // "uint32_t d : %x\n" + // // "uint32_t pat : %x\n" + // // "uint32_t g : %x\n" + // "uint32_t ignored1 : %x\n" + // "uint32_t page_frame << 12: %x\n", + // cur_ppte->present, cur_ppte->rw, cur_ppte->us, /* cur_ppte->pwt, + // cur_ppte->pcd, cur_ppte->a, cur_ppte->d, cur_ppte->pat, + // cur_ppte->g, */cur_ppte->ignored1, (cur_ppte->page_frame << 12)); + if (idx2 < 1023u) + { + pte next_pte = *(cur_ppte + 1); + // printf("NEXT PTE: %x\n", (cur_ppte + 1)); + // printf( "uint32_t present : %x\n" + // "uint32_t rw : %x\n" + // "uint32_t us : %x\n" + // // "uint32_t pwt : %x\n" + // // "uint32_t pcd : %x\n" + // // "uint32_t a : %x\n" + // // "uint32_t d : %x\n" + // // "uint32_t pat : %x\n" + // // "uint32_t g : %x\n" + // "uint32_t ignored1 : %x\n" + // "uint32_t page_frame << 12: %x\n", + // next_pte.present, next_pte.rw, next_pte.us, /* next_pte.pwt, + // next_pte.pcd, next_pte.a, next_pte.d, next_pte.pat, + // next_pte.g, */next_pte.ignored1, (next_pte.page_frame << 12)); + } + switch(cur_ppte->ignored1) + { + case not_stated: + { + printf("[PAGE FAULT HANDLING] PAGE FAULT EXCEPTION CANNOT BE HANDLED:1\n"); + asm("xchgw %bx, %bx"); + default_panic_handler(ctx); + return; + } + case disabled_page_frame: + { + cur_ppte->present = 1u; + cur_ppte->ignored1 = enabled_page_frame; + invalidate_page(cr2); + // load_page_directory(cr3); + // enable_paging(); + // printf("[PAGE FAULT HANDLING] PAGE FAULT EXCEPTION HANDLED:1\n"); + break; + } + case enabled_page_frame: + { + printf("[PAGE FAULT HANDLING] PAGE FAULT EXCEPTION CANNOT BE HANDLED:2\n"); + asm("xchgw %bx, %bx"); + default_panic_handler(ctx); + return; + } + case free_page_frame: + { + cur_ppte->ignored1 = enabled_page_frame; + cur_ppte->present = 1u; + cur_ppte->rw = 1u; + cur_ppte->us = 1u; + invalidate_page(cr2); + // load_page_directory(cr3); + // enable_paging(); + // printf("[PAGE FAULT HANDLING] PAGE FAULT EXCEPTION HANDLED:2\n"); + break; + } + default: + { + printf("[PAGE FAULT HANDLING] SWITCH-CASE TROUBLE IN PAGE FAULT EXCEPTION HANDLING: %d\n", cur_ppte->ignored1); + asm("xchgw %bx, %bx"); + default_panic_handler(ctx); + return; + } + } + } +} + +void page_fault_pse(context* ctx) +{ + // init_printer(); + // printf("[PAGE FAULT HANDLING] START\n"); + unsigned int ec = ctx->error_code; + if (!(ec & 1)) + { + ptr_t* cr2 = nullptr; + ppdtx cr3 = nullptr; + get_cr2_and_cr3(&cr2, &cr3); + printf("[PAGE FAULT HANDLING] CAUSE-ADDRESS %x\n", cr2); + int found = 0; + for(unsigned int i = 0u; i < 1023u; ++i) + { + if ((cr3->pages[i].frame_address << 22) <= (ptr_t)cr2 && (i == 767 || i == 1023 || + (cr3->pages[i + 1].frame_address << 22) > (ptr_t)cr2)) + { + printf("[PAGE FAULT HANDLING] PDE FOUND : %d\n", i); + switch(cr3->pages[i].ignored1) + { + case not_stated: + { + printf("[PAGE FAULT HANDLING] PAGE FAULT EXCEPTION CANNOT BE HANDLED:1\n"); + asm("xchgw %bx, %bx"); + default_panic_handler(ctx); + return; + } + case disabled_page_frame: + { + cr3->pages[i].present = 1u; + cr3->pages[i].ignored1 = enabled_page_frame; + invalidate_page(cr2); + // load_page_directory(cr3); + // enable_paging(); + // printf("[PAGE FAULT HANDLING] PAGE FAULT EXCEPTION HANDLED:1\n"); + found = 1; + break; + } + case enabled_page_frame: + { + printf("[PAGE FAULT HANDLING] PAGE FAULT EXCEPTION CANNOT BE HANDLED:2\n"); + asm("xchgw %bx, %bx"); + default_panic_handler(ctx); + return; + } + case free_page_frame: + { + cr3->pages[i].ignored1 = enabled_page_frame; + cr3->pages[i].present = 1u; + cr3->pages[i].rw = 1u; + cr3->pages[i].us = 1u; + invalidate_page(cr2); + // load_page_directory(cr3); + // enable_paging(); + //printf("[PAGE FAULT HANDLING] PAGE FAULT EXCEPTION HANDLED:2\n"); + found = 1; + break; + } + default: + { + printf("[PAGE FAULT HANDLING] SWITCH-CASE TROUBLE IN PAGE FAULT EXCEPTION HANDLING: PAGE-FLAG = %d\n", cr3->pages[i].ignored1); + asm("xchgw %bx, %bx"); + default_panic_handler(ctx); + return; + } + } + if (found) break; + } + } + if (!found) + { + printf("[PAGE FAULT HANDLING] CAUSE-ADDRESS NOT FOUND IN PDTX"); + asm("xchgw %bx, %bx"); + } + } +} + +void default_panic_handler(context* ctx) { + // init_printer(); + asm("cli"); + + unsigned int current_eflags; + + asm("pushf\n\t" + "pop %0" + : "=g"(current_eflags) + : + : "memory" + ); + + printf("Kernel panic: unhandled interrupt %x, interrupted process context:\n" + " EAX = %x ECX = %x EDX = %x EBX = %x\n" + " ESP = %x EBP = %x ESI = %x EDI = %x\n" + " DS = %x ES = %x FS = %x GS = %x\n" + " CS = %x SS = %x EIP = %x\n" + " EFLAGS (interrupted) = %x " "EFLAGS (current) = %x\n" + " error code = %x\n", + ctx->vector, + ctx->eax, ctx->ecx, ctx->edx, ctx->ebx, + ctx->esp, ctx->ebp, ctx->esi, ctx->edi, + ctx->ds, ctx->es, ctx->fs, ctx->gs, + ctx->cs, ctx->ss, ctx->eip, + ctx->eflags, current_eflags, + ctx->error_code); + + printf("Process #%x", tasks); + + if (ctx->vector >= 0x20) { + asm("sti"); + } + // asm("xchgw %bx, %bx"); +} \ No newline at end of file diff --git a/src/kernel/sys/interruption.h b/src/kernel/sys/interruption.h new file mode 100644 index 0000000..a1e8575 --- /dev/null +++ b/src/kernel/sys/interruption.h @@ -0,0 +1,23 @@ +#pragma once + +#include "./io/io.h" +#include "./tramplins.hpp" +#include "./idt.h" +#include "./pic/pic.h" +#include "./memory/memory.h" +#include "./context/context.h" + +#pragma pack(push, 1) +typedef struct { + uint16_t IDT_size; + uint32_t linear_addr_IDT; +} IDTD; +#pragma pack(pop) + +void kernel_panic(char* str, int type); +void panic_handler(int vector); + +InterruptDescriptor32* init_idt(); +void reg_idtd(InterruptDescriptor32* idt); + +void interrupt_handler(context* ctx); \ No newline at end of file diff --git a/src/kernel/sys/io/io.h b/src/kernel/sys/io/io.h new file mode 100644 index 0000000..e4b2ef1 --- /dev/null +++ b/src/kernel/sys/io/io.h @@ -0,0 +1,3 @@ +#pragma once + +#include "./printf.h" \ No newline at end of file diff --git a/src/kernel/sys/io/printf.c b/src/kernel/sys/io/printf.c new file mode 100644 index 0000000..3f2eea4 --- /dev/null +++ b/src/kernel/sys/io/printf.c @@ -0,0 +1,193 @@ +#include "printf.h" + +static int current_x; +static int current_y; + +int string_compare(const char* first, const char* second, int n) { + int res = 0; + while(*first && *second && n-- && !(res = (*first++ - *second++))); + return !res; +} + +void vga_print_char_raw(unsigned short symbol, int x, int y, unsigned short foreground_color) { + // if (current_x >= 80) end_line(); + // *((short *)(VGA_START + 2 * (y * 80 + x))) = ((short) foreground_color) << 8 | (short) symbol; + *((unsigned short *)(VGA_START + 2 * (y * 80 + x))) = ((short) foreground_color) << 8 | (short) symbol; +} + +void vga_print_char(char symbol, int x, int y, int foreground_color) { + // if (current_x >= 80) end_line(); + short sy = ((short) foreground_color) << 8 | (short) symbol; + + *((short *)(VGA_START + 2 * (current_y * 80 + current_x))) = ((short) foreground_color) << 8 | (short) symbol; +} + +void vga_clear_screen() { + memzero((void*)VGA_START, sizeof(short) * 25 * 80); +} + +void shift_up() { + memcpy((char*) VGA_START, (char*) VGA_START + sizeof(short) * 80, sizeof(short) * 24 * 80); + memzero((char*) VGA_START + sizeof(short) * 80 * 24, sizeof(short) * 80); +} + +void init_printer() { + current_x = 0; + current_y = 0; + vga_clear_screen(); +} + +void end_line() { + // asm("xchgw %bx, %bx"); + if (current_y >= 24) shift_up(); + else ++current_y; + current_x = 0; +} + +void print_char(char s, int color) { + // asm("xchgw %bx, %bx"); + if (current_y > 24) { + shift_up(); + current_y--; + } + vga_print_char(s, current_x, current_y, color); + // current_x++; + if (++current_x >= 80) end_line(); +} + +void print_string(char* str, int color) { + while (*str) { + print_char(*str, color); + ++str; + } +} + +mutex lock_printf = 0; + +void printf(const char* fmt, ...) { + return; + va_list a = va_start(fmt); + // lock_32(&lock_printf); + for (const char* i = fmt; *i; ++i) { + if (*i == '%') { + if (*(i + 1) == '%') { + print_char('%', WHITE); + ++i; + } else { + int color = WHITE; + + // mode select + char mode = *(i++ + 1); + + // color select (iff defined) + if (*(i + 1) == '_') { + i += 2; + const char* start = i; + const char* stop = i; + while (*i != '!') { + if (!*i) return; + stop = i++; + } + + if (start != stop) { + char* color_names = "BLACK\0BLUE\0GREEN\0CYAN\0RED\0PURPLE\0" + "BROWN\0GRAY\0DARK_GRAY\0LIGHT_BLUE\0LIGHT_GREEN\0" + "LIGHT_CYAN\0LIGHT_RED\0LIGHT_PURPLE\0YELLOW\0WHITE"; + char* cur_color = color_names; + for (int i = 0; i < _LAST; ++i) { + if (string_compare(start, cur_color, stop - start)) { + color = i; + break; + } + while (*cur_color++); + } + } + } + + // print + if (mode == 's') { + char* b = &va_arg(a, char); + print_string(b, color); + } else if (mode == 'd') { + unsigned b = (unsigned) va_arg(a, int); +#define _MAX_N_DIGITS_FOR_DEC_CASE (int)(12) + if (b != 0) { + char buffer[_MAX_N_DIGITS_FOR_DEC_CASE] = {0}; + + int counter = _MAX_N_DIGITS_FOR_DEC_CASE - 1; +#undef _MAX_N_DIGITS_FOR_DEC_CASE + int is_neg = 0; + if (b & (1 << sizeof(int) * 8 - 1)) + { + is_neg = 1; + b = ~b + 1; + } + while (b) { + buffer[--counter] = b % 10 + '0'; + b /= 10; + } + if (is_neg) + { + buffer[--counter] = '-'; + } + + print_string(buffer + counter, color); + } else { + print_char('0', color); + } + } else if (mode == 'x' || mode == 'X') { + unsigned int b = (unsigned int) va_arg(a, int); + print_string("0x", color); + if (b != 0) { + char buffer[sizeof(int) + 1] = {0}; + + int counter = 3; + if (b < 0) { + b *= -1; + } + while (b) { + int temp = b % 16; + + char symbol; + if (temp > 9) { + symbol = temp - 10 + (mode == 'X' ? 'A' : 'a'); + } else { + symbol = temp + '0'; + } + buffer[counter--] = symbol; + b >>= 4; + } + + print_string(buffer + counter + 1, color); + } else { + print_char('0', color); + } + } else if (mode == 'b') { + unsigned b = (unsigned) va_arg(a, unsigned); + print_string("0b", color); + char buffer[sizeof(unsigned) * 8 + 1] = {0}; + + int counter = sizeof(unsigned) * 8 - 1; + while (b) { + buffer[counter--] = (char)((b & 1) + '0'); + b >>= 1; + } + + print_string(buffer + counter + 1, color); + } + } + } else if (*i == '\n') { + // end_line(); + current_y++; + current_x = 0; + + } else if (*i == '\t' || *i == " ") { + // end_line(); + while(current_x++ % 4) {} + + } else { + print_char(*i, WHITE); + } + } + // unlock_32(&lock_printf); +} \ No newline at end of file diff --git a/src/kernel/sys/io/printf.h b/src/kernel/sys/io/printf.h new file mode 100644 index 0000000..aa824e7 --- /dev/null +++ b/src/kernel/sys/io/printf.h @@ -0,0 +1,43 @@ +#pragma once + +#include "../memory/memory.h" +#include "../../sync/sync.h" + +#define VGA_START (int)(0xb8000) +#define va_arg(list, type) ( (type*) ( list = (char*) list + sizeof(type) ) )[-1] +#define va_list char* +#define va_start(x) (char*)(&x + 1) + +enum color { + BLACK, + BLUE, + GREEN, + CYAN, + RED, + PURPLE, + BROWN, + GRAY, + DARK_GRAY, + LIGHT_BLUE, + LIGHT_GREEN, + LIGHT_CYAN, + LIGHT_RED, + LIGHT_PURPLE, + YELLOW, + WHITE, + _LAST +}; + +extern mutex lock_printf; + +int string_compare(const char* first, const char* second, int n); +void vga_print_char_raw(unsigned short symbol, int x, int y, unsigned short foreground_color); +void vga_print_char(char symbol, int x, int y, int foreground_color); +void vga_clear_screen(); +void vga_print_string(char* str, int x, int y, int text_color); +void shift_up(); +void init_printer(); +void end_line(); +void print_char(char s, int color); +void print_string(char* str, int color); +void printf(const char* fmt, ...); \ No newline at end of file diff --git a/src/kernel/sys/memory/alloc.c b/src/kernel/sys/memory/alloc.c new file mode 100644 index 0000000..7aa3c36 --- /dev/null +++ b/src/kernel/sys/memory/alloc.c @@ -0,0 +1,247 @@ +#include "./alloc.h" +#include "../paging/paging.h" +#include "../io/io.h" +#include "../../misc/list.h" + +#define MEMORY_MAX ((ptr_t)(0xFF000000)) +// #define MEMORY_MAX ((ptr_t)(0x2001F8)) + +static unsigned char* heap_start = (unsigned char*)(0x100000); +static unsigned char* top = (unsigned char*)(0x100000); + +void fix_heap_to_higher_half() +{ + heap_start = (unsigned char*)((ptr_t)heap_start + 0xC0000000); + top = (unsigned char*)((ptr_t)top + 0xC0000000); +} + +void unfix_heap_to_higher_half() +{ + heap_start = (unsigned char*)((ptr_t)heap_start - 0xC0000000); + top = (unsigned char*)((ptr_t)top - 0xC0000000); +} + +void fix_heap_to_N(unsigned long N) +{ + heap_start = (unsigned char*)(N); + top = (unsigned char*)(N); +} + +ptr_t get_top() +{ + ptr_t ret = (ptr_t)top; + return ret; +} + +void* malloc(ptr_t size) { + if ((ptr_t)top + size > MEMORY_MAX) + return nullptr; + printf("\n-----------------\nAlloc: %x [%x]\n", top, size); + top += size; + return top - size; +} + +// kernel_malloc, but aligned to (1u << align_bit) bytes +void* kernel_kmalloc(ptr_t size, unsigned int align_bit) { + return malloc(kernel_mem_align(size, align_bit)); + // return malloc(size); +} + +void* kernel_malloc(ptr_t size) { + void* allocated_mem = kernel_kmalloc(size, 12u); + /* void* last_pte = markup_mem(allocated_mem, count_aligned_chunks(size, 12u) + 1); */ + return allocated_mem; +} + +static void* calloc(ptr_t size) { + if (size + (ptr_t)top > MEMORY_MAX) + return nullptr; + memzero(top, size); + printf("\n-----------------\nAlloc: %x [%x]\n", top, size); + top += size; + return top - size; +} + +void* kernel_calloc(ptr_t size, ptr_t num) { + void* prepared_mem = kernel_kmalloc(size * num, 12u); + memzero(prepared_mem, size * num); + /* void* last_pte = markup_mem(prepared_mem, count_aligned_chunks( + kernel_mem_align(size * num, 12u), // gag (we need to return pair (void*, size) from malloc()) + 12u) + 1); */ + return prepared_mem; +} + +/* void* kernel_realloc(void* old_addr, ptr_t new_size) { + if (new_size + (ptr_t)top > MEMORY_MAX) + return nullptr; + void* new_addr = kernel_malloc(new_size); + memcpy(new_addr, old_addr, new_size); + return new_addr; +} */ + +void kernel_free(void* addr) { + top = heap_start; // we need to unset relevant present bits in pde's and pte's +} + +// ------------------ + +node* free_list = nullptr; + +void print_free_list() +{ + printf("\n ----------\n free_list:\n "); + node* cur = free_list; + unsigned int i = 0u; + while(cur) + { + printf("[%d] on %x : .data = %x, .data2 = %x, .next = %x\n ", i, cur, cur->data, cur->data2, cur->next); + cur = cur->next; + ++i; + } +} + +void* c_malloc(ptr_t size) +{ + if ((ptr_t)top + size > MEMORY_MAX) + { + if (free_list == nullptr) + { + printf("\n-----------------\nc_alloc(empty)\n"); + return nullptr; + } + node* cur = free_list; + node* found = nullptr; + unsigned int n_cur = 0u; + unsigned int n_found = 0u; + while(cur) + { + if ((ptr_t)cur->data2 >= size && ((found == nullptr) || (cur->data2 < found->data2))) + { + found = cur; + n_found = n_cur; + } + cur = cur->next; + ++n_cur; + } + if (found) + { + void* target = (void*)found->data; + printf("\n-----------------\nc_alloc(use free_list[%d]): %x [%x] [free_list.size = %x]\n", n_found, target, size, found->data2); + if (found->data2 > size) + { + found->data += size; + found->data2 -= size; + } + else + { + free_list = remove_n(free_list, n_found); + } + printf("address of free_list = %x\n", free_list); + return target; + } + return nullptr; + } + top += size; + printf("\n-----------------\nc_alloc: %x [%x]\n", top - size, size); + return top - size; +} + +void* c_calloc(ptr_t size) +{ + void* mem = c_malloc(size); + memzero(mem, size); + return mem; +} + +void c_delete(void* ptr, ptr_t size) +{ + node* found = free_list; + if (found && (ptr_t)found->data >= (ptr_t)ptr) + { + free_list = add_head(free_list, (uint32_t)ptr); + free_list->data2 = size; + // printf("\n-----------------\nc_delete(free_list[:0]): %x [%x]\n", ptr, size); + print_free_list(); + if ((ptr_t)free_list->data + size >= (ptr_t)free_list->next->data) + { + free_list->data2 += free_list->next->data2; + free_list = remove_n(free_list, 1u); + // printf("\n-----------------\nc_delete(free_list[:0]): concat with free_list[1], " + // "free_list[0].ptr = %x, .size = %x\n", free_list->data, free_list->data2); + print_free_list(); + } + return; + } + unsigned int i = 0u; + while(found) + { + node* cur = nullptr; + if ((ptr_t)found->data <= (ptr_t)ptr && ((cur = found->next) == nullptr || (ptr_t)cur->data >= (ptr_t)ptr)) + { + free_list = add_after_n(free_list, (uint32_t)ptr, i); + cur = found->next; + cur->data2 = size; + node* next = cur->next; + // printf("\n-----------------\nc_delete(free_list[%d]): %x [%x]\n", i + 1, ptr, size); + print_free_list(); + if (next && ((ptr_t)cur->data + size >= (ptr_t)next->data)) + { + cur->data2 += next->data2; + free_list = remove_n(free_list, i + 2); + // printf("\n-----------------\nc_delete(free_list[%d]): concat with free_list[%d], " + // "free_list[0].ptr = %x, .size = %x\n", i + 1, i + 2, cur->data, cur->data2); + print_free_list(); + } + if ((ptr_t)found->data + found->data2 >= (ptr_t)cur->data) + { + found->data2 += cur->data2; + free_list = remove_n(free_list, i + 1); + // printf("\n-----------------\nc_delete(free_list[%d]): concat with free_list[%d], " + // "free_list[0].ptr = %x, .size = %x\n", i + 1, i, found->data, found->data2); + print_free_list(); + } + return; + } + found = found->next; + ++i; + } + node* prev = add_tail(free_list, (uint32_t)ptr); + if (free_list == nullptr) + { + free_list = prev; + found = free_list; + found->data2 = size; + // printf("\n-----------------\nc_delete(free_list[::%d]): %x [%x]\n", i, found->data, found->data2); + print_free_list(); + } + else + { + found = prev->next; + found->data2 = size; + // printf("\n-----------------\nc_delete(free_list[::%d]): %x [%x]\n", i, found->data, found->data2); + print_free_list(); + if ((ptr_t)prev->data + prev->data2 >= (ptr_t)found->data) + { + prev->data2 += found->data2; + free_list = remove_tail(free_list); + // printf("\n-----------------\nc_delete(free_list[::%d]): concat with free_list[%d], " + // "free_list[0].ptr = %x, .size = %x\n", i, i - 1, prev->data, prev->data2); + print_free_list(); + } + } +} + +void* os_malloc(ptr_t size) +{ + return (void*)((ptr_t)c_malloc(size) + 0xC0000000); +} + +void* os_calloc(ptr_t size) +{ + return (void*)((ptr_t)c_calloc(size) + 0xC0000000); +} + +void os_delete(void* ptr, ptr_t size) +{ + c_delete((void*)((ptr_t)ptr + 0xC0000000), size); +} \ No newline at end of file diff --git a/src/kernel/sys/memory/alloc.h b/src/kernel/sys/memory/alloc.h new file mode 100644 index 0000000..a1e7483 --- /dev/null +++ b/src/kernel/sys/memory/alloc.h @@ -0,0 +1,43 @@ +#pragma once + +#ifndef nullptr +#define nullptr ((void*)(0)) +#endif + +#ifndef __ptr_base_def +#define __ptr_base_def +typedef unsigned int ptr_t; +#endif + +#define SZ_IN_BYTES_OF_ALIGN_CHUNK(align_bit) ((1u) << (ptr_t)(align_bit)) +#define count_aligned_chunks(mem, align_bit) ((ptr_t)(mem) / SZ_IN_BYTES_OF_ALIGN_CHUNK(align_bit)) +#define kernel_mem_is_aligned(mem, align_bit) (!((ptr_t)(mem) % SZ_IN_BYTES_OF_ALIGN_CHUNK(align_bit))) +#define kernel_mem_align_pad(mem, align_bit) (SZ_IN_BYTES_OF_ALIGN_CHUNK(align_bit) * ((1u) + count_aligned_chunks(mem, align_bit)) - (ptr_t)(mem)) +// #define kernel_mem_align_pad(mem, align_bit) ((ptr_t)(mem) + (SZ_IN_BYTES_OF_ALIGN_CHUNK(align_bit) - ((ptr_t)(mem) % SZ_IN_BYTES_OF_ALIGN_CHUNK(align_bit)))) +#define kernel_mem_align(mem, align_bit) ((ptr_t)(mem) + (kernel_mem_is_aligned(mem, align_bit) ? (0u) : kernel_mem_align_pad(mem, align_bit))) + +#include "mem_utils.h" + +void fix_heap_to_higher_half(); +void unfix_heap_to_higher_half(); +void fix_heap_to_N(unsigned long N); +ptr_t get_top(); + +void* malloc(ptr_t size); + +// kernel_malloc, but aligned to (1u << align_bit) bytes +void* kernel_kmalloc(ptr_t size, ptr_t align_bit); + +void* kernel_malloc(ptr_t size); +void* kernel_calloc(ptr_t size, ptr_t num); +/* void* kernel_realloc(void* old_addr, ptr_t new_size); */ +void kernel_free(void* addr); + +void init_alloc(); +void* c_malloc(ptr_t size); +void* c_calloc(ptr_t size); +void c_delete(void* ptr, ptr_t size); + +void* os_malloc(ptr_t size); +void* os_calloc(ptr_t size); +void os_delete(void* ptr, ptr_t size); \ No newline at end of file diff --git a/src/kernel/sys/memory/mem_utils.c b/src/kernel/sys/memory/mem_utils.c new file mode 100644 index 0000000..f64a1df --- /dev/null +++ b/src/kernel/sys/memory/mem_utils.c @@ -0,0 +1,40 @@ +#include "mem_utils.h" + +// Why are the comments Russian? + +const void* memcpy(const void* dst, const void* src, int n) { + unsigned long* wdst = (unsigned long*) dst; // текущая позиция в буфере назначения + unsigned long* wsrc = (unsigned long*) src; // текущая позиция в источнике + unsigned char* cdst; + unsigned char* csrc; + + for(int i = 0, m = n / sizeof(long); i < m; ++i) { // копируем основную часть блоками по 4 или 8 байт + *(wdst++) = *(wsrc++); // (в зависимости от платформы) + } + + cdst = (unsigned char*)wdst; + csrc = (unsigned char*)wsrc; + + for(int i = 0, m = n % sizeof(long); i < m; ++i) { // остаток копируем побайтно + *(cdst++) = *(csrc++); + } + + return dst; +} + +void* memzero(void* dst, int n) { + unsigned long* wdst = (unsigned long*) dst; // текущая позиция в буфере назначения + unsigned char* cdst; + + for(int i = 0, m = n / sizeof(long); i < m; ++i) { // копируем основную часть блоками по 4 или 8 байт + *(wdst++) = 0; // (в зависимости от платформы) + } + + cdst = (unsigned char*)wdst; + + for(int i = 0, m = n % sizeof(long); i < m; ++i) { // остаток копируем побайтно + *(cdst++) = 0; + } + + return dst; +} \ No newline at end of file diff --git a/src/kernel/sys/memory/mem_utils.h b/src/kernel/sys/memory/mem_utils.h new file mode 100644 index 0000000..7f41c71 --- /dev/null +++ b/src/kernel/sys/memory/mem_utils.h @@ -0,0 +1,8 @@ +#pragma once + +#ifndef nullptr +#define nullptr ((void*)(0)) +#endif + +const void* memcpy(const void* dst, const void* src, int n); +void* memzero(void* dst, int n); \ No newline at end of file diff --git a/src/kernel/sys/memory/memory.h b/src/kernel/sys/memory/memory.h new file mode 100644 index 0000000..adcb969 --- /dev/null +++ b/src/kernel/sys/memory/memory.h @@ -0,0 +1,7 @@ +#pragma once + +#ifndef nullptr +#define nullptr ((void*)(0)) +#endif + +#include "./alloc.h" \ No newline at end of file diff --git a/src/kernel/sys/paging/paging.asm b/src/kernel/sys/paging/paging.asm new file mode 100644 index 0000000..839a6cc --- /dev/null +++ b/src/kernel/sys/paging/paging.asm @@ -0,0 +1,150 @@ +[BITS 32] + +[GLOBAL load_page_directory] +[GLOBAL enable_paging] +[GLOBAL enable_paging_pse] +[GLOBAL get_cr2_and_cr3] +[GLOBAL invalidate_page] +[GLOBAL jmp_to_higher_half] +; [GLOBAL all_init_pdt] + +; all_init_pdt: +; push ebp +; mov ebp, esp +; pusha +; mov eax, [ebp + 36] + +; mov ebx, 0x0 +; mov edx, eax +; add edx, 4096 + +; .fill_pdt: +; ; pop +; push eax +; mov eax, [ebp + 4] +; add eax, 4096 +; mov [ebp + 4], eax +; pop +; mov ecx, 0x0 +; or ecx, [ebp + 40] +; mov [eax + ebx * 4], ecx +; cmp ebx, 0 +; jne .skip +; push 0x1 +; push 0x0 + +; .skip: +; push 0x0 +; push 0x0 +; ; push edx +; call all_init_pt + +; inc ebx, 1 +; cmp ebx, 1024 +; jne .fill_pdt + +; pop +; pop + +; popa +; mov esp, ebp +; pop ebp +; ret + +; all_init_pt: +; push ebp +; mov ebp, esp +; pusha +; ; mov edx, [ebp + 36] + +; mov eax, 0x0 +; mov ebx, [ebp + 40] + +; .fill_table: +; mov ecx, ebx +; or ecx, [ebp + 44] +; mov [edx + eax * 4], ecx +; add ebx, 4096 +; inc eax +; cmp eax, 1024 +; jne .fill_table + +; popa +; mov esp, ebp +; pop ebp +; ret + +load_page_directory: ; put &boot_page_directory in high 20 bits of cr3 register + push ebp + mov ebp, esp + push eax + push ebx + + mov eax, [ebp + 8] + mov ebx, cr3 + and ebx, 0xfff ; zero out existing 20 high bits + and eax, 0xfffff000 + or ebx, eax + mov cr3, ebx + + pop ebx + pop eax + mov esp, ebp + pop ebp + ret + +enable_paging: + ; enable 4MB paging + mov eax, cr4 ; read current cr4 + or eax, 0x00 ; set PSE + mov cr4, eax ; update cr4 + + ; enable paging (PG bit) + mov eax, cr0 ; read current cr0 + or eax, 0x80000001 ; set PE (bit 0) and PG (bit 31) + mov cr0, eax ; update cr0 + ; now paging is enabled + ret + +enable_paging_pse: + ; enable 4MB paging + mov eax, cr4 ; read current cr4 + or eax, 0x10 ; set PSE + mov cr4, eax ; update cr4 + + ; enable paging (PG bit) + mov eax, cr0 ; read current cr0 + or eax, 0x80000001 ; set PE (bit 0) and PG (bit 31) + mov cr0, eax ; update cr0 + ; now paging is enabled + ; xchg bx, bx + ; ret + pop eax + jmp eax + +get_cr2_and_cr3: + push ebp + mov ebp, esp + + mov eax, [ebp + 8] + mov ebx, cr2 + mov [eax], ebx + mov eax, [ebp + 12] + mov ebx, cr3 + mov [eax], ebx + + mov esp, ebp + pop ebp + ret + +invalidate_page: + INVLPG [esp + 4] + ret + +jmp_to_higher_half: + pop ebx + add ebx, 0xC0000000 + add ebp, 0xC0000000 + add esp, 0xC0000000 + push ebx + ret \ No newline at end of file diff --git a/src/kernel/sys/paging/paging.c b/src/kernel/sys/paging/paging.c new file mode 100644 index 0000000..24dd310 --- /dev/null +++ b/src/kernel/sys/paging/paging.c @@ -0,0 +1,240 @@ +#include "./paging.h" +#include "../io/io.h" + +static unsigned int sz_cur_dir = 0u; +static unsigned int sz_cur_page = 0u; +static ppde cur_dir = nullptr; +static ppte cur_page = nullptr; + +ppdt markup_pdt() +{ + ppdt pdt_mem = kernel_kmalloc(1024u * sizeof(pde), 12u); + if (!pdt_mem) + { + printf("[EXC] alloc_pdt():1: not enough memory!\n"); + return nullptr; + } + // count each 4 MB page (since 0x0) + // + 1u for mark up pdt itself (and each pt after it) + unsigned int total_amount_of_mem_to_mark = (unsigned)pdt_mem + (1u << 12); + unsigned int count_dir_pages_to_mark = count_aligned_chunks(total_amount_of_mem_to_mark, 22u); + total_amount_of_mem_to_mark += count_dir_pages_to_mark * (1u << 12); + //count_dir_pages_to_mark = count_aligned_chunks(total_amount_of_mem_to_mark, 22u) + 1; // adaptive mode + count_dir_pages_to_mark = 1024u; // all mode + ptr_t cur_phys_address = 0u; + for(unsigned int i = 0u; i < count_dir_pages_to_mark; ++i) + { + unsigned int count_pages_to_mark = 1024u; // adaptive/all mode + /* if (i == count_dir_pages_to_mark - 1 && + !kernel_mem_is_aligned(total_amount_of_mem_to_mark, 22u)) + { + // count each 4 KB page (since cur_phys_address) + unsigned int cur_mem_diff = total_amount_of_mem_to_mark - cur_phys_address; + count_pages_to_mark = count_aligned_chunks(cur_mem_diff, 12u); + } */ // adaptiva mode + // ppte pt_mem = kernel_kmalloc(1024u * sizeof(pte), 12u); // adaptiva mode + ppt pt_mem = kernel_kmalloc(1024u * sizeof(pte), 12u); // all mode + if (!pt_mem) + { + printf("[EXC] alloc_pdt():2: not enough memory!\n"); + return nullptr; + } + + ppde cur_pde = &pdt_mem->pages[i]; + // *cur_pde = *(ppde)(pt_mem); // maybe one day it will work + if (// cur_phys_address < (ptr_t)(pt_mem + 1024)) // adaptiva mode + cur_phys_address <= (ptr_t)(pt_mem + 1)) // all mode + { + cur_pde->present = 1u; + cur_pde->rw = 0u; + cur_pde->us = 0u; + } + else + { + cur_pde->present = 0u; + cur_pde->rw = 1u; + cur_pde->us = 1u; + } + cur_pde->pwt = 0u; + cur_pde->pcd = 0u; + cur_pde->a = 0u; + cur_pde->ignored1 = 0u; + cur_pde->ps = 0u; + cur_pde->ignored2 = 0u; + cur_pde->page_table = ((ptr_t)pt_mem >> 12); + + for(unsigned int j = 0u; j < count_pages_to_mark; ++j) + { + // ppte cur_pte = &pt_mem[j]; // adaptiva mode + ppte cur_pte = &pt_mem->pages[j]; // all mode + // *cur_pte = *(ppte)(cur_phys_address); // maybe one day it will work + if (// cur_phys_address < (ptr_t)(pt_mem + 1024)) // adaptiva mode + cur_phys_address <= (ptr_t)(pt_mem + 1)) // all mode + { + cur_pte-> present = 1u; + cur_pte-> rw = 0u; + cur_pte-> us = 0u; + cur_pte-> ignored1 = enabled_page_frame; + } + else + { + cur_pte-> present = 0u; + cur_pte-> rw = 1u; + cur_pte-> us = 1u; + cur_pte-> ignored1 = disabled_page_frame; + } + cur_pte-> pwt = 0u; + cur_pte-> pcd = 0u; + cur_pte-> a = 0u; + cur_pte-> d = 0u; + cur_pte-> pat = 0u; + cur_pte-> g = 0u; + cur_pte-> page_frame = (cur_phys_address >> 12); + cur_phys_address += (1u << 12); + + // cur_page = (j < 1023u) ? (cur_pte + 1) : nullptr; // adaptiva mode + // sz_cur_page = j; // adaptiva mode + } + + // cur_dir = (i < 1023u) ? (cur_pde + 1) : nullptr; // adaptiva mode + // sz_cur_dir = i; // adaptiva mode + } + return pdt_mem; +} + +ppdtx create_pdt_pse() +{ + return markup_pdt_pse(kernel_kmalloc(1024u * sizeof(pde), 12u)); +} + +// demand 1024u * sizeof(pde) of memory +ppdtx markup_pdt_pse(void* mem_place) +{ + ppdtx pdtx_mem = mem_place; + if (!pdtx_mem) + { + printf("[EXC] alloc_pdt():1: not enough memory!\n"); + return nullptr; + } + + ptr_t cur_virt_address = 0u; + for(unsigned int i = 0u; i < 1024u; ++i) + { + ppdex cur_pdex = &pdtx_mem->pages[i]; + if (0xC0000000u <= cur_virt_address) + { + cur_pdex->present = 1u; + cur_pdex->rw = 0u; + cur_pdex->us = 0u; + cur_pdex->ignored1 = enabled_page_frame; + cur_pdex->frame_address = ((cur_virt_address - 0xC0000000u) >> 22); + } + else if (cur_virt_address < 0x40000000u) + { + cur_pdex->present = 1u; + cur_pdex->rw = 0u; + cur_pdex->us = 0u; + cur_pdex->ignored1 = disabled_page_frame; + cur_pdex->frame_address = (cur_virt_address >> 22); + } + else + { + cur_pdex->present = 0u; + cur_pdex->rw = 1u; + cur_pdex->us = 1u; + cur_pdex->ignored1 = disabled_page_frame; + cur_pdex->frame_address = (cur_virt_address >> 22); + } + cur_pdex->cache_ctrl1 = 0u; + cur_pdex->ps = 1u; + cur_pdex->cache_ctrl2 = 0u; + cur_pdex->cache_ctrl3 = 0u; + cur_pdex->phys_address = 0u; + cur_pdex->reserved = 0u; + + cur_virt_address += (1u << 22); + } + + return pdtx_mem; +} + +// marks memory with each page of 4 KB to PDT +// [[deprecated]] +void* adaptive_markup_mem(void* mem, unsigned int count_pages) +{ + // if (count_pages > 1023u) + // { + // printf("[EXC] markup_mem():1: identity paging does not support allocating more than (4MB - 4 KB) data!"); + // return; + // } // invalid + void* result = nullptr; + for(unsigned int i = 0u; i < count_pages; ++i) + { + if (!cur_page || !cur_dir) + { + if (sz_cur_page != 1023) + { + if (sz_cur_page > 1023u) printf("[EXC] markup_mem():2: wrong sz_cur_page\n"); + else printf("[EXC] markup_mem():3: current PTE is nullptr\n"); + return nullptr; + } + if (sz_cur_dir >= 1023) + { + if (sz_cur_dir > 1023u) printf("[EXC] markup_mem():4: wrong sz_cur_dir\n"); + else printf("[EXC] markup_mem():5: not enough memory!\n"); + return nullptr; + } + cur_page = kernel_kmalloc(1024u * sizeof(pte), 12u); + if (!cur_page) + { + printf("[EXC] markup_mem():6: not enough memory!\n"); + return nullptr; + } + // *cur_pte = *(ppte)(cur_phys_address); // maybe one day it will work + cur_page-> present = 1u; + cur_page-> rw = 0u; + cur_page-> us = 0u; + cur_page-> pwt = 0u; + cur_page-> pcd = 0u; + cur_page-> a = 0u; + cur_page-> d = 0u; + cur_page-> pat = 0u; + cur_page-> g = 0u; + cur_page-> ignored1 = enabled_page_frame; + cur_page-> page_frame = ((ptr_t)cur_page >> 12); + + // *cur_pde = *(ppde)(pt_mem); // maybe one day it will work + cur_dir-> present = 1u; + cur_dir-> rw = 0u; + cur_dir-> us = 0u; + cur_dir-> pwt = 0u; + cur_dir-> pcd = 0u; + cur_dir-> a = 0u; + cur_dir-> ignored1 = 0u; + cur_dir-> ps = 0u; + cur_dir-> ignored2 = 0u; + cur_dir-> page_table = ((ptr_t)cur_page >> 12); + + result = (void*)(cur_page + 1024); + + cur_page = (++sz_cur_page < 1023u) ? (cur_page + 1) : nullptr; + cur_dir = (++sz_cur_dir < 1023u) ? (cur_dir + 1) : nullptr; + } + ppte cur_pte = cur_page; + // *cur_pte = *(ppte)(cur_phys_address); // maybe one day it will work + cur_pte-> present = 1u; + cur_pte-> rw = 1u; + cur_pte-> us = 1u; + cur_pte-> pwt = 0u; + cur_pte-> pcd = 0u; + cur_pte-> a = 0u; + cur_pte-> d = 0u; + cur_pte-> pat = 0u; + cur_pte-> g = 0u; + cur_pte-> ignored1 = enabled_page_frame; + cur_pte-> page_frame = ((ptr_t)mem >> 12); + cur_page = (++sz_cur_page < 1023u) ? (cur_page + 1) : nullptr; + mem = (void*)((ptr_t)mem + (1u << 12)); + } + return result; +} \ No newline at end of file diff --git a/src/kernel/sys/paging/paging.h b/src/kernel/sys/paging/paging.h new file mode 100644 index 0000000..70b826f --- /dev/null +++ b/src/kernel/sys/paging/paging.h @@ -0,0 +1,31 @@ +#pragma once + +#include "./pdt.h" +#include "./pt.h" +#include "../memory/alloc.h" + +#define not_stated 0 +#define disabled_page_frame 0b01 +#define enabled_page_frame 0b10 +#define free_page_frame 0b11 + +extern void load_page_directory(void* pdt); +// extern void enable_paging(); // non-PSE +extern void enable_paging_pse(); // PSE +extern void get_cr2_and_cr3(void* dest_cr2, void* dest_cr3); +extern void invalidate_page(void* virt_address); + +extern void jmp_to_higher_half(); + +//----------------------------------------------------------------- non-PSE +// marks memory with each page of 4 KB to PDT, non-PSE +ppdt markup_pdt(); +//----------------------------------------------------------------- PSE +ppdtx create_pdt_pse(); +// demand 1024u * sizeof(pde) of memory +ppdtx markup_pdt_pse(void* mem_place); +//----------------------------------------------------------------- + +// marks memory with each page of 4 KB to PDT +// [[deprecated]] +void* adaptive_markup_mem(void* mem, unsigned int count_pages); \ No newline at end of file diff --git a/src/kernel/sys/paging/pdt.h b/src/kernel/sys/paging/pdt.h new file mode 100644 index 0000000..a6105ec --- /dev/null +++ b/src/kernel/sys/paging/pdt.h @@ -0,0 +1,58 @@ +#pragma once + +#include + +#ifndef MAX_PDE_PER_PDT +#define MAX_PDE_PER_PDT (int)(1024) +#else +#error [DEF_ERROR] MAX_PDE_PER_PDT was defined earlier +#endif + +#pragma pack(push, 1) +struct page_directory_entry +{ + uint32_t present : 1; // bit 0: always 1 + uint32_t rw : 1; // bit 1: read/write + uint32_t us : 1; // bit 2: user or supervisor + uint32_t pwt : 1; // bit 3: page-level write-through + uint32_t pcd : 1; // bit 4: page-level cache disable + uint32_t a : 1; // bit 5: accessed + uint32_t ignored1 : 1; // bit 6: available + uint32_t ps : 1; // bit 7: page size, 0=4KB 1=4MB, must be 0 for this struct + uint32_t ignored2 : 4; // bit 8 - 11: available + uint32_t page_table : 20; // bit 12 - 31: physical address of 4KB aligned page table referenced by this entry + +} __attribute__((packed)); +#pragma pack(pop) +typedef struct page_directory_entry page_directory_entry_t, pde, *ppde; + +#pragma pack(push, 1) +struct page_directory_entry_pse +{ + uint32_t present : 1; // bit 0: always 1 + uint32_t rw : 1; // bit 1: read/write + uint32_t us : 1; // bit 2: user or supervisor + uint32_t cache_ctrl1 : 4; // bit 3 - 6: cache control + uint32_t ps : 1; // bit 7: page size, 0=4KB 1=4MB, must be 1 for this struct + uint32_t cache_ctrl2 : 1; // bit 8: cache control + uint32_t ignored1 : 3; // bit 9 - 11: available + uint32_t cache_ctrl3 : 1; // bit 12: cache control + uint32_t phys_address : 8; // bit 13 - 20: bits of physical address of page frame + uint32_t reserved : 1; // bit 21: reserved bit + uint32_t frame_address : 10; // bit 12 - 31: frame address + +} __attribute__((packed)); +#pragma pack(pop) +typedef struct page_directory_entry_pse page_directory_entry_x_t, pdex, *ppdex; + +typedef struct page_directory_table +{ + pde pages[MAX_PDE_PER_PDT]; + +} page_directory_table_t, pdt, *ppdt; + +typedef struct page_directory_table_pse +{ + pdex pages[MAX_PDE_PER_PDT]; + +} page_directory_table_x_t, pdtx, *ppdtx; \ No newline at end of file diff --git a/src/kernel/sys/paging/pt.h b/src/kernel/sys/paging/pt.h new file mode 100644 index 0000000..7f84b34 --- /dev/null +++ b/src/kernel/sys/paging/pt.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +#ifndef MAX_PTE_PER_PT +#define MAX_PTE_PER_PT (int)(1024) +#else +#error [DEF_ERROR] MAX_PTE_PER_PT was defined earlier +#endif + +#pragma pack(push, 1) +struct page_table_entry +{ + uint32_t present : 1; // bit 0: always 1 + uint32_t rw : 1; // bit 1: read/write + uint32_t us : 1; // bit 2: user or supervisor + uint32_t pwt : 1; // bit 3: page-level write-through + uint32_t pcd : 1; // bit 4: page-level cache disable + uint32_t a : 1; // bit 5: accessed + uint32_t d : 1; // bit 6: dirty + uint32_t pat : 1; // bit 7: must be 0 unless PAT supported + uint32_t g : 1; // bit 8: global translation + uint32_t ignored1 : 3; // bit 9 - 11: available + uint32_t page_frame : 20; // bit 12 - 31: physical address of 4KB page frame + +} __attribute__((packed)); +#pragma pack(pop) +typedef struct page_table_entry page_table_entry_t, pte, *ppte; + +// full capacity page table +typedef struct page_table +{ + pte pages[MAX_PTE_PER_PT]; + +} page_table_t, pt, *ppt; \ No newline at end of file diff --git a/src/kernel/sys/pic/pic.c b/src/kernel/sys/pic/pic.c new file mode 100644 index 0000000..79e50ad --- /dev/null +++ b/src/kernel/sys/pic/pic.c @@ -0,0 +1,78 @@ +#include "pic.h" + +#define MASTER_COMMAND 0x20 +#define MASTER_DATA 0x21 + +#define SLAVE_COMMAND 0xA0 +#define SLAVE_DATA 0xA1 + + +uint8_t inb(uint16_t port) { + uint8_t data; + // asm("xchgw %bx, %bx"); + asm("inb %1, %0" : "=a"(data) : "d"(port)); + return data; +} + +void outb(uint16_t port, uint8_t) { + asm("outb %al, %dx"); +} + +void delay() { + outb(0x80, 0); +} + +void setup_pic() { + uint16_t icw1 = 0b10001; + outb(MASTER_COMMAND, icw1); + delay(); + outb(SLAVE_COMMAND, icw1); + delay(); + + uint16_t icw2m = 0x20; + outb(MASTER_DATA, icw2m); + delay(); + uint16_t icw2s = 0x28; + outb(SLAVE_DATA, icw2s); + delay(); + + uint16_t icw3m = 0b100; + outb(MASTER_DATA, icw3m); + delay(); + uint16_t icw3s = 0b10; + outb(SLAVE_DATA, icw3s); + delay(); + + uint16_t icw4 = 0b1; + outb(MASTER_DATA, icw4); + delay(); + outb(SLAVE_DATA, icw4); + delay(); + + // 0 -- Programmable Interval Timer + // 1 -- Keyboard + // 2 -- Slave PIC + // 3 -- COM2 + // 4 -- COM1 + // 5 -- LPT2 + // 6 -- Floppy Disk + // 7 -- LPT / Spurious + // 8 -- CMOS Real-Time Clock + // 9-11 -- Free + // 12 -- PS/2 Mouse + // 13 -- Coprocessor + // 14 -- Primary ATA Hard Disk + // 15 -- Secondary ATA Hard Disk + + // 1. Упасть с вектором 0x20 + // outb(MASTER_DATA, 0b11111110); + // outb(SLAVE_DATA, 0b11111110); + + // 2. При нажатии на любую клавишу + outb(MASTER_DATA, 0b11111100); + outb(SLAVE_DATA, 0b11111111); + + // 3. Ничего не происходит при замаскированных битах + // outb(MASTER_DATA, 0b11111111); + // outb(SLAVE_DATA, 0b11111111); +} \ No newline at end of file diff --git a/src/kernel/sys/pic/pic.h b/src/kernel/sys/pic/pic.h new file mode 100644 index 0000000..4eb9c3d --- /dev/null +++ b/src/kernel/sys/pic/pic.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +// byte -> uint8_t + +uint8_t inb(uint16_t port); + +void outb(uint16_t port, uint8_t); + +void setup_pic(); \ No newline at end of file diff --git a/src/kernel/sys/process/exec.asm b/src/kernel/sys/process/exec.asm new file mode 100644 index 0000000..45f6cf7 --- /dev/null +++ b/src/kernel/sys/process/exec.asm @@ -0,0 +1,116 @@ +[BITS 32] + +[GLOBAL exec] +[GLOBAL continue_exec] +[GLOBAL purgatory] +[GLOBAL get_ebp] +[GLOBAL get_esp] +[GLOBAL set_ebp_esp] + +[EXTERN load_proc_ebp_pdt_entry_esp] +[EXTERN load_proc_esp_pdt_eip_ebp_esp] +[EXTERN unlock_32_irq] +[EXTERN lock_scheduler] + +exec: + ; xchg bx, bx + add esp, 4 + mov esp, ebp + push eax + push ebx + push eax + mov eax, 0x100000 + mov cr3, eax + push eax + push eax + push eax + call load_proc_ebp_pdt_entry_esp + pop eax + mov ebp, eax + pop eax + mov cr3, eax + pop eax + mov ebx, esp + mov esp, ebp + push eax + cmp eax, 0xC0000000 + jge .lol + xchg bx, bx +.lol: + mov esp, ebx + pop ebx + pop eax + pop esp + push eax + mov eax, lock_scheduler + push eax + call unlock_32_irq + pop eax + pop eax + ; xchg bx, bx + ret + +continue_exec: + ; xchg bx, bx + add esp, 4 + mov esp, ebp + push eax + push eax + push ebx + push eax + mov eax, 0x100000 + mov cr3, eax + push eax + push eax + push eax + call load_proc_esp_pdt_eip_ebp_esp + pop eax + mov ebp, eax + pop eax + mov cr3, eax + pop eax + mov ebx, esp + mov esp, ebp + push eax + cmp eax, 0xC0000000 + jge .lol + xchg bx, bx +.lol: + mov esp, ebx + pop ebx + pop eax + pop ebp + pop esp + sub esp, 4 + push eax + mov eax, lock_scheduler + push eax + call unlock_32_irq + pop eax + pop eax + ; xchg bx, bx + ret + +purgatory: + mov esp, ebp + mov eax, 0x100000 + mov cr3, eax +AGAIN: + hlt +before_we_gone: + jmp AGAIN + +get_ebp: + mov eax, ebp + ret + +get_esp: + mov eax, esp + ret + +set_ebp_esp: + pop eax + mov ebp, [esp] + mov esp, [esp + 4] + push eax + ret \ No newline at end of file diff --git a/src/kernel/sys/process/process.c b/src/kernel/sys/process/process.c new file mode 100644 index 0000000..5f4b123 --- /dev/null +++ b/src/kernel/sys/process/process.c @@ -0,0 +1,92 @@ +#include "process.h" +#include "../io/io.h" + +// creates new space (virtual memory pages) for new processes +// big bang +ppdtx bb() +{ + // creates memory for new process PDT on OS heap + ptr_t cur_top = get_top(0); + ptr_t pad_size = (((cur_top >> 12) + 1) << 12) - cur_top; + void* padding = c_malloc(pad_size); + ppdtx proc_pdt_mem = c_malloc(sizeof(pde) * 1024); + printf("[INFO] New process PDT: %x\n", proc_pdt_mem); + c_delete(padding, pad_size); + if (!proc_pdt_mem) + { + printf("[EXC] alloc_pdt():1: not enough memory!\n"); + return nullptr; + } + // proc_pdt_mem = markup_pdt_pse(proc_pdt_mem); + + // for first page (legacy reason for now, since GDT was set up in ASM in early period) + { + ppdex cur_pdex = &proc_pdt_mem->pages[0u]; + cur_pdex->present = 1u; + cur_pdex->ignored1 = enabled_page_frame; + cur_pdex->frame_address = 0u; + cur_pdex->rw = 0u; + cur_pdex->us = 0u; + cur_pdex->cache_ctrl1 = 0u; + cur_pdex->ps = 1u; + cur_pdex->cache_ctrl2 = 0u; + cur_pdex->cache_ctrl3 = 0u; + cur_pdex->phys_address = 0u; + cur_pdex->reserved = 0u; + } + for(unsigned int i = 1u; i < 1024u; ++i) + { + ppdex cur_pdex = &proc_pdt_mem->pages[i]; + // 1024 - 256 == 768 + // 0xC0 * 4 == 768 + // 0xC00 / 4 == 768 + if (i < 768) + { + cur_pdex->present = 0u; + cur_pdex->ignored1 = disabled_page_frame; + cur_pdex->frame_address = 0u; + cur_pdex->rw = 1u; + cur_pdex->us = 1u; + cur_pdex->cache_ctrl1 = 0u; + cur_pdex->ps = 1u; + cur_pdex->cache_ctrl2 = 0u; + cur_pdex->cache_ctrl3 = 0u; + cur_pdex->phys_address = 0u; + cur_pdex->reserved = 0u; + } + else + { + cur_pdex->present = 1u; + cur_pdex->ignored1 = enabled_page_frame; + cur_pdex->frame_address = i - 768; + cur_pdex->rw = 0u; + cur_pdex->us = 0u; + cur_pdex->cache_ctrl1 = 0u; + cur_pdex->ps = 1u; + cur_pdex->cache_ctrl2 = 0u; + cur_pdex->cache_ctrl3 = 0u; + cur_pdex->phys_address = 0u; + cur_pdex->reserved = 0u; + } + } + + // enable stack + { + ptr_t cur_top = get_top(0); + ptr_t pad_size = (((cur_top >> 22) + 1) << 22) - cur_top; + void* padding = c_malloc(pad_size); + void* stack_mem = c_malloc(1u << 22); + c_delete(padding, pad_size); + if (!stack_mem) + { + printf("[EXC] create stack: not enough memory!\n"); + return nullptr; + } + ppdex cur_pdex = &proc_pdt_mem->pages[768 - 1]; // 0xC0000000 - 4MB (ebp will be on 0xC0000000 - 1MB, so stack size = 3MB) + cur_pdex->present = 1u; + cur_pdex->ignored1 = enabled_page_frame; + cur_pdex->frame_address = ((ptr_t)stack_mem >> 22); + } + + return proc_pdt_mem; +} \ No newline at end of file diff --git a/src/kernel/sys/process/process.h b/src/kernel/sys/process/process.h new file mode 100644 index 0000000..c66a6db --- /dev/null +++ b/src/kernel/sys/process/process.h @@ -0,0 +1,11 @@ +#pragma once + +#include "../paging/paging.h" + +static unsigned char* process_stack_start = ((unsigned char*)(0xC0000000 - 0x100000 - 1)); // - 1MB +static unsigned char* process_heap_start = ((unsigned char*)(0x40000000)); // 1GB +static unsigned int MAX_ARGS = ((unsigned int)(10)); // max args to pass to process's entry function + +// creates new space (virtual memory pages) for new processes +// big bang +ppdtx bb(); \ No newline at end of file diff --git a/src/kernel/sys/process/scheduler.c b/src/kernel/sys/process/scheduler.c new file mode 100644 index 0000000..5ec239f --- /dev/null +++ b/src/kernel/sys/process/scheduler.c @@ -0,0 +1,299 @@ +#include "scheduler.h" +#include "process.h" +#include "../paging/paging.h" +#include "../../../libc/io/console.h" +#include "../../../libc/io/printer.h" + +#define va_arg(list, type) ( (type*) ( list = (char*) list + sizeof(type) ) )[-1] +#define va_list char* +#define va_start(x) (char*)(&x + 1) + +unsigned int ntasks = 0u; +node* tasks = nullptr; +node* os_task = nullptr; +mutex lock_scheduler = 0; + +extern void exec(); +extern void continue_exec(); +extern void purgatory(); +extern void mov_esp_ebp(void); +extern void set_ebp_esp(ptr_t ebp); + +void reg_os() +{ + node** os_task_hh = (node**)((ptr_t)&os_task + 0xC0000000); + *os_task_hh = os_malloc(sizeof(node)); + (*os_task_hh)->data = get_ebp(); + (*os_task_hh)->data2 = get_esp(); + (*os_task_hh)->data3 = 0x100000; +} + +void copy_rev(unsigned int *restrict dest, + unsigned int const *restrict src, + unsigned int n) +{ + unsigned int i, x; + for (i = 0; i < n; ++i) { + x = src[i]; + x = (x >> 16) | (x << 16); + x = ((x >> 8) & 0x00ff00ffU) | ((x & 0x00ff00ffU) << 8); + x = ((x >> 4) & 0x0f0f0f0fU) | ((x & 0x0f0f0f0fU) << 4); + x = ((x >> 2) & 0x33333333U) | ((x & 0x33333333U) << 2); + x = ((x >> 1) & 0x55555555U) | ((x & 0x555555555) << 1); + dest[n-1-i] = x; + } +} + +void self_destruct() +{ + asm("xchgw %bx, %bx"); + node* tasks_hh = (node*)*(node**)((ptr_t)&tasks + 0xC0000000); + node* os_task_hh = (node*)*(node**)((ptr_t)&os_task + 0xC0000000); + print("SELF-DESTRUCTION HAS BEEN ENGAGED FOR PROCESS #%x\n", *tasks_hh); + ((ptask)(tasks_hh->data))->state = DEAD; + asm("xchgw %bx, %bx"); + while(1) { asm("hlt"); } +} + +void add_task(ptr_t* entry, task_t type, char* process_name, int start_x, + int start_y, + int size_x, + int size_y, unsigned int sz_args, ...) +{ + lock_32_irq(&lock_scheduler); + va_list VAARGS = va_start(sz_args); + ptask new_task = os_malloc(sizeof(task)); + tasks = add_after_n(tasks, (uint32_t)new_task, 0u); + node* cur_node = find_n(tasks, 1u); + if (ntasks == 0u) + { + tasks->next = tasks; + } + ++ntasks; + new_task->entry = (ptr_t*)((ptr_t)entry + 0xC0000000); + new_task->type = type; + new_task->state = INIT; + new_task->reserved = nullptr; + new_task->lockword = 0u; + context* proc_ctx = os_malloc(sizeof(crop_context)); + new_task->ctx = proc_ctx; + new_task->ctx->ebp = (uint32_t)process_stack_start; + ppdtx new_space = bb(); + cur_node->data2 = (uint32_t)init_console(process_name, start_x, start_y, size_x, size_y); + cur_node->data3 = (uint32_t)new_space; + unsigned int args[MAX_ARGS]; + sz_args = (sz_args < MAX_ARGS) ? sz_args : MAX_ARGS; + if (sz_args > 0) + { + for(unsigned int i = 0u; i < sz_args; ++i) + { + args[i] = va_arg(VAARGS, unsigned int); + } + } + ptr_t* process_stack_esp_int = (ptr_t*)process_stack_start; + node** os_task_hh = (node**)((ptr_t)&os_task + 0xC0000000); + load_page_directory(new_space); + if (sz_args > 0) + { + // process_stack_esp_int -= sz_args; + // copy_rev(process_stack_esp_int, args, sz_args * sizeof(int)); + for(unsigned int i = 0u; i < sz_args; ++i, --process_stack_esp_int) + { + *process_stack_esp_int = args[sz_args - i - 1]; + } + // printf("COPYING ARGS : to %x from %x\n", process_stack_esp_int, args); + // asm("xchgw %bx, %bx"); + } + *process_stack_esp_int = ((ptr_t)&self_destruct + 0xC0000000); + // --process_stack_esp_int; + // *process_stack_esp_int = (uint32_t)process_stack_start; + load_page_directory((void*)(*os_task_hh)->data3); + new_task->ctx->ebp = (uint32_t)process_stack_esp_int; + --process_stack_esp_int; + new_task->ctx->esp = (uint32_t)process_stack_esp_int; + // printf("ESP : EBP = %x : %x\n", new_task->ctx->esp, new_task->ctx->ebp); + // asm("xchgw %bx, %bx"); + unlock_32_irq(&lock_scheduler); +} + +void load_proc_ebp_pdt_entry_esp(ptr_t ebp, ptr_t pdt, ptr_t entry, ptr_t fake1, ptr_t fake2, ptr_t esp) +{ + node* tasks_hh = (node*)*(node**)((ptr_t)&tasks + 0xC0000000); + ebp = (ptr_t)((ptask)(tasks_hh->data))->ctx->ebp; + pdt = (ptr_t)tasks_hh->data3; + entry = (ptr_t)((ptask)(tasks_hh->data))->entry; + esp = (ptr_t)((ptask)(tasks_hh->data))->ctx->esp; +} + +void load_proc_esp_pdt_eip_ebp_esp(ptr_t esp, ptr_t pdt, ptr_t eip, ptr_t fake1, ptr_t fake2, ptr_t ebp, ptr_t esp2) +{ + node* tasks_hh = (node*)*(node**)((ptr_t)&tasks + 0xC0000000); + ebp = (ptr_t)((ptask)(tasks_hh->data))->ctx->ebp; + pdt = (ptr_t)tasks_hh->data3; + eip = (ptr_t)((ptask)(tasks_hh->data))->ctx->eip; + esp = (ptr_t)((ptask)(tasks_hh->data))->ctx->esp; + esp2 = (ptr_t)((ptask)(tasks_hh->data))->ctx->esp; +} + +void terminate_task() +{ + // ... +} + +unsigned int switch_to_next(context* cur_ctx, unsigned int cur_lockword) +{ + node** tasks_hh = (node**)((ptr_t)&tasks + 0xC0000000); + node** os_task_hh = (node**)((ptr_t)&os_task + 0xC0000000); + unsigned int* ntasks_hh = (unsigned int*)((ptr_t)&ntasks + 0xC0000000); + node* old_task_node = (*tasks_hh); + ptask old_task = (ptask)((*tasks_hh)->data); + if (old_task->state == ACTIVE) + { + if ((*ntasks_hh) < 2) return old_task->lockword; + old_task->state = ON_PAUSE; + *(crop_context*)old_task->ctx = *(crop_context*)cur_ctx; // memcpy action + old_task->ctx->esp = (uint32_t)((ptr_t*)&(cur_ctx->eflags) + 2); + old_task->lockword = cur_lockword; + } + // printf("CUR_CTX ON %x, esp on %x, eflags on %x, old.esp on %x\n", cur_ctx, cur_ctx->esp, cur_ctx->eflags, old_task->ctx->esp); + // asm("xchgw %bx, %bx"); + + do + { + // printf("[SWITCH_TO_NEXT] : orig tasks %x\n", &tasks); + // printf("[SWITCH_TO_NEXT] : tasks %x, tasks->next %x\n", (*tasks_hh), (*tasks_hh)->next); + *tasks_hh = (*tasks_hh)->next; + // printf("[SWITCH_TO_NEXT] : tasks %x, tasks->next %x\n", tasks_hh, (*tasks_hh)->next); + ptask next_task = (ptask)((*tasks_hh)->data); + printf("[SWITCH_TO_NEXT]:case %x\n", next_task->state); + printf("[SWITCH_TO_NEXT]:tasks %x\n", tasks); + // printf("[SWITCH_TO_NEXT] : old_task %x, next_task %x\n", old_task, next_task); + switch (next_task->state) + { + case ACTIVE: + { + asm("xchgw %bx, %bx"); + asm("xchgw %bx, %bx"); + asm("xchgw %bx, %bx"); + asm("xchgw %bx, %bx"); + asm("xchgw %bx, %bx"); + asm("xchgw %bx, %bx"); + // load_page_directory((void*)(*tasks_hh)->data3); + return next_task->lockword; + } + case ON_PAUSE: + { + // asm("xchgw %bx, %bx"); + *(crop_context*)cur_ctx = *(crop_context*)next_task->ctx; + cur_ctx->ebp = (ptr_t)((*os_task_hh)->data2); + cur_ctx->esp = next_task->ctx->esp; + cur_ctx->eip = (uint32_t)((uint32_t*)&continue_exec + 0xC0000000); + next_task->state = ACTIVE; + printf("[SWITCH_TO_NEXT]:ON_PAUSE:next.state %x\n", next_task->state); + // asm("xchgw %bx, %bx"); + // load_page_directory((void*)(*tasks_hh)->data3); + return next_task->lockword; + } + case INIT: + { + // printf("CHANGE EBP, EIP : %x\n", cur_ctx); + // asm("xchgw %bx, %bx"); + cur_ctx->ebp = (ptr_t)((*os_task_hh)->data2); + cur_ctx->eip = (uint32_t)((uint32_t*)&exec + 0xC0000000); + // asm("xchgw %bx, %bx"); + next_task->state = ACTIVE; + printf("[SWITCH_TO_NEXT]:INIT:next.state %x\n", next_task->state); + + // unsigned int current_eflags; + // asm("pushf\n\t" + // "pop %0" + // : "=g"(current_eflags) + // : + // : "memory" + // ); + // printf("S[INFO] Interrupt %x, interrupted process context:\n" + // " EAX = %x ECX = %x EDX = %x EBX = %x\n" + // " ESP = %x EBP = %x ESI = %x EDI = %x\n" + // " DS = %x ES = %x FS = %x GS = %x\n" + // " CS = %x SS = %x EIP = %x\n" + // " EFLAGS (interrupted) = %x " "EFLAGS (current) = %x\n" + // " error code = %x\n", + // ((context*)cur_ctx)->vector, + // ((context*)cur_ctx)->eax, ((context*)cur_ctx)->ecx, ((context*)cur_ctx)->edx, ((context*)cur_ctx)->ebx, + // ((context*)cur_ctx)->esp, ((context*)cur_ctx)->ebp, ((context*)cur_ctx)->esi, ((context*)cur_ctx)->edi, + // ((context*)cur_ctx)->ds, ((context*)cur_ctx)->es, ((context*)cur_ctx)->fs, ((context*)cur_ctx)->gs, + // ((context*)cur_ctx)->cs, ((context*)cur_ctx)->ss, ((context*)cur_ctx)->eip, + // ((context*)cur_ctx)->eflags, current_eflags, + // ((context*)cur_ctx)->error_code); + + // load_page_directory((void*)(*tasks_hh)->data3); + // asm("xchgw %bx, %bx"); + return next_task->lockword; + } + case DEAD: + { + cur_ctx->ebp = (ptr_t)((*os_task_hh)->data2); + cur_ctx->eip = (uint32_t)((uint32_t*)&purgatory + 0xC0000000); + // for(unsigned int i = 1u; i < 768u; ++i) + // { + // os_delete((void*)(((ppdtx)(*tasks_hh)->data3)->pages[i].frame_address << 22), 1u << 22); + // } + // os_delete((void*)(*tasks_hh)->data3, sizeof(pde) * 1024); + // os_delete((void*)(*tasks_hh)->data, sizeof(task)); + + // manual remove head (cyclic list case) + if ((*ntasks_hh) > 1) + { + old_task_node->next = (*tasks_hh)->next; + // os_delete((void*)(*tasks_hh), sizeof(node)); + *ntasks_hh = *ntasks_hh - 1; + } + else + { + // os_delete((void*)(*tasks_hh), sizeof(node)); + *ntasks_hh = *ntasks_hh - 1; + print("LAST TASK GONE!"); + asm("xchgw %bx, %bx"); + return 0u; + } + } + default: + { + print("[SWITCH_TO_NEXT] : default!\n"); + return next_task->lockword; + } + } + } while(1); +} + +// static int IRQ_disable_counter = 0; +// void unblock_scheduler() +// { +// --IRQ_disable_counter; +// if(IRQ_disable_counter == 0) +// { +// asm("sti"); +// } +// } + +// void block_scheduler() +// { +// asm("cli"); +// ++IRQ_disable_counter; +// } + +// int is_solo_owning() +// { +// return IRQ_disable_counter; +// } + +void switch_to_os() +{ + node* os_task_hh = (node*)*(node**)((ptr_t)&os_task + 0xC0000000); + load_page_directory((void*)os_task_hh->data3); +} + +task_t get_type() +{ + return ((ptask)tasks->data)->type; +} \ No newline at end of file diff --git a/src/kernel/sys/process/scheduler.h b/src/kernel/sys/process/scheduler.h new file mode 100644 index 0000000..e6c8f10 --- /dev/null +++ b/src/kernel/sys/process/scheduler.h @@ -0,0 +1,57 @@ +#pragma once + +#include "../../misc/list.h" +#include "../memory/alloc.h" +#include "../context/context.h" +#include "../../sync/sync.h" + +extern unsigned int ntasks; +extern node* tasks; +extern node* os_task; + +typedef enum task_type +{ + ARBITRARY = 0b0, + OS = 0b1 + +} task_t; + +typedef enum state_type +{ + ON_PAUSE = 0b00, + ACTIVE = 0b01, + INIT = 0b10, + DEAD = 0b11 + +} state_t; + +#pragma pack(push, 1) +typedef struct task_struct +{ + task_t type; + state_t state; + ptr_t* entry; + context* ctx; + void* reserved; + unsigned int lockword; + +} task, *ptask; +#pragma pack(pop) + +extern mutex lock_scheduler; + +extern ptr_t get_ebp(void); +extern ptr_t get_esp(void); + +void reg_os(); +void add_task(ptr_t* entry, task_t type, char* process_name, int start_x, + int start_y, + int size_x, + int size_y, unsigned int sz_args, ...); +void terminate_task(); +unsigned int switch_to_next(context* cur_ctx, unsigned int cur_lockword); +// void unblock_scheduler(); +// void block_scheduler(); +// int is_solo_owning(); +void switch_to_os(); +task_t get_type(); \ No newline at end of file diff --git a/src/kernel/sys/tramplins.hpp b/src/kernel/sys/tramplins.hpp new file mode 100644 index 0000000..6cdcf12 --- /dev/null +++ b/src/kernel/sys/tramplins.hpp @@ -0,0 +1,295 @@ +#pragma once + +#define __gen_tramplin(x) static void tramplin_##x(); +#define __gen_tramplins(...) static void (*tramplins[])(void) = {__VA_ARGS__}; + +// AUTO-GENERATED CODE IS BELOW + +__gen_tramplin(0) +__gen_tramplin(1) +__gen_tramplin(2) +__gen_tramplin(3) +__gen_tramplin(4) +__gen_tramplin(5) +__gen_tramplin(6) +__gen_tramplin(7) +__gen_tramplin(8) +__gen_tramplin(9) +__gen_tramplin(a) +__gen_tramplin(b) +__gen_tramplin(c) +__gen_tramplin(d) +__gen_tramplin(e) +__gen_tramplin(f) +__gen_tramplin(10) +__gen_tramplin(11) +__gen_tramplin(12) +__gen_tramplin(13) +__gen_tramplin(14) +__gen_tramplin(15) +__gen_tramplin(16) +__gen_tramplin(17) +__gen_tramplin(18) +__gen_tramplin(19) +__gen_tramplin(1a) +__gen_tramplin(1b) +__gen_tramplin(1c) +__gen_tramplin(1d) +__gen_tramplin(1e) +__gen_tramplin(1f) +__gen_tramplin(20) +__gen_tramplin(21) +__gen_tramplin(22) +__gen_tramplin(23) +__gen_tramplin(24) +__gen_tramplin(25) +__gen_tramplin(26) +__gen_tramplin(27) +__gen_tramplin(28) +__gen_tramplin(29) +__gen_tramplin(2a) +__gen_tramplin(2b) +__gen_tramplin(2c) +__gen_tramplin(2d) +__gen_tramplin(2e) +__gen_tramplin(2f) +__gen_tramplin(30) +__gen_tramplin(31) +__gen_tramplin(32) +__gen_tramplin(33) +__gen_tramplin(34) +__gen_tramplin(35) +__gen_tramplin(36) +__gen_tramplin(37) +__gen_tramplin(38) +__gen_tramplin(39) +__gen_tramplin(3a) +__gen_tramplin(3b) +__gen_tramplin(3c) +__gen_tramplin(3d) +__gen_tramplin(3e) +__gen_tramplin(3f) +__gen_tramplin(40) +__gen_tramplin(41) +__gen_tramplin(42) +__gen_tramplin(43) +__gen_tramplin(44) +__gen_tramplin(45) +__gen_tramplin(46) +__gen_tramplin(47) +__gen_tramplin(48) +__gen_tramplin(49) +__gen_tramplin(4a) +__gen_tramplin(4b) +__gen_tramplin(4c) +__gen_tramplin(4d) +__gen_tramplin(4e) +__gen_tramplin(4f) +__gen_tramplin(50) +__gen_tramplin(51) +__gen_tramplin(52) +__gen_tramplin(53) +__gen_tramplin(54) +__gen_tramplin(55) +__gen_tramplin(56) +__gen_tramplin(57) +__gen_tramplin(58) +__gen_tramplin(59) +__gen_tramplin(5a) +__gen_tramplin(5b) +__gen_tramplin(5c) +__gen_tramplin(5d) +__gen_tramplin(5e) +__gen_tramplin(5f) +__gen_tramplin(60) +__gen_tramplin(61) +__gen_tramplin(62) +__gen_tramplin(63) +__gen_tramplin(64) +__gen_tramplin(65) +__gen_tramplin(66) +__gen_tramplin(67) +__gen_tramplin(68) +__gen_tramplin(69) +__gen_tramplin(6a) +__gen_tramplin(6b) +__gen_tramplin(6c) +__gen_tramplin(6d) +__gen_tramplin(6e) +__gen_tramplin(6f) +__gen_tramplin(70) +__gen_tramplin(71) +__gen_tramplin(72) +__gen_tramplin(73) +__gen_tramplin(74) +__gen_tramplin(75) +__gen_tramplin(76) +__gen_tramplin(77) +__gen_tramplin(78) +__gen_tramplin(79) +__gen_tramplin(7a) +__gen_tramplin(7b) +__gen_tramplin(7c) +__gen_tramplin(7d) +__gen_tramplin(7e) +__gen_tramplin(7f) +__gen_tramplin(80) +__gen_tramplin(81) +__gen_tramplin(82) +__gen_tramplin(83) +__gen_tramplin(84) +__gen_tramplin(85) +__gen_tramplin(86) +__gen_tramplin(87) +__gen_tramplin(88) +__gen_tramplin(89) +__gen_tramplin(8a) +__gen_tramplin(8b) +__gen_tramplin(8c) +__gen_tramplin(8d) +__gen_tramplin(8e) +__gen_tramplin(8f) +__gen_tramplin(90) +__gen_tramplin(91) +__gen_tramplin(92) +__gen_tramplin(93) +__gen_tramplin(94) +__gen_tramplin(95) +__gen_tramplin(96) +__gen_tramplin(97) +__gen_tramplin(98) +__gen_tramplin(99) +__gen_tramplin(9a) +__gen_tramplin(9b) +__gen_tramplin(9c) +__gen_tramplin(9d) +__gen_tramplin(9e) +__gen_tramplin(9f) +__gen_tramplin(a0) +__gen_tramplin(a1) +__gen_tramplin(a2) +__gen_tramplin(a3) +__gen_tramplin(a4) +__gen_tramplin(a5) +__gen_tramplin(a6) +__gen_tramplin(a7) +__gen_tramplin(a8) +__gen_tramplin(a9) +__gen_tramplin(aa) +__gen_tramplin(ab) +__gen_tramplin(ac) +__gen_tramplin(ad) +__gen_tramplin(ae) +__gen_tramplin(af) +__gen_tramplin(b0) +__gen_tramplin(b1) +__gen_tramplin(b2) +__gen_tramplin(b3) +__gen_tramplin(b4) +__gen_tramplin(b5) +__gen_tramplin(b6) +__gen_tramplin(b7) +__gen_tramplin(b8) +__gen_tramplin(b9) +__gen_tramplin(ba) +__gen_tramplin(bb) +__gen_tramplin(bc) +__gen_tramplin(bd) +__gen_tramplin(be) +__gen_tramplin(bf) +__gen_tramplin(c0) +__gen_tramplin(c1) +__gen_tramplin(c2) +__gen_tramplin(c3) +__gen_tramplin(c4) +__gen_tramplin(c5) +__gen_tramplin(c6) +__gen_tramplin(c7) +__gen_tramplin(c8) +__gen_tramplin(c9) +__gen_tramplin(ca) +__gen_tramplin(cb) +__gen_tramplin(cc) +__gen_tramplin(cd) +__gen_tramplin(ce) +__gen_tramplin(cf) +__gen_tramplin(d0) +__gen_tramplin(d1) +__gen_tramplin(d2) +__gen_tramplin(d3) +__gen_tramplin(d4) +__gen_tramplin(d5) +__gen_tramplin(d6) +__gen_tramplin(d7) +__gen_tramplin(d8) +__gen_tramplin(d9) +__gen_tramplin(da) +__gen_tramplin(db) +__gen_tramplin(dc) +__gen_tramplin(dd) +__gen_tramplin(de) +__gen_tramplin(df) +__gen_tramplin(e0) +__gen_tramplin(e1) +__gen_tramplin(e2) +__gen_tramplin(e3) +__gen_tramplin(e4) +__gen_tramplin(e5) +__gen_tramplin(e6) +__gen_tramplin(e7) +__gen_tramplin(e8) +__gen_tramplin(e9) +__gen_tramplin(ea) +__gen_tramplin(eb) +__gen_tramplin(ec) +__gen_tramplin(ed) +__gen_tramplin(ee) +__gen_tramplin(ef) +__gen_tramplin(f0) +__gen_tramplin(f1) +__gen_tramplin(f2) +__gen_tramplin(f3) +__gen_tramplin(f4) +__gen_tramplin(f5) +__gen_tramplin(f6) +__gen_tramplin(f7) +__gen_tramplin(f8) +__gen_tramplin(f9) +__gen_tramplin(fa) +__gen_tramplin(fb) +__gen_tramplin(fc) +__gen_tramplin(fd) +__gen_tramplin(fe) +__gen_tramplin(ff) +__gen_tramplins(tramplin_0, tramplin_1, tramplin_2, tramplin_3, tramplin_4, tramplin_5, tramplin_6, tramplin_7, + tramplin_8, tramplin_9, tramplin_a, tramplin_b, tramplin_c, tramplin_d, tramplin_e, tramplin_f, + tramplin_10, tramplin_11, tramplin_12, tramplin_13, tramplin_14, tramplin_15, tramplin_16, tramplin_17, + tramplin_18, tramplin_19, tramplin_1a, tramplin_1b, tramplin_1c, tramplin_1d, tramplin_1e, tramplin_1f, + tramplin_20, tramplin_21, tramplin_22, tramplin_23, tramplin_24, tramplin_25, tramplin_26, tramplin_27, + tramplin_28, tramplin_29, tramplin_2a, tramplin_2b, tramplin_2c, tramplin_2d, tramplin_2e, tramplin_2f, + tramplin_30, tramplin_31, tramplin_32, tramplin_33, tramplin_34, tramplin_35, tramplin_36, tramplin_37, + tramplin_38, tramplin_39, tramplin_3a, tramplin_3b, tramplin_3c, tramplin_3d, tramplin_3e, tramplin_3f, + tramplin_40, tramplin_41, tramplin_42, tramplin_43, tramplin_44, tramplin_45, tramplin_46, tramplin_47, + tramplin_48, tramplin_49, tramplin_4a, tramplin_4b, tramplin_4c, tramplin_4d, tramplin_4e, tramplin_4f, + tramplin_50, tramplin_51, tramplin_52, tramplin_53, tramplin_54, tramplin_55, tramplin_56, tramplin_57, + tramplin_58, tramplin_59, tramplin_5a, tramplin_5b, tramplin_5c, tramplin_5d, tramplin_5e, tramplin_5f, + tramplin_60, tramplin_61, tramplin_62, tramplin_63, tramplin_64, tramplin_65, tramplin_66, tramplin_67, + tramplin_68, tramplin_69, tramplin_6a, tramplin_6b, tramplin_6c, tramplin_6d, tramplin_6e, tramplin_6f, + tramplin_70, tramplin_71, tramplin_72, tramplin_73, tramplin_74, tramplin_75, tramplin_76, tramplin_77, + tramplin_78, tramplin_79, tramplin_7a, tramplin_7b, tramplin_7c, tramplin_7d, tramplin_7e, tramplin_7f, + tramplin_80, tramplin_81, tramplin_82, tramplin_83, tramplin_84, tramplin_85, tramplin_86, tramplin_87, + tramplin_88, tramplin_89, tramplin_8a, tramplin_8b, tramplin_8c, tramplin_8d, tramplin_8e, tramplin_8f, + tramplin_90, tramplin_91, tramplin_92, tramplin_93, tramplin_94, tramplin_95, tramplin_96, tramplin_97, + tramplin_98, tramplin_99, tramplin_9a, tramplin_9b, tramplin_9c, tramplin_9d, tramplin_9e, tramplin_9f, + tramplin_a0, tramplin_a1, tramplin_a2, tramplin_a3, tramplin_a4, tramplin_a5, tramplin_a6, tramplin_a7, + tramplin_a8, tramplin_a9, tramplin_aa, tramplin_ab, tramplin_ac, tramplin_ad, tramplin_ae, tramplin_af, + tramplin_b0, tramplin_b1, tramplin_b2, tramplin_b3, tramplin_b4, tramplin_b5, tramplin_b6, tramplin_b7, + tramplin_b8, tramplin_b9, tramplin_ba, tramplin_bb, tramplin_bc, tramplin_bd, tramplin_be, tramplin_bf, + tramplin_c0, tramplin_c1, tramplin_c2, tramplin_c3, tramplin_c4, tramplin_c5, tramplin_c6, tramplin_c7, + tramplin_c8, tramplin_c9, tramplin_ca, tramplin_cb, tramplin_cc, tramplin_cd, tramplin_ce, tramplin_cf, + tramplin_d0, tramplin_d1, tramplin_d2, tramplin_d3, tramplin_d4, tramplin_d5, tramplin_d6, tramplin_d7, + tramplin_d8, tramplin_d9, tramplin_da, tramplin_db, tramplin_dc, tramplin_dd, tramplin_de, tramplin_df, + tramplin_e0, tramplin_e1, tramplin_e2, tramplin_e3, tramplin_e4, tramplin_e5, tramplin_e6, tramplin_e7, + tramplin_e8, tramplin_e9, tramplin_ea, tramplin_eb, tramplin_ec, tramplin_ed, tramplin_ee, tramplin_ef, + tramplin_f0, tramplin_f1, tramplin_f2, tramplin_f3, tramplin_f4, tramplin_f5, tramplin_f6, tramplin_f7, + tramplin_f8, tramplin_f9, tramplin_fa, tramplin_fb, tramplin_fc, tramplin_fd, tramplin_fe, tramplin_ff) diff --git a/src/kernel/sys/tramplins.hpp.template b/src/kernel/sys/tramplins.hpp.template new file mode 100644 index 0000000..4a0d521 --- /dev/null +++ b/src/kernel/sys/tramplins.hpp.template @@ -0,0 +1,7 @@ +#pragma once + +#define __gen_tramplin(x) static void tramplin_##x() { panic_handler(0x##x); } +#define __gen_tramplins(...) static void (*tramplins[])(void) = {__VA_ARGS__}; + +// AUTO-GENERATED CODE IS BELOW + diff --git a/src/libc/io/console.c b/src/libc/io/console.c new file mode 100644 index 0000000..44b9b29 --- /dev/null +++ b/src/libc/io/console.c @@ -0,0 +1,78 @@ +#include "console.h" +#include "../../kernel/sys/memory/alloc.h" +#include "../../kernel/sys/io/io.h" + +static pair get_pair(int x, int y) +{ + pair p; + p.x = x; + p.y = y; + return p; +} + +static void frame_draw(console* cnsl, char* process_name) +{ + pair size = cnsl->size; + pair start = cnsl->start; + int startx = start.x; + int starty = start.y; + + vga_print_char_raw(201, start.x, start.y, WHITE); // 201 = ╔ + vga_print_char_raw(205, start.x + 1, start.y, WHITE); // 205 = '═' + + int i = 0; + for (; process_name[i]; i++) + { + vga_print_char_raw(process_name[i], start.x + 1 + i + 1, start.y, WHITE); + } + + for(; i < size.x - 2; i++) + { + vga_print_char_raw(205, start.x + 1 + i + 1, start.y, WHITE); // 205 = '═' + } + + vga_print_char_raw(187, start.x + size.x - 1, start.y, WHITE); // 187 = ╗ + + for (i = 1; i < size.y - 1; i++) + { + vga_print_char_raw(186, start.x, start.y + i, WHITE); // 186 = ║ + for(int j = 1; j < size.x - 1; j++) { + vga_print_char_raw('\0', start.x + j, start.y + i, WHITE); + } + vga_print_char_raw(186, start.x + size.x - 1, start.y + i, WHITE); // 186 = ║ + } + + vga_print_char_raw(200, start.x, start.y + size.y - 1, WHITE); // 200 = ╚ + for(i = 1; i < size.x - 1; i++) + { + vga_print_char_raw(205, start.x + i, start.y + size.y - 1, WHITE); // 205 = '═' + } + vga_print_char_raw(188, start.x + size.x - 1, start.y + size.y - 1, WHITE); // 188 = ╝ +} + +console* init_console(char* process_name, + int start_x, + int start_y, + int size_x, + int size_y) +{ + console* cnsl = os_malloc(sizeof(console)); + cnsl->start = get_pair(start_x, start_y); + cnsl->size = get_pair(size_x , size_y ); + cnsl->current_pos = get_pair(1 , 1 ); + // asm("xchgw %bx, %bx"); + frame_draw(cnsl, process_name); + // for(unsigned short i = 180; i < 256; i++) { + // printf("%d", i); + // asm("xchgw %bx, %bx"); + // vga_print_char_raw(i,i - 180, 0, WHITE); + // } + // asm("xchgw %bx, %bx"); + return cnsl; +} + +void delete_console(console* cnsl) +{ + +} + diff --git a/src/libc/io/console.h b/src/libc/io/console.h new file mode 100644 index 0000000..f64e296 --- /dev/null +++ b/src/libc/io/console.h @@ -0,0 +1,31 @@ +#pragma once + +typedef struct +{ + int x; + int y; +} pair; + +typedef struct +{ + // The beginning of the console is considered to be the upper right corner of the frame. + pair start; + + // To be precise, the size of the terminal includes its frames, + // so the text will be displayed on the size plane (size_x - 2, size_y - 2). + pair size; + + // The current position is calculated taking into account the frame. + // Therefore, the starting character is placed at position (1, 1). + pair current_pos; +} console; + + +console* init_console(char* process_name, + int start_x, + int start_y, + int size_x, + int size_y); + +void delete_console(console* cnsl); + diff --git a/src/libc/io/printer.c b/src/libc/io/printer.c new file mode 100644 index 0000000..3bc9ab5 --- /dev/null +++ b/src/libc/io/printer.c @@ -0,0 +1,173 @@ +#include "printer.h" +#include "console.h" +#include "../../kernel/sys/process/scheduler.h" +#include "../../kernel/sys/io/io.h" + +static void shift_up_console(console* cnsl) { + // asm("xchgw %bx, %bx"); + for (int i = cnsl->start.y + 1; i < cnsl->start.y + cnsl->size.y - 2; i++) { + memcpy((char*) VGA_START + (cnsl->start.x + 1) * sizeof(short) + 80 * i * sizeof(short), + (char*) VGA_START + (cnsl->start.x + 1) * sizeof(short) + 80 * (i + 1) * sizeof(short), + sizeof(short) * (cnsl->size.x - 2)); + } + memzero((char*) VGA_START + (cnsl->start.x + 1) * sizeof(short) + 80 * (cnsl->start.y + cnsl->size.y - 2) * sizeof(short), + sizeof(short) * (cnsl->size.x - 2)); + // memcpy((char*) VGA_START, (char*) VGA_START + sizeof(short) * 80, sizeof(short) * 24 * 80); + // memzero((char*) VGA_START + sizeof(short) * 80 * 24, sizeof(short) * 80); +} + +static void end_line_console(console* cnsl) { + // asm("xchgw %bx, %bx"); + if (cnsl->current_pos.y >= cnsl->size.y - 1 - 1) shift_up_console(cnsl); + else ++cnsl->current_pos.y; + cnsl->current_pos.x = 1; +} + +static void print_char_console(console* cnsl, char s, int color) { + // asm("xchgw %bx, %bx"); + if (cnsl->current_pos.y > cnsl->size.y - 1 - 1) { + shift_up_console(cnsl); + cnsl->current_pos.y--; + } + vga_print_char_raw(s, cnsl->start.x + cnsl->current_pos.x, cnsl->start.y + cnsl->current_pos.y, color); + if (++cnsl->current_pos.x >= cnsl->size.x - 1) end_line_console(cnsl); +} + +static void print_string_console(console *cnsl, char* str, int color) { + while (*str) { + print_char_console(cnsl, *str, color); + ++str; + } +} + +mutex lock_cprint = 0; + +void print(const char* fmt, ...) { + va_list a = va_start(fmt); + + lock_32(&lock_cprint); + console* current_console = (console*) ((node*)*(node**)((ptr_t)&tasks + 0xC0000000))->data2; + + for (const char* i = fmt; *i; ++i) { + if (*i == '%') { + if (*(i + 1) == '%') { + print_char_console(current_console, '%', WHITE); + ++i; + } else { + int color = WHITE; + + // mode select + char mode = *(i++ + 1); + + // color select (iff defined) + if (*(i + 1) == '_') { + i += 2; + const char* start = i; + const char* stop = i; + while (*i != '!') { + if (!*i) return; + stop = i++; + } + + if (start != stop) { + char* color_names = "BLACK\0BLUE\0GREEN\0CYAN\0RED\0PURPLE\0" + "BROWN\0GRAY\0DARK_GRAY\0LIGHT_BLUE\0LIGHT_GREEN\0" + "LIGHT_CYAN\0LIGHT_RED\0LIGHT_PURPLE\0YELLOW\0WHITE"; + char* cur_color = color_names; + for (int i = 0; i < _LAST; ++i) { + if (string_compare(start, cur_color, stop - start)) { + color = i; + break; + } + while (*cur_color++); + } + } + } + + // print + if (mode == 's') { + char* b = &va_arg(a, char); + print_string_console(current_console, b, color); + } else if (mode == 'd') { + unsigned b = (unsigned) va_arg(a, int); +#define _MAX_N_DIGITS_FOR_DEC_CASE (int)(12) + if (b != 0) { + char buffer[_MAX_N_DIGITS_FOR_DEC_CASE] = {0}; + + int counter = _MAX_N_DIGITS_FOR_DEC_CASE - 1; +#undef _MAX_N_DIGITS_FOR_DEC_CASE + int is_neg = 0; + if (b & (1 << sizeof(int) * 8 - 1)) + { + is_neg = 1; + b = ~b + 1; + } + while (b) { + buffer[--counter] = b % 10 + '0'; + b /= 10; + } + if (is_neg) + { + buffer[--counter] = '-'; + } + + print_string_console(current_console, buffer + counter, color); + } else { + print_char_console(current_console, '0', color); + } + } else if (mode == 'x' || mode == 'X') { + unsigned int b = (unsigned int) va_arg(a, int); + print_string_console(current_console, "0x", color); + if (b != 0) { + char buffer[sizeof(int) + 1] = {0}; + + int counter = 3; + if (b < 0) { + b *= -1; + } + while (b) { + int temp = b % 16; + + char symbol; + if (temp > 9) { + symbol = temp - 10 + (mode == 'X' ? 'A' : 'a'); + } else { + symbol = temp + '0'; + } + buffer[counter--] = symbol; + b >>= 4; + } + + print_string_console(current_console, buffer + counter + 1, color); + } else { + print_char_console(current_console, '0', color); + } + } else if (mode == 'b') { + unsigned b = (unsigned) va_arg(a, unsigned); + print_string_console(current_console, "0b", color); + char buffer[sizeof(unsigned) * 8 + 1] = {0}; + + int counter = sizeof(unsigned) * 8 - 1; + while (b) { + buffer[counter--] = (char)((b & 1) + '0'); + b >>= 1; + } + + print_string_console(current_console, buffer + counter + 1, color); + } + } + } else if (*i == '\n') { + // end_line_console(); + current_console->current_pos.y++; + current_console->current_pos.x = 1; + + } else if (*i == '\t' || *i == " ") { + // end_line_console(); + while(current_console->current_pos.x++ % 4) {} + + } else { + print_char_console(current_console, *i, WHITE); + } + } + unlock_32(&lock_cprint); +} \ No newline at end of file diff --git a/src/libc/io/printer.h b/src/libc/io/printer.h new file mode 100644 index 0000000..78e1fd7 --- /dev/null +++ b/src/libc/io/printer.h @@ -0,0 +1,6 @@ +#pragma once + +#include "../../kernel/sync/sync.h" + +extern mutex lock_cprint; +void print(const char* fmt, ...); \ No newline at end of file diff --git a/src/pm/gdt.asm b/src/pm/gdt.asm new file mode 100644 index 0000000..9499a9e --- /dev/null +++ b/src/pm/gdt.asm @@ -0,0 +1,36 @@ +%ifndef GDT + %define GDT +%endif + +; GDT + +gdt_start: + +gdt_null: + dd 0x0 + dd 0x0 + +gdt_code: + dw 0xffff + dw 0x0 + db 0x0 + db 10011010b + db 11001111b + db 0x0 + +gdt_data: + dw 0xffff + dw 0x0 + db 0x0 + db 10010010b + db 11001111b + db 0x0 + +gdt_end: + +gdt_descriptor: + dw gdt_end - gdt_start - 1 + dd gdt_start + 0x20000 + +CODE_SEG equ gdt_code - gdt_start +DATA_SEG equ gdt_data - gdt_start \ No newline at end of file diff --git a/src/pm/io/print_d2vm.asm b/src/pm/io/print_d2vm.asm new file mode 100644 index 0000000..833045d --- /dev/null +++ b/src/pm/io/print_d2vm.asm @@ -0,0 +1,39 @@ +%ifndef PRINT_D2VM + %define PRINT_D2VM +%endif + +[global asm_print_d2vm] + +; Printing directly to video memory + +[BITS 32] + +VIDEO_MEMORY equ 0xb8000 +WHITE_ON_BLACK equ 0x0f + +asm_print_d2vm: + push ebp + mov ebp, esp + mov ebx, [esp + 2 * 4] + pusha + mov edx, VIDEO_MEMORY + +print_d2vm_loop: + mov al, [ebx] + mov ah, WHITE_ON_BLACK + + test al, al + jz print_d2vm_done + + mov [edx], ax + + add ebx, 1 + add edx, 2 + + jmp print_d2vm_loop + +print_d2vm_done: + popa + mov esp, ebp + pop ebp + ret \ No newline at end of file diff --git a/src/pm/switch2pm.asm b/src/pm/switch2pm.asm new file mode 100644 index 0000000..5c1c5cb --- /dev/null +++ b/src/pm/switch2pm.asm @@ -0,0 +1,47 @@ +%ifndef SWITCH_TO_PM + %define SWITCH_TO_PM +%endif + +; Switch to protected mode + +%ifndef GDT + %include "./src/pm/gdt.asm" +%endif + +%ifndef PRINT_D2VM + %include "./src/pm/io/print_d2vm.asm" +%endif + +[BITS 16] + +switch_to_pm: + lgdt [gdt_descriptor] + + mov eax, cr0 + or eax, 0x1 + mov cr0, eax + + jmp CODE_SEG:init_pm + 0x7c00 + +[BITS 32] + +init_pm: + mov ax, DATA_SEG + mov ds, ax + mov ss, ax + mov es, ax + mov fs, ax + mov gs, ax + + mov ebp, 0x20000 + mov esp, ebp + + mov ebx, msg_pm_begin + 0x20000 + push ebx + call asm_print_d2vm + + call 0x20200 - 0x7c00 + + jmp $ + +msg_pm_begin db "Hello from 32-bit protected mode!", 0 diff --git a/src/rm/io/print.asm b/src/rm/io/print.asm new file mode 100644 index 0000000..92cf3ab --- /dev/null +++ b/src/rm/io/print.asm @@ -0,0 +1,21 @@ +%ifndef PRINT + %define PRINT +%endif + +[BITS 16] + +print: + pusha + +print_loop: + lodsb + or al, al + jz done_print + mov ah, 0x0e + mov bh, 0 + int 0x10 + jmp print_loop + +done_print: + popa + ret \ No newline at end of file diff --git a/src/rm/io/print_hex.asm b/src/rm/io/print_hex.asm new file mode 100644 index 0000000..437154a --- /dev/null +++ b/src/rm/io/print_hex.asm @@ -0,0 +1,6 @@ +%ifndef PRINT_HEX + %define PRINT_HEX +%endif + +[ORG 0x7c00] +[BITS 16] diff --git a/src/rm/misc/accumulate_sum.asm b/src/rm/misc/accumulate_sum.asm new file mode 100644 index 0000000..aa04eed --- /dev/null +++ b/src/rm/misc/accumulate_sum.asm @@ -0,0 +1,24 @@ +%ifndef ACCUMULATE_SUM + %define ACCUMULATE_SUM +%endif + +[BITS 16] + +accumulate: + pusha + xor bx, bx + +accumulate_loop: + lodsb + add bx, ax + cmp si, cx + jl accumulate_loop + + mov [sum], bx + popa + ret + +sum: + DW 0 +null_byte: + DB 0 \ No newline at end of file