basic process support and some syscalls
authorMinep <zelong56@gmail.com>
Mon, 30 May 2022 00:46:55 +0000 (01:46 +0100)
committerMinep <zelong56@gmail.com>
Mon, 30 May 2022 00:46:55 +0000 (01:46 +0100)
45 files changed:
lunaix-os/.vscode/c_cpp_properties.json
lunaix-os/arch/x86/boot.S
lunaix-os/arch/x86/hhk.c
lunaix-os/includes/arch/x86/gdt.h
lunaix-os/includes/arch/x86/interrupts.h
lunaix-os/includes/arch/x86/tss.h [new file with mode: 0644]
lunaix-os/includes/arch/x86/vectors.h [new file with mode: 0644]
lunaix-os/includes/hal/cpu.h
lunaix-os/includes/lunaix/common.h
lunaix-os/includes/lunaix/keyboard.h
lunaix-os/includes/lunaix/lunistd.h [new file with mode: 0644]
lunaix-os/includes/lunaix/mm/dmm.h
lunaix-os/includes/lunaix/mm/mm.h [new file with mode: 0644]
lunaix-os/includes/lunaix/mm/page.h
lunaix-os/includes/lunaix/mm/pmm.h
lunaix-os/includes/lunaix/mm/vmm.h
lunaix-os/includes/lunaix/proc.h [new file with mode: 0644]
lunaix-os/includes/lunaix/process.h [new file with mode: 0644]
lunaix-os/includes/lunaix/sched.h [new file with mode: 0644]
lunaix-os/includes/lunaix/status.h [new file with mode: 0644]
lunaix-os/includes/lunaix/syscall.h [new file with mode: 0644]
lunaix-os/includes/lunaix/types.h [new file with mode: 0644]
lunaix-os/kernel/asm/x86/gdt.c
lunaix-os/kernel/asm/x86/idt.c
lunaix-os/kernel/asm/x86/interrupt.S
lunaix-os/kernel/asm/x86/interrupts.c
lunaix-os/kernel/asm/x86/intr_routines.c
lunaix-os/kernel/asm/x86/pfault.c [new file with mode: 0644]
lunaix-os/kernel/asm/x86/prologue.S
lunaix-os/kernel/asm/x86/syscall.S [new file with mode: 0644]
lunaix-os/kernel/asm/x86/tss.c [new file with mode: 0644]
lunaix-os/kernel/ds/semaphore.c
lunaix-os/kernel/k_init.c
lunaix-os/kernel/lxinit.c [moved from lunaix-os/kernel/k_main.c with 75% similarity]
lunaix-os/kernel/mm/cow.c [new file with mode: 0644]
lunaix-os/kernel/mm/dmm.c
lunaix-os/kernel/mm/kalloc.c
lunaix-os/kernel/mm/pmm.c
lunaix-os/kernel/mm/vmm.c
lunaix-os/kernel/peripheral/ps2kbd.c
lunaix-os/kernel/process.c [new file with mode: 0644]
lunaix-os/kernel/sched.c [new file with mode: 0644]
lunaix-os/kernel/syscall.c [new file with mode: 0644]
lunaix-os/kernel/time/timer.c
lunaix-os/link/linker.ld

index f069ef530f2cc6381e4587e4e6e57e7a662c32b4..574a1bd865aa9b215005dd473f638bc7222cbc55 100644 (file)
@@ -3,7 +3,7 @@
         {
             "name": "OS-DEV",
             "includePath": [
-                "${workspaceFolder}/includes/**"
+                "${workspaceFolder}/includes"
             ],
             "compilerArgs": [
                 "-ffreestanding",
@@ -13,8 +13,7 @@
             "defines": [],
             "compilerPath": "${HOME}/opt/cross-compiler/bin/i686-elf-gcc",
             "cStandard": "gnu99",
-            "intelliSenseMode": "gcc-x86",
-            "configurationProvider": "ms-vscode.makefile-tools"
+            "intelliSenseMode": "gcc-x86"
         }
     ],
     "version": 4
index 8ba78cc39ab8443004b394545a786061c7995369..9c86bbc6bed8081695dcb00a58b33b100403b73e 100644 (file)
@@ -2,7 +2,7 @@
 #include <arch/x86/boot/multiboot.h>
 
 #define MB_FLAGS    MULTIBOOT_MEMORY_INFO | MULTIBOOT_PAGE_ALIGN
-#define KPG_SIZE    24*1024
+#define KPG_SIZE    10*4096
 
 .section .multiboot
     .long MULTIBOOT_MAGIC
@@ -24,9 +24,9 @@
 
 /* 
     1 page directory, 
-    5 page tables:
+    9 page tables:
         1. Mapping reserved area and hhk_init
-        2-5. Remapping the kernels
+        2-9. Remapping the kernels
 */
 
 .section .kpg
@@ -77,9 +77,9 @@
         andl $0xfffff000, %eax      # 有点多余,但写上还算明白一点
         movl %eax, %cr3
 
-        /* 开启分页与地址转换 (CR0.PG=1) */
+        /* 开启分页与地址转换 (CR0.PG=1, PG.WP=1) */
         movl %cr0, %eax
-        orl $0x80000000, %eax
+        orl $0x80010000, %eax
         movl %eax, %cr0
 
         addl $16, %esp
index c6797c892d0aef826d7534f855340cf429345481..5dae566790068ccf027982c9eede995a59ed7e0e 100644 (file)
 // use table #1
 #define PG_TABLE_IDENTITY           0
 
-// use table #2-4
+// use table #2-8
 // hence the max size of kernel is 8MiB
 #define PG_TABLE_KERNEL             1
 
-// use table #5
-#define PG_TABLE_STACK              4
+// use table #9
+#define PG_TABLE_STACK              8
 
 // Provided by linker (see linker.ld)
 extern uint8_t __kernel_start;
@@ -29,7 +29,7 @@ extern uint8_t _k_stack;
 
 void 
 _init_page(ptd_t* ptd) {
-    SET_PDE(ptd, 0, NEW_L1_ENTRY(PG_PRESENT, ptd + PG_MAX_ENTRIES))
+    SET_PDE(ptd, 0, NEW_L1_ENTRY(PG_PREM_RW, ptd + PG_MAX_ENTRIES))
     
     // 对低1MiB空间进行对等映射(Identity mapping),也包括了我们的VGA,方便内核操作。
     for (uint32_t i = 0; i < 256; i++)
@@ -67,7 +67,7 @@ _init_page(ptd_t* ptd) {
     if (kernel_pg_counts > (PG_TABLE_STACK - PG_TABLE_KERNEL) * PG_MAX_ENTRIES) {
         // ERROR: require more pages
         //  here should do something else other than head into blocking
-        while (1);
+        asm ("ud2");
     }
     
     // 计算内核.text段的物理地址
index bb2fa27cca915440b7f256520888844c67c51235..f3121669facdae462d320e936c9ce0a195a6da9b 100644 (file)
@@ -48,6 +48,8 @@
 #define SEG_R3_DATA         SD_TYPE(SEG_DATA_RDWR) | SD_CODE_DATA(1) | SD_DPL(3) | \
                             SD_PRESENT(1) | SD_AVL(0) | SD_64BITS(0) | SD_32BITS(1) | \
                             SD_4K_GRAN(1)
+
+#define SEG_TSS             SD_TYPE(9) | SD_DPL(0) | SD_PRESENT(1)
                             
 
 void
index 664d69d29336cd85079c5c5216e0e11eb6c61243..9d3d0857ddff155ad290d2ed095f071b9dacfaff 100644 (file)
@@ -1,49 +1,7 @@
 #ifndef __LUNAIX_INTERRUPTS_H
 #define __LUNAIX_INTERRUPTS_H
 
-
-#define FAULT_DIVISION_ERROR            0
-#define FAULT_TRAP_DEBUG_EXCEPTION      1
-#define INT_NMI                         2
-#define TRAP_BREAKPOINT                 3
-#define TRAP_OVERFLOW                   4
-#define FAULT_BOUND_EXCEED              5
-#define FAULT_INVALID_OPCODE            6
-#define FAULT_NO_MATH_PROCESSOR         7
-#define ABORT_DOUBLE_FAULT              8
-#define FAULT_RESERVED_0                9
-#define FAULT_INVALID_TSS               10
-#define FAULT_SEG_NOT_PRESENT           11
-#define FAULT_STACK_SEG_FAULT           12
-#define FAULT_GENERAL_PROTECTION        13
-#define FAULT_PAGE_FAULT                14
-#define FAULT_RESERVED_1                15
-#define FAULT_X87_FAULT                 16
-#define FAULT_ALIGNMENT_CHECK           17
-#define ABORT_MACHINE_CHECK             18
-#define FAULT_SIMD_FP_EXCEPTION         19
-#define FAULT_VIRTUALIZATION_EXCEPTION  20
-#define FAULT_CONTROL_PROTECTION        21
-
-// LunaixOS related
-#define LUNAIX_SYS_PANIC                32
-
-#define EX_INTERRUPT_BEGIN              200
-
-// Keyboard
-#define PC_KBD_IV                       201
-
-#define RTC_TIMER_IV                    210
-
-// 来自APIC的中断有着最高的优先级。
-// APIC related
-#define APIC_ERROR_IV                   250
-#define APIC_LINT0_IV                   251
-#define APIC_SPIV_IV                    252
-#define APIC_TIMER_IV                   253
-
-#define PC_AT_IRQ_RTC                   8
-#define PC_AT_IRQ_KBD                   1
+#include "vectors.h"
 
 #ifndef __ASM__
 #include <hal/cpu.h>
@@ -88,6 +46,7 @@ ISR(20)
 ISR(21)
 
 ISR(32)
+ISR(33)
 
 ISR(201)
 
diff --git a/lunaix-os/includes/arch/x86/tss.h b/lunaix-os/includes/arch/x86/tss.h
new file mode 100644 (file)
index 0000000..3310aa6
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __LUNAIX_TSS_H
+#define __LUNAIX_TSS_H
+#include <stdint.h>
+
+struct x86_tss {
+    uint32_t link;
+    uint32_t esp0;
+    uint16_t ss0;
+    uint8_t __padding[94];
+} __attribute__((packed));
+
+void tss_update(uint32_t ss0, uint32_t esp0);
+#endif /* __LUNAIX_TSS_H */
diff --git a/lunaix-os/includes/arch/x86/vectors.h b/lunaix-os/includes/arch/x86/vectors.h
new file mode 100644 (file)
index 0000000..5fb424f
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __LUNAIX_VECTORS_H
+#define __LUNAIX_VECTORS_H
+
+#define FAULT_DIVISION_ERROR            0
+#define FAULT_TRAP_DEBUG_EXCEPTION      1
+#define INT_NMI                         2
+#define TRAP_BREAKPOINT                 3
+#define TRAP_OVERFLOW                   4
+#define FAULT_BOUND_EXCEED              5
+#define FAULT_INVALID_OPCODE            6
+#define FAULT_NO_MATH_PROCESSOR         7
+#define ABORT_DOUBLE_FAULT              8
+#define FAULT_RESERVED_0                9
+#define FAULT_INVALID_TSS               10
+#define FAULT_SEG_NOT_PRESENT           11
+#define FAULT_STACK_SEG_FAULT           12
+#define FAULT_GENERAL_PROTECTION        13
+#define FAULT_PAGE_FAULT                14
+#define FAULT_RESERVED_1                15
+#define FAULT_X87_FAULT                 16
+#define FAULT_ALIGNMENT_CHECK           17
+#define ABORT_MACHINE_CHECK             18
+#define FAULT_SIMD_FP_EXCEPTION         19
+#define FAULT_VIRTUALIZATION_EXCEPTION  20
+#define FAULT_CONTROL_PROTECTION        21
+
+// LunaixOS related
+#define LUNAIX_SYS_PANIC                32
+#define LUNAIX_SYS_CALL                 33
+
+#define EX_INTERRUPT_BEGIN              200
+
+// Keyboard
+#define PC_KBD_IV                       201
+
+#define RTC_TIMER_IV                    210
+
+// 来自APIC的中断有着最高的优先级。
+// APIC related
+#define APIC_ERROR_IV                   250
+#define APIC_LINT0_IV                   251
+#define APIC_SPIV_IV                    252
+#define APIC_TIMER_IV                   253
+
+#define PC_AT_IRQ_RTC                   8
+#define PC_AT_IRQ_KBD                   1
+
+#endif /* __LUNAIX_VECTORS_H */
index bdb07c467267c56aa911bf3f37795b10b0747fc1..b155d4b57496e67a93b99e6ddd7a58432b599789 100644 (file)
@@ -39,19 +39,36 @@ cpu_has_apic();
 static inline reg32
 cpu_rcr0()
 {
-    asm("mov %cr0, %eax");
+    uintptr_t val;
+    asm volatile("movl %%cr0,%0" : "=r" (val));
+    return val;
 }
 
 static inline reg32
 cpu_rcr2()
 {
-    asm("mov %cr2, %eax");
+    uintptr_t val;
+    asm volatile("movl %%cr2,%0" : "=r" (val));
+    return val;
 }
 
 static inline reg32
 cpu_rcr3()
 {
-    asm("mov %cr3, %eax");
+    uintptr_t val;
+    asm volatile("movl %%cr3,%0" : "=r" (val));
+    return val;
+}
+
+static inline reg32
+cpu_reflags()
+{
+    uintptr_t val;
+    asm volatile(
+        "pushf\n"
+        "popl %0\n"
+        :"=r"(val)::);
+    return val;
 }
 #pragma GCC diagnostic pop
 
index 51c37f630e0c54ca353f59725fc33c58c7585514..27243bfba322957684e1ba6bd1806d9d159ce3dc 100644 (file)
@@ -1,20 +1,26 @@
 #ifndef __LUNAIX_CONSTANTS_H
 #define __LUNAIX_CONSTANTS_H
 
-#include <stddef.h>
-
-#define K_STACK_SIZE            (64 << 10)
-#define K_STACK_START           ((0xFFBFFFFFU - K_STACK_SIZE) + 1)
-#define HIGHER_HLF_BASE         0xC0000000UL
-#define MEM_1MB                 0x100000UL
+#define KSTACK_SIZE             (64 << 10)
+#define KSTACK_START            ((0xFFBFFFFFU - KSTACK_SIZE) + 1)
+#define KSTACK_TOP              0xffbffff0
+#define HIGHER_HLF_BASE         0xC0000000
+#define MEM_1MB                 0x100000
 
-#define VGA_BUFFER_VADDR        0xB0000000UL
-#define VGA_BUFFER_PADDR        0xB8000UL
+#define VGA_BUFFER_VADDR        0xB0000000
+#define VGA_BUFFER_PADDR        0xB8000
 #define VGA_BUFFER_SIZE         4096
 
-#define SYS_TIMER_FREQUENCY_HZ  2048
+#define KCODE_SEG              0x08
+#define KDATA_SEG              0x10
+#define UCODE_SEG              0x1B
+#define UDATA_SEG              0x23
+#define TSS_SEG                0x28
 
+#define SYS_TIMER_FREQUENCY_HZ  2048
 
+#ifndef __ASM__
+#include <stddef.h>
 // From Linux kernel v2.6.0 <kernel.h:194>
 /**
  * container_of - cast a member of a structure out to the containing structure
@@ -28,4 +34,5 @@
         const typeof( ((type *)0)->member ) *__mptr = (ptr);   \
         (type *)( (char *)__mptr - offsetof(type,member) );})
 
+#endif
 #endif /* __LUNAIX_CONSTANTS_H */
index 7f1308809e2abc0243cc5cf0920973fd880156e9..2dd40dd6df093af64196ad4229e949ee5b668781 100644 (file)
@@ -1,5 +1,6 @@
 #ifndef __LUNAIX_KEYBOARD_H
 #define __LUNAIX_KEYBOARD_H
+#include <lunaix/clock.h>
 
 //      Lunaix Keycode
 //       15        7         0
@@ -15,8 +16,6 @@
 
 typedef unsigned short kbd_keycode_t;
 typedef unsigned short kbd_kstate_t;
-#include <lunaix/clock.h>
-
 
 #define KEYPAD  0x0100
 #define FN_KEY  0x0200
diff --git a/lunaix-os/includes/lunaix/lunistd.h b/lunaix-os/includes/lunaix/lunistd.h
new file mode 100644 (file)
index 0000000..20e394f
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __LUNAIX_UNISTD_H
+#define __LUNAIX_UNISTD_H
+
+#include <lunaix/syscall.h>
+#include <lunaix/types.h>
+
+__LXSYSCALL(pid_t, fork)
+
+__LXSYSCALL1(int, sbrk, void*, addr)
+
+__LXSYSCALL1(void*, brk, size_t, size)
+
+#endif /* __LUNAIX_UNISTD_H */
index 22b0539391248ba746236e7f9422f821654c2e68..793ab3f8218cc1218737f4033262dbbe0ac2d907 100644 (file)
@@ -3,6 +3,8 @@
 // Dynamic Memory (i.e., heap) Manager
 
 #include <stddef.h>
+#include <lunaix/mm/mm.h>
+#include <lunaix/process.h>
 
 #define M_ALLOCATED 0x1
 #define M_PREV_FREE 0x2
 
 #define HEAP_INIT_SIZE 4096
 
-typedef struct 
-{
-    void* start;
-    void* brk;
-    void* max_addr;
-} heap_context_t;
-
 
 int
 dmm_init(heap_context_t* heap);
diff --git a/lunaix-os/includes/lunaix/mm/mm.h b/lunaix-os/includes/lunaix/mm/mm.h
new file mode 100644 (file)
index 0000000..2ea1ac2
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef __LUNAIX_MM_H
+#define __LUNAIX_MM_H
+
+#include <lunaix/ds/llist.h>
+#include <lunaix/ds/mutex.h>
+
+typedef struct 
+{
+    void* start;
+    void* brk;
+    void* max_addr;
+    mutex_t lock;
+} heap_context_t;
+
+/**
+ * @brief 私有区域,该区域中的页无法进行任何形式的共享。
+ * 
+ */
+#define REGION_PRIVATE      0x0
+
+/**
+ * @brief 读共享区域,该区域中的页可以被两个进程之间读共享,但任何写操作须应用Copy-On-Write
+ * 
+ */
+#define REGION_RSHARED      0x1
+
+/**
+ * @brief 写共享区域,该区域中的页可以被两个进程之间读共享,任何的写操作无需执行Copy-On-Write
+ * 
+ */
+#define REGION_WSHARED      0x2
+
+#define REGION_TYPE_CODE    (0)
+#define REGION_TYPE_DATA    (1 << 2)
+
+struct mm_region
+{
+    struct llist_header* head;
+    void* start;
+    void* end;
+    unsigned int attr;
+};
+
+#endif /* __LUNAIX_MM_H */
index 415ea9e09847c1d4177c0f2d8eadd9b328820880..a6b3162a9541379b1b35509f11015c6713be4a3b 100644 (file)
@@ -70,6 +70,7 @@
 typedef unsigned long ptd_t;
 typedef unsigned long pt_t;
 typedef unsigned int pt_attr;
+typedef uint32_t x86_pte_t;
 
 /**
  * @brief 虚拟映射属性
@@ -82,14 +83,23 @@ typedef struct {
     uintptr_t pa;
     // 映射的flags
     uint16_t flags;
+    // PTE地址
+    x86_pte_t *pte;
 } v_mapping;
 
-typedef uint32_t x86_pte_t;
 typedef struct
 {
     x86_pte_t entry[PG_MAX_ENTRIES];
 } __attribute__((packed)) x86_page_table;
 
 
+extern void __pg_mount_point;
+
+/* 三个页挂载点: 用于临时创建&编辑页表 */
+
+#define PG_MOUNT_1  (&__pg_mount_point)
+#define PG_MOUNT_2  (&__pg_mount_point + 0x1000)
+#define PG_MOUNT_3  (&__pg_mount_point + 0x2000)
+
 
 #endif /* __LUNAIX_PAGE_H */
index 36396dfcaed049055ad4ee6a2ca71d5060c4c3eb..d45af82653481d13ed7247ea1f91b0e2193b86f3 100644 (file)
@@ -4,9 +4,21 @@
 
 #include <stdint.h>
 #include <stddef.h>
+#include <lunaix/process.h>
 
 #define PM_PAGE_SIZE            4096
-#define PM_BMP_MAX_SIZE        (128 * 1024)
+#define PM_BMP_MAX_SIZE        (1024 * 1024)
+
+
+#define PP_FGPERSIST            0x1
+
+typedef uint32_t pp_attr_t;
+
+struct pp_struct {
+    pid_t owner;
+    uint32_t ref_counts;
+    pp_attr_t attr;
+};
 
 /**
  * @brief 标注物理页为可使用
@@ -20,7 +32,7 @@ void pmm_mark_page_free(uintptr_t ppn);
  * 
  * @param ppn 
  */
-void pmm_mark_page_occupied(uintptr_t ppn);
+void pmm_mark_page_occupied(pid_t owner, uintptr_t ppn, pp_attr_t attr);
 
 /**
  * @brief 标注多个连续的物理页为可用
@@ -36,14 +48,25 @@ void pmm_mark_chunk_free(uintptr_t start_ppn, size_t page_count);
  * @param start_ppn 起始PPN
  * @param page_count 数量
  */
-void pmm_mark_chunk_occupied(uintptr_t start_ppn, size_t page_count);
+void pmm_mark_chunk_occupied(pid_t owner, uintptr_t start_ppn, size_t page_count, pp_attr_t attr);
 
 /**
  * @brief 分配一个可用的物理页
  * 
  * @return void* 可用的页地址,否则为 NULL
  */
-void* pmm_alloc_page();
+void* pmm_alloc_page(pid_t owner, pp_attr_t attr);
+
+/**
+ * @brief 分配一个连续的物理内存区域
+ * 
+ * @param owner 
+ * @param num_pages 区域大小,单位为页
+ * @param attr 
+ * @return void* 
+ */
+void*
+pmm_alloc_cpage(pid_t owner, size_t num_pages, pp_attr_t attr);
 
 /**
  * @brief 初始化物理内存管理器
@@ -52,6 +75,7 @@ void* pmm_alloc_page();
  */
 void pmm_init(uintptr_t mem_upper_lim);
 
+struct pp_struct* pmm_query(void* pa);
 
 /**
  * @brief 释放一个已分配的物理页,假若页地址不存在,则无操作。
@@ -59,7 +83,9 @@ void pmm_init(uintptr_t mem_upper_lim);
  * @param page 页地址
  * @return 是否成功
  */
-int pmm_free_page(void* page);
+int pmm_free_page(pid_t owner, void* page);
+
 
+int pmm_ref_page(pid_t owner, void* page);
 
 #endif /* __LUNAIX_PMM_H */
index 3e124fc9923a12249f35b8267013876b4e3eb8fe..682f8d0611bd7d74a8a495ede00aa67a6825c5d5 100644 (file)
@@ -1,8 +1,10 @@
 #ifndef __LUNAIX_VMM_H
 #define __LUNAIX_VMM_H
 #include <lunaix/mm/page.h>
+#include <lunaix/process.h>
 #include <stddef.h>
 #include <stdint.h>
+#include <lunaix/mm/pmm.h>
 // Virtual memory manager
 
 /**
@@ -31,7 +33,7 @@ vmm_init_pd();
  * @return 虚拟页地址,如不成功,则为 NULL
  */
 void*
-vmm_map_page(void* va, void* pa, pt_attr tattr);
+vmm_map_page(pid_t pid, void* va, void* pa, pt_attr tattr);
 
 /**
  * @brief 建立一个映射关系,映射指定的物理页地址至虚拟页地址。如果指定的虚拟页地址已被占用,
@@ -44,16 +46,16 @@ vmm_map_page(void* va, void* pa, pt_attr tattr);
  * @return 虚拟页地址
  */
 void*
-vmm_fmap_page(void* va, void* pa, pt_attr tattr);
+vmm_fmap_page(pid_t pid, void* va, void* pa, pt_attr tattr);
 
 /**
  * @brief 尝试为一个虚拟页地址创建一个可用的物理页映射
  *
  * @param va 虚拟页地址
- * @return 物理页地址,如不成功,则为 NULL
+ * @return 虚拟页地址,如不成功,则为 NULL
  */
 void*
-vmm_alloc_page(void* va, pt_attr tattr);
+vmm_alloc_page(pid_t pid, void* va, void** pa, pt_attr tattr, pp_attr_t pattr);
 
 
 /**
@@ -65,7 +67,7 @@ vmm_alloc_page(void* va, pt_attr tattr);
  * @return int 是否成功
  */
 int
-vmm_alloc_pages(void* va, size_t sz, pt_attr tattr);
+vmm_alloc_pages(pid_t pid, void* va, size_t sz, pt_attr tattr, pp_attr_t pattr);
 
 /**
  * @brief 设置一个映射,如果映射已存在,则忽略。
@@ -74,8 +76,16 @@ vmm_alloc_pages(void* va, size_t sz, pt_attr tattr);
  * @param pa 
  * @param attr 
  */
+int
+vmm_set_mapping(pid_t pid, void* va, void* pa, pt_attr attr);
+
+/**
+ * @brief 删除并释放一个映射
+ *
+ * @param vpn
+ */
 void
-vmm_set_mapping(void* va, void* pa, pt_attr attr);
+vmm_unmap_page(pid_t pid, void* va);
 
 /**
  * @brief 删除一个映射
@@ -83,7 +93,7 @@ vmm_set_mapping(void* va, void* pa, pt_attr attr);
  * @param vpn
  */
 void
-vmm_unmap_page(void* va);
+vmm_unset_mapping(void* va);
 
 /**
  * @brief 将虚拟地址翻译为其对应的物理映射
@@ -103,4 +113,12 @@ vmm_v2p(void* va);
 v_mapping
 vmm_lookup(void* va);
 
+/**
+ * @brief (COW) 为虚拟页创建副本。
+ * 
+ * @return void* 包含虚拟页副本的物理页地址。
+ * 
+ */
+void* vmm_dup_page(void* va);
+
 #endif /* __LUNAIX_VMM_H */
diff --git a/lunaix-os/includes/lunaix/proc.h b/lunaix-os/includes/lunaix/proc.h
new file mode 100644 (file)
index 0000000..f22fd68
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __LUNAIX_SYS_H
+#define __LUNAIX_SYS_H
+
+#include <lunaix/syscall.h>
+
+__LXSYSCALL1(void, exit, int, status)
+
+__LXSYSCALL(void, yield)
+
+#endif /* __LUNAIX_SYS_H */
diff --git a/lunaix-os/includes/lunaix/process.h b/lunaix-os/includes/lunaix/process.h
new file mode 100644 (file)
index 0000000..25b1d60
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef __LUNAIX_PROCESS_H
+#define __LUNAIX_PROCESS_H
+
+#include <stdint.h>
+#include <arch/x86/interrupts.h>
+#include <lunaix/mm/mm.h>
+#include <lunaix/types.h>
+#include <lunaix/clock.h>
+
+// 虽然内核不是进程,但为了区分,这里使用Pid=-1来指代内核。这主要是方便物理页所有权检查。
+#define KERNEL_PID -1
+
+#define PROC_CREATED 0
+#define PROC_RUNNING 1
+#define PROC_STOPPED 2
+#define PROC_TERMNAT 3
+#define PROC_DESTROY 4
+
+
+struct proc_mm {
+    heap_context_t k_heap;
+    heap_context_t u_heap;
+    struct mm_region* region;
+};
+
+struct proc_info {
+    pid_t pid;
+    pid_t parent;
+    isr_param intr_ctx;
+    struct proc_mm mm;
+    void* page_table;
+    time_t created;
+    time_t parent_created;
+    uint8_t state;
+    int32_t exit_code;
+    int32_t k_status;
+};
+
+extern struct proc_info* __current;
+
+
+pid_t alloc_pid();
+
+/**
+ * @brief 向系统发布一个进程,使其可以被调度。
+ * 
+ * @param process 
+ */
+void push_process(struct proc_info* process);
+
+void destroy_process(pid_t pid);
+
+/**
+ * @brief 复制当前进程(LunaixOS的类 fork (unix) 实现)
+ * 
+ */
+void dup_proc();
+
+/**
+ * @brief 创建新进程(LunaixOS的类 CreateProcess (Windows) 实现)
+ * 
+ */
+void new_proc();
+
+/**
+ * @brief 终止(退出)当前进程
+ * 
+ */
+void terminate_process(int exit_code);
+
+struct proc_info* get_process(pid_t pid);
+
+#endif /* __LUNAIX_PROCESS_H */
diff --git a/lunaix-os/includes/lunaix/sched.h b/lunaix-os/includes/lunaix/sched.h
new file mode 100644 (file)
index 0000000..a0778a3
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __LUNAIX_SCHEDULER_H
+#define __LUNAIX_SCHEDULER_H
+
+#define SCHED_TIME_SLICE 1000
+
+struct scheduler {
+    struct proc_info* _procs;
+    int procs_index;
+    unsigned int ptable_len;
+};
+
+void sched_init();
+void schedule();
+
+#endif /* __LUNAIX_SCHEDULER_H */
diff --git a/lunaix-os/includes/lunaix/status.h b/lunaix-os/includes/lunaix/status.h
new file mode 100644 (file)
index 0000000..44fa2f9
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __LUNAIX_CODE_H
+#define __LUNAIX_CODE_H
+
+#define LXPROCFULL -(1)
+#define LXHEAPFULL -(2)
+#define LXINVLDPTR -(2)
+#define LXOUTOFMEM -(3)
+#define LXINVLDPID -(4)
+
+#endif /* __LUNAIX_CODE_H */
diff --git a/lunaix-os/includes/lunaix/syscall.h b/lunaix-os/includes/lunaix/syscall.h
new file mode 100644 (file)
index 0000000..d933584
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef __LUNAIX_SYSCALL_H
+#define __LUNAIX_SYSCALL_H
+
+#include <arch/x86/vectors.h>
+
+#define __SYSCALL_fork    0x1
+#define __SYSCALL_yield   0x2
+#define __SYSCALL_exit    0x3
+#define __SYSCALL_sbrk    0x4
+#define __SYSCALL_brk     0x5
+
+#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"
+    );
+}
+
+#define ___DOINT33(callcode, rettype)\
+    int v;    \
+    asm volatile (  \
+        "int %1\n"    \
+        :"=a"(v)    \
+        :"i"(LUNAIX_SYS_CALL), "a"(callcode));  \
+    return (rettype)v;     \
+
+#define __LXSYSCALL(rettype, name) \
+    rettype name () { \
+        ___DOINT33(__SYSCALL_##name, rettype) \
+    }
+
+#define __LXSYSCALL1(rettype, name, t1, p1) \
+    rettype name (t1 p1) { \
+        asm (""::"b"(p1)); \
+        ___DOINT33(__SYSCALL_##name, rettype) \
+    }
+
+#define __LXSYSCALL2(rettype, name, t1, p1, t2, p2) \
+    rettype name (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 (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 (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 */
diff --git a/lunaix-os/includes/lunaix/types.h b/lunaix-os/includes/lunaix/types.h
new file mode 100644 (file)
index 0000000..ed59da3
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __LUNAIX_TYPES_H
+#define __LUNAIX_TYPES_H
+
+#include <stdint.h>
+
+typedef int32_t pid_t;
+
+#endif /* __LUNAIX_TYPES_H */
index 41c597e962e7b9dc02e8e37739d923bac04f3f3f..1bd1c0028a77679cbfe7a439584c3b83d7682659 100644 (file)
@@ -1,7 +1,8 @@
 #include <arch/x86/gdt.h>
+#include <arch/x86/tss.h>
 #include <stdint.h>
 
-#define GDT_ENTRY 5
+#define GDT_ENTRY 6
 
 uint64_t _gdt[GDT_ENTRY];
 uint16_t _gdt_limit = sizeof(_gdt) - 1;
@@ -12,7 +13,8 @@ void _set_gdt_entry(uint32_t index, uint32_t base, uint32_t limit, uint32_t flag
     _gdt[index] |= SEG_BASE_L(base) | SEG_LIM_L(limit);
 }
 
+extern struct x86_tss _tss;
+
 void
 _init_gdt() {
     _set_gdt_entry(0, 0, 0, 0);
@@ -20,4 +22,5 @@ _init_gdt() {
     _set_gdt_entry(2, 0, 0xfffff, SEG_R0_DATA);
     _set_gdt_entry(3, 0, 0xfffff, SEG_R3_CODE);
     _set_gdt_entry(4, 0, 0xfffff, SEG_R3_DATA);
+    _set_gdt_entry(5, &_tss, sizeof(struct x86_tss) - 1, SEG_TSS);
 }
\ No newline at end of file
index e194d87b02492706b7c802181881f1f502e86d9b..9b2f0c6b469290c838fceffe266ebcc6d23074c1 100644 (file)
@@ -32,4 +32,5 @@ _init_idt() {
 
     // system defined interrupts
     _set_idt_entry(LUNAIX_SYS_PANIC, 0x08, _asm_isr32, 0);
+    _set_idt_entry(LUNAIX_SYS_CALL, 0x08, _asm_isr33, 0);
 }
\ No newline at end of file
index f05c3b80fa4e134df079101abfe785b6b5a96c71..471a8e643f44a204b23c3928f5269cc76cd69ddf 100644 (file)
@@ -1,5 +1,6 @@
 #define __ASM__
 #include <arch/x86/interrupts.h>
+// #define __ASM_INTR_DIAGNOSIS
 
 .macro isr_template vector, no_error_code=1
     .global _asm_isr\vector
         jmp interrupt_wrapper
 .endm
 
+#ifdef __ASM_INTR_DIAGNOSIS
+.section .bss
+    .global debug_resv
+    debug_resv:
+        .skip 16
+#endif
+
 .section .text
     isr_template FAULT_DIVISION_ERROR
     isr_template FAULT_GENERAL_PROTECTION, no_error_code=0
     isr_template FAULT_PAGE_FAULT, no_error_code=0
 
     isr_template LUNAIX_SYS_PANIC
+    isr_template LUNAIX_SYS_CALL
 
     isr_template APIC_ERROR_IV
     isr_template APIC_LINT0_IV
@@ -28,6 +37,7 @@
 
     interrupt_wrapper:
         pushl %esp
+
         pushl %esi
         pushl %ebp
         pushl %edi
@@ -42,6 +52,9 @@
         movl %eax, (%esp)
 
         call intr_handler
+
+    .global soft_iret
+    soft_iret:
         popl %esp
 
         popl %eax
 
         addl $8, %esp
 
-        iret
\ No newline at end of file
+#ifdef __ASM_INTR_DIAGNOSIS
+        cmpl $0, (%esp)
+        jz 1f
+        iret
+1:
+        movl $__current, %eax
+        movl  (%esp), %ebx
+        movl $debug_resv, %ecx
+        ud2
+#else
+        iret
+#endif
index a7ac25a5107c9ca516aff6c1dbaf83fa5fedf804..f6b55389ae68d8e43fd35db574f93301cdfb7528 100644 (file)
@@ -3,6 +3,10 @@
 #include <hal/cpu.h>
 #include <lunaix/syslog.h>
 #include <lunaix/tty/tty.h>
+#include <lunaix/process.h>
+#include <lunaix/sched.h>
+
+LOG_MODULE("intr")
 
 static int_subscriber subscribers[256];
 
@@ -25,9 +29,15 @@ intr_set_fallback_handler(int_subscriber subscribers) {
     fallback = subscribers;
 }
 
+
 void
 intr_handler(isr_param* param)
 {
+    // if (param->vector == LUNAIX_SYS_CALL) {
+    //     kprintf(KDEBUG "%p", param->registers.esp);
+    // }
+    __current->intr_ctx = *param;
+    
     if (param->vector <= 255) {
         int_subscriber subscriber = subscribers[param->vector];
         if (subscriber) {
@@ -48,10 +58,18 @@ intr_handler(isr_param* param)
             param->eip);
 
 done:
+
+    // if (__current->state != PROC_RUNNING) {
+    //     schedule();
+    // }
+
     // for all external interrupts except the spurious interrupt
     //  this is required by Intel Manual Vol.3A, section 10.8.1 & 10.8.5
     if (param->vector >= EX_INTERRUPT_BEGIN && param->vector != APIC_SPIV_IV) {
         apic_done_servicing();
     }
+
+    *param = __current->intr_ctx;
+
     return;
 }
\ No newline at end of file
index 8660df6bbd0889c8683aec07b30226521db6f1f1..f68b2ceeb80dec144b6b624f2a1a6809453c2b0d 100644 (file)
@@ -7,8 +7,12 @@
 
 #include <hal/apic.h>
 
+LOG_MODULE("INTR")
 
-static void 
+extern void
+intr_routine_page_fault (const isr_param* param);
+
+void 
 __print_panic_msg(const char* msg, const isr_param* param) 
 {
     kprint_panic("  INT %u: (%x) [%p: %p] %s",
@@ -33,20 +37,6 @@ intr_routine_general_protection (const isr_param* param)
     spin();
 }
 
-void
-intr_routine_page_fault (const isr_param* param) 
-{
-    void* pg_fault_ptr = cpu_rcr2();
-    if (!pg_fault_ptr) {
-        __print_panic_msg("Null pointer reference", param);
-    } else {
-        char buf[32];
-        sprintf(buf, "Page fault on %p", pg_fault_ptr);
-        __print_panic_msg(buf, param);
-    }
-    spin();
-}
-
 void
 intr_routine_sys_panic (const isr_param* param) 
 {
diff --git a/lunaix-os/kernel/asm/x86/pfault.c b/lunaix-os/kernel/asm/x86/pfault.c
new file mode 100644 (file)
index 0000000..c5ec07f
--- /dev/null
@@ -0,0 +1,21 @@
+#include <arch/x86/interrupts.h>
+#include <lunaix/mm/pmm.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/common.h>
+
+extern void __print_panic_msg(const char* msg, const isr_param* param);
+
+void
+intr_routine_page_fault (const isr_param* param) 
+{
+    void* pg_fault_ptr = cpu_rcr2();
+    if (!pg_fault_ptr) {
+        __print_panic_msg("Null pointer reference", param);
+        goto done;
+    }
+
+    __print_panic_msg("Page fault", param);
+
+done:
+    while(1);
+}
\ No newline at end of file
index 38716f52094de74a277466effacc0c52eb6a9bfe..ddd2652fe64bd353c15ad5c7dc3379939723b703 100644 (file)
@@ -1,5 +1,8 @@
 /* 高半核入口点 - 0xC0000000 */
 
+#define __ASM__
+#include <lunaix/common.h>
+
 .section .text
     .global hhk_entry_
     hhk_entry_:
@@ -24,7 +27,7 @@
         lgdt (%esp)
 
         /* 更新段寄存器 */
-        movw $0x10, %cx
+        movw $KDATA_SEG, %cx
         movw %cx, %es
         movw %cx, %ds
         movw %cx, %fs
@@ -32,7 +35,7 @@
         movw %cx, %ss
 
         /* 更新 CS:EIP */
-        pushw $0x08
+        pushw $KCODE_SEG
         pushl $_after_gdt
         retf
 
         movw %ax, (%esp)
         lidt (%esp)
 
+        /* 加载TSS段选择器 */
+        movw $TSS_SEG, %ax
+        ltr %ax
+
         addl $6, %esp
 
         call _kernel_init
 
-        /* 
-            加载新的栈指针,位于0xffbfffff,但因为16字节对齐的需求,低四位清零。
-            为什么不是0xffffffff? 因为0xffc00000 - 0xffffffff 这4MiB的空间用于
-            对页表与页目录的循环映射。
-        */
-        mov $0xffbffff0, %esp
-
-        call _kernel_post_init
-
-        /* 进入内核 */  
-        call _kernel_main
+        /* _kernel_init 永不返回 */
 
-        cli
-    j_:
+    1:
         hlt
-        jmp j_
\ No newline at end of file
+        jmp 1b
\ No newline at end of file
diff --git a/lunaix-os/kernel/asm/x86/syscall.S b/lunaix-os/kernel/asm/x86/syscall.S
new file mode 100644 (file)
index 0000000..2ea22d4
--- /dev/null
@@ -0,0 +1,48 @@
+#define __ASM__
+#include <lunaix/syscall.h>
+
+.section .data
+    /*
+        注意,这里的顺序非常重要。每个系统调用在这个地址表里的索引等于其调用号。
+    */
+    syscall_table:
+        .dc.l 0
+        .dc.l dup_proc
+        .dc.l schedule
+        .dc.l terminate_process
+        .dc.l _syscall_sbrk
+        .dc.l _syscall_brk
+
+.global syscall_hndlr
+
+.section .text
+    syscall_hndlr:
+        pushl %ebp
+        movl %esp, %ebp
+        addl $0x8, %ebp
+        movl (%ebp), %ebp
+
+        movl  (%ebp), %eax
+        cmpl  $__SYSCALL_MAX, %eax
+        jb 1f
+        neg   %eax
+        popl  %ebp
+        ret
+    1:
+        pushl 24(%ebp)    /* esi - #6 arg */
+        pushl 20(%ebp)    /* ebp - #5 arg */
+        pushl 16(%ebp)    /* edi - #4 arg */
+        pushl 12(%ebp)    /* edx - #3 arg */
+        pushl 8(%ebp)    /* ecx - #2 arg */
+        pushl 4(%ebp)    /* ebx - #1 arg */
+        shll $2, %eax
+        addl $syscall_table, %eax
+
+        call (%eax)
+
+        addl $24, %esp
+
+        popl %ebp
+        ret
+
+
diff --git a/lunaix-os/kernel/asm/x86/tss.c b/lunaix-os/kernel/asm/x86/tss.c
new file mode 100644 (file)
index 0000000..8946107
--- /dev/null
@@ -0,0 +1,13 @@
+#include <arch/x86/tss.h>
+#include <lunaix/common.h>
+
+struct x86_tss _tss = {
+    .link = 0,
+    .esp0 = KSTACK_START,
+    .ss0  = KDATA_SEG
+};
+
+void tss_update(uint32_t ss0, uint32_t esp0) {
+    _tss.esp0 = esp0;
+    _tss.ss0 = ss0;
+}
\ No newline at end of file
index 21d0e3399d761f3aaf2d3528a83dd55187144143..7b059a63d2c1907d0618041da6152edd3de68ff9 100644 (file)
@@ -1,4 +1,5 @@
 #include <lunaix/ds/semaphore.h>
+#include <lunaix/sched.h>
 
 void sem_init(struct sem_t *sem, unsigned int initial) {
     sem->counter = ATOMIC_VAR_INIT(initial);
@@ -6,7 +7,7 @@ void sem_init(struct sem_t *sem, unsigned int initial) {
 
 void sem_wait(struct sem_t *sem) {
     while (!atomic_load(&sem->counter)) {
-        // TODO: yield the cpu
+        schedule();
     }
     atomic_fetch_sub(&sem->counter, 1);
 }
index 74e3534fbacac48a5a6941ecac4af30298ba0cd8..bbd505d488b6c8123c25e98b983f1340ec79fd26 100644 (file)
@@ -10,6 +10,9 @@
 #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>
@@ -21,6 +24,7 @@
 #include <arch/x86/interrupts.h>
 
 #include <klibc/stdio.h>
+#include <klibc/string.h>
 
 #include <stdint.h>
 #include <stddef.h>
@@ -30,24 +34,23 @@ extern uint8_t __kernel_start;
 extern uint8_t __kernel_end;
 extern uint8_t __init_hhk_end;
 
+#define PP_KERN_SHARED (PP_FGSHARED | PP_TKERN)
 
 // Set remotely by kernel/asm/x86/prologue.S
 multiboot_info_t* _k_init_mb_info;
 
-LOG_MODULE("INIT");
+LOG_MODULE("BOOT");
 
-void
-setup_memory(multiboot_memory_map_t* map, size_t map_size);
+extern void _lxinit_main();
+void spawn_lxinit();
+void _kernel_post_init();
 
 void
-setup_kernel_runtime();
+setup_memory(multiboot_memory_map_t* map, size_t map_size);
 
 void
 lock_reserved_memory();
 
-void
-unlock_reserved_memory();
-
 void
 _kernel_pre_init() {
     _init_idt();
@@ -71,18 +74,62 @@ _kernel_init() {
     
     setup_memory((multiboot_memory_map_t*)_k_init_mb_info->mmap_addr, map_size);
 
-    setup_kernel_runtime();
+    // 为内核创建一个专属栈空间。
+    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);
+    }
+    kprintf(KINFO "[MM] Allocated %d pages for stack start at %p\n", KSTACK_SIZE>>PG_SIZE_BITS, KSTACK_START);
+
+    sched_init();
+
+    spawn_lxinit();
+}
+
+/**
+ * @brief 创建并运行init进程
+ * 
+ */
+void spawn_lxinit() {
+    struct proc_info kinit;
+    uint32_t* kstack = (uint32_t*)KSTACK_TOP - 4 * 5;
+
+    memset(&kinit, 0, sizeof(kinit));
+    kinit.page_table = (void*) cpu_rcr3();
+    kinit.parent = -1;
+    kinit.pid = 1;
+    kinit.intr_ctx = (isr_param) {
+        .registers.esp = kstack,
+        .cs = KCODE_SEG,
+        .eip = (void*)_kernel_post_init,
+        .ss = KDATA_SEG,
+        .eflags = cpu_reflags()
+    };
+
+    /* 
+        因为schedule从设计上是需要在中断环境中执行的
+        可是我们需要在这里手动调用 schedule,从而使我们的init能够被执行。
+        所以需要模拟中断产生时的栈里内容。
+    */ 
+    kstack[2] = kinit.intr_ctx.eip;
+    kstack[3] = kinit.intr_ctx.cs;
+    kstack[4] = kinit.intr_ctx.eflags;
+
+    push_process(&kinit);
+    
+    schedule();
 }
 
 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((void*)(i << PG_SIZE_BITS));
+        vmm_unmap_page(KERNEL_PID, (void*)(i << PG_SIZE_BITS));
     }
     
     // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射
@@ -90,12 +137,11 @@ _kernel_post_init() {
 
     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);
 
-    pmm_mark_page_occupied(FLOOR(__APIC_BASE_PADDR, PG_SIZE_BITS));
-    pmm_mark_page_occupied(FLOOR(ioapic_addr, PG_SIZE_BITS));
-
-    vmm_set_mapping(APIC_BASE_VADDR, __APIC_BASE_PADDR, PG_PREM_RW);
-    vmm_set_mapping(IOAPIC_BASE_VADDR, ioapic_addr, PG_PREM_RW);
+    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();
@@ -103,31 +149,19 @@ _kernel_post_init() {
     clock_init();
     ps2_kbd_init();
 
+    syscall_install();
+
     for (size_t i = 256; i < hhk_init_pg_count; i++) {
-        vmm_unmap_page((void*)(i << PG_SIZE_BITS));
+        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((pa + (j << PG_SIZE_BITS)), (pa + (j << PG_SIZE_BITS)), PG_PREM_R);
-        }
-    }
+    _lxinit_main();
+
+    spin();
 }
 
 void
-unlock_reserved_memory() {
+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++) {
@@ -139,7 +173,7 @@ unlock_reserved_memory() {
         size_t pg_num = CEIL(mmap.len_low, PG_SIZE_BITS);
         for (size_t j = 0; j < pg_num; j++)
         {
-            vmm_unmap_page((pa + (j << PG_SIZE_BITS)));
+            vmm_set_mapping(KERNEL_PID, (pa + (j << PG_SIZE_BITS)), (pa + (j << PG_SIZE_BITS)), PG_PREM_R);
         }
     }
 }
@@ -167,19 +201,20 @@ setup_memory(multiboot_memory_map_t* map, size_t map_size) {
 
     // 将内核占据的页,包括前1MB,hhk_init 设为已占用
     size_t pg_count = V2P(&__kernel_end) >> PG_SIZE_BITS;
-    pmm_mark_chunk_occupied(0, pg_count);
+    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(VGA_BUFFER_PADDR >> PG_SIZE_BITS, vga_buf_pgs);
+    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_RW
@@ -190,15 +225,4 @@ setup_memory(multiboot_memory_map_t* map, size_t map_size) {
     tty_set_buffer((void*)VGA_BUFFER_VADDR);
 
     kprintf(KINFO "[MM] Mapped VGA to %p.\n", VGA_BUFFER_VADDR);
-    
-}
-
-void
-setup_kernel_runtime() {
-    // 为内核创建一个专属栈空间。
-    for (size_t i = 0; i < (K_STACK_SIZE >> PG_SIZE_BITS); i++) {
-        vmm_alloc_page((void*)(K_STACK_START + (i << PG_SIZE_BITS)), PG_PREM_RW);
-    }
-    kprintf(KINFO "[MM] Allocated %d pages for stack start at %p\n", K_STACK_SIZE>>PG_SIZE_BITS, K_STACK_START);
-    assert_msg(kalloc_init(), "Fail to initialize heap");
 }
\ No newline at end of file
similarity index 75%
rename from lunaix-os/kernel/k_main.c
rename to lunaix-os/kernel/lxinit.c
index c3819d9d8050b1e54a8f15d420f328b8ca1ea3b0..7decff49900b513d3c7c85e38f3e4ca9252e4fbb 100644 (file)
@@ -7,18 +7,38 @@
 #include <lunaix/timer.h>
 #include <lunaix/keyboard.h>
 #include <lunaix/tty/tty.h>
-#include <stdint.h>
+#include <lunaix/lunistd.h>
+#include <lunaix/proc.h>
 
 extern uint8_t __kernel_start;
 
-LOG_MODULE("LX")
+LOG_MODULE("INIT")
 
 void 
 test_timer(void* payload);
 
 void
-_kernel_main()
+_lxinit_main()
 {
+    // 这里是就是LunaixOS的第一个进程了!
+    for (size_t i = 0; i < 10; i++)
+    {
+        pid_t pid = 0;
+        if (!(pid = fork())) {
+            while (1)
+            {
+                // kprintf(KINFO "Process %d\n", i);
+                tty_put_char('0'+i);
+                yield();
+            }
+        }
+        kprintf(KINFO "Forked %d\n", pid);
+    }
+
+    // FIXME: 这里fork会造成下面lxmalloc产生Heap corruption,需要实现COW和加入mutex
+    // fork();
+      
+
     char buf[64];
 
     kprintf(KINFO "Hello higher half kernel world!\nWe are now running in virtual "
@@ -66,6 +86,7 @@ _kernel_main()
             tty_sync_cursor();
         }
     }
+    
 
     spin();
 }
diff --git a/lunaix-os/kernel/mm/cow.c b/lunaix-os/kernel/mm/cow.c
new file mode 100644 (file)
index 0000000..30cead9
--- /dev/null
@@ -0,0 +1,16 @@
+#include <lunaix/mm/vmm.h>
+
+void* vmm_dup_page(void* va) {    
+    void* new_ppg = pmm_alloc_page(KERNEL_PID, 0);
+    vmm_fmap_page(KERNEL_PID, PG_MOUNT_3, new_ppg, PG_PREM_RW);
+
+    asm volatile (
+        "movl %1, %%edi\n"
+        "rep movsl\n"
+        :: "c"(1024), "r"(PG_MOUNT_3), "S"((uintptr_t)va)
+        : "memory", "%edi");
+
+    vmm_unset_mapping(PG_MOUNT_3);
+
+    return new_ppg;
+}
\ No newline at end of file
index ae899086d79fcd00f91bb1eb6faca4b8aa04dc04..dee5d28636fa30f5ff1fc3438762b1b5c1644662 100644 (file)
 #include <lunaix/mm/dmm.h>
 #include <lunaix/mm/vmm.h>
 #include <lunaix/mm/page.h>
+#include <lunaix/status.h>
 
 #include <lunaix/spike.h>
 
+
+int _syscall_sbrk(void* addr) {
+    heap_context_t* uheap = &__current->mm.u_heap;
+    mutex_lock(&uheap->lock);
+    int r = lxsbrk(uheap, addr);
+    mutex_unlock(&uheap->lock);
+    return r;
+}
+
+void* _syscall_brk(size_t size) {
+    heap_context_t* uheap = &__current->mm.u_heap;
+    mutex_lock(&uheap->lock);
+    void* r = lxbrk(uheap, size);
+    mutex_unlock(&uheap->lock);
+    return r;
+}
+
 int
 dmm_init(heap_context_t* heap)
 {
     assert((uintptr_t)heap->start % BOUNDARY == 0);
 
     heap->brk = heap->start;
+    mutex_init(&heap->lock);
 
-    return vmm_alloc_page(heap->brk, PG_PREM_RW) != NULL;
+    return vmm_alloc_page(__current->pid, heap->brk, NULL, PG_PREM_RW, 0) != NULL;
 }
 
 int
@@ -51,17 +70,16 @@ lxbrk(heap_context_t* heap, size_t size)
 
     // any invalid situations
     if (next >= heap->max_addr || next < current_brk) {
-        return NULL;
+        __current->k_status = LXINVLDPTR;
     }
 
     uintptr_t diff = PG_ALIGN(next) - PG_ALIGN(current_brk);
     if (diff) {
         // if next do require new pages to be allocated
-        if (!vmm_alloc_pages((void*)(PG_ALIGN(current_brk) + PG_SIZE),
+        if (!vmm_alloc_pages(__current->pid, (void*)(PG_ALIGN(current_brk) + PG_SIZE),
                              diff,
-                             PG_PREM_RW)) {
-            // for debugging
-            assert_msg(0, "unable to brk");
+                             PG_PREM_RW, 0)) {
+            __current->k_status = LXHEAPFULL;
             return NULL;
         }
     }
index 16c1d8286ba9164c7a5a0753b4a5853a2de01557..91905b4139cb2ee4933c07ddb7f4f5b37e1c93ef 100644 (file)
@@ -23,9 +23,6 @@
 
 extern uint8_t __kernel_heap_start;
 
-// FIXME: This should go to PCB once we're started to support multitasking
-static heap_context_t __kalloc_kheap;
-
 void*
 lx_malloc_internal(heap_context_t* heap, size_t size);
 
@@ -62,24 +59,25 @@ lx_grow_heap(heap_context_t* heap, size_t sz);
 
 int
 kalloc_init() {
-    __kalloc_kheap.start = &__kernel_heap_start;
-    __kalloc_kheap.brk = NULL;
-    __kalloc_kheap.max_addr = (void*)K_STACK_START;
+    heap_context_t* kheap = &__current->mm.k_heap;
+    kheap->start = &__kernel_heap_start;
+    kheap->brk = NULL;
+    kheap->max_addr = (void*)KSTACK_START;
 
-    if (!dmm_init(&__kalloc_kheap)) {
+    if (!dmm_init(kheap)) {
         return 0;
     }
 
-    SW(__kalloc_kheap.start, PACK(4, M_ALLOCATED));
-    SW(__kalloc_kheap.start + WSIZE, PACK(0, M_ALLOCATED));
-    __kalloc_kheap.brk += WSIZE;
+    SW(kheap->start, PACK(4, M_ALLOCATED));
+    SW(kheap->start + WSIZE, PACK(0, M_ALLOCATED));
+    kheap->brk += WSIZE;
 
-    return lx_grow_heap(&__kalloc_kheap, HEAP_INIT_SIZE) != NULL;
+    return lx_grow_heap(kheap, HEAP_INIT_SIZE) != NULL;
 }
 
 void*
 lxmalloc(size_t size) {
-    return lx_malloc_internal(&__kalloc_kheap, size);
+    return lx_malloc_internal(&__current->mm.k_heap, size);
 }
 
 void*
index dcc70b03aa14522fba1538fe414c5042536c6197..efb9dc8d36c67f169bec85ff80ff4b5ac1e035f2 100644 (file)
@@ -1,74 +1,48 @@
 #include <lunaix/mm/page.h>
 #include <lunaix/mm/pmm.h>
+#include <lunaix/status.h>
 
-#define MARK_PG_AUX_VAR(ppn)                                                   \
-    uint32_t group = ppn / 8;                                                  \
-    uint32_t msk = (0x80U >> (ppn % 8));                                       \
-
-#define MARK_CHUNK_AUX_VAR(start_ppn, page_count)                              \
-    uint32_t group = start_ppn / 8;                                            \
-    uint32_t offset = start_ppn % 8;                                           \
-    uint32_t group_count = (page_count + offset) / 8;                          \
-    uint32_t remainder = (page_count + offset) % 8;                            \
-    uint32_t leading_shifts =                                                  \
-      (page_count + offset) < 8 ? page_count : 8 - offset;
-
-static uint8_t pm_bitmap[PM_BMP_MAX_SIZE];
+// This is a very large array...
+static struct pp_struct pm_table[PM_BMP_MAX_SIZE];
 
 static uintptr_t max_pg;
 
-//  ... |xxxx xxxx |
-//  ... |-->|
 void
 pmm_mark_page_free(uintptr_t ppn)
 {
-    MARK_PG_AUX_VAR(ppn)
-    pm_bitmap[group] = pm_bitmap[group] & ~msk;
+    pm_table[ppn].ref_counts = 0;
 }
 
 void
-pmm_mark_page_occupied(uintptr_t ppn)
+pmm_mark_page_occupied(pid_t owner, uintptr_t ppn, pp_attr_t attr)
 {
-    MARK_PG_AUX_VAR(ppn)
-    pm_bitmap[group] = pm_bitmap[group] | msk;
+    pm_table[ppn] = (struct pp_struct) {
+        .owner = owner,
+        .ref_counts = 1,
+        .attr = attr
+    };
 }
 
 void
 pmm_mark_chunk_free(uintptr_t start_ppn, size_t page_count)
 {
-    MARK_CHUNK_AUX_VAR(start_ppn, page_count)
-
-    // nasty bit level hacks but it reduce # of iterations.
-
-    pm_bitmap[group] &= ~(((1U << leading_shifts) - 1) << (8 - offset - leading_shifts));
-
-    group++;
-
-    // prevent unsigned overflow
-    for (uint32_t i = 0; group_count !=0 && i < group_count - 1; i++, group++) {
-        pm_bitmap[group] = 0;
+    for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++)
+    {
+        pm_table[i].ref_counts = 0;
     }
-
-    pm_bitmap[group] &=
-      ~(((1U << (page_count > 8 ? remainder : 0)) - 1) << (8 - remainder));
 }
 
 void
-pmm_mark_chunk_occupied(uint32_t start_ppn, size_t page_count)
+pmm_mark_chunk_occupied(pid_t owner, uint32_t start_ppn, size_t page_count, pp_attr_t attr)
 {
-    MARK_CHUNK_AUX_VAR(start_ppn, page_count)
-
-    pm_bitmap[group] |= (((1U << leading_shifts) - 1) << (8 - offset - leading_shifts));
-
-    group++;
-
-    // prevent unsigned overflow
-    for (uint32_t i = 0; group_count !=0 && i < group_count - 1; i++, group++) {
-        pm_bitmap[group] = 0xFFU;
+    for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++)
+    {
+        pm_table[i] = (struct pp_struct) {
+            .owner = owner,
+            .ref_counts = 1,
+            .attr = attr
+        };
     }
-
-    pm_bitmap[group] |=
-      (((1U << (page_count > 8 ? remainder : 0)) - 1) << (8 - remainder));
 }
 
 // 我们跳过位于0x0的页。我们不希望空指针是指向一个有效的内存空间。
@@ -85,32 +59,54 @@ pmm_init(uintptr_t mem_upper_lim)
 
     // mark all as occupied
     for (size_t i = 0; i < PM_BMP_MAX_SIZE; i++) {
-        pm_bitmap[i] = 0xFFU;
+        pm_table[i] = (struct pp_struct) {
+            .owner = 0,
+            .attr = 0,
+            .ref_counts = 1
+        };
+    }
+}
+
+void*
+pmm_alloc_cpage(pid_t owner, size_t num_pages, pp_attr_t attr) {
+    size_t p1 = 0;
+    size_t p2 = 0;
+
+    while (p2 < max_pg && p2 - p1 < num_pages)
+    {
+        (!(&pm_table[p2])->ref_counts) ? (p2++) : (p1 = p2);
     }
+
+    if (p2 < max_pg) {
+        return NULL;
+    }
+
+    pmm_mark_chunk_occupied(owner, p1, num_pages, attr);
+
+    return p1 << 12;
 }
 
 void*
-pmm_alloc_page()
+pmm_alloc_page(pid_t owner, pp_attr_t attr)
 {
     // Next fit approach. Maximize the throughput!
     uintptr_t good_page_found = (uintptr_t)NULL;
     size_t old_pg_ptr = pg_lookup_ptr;
     size_t upper_lim = max_pg;
-    uint8_t chunk = 0;
+    struct pp_struct* pm;
     while (!good_page_found && pg_lookup_ptr < upper_lim) {
-        chunk = pm_bitmap[pg_lookup_ptr >> 3];
+        pm = &pm_table[pg_lookup_ptr];
 
         // skip the fully occupied chunk, reduce # of iterations
-        if (chunk != 0xFFU) {
-            for (size_t i = pg_lookup_ptr % 8; i < 8; i++, pg_lookup_ptr++) {
-                if (!(chunk & (0x80U >> i))) {
-                    pmm_mark_page_occupied(pg_lookup_ptr);
-                    good_page_found = pg_lookup_ptr << 12;
-                    break;
-                }
-            }
+        if (!pm->ref_counts) {
+            *pm = (struct pp_struct) {
+                .attr = attr,
+                .owner = owner,
+                .ref_counts = 1
+            };
+            good_page_found = pg_lookup_ptr << 12;
         } else {
-            pg_lookup_ptr += 8;
+            pg_lookup_ptr++;
 
             // We've searched the interval [old_pg_ptr, max_pg) but failed
             //   may be chances in [1, old_pg_ptr) ?
@@ -122,18 +118,54 @@ pmm_alloc_page()
             }
         }
     }
+    if (!good_page_found) {
+        __current->k_status = LXOUTOFMEM;
+    }
     return (void*)good_page_found;
 }
 
 int
-pmm_free_page(void* page)
+pmm_free_page(pid_t owner, void* page)
 {
-    // XXX: Add kernel reserved memory page check or simply ownership check?
-    uint32_t pg = (uintptr_t)page >> 12;
-    if (pg && pg < max_pg)
-    {
-        pmm_mark_page_free(pg);
+    struct pp_struct* pm = &pm_table[(intptr_t)page >> 12];
+    
+    // Oops, double free!
+    if (!(pm->ref_counts)) {
+        return 0;
+    }
+
+    // 检查权限,保证:1) 用户只能释放用户页; 2) 内核可释放所有页。
+    if ((pm->owner & owner) == pm->owner) {
+        pm->ref_counts--;
         return 1;
     }
     return 0;
+}
+
+int pmm_ref_page(pid_t owner, void* page) {
+    (void*) owner;      // TODO: do smth with owner
+    
+    uint32_t ppn = (uintptr_t)page >> 12;
+    
+    if (ppn >= PM_BMP_MAX_SIZE) {
+        return 0;
+    }
+
+    struct pp_struct* pm = &pm_table[ppn];
+    if (!pm->ref_counts) {
+        return 0;
+    }
+
+    pm->ref_counts++;
+    return 1;
+}
+
+struct pp_struct* pmm_query(void* pa) {
+    uint32_t ppn = (uintptr_t)pa >> 12;
+    
+    if (ppn >= PM_BMP_MAX_SIZE) {
+        return NULL;
+    }
+
+    return &pm_table[ppn];
 }
\ No newline at end of file
index 0aa09b8ee6c33fc942e66ed06f768c64f57f8e11..f791cc38969f340d49438fc748f32790ec7b2609 100644 (file)
@@ -1,7 +1,5 @@
 #include <hal/cpu.h>
 #include <klibc/string.h>
-#include <lunaix/mm/page.h>
-#include <lunaix/mm/pmm.h>
 #include <lunaix/mm/vmm.h>
 #include <lunaix/spike.h>
 
@@ -16,7 +14,7 @@ vmm_init()
 x86_page_table*
 vmm_init_pd()
 {
-    x86_page_table* dir = (x86_page_table*)pmm_alloc_page();
+    x86_page_table* dir = (x86_page_table*)pmm_alloc_page(KERNEL_PID, PP_FGPERSIST);
     for (size_t i = 0; i < PG_MAX_ENTRIES; i++) {
         dir->entry[i] = PTE_NULL;
     }
@@ -28,7 +26,8 @@ vmm_init_pd()
 }
 
 int
-__vmm_map_internal(uint32_t l1_inx,
+__vmm_map_internal(pid_t pid, 
+                   uint32_t l1_inx,
                    uint32_t l2_inx,
                    uintptr_t pa,
                    pt_attr attr,
@@ -41,14 +40,15 @@ __vmm_map_internal(uint32_t l1_inx,
     assert(attr <= 128);
 
     if (!l1pt->entry[l1_inx]) {
-        x86_page_table* new_l1pt_pa = pmm_alloc_page();
+        x86_page_table* new_l1pt_pa = pmm_alloc_page(pid, PP_FGPERSIST);
 
         // 物理内存已满!
         if (!new_l1pt_pa) {
             return 0;
         }
 
-        l1pt->entry[l1_inx] = NEW_L1_ENTRY(attr, new_l1pt_pa);
+        // This must be writable
+        l1pt->entry[l1_inx] = NEW_L1_ENTRY(attr | PG_WRITE, new_l1pt_pa);
         memset((void*)L2_VADDR(l1_inx), 0, PG_SIZE);
     }
 
@@ -57,9 +57,11 @@ __vmm_map_internal(uint32_t l1_inx,
         if (!forced) {
             return 0;
         }
-        if (HAS_FLAGS(l2pte, PG_PRESENT)) {
-            assert_msg(pmm_free_page(GET_PG_ADDR(l2pte)), "fail to release physical page");
-        }
+    }
+
+    if ((HAS_FLAGS(attr, PG_PRESENT))) {
+        // add one on reference count, regardless of existence.
+        pmm_ref_page(pid, pa);
     }
 
     l2pt->entry[l2_inx] = NEW_L2_ENTRY(attr, pa);
@@ -68,7 +70,7 @@ __vmm_map_internal(uint32_t l1_inx,
 }
 
 void*
-vmm_map_page(void* va, void* pa, pt_attr tattr)
+vmm_map_page(pid_t pid, void* va, void* pa, pt_attr tattr)
 {
     // 显然,对空指针进行映射没有意义。
     if (!pa || !va) {
@@ -92,8 +94,7 @@ vmm_map_page(void* va, void* pa, pt_attr tattr)
             l2pt = (x86_page_table*)L2_VADDR(l1_index);
         }
         // 页表有空位,只需要开辟一个新的 PTE (Level 2)
-        if (l2pt && !l2pt->entry[l2_index]) {
-            l2pt->entry[l2_index] = NEW_L2_ENTRY(tattr, pa);
+        if (__vmm_map_internal(pid, l1_index, l2_index, pa, tattr, false)) {
             return (void*)V_ADDR(l1_index, l2_index, PG_OFFSET(va));
         }
         l2_index++;
@@ -104,7 +105,7 @@ vmm_map_page(void* va, void* pa, pt_attr tattr)
         return NULL;
     }
 
-    if (!__vmm_map_internal(l1_index, l2_index, (uintptr_t)pa, tattr, false)) {
+    if (!__vmm_map_internal(pid, l1_index, l2_index, (uintptr_t)pa, tattr, false)) {
         return NULL;
     }
 
@@ -112,7 +113,7 @@ vmm_map_page(void* va, void* pa, pt_attr tattr)
 }
 
 void*
-vmm_fmap_page(void* va, void* pa, pt_attr tattr)
+vmm_fmap_page(pid_t pid, void* va, void* pa, pt_attr tattr)
 {
     if (!pa || !va) {
         return NULL;
@@ -123,42 +124,44 @@ vmm_fmap_page(void* va, void* pa, pt_attr tattr)
     uint32_t l1_index = L1_INDEX(va);
     uint32_t l2_index = L2_INDEX(va);
 
-    if (!__vmm_map_internal(l1_index, l2_index, (uintptr_t)pa, tattr, true)) {
+    if (!__vmm_map_internal(pid, l1_index, l2_index, (uintptr_t)pa, tattr, true)) {
         return NULL;
     }
 
     cpu_invplg(va);
 
-    return (void*)V_ADDR(l1_index, l2_index, PG_OFFSET(va));
+    return va;
 }
 
 void*
-vmm_alloc_page(void* vpn, pt_attr tattr)
+vmm_alloc_page(pid_t pid, void* vpn, void** pa, pt_attr tattr, pp_attr_t pattr)
 {
-    void* pp = pmm_alloc_page();
-    void* result = vmm_map_page(vpn, pp, tattr);
+    void* pp = pmm_alloc_page(pid, pattr);
+    void* result = vmm_map_page(pid, vpn, pp, tattr);
     if (!result) {
-        pmm_free_page(pp);
+        pmm_free_page(pp, pid);
     }
+    pa ? (*pa = pp) : 0;
     return result;
 }
 
 int
-vmm_alloc_pages(void* va, size_t sz, pt_attr tattr)
+vmm_alloc_pages(pid_t pid, void* va, size_t sz, pt_attr tattr, pp_attr_t pattr)
 {
     assert((uintptr_t)va % PG_SIZE == 0) assert(sz % PG_SIZE == 0);
 
     void* va_ = va;
     for (size_t i = 0; i < (sz >> PG_SIZE_BITS); i++, va_ += PG_SIZE) {
-        void* pp = pmm_alloc_page();
+        void* pp = pmm_alloc_page(pid, pattr);
         uint32_t l1_index = L1_INDEX(va_);
         uint32_t l2_index = L2_INDEX(va_);
         if (!pp || !__vmm_map_internal(
+                     pid,
                      l1_index, l2_index, (uintptr_t)pp, tattr, false)) {
             // if one failed, release previous allocated pages.
             va_ = va;
             for (size_t j = 0; j < i; j++, va_ += PG_SIZE) {
-                vmm_unmap_page(va_);
+                vmm_unmap_page(pid, va_);
             }
 
             return false;
@@ -168,8 +171,8 @@ vmm_alloc_pages(void* va, size_t sz, pt_attr tattr)
     return true;
 }
 
-void
-vmm_set_mapping(void* va, void* pa, pt_attr attr) {
+int
+vmm_set_mapping(pid_t pid, void* va, void* pa, pt_attr attr) {
     assert(((uintptr_t)va & 0xFFFU) == 0);
 
     uint32_t l1_index = L1_INDEX(va);
@@ -177,15 +180,15 @@ vmm_set_mapping(void* va, void* pa, pt_attr attr) {
 
     // prevent map of recursive mapping region
     if (l1_index == 1023) {
-        return;
+        return 0;
     }
     
-    __vmm_map_internal(l1_index, l2_index, (uintptr_t)pa, attr, false);
+    __vmm_map_internal(pid, l1_index, l2_index, (uintptr_t)pa, attr, false);
+    return 1;
 }
 
 void
-vmm_unmap_page(void* va)
-{
+__vmm_unmap_internal(pid_t pid, void* va, int free_ppage) {
     assert(((uintptr_t)va & 0xFFFU) == 0);
 
     uint32_t l1_index = L1_INDEX(va);
@@ -203,14 +206,25 @@ vmm_unmap_page(void* va)
     if (l1pte) {
         x86_page_table* l2pt = (x86_page_table*)L2_VADDR(l1_index);
         x86_pte_t l2pte = l2pt->entry[l2_index];
-        if (IS_CACHED(l2pte)) {
-            pmm_free_page((void*)l2pte);
+        if (IS_CACHED(l2pte) && free_ppage) {
+            pmm_free_page(pid, (void*)l2pte);
         }
         cpu_invplg(va);
         l2pt->entry[l2_index] = PTE_NULL;
     }
 }
 
+void
+vmm_unset_mapping(void* va) {
+    __vmm_unmap_internal(0, va, false);
+}
+
+void
+vmm_unmap_page(pid_t pid, void* va)
+{
+    __vmm_unmap_internal(pid, va, true);
+}
+
 v_mapping
 vmm_lookup(void* va)
 {
@@ -224,12 +238,13 @@ vmm_lookup(void* va)
 
     v_mapping mapping = { .flags = 0, .pa = 0, .pn = 0 };
     if (l1pte) {
-        x86_pte_t l2pte =
-          ((x86_page_table*)L2_VADDR(l1_index))->entry[l2_index];
+        x86_pte_t* l2pte =
+          &((x86_page_table*)L2_VADDR(l1_index))->entry[l2_index];
         if (l2pte) {
-            mapping.flags = PG_ENTRY_FLAGS(l2pte);
-            mapping.pa = PG_ENTRY_ADDR(l2pte);
+            mapping.flags = PG_ENTRY_FLAGS(*l2pte);
+            mapping.pa = PG_ENTRY_ADDR(*l2pte);
             mapping.pn = mapping.pa >> PG_SIZE_BITS;
+            mapping.pte = l2pte;
         }
     }
 
index 24c9a1e904ea42f17d8eb967cafa648035f1c40e..ece9eab778774a9c21d09cc0f8361db09835ee7b 100644 (file)
@@ -72,7 +72,7 @@ static kbd_keycode_t scancode_set2_shift[] = {
 #define KBD_STATE_CMDPROCS      0x40
 
 #define KBD_ENABLE_SPIRQ_FIX
-//#define KBD_DBGLOG
+// #define KBD_DBGLOG
 
 void intr_ps2_kbd_handler(const isr_param* param);
 static struct kdb_keyinfo_pkt* ps2_keybuffer_next_write();
diff --git a/lunaix-os/kernel/process.c b/lunaix-os/kernel/process.c
new file mode 100644 (file)
index 0000000..be7d423
--- /dev/null
@@ -0,0 +1,68 @@
+#include <lunaix/process.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/clock.h>
+#include <lunaix/syslog.h>
+#include <lunaix/common.h>
+
+LOG_MODULE("PROC")
+
+void dup_proc() {
+    pid_t pid = alloc_pid();
+
+    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*) L1_BASE_VADDR;
+
+    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*) L2_VADDR(i);
+        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++)
+        {
+            uintptr_t va = ((i << 10) | j) << 12;
+            x86_pte_t ppte = ppt->entry[j];
+            if (!ppte || !(ppte & PG_PRESENT)) {
+                pt->entry[j] = ppte;
+                continue;
+            }
+
+            // FIXME: 根据 mm_region 将读共享的页(如堆)标为只读,而私有的页(如栈),则复制;而写共享的页则无需更改flags
+            if (va >= KSTACK_START) {
+                void* ppa = vmm_dup_page(va);
+                ppte = ppte & 0xfff | (uintptr_t)ppa;
+            }
+            pt->entry[j] = ppte;
+            // ppte = ppte & ~PG_WRITE;
+            // pt->entry[j] = ppte;
+            // ppt->entry[j] = ppte;
+        }
+
+        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);
+
+    struct proc_info pcb = (struct proc_info) {
+        .created = clock_systime(),
+        .pid = pid,
+        .mm = __current->mm,
+        .page_table = ptd_pp,
+        .intr_ctx = __current->intr_ctx,
+        .parent_created = __current->created
+    };
+
+    // 正如同fork一样,返回两次。
+    pcb.intr_ctx.registers.eax = 0;
+    __current->intr_ctx.registers.eax = pid;
+
+    push_process(&pcb);
+    
+}
\ No newline at end of file
diff --git a/lunaix-os/kernel/sched.c b/lunaix-os/kernel/sched.c
new file mode 100644 (file)
index 0000000..ed2cc74
--- /dev/null
@@ -0,0 +1,120 @@
+#include <lunaix/process.h>
+#include <lunaix/sched.h>
+#include <lunaix/mm/vmm.h>
+#include <hal/cpu.h>
+#include <arch/x86/interrupts.h>
+#include <hal/apic.h>
+
+#include <lunaix/spike.h>
+#include <lunaix/status.h>
+#include <lunaix/syslog.h>
+
+#define MAX_PROCESS 512
+
+struct proc_info* __current;
+struct proc_info dummy;
+
+extern void __proc_table;
+
+struct scheduler sched_ctx;
+
+LOG_MODULE("SCHED")
+
+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
+    };
+
+    __current = &dummy;
+}
+
+void schedule() {
+    if (!sched_ctx.ptable_len) {
+        return;
+    }
+
+    struct proc_info* next;
+    int prev_ptr = sched_ctx.procs_index;
+    int ptr = prev_ptr;
+    // round-robin scheduler
+    do {
+        ptr = (ptr + 1) % sched_ctx.ptable_len;
+        next = &sched_ctx._procs[ptr];
+    } while((next->state != PROC_STOPPED && next->state != PROC_CREATED) && ptr != prev_ptr);
+    
+    sched_ctx.procs_index = ptr;
+    
+    __current->state = PROC_STOPPED;
+    next->state = PROC_RUNNING;
+    
+    __current = next;
+
+    cpu_lcr3(__current->page_table);
+
+    apic_done_servicing();
+
+    asm volatile ("pushl %0\n jmp soft_iret\n"::"r"(&__current->intr_ctx): "memory");
+}
+
+pid_t alloc_pid() {
+    pid_t i = 0;
+    for (; i < sched_ctx.ptable_len && sched_ctx._procs[i].state != PROC_DESTROY; i++);
+
+    if (i == MAX_PROCESS) {
+        __current->k_status = LXPROCFULL;
+        return -1;
+    }
+    return i + 1;
+}
+
+void push_process(struct proc_info* process) {
+    int index = process->pid - 1;
+    if (index < 0 || index > sched_ctx.ptable_len) {
+        __current->k_status = LXINVLDPID;
+        return;
+    }
+    
+    if (index == sched_ctx.ptable_len) {
+        sched_ctx.ptable_len++;
+    }
+    
+    process->parent = __current->pid;
+    process->state = PROC_CREATED;
+
+    sched_ctx._procs[index] = *process;
+}
+
+void destroy_process(pid_t pid) {
+    int index = pid - 1;
+    if (index < 0 || index > sched_ctx.ptable_len) {
+        __current->k_status = LXINVLDPID;
+        return;
+    }
+
+    sched_ctx._procs[index].state = PROC_DESTROY;
+
+    // TODO: recycle the physical pages used by page tables
+}
+
+void terminate_process(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;
+    if (index < 0 || index > sched_ctx.ptable_len) {
+        return NULL;
+    }
+    return &sched_ctx._procs[index];
+}
\ No newline at end of file
diff --git a/lunaix-os/kernel/syscall.c b/lunaix-os/kernel/syscall.c
new file mode 100644 (file)
index 0000000..0d41470
--- /dev/null
@@ -0,0 +1,13 @@
+#include <lunaix/syscall.h>
+#include <arch/x86/interrupts.h>
+#include <lunaix/process.h>
+#include <lunaix/sched.h>
+#include <lunaix/syslog.h>
+
+LOG_MODULE("SYSCALL")
+
+extern void syscall_hndlr(isr_param* param);
+
+void syscall_install() {
+    intr_subscribe(LUNAIX_SYS_CALL, syscall_hndlr);
+}
\ No newline at end of file
index 03ef2b4c2f4167dbb88df56124e2a0d16bef2d48..42a9ac214262d655a3e4b628091fce92d397373b 100644 (file)
@@ -16,6 +16,7 @@
 #include <lunaix/spike.h>
 #include <lunaix/syslog.h>
 #include <lunaix/timer.h>
+#include <lunaix/sched.h>
 
 #define LVT_ENTRY_TIMER(vector, mode) (LVT_DELIVERY_FIXED | mode | vector)
 
@@ -38,6 +39,9 @@ static volatile struct lx_timer_context* timer_ctx = NULL;
 static volatile uint32_t rtc_counter = 0;
 static volatile uint8_t apic_timer_done = 0;
 
+static volatile uint32_t sched_ticks = 0;
+static volatile uint32_t sched_ticks_counter = 0;
+
 #define APIC_CALIBRATION_CONST 0x100000
 
 void
@@ -51,6 +55,7 @@ timer_init_context()
     timer_ctx->active_timers =
       (struct lx_timer*)lxmalloc(sizeof(struct lx_timer));
     llist_init_head(timer_ctx->active_timers);
+
 }
 
 void
@@ -131,6 +136,9 @@ timer_init(uint32_t frequency)
     intr_subscribe(APIC_TIMER_IV, timer_update);
 
     apic_write_reg(APIC_TIMER_ICR, timer_ctx->tphz);
+
+    sched_ticks = timer_ctx->running_frequency / 1000 * SCHED_TIME_SLICE;
+    sched_ticks_counter = 0;
 }
 
 int
@@ -184,6 +192,13 @@ timer_update(const isr_param* param)
             lxfree(pos);
         }
     }
+    
+    sched_ticks_counter++;
+
+    if (sched_ticks_counter >= sched_ticks) {
+        sched_ticks_counter = 0;
+        schedule();
+    }
 }
 
 static void
index a81dad551c1dce19da6e2cea25ce1984b6c00ea0..2589aeb09273d00991842be20ced49701736fcce 100644 (file)
@@ -61,5 +61,9 @@ SECTIONS {
     }
 
     __kernel_end = ALIGN(4K);
+    __pg_mount_point = ALIGN(4K);
+    . += 12K;
+    __proc_table = ALIGN(4K);
+    . += 128M;
     __kernel_heap_start = ALIGN(4K);    /* 内核结束的地方即堆开始的地方 */
 }
\ No newline at end of file