feat: User mode support.
authorMinep <zelong56@gmail.com>
Sun, 19 Jun 2022 10:49:56 +0000 (11:49 +0100)
committerMinep <zelong56@gmail.com>
Sun, 19 Jun 2022 10:56:54 +0000 (11:56 +0100)
feat: All physical page allocations are now on-demand and being managed by PF handler.
fix: Remove the 'garbage' mapping due to reserve area locking when initialize ACPI.
refactor: alloc_pid now change to alloc_process.
chore: annonation on issues that should be fixed
chore: formatting some code.

21 files changed:
lunaix-os/arch/x86/hhk.c
lunaix-os/includes/lunaix/common.h
lunaix-os/includes/lunaix/mm/mm.h
lunaix-os/includes/lunaix/mm/region.h
lunaix-os/includes/lunaix/process.h
lunaix-os/includes/lunaix/spike.h
lunaix-os/kernel/asm/x86/idt.c
lunaix-os/kernel/asm/x86/interrupt.S
lunaix-os/kernel/asm/x86/intr_routines.c
lunaix-os/kernel/asm/x86/pfault.c
lunaix-os/kernel/asm/x86/tss.c
lunaix-os/kernel/k_init.c
lunaix-os/kernel/lxinit.c
lunaix-os/kernel/mm/region.c
lunaix-os/kernel/mm/vmm.c
lunaix-os/kernel/proc0.c
lunaix-os/kernel/process.c
lunaix-os/kernel/sched.c
lunaix-os/kernel/spike.c
lunaix-os/kernel/tty/tty.c
lunaix-os/link/linker.ld

index 5dae566790068ccf027982c9eede995a59ed7e0e..997bbdf86bcd886a84c0f37179f8aa2f8fc181bf 100644 (file)
@@ -1,25 +1,27 @@
 #include <arch/x86/boot/multiboot.h>
 #include <arch/x86/idt.h>
 #include <arch/x86/boot/multiboot.h>
 #include <arch/x86/idt.h>
-#include <lunaix/mm/page.h>
 #include <lunaix/common.h>
 #include <lunaix/common.h>
+#include <lunaix/mm/page.h>
 
 
-#define PT_ADDR(ptd, pt_index)                       ((ptd_t*)ptd + (pt_index + 1) * 1024)
-#define SET_PDE(ptd, pde_index, pde)                 *((ptd_t*)ptd + pde_index) = pde;
-#define SET_PTE(ptd, pt_index, pte_index, pte)       *(PT_ADDR(ptd, pt_index) + pte_index) = pte;
-#define sym_val(sym)                                 (uintptr_t)(&sym)
+#define PT_ADDR(ptd, pt_index) ((ptd_t*)ptd + (pt_index + 1) * 1024)
+#define SET_PDE(ptd, pde_index, pde) *((ptd_t*)ptd + pde_index) = pde;
+#define SET_PTE(ptd, pt_index, pte_index, pte)                                 \
+    *(PT_ADDR(ptd, pt_index) + pte_index) = pte;
+#define sym_val(sym) (uintptr_t)(&sym)
 
 
-#define KERNEL_PAGE_COUNT           ((sym_val(__kernel_end) - sym_val(__kernel_start) + 0x1000 - 1) >> 12);
-#define HHK_PAGE_COUNT              ((sym_val(__init_hhk_end) - 0x100000 + 0x1000 - 1) >> 12)
+#define KERNEL_PAGE_COUNT                                                      \
+    ((sym_val(__kernel_end) - sym_val(__kernel_start) + 0x1000 - 1) >> 12);
+#define HHK_PAGE_COUNT ((sym_val(__init_hhk_end) - 0x100000 + 0x1000 - 1) >> 12)
 
 // use table #1
 
 // use table #1
-#define PG_TABLE_IDENTITY           0
+#define PG_TABLE_IDENTITY 0
 
 // use table #2-8
 // hence the max size of kernel is 8MiB
 
 // use table #2-8
 // hence the max size of kernel is 8MiB
-#define PG_TABLE_KERNEL             1
+#define PG_TABLE_KERNEL 1
 
 // use table #9
 
 // use table #9
-#define PG_TABLE_STACK              8
+#define PG_TABLE_STACK 8
 
 // Provided by linker (see linker.ld)
 extern uint8_t __kernel_start;
 
 // Provided by linker (see linker.ld)
 extern uint8_t __kernel_start;
@@ -27,108 +29,115 @@ extern uint8_t __kernel_end;
 extern uint8_t __init_hhk_end;
 extern uint8_t _k_stack;
 
 extern uint8_t __init_hhk_end;
 extern uint8_t _k_stack;
 
-void 
-_init_page(ptd_t* ptd) {
+void
+_init_page(ptd_t* ptd)
+{
     SET_PDE(ptd, 0, NEW_L1_ENTRY(PG_PREM_RW, 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++)
-    {
-        SET_PTE(ptd, PG_TABLE_IDENTITY, i, NEW_L2_ENTRY(PG_PREM_RW, (i << PG_SIZE_BITS)))
+
+    // 对低1MiB空间进行对等映射(Identity
+    // mapping),也包括了我们的VGA,方便内核操作。
+    for (uint32_t i = 0; i < 256; i++) {
+        SET_PTE(ptd,
+                PG_TABLE_IDENTITY,
+                i,
+                NEW_L2_ENTRY(PG_PREM_RW, (i << PG_SIZE_BITS)))
     }
 
     }
 
-    // 对等映射我们的hhk_init,这样一来,当分页与地址转换开启后,我们依然能够照常执行最终的 jmp 指令来跳转至
+    // 对等映射我们的hhk_init,这样一来,当分页与地址转换开启后,我们依然能够照常执行最终的
+    // jmp 指令来跳转至
     //  内核的入口点
     //  内核的入口点
-    for (uint32_t i = 0; i < HHK_PAGE_COUNT; i++)
-    {
-        SET_PTE(ptd, PG_TABLE_IDENTITY, 256 + i, NEW_L2_ENTRY(PG_PREM_RW, 0x100000 + (i << PG_SIZE_BITS)))
+    for (uint32_t i = 0; i < HHK_PAGE_COUNT; i++) {
+        SET_PTE(ptd,
+                PG_TABLE_IDENTITY,
+                256 + i,
+                NEW_L2_ENTRY(PG_PREM_RW, 0x100000 + (i << PG_SIZE_BITS)))
     }
     }
-    
+
     // --- 将内核重映射至高半区 ---
     // --- 将内核重映射至高半区 ---
-    
-    // 这里是一些计算,主要是计算应当映射进的 页目录 与 页表 的条目索引(Entry Index)
+
+    // 这里是一些计算,主要是计算应当映射进的 页目录 与 页表 的条目索引(Entry
+    // Index)
     uint32_t kernel_pde_index = L1_INDEX(sym_val(__kernel_start));
     uint32_t kernel_pte_index = L2_INDEX(sym_val(__kernel_start));
     uint32_t kernel_pg_counts = KERNEL_PAGE_COUNT;
     uint32_t kernel_pde_index = L1_INDEX(sym_val(__kernel_start));
     uint32_t kernel_pte_index = L2_INDEX(sym_val(__kernel_start));
     uint32_t kernel_pg_counts = KERNEL_PAGE_COUNT;
-    
+
     // 将内核所需要的页表注册进页目录
     //  当然,就现在而言,我们的内核只占用不到50个页(每个页表包含1024个页)
     //  这里分配了3个页表(12MiB),未雨绸缪。
     // 将内核所需要的页表注册进页目录
     //  当然,就现在而言,我们的内核只占用不到50个页(每个页表包含1024个页)
     //  这里分配了3个页表(12MiB),未雨绸缪。
-    for (uint32_t i = 0; i < PG_TABLE_STACK - PG_TABLE_KERNEL; i++)
-    {
-        SET_PDE(
-            ptd, 
-            kernel_pde_index + i,   
-            NEW_L1_ENTRY(PG_PREM_RW, PT_ADDR(ptd, PG_TABLE_KERNEL + i))
-        )
+    for (uint32_t i = 0; i < PG_TABLE_STACK - PG_TABLE_KERNEL; i++) {
+        SET_PDE(ptd,
+                kernel_pde_index + i,
+                NEW_L1_ENTRY(PG_PREM_URW, PT_ADDR(ptd, PG_TABLE_KERNEL + i)))
     }
     }
-    
+
     // 首先,检查内核的大小是否可以fit进我们这几个表(12MiB)
     // 首先,检查内核的大小是否可以fit进我们这几个表(12MiB)
-    if (kernel_pg_counts > (PG_TABLE_STACK - PG_TABLE_KERNEL) * PG_MAX_ENTRIES) {
+    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
         // ERROR: require more pages
         //  here should do something else other than head into blocking
-        asm ("ud2");
+        asm("ud2");
     }
     }
-    
+
     // 计算内核.text段的物理地址
     uintptr_t kernel_pm = V2P(&__kernel_start);
     // 计算内核.text段的物理地址
     uintptr_t kernel_pm = V2P(&__kernel_start);
-    
+
     // 重映射内核至高半区地址(>=0xC0000000)
     // 重映射内核至高半区地址(>=0xC0000000)
-    for (uint32_t i = 0; i < kernel_pg_counts; i++)
-    {
-        SET_PTE(
-            ptd, 
-            PG_TABLE_KERNEL, 
-            kernel_pte_index + i, 
-            NEW_L2_ENTRY(PG_PREM_RW, kernel_pm + (i << PG_SIZE_BITS))
-        )
+    for (uint32_t i = 0; i < kernel_pg_counts; i++) {
+        // FIXME: 只是用作用户模式(R3)测试!
+        //        在实际中,内核代码除了极少部分需要暴露给R3(如从信号返回),其余的应为R0。
+        SET_PTE(ptd,
+                PG_TABLE_KERNEL,
+                kernel_pte_index + i,
+                NEW_L2_ENTRY(PG_PREM_URW, kernel_pm + (i << PG_SIZE_BITS)))
     }
 
     // 最后一个entry用于循环映射
     }
 
     // 最后一个entry用于循环映射
-    SET_PDE(
-        ptd,
-        PG_MAX_ENTRIES - 1,
-        NEW_L1_ENTRY(T_SELF_REF_PERM, ptd)
-    );
+    SET_PDE(ptd, PG_MAX_ENTRIES - 1, NEW_L1_ENTRY(T_SELF_REF_PERM, ptd));
 }
 
 }
 
-uint32_t __save_subset(uint8_t* destination, uint8_t* base, unsigned int size) {
+uint32_t
+__save_subset(uint8_t* destination, uint8_t* base, unsigned int size)
+{
     unsigned int i = 0;
     unsigned int i = 0;
-    for (; i < size; i++)
-    {
+    for (; i < size; i++) {
         *(destination + i) = *(base + i);
     }
     return i;
 }
 
         *(destination + i) = *(base + i);
     }
     return i;
 }
 
-void 
-_save_multiboot_info(multiboot_info_t* info, uint8_t* destination) {
+void
+_save_multiboot_info(multiboot_info_t* info, uint8_t* destination)
+{
     uint32_t current = 0;
     uint32_t current = 0;
-    uint8_t* info_b = (uint8_t*) info;
-    for (; current < sizeof(multiboot_info_t); current++)
-    {
+    uint8_t* info_b = (uint8_t*)info;
+    for (; current < sizeof(multiboot_info_t); current++) {
         *(destination + current) = *(info_b + current);
     }
 
         *(destination + current) = *(info_b + current);
     }
 
-    ((multiboot_info_t*) destination)->mmap_addr = (uintptr_t)destination + current;
-    current += __save_subset(destination + current, (uint8_t*)info->mmap_addr, info->mmap_length);
+    ((multiboot_info_t*)destination)->mmap_addr =
+      (uintptr_t)destination + current;
+    current += __save_subset(
+      destination + current, (uint8_t*)info->mmap_addr, info->mmap_length);
 
     if (present(info->flags, MULTIBOOT_INFO_DRIVE_INFO)) {
 
     if (present(info->flags, MULTIBOOT_INFO_DRIVE_INFO)) {
-        ((multiboot_info_t*) destination)->drives_addr = (uintptr_t)destination + current;
-        current += __save_subset(destination + current, (uint8_t*)info->drives_addr, info->drives_length);
+        ((multiboot_info_t*)destination)->drives_addr =
+          (uintptr_t)destination + current;
+        current += __save_subset(destination + current,
+                                 (uint8_t*)info->drives_addr,
+                                 info->drives_length);
     }
 }
 
     }
 }
 
-void 
-_hhk_init(ptd_t* ptd, uint32_t kpg_size) {
+void
+_hhk_init(ptd_t* ptd, uint32_t kpg_size)
+{
 
     // 初始化 kpg 全为0
     //      P.s. 真没想到GRUB会在这里留下一堆垃圾! 老子的页表全乱套了!
 
     // 初始化 kpg 全为0
     //      P.s. 真没想到GRUB会在这里留下一堆垃圾! 老子的页表全乱套了!
-    uint8_t* kpg = (uint8_t*) ptd;
-    for (uint32_t i = 0; i < kpg_size; i++)
-    {
+    uint8_t* kpg = (uint8_t*)ptd;
+    for (uint32_t i = 0; i < kpg_size; i++) {
         *(kpg + i) = 0;
     }
         *(kpg + i) = 0;
     }
-    
+
     _init_page(ptd);
 }
\ No newline at end of file
     _init_page(ptd);
 }
\ No newline at end of file
index f9ab67f5bb3a975006efad55df3b9daba49016d7..fe0c0bc31b34740563c32b5fce05f0266bb4ef58 100644 (file)
@@ -32,8 +32,8 @@
 
 #define USER_START 0x400000
 #define USTACK_SIZE 0x100000
 
 #define USER_START 0x400000
 #define USTACK_SIZE 0x100000
-#define USTACK_TOP 0x9fffffff
-#define USTACK_END (USTACK_TOP - USTACK_SIZE + 1)
+#define USTACK_TOP 0x9ffffff0
+#define USTACK_END (0x9fffffff - USTACK_SIZE + 1)
 #define UMMAP_AREA 0x4D000000
 
 #define SYS_TIMER_FREQUENCY_HZ 2048
 #define UMMAP_AREA 0x4D000000
 
 #define SYS_TIMER_FREQUENCY_HZ 2048
index 060b88181aa733d7d2592155a5fffe3509119e1a..6585916e4136d48cb2c0afa96ac341c4babfb65f 100644 (file)
@@ -33,6 +33,7 @@ typedef struct
 #define REGION_WSHARED 0x2
 
 #define REGION_PERM_MASK 0x1c
 #define REGION_WSHARED 0x2
 
 #define REGION_PERM_MASK 0x1c
+#define REGION_MODE_MASK 0x3
 
 #define REGION_READ (1 << 2)
 #define REGION_WRITE (1 << 3)
 
 #define REGION_READ (1 << 2)
 #define REGION_WRITE (1 << 3)
index 8271d2b68a16545084011edf1c714a93796fb268..9978d728f808e60d6a23fe312fadce315d4595e0 100644 (file)
@@ -4,18 +4,18 @@
 #include <lunaix/mm/mm.h>
 
 void
 #include <lunaix/mm/mm.h>
 
 void
-region_add(struct mm_region** proc,
+region_add(struct mm_region* proc,
            unsigned long start,
            unsigned long end,
            unsigned int attr);
 
 void
            unsigned long start,
            unsigned long end,
            unsigned int attr);
 
 void
-region_release_all(struct mm_region** proc);
+region_release_all(struct mm_region* proc);
 
 struct mm_region*
 
 struct mm_region*
-region_get(struct mm_region** proc, unsigned long vaddr);
+region_get(struct mm_region* proc, unsigned long vaddr);
 
 void
 
 void
-region_copy(struct mm_region** src, struct mm_region** dest);
+region_copy(struct mm_region* src, struct mm_region* dest);
 
 #endif /* __LUNAIX_REGION_H */
 
 #endif /* __LUNAIX_REGION_H */
index 26f33bd84dd9fbb21f753b5735a45a84458c2c5c..7a5d5024ef0c2a41c0ad0a2b9ddf62e35e9d9615 100644 (file)
@@ -24,7 +24,7 @@
 struct proc_mm
 {
     heap_context_t u_heap;
 struct proc_mm
 {
     heap_context_t u_heap;
-    struct mm_region* regions;
+    struct mm_region regions;
 };
 
 struct proc_sig
 };
 
 struct proc_sig
@@ -71,11 +71,21 @@ struct proc_info
 
 extern volatile struct proc_info* __current;
 
 
 extern volatile struct proc_info* __current;
 
-pid_t
-alloc_pid();
+/**
+ * @brief 分配并初始化一个进程控制块
+ *
+ * @return struct proc_info*
+ */
+struct proc_info*
+alloc_process();
 
 
+/**
+ * @brief 初始化进程用户空间
+ *
+ * @param pcb
+ */
 void
 void
-init_proc(struct proc_info* pcb);
+init_proc_user_space(struct proc_info* pcb);
 
 /**
  * @brief 向系统发布一个进程,使其可以被调度。
 
 /**
  * @brief 向系统发布一个进程,使其可以被调度。
@@ -83,7 +93,7 @@ init_proc(struct proc_info* pcb);
  * @param process
  */
 void
  * @param process
  */
 void
-push_process(struct proc_info* process);
+commit_process(struct proc_info* process);
 
 pid_t
 destroy_process(pid_t pid);
 
 pid_t
 destroy_process(pid_t pid);
index 8fd47b59b710d766afa0dc78429ca564bde2737d..1ce7481aabfb752242dff6ab7e018c3618fba07b 100644 (file)
@@ -4,42 +4,52 @@
 // Some helper functions. As helpful as Spike the Dragon! :)
 
 // 除法向上取整
 // Some helper functions. As helpful as Spike the Dragon! :)
 
 // 除法向上取整
-#define CEIL(v, k)          (((v) + (1 << (k)) - 1) >> (k))
+#define CEIL(v, k) (((v) + (1 << (k)) - 1) >> (k))
 
 // 除法向下取整
 
 // 除法向下取整
-#define FLOOR(v, k)         ((v) >> (k))
+#define FLOOR(v, k) ((v) >> (k))
 
 // 获取v最近的最大k倍数
 
 // 获取v最近的最大k倍数
-#define ROUNDUP(v, k)       (((v) + (k) - 1) & ~((k) - 1))
+#define ROUNDUP(v, k) (((v) + (k)-1) & ~((k)-1))
 
 // 获取v最近的最小k倍数
 
 // 获取v最近的最小k倍数
-#define ROUNDDOWN(v, k)     ((v) & ~((k) - 1))
+#define ROUNDDOWN(v, k) ((v) & ~((k)-1))
 
 
-inline static void spin() {
-    while(1);
+#define __USER__ __attribute__((section("usrtext")))
+
+inline static void
+spin()
+{
+    while (1)
+        ;
 }
 
 #ifdef __LUNAIXOS_DEBUG__
 }
 
 #ifdef __LUNAIXOS_DEBUG__
-#define assert(cond)                                  \
-    if (!(cond)) {                                    \
-        __assert_fail(#cond, __FILE__, __LINE__);     \
+#define assert(cond)                                                           \
+    if (!(cond)) {                                                             \
+        __assert_fail(#cond, __FILE__, __LINE__);                              \
     }
 
     }
 
-#define assert_msg(cond, msg)                         \
-    if (!(cond)) {                                    \
-        __assert_fail(msg, __FILE__, __LINE__);       \
+#define assert_msg(cond, msg)                                                  \
+    if (!(cond)) {                                                             \
+        __assert_fail(msg, __FILE__, __LINE__);                                \
     }
     }
-void __assert_fail(const char* expr, const char* file, unsigned int line) __attribute__((noinline, noreturn));
+void
+__assert_fail(const char* expr, const char* file, unsigned int line)
+  __attribute__((noinline, noreturn));
 #else
 #else
-#define assert(cond) (void)(cond); //assert nothing
-#define assert_msg(cond, msg) (void)(cond);  //assert nothing
+#define assert(cond) (void)(cond);          // assert nothing
+#define assert_msg(cond, msg) (void)(cond); // assert nothing
 #endif
 
 #endif
 
-void panick(const char* msg);
-
-
-#define wait_until(cond)    while(!(cond));
-#define loop_until(cond)    while(!(cond));
+void
+panick(const char* msg);
 
 
+#define wait_until(cond)                                                       \
+    while (!(cond))                                                            \
+        ;
+#define loop_until(cond)                                                       \
+    while (!(cond))                                                            \
+        ;
 
 #endif /* __LUNAIX_SPIKE_H */
 
 #endif /* __LUNAIX_SPIKE_H */
index f453313ccd9fbf13f83b7a38b528ab9ee43b79f9..3e408fd80836a09049370464b2fa9660bb3be307 100644 (file)
@@ -45,6 +45,7 @@ _init_idt()
     _set_idt_intr_entry(FAULT_DIVISION_ERROR, 0x08, _asm_isr0, 0);
     _set_idt_intr_entry(FAULT_GENERAL_PROTECTION, 0x08, _asm_isr13, 0);
     _set_idt_intr_entry(FAULT_PAGE_FAULT, 0x08, _asm_isr14, 0);
     _set_idt_intr_entry(FAULT_DIVISION_ERROR, 0x08, _asm_isr0, 0);
     _set_idt_intr_entry(FAULT_GENERAL_PROTECTION, 0x08, _asm_isr13, 0);
     _set_idt_intr_entry(FAULT_PAGE_FAULT, 0x08, _asm_isr14, 0);
+    _set_idt_intr_entry(FAULT_STACK_SEG_FAULT, 0x08, _asm_isr12, 0);
 
     _set_idt_intr_entry(APIC_ERROR_IV, 0x08, _asm_isr250, 0);
     _set_idt_intr_entry(APIC_LINT0_IV, 0x08, _asm_isr251, 0);
 
     _set_idt_intr_entry(APIC_ERROR_IV, 0x08, _asm_isr250, 0);
     _set_idt_intr_entry(APIC_LINT0_IV, 0x08, _asm_isr251, 0);
@@ -57,12 +58,7 @@ _init_idt()
     // system defined interrupts
     _set_idt_intr_entry(LUNAIX_SYS_PANIC, 0x08, _asm_isr32, 0);
 
     // system defined interrupts
     _set_idt_intr_entry(LUNAIX_SYS_PANIC, 0x08, _asm_isr32, 0);
 
-    // syscall is a trap gate (recall: trap does NOT clear IF flag upon
-    // interruption)
-    // // XXX: this should be fine, as our design of context switch support
-    // interruptible syscall We make this a non-trap entry, and enable interrupt
+    // We make this a non-trap entry, and enable interrupt
     // only when needed!
     // only when needed!
-    // FIXME: This may cause nasty concurrency bug! We should 'lockify' our
-    // code!
     _set_idt_intr_entry(LUNAIX_SYS_CALL, 0x08, _asm_isr33, 3);
 }
\ No newline at end of file
     _set_idt_intr_entry(LUNAIX_SYS_CALL, 0x08, _asm_isr33, 3);
 }
\ No newline at end of file
index cd3f547a10dd7522e9b47cff3b3e090d42940df7..e9419837ab5b6c07ea36b9a23173b4aec3d15ba4 100644 (file)
@@ -26,6 +26,7 @@
     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 FAULT_DIVISION_ERROR
     isr_template FAULT_GENERAL_PROTECTION, no_error_code=0
     isr_template FAULT_PAGE_FAULT, no_error_code=0
+    isr_template FAULT_STACK_SEG_FAULT, no_error_code=0
 
     isr_template LUNAIX_SYS_PANIC
     isr_template LUNAIX_SYS_CALL
 
     isr_template LUNAIX_SYS_PANIC
     isr_template LUNAIX_SYS_CALL
 
         iret  
 
 
         iret  
 
+.section .usrtext
     sig_wrapper:                # in user mode
         movl %esp, %eax
         and $0xfffffff0, %esp
     sig_wrapper:                # in user mode
         movl %esp, %eax
         and $0xfffffff0, %esp
index 0b05e751554245e2c19be72252a8035e99ff426e..8cc3ff558d3c338c7bf6a05ae4d46ae971774e89 100644 (file)
@@ -83,9 +83,10 @@ intr_routine_init()
     intr_subscribe(FAULT_DIVISION_ERROR, intr_routine_divide_zero);
     intr_subscribe(FAULT_GENERAL_PROTECTION, intr_routine_general_protection);
     intr_subscribe(FAULT_PAGE_FAULT, intr_routine_page_fault);
     intr_subscribe(FAULT_DIVISION_ERROR, intr_routine_divide_zero);
     intr_subscribe(FAULT_GENERAL_PROTECTION, intr_routine_general_protection);
     intr_subscribe(FAULT_PAGE_FAULT, intr_routine_page_fault);
+    intr_subscribe(FAULT_STACK_SEG_FAULT, intr_routine_page_fault);
     intr_subscribe(LUNAIX_SYS_PANIC, intr_routine_sys_panic);
     intr_subscribe(APIC_SPIV_IV, intr_routine_apic_spi);
     intr_subscribe(APIC_ERROR_IV, intr_routine_apic_error);
 
     intr_subscribe(LUNAIX_SYS_PANIC, intr_routine_sys_panic);
     intr_subscribe(APIC_SPIV_IV, intr_routine_apic_spi);
     intr_subscribe(APIC_ERROR_IV, intr_routine_apic_error);
 
-    intr_set_fallback_handler(intr_set_fallback_handler);
+    intr_set_fallback_handler(intr_routine_fallback);
 }
\ No newline at end of file
 }
\ No newline at end of file
index 34589cbe6685fc60b49aeb65fcf95819cef4e4cf..30fd498605d721f9c3d782210a37b186b4fa7ce9 100644 (file)
@@ -17,6 +17,8 @@ kprintf(const char* fmt, ...)
     va_end(args);
 }
 
     va_end(args);
 }
 
+#define COW_MASK (REGION_RSHARED | REGION_READ | REGION_WRITE)
+
 extern void
 __print_panic_msg(const char* msg, const isr_param* param);
 
 extern void
 __print_panic_msg(const char* msg, const isr_param* param);
 
@@ -48,17 +50,16 @@ intr_routine_page_fault(const isr_param* param)
         goto segv_term;
     }
 
         goto segv_term;
     }
 
-    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)) {
+    x86_pte_t* pte = &PTE_MOUNTED(PD_REFERENCED, ptr >> 12);
+    if ((*pte & PG_PRESENT)) {
+        if ((hit_region->attr & COW_MASK) == COW_MASK) {
             // normal page fault, do COW
             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;
             // normal page fault, do COW
             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;
+            goto resolved;
         }
         // impossible cases or accessing privileged page
         goto segv_term;
         }
         // impossible cases or accessing privileged page
         goto segv_term;
@@ -68,15 +69,18 @@ intr_routine_page_fault(const isr_param* param)
         // Invalid location
         goto segv_term;
     }
         // Invalid location
         goto segv_term;
     }
+
     uintptr_t loc = *pte & ~0xfff;
     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, not cached, pte attr is not null
+    //   -> 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;
     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;
+        goto resolved;
     }
     }
+
     // page not present, bring it from disk or somewhere else
     __print_panic_msg("WIP page fault route", param);
     while (1)
     // page not present, bring it from disk or somewhere else
     __print_panic_msg("WIP page fault route", param);
     while (1)
@@ -90,6 +94,12 @@ segv_term:
             param->eip);
     terminate_proc(LXSEGFAULT);
     // should not reach
             param->eip);
     terminate_proc(LXSEGFAULT);
     // should not reach
+    while (1)
+        ;
+
+resolved:
+    cpu_invplg(ptr);
+    return;
 }
 
 int
 }
 
 int
index c09db9e37e08bbaab8c42e17be81f03a06e5a494..74dad78748e7aa4136bf67c75dec5c60b91483dc 100644 (file)
@@ -1,12 +1,10 @@
 #include <arch/x86/tss.h>
 #include <lunaix/common.h>
 
 #include <arch/x86/tss.h>
 #include <lunaix/common.h>
 
-struct x86_tss _tss = {
-    .link = 0,
-    .esp0 = KSTACK_START,
-    .ss0  = KDATA_SEG
-};
+struct x86_tss _tss = { .link = 0, .esp0 = KSTACK_TOP, .ss0 = KDATA_SEG };
 
 
-void tss_update_esp(uint32_t esp0) {
+void
+tss_update_esp(uint32_t esp0)
+{
     _tss.esp0 = esp0;
 }
\ No newline at end of file
     _tss.esp0 = esp0;
 }
\ No newline at end of file
index 59d934748639ab6a26a83b0cf10e0d4b178b9629..257112e7d438ccaf81f5a28654222ee4db29b445 100644 (file)
@@ -96,7 +96,7 @@ _kernel_init()
 void
 spawn_proc0()
 {
 void
 spawn_proc0()
 {
-    struct proc_info proc0;
+    struct proc_info* proc0 = alloc_process();
 
     /**
      * @brief
 
     /**
      * @brief
@@ -113,15 +113,14 @@ spawn_proc0()
      * 目前的解决方案是2
      */
 
      * 目前的解决方案是2
      */
 
-    init_proc(&proc0);
-    proc0.intr_ctx = (isr_param){ .registers = { .ds = KDATA_SEG,
-                                                 .es = KDATA_SEG,
-                                                 .fs = KDATA_SEG,
-                                                 .gs = KDATA_SEG },
-                                  .cs = KCODE_SEG,
-                                  .eip = (void*)__proc0,
-                                  .ss = KDATA_SEG,
-                                  .eflags = cpu_reflags() };
+    proc0->intr_ctx = (isr_param){ .registers = { .ds = KDATA_SEG,
+                                                  .es = KDATA_SEG,
+                                                  .fs = KDATA_SEG,
+                                                  .gs = KDATA_SEG },
+                                   .cs = KCODE_SEG,
+                                   .eip = (void*)__proc0,
+                                   .ss = KDATA_SEG,
+                                   .eflags = cpu_reflags() };
 
     // 方案1:必须在读取eflags之后禁用。否则当进程被调度时,中断依然是关闭的!
     // cpu_disable_interrupt();
 
     // 方案1:必须在读取eflags之后禁用。否则当进程被调度时,中断依然是关闭的!
     // cpu_disable_interrupt();
@@ -129,10 +128,10 @@ spawn_proc0()
     /* Ok... 首先fork进我们的零号进程,而后由那里,我们fork进init进程。 */
 
     // 把当前虚拟地址空间(内核)复制一份。
     /* Ok... 首先fork进我们的零号进程,而后由那里,我们fork进init进程。 */
 
     // 把当前虚拟地址空间(内核)复制一份。
-    proc0.page_table = vmm_dup_vmspace(proc0.pid);
+    proc0->page_table = vmm_dup_vmspace(proc0->pid);
 
     // 直接切换到新的拷贝,进行配置。
 
     // 直接切换到新的拷贝,进行配置。
-    cpu_lcr3(proc0.page_table);
+    cpu_lcr3(proc0->page_table);
 
     // 为内核创建一个专属栈空间。
     for (size_t i = 0; i < (KSTACK_SIZE >> PG_SIZE_BITS); i++) {
 
     // 为内核创建一个专属栈空间。
     for (size_t i = 0; i < (KSTACK_SIZE >> PG_SIZE_BITS); i++) {
@@ -154,25 +153,25 @@ spawn_proc0()
                  "pushl $0\n"
                  "movl %%esp, %0\n"
                  "movl %%ebx, %%esp\n"
                  "pushl $0\n"
                  "movl %%esp, %0\n"
                  "movl %%ebx, %%esp\n"
-                 : "=m"(proc0.intr_ctx.registers.esp)
-                 : "i"(KSTACK_TOP), "i"(KCODE_SEG), "r"(proc0.intr_ctx.eip)
+                 : "=m"(proc0->intr_ctx.registers.esp)
+                 : "i"(KSTACK_TOP), "i"(KCODE_SEG), "r"(proc0->intr_ctx.eip)
                  : "%ebx", "memory");
 
     // 向调度器注册进程。
                  : "%ebx", "memory");
 
     // 向调度器注册进程。
-    push_process(&proc0);
+    commit_process(proc0);
 
     // 由于时钟中断与APIC未就绪,我们需要手动进行第一次调度。这里也会同时隐式地恢复我们的eflags.IF位
 
     // 由于时钟中断与APIC未就绪,我们需要手动进行第一次调度。这里也会同时隐式地恢复我们的eflags.IF位
-    struct proc_info* proc = get_process(0);
-    assert_msg(proc, "fail to get proc0!");
-
-    proc->state = PROC_RUNNING;
+    proc0->state = PROC_RUNNING;
     asm volatile("pushl %0\n"
     asm volatile("pushl %0\n"
-                 "jmp switch_to\n" ::"r"(proc));
+                 "jmp switch_to\n" ::"r"(proc0));
 
     /* Should not return */
     assert_msg(0, "Unexpected Return");
 }
 
 
     /* Should not return */
     assert_msg(0, "Unexpected Return");
 }
 
+extern void __usrtext_start;
+extern void __usrtext_end;
+
 // 按照 Memory map 标识可用的物理页
 void
 setup_memory(multiboot_memory_map_t* map, size_t map_size)
 // 按照 Memory map 标识可用的物理页
 void
 setup_memory(multiboot_memory_map_t* map, size_t map_size)
@@ -216,6 +215,14 @@ setup_memory(multiboot_memory_map_t* map, size_t map_size)
                         VMAP_NULL);
     }
 
                         VMAP_NULL);
     }
 
+    assert_msg(!((uintptr_t)&__usrtext_start & 0xfff) &&
+                 !((uintptr_t)&__usrtext_end & 0xfff),
+               "Bad usrtext alignment");
+
+    for (uintptr_t i = &__usrtext_start; i < &__usrtext_end; i += PG_SIZE) {
+        vmm_set_mapping(PD_REFERENCED, i, V2P(i), PG_PREM_UR, VMAP_NULL);
+    }
+
     // 更新VGA缓冲区位置至虚拟地址
     tty_set_buffer((void*)VGA_BUFFER_VADDR);
 
     // 更新VGA缓冲区位置至虚拟地址
     tty_set_buffer((void*)VGA_BUFFER_VADDR);
 
index 19e7effec7888bf22740e2decbc02036bb179ab3..57e2bda22421da102c8b063bca8adfd2f1fd58c4 100644 (file)
@@ -16,8 +16,9 @@ LOG_MODULE("INIT")
 
 // #define FORK_BOMB_DEMO
 #define WAIT_DEMO
 
 // #define FORK_BOMB_DEMO
 #define WAIT_DEMO
+#define IN_USER_MODE
 
 
-void
+void __USER__
 _lxinit_main()
 {
 #ifdef FORK_BOMB_DEMO
 _lxinit_main()
 {
 #ifdef FORK_BOMB_DEMO
@@ -93,15 +94,15 @@ _lxinit_main()
     struct kdb_keyinfo_pkt keyevent;
     while (1) {
         if (!kbd_recv_key(&keyevent)) {
     struct kdb_keyinfo_pkt keyevent;
     while (1) {
         if (!kbd_recv_key(&keyevent)) {
-            // yield();
+            yield();
             continue;
         }
         if ((keyevent.state & KBD_KEY_FPRESSED) &&
             (keyevent.keycode & 0xff00) <= KEYPAD) {
             tty_put_char((char)(keyevent.keycode & 0x00ff));
             continue;
         }
         if ((keyevent.state & KBD_KEY_FPRESSED) &&
             (keyevent.keycode & 0xff00) <= KEYPAD) {
             tty_put_char((char)(keyevent.keycode & 0x00ff));
-            tty_sync_cursor();
+            // FIXME: io to vga port is privileged and cause #GP in user mode
+            // tty_sync_cursor();
         }
     }
         }
     }
-
     spin();
 }
\ No newline at end of file
     spin();
 }
\ No newline at end of file
index d9fddeb0688da964512df788207637f959e6e0dd..1f706dc362140c5203a36b9371b04571b8f492b1 100644 (file)
@@ -2,7 +2,7 @@
 #include <lunaix/mm/region.h>
 
 void
 #include <lunaix/mm/region.h>
 
 void
-region_add(struct mm_region** regions,
+region_add(struct mm_region* regions,
            unsigned long start,
            unsigned long end,
            unsigned int attr)
            unsigned long start,
            unsigned long end,
            unsigned int attr)
@@ -11,55 +11,47 @@ region_add(struct mm_region** regions,
 
     *region = (struct mm_region){ .attr = attr, .end = end, .start = start };
 
 
     *region = (struct mm_region){ .attr = attr, .end = end, .start = start };
 
-    if (!*regions) {
-        llist_init_head(&region->head);
-        *regions = region;
-    } else {
-        llist_append(&(*regions)->head, &region->head);
-    }
+    llist_append(&regions->head, &region->head);
 }
 
 void
 }
 
 void
-region_release_all(struct mm_region** regions)
+region_release_all(struct mm_region* regions)
 {
     struct mm_region *pos, *n;
 
 {
     struct mm_region *pos, *n;
 
-    llist_for_each(pos, n, &(*regions)->head, head)
+    llist_for_each(pos, n, &regions->head, head)
     {
         lxfree(pos);
     }
     {
         lxfree(pos);
     }
-
-    *regions = NULL;
 }
 
 void
 }
 
 void
-region_copy(struct mm_region** src, struct mm_region** dest)
+region_copy(struct mm_region* src, struct mm_region* dest)
 {
 {
-    if (!*src) {
+    if (!src) {
         return;
     }
 
     struct mm_region *pos, *n;
 
         return;
     }
 
     struct mm_region *pos, *n;
 
-    llist_init_head(*dest);
-    llist_for_each(pos, n, &(*src)->head, head)
+    llist_for_each(pos, n, &src->head, head)
     {
         region_add(dest, pos->start, pos->end, pos->attr);
     }
 }
 
 struct mm_region*
     {
         region_add(dest, pos->start, pos->end, pos->attr);
     }
 }
 
 struct mm_region*
-region_get(struct mm_region** regions, unsigned long vaddr)
+region_get(struct mm_region* regions, unsigned long vaddr)
 {
 {
-    if (!*regions) {
+    if (!regions) {
         return NULL;
     }
 
     struct mm_region *pos, *n;
 
         return NULL;
     }
 
     struct mm_region *pos, *n;
 
-    llist_for_each(pos, n, &(*regions)->head, head)
+    llist_for_each(pos, n, &regions->head, head)
     {
     {
-        if (vaddr >= pos->start && vaddr < pos->end) {
+        if (pos->start <= vaddr && vaddr < pos->end) {
             return pos;
         }
     }
             return pos;
         }
     }
index 40e3724d5266a157d878dc5c3e74c08df08e451a..fe3d65cc46b7ca40ec4eacb232772754dbceba8d 100644 (file)
@@ -51,7 +51,9 @@ vmm_set_mapping(uintptr_t mnt,
         }
 
         // This must be writable
         }
 
         // This must be writable
-        l1pt->entry[l1_inx] = NEW_L1_ENTRY(attr | PG_WRITE, new_l1pt_pa);
+        l1pt->entry[l1_inx] =
+          NEW_L1_ENTRY(attr | PG_WRITE | PG_PRESENT, new_l1pt_pa);
+
         memset((void*)l2pt, 0, PG_SIZE);
     } else {
         x86_pte_t pte = l2pt->entry[l2_inx];
         memset((void*)l2pt, 0, PG_SIZE);
     } else {
         x86_pte_t pte = l2pt->entry[l2_inx];
index 2b21ac7c9b5d73e56fa8ff30674bf07857b6a5dd..4cc414c4d28cd92b8b91ae66b40bc2b496ecf6ab 100644 (file)
@@ -25,7 +25,23 @@ init_platform();
 void
 lock_reserved_memory();
 
 void
 lock_reserved_memory();
 
-// #define ENABLE_USER_MODE
+void
+unlock_reserved_memory();
+
+void
+__do_reserved_memory(int unlock);
+
+void __USER__
+__proc0_usr()
+{
+    if (!fork()) {
+        asm("jmp _lxinit_main");
+    }
+
+    while (1) {
+        yield();
+    }
+}
 
 /**
  * @brief LunaixOS的零号进程,该进程永远为可执行。
 
 /**
  * @brief LunaixOS的零号进程,该进程永远为可执行。
@@ -39,7 +55,9 @@ void
 __proc0()
 {
     init_platform();
 __proc0()
 {
     init_platform();
-#ifdef ENABLE_USER_MODE
+
+    init_proc_user_space(__current);
+
     asm volatile("movw %0, %%ax\n"
                  "movw %%ax, %%es\n"
                  "movw %%ax, %%ds\n"
     asm volatile("movw %0, %%ax\n"
                  "movw %%ax, %%es\n"
                  "movw %%ax, %%ds\n"
@@ -52,16 +70,8 @@ __proc0()
                  "retf" ::"i"(UDATA_SEG),
                  "i"(USTACK_TOP & ~0xf),
                  "i"(UCODE_SEG),
                  "retf" ::"i"(UDATA_SEG),
                  "i"(USTACK_TOP & ~0xf),
                  "i"(UCODE_SEG),
-                 "r"(&&usr));
-#endif
-usr:
-    if (!fork()) {
-        asm("jmp _lxinit_main");
-    }
-
-    while (1) {
-        yield();
-    }
+                 "r"(__proc0_usr)
+                 : "eax", "memory");
 }
 
 extern uint8_t __kernel_start;            /* link/linker.ld */
 }
 
 extern uint8_t __kernel_start;            /* link/linker.ld */
@@ -74,14 +84,11 @@ init_platform()
 {
     assert_msg(kalloc_init(), "Fail to initialize heap");
 
 {
     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
     // 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_del_mapping(PD_REFERENCED, (void*)(i << PG_SIZE_BITS));
-    }
+    // for (size_t i = 0; i < 3; i++) {
+    //     vmm_del_mapping(PD_REFERENCED, (void*)(i << PG_SIZE_BITS));
+    // }
 
     // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射
     lock_reserved_memory();
 
     // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射
     lock_reserved_memory();
@@ -105,13 +112,28 @@ init_platform()
 
     syscall_install();
 
 
     syscall_install();
 
-    for (size_t i = 256; i < hhk_init_pg_count; i++) {
-        vmm_del_mapping(PD_REFERENCED, (void*)(i << PG_SIZE_BITS));
+    unlock_reserved_memory();
+
+    for (size_t i = 0; i < (uintptr_t)(&__init_hhk_end); i += PG_SIZE) {
+        vmm_del_mapping(PD_REFERENCED, (void*)i);
+        pmm_free_page(KERNEL_PID, (void*)i);
     }
 }
 
 void
 lock_reserved_memory()
     }
 }
 
 void
 lock_reserved_memory()
+{
+    __do_reserved_memory(0);
+}
+
+void
+unlock_reserved_memory()
+{
+    __do_reserved_memory(1);
+}
+
+void
+__do_reserved_memory(int unlock)
 {
     multiboot_memory_map_t* mmaps = _k_init_mb_info->mmap_addr;
     size_t map_size =
 {
     multiboot_memory_map_t* mmaps = _k_init_mb_info->mmap_addr;
     size_t map_size =
@@ -119,18 +141,29 @@ lock_reserved_memory()
     // v_mapping mapping;
     for (unsigned int i = 0; i < map_size; i++) {
         multiboot_memory_map_t mmap = mmaps[i];
     // v_mapping mapping;
     for (unsigned int i = 0; i < map_size; i++) {
         multiboot_memory_map_t mmap = mmaps[i];
-        if (mmap.type == MULTIBOOT_MEMORY_AVAILABLE) {
+        uint8_t* pa = PG_ALIGN(mmap.addr_low);
+        if (mmap.type == MULTIBOOT_MEMORY_AVAILABLE || pa <= MEM_4MB) {
+            // Don't fuck up our kernel code or any free area!
             continue;
         }
             continue;
         }
-        uint8_t* pa = PG_ALIGN(mmap.addr_low);
         size_t pg_num = CEIL(mmap.len_low, PG_SIZE_BITS);
         size_t pg_num = CEIL(mmap.len_low, PG_SIZE_BITS);
-        for (size_t j = 0; j < pg_num; j++) {
-            uintptr_t _pa = pa + (j << PG_SIZE_BITS);
-            // if (vmm_lookup(_pa, &mapping) && *mapping.pte) {
-            //     continue;
-            // }
-            vmm_set_mapping(PD_REFERENCED, _pa, _pa, PG_PREM_R, VMAP_IGNORE);
-            pmm_mark_page_occupied(KERNEL_PID, _pa >> 12, 0);
+        size_t j = 0;
+        if (!unlock) {
+            for (; j < pg_num; j++) {
+                uintptr_t _pa = pa + (j << PG_SIZE_BITS);
+                if (_pa >= KERNEL_MM_BASE) {
+                    // Don't fuck up our kernel space!
+                    break;
+                }
+                vmm_set_mapping(PD_REFERENCED, _pa, _pa, PG_PREM_R, VMAP_NULL);
+            }
+            // Save the progress for later unmapping.
+            mmaps[i].len_low = j * PG_SIZE;
+        } else {
+            for (; j < pg_num; j++) {
+                uintptr_t _pa = pa + (j << PG_SIZE_BITS);
+                vmm_del_mapping(PD_REFERENCED, _pa);
+            }
         }
     }
 }
\ No newline at end of file
         }
     }
 }
\ No newline at end of file
index a41c6a6f170ffd7814169982cdee4ac79cc00bb5..a783efe13987a6a2b1c46fd932d67b863314b594 100644 (file)
@@ -47,7 +47,7 @@ __dup_pagetable(pid_t pid, uintptr_t mount_point)
             pt->entry[j] = pte;
         }
 
             pt->entry[j] = pte;
         }
 
-        ptd->entry[i] = (uintptr_t)pt_pp | PG_PREM_RW;
+        ptd->entry[i] = (uintptr_t)pt_pp | PG_ENTRY_FLAGS(ptde);
     }
 
     ptd->entry[PG_MAX_ENTRIES - 1] = NEW_L1_ENTRY(T_SELF_REF_PERM, ptd_pp);
     }
 
     ptd->entry[PG_MAX_ENTRIES - 1] = NEW_L1_ENTRY(T_SELF_REF_PERM, ptd_pp);
@@ -135,27 +135,38 @@ __DEFINE_LXSYSCALL2(int, setpgid, pid_t, pid, pid_t, pgid)
 }
 
 void
 }
 
 void
-init_proc(struct proc_info* pcb)
+init_proc_user_space(struct proc_info* pcb)
 {
 {
-    memset(pcb, 0, sizeof(*pcb));
+    vmm_mount_pd(PD_MOUNT_1, pcb->page_table);
 
 
-    pcb->pid = alloc_pid();
-    pcb->created = clock_systime();
-    pcb->state = PROC_CREATED;
-    pcb->pgid = pcb->pid;
+    /*---  分配用户栈  ---*/
+
+    // 注册用户栈区域
+    region_add(
+      &pcb->mm.regions, USTACK_END, USTACK_TOP, REGION_RW | REGION_RSHARED);
+
+    // 预留地址空间,具体物理页将由Page Fault Handler按需分配。
+    for (uintptr_t i = PG_ALIGN(USTACK_END); i < USTACK_TOP; i += PG_SIZE) {
+        vmm_set_mapping(PD_MOUNT_1, i, 0, PG_ALLOW_USER | PG_WRITE, VMAP_NULL);
+    }
+
+    // todo: other uspace initialization stuff
+
+    vmm_unmount_pd(PD_MOUNT_1);
 }
 
 void
 __mark_region(uintptr_t start_vpn, uintptr_t end_vpn, int attr)
 {
 }
 
 void
 __mark_region(uintptr_t start_vpn, uintptr_t end_vpn, int attr)
 {
-    for (size_t i = start_vpn; i < end_vpn; i++) {
+    for (size_t i = start_vpn; i <= end_vpn; i++) {
         x86_pte_t* curproc = &PTE_MOUNTED(PD_REFERENCED, i);
         x86_pte_t* newproc = &PTE_MOUNTED(PD_MOUNT_1, i);
         cpu_invplg(newproc);
 
         x86_pte_t* curproc = &PTE_MOUNTED(PD_REFERENCED, i);
         x86_pte_t* newproc = &PTE_MOUNTED(PD_MOUNT_1, i);
         cpu_invplg(newproc);
 
-        if (attr == REGION_RSHARED) {
+        if ((attr & REGION_MODE_MASK) == REGION_RSHARED) {
             // 如果读共享,则将两者的都标注为只读,那么任何写入都将会应用COW策略。
             cpu_invplg(curproc);
             // 如果读共享,则将两者的都标注为只读,那么任何写入都将会应用COW策略。
             cpu_invplg(curproc);
+            cpu_invplg(i << 12);
             *curproc = *curproc & ~PG_WRITE;
             *newproc = *newproc & ~PG_WRITE;
         } else {
             *curproc = *curproc & ~PG_WRITE;
             *newproc = *newproc & ~PG_WRITE;
         } else {
@@ -168,43 +179,38 @@ __mark_region(uintptr_t start_vpn, uintptr_t end_vpn, int attr)
 pid_t
 dup_proc()
 {
 pid_t
 dup_proc()
 {
-    struct proc_info pcb;
-    init_proc(&pcb);
-    pcb.mm = __current->mm;
-    pcb.intr_ctx = __current->intr_ctx;
-    pcb.parent = __current;
+    struct proc_info* pcb = alloc_process();
+    pcb->mm.u_heap = __current->mm.u_heap;
+    pcb->intr_ctx = __current->intr_ctx;
+    pcb->parent = __current;
 
 
-    region_copy(&__current->mm.regions, &pcb.mm.regions);
+    region_copy(&__current->mm.regions, &pcb->mm.regions);
 
 
-    setup_proc_mem(&pcb, PD_REFERENCED);
+    setup_proc_mem(pcb, PD_REFERENCED);
 
     // 根据 mm_region 进一步配置页表
 
     // 根据 mm_region 进一步配置页表
-    if (!__current->mm.regions) {
-        goto not_copy;
-    }
 
     struct mm_region *pos, *n;
 
     struct mm_region *pos, *n;
-    llist_for_each(pos, n, &pcb.mm.regions->head, head)
+    llist_for_each(pos, n, &pcb->mm.regions.head, head)
     {
         // 如果写共享,则不作处理。
         if ((pos->attr & REGION_WSHARED)) {
             continue;
         }
 
     {
         // 如果写共享,则不作处理。
         if ((pos->attr & REGION_WSHARED)) {
             continue;
         }
 
-        uintptr_t start_vpn = PG_ALIGN(pos->start) >> 12;
-        uintptr_t end_vpn = PG_ALIGN(pos->end) >> 12;
+        uintptr_t start_vpn = pos->start >> 12;
+        uintptr_t end_vpn = pos->end >> 12;
         __mark_region(start_vpn, end_vpn, pos->attr);
     }
 
         __mark_region(start_vpn, end_vpn, pos->attr);
     }
 
-not_copy:
     vmm_unmount_pd(PD_MOUNT_1);
 
     // 正如同fork,返回两次。
     vmm_unmount_pd(PD_MOUNT_1);
 
     // 正如同fork,返回两次。
-    pcb.intr_ctx.registers.eax = 0;
+    pcb->intr_ctx.registers.eax = 0;
 
 
-    push_process(&pcb);
+    commit_process(pcb);
 
 
-    return pcb.pid;
+    return pcb->pid;
 }
 
 extern void __kernel_end;
 }
 
 extern void __kernel_end;
@@ -241,12 +247,6 @@ setup_proc_mem(struct proc_info* proc, uintptr_t usedMnt)
     // 我们不需要分配内核的区域,因为所有的内核代码和数据段只能通过系统调用来访问,任何非法的访问
     // 都会导致eip落在区域外面,从而segmentation fault.
 
     // 我们不需要分配内核的区域,因为所有的内核代码和数据段只能通过系统调用来访问,任何非法的访问
     // 都会导致eip落在区域外面,从而segmentation fault.
 
-    // 定义用户栈区域,但是不分配实际的物理页。我们会在Page fault
-    // handler里面实现动态分配物理页的逻辑。(虚拟内存的好处!)
-    // FIXME: 这里应该放到spawn_proc里面。
-    // region_add(proc, USTACK_END, USTACK_SIZE, REGION_PRIVATE |
-    // REGION_RW);
-
     // 至于其他的区域我们暂时没有办法知道,因为那需要知道用户程序的信息。我们留到之后在处理。
     proc->page_table = pt_copy;
 }
\ No newline at end of file
     // 至于其他的区域我们暂时没有办法知道,因为那需要知道用户程序的信息。我们留到之后在处理。
     proc->page_table = pt_copy;
 }
\ No newline at end of file
index ee25ebb39f36bff3349adcd436c4438bef073cca..1a9743dd9752b182e6e151ef645a91c1d76eea68 100644 (file)
@@ -49,8 +49,9 @@ run(struct proc_info* proc)
     }
     proc->state = PROC_RUNNING;
 
     }
     proc->state = PROC_RUNNING;
 
-    // FIXME: 这里还是得再考虑一下。
+    // XXX: 我们需要这一步吗?
     // tss_update_esp(__current->intr_ctx.esp);
     // tss_update_esp(__current->intr_ctx.esp);
+
     apic_done_servicing();
 
     asm volatile("pushl %0\n"
     apic_done_servicing();
 
     asm volatile("pushl %0\n"
@@ -168,8 +169,8 @@ done:
     return destroy_process(proc->pid);
 }
 
     return destroy_process(proc->pid);
 }
 
-pid_t
-alloc_pid()
+struct proc_info*
+alloc_process()
 {
     pid_t i = 0;
     for (;
 {
     pid_t i = 0;
     for (;
@@ -180,29 +181,35 @@ alloc_pid()
     if (i == MAX_PROCESS) {
         panick("Panic in Ponyville shimmer!");
     }
     if (i == MAX_PROCESS) {
         panick("Panic in Ponyville shimmer!");
     }
-    return i;
-}
-
-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) {
+    if (i == sched_ctx.ptable_len) {
         sched_ctx.ptable_len++;
     }
 
         sched_ctx.ptable_len++;
     }
 
-    sched_ctx._procs[index] = *process;
+    struct proc_info* proc = &sched_ctx._procs[i];
+    memset(proc, 0, sizeof(*proc));
 
 
-    process = &sched_ctx._procs[index];
+    proc->state = PROC_CREATED;
+    proc->pid = i;
+    proc->created = clock_systime();
+    proc->pgid = proc->pid;
 
 
-    // make sure the reference is relative to process table
-    llist_init_head(&process->children);
-    llist_init_head(&process->grp_member);
+    llist_init_head(&proc->mm.regions);
+    llist_init_head(&proc->children);
+    llist_init_head(&proc->grp_member);
+
+    return proc;
+}
+
+void
+commit_process(struct proc_info* process)
+{
+    assert(process == &sched_ctx._procs[process->pid]);
+
+    if (process->state != PROC_CREATED) {
+        __current->k_status = LXINVL;
+        return;
+    }
 
     // every process is the child of first process (pid=1)
     if (process->parent) {
 
     // every process is the child of first process (pid=1)
     if (process->parent) {
@@ -230,12 +237,10 @@ destroy_process(pid_t pid)
     proc->state = PROC_DESTROY;
     llist_delete(&proc->siblings);
 
     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)
-        {
-            lxfree(pos);
-        }
+    struct mm_region *pos, *n;
+    llist_for_each(pos, n, &proc->mm.regions.head, head)
+    {
+        lxfree(pos);
     }
 
     vmm_mount_pd(PD_MOUNT_1, proc->page_table);
     }
 
     vmm_mount_pd(PD_MOUNT_1, proc->page_table);
index 4cb205105d84b6086fbfc9f7573574cdcc17e697..5aa0137421a7e5249aa4b51e8c5ea1d1a69ef044 100644 (file)
@@ -1,27 +1,26 @@
-#include <lunaix/spike.h>
 #include <arch/x86/interrupts.h>
 #include <klibc/stdio.h>
 #include <arch/x86/interrupts.h>
 #include <klibc/stdio.h>
+#include <lunaix/spike.h>
 
 static char buffer[1024];
 
 
 static char buffer[1024];
 
-void __assert_fail(const char* expr, const char* file, unsigned int line) {
+void
+__assert_fail(const char* expr, const char* file, unsigned int line)
+{
     sprintf(buffer, "%s (%s:%u)", expr, file, line);
 
     // Here we load the buffer's address into %edi ("D" constraint)
     //  This is a convention we made that the LUNAIX_SYS_PANIC syscall will
     sprintf(buffer, "%s (%s:%u)", expr, file, line);
 
     // Here we load the buffer's address into %edi ("D" constraint)
     //  This is a convention we made that the LUNAIX_SYS_PANIC syscall will
-    //  print the panic message passed via %edi. (see kernel/asm/x86/interrupts.c)
-    asm(
-        "int %0"
-        ::"i"(LUNAIX_SYS_PANIC), "D"(buffer)
-    );
+    //  print the panic message passed via %edi. (see
+    //  kernel/asm/x86/interrupts.c)
+    asm("int %0" ::"i"(LUNAIX_SYS_PANIC), "D"(buffer));
 
 
-    spin();     // never reach
+    spin(); // never reach
 }
 
 }
 
-void panick(const char* msg) {
-    asm(
-        "int %0"
-        ::"i"(LUNAIX_SYS_PANIC), "D"(msg)
-    );
+void
+panick(const char* msg)
+{
+    asm("int %0" ::"i"(LUNAIX_SYS_PANIC), "D"(msg));
     spin();
     spin();
-}
\ No newline at end of file
+}
index c779ed524029b6eaa89f6efc11a92f6a0512ff86..41642390ecdd4c03e4231699010243e2a3d9dbc7 100644 (file)
@@ -1,8 +1,8 @@
+#include <hal/io.h>
 #include <klibc/string.h>
 #include <klibc/string.h>
-#include <lunaix/tty/tty.h>
 #include <lunaix/common.h>
 #include <lunaix/common.h>
+#include <lunaix/tty/tty.h>
 #include <stdint.h>
 #include <stdint.h>
-#include <hal/io.h>
 
 #define TTY_WIDTH 80
 #define TTY_HEIGHT 25
 
 #define TTY_WIDTH 80
 #define TTY_HEIGHT 25
@@ -14,18 +14,22 @@ static vga_attribute tty_theme_color = VGA_COLOR_BLACK;
 static uint32_t tty_x = 0;
 static uint32_t tty_y = 0;
 
 static uint32_t tty_x = 0;
 static uint32_t tty_y = 0;
 
-void tty_init(void* vga_buf) {
+void
+tty_init(void* vga_buf)
+{
     tty_vga_buffer = (vga_attribute*)vga_buf;
     tty_clear();
 
     io_outb(0x3D4, 0x0A);
     tty_vga_buffer = (vga_attribute*)vga_buf;
     tty_clear();
 
     io_outb(0x3D4, 0x0A);
-       io_outb(0x3D5, (io_inb(0x3D5) & 0xC0) | 13);
-       io_outb(0x3D4, 0x0B);
-       io_outb(0x3D5, (io_inb(0x3D5) & 0xE0) | 15);
+    io_outb(0x3D5, (io_inb(0x3D5) & 0xC0) | 13);
+
+    io_outb(0x3D4, 0x0B);
+    io_outb(0x3D5, (io_inb(0x3D5) & 0xE0) | 15);
 }
 
 }
 
-void tty_set_buffer(void* vga_buf) {
+void
+tty_set_buffer(void* vga_buf)
+{
     tty_vga_buffer = (vga_attribute*)vga_buf;
 }
 
     tty_vga_buffer = (vga_attribute*)vga_buf;
 }
 
@@ -50,10 +54,12 @@ tty_put_char(char chr)
             break;
         case '\x08':
             tty_x = tty_x ? tty_x - 1 : 0;
             break;
         case '\x08':
             tty_x = tty_x ? tty_x - 1 : 0;
-            *(tty_vga_buffer + tty_x + tty_y * TTY_WIDTH) = (tty_theme_color | 0x20);
+            *(tty_vga_buffer + tty_x + tty_y * TTY_WIDTH) =
+              (tty_theme_color | 0x20);
             break;
         default:
             break;
         default:
-            *(tty_vga_buffer + tty_x + tty_y * TTY_WIDTH) = (tty_theme_color | chr);
+            *(tty_vga_buffer + tty_x + tty_y * TTY_WIDTH) =
+              (tty_theme_color | chr);
             tty_x++;
             break;
     }
             tty_x++;
             break;
     }
@@ -67,12 +73,15 @@ tty_put_char(char chr)
     }
 }
 
     }
 }
 
-void tty_sync_cursor() {
+void
+tty_sync_cursor()
+{
     tty_set_cursor(tty_x, tty_y);
 }
 
     tty_set_cursor(tty_x, tty_y);
 }
 
-
-void tty_set_cursor(uint8_t x, uint8_t y) {
+void
+tty_set_cursor(uint8_t x, uint8_t y)
+{
     if (x >= TTY_WIDTH || y >= TTY_HEIGHT) {
         x = y = 0;
     }
     if (x >= TTY_WIDTH || y >= TTY_HEIGHT) {
         x = y = 0;
     }
@@ -90,7 +99,11 @@ tty_put_str(char* str)
         tty_put_char(*str);
         str++;
     }
         tty_put_char(*str);
         str++;
     }
-    tty_sync_cursor();
+    // FIXME: This does not work in user mode.
+    // Work around:
+    //  1. (Easy) Define an IO Permission bitmap in TSS
+    //  2. (More effort) Mount onto file system. (/dev/tty)
+    // tty_sync_cursor();
 }
 
 void
 }
 
 void
@@ -115,26 +128,29 @@ tty_clear()
 }
 
 void
 }
 
 void
-tty_clear_line(unsigned int y) {
-    for (size_t i = 0; i < TTY_WIDTH; i++)
-    {
+tty_clear_line(unsigned int y)
+{
+    for (size_t i = 0; i < TTY_WIDTH; i++) {
         *(tty_vga_buffer + i + y * TTY_WIDTH) = tty_theme_color;
     }
 }
 
 void
         *(tty_vga_buffer + i + y * TTY_WIDTH) = tty_theme_color;
     }
 }
 
 void
-tty_set_cpos(unsigned int x, unsigned int y) {
+tty_set_cpos(unsigned int x, unsigned int y)
+{
     tty_x = x % TTY_WIDTH;
     tty_y = y % TTY_HEIGHT;
 }
 
 void
     tty_x = x % TTY_WIDTH;
     tty_y = y % TTY_HEIGHT;
 }
 
 void
-tty_get_cpos(unsigned int* x, unsigned int* y) {
+tty_get_cpos(unsigned int* x, unsigned int* y)
+{
     *x = tty_x;
     *y = tty_y;
 }
 
 vga_attribute
     *x = tty_x;
     *y = tty_y;
 }
 
 vga_attribute
-tty_get_theme() {
+tty_get_theme()
+{
     return tty_theme_color;
 }
\ No newline at end of file
     return tty_theme_color;
 }
\ No newline at end of file
index 2bd3ded63ae48b8b4bcad3fd302ff09ac1328aa5..ba3a3853a232d4fb4c9bd10df8a1175f660ff367 100644 (file)
@@ -41,6 +41,12 @@ SECTIONS {
         build/obj/hal/*.o (.text)
     }
 
         build/obj/hal/*.o (.text)
     }
 
+    __usrtext_start = ALIGN(4K);
+    .usrtext BLOCK(4K) : AT ( ADDR(.usrtext) - 0xC0000000 ) {
+        build/obj/kernel/*.o (.usrtext)
+    }
+    __usrtext_end = ALIGN(4K);
+
     .bss BLOCK(4K) : AT ( ADDR(.bss) - 0xC0000000 ) {
         build/obj/kernel/*.o (.bss)
         build/obj/hal/*.o (.bss)
     .bss BLOCK(4K) : AT ( ADDR(.bss) - 0xC0000000 ) {
         build/obj/kernel/*.o (.bss)
         build/obj/hal/*.o (.bss)