📄 main.c
字号:
/* Copyright (C) 2004 The SOS Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <sos/errno.h>/* Include definitions of the multiboot standard */#include <bootstrap/multiboot.h>#include <hwcore/idt.h>#include <hwcore/gdt.h>#include <hwcore/irq.h>#include <hwcore/exception.h>#include <hwcore/i8254.h>#include <sos/list.h>#include <sos/physmem.h>#include <hwcore/paging.h>#include <hwcore/mm_context.h>#include <hwcore/swintr.h>#include <sos/kmem_vmm.h>#include <sos/kmalloc.h>#include <sos/time.h>#include <sos/thread.h>#include <sos/process.h>#include <sos/umem_vmm.h>#include <sos/klibc.h>#include <sos/assert.h>#include <drivers/x86_videomem.h>#include <drivers/bochs.h>#include <sos/calcload.h>#include <sos/umem_vmm.h>#include <sos/binfmt_elf32.h>#include <drivers/zero.h>#include <sos/fs.h>#include <drivers/fs_virtfs.h>/* Helper function to display each bits of a 32bits integer on the screen as dark or light carrets */void display_bits(unsigned char row, unsigned char col, unsigned char attribute, sos_ui32_t integer){ int i; /* Scan each bit of the integer, MSb first */ for (i = 31 ; i >= 0 ; i--) { /* Test if bit i of 'integer' is set */ int bit_i = (integer & (1 << i)); /* Ascii 219 => dark carret, Ascii 177 => light carret */ unsigned char ascii_code = bit_i?219:177; sos_x86_videomem_putchar(row, col++, attribute, ascii_code); }}/* Clock IRQ handler */static void clk_it(int intid){ static sos_ui32_t clock_count = 0; display_bits(0, 48, SOS_X86_VIDEO_FG_LTGREEN | SOS_X86_VIDEO_BG_BLUE, clock_count); clock_count++; /* Execute the expired timeout actions (if any) */ sos_time_do_tick(); /* Update scheduler statistics and status */ sos_sched_do_timer_tick();}/* ====================================================================== * Page fault exception handling *//* Page fault exception handler with demand paging for the kernel */static void pgflt_ex(int intid, struct sos_cpu_state *ctxt){ static sos_ui32_t demand_paging_count = 0; struct sos_thread * cur_thr = sos_thread_get_current(); sos_vaddr_t faulting_vaddr = sos_cpu_context_get_EX_faulting_vaddr(ctxt); sos_paddr_t ppage_paddr; if (sos_cpu_context_is_in_user_mode(ctxt) || (cur_thr->fixup_uaccess.return_vaddr)) { __label__ unforce_address_space; sos_bool_t need_to_setup_mmu; sos_ui32_t errcode = sos_cpu_context_get_EX_info(ctxt); /* Make sure to always stay in the interrupted thread's MMU configuration */ need_to_setup_mmu = (cur_thr->squatted_mm_context != sos_process_get_mm_context(cur_thr->process)); if (need_to_setup_mmu) sos_thread_prepare_user_space_access(NULL, 0); if (SOS_OK == sos_umem_vmm_try_resolve_page_fault(faulting_vaddr, errcode & (1 << 1), TRUE)) goto unforce_address_space; /* If the page fault occured in kernel mode, return to kernel to the fixup address */ if (! sos_cpu_context_is_in_user_mode(ctxt)) { cur_thr->fixup_uaccess.faulted_uaddr = faulting_vaddr; sos_cpu_context_set_EX_return_address(ctxt, cur_thr->fixup_uaccess.return_vaddr); goto unforce_address_space; } if (need_to_setup_mmu) sos_thread_end_user_space_access(); sos_bochs_printf("Unresolved USER page Fault at instruction 0x%x on access to address 0x%x (info=%x)!\n", sos_cpu_context_get_PC(ctxt), (unsigned)faulting_vaddr, (unsigned)sos_cpu_context_get_EX_info(ctxt)); sos_bochs_printf("Terminating User thread\n"); sos_thread_exit(); unforce_address_space: if (need_to_setup_mmu) sos_thread_end_user_space_access(); return; } /* Check if address is covered by any VMM range */ if (! sos_kmem_vmm_is_valid_vaddr(faulting_vaddr)) { /* No: The page fault is out of any kernel virtual region. For the moment, we don't handle this. */ sos_display_fatal_error("Unresolved page Fault at instruction 0x%x on access to address 0x%x (info=%x)!", sos_cpu_context_get_PC(ctxt), (unsigned)faulting_vaddr, (unsigned)sos_cpu_context_get_EX_info(ctxt)); SOS_ASSERT_FATAL(! "Got page fault (note: demand paging is disabled)"); } /* * Demand paging in kernel space */ /* Update the number of demand paging requests handled */ demand_paging_count ++; display_bits(0, 0, SOS_X86_VIDEO_FG_LTRED | SOS_X86_VIDEO_BG_BLUE, demand_paging_count); /* Allocate a new page for the virtual address */ ppage_paddr = sos_physmem_ref_physpage_new(FALSE); if (! ppage_paddr) SOS_ASSERT_FATAL(! "TODO: implement swap. (Out of mem in demand paging because no swap for kernel yet !)"); SOS_ASSERT_FATAL(SOS_OK == sos_paging_map(ppage_paddr, SOS_PAGE_ALIGN_INF(faulting_vaddr), FALSE, SOS_VM_MAP_PROT_READ | SOS_VM_MAP_PROT_WRITE | SOS_VM_MAP_ATOMIC)); sos_physmem_unref_physpage(ppage_paddr); /* Ok, we can now return to interrupted context */}/* ====================================================================== * An operating system MUST always have a ready thread ! Otherwise: * what would the CPU have to execute ?! */static void idle_thread(){ sos_ui32_t idle_twiddle = 0; while (1) { /* Remove this instruction if you get an "Invalid opcode" CPU exception (old 80386 CPU) */ asm("hlt\n"); idle_twiddle ++; display_bits(0, 0, SOS_X86_VIDEO_FG_GREEN | SOS_X86_VIDEO_BG_BLUE, idle_twiddle); /* Lend the CPU to some other thread */ sos_thread_yield(); }}/* ====================================================================== * Kernel thread showing some CPU usage statistics on the console every 1s */static void stat_thread(){ while (1) { sos_ui32_t flags; sos_ui32_t load1, load5, load15; char str1[11], str5[11], str15[11]; struct sos_time t; t.sec = 1; t.nanosec = 0; sos_thread_sleep(& t); sos_disable_IRQs(flags); /* The IDLE task is EXcluded in the following computation */ sos_load_get_sload(&load1, &load5, &load15); sos_load_to_string(str1, load1); sos_load_to_string(str5, load5); sos_load_to_string(str15, load15); sos_x86_videomem_printf(16, 34, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE, "Kernel (- Idle): %s %s %s ", str1, str5, str15); sos_load_get_uload(&load1, &load5, &load15); sos_load_to_string(str1, load1); sos_load_to_string(str5, load5); sos_load_to_string(str15, load15); sos_x86_videomem_printf(17, 34, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE, "User: %s %s %s ", str1, str5, str15); sos_load_get_uratio(&load1, &load5, &load15); sos_load_to_string(str1, load1); sos_load_to_string(str5, load5); sos_load_to_string(str15, load15); sos_x86_videomem_printf(18, 34, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE, "User CPU %%: %s %s %s ", str1, str5, str15); /* The IDLE task is INcluded in the following computation */ sos_load_get_sratio(&load1, &load5, &load15); sos_load_to_string(str1, load1); sos_load_to_string(str5, load5); sos_load_to_string(str15, load15); sos_x86_videomem_printf(19, 34, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE, "Kernel CPU %% (+ Idle): %s %s %s ", str1, str5, str15); sos_restore_IRQs(flags); }}/* ====================================================================== * Start the "init" (userland) process */static sos_ret_tstart_init(struct sos_fs_manager_instance * rootfs){ sos_ret_t retval; struct sos_umem_vmm_as *as_init; struct sos_process *proc_init; struct sos_thread *new_thr; sos_uaddr_t ustack, start_uaddr; struct sos_fs_opened_file * init_root, * init_cwd, * unused_of; /* Create the new process */ proc_init = sos_process_create("init", FALSE); if (! proc_init) return -SOS_ENOMEM; as_init = sos_process_get_address_space(proc_init);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -