Merge branch 'master' into prog-loader
authorMinep <zelong56@gmail.com>
Tue, 17 Jan 2023 10:30:13 +0000 (10:30 +0000)
committerMinep <zelong56@gmail.com>
Tue, 17 Jan 2023 10:30:13 +0000 (10:30 +0000)
122 files changed:
README.md
docs/README_en.md
lunaix-os/.gitignore
lunaix-os/.vscode/c_cpp_properties.json
lunaix-os/arch/x86/boot.S
lunaix-os/config/make-cc
lunaix-os/config/make-locations
lunaix-os/config/make-os
lunaix-os/debug/bg_lsdbg.c
lunaix-os/debug/gdbstub.c
lunaix-os/debug/sdbg.c
lunaix-os/hal/ahci/io_event.c
lunaix-os/includes/arch/x86/interrupts.h
lunaix-os/includes/hal/rnd.h
lunaix-os/includes/lunaix/common.h
lunaix-os/includes/lunaix/ds/llist.h
lunaix-os/includes/lunaix/elf.h [new file with mode: 0644]
lunaix-os/includes/lunaix/fctrl.h [deleted file]
lunaix-os/includes/lunaix/foptions.h
lunaix-os/includes/lunaix/fs.h
lunaix-os/includes/lunaix/ioctl.h
lunaix-os/includes/lunaix/ld.h [new file with mode: 0644]
lunaix-os/includes/lunaix/lunistd.h [deleted file]
lunaix-os/includes/lunaix/lxsignal.h [deleted file]
lunaix-os/includes/lunaix/mm/dmm.h [deleted file]
lunaix-os/includes/lunaix/mm/kalloc.h [deleted file]
lunaix-os/includes/lunaix/mm/mm.h
lunaix-os/includes/lunaix/mm/mmap.h [new file with mode: 0644]
lunaix-os/includes/lunaix/mm/page.h
lunaix-os/includes/lunaix/mm/region.h
lunaix-os/includes/lunaix/mm/vmm.h
lunaix-os/includes/lunaix/process.h
lunaix-os/includes/lunaix/signal.h
lunaix-os/includes/lunaix/spike.h
lunaix-os/includes/lunaix/status.h
lunaix-os/includes/lunaix/syscall.h
lunaix-os/includes/lunaix/syscall_utils.h [new file with mode: 0644]
lunaix-os/includes/lunaix/types.h
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
lunaix-os/kernel/asm/x86/syscall.S
lunaix-os/kernel/demos/dir_read.c [deleted file]
lunaix-os/kernel/demos/input_test.c [deleted file]
lunaix-os/kernel/demos/iotest.c [deleted file]
lunaix-os/kernel/demos/signal_demo.c [deleted file]
lunaix-os/kernel/demos/simple_sh.c [deleted file]
lunaix-os/kernel/device/devfs.c
lunaix-os/kernel/device/device.c
lunaix-os/kernel/fs/iso9660/directory.c
lunaix-os/kernel/fs/mount.c
lunaix-os/kernel/fs/path_walk.c
lunaix-os/kernel/fs/twimap.c
lunaix-os/kernel/fs/vfs.c
lunaix-os/kernel/fs/xattr.c
lunaix-os/kernel/k_init.c
lunaix-os/kernel/loader/elf.c [new file with mode: 0644]
lunaix-os/kernel/loader/exec.c [new file with mode: 0644]
lunaix-os/kernel/loader/ld.c [new file with mode: 0644]
lunaix-os/kernel/lxinit.c [deleted file]
lunaix-os/kernel/mm/cow.c
lunaix-os/kernel/mm/dmm.c
lunaix-os/kernel/mm/kalloc.c [deleted file]
lunaix-os/kernel/mm/mmap.c [new file with mode: 0644]
lunaix-os/kernel/mm/mmio.c
lunaix-os/kernel/mm/region.c
lunaix-os/kernel/mm/vmap.c
lunaix-os/kernel/mm/vmm.c
lunaix-os/kernel/proc0.c
lunaix-os/kernel/process/process.c
lunaix-os/kernel/process/sched.c
lunaix-os/kernel/process/signal.c
lunaix-os/kernel/process/task_attr.c
lunaix-os/kernel/process/taskfs.c
lunaix-os/kernel/tty/lxconsole.c
lunaix-os/libs/klibc/string/strlen.c
lunaix-os/libs/ulibc/printf.c [deleted file]
lunaix-os/makefile
lunaix-os/makefile.ker [new file with mode: 0644]
lunaix-os/makefile.prog [new file with mode: 0644]
lunaix-os/makefile.usr [new file with mode: 0644]
lunaix-os/uprog/init.c [new file with mode: 0644]
lunaix-os/uprog/ls.c [new file with mode: 0644]
lunaix-os/usr/api/dirent.c [new file with mode: 0644]
lunaix-os/usr/api/errno.c [new file with mode: 0644]
lunaix-os/usr/api/fcntl.c [new file with mode: 0644]
lunaix-os/usr/api/ioctl.c [new file with mode: 0644]
lunaix-os/usr/api/lunaix.c [moved from lunaix-os/includes/lunaix/lunaix.h with 62% similarity]
lunaix-os/usr/api/mann.c [new file with mode: 0644]
lunaix-os/usr/api/mount.c [new file with mode: 0644]
lunaix-os/usr/api/signal.c [new file with mode: 0644]
lunaix-os/usr/api/unistd.c [new file with mode: 0644]
lunaix-os/usr/includes/dirent.h [new file with mode: 0644]
lunaix-os/usr/includes/errno.h [new file with mode: 0644]
lunaix-os/usr/includes/fcntl.h [new file with mode: 0644]
lunaix-os/usr/includes/fcntl_defs.h [new file with mode: 0644]
lunaix-os/usr/includes/signal.h [new file with mode: 0644]
lunaix-os/usr/includes/signal_defs.h [new file with mode: 0644]
lunaix-os/usr/includes/stdio.h [moved from lunaix-os/includes/ulibc/stdio.h with 96% similarity]
lunaix-os/usr/includes/stdlib.h [new file with mode: 0644]
lunaix-os/usr/includes/string.h [new file with mode: 0644]
lunaix-os/usr/includes/sys/dirent_defs.h [moved from lunaix-os/includes/lunaix/dirent.h with 65% similarity]
lunaix-os/usr/includes/sys/ioctl.h [new file with mode: 0644]
lunaix-os/usr/includes/sys/ioctl_defs.h [new file with mode: 0644]
lunaix-os/usr/includes/sys/lunaix.h [new file with mode: 0644]
lunaix-os/usr/includes/sys/lxdirent.h [new file with mode: 0644]
lunaix-os/usr/includes/sys/mann.h [new file with mode: 0644]
lunaix-os/usr/includes/sys/mann_flags.h [new file with mode: 0644]
lunaix-os/usr/includes/sys/mount.h [new file with mode: 0644]
lunaix-os/usr/includes/sys/types.h [new file with mode: 0644]
lunaix-os/usr/includes/unistd.h [new file with mode: 0644]
lunaix-os/usr/libc/_mystdio.h [new file with mode: 0644]
lunaix-os/usr/libc/_vprintf.c [new file with mode: 0644]
lunaix-os/usr/libc/itoa.c [new file with mode: 0644]
lunaix-os/usr/libc/printf.c [new file with mode: 0644]
lunaix-os/usr/libc/readdir.c [new file with mode: 0644]
lunaix-os/usr/libc/string.c [new file with mode: 0644]
lunaix-os/usr/link-usr.ld [new file with mode: 0644]
lunaix-os/usr/uinit.c [new file with mode: 0644]
lunaix-os/usr/uwrap.S [new file with mode: 0644]
reference-material/TIS-ELF.pdf [new file with mode: 0644]

index c593d19accfe57ec8d5cdb74bfaa86074394a635..a9d1b66eb5b38eba7063d779bd83d9a4eea9b175 100644 (file)
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ LunaixOS - 一个简单的,详细的,POSIX兼容的(但愿!),带有
 + 内存管理与按需分页(Demand Paging)
 + 键盘输入
 + 多进程
-+ 47个常见的Linux/POSIX系统调用([附录1](#appendix1))
++ 50个常见的Linux/POSIX系统调用([附录1](#appendix1))
 + 用户模式
 + 信号机制
 + PCI 3.0
@@ -144,6 +144,7 @@ qemu-img create -f vdi machine/disk0.vdi 128M
 + [ECMA-119 (ISO9660)](https://www.ecma-international.org/publications-and-standards/standards/ecma-119/)
 + Rock Ridge Interchange Protocol (RRIP: IEEE P1282)
 + System Use Sharing Protocol (SUSP: IEEE P1281)
++ Tool Interface Standard (TIS) Portable Formats Specification (Version 1.1)
 
 **免责声明:PCI相关的标准最终解释权归PCI-SIG所有。此处提供的副本仅供个人学习使用。任何商用目的须向PCI-SIG购买。**
 
@@ -190,7 +191,7 @@ qemu-img create -f vdi machine/disk0.vdi 128M
 2. `write(2)`
 2. `open(2)`
 2. `close(2)`
-2. `mkdir(2)`
+2. `mkdir(2)`
 2. `lseek(2)`
 2. `readdir(2)`
 2. `readlink(2)`※
@@ -216,6 +217,9 @@ qemu-img create -f vdi machine/disk0.vdi 128M
 2. `ioctl(2)`
 2. `getpgid(2)`
 2. `setpgid(2)`
+2. `mmap(2)`
+2. `munmap(2)`
+2. `execve(2)`
 
 **LunaixOS自有**
 
index a0ce1252806854c79e51a0890ab9bc6841f06a2e..a7dd4156c3cbfcdbc5b10308059da6bf9fbe11f2 100644 (file)
@@ -25,7 +25,7 @@ The following list presents all features it does have in current stage.
 + Memory management & demand paging
 + PS/2 Keyboard support
 + Muti-tasking and task management
-+ 47 commonly used POSIX syscall([See Appendix 1](#appendix1))
++ 50 commonly used POSIX syscall([See Appendix 1](#appendix1))
 + User Space
 + Signal
 + PCI 3.0
@@ -142,6 +142,7 @@ The following list also enumerated such materials the author has used:
 + [ECMA-119 (ISO9660)](https://www.ecma-international.org/publications-and-standards/standards/ecma-119/)
 + Rock Ridge Interchange Protocol (RRIP: IEEE P1282)
 + System Use Sharing Protocol (SUSP: IEEE P1281)
++ Tool Interface Standard (TIS) Portable Formats Specification (Version 1.1)
 
 **DISCLAIMER: All rights of PCI-related specification is reserved by PCI-SIG. It is provided ONLY for learning purpose. Any commercial use should purchase a copy from PCI-SIG**
 
@@ -186,7 +187,7 @@ The following list also enumerated such materials the author has used:
 2. `write(2)`
 2. `open(2)`
 2. `close(2)`
-2. `mkdir(2)`
+2. `mkdir(2)`
 2. `lseek(2)`
 2. `readdir(2)`
 2. `readlink(2)`※
@@ -209,9 +210,12 @@ The following list also enumerated such materials the author has used:
 2. `setxattr(2)`※
 2. `fgetxattr(2)`※
 2. `fsetxattr(2)`※
-2. `ioctl(2)`
+2. `ioctl(2)`
 2. `getpgid(2)`
 2. `setpgid(2)`
+2. `mmap(2)`
+2. `munmap(2)`
+2. `execve(2)`
 
 **LunaixOS**
 
index b20e749181e4af696b192bccbf231fd593f98bae..251d9927cb8841558c2432105eebace64b26baba 100644 (file)
@@ -7,4 +7,5 @@ playground/
 bx_enh_dbg.ini
 machine/
 draft/
-iso_inspect/
\ No newline at end of file
+iso_inspect/
+unused/
\ No newline at end of file
index c68b4c707b47f8732525c3186b1c8253c6b996fa..0fdf9959bb64051d315742a6b29720a0728ec772 100644 (file)
@@ -3,7 +3,8 @@
         {
             "name": "OS-DEV",
             "includePath": [
-                "${workspaceFolder}/includes"
+                "${workspaceFolder}/includes",
+                "${workspaceFolder}/usr/includes"
             ],
             "compilerArgs": [
                 "-ffreestanding",
index 9e44437c7803d24b40323c6d69f3a67b455b5f37..d1d14ba7e8af8ded3708aab9aa81fb330d65f62a 100644 (file)
@@ -78,7 +78,7 @@
         movl %eax, %cr3
 
         movl %cr0, %eax
-        orl $0x80010000, %eax   /* 开启分页与地址转换 (CR0.PG=1, CR0.WP=1) */
+        orl $0x80000000, %eax   /* 开启分页与地址转换 (CR0.PG=1, CR0.WP=0) */
         andl $0xfffffffb, %eax
         orl $0x2, %eax          /* 启用x87 FPU (CR0.MP=1, CR0.EM=0) */
         movl %eax, %cr0
index 4491370c42fd1fa3fa5570f97e98f6398784df31..7915afe89a0949d305ea569d5c9664564b9c3e52 100644 (file)
@@ -1,5 +1,6 @@
 CC := i686-elf-gcc
 AS := i686-elf-as
+AR := i686-elf-ar
 
 
 ARCH_OPT := -D__ARCH_IA32 -include flags.h
@@ -16,7 +17,10 @@ OFLAGS := -fno-gcse\
                  -fno-cse-follow-jumps\
                  -fno-cse-skip-blocks\
                  -fno-optimize-strlen\
-                 -fno-tree-builtin-call-dce 
+                 -fno-inline-functions-called-once \
+                 -fno-inline-functions \
+                 -fno-inline-small-functions \
+                 -fno-indirect-inlining
 
 CFLAGS := -std=gnu99 -ffreestanding $(O) $(OFLAGS) $(W) $(ARCH_OPT)
 LDFLAGS := -ffreestanding $(O) -nostdlib -lgcc
\ No newline at end of file
index b60503ea21e56c344921710f827b6cfe0032cdb4..093f7baaf020627e24103bd886360a3aca8a6d5d 100644 (file)
@@ -3,7 +3,8 @@ KERNEL_DIR := kernel
 OBJECT_DIR := $(BUILD_DIR)/obj
 BIN_DIR := $(BUILD_DIR)/bin
 ISO_DIR := $(BUILD_DIR)/iso
+USR_DIR := $(BUILD_DIR)/usr
 ISO_BOOT_DIR := $(ISO_DIR)/boot
 ISO_GRUB_DIR := $(ISO_BOOT_DIR)/grub
 
-INCLUDES_DIR := includes
\ No newline at end of file
+INCLUDES := -Iincludes -Iusr/includes
\ No newline at end of file
index e3c26b7e28c2ca06a66caad1fdbf77dc30d6768a..7ea5c01c025a090f4000a093c720bac4ca41b593 100644 (file)
@@ -1,4 +1,6 @@
 OS_ARCH := x86
-OS_NAME = lunaix
-OS_BIN = $(OS_NAME).bin
-OS_ISO = $(OS_NAME).iso
\ No newline at end of file
+OS_NAME := lunaix
+OS_BIN := $(OS_NAME).bin
+OS_ISO := $(OS_NAME).iso
+
+USR_LIB := liblxusrt.a
\ No newline at end of file
index 0f0496de4681dc506fa65b28e45eb16847fc7c94..9c428b2755c11877e1fc989cfcc3d94db310f011 100644 (file)
@@ -29,9 +29,11 @@ lunaix_sdbg_loop(isr_param* param)
     char c;
 
     if (sdbg_state == SDBG_STATE_WAIT_BRK) {
-        (param)->eflags &= ~(1 << 8);
+        (param)->execp->eflags &= ~(1 << 8);
         sdbg_state = SDBG_STATE_INSESSION;
-        sdbg_printf("[%p:%p] Break point reached.\n", param->cs, param->eip);
+        sdbg_printf("[%p:%p] Break point reached.\n",
+                    param->execp->cs,
+                    param->execp->eip);
     }
 
     while (1) {
@@ -44,12 +46,14 @@ lunaix_sdbg_loop(isr_param* param)
         switch (c) {
             case SDBG_CLNT_HI:
                 if (sdbg_state == SDBG_STATE_START) {
-                    sdbg_printf(
-                      "[%p:%p] Session started.\n", param->cs, param->eip);
+                    sdbg_printf("[%p:%p] Session started.\n",
+                                param->execp->cs,
+                                param->execp->eip);
                     sdbg_state = SDBG_STATE_INSESSION;
                 } else {
-                    sdbg_printf(
-                      "[%p:%p] Session resumed.\n", param->cs, param->eip);
+                    sdbg_printf("[%p:%p] Session resumed.\n",
+                                param->execp->cs,
+                                param->execp->eip);
                 }
                 break;
             case SDBG_CLNT_RREG:
@@ -57,7 +61,7 @@ lunaix_sdbg_loop(isr_param* param)
                 serial_tx_buffer(SERIAL_COM1, (char*)param, sizeof(isr_param));
                 break;
             case SDBG_CLNT_STEP:
-                ((isr_param*)param)->eflags |= (1 << 8); // set TF flags
+                ((isr_param*)param)->execp->eflags |= (1 << 8); // set TF flags
                 sdbg_state = SDBG_STATE_WAIT_BRK;
                 return;
             case SDBG_CLNT_BRKP:
index 9546b85800693788888f181892fc75494e98f551..d87db19fa33cc46ad519da0f74287cd2a0eb8c41 100644 (file)
@@ -1211,7 +1211,7 @@ void
 gdbstub_loop(isr_param* param)
 {
     /* Translate vector to signal */
-    switch (param->vector) {
+    switch (param->execp->vector) {
         case 1:
             gdb_state.signum = 5;
             break;
@@ -1227,14 +1227,14 @@ gdbstub_loop(isr_param* param)
     gdb_state.registers[GDB_CPU_I386_REG_ECX] = param->registers.ecx;
     gdb_state.registers[GDB_CPU_I386_REG_EDX] = param->registers.edx;
     gdb_state.registers[GDB_CPU_I386_REG_EBX] = param->registers.ebx;
-    gdb_state.registers[GDB_CPU_I386_REG_ESP] = param->registers.esp;
+    gdb_state.registers[GDB_CPU_I386_REG_ESP] = param->esp;
     gdb_state.registers[GDB_CPU_I386_REG_EBP] = param->registers.ebp;
     gdb_state.registers[GDB_CPU_I386_REG_ESI] = param->registers.esi;
     gdb_state.registers[GDB_CPU_I386_REG_EDI] = param->registers.edi;
-    gdb_state.registers[GDB_CPU_I386_REG_PC] = param->eip;
-    gdb_state.registers[GDB_CPU_I386_REG_CS] = param->cs;
-    gdb_state.registers[GDB_CPU_I386_REG_PS] = param->eflags;
-    gdb_state.registers[GDB_CPU_I386_REG_SS] = param->ss;
+    gdb_state.registers[GDB_CPU_I386_REG_PC] = param->execp->eip;
+    gdb_state.registers[GDB_CPU_I386_REG_CS] = param->execp->cs;
+    gdb_state.registers[GDB_CPU_I386_REG_PS] = param->execp->eflags;
+    gdb_state.registers[GDB_CPU_I386_REG_SS] = param->execp->ss;
     gdb_state.registers[GDB_CPU_I386_REG_DS] = param->registers.ds;
     gdb_state.registers[GDB_CPU_I386_REG_ES] = param->registers.es;
     gdb_state.registers[GDB_CPU_I386_REG_FS] = param->registers.fs;
@@ -1247,14 +1247,14 @@ gdbstub_loop(isr_param* param)
     param->registers.ecx = gdb_state.registers[GDB_CPU_I386_REG_ECX];
     param->registers.edx = gdb_state.registers[GDB_CPU_I386_REG_EDX];
     param->registers.ebx = gdb_state.registers[GDB_CPU_I386_REG_EBX];
-    param->registers.esp = gdb_state.registers[GDB_CPU_I386_REG_ESP];
+    param->esp = gdb_state.registers[GDB_CPU_I386_REG_ESP];
     param->registers.ebp = gdb_state.registers[GDB_CPU_I386_REG_EBP];
     param->registers.esi = gdb_state.registers[GDB_CPU_I386_REG_ESI];
     param->registers.edi = gdb_state.registers[GDB_CPU_I386_REG_EDI];
-    param->eip = gdb_state.registers[GDB_CPU_I386_REG_PC];
-    param->cs = gdb_state.registers[GDB_CPU_I386_REG_CS];
-    param->eflags = gdb_state.registers[GDB_CPU_I386_REG_PS];
-    param->ss = gdb_state.registers[GDB_CPU_I386_REG_SS];
+    param->execp->eip = gdb_state.registers[GDB_CPU_I386_REG_PC];
+    param->execp->cs = gdb_state.registers[GDB_CPU_I386_REG_CS];
+    param->execp->eflags = gdb_state.registers[GDB_CPU_I386_REG_PS];
+    param->execp->ss = gdb_state.registers[GDB_CPU_I386_REG_SS];
     param->registers.ds = gdb_state.registers[GDB_CPU_I386_REG_DS];
     param->registers.es = gdb_state.registers[GDB_CPU_I386_REG_ES];
     param->registers.fs = gdb_state.registers[GDB_CPU_I386_REG_FS];
index 3cc23cf29d388068ec7668b89ab6955d749acd04..60a89f360a40cffc3b4e1fe91fd790ff802a16e7 100644 (file)
@@ -22,7 +22,8 @@ sdbg_loop(const isr_param* param)
     // synchronized way. And we don't want these irq queue up at our APIC and
     // confuse the CPU after ACK with APIC.
     serial_disable_irq(SERIAL_COM1);
-    if (param->vector == 1 || param->vector == 3) {
+    struct exec_param* execp = param->execp;
+    if (execp->vector == 1 || execp->vector == 3) {
         goto cont;
     }
 
@@ -74,10 +75,11 @@ done:
 void
 sdbg_imm(const isr_param* param)
 {
+    struct exec_param* execp = param->execp;
     kprintf(KDEBUG "Quick debug mode\n");
     kprintf(KDEBUG "cs=%p eip=%p eax=%p ebx=%p\n",
-            param->cs,
-            param->eip,
+            execp->cs,
+            execp->eip,
             param->registers.eax,
             param->registers.ebx);
     kprintf(KDEBUG "ecx=%p edx=%p edi=%p esi=%p\n",
@@ -86,12 +88,12 @@ sdbg_imm(const isr_param* param)
             param->registers.edi,
             param->registers.esi);
     kprintf(KDEBUG "u.esp=%p k.esp=%p ebp=%p ps=%p\n",
-            param->registers.esp,
             param->esp,
+            execp->esp,
             param->registers.ebp,
-            param->eflags);
+            execp->eflags);
     kprintf(KDEBUG "ss=%p ds=%p es=%p fs=%p gs=%p\n",
-            param->ss,
+            execp->ss,
             param->registers.ds,
             param->registers.es,
             param->registers.fs,
index e11016a3b5a1165208e1a78b40fef4465226d819..c1bd6a5ad2f2cc9465aac2ab52beec962314c99c 100644 (file)
@@ -15,7 +15,7 @@ __ahci_hba_isr(const isr_param* param)
     struct ahci_driver *pos, *n;
     llist_for_each(pos, n, &ahcis, ahci_drvs)
     {
-        if (pos->id == param->vector) {
+        if (pos->id == param->execp->vector) {
             hba = &pos->hba;
             goto proceed;
         }
index d25fbe3b68d9e931b7062d559b7f9cbf6ad411ed..f1684a8ad1398d52919a4a28d41c01457ecfb886 100644 (file)
@@ -5,8 +5,12 @@
 
 #ifndef __ASM__
 #include <hal/cpu.h>
+
+struct exec_param;
+
 typedef struct
 {
+    unsigned int depth;
     struct
     {
         reg32 eax;
@@ -20,9 +24,18 @@ typedef struct
         reg32 es;
         reg32 fs;
         reg32 gs;
-        reg32 esp;
     } __attribute__((packed)) registers;
 
+    union
+    {
+        reg32 esp;
+        volatile struct exec_param* execp;
+    };
+} __attribute__((packed)) isr_param;
+
+struct exec_param
+{
+    isr_param saved_prev_ctx;
     unsigned int vector;
     unsigned int err_code;
     unsigned int eip;
@@ -30,7 +43,9 @@ typedef struct
     unsigned int eflags;
     unsigned int esp;
     unsigned int ss;
-} __attribute__((packed)) isr_param;
+} __attribute__((packed));
+
+#define ISR_PARAM_SIZE sizeof(isr_param)
 
 void
 intr_handler(isr_param* param);
index 8ab544a1e92d53a449803d193677af89daa1edaf..1b4a8e3b3b6a65042d0d93653c114427f9319cf4 100644 (file)
@@ -13,7 +13,7 @@ rnd_fill(void* data, size_t len)
                  "subl $4, %1\n"
                  "jnz 1b" ::"r"((ptr_t)data),
                  "r"((len & ~0x3))
-                 : "%al");
+                 : "%eax");
 }
 
 int
index 1ebf15836f509c7bbd0a5fcb8bcb00c636947166..daa55af83023e921746a6fc788a96716e4421d7f 100644 (file)
@@ -8,9 +8,11 @@
 #define MEM_1MB 0x100000
 #define MEM_4MB 0x400000
 
+#define USER_START 0x400000
+
 #define KSTACK_SIZE MEM_1MB
-#define KSTACK_START ((0x3FFFFFU - KSTACK_SIZE) + 1)
-#define KSTACK_TOP 0x3FFFF0U
+#define KSTACK_START (USER_START - KSTACK_SIZE)
+#define KSTACK_TOP ((USER_START - 1) & ~0xf)
 
 #define KERNEL_MM_BASE 0xC0000000
 
 #define UDATA_SEG 0x23
 #define TSS_SEG 0x28
 
-#define USER_START 0x400000
-#define USTACK_SIZE 0x100000
+#define USTACK_SIZE MEM_4MB
 #define USTACK_TOP 0x9ffffff0
 #define USTACK_END (0x9fffffff - USTACK_SIZE + 1)
-#define UMMAP_AREA 0x4D000000
+#define UMMAP_START 0x4D000000
+#define UMMAP_END (USTACK_END - MEM_4MB)
 
 #ifndef __ASM__
 #include <stddef.h>
index a4797c34d3f889ab9c0e970ed693607ee7953fbe..65ba474d750328d80ff3c08eba0611c9cb076f30 100644 (file)
@@ -50,6 +50,12 @@ llist_prepend(struct llist_header* head, struct llist_header* elem)
     __llist_add(elem, head, head->next);
 }
 
+static inline void
+llist_insert_after(struct llist_header* head, struct llist_header* elem)
+{
+    __llist_add(elem, head, head->next);
+}
+
 static inline void
 llist_delete(struct llist_header* elem)
 {
diff --git a/lunaix-os/includes/lunaix/elf.h b/lunaix-os/includes/lunaix/elf.h
new file mode 100644 (file)
index 0000000..f61fa96
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef __LUNAIX_ELF_H
+#define __LUNAIX_ELF_H
+
+#include <lunaix/types.h>
+
+typedef unsigned int elf32_ptr_t;
+typedef unsigned short elf32_hlf_t;
+typedef unsigned int elf32_off_t;
+typedef unsigned int elf32_swd_t;
+typedef unsigned int elf32_wrd_t;
+
+#define ET_NONE 0
+#define ET_EXEC 2
+
+#define PT_LOAD 1
+
+#define PF_X 0x1
+#define PF_W 0x2
+#define PF_R 0x4
+
+#define EM_NONE 0
+#define EM_386 3
+
+#define EV_CURRENT 1
+
+// [0x7f, 'E', 'L', 'F']
+#define ELFMAGIC 0x464c457fU
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+#define ELFDATA2LSB 1
+#define ELFDATA2MSB 2
+
+#define EI_CLASS 4
+#define EI_DATA 5
+
+struct elf32_ehdr
+{
+    u8_t e_ident[16];
+    elf32_hlf_t e_type;
+    elf32_hlf_t e_machine;
+    elf32_wrd_t e_version;
+    elf32_ptr_t e_entry;
+    elf32_off_t e_phoff;
+    elf32_off_t e_shoff;
+    elf32_wrd_t e_flags;
+    elf32_hlf_t e_ehsize;
+    elf32_hlf_t e_phentsize;
+    elf32_hlf_t e_phnum;
+    elf32_hlf_t e_shentsize;
+    elf32_hlf_t e_shnum;
+    elf32_hlf_t e_shstrndx;
+};
+
+struct elf32_phdr
+{
+    elf32_wrd_t p_type;
+    elf32_off_t p_offset;
+    elf32_ptr_t p_va;
+    elf32_ptr_t p_pa;
+    elf32_wrd_t p_filesz;
+    elf32_wrd_t p_memsz;
+    elf32_wrd_t p_flags;
+    elf32_wrd_t p_align;
+};
+
+#define SIZE_EHDR sizeof(struct elf32_ehdr)
+#define SIZE_PHDR sizeof(struct elf32_phdr)
+
+static inline int
+elf_check_exec(struct elf32_ehdr* ehdr)
+{
+    return *(u32_t*)(ehdr->e_ident) == ELFMAGIC &&
+           ehdr->e_ident[EI_CLASS] == ELFCLASS32 &&
+           ehdr->e_ident[EI_DATA] == ELFDATA2LSB && ehdr->e_type == ET_EXEC &&
+           ehdr->e_machine == EM_386;
+}
+#endif /* __LUNAIX_ELF_H */
diff --git a/lunaix-os/includes/lunaix/fctrl.h b/lunaix-os/includes/lunaix/fctrl.h
deleted file mode 100644 (file)
index 5ec0eef..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef __LUNAIX_FCTRL_H
-#define __LUNAIX_FCTRL_H
-
-#include <lunaix/dirent.h>
-#include <lunaix/syscall.h>
-#include <stddef.h>
-
-__LXSYSCALL2(int, open, const char*, path, int, options)
-
-__LXSYSCALL1(int, mkdir, const char*, path)
-__LXSYSCALL2(int, unlinkat, int, fd, const char*, pathname)
-
-__LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent)
-
-__LXSYSCALL4(int,
-             readlinkat,
-             int,
-             dirfd,
-             const char*,
-             pathname,
-             char*,
-             buf,
-             size_t,
-             size)
-
-__LXSYSCALL3(int, realpathat, int, fd, char*, buf, size_t, size)
-
-__LXSYSCALL4(int,
-             mount,
-             const char*,
-             source,
-             const char*,
-             target,
-             const char*,
-             fstype,
-             int,
-             options)
-
-__LXSYSCALL1(int, unmount, const char*, target)
-
-__LXSYSCALL4(int,
-             getxattr,
-             const char*,
-             path,
-             const char*,
-             name,
-             void*,
-             value,
-             size_t,
-             len)
-
-__LXSYSCALL4(int,
-             setxattr,
-             const char*,
-             path,
-             const char*,
-             name,
-             void*,
-             value,
-             size_t,
-             len)
-
-__LXSYSCALL4(int,
-             fgetxattr,
-             int,
-             fd,
-             const char*,
-             name,
-             void*,
-             value,
-             size_t,
-             len)
-
-__LXSYSCALL4(int,
-             fsetxattr,
-             int,
-             fd,
-             const char*,
-             name,
-             void*,
-             value,
-             size_t,
-             len)
-
-#endif /* __LUNAIX_FCTRL_H */
index 0bb6ac4821a8951ac3258bc01cde2c4d93297266..625c0b22074f045ba2273c06bb923bb1e2c9603a 100644 (file)
@@ -1,14 +1,6 @@
 #ifndef __LUNAIX_FOPTIONS_H
 #define __LUNAIX_FOPTIONS_H
 
-#define FO_CREATE 0x1
-#define FO_APPEND 0x2
-#define FO_DIRECT 0x4
-
-#define FSEEK_SET 0x1
-#define FSEEK_CUR 0x2
-#define FSEEK_END 0x3
-
-#define MNT_RO 0x1
+#include <fcntl_defs.h>
 
 #endif /* __LUNAIX_FOPTIONS_H */
index 3ec85f5c2b711fce57f8b273af22694d0c1da571..4b2888157d59003569801d30fbcf6d13c32565f6 100644 (file)
@@ -9,7 +9,6 @@
 #include <lunaix/ds/llist.h>
 #include <lunaix/ds/lru.h>
 #include <lunaix/ds/mutex.h>
-#include <lunaix/process.h>
 #include <lunaix/status.h>
 #include <stdatomic.h>
 
@@ -36,9 +35,6 @@
 
 #define FSTYPE_ROFS 0x1
 
-#define DO_STATUS(errno) SYSCALL_ESTATUS(__current->k_status = errno)
-#define DO_STATUS_OR_RETURN(errno) ({ errno < 0 ? DO_STATUS(errno) : errno; })
-
 #define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD)
 
 #define VFS_VALID_CHAR(chr)                                                    \
@@ -400,6 +396,9 @@ vfs_get_dtype(int itype);
 void
 vfs_ref_dnode(struct v_dnode* dnode);
 
+void
+vfs_ref_file(struct v_file* file);
+
 void
 vfs_unref_dnode(struct v_dnode* dnode);
 
index e074bbaaf65217554a4cde9c9ae48997586a23b4..6dcd83c0ceefc3d67a848174a24f6f6e61a66cdd 100644 (file)
@@ -1,19 +1,6 @@
 #ifndef __LUNAIX_IOCTL_H
 #define __LUNAIX_IOCTL_H
 
-#include <lunaix/syscall.h>
-
-#define IOREQ(cmd, arg_num) ((((cmd)&0xffff) << 8) | ((arg_num)&0xff))
-
-#define IOCMD(req) ((req) >> 8)
-
-#define IOARGNUM(req) ((req)&0xff)
-
-#define TIOCGPGRP IOREQ(1, 0)
-#define TIOCSPGRP IOREQ(1, 1)
-#define TIOCCLSBUF IOREQ(2, 0)
-#define TIOCFLUSH IOREQ(3, 0)
-
-__LXSYSCALL2_VARG(int, ioctl, int, fd, int, req);
+#include <sys/ioctl_defs.h>
 
 #endif /* __LUNAIX_IOCTL_H */
diff --git a/lunaix-os/includes/lunaix/ld.h b/lunaix-os/includes/lunaix/ld.h
new file mode 100644 (file)
index 0000000..690f95f
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef __LUNAIX_LOADER_H
+#define __LUNAIX_LOADER_H
+
+#include <lunaix/elf.h>
+#include <lunaix/process.h>
+#include <lunaix/types.h>
+
+#define LD_STAT_FKUP 0x1U
+
+#define MAX_VAR_PAGES 8
+#define DEFAULT_HEAP_PAGES 16
+
+struct ld_info
+{
+    struct elf32_ehdr ehdr_out;
+    ptr_t base;
+    ptr_t end;
+    ptr_t mem_sz;
+
+    ptr_t stack_top;
+    ptr_t entry;
+};
+
+struct ld_param
+{
+    struct proc_info* proc;
+    ptr_t vms_mnt;
+
+    struct ld_info info;
+    int status;
+};
+
+struct usr_exec_param
+{
+    int argc;
+    char** argv;
+    int envc;
+    char** envp;
+    struct ld_info info;
+} PACKED;
+
+#ifndef __USR_WRAPPER__
+int
+elf_load(struct ld_param* ldparam, struct v_file* elfile);
+
+int
+exec_load_byname(struct ld_param* param,
+                 const char* filename,
+                 const char** argv,
+                 const char** envp);
+
+int
+exec_load(struct ld_param* param,
+          struct v_file* executable,
+          const char** argv,
+          const char** envp);
+
+void
+ld_create_param(struct ld_param* param, struct proc_info* proc, ptr_t vms);
+#endif
+
+#endif /* __LUNAIX_LOADER_H */
diff --git a/lunaix-os/includes/lunaix/lunistd.h b/lunaix-os/includes/lunaix/lunistd.h
deleted file mode 100644 (file)
index 9f2ef9e..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef __LUNAIX_UNISTD_H
-#define __LUNAIX_UNISTD_H
-
-#include <lunaix/syscall.h>
-#include <lunaix/types.h>
-#include <stddef.h>
-
-__LXSYSCALL(pid_t, fork)
-
-__LXSYSCALL1(int, sbrk, void*, addr)
-
-__LXSYSCALL1(void*, brk, unsigned long, size)
-
-__LXSYSCALL(pid_t, getpid)
-
-__LXSYSCALL(pid_t, getppid)
-
-__LXSYSCALL(pid_t, getpgid)
-
-__LXSYSCALL2(pid_t, setpgid, pid_t, pid, pid_t, pgid)
-
-__LXSYSCALL1(void, _exit, int, status)
-
-__LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
-
-__LXSYSCALL(int, pause)
-
-__LXSYSCALL2(int, kill, pid_t, pid, int, signum)
-
-__LXSYSCALL1(unsigned int, alarm, unsigned int, seconds)
-
-__LXSYSCALL2(int, link, const char*, oldpath, const char*, newpath)
-
-__LXSYSCALL1(int, rmdir, const char*, pathname)
-
-__LXSYSCALL3(int, read, int, fd, void*, buf, unsigned int, count)
-
-__LXSYSCALL3(int, write, int, fd, void*, buf, unsigned int, count)
-
-__LXSYSCALL3(int, readlink, const char*, path, char*, buf, size_t, size)
-
-__LXSYSCALL3(int, lseek, int, fd, int, offset, int, options)
-
-__LXSYSCALL1(int, unlink, const char*, pathname)
-
-__LXSYSCALL1(int, close, int, fd)
-
-__LXSYSCALL2(int, dup2, int, oldfd, int, newfd)
-
-__LXSYSCALL1(int, dup, int, oldfd)
-
-__LXSYSCALL1(int, fsync, int, fildes)
-
-__LXSYSCALL2(int, symlink, const char*, pathname, const char*, link_target)
-
-__LXSYSCALL1(int, chdir, const char*, path)
-
-__LXSYSCALL1(int, fchdir, int, fd)
-
-__LXSYSCALL2(char*, getcwd, char*, buf, size_t, size)
-
-__LXSYSCALL2(int, rename, const char*, oldpath, const char*, newpath)
-
-#endif /* __LUNAIX_UNISTD_H */
diff --git a/lunaix-os/includes/lunaix/lxsignal.h b/lunaix-os/includes/lunaix/lxsignal.h
deleted file mode 100644 (file)
index 5b54ffc..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __LUNAIX_LXSIGNAL_H
-#define __LUNAIX_LXSIGNAL_H
-
-#include <lunaix/types.h>
-
-int
-signal_send(pid_t pid, int signum);
-
-#endif /* __LUNAIX_LXSIGNAL_H */
diff --git a/lunaix-os/includes/lunaix/mm/dmm.h b/lunaix-os/includes/lunaix/mm/dmm.h
deleted file mode 100644 (file)
index 346c479..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef __LUNAIX_DMM_H
-#define __LUNAIX_DMM_H
-// Dynamic Memory (i.e., heap) Manager
-
-#include <lunaix/mm/mm.h>
-#include <lunaix/process.h>
-#include <stddef.h>
-
-#define M_ALLOCATED 0x1
-#define M_PREV_FREE 0x2
-
-#define M_NOT_ALLOCATED 0x0
-#define M_PREV_ALLOCATED 0x0
-
-#define CHUNK_S(header) ((header) & ~0x3)
-#define CHUNK_PF(header) ((header)&M_PREV_FREE)
-#define CHUNK_A(header) ((header)&M_ALLOCATED)
-
-#define PACK(size, flags) (((size) & ~0x3) | (flags))
-
-#define SW(p, w) (*((u32_t*)(p)) = w)
-#define LW(p) (*((u32_t*)(p)))
-
-#define HPTR(bp) ((u32_t*)(bp)-1)
-#define BPTR(bp) ((uint8_t*)(bp) + WSIZE)
-#define FPTR(hp, size) ((u32_t*)(hp + size - WSIZE))
-#define NEXT_CHK(hp) ((uint8_t*)(hp) + CHUNK_S(LW(hp)))
-
-#define BOUNDARY 4
-#define WSIZE 4
-
-#define HEAP_INIT_SIZE 4096
-
-int
-dmm_init(heap_context_t* heap);
-
-int
-lxbrk(heap_context_t* heap, void* addr, int user);
-
-void*
-lxsbrk(heap_context_t* heap, size_t size, int user);
-
-void*
-lx_malloc_internal(heap_context_t* heap, size_t size);
-
-void
-lx_free_internal(void* ptr);
-
-#endif /* __LUNAIX_DMM_H */
diff --git a/lunaix-os/includes/lunaix/mm/kalloc.h b/lunaix-os/includes/lunaix/mm/kalloc.h
deleted file mode 100644 (file)
index 6b97b3f..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef __LUNAIX_KALLOC_H
-#define __LUNAIX_KALLOC_H
-
-#include <stddef.h>
-
-int
-kalloc_init();
-
-/**
- * @brief Allocate a contiguous and un-initialized memory region in kernel heap. 
- * 
- * @remarks 
- *  This is NOT the same as kmalloc in Linux! 
- *  LunaixOS does NOT guarantee the continuity in physical pages.
- * 
- * @param size 
- * @return void* 
- */
-void*
-lxmalloc(size_t size);
-
-/**
- * @brief Allocate a contiguous and initialized memory region in kernel heap.
- * @param size 
- * @return void*
- */
-void*
-lxcalloc(size_t n, size_t elem);
-
-/**
- * @brief Free the memory region allocated by kmalloc
- * 
- * @param size 
- * @return void* 
- */
-void
-lxfree(void* ptr);
-
-#endif /* __LUNAIX_KALLOC_H */
index 6585916e4136d48cb2c0afa96ac341c4babfb65f..74868b0e9d39781b440edeb7731c1570a38a44eb 100644 (file)
@@ -3,54 +3,91 @@
 
 #include <lunaix/ds/llist.h>
 #include <lunaix/ds/mutex.h>
+#include <lunaix/fs.h>
+#include <lunaix/types.h>
 
-typedef struct
-{
-    void* start;
-    void* brk;
-    void* max_addr;
-    mutex_t lock;
-} heap_context_t;
+#include <sys/mann_flags.h>
 
 /**
  * @brief 私有区域,该区域中的页无法进行任何形式的共享。
  *
  */
-#define REGION_PRIVATE 0x0
+#define REGION_PRIVATE MAP_EXCLUSIVE
 
 /**
  * @brief
  * 读共享区域,该区域中的页可以被两个进程之间读共享,但任何写操作须应用Copy-On-Write
+ * 等价于 POSIX 的 MAP_PRIVATE
  *
  */
-#define REGION_RSHARED 0x1
+#define REGION_RSHARED MAP_PRIVATE
 
 /**
  * @brief
  * 写共享区域,该区域中的页可以被两个进程之间读共享,任何的写操作无需执行Copy-On-Write
- *
+ * 等价于 POSIX 的 MAP_SHARED
  */
-#define REGION_WSHARED 0x2
+#define REGION_WSHARED MAP_SHARED
 
 #define REGION_PERM_MASK 0x1c
 #define REGION_MODE_MASK 0x3
 
-#define REGION_READ (1 << 2)
-#define REGION_WRITE (1 << 3)
-#define REGION_EXEC (1 << 4)
+#define REGION_READ PROT_READ
+#define REGION_WRITE PROT_WRITE
+#define REGION_EXEC PROT_EXEC
+#define REGION_ANON MAP_ANON
 #define REGION_RW REGION_READ | REGION_WRITE
 
-#define REGION_TYPE_CODE (1 << 16);
-#define REGION_TYPE_GENERAL (2 << 16);
-#define REGION_TYPE_HEAP (3 << 16);
-#define REGION_TYPE_STACK (4 << 16);
+#define REGION_TYPE_CODE (1 << 16)
+#define REGION_TYPE_GENERAL (2 << 16)
+#define REGION_TYPE_HEAP (3 << 16)
+#define REGION_TYPE_STACK (4 << 16)
+#define REGION_TYPE_VARS (5 << 16)
+
+struct proc_mm;
 
 struct mm_region
 {
-    struct llist_header head;
-    unsigned long start;
-    unsigned long end;
-    unsigned int attr;
+    struct llist_header head; // must be first field!
+    struct proc_mm* proc_vms;
+
+    // file mapped to this region
+    struct v_file* mfile;
+    // mapped file offset
+    off_t foff;
+    // mapped file length
+    u32_t flen;
+
+    ptr_t start;
+    ptr_t end;
+    u32_t attr;
+
+    void** index; // fast reference, to accelerate access to this very region.
+
+    void* data;
+    // When a page is mapped and required initialize
+    int (*init_page)(struct mm_region*, void*, off_t);
+    // when a region is copied
+    void (*region_copied)(struct mm_region*);
+    // when a region is unmapped
+    void (*destruct_region)(struct mm_region*);
+};
+
+static inline void
+mm_index(void** index, struct mm_region* target)
+{
+    *index = (void*)target;
+    target->index = index;
+}
+
+typedef struct llist_header vm_regions_t;
+
+struct proc_mm
+{
+    vm_regions_t regions;
+    struct mm_region* heap;
+    struct mm_region* stack;
+    pid_t pid;
 };
 
 #endif /* __LUNAIX_MM_H */
diff --git a/lunaix-os/includes/lunaix/mm/mmap.h b/lunaix-os/includes/lunaix/mm/mmap.h
new file mode 100644 (file)
index 0000000..f85302e
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef __LUNAIX_MMAP_H
+#define __LUNAIX_MMAP_H
+
+#include <lunaix/fs.h>
+#include <lunaix/mm/region.h>
+#include <lunaix/types.h>
+
+struct mmap_param
+{
+    ptr_t vms_mnt;        // vm mount point
+    struct proc_mm* pvms; // process vm
+    off_t offset;         // mapped file offset
+    size_t mlen;          // mapped memory length
+    size_t flen;          // mapped file length
+    u32_t proct;          // protections
+    u32_t flags;          // other options
+    u32_t type;           // region type
+};
+
+int
+mem_adjust_inplace(vm_regions_t* regions,
+                   struct mm_region* region,
+                   ptr_t newend);
+
+int
+mem_map(void** addr_out,
+        struct mm_region** created,
+        void* addr,
+        struct v_file* file,
+        struct mmap_param* param);
+
+int
+mem_unmap(ptr_t mnt, vm_regions_t* regions, void* addr, size_t length);
+
+void
+mem_unmap_region(ptr_t mnt, struct mm_region* region);
+
+void
+mem_sync_pages(ptr_t mnt,
+               struct mm_region* region,
+               ptr_t start,
+               ptr_t length,
+               int options);
+
+int
+mem_msync(ptr_t mnt,
+          vm_regions_t* regions,
+          ptr_t addr,
+          size_t length,
+          int options);
+
+#endif /* __LUNAIX_MMAP_H */
index f2c45de00bcfd0e81b365759cf5c5e818a81b14a..9330274f2cf144e85e90d3e06666d0024a9ee299 100644 (file)
@@ -9,30 +9,34 @@
 
 #define PTE_NULL 0
 
-#define P2V(paddr) ((uintptr_t)(paddr) + KERNEL_MM_BASE)
-#define V2P(vaddr) ((uintptr_t)(vaddr)-KERNEL_MM_BASE)
+#define P2V(paddr) ((ptr_t)(paddr) + KERNEL_MM_BASE)
+#define V2P(vaddr) ((ptr_t)(vaddr)-KERNEL_MM_BASE)
 
-#define PG_ALIGN(addr) ((uintptr_t)(addr)&0xFFFFF000UL)
+#define PG_ALIGN(addr) ((ptr_t)(addr)&0xFFFFF000UL)
+#define PG_ALIGNED(addr) (!((ptr_t)(addr)&0x00000FFFUL))
 
-#define L1_INDEX(vaddr) (u32_t)(((uintptr_t)(vaddr)&0xFFC00000UL) >> 22)
-#define L2_INDEX(vaddr) (u32_t)(((uintptr_t)(vaddr)&0x003FF000UL) >> 12)
-#define PG_OFFSET(vaddr) (u32_t)((uintptr_t)(vaddr)&0x00000FFFUL)
+#define L1_INDEX(vaddr) (u32_t)(((ptr_t)(vaddr)&0xFFC00000UL) >> 22)
+#define L2_INDEX(vaddr) (u32_t)(((ptr_t)(vaddr)&0x003FF000UL) >> 12)
+#define PG_OFFSET(vaddr) (u32_t)((ptr_t)(vaddr)&0x00000FFFUL)
 
 #define GET_PT_ADDR(pde) PG_ALIGN(pde)
 #define GET_PG_ADDR(pte) PG_ALIGN(pte)
 
-#define PG_DIRTY(pte) ((pte & (1 << 6)) >> 6)
-#define PG_ACCESSED(pte) ((pte & (1 << 5)) >> 5)
-
 #define IS_CACHED(entry) ((entry & 0x1))
 
 #define PG_PRESENT (0x1)
+#define PG_DIRTY (1 << 6)
+#define PG_ACCESSED (1 << 5)
 #define PG_WRITE (0x1 << 1)
 #define PG_ALLOW_USER (0x1 << 2)
 #define PG_WRITE_THROUGH (1 << 3)
 #define PG_DISABLE_CACHE (1 << 4)
 #define PG_PDE_4MB (1 << 7)
 
+#define PG_IS_DIRTY(pte) ((pte)&PG_DIRTY)
+#define PG_IS_ACCESSED(pte) ((pte)&PG_ACCESSED)
+#define PG_IS_PRESENT(pte) ((pte)&PG_PRESENT)
+
 #define NEW_L1_ENTRY(flags, pt_addr)                                           \
     (PG_ALIGN(pt_addr) | (((flags) | PG_WRITE_THROUGH) & 0xfff))
 #define NEW_L2_ENTRY(flags, pg_addr) (PG_ALIGN(pg_addr) | ((flags)&0xfff))
 #define HAS_FLAGS(entry, flags) ((PG_ENTRY_FLAGS(entry) & (flags)) == flags)
 #define CONTAINS_FLAGS(entry, flags) (PG_ENTRY_FLAGS(entry) & (flags))
 
-#define PG_PREM_R PG_PRESENT
-#define PG_PREM_RW PG_PRESENT | PG_WRITE
-#define PG_PREM_UR PG_PRESENT | PG_ALLOW_USER
-#define PG_PREM_URW PG_PRESENT | PG_WRITE | PG_ALLOW_USER
+#define PG_PREM_R (PG_PRESENT)
+#define PG_PREM_RW (PG_PRESENT | PG_WRITE)
+#define PG_PREM_UR (PG_PRESENT | PG_ALLOW_USER)
+#define PG_PREM_URW (PG_PRESENT | PG_WRITE | PG_ALLOW_USER)
 
 // 用于对PD进行循环映射,因为我们可能需要对PD进行频繁操作,我们在这里禁用TLB缓存
 #define T_SELF_REF_PERM PG_PREM_RW | PG_DISABLE_CACHE | PG_WRITE_THROUGH
@@ -75,11 +79,11 @@ typedef u32_t x86_pte_t;
 typedef struct
 {
     // 虚拟页地址
-    uintptr_t va;
+    ptr_t va;
     // 物理页码(如果不存在映射,则为0)
     u32_t pn;
     // 物理页地址(如果不存在映射,则为0)
-    uintptr_t pa;
+    ptr_t pa;
     // 映射的flags
     uint16_t flags;
     // PTE地址
@@ -95,17 +99,17 @@ extern void __pg_mount_point;
 
 /* 四个页挂载点,两个页目录挂载点: 用于临时创建&编辑页表 */
 #define PG_MOUNT_RANGE(l1_index) (701 <= l1_index && l1_index <= 703)
-#define PD_MOUNT_1 (KERNEL_MM_BASE + MEM_4MB)
-#define PG_MOUNT_BASE (PD_MOUNT_1 + MEM_4MB)
+#define VMS_MOUNT_1 (KERNEL_MM_BASE + MEM_4MB)
+#define PG_MOUNT_BASE (VMS_MOUNT_1 + MEM_4MB)
 #define PG_MOUNT_1 (PG_MOUNT_BASE)
 #define PG_MOUNT_2 (PG_MOUNT_BASE + 0x1000)
 #define PG_MOUNT_3 (PG_MOUNT_BASE + 0x2000)
 #define PG_MOUNT_4 (PG_MOUNT_BASE + 0x3000)
 
-#define PD_REFERENCED L2_BASE_VADDR
+#define VMS_SELF L2_BASE_VADDR
 
 #define CURPROC_PTE(vpn)                                                       \
-    (&((x86_page_table*)(PD_MOUNT_1 | (((vpn)&0xffc00) << 2)))                 \
+    (&((x86_page_table*)(VMS_MOUNT_1 | (((vpn)&0xffc00) << 2)))                \
         ->entry[(vpn)&0x3ff])
 #define PTE_MOUNTED(mnt, vpn)                                                  \
     (((x86_page_table*)((mnt) | (((vpn)&0xffc00) << 2)))->entry[(vpn)&0x3ff])
index 9978d728f808e60d6a23fe312fadce315d4595e0..99e9990a3e306c51e727ffd019c5c238e700954d 100644 (file)
@@ -3,19 +3,25 @@
 
 #include <lunaix/mm/mm.h>
 
+struct mm_region*
+region_create(ptr_t start, ptr_t end, u32_t attr);
+
+struct mm_region*
+region_create_range(ptr_t start, size_t length, u32_t attr);
+
+void
+region_add(vm_regions_t* lead, struct mm_region* vmregion);
+
 void
-region_add(struct mm_region* proc,
-           unsigned long start,
-           unsigned long end,
-           unsigned int attr);
+region_release(struct mm_region* region);
 
 void
-region_release_all(struct mm_region* proc);
+region_release_all(vm_regions_t* lead);
 
 struct mm_region*
-region_get(struct mm_region* proc, unsigned long vaddr);
+region_get(vm_regions_t* lead, unsigned long vaddr);
 
 void
-region_copy(struct mm_region* src, struct mm_region* dest);
+region_copy(struct proc_mm* src, struct proc_mm* dest);
 
 #endif /* __LUNAIX_REGION_H */
index 182058bf9835b444d9d56e8a5dbdac25fe1b2528..9749255b4a2565d0b079c6159508f18f98b4d449 100644 (file)
@@ -67,14 +67,25 @@ uintptr_t
 vmm_del_mapping(uintptr_t mnt, uintptr_t va);
 
 /**
- * @brief 查找一个映射
+ * @brief 在当前虚拟地址空间里查找一个映射
  *
  * @param va 虚拟地址
- * @return v_mapping 映射相关属性
+ * @param mapping 映射相关属性
  */
 int
 vmm_lookup(uintptr_t va, v_mapping* mapping);
 
+/**
+ * @brief 在指定的虚拟地址空间里查找一个映射
+ *
+ * @param mnt 地址空间锚定点
+ * @param va 虚拟地址
+ * @param mapping 映射相关属性
+ * @return int
+ */
+int
+vmm_lookupat(ptr_t mnt, uintptr_t va, v_mapping* mapping);
+
 /**
  * @brief (COW) 为虚拟页创建副本。
  *
@@ -119,7 +130,23 @@ vmm_next_free(uintptr_t start, int options);
 void*
 vmm_vmap(uintptr_t paddr, size_t size, pt_attr attr);
 
+/**
+ * @brief 将当前地址空间的虚拟地址转译为物理地址。
+ *
+ * @param va 虚拟地址
+ * @return void*
+ */
 void*
 vmm_v2p(void* va);
 
+/**
+ * @brief 将指定地址空间的虚拟地址转译为物理地址
+ *
+ * @param mnt 地址空间锚定点
+ * @param va 虚拟地址
+ * @return void*
+ */
+void*
+vmm_v2pat(ptr_t mnt, void* va);
+
 #endif /* __LUNAIX_VMM_H */
index 7674a925ab182dc7b90bfa9f41cff7c59f3d663a..27137a103db53763d07f7c28d02b5f9a5107df29 100644 (file)
@@ -6,6 +6,7 @@
 #include <lunaix/ds/waitq.h>
 #include <lunaix/fs.h>
 #include <lunaix/mm/mm.h>
+#include <lunaix/mm/region.h>
 #include <lunaix/signal.h>
 #include <lunaix/timer.h>
 #include <lunaix/types.h>
 
 #define PROC_FINPAUSE 1
 
-struct proc_mm
-{
-    heap_context_t u_heap;
-    struct mm_region regions;
-};
-
 struct proc_sigstate
 {
     isr_param proc_regs;
@@ -57,9 +52,9 @@ struct proc_info
     pid_t pid;                // offset = 0
     struct proc_info* parent; // offset = 4
     isr_param intr_ctx;       // offset = 8
-    uintptr_t ustack_top;     // offset = 84
-    void* page_table;         // offset = 88
-    void* fxstate;            // offset = 92
+    uintptr_t ustack_top;     // offset = 84 -> 56 -> 60
+    void* page_table;         // offset = 88 -> 60 -> 64
+    void* fxstate;            // offset = 92 -> 64 -> 68
 
     /* ---- critical section end ---- */
 
index 43cfb990b30023906adda352ee882df29e0383ad..c815c4f7cdf694332c77ba849cc5bc79facc5afa 100644 (file)
@@ -1,21 +1,21 @@
 #ifndef __LUNAIX_SIGNAL_H
 #define __LUNAIX_SIGNAL_H
 
-#include <lunaix/syscall.h>
+#include <signal_defs.h>
 
 #define _SIG_NUM 16
 
 #define _SIG_PENDING(bitmap, sig) ((bitmap) & (1 << (sig)))
 
-#define _SIGSEGV 1
-#define _SIGALRM 2
-#define _SIGCHLD 3
-#define _SIGCLD _SIGCHLD
-#define _SIGINT 4
-#define _SIGKILL 5
-#define _SIGSTOP 6
-#define _SIGCONT 7
-#define _SIGTERM 8
+#define _SIGSEGV SIGSEGV
+#define _SIGALRM SIGALRM
+#define _SIGCHLD SIGCHLD
+#define _SIGCLD SIGCLD
+#define _SIGINT SIGINT
+#define _SIGKILL SIGKILL
+#define _SIGSTOP SIGSTOP
+#define _SIGCONT SIGCONT
+#define _SIGTERM SIGTERM
 
 #define __SIGNAL(num) (1 << (num))
 #define __SIGSET(bitmap, num) (bitmap = bitmap | __SIGNAL(num))
 
 #define _SIGNAL_UNMASKABLE (__SIGNAL(_SIGKILL) | __SIGNAL(_SIGSTOP))
 
-#define _SIG_BLOCK 1
-#define _SIG_UNBLOCK 2
-#define _SIG_SETMASK 3
-
-typedef unsigned int sigset_t;
-typedef void (*sighandler_t)(int);
-
-__LXSYSCALL2(int, signal, int, signum, sighandler_t, handler);
-
-__LXSYSCALL1(int, sigpending, sigset_t, *set);
-__LXSYSCALL1(int, sigsuspend, const sigset_t, *mask);
-
-__LXSYSCALL3(int,
-             sigprocmask,
-             int,
-             how,
-             const sigset_t,
-             *set,
-             sigset_t,
-             *oldset);
+#define _SIG_BLOCK SIG_BLOCK
+#define _SIG_UNBLOCK SIG_UNBLOCK
+#define _SIG_SETMASK SIG_SETMASK
 
 #endif /* __LUNAIX_SIGNAL_H */
index 298593d5d3015e540f43650fb1ebabe5a948538b..6cece75784b807cd6c5e32a60d11a948edac5e54 100644 (file)
@@ -11,7 +11,7 @@
 // 除法 v/(2^k) 向下取整
 #define FLOOR(v, k) ((v) >> (k))
 
-// 获取v最近的最大k倍数
+// 获取v最近的最大k倍数 (k=2^n)
 #define ROUNDUP(v, k) (((v) + (k)-1) & ~((k)-1))
 
 // 获取v最近的最小k倍数 (k=2^m)
  *
  */
 #define ILOG2(x)                                                               \
-    __builtin_constant_p(x) ? ((x) == 0              ? 0                       \
-                               : ((x) & (1ul << 31)) ? 31                      \
-                               : ((x) & (1ul << 30)) ? 30                      \
-                               : ((x) & (1ul << 29)) ? 29                      \
-                               : ((x) & (1ul << 28)) ? 28                      \
-                               : ((x) & (1ul << 27)) ? 27                      \
-                               : ((x) & (1ul << 26)) ? 26                      \
-                               : ((x) & (1ul << 25)) ? 25                      \
-                               : ((x) & (1ul << 24)) ? 24                      \
-                               : ((x) & (1ul << 23)) ? 23                      \
-                               : ((x) & (1ul << 22)) ? 22                      \
-                               : ((x) & (1ul << 21)) ? 21                      \
-                               : ((x) & (1ul << 20)) ? 20                      \
-                               : ((x) & (1ul << 19)) ? 19                      \
-                               : ((x) & (1ul << 18)) ? 18                      \
-                               : ((x) & (1ul << 17)) ? 17                      \
-                               : ((x) & (1ul << 16)) ? 16                      \
-                               : ((x) & (1ul << 15)) ? 15                      \
-                               : ((x) & (1ul << 14)) ? 14                      \
-                               : ((x) & (1ul << 13)) ? 13                      \
-                               : ((x) & (1ul << 12)) ? 12                      \
-                               : ((x) & (1ul << 11)) ? 11                      \
-                               : ((x) & (1ul << 10)) ? 10                      \
-                               : ((x) & (1ul << 9))  ? 9                       \
-                               : ((x) & (1ul << 8))  ? 8                       \
-                               : ((x) & (1ul << 7))  ? 7                       \
-                               : ((x) & (1ul << 6))  ? 6                       \
-                               : ((x) & (1ul << 5))  ? 5                       \
-                               : ((x) & (1ul << 4))  ? 4                       \
-                               : ((x) & (1ul << 3))  ? 3                       \
-                               : ((x) & (1ul << 2))  ? 2                       \
-                               : ((x) & (1ul << 1))  ? 1                       \
-                                                     : 0)                       \
-                            : (31 - __builtin_clz(x))
+    (__builtin_constant_p(x) ? ((x) == 0              ? 0                      \
+                                : ((x) & (1ul << 31)) ? 31                     \
+                                : ((x) & (1ul << 30)) ? 30                     \
+                                : ((x) & (1ul << 29)) ? 29                     \
+                                : ((x) & (1ul << 28)) ? 28                     \
+                                : ((x) & (1ul << 27)) ? 27                     \
+                                : ((x) & (1ul << 26)) ? 26                     \
+                                : ((x) & (1ul << 25)) ? 25                     \
+                                : ((x) & (1ul << 24)) ? 24                     \
+                                : ((x) & (1ul << 23)) ? 23                     \
+                                : ((x) & (1ul << 22)) ? 22                     \
+                                : ((x) & (1ul << 21)) ? 21                     \
+                                : ((x) & (1ul << 20)) ? 20                     \
+                                : ((x) & (1ul << 19)) ? 19                     \
+                                : ((x) & (1ul << 18)) ? 18                     \
+                                : ((x) & (1ul << 17)) ? 17                     \
+                                : ((x) & (1ul << 16)) ? 16                     \
+                                : ((x) & (1ul << 15)) ? 15                     \
+                                : ((x) & (1ul << 14)) ? 14                     \
+                                : ((x) & (1ul << 13)) ? 13                     \
+                                : ((x) & (1ul << 12)) ? 12                     \
+                                : ((x) & (1ul << 11)) ? 11                     \
+                                : ((x) & (1ul << 10)) ? 10                     \
+                                : ((x) & (1ul << 9))  ? 9                      \
+                                : ((x) & (1ul << 8))  ? 8                      \
+                                : ((x) & (1ul << 7))  ? 7                      \
+                                : ((x) & (1ul << 6))  ? 6                      \
+                                : ((x) & (1ul << 5))  ? 5                      \
+                                : ((x) & (1ul << 4))  ? 4                      \
+                                : ((x) & (1ul << 3))  ? 3                      \
+                                : ((x) & (1ul << 2))  ? 2                      \
+                                : ((x) & (1ul << 1))  ? 1                      \
+                                                      : 0)                      \
+                             : (31 - __builtin_clz(x)))
 
 #define __USER__ __attribute__((section(".usrtext")))
 
@@ -81,6 +81,9 @@ spin()
     if (!(cond)) {                                                             \
         __assert_fail(msg, __FILE__, __LINE__);                                \
     }
+
+#define fail(msg) __assert_fail(msg, __FILE__, __LINE__);
+
 void
 __assert_fail(const char* expr, const char* file, unsigned int line)
   __attribute__((noinline, noreturn));
index f9b947de7f4bd309445a527a360ca5c259e1d236..31d2327f1f01bac60f867e66fdb86d8d62d1c00f 100644 (file)
@@ -30,5 +30,7 @@
 #define ENOTDEV -24
 #define EOVERFLOW -25
 #define ENOTBLK -26
+#define ENOEXEC -27
+#define E2BIG -28
 
 #endif /* __LUNAIX_CODE_H */
index 82fc4b9b6bc96f0998809f2f36b27682b28819f1..a512bd7b8a48cb21aafd6bd3d48c59dbbca54534 100644 (file)
@@ -27,7 +27,7 @@
 
 #define __SYSCALL_read 21
 #define __SYSCALL_write 22
-#define __SYSCALL_readdir 23
+#define __SYSCALL_sys_readdir 23
 #define __SYSCALL_mkdir 24
 #define __SYSCALL_lseek 25
 #define __SYSCALL_geterrno 26
 
 #define __SYSCALL_syslog 51
 
+#define __SYSCALL_sys_mmap 52
+#define __SYSCALL_munmap 53
+
+#define __SYSCALL_execve 54
+
 #define __SYSCALL_MAX 0x100
 
 #ifndef __ASM__
@@ -93,6 +98,11 @@ syscall_install();
     asmlinkage rettype __lxsys_##name(                                         \
       __PARAM_MAP4(t1, p1, t2, p2, t3, p3, t4, p4))
 
+#define __DEFINE_LXSYSCALL5(                                                   \
+  rettype, name, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5)                       \
+    asmlinkage rettype __lxsys_##name(                                         \
+      __PARAM_MAP5(t1, p1, t2, p2, t3, p3, t4, p4, t5, p5))
+
 #define __SYSCALL_INTERRUPTIBLE(code)                                          \
     asm("sti");                                                                \
     { code };                                                                  \
@@ -104,48 +114,54 @@ syscall_install();
     return (rettype)v;
 
 #define __LXSYSCALL(rettype, name)                                             \
-    static rettype name()                                                      \
+    rettype name()                                                             \
     {                                                                          \
         ___DOINT33(__SYSCALL_##name, rettype)                                  \
     }
 
 #define __LXSYSCALL1(rettype, name, t1, p1)                                    \
-    static rettype name(__PARAM_MAP1(t1, p1))                                  \
+    rettype name(__PARAM_MAP1(t1, p1))                                         \
     {                                                                          \
         asm("" ::"b"(p1));                                                     \
         ___DOINT33(__SYSCALL_##name, rettype)                                  \
     }
 
 #define __LXSYSCALL2(rettype, name, t1, p1, t2, p2)                            \
-    static rettype name(__PARAM_MAP2(t1, p1, t2, p2))                          \
+    rettype name(__PARAM_MAP2(t1, p1, t2, p2))                                 \
     {                                                                          \
         asm("\n" ::"b"(p1), "c"(p2));                                          \
         ___DOINT33(__SYSCALL_##name, rettype)                                  \
     }
 
 #define __LXSYSCALL3(rettype, name, t1, p1, t2, p2, t3, p3)                    \
-    static rettype name(__PARAM_MAP3(t1, p1, t2, p2, t3, p3))                  \
+    rettype name(__PARAM_MAP3(t1, p1, t2, p2, t3, p3))                         \
     {                                                                          \
         asm("\n" ::"b"(p1), "c"(p2), "d"(p3));                                 \
         ___DOINT33(__SYSCALL_##name, rettype)                                  \
     }
 
 #define __LXSYSCALL4(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4)            \
-    static rettype name(__PARAM_MAP4(t1, p1, t2, p2, t3, p3, t4, p4))          \
+    rettype name(__PARAM_MAP4(t1, p1, t2, p2, t3, p3, t4, p4))                 \
     {                                                                          \
         asm("\n" ::"b"(p1), "c"(p2), "d"(p3), "D"(p4));                        \
         ___DOINT33(__SYSCALL_##name, rettype)                                  \
     }
 
+#define __LXSYSCALL5(rettype, name, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5)    \
+    rettype name(__PARAM_MAP5(t1, p1, t2, p2, t3, p3, t4, p4, t5, p5))         \
+    {                                                                          \
+        asm("" ::"r"(p5), "b"(p1), "c"(p2), "d"(p3), "D"(p4), "S"(p5));        \
+        ___DOINT33(__SYSCALL_##name, rettype)                                  \
+    }
+
 #define __LXSYSCALL2_VARG(rettype, name, t1, p1, t2, p2)                       \
-    __attribute__((noinline)) static rettype name(                             \
-      __PARAM_MAP2(t1, p1, t2, p2), ...)                                       \
+    __attribute__((noinline)) rettype name(__PARAM_MAP2(t1, p1, t2, p2), ...)  \
     {                                                                          \
         /* No inlining! This depends on the call frame assumption */           \
         void* _last = (void*)&p2 + sizeof(void*);                              \
         asm("\n" ::"b"(p1), "c"(p2), "d"(_last));                              \
         ___DOINT33(__SYSCALL_##name, rettype)                                  \
     }
-#endif
 
+#endif
 #endif /* __LUNAIX_SYSCALL_H */
diff --git a/lunaix-os/includes/lunaix/syscall_utils.h b/lunaix-os/includes/lunaix/syscall_utils.h
new file mode 100644 (file)
index 0000000..fcc7dc3
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __LUNAIX_SYSCALL_UTILS_H
+#define __LUNAIX_SYSCALL_UTILS_H
+
+#include <lunaix/process.h>
+#include <lunaix/syscall.h>
+
+#define DO_STATUS(errno) SYSCALL_ESTATUS(__current->k_status = errno)
+#define DO_STATUS_OR_RETURN(errno) ({ errno < 0 ? DO_STATUS(errno) : errno; })
+
+#endif /* __LUNAIX_SYSCALL_UTILS_H */
index f99620f9aff93b52e8def4a70e470464fa253f74..a98ae976c8e63615ce4da5073002861d6627b59e 100644 (file)
@@ -2,23 +2,8 @@
 #define __LUNAIX_TYPES_H
 
 #include <stdarg.h>
-#include <stddef.h>
 #include <stdint.h>
-
-#define PEXITTERM 0x100
-#define PEXITSTOP 0x200
-#define PEXITSIG 0x400
-
-#define PEXITNUM(flag, code) (flag | (code & 0xff))
-
-#define WNOHANG 1
-#define WUNTRACED 2
-#define WEXITSTATUS(wstatus) ((wstatus & 0xff))
-#define WIFSTOPPED(wstatus) ((wstatus & PEXITSTOP))
-#define WIFEXITED(wstatus)                                                     \
-    ((wstatus & PEXITTERM) && ((char)WEXITSTATUS(wstatus) >= 0))
-
-#define WIFSIGNALED(wstatus) ((wstatus & PEXITSIG))
+#include <sys/types.h>
 
 #define PACKED __attribute__((packed))
 
@@ -31,9 +16,7 @@ typedef unsigned short u16_t;
 typedef unsigned int u32_t;
 typedef unsigned long long u64_t;
 typedef unsigned long ptr_t;
-typedef signed long ssize_t;
 
-typedef int32_t pid_t;
 typedef int64_t lba_t;
 
 #endif /* __LUNAIX_TYPES_H */
index 2961f3b7d89f50a8f01677abbf1d452bc972b323..23df5b507a3a0b7c213d1a0407930a0b6c09d23d 100644 (file)
@@ -9,6 +9,8 @@
     .global debug_resv
     debug_resv:
         .skip 16
+    tmp_store:
+        .skip 4
 #endif
 
 .section .bss
         .skip 128
     tmp_stack:
 
+/*
+    This perhaps the ugliest part in the project. 
+    It contains code to handle arbitrary depth of 
+    nested interrupt and all those corner cases and 
+    nasty gotchas.
+
+    Be aware the twists, offsets and hidden dependencies!
+
+*/
+
 .section .text
     .global interrupt_wrapper
     interrupt_wrapper:
         /*
          Stack layout (layout of struct isr_param)
-    msa:   [ss]
-           [esp]
-           eflags     > offset = 48 + 16 = 64
-           cs
-           eip
-           err_code   
-           vector     > offset = 28 + 16 + 4 = 48
+    msa:   [ss]             > 76
+           [esp]            > 72
+           eflags           > 68
+           cs               > 64
+           eip              > 60
+           err_code         > 56
+           vector           > offset = 52
+           [saved_prev_ctx] > offset = 0
+           ---
            esp
            gs
            fs
            es
-           ds         > offset = 7 * 4 = 28
+           ds         > offset = 7 * 4 = 28 + 4
            esi
            ebp
            edi
            edx
            ecx
            ebx
-    lsa:   eax        > offset = 0
+           eax
+    lsa:   depth       > offset = 0
 
             las: Least Significant Address
             msa: Most Significant Address
         */
         cld
+
+        subl $52, %esp
         pushl %esp
 
         subl $16, %esp
         pushl %ebx
         pushl %eax
 
-        movl 60(%esp), %eax   /* 取出 %cs */
+        movl __current, %eax
+        movl 8(%eax), %eax
+        incl %eax
+        pushl %eax          # nested intr: current depth
+
+        movl 116(%esp), %eax   /* 取出 %cs */
         andl $0x3, %eax          /* 判断 RPL */
         jz 1f
 
 
         # 保存用户栈顶指针。这是因为我们允许系统调用内进行上下文切换,而这样一来,我们就失去了用户栈的信息,
         # 这样一来,就无法设置信号上下文。这主要是为了实现了pause()而做的准备
-        movl (__current), %eax
+        movl __current, %eax
 
         # 保存x87FPU的状态
-        movl 92(%eax), %ebx
+        movl 68(%eax), %ebx
         fxsave (%ebx)
 
-        movl 68(%esp), %ebx     # 取出esp
-        movl %ebx, 84(%eax)     # 存入__current->ustack_top
+        movl 124(%esp), %ebx     # 取出esp
+        movl %ebx, 60(%eax)     # 存入__current->ustack_top
 
     1:
         movl %esp, %eax
 
 #ifdef __ASM_INTR_DIAGNOSIS
         movl %eax, (debug_resv + 8)
-        movl 56(%esp), %eax
-        movl %eax, (debug_resv + 4)
+        movl 48(%esp), %eax
+        movl 60(%eax), %eax
+        movl %eax, (debug_resv + 4) # eip
 #endif
-        movl (__current), %eax
-        movl 92(%eax), %eax
+        movl __current, %eax
+        movl 68(%eax), %eax
         
         test %eax, %eax     # do we have stored x87 context?
         jz 1f 
         fxrstor (%eax)      
 1:
+        popl %eax   # discard isr_param::depth
         popl %eax
         popl %ebx
         popl %ecx
 
         movl 16(%esp), %esp
 
+        movl %eax, tmp_store
+        movl __current, %eax
+        # nested intr: restore saved context
+        popl 8(%eax)       # depth
+        popl 12(%eax)      # eax
+        popl 16(%eax)      # ebx
+        popl 20(%eax)      # ecx
+        popl 24(%eax)      # edx
+        popl 28(%eax)      # edi
+        popl 32(%eax)      # ebp
+        popl 36(%eax)      # esi
+        popl 40(%eax)      # ds
+        popl 44(%eax)      # es
+        popl 48(%eax)      # fs
+        popl 52(%eax)      # gs
+        popl 56(%eax)      # esp
+
         addl $8, %esp
 
-        pushl %eax
 #ifdef __ASM_INTR_DIAGNOSIS
-        movl 4(%esp), %eax
+        movl (%esp), %eax
         movl %eax, debug_resv
 #endif
         # 处理TSS.ESP的一些边界条件。如果是正常iret(即从内核模式*优雅地*退出)
         # 那么TSS.ESP0应该为iret进行弹栈后,%esp的值。
         # 所以这里的边界条件是:如返回用户模式,iret会额外弹出8个字节(ss,esp)
-        movl 8(%esp), %eax
+        movl 4(%esp), %eax
         andl $3, %eax
         setnz %al
         shll $3, %eax
-        addl $16, %eax
+        addl $12, %eax
         addl %esp, %eax
         movl %eax, (_tss + 4)
-        popl %eax
+        movl tmp_store, %eax
         iret
 
     .global switch_to
 
         popl %ebx               # next
         movl __current, %eax    
-        movl 88(%eax), %ecx     # __current->pagetable
-        movl 88(%ebx), %eax     # next->pagetable
+        movl 64(%eax), %ecx     # __current->pagetable
+        movl 64(%ebx), %eax     # next->pagetable
         
         cmpl %ecx, %eax         # if(next->pagtable != __current->pagetable) {
         jz 1f
 
         pushl $UDATA_SEG        # proc_sig->prev_context.proc_regs.ss
         pushl %eax              # esp
-        pushl 64(%ebx)          # proc_sig->prev_context.proc_regs.eflags
+        movl 48(%ebx), %ebx
+        pushl 68(%ebx)          # proc_sig->prev_context.proc_regs.execp->eflags
         pushl $UCODE_SEG        # cs
         pushl $sig_wrapper      # eip for sig wrapper
 
         pushl %eax              # Addr to proc_sig structure 
         pushl 4(%eax)           # proc_sig->sig_num     ---- 16 bytes aligned
 
-        call (%eax)             # invoke signal handler
+        call *(%eax)             # invoke signal handler
 
         # invoke the sigreturn syscall to exit the signal wrapper
         movl $__SYSCALL_sigreturn, %eax
index 25b3791e7415f73af0d632d3702e020ced94a9a3..3fb24cbc054eab3d955078da2a27d42d35ee00e7 100644 (file)
@@ -19,26 +19,27 @@ extern x86_page_table* __kernel_ptd;
 void
 intr_handler(isr_param* param)
 {
+    param->execp->saved_prev_ctx = __current->intr_ctx;
     __current->intr_ctx = *param;
 
-    isr_param* lparam = &__current->intr_ctx;
+    volatile struct exec_param* execp = __current->intr_ctx.execp;
 
-    if (lparam->vector <= 255) {
-        isr_cb subscriber = isrm_get(lparam->vector);
+    if (execp->vector <= 255) {
+        isr_cb subscriber = isrm_get(execp->vector);
         subscriber(param);
         goto done;
     }
 
     kprint_panic("INT %u: (%x) [%p: %p] Unknown",
-                 lparam->vector,
-                 lparam->err_code,
-                 lparam->cs,
-                 lparam->eip);
+                 execp->vector,
+                 execp->err_code,
+                 execp->cs,
+                 execp->eip);
 
 done:
     // for all external interrupts except the spurious interrupt
     //  this is required by Intel Manual Vol.3A, section 10.8.1 & 10.8.5
-    if (lparam->vector >= IV_EX && lparam->vector != APIC_SPIV_IV) {
+    if (execp->vector >= IV_EX && execp->vector != APIC_SPIV_IV) {
         apic_done_servicing();
     }
 
index 97903cffebfdc5c1e3e145485e71825605527e90..f4bebae4159490173e9df5c693421ed503890121 100644 (file)
@@ -22,11 +22,12 @@ extern u32_t debug_resv;
 void
 __print_panic_msg(const char* msg, const isr_param* param)
 {
+    struct exec_param* execp = param->execp;
     kprint_panic("  INT %u: (%x) [%p: %p] %s",
-                 param->vector,
-                 param->err_code,
-                 param->cs,
-                 param->eip,
+                 execp->vector,
+                 execp->err_code,
+                 execp->cs,
+                 execp->eip,
                  msg);
 }
 
index fcd52cc26480058f3a83b2144e8b46ee0b2c949a..610c1cb978fd0dd1031a4d5825b6cbbacc8fbb36 100644 (file)
@@ -1,14 +1,16 @@
 #include <arch/x86/interrupts.h>
 #include <lunaix/common.h>
-#include <lunaix/lxsignal.h>
 #include <lunaix/mm/mm.h>
 #include <lunaix/mm/pmm.h>
 #include <lunaix/mm/region.h>
 #include <lunaix/mm/vmm.h>
 #include <lunaix/sched.h>
+#include <lunaix/signal.h>
 #include <lunaix/status.h>
 #include <lunaix/syslog.h>
 
+#include <klibc/string.h>
+
 static void
 kprintf(const char* fmt, ...)
 {
@@ -36,7 +38,7 @@ intr_routine_page_fault(const isr_param* param)
         goto segv_term;
     }
 
-    if (!SEL_RPL(param->cs)) {
+    if (!SEL_RPL(param->execp->cs)) {
         // 如果是内核页错误……
         if (do_kernel(&mapping)) {
             return;
@@ -51,48 +53,87 @@ intr_routine_page_fault(const isr_param* param)
         goto segv_term;
     }
 
-    volatile x86_pte_t* pte = &PTE_MOUNTED(PD_REFERENCED, ptr >> 12);
-    if ((*pte & PG_PRESENT)) {
+    volatile x86_pte_t* pte = &PTE_MOUNTED(VMS_SELF, ptr >> 12);
+    if (PG_IS_PRESENT(*pte)) {
         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;
+            *pte = (*pte & 0xFFF & ~PG_DIRTY) | pa | PG_WRITE;
             goto resolved;
         }
         // impossible cases or accessing privileged page
         goto segv_term;
     }
 
-    if (!(*pte)) {
-        // Invalid location
+    // an anonymous page and not present
+    //   -> a new page need to be alloc
+    if ((hit_region->attr & REGION_ANON)) {
+        if (!PG_IS_PRESENT(*pte)) {
+            cpu_invplg(pte);
+            uintptr_t pa = pmm_alloc_page(__current->pid, 0);
+            if (!pa) {
+                goto oom;
+            }
+
+            *pte = *pte | pa | PG_PRESENT;
+            memset(PG_ALIGN(ptr), 0, PG_SIZE);
+            goto resolved;
+        }
+        // permission denied on anon page (e.g., write on readonly page)
         goto segv_term;
     }
 
-    uintptr_t loc = *pte & ~0xfff;
+    // if mfile is set (Non-anonymous), then it is a mem map
+    if (hit_region->mfile && !PG_IS_PRESENT(*pte)) {
+        struct v_file* file = hit_region->mfile;
 
-    // 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);
+        ptr = PG_ALIGN(ptr);
+
+        u32_t offset = (ptr - hit_region->start) + hit_region->foff;
         uintptr_t pa = pmm_alloc_page(__current->pid, 0);
-        *pte = *pte | pa | PG_PRESENT;
+
+        if (!pa) {
+            goto oom;
+        }
+
+        cpu_invplg(pte);
+        *pte = (*pte & 0xFFF) | pa | PG_PRESENT;
+
+        memset(ptr, 0, PG_SIZE);
+
+        int errno = 0;
+        if (hit_region->init_page) {
+            errno = hit_region->init_page(hit_region, ptr, offset);
+        } else {
+            errno = file->ops->read_page(file->inode, ptr, PG_SIZE, offset);
+        }
+
+        if (errno < 0) {
+            kprintf(KERROR "fail to populate page (%d)\n", errno);
+            goto segv_term;
+        }
+
+        *pte &= ~PG_DIRTY;
+
         goto resolved;
     }
 
-    // page not present, bring it from disk or somewhere else
+    // page not present, might be a chance to introduce swap file?
     __print_panic_msg("WIP page fault route", param);
     while (1)
         ;
 
+oom:
+    kprintf(KERROR "out of memory\n");
 segv_term:
     kprintf(KERROR "(pid: %d) Segmentation fault on %p (%p:%p)\n",
             __current->pid,
             ptr,
-            param->cs,
-            param->eip);
+            param->execp->cs,
+            param->execp->eip);
     __SIGSET(__current->sig_pending, _SIGSEGV);
     schedule();
     // should not reach
index 93ea1c7bf63230b1faf7c330c4c71d4142b1d483..62e07212264d300aed2a80d7aaee2c0d0267d635 100644 (file)
@@ -30,7 +30,7 @@
         .long __lxsys_close         /* 20 */
         .long __lxsys_read
         .long __lxsys_write
-        .long __lxsys_readdir
+        .long __lxsys_sys_readdir
         .long __lxsys_mkdir
         .long __lxsys_lseek         /* 25 */
         .long __lxsys_geterrno
@@ -59,6 +59,9 @@
         .long __lxsys_getpgid
         .long __lxsys_setpgid       /* 50 */
         .long __lxsys_syslog
+        .long __lxsys_sys_mmap
+        .long __lxsys_munmap
+        .long __lxsys_execve
         2:
         .rept __SYSCALL_MAX - (2b - 1b)/4
             .long 0
 .section .text
     syscall_hndlr:
         pushl %ebp
-        movl 8(%esp), %ebp
+        movl 8(%esp), %ebp          // isr_param*
 
-        movl  (%ebp), %eax          /* eax: call code as well as the return value from syscall */
-        cmpl  $__SYSCALL_MAX, %eax
+        addl $4, %ebp
+        movl (%ebp), %eax          /* eax: call code as well as the return value from syscall */
+        cmpl $__SYSCALL_MAX, %eax
         jae 2f
 
         shll $2, %eax
@@ -84,8 +88,7 @@
         popl  %ebp
         ret
     1:
-        pushl 24(%ebp)      /* esi - #6 arg */
-        pushl 20(%ebp)      /* ebp - #5 arg */
+        pushl 24(%ebp)      /* esi - #5 arg */
         pushl 16(%ebp)      /* edi - #4 arg */
         pushl 12(%ebp)      /* edx - #3 arg */
         pushl 8(%ebp)       /* ecx - #2 arg */
@@ -95,7 +98,7 @@
 
         movl %eax, (%ebp)    /* save the return value */
 
-        addl $24, %esp      /* remove the parameters from stack */
+        addl $20, %esp      /* remove the parameters from stack */
 
         popl %ebp
         
diff --git a/lunaix-os/kernel/demos/dir_read.c b/lunaix-os/kernel/demos/dir_read.c
deleted file mode 100644 (file)
index e1ef7a2..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <lunaix/dirent.h>
-#include <lunaix/fctrl.h>
-#include <lunaix/lunaix.h>
-#include <lunaix/lunistd.h>
-
-void
-_readdir_main()
-{
-    int fd = open("/dev/./../dev/.", 0);
-    if (fd == -1) {
-        printf("fail to open (%d)\n", geterrno());
-        return;
-    }
-
-    char path[129];
-    int len = realpathat(fd, path, 128);
-    if (len < 0) {
-        printf("fail to read (%d)\n", geterrno());
-    } else {
-        path[len] = 0;
-        printf("%s\n", path);
-    }
-
-    struct dirent ent = { .d_offset = 0 };
-
-    while (readdir(fd, &ent) == 1) {
-        printf("%s\n", ent.d_name);
-    }
-
-    close(fd);
-
-    return;
-}
\ No newline at end of file
diff --git a/lunaix-os/kernel/demos/input_test.c b/lunaix-os/kernel/demos/input_test.c
deleted file mode 100644 (file)
index 47e0081..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <lunaix/fctrl.h>
-#include <lunaix/foptions.h>
-#include <lunaix/input.h>
-#include <lunaix/lunaix.h>
-#include <lunaix/lunistd.h>
-#include <ulibc/stdio.h>
-
-#define STDIN 1
-#define STDOUT 0
-
-void
-input_test()
-{
-    int fd = open("/dev/input/i8042-kbd", 0);
-
-    if (fd < 0) {
-        printf("fail to open (%d)", geterrno());
-        return;
-    }
-
-    struct input_evt_pkt event;
-
-    while (read(fd, &event, sizeof(event)) > 0) {
-        char* action;
-        if (event.pkt_type == PKT_PRESS) {
-            action = "pressed";
-        } else {
-            action = "release";
-        }
-
-        printf("%u: %s '%c', class=0x%x, scan=%x\n",
-               event.timestamp,
-               action,
-               event.sys_code & 0xff,
-               (event.sys_code & 0xff00) >> 8,
-               event.scan_code);
-    }
-    return;
-}
\ No newline at end of file
diff --git a/lunaix-os/kernel/demos/iotest.c b/lunaix-os/kernel/demos/iotest.c
deleted file mode 100644 (file)
index cba8962..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#include <lunaix/fctrl.h>
-#include <lunaix/foptions.h>
-#include <lunaix/lunaix.h>
-#include <lunaix/lunistd.h>
-#include <ulibc/stdio.h>
-
-void
-_iotest_main()
-{
-    char test_sequence[] = "Once upon a time, in a magical land of Equestria. "
-                           "There were two regal sisters who ruled together "
-                           "and created harmony for all the land.";
-    char read_out[256];
-
-    // 切换工作目录至 /dev
-    int errno = chdir("/dev");
-    if (errno) {
-        write(stdout, "fail to chdir", 15);
-        return;
-    }
-
-    if (getcwd(read_out, sizeof(read_out))) {
-        printf("current working dir: %s\n", read_out);
-    }
-
-    // sda 设备 - 硬盘
-    //  sda设备属于容积设备(Volumetric Device),
-    //  Lunaix会尽可能缓存任何对此设备的上层读写,并使用延迟写入策略。(FO_DIRECT可用于屏蔽该功能)
-    int fd = open("./sda", 0);
-
-    if (fd < 0) {
-        printf("fail to open (%d)\n", geterrno());
-        return;
-    }
-
-    // 移动指针至512字节,在大多数情况下,这是第二个逻辑扇区的起始处
-    lseek(fd, 512, FSEEK_SET);
-
-    // 总共写入 64 * 136 字节,会产生3个页作为缓存
-    for (size_t i = 0; i < 64; i++) {
-        write(fd, test_sequence, sizeof(test_sequence));
-    }
-
-    // 随机读写测试
-    lseek(fd, 4 * 4096, FSEEK_SET);
-    write(fd, test_sequence, sizeof(test_sequence));
-
-    printf("input: ");
-    int size = read(stdin, read_out, 256);
-
-    printf("your said: %s\n", read_out);
-
-    write(fd, read_out, size);
-
-    // 读出我们写的内容
-    lseek(fd, 512, FSEEK_SET);
-    read(fd, read_out, sizeof(read_out));
-
-    // 将读出的内容直接写入tty设备
-    write(stdout, read_out, sizeof(read_out));
-    write(stdout, "\n", 1);
-
-    // 关闭文件,这同时会将页缓存中的数据下发到底层驱动
-    close(fd);
-}
\ No newline at end of file
diff --git a/lunaix-os/kernel/demos/signal_demo.c b/lunaix-os/kernel/demos/signal_demo.c
deleted file mode 100644 (file)
index 3878a18..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#include <lunaix/lunaix.h>
-#include <lunaix/lunistd.h>
-#include <lunaix/signal.h>
-#include <lunaix/spike.h>
-#include <lunaix/types.h>
-#include <ulibc/stdio.h>
-
-void __USER__
-sigchild_handler(int signum)
-{
-    printf("SIGCHLD received\n");
-}
-
-void __USER__
-sigsegv_handler(int signum)
-{
-    pid_t pid = getpid();
-    printf("SIGSEGV received on process %d\n", pid);
-    _exit(signum);
-}
-
-void __USER__
-sigalrm_handler(int signum)
-{
-    pid_t pid = getpid();
-    printf("I, pid %d, have received an alarm!\n", pid);
-}
-
-void __USER__
-_signal_demo_main()
-{
-    signal(_SIGCHLD, sigchild_handler);
-    signal(_SIGSEGV, sigsegv_handler);
-    signal(_SIGALRM, sigalrm_handler);
-
-    alarm(5);
-
-    int status;
-    pid_t p = 0;
-
-    printf("Child sleep 3s, parent pause.\n");
-    if (!fork()) {
-        sleep(3);
-        _exit(0);
-    }
-
-    pause();
-
-    printf("Parent resumed on SIGCHILD\n");
-
-    for (int i = 0; i < 5; i++) {
-        pid_t pid = 0;
-        if (!(pid = fork())) {
-            signal(_SIGSEGV, sigsegv_handler);
-            sleep(i);
-            if (i == 3) {
-                i = *(int*)0xdeadc0de; // seg fault!
-            }
-            printf("%d\n", i);
-            _exit(0);
-        }
-        printf("Forked %d\n", pid);
-    }
-
-    while ((p = wait(&status)) >= 0) {
-        short code = WEXITSTATUS(status);
-        if (WIFSIGNALED(status)) {
-            printf("Process %d terminated by signal, exit_code: %d\n", p, code);
-        } else if (WIFEXITED(status)) {
-            printf("Process %d exited with code %d\n", p, code);
-        } else {
-            printf("Process %d aborted with code %d\n", p, code);
-        }
-    }
-
-    printf("done\n");
-}
\ No newline at end of file
diff --git a/lunaix-os/kernel/demos/simple_sh.c b/lunaix-os/kernel/demos/simple_sh.c
deleted file mode 100644 (file)
index acebe21..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-#include <lunaix/fctrl.h>
-#include <lunaix/foptions.h>
-#include <lunaix/ioctl.h>
-#include <lunaix/lunaix.h>
-#include <lunaix/lunistd.h>
-#include <lunaix/signal.h>
-#include <lunaix/status.h>
-
-#include <klibc/string.h>
-#include <ulibc/stdio.h>
-
-char pwd[512];
-char cat_buf[1024];
-
-/*
-    Simple shell - (actually this is not even a shell)
-    It just to make the testing more easy.
-*/
-
-void
-parse_cmdline(char* line, char** cmd, char** arg_part)
-{
-    strrtrim(line);
-    line = strltrim_safe(line);
-    int l = 0;
-    char c = 0;
-    while ((c = line[l])) {
-        if (c == ' ') {
-            line[l++] = 0;
-            break;
-        }
-        l++;
-    }
-    *cmd = line;
-    *arg_part = strltrim_safe(line + l);
-}
-
-void
-sh_printerr()
-{
-    int errno = geterrno();
-    switch (errno) {
-        case ENOTDIR:
-            printf("Error: Not a directory\n");
-            break;
-        case ENOENT:
-            printf("Error: No such file or directory\n");
-            break;
-        case EINVAL:
-            printf("Error: Invalid parameter or operation\n");
-            break;
-        case ENOTSUP:
-            printf("Error: Not supported\n");
-            break;
-        case EROFS:
-            printf("Error: File system is read only\n");
-            break;
-        case ENOMEM:
-            printf("Error: Out of memory\n");
-            break;
-        case EISDIR:
-            printf("Error: This is a directory\n");
-            break;
-        default:
-            printf("Error: (%d)\n", errno);
-            break;
-    }
-}
-
-void
-sigint_handle(int signum)
-{
-    return;
-}
-
-void
-do_cat(const char* file)
-{
-    int fd = open(file, 0);
-    if (fd < 0) {
-        sh_printerr();
-    } else {
-        int sz;
-        while ((sz = read(fd, cat_buf, 1024)) > 0) {
-            write(stdout, cat_buf, sz);
-        }
-        if (sz < 0) {
-            sh_printerr();
-        }
-        close(fd);
-        printf("\n");
-    }
-}
-
-void
-do_ls(const char* path)
-{
-    int fd = open(path, 0);
-    if (fd < 0) {
-        sh_printerr();
-    } else {
-        struct dirent ent = { .d_offset = 0 };
-        int status;
-        while ((status = readdir(fd, &ent)) == 1) {
-            if (ent.d_type == DT_DIR) {
-                printf(" \033[3m%s\033[39;49m\n", ent.d_name);
-            } else {
-                printf(" %s\n", ent.d_name);
-            }
-        }
-
-        if (status < 0)
-            sh_printerr();
-
-        close(fd);
-    }
-}
-
-void
-sh_loop()
-{
-    char buf[512];
-    char *cmd, *argpart;
-    pid_t p;
-    signal(_SIGINT, sigint_handle);
-
-    // set our shell as foreground process
-    // (unistd.h:tcsetpgrp is essentially a wrapper of this)
-    // stdout (by default, unless user did smth) is the tty we are currently at
-    ioctl(stdout, TIOCSPGRP, getpgid());
-
-    while (1) {
-        getcwd(pwd, 512);
-        printf("[\033[2m%s\033[39;49m]$ ", pwd);
-        size_t sz = read(stdin, buf, 511);
-        if (sz < 0) {
-            printf("fail to read user input (%d)\n", geterrno());
-            return;
-        }
-        buf[sz] = '\0';
-        parse_cmdline(buf, &cmd, &argpart);
-        if (cmd[0] == 0) {
-            printf("\n");
-            goto cont;
-        }
-        if (streq(cmd, "cd")) {
-            if (chdir(argpart) < 0) {
-                sh_printerr();
-            }
-            goto cont;
-        } else if (streq(cmd, "clear")) {
-            ioctl(stdout, TIOCCLSBUF);
-            goto cont;
-        } else if (streq(cmd, "ls")) {
-            if (!(p = fork())) {
-                do_ls(argpart);
-                _exit(0);
-            }
-        } else if (streq(cmd, "cat")) {
-            if (!(p = fork())) {
-                do_cat(argpart);
-                _exit(0);
-            }
-        } else {
-            printf("unknow command\n");
-            goto cont;
-        }
-        setpgid(p, getpgid());
-        waitpid(p, NULL, 0);
-    cont:
-        printf("\n");
-    }
-}
-
-void
-sh_main()
-{
-    printf("\n Simple shell. Use <PG_UP> or <PG_DOWN> to scroll.\n\n");
-    if (!fork()) {
-        sh_loop();
-        _exit(0);
-    }
-    wait(NULL);
-}
\ No newline at end of file
index c265c4b36aa3b08e4e2b598ad8edd57da28b7b6e..867f93d1ca76891deb65d24f33b1c65fe6fea7d4 100644 (file)
@@ -1,9 +1,10 @@
 #include <lunaix/device.h>
-#include <lunaix/dirent.h>
 #include <lunaix/fs.h>
 #include <lunaix/fs/devfs.h>
 #include <lunaix/spike.h>
 
+#include <sys/dirent_defs.h>
+
 extern struct v_inode_ops devfs_inode_ops;
 extern struct v_file_ops devfs_file_ops;
 
index b784fdbf4c3649bfcf49d99781dfa139da9a2846..3647f10a87f778395cb4efba6f4080b622cd0f63 100644 (file)
@@ -6,6 +6,7 @@
 #include <lunaix/mm/valloc.h>
 #include <lunaix/spike.h>
 #include <lunaix/syscall.h>
+#include <lunaix/syscall_utils.h>
 
 static DEFINE_LLIST(root_list);
 
index c3150dcbb64426b7da5bd2fe5c4ed5469694a2be..1d35978b06f84b3ead66688b1b661a875bb13a38 100644 (file)
@@ -1,4 +1,3 @@
-#include <lunaix/dirent.h>
 #include <lunaix/fs.h>
 #include <lunaix/fs/iso9660.h>
 #include <lunaix/mm/cake.h>
@@ -7,6 +6,8 @@
 
 #include <klibc/string.h>
 
+#include <sys/dirent_defs.h>
+
 extern struct cake_pile* drec_cache_pile;
 
 void
index 7db951389e3866499f772e201e9a49eff8c118f5..12e1d4b94c273acc87df26203f8ea96c2b611711 100644 (file)
@@ -3,6 +3,7 @@
 #include <lunaix/mm/valloc.h>
 #include <lunaix/process.h>
 #include <lunaix/spike.h>
+#include <lunaix/syscall_utils.h>
 #include <lunaix/syslog.h>
 #include <lunaix/types.h>
 
index a0331e70139d644b1a4657d2c9d64aaa404bfe04..cd0ac01565e4616ca68901a8ccaa7ed2938b244b 100644 (file)
@@ -1,5 +1,6 @@
 #include <lunaix/fs.h>
 #include <lunaix/mm/valloc.h>
+#include <lunaix/process.h>
 #include <lunaix/spike.h>
 
 #include <klibc/string.h>
index 009cdf319ef8fce97cc69e4ca5b3420a0096286d..2371eb8b257b63b1991986e5f04a954ee324798f 100644 (file)
@@ -6,7 +6,7 @@
 #include <klibc/stdio.h>
 #include <klibc/string.h>
 
-#define TWIMAP_BUFFER_SIZE 1024
+#define TWIMAP_BUFFER_SIZE 4096
 
 void
 __twimap_default_reset(struct twimap* map)
@@ -62,6 +62,11 @@ twimap_read(struct twimap* map, void* buffer, size_t len, size_t fpos)
         acc_size += rdlen;
     }
 
+    if (acc_size <= len - 1) {
+        // pad zero
+        *(char*)(buffer + acc_size + 1) = 0;
+    }
+
     vfree(map->buffer);
     return acc_size;
 }
@@ -75,7 +80,7 @@ twimap_printf(struct twimap* mapping, const char* fmt, ...)
     char* buf = mapping->buffer + mapping->size_acc;
 
     mapping->size_acc +=
-      __ksprintf_internal(buf, fmt, TWIMAP_BUFFER_SIZE, args);
+      __ksprintf_internal(buf, fmt, TWIMAP_BUFFER_SIZE, args) - 1;
 
     va_end(args);
 }
@@ -112,6 +117,7 @@ twimap_create(void* data)
 
 struct v_file_ops twimap_file_ops = { .close = default_file_close,
                                       .read = __twimap_file_read,
+                                      .read_page = __twimap_file_read,
                                       .readdir = default_file_readdir,
                                       .seek = default_file_seek,
                                       .write = default_file_write };
\ No newline at end of file
index 9680f2e9056a274b734d048853c4001cea05e254..8a4a8a17e0a9f148f0307e2b6f32f43b27d0558f 100644 (file)
@@ -44,7 +44,6 @@
 */
 
 #include <klibc/string.h>
-#include <lunaix/dirent.h>
 #include <lunaix/foptions.h>
 #include <lunaix/fs.h>
 #include <lunaix/mm/cake.h>
 #include <lunaix/process.h>
 #include <lunaix/spike.h>
 #include <lunaix/syscall.h>
+#include <lunaix/syscall_utils.h>
 
 #include <lunaix/fs/twifs.h>
 
+#include <sys/dirent_defs.h>
+
 static struct cake_pile* dnode_pile;
 static struct cake_pile* inode_pile;
 static struct cake_pile* file_pile;
@@ -624,13 +626,13 @@ __vfs_readdir_callback(struct dir_context* dctx,
                        const int len,
                        const int dtype)
 {
-    struct dirent* dent = (struct dirent*)dctx->cb_data;
+    struct lx_dirent* dent = (struct lx_dirent*)dctx->cb_data;
     strncpy(dent->d_name, name, DIRENT_NAME_MAX_LEN);
     dent->d_nlen = len;
     dent->d_type = dtype;
 }
 
-__DEFINE_LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent)
+__DEFINE_LXSYSCALL2(int, sys_readdir, int, fd, struct lx_dirent*, dent)
 {
     struct v_fd* fd_s;
     int errno;
@@ -1223,6 +1225,12 @@ done:
     return DO_STATUS(errno);
 }
 
+void
+vfs_ref_file(struct v_file* file)
+{
+    atomic_fetch_add(&file->ref_count, 1);
+}
+
 void
 vfs_ref_dnode(struct v_dnode* dnode)
 {
index 94f85b76dce7489708124e87a8a34f7988e4451d..6fdb300727f574972c5c3b99d104956681111efd 100644 (file)
@@ -1,7 +1,11 @@
 #include <klibc/string.h>
 #include <lunaix/fs.h>
 #include <lunaix/mm/valloc.h>
+#include <lunaix/process.h>
 #include <lunaix/syscall.h>
+#include <lunaix/syscall_utils.h>
+
+#define DO_STATUS(errno) SYSCALL_ESTATUS(__current->k_status = errno)
 
 struct v_xattr_entry*
 xattr_new(struct hstr* name)
index e0730e32fef15ab7aeaadb12f159dcbbed86965a..a2edf1a9d5c66007b5ada75b4e93aa0e80ad92cb 100644 (file)
@@ -127,11 +127,7 @@ spawn_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() };
+                                                  .gs = KDATA_SEG } };
     proc0->parent = proc0;
 
     // 方案1:必须在读取eflags之后禁用。否则当进程被调度时,中断依然是关闭的!
@@ -148,26 +144,21 @@ spawn_proc0()
     // 为内核创建一个专属栈空间。
     for (size_t i = 0; i < (KSTACK_SIZE >> PG_SIZE_BITS); i++) {
         uintptr_t pa = pmm_alloc_page(KERNEL_PID, 0);
-        vmm_set_mapping(PD_REFERENCED,
+        vmm_set_mapping(VMS_SELF,
                         KSTACK_START + (i << PG_SIZE_BITS),
                         pa,
                         PG_PREM_RW,
                         VMAP_NULL);
     }
 
-    // 手动设置进程上下文:用于第一次调度
-    asm volatile("movl %%esp, %%ebx\n"
-                 "movl %1, %%esp\n"
-                 "pushf\n"
-                 "pushl %2\n"
-                 "pushl %3\n"
-                 "pushl $0\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)
-                 : "%ebx", "memory");
+    struct exec_param* execp =
+      (struct exec_param*)(KSTACK_TOP - sizeof(struct exec_param));
+
+    *execp = (struct exec_param){ .cs = KCODE_SEG,
+                                  .eip = (void*)__proc0,
+                                  .ss = KDATA_SEG,
+                                  .eflags = cpu_reflags() };
+    proc0->intr_ctx.execp = execp;
 
     // 加载x87默认配置
     asm volatile("fninit\n"
@@ -210,11 +201,11 @@ setup_memory(multiboot_memory_map_t* map, size_t map_size)
     pmm_mark_chunk_occupied(KERNEL_PID, 0, pg_count, PP_FGLOCKED);
 
     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);
+        vmm_set_mapping(VMS_SELF, i, V2P(i), PG_PREM_UR, VMAP_NULL);
     }
 
     // reserve higher half
     for (size_t i = L1_INDEX(KERNEL_MM_BASE); i < 1023; i++) {
-        assert(vmm_set_mapping(PD_REFERENCED, i << 22, 0, 0, VMAP_NOMAP));
+        assert(vmm_set_mapping(VMS_SELF, i << 22, 0, 0, VMAP_NOMAP));
     }
 }
diff --git a/lunaix-os/kernel/loader/elf.c b/lunaix-os/kernel/loader/elf.c
new file mode 100644 (file)
index 0000000..241ddf9
--- /dev/null
@@ -0,0 +1,148 @@
+#include <lunaix/common.h>
+#include <lunaix/elf.h>
+#include <lunaix/fs.h>
+#include <lunaix/ld.h>
+#include <lunaix/mm/mmap.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/spike.h>
+
+int
+__elf_populate_mapped(struct mm_region* region, void* pg, off_t segfoff)
+{
+    size_t segsz = region->flen;
+    size_t segmoff = segfoff - region->foff;
+
+    if (segmoff >= segsz) {
+        return 0;
+    }
+
+    struct v_file* file = region->mfile;
+    size_t rdlen = MIN(segsz - segmoff, PG_SIZE);
+
+    if (rdlen == PG_SIZE) {
+        // This is because we want to exploit any optimization on read_page
+        return file->ops->read_page(file->inode, pg, PG_SIZE, segfoff);
+    } else {
+        // we don't want to over-read the segment!
+        return file->ops->read(file->inode, pg, rdlen, segfoff);
+    }
+}
+
+int
+elf_map_segment(struct ld_param* ldparam,
+                struct v_file* elfile,
+                struct elf32_phdr* phdr)
+{
+    int proct = 0;
+    if ((phdr->p_flags & PF_R)) {
+        proct |= PROT_READ;
+    }
+    if ((phdr->p_flags & PF_W)) {
+        proct |= PROT_WRITE;
+    }
+    if ((phdr->p_flags & PF_X)) {
+        proct |= PROT_EXEC;
+    }
+
+    struct mm_region* seg_reg;
+    struct mmap_param param = { .vms_mnt = ldparam->vms_mnt,
+                                .pvms = &ldparam->proc->mm,
+                                .proct = proct,
+                                .offset = phdr->p_offset,
+                                .mlen = ROUNDUP(phdr->p_memsz, PG_SIZE),
+                                .flen = phdr->p_filesz,
+                                .flags = MAP_FIXED | MAP_PRIVATE,
+                                .type = REGION_TYPE_CODE };
+
+    int status = mem_map(NULL, &seg_reg, PG_ALIGN(phdr->p_va), elfile, &param);
+
+    if (!status) {
+        seg_reg->init_page = __elf_populate_mapped;
+
+        size_t next_addr = phdr->p_memsz + phdr->p_va;
+        ldparam->info.end = MAX(ldparam->info.end, ROUNDUP(next_addr, PG_SIZE));
+        ldparam->info.mem_sz += phdr->p_memsz;
+    }
+
+    return status;
+}
+
+int
+elf_setup_mapping(struct ld_param* ldparam,
+                  struct v_file* elfile,
+                  struct elf32_ehdr* ehdr)
+{
+    int status = 0;
+    size_t tbl_sz = ehdr->e_phnum * SIZE_PHDR;
+    struct elf32_phdr* phdrs = valloc(tbl_sz);
+
+    if (!phdrs) {
+        status = ENOMEM;
+        goto done;
+    }
+
+    tbl_sz = 1 << ILOG2(tbl_sz);
+    status = elfile->ops->read(elfile->inode, phdrs, tbl_sz, ehdr->e_phoff);
+
+    if (status < 0) {
+        goto done;
+    }
+
+    if (PG_ALIGN(phdrs[0].p_va) != USER_START) {
+        status = ENOEXEC;
+        goto done;
+    }
+
+    size_t entries = tbl_sz / SIZE_PHDR;
+    for (size_t i = 0; i < entries; i++) {
+        struct elf32_phdr* phdr = &phdrs[i];
+
+        if (phdr->p_type == PT_LOAD) {
+            if (phdr->p_align == PG_SIZE) {
+                status = elf_map_segment(ldparam, elfile, phdr);
+            } else {
+                // surprising alignment!
+                status = ENOEXEC;
+            }
+        }
+        // TODO process other types of segments
+
+        if (status) {
+            // errno in the middle of mapping restructuring, it is impossible
+            // to recover!
+            ldparam->status |= LD_STAT_FKUP;
+            goto done;
+        }
+    }
+
+done:
+    vfree(phdrs);
+    return status;
+}
+
+int
+elf_load(struct ld_param* ldparam, struct v_file* elfile)
+{
+    struct elf32_ehdr* ehdr = valloc(SIZE_EHDR);
+    int status = elfile->ops->read(elfile->inode, ehdr, SIZE_EHDR, 0);
+
+    if (status < 0) {
+        goto done;
+    }
+
+    if (!elf_check_exec(ehdr)) {
+        status = ENOEXEC;
+        goto done;
+    }
+
+    if ((status = elf_setup_mapping(ldparam, elfile, ehdr))) {
+        goto done;
+    }
+
+    ldparam->info.ehdr_out = *ehdr;
+
+done:
+    vfree(ehdr);
+    return status;
+}
\ No newline at end of file
diff --git a/lunaix-os/kernel/loader/exec.c b/lunaix-os/kernel/loader/exec.c
new file mode 100644 (file)
index 0000000..331cacc
--- /dev/null
@@ -0,0 +1,197 @@
+#include <lunaix/elf.h>
+#include <lunaix/fs.h>
+#include <lunaix/ld.h>
+#include <lunaix/mm/mmap.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/process.h>
+#include <lunaix/spike.h>
+#include <lunaix/status.h>
+#include <lunaix/syscall.h>
+#include <lunaix/syscall_utils.h>
+
+#include <klibc/string.h>
+
+size_t
+exec_str_size(const char** str_arr, size_t* length)
+{
+    if (!str_arr) {
+        *length = 0;
+        return 0;
+    }
+
+    const char* chr = *str_arr;
+    size_t sz = 0, len = 0;
+
+    while (chr) {
+        sz += strlen(chr);
+        len++;
+
+        chr = *(str_arr + sz);
+    }
+
+    *length = len;
+    return sz + 1;
+}
+
+void
+__heap_copied(struct mm_region* region)
+{
+    mm_index((void**)&region->proc_vms->heap, region);
+}
+
+int
+__exec_remap_heap(struct ld_param* param, struct proc_mm* pvms)
+{
+    if (pvms->heap) {
+        mem_unmap_region(param->vms_mnt, pvms->heap);
+    }
+
+    struct mmap_param map_param = { .pvms = pvms,
+                                    .vms_mnt = param->vms_mnt,
+                                    .flags = MAP_ANON | MAP_PRIVATE,
+                                    .type = REGION_TYPE_HEAP,
+                                    .proct = PROT_READ | PROT_WRITE,
+                                    .mlen = PG_SIZE };
+    int status = 0;
+    struct mm_region* heap;
+    if ((status = mem_map(NULL, &heap, param->info.end, NULL, &map_param))) {
+        param->status |= LD_STAT_FKUP;
+        return status;
+    }
+
+    heap->region_copied = __heap_copied;
+    mm_index((void**)&pvms->heap, heap);
+
+    return status;
+}
+
+int
+exec_load(struct ld_param* param,
+          struct v_file* executable,
+          const char** argv,
+          const char** envp)
+{
+    int errno = 0;
+
+    size_t argv_len, envp_len;
+    size_t sz_argv = exec_str_size(argv, &argv_len);
+    size_t sz_envp = exec_str_size(envp, &envp_len);
+    size_t total_sz = ROUNDUP(sz_argv + sz_envp, PG_SIZE);
+
+    if (total_sz / PG_SIZE > MAX_VAR_PAGES) {
+        errno = E2BIG;
+        goto done;
+    }
+
+    if ((errno = elf_load(param, executable))) {
+        goto done;
+    }
+
+    struct proc_mm* pvms = &param->proc->mm;
+    struct mmap_param map_vars = { .pvms = pvms,
+                                   .vms_mnt = param->vms_mnt,
+                                   .flags = MAP_ANON | MAP_PRIVATE | MAP_FIXED,
+                                   .type = REGION_TYPE_VARS,
+                                   .proct = PROT_READ,
+                                   .mlen = MAX_VAR_PAGES * PG_SIZE };
+
+    void* mapped;
+
+    if ((errno = __exec_remap_heap(param, pvms))) {
+        goto done;
+    }
+
+    if ((errno = mem_map(&mapped, NULL, UMMAP_END, NULL, &map_vars))) {
+        goto done;
+    }
+
+    if (param->vms_mnt == VMS_SELF) {
+        // we are loading executable into current addr space
+
+        // make some handy infos available to user space
+        ptr_t arg_start = mapped + sizeof(struct usr_exec_param);
+        if (argv)
+            memcpy(arg_start, (void*)argv, sz_argv);
+        if (envp)
+            memcpy(arg_start + sz_argv, (void*)envp, sz_envp);
+
+        ptr_t* ustack = (ptr_t*)USTACK_TOP;
+        struct usr_exec_param* exec_param = mapped;
+
+        ustack[-1] = (ptr_t)mapped;
+        param->info.stack_top = &ustack[-1];
+
+        *exec_param = (struct usr_exec_param){ .argc = argv_len,
+                                               .argv = arg_start,
+                                               .envc = envp_len,
+                                               .envp = arg_start + sz_argv,
+                                               .info = param->info };
+    } else {
+        // TODO need to find a way to inject argv and envp remotely
+        fail("not implemented");
+    }
+
+    param->info.entry = param->info.ehdr_out.e_entry;
+done:
+    return errno;
+}
+
+int
+exec_load_byname(struct ld_param* param,
+                 const char* filename,
+                 const char** argv,
+                 const char** envp)
+{
+    int errno = 0;
+    struct v_dnode* dnode;
+    struct v_file* file;
+
+    if ((errno = vfs_walk_proc(filename, &dnode, NULL, 0))) {
+        goto done;
+    }
+
+    if ((errno = vfs_open(dnode, &file))) {
+        goto done;
+    }
+
+    if ((errno = exec_load(param, file, argv, envp))) {
+        vfs_pclose(file, __current->pid);
+    }
+
+done:
+    return errno;
+}
+
+__DEFINE_LXSYSCALL3(int,
+                    execve,
+                    const char*,
+                    filename,
+                    const char*,
+                    argv[],
+                    const char*,
+                    envp[])
+{
+    int errno = 0;
+    struct ld_param ldparam;
+    ld_create_param(&ldparam, __current, VMS_SELF);
+
+    if ((errno = exec_load_byname(&ldparam, filename, argv, envp))) {
+        if ((ldparam.status & LD_STAT_FKUP)) {
+            // we fucked up our address space.
+            terminate_proc(11451);
+            schedule();
+            fail("should not reach");
+        }
+        goto done;
+    }
+
+    volatile struct exec_param* execp = __current->intr_ctx.execp;
+    execp->esp = ldparam.info.stack_top;
+    execp->eip = ldparam.info.entry;
+
+    // we will jump to new entry point (_u_start) upon syscall's
+    // return so execve 'will not return' from the perspective of it's invoker
+
+done:
+    return DO_STATUS(errno);
+}
\ No newline at end of file
diff --git a/lunaix-os/kernel/loader/ld.c b/lunaix-os/kernel/loader/ld.c
new file mode 100644 (file)
index 0000000..413e0f8
--- /dev/null
@@ -0,0 +1,7 @@
+#include <lunaix/ld.h>
+
+void
+ld_create_param(struct ld_param* param, struct proc_info* proc, ptr_t vms)
+{
+    *param = (struct ld_param){ .proc = proc, .vms_mnt = vms };
+}
\ No newline at end of file
diff --git a/lunaix-os/kernel/lxinit.c b/lunaix-os/kernel/lxinit.c
deleted file mode 100644 (file)
index f53405a..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#include <hal/cpu.h>
-#include <lunaix/clock.h>
-#include <lunaix/lunaix.h>
-#include <lunaix/lunistd.h>
-#include <lunaix/lxconsole.h>
-#include <lunaix/mm/kalloc.h>
-#include <lunaix/mm/vmm.h>
-#include <lunaix/spike.h>
-#include <lunaix/syslog.h>
-#include <lunaix/timer.h>
-
-extern uint8_t __kernel_start;
-
-LOG_MODULE("INIT")
-
-// #define FORK_BOMB_DEMO
-#define WAIT_DEMO
-#define IN_USER_MODE
-
-void __USER__
-_lxinit_main()
-{
-#ifdef FORK_BOMB_DEMO
-    // fork炸弹
-    for (;;) {
-        pid_t p;
-        if ((p = fork())) {
-            kprintf(KDEBUG "Pinkie Pie #%d: FUN!\n", p);
-        }
-    }
-#endif
-
-    int status;
-#ifdef WAIT_DEMO
-    // 测试wait
-    kprintf("I am parent, going to fork my child and wait.\n");
-    if (!fork()) {
-        kprintf("I am child, going to sleep for 2 seconds\n");
-        sleep(2);
-        kprintf("I am child, I am about to terminated\n");
-        _exit(1);
-    }
-    wait(&status);
-    pid_t child = wait(&status);
-    kprintf("I am parent, my child (%d) terminated normally with code: %d.\n",
-            child,
-            WEXITSTATUS(status));
-#endif
-
-    pid_t p = 0;
-
-    if (!fork()) {
-        kprintf("Test no hang!\n");
-        sleep(6);
-        _exit(0);
-    }
-
-    waitpid(-1, &status, WNOHANG);
-
-    for (size_t i = 0; i < 5; i++) {
-        pid_t pid = 0;
-        if (!(pid = fork())) {
-            sleep(i);
-            if (i == 3) {
-                i = *(int*)0xdeadc0de; // seg fault!
-            }
-            kprintf(KINFO "%d\n", i);
-            _exit(0);
-        }
-        kprintf(KINFO "Forked %d\n", pid);
-    }
-
-    while ((p = wait(&status)) >= 0) {
-        short code = WEXITSTATUS(status);
-        if (WIFEXITED(status)) {
-            kprintf(KINFO "Process %d exited with code %d\n", p, code);
-        } else {
-            kprintf(KWARN "Process %d aborted with code %d\n", p, code);
-        }
-    }
-
-    char buf[64];
-
-    kprintf(KINFO "Hello processes!\n");
-
-    cpu_get_brand(buf);
-    kprintf("CPU: %s\n\n", buf);
-
-    _exit(0);
-}
\ No newline at end of file
index 81e064892cb480cbdcaf8a602e4922f7485966ad..2350188f747c8e2bbd3f343b4449f314bd63b3e0 100644 (file)
@@ -4,8 +4,8 @@ void*
 vmm_dup_page(pid_t pid, void* pa)
 {
     void* new_ppg = pmm_alloc_page(pid, 0);
-    vmm_set_mapping(PD_REFERENCED, PG_MOUNT_3, new_ppg, PG_PREM_RW, VMAP_NULL);
-    vmm_set_mapping(PD_REFERENCED, PG_MOUNT_4, pa, PG_PREM_RW, VMAP_NULL);
+    vmm_set_mapping(VMS_SELF, PG_MOUNT_3, new_ppg, PG_PREM_RW, VMAP_NULL);
+    vmm_set_mapping(VMS_SELF, PG_MOUNT_4, pa, PG_PREM_RW, VMAP_NULL);
 
     asm volatile("movl %1, %%edi\n"
                  "movl %2, %%esi\n"
@@ -14,8 +14,8 @@ vmm_dup_page(pid_t pid, void* pa)
                  "r"(PG_MOUNT_4)
                  : "memory", "%edi", "%esi");
 
-    vmm_del_mapping(PD_REFERENCED, PG_MOUNT_3);
-    vmm_del_mapping(PD_REFERENCED, PG_MOUNT_4);
+    vmm_del_mapping(VMS_SELF, PG_MOUNT_3);
+    vmm_del_mapping(VMS_SELF, PG_MOUNT_4);
 
     return new_ppg;
 }
\ No newline at end of file
index edc28efadeb77ec6f7c16b2a16a038849f9ef84d..cc75bd9be9b4d5f32b782b28733fbf7be54fbd31 100644 (file)
@@ -1,99 +1,30 @@
-/**
- * @file dmm.c
- * @author Lunaixsky
- * @brief Dynamic memory manager for heap. This design do not incorporate any\
- * specific implementation of malloc family. The main purpose of this routines
- * is to provide handy method to initialize & grow the heap as needed by
- * upstream implementation.
- *
- * This is designed to be portable, so it can serve as syscalls to malloc/free
- * in the c std lib.
- *
- * @version 0.2
- * @date 2022-03-3
- *
- * @copyright Copyright (c) Lunaixsky 2022
- *
- */
-
-#include <lunaix/mm/dmm.h>
-#include <lunaix/mm/page.h>
-#include <lunaix/mm/vmm.h>
+#include <lunaix/mm/mmap.h>
+#include <lunaix/process.h>
 #include <lunaix/status.h>
 
 #include <lunaix/spike.h>
 #include <lunaix/syscall.h>
+#include <lunaix/syscall_utils.h>
 
-__DEFINE_LXSYSCALL1(int, sbrk, size_t, size)
-{
-    heap_context_t* uheap = &__current->mm.u_heap;
-    mutex_lock(&uheap->lock);
-    void* r = lxsbrk(uheap, size, PG_ALLOW_USER);
-    mutex_unlock(&uheap->lock);
-    return r;
-}
-
-__DEFINE_LXSYSCALL1(void*, brk, void*, addr)
-{
-    heap_context_t* uheap = &__current->mm.u_heap;
-    mutex_lock(&uheap->lock);
-    int r = lxbrk(uheap, addr, PG_ALLOW_USER);
-    mutex_unlock(&uheap->lock);
-    return r;
-}
-
-int
-dmm_init(heap_context_t* heap)
+__DEFINE_LXSYSCALL1(void*, sbrk, ssize_t, incr)
 {
-    assert((uintptr_t)heap->start % BOUNDARY == 0);
-
-    heap->brk = heap->start;
-    mutex_init(&heap->lock);
-
-    return vmm_set_mapping(PD_REFERENCED,
-                           heap->brk,
-                           0,
-                           PG_WRITE | PG_ALLOW_USER,
-                           VMAP_NULL) != NULL;
-}
+    struct proc_mm* pvms = &__current->mm;
+    struct mm_region* heap = pvms->heap;
 
-int
-lxbrk(heap_context_t* heap, void* addr, int user)
-{
-    return -(lxsbrk(heap, addr - heap->brk, user) == (void*)-1);
+    assert(heap);
+    int err = mem_adjust_inplace(&pvms->regions, heap, heap->end + incr);
+    if (err) {
+        return (void*)DO_STATUS(err);
+    }
+    return (void*)heap->end;
 }
 
-void*
-lxsbrk(heap_context_t* heap, size_t size, int user)
+__DEFINE_LXSYSCALL1(int, brk, void*, addr)
 {
-    if (size == 0) {
-        return heap->brk;
-    }
-
-    void* current_brk = heap->brk;
-
-    // The upper bound of our next brk of heap given the size.
-    // This will be used to calculate the page we need to allocate.
-    void* next = current_brk + ROUNDUP(size, BOUNDARY);
-
-    // any invalid situations
-    if (next >= heap->max_addr || next < current_brk) {
-        __current->k_status = LXINVLDPTR;
-        return (void*)-1;
-    }
-
-    uintptr_t diff = PG_ALIGN(next) - PG_ALIGN(current_brk);
-    if (diff) {
-        // if next do require new pages to be mapped
-        for (size_t i = 0; i < diff; i += PG_SIZE) {
-            vmm_set_mapping(PD_REFERENCED,
-                            PG_ALIGN(current_brk) + PG_SIZE + i,
-                            0,
-                            PG_WRITE | user,
-                            VMAP_NULL);
-        }
-    }
+    struct proc_mm* pvms = &__current->mm;
+    struct mm_region* heap = pvms->heap;
 
-    heap->brk += size;
-    return current_brk;
+    assert(heap);
+    int err = mem_adjust_inplace(&pvms->regions, heap, (ptr_t)addr);
+    return DO_STATUS(err);
 }
\ No newline at end of file
diff --git a/lunaix-os/kernel/mm/kalloc.c b/lunaix-os/kernel/mm/kalloc.c
deleted file mode 100644 (file)
index 0ce97e9..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-
-/**** DO NOT USE ****/
-
-/**
- * @file kalloc.c
- * @author Lunaixsky
- * @brief Implicit free list implementation of malloc family, for kernel use.
- *
- * This version of code is however the simplest and yet insecured, thread unsafe
- * it just to demonstrate how the malloc/free works behind the curtain
- * @version 0.1
- * @date 2022-03-05
- *
- * @copyright Copyright (c) 2022
- *
- */
-// #include <lunaix/mm/dmm.h>
-// #include <lunaix/mm/kalloc.h>
-// #include <lunaix/mm/vmm.h>
-
-// #include <lunaix/common.h>
-// #include <lunaix/spike.h>
-
-// #include <klibc/string.h>
-
-// #include <stdint.h>
-
-// extern uint8_t __kernel_heap_start;
-
-// void*
-// lx_malloc_internal(heap_context_t* heap, size_t size);
-
-// void
-// place_chunk(uint8_t* ptr, size_t size);
-
-// void
-// lx_free_internal(void* ptr);
-
-// void*
-// coalesce(uint8_t* chunk_ptr);
-
-// void*
-// lx_grow_heap(heap_context_t* heap, size_t sz);
-
-// /*
-//     At the beginning, we allocate an empty page and put our initial marker
-
-//     | 4/1 | 0/1 |
-//     ^     ^ brk
-//     start
-
-//     Then, expand the heap further, with HEAP_INIT_SIZE (evaluated to 4096,
-//     i.e.,
-//    1 pg size) This will allocate as much pages and override old epilogue
-//    marker with a free region hdr and put new epilogue marker. These are
-//    handled by lx_grow_heap which is internally used by alloc to expand the
-//    heap at many moment when needed.
-
-//     | 4/1 | 4096/0 |   .......   | 4096/0 | 0/1 |
-//     ^     ^ brk_old                       ^
-//     start                                 brk
-
-//     Note: the brk always point to the beginning of epilogue.
-// */
-
-// static heap_context_t kheap;
-
-// int
-// kalloc_init()
-// {
-//     kheap.start = KHEAP_START;
-//     kheap.brk = NULL;
-//     kheap.max_addr =
-//       (void*)PROC_START; // 在新的布局中,堆结束的地方即为进程表开始的地方
-
-//     for (size_t i = 0; i < KHEAP_SIZE_MB >> 2; i++) {
-//         vmm_set_mapping(PD_REFERENCED,
-//                         (uintptr_t)kheap.start + (i << 22),
-//                         0,
-//                         PG_PREM_RW,
-//                         VMAP_NOMAP);
-//     }
-
-//     if (!dmm_init(&kheap)) {
-//         return 0;
-//     }
-
-//     SW(kheap.start, PACK(4, M_ALLOCATED));
-//     SW(kheap.start + WSIZE, PACK(0, M_ALLOCATED));
-//     kheap.brk += WSIZE;
-
-//     return lx_grow_heap(&kheap, HEAP_INIT_SIZE) != NULL;
-// }
-
-// void*
-// lxmalloc(size_t size)
-// {
-//     mutex_lock(&kheap.lock);
-//     void* r = lx_malloc_internal(&kheap, size);
-//     mutex_unlock(&kheap.lock);
-
-//     return r;
-// }
-
-// void*
-// lxcalloc(size_t n, size_t elem)
-// {
-//     size_t pd = n * elem;
-
-//     // overflow detection
-//     if (pd < elem || pd < n) {
-//         return NULL;
-//     }
-
-//     void* ptr = lxmalloc(pd);
-//     if (!ptr) {
-//         return NULL;
-//     }
-
-//     return memset(ptr, 0, pd);
-// }
-
-// void
-// lxfree(void* ptr)
-// {
-//     if (!ptr) {
-//         return;
-//     }
-//     mutex_lock(&kheap.lock);
-
-//     uint8_t* chunk_ptr = (uint8_t*)ptr - WSIZE;
-//     u32_t hdr = LW(chunk_ptr);
-//     size_t sz = CHUNK_S(hdr);
-//     uint8_t* next_hdr = chunk_ptr + sz;
-
-//     // make sure the ptr we are 'bout to free makes sense
-//     //   the size trick is stolen from glibc's malloc/malloc.c:4437 ;P
-
-//     assert_msg(((uintptr_t)ptr < (uintptr_t)(-sz)) && !((uintptr_t)ptr &
-//     0x3),
-//                "free(): invalid pointer");
-
-//     assert_msg(sz > WSIZE, "free(): invalid size");
-
-//     SW(chunk_ptr, hdr & ~M_ALLOCATED);
-//     SW(FPTR(chunk_ptr, sz), hdr & ~M_ALLOCATED);
-//     SW(next_hdr, LW(next_hdr) | M_PREV_FREE);
-
-//     coalesce(chunk_ptr);
-
-//     mutex_unlock(&kheap.lock);
-// }
-
-// void*
-// lx_malloc_internal(heap_context_t* heap, size_t size)
-// {
-//     // Simplest first fit approach.
-
-//     if (!size) {
-//         return NULL;
-//     }
-
-//     uint8_t* ptr = heap->start;
-//     // round to largest 4B aligned value
-//     //  and space for header
-//     size = ROUNDUP(size + WSIZE, BOUNDARY);
-//     while (ptr < (uint8_t*)heap->brk) {
-//         u32_t header = *((u32_t*)ptr);
-//         size_t chunk_size = CHUNK_S(header);
-//         if (!chunk_size && CHUNK_A(header)) {
-//             break;
-//         }
-//         if (chunk_size >= size && !CHUNK_A(header)) {
-//             // found!
-//             place_chunk(ptr, size);
-//             return BPTR(ptr);
-//         }
-//         ptr += chunk_size;
-//     }
-
-//     // if heap is full (seems to be!), then allocate more space (if it's
-//     // okay...)
-//     if ((ptr = lx_grow_heap(heap, size))) {
-//         place_chunk(ptr, size);
-//         return BPTR(ptr);
-//     }
-
-//     // Well, we are officially OOM!
-//     return NULL;
-// }
-
-// void
-// place_chunk(uint8_t* ptr, size_t size)
-// {
-//     u32_t header = *((u32_t*)ptr);
-//     size_t chunk_size = CHUNK_S(header);
-//     *((u32_t*)ptr) = PACK(size, CHUNK_PF(header) | M_ALLOCATED);
-//     uint8_t* n_hdrptr = (uint8_t*)(ptr + size);
-//     u32_t diff = chunk_size - size;
-
-//     if (!diff) {
-//         // if the current free block is fully occupied
-//         u32_t n_hdr = LW(n_hdrptr);
-//         // notify the next block about our avaliability
-//         SW(n_hdrptr, n_hdr & ~0x2);
-//     } else {
-//         // if there is remaining free space left
-//         u32_t remainder_hdr = PACK(diff, M_NOT_ALLOCATED |
-//         M_PREV_ALLOCATED); SW(n_hdrptr, remainder_hdr); SW(FPTR(n_hdrptr,
-//         diff), remainder_hdr);
-
-//         /*
-//             | xxxx |      |         |
-
-//                         |
-//                         v
-
-//             | xxxx |                |
-//         */
-//         coalesce(n_hdrptr);
-//     }
-// }
-
-// void*
-// coalesce(uint8_t* chunk_ptr)
-// {
-//     u32_t hdr = LW(chunk_ptr);
-//     u32_t pf = CHUNK_PF(hdr);
-//     u32_t sz = CHUNK_S(hdr);
-
-//     u32_t n_hdr = LW(chunk_ptr + sz);
-
-//     if (CHUNK_A(n_hdr) && pf) {
-//         // case 1: prev is free
-//         u32_t prev_ftr = LW(chunk_ptr - WSIZE);
-//         size_t prev_chunk_sz = CHUNK_S(prev_ftr);
-//         u32_t new_hdr = PACK(prev_chunk_sz + sz, CHUNK_PF(prev_ftr));
-//         SW(chunk_ptr - prev_chunk_sz, new_hdr);
-//         SW(FPTR(chunk_ptr, sz), new_hdr);
-//         chunk_ptr -= prev_chunk_sz;
-//     } else if (!CHUNK_A(n_hdr) && !pf) {
-//         // case 2: next is free
-//         size_t next_chunk_sz = CHUNK_S(n_hdr);
-//         u32_t new_hdr = PACK(next_chunk_sz + sz, pf);
-//         SW(chunk_ptr, new_hdr);
-//         SW(FPTR(chunk_ptr, sz + next_chunk_sz), new_hdr);
-//     } else if (!CHUNK_A(n_hdr) && pf) {
-//         // case 3: both free
-//         u32_t prev_ftr = LW(chunk_ptr - WSIZE);
-//         size_t next_chunk_sz = CHUNK_S(n_hdr);
-//         size_t prev_chunk_sz = CHUNK_S(prev_ftr);
-//         u32_t new_hdr =
-//           PACK(next_chunk_sz + prev_chunk_sz + sz, CHUNK_PF(prev_ftr));
-//         SW(chunk_ptr - prev_chunk_sz, new_hdr);
-//         SW(FPTR(chunk_ptr, sz + next_chunk_sz), new_hdr);
-//         chunk_ptr -= prev_chunk_sz;
-//     }
-
-//     // (fall through) case 4: prev and next are not free
-//     return chunk_ptr;
-// }
-
-// void*
-// lx_grow_heap(heap_context_t* heap, size_t sz)
-// {
-//     void* start;
-
-//     // The "+ WSIZE" capture the overhead for epilogue marker
-//     if (!(start = lxsbrk(heap, sz + WSIZE, 0))) {
-//         return NULL;
-//     }
-//     sz = ROUNDUP(sz, BOUNDARY);
-
-//     // minus the overhead for epilogue, keep the invariant.
-//     heap->brk -= WSIZE;
-
-//     u32_t old_marker = *((u32_t*)start);
-//     u32_t free_hdr = PACK(sz, CHUNK_PF(old_marker));
-//     SW(start, free_hdr);
-//     SW(FPTR(start, sz), free_hdr);
-//     SW(NEXT_CHK(start), PACK(0, M_ALLOCATED | M_PREV_FREE));
-
-//     return coalesce(start);
-// }
\ No newline at end of file
diff --git a/lunaix-os/kernel/mm/mmap.c b/lunaix-os/kernel/mm/mmap.c
new file mode 100644 (file)
index 0000000..f700fd5
--- /dev/null
@@ -0,0 +1,341 @@
+#include <lunaix/mm/mmap.h>
+#include <lunaix/mm/pmm.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/spike.h>
+
+#include <lunaix/syscall.h>
+#include <lunaix/syscall_utils.h>
+
+// any size beyond this is bullshit
+#define BS_SIZE (KERNEL_MM_BASE - UMMAP_START)
+
+int
+mem_has_overlap(vm_regions_t* regions, ptr_t start, ptr_t end)
+{
+    struct mm_region *pos, *n;
+    llist_for_each(pos, n, regions, head)
+    {
+        if (pos->end >= start && pos->start < start) {
+            return 1;
+        }
+
+        if (pos->end <= end && pos->start >= start) {
+            return 1;
+        }
+
+        if (pos->end >= end && pos->start < end) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+int
+mem_adjust_inplace(vm_regions_t* regions,
+                   struct mm_region* region,
+                   ptr_t newend)
+{
+    ssize_t len = newend - region->start;
+    if (len == 0) {
+        return 0;
+    }
+
+    if (len < 0) {
+        return EINVAL;
+    }
+
+    if (mem_has_overlap(regions, region->start, newend)) {
+        return ENOMEM;
+    }
+
+    region->end = newend;
+
+    return 0;
+}
+
+int
+mem_map(void** addr_out,
+        struct mm_region** created,
+        void* addr,
+        struct v_file* file,
+        struct mmap_param* param)
+{
+    assert_msg(addr, "addr can not be NULL");
+
+    ptr_t last_end = USER_START, found_loc = (ptr_t)addr;
+    struct mm_region *pos, *n;
+
+    vm_regions_t* vm_regions = &param->pvms->regions;
+
+    if ((param->flags & MAP_FIXED_NOREPLACE)) {
+        if (mem_has_overlap(vm_regions, found_loc, param->mlen + found_loc)) {
+            return EEXIST;
+        }
+        goto found;
+    }
+
+    if ((param->flags & MAP_FIXED)) {
+        int status =
+          mem_unmap(param->vms_mnt, vm_regions, found_loc, param->mlen);
+        if (status) {
+            return status;
+        }
+        goto found;
+    }
+
+    llist_for_each(pos, n, vm_regions, head)
+    {
+        if (last_end < found_loc) {
+            size_t avail_space = pos->start - found_loc;
+            if (pos->start > found_loc && avail_space > param->mlen) {
+                goto found;
+            }
+            found_loc = pos->end + PG_SIZE;
+        }
+
+        last_end = pos->end;
+    }
+
+    return ENOMEM;
+
+found:
+    if (found_loc >= KERNEL_MM_BASE || found_loc < USER_START) {
+        return ENOMEM;
+    }
+
+    struct mm_region* region = region_create_range(
+      found_loc,
+      param->mlen,
+      ((param->proct | param->flags) & 0x3f) | (param->type & ~0xffff));
+
+    region->mfile = file;
+    region->foff = param->offset;
+    region->flen = param->flen;
+    region->proc_vms = param->pvms;
+
+    region_add(vm_regions, region);
+
+    u32_t attr = PG_ALLOW_USER;
+    if ((param->proct & REGION_WRITE)) {
+        attr |= PG_WRITE;
+    }
+
+    for (u32_t i = 0; i < param->mlen; i += PG_SIZE) {
+        vmm_set_mapping(param->vms_mnt, found_loc + i, 0, attr, 0);
+    }
+
+    if (file) {
+        vfs_ref_file(file);
+    }
+
+    if (addr_out) {
+        *addr_out = found_loc;
+    }
+    if (created) {
+        *created = region;
+    }
+    return 0;
+}
+
+void
+mem_sync_pages(ptr_t mnt,
+               struct mm_region* region,
+               ptr_t start,
+               ptr_t length,
+               int options)
+{
+    if (!region->mfile || !(region->attr & REGION_WSHARED)) {
+        return;
+    }
+
+    v_mapping mapping;
+    for (size_t i = 0; i < length; i += PG_SIZE) {
+        if (!vmm_lookupat(mnt, start + i, &mapping)) {
+            continue;
+        }
+
+        if (PG_IS_DIRTY(*mapping.pte)) {
+            size_t offset = mapping.va - region->start + region->foff;
+            struct v_inode* inode = region->mfile->inode;
+            region->mfile->ops->write_page(inode, mapping.va, PG_SIZE, offset);
+            *mapping.pte &= ~PG_DIRTY;
+            cpu_invplg(mapping.pte);
+        } else if ((options & MS_INVALIDATE)) {
+            goto invalidate;
+        }
+
+        if (options & MS_INVALIDATE_ALL) {
+            goto invalidate;
+        }
+
+        continue;
+
+    invalidate:
+        *mapping.pte &= ~PG_PRESENT;
+        pmm_free_page(KERNEL_PID, mapping.pa);
+        cpu_invplg(mapping.pte);
+    }
+}
+
+int
+mem_msync(ptr_t mnt,
+          vm_regions_t* regions,
+          ptr_t addr,
+          size_t length,
+          int options)
+{
+    struct mm_region* pos = list_entry(regions->next, struct mm_region, head);
+    while (length && (ptr_t)&pos->head != (ptr_t)regions) {
+        if (pos->end >= addr && pos->start <= addr) {
+            size_t l = MIN(length, pos->end - addr);
+            mem_sync_pages(mnt, pos, addr, l, options);
+
+            addr += l;
+            length -= l;
+        }
+        pos = list_entry(pos->head.next, struct mm_region, head);
+    }
+
+    if (length) {
+        return ENOMEM;
+    }
+
+    return 0;
+}
+
+void
+mem_unmap_region(ptr_t mnt, struct mm_region* region)
+{
+    size_t len = ROUNDUP(region->end - region->start, PG_SIZE);
+    mem_sync_pages(mnt, region, region->start, len, 0);
+
+    for (size_t i = region->start; i <= region->end; i += PG_SIZE) {
+        ptr_t pa = vmm_del_mapping(mnt, i);
+        if (pa) {
+            pmm_free_page(__current->pid, pa);
+        }
+    }
+    llist_delete(&region->head);
+    region_release(region);
+}
+
+int
+mem_unmap(ptr_t mnt, vm_regions_t* regions, void* addr, size_t length)
+{
+    length = ROUNDUP(length, PG_SIZE);
+    ptr_t cur_addr = PG_ALIGN(addr);
+    struct mm_region *pos, *n;
+
+    llist_for_each(pos, n, regions, head)
+    {
+        if (pos->start <= cur_addr && pos->end >= cur_addr) {
+            break;
+        }
+    }
+
+    while (&pos->head != regions && cur_addr >= pos->start) {
+        u32_t l = pos->end - cur_addr;
+        pos->end = cur_addr;
+
+        if (l > length) {
+            // unmap cause discontinunity in a memory region -  do split
+            struct mm_region* region = valloc(sizeof(struct mm_region));
+            *region = *pos;
+            region->start = cur_addr + length;
+            llist_insert_after(&pos->head, &region->head);
+            l = length;
+        }
+
+        mem_sync_pages(mnt, pos, cur_addr, l, 0);
+
+        for (size_t i = 0; i < l; i += PG_SIZE) {
+            ptr_t pa = vmm_del_mapping(mnt, cur_addr + i);
+            if (pa) {
+                pmm_free_page(pos->proc_vms->pid, pa);
+            }
+        }
+
+        n = container_of(pos->head.next, typeof(*pos), head);
+        if (pos->end == pos->start) {
+            llist_delete(&pos->head);
+            region_release(pos);
+        }
+
+        pos = n;
+        length -= l;
+        cur_addr += length;
+    }
+
+    return 0;
+}
+
+__DEFINE_LXSYSCALL3(void*, sys_mmap, void*, addr, size_t, length, va_list, lst)
+{
+    int proct = va_arg(lst, int);
+    int fd = va_arg(lst, u32_t);
+    off_t offset = va_arg(lst, off_t);
+    int options = va_arg(lst, int);
+    int errno = 0;
+    void* result = (void*)-1;
+
+    if (!length || length > BS_SIZE || !PG_ALIGNED(addr)) {
+        errno = EINVAL;
+        goto done;
+    }
+
+    if (!addr) {
+        addr = UMMAP_START;
+    } else if (addr < UMMAP_START || addr + length >= UMMAP_END) {
+        errno = ENOMEM;
+        goto done;
+    }
+
+    struct v_fd* vfd;
+    if ((errno = vfs_getfd(fd, &vfd))) {
+        goto done;
+    }
+
+    struct v_file* file = vfd->file;
+
+    if (!(options & MAP_ANON)) {
+        if (!file->ops->read_page) {
+            errno = ENODEV;
+            goto done;
+        }
+    } else {
+        file = NULL;
+    }
+
+    struct mmap_param param = { .flags = options,
+                                .mlen = ROUNDUP(length, PG_SIZE),
+                                .offset = offset,
+                                .type = REGION_TYPE_GENERAL,
+                                .proct = proct,
+                                .pvms = &__current->mm,
+                                .vms_mnt = VMS_SELF };
+
+    errno = mem_map(&result, NULL, addr, file, &param);
+
+done:
+    __current->k_status = errno;
+    return result;
+}
+
+__DEFINE_LXSYSCALL2(void, munmap, void*, addr, size_t, length)
+{
+    return mem_unmap(VMS_SELF, &__current->mm.regions, addr, length);
+}
+
+__DEFINE_LXSYSCALL3(int, msync, void*, addr, size_t, length, int, flags)
+{
+    if (!PG_ALIGNED(addr) || ((flags & MS_ASYNC) && (flags & MS_SYNC))) {
+        return DO_STATUS(EINVAL);
+    }
+
+    int status =
+      mem_msync(VMS_SELF, &__current->mm.regions, addr, length, flags);
+
+    return DO_STATUS(status);
+}
\ No newline at end of file
index 99e8fb8e36298d3b45c394e2eb3a5246377a7c4b..e9843d64d9ade7273b7b8e845446515752283d7d 100644 (file)
@@ -20,7 +20,7 @@ void*
 iounmap(uintptr_t vaddr, u32_t size)
 {
     for (size_t i = 0; i < size; i += PG_SIZE) {
-        uintptr_t paddr = vmm_del_mapping(PD_REFERENCED, vaddr + i);
+        uintptr_t paddr = vmm_del_mapping(VMS_SELF, vaddr + i);
         pmm_free_page(KERNEL_PID, paddr);
     }
 }
\ No newline at end of file
index bd3b26ec0d5fc1009b0e9cf424869934816d2c03..6340cfbb9d1768632abda81f34352f62898b4d26 100644 (file)
+#include <lunaix/mm/page.h>
 #include <lunaix/mm/region.h>
 #include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
 
-void
-region_add(struct mm_region* regions,
-           unsigned long start,
-           unsigned long end,
-           unsigned int attr)
+#include <klibc/string.h>
+
+struct mm_region*
+region_create(ptr_t start, ptr_t end, u32_t attr)
 {
+    assert_msg(PG_ALIGNED(start), "not page aligned");
+    assert_msg(PG_ALIGNED(end), "not page aligned");
     struct mm_region* region = valloc(sizeof(struct mm_region));
+    *region =
+      (struct mm_region){ .attr = attr, .start = start, .end = end - 1 };
+    return region;
+}
+
+struct mm_region*
+region_create_range(ptr_t start, size_t length, u32_t attr)
+{
+    assert_msg(PG_ALIGNED(start), "not page aligned");
+    assert_msg(PG_ALIGNED(length), "not page aligned");
+    struct mm_region* region = valloc(sizeof(struct mm_region));
+    *region = (struct mm_region){ .attr = attr,
+                                  .start = start,
+                                  .end = PG_ALIGN(start + length - 1) };
+    return region;
+}
 
-    *region = (struct mm_region){ .attr = attr, .end = end, .start = start };
+void
+region_add(vm_regions_t* lead, struct mm_region* vmregion)
+{
+    if (llist_empty(lead)) {
+        llist_append(lead, &vmregion->head);
+        return;
+    }
 
-    llist_append(&regions->head, &region->head);
+    ptr_t cur_end = 0;
+    struct mm_region *pos = (struct mm_region*)lead,
+                     *n = list_entry(lead->next, struct mm_region, head);
+    do {
+        if (vmregion->start > cur_end && vmregion->end < n->start) {
+            break;
+        }
+        cur_end = n->end;
+        pos = n;
+        n = list_entry(n->head.next, struct mm_region, head);
+    } while ((ptr_t)&n->head != (ptr_t)lead);
+
+    // XXX caution. require mm_region::head to be the lead of struct
+    llist_insert_after(&pos->head, &vmregion->head);
 }
 
 void
-region_release_all(struct mm_region* regions)
+region_release(struct mm_region* region)
 {
-    struct mm_region *pos, *n;
+    if (region->destruct_region) {
+        region->destruct_region(region);
+    }
 
-    llist_for_each(pos, n, &regions->head, head)
-    {
-        vfree(pos);
+    if (region->mfile) {
+        vfs_pclose(region->mfile, region->proc_vms->pid);
     }
+
+    if (region->index) {
+        *region->index = NULL;
+    }
+
+    vfree(region);
 }
 
 void
-region_copy(struct mm_region* src, struct mm_region* dest)
+region_release_all(vm_regions_t* lead)
 {
-    if (!src) {
-        return;
+    struct mm_region *pos, *n;
+
+    llist_for_each(pos, n, lead, head)
+    {
+        region_release(pos);
     }
+}
 
-    struct mm_region *pos, *n;
+void
+region_copy(struct proc_mm* src, struct proc_mm* dest)
+{
+    struct mm_region *pos, *n, *dup;
 
-    llist_for_each(pos, n, &src->head, head)
+    llist_for_each(pos, n, &src->regions, head)
     {
-        region_add(dest, pos->start, pos->end, pos->attr);
+        dup = valloc(sizeof(struct mm_region));
+        memcpy(dup, pos, sizeof(*pos));
+
+        dup->proc_vms = dest;
+
+        if (dup->mfile) {
+            vfs_ref_file(dup->mfile);
+        }
+
+        if (dup->region_copied) {
+            dup->region_copied(dup);
+        }
+
+        region_add(&dest->regions, dup);
     }
 }
 
 struct mm_region*
-region_get(struct mm_region* regions, unsigned long vaddr)
+region_get(vm_regions_t* lead, unsigned long vaddr)
 {
-    if (!regions) {
+    if (llist_empty(lead)) {
         return NULL;
     }
 
     struct mm_region *pos, *n;
 
-    llist_for_each(pos, n, &regions->head, head)
+    vaddr = PG_ALIGN(vaddr);
+
+    llist_for_each(pos, n, lead, head)
     {
-        if (pos->start <= vaddr && vaddr < pos->end) {
+        if (pos->start <= vaddr && vaddr <= pos->end) {
             return pos;
         }
     }
index 7507b1a86113a5364d6e6020d6e5a4724ca239a7..285debce407359fbd5ef14654fab724e5a4d96fe 100644 (file)
@@ -3,7 +3,7 @@
 #include <lunaix/spike.h>
 
 #define VMAP_START PG_MOUNT_BASE + MEM_4MB
-#define VMAP_END PD_REFERENCED
+#define VMAP_END VMS_SELF
 
 static uintptr_t start = VMAP_START;
 
@@ -56,8 +56,7 @@ vmm_vmap(uintptr_t paddr, size_t size, pt_attr attr)
 done:
     uintptr_t alloc_begin = current_addr - examed_size;
     for (size_t i = 0; i < size; i += PG_SIZE) {
-        vmm_set_mapping(
-          PD_REFERENCED, alloc_begin + i, paddr + i, PG_PREM_RW, 0);
+        vmm_set_mapping(VMS_SELF, alloc_begin + i, paddr + i, PG_PREM_RW, 0);
         pmm_ref_page(KERNEL_PID, paddr + i);
     }
     start = alloc_begin + size;
index 445071c39483a7a94a211be9600a345f1ebdc281..8f67bd2d8237ad53d80a5ddd48f98f4b38e762b1 100644 (file)
@@ -68,7 +68,7 @@ vmm_set_mapping(uintptr_t mnt,
         }
     }
 
-    if (mnt == PD_REFERENCED) {
+    if (mnt == VMS_SELF) {
         cpu_invplg(va);
     }
 
@@ -112,16 +112,22 @@ vmm_del_mapping(uintptr_t mnt, uintptr_t va)
 
 int
 vmm_lookup(uintptr_t va, v_mapping* mapping)
+{
+    return vmm_lookupat(VMS_SELF, va, mapping);
+}
+
+int
+vmm_lookupat(ptr_t mnt, uintptr_t va, v_mapping* mapping)
 {
     u32_t l1_index = L1_INDEX(va);
     u32_t l2_index = L2_INDEX(va);
 
-    x86_page_table* l1pt = (x86_page_table*)L1_BASE_VADDR;
+    x86_page_table* l1pt = (x86_page_table*)(mnt | 1023 << 12);
     x86_pte_t l1pte = l1pt->entry[l1_index];
 
     if (l1pte) {
         x86_pte_t* l2pte =
-          &((x86_page_table*)L2_VADDR(l1_index))->entry[l2_index];
+          &((x86_page_table*)(mnt | (l1_index << 12)))->entry[l2_index];
         if (l2pte) {
             mapping->flags = PG_ENTRY_FLAGS(*l2pte);
             mapping->pa = PG_ENTRY_ADDR(*l2pte);
@@ -153,6 +159,25 @@ vmm_v2p(void* va)
     return 0;
 }
 
+void*
+vmm_v2pat(ptr_t mnt, void* va)
+{
+    u32_t l1_index = L1_INDEX(va);
+    u32_t l2_index = L2_INDEX(va);
+
+    x86_page_table* l1pt = (x86_page_table*)(mnt | 1023 << 12);
+    x86_pte_t l1pte = l1pt->entry[l1_index];
+
+    if (l1pte) {
+        x86_pte_t* l2pte =
+          &((x86_page_table*)(mnt | (l1_index << 12)))->entry[l2_index];
+        if (l2pte) {
+            return PG_ENTRY_ADDR(*l2pte) | ((uintptr_t)va & 0xfff);
+        }
+    }
+    return 0;
+}
+
 void*
 vmm_mount_pd(uintptr_t mnt, void* pde)
 {
index 19f04dce4d077b59bcd7c47099071ee5dc69d7b7..abd0ac0df4f3d925a6f7f171b2f8d9e67f4a37f7 100644 (file)
@@ -1,11 +1,9 @@
 #include <lunaix/block.h>
 #include <lunaix/common.h>
-#include <lunaix/fctrl.h>
 #include <lunaix/foptions.h>
 #include <lunaix/fs.h>
 #include <lunaix/fs/twifs.h>
-#include <lunaix/lunaix.h>
-#include <lunaix/lunistd.h>
+#include <lunaix/ld.h>
 #include <lunaix/lxconsole.h>
 #include <lunaix/mm/cake.h>
 #include <lunaix/mm/pmm.h>
 
 #include <klibc/string.h>
 
-#include <ulibc/stdio.h>
-
 LOG_MODULE("PROC0")
 
-extern void
-_lxinit_main(); /* lxinit.c */
-
 void
 init_platform();
 
@@ -50,84 +43,59 @@ unlock_reserved_memory();
 void
 __do_reserved_memory(int unlock);
 
-#define USE_DEMO
-// #define DEMO_SIGNAL
-// #define DEMO_READDIR
-// #define DEMO_IOTEST
-// #define DEMO_INPUT_TEST
-#define DEMO_SIMPLE_SH
-
-extern void
-_pconsole_main();
-
-extern void
-_signal_demo_main();
-
-extern void
-_lxinit_main();
-
-extern void
-_readdir_main();
-
-extern void
-_iotest_main();
-
-extern void
-input_test();
-
-extern void
-sh_main();
-
-void __USER__
-__setup_dir()
+int
+mount_bootmedium()
 {
-    int errno;
-    mkdir("/mnt");
-    mkdir("/mnt/lunaix-os");
+    struct v_dnode* dnode;
+    int errno = 0;
+    if ((errno = vfs_walk_proc("/dev/sdb", &dnode, NULL, 0))) {
+        kprintf(KERROR "fail to acquire device. (%d)", errno);
+        return 0;
+    }
 
-    if ((errno = mount("/dev/sdb", "/mnt/lunaix-os", "iso9660", 0))) {
-        syslog(2, "fail mounting boot medium. (%d)\n", errno);
+    struct device* dev = (struct device*)dnode->inode->data;
+    if ((errno = vfs_mount("/mnt/lunaix-os", "iso9660", dev, 0))) {
+        kprintf(KERROR "fail to boot medium. (%d)", errno);
+        return 0;
     }
+
+    return 1;
 }
 
-void __USER__
-__proc0_usr()
+int
+exec_initd()
 {
-    // 打开tty设备(控制台),作为标准输入输出。
-    //  tty设备属于序列设备(Sequential Device),该类型设备的上层读写
-    //  无须经过Lunaix的缓存层,而是直接下发到底层驱动。(不受FO_DIRECT的影响)
-    int fdstdout = open("/dev/tty", 0);
-    int fdstdin = dup2(stdout, 1);
-
-    __setup_dir();
-
-    pid_t p;
-
-    if (!(p = fork())) {
-#ifndef USE_DEMO
-        _exit(0);
-#elif defined DEMO_SIGNAL
-        _signal_demo_main();
-#elif defined DEMO_READDIR
-        _readdir_main();
-#elif defined DEMO_IOTEST
-        _iotest_main();
-#elif defined DEMO_INPUT_TEST
-        input_test();
-#elif defined DEMO_SIMPLE_SH
-        sh_main();
-#else
-        _lxinit_main();
-#endif
-        printf("==== test end ====\n");
-        _exit(0);
-    }
+    int errno = 0;
+    struct ld_param param;
+    char filename[] = "/mnt/lunaix-os/usr/init";
 
-    waitpid(p, 0, 0);
+    ld_create_param(&param, __current, VMS_SELF);
 
-    while (1) {
-        yield();
+    if ((errno = exec_load_byname(&param, filename, NULL, NULL))) {
+        goto fail;
     }
+
+    // user space
+    asm volatile("movw %0, %%ax\n"
+                 "movw %%ax, %%es\n"
+                 "movw %%ax, %%ds\n"
+                 "movw %%ax, %%fs\n"
+                 "movw %%ax, %%gs\n"
+                 "pushl %0\n"
+                 "pushl %1\n"
+                 "pushl %2\n"
+                 "pushl %3\n"
+                 "retf" ::"i"(UDATA_SEG),
+                 "r"(param.info.stack_top),
+                 "i"(UCODE_SEG),
+                 "r"(param.info.entry)
+                 : "eax", "memory");
+
+    fail("should not reach");
+
+fail:
+    kprintf(KERROR "fail to load initd. (%d)", errno);
+    return 0;
 }
 
 /**
@@ -145,21 +113,12 @@ __proc0()
 
     init_proc_user_space(__current);
 
-    // user space
-    asm volatile("movw %0, %%ax\n"
-                 "movw %%ax, %%es\n"
-                 "movw %%ax, %%ds\n"
-                 "movw %%ax, %%fs\n"
-                 "movw %%ax, %%gs\n"
-                 "pushl %0\n"
-                 "pushl %1\n"
-                 "pushl %2\n"
-                 "pushl %3\n"
-                 "retf" ::"i"(UDATA_SEG),
-                 "i"(USTACK_TOP & ~0xf),
-                 "i"(UCODE_SEG),
-                 "r"(__proc0_usr)
-                 : "eax", "memory");
+    if (!mount_bootmedium() || !exec_initd()) {
+        while (1) {
+            asm("hlt");
+        }
+        // should not reach
+    }
 }
 
 extern uint8_t __kernel_start;            /* link/linker.ld */
@@ -211,7 +170,7 @@ init_platform()
 
     // clean up
     for (size_t i = 0; i < (uintptr_t)(&__init_hhk_end); i += PG_SIZE) {
-        vmm_del_mapping(PD_REFERENCED, (void*)i);
+        vmm_del_mapping(VMS_SELF, (void*)i);
         pmm_free_page(KERNEL_PID, (void*)i);
     }
 }
@@ -255,7 +214,7 @@ __do_reserved_memory(int unlock)
                     // Don't fuck up our kernel space!
                     break;
                 }
-                vmm_set_mapping(PD_REFERENCED, _pa, _pa, PG_PREM_R, VMAP_NULL);
+                vmm_set_mapping(VMS_SELF, _pa, _pa, PG_PREM_R, VMAP_NULL);
                 pmm_mark_page_occupied(
                   KERNEL_PID, _pa >> PG_SIZE_BITS, PP_FGLOCKED);
             }
@@ -268,7 +227,7 @@ __do_reserved_memory(int unlock)
                     mmap.type);
             for (; j < pg_num; j++) {
                 uintptr_t _pa = pa + (j << PG_SIZE_BITS);
-                vmm_del_mapping(PD_REFERENCED, _pa);
+                vmm_del_mapping(VMS_SELF, _pa);
                 if (mmap.type == MULTIBOOT_MEMORY_ACPI_RECLAIMABLE) {
                     pmm_mark_page_free(_pa >> PG_SIZE_BITS);
                 }
index 74c93807f57115ac85f582d60c5acdd58996d313..23ff6a4dcc3e9a24ae115ebb532f4bed10de17bf 100644 (file)
@@ -1,6 +1,7 @@
 #include <klibc/string.h>
 #include <lunaix/clock.h>
 #include <lunaix/common.h>
+#include <lunaix/mm/mmap.h>
 #include <lunaix/mm/pmm.h>
 #include <lunaix/mm/region.h>
 #include <lunaix/mm/valloc.h>
@@ -17,7 +18,7 @@ void*
 __dup_pagetable(pid_t pid, uintptr_t mount_point)
 {
     void* ptd_pp = pmm_alloc_page(pid, PP_FGPERSIST);
-    vmm_set_mapping(PD_REFERENCED, PG_MOUNT_1, ptd_pp, PG_PREM_RW, VMAP_NULL);
+    vmm_set_mapping(VMS_SELF, PG_MOUNT_1, ptd_pp, PG_PREM_RW, VMAP_NULL);
 
     x86_page_table* ptd = PG_MOUNT_1;
     x86_page_table* pptd = (x86_page_table*)(mount_point | (0x3FF << 12));
@@ -36,8 +37,7 @@ __dup_pagetable(pid_t pid, uintptr_t mount_point)
 
         // 复制L2页表
         void* pt_pp = pmm_alloc_page(pid, PP_FGPERSIST);
-        vmm_set_mapping(
-          PD_REFERENCED, PG_MOUNT_2, pt_pp, PG_PREM_RW, VMAP_NULL);
+        vmm_set_mapping(VMS_SELF, PG_MOUNT_2, pt_pp, PG_PREM_RW, VMAP_NULL);
 
         x86_page_table* ppt = (x86_page_table*)(mount_point | (i << 12));
         x86_page_table* pt = PG_MOUNT_2;
@@ -87,7 +87,7 @@ __del_pagetable(pid_t pid, uintptr_t mount_point)
 void*
 vmm_dup_vmspace(pid_t pid)
 {
-    return __dup_pagetable(pid, PD_REFERENCED);
+    return __dup_pagetable(pid, VMS_SELF);
 }
 
 __DEFINE_LXSYSCALL(pid_t, fork)
@@ -135,33 +135,46 @@ __DEFINE_LXSYSCALL2(int, setpgid, pid_t, pid, pid_t, pgid)
     return 0;
 }
 
+void
+__stack_copied(struct mm_region* region)
+{
+    mm_index((void**)&region->proc_vms->stack, region);
+}
+
 void
 init_proc_user_space(struct proc_info* pcb)
 {
-    vmm_mount_pd(PD_MOUNT_1, pcb->page_table);
+    vmm_mount_pd(VMS_MOUNT_1, pcb->page_table);
 
     /*---  分配用户栈  ---*/
 
-    // 注册用户栈区域
-    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);
+    struct mm_region* mapped;
+    struct mmap_param param = { .vms_mnt = VMS_MOUNT_1,
+                                .pvms = &pcb->mm,
+                                .mlen = USTACK_SIZE,
+                                .proct = PROT_READ | PROT_WRITE,
+                                .flags = MAP_ANON | MAP_PRIVATE | MAP_FIXED,
+                                .type = REGION_TYPE_STACK };
+
+    int status = 0;
+    if ((status = mem_map(NULL, &mapped, USTACK_END, NULL, &param))) {
+        kprint_panic("fail to alloc user stack: %d", status);
     }
 
+    mapped->region_copied = __stack_copied;
+    mm_index((void**)&pcb->mm.stack, mapped);
+
     // TODO other uspace initialization stuff
 
-    vmm_unmount_pd(PD_MOUNT_1);
+    vmm_unmount_pd(VMS_MOUNT_1);
 }
 
 void
 __mark_region(uintptr_t start_vpn, uintptr_t end_vpn, int attr)
 {
     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);
+        x86_pte_t* curproc = &PTE_MOUNTED(VMS_SELF, i);
+        x86_pte_t* newproc = &PTE_MOUNTED(VMS_MOUNT_1, i);
         cpu_invplg(newproc);
 
         if ((attr & REGION_MODE_MASK) == REGION_RSHARED) {
@@ -192,7 +205,6 @@ pid_t
 dup_proc()
 {
     struct proc_info* pcb = alloc_process();
-    pcb->mm.u_heap = __current->mm.u_heap;
     pcb->intr_ctx = __current->intr_ctx;
     pcb->parent = __current;
 
@@ -204,14 +216,14 @@ dup_proc()
     }
 
     __copy_fdtable(pcb);
-    region_copy(&__current->mm.regions, &pcb->mm.regions);
+    region_copy(&__current->mm, &pcb->mm);
 
-    setup_proc_mem(pcb, PD_REFERENCED);
+    setup_proc_mem(pcb, VMS_SELF);
 
     // 根据 mm_region 进一步配置页表
 
     struct mm_region *pos, *n;
-    llist_for_each(pos, n, &pcb->mm.regions.head, head)
+    llist_for_each(pos, n, &pcb->mm.regions, head)
     {
         // 如果写共享,则不作处理。
         if ((pos->attr & REGION_WSHARED)) {
@@ -223,7 +235,7 @@ dup_proc()
         __mark_region(start_vpn, end_vpn, pos->attr);
     }
 
-    vmm_unmount_pd(PD_MOUNT_1);
+    vmm_unmount_pd(VMS_MOUNT_1);
 
     // 正如同fork,返回两次。
     pcb->intr_ctx.registers.eax = 0;
@@ -242,11 +254,11 @@ setup_proc_mem(struct proc_info* proc, uintptr_t usedMnt)
     pid_t pid = proc->pid;
     void* pt_copy = __dup_pagetable(pid, usedMnt);
 
-    vmm_mount_pd(PD_MOUNT_1, pt_copy); // 将新进程的页表挂载到挂载点#2
+    vmm_mount_pd(VMS_MOUNT_1, pt_copy); // 将新进程的页表挂载到挂载点#2
 
     // copy the kernel stack
     for (size_t i = KSTACK_START >> 12; i <= KSTACK_TOP >> 12; i++) {
-        volatile x86_pte_t* ppte = &PTE_MOUNTED(PD_MOUNT_1, i);
+        volatile x86_pte_t* ppte = &PTE_MOUNTED(VMS_MOUNT_1, i);
 
         /*
             This is a fucking nightmare, the TLB caching keep the rewrite to PTE
index 5e882b7df8f4c32fa3ff7757f84be78d215efae4..edde8bc79f54f9c677207fce9813f5e79a88a6fa 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <lunaix/fs/taskfs.h>
 #include <lunaix/mm/cake.h>
-#include <lunaix/mm/kalloc.h>
+#include <lunaix/mm/mmap.h>
 #include <lunaix/mm/pmm.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/mm/vmm.h>
@@ -18,6 +18,8 @@
 #include <lunaix/syscall.h>
 #include <lunaix/syslog.h>
 
+#include <klibc/string.h>
+
 volatile struct proc_info* __current;
 
 static struct proc_info dummy_proc;
@@ -58,23 +60,23 @@ sched_init_dummy()
     extern void my_dummy();
     static char dummy_stack[DUMMY_STACK_SIZE] __attribute__((aligned(16)));
 
-    // memset to 0
-    dummy_proc = (struct proc_info){};
-    dummy_proc.intr_ctx = (isr_param){
-        .registers = { .ds = KDATA_SEG,
-                       .es = KDATA_SEG,
-                       .fs = KDATA_SEG,
-                       .gs = KDATA_SEG,
-                       .esp = (void*)dummy_stack + DUMMY_STACK_SIZE - 20 },
+    struct exec_param* execp =
+      (void*)dummy_stack + DUMMY_STACK_SIZE - sizeof(struct exec_param);
+
+    *execp = (struct exec_param){
         .cs = KCODE_SEG,
+        .eflags = cpu_reflags() | 0x0200,
         .eip = (void*)my_dummy,
         .ss = KDATA_SEG,
-        .eflags = cpu_reflags() | 0x0200
     };
 
-    *(u32_t*)(&dummy_stack[DUMMY_STACK_SIZE - 4]) = dummy_proc.intr_ctx.eflags;
-    *(u32_t*)(&dummy_stack[DUMMY_STACK_SIZE - 8]) = KCODE_SEG;
-    *(u32_t*)(&dummy_stack[DUMMY_STACK_SIZE - 12]) = dummy_proc.intr_ctx.eip;
+    // memset to 0
+    dummy_proc = (struct proc_info){};
+    dummy_proc.intr_ctx = (isr_param){ .registers = { .ds = KDATA_SEG,
+                                                      .es = KDATA_SEG,
+                                                      .fs = KDATA_SEG,
+                                                      .gs = KDATA_SEG },
+                                       .execp = execp };
 
     dummy_proc.page_table = cpu_rcr3();
     dummy_proc.state = PS_READY;
@@ -97,7 +99,7 @@ run(struct proc_info* proc)
         由于这中间没有进行地址空间的交换,所以第二次跳转使用的是同一个内核栈,而之前默认tss.esp0的值是永远指向最顶部
         这样一来就有可能会覆盖更早的上下文信息(比如嵌套的信号捕获函数)
     */
-    tss_update_esp(proc->intr_ctx.registers.esp);
+    tss_update_esp(proc->intr_ctx.esp);
 
     apic_done_servicing();
 
@@ -327,13 +329,14 @@ alloc_process()
 
     proc->state = PS_CREATED;
     proc->pid = i;
+    proc->mm.pid = i;
     proc->created = clock_systime();
     proc->pgid = proc->pid;
     proc->fdtable = vzalloc(sizeof(struct v_fdtable));
     proc->fxstate =
       vzalloc_dma(512); // FXSAVE需要十六位对齐地址,使用DMA块(128位对齐)
 
-    llist_init_head(&proc->mm.regions.head);
+    llist_init_head(&proc->mm.regions);
     llist_init_head(&proc->tasks);
     llist_init_head(&proc->children);
     llist_init_head(&proc->grp_member);
@@ -403,17 +406,18 @@ destroy_process(pid_t pid)
     vfree(proc->fdtable);
     vfree_dma(proc->fxstate);
 
+    vmm_mount_pd(VMS_MOUNT_1, proc->page_table);
+
     struct mm_region *pos, *n;
-    llist_for_each(pos, n, &proc->mm.regions.head, head)
+    llist_for_each(pos, n, &proc->mm.regions, head)
     {
-        vfree(pos);
+        mem_sync_pages(VMS_MOUNT_1, pos, pos->start, pos->end - pos->start, 0);
+        region_release(pos);
     }
 
-    vmm_mount_pd(PD_MOUNT_1, proc->page_table);
-
-    __del_pagetable(pid, PD_MOUNT_1);
+    __del_pagetable(pid, VMS_MOUNT_1);
 
-    vmm_unmount_pd(PD_MOUNT_1);
+    vmm_unmount_pd(VMS_MOUNT_1);
 
     cake_release(proc_pile, proc);
 
index 9a9a34999dc86b19bf461b713c897b13357424c2..0f43b1f65216adc7d1dfadae52f365318b40248e 100644 (file)
@@ -1,6 +1,3 @@
-#include <klibc/string.h>
-#include <lunaix/lunistd.h>
-#include <lunaix/lxsignal.h>
 #include <lunaix/process.h>
 #include <lunaix/sched.h>
 #include <lunaix/signal.h>
@@ -8,6 +5,8 @@
 #include <lunaix/status.h>
 #include <lunaix/syscall.h>
 
+#include <klibc/string.h>
+
 extern struct scheduler sched_ctx; /* kernel/sched.c */
 
 void __USER__
index 4610acf2b9969d4ccfd77752e324a1f708bb8a9e..7c954b30ea9c3a44510885d0e389dbd8de379c05 100644 (file)
@@ -1,4 +1,5 @@
 #include <lunaix/fs/taskfs.h>
+#include <lunaix/process.h>
 
 void
 __read_pending_sig(struct twimap* map)
index 753470306ea4b852bff5154ad543873d8559ceda..ca7f61e13c8dfabeb62af094b8cc9fa371068e2f 100644 (file)
@@ -1,4 +1,3 @@
-#include <lunaix/dirent.h>
 #include <lunaix/fs/taskfs.h>
 #include <lunaix/fs/twimap.h>
 #include <lunaix/mm/valloc.h>
@@ -8,6 +7,8 @@
 #include <klibc/stdio.h>
 #include <klibc/string.h>
 
+#include <sys/dirent_defs.h>
+
 #define COUNTER_MASK ((1 << 16) - 1)
 
 static struct hbucket* attr_export_table;
index 21802bed7a66f84bc2234f1bd4ff131d38163015..adf577a6ed5339c6d98b22229abe6d7d67460cb8 100644 (file)
@@ -8,11 +8,10 @@
 #include <lunaix/mm/valloc.h>
 #include <lunaix/mm/vmm.h>
 #include <lunaix/sched.h>
+#include <lunaix/signal.h>
 #include <lunaix/tty/console.h>
 #include <lunaix/tty/tty.h>
 
-#include <lunaix/lxsignal.h>
-
 static struct console lx_console;
 
 int
index 30ceb654ddc584f0d0d9b89ec83108fc155475bf..c982f7ada1206af56d565155e639e1212e7b7e81 100644 (file)
@@ -10,7 +10,8 @@ strlen(const char* str)
 }
 
 size_t
-strnlen(const char* str, size_t max_len) {
+strnlen(const char* str, size_t max_len)
+{
     size_t len = 0;
     while (str[len] && len <= max_len)
         len++;
diff --git a/lunaix-os/libs/ulibc/printf.c b/lunaix-os/libs/ulibc/printf.c
deleted file mode 100644 (file)
index 18e2387..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <klibc/stdio.h>
-#include <lunaix/lunistd.h>
-#include <lunaix/spike.h>
-#include <ulibc/stdio.h>
-
-// This is VERY bad implementation as it mixes both kernel and user space
-// code together. It is here however, just for the convenience of our testing
-// program.
-// FIXME Eliminate this when we're able to load program.
-
-void __USER__
-printf(const char* fmt, ...)
-{
-    const char buf[512];
-    va_list args;
-    va_start(args, fmt);
-
-    size_t sz = __ksprintf_internal(buf, fmt, 512, args);
-
-    write(stdout, buf, sz);
-
-    va_end(args);
-}
\ No newline at end of file
index ede34f48a624bb7c0e3b726038ef5fba49ce4680..c1c800ccb68797a7630e44b7c62de4e4b1cddd35 100644 (file)
@@ -3,11 +3,7 @@ include config/make-os
 include config/make-cc
 include config/make-debug-tool
 
-DEPS := $(CC) $(LD) xorriso grub-mkrescue
-
-INCLUDES := $(patsubst %, -I%, $(INCLUDES_DIR))
-SOURCE_FILES := $(shell find -name "*.[cS]")
-SRC := $(patsubst ./%, $(OBJECT_DIR)/%.o, $(SOURCE_FILES))
+DEPS := $(CC) $(LD) $(AR) xorriso grub-mkrescue
 
 $(DEPS):
        @echo -n "checking $@ .... "
@@ -21,47 +17,45 @@ check-cc:
        @echo -n "checking target i686-elf.... "
        @test "`i686-elf-gcc -dumpmachine`" = "i686-elf" && echo ok || (echo "failed" && exit 1)
 
-check: $(DEPS) check-cc
-
 $(OBJECT_DIR):
        @mkdir -p $(OBJECT_DIR)
 
 $(BIN_DIR):
        @mkdir -p $(BIN_DIR)
 
+$(USR_DIR):
+       @mkdir -p $(USR_DIR)
+
 $(ISO_DIR):
        @mkdir -p $(ISO_DIR)
        @mkdir -p $(ISO_BOOT_DIR)
        @mkdir -p $(ISO_GRUB_DIR)
 
-$(OBJECT_DIR)/%.S.o: %.S
-       @mkdir -p $(@D)
-       @echo "  CC    $<"
-       @$(CC) $(INCLUDES) -c $< -o $@
+check: $(DEPS) check-cc GRUB_TEMPLATE
+
+prepare: check $(OBJECT_DIR) $(BIN_DIR) $(ISO_DIR) $(USR_DIR)
+
+usrlib: prepare makefile.usr
+       @make -f makefile.usr usr-runtime
+
+usrlib-debug: prepare makefile.usr
+       @make -f makefile.usr usr-runtime-debug
 
-$(OBJECT_DIR)/%.c.o: %.c 
-       @mkdir -p $(@D)
-       @echo "  CC    $<"
-       @$(CC) $(INCLUDES) -c $< -o $@ $(CFLAGS)
+usr-prog: prepare usrlib makefile.prog
+       @make -f makefile.prog all
 
-$(BIN_DIR)/$(OS_BIN): $(OBJECT_DIR) $(BIN_DIR) $(SRC)
-       @echo "  LD    $(BIN_DIR)/$(OS_BIN)"
-       @$(CC) -T link/linker.ld -o $(BIN_DIR)/$(OS_BIN) $(SRC) $(LDFLAGS)
+bootable: usr-prog usrlib makefile.ker
+       @make -f makefile.ker all
 
-$(BUILD_DIR)/$(OS_ISO): check $(ISO_DIR) $(BIN_DIR)/$(OS_BIN) GRUB_TEMPLATE
-       @./config-grub.sh ${OS_NAME} $(ISO_GRUB_DIR)/grub.cfg
-       @cp $(BIN_DIR)/$(OS_BIN) $(ISO_BOOT_DIR)
-       @grub-mkrescue -o $(BUILD_DIR)/$(OS_ISO) $(ISO_DIR)
+bootable-debug: usr-prog usrlib-debug makefile.ker
+       @make -f makefile.ker all-debug
 
-all: $(BUILD_DIR)/$(OS_ISO)
+all: bootable
 
 instable: CFLAGS := -g -std=gnu99 -ffreestanding $(O) $(W) $(ARCH_OPT) -D__LUNAIXOS_DEBUG__
 instable: all
 
-all-debug: O := -Og
-all-debug: CFLAGS := -g -std=gnu99 -ffreestanding $(O) $(W) $(ARCH_OPT) -D__LUNAIXOS_DEBUG__
-all-debug: LDFLAGS := -g -ffreestanding $(O) -nostdlib -lgcc
-all-debug: clean $(BUILD_DIR)/$(OS_ISO)
+all-debug: clean bootable-debug
        @echo "Dumping the disassembled kernel code to $(BUILD_DIR)/kdump.txt"
        @i686-elf-objdump -S $(BIN_DIR)/$(OS_BIN) > $(BUILD_DIR)/kdump.txt
 
diff --git a/lunaix-os/makefile.ker b/lunaix-os/makefile.ker
new file mode 100644 (file)
index 0000000..8411140
--- /dev/null
@@ -0,0 +1,41 @@
+include config/make-os
+include config/make-cc
+include config/make-debug-tool
+include config/make-locations
+
+SRC_DIRS := kernel \
+                       hal \
+                       debug \
+                       libs \
+                       arch \
+
+SRC_FILES := $(foreach f, $(SRC_DIRS), $(shell find $(f) -name "*.[cS]"))
+
+OBJS := $(foreach f, $(SRC_FILES), $(OBJECT_DIR)/$(f).o)
+
+$(OBJECT_DIR)/%.S.o: %.S
+       @mkdir -p $(@D)
+       @echo "  CC    $<"
+       @$(CC) $(INCLUDES) -c $< -o $@
+
+$(OBJECT_DIR)/%.c.o: %.c 
+       @mkdir -p $(@D)
+       @echo "  CC    $<"
+       @$(CC) $(INCLUDES) -c $< -o $@ $(CFLAGS)
+
+$(BIN_DIR)/$(OS_BIN): $(OBJECT_DIR) $(BIN_DIR) $(OBJS)
+       @echo "  LD    $(BIN_DIR)/$(OS_BIN)"
+       @$(CC) -T link/linker.ld -o $(BIN_DIR)/$(OS_BIN) $(OBJS) $(BIN_DIR)/$(USR_LIB) $(LDFLAGS)
+
+$(BUILD_DIR)/$(OS_ISO): $(BIN_DIR)/$(OS_BIN)
+       @./config-grub.sh ${OS_NAME} $(ISO_GRUB_DIR)/grub.cfg
+       @cp $(BIN_DIR)/$(OS_BIN) $(ISO_BOOT_DIR)
+       @cp -r $(USR_DIR) $(ISO_DIR)
+       @grub-mkrescue -o $(BUILD_DIR)/$(OS_ISO) $(ISO_DIR)
+
+all: $(BUILD_DIR)/$(OS_ISO)
+
+all-debug: O := -Og
+all-debug: CFLAGS := -g -std=gnu99 -ffreestanding $(O) $(W) $(ARCH_OPT) -D__LUNAIXOS_DEBUG__
+all-debug: LDFLAGS := -g -ffreestanding $(O) -nostdlib -lgcc
+all-debug: all
\ No newline at end of file
diff --git a/lunaix-os/makefile.prog b/lunaix-os/makefile.prog
new file mode 100644 (file)
index 0000000..2c8b8e7
--- /dev/null
@@ -0,0 +1,12 @@
+include config/make-locations
+include config/make-os
+include config/make-cc
+
+SRC_FILES := $(wildcard uprog/*.c)
+PROGRAMES := $(patsubst uprog/%.c, $(USR_DIR)/%, $(SRC_FILES))
+
+$(USR_DIR)/%:
+       @echo "  BUILD   $(*F)"
+       @$(CC) -T usr/link-usr.ld $(INCLUDES) $(CFLAGS) -g $(LDFLAGS) uprog/$(*F).c $(BIN_DIR)/$(USR_LIB) -o $@
+
+all: $(PROGRAMES)
\ No newline at end of file
diff --git a/lunaix-os/makefile.usr b/lunaix-os/makefile.usr
new file mode 100644 (file)
index 0000000..7cbec35
--- /dev/null
@@ -0,0 +1,32 @@
+include config/make-cc
+include config/make-os
+include config/make-locations
+
+SRC_DIRS := usr
+
+SRC_FILES := $(foreach f, $(SRC_DIRS), $(shell find $(f) -name "*.[cS]"))
+
+OBJS := $(foreach f, $(SRC_FILES), $(OBJECT_DIR)/$(f).o)
+
+$(OBJECT_DIR)/%.S.o: %.S
+       @mkdir -p $(@D)
+       @echo "  CC    $<"
+       @$(CC) $(INCLUDES) -c $< -o $@
+
+$(OBJECT_DIR)/%.c.o: %.c 
+       @mkdir -p $(@D)
+       @echo "  CC    $<"
+       @$(CC) $(INCLUDES) $(CFLAGS) -g -c $< -o $@ 
+
+$(BIN_DIR)/$(USR_LIB): $(OBJS)
+       @echo "  AR    $@"
+       @$(AR) rcs $@ $^
+
+usr-runtime: $(BIN_DIR)/$(USR_LIB)
+
+usr-runtime-debug: O := -Og
+usr-runtime-debug: CFLAGS := -g -std=gnu99 -ffreestanding $(O) $(W) $(ARCH_OPT) -D__LUNAIXOS_DEBUG__
+usr-runtime-debug: LDFLAGS := -g -ffreestanding $(O) -nostdlib -lgcc
+usr-runtime-debug: usr-runtime
+
+usr-objs: $(OBJS)
\ No newline at end of file
diff --git a/lunaix-os/uprog/init.c b/lunaix-os/uprog/init.c
new file mode 100644 (file)
index 0000000..dd083ad
--- /dev/null
@@ -0,0 +1,33 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/lunaix.h>
+#include <unistd.h>
+
+int
+main(int argc, const char** argv)
+{
+    int errno = 0;
+
+    if ((errno = open("/dev/tty", 0)) < 0) {
+        syslog(2, "fail to open tty (%d)\n", errno);
+        return 0;
+    }
+
+    if ((errno = dup(errno)) < 0) {
+        syslog(2, "fail to setup tty i/o (%d)\n", errno);
+        return 0;
+    }
+
+    printf("(%p) user space!\n", (void*)main);
+
+    pid_t pid;
+    if (!(pid = fork())) {
+        int err = execve("/mnt/lunaix-os/usr/ls", NULL, NULL);
+        printf("fail to execute (%d)\n", err);
+        _exit(err);
+    }
+
+    waitpid(pid, NULL, 0);
+
+    return 0;
+}
\ No newline at end of file
diff --git a/lunaix-os/uprog/ls.c b/lunaix-os/uprog/ls.c
new file mode 100644 (file)
index 0000000..accc7f7
--- /dev/null
@@ -0,0 +1,32 @@
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+
+int
+main(int argc, const char* argv[])
+{
+    char* path = ".";
+    if (argc > 0) {
+        path = argv[0];
+    }
+
+    DIR* dir = opendir(path);
+
+    if (!dir) {
+        return errno;
+    }
+
+    struct dirent* dent;
+
+    while ((dent = readdir(dir))) {
+        if (dent->d_type == DT_DIR) {
+            printf(" \033[3m%s\033[39;49m\n", dent->d_name);
+        } else {
+            printf(" %s\n", dent->d_name);
+        }
+    }
+
+    closedir(dir);
+
+    return 0;
+}
\ No newline at end of file
diff --git a/lunaix-os/usr/api/dirent.c b/lunaix-os/usr/api/dirent.c
new file mode 100644 (file)
index 0000000..e309582
--- /dev/null
@@ -0,0 +1,4 @@
+#include <lunaix/syscall.h>
+#include <sys/lxdirent.h>
+
+__LXSYSCALL2(int, sys_readdir, int, fd, struct lx_dirent*, dent)
diff --git a/lunaix-os/usr/api/errno.c b/lunaix-os/usr/api/errno.c
new file mode 100644 (file)
index 0000000..ac0d004
--- /dev/null
@@ -0,0 +1,4 @@
+#include <lunaix/syscall.h>
+#include <errno.h>
+
+__LXSYSCALL(int, geterrno);
\ No newline at end of file
diff --git a/lunaix-os/usr/api/fcntl.c b/lunaix-os/usr/api/fcntl.c
new file mode 100644 (file)
index 0000000..92e2fa3
--- /dev/null
@@ -0,0 +1,4 @@
+#include <lunaix/syscall.h>
+#include <fcntl.h>
+
+__LXSYSCALL2(int, open, const char*, path, int, options)
diff --git a/lunaix-os/usr/api/ioctl.c b/lunaix-os/usr/api/ioctl.c
new file mode 100644 (file)
index 0000000..bb2126a
--- /dev/null
@@ -0,0 +1,4 @@
+#include <lunaix/syscall.h>
+#include <sys/ioctl.h>
+
+__LXSYSCALL2_VARG(int, ioctl, int, fd, int, req);
\ No newline at end of file
similarity index 62%
rename from lunaix-os/includes/lunaix/lunaix.h
rename to lunaix-os/usr/api/lunaix.c
index adbde1dca148513d2c627aaa8994bacc015183e9..59fe79a2beb9e5b3598bb69b21c010c8257d4989 100644 (file)
@@ -1,8 +1,5 @@
-#ifndef __LUNAIX_LUNAIX_H
-#define __LUNAIX_LUNAIX_H
-
 #include <lunaix/syscall.h>
-#include <lunaix/types.h>
+#include <sys/lunaix.h>
 
 __LXSYSCALL(void, yield);
 
@@ -10,8 +7,6 @@ __LXSYSCALL1(pid_t, wait, int*, status);
 
 __LXSYSCALL3(pid_t, waitpid, pid_t, pid, int*, status, int, options);
 
-__LXSYSCALL(int, geterrno);
-
 __LXSYSCALL2_VARG(void, syslog, int, level, const char*, fmt);
 
-#endif /* __LUNAIX_LUNAIX_H */
+__LXSYSCALL3(int, realpathat, int, fd, char*, buf, size_t, size)
diff --git a/lunaix-os/usr/api/mann.c b/lunaix-os/usr/api/mann.c
new file mode 100644 (file)
index 0000000..e211cad
--- /dev/null
@@ -0,0 +1,12 @@
+#include <lunaix/syscall.h>
+#include <sys/mann.h>
+
+__LXSYSCALL2_VARG(void*, sys_mmap, void*, addr, size_t, length);
+
+void*
+mmap(void* addr, size_t length, int proct, int flags, int fd, off_t offset)
+{
+    return sys_mmap(addr, length, proct, fd, offset, flags);
+}
+
+__LXSYSCALL2(void, munmap, void*, addr, size_t, length)
diff --git a/lunaix-os/usr/api/mount.c b/lunaix-os/usr/api/mount.c
new file mode 100644 (file)
index 0000000..854c96b
--- /dev/null
@@ -0,0 +1,15 @@
+#include <lunaix/syscall.h>
+#include <sys/mount.h>
+
+__LXSYSCALL4(int,
+             mount,
+             const char*,
+             source,
+             const char*,
+             target,
+             const char*,
+             fstype,
+             int,
+             options)
+
+__LXSYSCALL1(int, unmount, const char*, target)
\ No newline at end of file
diff --git a/lunaix-os/usr/api/signal.c b/lunaix-os/usr/api/signal.c
new file mode 100644 (file)
index 0000000..191e8d8
--- /dev/null
@@ -0,0 +1,16 @@
+#include <lunaix/syscall.h>
+#include <signal.h>
+
+__LXSYSCALL2(int, signal, int, signum, sighandler_t, handler);
+
+__LXSYSCALL1(int, sigpending, sigset_t, *set);
+__LXSYSCALL1(int, sigsuspend, const sigset_t, *mask);
+
+__LXSYSCALL3(int,
+             sigprocmask,
+             int,
+             how,
+             const sigset_t,
+             *set,
+             sigset_t,
+             *oldset);
diff --git a/lunaix-os/usr/api/unistd.c b/lunaix-os/usr/api/unistd.c
new file mode 100644 (file)
index 0000000..088c335
--- /dev/null
@@ -0,0 +1,126 @@
+#include <lunaix/syscall.h>
+#include <unistd.h>
+
+__LXSYSCALL(pid_t, fork)
+
+__LXSYSCALL1(int, brk, void*, addr)
+
+__LXSYSCALL1(void*, sbrk, ssize_t, size)
+
+__LXSYSCALL(pid_t, getpid)
+
+__LXSYSCALL(pid_t, getppid)
+
+__LXSYSCALL(pid_t, getpgid)
+
+__LXSYSCALL2(pid_t, setpgid, pid_t, pid, pid_t, pgid)
+
+__LXSYSCALL1(void, _exit, int, status)
+
+__LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
+
+__LXSYSCALL(int, pause)
+
+__LXSYSCALL2(int, kill, pid_t, pid, int, signum)
+
+__LXSYSCALL1(unsigned int, alarm, unsigned int, seconds)
+
+__LXSYSCALL2(int, link, const char*, oldpath, const char*, newpath)
+
+__LXSYSCALL1(int, rmdir, const char*, pathname)
+
+__LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count)
+
+__LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count)
+
+__LXSYSCALL3(int, readlink, const char*, path, char*, buf, size_t, size)
+
+__LXSYSCALL3(int, lseek, int, fd, off_t, offset, int, options)
+
+__LXSYSCALL1(int, unlink, const char*, pathname)
+
+__LXSYSCALL1(int, close, int, fd)
+
+__LXSYSCALL2(int, dup2, int, oldfd, int, newfd)
+
+__LXSYSCALL1(int, dup, int, oldfd)
+
+__LXSYSCALL1(int, fsync, int, fildes)
+
+__LXSYSCALL2(int, symlink, const char*, pathname, const char*, link_target)
+
+__LXSYSCALL1(int, chdir, const char*, path)
+
+__LXSYSCALL1(int, fchdir, int, fd)
+
+__LXSYSCALL2(char*, getcwd, char*, buf, size_t, size)
+
+__LXSYSCALL2(int, rename, const char*, oldpath, const char*, newpath)
+
+__LXSYSCALL4(int,
+             getxattr,
+             const char*,
+             path,
+             const char*,
+             name,
+             void*,
+             value,
+             size_t,
+             len)
+
+__LXSYSCALL4(int,
+             setxattr,
+             const char*,
+             path,
+             const char*,
+             name,
+             void*,
+             value,
+             size_t,
+             len)
+
+__LXSYSCALL4(int,
+             fgetxattr,
+             int,
+             fd,
+             const char*,
+             name,
+             void*,
+             value,
+             size_t,
+             len)
+
+__LXSYSCALL4(int,
+             fsetxattr,
+             int,
+             fd,
+             const char*,
+             name,
+             void*,
+             value,
+             size_t,
+             len)
+
+__LXSYSCALL4(int,
+             readlinkat,
+             int,
+             dirfd,
+             const char*,
+             pathname,
+             char*,
+             buf,
+             size_t,
+             size)
+
+__LXSYSCALL2(int, unlinkat, int, fd, const char*, pathname)
+
+__LXSYSCALL1(int, mkdir, const char*, path)
+
+__LXSYSCALL3(int,
+             execve,
+             const char*,
+             filename,
+             const char**,
+             argv,
+             const char**,
+             envp)
\ No newline at end of file
diff --git a/lunaix-os/usr/includes/dirent.h b/lunaix-os/usr/includes/dirent.h
new file mode 100644 (file)
index 0000000..78d57e3
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef __LUNAIX_SYS_DIRENT_H
+#define __LUNAIX_SYS_DIRENT_H
+
+#include <sys/dirent_defs.h>
+
+typedef struct
+{
+    int dirfd;
+    struct lx_dirent _lxd;
+} DIR;
+
+struct dirent
+{
+    unsigned char d_type;
+    char d_name[256];
+};
+
+DIR*
+opendir(const char* dirp);
+
+int
+closedir(DIR* dirp);
+
+struct dirent*
+readdir(DIR* dir);
+
+#endif /* __LUNAIX_DIRENT_H */
diff --git a/lunaix-os/usr/includes/errno.h b/lunaix-os/usr/includes/errno.h
new file mode 100644 (file)
index 0000000..f3c5347
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __LUNAIX_SYS_ERRNO_H
+#define __LUNAIX_SYS_ERRNO_H
+
+#define EINVAL -(6)
+#define EINTR -(7)
+#define EMFILE -8
+#define ENOENT -9
+#define ENAMETOOLONG -10
+#define ENOTDIR -11
+#define EEXIST -12
+#define EBADF -13
+#define ENOTSUP -14
+#define EIO -15
+#define ELOOP -16
+#define ENOTEMPTY -17
+#define EROFS -18
+#define EISDIR -19
+#define EBUSY -20
+#define EXDEV -21
+#define ENODEV -22
+#define ERANGE -23
+#define ENOMEM -(3)
+#define ENOTDEV -24
+#define EOVERFLOW -25
+#define ENOTBLK -26
+#define ENOEXEC -27
+#define E2BIG -28
+
+int
+geterrno();
+
+#define errno (geterrno())
+
+#endif /* __LUNAIX_ERRNO_H */
diff --git a/lunaix-os/usr/includes/fcntl.h b/lunaix-os/usr/includes/fcntl.h
new file mode 100644 (file)
index 0000000..0ce31d8
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __LUNAIX_SYS_FCNTL_H
+#define __LUNAIX_SYS_FCNTL_H
+
+#include <fcntl_defs.h>
+#include <sys/types.h>
+
+int
+open(const char* path, int flags);
+
+#endif /* __LUNAIX_FCNTL_H */
diff --git a/lunaix-os/usr/includes/fcntl_defs.h b/lunaix-os/usr/includes/fcntl_defs.h
new file mode 100644 (file)
index 0000000..c6cbe4f
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __LUNAIX_SYS_FCNTL_DEFS_H
+#define __LUNAIX_SYS_FCNTL_DEFS_H
+
+#define FO_CREATE 0x1
+#define FO_APPEND 0x2
+#define FO_DIRECT 0x4
+#define FO_WRONLY 0x8
+#define FO_RDONLY 0x10
+#define FO_RDWR 0x20
+
+#define FSEEK_SET 0x1
+#define FSEEK_CUR 0x2
+#define FSEEK_END 0x3
+
+#define O_CREAT FO_CREATE
+#define O_APPEND FO_APPEND
+#define O_DIRECT FO_DIRECT
+#define O_WRONLY FO_WRONLY
+#define O_RDONLY FO_RDONLY
+#define O_RDWR FO_RDWR
+
+#define MNT_RO 0x1
+
+#endif /* __LUNAIX_FNCTL_DEFS_H */
diff --git a/lunaix-os/usr/includes/signal.h b/lunaix-os/usr/includes/signal.h
new file mode 100644 (file)
index 0000000..56da91e
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef __LUNAIX_SYS_SIGNAL_H
+#define __LUNAIX_SYS_SIGNAL_H
+
+#include <signal_defs.h>
+#include <sys/types.h>
+
+int
+signal(int signum, sighandler_t handler);
+
+int
+sigpending(sigset_t* set);
+
+int
+sigsuspend(const sigset_t* mask);
+
+int
+sigprocmask(int how, const sigset_t* set, sigset_t* oldset);
+
+#endif /* __LUNAIX_SIGNAL_H */
diff --git a/lunaix-os/usr/includes/signal_defs.h b/lunaix-os/usr/includes/signal_defs.h
new file mode 100644 (file)
index 0000000..ac102ab
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __LUNAIX_SYS_SIGNAL_DEFS_H
+#define __LUNAIX_SYS_SIGNAL_DEFS_H
+
+#define SIGSEGV 1
+#define SIGALRM 2
+#define SIGCHLD 3
+#define SIGCLD SIGCHLD
+#define SIGINT 4
+#define SIGKILL 5
+#define SIGSTOP 6
+#define SIGCONT 7
+#define SIGTERM 8
+
+#define SIG_BLOCK 1
+#define SIG_UNBLOCK 2
+#define SIG_SETMASK 3
+
+typedef unsigned int sigset_t;
+typedef void (*sighandler_t)(int);
+
+#endif /* __LUNAIX_SIGNAL_DEFS_H */
similarity index 96%
rename from lunaix-os/includes/ulibc/stdio.h
rename to lunaix-os/usr/includes/stdio.h
index e9496a825ad131ff293a080c315b2c9002067794..0ef2e146fa2211b1a2fee357c7cb9e2271ea4e6e 100644 (file)
@@ -4,7 +4,7 @@
 #define stdout 0
 #define stdin 1
 
-void
+int
 printf(const char* fmt, ...);
 
 #endif /* __LUNAIX_USTDIO_H */
diff --git a/lunaix-os/usr/includes/stdlib.h b/lunaix-os/usr/includes/stdlib.h
new file mode 100644 (file)
index 0000000..0e38fb5
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __LUNAIX_STDLIB_H
+#define __LUNAIX_STDLIB_H
+
+char*
+itoa(int value, char* str, int base);
+
+#endif /* __LUNAIX_STDLIB_H */
diff --git a/lunaix-os/usr/includes/string.h b/lunaix-os/usr/includes/string.h
new file mode 100644 (file)
index 0000000..2b5799a
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __LUNAIX_STRING_H
+#define __LUNAIX_STRING_H
+
+#include <stddef.h>
+
+size_t
+strlen(const char* str);
+
+size_t
+strnlen(const char* str, size_t max_len);
+
+char*
+strncpy(char* dest, const char* src, size_t n);
+
+const char*
+strchr(const char* str, int character);
+
+char*
+strcpy(char* dest, const char* src);
+
+#endif /* __LUNAIX_STRING_H */
similarity index 65%
rename from lunaix-os/includes/lunaix/dirent.h
rename to lunaix-os/usr/includes/sys/dirent_defs.h
index 160365d6c3db97bbee27dbf90f005ca0086a81d7..779235519d0ce6263ce1f72250bcb0164d3db8f5 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __LUNAIX_DIRENT_H
-#define __LUNAIX_DIRENT_H
+#ifndef __LUNAIX_SYS_DIRENT_DEFS_H
+#define __LUNAIX_SYS_DIRENT_DEFS_H
 
 #define DIRENT_NAME_MAX_LEN 256
 
@@ -8,7 +8,7 @@
 #define DT_SYMLINK 0x2
 #define DT_PIPE 0x2
 
-struct dirent
+struct lx_dirent
 {
     unsigned int d_type;
     unsigned int d_offset;
@@ -16,4 +16,4 @@ struct dirent
     char d_name[DIRENT_NAME_MAX_LEN];
 };
 
-#endif /* __LUNAIX_DIRENT_H */
+#endif /* __LUNAIX_DIRENT_DEFS_H */
diff --git a/lunaix-os/usr/includes/sys/ioctl.h b/lunaix-os/usr/includes/sys/ioctl.h
new file mode 100644 (file)
index 0000000..58c681a
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __LUNAIX_SYS_IOCTL_H
+#define __LUNAIX_SYS_IOCTL_H
+
+#include <sys/ioctl_defs.h>
+
+int
+ioctl(int fd, int req, ...);
+
+#endif /* __LUNAIX_IOCTL_H */
diff --git a/lunaix-os/usr/includes/sys/ioctl_defs.h b/lunaix-os/usr/includes/sys/ioctl_defs.h
new file mode 100644 (file)
index 0000000..7be48e7
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __LUNAIX_SYS_IOCTL_DEFS_H
+#define __LUNAIX_SYS_IOCTL_DEFS_H
+
+#define IOREQ(cmd, arg_num) ((((cmd)&0xffff) << 8) | ((arg_num)&0xff))
+
+#define IOCMD(req) ((req) >> 8)
+
+#define IOARGNUM(req) ((req)&0xff)
+
+#define TIOCGPGRP IOREQ(1, 0)
+#define TIOCSPGRP IOREQ(1, 1)
+#define TIOCCLSBUF IOREQ(2, 0)
+#define TIOCFLUSH IOREQ(3, 0)
+
+#endif /* __LUNAIX_IOCTL_DEFS_H */
diff --git a/lunaix-os/usr/includes/sys/lunaix.h b/lunaix-os/usr/includes/sys/lunaix.h
new file mode 100644 (file)
index 0000000..febcb59
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __LUNAIX_SYS_LUNAIX_H
+#define __LUNAIX_SYS_LUNAIX_H
+
+#include <sys/types.h>
+
+void
+yield();
+
+pid_t
+wait(int* status);
+
+pid_t
+waitpid(pid_t pid, int* status, int flags);
+
+void
+syslog(int level, const char* fmt, ...);
+
+int
+realpathat(int fd, char* buf, size_t size);
+
+#endif /* __LUNAIX_LUNAIX_H */
diff --git a/lunaix-os/usr/includes/sys/lxdirent.h b/lunaix-os/usr/includes/sys/lxdirent.h
new file mode 100644 (file)
index 0000000..e616180
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __LUNAIX_SYS_LXDIRENT_H
+#define __LUNAIX_SYS_LXDIRENT_H
+
+#include <sys/dirent_defs.h>
+
+int
+sys_readdir(int fd, struct lx_dirent* dirent);
+
+#endif /* __LUNAIX_DIRENT_H */
diff --git a/lunaix-os/usr/includes/sys/mann.h b/lunaix-os/usr/includes/sys/mann.h
new file mode 100644 (file)
index 0000000..0e424d4
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __LUNAIX_SYS_MANN_H
+#define __LUNAIX_SYS_MANN_H
+
+#include <sys/mann_flags.h>
+#include <sys/types.h>
+
+void*
+mmap(void* addr, size_t length, int proct, int flags, int fd, off_t offset);
+
+void
+munmap(void* addr, size_t length);
+
+#endif /* __LUNAIX_MANN_H */
diff --git a/lunaix-os/usr/includes/sys/mann_flags.h b/lunaix-os/usr/includes/sys/mann_flags.h
new file mode 100644 (file)
index 0000000..479c60b
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef __LUNAIX_SYS_MANN_FLAGS_H
+#define __LUNAIX_SYS_MANN_FLAGS_H
+
+// POSIX compliant.
+
+// identity mapped to region attributes
+#define PROT_READ (1 << 2)
+#define PROT_WRITE (1 << 3)
+#define PROT_EXEC (1 << 4)
+
+// identity mapped to region attributes
+
+#define MAP_WSHARED 0x2
+#define MAP_RSHARED 0x1
+#define MAP_SHARED MAP_WSHARED
+#define MAP_PRIVATE MAP_RSHARED
+#define MAP_EXCLUSIVE 0x0
+#define MAP_ANON (1 << 5)
+#define MAP_STACK 0 // no effect in Lunaix
+
+// other MAP_* goes should beyond 0x20
+
+#define MAP_FIXED 0x40
+#define MAP_FIXED_NOREPLACE 0x80
+
+#define MS_ASYNC 0x1
+#define MS_SYNC 0x2
+#define MS_INVALIDATE 0x4
+#define MS_INVALIDATE_ALL 0x8
+
+#endif /* __LUNAIX_MANN_FLAGS_H */
diff --git a/lunaix-os/usr/includes/sys/mount.h b/lunaix-os/usr/includes/sys/mount.h
new file mode 100644 (file)
index 0000000..5d12df8
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __LUNAIX_SYS_MOUNT_H
+#define __LUNAIX_SYS_MOUNT_H
+
+#include <sys/types.h>
+
+int
+mount(const char* source, const char* target, const char* fstype, int flags);
+
+int
+unmount(const char* target);
+
+static inline int
+umount(const char* target)
+{
+    return unmount(target);
+}
+#endif /* __LUNAIX_MOUNT_H */
diff --git a/lunaix-os/usr/includes/sys/types.h b/lunaix-os/usr/includes/sys/types.h
new file mode 100644 (file)
index 0000000..8b30318
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __LUNAIX_SYS_TYPES_H
+#define __LUNAIX_SYS_TYPES_H
+
+#define NULL (void*)0
+
+#define PEXITTERM 0x100
+#define PEXITSTOP 0x200
+#define PEXITSIG 0x400
+
+#define PEXITNUM(flag, code) (flag | (code & 0xff))
+
+#define WNOHANG 1
+#define WUNTRACED 2
+#define WEXITSTATUS(wstatus) ((wstatus & 0xff))
+#define WIFSTOPPED(wstatus) ((wstatus & PEXITSTOP))
+#define WIFEXITED(wstatus)                                                     \
+    ((wstatus & PEXITTERM) && ((char)WEXITSTATUS(wstatus) >= 0))
+
+#define WIFSIGNALED(wstatus) ((wstatus & PEXITSIG))
+
+typedef signed long ssize_t;
+
+typedef int pid_t;
+
+typedef unsigned long size_t;
+
+typedef unsigned long off_t;
+
+#endif /* __LUNAIX_TYPES_H */
diff --git a/lunaix-os/usr/includes/unistd.h b/lunaix-os/usr/includes/unistd.h
new file mode 100644 (file)
index 0000000..8420ffa
--- /dev/null
@@ -0,0 +1,116 @@
+#ifndef __LUNAIX_SYS_UNISTD_H
+#define __LUNAIX_SYS_UNISTD_H
+
+#include <sys/types.h>
+
+extern const char** environ;
+
+pid_t
+fork();
+
+pid_t
+getpid();
+
+pid_t
+getppid();
+
+pid_t
+getpgid();
+
+pid_t
+setpgid(pid_t pid, pid_t pgid);
+
+int
+brk(void* addr);
+
+void*
+sbrk(ssize_t size);
+
+void
+_exit(int status);
+
+unsigned int
+sleep(unsigned int);
+
+int
+pause();
+
+int
+kill(pid_t pid, int signum);
+
+unsigned int
+alarm(unsigned int seconds);
+
+int
+link(const char* oldpath, const char* newpath);
+
+int
+rmdir(const char* pathname);
+
+int
+read(int fd, void* buf, size_t size);
+
+int
+write(int fd, void* buf, size_t size);
+
+int
+readlink(const char* path, char* buffer, size_t size);
+
+int
+readlinkat(int dirfd, const char* pathname, char* buffer, size_t size);
+
+int
+lseek(int fd, off_t offset, int mode);
+
+int
+unlink(const char* pathname);
+
+int
+unlinat(int fd, const char* pathname);
+
+int
+mkdir(const char* path);
+
+int
+close(int fd);
+
+int
+dup2(int oldfd, int newfd);
+
+int
+dup(int oldfd);
+
+int
+fsync(int fd);
+
+int
+symlink(const char* pathname, const char* linktarget);
+
+int
+chdir(const char* path);
+
+int
+fchdir(int fd);
+
+char*
+getcwd(char* buf, size_t size);
+
+int
+rename(const char* oldpath, const char* newpath);
+
+int
+getxattr(const char* path, const char* name, void* value, size_t len);
+
+int
+setxattr(const char* path, const char* name, void* value, size_t len);
+
+int
+fgetxattr(int fd, const char* name, void* value, size_t len);
+
+int
+fsetxattr(int fd, const char* name, void* value, size_t len);
+
+int
+execve(const char* filename, const char* argv[], const char* envp[]);
+
+#endif /* __LUNAIX_UNISTD_H */
diff --git a/lunaix-os/usr/libc/_mystdio.h b/lunaix-os/usr/libc/_mystdio.h
new file mode 100644 (file)
index 0000000..d60fed3
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __LUNAIX__MYSTDIO_H
+#define __LUNAIX__MYSTDIO_H
+
+#include <stdarg.h>
+#include <stddef.h>
+
+int
+__vprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs);
+
+#endif /* __LUNAIX__MYSTDIO_H */
diff --git a/lunaix-os/usr/libc/_vprintf.c b/lunaix-os/usr/libc/_vprintf.c
new file mode 100644 (file)
index 0000000..1e56305
--- /dev/null
@@ -0,0 +1,198 @@
+#include "_mystdio.h"
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NUMBUFSIZ 24
+
+static const char flag_chars[] = "#0- +";
+
+#define FLAG_ALT (1 << 0)
+#define FLAG_ZERO (1 << 1)
+#define FLAG_LEFTJUSTIFY (1 << 2)
+#define FLAG_SPACEPOSITIVE (1 << 3)
+#define FLAG_PLUSPOSITIVE (1 << 4)
+#define FLAG_NUMERIC (1 << 5)
+#define FLAG_SIGNED (1 << 6)
+#define FLAG_NEGATIVE (1 << 7)
+#define FLAG_ALT2 (1 << 8)
+#define FLAG_CAPS (1 << 9)
+
+int
+__vprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs)
+{
+    // This sprintf just a random implementation I found it on Internet . lol.
+    //      Of course, with some modifications for porting to LunaixOS :)
+
+    char numbuf[NUMBUFSIZ];
+    uintptr_t ptr = 0;
+    for (; *fmt; ++fmt) {
+        if (max_len && ptr >= max_len - 1) {
+            break;
+        }
+
+        if (*fmt != '%') {
+            buffer[ptr++] = *fmt;
+            continue;
+        }
+
+        // process flags
+        int flags = 0;
+        for (++fmt; *fmt; ++fmt) {
+            const char* flagc = strchr(flag_chars, *fmt);
+            if (flagc) {
+                flags |= 1 << (flagc - flag_chars);
+            } else {
+                break;
+            }
+        }
+
+        // process width
+        int width = -1;
+        if (*fmt >= '1' && *fmt <= '9') {
+            for (width = 0; *fmt >= '0' && *fmt <= '9';) {
+                width = 10 * width + *fmt++ - '0';
+            }
+        } else if (*fmt == '*') {
+            width = va_arg(vargs, int);
+            ++fmt;
+        }
+
+        // process precision
+        int precision = -1;
+        if (*fmt == '.') {
+            ++fmt;
+            if (*fmt >= '0' && *fmt <= '9') {
+                for (precision = 0; *fmt >= '0' && *fmt <= '9';) {
+                    precision = 10 * precision + *fmt++ - '0';
+                }
+            } else if (*fmt == '*') {
+                precision = va_arg(vargs, int);
+                ++fmt;
+            }
+            if (precision < 0) {
+                precision = 0;
+            }
+        }
+
+        // process main conversion character
+        int base = 10;
+        unsigned long num = 0;
+        int length = 0;
+        char* data = "";
+    again:
+        switch (*fmt) {
+            case 'l':
+            case 'z':
+                length = 1;
+                ++fmt;
+                goto again;
+            case 'd':
+            case 'i': {
+                long x = length ? va_arg(vargs, long) : va_arg(vargs, int);
+                int negative = x < 0 ? FLAG_NEGATIVE : 0;
+                num = negative ? -x : x;
+                flags |= FLAG_NUMERIC | FLAG_SIGNED | negative;
+                break;
+            }
+            case 'u':
+            format_unsigned:
+                num = length ? va_arg(vargs, unsigned long)
+                             : va_arg(vargs, unsigned);
+                flags |= FLAG_NUMERIC;
+                break;
+            case 'b':
+                base = 2;
+                goto format_unsigned;
+            case 'x':
+                base = 16;
+                goto format_unsigned;
+            case 'X':
+                flags = flags | FLAG_CAPS;
+                base = 16;
+                goto format_unsigned;
+            case 'p':
+                num = (uintptr_t)va_arg(vargs, void*);
+                base = 16;
+                flags |= FLAG_ALT | FLAG_ALT2 | FLAG_NUMERIC;
+                break;
+            case 's':
+                data = va_arg(vargs, char*);
+                break;
+            case 'c':
+                data = numbuf;
+                numbuf[0] = va_arg(vargs, int);
+                numbuf[1] = '\0';
+                break;
+            default:
+                data = numbuf;
+                numbuf[0] = (*fmt ? *fmt : '%');
+                numbuf[1] = '\0';
+                if (!*fmt) {
+                    fmt--;
+                }
+                break;
+        }
+
+        if (flags & FLAG_NUMERIC) {
+            data = itoa(num, numbuf, base);
+            int i = 0;
+            char c;
+            while ((flags & FLAG_CAPS) && (c = data[i])) {
+                data[i] = c & ~((c & 0x40) >> 1);
+                i++;
+            }
+        }
+
+        const char* prefix = "";
+        if ((flags & FLAG_NUMERIC) && (flags & FLAG_SIGNED)) {
+            if (flags & FLAG_NEGATIVE) {
+                prefix = "-";
+            } else if (flags & FLAG_PLUSPOSITIVE) {
+                prefix = "+";
+            } else if (flags & FLAG_SPACEPOSITIVE) {
+                prefix = " ";
+            }
+        } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ALT) &&
+                   (base == 16 || base == -16) &&
+                   (num || (flags & FLAG_ALT2))) {
+            prefix = "0x";
+        }
+
+        int len;
+        if (precision >= 0 && !(flags & FLAG_NUMERIC)) {
+            len = strnlen(data, precision);
+        } else {
+            len = strlen(data);
+        }
+        int zeros;
+        if ((flags & FLAG_NUMERIC) && precision >= 0) {
+            zeros = precision > len ? precision - len : 0;
+        } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ZERO) &&
+                   !(flags & FLAG_LEFTJUSTIFY) &&
+                   len + (int)strlen(prefix) < width) {
+            zeros = width - len - strlen(prefix);
+        } else {
+            zeros = 0;
+        }
+        width -= len + zeros + strlen(prefix);
+        for (; !(flags & FLAG_LEFTJUSTIFY) && width > 0; --width) {
+            buffer[ptr++] = ' ';
+        }
+        for (; *prefix; ++prefix) {
+            buffer[ptr++] = *prefix;
+        }
+        for (; zeros > 0; --zeros) {
+            buffer[ptr++] = '0';
+        }
+        for (; len > 0; ++data, --len) {
+            buffer[ptr++] = *data;
+        }
+        for (; width > 0; --width) {
+            buffer[ptr++] = ' ';
+        }
+    }
+    buffer[ptr++] = '\0';
+
+    return ptr;
+}
diff --git a/lunaix-os/usr/libc/itoa.c b/lunaix-os/usr/libc/itoa.c
new file mode 100644 (file)
index 0000000..d60599f
--- /dev/null
@@ -0,0 +1,46 @@
+#include <stddef.h>
+#include <stdlib.h>
+
+char base_char[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+char*
+__uitoa_internal(unsigned int value, char* str, int base, unsigned int* size)
+{
+    unsigned int ptr = 0;
+    do {
+        str[ptr] = base_char[value % base];
+        value = value / base;
+        ptr++;
+    } while (value);
+
+    for (unsigned int i = 0; i < (ptr >> 1); i++) {
+        char c = str[i];
+        str[i] = str[ptr - i - 1];
+        str[ptr - i - 1] = c;
+    }
+    str[ptr] = '\0';
+    if (size) {
+        *size = ptr;
+    }
+    return str;
+}
+
+char*
+__itoa_internal(int value, char* str, int base, unsigned int* size)
+{
+    if (value < 0 && base == 10) {
+        str[0] = '-';
+        unsigned int _v = (unsigned int)(-value);
+        __uitoa_internal(_v, str + 1, base, size);
+    } else {
+        __uitoa_internal(value, str, base, size);
+    }
+
+    return str;
+}
+
+char*
+itoa(int value, char* str, int base)
+{
+    return __itoa_internal(value, str, base, NULL);
+}
\ No newline at end of file
diff --git a/lunaix-os/usr/libc/printf.c b/lunaix-os/usr/libc/printf.c
new file mode 100644 (file)
index 0000000..3268a3f
--- /dev/null
@@ -0,0 +1,15 @@
+#include "_mystdio.h"
+#include <stdio.h>
+#include <unistd.h>
+
+int
+printf(const char* fmt, ...)
+{
+    char buf[1024];
+    va_list args;
+    va_start(args, fmt);
+    int n = __vprintf_internal(buf, fmt, 1024, args);
+    va_end(args);
+
+    return write(stdout, buf, n);
+}
\ No newline at end of file
diff --git a/lunaix-os/usr/libc/readdir.c b/lunaix-os/usr/libc/readdir.c
new file mode 100644 (file)
index 0000000..f8285b8
--- /dev/null
@@ -0,0 +1,58 @@
+#include <dirent.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/lxdirent.h>
+#include <unistd.h>
+
+DIR*
+opendir(const char* dir)
+{
+    static DIR _dir;
+    int fd = open(dir, O_RDONLY);
+    if (fd < 0) {
+        return NULL;
+    }
+
+    _dir = (DIR){ .dirfd = fd };
+    return &_dir;
+}
+
+int
+closedir(DIR* dirp)
+{
+    if (!dirp || dirp->dirfd == -1) {
+        // TODO migrate the status.h
+        return -1;
+    }
+
+    int err = close(dirp->dirfd);
+
+    if (!err) {
+        dirp->dirfd = -1;
+        return 0;
+    }
+
+    return -1;
+}
+
+struct dirent*
+readdir(DIR* dir)
+{
+    static struct dirent _dirent;
+    if (!dir) {
+        return NULL;
+    }
+
+    struct lx_dirent* _lxd = &dir->_lxd;
+
+    int more = sys_readdir(dir->dirfd, _lxd);
+
+    _dirent.d_type = _lxd->d_type;
+    strncpy(_dirent.d_name, _lxd->d_name, 256);
+
+    if (more) {
+        return &_dirent;
+    }
+
+    return NULL;
+}
\ No newline at end of file
diff --git a/lunaix-os/usr/libc/string.c b/lunaix-os/usr/libc/string.c
new file mode 100644 (file)
index 0000000..280cbbe
--- /dev/null
@@ -0,0 +1,57 @@
+#include <string.h>
+
+size_t
+strlen(const char* str)
+{
+    size_t len = 0;
+    while (str[len])
+        len++;
+    return len;
+}
+
+const char*
+strchr(const char* str, int character)
+{
+    char c = (char)character;
+    while ((*str)) {
+        if (*str == c) {
+            return str;
+        }
+        str++;
+    }
+    return c == '\0' ? str : NULL;
+}
+
+size_t
+strnlen(const char* str, size_t max_len)
+{
+    size_t len = 0;
+    while (str[len] && len <= max_len)
+        len++;
+    return len;
+}
+
+char*
+strncpy(char* dest, const char* src, size_t n)
+{
+    char c;
+    unsigned int i = 0;
+    while ((c = src[i]) && i <= n)
+        dest[i++] = c;
+    while (i <= n)
+        dest[i++] = 0;
+    return dest;
+}
+
+char*
+strcpy(char* dest, const char* src)
+{
+    char c;
+    unsigned int i = 0;
+    while ((c = src[i])) {
+        dest[i] = c;
+        i++;
+    }
+    dest[i] = '\0';
+    return dest;
+}
diff --git a/lunaix-os/usr/link-usr.ld b/lunaix-os/usr/link-usr.ld
new file mode 100644 (file)
index 0000000..49fb4c9
--- /dev/null
@@ -0,0 +1,5 @@
+ENTRY(_u_start)
+
+SECTIONS {
+    . = 0x400000;
+}
\ No newline at end of file
diff --git a/lunaix-os/usr/uinit.c b/lunaix-os/usr/uinit.c
new file mode 100644 (file)
index 0000000..0352743
--- /dev/null
@@ -0,0 +1,13 @@
+#define __USR_WRAPPER__
+#include <lunaix/ld.h>
+
+int
+usr_pre_init(struct usr_exec_param* param)
+{
+    // TODO some inits before executing user program
+
+    extern ptr_t environ;
+    environ = (ptr_t)param->envp;
+
+    return 0;
+}
\ No newline at end of file
diff --git a/lunaix-os/usr/uwrap.S b/lunaix-os/usr/uwrap.S
new file mode 100644 (file)
index 0000000..5708463
--- /dev/null
@@ -0,0 +1,28 @@
+#define __ASM__
+#include <lunaix/syscall.h>
+
+.section .data
+    .global environ
+    environ:
+        .long 0
+
+.section .text
+    .global _u_start
+    _u_start:
+        call usr_pre_init
+        jnz 1f
+
+        popl %eax
+
+        pushl (%eax)    // argc
+        pushl 4(%eax)   // argv
+        
+        xorl %eax, %eax
+        call main
+        
+    1:
+        movl %eax, %ebx
+        movl $__SYSCALL__exit, %eax
+        int $LUNAIX_SYS_CALL
+
+        ud2 // should not reach
\ No newline at end of file
diff --git a/reference-material/TIS-ELF.pdf b/reference-material/TIS-ELF.pdf
new file mode 100644 (file)
index 0000000..7175400
Binary files /dev/null and b/reference-material/TIS-ELF.pdf differ