Merge branch 'master' of github.com:Minep/lunaix-os
authorMinep <zelong56@gmail.com>
Fri, 10 Jun 2022 21:43:01 +0000 (22:43 +0100)
committerMinep <zelong56@gmail.com>
Fri, 10 Jun 2022 21:43:01 +0000 (22:43 +0100)
12 files changed:
lunaix-os/.clang-format [new file with mode: 0644]
lunaix-os/README.md [new file with mode: 0644]
lunaix-os/includes/lunaix/lunistd.h
lunaix-os/includes/lunaix/syscall.h
lunaix-os/kernel/asm/x86/pfault.c
lunaix-os/kernel/asm/x86/prologue.S
lunaix-os/kernel/k_init.c
lunaix-os/kernel/lxinit.c
lunaix-os/kernel/proc0.c [new file with mode: 0644]
lunaix-os/kernel/process.c
lunaix-os/kernel/sched.c
lunaix-os/link/linker.ld

diff --git a/lunaix-os/.clang-format b/lunaix-os/.clang-format
new file mode 100644 (file)
index 0000000..a429ba1
--- /dev/null
@@ -0,0 +1,137 @@
+---
+Language:        Cpp
+# BasedOnStyle:  Mozilla
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveMacros: false
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: Right
+AlignOperands:   true
+AlignTrailingComments: true
+AllowAllArgumentsOnNextLine: true
+AllowAllConstructorInitializersOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: Never
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortLambdasOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: TopLevel
+AlwaysBreakAfterReturnType: TopLevel
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: Yes
+BinPackArguments: false
+BinPackParameters: false
+BraceWrapping:
+  AfterCaseLabel:  false
+  AfterClass:      true
+  AfterControlStatement: false
+  AfterEnum:       true
+  AfterFunction:   true
+  AfterNamespace:  false
+  AfterObjCDeclaration: false
+  AfterStruct:     true
+  AfterUnion:      true
+  AfterExternBlock: true
+  BeforeCatch:     false
+  BeforeElse:      false
+  IndentBraces:    false
+  SplitEmptyFunction: true
+  SplitEmptyRecord: false
+  SplitEmptyNamespace: true
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Mozilla
+BreakBeforeInheritanceComma: false
+BreakInheritanceList: BeforeComma
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeComma
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit:     80
+CommentPragmas:  '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 2
+ContinuationIndentWidth: 2
+Cpp11BracedListStyle: false
+DeriveLineEnding: true
+DerivePointerAlignment: false
+DisableFormat:   false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: false
+ForEachMacros:
+  - foreach
+  - Q_FOREACH
+  - BOOST_FOREACH
+IncludeBlocks:   Preserve
+IncludeCategories:
+  - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
+    Priority:        2
+    SortPriority:    0
+  - Regex:           '^(<|"(gtest|gmock|isl|json)/)'
+    Priority:        3
+    SortPriority:    0
+  - Regex:           '.*'
+    Priority:        1
+    SortPriority:    0
+IncludeIsMainRegex: '(Test)?$'
+IncludeIsMainSourceRegex: ''
+IndentCaseLabels: true
+IndentGotoLabels: true
+IndentPPDirectives: None
+IndentWidth:     4
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd:   ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBinPackProtocolList: Auto
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: true
+ObjCSpaceBeforeProtocolList: false
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 200
+PointerAlignment: Left
+ReflowComments:  true
+SortIncludes:    true
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: false
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatements
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyBlock: false
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles:  false
+SpacesInConditionalStatement: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+SpaceBeforeSquareBrackets: false
+Standard:        Latest
+StatementMacros:
+  - Q_UNUSED
+  - QT_REQUIRE_VERSION
+TabWidth:        8
+UseCRLF:         false
+UseTab:          Never
+...
+
diff --git a/lunaix-os/README.md b/lunaix-os/README.md
new file mode 100644 (file)
index 0000000..234ea1b
--- /dev/null
@@ -0,0 +1,18 @@
+# LunaixOS 源代码
+
+我知道这个目录结构看起来相当的劝退。特别是并没有像初代Linux那种一个文件夹里就只是一堆文件的简单朴素。但至少,就我而言,把结构细分一点儿总是好的。
+
+## 目录结构
+
++ `arch` 平台相关代码,LunaixOS的内核引导就在这里。
++ `hal`  硬件抽象层,存放主板相关的代码,提供了一些访问主板功能(比如CPU,计时器)的抽象
++ `includes`  所有头文件
++ `kernel` 这里就是内核了
+  + `asm` 共内核使用的,且平台相关的代码。
+  + `ds` 提供一些基本的数据结构支持。
+  + `mm` 各类内存管理器。
+  + `peripheral` 外部设备驱动(如键盘)。
+  + `time` 为内核提供基本的时间,计时服务。
+  + `tty` 提供基本的显存操作服务。
++ `lib` 一些内核使用的运行时库,主要提供是内核模式下的一些C标准库里的实现。
++ `link` 链接器脚本
\ No newline at end of file
index a7ac03b63a269c0b3ab08dbebc0415867a20873c..fc1a535cd02751916600a0792e10446a03de01da 100644 (file)
@@ -8,7 +8,7 @@ __LXSYSCALL(pid_t, fork)
 
 __LXSYSCALL1(int, sbrk, void*, addr)
 
-__LXSYSCALL1(void*, brk, size_t, size)
+__LXSYSCALL1(void*, brk, unsigned long, size)
 
 __LXSYSCALL(pid_t, getpid)
 
index 7faa7ded58f2fd3eff9e443c3cb88c870a8973d2..dc61f64fc0e656f4aa942127d24e0243578f877f 100644 (file)
@@ -3,27 +3,26 @@
 
 #include <arch/x86/vectors.h>
 
-#define __SYSCALL_fork    1
-#define __SYSCALL_yield   2
-#define __SYSCALL_sbrk    3
-#define __SYSCALL_brk     4
-#define __SYSCALL_getpid     5
-#define __SYSCALL_getppid    6
-#define __SYSCALL_sleep    7
-#define __SYSCALL__exit    8
-#define __SYSCALL_wait    9
-
-#define __SYSCALL_MAX     0x100
+#define __SYSCALL_fork 1
+#define __SYSCALL_yield 2
+#define __SYSCALL_sbrk 3
+#define __SYSCALL_brk 4
+#define __SYSCALL_getpid 5
+#define __SYSCALL_getppid 6
+#define __SYSCALL_sleep 7
+#define __SYSCALL__exit 8
+#define __SYSCALL_wait 9
+
+#define __SYSCALL_MAX 0x100
 
 #ifndef __ASM__
-void syscall_install();
-
-static void* syscall(unsigned int callcode) {
-    asm volatile(
-        "int %0"
-        ::"i"(LUNAIX_SYS_CALL), "D"(callcode)
-        :"eax"
-    );
+void
+syscall_install();
+
+static void*
+syscall(unsigned int callcode)
+{
+    asm volatile("int %0" ::"i"(LUNAIX_SYS_CALL), "D"(callcode) : "eax");
 }
 
 #define asmlinkage __attribute__((regparm(0)))
@@ -35,57 +34,58 @@ static void* syscall(unsigned int callcode) {
 #define __PARAM_MAP5(t1, p1, ...) t1 p1, __PARAM_MAP4(__VA_ARGS__)
 #define __PARAM_MAP6(t1, p1, ...) t1 p1, __PARAM_MAP5(__VA_ARGS__)
 
-#define ___DOINT33(callcode, rettype)\
-    int v;    \
-    asm volatile (  \
-        "int %1\n"    \
-        :"=a"(v)    \
-        :"i"(LUNAIX_SYS_CALL), "a"(callcode));  \
-    return (rettype)v;     \
+#define ___DOINT33(callcode, rettype)                                          \
+    int v;                                                                     \
+    asm volatile("int %1\n" : "=a"(v) : "i"(LUNAIX_SYS_CALL), "a"(callcode));  \
+    return (rettype)v;
 
-#define __DEFINE_LXSYSCALL(rettype, name) \
-    asmlinkage rettype __lxsys_##name()
+#define __DEFINE_LXSYSCALL(rettype, name) asmlinkage rettype __lxsys_##name()
 
-#define __DEFINE_LXSYSCALL1(rettype, name, t1, p1) \
+#define __DEFINE_LXSYSCALL1(rettype, name, t1, p1)                             \
     asmlinkage rettype __lxsys_##name(__PARAM_MAP1(t1, p1))
 
-#define __DEFINE_LXSYSCALL2(rettype, name, t1, p1, t2, p2) \
+#define __DEFINE_LXSYSCALL2(rettype, name, t1, p1, t2, p2)                     \
     asmlinkage rettype __lxsys_##name(__PARAM_MAP2(t1, p1, t2, p2))
 
-#define __DEFINE_LXSYSCALL3(rettype, name, t1, p1, t2, p2, t3, p3) \
+#define __DEFINE_LXSYSCALL3(rettype, name, t1, p1, t2, p2, t3, p3)             \
     asmlinkage rettype __lxsys_##name(__PARAM_MAP3(t1, p1, t2, p2, t3, p3));
 
-#define __DEFINE_LXSYSCALL4(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4) \
-    asmlinkage rettype __lxsys_##nam (__PARAM_MAP4(t1, p1, t2, p2, t3, p3, t4, p4))
-
+#define __DEFINE_LXSYSCALL4(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4)     \
+    asmlinkage rettype __lxsys_##nam(                                          \
+      __PARAM_MAP4(t1, p1, t2, p2, t3, p3, t4, p4))
 
-#define __LXSYSCALL(rettype, name) \
-    rettype name () { \
-        ___DOINT33(__SYSCALL_##name, rettype) \
+#define __LXSYSCALL(rettype, name)                                             \
+    static rettype name()                                                      \
+    {                                                                          \
+        ___DOINT33(__SYSCALL_##name, rettype)                                  \
     }
 
-#define __LXSYSCALL1(rettype, name, t1, p1) \
-    rettype name (__PARAM_MAP1(t1, p1)) { \
-        asm (""::"b"(p1)); \
-        ___DOINT33(__SYSCALL_##name, rettype) \
+#define __LXSYSCALL1(rettype, name, t1, p1)                                    \
+    static rettype name(__PARAM_MAP1(t1, p1))                                  \
+    {                                                                          \
+        asm("" ::"b"(p1));                                                     \
+        ___DOINT33(__SYSCALL_##name, rettype)                                  \
     }
 
-#define __LXSYSCALL2(rettype, name, t1, p1, t2, p2) \
-    rettype name (__PARAM_MAP2(t1, p1, t2, p2)) { \
-        asm ("\n"::"b"(p1), "c"(p2)); \
-        ___DOINT33(__SYSCALL_##name, rettype) \
+#define __LXSYSCALL2(rettype, name, t1, p1, t2, p2)                            \
+    static rettype name(__PARAM_MAP2(t1, p1, t2, p2))                          \
+    {                                                                          \
+        asm("\n" ::"b"(p1), "c"(p2));                                          \
+        ___DOINT33(__SYSCALL_##name, rettype)                                  \
     }
 
-#define __LXSYSCALL3(rettype, name, t1, p1, t2, p2, t3, p3) \
-    rettype name (__PARAM_MAP3(t1, p1, t2, p2, t3, p3)) { \
-        asm ("\n"::"b"(p1), "c"(p2), "d"(p3)); \
-        ___DOINT33(__SYSCALL_##name, rettype) \
+#define __LXSYSCALL3(rettype, name, t1, p1, t2, p2, t3, p3)                    \
+    static rettype name(__PARAM_MAP3(t1, p1, t2, p2, t3, p3))                  \
+    {                                                                          \
+        asm("\n" ::"b"(p1), "c"(p2), "d"(p3));                                 \
+        ___DOINT33(__SYSCALL_##name, rettype)                                  \
     }
 
-#define __LXSYSCALL4(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4) \
-    rettype name (__PARAM_MAP3(t1, p1, t2, p2, t3, p3, t4, p4)) { \
-        asm ("\n"::"b"(p1), "c"(p2), "d"(p3), "D"(p4)); \
-        ___DOINT33(__SYSCALL_##name, rettype) \
+#define __LXSYSCALL4(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4)            \
+    static rettype name(__PARAM_MAP3(t1, p1, t2, p2, t3, p3, t4, p4))          \
+    {                                                                          \
+        asm("\n" ::"b"(p1), "c"(p2), "d"(p3), "D"(p4));                        \
+        ___DOINT33(__SYSCALL_##name, rettype)                                  \
     }
 #endif
 #endif /* __LUNAIX_SYSCALL_H */
index c16385a892c05a487b50465fbbbcea48112be00a..9d5e1d1bdbe2bc10fab8514bec0fe71f6b915bb7 100644 (file)
@@ -1,19 +1,27 @@
 #include <arch/x86/interrupts.h>
-#include <lunaix/mm/pmm.h>
+#include <lunaix/common.h>
 #include <lunaix/mm/mm.h>
+#include <lunaix/mm/pmm.h>
 #include <lunaix/mm/region.h>
 #include <lunaix/mm/vmm.h>
-#include <lunaix/common.h>
-#include <lunaix/syslog.h>
-#include <lunaix/status.h>
 #include <lunaix/sched.h>
+#include <lunaix/status.h>
+#include <lunaix/syslog.h>
 
-static void kprintf(const char* fmt, ...) { va_list args; va_start(args, fmt); __kprintf("PFAULT", fmt, args); va_end(args); }
+static void
+kprintf(const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    __kprintf("PFAULT", fmt, args);
+    va_end(args);
+}
 
-extern void __print_panic_msg(const char* msg, const isr_param* param);
+extern void
+__print_panic_msg(const char* msg, const isr_param* param);
 
 void
-intr_routine_page_fault (const isr_param* param) 
+intr_routine_page_fault(const isr_param* param)
 {
     uintptr_t ptr = cpu_rcr2();
     if (!ptr) {
@@ -27,18 +35,17 @@ intr_routine_page_fault (const isr_param* param)
         goto segv_term;
     }
 
-    // if (param->eip == ptr && !(hit_region->attr & REGION_EXEC)) {
-    //     goto segv_term;
-    // }
-
-    x86_pte_t* pte = CURPROC_PTE(ptr >> 12);
+    x86_pte_t* pte = PTE_MOUNTED(PD_REFERENCED, ptr >> 12);
     if (*pte & PG_PRESENT) {
-        if ((hit_region->attr & REGION_PERM_MASK) == (REGION_RSHARED | REGION_READ)) {
+        if ((hit_region->attr & REGION_PERM_MASK) ==
+            (REGION_RSHARED | REGION_READ)) {
             // normal page fault, do COW
-                uintptr_t pa = (uintptr_t)vmm_dup_page(__current->pid, PG_ENTRY_ADDR(*pte));
-                pmm_free_page(__current->pid, *pte & ~0xFFF);
-                *pte = (*pte & 0xFFF) | pa | PG_WRITE;
-                return;
+            cpu_invplg(pte);
+            uintptr_t pa =
+              (uintptr_t)vmm_dup_page(__current->pid, PG_ENTRY_ADDR(*pte));
+            pmm_free_page(__current->pid, *pte & ~0xFFF);
+            *pte = (*pte & 0xFFF) | pa | PG_WRITE;
+            return;
         }
         // impossible cases or accessing privileged page
         goto segv_term;
@@ -49,18 +56,25 @@ intr_routine_page_fault (const isr_param* param)
         goto segv_term;
     }
     uintptr_t loc = *pte & ~0xfff;
-    // a writable page, not present, pte attr is not null and no indication of cached page -> a new page need to be alloc
+    // a writable page, not present, pte attr is not null
+    //   and no indication of cached page -> a new page need to be alloc
     if ((hit_region->attr & REGION_WRITE) && (*pte & 0xfff) && !loc) {
+        cpu_invplg(pte);
         uintptr_t pa = pmm_alloc_page(__current->pid, 0);
         *pte = *pte | pa | PG_PRESENT;
         return;
     }
     // page not present, bring it from disk or somewhere else
     __print_panic_msg("WIP page fault route", param);
-    while (1);
+    while (1)
+        ;
 
 segv_term:
-    kprintf(KERROR "(pid: %d) Segmentation fault on %p (%p:%p)\n", __current->pid, ptr, param->cs, param->eip);
+    kprintf(KERROR "(pid: %d) Segmentation fault on %p (%p:%p)\n",
+            __current->pid,
+            ptr,
+            param->cs,
+            param->eip);
     terminate_proc(LXSEGFAULT);
     // should not reach
 }
\ No newline at end of file
index ef559bbdd9398fd87236de5f3c1d8935be5b8f0f..6cdab40490e2c0e08a524412ca6021d1f6f4d812 100644 (file)
 
         call _kernel_init
 
-        movl $KSTACK_TOP, %esp
-
-        call _kernel_post_init
-
     1:
         hlt
         jmp 1b
\ No newline at end of file
index 863f57496a9244bd4f7b4a910cd19d8142e82fbf..eee475fc604d0dbb7786c174a7bd530df1368ca9 100644 (file)
@@ -1,23 +1,18 @@
 #include <lunaix/common.h>
 #include <lunaix/tty/tty.h>
 
+#include <lunaix/clock.h>
+#include <lunaix/mm/kalloc.h>
 #include <lunaix/mm/page.h>
 #include <lunaix/mm/pmm.h>
 #include <lunaix/mm/vmm.h>
-#include <lunaix/mm/kalloc.h>
+#include <lunaix/process.h>
+#include <lunaix/sched.h>
 #include <lunaix/spike.h>
 #include <lunaix/syslog.h>
 #include <lunaix/timer.h>
-#include <lunaix/clock.h>
-#include <lunaix/peripheral/ps2kbd.h>
-#include <lunaix/process.h>
-#include <lunaix/sched.h>
-#include <lunaix/syscall.h>
 
 #include <hal/rtc.h>
-#include <hal/apic.h>
-#include <hal/ioapic.h>
-#include <hal/acpi/acpi.h>
 
 #include <arch/x86/boot/multiboot.h>
 #include <arch/x86/idt.h>
@@ -26,9 +21,8 @@
 #include <klibc/stdio.h>
 #include <klibc/string.h>
 
-#include <stdint.h>
 #include <stddef.h>
-
+#include <stdint.h>
 
 extern uint8_t __kernel_start;
 extern uint8_t __kernel_end;
@@ -45,18 +39,18 @@ struct proc_info tmp;
 
 LOG_MODULE("BOOT");
 
-extern void _lxinit_main();
-void spawn_lxinit();
-void _kernel_post_init();
+extern void
+__proc0(); /* proc0.c */
 
 void
-setup_memory(multiboot_memory_map_t* map, size_t map_size);
+spawn_proc0();
 
 void
-lock_reserved_memory();
+setup_memory(multiboot_memory_map_t* map, size_t map_size);
 
 void
-_kernel_pre_init() {
+_kernel_pre_init()
+{
     _init_idt();
     intr_routine_init();
 
@@ -69,153 +63,126 @@ _kernel_pre_init() {
 
     __kernel_ptd = cpu_rcr3();
 
-    tmp = (struct proc_info) {
-        .page_table = __kernel_ptd
-    };
+    tmp = (struct proc_info){ .page_table = __kernel_ptd };
 
     __current = &tmp;
 }
 
 void
-_kernel_init() {
+_kernel_init()
+{
     kprintf("[MM] Mem: %d KiB, Extended Mem: %d KiB\n",
-           _k_init_mb_info->mem_lower,
-           _k_init_mb_info->mem_upper);
+            _k_init_mb_info->mem_lower,
+            _k_init_mb_info->mem_upper);
+
+    unsigned int map_size =
+      _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t);
 
-    unsigned int map_size = _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t);
-    
     setup_memory((multiboot_memory_map_t*)_k_init_mb_info->mmap_addr, map_size);
 
     // 为内核创建一个专属栈空间。
     for (size_t i = 0; i < (KSTACK_SIZE >> PG_SIZE_BITS); i++) {
-        vmm_alloc_page(KERNEL_PID, (void*)(KSTACK_START + (i << PG_SIZE_BITS)), NULL, PG_PREM_RW, 0);
+        vmm_alloc_page(KERNEL_PID,
+                       (void*)(KSTACK_START + (i << PG_SIZE_BITS)),
+                       NULL,
+                       PG_PREM_RW,
+                       0);
     }
-    kprintf(KINFO "[MM] Allocated %d pages for stack start at %p\n", KSTACK_SIZE>>PG_SIZE_BITS, KSTACK_START);
+    kprintf(KINFO "[MM] Allocated %d pages for stack start at %p\n",
+            KSTACK_SIZE >> PG_SIZE_BITS,
+            KSTACK_START);
 
     sched_init();
+
+    spawn_proc0();
 }
 
 /**
- * @brief 创建并运行init进程
- * 
+ * @brief 创建并运行proc0进程
+ *
  */
-void spawn_lxinit() {
-    struct proc_info kinit;
-
-    init_proc(&kinit);
-    kinit.intr_ctx = (isr_param) {
-        .registers.esp = KSTACK_TOP - 20,
-        .cs = KCODE_SEG,
-        .eip = (void*)_lxinit_main,
-        .ss = KDATA_SEG,
-        .eflags = cpu_reflags()
-    };
-
-    setup_proc_mem(&kinit, PD_REFERENCED);
-
-    // Ok... 准备fork进我们的init进程
+void
+spawn_proc0()
+{
+    struct proc_info proc0;
+
+    /**
+     * @brief
+     * 注意:这里和视频中说的不一样,属于我之后的一点微调。
+     * 在视频中,spawn_proc0是在_kernel_post_init的末尾才调用的。并且是直接跳转到_proc0
+     *
+     * 但是我后来发现,上述的方法会产生竞态条件。这是因为spawn_proc0被调用的时候,时钟中断已经开启,
+     * 而中断的产生会打乱栈的布局,从而使得下面的上下文设置代码产生未定义行为(Undefined
+     * Behaviour)。 为了保险起见,有两种办法:
+     *      1. 在创建proc0进程前关闭中断
+     *      2. 将_kernel_post_init搬进proc0进程
+     * (_kernel_post_init已经更名为init_platform)
+     *
+     * 目前的解决方案是两者都使用
+     */
+
+    init_proc(&proc0);
+    proc0.intr_ctx = (isr_param){ .registers.esp = KSTACK_TOP - 20,
+                                  .cs = KCODE_SEG,
+                                  .eip = (void*)__proc0,
+                                  .ss = KDATA_SEG,
+                                  .eflags = cpu_reflags() };
+
+    // 必须在读取eflags之后禁用。否则当进程被调度时,中断依然是关闭的!
+    cpu_disable_interrupt();
+    setup_proc_mem(&proc0, PD_REFERENCED);
+
+    // Ok... 首先fork进我们的零号进程,而后由那里,我们fork进init进程。
     /*
         这里是一些栈的设置,因为我们将切换到一个新的地址空间里,并且使用一个全新的栈。
         让iret满意!
     */
-    asm volatile(
-        "movl %%cr3, %%eax\n"
-        "movl %%esp, %%ebx\n"
-        "movl %0, %%cr3\n"
-        "movl %1, %%esp\n"
-        "pushf\n"
-        "pushl %2\n"
-        "pushl %3\n"
-        "pushl $0\n"
-        "pushl $0\n"
-        "movl %%eax, %%cr3\n"
-        "movl %%ebx, %%esp\n"
-        ::"r"(kinit.page_table), "i"(KSTACK_TOP), "i"(KCODE_SEG), "r"(kinit.intr_ctx.eip)
-        :"%eax", "%ebx", "memory"
-    );
-
-    // 向调度器注册进程,然后这里阻塞等待调度器调度就好了。
-    push_process(&kinit);
-
-}
-
-void 
-_kernel_post_init() {
-    assert_msg(kalloc_init(), "Fail to initialize heap");
-    
-    size_t hhk_init_pg_count = ((uintptr_t)(&__init_hhk_end)) >> PG_SIZE_BITS;
-    kprintf(KINFO "[MM] Releaseing %d pages from 0x0.\n", hhk_init_pg_count);
-
-    // Fuck it, I will no longer bother this little 1MiB
-    // I just release 4 pages for my APIC & IOAPIC remappings
-    for (size_t i = 0; i < 3; i++) {
-        vmm_unmap_page(KERNEL_PID, (void*)(i << PG_SIZE_BITS));
-    }
-    
-    // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射
-    lock_reserved_memory();
-
-    acpi_init(_k_init_mb_info);
-    uintptr_t ioapic_addr = acpi_get_context()->madt.ioapic->ioapic_addr;
-    pmm_mark_page_occupied(KERNEL_PID, FLOOR(__APIC_BASE_PADDR, PG_SIZE_BITS), 0);
-    pmm_mark_page_occupied(KERNEL_PID, FLOOR(ioapic_addr, PG_SIZE_BITS), 0);
-
-    vmm_set_mapping(KERNEL_PID, APIC_BASE_VADDR, __APIC_BASE_PADDR, PG_PREM_RW);
-    vmm_set_mapping(KERNEL_PID, IOAPIC_BASE_VADDR, ioapic_addr, PG_PREM_RW);
-
-    apic_init();
-    ioapic_init();
-    timer_init(SYS_TIMER_FREQUENCY_HZ);
-    clock_init();
-    ps2_kbd_init();
-
-    syscall_install();
-
-    for (size_t i = 256; i < hhk_init_pg_count; i++) {
-        vmm_unmap_page(KERNEL_PID, (void*)(i << PG_SIZE_BITS));
-    }
-
-    spawn_lxinit();
-
-    spin();
-}
-
-void
-lock_reserved_memory() {
-    multiboot_memory_map_t* mmaps = _k_init_mb_info->mmap_addr;
-    size_t map_size = _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t);
-    for (unsigned int i = 0; i < map_size; i++) {
-        multiboot_memory_map_t mmap = mmaps[i];
-        if (mmap.type == MULTIBOOT_MEMORY_AVAILABLE) {
-            continue;
-        }
-        uint8_t* pa = PG_ALIGN(mmap.addr_low);
-        size_t pg_num = CEIL(mmap.len_low, PG_SIZE_BITS);
-        for (size_t j = 0; j < pg_num; j++)
-        {
-            vmm_set_mapping(KERNEL_PID, (pa + (j << PG_SIZE_BITS)), (pa + (j << PG_SIZE_BITS)), PG_PREM_R);
-        }
-    }
+    asm volatile("movl %%cr3, %%eax\n"
+                 "movl %%esp, %%ebx\n"
+                 "movl %0, %%cr3\n"
+                 "movl %1, %%esp\n"
+                 "pushf\n"
+                 "pushl %2\n"
+                 "pushl %3\n"
+                 "pushl $0\n"
+                 "pushl $0\n"
+                 "movl %%eax, %%cr3\n"
+                 "movl %%ebx, %%esp\n" ::"r"(proc0.page_table),
+                 "i"(KSTACK_TOP),
+                 "i"(KCODE_SEG),
+                 "r"(proc0.intr_ctx.eip)
+                 : "%eax", "%ebx", "memory");
+
+    // 向调度器注册进程。
+    push_process(&proc0);
+
+    // 由于时钟中断未就绪,我们需要手动通知调度器进行第一次调度。这里也会同时隐式地恢复我们的eflags.IF位
+    schedule();
+
+    /* Should not return */
+    assert_msg(0, "Unexpected Return");
 }
 
 // 按照 Memory map 标识可用的物理页
 void
-setup_memory(multiboot_memory_map_t* map, size_t map_size) {
+setup_memory(multiboot_memory_map_t* map, size_t map_size)
+{
 
     // First pass, to mark the physical pages
     for (unsigned int i = 0; i < map_size; i++) {
         multiboot_memory_map_t mmap = map[i];
         kprintf("[MM] Base: 0x%x, len: %u KiB, type: %u\n",
-               map[i].addr_low,
-               map[i].len_low >> 10,
-               map[i].type);
+                map[i].addr_low,
+                map[i].len_low >> 10,
+                map[i].type);
         if (mmap.type == MULTIBOOT_MEMORY_AVAILABLE) {
             // 整数向上取整除法
             uintptr_t pg = map[i].addr_low + 0x0fffU;
-            pmm_mark_chunk_free(pg >> PG_SIZE_BITS, map[i].len_low >> PG_SIZE_BITS);
+            pmm_mark_chunk_free(pg >> PG_SIZE_BITS,
+                                map[i].len_low >> PG_SIZE_BITS);
             kprintf(KINFO "[MM] Freed %u pages start from 0x%x\n",
-                   map[i].len_low >> PG_SIZE_BITS,
-                   pg & ~0x0fffU);
+                    map[i].len_low >> PG_SIZE_BITS,
+                    pg & ~0x0fffU);
         }
     }
 
@@ -224,25 +191,22 @@ setup_memory(multiboot_memory_map_t* map, size_t map_size) {
     pmm_mark_chunk_occupied(KERNEL_PID, 0, pg_count, 0);
     kprintf(KINFO "[MM] Allocated %d pages for kernel.\n", pg_count);
 
-
     size_t vga_buf_pgs = VGA_BUFFER_SIZE >> PG_SIZE_BITS;
-    
+
     // 首先,标记VGA部分为已占用
-    pmm_mark_chunk_occupied(KERNEL_PID, VGA_BUFFER_PADDR >> PG_SIZE_BITS, vga_buf_pgs, 0);
-    
+    pmm_mark_chunk_occupied(
+      KERNEL_PID, VGA_BUFFER_PADDR >> PG_SIZE_BITS, vga_buf_pgs, 0);
+
     // 重映射VGA文本缓冲区(以后会变成显存,i.e., framebuffer)
-    for (size_t i = 0; i < vga_buf_pgs; i++)
-    {
-        vmm_map_page(
-            KERNEL_PID,
-            (void*)(VGA_BUFFER_VADDR + (i << PG_SIZE_BITS)), 
-            (void*)(VGA_BUFFER_PADDR + (i << PG_SIZE_BITS)), 
-            PG_PREM_URW
-        );
+    for (size_t i = 0; i < vga_buf_pgs; i++) {
+        vmm_map_page(KERNEL_PID,
+                     (void*)(VGA_BUFFER_VADDR + (i << PG_SIZE_BITS)),
+                     (void*)(VGA_BUFFER_PADDR + (i << PG_SIZE_BITS)),
+                     PG_PREM_URW);
     }
-    
+
     // 更新VGA缓冲区位置至虚拟地址
     tty_set_buffer((void*)VGA_BUFFER_VADDR);
 
     kprintf(KINFO "[MM] Mapped VGA to %p.\n", VGA_BUFFER_VADDR);
-}
\ No newline at end of file
+}
index e6ca67bf05febd3aa36cfb934eb0b6c5fa87f923..d951a9fc6f5e553f108d9d3d5b36703b3f4195df 100644 (file)
@@ -1,14 +1,14 @@
 #include <hal/cpu.h>
-#include <lunaix/syslog.h>
+#include <lunaix/clock.h>
+#include <lunaix/keyboard.h>
+#include <lunaix/lunistd.h>
 #include <lunaix/mm/kalloc.h>
 #include <lunaix/mm/vmm.h>
+#include <lunaix/proc.h>
 #include <lunaix/spike.h>
-#include <lunaix/clock.h>
+#include <lunaix/syslog.h>
 #include <lunaix/timer.h>
-#include <lunaix/keyboard.h>
 #include <lunaix/tty/tty.h>
-#include <lunaix/lunistd.h>
-#include <lunaix/proc.h>
 
 extern uint8_t __kernel_start;
 
@@ -25,7 +25,7 @@ _lxinit_main()
     for (;;) {
         pid_t p;
         if ((p = fork())) {
-            kprintf(KDEBUG "Forked %d\n", p);
+            kprintf(KDEBUG "Pinkie Pie #%d: FUN!\n", p);
         }
     }
 #endif
@@ -41,19 +41,21 @@ _lxinit_main()
     }
     int status;
     pid_t child = wait(&status);
-    kprintf("I am parent, my child (%d) terminated with code: %d.\n", child, status);
+    kprintf(
+      "I am parent, my child (%d) terminated with code: %d.\n", child, status);
 #endif
-    
+
+    sleep(5);
+
     // 这里是就是LunaixOS的第一个进程了!
-    for (size_t i = 0; i < 10; i++)
-    {
+    for (size_t i = 0; i < 10; i++) {
         pid_t pid = 0;
         if (!(pid = fork())) {
             sleep(i);
             if (i == 3) {
-                i = *(int*)0xdeadc0de;    // seg fault!
+                i = *(int*)0xdeadc0de; // seg fault!
             }
-            tty_put_char('0'+i);
+            tty_put_char('0' + i);
             tty_put_char('\n');
             _exit(0);
         }
@@ -67,22 +69,22 @@ _lxinit_main()
     cpu_get_brand(buf);
     kprintf("CPU: %s\n\n", buf);
 
-    // no lxmalloc here! This can only be used within kernel, but here, we are in a dedicated process!
-    // any access to kernel method must be done via syscall
+    // no lxmalloc here! This can only be used within kernel, but here, we are
+    // in a dedicated process! any access to kernel method must be done via
+    // syscall
 
     struct kdb_keyinfo_pkt keyevent;
-    while (1)
-    {
+    while (1) {
         if (!kbd_recv_key(&keyevent)) {
             // yield();
             continue;
         }
-        if ((keyevent.state & KBD_KEY_FPRESSED) && (keyevent.keycode & 0xff00) <= KEYPAD) {
+        if ((keyevent.state & KBD_KEY_FPRESSED) &&
+            (keyevent.keycode & 0xff00) <= KEYPAD) {
             tty_put_char((char)(keyevent.keycode & 0x00ff));
             tty_sync_cursor();
         }
     }
-    
 
     spin();
 }
\ No newline at end of file
diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c
new file mode 100644 (file)
index 0000000..a2102ae
--- /dev/null
@@ -0,0 +1,109 @@
+#include <arch/x86/boot/multiboot.h>
+#include <lunaix/common.h>
+#include <lunaix/lunistd.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/peripheral/ps2kbd.h>
+#include <lunaix/spike.h>
+#include <lunaix/syscall.h>
+#include <lunaix/syslog.h>
+#include <stddef.h>
+
+#include <hal/acpi/acpi.h>
+#include <hal/apic.h>
+#include <hal/ioapic.h>
+
+LOG_MODULE("PROC0")
+
+extern void
+_lxinit_main(); /* lxinit.c */
+
+void
+init_platform();
+
+void
+lock_reserved_memory();
+
+/**
+ * @brief LunaixOS的零号进程,该进程永远为可执行。
+ *
+ * 这主要是为了保证调度器在没有进程可调度时依然有事可做。
+ *
+ * 同时,该进程也负责fork出我们的init进程。
+ *
+ */
+void
+__proc0()
+{
+    init_platform();
+    if (!fork()) {
+        asm("jmp _lxinit_main");
+    }
+
+    asm("1: jmp 1b");
+}
+
+extern uint8_t __kernel_start;            /* link/linker.ld */
+extern uint8_t __kernel_end;              /* link/linker.ld */
+extern uint8_t __init_hhk_end;            /* link/linker.ld */
+extern multiboot_info_t* _k_init_mb_info; /* k_init.c */
+
+void
+init_platform()
+{
+    assert_msg(kalloc_init(), "Fail to initialize heap");
+
+    size_t hhk_init_pg_count = ((uintptr_t)(&__init_hhk_end)) >> PG_SIZE_BITS;
+    kprintf(KINFO "[MM] Releaseing %d pages from 0x0.\n", hhk_init_pg_count);
+
+    // Fuck it, I will no longer bother this little 1MiB
+    // I just release 4 pages for my APIC & IOAPIC remappings
+    for (size_t i = 0; i < 3; i++) {
+        vmm_unmap_page(KERNEL_PID, (void*)(i << PG_SIZE_BITS));
+    }
+
+    // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射
+    lock_reserved_memory();
+
+    acpi_init(_k_init_mb_info);
+    uintptr_t ioapic_addr = acpi_get_context()->madt.ioapic->ioapic_addr;
+    pmm_mark_page_occupied(
+      KERNEL_PID, FLOOR(__APIC_BASE_PADDR, PG_SIZE_BITS), 0);
+    pmm_mark_page_occupied(KERNEL_PID, FLOOR(ioapic_addr, PG_SIZE_BITS), 0);
+
+    vmm_set_mapping(KERNEL_PID, APIC_BASE_VADDR, __APIC_BASE_PADDR, PG_PREM_RW);
+    vmm_set_mapping(KERNEL_PID, IOAPIC_BASE_VADDR, ioapic_addr, PG_PREM_RW);
+
+    apic_init();
+    ioapic_init();
+    timer_init(SYS_TIMER_FREQUENCY_HZ);
+    clock_init();
+    ps2_kbd_init();
+
+    syscall_install();
+
+    for (size_t i = 256; i < hhk_init_pg_count; i++) {
+        vmm_unmap_page(KERNEL_PID, (void*)(i << PG_SIZE_BITS));
+    }
+}
+
+void
+lock_reserved_memory()
+{
+    multiboot_memory_map_t* mmaps = _k_init_mb_info->mmap_addr;
+    size_t map_size =
+      _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t);
+    for (unsigned int i = 0; i < map_size; i++) {
+        multiboot_memory_map_t mmap = mmaps[i];
+        if (mmap.type == MULTIBOOT_MEMORY_AVAILABLE) {
+            continue;
+        }
+        uint8_t* pa = PG_ALIGN(mmap.addr_low);
+        size_t pg_num = CEIL(mmap.len_low, PG_SIZE_BITS);
+        for (size_t j = 0; j < pg_num; j++) {
+            vmm_set_mapping(KERNEL_PID,
+                            (pa + (j << PG_SIZE_BITS)),
+                            (pa + (j << PG_SIZE_BITS)),
+                            PG_PREM_R);
+        }
+    }
+}
\ No newline at end of file
index 5112ae19e04a7e78ddf2cc36587e5684799ff5a0..87a7413c963f0db793f22f842c5c59bdaf491e50 100644 (file)
@@ -1,34 +1,34 @@
-#include <lunaix/process.h>
-#include <lunaix/mm/vmm.h>
-#include <lunaix/mm/region.h>
+#include <klibc/string.h>
 #include <lunaix/clock.h>
-#include <lunaix/syslog.h>
 #include <lunaix/common.h>
-#include <lunaix/syscall.h>
+#include <lunaix/mm/region.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/process.h>
 #include <lunaix/spike.h>
-#include <klibc/string.h>
+#include <lunaix/syscall.h>
+#include <lunaix/syslog.h>
 
 LOG_MODULE("PROC")
 
-void* __dup_pagetable(pid_t pid, uintptr_t mount_point) {
+void*
+__dup_pagetable(pid_t pid, uintptr_t mount_point)
+{
     void* ptd_pp = pmm_alloc_page(pid, PP_FGPERSIST);
     x86_page_table* ptd = vmm_fmap_page(pid, PG_MOUNT_1, ptd_pp, PG_PREM_RW);
-    x86_page_table* pptd = (x86_page_table*) (mount_point | (0x3FF << 12));
+    x86_page_table* pptd = (x86_page_table*)(mount_point | (0x3FF << 12));
 
-    for (size_t i = 0; i < PG_MAX_ENTRIES - 1; i++)
-    {
+    for (size_t i = 0; i < PG_MAX_ENTRIES - 1; i++) {
         x86_pte_t ptde = pptd->entry[i];
         if (!ptde || !(ptde & PG_PRESENT)) {
             ptd->entry[i] = ptde;
             continue;
         }
-        
-        x86_page_table* ppt = (x86_page_table*) (mount_point | (i << 12));
+
+        x86_page_table* ppt = (x86_page_table*)(mount_point | (i << 12));
         void* pt_pp = pmm_alloc_page(pid, PP_FGPERSIST);
         x86_page_table* pt = vmm_fmap_page(pid, PG_MOUNT_2, pt_pp, PG_PREM_RW);
 
-        for (size_t j = 0; j < PG_MAX_ENTRIES; j++)
-        {
+        for (size_t j = 0; j < PG_MAX_ENTRIES; j++) {
             x86_pte_t pte = ppt->entry[j];
             pmm_ref_page(pid, PG_ENTRY_ADDR(pte));
             pt->entry[j] = pte;
@@ -36,30 +36,30 @@ void* __dup_pagetable(pid_t pid, uintptr_t mount_point) {
 
         ptd->entry[i] = (uintptr_t)pt_pp | PG_PREM_RW;
     }
-    
+
     ptd->entry[PG_MAX_ENTRIES - 1] = NEW_L1_ENTRY(T_SELF_REF_PERM, ptd_pp);
 
     return ptd_pp;
 }
 
-void __del_pagetable(pid_t pid, uintptr_t mount_point) {
-    x86_page_table* pptd = (x86_page_table*) (mount_point | (0x3FF << 12));
+void
+__del_pagetable(pid_t pid, uintptr_t mount_point)
+{
+    x86_page_table* pptd = (x86_page_table*)(mount_point | (0x3FF << 12));
 
-    for (size_t i = 0; i < PG_MAX_ENTRIES - 1; i++)
-    {
+    for (size_t i = 0; i < PG_MAX_ENTRIES - 1; i++) {
         x86_pte_t ptde = pptd->entry[i];
         if (!ptde || !(ptde & PG_PRESENT)) {
             continue;
         }
-        
-        x86_page_table* ppt = (x86_page_table*) (mount_point | (i << 12));
 
-        for (size_t j = 0; j < PG_MAX_ENTRIES; j++)
-        {
+        x86_page_table* ppt = (x86_page_table*)(mount_point | (i << 12));
+
+        for (size_t j = 0; j < PG_MAX_ENTRIES; j++) {
             x86_pte_t pte = ppt->entry[j];
             // free the 4KB data page
             if ((pte & PG_PRESENT)) {
-                pmm_free_page(pid,PG_ENTRY_ADDR(pte));
+                pmm_free_page(pid, PG_ENTRY_ADDR(pte));
             }
         }
         // free the L2 page table
@@ -69,23 +69,30 @@ void __del_pagetable(pid_t pid, uintptr_t mount_point) {
     pmm_free_page(pid, PG_ENTRY_ADDR(pptd->entry[PG_MAX_ENTRIES - 1]));
 }
 
-void* dup_pagetable(pid_t pid) {
+void*
+dup_pagetable(pid_t pid)
+{
     return __dup_pagetable(pid, PD_REFERENCED);
 }
 
-__DEFINE_LXSYSCALL(pid_t, fork) {
+__DEFINE_LXSYSCALL(pid_t, fork)
+{
     return dup_proc();
 }
 
-__DEFINE_LXSYSCALL(pid_t, getpid) {
+__DEFINE_LXSYSCALL(pid_t, getpid)
+{
     return __current->pid;
 }
 
-__DEFINE_LXSYSCALL(pid_t, getppid) {
+__DEFINE_LXSYSCALL(pid_t, getppid)
+{
     return __current->parent->pid;
 }
 
-void init_proc(struct proc_info *pcb) {
+void
+init_proc(struct proc_info* pcb)
+{
     memset(pcb, 0, sizeof(*pcb));
 
     pcb->pid = alloc_pid();
@@ -93,7 +100,9 @@ void init_proc(struct proc_info *pcb) {
     pcb->state = PROC_CREATED;
 }
 
-pid_t dup_proc() {
+pid_t
+dup_proc()
+{
     struct proc_info pcb;
     init_proc(&pcb);
     pcb.mm = __current->mm;
@@ -101,7 +110,7 @@ pid_t dup_proc() {
     pcb.parent = __current;
 
 #ifdef USE_KERNEL_PG
-    setup_proc_mem(&pcb, PD_MOUNT_1);    //挂载点#1是当前进程的页表
+    setup_proc_mem(&pcb, PD_MOUNT_1); //挂载点#1是当前进程的页表
 #else
     setup_proc_mem(&pcb, PD_REFERENCED);
 #endif
@@ -110,9 +119,11 @@ pid_t dup_proc() {
     if (!__current->mm.regions) {
         goto not_copy;
     }
-    
+
+    llist_init_head(&pcb.mm.regions);
     struct mm_region *pos, *n;
-    llist_for_each(pos, n, &__current->mm.regions->head, head) {
+    llist_for_each(pos, n, &__current->mm.regions->head, head)
+    {
         region_add(&pcb, pos->start, pos->end, pos->attr);
 
         // 如果写共享,则不作处理。
@@ -122,25 +133,23 @@ pid_t dup_proc() {
 
         uintptr_t start_vpn = PG_ALIGN(pos->start) >> 12;
         uintptr_t end_vpn = PG_ALIGN(pos->end) >> 12;
-        for (size_t i = start_vpn; i < end_vpn; i++)
-        {
-            x86_pte_t *curproc = &PTE_MOUNTED(PD_MOUNT_1, i);
-            x86_pte_t *newproc = &PTE_MOUNTED(PD_MOUNT_2, i);
-            cpu_invplg(curproc);
+        for (size_t i = start_vpn; i < end_vpn; i++) {
+            x86_pte_t* curproc = &PTE_MOUNTED(PD_MOUNT_1, i);
+            x86_pte_t* newproc = &PTE_MOUNTED(PD_MOUNT_2, i);
             cpu_invplg(newproc);
 
             if (pos->attr == REGION_RSHARED) {
                 // 如果读共享,则将两者的都标注为只读,那么任何写入都将会应用COW策略。
+                cpu_invplg(curproc);
                 *curproc = *curproc & ~PG_WRITE;
                 *newproc = *newproc & ~PG_WRITE;
-            }
-            else {
+            } else {
                 // 如果是私有页,则将该页从新进程中移除。
                 *newproc = 0;
             }
         }
     }
-    
+
 not_copy:
     vmm_unmount_pd(PD_MOUNT_2);
 
@@ -154,24 +163,26 @@ not_copy:
 
 extern void __kernel_end;
 
-void setup_proc_mem(struct proc_info* proc, uintptr_t usedMnt) {
+void
+setup_proc_mem(struct proc_info* proc, uintptr_t usedMnt)
+{
     // copy the entire kernel page table
     pid_t pid = proc->pid;
     void* pt_copy = __dup_pagetable(pid, usedMnt);
 
-    vmm_mount_pd(PD_MOUNT_2, pt_copy);   // 将新进程的页表挂载到挂载点#2
+    vmm_mount_pd(PD_MOUNT_2, pt_copy); // 将新进程的页表挂载到挂载点#2
 
     // copy the kernel stack
-    for (size_t i = KSTACK_START >> 12; i <= KSTACK_TOP >> 12; i++)
-    {
-        volatile x86_pte_t *ppte = &PTE_MOUNTED(PD_MOUNT_2, i);
+    for (size_t i = KSTACK_START >> 12; i <= KSTACK_TOP >> 12; i++) {
+        volatile x86_pte_t* ppte = &PTE_MOUNTED(PD_MOUNT_2, i);
 
         /*
-            This is a fucking nightmare, the TLB caching keep the rewrite to PTE from updating.
-            Even the Nightmare Moon the Evil is far less nasty than this.
-            It took me hours of debugging to figure this out.
+            This is a fucking nightmare, the TLB caching keep the rewrite to PTE
+           from updating. Even the Nightmare Moon the Evil is far less nasty
+           than this. It took me hours of debugging to figure this out.
 
-            In the name of Celestia our glorious goddess, I will fucking HATE the TLB for the rest of my LIFE!
+            In the name of Celestia our glorious goddess, I will fucking HATE
+           the TLB for the rest of my LIFE!
         */
         cpu_invplg(ppte);
 
@@ -182,8 +193,9 @@ void setup_proc_mem(struct proc_info* proc, uintptr_t usedMnt) {
 
     // 我们不需要分配内核的区域,因为所有的内核代码和数据段只能通过系统调用来访问,任何非法的访问
     // 都会导致eip落在区域外面,从而segmentation fault.
-    
-    // 定义用户栈区域,但是不分配实际的物理页。我们会在Page fault handler里面实现动态分配物理页的逻辑。(虚拟内存的好处!)
+
+    // 定义用户栈区域,但是不分配实际的物理页。我们会在Page fault
+    // handler里面实现动态分配物理页的逻辑。(虚拟内存的好处!)
     // FIXME: 这里应该放到spawn_proc里面。
     // region_add(proc, USTACK_END, USTACK_SIZE, REGION_PRIVATE | REGION_RW);
 
index 758b157befb68a2b48656ab90f9887067c0f4997..8f65087f8253175f0a2dd2f4f26ab34afd718a4a 100644 (file)
@@ -1,16 +1,16 @@
-#include <lunaix/process.h>
-#include <lunaix/sched.h>
-#include <lunaix/mm/vmm.h>
-#include <lunaix/mm/kalloc.h>
-#include <hal/cpu.h>
 #include <arch/x86/interrupts.h>
 #include <arch/x86/tss.h>
 #include <hal/apic.h>
+#include <hal/cpu.h>
+#include <lunaix/mm/kalloc.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/process.h>
+#include <lunaix/sched.h>
 
 #include <lunaix/spike.h>
 #include <lunaix/status.h>
-#include <lunaix/syslog.h>
 #include <lunaix/syscall.h>
+#include <lunaix/syslog.h>
 
 #define MAX_PROCESS 512
 
@@ -24,26 +24,27 @@ struct scheduler sched_ctx;
 
 LOG_MODULE("SCHED")
 
-void sched_init() {
+void
+sched_init()
+{
     size_t pg_size = ROUNDUP(sizeof(struct proc_info) * MAX_PROCESS, 0x1000);
-    assert_msg(
-        vmm_alloc_pages(KERNEL_PID, &__proc_table, pg_size, PG_PREM_RW, PP_FGPERSIST), 
-        "Fail to allocate proc table"
-    );
-    
-    sched_ctx = (struct scheduler) {
-        ._procs = (struct proc_info*) &__proc_table,
-        .ptable_len = 0,
-        .procs_index = 0
-    };
+    assert_msg(vmm_alloc_pages(
+                 KERNEL_PID, &__proc_table, pg_size, PG_PREM_RW, PP_FGPERSIST),
+               "Fail to allocate proc table");
+
+    sched_ctx = (struct scheduler){ ._procs = (struct proc_info*)&__proc_table,
+                                    .ptable_len = 0,
+                                    .procs_index = 0 };
 }
 
-void run(struct proc_info* proc) {
+void
+run(struct proc_info* proc)
+{
     if (!(__current->state & ~PROC_RUNNING)) {
         __current->state = PROC_STOPPED;
     }
     proc->state = PROC_RUNNING;
-    
+
     // FIXME: 这里还是得再考虑一下。
     // tss_update_esp(__current->intr_ctx.esp);
 
@@ -51,19 +52,20 @@ void run(struct proc_info* proc) {
         __current = proc;
         cpu_lcr3(__current->page_table);
         // from now on, the we are in the kstack of another process
-    }
-    else {
+    } else {
         __current = proc;
     }
 
     apic_done_servicing();
 
-    asm volatile (
-        "pushl %0\n"
-        "jmp soft_iret\n"::"r"(&__current->intr_ctx): "memory");
+    asm volatile("pushl %0\n"
+                 "jmp soft_iret\n" ::"r"(&__current->intr_ctx)
+                 : "memory");
 }
 
-void schedule() {
+void
+schedule()
+{
     if (!sched_ctx.ptable_len) {
         return;
     }
@@ -75,20 +77,22 @@ void schedule() {
     do {
         ptr = (ptr + 1) % sched_ctx.ptable_len;
         next = &sched_ctx._procs[ptr];
-    } while(next->state != PROC_STOPPED && ptr != prev_ptr);
-    
-    sched_ctx.procs_index = ptr;
+    } while (next->state != PROC_STOPPED && ptr != prev_ptr);
 
+    sched_ctx.procs_index = ptr;
 
     run(next);
 }
 
-static void proc_timer_callback(struct proc_info* proc) {
+static void
+proc_timer_callback(struct proc_info* proc)
+{
     proc->timer = NULL;
     proc->state = PROC_STOPPED;
 }
 
-__DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds) {
+__DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
+{
     // FIXME: sleep的实现或许需要改一下。专门绑一个计时器好像没有必要……
     if (!seconds) {
         return 0;
@@ -97,34 +101,40 @@ __DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds) {
         return __current->timer->counter / timer_context()->running_frequency;
     }
 
-    struct lx_timer* timer = timer_run_second(seconds, proc_timer_callback, __current, 0);
+    struct lx_timer* timer =
+      timer_run_second(seconds, proc_timer_callback, __current, 0);
     __current->timer = timer;
     __current->intr_ctx.registers.eax = seconds;
     __current->state = PROC_BLOCKED;
     schedule();
 }
 
-__DEFINE_LXSYSCALL1(void, exit, int, status) {
+__DEFINE_LXSYSCALL1(void, exit, int, status)
+{
     terminate_proc(status);
 }
 
-__DEFINE_LXSYSCALL(void, yield) {
+__DEFINE_LXSYSCALL(void, yield)
+{
     schedule();
 }
 
-__DEFINE_LXSYSCALL1(pid_t, wait, int*, status) {
+__DEFINE_LXSYSCALL1(pid_t, wait, int*, status)
+{
     pid_t cur = __current->pid;
     struct proc_info *proc, *n;
     if (llist_empty(&__current->children)) {
         return -1;
     }
 repeat:
-    llist_for_each(proc, n, &__current->children, siblings) {
+    llist_for_each(proc, n, &__current->children, siblings)
+    {
         if (proc->state == PROC_TERMNAT) {
             goto done;
         }
     }
-    // FIXME: 除了循环,也许有更高效的办法…… (在这里进行schedule,需要重写context switch!)
+    // FIXME: 除了循环,也许有更高效的办法……
+    // (在这里进行schedule,需要重写context switch!)
     goto repeat;
 
 done:
@@ -132,27 +142,34 @@ done:
     return destroy_process(proc->pid);
 }
 
-pid_t alloc_pid() {
+pid_t
+alloc_pid()
+{
     pid_t i = 0;
-    for (; i < sched_ctx.ptable_len && sched_ctx._procs[i].state != PROC_DESTROY; i++);
+    for (;
+         i < sched_ctx.ptable_len && sched_ctx._procs[i].state != PROC_DESTROY;
+         i++)
+        ;
 
     if (i == MAX_PROCESS) {
-        panick("Process table is full");
+        panick("Panic in Ponyville shimmer!");
     }
-    return i + 1;
+    return i;
 }
 
-void push_process(struct proc_info* process) {
-    int index = process->pid - 1;
+void
+push_process(struct proc_info* process)
+{
+    int index = process->pid;
     if (index < 0 || index > sched_ctx.ptable_len) {
         __current->k_status = LXINVLDPID;
         return;
     }
-    
+
     if (index == sched_ctx.ptable_len) {
         sched_ctx.ptable_len++;
     }
-    
+
     sched_ctx._procs[index] = *process;
 
     process = &sched_ctx._procs[index];
@@ -162,30 +179,33 @@ void push_process(struct proc_info* process) {
     // every process is the child of first process (pid=1)
     if (process->parent) {
         llist_append(&process->parent->children, &process->siblings);
-    }
-    else {
+    } else {
         process->parent = &sched_ctx._procs[0];
     }
 
-    process->state = PROC_STOPPED;    
+    process->state = PROC_STOPPED;
 }
 
 // from <kernel/process.c>
-extern void __del_pagetable(pid_t pid, uintptr_t mount_point);
+extern void
+__del_pagetable(pid_t pid, uintptr_t mount_point);
 
-pid_t destroy_process(pid_t pid) {
-    int index = pid - 1;
+pid_t
+destroy_process(pid_t pid)
+{
+    int index = pid;
     if (index <= 0 || index > sched_ctx.ptable_len) {
         __current->k_status = LXINVLDPID;
         return;
     }
-    struct proc_info *proc = &sched_ctx._procs[index];
+    struct proc_infoproc = &sched_ctx._procs[index];
     proc->state = PROC_DESTROY;
     llist_delete(&proc->siblings);
 
     if (proc->mm.regions) {
         struct mm_region *pos, *n;
-        llist_for_each(pos, n, &proc->mm.regions->head, head) {
+        llist_for_each(pos, n, &proc->mm.regions->head, head)
+        {
             lxfree(pos);
         }
     }
@@ -199,27 +219,35 @@ pid_t destroy_process(pid_t pid) {
     return pid;
 }
 
-void terminate_proc(int exit_code) {
+void
+terminate_proc(int exit_code)
+{
     __current->state = PROC_TERMNAT;
     __current->exit_code = exit_code;
 
     schedule();
 }
 
-struct proc_info* get_process(pid_t pid) {
-    int index = pid - 1;
+struct proc_info*
+get_process(pid_t pid)
+{
+    int index = pid;
     if (index < 0 || index > sched_ctx.ptable_len) {
         return NULL;
     }
     return &sched_ctx._procs[index];
 }
 
-int orphaned_proc(pid_t pid) {
-    if(!pid) return 0;
-    if(pid >= sched_ctx.ptable_len) return 0;
-    struct proc_info* proc = &sched_ctx._procs[pid-1];
+int
+orphaned_proc(pid_t pid)
+{
+    if (!pid)
+        return 0;
+    if (pid >= sched_ctx.ptable_len)
+        return 0;
+    struct proc_info* proc = &sched_ctx._procs[pid];
     struct proc_info* parent = proc->parent;
-    
+
     // 如果其父进程的状态是terminated 或 destroy中的一种
     // 或者其父进程是在该进程之后创建的,那么该进程为孤儿进程
     return (parent->state & PROC_TERMMASK) || parent->created > proc->created;
index f61e368f19483ee54d69c467bcb9678d9a452819..958082a484da305dcd833797d11d67e8e2243eac 100644 (file)
@@ -62,6 +62,6 @@ SECTIONS {
 
     __kernel_end = ALIGN(4K);
     __proc_table = ALIGN(4K);
-    . += 128M;
+    . += 4M;
     __kernel_heap_start = ALIGN(4K);    /* 内核结束的地方即堆开始的地方 */
 }
\ No newline at end of file