From d71715a3dc80ffbabd5e8b46e17d0eccd20f7429 Mon Sep 17 00:00:00 2001 From: ShivamShah1 <93140921+ShivamShah1@users.noreply.github.com> Date: Thu, 30 Jan 2025 01:21:25 -0800 Subject: [PATCH 1/5] Kernel-User space switching 1.0 Here I have created task-switching segments for the system to push and pull the registers during kernel-user switching tasks. From 0efff39eb4af076b31de820f2e8f44ba181d680d Mon Sep 17 00:00:00 2001 From: ShivamShah1 <93140921+ShivamShah1@users.noreply.github.com> Date: Thu, 30 Jan 2025 15:33:38 -0800 Subject: [PATCH 2/5] Kernel-User space switching 2.0 This is for kernel and user space switching using TSS, task and process creation. --- Makefile | 5 +- src/config.h | 3 + src/gdt/gdt.h | 2 +- src/memory/paging/paging.c | 75 ++++++++++++++ src/memory/paging/paging.h | 4 + src/status.h | 1 + src/string/string.c | 17 ++++ src/string/string.h | 1 + src/task/process.c | 197 +++++++++++++++++++++++++++++++++++++ src/task/process.h | 47 +++++++++ src/task/task.c | 10 +- src/task/task.h | 6 +- 12 files changed, 361 insertions(+), 7 deletions(-) create mode 100644 src/task/process.c create mode 100644 src/task/process.h diff --git a/Makefile b/Makefile index fcc22bd..3119deb 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -FILES = ./build/kernel.asm.o ./build/kernel.o ./build/idt/idt.asm.o ./build/idt/idt.o ./build/memory/memory.o ./build/io/io.asm.o ./build/memory/heap/heap.o ./build/memory/heap/kheap.o ./build/memory/paging/paging.o ./build/memory/paging/paging.asm.o ./build/disk/disk.o ./build/string/string.o ./build/fs/pparser.o ./build/disk/streamer.o ./build/fs/file.o ./build/fs/fat/fat16.o ./build/gdt/gdt.o ./build/gdt/gdt.asm.o ./build/task/tss.asm.o ./build/task/task.o +FILES = ./build/kernel.asm.o ./build/kernel.o ./build/idt/idt.asm.o ./build/idt/idt.o ./build/memory/memory.o ./build/io/io.asm.o ./build/memory/heap/heap.o ./build/memory/heap/kheap.o ./build/memory/paging/paging.o ./build/memory/paging/paging.asm.o ./build/disk/disk.o ./build/string/string.o ./build/fs/pparser.o ./build/disk/streamer.o ./build/fs/file.o ./build/fs/fat/fat16.o ./build/gdt/gdt.o ./build/gdt/gdt.asm.o ./build/task/tss.asm.o ./build/task/task.o ./build/task/process.o INCLUDES = -I./src FLAGS = -g -ffreestanding -falign-jumps -falign-functions -falign-lables -falign-loops -fstrength-reduce -fomit-frame-pointer -finline-functions -Wno-unused-function -fno-builtin -Werror -Wno-cpp -Wno-unused-parameter -nostdlib -nostartfiles -nodefaultlibs -Wall -O0 -Iinc @@ -84,6 +84,9 @@ all: ./bin/boot.bin ./bin/kernel.bin ./build/task/task.o: ./src/task/task.c i686-elf-gcc $(INCLUDES) -I./src/task $(FLAGS) -std=gnu99 -c ./src/task/task.c -o ./build/task/task.o +./build/task/process.o: ./src/task/process.c + i686-elf-gcc $(INCLUDES) -I./src/task $(FLAGS) -std=gnu99 -c ./src/task/process.c -o ./build/task/process.o + clean: rm -rf ./bin/boot.bin rm -rf ./bin/kernel.bin diff --git a/src/config.h b/src/config.h index e3a8421..26395de 100644 --- a/src/config.h +++ b/src/config.h @@ -30,4 +30,7 @@ #define USER_DATA_SEGMENT 0x23 #define USER_CODE_SEGMEnt 0x1b +#define PEACHOS_MAX_PROGRAM_ALLOCATIONS 1024 +#define PEACHOS_MAX_PROCESSES 12 + #endif \ No newline at end of file diff --git a/src/gdt/gdt.h b/src/gdt/gdt.h index ce48e70..8c3a925 100644 --- a/src/gdt/gdt.h +++ b/src/gdt/gdt.h @@ -20,7 +20,7 @@ struct gdt{ uint8_t access; uint8_t high_flags; uint8_t base_24_31_bits; -}; +} __attribute__((packed)); /* create another sturcture which will use the gdt struct diff --git a/src/memory/paging/paging.c b/src/memory/paging/paging.c index 47b02b0..8b78d67 100644 --- a/src/memory/paging/paging.c +++ b/src/memory/paging/paging.c @@ -101,6 +101,81 @@ int paging_get_indexes(void* virtual_address, uint32_t* directory_index_out, uin return res; } +/* + making sure that virtual and physical pages are alligned properly +*/ +void* paging_is_alligned_address(void* ptr){ + if((uint32_t)ptr % PAGING_PAGE_SIZE){ + return (void*)((uint32_t)ptr + PAGING_PAGE_SIZE - ((uint32_t)ptr % PAGING_PAGE_SIZE)); + } + + return ptr; +} + +/* + making sure that virtual and physical pages are mapped properly +*/ +int paging_map(uint32_t* directory, void* virt, void* phys, int flags){ + if(((unsigned int)virt % PAGING_PAGE_SIZE) || ((unsigned int)phys % PAGING_PAGE_SIZE)){ + return -EINVARG; + } + + return paging_set(directory, virt, (uint32_t)phys | flags); +} + +/* + mapping the range of paging of the process +*/ +int paging_map_range(uint32_t* directory, void* virt, void* phys, int count, int flags){ + int res = 0; + for(int i=0; i=PEACHOS_MAX_PROCESSES){ + return NULL; + } + + return processes[process_id]; +} + +/* + loading the binaries to the data to support the ELF file +*/ +static int process_load_binary(const char* filename, struct process* process){ + int res = 0; + int fd = fopen(filename, "r"); + if(!fd){ + res = -EIO; + goto out; + } + + struct file_stat stat; + res = fstat(fd, &stat); + if(res != PEACHOS_ALL_OK){ + goto out; + } + + void* program_data_ptr = kzalloc(stat.filesize); + if(!program_data_ptr){ + res = -ENOMEM; + goto out; + } + + if(fread(program_data_ptr, stat.filesize, 1, fd) != 1){ + res = -EIO; + goto out; + } + + process->ptr = program_data_ptr; + process->size = stat.filesize; + +out: + fclose(fd); + return res; +} + +/* + loading the data to the process +*/ +static int process_load_data(const char* filename, struct process* process){ + int res = 0; + /* incase we support ELF files */ + res = process_load_binary(filename, process); + return res; +} + +/* + to convert the process mapped memory into binary for ELF files +*/ +int process_map_binary(struct process* process){ + int res = 0; + paging_map_to(process->task->page_directory->directory_entry, (void*)PEACHOS_PROGRAM_VIRTUAL_ADDRESS, process->ptr, paging_align_address(process->ptr + process->size), PAGING_IS_PRESENT | PAGING_ACCESS_FROM_ALL | PAGING_IS_WRITEABLE); + return res; +} + +/* + this functions assuems that the process is initialized correctly + otherwise calling this function before that will create kernel panic +*/ +int process_map_memory(struct process* process){ + int res = 0; + /* incase we support ELF files */ + res = process_map_binary(process); + return res; +} + +/* + find the free slot in the process array to load and perform tasks +*/ +int process_get_free_slot(){ + for(int i=0; ifilename, filename, sizeof(_process->filename)); + _process->stack = program_stack_ptr; + _process->id = process_slot; + + /* create a task */ + task = task_new(_process); + if(ERROR_I(task == 0)){ + res = ERROR_I(task); + } + + _process->task = task; + + res = process_map_memory(_process); + if(res<0){ + goto out; + } + + *process = _process; + + /* add the process to the array */ + processes[process_slot] = _process; + +out: + if(ISERR(res)){ + if(_process && _process->task){ + task_free(_process->task); + } + + kfree(_process); + } + return res; +} \ No newline at end of file diff --git a/src/task/process.h b/src/task/process.h new file mode 100644 index 0000000..85f2dc5 --- /dev/null +++ b/src/task/process.h @@ -0,0 +1,47 @@ +/* + This is header file for processes which will be created and + handled properly by our OS. +*/ +#ifndef PROCESS_H +#define PROCESS_H + +#include +#include "config.h" +#include "memory/memory.h" +#include "status.h" +#include "task/task.h" +#include "memory/heap/kheap.h" +#include "fs/file.h" +#include "string/string.h" +#include "kernel.h" +#include "memory/paging/paging.h" + +/* + This is the structure of all the processes which will be created in this system +*/ +struct process{ + /* the process id */ + uint16_t id; + + char filename[PEACHOS_MAX_PATH]; + + /* themain process task */ + struct task* task; + + /* this is to track the memory allocated by the kernel */ + /* so we can free them at the termination of program */ + void* allocations[PEACHOS_MAX_PROGRAM_ALLOCATIONS]; + + /* the physical pointer to the process memory */ + void* ptr; + + /* the physical pointer to the stack memory */ + void* stack; + + /* the size of the data pointed to by ptr */ + uint32_t size; +}; + +int process_load_for_slot(const char* filename, struct process** process, int process_slot); + +#endif PROCESS_H \ No newline at end of file diff --git a/src/task/task.c b/src/task/task.c index 6392f46..aa1f6e1 100644 --- a/src/task/task.c +++ b/src/task/task.c @@ -16,13 +16,13 @@ struct task* current_task = 0; struct task* task_tail = 0; struct task* task_head = 0; -int task_init(struct task* task); +int task_init(struct task* task, struct process* process); struct task* task_current(){ return current_task; }; -struct task* task_new(){ +struct task* task_new(struct process* process){ int res = 0; struct task* task = kzalloc(sizeof(struct task)); if(!task){ @@ -30,7 +30,7 @@ struct task* task_new(){ goto out; } - res = task_init(task); + res = task_init(task, process); if(res != PEACHOS_ALL_OK){ goto out; } @@ -102,7 +102,7 @@ int task_free(struct task* task){ /* to initialize the task with the regesters */ -int task_init(struct task* task){ +int task_init(struct task* task, struct process* process){ memset(task, 0, sizeof(struct task)); /* mape the entire 4GB address space to itself */ @@ -116,5 +116,7 @@ int task_init(struct task* task){ task->registers.ss = USER_DATA_SEGMENT; task->registers.esp = PEACHOS_PROGRAM_VIRTUAL_STACK_ADDRESS_STATE; + task->process = process; + return 0; } \ No newline at end of file diff --git a/src/task/task.h b/src/task/task.h index 5568f97..5343c25 100644 --- a/src/task/task.h +++ b/src/task/task.h @@ -11,6 +11,7 @@ #include "memory/paging/paging.h" #include "memory/heap/kheap.h" #include "memory/memory.h" +#include "process.h" #include /* @@ -42,6 +43,9 @@ struct task{ /* the registers of the task when the task is not running */ struct registers registers; + /* the process of the task */ + struct process* process; + /* the next task in the linked list */ struct task* next; @@ -49,7 +53,7 @@ struct task{ struct task* prev; }; -struct task* task_new(); +struct task* task_new(struct process* process); struct task* task_current(); struct task* task_get_next(); int task_free(struct task* task); From fef4e733b6103fd60c4b051c46e5eb48fbd08de9 Mon Sep 17 00:00:00 2001 From: ShivamShah1 <93140921+ShivamShah1@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:25:51 -0800 Subject: [PATCH 3/5] Kernel-User space, user program creation 3.0 TIll here, I completed custom bootloader, kernel, custom compiler, linker script, memory allocation and freeing, interrupts, input/output, paging and mapping, disk reading, file management, disk streaming, FAT16 implementation by reading a file during boot, filesystem and descriptor, kernel panic, GDT(Global Descriptive Table), TSS(Task Switch Segment), kernel user space switching, user task and user process creation. --- Makefile | 15 +++++-- programs/blank/blank.asm | 13 ++++++ programs/blank/build/Makefile | 6 +++ programs/blank/linker.ld | 46 +++++++++++++++++++++ src/boot/boot.asm | 40 +++++++++---------- src/memory/paging/paging.asm | 4 +- src/task/task.asm | 75 +++++++++++++++++++++++++++++++++++ src/task/task.c | 34 ++++++++++++++++ src/task/task.h | 11 +++++ src/task/tss.asm | 4 +- 10 files changed, 221 insertions(+), 27 deletions(-) create mode 100644 programs/blank/blank.asm create mode 100644 programs/blank/build/Makefile create mode 100644 programs/blank/linker.ld create mode 100644 src/task/task.asm diff --git a/Makefile b/Makefile index 3119deb..936a156 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ -FILES = ./build/kernel.asm.o ./build/kernel.o ./build/idt/idt.asm.o ./build/idt/idt.o ./build/memory/memory.o ./build/io/io.asm.o ./build/memory/heap/heap.o ./build/memory/heap/kheap.o ./build/memory/paging/paging.o ./build/memory/paging/paging.asm.o ./build/disk/disk.o ./build/string/string.o ./build/fs/pparser.o ./build/disk/streamer.o ./build/fs/file.o ./build/fs/fat/fat16.o ./build/gdt/gdt.o ./build/gdt/gdt.asm.o ./build/task/tss.asm.o ./build/task/task.o ./build/task/process.o +FILES = ./build/kernel.asm.o ./build/kernel.o ./build/idt/idt.asm.o ./build/idt/idt.o ./build/memory/memory.o ./build/io/io.asm.o ./build/memory/heap/heap.o ./build/memory/heap/kheap.o ./build/memory/paging/paging.o ./build/memory/paging/paging.asm.o ./build/disk/disk.o ./build/string/string.o ./build/fs/pparser.o ./build/disk/streamer.o ./build/fs/file.o ./build/fs/fat/fat16.o ./build/gdt/gdt.o ./build/gdt/gdt.asm.o ./build/task/tss.asm.o ./build/task/task.o ./build/task/process.o ./build/task/task.asm.o INCLUDES = -I./src FLAGS = -g -ffreestanding -falign-jumps -falign-functions -falign-lables -falign-loops -fstrength-reduce -fomit-frame-pointer -finline-functions -Wno-unused-function -fno-builtin -Werror -Wno-cpp -Wno-unused-parameter -nostdlib -nostartfiles -nodefaultlibs -Wall -O0 -Iinc -all: ./bin/boot.bin ./bin/kernel.bin +all: ./bin/boot.bin ./bin/kernel.bin user_programs rm -rf ./bin/os.bin dd if=./bin/boot.bin >> ./bin/os.bin dd if=./bin/kernel.bin >> ./bin/os.bin @@ -87,7 +87,16 @@ all: ./bin/boot.bin ./bin/kernel.bin ./build/task/process.o: ./src/task/process.c i686-elf-gcc $(INCLUDES) -I./src/task $(FLAGS) -std=gnu99 -c ./src/task/process.c -o ./build/task/process.o -clean: +./build/task/task.asm.o: ./src/task/task.asm + nasm -f elf -g ./src/task/task.asm -o ./build/task/task.asm.o + +user_programs: + cd ./programs/blank && $(MAKE) all + +user_programs_clean: + cd ./programs/blank && $(MAKE) clean + +clean: user_programs_clean rm -rf ./bin/boot.bin rm -rf ./bin/kernel.bin rm -rf ./bin/os.bin diff --git a/programs/blank/blank.asm b/programs/blank/blank.asm new file mode 100644 index 0000000..1684146 --- /dev/null +++ b/programs/blank/blank.asm @@ -0,0 +1,13 @@ +%%if 0 + creating the first program where it will jump in to itself +%%endif +[BITS 32] + +section .asm + +global _start + +_start: + +label: + jmp label \ No newline at end of file diff --git a/programs/blank/build/Makefile b/programs/blank/build/Makefile new file mode 100644 index 0000000..a7e5ec7 --- /dev/null +++ b/programs/blank/build/Makefile @@ -0,0 +1,6 @@ +all: + nasm -f elf ./blank.asm -o ./build/blank.o + i686-elf-gcc -g -T ./linker.ld -o ./blank.bin -ffreestanding -O0 -nostdlib -fpic -g ./build/blank.o + +clean: + rm -rf ./build/blank.o \ No newline at end of file diff --git a/programs/blank/linker.ld b/programs/blank/linker.ld new file mode 100644 index 0000000..0b18673 --- /dev/null +++ b/programs/blank/linker.ld @@ -0,0 +1,46 @@ +/* + Here we are specifing the sections that which section is doing which part + and so on. + + Here in SECTIONS '. = 1M' means (1024x1024=100000 (in hex)) + So we are telling that after the boot go to this location where the + kernel.bin is saved and start running from that part. + + Here we are aligning everything properly as we are now coding in C. + During assmebly we need not wrry for the alignment but for both + asm and C we need to align otherwise code not work properly. + + So we added times 512 at the end of kernel.asm and here. +*/ + +ENTRY(_start) +OUTPUT_FORMAT(binary) +SECTIONS +{ + . = 0x400000; + .text : ALIGN(4096) + { + *(.text) + } + + .rodata : ALIGN(4096) + { + *(.rodata) + } + + .data : ALIGN(4096) + { + *(.data) + } + + .bss : ALIGN(4096) + { + *(COMMON) + *(.bss) + } + + .asm : ALIGN(4096) + { + *(.asm) + } +} \ No newline at end of file diff --git a/src/boot/boot.asm b/src/boot/boot.asm index 9566411..2ba99b9 100644 --- a/src/boot/boot.asm +++ b/src/boot/boot.asm @@ -1,4 +1,4 @@ -/* +%%if 0 First we need to specify the origin so that Os knows the offset needed for the data Ideally the origin should be 0x0000 and then the system should jump to the designated location in the case of this system is 0x7c00. @@ -18,9 +18,9 @@ are not enough to fill 510 bytes then it will pad it with 0's. Now then providing the boot signature which is 0x55AA, but we are writing here 0xAA55 due to endianess. -*/ +%%endif -/* +%%if 0 Use Makefile1 for build Now to run this in the system using qemu we will first create a binary file '.bin'. @@ -34,9 +34,9 @@ Now to run on qemu use this cmd cmd - 'qemu-system-x86_64 -hda ./boot.bin' -*/ +%%endif -/* +%%if 0 ORG 0x7c00 BITS 16 @@ -50,10 +50,10 @@ start: times 510-($ - $$) db 0 dw 0xAA55 -*/ +%%endif -/* +%%if 0 Use Makefile1 for build To print custom message on the booting screen we will use the below code. @@ -87,10 +87,10 @@ message: db 'Hello World!', 0 times 510-($ - $$) db 0 dw 0xAA55 -*/ +%%endif -/* +%%if 0 Use Makefile1 for build Ideally we place our start point 0x0000 and we jump from that to the desired location. @@ -148,10 +148,10 @@ message: db 'Hello World!', 0 times 510-($ - $$) db 0 dw 0xAA55 -*/ +%%endif -/* +%%if 0 Use Makefile1 for build This section we will write and call custom interrupts for Real Mode. @@ -231,11 +231,11 @@ message: db 'Hello World!', 0 times 510-($ - $$) db 0 dw 0xAA55 -*/ +%%endif -/* +%%if 0 Use Makefile1 for build Removing the unnecessary things from the code like interrupts and able to read the message.txt @@ -305,10 +305,10 @@ times 510-($ - $$) db 0 dw 0xAA55 buffer: -*/ +%%endif -/* +%%if 0 For here use Makefile2 and earlier use Makefile1 To start the processor in the protected mode after the real mode. @@ -410,10 +410,10 @@ load32: times 510-($ - $$) db 0 dw 0xAA55 -*/ +%%endif -/* +%%if 0 From here use Makefile and earlier use Makefile1 Now we are creating another file called kernel.asm so we are using this @@ -554,14 +554,14 @@ ata_lba_read: times 510-($ - $$) db 0 dw 0xAA55 -*/ +%%endif -/* +%%if 0 From here use Makefile and earlier use Makefile1 In this we are adding FAT16 system to our booting part so that kernel knows how to read the files. -*/ +%%endif ORG 0x7c00 BITS 16 diff --git a/src/memory/paging/paging.asm b/src/memory/paging/paging.asm index 9f79d85..b4d1ff9 100644 --- a/src/memory/paging/paging.asm +++ b/src/memory/paging/paging.asm @@ -1,7 +1,7 @@ -/* +%%if 0 This is the assembly file for the paging to load and enable paging as C lang does not support this instructions in Intel -*/ +%%endif [BITS 32] diff --git a/src/task/task.asm b/src/task/task.asm new file mode 100644 index 0000000..5695ed0 --- /dev/null +++ b/src/task/task.asm @@ -0,0 +1,75 @@ +; for user land functionality + +[BITS 32] + +section .asm + +global restore_general_purpose_registers +global user_registers +global task_return + +; void task_return(struct registers* regs); +task_return: + mov ebp, esp; + ; push the data segment (SS will be fine) + ; push the stack address + ; push the flags + ; push the code segment + ; push ip + + ; lets access the structure passed to us + mov ebx, [ebp+4] + ; push the data/stack selector + push dword [ebx+44] + ; push the stack pointer + push dword [ebx+40] + + ; push the flags + pushf + pop eax + or eax, 0x200 + push eax + + ; push the code segment + push dword [ebx+32] + + ; push the IP (program counter) to execute + push dword [ebx+28] + + ; setup some segment registers + mov ax, [ebx+44] + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + push dword [ebx+4] + call restore_general_purpose_registers + add esp, 4 + + ; lets leave kernel land and execute in user land + iretd + +; void restore general pusrpose registers (struct register* regs); +restore_general_purpose_registers: + push ebp + mov ebp, esp + mov ebx, [ebp+8] + mov edi, [ebx] + mov esi, [ebx+4] + mov ebp, [ebx+8] + mov edx, [ebx+16] + mov ecx, [ebx+20] + mov eax, [ebx+24] + mov ebx, [ebx+12] + pop esp + ret + +; void user_registers(); +user_registers: + mov ax, 0x23 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + ret \ No newline at end of file diff --git a/src/task/task.c b/src/task/task.c index aa1f6e1..c896592 100644 --- a/src/task/task.c +++ b/src/task/task.c @@ -99,6 +99,40 @@ int task_free(struct task* task){ return 0; } +/* + switching the context of the tasks for task scheduling and task switching +*/ +int task_switch(struct task* task){ + current_task = task; + paging_switch(task->page_directory->directory_entry); + return 0; +} + +/* + takes page from kernel directory and loads into the task/page directory + + as during the interrupts, the kernel will called and when we switch back + we will look into task directory/space so when it return they see the + memory as it was before +*/ +int task_page(){ + user_registers(); + task_switch(current_task); + return 0; +} + +/* + to run the very first task in the system +*/ +void task_run_first_ever_task(){ + if(!current_task){ + panic("task_run_first_ever_task(): No curretn task exists!"); + } + + task_switch(task_head); + task_return(&task_head->registers); +} + /* to initialize the task with the regesters */ diff --git a/src/task/task.h b/src/task/task.h index 5343c25..d5b4149 100644 --- a/src/task/task.h +++ b/src/task/task.h @@ -56,6 +56,17 @@ struct task{ struct task* task_new(struct process* process); struct task* task_current(); struct task* task_get_next(); + int task_free(struct task* task); +int task_switch(struct task* task); +int task_page(); + +/* runing the very first task in the system */ +void task_run_first_ever_task(); + +/* drop us into the user land */ +void task_return(struct registers* process); +void restore_general_purpose_registers(struct registers* regs); +void user_registers(); #endif \ No newline at end of file diff --git a/src/task/tss.asm b/src/task/tss.asm index 18e4724..9c4718c 100644 --- a/src/task/tss.asm +++ b/src/task/tss.asm @@ -1,10 +1,10 @@ -/* +%%if 0 this is a assembly file for the TSS(Task Switching Segment) When the kernel switches from kernel mode to user mode it will pull this segment to continue its old work or from user mode to kernel mode, it will push this segment for future completion. -*/ +%%endif section .asm global tss_load From 3bed892bf2b16dd181044a7f968ec4722999fe71 Mon Sep 17 00:00:00 2001 From: ShivamShah1 <93140921+ShivamShah1@users.noreply.github.com> Date: Thu, 13 Feb 2025 14:49:25 -0800 Subject: [PATCH 4/5] Kernel-User space, user program creation 4.0 TIll here, I completed custom bootloader, kernel, custom compiler, linker script, memory allocation and freeing, interrupts, input/output, paging and mapping, disk reading, file management, disk streaming, FAT16 implementation by reading a file during boot, filesystem and descriptor, kernel panic, GDT(Global Descriptive Table), TSS(Task Switch Segment), user task and user process creation and using interrupts for kernel user space switching. --- Makefile | 9 +- OS_n_Booting.docx | Bin 3417096 -> 3421322 bytes build/isr80h/to_keep | 1 + programs/blank/blank.asm | 4 +- src/config.h | 2 + src/idt/idt.asm | 42 ++++++- src/idt/idt.c | 54 ++++++++- src/idt/idt.h | 21 ++++ src/isr80h/isr80h.c | 10 ++ src/isr80h/isr80h.h | 13 +++ src/isr80h/misc.c | 10 ++ src/isr80h/misc.h | 10 ++ src/kernel.asm | 10 ++ src/kernel.c | 221 ++++--------------------------------- src/kernel.h | 2 + src/memory/paging/paging.c | 14 +-- src/memory/paging/paging.h | 16 +-- src/task/process.c | 3 +- src/task/process.h | 1 + src/task/task.asm | 4 +- src/task/task.c | 35 +++++- src/task/task.h | 6 + 22 files changed, 263 insertions(+), 225 deletions(-) create mode 100644 build/isr80h/to_keep create mode 100644 src/isr80h/isr80h.c create mode 100644 src/isr80h/isr80h.h create mode 100644 src/isr80h/misc.c create mode 100644 src/isr80h/misc.h diff --git a/Makefile b/Makefile index 936a156..cfb9f41 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -FILES = ./build/kernel.asm.o ./build/kernel.o ./build/idt/idt.asm.o ./build/idt/idt.o ./build/memory/memory.o ./build/io/io.asm.o ./build/memory/heap/heap.o ./build/memory/heap/kheap.o ./build/memory/paging/paging.o ./build/memory/paging/paging.asm.o ./build/disk/disk.o ./build/string/string.o ./build/fs/pparser.o ./build/disk/streamer.o ./build/fs/file.o ./build/fs/fat/fat16.o ./build/gdt/gdt.o ./build/gdt/gdt.asm.o ./build/task/tss.asm.o ./build/task/task.o ./build/task/process.o ./build/task/task.asm.o +FILES = ./build/kernel.asm.o ./build/kernel.o ./build/idt/idt.asm.o ./build/idt/idt.o ./build/memory/memory.o ./build/io/io.asm.o ./build/memory/heap/heap.o ./build/memory/heap/kheap.o ./build/memory/paging/paging.o ./build/memory/paging/paging.asm.o ./build/disk/disk.o ./build/string/string.o ./build/fs/pparser.o ./build/disk/streamer.o ./build/fs/file.o ./build/fs/fat/fat16.o ./build/gdt/gdt.o ./build/gdt/gdt.asm.o ./build/task/tss.asm.o ./build/task/task.o ./build/task/process.o ./build/task/task.asm.o ./build/isr80h/isr80h.o ./build/isr80h/misc.o INCLUDES = -I./src FLAGS = -g -ffreestanding -falign-jumps -falign-functions -falign-lables -falign-loops -fstrength-reduce -fomit-frame-pointer -finline-functions -Wno-unused-function -fno-builtin -Werror -Wno-cpp -Wno-unused-parameter -nostdlib -nostartfiles -nodefaultlibs -Wall -O0 -Iinc @@ -15,6 +15,7 @@ all: ./bin/boot.bin ./bin/kernel.bin user_programs # copy a file over sudo cp ./hello.txt /mnt/d + sudo cp ./programs/blank/blank.bin /mnt/d sudo unmount /mnt/d ./bin/kernel.bin: $(FILES) @@ -90,6 +91,12 @@ all: ./bin/boot.bin ./bin/kernel.bin user_programs ./build/task/task.asm.o: ./src/task/task.asm nasm -f elf -g ./src/task/task.asm -o ./build/task/task.asm.o +./build/isr80h/isr80h.o: ./src/isr80h/isr80h.c + i686-elf-gcc $(INCLUDES) -I./src/isr80h $(FLAGS) -std=gnu99 -c ./src/isr80h/isr80h.c -o ./build/isr80h/isr80h.o + +./build/isr80h/misc.o: ./src/isr80h/misc.c + i686-elf-gcc $(INCLUDES) -I./src/isr80h $(FLAGS) -std=gnu99 -c ./src/isr80h/misc.c -o ./build/isr80h/misc.o + user_programs: cd ./programs/blank && $(MAKE) all diff --git a/OS_n_Booting.docx b/OS_n_Booting.docx index 4e45a46d59a84c4eaf2a40f436d4b4112d357b95..83dd068fc8c13912f02c6bf61d9f039b1a0efdd0 100644 GIT binary patch delta 18380 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 E4UpRqB>(^b delta 14106 zcmZA81yJ75w;*ubDemr2Xt57>clYA%?ivadcPL+RcXxLyrMSDhJ4GM=-JN}JH#5IE zGnqSQGD+sVUK*=VCW*gZR>Nig+dc(pjoL`Nq~;W6vrxSjpui8>7$ z7!0Q8GCD&V^;tBq&Pf3ePicqcSH!pm(QErhSDsc})9bjDnU+jGpMHC+w#ChMtK|T% zeITt_G+>pJr~$1KP6Sh8&|tKRT+V89W!Q&h#l@j%a3pm43mU{*dU+dbB^{{3>nYu3 zeI$b|i80b=Ps1oc?B`+YQp$MPCjVxm!Ss3@)t|y7Pmvt}6zLYa0?|88BrTo(S?3WfgAfw(W7zBd;2Ta4G+J5S|9IOCkrHvZ~4{mDvF<3 z+o3pnEv9r6v>JoR!&^URnn^Bj6J~qpVYqg?Q!4_|#-XYF?G^`%wty6X!>DLEd z1qt$`SpkKC2{v<2zOqr}$q|Z;9+882qPd01`SO`=8P{AvdKnB=8GZdlyoT^_b`wW! z`q!sXAqe!pD2oL4eD`*C4VYV}!O7v;zs*kvDyV+~!WOaqd<8T2@GoHNvXD$3y2|66 z;jud^>a;z!2mPDu(7$ml?DcmJUUh-Pr+Y0h6td^$ky?(0+GOO~xC6%L1)|6VHv@Ev z455vyzJV;@SW!Bl%F>ixtCkS!{82f3Ch3uXbXAd3^*U&}FZKWh_2*g3iQq6beGq7N zESeYKzT{Vo3gIbK@!VG4rHnomug)h+f+8Is6;dC~Lab9S;Gc5cXqWyS&Pr=%zhH17 zApJ{DDi@)oTzVoVY_wsj;#MS;9?KqX$@=V)&fEs^ENN=~1{F8ti`Jb9oCnFR%sH8& zk;?BpCeJ=ZCVBiZ76?IQmU1*I1?9Gg7x!17i?I6)PiUV(L2TH$FjgkvG1K^u6!b1D z0qw@IU{+B=w{ed?*I$pn#6u#vXz9~I`xrp6)Y~IwVtmYJ7~5!!7%H`!TG;+KHrINSDhkpv$NSfN+Hn~Wj(>J2P`2gaW@E(QK*o9Dc7?|d2<*pl#Sa&(gZtUV zrdT1f&X4vmUGSvT(KGzx!V%|nTqy`&d1K-pwEWRX_otJtytupHwLQvA{J4H*u>=x4 zz%lGP-Hqk#s7+y!%hT{->xpU4U`yEnwsI?RhI3qVja866vGr=V1A2#wi%HQ28EKYl(}RzSYTckQ?NTiHAg1IM}lY zub(}Au9|=OgCuQXK^sl4(yErv;48O1 z3fY_4oN~<1@%V#}Ko{MdGv9hgAG^{!tC?Jg)*`6YBz2l10-vas)ynxNb5j)G$nu<2 zsJ(a$6B-R2`+)()S2$Obc%OI%ukADXsA)-4ZB7lI9~$=lH0$B1lSIpwm;K_S(^rzo zOxWcZzD(^$Rl1?7?%GbMm6*U0AX07jz_gL5vTiwyDZ-FC(WzKI4VFiZw^J>FHNNu^ zPRd@`+B(d38)UH=t@$+sCwA`XrSt*X?YD5gN_j2sBFsfr5Jiob>3VAnEa4r>*5peb zX$)t1<$%}}Pq|!X#rKO&dZ`QdCfGWXnNAx~NqulxbAK&nDkU8=>g5C7>604TG<#9t?d6hjdU zS)KV{(IbAS`YtYcqVu_0w^PnsxT<7VAN%AjI8?3KhsA2qpbV)qgB^>JOCm$ER8F!3 zpSQ}*o{!tl7`-&_=;azSTv*%6v|4iHpI=RWni4u11cA)vTs(ICl8cV_Yfh>9XM~#dFErI%{xABU8+IfUKPb*P^l

@S?Ai4qM7CXhX-J@mFcZ7% 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 C= PEACHOS_MAX_ISR80H_COMMANDS){ + panic("The command is out of box\n"); + } + + if(isr80h_commands[command_id]){ + panic("You are attempting to overwrite an existing command\n"); + } + + isr80h_commands[command_id] = command; +} + +/* + to handle the interrupt +*/ +void* isr80h_handler_command(int command, struct interrupt_frame* frame){ + void* result = 0; + if(command < 0 || command >= PEACHOS_MAX_ISR80H_COMMANDS){ + return 0; + } + + ISR80H_COMMAND command_func = isr80h_commands[command]; + if(!command_func){ + return 0; + } + + result = command_func(frame); + return result; +} + +/* + Interrupt handler when called will pass the command to kernel + to print the message from userspace +*/ +void* isr80h_handler(int command, struct interrupt_frame* frame){ + void* res = 0; + kernel_page(); + /* for multi-tasking/threading pusrposes by saving old task state */ + task_current_save_status(frame); + res = isr80h_handler_command(command, frame); + task_page(); + return res; } \ No newline at end of file diff --git a/src/idt/idt.h b/src/idt/idt.h index df2e71d..a0ed435 100644 --- a/src/idt/idt.h +++ b/src/idt/idt.h @@ -7,6 +7,9 @@ #include +struct interrupt_frame; +typedef void*(*ISR80H_COMMAND)(struct interrupt_frame* frame); + struct idt_desc{ uint16_t offset_1; // offset bits 0-15 uint16_t selector; // selector thats in out GDT @@ -20,8 +23,26 @@ struct idtr_desc{ uint32_t base; // base address of the start of the interrupt descriptor table } __attribute__((packed)); +struct interrupt_frame{ + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t reserved; + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + uint32_t ip; + uint32_t cs; + uint32_t flags; + /* user land stack pointer */ + uint32_t esp; + uint32_t ss; +} __attribute__((packed)); + void idt_init(); void enable_interrupts(); void disable_interrupts(); +void isr80h_register_command(int command_id,ISR80H_COMMAND command); #endif \ No newline at end of file diff --git a/src/isr80h/isr80h.c b/src/isr80h/isr80h.c new file mode 100644 index 0000000..90343e9 --- /dev/null +++ b/src/isr80h/isr80h.c @@ -0,0 +1,10 @@ +/* + This will take care of interrupt 80 when generated +*/ +#include "isr80h.h" +#include "idt/idt.h" +#include "misc.h" + +void isr80h_register_commands(){ + isr80h_register_command(SYSTEM_COMMAND0_SUM, isr80h_command0_sum); +} \ No newline at end of file diff --git a/src/isr80h/isr80h.h b/src/isr80h/isr80h.h new file mode 100644 index 0000000..497c78e --- /dev/null +++ b/src/isr80h/isr80h.h @@ -0,0 +1,13 @@ +/* + This is header which take care of interrupt 80 when generated +*/ +#ifndef ISR80H_H +#define ISR80H_H + +enum SystemCommands{ + SYSTEM_COMMAND0_SUM +}; + +void isr80h_register_commands(); + +#endif ISR80H_H \ No newline at end of file diff --git a/src/isr80h/misc.c b/src/isr80h/misc.c new file mode 100644 index 0000000..c4fca46 --- /dev/null +++ b/src/isr80h/misc.c @@ -0,0 +1,10 @@ +/* + This is miscillaneous sector where it will store and register interrupts +*/ +#include "misc.h" +#include "idt/idt.h" + +void* isr80h_command0_sum(struct interrupt_frame* frame){ + + return 0; +} \ No newline at end of file diff --git a/src/isr80h/misc.h b/src/isr80h/misc.h new file mode 100644 index 0000000..36e0ba1 --- /dev/null +++ b/src/isr80h/misc.h @@ -0,0 +1,10 @@ +/* + This is header for miscillaneous sector where it will store and register interrupts +*/ +#ifndef ISR80H_MISC_H +#define ISR80H_MISC_H + +struct interrupt_frame; +void* isr80h_command0_sum(struct interrupt_frame* frame); + +#endif ISR80H_MISC_H \ No newline at end of file diff --git a/src/kernel.asm b/src/kernel.asm index e3e4706..ce31f93 100644 --- a/src/kernel.asm +++ b/src/kernel.asm @@ -2,6 +2,8 @@ global _start global problem +global kernel_registers + extern kernel_main CODE_SEG equ 0x08 @@ -41,6 +43,14 @@ _start: jmp $ +kernel_registers: + mov ax, 0x10 + mov ds, ax + mov es, ax + mov gs, ax + mov fs, ax + ret + problem: ; in idt.c there we are declaring int 0 for how to manage it ; so we are calling interrupt here diff --git a/src/kernel.c b/src/kernel.c index f35d5aa..1ebf7aa 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -14,6 +14,10 @@ #include "config.h" #include "gdt/gdt.h" #include "task/tss.h" +#include "task/task.h" +#include "task/process.h" +#include "status.h" +#include "isr80h/isr80h.h" uint16_t* video_mem = 0; uint16_t terminal_row = 0; @@ -105,6 +109,15 @@ void panic(const char* msg){ while(1){} } +/* + Will switch page directory from kernel page directory + and also change from registers from kernel registers +*/ +void kernel_page(){ + kernel_registers(); + paging_switch(kernel_chunk); +} + /* to declare the user and kernel segments */ @@ -120,32 +133,6 @@ struct gdt_structured gdt_structured[PEACHOS_TOTAL_GDT_SEGMENTS] = { }; void kernel_main(){ - /* - here we will see a letter 'A' in blue colour at the booting process with other data - on the screen. - - To run this run ./build.sh in cmd list and then go to bin dir and then run the - 'qemu-system-x86_64 -hda ./os.bin' - - char* video_mem = (char*)(0xB8000); - video_mem[0] = 'A'; - video_mem[1] = 1; - video_mem[2] = 'B'; - video_mem[3] = 2; - */ - - /* - Here we know this uses 2 bytes so we use uint_16 for more precision. - - For this we need to change the values which we provides like - we know A=0x41 and 1=0x01, so we will provide as '0x4101'. - - Here we need to provide 0x0141 because of edianess. - - uint16_t* video_mem = (uint16_t*)(0xB8000); - video_mem[0] = 0x0141; - */ - /* Everytime its not good to provide it with hex values. @@ -206,13 +193,6 @@ void kernel_main(){ */ kernel_chunk = paging_new_4gb(PAGING_IS_WRITEABLE | PAGING_IS_PRESENT | PAGING_ACCESS_FROM_ALL); - /* - To directly read from the location into buffer - - char buf[512]; - disk_read_block(disk_get(0), 20, 4, &buf); - */ - /* In-charge of switching pages as in paging there is no contigous memory location. So, if the memory is contigous then there is no meaning of paging. @@ -222,37 +202,7 @@ void kernel_main(){ paging_4gb_chunk_get_directory is for getting location of page. */ - paging_switch(paging_4gb_chunk_get_directory(kernel_chunk)); - - /* - mapping the memory - - char *ptr = kzalloc(4096); - */ - - /* - setting up for paging, so here in virtual addr 0x1000 should map to the ptr addr. - So if we use another ptr pointing to 0x1000, the data will be same as even though - physical address is different as it is mapped to 0x1000 on virtual address. - - paging_set(paging_4gb_chunk_get_directory(kernel_chunk), (void*)0x1000, (uint32_t)ptr | PAGING_IS_PRESENT | PAGING_ACCESS_FROM_ALL | PAGING_IS_WRITEABLE); - */ - - /* - testing the above mapping mechanism in working as we have a ptr pointing to 0x1000 virtual address - and the above ptr is pointing to 0x1000 virtual address having different physical address. - - Here we have not yet implemented the enable_pagin(), so it is not enabled. = - So by changing the values at ptr2, we will not change the data at different physical address. - - Output- ptr2 -AB and ptr - empty. - - char* ptr2 = (char*) 0x1000; - ptr2[0] = 'A'; - ptr2[1] = 'B'; - print(ptr2); - print(ptr); - */ + paging_switch(kernel_chunk); /* enabling the paging @@ -260,145 +210,20 @@ void kernel_main(){ enable_paging; /* - sometimes setting paging, it disables or triggers unneccessay interrupts + registering kernel commands */ - enable_interrupts; + isr80h_register_commands(); /* - using path parser to move from one part to another - - struct path_root* root_path = pathparser_parse("0:/bin/shell.exe", NULL); - if(root_path){ - - } - */ - - /* - Assigning disk 0 to read, then selecting single byte to read which is - 0x201 and storing that location data to c. - - struct disk_stream* stream = diskstreamer_new(0); - diskstreamer_seek(stream, 0x201); - unsigned char c = 0; - diskstreamer_read(stream, &c, 1); - to hold to see the data in qemu - while(1){} + providing the process */ - - /* - to check if the strcpy works properly - - char buf[20]; - strcpy(buf, "hello!"); - */ - - /* - testing the fat16 implementation using file descriptor using fopen, fread and fseek. - - first fd is created and from that, it will look for a file name hello.txt - if it finds then loads its directory and items. - Once loaded, we can now read and write into them in streams also. - - int fd = fopen("0:/hello.txt", "r"); - if(fd){ - print("\n we opend hello.txt file \n"); - char buf[14]; - fseek(fd, 2, SEEK_SET); - // now reading from pos 2 instead of 0 - fread(buf, 11, 1, fd); - // NULL terminator - buf[13] = 0x00; - print(buf); + struct process* process = 0; + int res = process_load("0:/blank.bin", &process); + if(res != PEACHOS_ALL_OK){ + panic("Failed to load blank.bin\n"); } - */ - - /* - testing filesystem using file programs - */ - int fd = fopen("0:/hello.txt", "r"); - print("\n file opened\n"); - if(fd){ - struct file_stat s; - fstat(fd, &s); - print("\n status of file\n"); - fclose(fd); - print("\n file closed\n"); - } - - /* - reading into the buffer - Place the init code for disk at the start of the kernel so that it init the disk - at the start so that it is easy to map and access the location through an interface. - - We can directly use the below without disk init, but a proper interface wont be create to regualrlly - and randomly accessing the data using API. We will need to know the exact location in the - physical memory for paging and maping. - - char buf[512]; - disk_read_sector(0, 1, buf); - */ - - /* - testing the above mapping mechanism in working as we have a ptr pointing to 0x1000 virtual address - and the above ptr is pointing to 0x1000 virtual address having different physical address. - - Here we have enabled paging - So by changing the values at ptr2, we will change the data at different physical address. - - Output - ptr2 - AB and ptr - AB. - - char* ptr2 = (char*) 0x1000; - ptr2[0] = 'A'; - ptr2[1] = 'B'; - print(ptr2); - print(ptr); - */ - void* ptr = kmalloc(50); - void* ptr2 = kmalloc(5000); - void* ptr3 = kmalloc(5600); - kfree(ptr); - void* ptr4 = kmalloc(50); - /* here we are using this to see if we have aloocated memory or not - if( ptr || ptr2 || ptr3 || ptr4){ + task_run_first_ever_task(); - } - */ - kfree(ptr2); - kfree(ptr3); - kfree(ptr4); - /* - disable interrupts so the system does not get interrupted while doing this - */ - disable_interrupts(); - - /* - generating an interrupt as we are dividing it number by zero - */ - problem(); - - /* - enabling interrupts so the system does get interrupted for another interrupts - */ - enable_interrupts(); - - /* - using io to provide output this char - The below code after outb is to do io using interrupts - - outb(0x60, 0xff); - */ - - /* - the above one is to directly call the i/o - This is used to handle the i/o using interrupts - - We are using keyboard to call this interrupt. - - this way we are only taking interrupt from keyboard only once - so we need will change it that is takes interrupt everytime. - - If we change the interrupt from 0x21 to 0x20, as 20 is for timer - then we will get continous interrupt on the screen for keyboard. - */ + while(1) {} } \ No newline at end of file diff --git a/src/kernel.h b/src/kernel.h index 5f9485a..e9c5f47 100644 --- a/src/kernel.h +++ b/src/kernel.h @@ -13,6 +13,8 @@ void kernel_main(); void print(const char* str); void panic(const char* msg); +void kernel_page(); +void kernel_registers(); #define ERROR(value) (void*)(value) #define ERROR_I(value) (int)(value) diff --git a/src/memory/paging/paging.c b/src/memory/paging/paging.c index 8b78d67..23fadfe 100644 --- a/src/memory/paging/paging.c +++ b/src/memory/paging/paging.c @@ -55,9 +55,9 @@ struct paging_4gb_chunk* paging_new_4gb(uint8_t flags){ So, to get the data properly as the location of the data is scatter all the place, to retrive the data properly we use page switching method. */ -void paging_switch(uint32_t* directory){ - paging_load_directory(directory); - current_directory = directory; +void paging_switch(struct paging_4gb_chunk* directory){ + paging_load_directory(directory->directory_entry); + current_directory = directory->directory_entry; } /* @@ -115,18 +115,18 @@ void* paging_is_alligned_address(void* ptr){ /* making sure that virtual and physical pages are mapped properly */ -int paging_map(uint32_t* directory, void* virt, void* phys, int flags){ +int paging_map(struct paging_4gb_chunk* directory, void* virt, void* phys, int flags){ if(((unsigned int)virt % PAGING_PAGE_SIZE) || ((unsigned int)phys % PAGING_PAGE_SIZE)){ return -EINVARG; } - return paging_set(directory, virt, (uint32_t)phys | flags); + return paging_set(directory->directory_entry, virt, (uint32_t)phys | flags); } /* mapping the range of paging of the process */ -int paging_map_range(uint32_t* directory, void* virt, void* phys, int count, int flags){ +int paging_map_range(struct paging_4gb_chunk* directory, void* virt, void* phys, int count, int flags){ int res = 0; for(int i=0; itask->page_directory->directory_entry, (void*)PEACHOS_PROGRAM_VIRTUAL_ADDRESS, process->ptr, paging_align_address(process->ptr + process->size), PAGING_IS_PRESENT | PAGING_ACCESS_FROM_ALL | PAGING_IS_WRITEABLE); + paging_map_to(process->task->page_directory, (void*)PEACHOS_PROGRAM_VIRTUAL_ADDRESS, process->ptr, paging_align_address(process->ptr + process->size), PAGING_IS_PRESENT | PAGING_ACCESS_FROM_ALL | PAGING_IS_WRITEABLE); return res; } @@ -171,6 +171,7 @@ int process_load_for_slot(const char* filename, struct process** process, int pr task = task_new(_process); if(ERROR_I(task == 0)){ res = ERROR_I(task); + goto out; } _process->task = task; diff --git a/src/task/process.h b/src/task/process.h index 85f2dc5..a7ed199 100644 --- a/src/task/process.h +++ b/src/task/process.h @@ -42,6 +42,7 @@ struct process{ uint32_t size; }; +int process_load(const char* filename, struct process** process); int process_load_for_slot(const char* filename, struct process** process, int process_slot); #endif PROCESS_H \ No newline at end of file diff --git a/src/task/task.asm b/src/task/task.asm index 5695ed0..20d878b 100644 --- a/src/task/task.asm +++ b/src/task/task.asm @@ -43,7 +43,7 @@ task_return: mov fs, ax mov gs, ax - push dword [ebx+4] + push dword [ebp+4] call restore_general_purpose_registers add esp, 4 @@ -62,7 +62,7 @@ restore_general_purpose_registers: mov ecx, [ebx+20] mov eax, [ebx+24] mov ebx, [ebx+12] - pop esp + pop epb ret ; void user_registers(); diff --git a/src/task/task.c b/src/task/task.c index c896592..e475f04 100644 --- a/src/task/task.c +++ b/src/task/task.c @@ -38,6 +38,7 @@ struct task* task_new(struct process* process){ if(task_head == 0){ task_head = task; task_tail = task; + current_task = task; goto out; } @@ -104,10 +105,41 @@ int task_free(struct task* task){ */ int task_switch(struct task* task){ current_task = task; - paging_switch(task->page_directory->directory_entry); + paging_switch(task->page_directory); return 0; } +/* + To save the task as interrupt called so when interrupt returns, kernel starts + from the place where it paused +*/ +void task_save_state(struct task* task, struct interrupt_frame* frame){ + task->registers.ip = frame->ip; + task->registers.cs = frame->cs; + task->registers.flags = frame->flags; + task->registers.esp = frame->esp; + task->registers.ss = frame->ss; + task->registers.eax = frame->eax; + task->registers.ebp = frame->ebp; + task->registers.ebx = frame->ebx; + task->registers.ecx = frame->ecx; + task->registers.edi = frame->edi; + task->registers.edx = frame->edx; + task->registers.esi = frame->esi; +} + +/* + to save the current stage of the process +*/ +void task_current_save_state(struct interrupt_frame* frame){ + if(!task_current()){ + panic("No current task to save\n"); + } + + struct task* task = task_current(); + task_save_state(task, frame); +} + /* takes page from kernel directory and loads into the task/page directory @@ -148,6 +180,7 @@ int task_init(struct task* task, struct process* process){ /* for the first time program counter will point to the virtual address of process */ task->registers.ip = PEACHOS_PROGRAM_VIRTUAL_ADDRESS; task->registers.ss = USER_DATA_SEGMENT; + task->registers.cs = USER_CODE_SEGMEnt; task->registers.esp = PEACHOS_PROGRAM_VIRTUAL_STACK_ADDRESS_STATE; task->process = process; diff --git a/src/task/task.h b/src/task/task.h index d5b4149..965dfc3 100644 --- a/src/task/task.h +++ b/src/task/task.h @@ -12,8 +12,11 @@ #include "memory/heap/kheap.h" #include "memory/memory.h" #include "process.h" +#include "idt/idt.h" + #include +struct interrupt_frame; /* here we are creating structures for register as we need to move and store registers as moving from kernel @@ -69,4 +72,7 @@ void task_return(struct registers* process); void restore_general_purpose_registers(struct registers* regs); void user_registers(); +/* saving the task */ +void task_current_save_state(struct interrupt_frame* frame); + #endif \ No newline at end of file From 169a240d3f8400f645479dce8f6ed5c99260d6dc Mon Sep 17 00:00:00 2001 From: ShivamShah1 <93140921+ShivamShah1@users.noreply.github.com> Date: Fri, 14 Feb 2025 00:56:20 -0800 Subject: [PATCH 5/5] Kernel-User space, user program creation 5.0 TIll here, I completed custom bootloader, kernel, custom compiler, linker script, memory allocation and freeing, interrupts, input/output, paging and mapping, disk reading, file management, disk streaming, FAT16 implementation by reading a file during boot, filesystem and descriptor, kernel panic, GDT(Global Descriptive Table), TSS(Task Switch Segment), user task and user process creation, interrupt handling for kernel and user space switching, and printing string from user space (first user program run). --- Makefile | 5 ++- programs/blank/blank.asm | 10 ++++-- programs/blank/linker.ld | 10 +++--- src/isr80h/io.c | 19 +++++++++++ src/isr80h/io.h | 10 ++++++ src/isr80h/isr80h.c | 2 ++ src/isr80h/isr80h.h | 3 +- src/isr80h/misc.c | 6 ++-- src/linker.ld | 10 +++--- src/memory/paging/paging.c | 11 ++++++- src/memory/paging/paging.h | 2 +- src/task/process.c | 7 ++++ src/task/task.c | 66 ++++++++++++++++++++++++++++++++++++++ src/task/task.h | 5 +++ 14 files changed, 147 insertions(+), 19 deletions(-) create mode 100644 src/isr80h/io.c create mode 100644 src/isr80h/io.h diff --git a/Makefile b/Makefile index cfb9f41..f080df4 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -FILES = ./build/kernel.asm.o ./build/kernel.o ./build/idt/idt.asm.o ./build/idt/idt.o ./build/memory/memory.o ./build/io/io.asm.o ./build/memory/heap/heap.o ./build/memory/heap/kheap.o ./build/memory/paging/paging.o ./build/memory/paging/paging.asm.o ./build/disk/disk.o ./build/string/string.o ./build/fs/pparser.o ./build/disk/streamer.o ./build/fs/file.o ./build/fs/fat/fat16.o ./build/gdt/gdt.o ./build/gdt/gdt.asm.o ./build/task/tss.asm.o ./build/task/task.o ./build/task/process.o ./build/task/task.asm.o ./build/isr80h/isr80h.o ./build/isr80h/misc.o +FILES = ./build/kernel.asm.o ./build/kernel.o ./build/idt/idt.asm.o ./build/idt/idt.o ./build/memory/memory.o ./build/io/io.asm.o ./build/memory/heap/heap.o ./build/memory/heap/kheap.o ./build/memory/paging/paging.o ./build/memory/paging/paging.asm.o ./build/disk/disk.o ./build/string/string.o ./build/fs/pparser.o ./build/disk/streamer.o ./build/fs/file.o ./build/fs/fat/fat16.o ./build/gdt/gdt.o ./build/gdt/gdt.asm.o ./build/task/tss.asm.o ./build/task/task.o ./build/task/process.o ./build/task/task.asm.o ./build/isr80h/isr80h.o ./build/isr80h/misc.o ./build/isr80h/io.o INCLUDES = -I./src FLAGS = -g -ffreestanding -falign-jumps -falign-functions -falign-lables -falign-loops -fstrength-reduce -fomit-frame-pointer -finline-functions -Wno-unused-function -fno-builtin -Werror -Wno-cpp -Wno-unused-parameter -nostdlib -nostartfiles -nodefaultlibs -Wall -O0 -Iinc @@ -97,6 +97,9 @@ all: ./bin/boot.bin ./bin/kernel.bin user_programs ./build/isr80h/misc.o: ./src/isr80h/misc.c i686-elf-gcc $(INCLUDES) -I./src/isr80h $(FLAGS) -std=gnu99 -c ./src/isr80h/misc.c -o ./build/isr80h/misc.o +./build/isr80h/io.o: ./src/isr80h/io.c + i686-elf-gcc $(INCLUDES) -I./src/isr80h $(FLAGS) -std=gnu99 -c ./src/isr80h/io.c -o ./build/isr80h/io.o + user_programs: cd ./programs/blank && $(MAKE) all diff --git a/programs/blank/blank.asm b/programs/blank/blank.asm index d91a942..1648e7b 100644 --- a/programs/blank/blank.asm +++ b/programs/blank/blank.asm @@ -8,8 +8,12 @@ section .asm global _start _start: - - mov eax, 0 + push message + mov eax, 1 ; command print int 0x80 + add esp, 4 - jmp label \ No newline at end of file + jmp $ + +section .data +message: db 'This is from user space', 0 \ No newline at end of file diff --git a/programs/blank/linker.ld b/programs/blank/linker.ld index 0b18673..800df6e 100644 --- a/programs/blank/linker.ld +++ b/programs/blank/linker.ld @@ -23,6 +23,11 @@ SECTIONS *(.text) } + .asm : ALIGN(4096) + { + *(.asm) + } + .rodata : ALIGN(4096) { *(.rodata) @@ -38,9 +43,4 @@ SECTIONS *(COMMON) *(.bss) } - - .asm : ALIGN(4096) - { - *(.asm) - } } \ No newline at end of file diff --git a/src/isr80h/io.c b/src/isr80h/io.c new file mode 100644 index 0000000..692159a --- /dev/null +++ b/src/isr80h/io.c @@ -0,0 +1,19 @@ +/* + This is IO file for interrupt +*/ + +#include "io.h" +#include "task/task.h" +#include "kernel.h" + +/* + This is to print the command or string from the frame or task +*/ +void* isr80h_command1_print(struct interrupt_frame* frame){ + void* user_space_msg_buffer = task_get_stack_item(task_current(), 0); + char buf[1024]; + copy_string_from_task(task_current(), user_space_msg_buffer, buf, sizeof(buf)); + + print(buf); + return 0; +} \ No newline at end of file diff --git a/src/isr80h/io.h b/src/isr80h/io.h new file mode 100644 index 0000000..742b985 --- /dev/null +++ b/src/isr80h/io.h @@ -0,0 +1,10 @@ +/* + This is header file for IO operations for interrupts +*/ + +#ifndef ISR80H_IO_H +#define ISR80H_IO_H + +struct interrupt_frame; +void *isr80h_command1_print(struct interrupt_frame* frame); +#endif \ No newline at end of file diff --git a/src/isr80h/isr80h.c b/src/isr80h/isr80h.c index 90343e9..3d7b8f2 100644 --- a/src/isr80h/isr80h.c +++ b/src/isr80h/isr80h.c @@ -4,7 +4,9 @@ #include "isr80h.h" #include "idt/idt.h" #include "misc.h" +#include "io.h" void isr80h_register_commands(){ isr80h_register_command(SYSTEM_COMMAND0_SUM, isr80h_command0_sum); + isr80h_register_command(SYSTEM_COMMAND1_PRINT, isr80h_command1_print); } \ No newline at end of file diff --git a/src/isr80h/isr80h.h b/src/isr80h/isr80h.h index 497c78e..ff75ef7 100644 --- a/src/isr80h/isr80h.h +++ b/src/isr80h/isr80h.h @@ -5,7 +5,8 @@ #define ISR80H_H enum SystemCommands{ - SYSTEM_COMMAND0_SUM + SYSTEM_COMMAND0_SUM, + SYSTEM_COMMAND1_PRINT, }; void isr80h_register_commands(); diff --git a/src/isr80h/misc.c b/src/isr80h/misc.c index c4fca46..b2c6ee7 100644 --- a/src/isr80h/misc.c +++ b/src/isr80h/misc.c @@ -3,8 +3,10 @@ */ #include "misc.h" #include "idt/idt.h" +#include "task/task.h" void* isr80h_command0_sum(struct interrupt_frame* frame){ - - return 0; + int v2 = (int)task_get_stack_item(task_current(), 1); + int v1 = (int)task_get_stack_item(task_current(), 0); + return (void*)(v1 + v2); } \ No newline at end of file diff --git a/src/linker.ld b/src/linker.ld index c025b62..1857810 100644 --- a/src/linker.ld +++ b/src/linker.ld @@ -23,6 +23,11 @@ SECTIONS *(.text) } + .asm : ALIGN(4096) + { + *(.asm) + } + .rodata : ALIGN(4096) { *(.rodata) @@ -38,9 +43,4 @@ SECTIONS *(COMMON) *(.bss) } - - .asm : ALIGN(4096) - { - *(.asm) - } } \ No newline at end of file diff --git a/src/memory/paging/paging.c b/src/memory/paging/paging.c index 23fadfe..e67be2a 100644 --- a/src/memory/paging/paging.c +++ b/src/memory/paging/paging.c @@ -130,7 +130,7 @@ int paging_map_range(struct paging_4gb_chunk* directory, void* virt, void* phys, int res = 0; for(int i=0; itask->page_directory, (void*)PEACHOS_PROGRAM_VIRTUAL_STACK_ADDRESS_END, process->stack, paging_align_address(process->stack+PEACHOS_USER_PROGRAM_STACK_SIZE), PAGING_IS_PRESENT | PAGING_ACCESS_FROM_ALL | PAGING_IS_WRITEABLE); +out: return res; } diff --git a/src/task/task.c b/src/task/task.c index e475f04..73d9760 100644 --- a/src/task/task.c +++ b/src/task/task.c @@ -128,6 +128,44 @@ void task_save_state(struct task* task, struct interrupt_frame* frame){ task->registers.esi = frame->esi; } +/* + Copy string from user tasks +*/ +int copy_string_from_task(struct task* task, void* virtual, void* phys, int max){ + if(max >= PAGING_PAGE_SIZE){ + return -EINVARG; + } + + /* providing memory for task sharing */ + int res = 0; + char* tmp = kzalloc(max); + if(!tmp){ + res = -ENOMEM; + goto out; + } + + uint32_t* task_directory = task->page_directory->directory_entry; + uint32_t old_entry = paging_get(task_directory, tmp); + paging_map(task->page_directory, tmp, tmp, PAGING_IS_WRITEABLE | PAGING_IS_PRESENT | PAGING_ACCESS_FROM_ALL); + paging_switch(task->page_directory); + strncpy(tmp, virtual, max); + kernel_page(); + + res = paging_set(task_directory, tmp, old_entry); + if(res<0){ + res = -EIO; + goto out_free; + } + + strncpy(phys, tmp, max); + +out_free: + kfree(tmp); + +out: + return res; +} + /* to save the current stage of the process */ @@ -153,6 +191,15 @@ int task_page(){ return 0; } +/* + changing page directory to point task page directory +*/ +int task_page_task(struct task* task){ + user_registers(); + paging_switch(task->page_directory); + return 0; +} + /* to run the very first task in the system */ @@ -186,4 +233,23 @@ int task_init(struct task* task, struct process* process){ task->process = process; return 0; +} + +/* + assigning stack pointer and item from the task +*/ +void* task_get_stack_item(struct task* task, int index){ + void* result = 0; + + uint32_t* sp_ptr = (uint32_t*)task->registers.esp; + + /* switch to the given tasks page */ + task_page_task(task); + + result = (void*)sp_ptr[index]; + + /* switch back to the kernel page */ + kernel_page(); + + return result; } \ No newline at end of file diff --git a/src/task/task.h b/src/task/task.h index 965dfc3..b98e72e 100644 --- a/src/task/task.h +++ b/src/task/task.h @@ -13,6 +13,8 @@ #include "memory/memory.h" #include "process.h" #include "idt/idt.h" +#include "memory/paging/paging.h" +#include "string/string.h" #include @@ -74,5 +76,8 @@ void user_registers(); /* saving the task */ void task_current_save_state(struct interrupt_frame* frame); +int copy_string_from_task(struct task* task, void* virtual, void* phys, int max); +void* task_get_stack_item(struct task* task, int index); +int task_page_task(struct task* task); #endif \ No newline at end of file