CeDOS - Commit 310276e3

Added process struct and functions
Celina Sophie Kalus
Tue, 02 Jan 2018 01:58:19 +0100
16 files changed, 205 insertions(+), 89 deletions(-)
M boot/stage2/main.cboot/stage2/main.c

@@ -7,7 +7,7 @@ #define VGA_TEXTMODE_CELLS (VGA_TEXTMODE_COLUMNS * VGA_TEXTMODE_LINES)

#define VGA_TEXT_COLOR 0x02 -const uint8_t const *display_start = (uint8_t*)0xB8000; +uint8_t const *display_start = (uint8_t*)0xB8000; uint8_t *display = (uint8_t*)0xB8000; void simple_clear(void) {
A include/cedos/kernel.h

@@ -0,0 +1,13 @@

+/*! + * Defines important kernel mode functions + */ +#ifndef KERNEL_H +#define KERNEL_H + +#include "cedos/drivers/console.h" + +__attribute__((always_inline)) inline void printk(const char* string) { + vga_con.write_s(string); +} + +#endif
M include/cedos/mm/paging.hinclude/cedos/mm/paging.h

@@ -17,61 +17,29 @@ typedef void* PHYS_ADDR;

typedef void* VIRT_ADDR; //! Represents a single page entry in a page table. -typedef union { - uint32_t entry; - struct - { - uint32_t present : 1; - uint32_t read_write : 1; - uint32_t user_supervisor : 1; - uint32_t write_through : 1; - uint32_t cache_disabled : 1; - uint32_t accessed : 1; - uint32_t __zero : 1; - uint32_t page_size : 1; - uint32_t __ignored : 1; - uint32_t available : 3; - uint32_t page_table_addr : 20; - } __attribute__((packed)) fields; -} PAGE_DIR_ENTRY; +typedef uint32_t PAGE_DIR_ENTRY; //! Represents a single page table entry in a page directory. -typedef union { - uint32_t entry; - uint8_t bytes[4]; - struct { - uint32_t present : 1; - uint32_t read_write : 1; - uint32_t user_supervisor : 1; - uint32_t write_through : 1; - uint32_t cache_disabled : 1; - uint32_t accessed : 1; - uint32_t dirty : 1; - uint32_t __zero : 1; - uint32_t global : 1; - uint32_t available : 3; - uint32_t page_addr : 20; - } __attribute__((packed)) fields; -} PAGE_TABLE_ENTRY; +typedef uint32_t PAGE_TABLE_ENTRY; /*! * Sets cr3 to new page directory and returns the old one. * \param page_dir Address of new page directory that is supposed to be used. * \return Address of old page directory. */ -inline void* switch_page_dir(void* page_dir) { +__attribute__((always_inline)) inline void* switch_page_dir(void* page_dir) { uint32_t res; __asm__ volatile ( "mov %%cr3, %0\n" "mov %1, %%cr3" : "=a" (res) : "Nd" (page_dir)); - return res; + return (void*)res; } /*! * Invalidates all pages, forces buffer reload. */ -inline void inv_all_pages(void) { +__attribute__((always_inline)) inline void inv_all_pages(void) { __asm__ volatile ( "mov %cr3, %eax\n" "mov %eax, %cr3"); }
A include/cedos/process.h

@@ -0,0 +1,40 @@

+/*! \file + * Defines processes, a process list and process IDs + */ +#ifndef PROCESS_H +#define PROCESS_H + +#include "cedos/mm/paging.h" + +typedef enum { + PSTATE_READY, + PSTATE_RUNNING, + PSTATE_BLOCKED, + PSTATE_TERMINATED +} PROCESS_STATE; + +typedef uint32_t PROCESS_ID; + +struct __PROCESS { + struct __PROCESS *next; + PROCESS_ID id; + + PHYS_ADDR page_dir; + + PROCESS_STATE state; + VIRT_ADDR eip; + VIRT_ADDR esp; + + uint32_t eax, ebx, ecx, edx; +}; + +typedef struct __PROCESS PROCESS; + +PROCESS* get_process(PROCESS_ID pid); +PROCESS_STATE get_process_state(PROCESS_ID pid); +PROCESS_ID get_current_process(void); + +PROCESS_ID add_process(PROCESS* process); +void remove_process(PROCESS_ID pid); + +#endif
M include/cedos/scheduler.hinclude/cedos/scheduler.h

@@ -6,13 +6,17 @@ #define SCHEDULER_H

#include <stdint.h> -typedef uint32_t ProcessID; +#include "cedos/process.h" +#include "cedos/mm/paging.h" /*! * Executes a task. */ -ProcessID sched_exec(void); +PROCESS_ID sched_exec(PHYS_ADDR page_dir, VIRT_ADDR eip, VIRT_ADDR esp); +/*! + * Initializes the scheduler. + */ int sched_init(void); #endif
M include/string.hinclude/string.h

@@ -6,6 +6,8 @@ #define STRING_H

#include <stdint.h> +#define NULL ((void*)0) + /*! * Unsigned integral type. */
M kernel/drivers/ps2_keyboard.ckernel/drivers/ps2_keyboard.c

@@ -22,14 +22,14 @@ ps2_kb_init,

ps2_kb_read }; -__attribute__((interrupt)) volatile void keyboard_int_handler(INTERRUPT_FRAME *frame) { +__attribute__((interrupt)) void keyboard_int_handler(INTERRUPT_FRAME *frame) { } int ps2_kb_init(void) { - + return 1; } uint8_t ps2_kb_read(void) { - + return 0; }
M kernel/entry.skernel/entry.s

@@ -17,4 +17,4 @@ loop:

jmp loop error: - jmp error+ jmp error
M kernel/interrupts.ckernel/interrupts.c

@@ -14,16 +14,16 @@ (uint8_t)(type), \

(uint16_t)(0xC000) \ } -__attribute__((interrupt)) volatile void default_isr(INTERRUPT_FRAME *frame) { +__attribute__((interrupt)) void default_isr(INTERRUPT_FRAME *frame) { vga_con.write_s("interrupt was issued\n"); } -__attribute__((interrupt)) volatile void breakpoint_isr(INTERRUPT_FRAME *frame) { +__attribute__((interrupt)) void breakpoint_isr(INTERRUPT_FRAME *frame) { vga_con.write_s("BREAKPOINT WAS HIT\n"); // dump registers to stdout } -__attribute__((interrupt)) volatile void double_fault_isr(INTERRUPT_FRAME *frame) { +__attribute__((interrupt)) void double_fault_isr(INTERRUPT_FRAME *frame) { vga_con.write_s("CRITICAL: DOUBLE FAULT\n"); //while (1) {} }

@@ -60,13 +60,13 @@ default:

install_interrupt(i, default_isr, 0x08, HARDWARE_INTERRUPT); break; } - - return 1; } - + __asm__ volatile ( "lidt (%0)\n" "sti" : : "m" (IDT_DESC) ); + + return 1; }
M kernel/main.ckernel/main.c

@@ -2,28 +2,32 @@ #include "cedos/drivers/console.h"

#include "cedos/interrupts.h" #include "cedos/pic.h" #include "cedos/scheduler.h" +#include "cedos/mm/paging.h" +#include "cedos/kernel.h" int os_init(void) { vga_con.init(); - vga_con.write_s("TTY output initialized.\n"); + printk("TTY output initialized.\n"); - vga_con.write_s("Initializing PIC..."); + printk("Initializing PIC..."); pic_init(); - vga_con.write_s("done.\n"); + printk("done.\n"); - vga_con.write_s("Initializing interrupts..."); + printk("Initializing interrupts..."); interrupts_init(); - vga_con.write_s("done.\n"); + printk("done.\n"); - vga_con.write_s("Initialization finished.\n--------------\n"); + printk("Initialization finished.\n--------------\n"); + + return 1; } int os_main(void) { //const char* string[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; - vga_con.write_s("Starting scheduler.\n"); - sched_exec(); + printk("Starting scheduler.\n"); + sched_exec(create_empty_page_dir(), (void*)0, (void*)0); - vga_con.write_s("Main procedure terminating.\n"); + printk("Main procedure terminating.\n"); return 0; }
M kernel/makefilekernel/makefile

@@ -10,7 +10,7 @@ SUBDIRS = $(wildcard */.)

.PHONY: build build: folder $(SUBDIRS) $(OBJECTS) -> $(GCC_PREFIX)ld $(LOCAL_BUILD)/*.o -r -e _kernel_start -o $(GLOBAL_BUILD)/kernel.o --oformat elf32-i386 +> $(GCC_PREFIX)ld $(LOCAL_BUILD)/*.o -r -o $(GLOBAL_BUILD)/kernel.o --oformat elf32-i386 .PHONY: folder folder:
M kernel/mm/memory.ckernel/mm/memory.c

@@ -6,7 +6,7 @@ * \param size Size in bytes of the requested block of memory.

* \return Memory address to the new memory block */ void* os_kernel_malloc(size_t size) { - + return (void*)0; } /*!

@@ -14,7 +14,7 @@ * Frees a previously allocated block of memory. (KERNEL MODE)

* \param ptr Pointer to the memory block to be freed. */ void os_kernel_free(void* ptr) { - + } /*!

@@ -23,7 +23,7 @@ * \param size Size in bytes of the requested block of memory.

* \return Memory address to the new memory block */ void* os_user_malloc(size_t size) { - + return (void*)0; } /*!
M kernel/mm/paging.ckernel/mm/paging.c

@@ -22,20 +22,24 @@ #define PAGE_TABLE_ALT_MAPPED_ADDR(index) \

((PAGE_TABLE_ENTRY*)(PAGE_MAPPED_ADDR((PAGE_ENTRY_COUNT - 2), index))) #define PAGE_DIR_ALT_MAPPED_ADDR \ ((PAGE_DIR_ENTRY*)(PAGE_TABLE_ALT_MAPPED_ADDR(PAGE_ENTRY_COUNT - 1))) - + #define PAGE_TABLE_FLAGS 0b000000000011 - + +__attribute__((always_inline)) inline int is_present(uint32_t entry) { + return (entry & 0b000000000001); +} + /*! * WARNING: This method assumes the target page directory has already been mounted * to the second to last page directory entry */ -inline int is_addr_available(uint32_t dir_index, uint32_t table_index) { +__attribute__((always_inline)) inline int is_addr_available(uint32_t dir_index, uint32_t table_index) { PAGE_DIR_ENTRY* page_dir = PAGE_DIR_ALT_MAPPED_ADDR; PAGE_TABLE_ENTRY* page_table = PAGE_TABLE_ALT_MAPPED_ADDR(table_index); - if(!(page_dir[dir_index].fields.present)) { + if(!is_present(page_dir[dir_index])) { return 1; - } else if (!(page_table[table_index].fields.present)) { + } else if (!is_present(page_table[table_index])) { return 1; } else { return 0;

@@ -52,15 +56,15 @@ PAGE_TABLE_ENTRY* page_table = PAGE_TABLE_ALT_MAPPED_ADDR(dir_index);

int tmp = 0; - if (!(page_dir[dir_index].fields.present)) { + if (!is_present(page_dir[dir_index])) { // acquire new page table void *new_page_table = get_free_page(); - page_dir[dir_index].entry = MAKE_PAGE_ENTRY(new_page_table, PAGE_TABLE_FLAGS); + page_dir[dir_index] = MAKE_PAGE_ENTRY(new_page_table, PAGE_TABLE_FLAGS); } - if (!(page_table[table_index].fields.present)) { + if (!is_present(page_table[table_index])) { // map page - page_table[table_index].entry = MAKE_PAGE_ENTRY(page_addr, flags); + page_table[table_index] = MAKE_PAGE_ENTRY(page_addr, flags); return 1; } else { // didn't works

@@ -68,6 +72,11 @@ return 0;

} } +void mount_page_dir(PHYS_ADDR page_dir) { + PAGE_DIR_ENTRY *cur_page_dir = PAGE_DIR_MAPPED_ADDR; + cur_page_dir[PAGE_ENTRY_COUNT - 2] = MAKE_PAGE_ENTRY(page_dir, PAGE_TABLE_FLAGS); +} + int map_range_to(PHYS_ADDR page_dir, VIRT_ADDR dest, PHYS_ADDR src, uint32_t page_count, uint32_t flags) { mount_page_dir(page_dir);

@@ -76,7 +85,7 @@ for (uint32_t i = 0; i < page_count; i++) {

uint32_t dir_index = PAGE_DIR_INDEX(dest + i * PAGE_SIZE); uint32_t table_index = PAGE_TABLE_INDEX(dest + i * PAGE_SIZE); - if (!(is_addr_available(dir_index, table_index))) { return 0; } + if (!is_addr_available(dir_index, table_index)) { return 0; } } for (uint32_t i = 0; i < page_count; i++) {

@@ -85,11 +94,8 @@ uint32_t table_index = PAGE_TABLE_INDEX(dest + i * PAGE_SIZE);

map_page_to(src + i * PAGE_SIZE, dir_index, table_index, flags); } -} -void mount_page_dir(PHYS_ADDR page_dir) { - PAGE_DIR_ENTRY *cur_page_dir = PAGE_DIR_MAPPED_ADDR; - cur_page_dir[PAGE_ENTRY_COUNT - 2].entry = MAKE_PAGE_ENTRY(page_dir, PAGE_TABLE_FLAGS); + return 1; } VIRT_ADDR map_first_free(PHYS_ADDR page_dir, VIRT_ADDR search_start, PHYS_ADDR page, uint32_t flags) {

@@ -118,12 +124,12 @@

memset(page_dir, 0, PAGE_SIZE); // map to itself - page_dir[PAGE_ENTRY_COUNT - 1].entry = MAKE_PAGE_ENTRY(page_dir_phys, PAGE_TABLE_FLAGS); + page_dir[PAGE_ENTRY_COUNT - 1] = MAKE_PAGE_ENTRY(page_dir_phys, PAGE_TABLE_FLAGS); page_dir = PAGE_DIR_ALT_MAPPED_ADDR; // map kernel - page_dir[PAGE_DIR_INDEX(0xc0000000)].entry = PAGE_DIR_MAPPED_ADDR[PAGE_DIR_INDEX(0xc0000000)].entry; + page_dir[PAGE_DIR_INDEX(0xc0000000)] = PAGE_DIR_MAPPED_ADDR[PAGE_DIR_INDEX(0xc0000000)]; return page_dir_phys; }
M kernel/pic.ckernel/pic.c

@@ -6,7 +6,7 @@ /*!

* Moves irqs to appropriate addresses and enables all PIC interrupts * \return 1 on success, 0 on fail */ -volatile int pic_init(void) { +int pic_init(void) { // start initialization sequence outb(0x11, PIC1_COMMAND); outb(0x11, PIC2_COMMAND);

@@ -30,6 +30,8 @@

// clear interrupt masks outb(0xff, PIC1_DATA); outb(0xff, PIC2_DATA); + + return 1; } /*!

@@ -50,6 +52,8 @@

uint8_t mask = inb(port); mask &= ~(1 << irq); outb(mask, port); + + return 1; } /*!

@@ -70,4 +74,6 @@

uint8_t mask = inb(port); mask |= 1 << irq; outb(mask, port); + + return 1; }
A kernel/process.c

@@ -0,0 +1,62 @@

+#include "cedos/process.h" + +#define NULL ((void*)0) + +PROCESS* list_head; +PROCESS_ID current_process = 0; +PROCESS_ID next_available = 0; + +PROCESS* get_process(PROCESS_ID pid) { + for (PROCESS *p = list_head; p != NULL; p = p->next) { + if (p->id == pid) { + return p; + } else if (p->id > pid) { + return NULL; + } + } + + return NULL; +} + +PROCESS_STATE get_process_state(PROCESS_ID pid) { + PROCESS* p = get_process(pid); + if (p == NULL) { + return PSTATE_TERMINATED; + } else { + return p->state; + } +} + +PROCESS_ID get_current_process(void) { + return current_process; +} + +PROCESS_ID add_process(PROCESS* process) { + for (PROCESS **p = &list_head; *p != NULL; p = &((*p)->next)) { + if ((*p)->next == NULL) { + (*p)->next = process; + process->id = (*p)->id + 1; + process->next = NULL; + return process->id; + } else if ((*p)->next->id > (*p)->id + 1) { + (*p)->next = process; + process->id = (*p)->id + 1; + process->next = (*p); + return process->id; + } + } + + list_head = process; + process->next = NULL; + process->id = 0; + return 0; +} + +void remove_process(PROCESS_ID pid) { + for (PROCESS **p = &list_head; (*p) != NULL; p = &((*p)->next)) { + if ((*p)->next != NULL && (*p)->next->id == pid) { + (*p)->next = (*p)->next->next; + return; + } + } +}
M kernel/scheduler.ckernel/scheduler.c

@@ -1,22 +1,33 @@

#include "cedos/scheduler.h" +#include "cedos/process.h" #include "cedos/mm/paging.h" #include "cedos/drivers/console.h" +#include "cedos/kernel.h" + +PROCESS* get_slot(void) { + static PROCESS free_slots[4]; + static uint32_t index = 0; + return &(free_slots[index++]); +} /*! * Executes a task. */ -ProcessID sched_exec(void) { - void* page_dir = create_empty_page_dir(); - switch_page_dir(page_dir); +PROCESS_ID sched_exec(PHYS_ADDR page_dir, VIRT_ADDR eip, VIRT_ADDR esp) { + PROCESS* p = get_slot(); + + p->page_dir = page_dir; + p->eip = eip; + p->esp = esp; + + // TODO: add file descriptors for stdin, stdout and stderr - map_range_to(page_dir, (VIRT_ADDR)0x00000000, (PHYS_ADDR)0x00000000, PAGE_ENTRY_COUNT, 0b000000000011); - - // will not work because lower memory not mapped - vga_con.write_s("Successfully switched to new page directory.\n"); - - return 0; + p->state = PSTATE_READY; + + return add_process(p); } int sched_init(void) { + // TODO: create and start idle process return 1; }