From: Minep Date: Wed, 4 Jan 2023 16:12:56 +0000 (+0000) Subject: Merge branch 'interrupt-rework' into prog-loader X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/0cf90cca0c924622f3fee8d2a3fafa8238363dc6?hp=4b61c735d6ab7cb250c9a170b87784746476434f Merge branch 'interrupt-rework' into prog-loader --- diff --git a/README.md b/README.md index da02130..f1cf6b6 100644 --- 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 @@ -216,6 +216,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自有** diff --git a/docs/README_en.md b/docs/README_en.md index be03432..07d17b7 100644 --- a/docs/README_en.md +++ b/docs/README_en.md @@ -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 @@ -209,9 +209,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** diff --git a/lunaix-os/.gitignore b/lunaix-os/.gitignore index b20e749..251d992 100644 --- a/lunaix-os/.gitignore +++ b/lunaix-os/.gitignore @@ -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 diff --git a/lunaix-os/.vscode/c_cpp_properties.json b/lunaix-os/.vscode/c_cpp_properties.json index c68b4c7..0fdf995 100644 --- a/lunaix-os/.vscode/c_cpp_properties.json +++ b/lunaix-os/.vscode/c_cpp_properties.json @@ -3,7 +3,8 @@ { "name": "OS-DEV", "includePath": [ - "${workspaceFolder}/includes" + "${workspaceFolder}/includes", + "${workspaceFolder}/usr/includes" ], "compilerArgs": [ "-ffreestanding", diff --git a/lunaix-os/arch/x86/boot.S b/lunaix-os/arch/x86/boot.S index 9e44437..d1d14ba 100644 --- a/lunaix-os/arch/x86/boot.S +++ b/lunaix-os/arch/x86/boot.S @@ -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 diff --git a/lunaix-os/config/make-cc b/lunaix-os/config/make-cc index a7c2468..7915afe 100644 --- a/lunaix-os/config/make-cc +++ b/lunaix-os/config/make-cc @@ -1,5 +1,6 @@ CC := i686-elf-gcc AS := i686-elf-as +AR := i686-elf-ar ARCH_OPT := -D__ARCH_IA32 -include flags.h diff --git a/lunaix-os/config/make-locations b/lunaix-os/config/make-locations index b60503e..093f7ba 100644 --- a/lunaix-os/config/make-locations +++ b/lunaix-os/config/make-locations @@ -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 diff --git a/lunaix-os/config/make-os b/lunaix-os/config/make-os index e3c26b7..7ea5c01 100644 --- a/lunaix-os/config/make-os +++ b/lunaix-os/config/make-os @@ -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 diff --git a/lunaix-os/includes/hal/rnd.h b/lunaix-os/includes/hal/rnd.h index 8ab544a..1b4a8e3 100644 --- a/lunaix-os/includes/hal/rnd.h +++ b/lunaix-os/includes/hal/rnd.h @@ -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 diff --git a/lunaix-os/includes/lunaix/common.h b/lunaix-os/includes/lunaix/common.h index 1ebf158..daa55af 100644 --- a/lunaix-os/includes/lunaix/common.h +++ b/lunaix-os/includes/lunaix/common.h @@ -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 @@ -26,11 +28,11 @@ #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 diff --git a/lunaix-os/includes/lunaix/ds/llist.h b/lunaix-os/includes/lunaix/ds/llist.h index a4797c3..65ba474 100644 --- a/lunaix-os/includes/lunaix/ds/llist.h +++ b/lunaix-os/includes/lunaix/ds/llist.h @@ -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 index 0000000..f61fa96 --- /dev/null +++ b/lunaix-os/includes/lunaix/elf.h @@ -0,0 +1,77 @@ +#ifndef __LUNAIX_ELF_H +#define __LUNAIX_ELF_H + +#include + +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 index 5ec0eef..0000000 --- a/lunaix-os/includes/lunaix/fctrl.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef __LUNAIX_FCTRL_H -#define __LUNAIX_FCTRL_H - -#include -#include -#include - -__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 */ diff --git a/lunaix-os/includes/lunaix/foptions.h b/lunaix-os/includes/lunaix/foptions.h index 0bb6ac4..625c0b2 100644 --- a/lunaix-os/includes/lunaix/foptions.h +++ b/lunaix-os/includes/lunaix/foptions.h @@ -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 #endif /* __LUNAIX_FOPTIONS_H */ diff --git a/lunaix-os/includes/lunaix/fs.h b/lunaix-os/includes/lunaix/fs.h index 3ec85f5..4b28881 100644 --- a/lunaix-os/includes/lunaix/fs.h +++ b/lunaix-os/includes/lunaix/fs.h @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -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); diff --git a/lunaix-os/includes/lunaix/ioctl.h b/lunaix-os/includes/lunaix/ioctl.h index e074bba..6dcd83c 100644 --- a/lunaix-os/includes/lunaix/ioctl.h +++ b/lunaix-os/includes/lunaix/ioctl.h @@ -1,19 +1,6 @@ #ifndef __LUNAIX_IOCTL_H #define __LUNAIX_IOCTL_H -#include - -#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 #endif /* __LUNAIX_IOCTL_H */ diff --git a/lunaix-os/includes/lunaix/ld.h b/lunaix-os/includes/lunaix/ld.h new file mode 100644 index 0000000..690f95f --- /dev/null +++ b/lunaix-os/includes/lunaix/ld.h @@ -0,0 +1,62 @@ +#ifndef __LUNAIX_LOADER_H +#define __LUNAIX_LOADER_H + +#include +#include +#include + +#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 index 9f2ef9e..0000000 --- a/lunaix-os/includes/lunaix/lunistd.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef __LUNAIX_UNISTD_H -#define __LUNAIX_UNISTD_H - -#include -#include -#include - -__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 index 5b54ffc..0000000 --- a/lunaix-os/includes/lunaix/lxsignal.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __LUNAIX_LXSIGNAL_H -#define __LUNAIX_LXSIGNAL_H - -#include - -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 index 346c479..0000000 --- a/lunaix-os/includes/lunaix/mm/dmm.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef __LUNAIX_DMM_H -#define __LUNAIX_DMM_H -// Dynamic Memory (i.e., heap) Manager - -#include -#include -#include - -#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 index 6b97b3f..0000000 --- a/lunaix-os/includes/lunaix/mm/kalloc.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef __LUNAIX_KALLOC_H -#define __LUNAIX_KALLOC_H - -#include - -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 */ diff --git a/lunaix-os/includes/lunaix/mm/mm.h b/lunaix-os/includes/lunaix/mm/mm.h index 6585916..74868b0 100644 --- a/lunaix-os/includes/lunaix/mm/mm.h +++ b/lunaix-os/includes/lunaix/mm/mm.h @@ -3,54 +3,91 @@ #include #include +#include +#include -typedef struct -{ - void* start; - void* brk; - void* max_addr; - mutex_t lock; -} heap_context_t; +#include /** * @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 index 0000000..ff1e443 --- /dev/null +++ b/lunaix-os/includes/lunaix/mm/mmap.h @@ -0,0 +1,47 @@ +#ifndef __LUNAIX_MMAP_H +#define __LUNAIX_MMAP_H + +#include +#include +#include + +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_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 */ diff --git a/lunaix-os/includes/lunaix/mm/page.h b/lunaix-os/includes/lunaix/mm/page.h index f2c45de..9330274 100644 --- a/lunaix-os/includes/lunaix/mm/page.h +++ b/lunaix-os/includes/lunaix/mm/page.h @@ -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)) @@ -46,10 +50,10 @@ #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]) diff --git a/lunaix-os/includes/lunaix/mm/region.h b/lunaix-os/includes/lunaix/mm/region.h index 9978d72..99e9990 100644 --- a/lunaix-os/includes/lunaix/mm/region.h +++ b/lunaix-os/includes/lunaix/mm/region.h @@ -3,19 +3,25 @@ #include +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 */ diff --git a/lunaix-os/includes/lunaix/mm/vmm.h b/lunaix-os/includes/lunaix/mm/vmm.h index 182058b..9749255 100644 --- a/lunaix-os/includes/lunaix/mm/vmm.h +++ b/lunaix-os/includes/lunaix/mm/vmm.h @@ -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 */ diff --git a/lunaix-os/includes/lunaix/process.h b/lunaix-os/includes/lunaix/process.h index 0b8d302..27137a1 100644 --- a/lunaix-os/includes/lunaix/process.h +++ b/lunaix-os/includes/lunaix/process.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -25,12 +26,6 @@ #define PROC_FINPAUSE 1 -struct proc_mm -{ - heap_context_t u_heap; - struct mm_region regions; -}; - struct proc_sigstate { isr_param proc_regs; diff --git a/lunaix-os/includes/lunaix/signal.h b/lunaix-os/includes/lunaix/signal.h index 43cfb99..c815c4f 100644 --- a/lunaix-os/includes/lunaix/signal.h +++ b/lunaix-os/includes/lunaix/signal.h @@ -1,21 +1,21 @@ #ifndef __LUNAIX_SIGNAL_H #define __LUNAIX_SIGNAL_H -#include +#include #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)) @@ -24,25 +24,8 @@ #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 */ diff --git a/lunaix-os/includes/lunaix/spike.h b/lunaix-os/includes/lunaix/spike.h index 298593d..6cece75 100644 --- a/lunaix-os/includes/lunaix/spike.h +++ b/lunaix-os/includes/lunaix/spike.h @@ -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) @@ -27,40 +27,40 @@ * */ #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)); diff --git a/lunaix-os/includes/lunaix/status.h b/lunaix-os/includes/lunaix/status.h index f9b947d..31d2327 100644 --- a/lunaix-os/includes/lunaix/status.h +++ b/lunaix-os/includes/lunaix/status.h @@ -30,5 +30,7 @@ #define ENOTDEV -24 #define EOVERFLOW -25 #define ENOTBLK -26 +#define ENOEXEC -27 +#define E2BIG -28 #endif /* __LUNAIX_CODE_H */ diff --git a/lunaix-os/includes/lunaix/syscall.h b/lunaix-os/includes/lunaix/syscall.h index 82fc4b9..a512bd7 100644 --- a/lunaix-os/includes/lunaix/syscall.h +++ b/lunaix-os/includes/lunaix/syscall.h @@ -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 @@ -60,6 +60,11 @@ #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 index 0000000..fcc7dc3 --- /dev/null +++ b/lunaix-os/includes/lunaix/syscall_utils.h @@ -0,0 +1,10 @@ +#ifndef __LUNAIX_SYSCALL_UTILS_H +#define __LUNAIX_SYSCALL_UTILS_H + +#include +#include + +#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 */ diff --git a/lunaix-os/includes/lunaix/types.h b/lunaix-os/includes/lunaix/types.h index f99620f..a98ae97 100644 --- a/lunaix-os/includes/lunaix/types.h +++ b/lunaix-os/includes/lunaix/types.h @@ -2,23 +2,8 @@ #define __LUNAIX_TYPES_H #include -#include #include - -#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 #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 */ diff --git a/lunaix-os/kernel/asm/x86/pfault.c b/lunaix-os/kernel/asm/x86/pfault.c index 2e47503..2b0a8f1 100644 --- a/lunaix-os/kernel/asm/x86/pfault.c +++ b/lunaix-os/kernel/asm/x86/pfault.c @@ -1,14 +1,16 @@ #include #include -#include #include #include #include #include #include +#include #include #include +#include + static void kprintf(const char* fmt, ...) { @@ -51,42 +53,79 @@ 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; + 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; + u32_t offset = + ((ptr - hit_region->start) & (PG_SIZE - 1)) + hit_region->foff; + uintptr_t pa = pmm_alloc_page(__current->pid, 0); + + if (!pa) { + goto oom; + } - // a writable page, not present, not cached, pte attr is not null - // -> a new page need to be alloc - if ((hit_region->attr & REGION_WRITE) && (*pte & 0xfff) && !loc) { cpu_invplg(pte); - uintptr_t pa = pmm_alloc_page(__current->pid, 0); - *pte = *pte | pa | PG_PRESENT; + *pte = (*pte & 0xFFF) | pa | PG_PRESENT; + + ptr = PG_ALIGN(ptr); + 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, diff --git a/lunaix-os/kernel/asm/x86/syscall.S b/lunaix-os/kernel/asm/x86/syscall.S index ff30f44..62e0721 100644 --- a/lunaix-os/kernel/asm/x86/syscall.S +++ b/lunaix-os/kernel/asm/x86/syscall.S @@ -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 @@ -85,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 */ @@ -96,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 index e1ef7a2..0000000 --- a/lunaix-os/kernel/demos/dir_read.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include - -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 index 47e0081..0000000 --- a/lunaix-os/kernel/demos/input_test.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#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 index cba8962..0000000 --- a/lunaix-os/kernel/demos/iotest.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include -#include -#include -#include - -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 index 3878a18..0000000 --- a/lunaix-os/kernel/demos/signal_demo.c +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include -#include -#include -#include -#include - -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 index acebe21..0000000 --- a/lunaix-os/kernel/demos/simple_sh.c +++ /dev/null @@ -1,184 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -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 or to scroll.\n\n"); - if (!fork()) { - sh_loop(); - _exit(0); - } - wait(NULL); -} \ No newline at end of file diff --git a/lunaix-os/kernel/device/devfs.c b/lunaix-os/kernel/device/devfs.c index c265c4b..867f93d 100644 --- a/lunaix-os/kernel/device/devfs.c +++ b/lunaix-os/kernel/device/devfs.c @@ -1,9 +1,10 @@ #include -#include #include #include #include +#include + extern struct v_inode_ops devfs_inode_ops; extern struct v_file_ops devfs_file_ops; diff --git a/lunaix-os/kernel/device/device.c b/lunaix-os/kernel/device/device.c index b784fdb..3647f10 100644 --- a/lunaix-os/kernel/device/device.c +++ b/lunaix-os/kernel/device/device.c @@ -6,6 +6,7 @@ #include #include #include +#include static DEFINE_LLIST(root_list); diff --git a/lunaix-os/kernel/fs/iso9660/directory.c b/lunaix-os/kernel/fs/iso9660/directory.c index c3150dc..1d35978 100644 --- a/lunaix-os/kernel/fs/iso9660/directory.c +++ b/lunaix-os/kernel/fs/iso9660/directory.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -7,6 +6,8 @@ #include +#include + extern struct cake_pile* drec_cache_pile; void diff --git a/lunaix-os/kernel/fs/mount.c b/lunaix-os/kernel/fs/mount.c index 7db9513..12e1d4b 100644 --- a/lunaix-os/kernel/fs/mount.c +++ b/lunaix-os/kernel/fs/mount.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include diff --git a/lunaix-os/kernel/fs/path_walk.c b/lunaix-os/kernel/fs/path_walk.c index a0331e7..cd0ac01 100644 --- a/lunaix-os/kernel/fs/path_walk.c +++ b/lunaix-os/kernel/fs/path_walk.c @@ -1,5 +1,6 @@ #include #include +#include #include #include diff --git a/lunaix-os/kernel/fs/twimap.c b/lunaix-os/kernel/fs/twimap.c index 009cdf3..2371eb8 100644 --- a/lunaix-os/kernel/fs/twimap.c +++ b/lunaix-os/kernel/fs/twimap.c @@ -6,7 +6,7 @@ #include #include -#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 diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index 9680f2e..8a4a8a1 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -44,7 +44,6 @@ */ #include -#include #include #include #include @@ -53,9 +52,12 @@ #include #include #include +#include #include +#include + 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) { diff --git a/lunaix-os/kernel/fs/xattr.c b/lunaix-os/kernel/fs/xattr.c index 94f85b7..6fdb300 100644 --- a/lunaix-os/kernel/fs/xattr.c +++ b/lunaix-os/kernel/fs/xattr.c @@ -1,7 +1,11 @@ #include #include #include +#include #include +#include + +#define DO_STATUS(errno) SYSCALL_ESTATUS(__current->k_status = errno) struct v_xattr_entry* xattr_new(struct hstr* name) diff --git a/lunaix-os/kernel/k_init.c b/lunaix-os/kernel/k_init.c index 25af27e..a2edf1a 100644 --- a/lunaix-os/kernel/k_init.c +++ b/lunaix-os/kernel/k_init.c @@ -144,7 +144,7 @@ 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, @@ -201,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 index 0000000..241ddf9 --- /dev/null +++ b/lunaix-os/kernel/loader/elf.c @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +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, ¶m); + + 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 index 0000000..cf0a422 --- /dev/null +++ b/lunaix-os/kernel/loader/exec.c @@ -0,0 +1,195 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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**)®ion->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 | MAP_FIXED, + .type = REGION_TYPE_HEAP, + .proct = PROT_READ | PROT_WRITE, + .mlen = DEFAULT_HEAP_PAGES * 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 = ¶m->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"); + } + } + + isr_param* intr_ctx = &__current->intr_ctx; + intr_ctx->esp = ldparam.info.stack_top; + intr_ctx->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 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 index 0000000..413e0f8 --- /dev/null +++ b/lunaix-os/kernel/loader/ld.c @@ -0,0 +1,7 @@ +#include + +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 index f53405a..0000000 --- a/lunaix-os/kernel/lxinit.c +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 diff --git a/lunaix-os/kernel/mm/cow.c b/lunaix-os/kernel/mm/cow.c index 81e0648..2350188 100644 --- a/lunaix-os/kernel/mm/cow.c +++ b/lunaix-os/kernel/mm/cow.c @@ -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 diff --git a/lunaix-os/kernel/mm/dmm.c b/lunaix-os/kernel/mm/dmm.c index edc28ef..188bb06 100644 --- a/lunaix-os/kernel/mm/dmm.c +++ b/lunaix-os/kernel/mm/dmm.c @@ -1,22 +1,3 @@ -/** - * @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 #include #include #include @@ -26,74 +7,12 @@ __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; + // TODO mem_remap to expand heap region + return 0; } __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) -{ - 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; -} - -int -lxbrk(heap_context_t* heap, void* addr, int user) -{ - return -(lxsbrk(heap, addr - heap->brk, user) == (void*)-1); -} - -void* -lxsbrk(heap_context_t* heap, size_t size, int user) -{ - 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); - } - } - - heap->brk += size; - return current_brk; + // TODO mem_remap to expand heap region + return 0; } \ 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 index 0ce97e9..0000000 --- a/lunaix-os/kernel/mm/kalloc.c +++ /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 -// #include -// #include - -// #include -// #include - -// #include - -// #include - -// 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 index 0000000..da1a0b6 --- /dev/null +++ b/lunaix-os/kernel/mm/mmap.c @@ -0,0 +1,319 @@ +#include +#include +#include +#include +#include + +#include +#include + +// 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, size_t len) +{ + ptr_t end = start + end - 1; + 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_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 = ¶m->pvms->regions; + + if ((param->flags & MAP_FIXED_NOREPLACE)) { + if (mem_has_overlap(vm_regions, found_loc, param->mlen)) { + 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 ((int)avail_space > 0 && avail_space > param->mlen) { + goto found; + } + found_loc = pos->end + PG_SIZE; + } + + last_end = pos->end + PG_SIZE; + } + + 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(®ion->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, ®ion->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, ¶m); + +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 diff --git a/lunaix-os/kernel/mm/mmio.c b/lunaix-os/kernel/mm/mmio.c index 99e8fb8..e9843d6 100644 --- a/lunaix-os/kernel/mm/mmio.c +++ b/lunaix-os/kernel/mm/mmio.c @@ -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 diff --git a/lunaix-os/kernel/mm/region.c b/lunaix-os/kernel/mm/region.c index bd3b26e..f883edb 100644 --- a/lunaix-os/kernel/mm/region.c +++ b/lunaix-os/kernel/mm/region.c @@ -1,57 +1,124 @@ +#include #include #include +#include -void -region_add(struct mm_region* regions, - unsigned long start, - unsigned long end, - unsigned int attr) +#include + +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(®ions->head, ®ion->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)&pos->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, ®ions->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, ®ions->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; } } diff --git a/lunaix-os/kernel/mm/vmap.c b/lunaix-os/kernel/mm/vmap.c index 7507b1a..285debc 100644 --- a/lunaix-os/kernel/mm/vmap.c +++ b/lunaix-os/kernel/mm/vmap.c @@ -3,7 +3,7 @@ #include #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; diff --git a/lunaix-os/kernel/mm/vmm.c b/lunaix-os/kernel/mm/vmm.c index 445071c..8f67bd2 100644 --- a/lunaix-os/kernel/mm/vmm.c +++ b/lunaix-os/kernel/mm/vmm.c @@ -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) { diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c index 19f04dc..abd0ac0 100644 --- a/lunaix-os/kernel/proc0.c +++ b/lunaix-os/kernel/proc0.c @@ -1,11 +1,9 @@ #include #include -#include #include #include #include -#include -#include +#include #include #include #include @@ -31,13 +29,8 @@ #include -#include - 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(¶m, __current, VMS_SELF); - while (1) { - yield(); + if ((errno = exec_load_byname(¶m, 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); } diff --git a/lunaix-os/kernel/process/process.c b/lunaix-os/kernel/process/process.c index 74c9380..23ff6a4 100644 --- a/lunaix-os/kernel/process/process.c +++ b/lunaix-os/kernel/process/process.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -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**)®ion->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, ¶m))) { + 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 diff --git a/lunaix-os/kernel/process/sched.c b/lunaix-os/kernel/process/sched.c index 4ed9d34..ade13b3 100644 --- a/lunaix-os/kernel/process/sched.c +++ b/lunaix-os/kernel/process/sched.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include #include @@ -18,6 +18,8 @@ #include #include +#include + volatile struct proc_info* __current; static struct proc_info dummy_proc; @@ -324,13 +326,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); @@ -400,17 +403,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); diff --git a/lunaix-os/kernel/process/signal.c b/lunaix-os/kernel/process/signal.c index 9a9a349..0f43b1f 100644 --- a/lunaix-os/kernel/process/signal.c +++ b/lunaix-os/kernel/process/signal.c @@ -1,6 +1,3 @@ -#include -#include -#include #include #include #include @@ -8,6 +5,8 @@ #include #include +#include + extern struct scheduler sched_ctx; /* kernel/sched.c */ void __USER__ diff --git a/lunaix-os/kernel/process/task_attr.c b/lunaix-os/kernel/process/task_attr.c index 4610acf..7c954b3 100644 --- a/lunaix-os/kernel/process/task_attr.c +++ b/lunaix-os/kernel/process/task_attr.c @@ -1,4 +1,5 @@ #include +#include void __read_pending_sig(struct twimap* map) diff --git a/lunaix-os/kernel/process/taskfs.c b/lunaix-os/kernel/process/taskfs.c index 7534703..ca7f61e 100644 --- a/lunaix-os/kernel/process/taskfs.c +++ b/lunaix-os/kernel/process/taskfs.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -8,6 +7,8 @@ #include #include +#include + #define COUNTER_MASK ((1 << 16) - 1) static struct hbucket* attr_export_table; diff --git a/lunaix-os/kernel/tty/lxconsole.c b/lunaix-os/kernel/tty/lxconsole.c index 21802be..adf577a 100644 --- a/lunaix-os/kernel/tty/lxconsole.c +++ b/lunaix-os/kernel/tty/lxconsole.c @@ -8,11 +8,10 @@ #include #include #include +#include #include #include -#include - static struct console lx_console; int diff --git a/lunaix-os/libs/klibc/string/strlen.c b/lunaix-os/libs/klibc/string/strlen.c index 30ceb65..c982f7a 100644 --- a/lunaix-os/libs/klibc/string/strlen.c +++ b/lunaix-os/libs/klibc/string/strlen.c @@ -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 index 18e2387..0000000 --- a/lunaix-os/libs/ulibc/printf.c +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include -#include - -// 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 diff --git a/lunaix-os/makefile b/lunaix-os/makefile index ede34f4..c1c800c 100644 --- a/lunaix-os/makefile +++ b/lunaix-os/makefile @@ -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 index 0000000..8411140 --- /dev/null +++ b/lunaix-os/makefile.ker @@ -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 index 0000000..1c09c78 --- /dev/null +++ b/lunaix-os/makefile.prog @@ -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) $(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 index 0000000..d71ad71 --- /dev/null +++ b/lunaix-os/makefile.usr @@ -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) -c $< -o $@ $(CFLAGS) + +$(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 index 0000000..c0c3fdd --- /dev/null +++ b/lunaix-os/uprog/init.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +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", 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 index 0000000..605723c --- /dev/null +++ b/lunaix-os/uprog/ls.c @@ -0,0 +1,30 @@ +#include +#include +#include + +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); + } + } + + 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 index 0000000..10d9213 --- /dev/null +++ b/lunaix-os/usr/api/dirent.c @@ -0,0 +1,4 @@ +#include +#include + +__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 index 0000000..ac0d004 --- /dev/null +++ b/lunaix-os/usr/api/errno.c @@ -0,0 +1,4 @@ +#include +#include + +__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 index 0000000..92e2fa3 --- /dev/null +++ b/lunaix-os/usr/api/fcntl.c @@ -0,0 +1,4 @@ +#include +#include + +__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 index 0000000..bb2126a --- /dev/null +++ b/lunaix-os/usr/api/ioctl.c @@ -0,0 +1,4 @@ +#include +#include + +__LXSYSCALL2_VARG(int, ioctl, int, fd, int, req); \ No newline at end of file diff --git a/lunaix-os/includes/lunaix/lunaix.h b/lunaix-os/usr/api/lunaix.c similarity index 62% rename from lunaix-os/includes/lunaix/lunaix.h rename to lunaix-os/usr/api/lunaix.c index adbde1d..59fe79a 100644 --- a/lunaix-os/includes/lunaix/lunaix.h +++ b/lunaix-os/usr/api/lunaix.c @@ -1,8 +1,5 @@ -#ifndef __LUNAIX_LUNAIX_H -#define __LUNAIX_LUNAIX_H - #include -#include +#include __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 index 0000000..e211cad --- /dev/null +++ b/lunaix-os/usr/api/mann.c @@ -0,0 +1,12 @@ +#include +#include + +__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 index 0000000..854c96b --- /dev/null +++ b/lunaix-os/usr/api/mount.c @@ -0,0 +1,15 @@ +#include +#include + +__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 index 0000000..191e8d8 --- /dev/null +++ b/lunaix-os/usr/api/signal.c @@ -0,0 +1,16 @@ +#include +#include + +__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 index 0000000..e8a4a0a --- /dev/null +++ b/lunaix-os/usr/api/unistd.c @@ -0,0 +1,126 @@ +#include +#include + +__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, 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 index 0000000..30ed892 --- /dev/null +++ b/lunaix-os/usr/includes/dirent.h @@ -0,0 +1,24 @@ +#ifndef __LUNAIX_SYS_DIRENT_H +#define __LUNAIX_SYS_DIRENT_H + +#include + +typedef struct +{ + int dirfd; + int prev_res; +} DIR; + +struct dirent +{ + unsigned char d_type; + char d_name[256]; +}; + +DIR* +opendir(const char* dir); + +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 index 0000000..5b9b51b --- /dev/null +++ b/lunaix-os/usr/includes/errno.h @@ -0,0 +1,9 @@ +#ifndef __LUNAIX_SYS_ERRNO_H +#define __LUNAIX_SYS_ERRNO_H + +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 index 0000000..0ce31d8 --- /dev/null +++ b/lunaix-os/usr/includes/fcntl.h @@ -0,0 +1,10 @@ +#ifndef __LUNAIX_SYS_FCNTL_H +#define __LUNAIX_SYS_FCNTL_H + +#include +#include + +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 index 0000000..c6cbe4f --- /dev/null +++ b/lunaix-os/usr/includes/fcntl_defs.h @@ -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 index 0000000..56da91e --- /dev/null +++ b/lunaix-os/usr/includes/signal.h @@ -0,0 +1,19 @@ +#ifndef __LUNAIX_SYS_SIGNAL_H +#define __LUNAIX_SYS_SIGNAL_H + +#include +#include + +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 index 0000000..ac102ab --- /dev/null +++ b/lunaix-os/usr/includes/signal_defs.h @@ -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 */ diff --git a/lunaix-os/includes/ulibc/stdio.h b/lunaix-os/usr/includes/stdio.h similarity index 74% rename from lunaix-os/includes/ulibc/stdio.h rename to lunaix-os/usr/includes/stdio.h index e9496a8..f898bed 100644 --- a/lunaix-os/includes/ulibc/stdio.h +++ b/lunaix-os/usr/includes/stdio.h @@ -7,4 +7,7 @@ void printf(const char* fmt, ...); +const char* +strchr(const char* str, int character); + #endif /* __LUNAIX_USTDIO_H */ diff --git a/lunaix-os/usr/includes/stdlib.h b/lunaix-os/usr/includes/stdlib.h new file mode 100644 index 0000000..0e38fb5 --- /dev/null +++ b/lunaix-os/usr/includes/stdlib.h @@ -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 index 0000000..a309924 --- /dev/null +++ b/lunaix-os/usr/includes/string.h @@ -0,0 +1,15 @@ +#ifndef __LUNAIX_STRING_H +#define __LUNAIX_STRING_H + +#include + +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); + +#endif /* __LUNAIX_STRING_H */ diff --git a/lunaix-os/usr/includes/sys/dirent_defs.h b/lunaix-os/usr/includes/sys/dirent_defs.h new file mode 100644 index 0000000..7792355 --- /dev/null +++ b/lunaix-os/usr/includes/sys/dirent_defs.h @@ -0,0 +1,19 @@ +#ifndef __LUNAIX_SYS_DIRENT_DEFS_H +#define __LUNAIX_SYS_DIRENT_DEFS_H + +#define DIRENT_NAME_MAX_LEN 256 + +#define DT_FILE 0x0 +#define DT_DIR 0x1 +#define DT_SYMLINK 0x2 +#define DT_PIPE 0x2 + +struct lx_dirent +{ + unsigned int d_type; + unsigned int d_offset; + unsigned int d_nlen; + char d_name[DIRENT_NAME_MAX_LEN]; +}; + +#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 index 0000000..827cd44 --- /dev/null +++ b/lunaix-os/usr/includes/sys/ioctl.h @@ -0,0 +1,7 @@ +#ifndef __LUNAIX_SYS_IOCTL_H +#define __LUNAIX_SYS_IOCTL_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 index 0000000..7be48e7 --- /dev/null +++ b/lunaix-os/usr/includes/sys/ioctl_defs.h @@ -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 index 0000000..febcb59 --- /dev/null +++ b/lunaix-os/usr/includes/sys/lunaix.h @@ -0,0 +1,21 @@ +#ifndef __LUNAIX_SYS_LUNAIX_H +#define __LUNAIX_SYS_LUNAIX_H + +#include + +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 index 0000000..e616180 --- /dev/null +++ b/lunaix-os/usr/includes/sys/lxdirent.h @@ -0,0 +1,9 @@ +#ifndef __LUNAIX_SYS_LXDIRENT_H +#define __LUNAIX_SYS_LXDIRENT_H + +#include + +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 index 0000000..0e424d4 --- /dev/null +++ b/lunaix-os/usr/includes/sys/mann.h @@ -0,0 +1,13 @@ +#ifndef __LUNAIX_SYS_MANN_H +#define __LUNAIX_SYS_MANN_H + +#include +#include + +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 index 0000000..479c60b --- /dev/null +++ b/lunaix-os/usr/includes/sys/mann_flags.h @@ -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 index 0000000..5d12df8 --- /dev/null +++ b/lunaix-os/usr/includes/sys/mount.h @@ -0,0 +1,17 @@ +#ifndef __LUNAIX_SYS_MOUNT_H +#define __LUNAIX_SYS_MOUNT_H + +#include + +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 index 0000000..8b30318 --- /dev/null +++ b/lunaix-os/usr/includes/sys/types.h @@ -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 index 0000000..90740a0 --- /dev/null +++ b/lunaix-os/usr/includes/unistd.h @@ -0,0 +1,114 @@ +#ifndef __LUNAIX_SYS_UNISTD_H +#define __LUNAIX_SYS_UNISTD_H + +#include + +pid_t +fork(); + +pid_t +getpid(); + +pid_t +getppid(); + +pid_t +getpgid(); + +pid_t +setpgid(pid_t pid, pid_t pgid); + +int +sbrk(void* addr); + +void* +brk(size_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 index 0000000..d60fed3 --- /dev/null +++ b/lunaix-os/usr/libc/_mystdio.h @@ -0,0 +1,10 @@ +#ifndef __LUNAIX__MYSTDIO_H +#define __LUNAIX__MYSTDIO_H + +#include +#include + +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 index 0000000..1e56305 --- /dev/null +++ b/lunaix-os/usr/libc/_vprintf.c @@ -0,0 +1,198 @@ +#include "_mystdio.h" +#include +#include +#include + +#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 index 0000000..d60599f --- /dev/null +++ b/lunaix-os/usr/libc/itoa.c @@ -0,0 +1,46 @@ +#include +#include + +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 index 0000000..2557117 --- /dev/null +++ b/lunaix-os/usr/libc/printf.c @@ -0,0 +1,15 @@ +#include "_mystdio.h" +#include +#include + +void +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 index 0000000..9d2b23e --- /dev/null +++ b/lunaix-os/usr/libc/readdir.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include + +DIR* +opendir(const char* dir) +{ + static DIR _dir; + int fd = open(dir, O_RDONLY); + if (fd < 0) { + return NULL; + } + + _dir = (DIR){ .dirfd = fd, .prev_res = 0 }; + return &_dir; +} + +struct dirent* +readdir(DIR* dir) +{ + static struct dirent _dirent; + if (!dir) { + return NULL; + } + + struct lx_dirent _lxd; + int more = sys_readdir(dir->dirfd, &_lxd); + + _dirent.d_type = _lxd.d_type; + strncpy(_dirent.d_name, _lxd.d_name, 256); + + if (more || dir->prev_res) { + dir->prev_res = more; + return &_dirent; + } + + if (!dir->prev_res) { + 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 index 0000000..2e34dc7 --- /dev/null +++ b/lunaix-os/usr/libc/string.c @@ -0,0 +1,44 @@ +#include + +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; +} \ No newline at end of file diff --git a/lunaix-os/usr/link-usr.ld b/lunaix-os/usr/link-usr.ld new file mode 100644 index 0000000..49fb4c9 --- /dev/null +++ b/lunaix-os/usr/link-usr.ld @@ -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 index 0000000..ab383c2 --- /dev/null +++ b/lunaix-os/usr/uinit.c @@ -0,0 +1,10 @@ +#define __USR_WRAPPER__ +#include + +int +usr_pre_init(struct usr_exec_param* param) +{ + // TODO some inits before executing user program + + 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 index 0000000..1f07722 --- /dev/null +++ b/lunaix-os/usr/uwrap.S @@ -0,0 +1,23 @@ +#define __ASM__ +#include + +.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