732 Commits 32b3c0c913 ... ca2ad4c427

Author SHA1 Message Date
  greatbridf 32b3c0c913 initial commit 2 months ago
  greatbridf ca2ad4c427 Merge remote-tracking branch 'github/mm' into shiai-master 3 months ago
  shao ab64258c5e feat(pcp): improve per-cpus pages support 3 months ago
  greatbridf a3f7ad83a1 Merge remote-tracking branch 'github/mm' into shiai-master 3 months ago
  shao 4e7bed8818 feat(pcp): add per-cpu pages support 3 months ago
  greatbridf 6f90bfbd38 Merge branch 'fix' into shiai-master 3 months ago
  greatbridf f10251a691 feat: add sys_chmod, remove debug prints 3 months ago
  greatbridf ac2cb64f02 feat: blank impl for getrusage and madvise 3 months ago
  greatbridf e9ec2880b8 feat: temp. impl for sys_times, update sys_statx 3 months ago
  greatbridf ee488bcb18 feat(syscall): temporary impl of getrlimit, vfork and sysinfo 3 months ago
  greatbridf eaa6cda7db style: remove unused warnings 3 months ago
  greatbridf f5b4da3309 change(mm_list): separate mm_list from process on elf loading 3 months ago
  greatbridf 555b383d90 feat(syscall): add sys_pipe2 3 months ago
  greatbridf a66b415fd7 feat(syscall): add sys_prlimit64 3 months ago
  greatbridf 780114025c clean: remove some redundant types 3 months ago
  greatbridf d5421e4f17 feat(fat32): support of long file names 3 months ago
  greatbridf c561df82d2 chore: add build-img script for making images 3 months ago
  greatbridf 63a2aca6fb feat: add temporary impl for prlimit64 3 months ago
  greatbridf 255b3636d7 fix(getcwd): do not copy to user directly 3 months ago
  greatbridf 321fbcac00 fix(ahci): minus 1 from PRDTEntry.len 3 months ago
  greatbridf 46beec348b style(block): change idents 3 months ago
  greatbridf d400fb8fdc fix(setpgid): move the process to new pgroup 3 months ago
  greatbridf 17e60b5661 doc: update origin 3 months ago
  greatbridf 113ce48d38 doc: rename kernel name 3 months ago
  shao 833e7f9c75 docs: add doc about memory management and multi-arch support 3 months ago
  greatbridf 8a40ff8f6f doc: add more testcases 3 months ago
  greatbridf 4c21fc6989 doc: update device_driver.md 3 months ago
  greatbridf 3c76def031 style(block): change idents 3 months ago
  greatbridf f7441a1470 doc: add device_driver.md 3 months ago
  greatbridf e8b3f94f91 doc: add doc for filesystem 3 months ago
  greatbridf 92cfd5ccee doc: add problems and TODO part 3 months ago
  greatbridf c2a8b82a50 doc: add task.md 3 months ago
  greatbridf 42eb4fbb73 chore: remove kvm accel for dists such as ubuntu 3 months ago
  greatbridf aabe4b75b7 fix(setpgid): move the process to new pgroup 3 months ago
  greatbridf e2c3fbd379 chore: update README.md, add docs 3 months ago
  greatbridf afc4956f30 chore: rename project name 3 months ago
  greatbridf bad164e483 remove some stale C++ code. extract more platform-dependent parts 3 months ago
  greatbridf a7bcb9ce15 Merge branch 'buddy_refactor' 4 months ago
  greatbridf 29bc525d10 Merge branch 'process-rewrite' 4 months ago
  greatbridf 8f28dfb772 feat: impl Write for dyn Buffer 4 months ago
  shao 5b3f887a65 refactor: refactor page alloc in rust 4 months ago
  greatbridf 12dacd3fad fix(c++build): disable mmx and sse 4 months ago
  greatbridf 66958893e5 rewrite: move Process, ProcessGroup, Session out of thread.rs 4 months ago
  greatbridf e037208da1 fix(exit): skip checking whether the children have an init parent 4 months ago
  greatbridf b8a282ecb6 fix(context): new version rustc says we should use naked_asm 4 months ago
  greatbridf 980f18bf51 fix: add smp boot option to qemu run 4 months ago
  greatbridf 4602c4d71c Merge branch 'fix' 4 months ago
  greatbridf e6365b41be fix(page_fault): potential skipped free in page fault handler 4 months ago
  greatbridf d161134335 chore: add tmux debug script in Makefile 4 months ago
  greatbridf 13f7fff46d Merge branch 'multiarch' 4 months ago
  greatbridf 07cdd43e60 Merge branch 'smp' 4 months ago
  greatbridf 68afbfce01 feat: set ap cpus online in scheduler! 4 months ago
  greatbridf 742d1ef505 fix(buddy): hold global buddy lock for EVERYTHING 4 months ago
  shao f048367b02 refactor: refactor better abstraction for context switch 4 months ago
  greatbridf 4d1ab3b719 feat: initialize ap cpus to a usable state 4 months ago
  greatbridf 44231d9217 fix(idle_task): disable irq when we use scheduler 4 months ago
  greatbridf 9aae18ed2e fix: irq handlers should be unlocked when being handled 4 months ago
  greatbridf fab09e80c7 feat: bootstrap cpus, assign a stack to each of them 4 months ago
  greatbridf 256aa9d443 feat: make TSS and GDT per cpu 4 months ago
  greatbridf faa54c5e0a fix(UserString): mark %al as clobbered 4 months ago
  greatbridf 29a3461810 feat: make CURRENT and IDLE_TASK per cpu 4 months ago
  greatbridf cbceec6084 feat: add percpu variables 4 months ago
  greatbridf bfcf57b9a0 prepare the memory layout for smp cpu init 4 months ago
  greatbridf b016c589f6 rewrite(signal_list): provide better encapsulation 4 months ago
  greatbridf e021390c95 fix(wait): generate corrent wstatus to handle stop signals 4 months ago
  greatbridf 0192745ef2 fix(scheduler): permit iwake called on Running threads 4 months ago
  greatbridf d873af30d8 fix(UserString): register should be marked inout 4 months ago
  greatbridf 1977d04c21 fix(tty): some abnormal behavior in tty job control ops. 4 months ago
  greatbridf 6612cf8b21 fix: deadlocks that happens on task switches 4 months ago
  shao 6ecf5b4237 fix build bug in gblibc 4 months ago
  greatbridf 0295d3e954 fix: UserBuffer move CheckedUserPointer on fill called 4 months ago
  greatbridf c6d416043e fix terminal subsystem, print syscall debug info conditionally 4 months ago
  greatbridf 2c72c9ba77 fixes and updates, basically on mem and scheduler 4 months ago
  greatbridf fca6223938 move interrupt and vm to rust 4 months ago
  greatbridf a8adfd1dfc chore: add READM.md 5 months ago
  greatbridf b9756e3233 rewrite: some of the process part and syscalls 5 months ago
  greatbridf 7930b71762 feat: rewrite filearray with rust 5 months ago
  greatbridf e35fd75836 fix(pipe_read): reads don't need to be atomic 5 months ago
  greatbridf ae698248ee [partial] feat: add sync stuffs 5 months ago
  greatbridf f4128f04a0 Merge branch 'vfs-refactor' 6 months ago
  greatbridf b67ed10025 feat: load huge kernel, new memory layout 6 months ago
  greatbridf b94122a5fb fix(buddy): create_zone with args like 12, 15 6 months ago
  greatbridf 1d5525f5c1 rewrite Dentry module with rust 6 months ago
  greatbridf ea629feec9 rewrite(ahci): rewrite ahci module with rust 6 months ago
  greatbridf b43277c46c refactor: rewrite fs submodule with rust 6 months ago
  greatbridf c3b20946d2 rewrite(e1000e): rewrite e1000e driver with rust 7 months ago
  greatbridf 1f7bed61dd feat: rust support 7 months ago
  greatbridf b92bb0270f change(defs): i* should not be explicitly signed 7 months ago
  greatbridf d12f42764e fix(readdir): the third argument is unsupported 7 months ago
  greatbridf f952057453 change(vector): emplace_back should return a ref 7 months ago
  greatbridf 3d37d43eb5 fix(types::list): erroneous get and remove 7 months ago
  greatbridf d785937269 chore: change debugging settings 7 months ago
  greatbridf 58eb82d5b3 feat(driver): add e1000e driver 7 months ago
  greatbridf d75905e322 change: improve module arch. and fix some bugs 7 months ago
  greatbridf eedcf95ee9 chore(pretty-print): rewrite pretty printers 7 months ago
  greatbridf 538244e339 style: reformat all codes with new format 7 months ago
  greatbridf eec5d5c283 chore: update .gitignore and CMakeLists.txt 7 months ago
  greatbridf f88b4da3fd change(gblibstdc++): use EBO for all stl classes 8 months ago
  greatbridf e6c6d8f1b7 feat: use RAII to manage dentry pointers 8 months ago
  greatbridf 4e79226a6f chore(debug): add dwarf data for ISR 8 months ago
  greatbridf cafeec4a85 refactor: rewrite all dentry part of vfs 8 months ago
  greatbridf 4851662c29 change(vfs): move class vfs out 9 months ago
  greatbridf 4ec085b55c fix(syscall): make getcwd return buf length filled 9 months ago
  greatbridf 4eb3d8228e change(process): remove k_new_threadd 9 months ago
  greatbridf 6be43506e5 change(filearray): add filearray class 9 months ago
  greatbridf 80d0ee4dd2 fix(shared_ptr): operator= on derived class, swap 9 months ago
  greatbridf 23ec09cb64 fix: fifo, paging, tkill, preemptive kernel 9 months ago
  greatbridf 0b5c54c2cf change(sched): move idle task out of ready queue 9 months ago
  greatbridf e526dc0708 Merge branch 'long-mode' into vfs-refactor 9 months ago
  greatbridf 6c5408c96f add schedstat, improve schedule algorithm 9 months ago
  greatbridf 4f18b18088 fix: tls_desc32 may not be correctly copied 9 months ago
  greatbridf dd6a779790 fix hash_map 9 months ago
  greatbridf 753cb3d885 fix: getdents64 struct size 9 months ago
  greatbridf 62e0eaff42 fix temporary user_space_program/init 9 months ago
  greatbridf b6b04e657d works 9 months ago
  greatbridf 0d8f6f019b fix: fat32 filesystem 9 months ago
  greatbridf 73ab9a9320 syscall 9 months ago
  greatbridf dfcbe573b1 fix bugs, add serial module 9 months ago
  greatbridf 6734968dc6 fix 9 months ago
  greatbridf cb243f2a67 align rsp to 16 bytes 9 months ago
  greatbridf 15dabfee26 fix some problems 9 months ago
  greatbridf aab3befaf5 use layout regs when debugging 9 months ago
  greatbridf ac083a7cf0 brand new mem subsystem 9 months ago
  greatbridf 4572e5ce46 remove keyboard drive, make serial module 10 months ago
  greatbridf 6f29d1acca allocator 10 months ago
  greatbridf a092424c56 slab and buddy allocator 10 months ago
  greatbridf 04c392fdc7 create page table, enter long mode 10 months ago
  greatbridf 6c586cfd98 feat(timer & syscall): add readv, change tick rate 10 months ago
  greatbridf 6674d1b5bb change(mbr): read 64k more 10 months ago
  greatbridf c4ce6874f5 fix(blk_allocator): update p_start properly 10 months ago
  greatbridf 2a7dde2f9e feat(procfs): impl procfs and mount() syscall 10 months ago
  greatbridf b4bb1feadf rewrite(string): new string class 11 months ago
  greatbridf 635ea3e5ee feat(llseek): llseek return file->seek 11 months ago
  greatbridf 2cb5366997 fix(vector): resize should check m_capacity 11 months ago
  greatbridf bd0da59162 fix(lock): add lock_irq to avoid deadlocks 11 months ago
  greatbridf 970c203132 change(fat32): use map to store cluster buffer 11 months ago
  greatbridf b12cf751c9 feat(syscall): impl MONOTONIC clock for gettime 11 months ago
  greatbridf 87949fe12a feat(syscall): impl. symlink and readlink 11 months ago
  greatbridf 370949b19a refactor(ahci, fat): make achi read 3kb a time 11 months ago
  greatbridf 95ee316d1b fix(interrupt): send EOI to PIC2 for IRQ8-15 11 months ago
  greatbridf 1dacf49c2a fix(lock): lock not properly locked 11 months ago
  greatbridf 7efa80fa12 feat: poll() and llseek() for busybox shell 11 months ago
  greatbridf ad3ff833e5 refactor: rewrite thread and readyqueue 11 months ago
  greatbridf 1504e35835 change(syscall): kill unsupported syscall in place 11 months ago
  greatbridf 698266b865 feature(tty): support of tty termios 11 months ago
  greatbridf b1b6d920f8 refactor: special node files and partprobe 11 months ago
  greatbridf 94f3cee3e5 refactor: move init script out of init_vfs 11 months ago
  greatbridf dbda9e3578 refactor: divide vfs.hpp into four 11 months ago
  greatbridf da84d0d39b refactor: vfs 11 months ago
  greatbridf f67d993913 remove: some redundant code 11 months ago
  greatbridf e75d8437f5 feature(syscall): unlink and access 11 months ago
  greatbridf cb12970934 feature(shared_ptr): add make_shared(); 11 months ago
  greatbridf 059465cfd5 feature(hash_map): add begin() and end() 11 months ago
  greatbridf 56349fea2c change(user-sh): suppress runcmd() warning 11 months ago
  greatbridf f607aecdab update: pretty print script 11 months ago
  greatbridf eccb650472 chore: update Makefile.src, remove redundant files 11 months ago
  greatbridf 735b7988b3 fix: remove constexpr from some function decl. 11 months ago
  greatbridf 61eaa076d3 chore: check if we should probe fdisk path in conf. 11 months ago
  greatbridf 1c7a276b93 change(proclist): remove emplace from proclist; 11 months ago
  greatbridf 530db35b6a feat(file): append to file 1 year ago
  greatbridf c342508132 feat(syscall.open): add truncate support 1 year ago
  greatbridf 0c005d1b68 fix(dup2): newfd should not share flags(O_CLOEXEC) with oldfd 1 year ago
  greatbridf c29afbde1d feat(truncate): add it to syscall, vfs and tmpfs 1 year ago
  greatbridf c7a6dee5eb fix(ahci): copy minimum of cnt and sector size in read() 1 year ago
  greatbridf 4ac28ae9a7 feat(init): execute init script using busybox sh 1 year ago
  greatbridf 1cacb91f2b feat(thead_local): save and load thread local area 1 year ago
  greatbridf 74c913f994 feat(syscall): implement sigaction 1 year ago
  greatbridf e7f8d74f83 fix(rt_sigprocmask): SIG_UNBLOCK should invoke signals.unmask 1 year ago
  greatbridf 3aa82c2b13 feat(scheduler): support multi kernel stack frames 1 year ago
  greatbridf b2d19e6ff6 change(mm): remove extra memory fences 1 year ago
  greatbridf f998f5ec25 fix(port, kmods): make kmods aligned to 16bytes, make inl volatile 1 year ago
  greatbridf 6097ccb5cc fix(fat32): read the whole fat table 1 year ago
  greatbridf 759eb73ba3 rewrite(allocator): locked version of kernel allocator 1 year ago
  greatbridf 0809eb0e7b fix(filearr): allocate fd in dup2() 1 year ago
  greatbridf d5070d823a feat(syscall): mkdir 1 year ago
  greatbridf 496a4bb31f feat(syscall): impl. partial gettid and wait4 1 year ago
  greatbridf 5926e83a34 feat(syscall): uname, getpgid, getuid, rt_sigaction(half works) 1 year ago
  greatbridf 20ed412b5a fix(rbtree): rbtree copy 1 year ago
  greatbridf fdb0052684 fix(signal): wakeup the threading on signals generated 1 year ago
  greatbridf a52f58ffb4 feat(syscall): add rt_sigprocmask 1 year ago
  greatbridf d53ea9f452 fix(usp-sh): fix pipecmd 1 year ago
  greatbridf 35cce41a09 fix(vfs): close pipes properly, prohibit sendfile64 used on non regular files 1 year ago
  greatbridf 5813062c00 Merge branch 'dev' 1 year ago
  greatbridf 41566272a6 fix(mmap): adjust file nullptr check 1 year ago
  greatbridf d8a51c9d64 chore(make): update Makefile.src 1 year ago
  greatbridf b4ec221a53 feat(ahci): add ahci controller driver 1 year ago
  greatbridf 12c41b087e refactor(irq): new irq handling method 1 year ago
  greatbridf 46dc1ed418 fix(vfs): check whether a dentry is a directory before read and write 1 year ago
  greatbridf 880a7a1057 change(mbr): read 320KB 1 year ago
  greatbridf 0746c681e2 change(allocator): make all functions constexpr 1 year ago
  greatbridf 5cf3c5bd56 fix(vector): fix bugs, optimize memory allocation 1 year ago
  greatbridf 25e48c79a2 change(image): rename bb to busybox_ 1 year ago
  greatbridf 8efa4a211a feat(syscall): add sendfile64 1 year ago
  greatbridf 8123051e6a feat(libstdc++): addr max and min 1 year ago
  greatbridf 4a42fe3956 refactor(vfs): rewrite struct file 1 year ago
  greatbridf 47934b45b5 feat(libstdc++): add shared_ptr 1 year ago
  greatbridf 9ca65a15e9 fix(inode_write): update inode size after writting 1 year ago
  greatbridf 6d321f5eac feat(open): open() can now create new files 1 year ago
  greatbridf b5faee6ded feat(types::path): add types::path to handle paths 1 year ago
  greatbridf 0f9c6c4603 feat(syscall): add getdents64 1 year ago
  greatbridf 09fa92b097 feat(syscall): add fcntl64 1 year ago
  greatbridf 2656facbab feat(syscall): add statx 1 year ago
  greatbridf 8576f82ca1 fix(mm.split): update file offset of newmm 1 year ago
  greatbridf 50b9527a09 feat(syscall): add mmap and munmap 1 year ago
  greatbridf 281050186a feat(std::set): add template key version of lower_bound 1 year ago
  greatbridf 8115a79f02 feat(syscall): add brk 1 year ago
  greatbridf 4ee526a1aa refactor(mm): some tweaks of mm and mm_list 1 year ago
  greatbridf e991778937 fix(rbtree): fix rbtree rotate and set copy ctor 1 year ago
  greatbridf 915f90251e feat(image): add busybox to mount image 1 year ago
  greatbridf 696aaa567c feat(syscall): add clock_gettime64, getuid and prctl 1 year ago
  greatbridf da4fc9c087 feat(syscall): add syscalls, change syscall ids 1 year ago
  greatbridf 3cf21d6082 feat(syscall): add set_thread_area 1 year ago
  greatbridf 423968a920 feat(vfs): support opening relative path 1 year ago
  greatbridf 1da64db368 feat(libstdc++): add priority_queue 1 year ago
  greatbridf c98321cc3d feat(libstdc++): add deduction guides and iter tools 1 year ago
  greatbridf 2355016228 feat(libstdc++): add vector 1 year ago
  greatbridf fa48094702 fix(cmake): remove list.hpp 1 year ago
  greatbridf 719a421750 change(kernel): replace types::list with std::list 1 year ago
  greatbridf 1f1af196a0 feat(libstdc++): add std::list 1 year ago
  greatbridf ae07552418 fix(rbtree): propagate... of allocator 1 year ago
  greatbridf 6f77e1dd82 fix(int14): save mmx registers 1 year ago
  greatbridf 61cd2982f9 change(vfs): move dentry dtors to hpp 1 year ago
  greatbridf 929a17f7a3 fix(ld): add sentry to prevent kernel too large 1 year ago
  greatbridf 8b90f07a34 change(vfs): readdir callback should pass by ref. 1 year ago
  greatbridf a9b38d3154 change(types::alloc): alloc 8 bytes once at least 1 year ago
  greatbridf 4e0f5a1b06 fix(functional): larger _data for vtable 1 year ago
  greatbridf 5287b2b529 feat(rbtree): upper bound and lower bound 1 year ago
  greatbridf 247863ce35 refactor(thread): remove thdlist and some ctors 1 year ago
  greatbridf 0a7b5413a5 fix tuple and rbtree, simplify kernel process 1 year ago
  greatbridf bc841ee42e feat(libstdc++): add at and [] to map 1 year ago
  greatbridf 3893ba9cea feat(libstdc++): add stl map 1 year ago
  greatbridf feadee8506 feat(libstdc++): some more features of set 1 year ago
  greatbridf 3807ff3e32 feat(libstdc++): add stl set 1 year ago
  greatbridf ec19ff3095 change(proclist): remove tty_idx 1 year ago
  greatbridf 07638e3531 change(kernel): remove types::pair 1 year ago
  greatbridf 5444b2ee83 feat(libstdc++): add pair 1 year ago
  greatbridf 15063be59a fix(tuple): make tuple copy & move ctor. constexpr 1 year ago
  greatbridf c4bd0eb20e feat(libstdc++): tuple 1 year ago
  greatbridf e1446fc737 style(process): use structured binding... 1 year ago
  greatbridf e289c9a72b feat(bitmap): change bm_ funcs to class bitmap 1 year ago
  greatbridf 188c55e96e change(vector): change the behavior of resize 1 year ago
  greatbridf 94d7406520 fix(vector): does nothing if size() == n 1 year ago
  greatbridf e9e2680a69 change(mem.cpp): use structured binding 1 year ago
  greatbridf 9fcf1ba7ba feat(libstdc++): add bit_cast 1 year ago
  greatbridf 2d8ca9bdaa fix(libstdc++): make deleted addressof const T* 1 year ago
  greatbridf d5a5a44d02 feat(functional): add invoke_r 1 year ago
  greatbridf 400d5597f6 feat(tty): show control char on screen 1 year ago
  greatbridf 2e38e5e6de fix(type_traits): fix decay 1 year ago
  greatbridf 2ba94b1ce9 feat(functional): c++ std::function 1 year ago
  greatbridf 20fa42c8e4 fix(type_traits): is_template_instance<> 1 year ago
  greatbridf 727c3c936a refactor(gblibstdc++): add type_traits and utility 1 year ago
  greatbridf 7472cbe839 feat(gbstdlibc++): add gbstdlibc++ and utility 1 year ago
  greatbridf 4cf6746d1d fix(tcsetpgrp): get ctrl tty by sid instead of pid 1 year ago
  greatbridf 5858a28309 fix(int14): preserve SSE registers 1 year ago
  greatbridf 225bbdf08a fix(crt0): do not use parameters on the stack 1 year ago
  greatbridf 8dfd98cdb1 fix(mem): add memory fence to prevent reordering 1 year ago
  greatbridf 1baa59a2b2 style(lazybox): call main() recursively 1 year ago
  greatbridf 71c939840d fix(elf): check before mmapping LOAD sections 1 year ago
  greatbridf cef73c3edd style(paccess): make paccess() inline 1 year ago
  greatbridf f8670fcfce fix(function): check size of FuncLike object 1 year ago
  greatbridf b6dbdcae1e fix(sh): ignore -Winfinity-recursion 1 year ago
  greatbridf 431d80298f fix(stack_protector): move stack_chk_guard to libc 1 year ago
  greatbridf cf416c45b5 feat(kill): add syscall kill() 2 years ago
  greatbridf 9483e98eca fix(proclist::find()): check iter null 2 years ago
  greatbridf 769feae046 feat(gblibc): add umask() 2 years ago
  greatbridf a4c5491f01 change(types): add mode_t 2 years ago
  greatbridf 5eee6fd14b feat(gblibc): add gettimeofday() 2 years ago
  greatbridf 7e873a0e79 feat(gblibc): add stat() 2 years ago
  greatbridf db73e41887 feat(gblibc): add fstat() 2 years ago
  greatbridf 64c1db8727 feat(gblibc): realloc 2 years ago
  greatbridf 2252c898bf feat(gblibc): add strsignal() 2 years ago
  greatbridf f17738319d feat(gblibc): add strndup, strdup 2 years ago
  greatbridf e9937eddbd feat(environ): pass envs between procs 2 years ago
  greatbridf b8bfecd56f feat(gblibc): asprintf and vasprintf 2 years ago
  greatbridf 2298a86ef1 feat(gblibc): add ferror_unlocked 2 years ago
  greatbridf 405ef53f7a feat(tty): clear read buf in default sig. handlers 2 years ago
  greatbridf 92f2e82f02 feat(gblibc): clearerr, ferror, feof 2 years ago
  greatbridf 1f9648b753 feat(gblibc): bsearch() 2 years ago
  greatbridf e4159f941b feat(gblibc): add qsort, rand, alloca 2 years ago
  greatbridf 5799cd8bfd fix(ioctl): check whether file is /dev/console 2 years ago
  greatbridf 69803ca140 feat(gblibc): isatty() 2 years ago
  greatbridf a3b9f3e011 feat(gblibc): add {ge,pu}tc_unlocked 2 years ago
  greatbridf 8eab661b1a fix(gblibc): change NDINSERT and NDERASE to func 2 years ago
  greatbridf 8d8a8f7a1c feat(gblibc): add fopen and move stdout 2 years ago
  greatbridf 652028e079 feat(gblibc): buffered io and printf 2 years ago
  greatbridf 1ce4b3415e feat(gblibc): add malloc, brk, sbrk 2 years ago
  greatbridf 0c919f05e7 feat(gblibc): set errno for syscalls 2 years ago
  greatbridf 3bca251840 feat(gblibc): stderror() 2 years ago
  greatbridf 2d34baf675 feat(gblibc): add strstr() 2 years ago
  greatbridf d67ccc411a feat(gblibc): strcspn 2 years ago
  greatbridf 428d0d3321 feat(gblibc): add strcasecmp and strncasecmp 2 years ago
  greatbridf f3ad9758aa feat(gblibc): add __stack_chk_fail_local 2 years ago
  greatbridf 3e141f09b7 change(gblibc): move errno to gblibc 2 years ago
  greatbridf 7b059e1a11 feat(gblibc): add string.h and stdio.h funcs 2 years ago
  greatbridf 15f53c60ab remove crt0 out of gblibc 2 years ago
  greatbridf eaa4c84140 feat: vfs_open_proc for user space syscalls 2 years ago
  greatbridf d3f2ae9dcf Merge branch 'dev' 2 years ago
  greatbridf f41f73a8b1 fix: mmaped pages of child procs may be empty 2 years ago
  greatbridf b60840f419 change(mmap): remove _mmap 2 years ago
  greatbridf 8887ccd4ed fix: set p bit of cow page whose refcount is 1 2 years ago
  greatbridf 1724d02506 fix(mm_list): set children mm's owner on moving 2 years ago
  greatbridf 8e1293cd43 feat: support fat32 lowercase filename 2 years ago
  greatbridf c4c0936a8f feat(gblibc): add ctype 2 years ago
  greatbridf e32a680f5d feat: getpid and getppid 2 years ago
  greatbridf 9d560da181 feat: tc{s,g}etpgrp 2 years ago
  greatbridf 427190bcbe feat: setpgrp 2 years ago
  greatbridf 167dd07e9b feat(pipe): send SIGPIPE on read end close 2 years ago
  greatbridf 760c462f77 feat(pipe): send EOF on write end close 2 years ago
  greatbridf dd684f86df style: remove unused params of syscall funcs 2 years ago
  greatbridf ba8f40e69b feat: read and write of pipes will wait for data 2 years ago
  greatbridf 1ff2137333 feat: replace evequeue by cond_var 2 years ago
  greatbridf da154fd066 change: use schedule_noreturn() in syscall exit 2 years ago
  greatbridf 6ab99e3b3d change: make schedule() return int. status 2 years ago
  greatbridf ea0c108eea change: use linux x86_64 syscall no. 2 years ago
  greatbridf 611384a51b feat(pipe): add syscall pipe 2 years ago
  greatbridf 2c198376c8 fix(map): fix map swap 2 years ago
  greatbridf 72448d4099 change(syscall): check syscall_no in syscall.cpp 2 years ago
  greatbridf c268e31f28 feat(dup): add syscall dup and dup2 2 years ago
  greatbridf 56bf9be365 chore(pretty-printer): show iterator 2 years ago
  greatbridf 5ca22c8baf feat(init): open all three file descriptors 2 years ago
  greatbridf 913821be67 feat: set errno in syscall 2 years ago
  greatbridf ca1a736d4f feat: close() syscall and shell redirection 2 years ago
  greatbridf 2aa7013175 Merge branch 'tty' into dev 2 years ago
  greatbridf feff857aaf Merge branch 'signal' into tty 2 years ago
  greatbridf 04de266681 feat(signal): send SIGINT, SIGQUIT and SIGSTOP 2 years ago
  greatbridf 8fbf10ff42 feat: syscall entry stub 2 years ago
  greatbridf 300de58007 add sid and pgid 2 years ago
  greatbridf 3aaae12c07 add sigquit 2 years ago
  greatbridf 71010de5b0 immediately return from read on EOF 2 years ago
  greatbridf 79e34047f3 Merge branch 'dev' into tty 2 years ago
  greatbridf 69cc04e836 feat: gdb pretty printer 2 years ago
  greatbridf 533155f3ad change: move def. of pid_t to gblibc 2 years ago
  greatbridf 29fd9b2493 dev: stash 2 years ago
  greatbridf 3f9c17ee90 Merge branch 'memory' into dev 2 years ago
  greatbridf 841e258a13 fix: free stage1 and kinit 2 years ago
  greatbridf a3d94d13c1 fix: mark kstack as allocated 2 years ago
  greatbridf 0471ee9813 change: replace some _new with operator new 2 years ago
  greatbridf 48c771e1c8 fix: __alloc_raw_page may return used page 2 years ago
  greatbridf 304ecefefb feat: move kernel to 0xc0000000 2 years ago
  greatbridf 210279a15b change: check allocated memory in vector::resize 2 years ago
  greatbridf 082d9bd19a fix(list): make _empty_list.begin() return end() 2 years ago
  greatbridf b2aa149ae2 change stage1 start addr to 0x8000 2 years ago
  greatbridf 32369676cd dev: load kernel to 0xc0000000 2 years ago
  greatbridf 9de7953c44 style(mem.cpp): mark addr range 2 years ago
  greatbridf cb96ca109a feat: free kinit memory 2 years ago
  greatbridf bfcf1567b6 style: add sections 2 years ago
  greatbridf a9e1f08cc6 style: kernel_main 2 years ago
  greatbridf d8a3f66f7a fix(vfs_open): check nullptr 2 years ago
  greatbridf 183ed5166f feat: check O_DIRECTORY flag 2 years ago
  greatbridf 68b4a8d207 feat: add {open,read}dir and lazybox ls 2 years ago
  greatbridf 36654c55e7 style: add type conversion for getcwd 2 years ago
  greatbridf 1e8ced7113 feat(usp): add lazybox and pwd 2 years ago
  greatbridf 5cd3d7fd69 feat(syscall): add getcwd 2 years ago
  greatbridf 0be57320a7 feat(chdir): add syscall chdir 2 years ago
  greatbridf 83ae21d337 Merge branch 'fix-stdio' into dev 2 years ago
  greatbridf bd41632d2d fix(stdio): add vsnprintf for va_list 2 years ago
  greatbridf f136d0c455 Merge branch 'libc' into dev 2 years ago
  greatbridf 5e8359fd6b feat(elf): set .bss section zero 2 years ago
  greatbridf b22ee32e67 Merge branch 'shell' 2 years ago
  greatbridf 5808eb0276 Merge branch 'master' into shell 2 years ago
  greatbridf c0271b312e Merge branch 'assert-checks' 2 years ago
  greatbridf f4b2f9707d Merge branch 'master' into assert-checks 2 years ago
  greatbridf 1cb6fa31ce Merge branch 'fix-elf' 2 years ago
  greatbridf bb5739aff8 fix(elf): fill zeros for memory not in the file 2 years ago
  greatbridf 468581437b style: add some assert checks 2 years ago
  greatbridf 9eca5ea767 feat: port xv6 sh 2 years ago
  greatbridf ab1d508e44 Merge branch 'mem-priv' 2 years ago
  greatbridf 61e15f9966 feat: kill user proc. on int6 and int13 2 years ago
  greatbridf 8cd5128366 feat: add freeze() and kill_current() 2 years ago
  greatbridf edcbbf0ac5 Merge branch 'master' into mem-priv 2 years ago
  greatbridf aa68b006d0 Merge branch 'libc' 2 years ago
  greatbridf f8dda1c0bd change: remove assert.h in kernel 2 years ago
  greatbridf 9c5570cfcf chore: use C_CXX_FLAGS to save common flags 2 years ago
  greatbridf 80076fd773 Merge branch 'master' into libc 2 years ago
  greatbridf 6982ae33f9 Merge branch 'fix-kstack' 2 years ago
  greatbridf 38c7861ce7 fix(thd): subtract ptr by kstack size on freeing 2 years ago
  greatbridf 44be3910a1 fix(ldscript): make ctors align to 4 bytes 2 years ago
  greatbridf a69cd63f14 change: replace _Noreturn to attr(noret) 2 years ago
  greatbridf 3e759fa4dd feat: assert 2 years ago
  greatbridf 1446211242 feat: add std{in,out,err} macro def. 2 years ago
  greatbridf 9ada56e74b Merge branch 'master' into libc 2 years ago
  greatbridf 24d92f5489 Merge branch 'kill' 2 years ago
  greatbridf bc52f08bfe feat(mm): kill user process on access to priv. mem 2 years ago
  greatbridf bc87e8c44f feat: move codes to kill proc into proclist kill() 2 years ago
  greatbridf 07c6dad04c Merge branch 'fix-filearr' 2 years ago
  greatbridf 3b78bb6760 fix(files): files may be closed for multiple times 2 years ago
  greatbridf 39430cb4c3 Merge branch 'fix-map' 2 years ago
  greatbridf 734d075ade fix(map): fix erase 2 years ago
  greatbridf 7c895c1ac3 Merge branch 'mac' 2 years ago
  greatbridf 8dbabbba51 Merge branch 'master' into mac 2 years ago
  greatbridf 95e561acf6 Merge branch 'fix-mm' 2 years ago
  greatbridf 4a36d3b820 fix(mm): mem leak when unmapping mem area and mm 2 years ago
  greatbridf 1dba142be9 chore: clear cmake default linker options 2 years ago
  greatbridf 4596fdcda2 chore(usp): move usp linker args into ldscript 2 years ago
  greatbridf 7438992327 fix: make pid_t type 'int' 2 years ago
  greatbridf 2106a9dbaf Merge branch 'libc' 2 years ago
  greatbridf d4122bd571 feat(posix): impl. posix interface, update usp 2 years ago
  greatbridf 521d554189 Merge branch 'master' into libc 2 years ago
  greatbridf 08b04e54c1 Merge branch 'fix-libstdc++-map' 2 years ago
  greatbridf fa8c43ffc7 fix(libstdc++): map deleting elements 2 years ago
  greatbridf f5cdd03c55 Merge branch 'fix-mmap' 2 years ago
  greatbridf f6dff3e420 fix(mm): invlpg after unmapping mem areas 2 years ago
  greatbridf 90b868a5cf feat(gblibc): set entry point to _start 2 years ago
  greatbridf fc545e1710 chore: build user-space-program with cmake 2 years ago
  greatbridf 33e5982d79 change(cmake): link the kernel with cmake 2 years ago
  greatbridf d44046d21c feat(gblibc): separate libc from kernel code 2 years ago
  greatbridf df785572f8 Merge branch 'getdents' 2 years ago
  greatbridf c8ff5b072a feat(syscall): add getdents 2 years ago
  greatbridf 0120d746b3 feat(map): add operator bool, fix find() 2 years ago
  greatbridf f12a8f26ab feat(c++): add std::function 2 years ago
  greatbridf bd25366506 change(file): add ptr to parent in struct file 2 years ago
  greatbridf b74163b1d5 Merge branch 'open_working' into open 2 years ago
  greatbridf d3a2691a11 feat(tty): read from tty 2 years ago
  greatbridf 246de6198f output less debug info in kernel_main 2 years ago
  greatbridf 551cec8c54 feat: bufferred tty reading 2 years ago
  greatbridf 5b120d25aa rewrite tty with c++ classes 2 years ago
  greatbridf 3bb9a50d6a add non copyable class 2 years ago
  greatbridf 23e86efdae fix buffer constructor 2 years ago
  greatbridf 8326c982e1 adapt more parts to cpp 2 years ago
  greatbridf c23b25c8eb remove constexpr of ~mm_list() 2 years ago
  greatbridf 576ca427b0 limit vfs_read buffer size when doing system calls 2 years ago
  greatbridf 57bb3fc54e stash 2 2 years ago
  greatbridf 95059ec7e0 stash 1 2 years ago
  greatbridf 248e32a46d change(buffer): rename buffer.{c,h} to buffer.hpp 2 years ago
  greatbridf 79482631aa feat(file): add file descriptors 2 years ago
  greatbridf 789d002b13 fix(hash_map): make find() const compatible 2 years ago
  greatbridf edb5ac858c fix(syscall_exit): remove all thds from ready list 2 years ago
  greatbridf 9caca574db change(thread): add class thdlist 2 years ago
  greatbridf e4b84ad3da feat(c++): add is_template_instance 2 years ago
  greatbridf c5a6be277a change(process): use map for process list 2 years ago
  greatbridf a1ddb6a031 feat(map): add template container map 2 years ago
  greatbridf 44a9b33979 feat(hash_map): move pair class out of hash_map 2 years ago
  greatbridf f021bc88bb change(vfs): make fs_root inline global var 2 years ago
  greatbridf 5619ebf4c1 Merge branch 'vfs_fix' into open 2 years ago
  greatbridf 5a58906104 change(vfs): only allocate children lists for dirs 2 years ago
  greatbridf 87883c5978 refactor(new): add _new and pnew for allocators 2 years ago
  greatbridf 0f4efff41e fix(vfs): wrong comment of dentry flags 2 years ago
  greatbridf f2dd3f8c06 fix(vfs): wrong comment of dentry flags 2 years ago
  greatbridf 9dfbab81c4 Merge branch 'process-classes' 2 years ago
  greatbridf b8cc71517a feat(ata): check buf_size in ata_read() 2 years ago
  greatbridf 6e4a649a55 feat(c++): add operator& to list iterators 2 years ago
  greatbridf b120b34b82 feat(process): add class readyqueue 2 years ago
  greatbridf 1c4a86f31d style(process.cpp): use _noreturn_crash() 2 years ago
  greatbridf 56756566e1 refactor(irq0): remove is_scheduler_ready 2 years ago
  greatbridf 0d8e0a0ef4 feat(proc): add class proclist 2 years ago
  greatbridf f96fe8524c fix(c++): fix move and forward 2 years ago
  greatbridf d5aa6193eb Merge branch 'fix-release' 2 years ago
  greatbridf 07d5acdffa fix(scheduler): push pseudo ret.addr. of go_kernel 2 years ago
  greatbridf 47a3dcc803 fix(lock): wrong jmp label 2 years ago
  greatbridf 749f13d09d fix(evtqueue): return front() by value 2 years ago
  greatbridf 3a9e9ef206 fix(assert): assert_likely is undefined in Release 2 years ago
  greatbridf e73c206e52 Merge branch 'exec' 2 years ago
  greatbridf 1285e661c3 refactor(assert): move assert and breakpoint code 2 years ago
  greatbridf e548724797 fix(a20): check a20 status without breaking code 2 years ago
  greatbridf 020f3cb5c6 Merge branch 'exit_and_wait' into exec 2 years ago
  greatbridf b2586e331c feat(syscall): impl. exit and wait syscall 2 years ago
  greatbridf cd69b19fe7 fix(init): send kernel address to get exit code 2 years ago
  greatbridf 5d0c569a04 feat(stack-protector): protect stack overflowing 2 years ago
  greatbridf fc29de6d6f fix(mm): continue; in clear_user() 2 years ago
  greatbridf 7936499704 fix(sse): use cpu SandyBridge to enable SSE 2 years ago
  greatbridf 6953011b53 refactor(scheduling): switch ctx. with schedule() 2 years ago
  greatbridf cebc24a3ae feat(assert): check error with assert 2 years ago
  greatbridf 0cf0b4d4c3 feat(mm): make mm_list constexpr 2 years ago
  greatbridf a3602de618 feat(mm): add mm_list class 2 years ago
  greatbridf 5e395c9d64 feat(containers): make destructors constexpr 2 years ago
  greatbridf e3a4dc9d3a feat(process): use lock guard for kthreadd 2 years ago
  greatbridf 569a73f635 fix(kthreadd): exec task in child proc 2 years ago
  greatbridf 9ddd370740 feat(elf): pass program arguments to elf loader 2 years ago
  greatbridf c1d7c094e0 feat(lock): add lock_guards 2 years ago
  greatbridf ddb1ca3b92 feat(mm): free raw pages 2 years ago
  greatbridf cc9c4c4989 feat(user): add syscall wrappers 2 years ago
  greatbridf f4fa88196f style: simplify code 2 years ago
  greatbridf f27f7ddade fix(syscall): not releasing pg_lists on unmapping 2 years ago
  greatbridf 6a7579eae5 feat(syscall): exit with no resource release 2 years ago
  greatbridf 50d68c0ff9 change(debugging): crash when makeing breakpoints 2 years ago
  greatbridf a68e15e75d change(init): move init decl. to kernel_main.c 2 years ago
  greatbridf 3995b9ef2e fix(elf): set up stack when loading elf files 2 years ago
  greatbridf ea96c12385 Merge branch 'stl' into exit_and_wait 2 years ago
  greatbridf a1cc77112e chore(debugging): add pretty print script 2 years ago
  greatbridf 09e5da2aaa fix(k_map): clear source page's 'a' bit 2 years ago
  greatbridf 0371ab9514 Merge branch 'mem_fix' into exec 2 years ago
  greatbridf f992f91617 fix(lock): labels may be defined multiple times 2 years ago
  greatbridf ffdfb9c093 fix(process): stacks of kthds are not mirrored 2 years ago
  greatbridf 74fa329672 feat: make compiler optimize likely branches 2 years ago
  greatbridf 362f149fcb refactor(paging): move kernel pd and empty page 2 years ago
  greatbridf 16cb499967 fix(port): add asm volatile 2 years ago
  greatbridf f10031fe36 fix(syscall): tell compiler it affects eax and edx 2 years ago
  greatbridf 03d4bfa86e chore(mm): add TODO for mm_area mirroring 2 years ago
  greatbridf 943868c7f9 feat(mm): add k_unmap and dealloc_{pd, pt} 2 years ago
  greatbridf d551a55a48 fix(page.refcount): alloc refcount in ident. area 2 years ago
  greatbridf 68a2a9fdd3 feat(c++): add PointerType, pnew 2 years ago
  greatbridf ab67740b4f fix(k_map): invalidate tlb cache when mapping cow 2 years ago
  greatbridf 673c784b88 fix(mmap): save mmap'ped file info when copying mm 2 years ago
  greatbridf e3d5803469 optimize(mm): rename pptr_t, make funcs constexpr 2 years ago
  greatbridf 8af1356b08 style(mm): simplify code 2 years ago
  greatbridf b656c201bf fix(list): return end() when not found 2 years ago
  greatbridf 130a495df4 fIx(mm): make cow referred pages also cow 2 years ago
  greatbridf 03b2aadd9f feat(concept): add concept Hasher and Allocator 2 years ago
  greatbridf 45ed1dda86 feat(containers): make operator== const 2 years ago
  greatbridf ad0c8653da chore(c++): compile with standard c++20 2 years ago
  greatbridf 2de03e53eb fix(CMakeLists): set FDISK_BIN if not defined 2 years ago
  greatbridf 2eafad4b65 chore(configure): check and set FDISK_BIN 2 years ago
  greatbridf 34b3bf7644 feat(syscall): impl. exec() to load elf files 2 years ago
  greatbridf 3d716d00d5 Merge branch 'ata' 2 years ago
  greatbridf 6627cd11bd Merge branch 'special-device-file' into ata 2 years ago
  greatbridf 3f508e8775 feat(fs): add fat32 filesystem 2 years ago
  greatbridf a9363f3a4a fix(mmap): correct mmap() definition 2 years ago
  greatbridf 148cec14b4 fix(mbr): read 128k 2 years ago
  greatbridf 4eca7c8ff6 fix(string): remove string custom constructors 2 years ago
  greatbridf 843b17eb68 fix(string): fix operator+=(const char) and back() 2 years ago
  greatbridf 1e81695c9a feat(vector): add copy constructor 2 years ago
  greatbridf b8d3768286 fix(vector): make operator= return *this 2 years ago
  greatbridf 14b037a6df fix(hash_map): several fixes 2 years ago
  greatbridf 6bab50c7fe feat(string): add operator== 2 years ago
  greatbridf 14c830a22c feat(vector): add move assignment func. 2 years ago
  greatbridf 41b56ecb26 feat(c++): add remove_cv, decay 2 years ago
  greatbridf 8058928329 feat(vfs): make vfs a interface 2 years ago
  greatbridf 5e6a91193c feat(hash): add string hash functions 2 years ago
  greatbridf 7c938ba933 feat(hash_map): impl. hash_map 2 years ago
  greatbridf 2ef440f8e1 change(vfs): use c++ 2 years ago
  greatbridf 2dafb2999b feat(make): use mtools to copy files into boot.img 2 years ago
  greatbridf 8da2920aa5 chore(configure): check whether mkfs.fat exists 2 years ago
  greatbridf 05cf4932d8 feat(vfs): add new struct special_node 2 years ago
  greatbridf 41aeb2dd0d style(vfs): rename union special_node to node_t 2 years ago
  greatbridf f9ba0231e8 change(ata): make identify() return a status value 2 years ago
  greatbridf 9b715713dc fix(vfs): check if special node ops func exist 2 years ago
  greatbridf 23542e4786 change(boot.img): use 512MiB as the disk image size 2 years ago
  greatbridf 827b33c6cb Merge branch 'disk-prepare' into special-device-file 2 years ago
  greatbridf 1a8bd33e17 chore(boot.img): create fat partition 2 years ago
  greatbridf b5bd5dc2d7 chore(cmake): use cmds working on both platforms 2 years ago
  greatbridf d6de8a08f0 feat(mbr): build mbr.bin separately 2 years ago
  greatbridf ad07d066eb fix(mmap): read mapped data from file[offset] 2 years ago
  greatbridf 0638ea3bec Merge branch 'ata' into special-device-file 2 years ago
  greatbridf 95c4bb21cc Merge branch 'mmap' into ata 2 years ago
  greatbridf 82cd10f0fc feat(mmap): able to do memory maps in kernel space 2 years ago
  greatbridf 1356bd2e63 feat(ata): ata read sector by reading node 2,0 2 years ago
  greatbridf e88af94e05 feat(node): impl. mknode 2 years ago
  greatbridf 462ec39241 feat(ata): impl. init. ata and read sectors 2 years ago
  greatbridf 9c72ff3f2c feat(syscall): add syscall crash 2 years ago
  greatbridf e929d98515 feat(port): add class port 2 years ago
  greatbridf 7348abf2a1 chore(gitignore): ignore vim swap files 2 years ago
  greatbridf 05ab779eda feat(process): add k_new_thread 2 years ago
  greatbridf 941a9874cf fix(lock): make lock type volatile 2 years ago
  greatbridf 6107790323 fix(kthdd): acquire the lock only on func not null 2 years ago
  greatbridf 710e9cf529 Merge branch 'kernel-thread' into user-space-program 2 years ago
  greatbridf 88add58cf5 feat(kernel_thread): impl. kernel_thread forking 2 years ago
  greatbridf aa5b5749c4 feat(lock): impl. spin lock 2 years ago
  greatbridf 9b18576715 chore(cross-compile.cmake): gen. it in ./configure 2 years ago
  greatbridf 7add1ab9a3 feat(list): make node->next and prev node_type 2 years ago
  greatbridf db7926548d feat: create kernel thread 2 years ago
  greatbridf ecd76edc09 feat(syscall): impl. fork 2 years ago
  greatbridf aed24262ab chore(configure): set hardware accel. type 2 years ago
  greatbridf d50e70efaa feat(syscall): impl. sleep 2 years ago
  greatbridf 904883c5e3 refactor: add context save and load functions 2 years ago
  greatbridf e6dc019e17 feat: build and link user space programs 2 years ago
  greatbridf 9a6aa020d8 Merge branch 'syscall' 2 years ago
  greatbridf 0aaa529fd0 chore(Makefile): rename configure, add reconfigure 2 years ago
  greatbridf b013728ac4 feat(syscall): impl. syscalls 2 years ago
  greatbridf c5d37ef334 style: change struct to class, remove parentheses 2 years ago
  greatbridf 14d8c7760e chore: update global_find script 2 years ago
  greatbridf 54740e3f8e Merge branch 'macos-adaption' 2 years ago
  greatbridf 5020eb6f75 feat(Makefile): enable parallel build 2 years ago
  greatbridf 941ac209b9 fix(configure): suppress output and return 0 2 years ago
  greatbridf 896023acbf fix(linker): old 'ctors' won't be called 2 years ago
  greatbridf fc23e8cba2 chore: add configure script 2 years ago
  greatbridf c6a8f96e74 feat(serial): input data echo 2 years ago
  greatbridf 0de053a20f Merge branch 'process' 2 years ago
  greatbridf b93a90442c feat(mm): add constructor for class mm 2 years ago
  greatbridf 21c06ac7c9 feat(process): add constructor for class process 2 years ago
  greatbridf 975ac4c437 fix(list): check if ptr is null before releasing 2 years ago
  greatbridf 06e54f821f feat(c++): rvalue_ref 2 years ago
  greatbridf 0d79b8eae9 feat(c++): impl. forward and move 2 years ago
  greatbridf afe474b291 refactor(process): do not store segs. in process 2 years ago
  greatbridf be01268409 feat(process): scheduling 2 years ago
  greatbridf 77f3523304 feat(process): use emplace_back 2 years ago
  greatbridf 93685f6053 fix(c++): template forwarding should use && 2 years ago
  greatbridf ffa995672b feat(list, vector): impl. emplace_back 2 years ago
  greatbridf 5e5b8a16e0 feat(vector): impl. operator= 2 years ago
  greatbridf 58349d6b5c refactor(list, vector): simplify def. 2 years ago
  greatbridf dcfa27d1dc feat(process): add struct thread 2 years ago
  greatbridf c0158d5a7e feat(list): clear, erase and operator= 2 years ago
  greatbridf 342ecc0e21 feat(process): enter user mode 2 years ago
  greatbridf 9ba4232b4c feat(interrupt): align stack in ISR 2 years ago
  greatbridf bfd97f6c89 Merge branch 'mem' 2 years ago
  greatbridf 90cc9522ab refactor: 拆分mem和mm,对interrupt使用cpp 2 years ago
  greatbridf f7bf58435d fix(allocator): allocate wrong size 2 years ago
  greatbridf 010eeefb18 refactor(mem): use cpp 2 years ago
  greatbridf d5f54a40c5 refactor: prohibit c++ global objects 2 years ago
  greatbridf 7741c9d172 Merge branch 'vfs' 2 years ago
  greatbridf 1e170f1028 feat(vfs_stat): handle / and directories 2 years ago
  greatbridf 4660803811 feat(vfs): query file stat 2 years ago
  greatbridf 7f67c01d7e feat(string): pop(), back() etc. 2 years ago
  greatbridf abed3286f0 fix(errno): add __cplusplus header 2 years ago
  greatbridf 78e4bbef4b fix(list,vector): remove explicit of initializer 2 years ago
  greatbridf 32acbc5031 fix(vector): dealloc undefined ptr on vector init 2 years ago
  greatbridf 137583508c fix(vector): wrong const back() type 2 years ago
  greatbridf a1dfcee9b7 feat(string): impl. clear() and c_str() 2 years ago
  greatbridf f581b0765b feat(string): add string class 2 years ago
  greatbridf 86643b9091 fix(vector): end() return wrong position 2 years ago
  greatbridf 89a69a47e9 feat(vfs): impl. vfs_open to open file and dirs 2 years ago
  greatbridf 44395a727c feat(stdio): impl. strncpy 2 years ago
  greatbridf f1116ddf25 feat(list): impl. find() 2 years ago
  greatbridf 3fd580fe86 feat: find inode according to filename 2 years ago
  greatbridf 60d64c224c refactor: write tmpfs with c++ 2 years ago
  greatbridf 0d93ab9d36 fix: bss_addr type conversion 2 years ago
  greatbridf 9f1b0d0b7d feat: vector and allocator improvement 2 years ago
  greatbridf b103ac85fe fix: use brace init. for mklink file entry 2 years ago
  greatbridf b19b0323e6 feat: create tmpfs and impl. basic ops 2 years ago
  greatbridf a0c10918b1 Merge branch 'new_mem_allocation' 2 years ago
  greatbridf e083913ad7 refactor: move bss initialization to kernel_main 2 years ago
  greatbridf 1ae32368a5 fix: translate iden. mapped ptr in v_ptr_to_p_ptr 2 years ago
  greatbridf 33f97a35c3 Merge branch 'cross-compiling' 2 years ago
  greatbridf bd83189b48 chore: separate qemu args 2 years ago
  greatbridf fe614c21b5 fix: match the two type definitions of kernel_size 2 years ago
  greatbridf f848946130 chore: empty cross compiling toolchain prefix 2 years ago
  greatbridf a3403a2a44 chore: update compiling flags 2 years ago
  greatbridf 7e5a6e89c7 Merge branch 'paging' 2 years ago
  greatbridf d9ed36797d Merge branch 'dev' into paging 2 years ago
  greatbridf 30b511a13f fix: map more pages for the heap 2 years ago
  greatbridf 2dccf820fa fix: release mode sse bug 2 years ago
  greatbridf d923498640 feat: copy on write 2 years ago
  greatbridf 1cc56a7e13 feat: memory initialization 2 years ago
  greatbridf 2eaf205b8a memory allocation 2 years ago
  greatbridf a9ffa8ad1a fix: tty.h not using extern "C" 2 years ago
  greatbridf f2dab67f6e style: remove TODOs 2 years ago
  greatbridf 5c72b6b203 feat: init_paging: check errors 2 years ago
  greatbridf f495739520 style: kernel_main.c include paths 2 years ago
  greatbridf c4c0c61e6b feat: page mapping 2 years ago
  greatbridf b021d6d93d fix: not disabling interrupt while setting up gdt 2 years ago
  greatbridf 7c311199cb working on broken system 2 years ago
  greatbridf 2396f6a355 feat: allocate pages for page tables (BROKEN) 2 years ago
  greatbridf 4ad62d98cf feat: move kernel to 0x100000 2 years ago
  greatbridf 12f53f49eb feat: type bitmap 2 years ago
  greatbridf 69a9725e1f feat: load kernel size 2 years ago
  greatbridf 0d6d8d95fd chore: update Makefile for debugging and running 2 years ago
  greatbridf 7cb2030b14 feat: tty, memcpy and strlen 2 years ago
  greatbridf 177ff70411 feat: serial port read and write 2 years ago
  greatbridf f1e064e225 fix: update loader read size 2 years ago
  greatbridf 3e52ddd462 fix: enable SSE to prevent crashes 2 years ago
  greatbridf ed409420ad chore: update Makefile to run with qemu 2 years ago
  greatbridf 29cbe96c11 chore: update .gitignore 2 years ago
  greatbridf d7bbbc54d6 chore: export compile command for vim and etc. 2 years ago
  greatbridf c6488b7839 chore: supress some warnings concerning types 3 years ago
  greatbridf 682a1ebb2d feat: set new gdt and tss 3 years ago
  greatbridf 17a56ef31e style: simplify kernel_main 3 years ago
  greatbridf 192da56cf8 Merge branch 'fix' into paging 3 years ago
  greatbridf 5c6f57e50f fix: macos build problem 3 years ago
  greatbridf 06c0d7de96 feat: page fault handing 3 years ago
  greatbridf 934bbc12aa fix: wrong cmake script (linker path) 3 years ago
  greatbridf 900b7a9f43 Merge branch 'macos-compiling' into paging 3 years ago
  greatbridf 68225b9fab Merge remote-tracking branch 'origin/paging' into paging 3 years ago
  greatbridf 1a5b8ccba3 feat: cross compiling in macos 3 years ago
  greatbridf 5b08ce1baf fix: change def of size_t 3 years ago
  greatbridf e5736d17d8 feat: add user segments 3 years ago
  greatbridf 3ef0e3e514 feat: print 64bit hex numbers 3 years ago
  greatbridf e6ad94fa10 feat: define ptr_t basing on cpu type 3 years ago
  greatbridf 8263290dfb feat: map 0xc0000000 as kernel space 3 years ago
  greatbridf 7f1ca69928 feat: enable paging 3 years ago
  greatbridf 3a9982a94d feat: initialize pd and pt 3 years ago
  greatbridf 12ac6c5230 change: move kernel loader dest 3 years ago
  greatbridf 42fb5927b1 feat: use full address space 3 years ago
  greatbridf 36c0bb6a52 feat: page directory and page table struct 3 years ago
  greatbridf e0bd7ce1a4 feat: read mem_map from bios 3 years ago
  greatbridf 2ad7c01332 feat: macro printkf 3 years ago
  greatbridf 1298cee68d feat: print long long decimals 3 years ago
  greatbridf 48978f5f74 feat: timer 3 years ago
  greatbridf 9bc1fa9db7 feat: vga support CR 3 years ago
  greatbridf 1be69f0785 feat: improved keyboard event handling 3 years ago
  greatbridf cfba937af6 fix: minus size after erasing element 3 years ago
  greatbridf 127fbbd0af fix: add const version of _size() for list 3 years ago
  greatbridf cb4d47c312 feat: call c++ objects' constructors 3 years ago
  greatbridf d8f7580096 feat: list::empty() 3 years ago
  greatbridf acd56e0f93 feat: keycodes definitions 3 years ago
  greatbridf c07460aae0 chore: gdb notes 3 years ago
  greatbridf 20c4330c5b feat: list container 3 years ago
  greatbridf 17edec9339 feat: print pointer and improvements on stdio 3 years ago
  greatbridf bf43fc164f fix: vga vbuffer overflow 3 years ago
  greatbridf b78d75811a chore: add extern "C" to some headers 3 years ago
  greatbridf f26f9d7c34 feat: add port number for keyboard 3 years ago
  greatbridf d6716c631d chore: use qemu for debugging 3 years ago
  greatbridf 8e0fa0e23a fix: execute cli before setting idt 3 years ago
  greatbridf b442fa0499 chore: generate symbol file and debug info 3 years ago
  greatbridf 91cf3e6e82 fix: change return value of snprintf to ssize_t 3 years ago
  greatbridf a42cf01bcf chore: format 3 years ago
  greatbridf d1816c9600 change: disable stack protector 3 years ago
  greatbridf 989a1f40ec some articles about memory allocation 4 years ago
  greatbridf a2e73c829b malloc documentation 4 years ago
  greatbridf 2de79572aa k_free and split large memory blocks 4 years ago
  greatbridf edd0a3e83a split block 4 years ago
  greatbridf f64531c224 k_malloc 4 years ago
  greatbridf 754f25b2f8 increase memory space used to 64m 4 years ago
  greatbridf a501e2b69c add errno 4 years ago
  greatbridf 723d523b13 generate symbol files 4 years ago
  greatbridf 043b189910 read 16k of kernel 4 years ago
  greatbridf 5e32772cc9 some docs about the interrupt handling 4 years ago
  greatbridf 2900526df3 speed up keyboard int handling 4 years ago
  greatbridf 1b903a6424 use ring_buf to save scan codes 4 years ago
  greatbridf 96db07236f snprintf print hex numbers 4 years ago
  greatbridf 12a1f4b207 fix stdio print negative number 4 years ago
  greatbridf cdd34f456e handle int 13 4 years ago
  greatbridf e2cabea44b add c defs of hlt cli sti 4 years ago
  greatbridf bea738fe10 ring buffer 4 years ago
  greatbridf 6ec402e085 print init idt success info 4 years ago
  greatbridf 27d1d87806 vga buffer looped mode 4 years ago
  greatbridf 468c2091c4 receive keyboard data 4 years ago
  greatbridf 13f90ef413 make vdi 4 years ago
  greatbridf 1f23172be8 initialize idt 4 years ago
  greatbridf bc404e29af align stack 4 years ago
  greatbridf 959bc32960 clear screen on boot 4 years ago
  greatbridf a9fb75786b fix: update CMakeLists.txt 4 years ago
  greatbridf b69d4d795d add size.h and types.h 4 years ago
  greatbridf aedae45086 change vga_printk definitions 4 years ago
  greatbridf 387a79a16e break point 4 years ago
  greatbridf bb030a6eb6 detect memroy 4 years ago
  greatbridf a55ce6a3d1 vga printk supports \n 4 years ago
  greatbridf bf6f14732c snprintf 4 years ago
  greatbridf c19661f79e size_t 4 years ago
  greatbridf 747c03148f make virtualbox vdi 4 years ago
  greatbridf 9c71c66e88 halt system 4 years ago
  greatbridf 7cb648b8c6 get memory size info 4 years ago
  greatbridf 52ebd67efd explicitly convert string pointer type 4 years ago
  greatbridf bbbc09c442 use stdint 4 years ago
  greatbridf 6d4c446ddf printk and put char 4 years ago
  greatbridf 17b272f978 add pragma once 4 years ago
  greatbridf 1b7348b670 check a20 4 years ago
  greatbridf 6b2fab4ef6 introcude c 4 years ago
  greatbridf ac64b6b352 docs 4 years ago
  greatbridf 7b880566be protected mode 4 years ago
  greatbridf 84095c6cd7 read from disk 4 years ago
  greatbridf bbb2dbc19b 128 bytes stack 4 years ago
  greatbridf 09590c450d update .gitignore 4 years ago
  greatbridf cb2c39a5dc initial commit 4 years ago
100 changed files with 7363 additions and 0 deletions
  1. 7 0
      .cargo/config.toml
  2. 29 0
      .clang-format
  3. 23 0
      .gitignore
  4. 78 0
      .rustfmt.toml
  5. 95 0
      CMakeLists.txt
  6. 348 0
      Cargo.lock
  7. 43 0
      Cargo.toml
  8. 78 0
      Makefile.src
  9. 214 0
      README.md
  10. 68 0
      arch/Cargo.lock
  11. 8 0
      arch/Cargo.toml
  12. 54 0
      arch/percpu-macros/Cargo.lock
  13. 12 0
      arch/percpu-macros/Cargo.toml
  14. 21 0
      arch/percpu-macros/src/arch.rs
  15. 117 0
      arch/percpu-macros/src/lib.rs
  16. 14 0
      arch/src/lib.rs
  17. 71 0
      arch/src/x86_64/context.rs
  18. 91 0
      arch/src/x86_64/gdt.rs
  19. 241 0
      arch/src/x86_64/init.rs
  20. 480 0
      arch/src/x86_64/interrupt.rs
  21. 93 0
      arch/src/x86_64/io.rs
  22. 134 0
      arch/src/x86_64/mod.rs
  23. 16 0
      arch/src/x86_64/percpu.rs
  24. 54 0
      arch/src/x86_64/user.rs
  25. 28 0
      build.rs
  26. BIN
      busybox
  27. BIN
      busybox-minimal
  28. 152 0
      configure
  29. 5 0
      doc/assembly.md
  30. 24 0
      doc/bios_functions.md
  31. 25 0
      doc/boot.md
  32. 59 0
      doc/device_driver.md
  33. 75 0
      doc/filesystem.md
  34. BIN
      doc/images/image-0.png
  35. BIN
      doc/images/image-1.png
  36. 260 0
      doc/images/mm.drawio
  37. BIN
      doc/images/mm_layout.png
  38. BIN
      doc/images/mm_zone.png
  39. 21 0
      doc/interrupt.md
  40. 45 0
      doc/malloc.md
  41. 33 0
      doc/mem_layout.txt
  42. 97 0
      doc/memory.md
  43. 90 0
      doc/multi_arch.md
  44. 148 0
      doc/task.md
  45. 71 0
      gblibc/CMakeLists.txt
  46. 16 0
      gblibc/include/alloca.h
  47. 21 0
      gblibc/include/assert.h
  48. 32 0
      gblibc/include/bits/alltypes.h
  49. 27 0
      gblibc/include/bits/ioctl.h
  50. 18 0
      gblibc/include/ctype.h
  51. 35 0
      gblibc/include/dirent.h
  52. 41 0
      gblibc/include/errno.h
  53. 49 0
      gblibc/include/fcntl.h
  54. 35 0
      gblibc/include/poll.h
  55. 69 0
      gblibc/include/signal.h
  56. 11 0
      gblibc/include/stdarg.h
  57. 30 0
      gblibc/include/stdint.h
  58. 80 0
      gblibc/include/stdio.h
  59. 37 0
      gblibc/include/stdlib.h
  60. 50 0
      gblibc/include/string.h
  61. 16 0
      gblibc/include/sys/ioctl.h
  62. 24 0
      gblibc/include/sys/mman.h
  63. 21 0
      gblibc/include/sys/mount.h
  64. 17 0
      gblibc/include/sys/prctl.h
  65. 105 0
      gblibc/include/sys/stat.h
  66. 16 0
      gblibc/include/sys/time.h
  67. 28 0
      gblibc/include/sys/types.h
  68. 19 0
      gblibc/include/sys/uio.h
  69. 43 0
      gblibc/include/sys/utsname.h
  70. 29 0
      gblibc/include/sys/wait.h
  71. 182 0
      gblibc/include/termios.h
  72. 19 0
      gblibc/include/time.h
  73. 63 0
      gblibc/include/unistd.h
  74. 11 0
      gblibc/private-include/devutil.h
  75. 34 0
      gblibc/private-include/list.h
  76. 41 0
      gblibc/private-include/priv-vars.h
  77. 97 0
      gblibc/private-include/syscall.h
  78. 65 0
      gblibc/src/arithmetic.c
  79. 12 0
      gblibc/src/assert.c
  80. 35 0
      gblibc/src/crt0.s
  81. 25 0
      gblibc/src/ctype.c
  82. 77 0
      gblibc/src/dirent.c
  83. 37 0
      gblibc/src/errno.c
  84. 27 0
      gblibc/src/fcntl.c
  85. 116 0
      gblibc/src/init.c
  86. 20 0
      gblibc/src/internal.c
  87. 5 0
      gblibc/src/platform-independent.s
  88. 23 0
      gblibc/src/signal.c
  89. 29 0
      gblibc/src/stat.c
  90. 845 0
      gblibc/src/stdio.c
  91. 286 0
      gblibc/src/stdlib.c
  92. 269 0
      gblibc/src/string.c
  93. 20 0
      gblibc/src/time.c
  94. 249 0
      gblibc/src/unistd.c
  95. 12 0
      gblibc/src/wait.c
  96. 41 0
      gblibstdc++/CMakeLists.txt
  97. 214 0
      gblibstdc++/include/algorithm
  98. 14 0
      gblibstdc++/include/bit
  99. 70 0
      gblibstdc++/include/bits/compressed_pair
  100. 34 0
      gblibstdc++/include/bits/forward

+ 7 - 0
.cargo/config.toml

@@ -0,0 +1,7 @@
+[build]
+target = 'x86_64-unknown-none.json'
+target-dir = 'build'
+
+[unstable]
+build-std-features = ['compiler-builtins-mem']
+build-std = ['core', 'compiler_builtins', 'alloc']

+ 29 - 0
.clang-format

@@ -0,0 +1,29 @@
+---
+BasedOnStyle: Google
+AllowShortBlocksOnASingleLine: 'false'
+AllowShortCaseLabelsOnASingleLine: 'false'
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLoopsOnASingleLine: 'false'
+BreakConstructorInitializers: BeforeComma
+ColumnLimit: '100'
+FixNamespaceComments: 'true'
+IncludeBlocks: Regroup
+IndentWidth: '4'
+NamespaceIndentation: Inner
+SpacesBeforeTrailingComments: '1'
+Language: Cpp
+Standard: Cpp11
+IncludeCategories:
+  - Regex: '^<types/'
+    Priority: '4'
+  - Regex: '^<(kernel|fs|net|driver)/'
+    Priority: '5'
+  - Regex: '^<.*\.h>'
+    Priority: '3'
+  - Regex: '^<.*>'
+    Priority: '2'
+  - Regex: '.*'
+    Priority: '1'
+
+...

+ 23 - 0
.gitignore

@@ -0,0 +1,23 @@
+build/
+
+.vscode/
+
+test/
+
+bx_enh_dbg.ini
+
+.cache/
+*.swp
+
+compile_commands.json
+
+Makefile
+cross-compile.cmake
+
+.DS_Store
+.Spotlight-V100
+.Trashes
+
+.gdbinit
+
+src/bindings.rs

+ 78 - 0
.rustfmt.toml

@@ -0,0 +1,78 @@
+max_width = 100
+hard_tabs = false
+tab_spaces = 4
+newline_style = "Auto"
+indent_style = "Block"
+use_small_heuristics = "Default"
+fn_call_width = 60
+attr_fn_like_width = 70
+struct_lit_width = 18
+struct_variant_width = 35
+array_width = 60
+chain_width = 60
+single_line_if_else_max_width = 60
+single_line_let_else_max_width = 60
+wrap_comments = false
+format_code_in_doc_comments = false
+doc_comment_code_block_width = 100
+comment_width = 80
+normalize_comments = false
+normalize_doc_attributes = false
+format_strings = false
+format_macro_matchers = false
+format_macro_bodies = true
+skip_macro_invocations = []
+hex_literal_case = "Preserve"
+empty_item_single_line = true
+struct_lit_single_line = true
+fn_single_line = false
+where_single_line = false
+imports_indent = "Block"
+imports_layout = "Mixed"
+imports_granularity = "Preserve"
+group_imports = "Preserve"
+reorder_imports = true
+reorder_modules = true
+reorder_impl_items = false
+type_punctuation_density = "Wide"
+space_before_colon = false
+space_after_colon = true
+spaces_around_ranges = false
+binop_separator = "Front"
+remove_nested_parens = true
+combine_control_expr = true
+short_array_element_width_threshold = 10
+overflow_delimited_expr = false
+struct_field_align_threshold = 0
+enum_discrim_align_threshold = 0
+match_arm_blocks = true
+match_arm_leading_pipes = "Never"
+force_multiline_blocks = false
+fn_params_layout = "Tall"
+brace_style = "SameLineWhere"
+control_brace_style = "AlwaysSameLine"
+trailing_semicolon = true
+trailing_comma = "Vertical"
+match_block_trailing_comma = false
+blank_lines_upper_bound = 1
+blank_lines_lower_bound = 0
+edition = "2015"
+version = "One"
+inline_attribute_width = 0
+format_generated_files = true
+generated_marker_line_search_limit = 5
+merge_derives = true
+use_try_shorthand = false
+use_field_init_shorthand = false
+force_explicit_abi = true
+condense_wildcard_suffixes = false
+color = "Auto"
+unstable_features = false
+disable_all_formatting = false
+skip_children = false
+show_parse_errors = true
+error_on_line_overflow = false
+error_on_unformatted = false
+ignore = []
+emit_mode = "Files"
+make_backup = false

+ 95 - 0
CMakeLists.txt

@@ -0,0 +1,95 @@
+cmake_minimum_required(VERSION 3.15)
+project(kernel_main C CXX ASM)
+
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
+set(CMAKE_CXX_LINK_EXECUTABLE
+    "<CMAKE_LINKER> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
+
+set(C_CXX_FLAGS "-nostdinc -nostdlib -mno-sse -mno-mmx -W -Wall -Wextra -Wno-stringop-overflow -Wno-builtin-declaration-mismatch -Wno-format -fverbose-asm -fno-exceptions -ffreestanding -fno-pic -mno-red-zone -mstack-protector-guard=global -mcmodel=kernel")
+set(CMAKE_C_FLAGS "${C_CXX_FLAGS} -Werror=implicit-int -Werror=implicit-function-declaration -Werror=strict-aliasing")
+set(CMAKE_CXX_FLAGS "${C_CXX_FLAGS} -fno-use-cxa-atexit -fno-rtti")
+set(CMAKE_CXX_LINK_FLAGS "-z noexecstack --gc-sections")
+SET(CMAKE_ASM_FLAGS "${CFLAGS} -x assembler-with-cpp")
+set(CMAKE_CXX_STANDARD 20)
+
+if (CMAKE_BUILD_TYPE STREQUAL "Debug")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDEBUG -O0 -g")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDEBUG -O0 -g")
+    set(CARGO_BUILD_TYPE "debug")
+    set(CARGO_BUILD_FLAGS "")
+elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g -DNDEBUG")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -g -DNDEBUG")
+    set(CARGO_BUILD_TYPE "release")
+    set(CARGO_BUILD_FLAGS "--release")
+endif()
+
+if (NOT DEFINED FDISK_BIN)
+    set(FDISK_BIN fdisk)
+endif()
+
+add_subdirectory(gblibc)
+add_subdirectory(gblibstdc++)
+add_subdirectory(user-space-program)
+
+set(BOOTLOADER_SOURCES src/boot.s
+                       src/mbr.S
+                       )
+
+set(KERNEL_MAIN_SOURCES src/kinit.cpp
+                        src/kernel/async/lock.cc
+                        src/kernel/allocator.cc
+                        src/kernel/mem/slab.cc
+                        src/kernel/hw/acpi.cc
+                        src/kernel/hw/pci.cc
+                        src/types/libstdcpp.cpp
+                        include/defs.hpp
+                        include/kernel/async/lock.hpp
+                        include/kernel/mem/paging.hpp
+                        include/kernel/mem/slab.hpp
+                        include/kernel/mem/types.hpp
+                        include/kernel/utsname.hpp
+                        include/kernel/hw/acpi.hpp
+                        include/kernel/hw/pci.hpp
+                        include/kernel/hw/port.hpp
+                        include/types/list.hpp
+                        include/types/types.h
+                        include/types/allocator.hpp
+                        include/kernel/log.hpp
+                        )
+
+add_executable(kernel.out ${KERNEL_MAIN_SOURCES} ${BOOTLOADER_SOURCES})
+add_dependencies(kernel.out rustpart)
+target_link_libraries(kernel.out gblibc gblibstdc++ gbos_rust_part)
+target_include_directories(kernel.out PRIVATE ${PROJECT_SOURCE_DIR}/include)
+target_link_options(kernel.out PRIVATE
+    -T "${CMAKE_SOURCE_DIR}/src/kernel.ld"
+    -L "${CMAKE_BINARY_DIR}/x86_64-unknown-none/${CARGO_BUILD_TYPE}"
+    --no-check-sections
+    )
+set_target_properties(kernel.out PROPERTIES LINK_DEPENDS "${CMAKE_SOURCE_DIR}/src/kernel.ld")
+set_source_files_properties(src/mbr.S PROPERTIES OBJECT_DEPENDS
+    "${CMAKE_BINARY_DIR}/x86_64-unknown-none/${CARGO_BUILD_TYPE}/libgbos_rust_part.a"
+    )
+
+add_custom_target(rustpart
+    COMMAND cargo build ${CARGO_BUILD_FLAGS}
+)
+
+add_custom_command(OUTPUT mbr_hole.bin
+    DEPENDS kernel.out
+    COMMAND ${CMAKE_OBJCOPY} --strip-debug -O binary ${CMAKE_BINARY_DIR}/kernel.out mbr_hole.bin
+)
+
+add_custom_target(boot.img
+    DEPENDS mbr_hole.bin
+    DEPENDS user_space_programs
+    COMMAND make -C ${CMAKE_SOURCE_DIR} image
+)
+
+add_custom_command(OUTPUT run
+    POST_BUILD
+    DEPENDS boot.img
+    COMMAND bochs -f ${CMAKE_SOURCE_DIR}/bochs.conf
+)

+ 348 - 0
Cargo.lock

@@ -0,0 +1,348 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "arch"
+version = "0.1.0"
+dependencies = [
+ "cfg-if",
+ "percpu-macros",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+
+[[package]]
+name = "bindgen"
+version = "0.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f"
+dependencies = [
+ "bitflags",
+ "cexpr",
+ "clang-sys",
+ "itertools",
+ "log",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "rustc-hash",
+ "shlex",
+ "syn",
+]
+
+[[package]]
+name = "bitflags"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+
+[[package]]
+name = "cexpr"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
+dependencies = [
+ "nom",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clang-sys"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
+dependencies = [
+ "glob",
+ "libc",
+ "libloading",
+]
+
+[[package]]
+name = "either"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
+
+[[package]]
+name = "gbos-rust-part"
+version = "0.1.0"
+dependencies = [
+ "arch",
+ "bindgen",
+ "bitflags",
+ "itertools",
+ "lazy_static",
+ "spin",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
+[[package]]
+name = "itertools"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+dependencies = [
+ "spin",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.164"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
+
+[[package]]
+name = "libloading"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
+dependencies = [
+ "cfg-if",
+ "windows-targets",
+]
+
+[[package]]
+name = "lock_api"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "percpu-macros"
+version = "0.1.0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "prettyplease"
+version = "0.2.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
+dependencies = [
+ "proc-macro2",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+dependencies = [
+ "lock_api",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

+ 43 - 0
Cargo.toml

@@ -0,0 +1,43 @@
+[package]
+name = "gbos-rust-part"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+crate-type = ["staticlib"]
+
+[dependencies]
+arch = { path = "./arch" }
+bitflags = "2.6.0"
+itertools = { version = "0.13.0", default-features = false }
+lazy_static = { version = "1.5.0", features = ["spin_no_std"] }
+spin = "0.9.8"
+
+[features]
+default = ["smp"]
+debug_syscall = []
+smp = []
+
+[build-dependencies]
+bindgen = "0.70.1"
+
+[profile.dev]
+panic = "abort"
+
+[profile.dev.package.core]
+opt-level = 2
+debug = true
+
+[profile.dev.package."*"]
+opt-level = 2
+debug = false
+
+[profile.dev.build-override]
+opt-level = 0
+codegen-units = 256
+debug = false
+
+[profile.release.build-override]
+opt-level = 0
+codegen-units = 256
+debug = false

+ 78 - 0
Makefile.src

@@ -0,0 +1,78 @@
+# disable kvm to debug triple faults
+QEMU_BIN=##PLACEHOLDER_1##
+GDB_BIN=##PLACEHOLDER_2##
+QEMU_ACCELERATION_FLAG=##PLACEHOLDER_3##
+QEMU_DEBUG_FLAG=#-d cpu_reset,int
+QEMU_ARGS=-machine q35 -drive id=disk,file=build/boot.img,format=raw,if=none \
+	-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -smp 4 \
+	-no-reboot -no-shutdown $(QEMU_ACCELERATION_FLAG) $(QEMU_DEBUG_FLAG)
+
+FDISK_BIN ?= ##PLACEHOLDER_5##
+
+CROSS_COMPILE=##PLACEHOLDER_4##
+.PHONY: run
+run: build
+	$(QEMU_BIN) $(QEMU_ARGS) -display curses -S -s
+.PHONY: srun
+srun: build
+	$(QEMU_BIN) $(QEMU_ARGS) -display none -S -s -serial mon:stdio
+.PHONY: nativerun
+nativerun: build
+	$(QEMU_BIN) $(QEMU_ARGS) -display none -serial mon:stdio
+
+.PHONY: prepare
+prepare:
+	cmake -Bbuild -DCMAKE_BUILD_TYPE=Debug $(CROSS_COMPILE)
+	cp build/compile_commands.json .
+
+.PHONY: reprepare
+reprepare: clean prepare
+	true
+
+.PHONY: build
+build:
+	cmake --build build -j 6 --target boot.img
+
+.PHONY: clean
+clean:
+	-rm -rf build
+	-rm compile_commands.json
+
+.PHONY: clean-all
+clean-all: clean
+	-rm Makefile
+
+.PHONY: debug
+debug:
+	-$(GDB_BIN) --symbols=build/kernel.out \
+		-iex 'source pretty-print.py' \
+		-iex 'set pagination off' \
+		-iex 'set output-radix 16' \
+		-iex 'set print asm-demangle on' \
+		-iex 'set print pretty on' \
+		-iex 'target remote:1234'
+	-killall $(QEMU_BIN)
+
+.PHONY: tmux-debug
+tmux-debug:
+	tmux new-session -s gbos-debug -d
+	-tmux split-window -t gbos-debug -hf
+	-tmux send-keys -t gbos-debug:1.1 'make srun' C-m
+	-tmux send-keys -t gbos-debug:1.2 'make debug' C-m C-m
+	-tmux attach -t gbos-debug
+	tmux kill-session -t gbos-debug
+
+build/fs.img: init_script.sh
+	sh script/build-img.sh
+
+build/boot.img: build/fs.img build/mbr_hole.bin
+	dd if=build/mbr_hole.bin of=build/boot.img
+	dd if=build/fs.img of=build/boot.img bs=$(shell expr 4 \* 1024 \* 1024) seek=1 conv=notrunc
+	sh -c 'echo n; echo; echo; echo 8192; echo; echo a; echo w' | $(FDISK_BIN) build/boot.img
+
+build/boot.vdi: build/boot.img
+	-rm build/boot.vdi
+	VBoxManage convertfromraw $< $@ --format VDI
+
+.PHONY: image
+image: build/boot.img

+ 214 - 0
README.md

@@ -0,0 +1,214 @@
+# Eonix
+
+*Eonix* 是一个基于 *Rust* 编写的开源项目,旨在提供一个适用于多处理器多架构的宏内核操作系统。
+
+*Eonix* 项目的目标是创建一个高效、安全、可靠的操作系统。我们的目标是提供一个简单的内核设计,使得它易于理解和维护。同时,我们也希望 *Eonix* 能够提供足够复杂的特性,如虚拟内存管理、多进程支持、*POSIX* 兼容的文件系统模型、易于使用的设备驱动开发接口等,使其拥有较强的实用性。
+
+## 项目特性
+
+- [x] 多处理器支持
+- [x] 多架构支持(平台相关接口抽象,目前只有 x86_64 一种实现,正在加入其他架构的实现)
+- [x] 内存管理
+- [x] 进程管理
+- [x] 文件系统
+- [x] *POSIX* 兼容性,兼容 *Linux* 系统调用接口
+- [x] 静态 ELF 加载器
+- [x] TTY 及任务控制接口(正在进一步实现)
+- [x] FAT32 文件系统的读取实现
+- [ ] 全部 Rust 化(只剩一点点)
+- [ ] 网卡驱动(WIP)
+- [ ] POSIX 线程接口(WIP)
+- [ ] 动态加载器(WIP)
+- [ ] 用户、权限(WIP)
+
+项目经测试可使用 *busybox* 中大多数功能,并且该内核使用 *busybox* 搭配 init 脚本启动,运行 *busybox* 提供的 *ash* 来执行 shell 命令。
+
+![测试](doc/images/image-0.png)
+![test pipes](doc/images/image-1.png)
+
+## 初赛文档
+
+本项目开发时代码仓库在 [GitHub](https://github.com/greatbridf/osdev.git)。
+
+- [启动加载](https://gitlab.eduxiji.net/T202410247994622/project2608132-275906/-/blob/master/doc/boot.md)
+- [内存管理](https://gitlab.eduxiji.net/T202410247994622/project2608132-275906/-/blob/master/doc/memory.md)
+- [进程管理](https://gitlab.eduxiji.net/T202410247994622/project2608132-275906/-/blob/master/doc/task.md)
+- [文件系统](https://gitlab.eduxiji.net/T202410247994622/project2608132-275906/-/blob/master/doc/filesystem.md)
+- [设备驱动](https://gitlab.eduxiji.net/T202410247994622/project2608132-275906/-/blob/master/doc/device_driver.md)
+- [多平台支持](https://gitlab.eduxiji.net/T202410247994622/project2608132-275906/-/blob/master/doc/multi_arch.md)
+
+## 代码树结构
+
+```
+.
+├── arch                          # 平台相关代码
+│   ├── percpu-macros             # percpu变量宏
+│   └── src
+│       └── x86_64                # x86_64
+│           ├── context.rs        # 上下文切换相关
+│           ├── gdt.rs            # x86 架构 GDT相关
+│           ├── init.rs           # 内核初始化相关
+│           ├── interrupt.rs      # 中断相关
+│           ├── io.rs             # IO 相关
+│           ├── percpu.rs         # percpu 变量相关
+│           └── user.rs           # 用户态相关
+├── busybox                       # 默认选项编译的busybox
+├── busybox-minimal               # 预编译的精简版busybox
+├── configure                     # 编译准备用
+├── doc                           # 开发文档
+├── gblibc                        # C 标准库实现
+├── gblibstdc++                   # C++ 标准库
+├── include                       # C++ 头文件
+├── init_script.sh                # init 进程使用的脚本文件
+├── src
+│   ├── boot.s                    # 启动代码
+│   ├── driver
+│   │   ├── ahci                  # AHCI 控制器驱动
+│   │   ├── e1000e                # e1000e 网卡驱动(WIP)
+│   │   └── serial.rs             # 串口驱动
+│   ├── driver.rs                 # 驱动相关
+│   ├── elf.rs                    # ELF 加载器
+│   ├── fs
+│   │   ├── fat32.rs              # FAT32 实现
+│   │   ├── procfs.rs             # procfs 实现
+│   │   └── tmpfs.rs              # ramfs 实现
+│   ├── hash.rs                   # Hash 函数等
+│   ├── intrusive_list.rs         # 侵入式链表
+│   ├── io.rs                     # IO 工具类
+│   ├── kernel
+│   │   ├── allocator.cc          # C++ 分配器
+│   │   ├── async
+│   │   │   └── lock.cc           # C++ 中自旋锁
+│   │   ├── block.rs              # 块设备抽象
+│   │   ├── chardev.rs            # 字符设备抽象
+│   │   ├── console.rs            # 内核 console 抽象
+│   │   ├── constants.rs          # 常量定义
+│   │   ├── cpu.rs                # CPU 状态相关
+│   │   ├── hw
+│   │   │   ├── acpi.cc           # ACPI 数据相关(待移除)
+│   │   │   └── pci.cc            # PCI 设备相关(待移除)
+│   │   ├── interrupt.rs          # 中断相关(共通)
+│   │   ├── mem
+│   │   │   ├── address.rs        # 虚拟地址等抽象
+│   │   │   ├── mm_area.rs        # 映射区域
+│   │   │   ├── mm_list
+│   │   │   │   └── page_fault.rs # 处理Page Fault
+│   │   │   ├── mm_list.rs        # 地址空间
+│   │   │   ├── page_alloc.rs     # 页分配器
+│   │   │   ├── page_table.rs     # 页表
+│   │   │   ├── paging.rs         # 分页相关
+│   │   │   ├── phys.rs           # 物理地址访问相关
+│   │   │   └── slab.cc           # Slab 分配器
+│   │   ├── smp.rs                # 多处理器相关
+│   │   ├── syscall
+│   │   │   ├── file_rw.rs        # 文件相关syscall
+│   │   │   ├── mm.rs             # 内存相关syscall
+│   │   │   ├── net.rs            # 网络相关syscall
+│   │   │   ├── procops.rs        # 进程管理相关syscall
+│   │   │   └── sysinfo.rs        # sys_utsname
+│   │   ├── syscall.rs            # syscall相关定义
+│   │   ├── task
+│   │   │   ├── kstack.rs         # 内核栈操作
+│   │   │   ├── process.rs        # 进程
+│   │   │   ├── process_group.rs  # 进程组
+│   │   │   ├── process_list.rs   # 进程列表
+│   │   │   ├── scheduler.rs      # 调度器
+│   │   │   ├── session.rs        # 会话
+│   │   │   ├── signal.rs         # 信号处理
+│   │   │   └── thread.rs         # 线程
+│   │   ├── task.rs               # 任务模块
+│   │   ├── terminal.rs           # 终端抽象
+│   │   ├── timer.rs              # 时钟模块
+│   │   ├── user
+│   │   │   └── dataflow.rs       # 用户空间数据访问
+│   │   ├── user.rs
+│   │   └── vfs
+│   │       ├── dentry
+│   │       │   └── dcache.rs     # Dentry 缓存
+│   │       ├── dentry.rs         # Dentry
+│   │       ├── file.rs           # 打开的文件
+│   │       ├── filearray.rs      # 用户的文件数组
+│   │       ├── inode.rs          # Inode
+│   │       ├── mount.rs          # 文件系统挂载
+│   │       └── vfs.rs            # 虚拟文件系统
+│   ├── kernel.ld                 # 链接脚本
+│   ├── kernel.rs
+│   ├── kinit.cpp            # 初始化
+│   ├── lib.rs
+│   ├── mbr.S                # MBR 代码
+│   ├── net
+│   │   └── netdev.rs        # 网络设备抽象
+│   ├── path.rs              # 路径处理
+│   ├── rcu.rs               # RCU 的一个临时实现
+│   ├── sync
+│   │   ├── condvar.rs       # 条件变量
+│   │   ├── lock.rs          # 抽象锁类
+│   │   ├── locked.rs        # 依赖锁变量
+│   │   ├── semaphore.rs     # 信号量
+│   │   ├── spin.rs          # 自旋锁
+│   │   └── strategy.rs      # 锁策略
+│   ├── sync.rs              # 同步模块
+│   └── types
+│       └── libstdcpp.cpp    # C++ 标准库用
+├── user-space-program       # 测试用用户程序
+└── x86_64-unknown-none.json # Rust 用 x86_64 工具链文件
+```
+
+# 编译 & 运行
+
+## 构建依赖
+
+#### 编译
+
+- [GCC (测试过)](https://gcc.gnu.org/) or
+
+- [Rust(nightly-2024-12-18)](https://www.rust-lang.org/)
+- [CMake](https://cmake.org/)
+
+#### 生成硬盘镜像
+
+- [(Optional) busybox (项目目录下有预编译过的busybox)](https://www.busybox.net/)
+- [fdisk](https://www.gnu.org/software/fdisk/)
+- [mtools](http://www.gnu.org/software/mtools/)
+
+#### 调试 & 运行
+
+- [GDB](https://www.gnu.org/software/gdb/)
+- [QEMU](https://www.qemu.org/)
+
+## 编译及运行命令
+
+```bash
+# 配置构建环境
+./configure && make prepare && make build
+
+# 直接运行
+
+make nativerun
+
+# 如果需要调试
+
+# 1: 启动调试
+make srun
+
+# 2: 启动调试器
+make debug
+
+# 或者如果有 tmux
+
+make tmux-debug
+```
+
+可能需要在运行 `./configure` 时在环境变量中指定正确版本的构建工具。
+
+- `QEMU`: 用于调试运行的 QEMU。默认使用 `qemu-system-x86_64`。
+- `GDB`: 用于 `make debug` 的 GDB。我们将默认查找 `gdb` 或者是 `x86_64-elf-gdb` 并检查支持的架构。
+- `FDISK_BIN`: 用于创建磁盘镜像分区表的 fdisk 可执行文件。默认使用 `fdisk`。
+
+如果正在进行交叉编译,请在运行 `./configure` 时将 `CROSS_COMPILE` 设置为你的交叉编译器的相应目标三元组。
+
+## 运行自己编译的程序
+
+项目目录下的 `user` 目录主要是出于一些*历史*原因存在,几乎没有任何用处。所以不要尝试查看里面的内容。
+
+要将你的程序(可以使用任何编译器为i386架构编译,静态链接)复制到构建的磁盘镜像中,你可以编辑 `CMakeLists.txt` 并在 `boot.img` 部分添加一行。你也可以尝试编辑 `init_script.sh` 以自定义启动过程。

+ 68 - 0
arch/Cargo.lock

@@ -0,0 +1,68 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "arch"
+version = "0.1.0"
+dependencies = [
+ "cfg-if",
+ "percpu",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "percpu"
+version = "0.1.0"
+dependencies = [
+ "percpu-macros",
+]
+
+[[package]]
+name = "percpu-macros"
+version = "0.1.0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"

+ 8 - 0
arch/Cargo.toml

@@ -0,0 +1,8 @@
+[package]
+name = "arch"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+percpu-macros = { path="./percpu-macros" }
+cfg-if = "1.0"

+ 54 - 0
arch/percpu-macros/Cargo.lock

@@ -0,0 +1,54 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "percpu-macros"
+version = "0.1.0"
+dependencies = [
+ "cfg-if",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"

+ 12 - 0
arch/percpu-macros/Cargo.toml

@@ -0,0 +1,12 @@
+[package]
+name = "percpu-macros"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+proc-macro2 = "1.0"
+quote = "1.0"
+syn = { version = "2.0", features = ["full"] }

+ 21 - 0
arch/percpu-macros/src/arch.rs

@@ -0,0 +1,21 @@
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{Ident, Type};
+
+/// Get the base address for percpu variables of the current thread.
+pub fn get_percpu_pointer(percpu: &Ident, ty: &Type) -> TokenStream {
+    quote! {
+        #[cfg(target_arch = "x86_64")] {
+            let base: *mut #ty;
+            ::core::arch::asm!(
+                "mov %gs:0, {address}",
+                "add ${percpu_pointer}, {address}",
+                percpu_pointer = sym #percpu,
+                address = out(reg) base,
+                options(att_syntax)
+            );
+            base
+        }
+    }
+    .into()
+}

+ 117 - 0
arch/percpu-macros/src/lib.rs

@@ -0,0 +1,117 @@
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+use quote::{format_ident, quote};
+use syn::{parse_macro_input, ItemStatic};
+
+mod arch;
+
+#[proc_macro_attribute]
+pub fn define_percpu(attrs: TokenStream, item: TokenStream) -> TokenStream {
+    if !attrs.is_empty() {
+        panic!("`define_percpu` attribute does not take any arguments");
+    }
+
+    let item = parse_macro_input!(item as ItemStatic);
+    let vis = &item.vis;
+    let ident = &item.ident;
+    let ty = &item.ty;
+    let expr = &item.expr;
+
+    let is_bool = quote!(#ty).to_string().as_str() == "bool";
+    let is_integer =
+        ["u8", "u16", "u32", "u64", "usize"].contains(&quote!(#ty).to_string().as_str());
+
+    let is_atomic_like = is_bool || is_integer || quote!(#ty).to_string().contains("NonNull");
+
+    let inner_ident = format_ident!("_percpu_inner_{}", ident);
+    let access_ident = format_ident!("_access_{}", ident);
+
+    let integer_methods = if is_integer {
+        quote! {
+            pub fn add(&self, value: #ty) {
+                *unsafe { self.as_mut() } += value;
+            }
+
+            pub fn sub(&self, value: #ty) {
+                *unsafe { self.as_mut() } -= value;
+            }
+        }
+    } else {
+        quote! {}
+    };
+
+    let preempt_disable = if !is_atomic_like {
+        quote! { crate::sync::preempt::disable(); }
+    } else {
+        quote! {}
+    };
+
+    let preempt_enable = if !is_atomic_like {
+        quote! { crate::sync::preempt::enable(); }
+    } else {
+        quote! {}
+    };
+
+    let as_ptr = arch::get_percpu_pointer(&inner_ident, &ty);
+
+    quote! {
+        #[link_section = ".percpu"]
+        #[allow(non_upper_case_globals)]
+        static mut #inner_ident: #ty = #expr;
+        #[allow(non_camel_case_types)]
+        #vis struct #access_ident;
+        #vis static #ident: #access_ident = #access_ident;
+
+        impl #access_ident {
+            /// # Safety
+            /// This function is unsafe because it allows for mutable aliasing of the percpu
+            /// variable.
+            /// Make sure that preempt is disabled when calling this function.
+            pub unsafe fn as_ptr(&self) -> *mut #ty {
+                #as_ptr
+            }
+
+            pub fn get(&self) -> #ty {
+                #preempt_disable
+                let value = unsafe { self.as_ptr().read() };
+                #preempt_enable
+                value
+            }
+
+            pub fn set(&self, value: #ty) {
+                #preempt_disable
+                unsafe { self.as_ptr().write(value) }
+                #preempt_enable
+            }
+
+            pub fn swap(&self, mut value: #ty) -> #ty {
+                #preempt_disable
+                unsafe { self.as_ptr().swap(&mut value) }
+                #preempt_enable
+                value
+            }
+
+            /// # Safety
+            /// This function is unsafe because it allows for immutable aliasing of the percpu
+            /// variable.
+            /// Make sure that preempt is disabled when calling this function.
+            pub unsafe fn as_ref(&self) -> & #ty {
+                // SAFETY: This is safe because `as_ptr()` is guaranteed to be valid.
+                self.as_ptr().as_ref().unwrap()
+            }
+
+            /// # Safety
+            /// This function is unsafe because it allows for mutable aliasing of the percpu
+            /// variable.
+            /// Make sure that preempt is disabled when calling this function.
+            pub unsafe fn as_mut(&self) -> &mut #ty {
+                // SAFETY: This is safe because `as_ptr()` is guaranteed to be valid.
+                self.as_ptr().as_mut().unwrap()
+            }
+
+            #integer_methods
+        }
+    }
+    .into()
+}

+ 14 - 0
arch/src/lib.rs

@@ -0,0 +1,14 @@
+#![no_std]
+#![feature(naked_functions)]
+
+cfg_if::cfg_if! {
+    if #[cfg(target_arch = "x86_64")] {
+        mod x86_64;
+        pub use self::x86_64::*;
+    } else if #[cfg(target_arch = "riscv64")] {
+        mod riscv;
+        pub use self::riscv::*;
+    } else if #[cfg(target_arch = "aarch64")]{
+        // TODO!!!
+    }
+}

+ 71 - 0
arch/src/x86_64/context.rs

@@ -0,0 +1,71 @@
+use core::arch::naked_asm;
+
+#[repr(C)]
+#[derive(Debug, Default)]
+struct ContextSwitchFrame {
+    r15: u64,
+    r14: u64,
+    r13: u64,
+    r12: u64,
+    rbx: u64,
+    rbp: u64,
+    eflags: u64,
+    rip: u64,
+}
+
+/// Necessary hardware states of task for context switch
+pub struct TaskContext {
+    /// The kernel stack pointer
+    pub rsp: u64,
+    // Extended states, i.e., FP/SIMD states to do!
+}
+
+impl TaskContext {
+    pub const fn new() -> Self {
+        Self { rsp: 0 }
+    }
+
+    pub fn init(&mut self, entry: usize, kstack_top: usize) {
+        unsafe {
+            let frame_ptr = (kstack_top as *mut ContextSwitchFrame).sub(1);
+            core::ptr::write(
+                frame_ptr,
+                ContextSwitchFrame {
+                    rip: entry as u64,
+                    eflags: 0x200,
+                    ..Default::default()
+                },
+            );
+            self.rsp = frame_ptr as u64;
+        }
+    }
+
+    #[inline(always)]
+    pub fn switch_to(&mut self, next_task: &mut Self) {
+        unsafe { _switch_to(&mut self.rsp, &mut next_task.rsp) }
+    }
+}
+
+#[naked]
+unsafe extern "C" fn _switch_to(current_context_sp: &mut u64, next_context_sp: &mut u64) {
+    naked_asm!(
+        "pushf",
+        "push %rbp",
+        "push %rbx",
+        "push %r12",
+        "push %r13",
+        "push %r14",
+        "push %r15",
+        "mov %rsp, (%rdi)",
+        "mov (%rsi), %rsp",
+        "pop %r15",
+        "pop %r14",
+        "pop %r13",
+        "pop %r12",
+        "pop %rbx",
+        "pop %rbp",
+        "popf",
+        "ret",
+        options(att_syntax),
+    );
+}

+ 91 - 0
arch/src/x86_64/gdt.rs

@@ -0,0 +1,91 @@
+use crate::TSS;
+use core::arch::asm;
+
+#[repr(transparent)]
+#[derive(Debug, Clone, Copy)]
+pub struct GDTEntry(u64);
+
+pub struct GDT([GDTEntry; GDT::LEN]);
+
+impl GDTEntry {
+    const NULL: Self = Self(0);
+
+    const KERNEL_CODE64: Self = Self::new(0, 0, 0x9a, 0x2);
+    const KERNEL_DATA64: Self = Self::new(0, 0, 0x92, 0x0);
+
+    const USER_CODE64: Self = Self::new(0, 0, 0xfa, 0x2);
+    const USER_DATA64: Self = Self::new(0, 0, 0xf2, 0x0);
+
+    const USER_CODE32: Self = Self::new(0, 0xfffff, 0xfa, 0xc);
+    const USER_DATA32: Self = Self::new(0, 0xfffff, 0xf2, 0xc);
+
+    pub const fn new(base: u32, limit: u32, access: u8, flags: u8) -> Self {
+        let mut entry = 0u64;
+        entry |= (limit & 0x0000_ffff) as u64;
+        entry |= ((limit & 0x000f_0000) as u64) << 32;
+        entry |= ((base & 0x00ff_ffff) as u64) << 16;
+        entry |= ((base & 0xff00_0000) as u64) << 32;
+        entry |= (access as u64) << 40;
+        entry |= (flags as u64) << 52;
+
+        GDTEntry(entry)
+    }
+
+    pub const fn new_ldt(base: u64, limit: u32) -> [Self; 2] {
+        let first = Self::new(base as u32, limit, 0x82, 0x0);
+        let second = Self(base >> 32);
+        [first, second]
+    }
+
+    pub const fn new_tss(base: u64, limit: u32) -> [Self; 2] {
+        let first = Self::new(base as u32, limit, 0x89, 0x0);
+        let second = Self(base >> 32);
+        [first, second]
+    }
+}
+
+impl GDT {
+    const LEN: usize = 10;
+    const TLS32_INDEX: usize = 7;
+    const TSS_INDEX: usize = 8;
+
+    pub fn new() -> Self {
+        Self([
+            GDTEntry::NULL,
+            GDTEntry::KERNEL_CODE64,
+            GDTEntry::KERNEL_DATA64,
+            GDTEntry::USER_CODE64,
+            GDTEntry::USER_DATA64,
+            GDTEntry::USER_CODE32,
+            GDTEntry::USER_DATA32,
+            GDTEntry::NULL, // User TLS 32bit
+            GDTEntry::NULL, // TSS Descriptor Low
+            GDTEntry::NULL, // TSS Descriptor High
+        ])
+    }
+
+    pub fn set_tss(&mut self, base: u64) {
+        let tss = GDTEntry::new_tss(base, size_of::<TSS>() as u32 - 1);
+        self.0[Self::TSS_INDEX] = tss[0];
+        self.0[Self::TSS_INDEX + 1] = tss[1];
+    }
+
+    pub fn set_tls32(&mut self, desc: GDTEntry) {
+        self.0[Self::TLS32_INDEX] = desc;
+    }
+
+    pub unsafe fn load(&self) {
+        let len = Self::LEN * 8 - 1;
+        let descriptor: [u64; 2] = [(len as u64) << 48, self.0.as_ptr() as u64];
+        assert!(len < 0x10000, "GDT too large");
+
+        let descriptor_address = &descriptor as *const _ as usize + 6;
+        asm!(
+            "lgdt ({})",
+            "ltr %ax",
+            in(reg) descriptor_address,
+            in("ax") Self::TSS_INDEX as u16 * 8,
+            options(att_syntax)
+        );
+    }
+}

+ 241 - 0
arch/src/x86_64/init.rs

@@ -0,0 +1,241 @@
+use core::{
+    alloc::Layout,
+    pin::Pin,
+    ptr::{addr_of, NonNull},
+};
+
+use super::{enable_sse, percpu::init_percpu_area_thiscpu, GDTEntry, InterruptControl, GDT};
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+#[allow(non_camel_case_types)]
+struct TSS_SP {
+    low: u32,
+    high: u32,
+}
+
+#[repr(C)]
+pub struct TSS {
+    _reserved1: u32,
+    rsp: [TSS_SP; 3],
+    _reserved2: u32,
+    _reserved3: u32,
+    ist: [TSS_SP; 7],
+    _reserved4: u32,
+    _reserved5: u32,
+    _reserved6: u16,
+    iomap_base: u16,
+}
+
+impl TSS {
+    pub fn new() -> Self {
+        Self {
+            _reserved1: 0,
+            rsp: [TSS_SP { low: 0, high: 0 }; 3],
+            _reserved2: 0,
+            _reserved3: 0,
+            ist: [TSS_SP { low: 0, high: 0 }; 7],
+            _reserved4: 0,
+            _reserved5: 0,
+            _reserved6: 0,
+            iomap_base: 0,
+        }
+    }
+
+    pub fn set_rsp0(&mut self, rsp: u64) {
+        self.rsp[0].low = rsp as u32;
+        self.rsp[0].high = (rsp >> 32) as u32;
+    }
+}
+
+/// Architecture-specific per-cpu status.
+#[allow(dead_code)]
+pub struct CPUStatus {
+    id: usize,
+    gdt: GDT,
+    tss: TSS,
+
+    percpu_area: NonNull<u8>,
+    pub interrupt: InterruptControl,
+}
+
+impl CPUStatus {
+    pub unsafe fn new_thiscpu<F>(allocate: F) -> Self
+    where
+        F: FnOnce(Layout) -> NonNull<u8>,
+    {
+        const PAGE_SIZE: usize = 0x1000;
+        extern "C" {
+            static PERCPU_PAGES: usize;
+            fn _PERCPU_DATA_START();
+        }
+
+        let percpu_area = allocate(Layout::from_size_align_unchecked(
+            PERCPU_PAGES * PAGE_SIZE,
+            PAGE_SIZE,
+        ));
+
+        percpu_area.copy_from_nonoverlapping(
+            NonNull::new(_PERCPU_DATA_START as *mut u8).unwrap(),
+            PERCPU_PAGES * PAGE_SIZE,
+        );
+
+        let (interrupt_control, cpuid) = InterruptControl::new();
+
+        init_percpu_area_thiscpu(percpu_area);
+        Self {
+            id: cpuid,
+            gdt: GDT::new(),
+            tss: TSS::new(),
+            percpu_area,
+            interrupt: interrupt_control,
+        }
+    }
+
+    /// Load GDT and TSS in place.
+    ///
+    /// # Safety
+    /// Make sure preemption and interrupt are disabled before calling this function.
+    pub unsafe fn init(self: Pin<&mut Self>) {
+        enable_sse();
+
+        // SAFETY: We don't move the object.
+        let self_mut = self.get_unchecked_mut();
+
+        let tss_addr = addr_of!(self_mut.tss);
+        self_mut.gdt.set_tss(tss_addr as u64);
+        self_mut.gdt.load();
+
+        // SAFETY: `self` is pinned, so are its fields.
+        Pin::new_unchecked(&mut self_mut.interrupt).setup_idt();
+        self_mut.interrupt.setup_timer();
+    }
+
+    /// Bootstrap all CPUs.
+    /// This should only be called on the BSP.
+    pub unsafe fn bootstrap_cpus(&self) {
+        self.interrupt.send_sipi();
+    }
+
+    pub unsafe fn set_rsp0(&mut self, rsp: u64) {
+        self.tss.set_rsp0(rsp);
+    }
+
+    pub unsafe fn set_tls32(&mut self, desc: GDTEntry) {
+        self.gdt.set_tls32(desc);
+    }
+
+    pub fn cpuid(&self) -> usize {
+        self.id
+    }
+}
+
+#[macro_export]
+macro_rules! define_smp_bootstrap {
+    ($cpu_count:literal, $ap_entry:ident, $alloc_kstack:tt) => {
+        #[no_mangle]
+        static BOOT_SEMAPHORE: core::sync::atomic::AtomicU64 =
+            core::sync::atomic::AtomicU64::new(0);
+        #[no_mangle]
+        static BOOT_STACK: core::sync::atomic::AtomicU64 =
+            core::sync::atomic::AtomicU64::new(0);
+
+        #[no_mangle]
+        static CPU_COUNT: core::sync::atomic::AtomicU64 =
+            core::sync::atomic::AtomicU64::new(0);
+
+        core::arch::global_asm!(
+            r#"
+        .pushsection .stage1.smp
+        .code16
+        .globl ap_bootstrap
+        .type ap_bootstrap, @function
+        ap_bootstrap:
+            ljmp $0x0, $.Lap1
+
+        .Lap1:
+            # we use the shared gdt for cpu bootstrapping
+            lgdt .Lshared_gdt_desc
+
+            # set msr
+            mov $0xc0000080, %ecx
+            rdmsr
+            or $0x901, %eax # set LME, NXE, SCE
+            wrmsr
+
+            # set cr4
+            mov %cr4, %eax
+            or $0xa0, %eax # set PAE, PGE
+            mov %eax, %cr4
+
+            # load new page table
+            mov ${KERNEL_PML4}, %eax
+            mov %eax, %cr3
+
+            mov %cr0, %eax
+            // SET PE, WP, PG
+            or $0x80010001, %eax
+            mov %eax, %cr0
+
+            ljmp $0x08, $.Lap_bootstrap_end
+
+        .align 16
+        .Lshared_gdt_desc:
+            .8byte 0x0000000000005f
+
+        .code64
+        .Lap_bootstrap_end:
+            mov $0x10, %ax
+            mov %ax, %ds
+            mov %ax, %es
+            mov %ax, %ss
+
+            xor %rsp, %rsp
+            xor %rax, %rax
+            inc %rax
+        1:
+            xchg %rax, {BOOT_SEMAPHORE}
+            cmp $0, %rax
+            je 1f
+            pause
+            jmp 1b
+
+        1:
+            mov {BOOT_STACK}, %rsp # Acquire
+            cmp $0, %rsp
+            jne 1f
+            pause
+            jmp 1b
+
+        1:
+            xor %rax, %rax
+            mov %rax, {BOOT_STACK} # Release
+            xchg %rax, {BOOT_SEMAPHORE}
+
+            lock incq {CPU_COUNT}
+
+            xor %rbp, %rbp
+            push %rbp # NULL return address
+            jmp {AP_ENTRY}
+            .popsection
+            "#,
+            KERNEL_PML4 = const 0x2000,
+            BOOT_SEMAPHORE = sym BOOT_SEMAPHORE,
+            BOOT_STACK = sym BOOT_STACK,
+            CPU_COUNT = sym CPU_COUNT,
+            AP_ENTRY = sym $ap_entry,
+            options(att_syntax),
+        );
+
+        pub unsafe fn wait_cpus_online() {
+            use core::sync::atomic::Ordering;
+            while CPU_COUNT.load(Ordering::Acquire) != $cpu_count - 1 {
+                if BOOT_STACK.load(Ordering::Acquire) == 0 {
+                    let stack_bottom = $alloc_kstack as u64;
+                    BOOT_STACK.store(stack_bottom, Ordering::Release);
+                }
+                $crate::pause();
+            }
+        }
+    };
+}

+ 480 - 0
arch/src/x86_64/interrupt.rs

@@ -0,0 +1,480 @@
+use core::{
+    arch::{asm, global_asm},
+    pin::Pin,
+    ptr::NonNull,
+};
+
+use crate::rdmsr;
+
+use super::pause;
+
+global_asm!(
+    r"
+    .set RAX, 0x00
+    .set RBX, 0x08
+    .set RCX, 0x10
+    .set RDX, 0x18
+    .set RDI, 0x20
+    .set RSI, 0x28
+    .set R8, 0x30
+    .set R9, 0x38
+    .set R10, 0x40
+    .set R11, 0x48
+    .set R12, 0x50
+    .set R13, 0x58
+    .set R14, 0x60
+    .set R15, 0x68
+    .set RBP, 0x70
+    .set INT_NO, 0x78
+    .set ERRCODE, 0x80
+    .set RIP, 0x88
+    .set CS, 0x90
+    .set FLAGS, 0x98
+    .set RSP, 0xa0
+    .set SS, 0xa8
+
+    .macro movcfi reg, offset
+    	mov \reg, \offset(%rsp)
+    	.cfi_rel_offset \reg, \offset
+    .endm
+
+    .macro movrst reg, offset
+    	mov \offset(%rsp), \reg
+    	.cfi_restore \reg
+    .endm
+
+    .globl ISR_stub_restore
+    .type ISR_stub_restore @function
+
+    ISR_stub:
+    	.cfi_startproc
+    	.cfi_signal_frame
+    	.cfi_def_cfa_offset 0x18
+    	.cfi_offset %rsp, 0x10
+
+    	cmpq $0x08, 24(%rsp)
+    	je 1f
+    	swapgs
+    
+    1:
+    	sub $0x78, %rsp
+    	.cfi_def_cfa_offset 0x90
+    
+    	movcfi %rax, RAX
+    	movcfi %rbx, RBX
+    	movcfi %rcx, RCX
+    	movcfi %rdx, RDX
+    	movcfi %rdi, RDI
+    	movcfi %rsi, RSI
+    	movcfi %r8,  R8
+    	movcfi %r9,  R9
+    	movcfi %r10, R10
+    	movcfi %r11, R11
+    	movcfi %r12, R12
+    	movcfi %r13, R13
+    	movcfi %r14, R14
+    	movcfi %r15, R15
+    	movcfi %rbp, RBP
+    
+    	mov INT_NO(%rsp), %rax
+    	sub $ISR0, %rax
+    	shr $3, %rax
+    	mov %rax, INT_NO(%rsp)
+    
+    	mov %rsp, %rbx
+    	.cfi_def_cfa_register %rbx
+    
+    	and $~0xf, %rsp
+    	sub $512, %rsp
+    	fxsave (%rsp)
+    
+    	mov %rbx, %rdi
+    	mov %rsp, %rsi
+    	call interrupt_handler
+    
+    ISR_stub_restore:
+    	fxrstor (%rsp)
+    	mov %rbx, %rsp
+    	.cfi_def_cfa_register %rsp
+    
+    	movrst %rax, RAX
+    	movrst %rbx, RBX
+    	movrst %rcx, RCX
+    	movrst %rdx, RDX
+    	movrst %rdi, RDI
+    	movrst %rsi, RSI
+    	movrst %r8,  R8
+    	movrst %r9,  R9
+    	movrst %r10, R10
+    	movrst %r11, R11
+    	movrst %r12, R12
+    	movrst %r13, R13
+    	movrst %r14, R14
+    	movrst %r15, R15
+    	movrst %rbp, RBP
+    
+    	add $0x88, %rsp
+    	.cfi_def_cfa_offset 0x08
+    
+    	cmpq $0x08, 8(%rsp)
+    	je 1f
+    	swapgs
+    
+    1:
+    	iretq
+    	.cfi_endproc
+    
+    .altmacro
+    .macro build_isr_no_err name
+    	.align 8
+    	.globl ISR\name
+    	.type  ISR\name @function
+    	ISR\name:
+    		.cfi_startproc
+    		.cfi_signal_frame
+    		.cfi_def_cfa_offset 0x08
+    		.cfi_offset %rsp, 0x10
+    
+    		.cfi_same_value %rax
+    		.cfi_same_value %rbx
+    		.cfi_same_value %rcx
+    		.cfi_same_value %rdx
+    		.cfi_same_value %rdi
+    		.cfi_same_value %rsi
+    		.cfi_same_value %r8
+    		.cfi_same_value %r9
+    		.cfi_same_value %r10
+    		.cfi_same_value %r11
+    		.cfi_same_value %r12
+    		.cfi_same_value %r13
+    		.cfi_same_value %r14
+    		.cfi_same_value %r15
+    		.cfi_same_value %rbp
+    
+    		push %rbp # push placeholder for error code
+    		.cfi_def_cfa_offset 0x10
+    
+    		call ISR_stub
+    		.cfi_endproc
+    .endm
+    
+    .altmacro
+    .macro build_isr_err name
+    	.align 8
+    	.globl ISR\name
+    	.type  ISR\name @function
+    	ISR\name:
+    		.cfi_startproc
+    		.cfi_signal_frame
+    		.cfi_def_cfa_offset 0x10
+    		.cfi_offset %rsp, 0x10
+    
+    		.cfi_same_value %rax
+    		.cfi_same_value %rbx
+    		.cfi_same_value %rcx
+    		.cfi_same_value %rdx
+    		.cfi_same_value %rdi
+    		.cfi_same_value %rsi
+    		.cfi_same_value %r8
+    		.cfi_same_value %r9
+    		.cfi_same_value %r10
+    		.cfi_same_value %r11
+    		.cfi_same_value %r12
+    		.cfi_same_value %r13
+    		.cfi_same_value %r14
+    		.cfi_same_value %r15
+    		.cfi_same_value %rbp
+    
+    		call ISR_stub
+    		.cfi_endproc
+    .endm
+    
+    build_isr_no_err 0
+    build_isr_no_err 1
+    build_isr_no_err 2
+    build_isr_no_err 3
+    build_isr_no_err 4
+    build_isr_no_err 5
+    build_isr_no_err 6
+    build_isr_no_err 7
+    build_isr_err    8
+    build_isr_no_err 9
+    build_isr_err    10
+    build_isr_err    11
+    build_isr_err    12
+    build_isr_err    13
+    build_isr_err    14
+    build_isr_no_err 15
+    build_isr_no_err 16
+    build_isr_err    17
+    build_isr_no_err 18
+    build_isr_no_err 19
+    build_isr_no_err 20
+    build_isr_err    21
+    build_isr_no_err 22
+    build_isr_no_err 23
+    build_isr_no_err 24
+    build_isr_no_err 25
+    build_isr_no_err 26
+    build_isr_no_err 27
+    build_isr_no_err 28
+    build_isr_err    29
+    build_isr_err    30
+    build_isr_no_err 31
+    
+    .set i, 32
+    .rept 0x80+1
+    	build_isr_no_err %i
+    	.set i, i+1
+    .endr
+    
+    .section .rodata
+    
+    .align 8
+    .globl ISR_START_ADDR
+    .type  ISR_START_ADDR @object
+    ISR_START_ADDR:
+    	.quad ISR0
+    ",
+    options(att_syntax),
+);
+
+/// Saved registers when a trap (interrupt or exception) occurs.
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Debug, Default, Clone, Copy)]
+pub struct InterruptContext {
+    pub rax: u64,
+    pub rbx: u64,
+    pub rcx: u64,
+    pub rdx: u64,
+    pub rdi: u64,
+    pub rsi: u64,
+    pub r8: u64,
+    pub r9: u64,
+    pub r10: u64,
+    pub r11: u64,
+    pub r12: u64,
+    pub r13: u64,
+    pub r14: u64,
+    pub r15: u64,
+    pub rbp: u64,
+
+    pub int_no: u64,
+    pub error_code: u64,
+
+    // Pushed by CPU
+    pub rip: u64,
+    pub cs: u64,
+    pub eflags: u64,
+    pub rsp: u64,
+    pub ss: u64,
+}
+
+#[allow(missing_docs)]
+#[repr(C)]
+#[derive(Clone, Copy)]
+pub struct ExtendedContext {
+    /// For FPU states
+    data: [u8; 512],
+}
+
+#[repr(C)]
+#[derive(Clone, Copy)]
+struct IDTEntry {
+    offset_low: u16,
+    selector: u16,
+
+    interrupt_stack: u8,
+    attributes: u8,
+
+    offset_mid: u16,
+    offset_high: u32,
+    reserved: u32,
+}
+
+pub struct APICReg(*mut u32);
+pub struct APICRegs {
+    base: NonNull<u32>,
+}
+
+/// Architecture-specific interrupt control block.
+pub struct InterruptControl {
+    idt: [IDTEntry; 256],
+    apic_base: APICRegs,
+}
+
+impl IDTEntry {
+    const fn new(offset: usize, selector: u16, attributes: u8) -> Self {
+        Self {
+            offset_low: offset as u16,
+            selector,
+            interrupt_stack: 0,
+            attributes,
+            offset_mid: (offset >> 16) as u16,
+            offset_high: (offset >> 32) as u32,
+            reserved: 0,
+        }
+    }
+
+    const fn null() -> Self {
+        Self {
+            offset_low: 0,
+            selector: 0,
+            interrupt_stack: 0,
+            attributes: 0,
+            offset_mid: 0,
+            offset_high: 0,
+            reserved: 0,
+        }
+    }
+}
+
+impl APICReg {
+    fn new(pointer: *mut u32) -> Self {
+        Self(pointer)
+    }
+
+    pub fn read(&self) -> u32 {
+        unsafe { self.0.read_volatile() }
+    }
+
+    pub fn write(&self, value: u32) {
+        unsafe { self.0.write_volatile(value) }
+    }
+}
+
+impl APICRegs {
+    pub fn local_apic_id(&self) -> APICReg {
+        unsafe { APICReg::new(self.base.byte_offset(0x20).as_ptr()) }
+    }
+
+    pub fn task_priority(&self) -> APICReg {
+        unsafe { APICReg::new(self.base.byte_offset(0x80).as_ptr()) }
+    }
+
+    pub fn end_of_interrupt(&self) {
+        unsafe { APICReg::new(self.base.byte_offset(0xb0).as_ptr()).write(0) }
+    }
+
+    pub fn spurious(&self) -> APICReg {
+        unsafe { APICReg::new(self.base.byte_offset(0xf0).as_ptr()) }
+    }
+
+    pub fn interrupt_command(&self) -> APICReg {
+        unsafe { APICReg::new(self.base.byte_offset(0x300).as_ptr()) }
+    }
+
+    pub fn timer_register(&self) -> APICReg {
+        unsafe { APICReg::new(self.base.byte_offset(0x320).as_ptr()) }
+    }
+
+    pub fn timer_initial_count(&self) -> APICReg {
+        unsafe { APICReg::new(self.base.byte_offset(0x380).as_ptr()) }
+    }
+
+    pub fn timer_current_count(&self) -> APICReg {
+        unsafe { APICReg::new(self.base.byte_offset(0x390).as_ptr()) }
+    }
+
+    pub fn timer_divide(&self) -> APICReg {
+        unsafe { APICReg::new(self.base.byte_offset(0x3e0).as_ptr()) }
+    }
+}
+
+impl InterruptControl {
+    /// # Return
+    /// Returns a tuple of InterruptControl and the cpu id of the current cpu.
+    pub unsafe fn new() -> (Self, usize) {
+        extern "C" {
+            static ISR_START_ADDR: usize;
+        }
+
+        let idt = core::array::from_fn(|idx| match idx {
+            0..0x80 => IDTEntry::new(unsafe { ISR_START_ADDR } + 8 * idx, 0x08, 0x8e),
+            0x80 => IDTEntry::new(unsafe { ISR_START_ADDR } + 8 * idx, 0x08, 0xee),
+            _ => IDTEntry::null(),
+        });
+
+        let apic_base = {
+            let apic_base = rdmsr(0x1b);
+            assert_eq!(apic_base & 0x800, 0x800, "LAPIC not enabled");
+
+            let apic_base = ((apic_base & !0xfff) + 0xffffff00_00000000) as *mut u32;
+            APICRegs {
+                // TODO: A better way to convert to physical address
+                base: NonNull::new(apic_base).expect("Invalid APIC base"),
+            }
+        };
+
+        // Make sure APIC is enabled.
+        apic_base.spurious().write(0x1ff);
+
+        let cpuid = apic_base.local_apic_id().read() >> 24;
+
+        (Self { idt, apic_base }, cpuid as usize)
+    }
+
+    pub fn setup_timer(&self) {
+        self.apic_base.task_priority().write(0);
+        self.apic_base.timer_divide().write(0x3); // Divide by 16
+        self.apic_base.timer_register().write(0x20040);
+
+        // TODO: Get the bus frequency from...?
+        let freq = 200;
+        let count = freq * 1_000_000 / 16 / 100;
+        self.apic_base.timer_initial_count().write(count as u32);
+    }
+
+    pub fn setup_idt(self: Pin<&mut Self>) {
+        lidt(
+            self.idt.as_ptr() as usize,
+            (size_of::<IDTEntry>() * 256 - 1) as u16,
+        );
+    }
+
+    pub fn send_sipi(&self) {
+        let icr = self.apic_base.interrupt_command();
+
+        icr.write(0xc4500);
+        while icr.read() & 0x1000 != 0 {
+            pause();
+        }
+
+        icr.write(0xc4601);
+        while icr.read() & 0x1000 != 0 {
+            pause();
+        }
+    }
+
+    /// Send EOI to APIC so that it can send more interrupts.
+    pub fn end_of_interrupt(&self) {
+        self.apic_base.end_of_interrupt()
+    }
+}
+
+pub fn enable_irqs() {
+    unsafe {
+        asm!("sti");
+    }
+}
+
+pub fn disable_irqs() {
+    unsafe {
+        asm!("cli");
+    }
+}
+
+fn lidt(base: usize, limit: u16) {
+    let mut idt_descriptor = [0u16; 5];
+
+    idt_descriptor[0] = limit;
+    idt_descriptor[1] = base as u16;
+    idt_descriptor[2] = (base >> 16) as u16;
+    idt_descriptor[3] = (base >> 32) as u16;
+    idt_descriptor[4] = (base >> 48) as u16;
+
+    unsafe {
+        asm!("lidt ({})", in(reg) &idt_descriptor, options(att_syntax));
+    }
+}

+ 93 - 0
arch/src/x86_64/io.rs

@@ -0,0 +1,93 @@
+use core::arch::asm;
+
+pub fn enable_sse() {
+    unsafe {
+        asm!(
+            "mov %cr0, %rax",
+            "and $(~0xc), %rax",
+            "or $0x22, %rax",
+            "mov %rax, %cr0",
+            "mov %cr4, %rax",
+            "or $0x600, %rax",
+            "mov %rax, %cr4",
+            "fninit",
+            out("rax") _,
+            options(att_syntax, nomem, nostack)
+        )
+    }
+}
+
+pub fn inb(no: u16) -> u8 {
+    let data;
+    unsafe {
+        asm!(
+            "inb %dx, %al",
+            in("dx") no,
+            out("al") data,
+            options(att_syntax, nomem, nostack)
+        )
+    };
+
+    data
+}
+
+pub fn inw(no: u16) -> u16 {
+    let data;
+    unsafe {
+        asm!(
+            "inw %dx, %ax",
+            in("dx") no,
+            out("ax") data,
+            options(att_syntax, nomem, nostack)
+        )
+    };
+
+    data
+}
+
+pub fn inl(no: u16) -> u32 {
+    let data;
+    unsafe {
+        asm!(
+            "inl %dx, %eax",
+            in("dx") no,
+            out("eax") data,
+            options(att_syntax, nomem, nostack)
+        )
+    };
+
+    data
+}
+
+pub fn outb(no: u16, data: u8) {
+    unsafe {
+        asm!(
+            "outb %al, %dx",
+            in("al") data,
+            in("dx") no,
+            options(att_syntax, nomem, nostack)
+        )
+    };
+}
+
+pub fn outw(no: u16, data: u16) {
+    unsafe {
+        asm!(
+            "outw %ax, %dx",
+            in("ax") data,
+            in("dx") no,
+            options(att_syntax, nomem, nostack)
+        )
+    };
+}
+
+pub fn outl(no: u16, data: u32) {
+    unsafe {
+        asm!(
+            "outl %eax, %dx",
+            in("eax") data,
+            in("dx") no,
+            options(att_syntax, nomem, nostack)
+        )
+    };
+}

+ 134 - 0
arch/src/x86_64/mod.rs

@@ -0,0 +1,134 @@
+mod context;
+mod gdt;
+mod init;
+mod interrupt;
+mod io;
+mod user;
+
+pub(self) mod percpu;
+
+pub use self::context::*;
+pub use self::gdt::*;
+pub use self::init::*;
+pub use self::interrupt::*;
+pub use self::io::*;
+pub use self::user::*;
+pub use percpu_macros::define_percpu;
+
+use core::arch::asm;
+
+#[inline(always)]
+pub fn flush_tlb(vaddr: usize) {
+    unsafe {
+        asm!(
+            "invlpg ({})",
+            in(reg) vaddr,
+            options(att_syntax)
+        );
+    }
+}
+
+#[inline(always)]
+pub fn flush_tlb_all() {
+    unsafe {
+        asm!(
+            "mov %cr3, %rax",
+            "mov %rax, %cr3",
+            out("rax") _,
+            options(att_syntax)
+        );
+    }
+}
+
+#[inline(always)]
+pub fn get_root_page_table() -> usize {
+    let cr3: usize;
+    unsafe {
+        asm!(
+            "mov %cr3, {0}",
+            out(reg) cr3,
+            options(att_syntax)
+        );
+    }
+    cr3
+}
+
+#[inline(always)]
+pub fn set_root_page_table(pfn: usize) {
+    unsafe {
+        asm!(
+            "mov {0}, %cr3",
+            in(reg) pfn,
+            options(att_syntax)
+        );
+    }
+}
+
+#[inline(always)]
+pub fn get_page_fault_address() -> usize {
+    let cr2: usize;
+    unsafe {
+        asm!(
+            "mov %cr2, {}",
+            out(reg) cr2,
+            options(att_syntax)
+        );
+    }
+    cr2
+}
+
+#[inline(always)]
+pub fn halt() {
+    unsafe {
+        asm!("hlt", options(att_syntax, nostack));
+    }
+}
+
+#[inline(always)]
+pub fn pause() {
+    unsafe {
+        asm!("pause", options(att_syntax, nostack));
+    }
+}
+
+#[inline(always)]
+pub fn freeze() -> ! {
+    loop {
+        interrupt::disable_irqs();
+        halt();
+    }
+}
+
+#[inline(always)]
+pub fn rdmsr(msr: u32) -> u64 {
+    let edx: u32;
+    let eax: u32;
+
+    unsafe {
+        asm!(
+            "rdmsr",
+            in("ecx") msr,
+            out("eax") eax,
+            out("edx") edx,
+            options(att_syntax),
+        );
+    }
+
+    (edx as u64) << 32 | eax as u64
+}
+
+#[inline(always)]
+pub fn wrmsr(msr: u32, value: u64) {
+    let eax = value as u32;
+    let edx = (value >> 32) as u32;
+
+    unsafe {
+        asm!(
+            "wrmsr",
+            in("ecx") msr,
+            in("eax") eax,
+            in("edx") edx,
+            options(att_syntax),
+        );
+    }
+}

+ 16 - 0
arch/src/x86_64/percpu.rs

@@ -0,0 +1,16 @@
+use super::wrmsr;
+use core::{arch::asm, ptr::NonNull};
+
+fn save_percpu_pointer(percpu_area_base: NonNull<u8>) {
+    wrmsr(0xC0000101, percpu_area_base.as_ptr() as u64);
+}
+
+pub unsafe fn init_percpu_area_thiscpu(percpu_area_base: NonNull<u8>) {
+    save_percpu_pointer(percpu_area_base);
+
+    asm!(
+        "movq {}, %gs:0",
+        in(reg) percpu_area_base.as_ptr(),
+        options(att_syntax)
+    );
+}

+ 54 - 0
arch/src/x86_64/user.rs

@@ -0,0 +1,54 @@
+use core::pin::Pin;
+
+use super::{CPUStatus, GDTEntry};
+
+#[derive(Debug, Clone)]
+pub enum UserTLS {
+    /// TODO: This is not used yet.
+    #[allow(dead_code)]
+    TLS64(u64),
+    TLS32 {
+        base: u64,
+        desc: GDTEntry,
+    },
+}
+
+impl UserTLS {
+    /// # Return
+    /// Returns the TLS descriptor and the index of the TLS segment.
+    pub fn new32(base: u32, limit: u32, is_limit_in_pages: bool) -> (Self, u32) {
+        let flags = if is_limit_in_pages { 0xc } else { 0x4 };
+
+        (
+            Self::TLS32 {
+                base: base as u64,
+                desc: GDTEntry::new(base, limit, 0xf2, flags),
+            },
+            7,
+        )
+    }
+
+    pub fn load(&self, cpu_status: Pin<&mut CPUStatus>) {
+        match self {
+            Self::TLS64(base) => {
+                const IA32_KERNEL_GS_BASE: u32 = 0xc0000102;
+                super::wrmsr(IA32_KERNEL_GS_BASE, *base);
+            }
+            Self::TLS32 { base, desc } => {
+                unsafe {
+                    // SAFETY: We don't move the CPUStatus object.
+                    let cpu_mut = cpu_status.get_unchecked_mut();
+                    cpu_mut.set_tls32(*desc);
+                }
+
+                const IA32_KERNEL_GS_BASE: u32 = 0xc0000102;
+                super::wrmsr(IA32_KERNEL_GS_BASE, *base);
+            }
+        }
+    }
+}
+
+pub unsafe fn load_interrupt_stack(cpu_status: Pin<&mut CPUStatus>, stack: u64) {
+    // SAFETY: We don't move the CPUStatus object.
+    cpu_status.get_unchecked_mut().set_rsp0(stack);
+}

+ 28 - 0
build.rs

@@ -0,0 +1,28 @@
+fn main() {
+    println!("cargo:rustc-link-search=native=./build/gblibstdc++");
+    println!("cargo:rustc-link-lib=static=gblibstdc++");
+
+    let headers = [
+        "rust-headers.hpp",
+        "include/kernel/hw/pci.hpp",
+    ];
+
+    let bindings = bindgen::Builder::default()
+        .use_core()
+        .ctypes_prefix("core::ffi")
+        .headers(headers)
+        .clang_arg("-I./gblibstdc++/include")
+        .clang_arg("-I./gblibc/include")
+        .clang_arg("-I./include")
+        .clang_arg("-std=c++20")
+        .opaque_type("std::.*")
+        .enable_cxx_namespaces()
+        .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
+        .generate()
+        .expect("Unable to generate bindings");
+
+    let out_path = std::path::PathBuf::from(std::env::var("PWD").unwrap());
+    bindings
+        .write_to_file(out_path.join("src/bindings.rs"))
+        .expect("Couldn't write bindings!");
+}

BIN
busybox


BIN
busybox-minimal


+ 152 - 0
configure

@@ -0,0 +1,152 @@
+#!/bin/sh
+QEMU_EXECUTABLES="qemu-system-x86_64"
+GDB_EXECUTABLES="gdb x86_64-elf-gdb"
+
+event() {
+    printf "$1... "
+}
+
+# $1: OS NAME
+# $2: CROSS COMPILE FLAG
+# $3: FDISK_BIN
+generate_cross_compile_script() {
+cat > cross-compile.cmake <<EOF
+set(CMAKE_SYSTEM_NAME $1)
+
+set(TOOLCHAIN_PATH_AND_PREFIX "$2")
+
+set(CMAKE_C_COMPILER \${TOOLCHAIN_PATH_AND_PREFIX}gcc)
+set(CMAKE_CXX_COMPILER \${TOOLCHAIN_PATH_AND_PREFIX}c++)
+set(CMAKE_AR \${TOOLCHAIN_PATH_AND_PREFIX}ar)
+set(CMAKE_LINKER \${TOOLCHAIN_PATH_AND_PREFIX}ld)
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+
+SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+# for libraries and headers in the target directories
+SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+SET(FDISK_BIN $3)
+EOF
+}
+
+event "finding qemu"
+for item in $QEMU_EXECUTABLES; do
+    if $item --version > /dev/null 2>&1; then
+        QEMU="$item"
+        break
+    fi
+done
+if [ "$QEMU" = "" ]; then
+    echo "failed"
+    exit 1
+fi
+echo "$QEMU"
+
+check_gdb_arch() {
+    local item="$1"
+    if $item --init-eval-command 'set arch' \
+             --init-eval-command 'q' 2>&1 \
+             | grep 'x86-64' >/dev/null 2>&1; then
+        return 0
+    else
+        return 1
+    fi
+}
+
+if [ "$GDB" = "" ]; then
+    event "finding gdb"
+    for item in $GDB_EXECUTABLES; do
+        if check_gdb_arch "$item"; then
+            GDB="$item"
+            break
+        fi
+    done
+    if [ "$GDB" = "" ]; then
+        echo "failed"
+        exit 1
+    fi
+else
+    event 'checking given gdb'
+    if ! check_gdb_arch "$GDB"; then
+        echo "failed"
+        exit 1
+    fi
+fi
+echo "$GDB"
+
+event "checking os type"
+OS=`uname`
+case "$OS" in
+    "Linux")
+        echo "Linux"
+        ;;
+    "Darwin")
+        echo "macOS"
+        ;;
+    *)
+        echo "unknown"
+        exit 1
+        ;;
+esac
+
+event "setting hardware acceleration type"
+case "$OS" in
+    "Linux")
+        echo "kvm"
+        # QEMU_ACCEL='-enable-kvm'
+        ;;
+    "Darwin")
+        echo "tcg"
+        QEMU_ACCEL='-accel tcg'
+        ;;
+esac
+
+event "checking util-linux fdisk"
+if [ "$FDISK_BIN" = "" -a "$CROSS_COMPILE" = "" ]; then
+    if ! which fdisk > /dev/null 2>&1; then
+        echo "no"
+        exit 1
+    fi
+    FDISK_BIN=`which fdisk`
+fi
+
+if ! $FDISK_BIN -v 2>&1 | grep util-linux > /dev/null 2>&1 ; then
+    echo "no, fdisk is not from util-linux"
+    exit 1
+else
+    echo "$FDISK_BIN"
+fi
+
+event "checking cross compiling"
+if [ "$CROSS_COMPILE" != "" ]; then
+    echo "yes"
+    CROSS_COMPILE_FLAG='--toolchain cross-compile.cmake'
+    generate_cross_compile_script "$OS" "$CROSS_COMPILE" "$FDISK_BIN"
+else
+    echo "no"
+    CROSS_COMPILE_FLAG=
+fi
+
+event "checking mkfs tool"
+if ! which mkfs.fat > /dev/null 2>&1; then
+    echo "no"
+    exit 1
+else
+    echo `which mkfs.fat`
+fi
+
+event "checking mtools"
+if ! which mcopy > /dev/null 2>&1; then
+    echo "no"
+    exit 1
+else
+    echo `which mcopy`
+fi
+
+cp Makefile.src Makefile
+sed -i '' -e "s|##PLACEHOLDER_1##|$QEMU|" Makefile > /dev/null 2>&1
+sed -i '' -e "s|##PLACEHOLDER_2##|$GDB|" Makefile > /dev/null 2>&1
+sed -i '' -e "s|##PLACEHOLDER_3##|$QEMU_ACCEL|" Makefile > /dev/null 2>&1
+sed -i '' -e "s|##PLACEHOLDER_4##|$CROSS_COMPILE_FLAG|" Makefile > /dev/null 2>&1
+sed -i '' -e "s|##PLACEHOLDER_5##|$FDISK_BIN|" Makefile > /dev/null 2>&1
+exit 0

+ 5 - 0
doc/assembly.md

@@ -0,0 +1,5 @@
+# Assembly Instructions
+
+## About interrupts
+cli: clear interrupt flags
+sti: set interrupt flags

+ 24 - 0
doc/bios_functions.md

@@ -0,0 +1,24 @@
+# BIOS Functions
+## int 0x10
+
+### print string
+bp: string address
+ah: 0x13 // write string
+al: 0x01 // update cursor after printing
+bh: 0x00 // page number?
+bl: 0x0f // color
+cx: $char_nums_to_print
+
+### print char
+ah: 0x0e // print char
+al: $char_to_print
+bh: 0x00 // page number?
+
+## int 0x13
+
+### read LBA
+si: $read_data_pack_address
+ah: 0x42 // read LBA
+dl: $drive_number // $0x80 + \[drive_number\]
+
+check error flag after performing interrupt

+ 25 - 0
doc/boot.md

@@ -0,0 +1,25 @@
+# 启动加载阶段
+
+## MBR 阶段
+
+BIOS 从磁盘的第一个扇区加载 MBR(Master Boot Record)到内存地址 0x7C00 并执行。MBR 代码会设置段寄存器并切换到保护模式。
+
+首先 MBR 代码通过 BIOS 中断 0x15 获取内存信息,并保存到内存中。具体操作包括调用 e820 内存检测功能,获取内存布局信息。这一步骤确保之后系统能够正确识别和利用所有可用的物理内存。然后设置32位的 GDT 并加载到 GDTR 寄存器中。之后会通过 BIOS 中断读取 Stage1 的一小段代码到内存中,然后用`ljmp`指令跳转到 Stage1 执行,同时开启保护模式。通过这些操作,系统从实模式切换到保护模式,为后续的内存管理和多任务处理提供基础。
+
+## Stage1
+
+MBR 代码使用 BIOS 功能从磁盘读取 Stage1 到内存地址 0x1000 并跳转执行。Stage1 代码使用刚才 MBR 中初始化的那个临时栈,并通过 BIOS 中断读取磁盘中的内核镜像(分成了多个 32K 块),并将其复制到内存中的指定位置。
+
+然后,Stage1 代码设置分页结构并启用分页。具体操作包括设置内核的 PML4、PDPT、PD和 PT 表项,并启用 CR0 寄存器中的分页位。分页机制的启用使得系统能够管理虚拟内存,并提供内存保护和隔离功能。再之后,Stage1 会初始化 64位模式使用的 GDT 和设置 IDT(中断描述符表),然后将其加载。通过这些操作,Stage1 确保了内核在进入保护模式后能够正确运行,并为内核的初始化提供了必要的环境。此时,Stage1 代码跳转到内核 64 位模式的入口,正式进入 64 位模式运行。
+
+## 下一步初始化
+
+内核代码初始化内存管理、CPU 状态、多处理器支持及启动调度器等。具体操作包括设置真正的内核页表、保存内存信息、初始化 **buddy** 系统等。
+
+内核初始化过程中,首先进入 C++ 中的 kinit.cpp,设置真正的内核页表,确保内核地址空间的正确映射。接着,通过保存从 Stage1 获取的内存信息,包括内存大小和 e820 内存布局信息。然后,调用 `setup_buddy` 函数初始化伙伴系统,管理物理内存的分配。然后进入 Rust 中的内核初始化阶段。
+
+在 Rust 中的内核初始化阶段,首先调用 `init_thiscpu` 函数初始化当前 CPU 的状态,包括设置 GDT 和 TSS。接着,初始化中断控制器和定时器。然后,初始化多任务处理系统,包括创建调度器和空闲任务。接下来,挂载文件系统,并加载 init 进程。init 进程是一个 init 脚本,使用 busybox 运行,用于配置文件系统环境并且启动真正的用户 init进程。最后,内核进入正常运行状态,准备处理用户请求和执行应用程序。整个过程确保内核从启动到运行的过程顺利进行,并为后续的操作系统功能提供基础。
+
+## 还需要做的改进
+
+我们希望实现多平台多架构兼容,但是启动的这个位置我们还没有做多平台共通的接口。一个想法是可以将所有这些 bootstrap 用的代码都放到 arch 中,在一系列的初始化操作都完成以后,再将控制权交给共通部分的函数处。这个实现正在完成过程当中。

+ 59 - 0
doc/device_driver.md

@@ -0,0 +1,59 @@
+# 设备与驱动
+
+设备与驱动模块是 Eonix 内核的核心功能之一,提供了对硬件资源的抽象与管理支持,涵盖了块设备、字符设备等多种类型,其中细分还有终端设备的支持。通过模块化与接口化的设计,Eonix 提供了灵活的扩展性和高效的硬件访问能力。
+
+---
+
+## 1. 块设备
+
+块设备主要用于存储设备的管理,以固定大小的块为单位进行数据传输。
+
+### 块设备抽象与接口
+块设备通过 `BlockDevice` 抽象,支持磁盘(Disk)和分区(Partition)两种类型。核心接口包括:
+- 设备 ID(`DevId`):唯一标识块设备。
+- 容量与请求大小:支持定义设备容量和最大传输页数。
+- 块设备队列接口:通过 `BlockRequestQueue` 标准化数据请求的管理。`BlockDevice`为设备实现请求队列以及块缓存(正在写)的功能,设备驱动只要实现其请求队列中处理请求的部分即可,这样大大方便了设备驱动的开发。
+
+### 块设备功能
+- 注册与分区管理  
+  驱动中将块设备通过注册后,可通过读取 MBR 实现自动分区探测,并支持动态添加分区等。
+- I/O 操作  
+  块设备支持直接数据传输(`read_raw`)和分段读取(`read_some`),实现高效且灵活的数据访问。
+
+### AHCI 驱动的集成
+
+Eonix 内核通过 AHCI 驱动实现对 SATA 设备的支持。Eonix 内核的 AHCI 驱动设计模块化、结构清晰,包含命令接口、控制器和端口管理以及高效的中断处理机制。通过统一的接口设计和硬件加速机制,该驱动能够高效地完成设备初始化、数据传输和错误处理,为现代存储系统提供了可靠的支持。
+
+AHCI 控制器通过 `AdapterControl` 结构进行管理。该结构映射了 HBA 的全局寄存器块(GHC),支持提供方法处理全局中断,通过读取 ports_implemented 寄存器获取已实现端口信息,为设备的多端口特性提供支持。`AdapterControl` 的方法通过读写寄存器实现对控制器状态的直接操作。每个 AHCI 端口通过 AdapterPort 表示,负责特定硬盘的命令管理和数据传输。AHCI 驱动通过统一的 `Command` 接口抽象了硬盘的各种操作命令。不同类型的命令如标识命令(`IdentifyCommand`)和逻辑块读取命令(`ReadLBACommand`)实现了该接口。其中使用 FreeList 结构维护空闲和工作中的命令槽,实现多命令并发处理。通过 `send_command` 方法发送命令,利用硬件加速的数据结构 PRDT 支持高效数据传输。在中断触发时,通过 `handle_interrupt` 方法检测并处理各个端口的中断请求,确保传输过程的完整性。
+
+---
+
+## 2. 字符设备
+
+字符设备主要面向流式数据传输,适用于终端、虚拟设备等交互场景。
+
+### 字符设备抽象与管理
+字符设备通过 `CharDevice` 抽象,包括两种类型:
+- 终端(TTY)设备:支持用户交互和作业控制。
+- 其他虚拟设备:如 `/dev/null` 和 `/dev/zero` 和控制台设备(`console`)提供特殊功能,满足多样化需求。
+
+字符设备通过 `register` 方法完成注册,并维护全局字符设备表(`CHAR_DEVICES`)以支持快速查找。I/O 操作与设备支持输入输出操作,通过 `read` 和 `write` 方法完成数据的流式传输。字符设备也具有很好的扩展性,Eonix 提供了 `VirtualCharDevice` 接口,只需实现 `read` 和 `write` 这两个方法即可快速扩展字符设备支持。
+
+---
+
+## 3. 终端设备
+
+终端设备是字符设备的子集,专注于用户交互和作业控制,结合会话与进程组实现全面支持。
+
+### 终端功能
+1. 交互式控制:通过 `commit_char`、`show_char` 等方法支持根据当前终端的配置完成字符回显、信号响应和缓冲区管理。
+- 模式切换:支持 **canonical(cooked)** 模式和 **raw**模式,适应不同的交互需求。
+- 信号与回显:通过 `signal` 和 `echo_char` 方法,支持中断、退出和挂起等信号处理。
+- 作业控制:通过 `set_session` 和 `drop_session` 实现终端与会话的动态绑定。终端设备中保存的会话对象有前台进程组的属性,当接收到控制字符的时候可以产生对应的信号,并且发送给前台进程组。用户程序可以使用 `tcsetpgrp` 等设置当前的前台进程组,完成作业控制。
+- 终端配置:终端设备通过 `Termios` 结构实现配置管理,支持输入、输出、控制和本地模式等多种配置参数,并提供标准化方法(如 `new_standard`)快速初始化。
+
+其他的设备驱动想要实现一个终端也非常容易,只要实现 `TerminalDevice` 接口,就可以创建一个终端设备,也简化了设备驱动的开发。
+
+## 4. 可以改进的点
+
+由于项目之前的架构调整,块设备的请求队列的缓存被删掉了。正在将块缓存重新加回来。。。

+ 75 - 0
doc/filesystem.md

@@ -0,0 +1,75 @@
+# 文件系统
+
+Eonix 内核的文件系统模块通过 `Inode`、`Dentry` 和 `DentryCache` 数据结构实现高效的文件管理、路径解析和缓存机制。它们共同构成了 Eonix 内核文件系统的核心数据结构,提供了高效的文件操作和路径解析能力。`Inode` 描述文件的元数据和操作接口,`Dentry` 连接路径和文件内容,而 `DentryCache` 则通过缓存机制大幅提升文件系统的性能。三者的协作确保了文件系统在复杂操作和高并发环境下的高效性和稳定性。
+
+---
+
+#### 1. Inode:文件和目录的核心描述
+
+`Inode` 是 Eonix 文件系统中表示文件或目录的核心结构,提供了文件元数据的存储与访问。它通过 `InodeData` 和 `Inode` 接口实现,支持文件的基础操作。
+
+**基本属性:**
+- `ino`:文件的唯一标识符。
+- `size` 和 `nlink`:表示文件大小和硬链接计数。
+- `uid` 和 `gid`:文件的拥有者和组。
+- `mode`:文件的权限和类型(如目录、常规文件等)。
+- `atime`、`ctime` 和 `mtime`:文件的访问、创建和修改时间。
+- `rwsem`:读写信号量,用于并发访问控制。
+
+**功能接口:**
+- 提供创建文件(`creat`)、创建目录(`mkdir`)、读写文件(`read` 和 `write`)等基本操作。
+- 支持通过 `lookup` 方法查找子文件,`statx` 获取文件元数据,`truncate` 修改文件大小。
+- 提供与设备相关的接口,如 `readlink` 解析符号链接,`mknod` 创建特殊文件。
+
+**并发支持:**
+- 使用原子操作和信号量确保多线程环境下的安全性。
+- 通过 `Spin` 和 `RwSemaphore` 实现时间和读写操作的并发控制。
+
+---
+
+#### 2. Dentry:用于路径解析与文件缓存
+
+`Dentry` 是文件路径与 `Inode` 的映射关系,主要用于路径解析和目录缓存。
+
+**基本结构:**
+- `name` 和 `parent`:当前路径组件名称及其父目录的 `Dentry`。
+- `data`:指向文件或目录的 `Inode`。
+- `hash`:通过路径计算的哈希值,用于高效查找。
+- 链表指针(`prev` 和 `next`):支持 `DentryCache` 中的快速访问。
+
+**功能接口:**
+- `find` 和 `open_recursive` 支持路径解析,递归查找目录结构。
+- `save_data` 和 `get_inode` 关联或获取 `Inode`。
+- 提供对文件的操作接口,包括 `mkdir`、`unlink`、`readlink` 和 `write`。
+- 支持符号链接解析,通过 `resolve_directory` 实现递归解析。
+- 提供 `is_directory` 和 `is_valid` 方法检查当前节点是否为目录及其是否有效。
+
+---
+
+#### 3. DentryCache:加速文件路径解析
+
+`DentryCache` 是路径解析的高速缓存,通过维护 `Dentry` 的哈希表加速文件和目录的查找。
+
+**缓存结构**方面,我们使用定长哈希表(`DCACHE`)存储不同哈希值对应的 `Dentry` 列表。提供静态根目录(`DROOT`),便于路径解析的起点管理。
+
+**缓存一致性**方面,使用 RCU(Read-Copy-Update)机制维护多线程环境下的缓存一致性,确保高效的并发访问。
+
+**核心操作:**
+- `d_add`:将新的 `Dentry` 加入缓存。
+- `d_find_fast` 和 `d_iter_for`:根据哈希值快速查找缓存中的 `Dentry`。
+- `d_replace` 和 `d_remove`:支持缓存中节点的替换和移除操作。
+- `d_try_revalidate`:通过父目录的 `lookup` 方法验证节点有效性。
+
+---
+
+### 4. Inode、Dentry 和 DentryCache 的协作
+
+#### 路径解析
+
+用户请求文件路径时,内核通过 `Dentry` 递归解析路径。若缓存命中,`DentryCache` 提供快速访问;若缓存未命中,调用父目录的 `lookup` 方法查找对应的 `Inode`。
+
+#### 文件操作
+文件操作首先通过 `Dentry` 获取 `Inode`,然后调用 `Inode` 提供的读写、创建等接口完成操作。在操作结束后,通过 `DentryCache` 缓存结果,加速后续访问。
+
+#### 并发访问
+- `Inode` 的读写信号量(`rwsem`)和 `Dentry` 的 RCU 机制共同保障文件系统的并发访问安全。

BIN
doc/images/image-0.png


BIN
doc/images/image-1.png


+ 260 - 0
doc/images/mm.drawio

@@ -0,0 +1,260 @@
+<mxfile host="65bd71144e">
+    <diagram id="4VEP11HeOnmaw6osTsnV" name="第 1 页">
+        <mxGraphModel dx="929" dy="1067" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="827" pageHeight="1169" background="#FFF6E8" math="0" shadow="0">
+            <root>
+                <mxCell id="0"/>
+                <mxCell id="1" parent="0"/>
+                <mxCell id="4" style="edgeStyle=none;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" parent="1" source="2" edge="1">
+                    <mxGeometry relative="1" as="geometry">
+                        <mxPoint x="132.18" y="83.66668701171875" as="targetPoint"/>
+                    </mxGeometry>
+                </mxCell>
+                <mxCell id="2" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#333333;" parent="1" vertex="1">
+                    <mxGeometry x="76.18" y="-61" width="111" height="364" as="geometry"/>
+                </mxCell>
+                <mxCell id="3" value="&lt;font color=&quot;#252323&quot;&gt;&lt;b&gt;代码段&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;" parent="1" vertex="1">
+                    <mxGeometry x="76.18" y="252" width="111" height="34" as="geometry"/>
+                </mxCell>
+                <mxCell id="5" value="&lt;font color=&quot;#252323&quot;&gt;&lt;b&gt;数据段&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
+                    <mxGeometry x="76.18" y="214" width="111" height="34" as="geometry"/>
+                </mxCell>
+                <mxCell id="6" value="&lt;font color=&quot;#252323&quot;&gt;&lt;b&gt;BSS段&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
+                    <mxGeometry x="76.18" y="187" width="111" height="23" as="geometry"/>
+                </mxCell>
+                <mxCell id="7" value="&lt;font color=&quot;#252323&quot;&gt;&lt;b&gt;用户堆&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" parent="1" vertex="1">
+                    <mxGeometry x="76.18" y="138" width="111" height="45" as="geometry"/>
+                </mxCell>
+                <mxCell id="8" value="&lt;font color=&quot;#252323&quot;&gt;&lt;b&gt;用户栈&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#bac8d3;strokeColor=#23445d;" parent="1" vertex="1">
+                    <mxGeometry x="76.18" y="-59" width="111" height="93" as="geometry"/>
+                </mxCell>
+                <mxCell id="9" value="&lt;font color=&quot;#252323&quot;&gt;&lt;b&gt;MMAP区&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b0e3e6;strokeColor=#0e8088;" parent="1" vertex="1">
+                    <mxGeometry x="76.18" y="67" width="111" height="45" as="geometry"/>
+                </mxCell>
+                <mxCell id="18" style="edgeStyle=none;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" parent="1" source="19" edge="1">
+                    <mxGeometry relative="1" as="geometry">
+                        <mxPoint x="461.05" y="80.66668701171875" as="targetPoint"/>
+                    </mxGeometry>
+                </mxCell>
+                <mxCell id="19" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#333333;" parent="1" vertex="1">
+                    <mxGeometry x="405.05" y="-64" width="111" height="364" as="geometry"/>
+                </mxCell>
+                <mxCell id="31" value="&lt;b&gt;&lt;font style=&quot;font-size: 16px;&quot;&gt;进程虚拟内存空间&lt;/font&gt;&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="66.68" y="328" width="135.5" height="30" as="geometry"/>
+                </mxCell>
+                <mxCell id="34" value="&lt;b style=&quot;color: rgb(240, 240, 240); font-size: 12px;&quot;&gt;&lt;font color=&quot;#000000&quot;&gt;0x0000 7FFF FFFF F000&lt;/font&gt;&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="197.18" y="-78" width="145" height="30" as="geometry"/>
+                </mxCell>
+                <mxCell id="35" value="&lt;b style=&quot;color: rgb(51, 51, 51); font-size: 12px;&quot;&gt;0x0000 0000 0000 0000&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="197.18" y="286" width="140" height="30" as="geometry"/>
+                </mxCell>
+                <mxCell id="36" value="&lt;b&gt;&lt;font style=&quot;font-size: 16px;&quot;&gt;内核虚拟内存空间&lt;/font&gt;&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="398.18" y="325" width="135.5" height="30" as="geometry"/>
+                </mxCell>
+                <mxCell id="37" value="&lt;b style=&quot;color: rgb(51, 51, 51); font-size: 12px;&quot;&gt;0xFFFF 8000 0000 0000&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="536.05" y="283" width="140" height="30" as="geometry"/>
+                </mxCell>
+                <mxCell id="38" value="&lt;b style=&quot;color: rgb(51, 51, 51); font-size: 12px;&quot;&gt;0xFFFF FFFF FFFF FFFF&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="532.68" y="-78" width="146.37" height="30" as="geometry"/>
+                </mxCell>
+                <mxCell id="39" value="&lt;font color=&quot;#252323&quot;&gt;&lt;b&gt;直接映射区&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#bac8d3;strokeColor=#23445d;" vertex="1" parent="1">
+                    <mxGeometry x="405.05" y="201" width="111" height="61" as="geometry"/>
+                </mxCell>
+                <mxCell id="40" value="&lt;b style=&quot;color: rgb(51, 51, 51); font-size: 12px;&quot;&gt;0xFFFF FF00 0000 0000&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="537.05" y="245" width="140" height="30" as="geometry"/>
+                </mxCell>
+                <mxCell id="41" value="&lt;b&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;0xFFFF FF80 0000 0000&lt;/font&gt;&lt;/b&gt;" style="text;whiteSpace=wrap;html=1;fontSize=16;fontFamily=Helvetica;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="536.05" y="185" width="141.5" height="32" as="geometry"/>
+                </mxCell>
+                <mxCell id="43" value="&lt;font color=&quot;#252323&quot;&gt;&lt;b&gt;内核堆&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
+                    <mxGeometry x="405.05" y="45" width="111" height="45" as="geometry"/>
+                </mxCell>
+                <mxCell id="45" value="&lt;font color=&quot;#252323&quot;&gt;&lt;b&gt;Kernel Image&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
+                    <mxGeometry x="405.05" y="-32" width="111" height="51" as="geometry"/>
+                </mxCell>
+                <mxCell id="46" value="&lt;font color=&quot;#252323&quot;&gt;&lt;b&gt;Memory Map&lt;br&gt;(Page Array)区&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;gradientColor=#97d077;" vertex="1" parent="1">
+                    <mxGeometry x="405.05" y="123" width="111" height="45" as="geometry"/>
+                </mxCell>
+                <mxCell id="47" value="&lt;b&gt;0xFFFF FF81 8000 0000&lt;/b&gt;" style="text;whiteSpace=wrap;html=1;fontSize=12;fontFamily=Helvetica;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="534.68" y="76" width="140" height="23" as="geometry"/>
+                </mxCell>
+                <mxCell id="48" value="&lt;b&gt;0xFFFF&amp;nbsp;FFFF FFC0 0000&lt;/b&gt;" style="text;whiteSpace=wrap;html=1;fontSize=12;fontFamily=Helvetica;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="533.68" y="2" width="149.37" height="25" as="geometry"/>
+                </mxCell>
+                <mxCell id="49" value="&lt;b&gt;0xFFFF FFFF FFE0 0000&lt;/b&gt;" style="text;whiteSpace=wrap;html=1;fontSize=12;fontFamily=Helvetica;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="533.68" y="-47" width="145.2" height="25" as="geometry"/>
+                </mxCell>
+                <mxCell id="50" value="&lt;b&gt;0xFFFF FFC0 0000 0000&lt;/b&gt;" style="text;whiteSpace=wrap;html=1;fontSize=12;fontFamily=Helvetica;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="533.68" y="34" width="139" height="25.5" as="geometry"/>
+                </mxCell>
+                <mxCell id="51" value="&lt;b&gt;0xFFFF FF80 4000 0000&lt;/b&gt;" style="text;whiteSpace=wrap;html=1;fontSize=12;fontFamily=Helvetica;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="535.68" y="155" width="140" height="25" as="geometry"/>
+                </mxCell>
+                <mxCell id="52" value="&lt;b&gt;0xFFFF FF81 4000 0000&lt;/b&gt;" style="text;whiteSpace=wrap;html=1;fontSize=12;fontFamily=Helvetica;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="534.68" y="116" width="140" height="27" as="geometry"/>
+                </mxCell>
+                <mxCell id="53" value="" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1">
+                    <mxGeometry x="70.68" y="-355" width="131" height="199" as="geometry"/>
+                </mxCell>
+                <mxCell id="54" value="&lt;b&gt;Zone&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="108.68" y="-389" width="60" height="30" as="geometry"/>
+                </mxCell>
+                <mxCell id="55" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;0&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
+                    <mxGeometry x="146.55" y="-319" width="41.13" height="23" as="geometry"/>
+                </mxCell>
+                <mxCell id="97" style="edgeStyle=none;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="66" target="83">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="66" value="&lt;b&gt;&lt;font color=&quot;#000000&quot;&gt;1&lt;/font&gt;&lt;/b&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
+                    <mxGeometry x="146.55" y="-296" width="41.13" height="23" as="geometry"/>
+                </mxCell>
+                <mxCell id="108" style="edgeStyle=none;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="69" target="85">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="69" value="&lt;b&gt;&lt;font color=&quot;#000000&quot;&gt;2&lt;/font&gt;&lt;/b&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
+                    <mxGeometry x="146.55" y="-273" width="41.13" height="23" as="geometry"/>
+                </mxCell>
+                <mxCell id="126" style="edgeStyle=none;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="76" target="124">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="76" value="&lt;b&gt;&lt;font color=&quot;#000000&quot;&gt;10&lt;/font&gt;&lt;/b&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
+                    <mxGeometry x="146.55" y="-189" width="41.13" height="23" as="geometry"/>
+                </mxCell>
+                <mxCell id="77" value="&lt;b&gt;FreeArea&lt;br&gt;[MAX_PAGE_ORDER]&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
+                    <mxGeometry x="66.68" y="-351" width="141" height="30" as="geometry"/>
+                </mxCell>
+                <mxCell id="90" style="edgeStyle=none;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;fontFamily=Helvetica;fontSize=12;fontColor=#000000;strokeColor=#000000;" edge="1" parent="1" source="79" target="55">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="92" style="edgeStyle=none;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="79" target="91">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="79" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="219.68" y="-318.5" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="82" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;......&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
+                    <mxGeometry x="146.55" y="-250" width="41.13" height="62" as="geometry"/>
+                </mxCell>
+                <mxCell id="98" style="edgeStyle=none;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="83" target="66">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="83" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="219.68" y="-294" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="101" style="edgeStyle=none;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="84" target="99">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="84" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="251.68" y="-294" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="109" style="edgeStyle=none;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="85" target="69">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="85" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="219.68" y="-270" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="86" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="251.68" y="-270" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="87" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="283.68" y="-270" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="114" style="edgeStyle=none;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="88" target="110">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="88" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="315.68" y="-270" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="89" value="" style="endArrow=classic;html=1;fontFamily=Helvetica;fontSize=12;fontColor=#000000;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeColor=#000000;" edge="1" parent="1" source="55" target="79">
+                    <mxGeometry width="50" height="50" relative="1" as="geometry">
+                        <mxPoint x="335.68" y="-121" as="sourcePoint"/>
+                        <mxPoint x="385.68" y="-171" as="targetPoint"/>
+                    </mxGeometry>
+                </mxCell>
+                <mxCell id="93" style="edgeStyle=none;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="91" target="79">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="95" style="edgeStyle=none;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="91" target="94">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="91" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="278.68" y="-318.5" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="96" style="edgeStyle=none;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="94" target="91">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="94" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="337.68" y="-318.5" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="102" style="edgeStyle=none;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="99" target="84">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="99" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="303.55" y="-294" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="105" style="edgeStyle=none;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="100" target="103">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="100" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="335.55" y="-294" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="106" style="edgeStyle=none;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="103">
+                    <mxGeometry relative="1" as="geometry">
+                        <mxPoint x="370.0133740234375" y="-279" as="targetPoint"/>
+                    </mxGeometry>
+                </mxCell>
+                <mxCell id="103" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="388.68" y="-294" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="122" style="edgeStyle=none;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="104">
+                    <mxGeometry relative="1" as="geometry">
+                        <mxPoint x="475.34668701171876" y="-289" as="targetPoint"/>
+                    </mxGeometry>
+                </mxCell>
+                <mxCell id="104" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="420.68" y="-294" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="115" style="edgeStyle=none;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="110" target="88">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="110" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="372.68" y="-270" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="111" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="404.68" y="-270" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="112" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="436.68" y="-270" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="113" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="468.68" y="-270" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="123" style="edgeStyle=none;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="120" target="104">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="120" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="475.68" y="-294" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="121" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="507.68" y="-294" width="32" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="127" style="edgeStyle=none;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="124" target="76">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="129" style="edgeStyle=none;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="124" target="128">
+                    <mxGeometry relative="1" as="geometry"/>
+                </mxCell>
+                <mxCell id="124" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;1024个Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="215.68" y="-189" width="228" height="20" as="geometry"/>
+                </mxCell>
+                <mxCell id="130" style="edgeStyle=none;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;strokeColor=#000000;fontFamily=Helvetica;fontSize=12;fontColor=#000000;" edge="1" parent="1" source="128">
+                    <mxGeometry relative="1" as="geometry">
+                        <mxPoint x="446.0133740234375" y="-176" as="targetPoint"/>
+                    </mxGeometry>
+                </mxCell>
+                <mxCell id="128" value="&lt;font color=&quot;#000000&quot;&gt;&lt;b&gt;1024个Page&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
+                    <mxGeometry x="471.68" y="-191" width="228" height="20" as="geometry"/>
+                </mxCell>
+            </root>
+        </mxGraphModel>
+    </diagram>
+</mxfile>

BIN
doc/images/mm_layout.png


BIN
doc/images/mm_zone.png


+ 21 - 0
doc/interrupt.md

@@ -0,0 +1,21 @@
+# Interrupt handling
+
+When an interrupt is raised, the x86 cpu will
+push some of the current working states into
+current user stack. (At least for GE ints) in
+the following order:
+
+push  (EFLAGS)
+push  %cs
+pushl %eip
+push  (ERROR_CODE)
+
+The eip should points to the instruction that
+caused the exception.
+
+ERROR_CODE can be segment selector index (if
+the exception is segment related) or simply
+zero
+
+Notice that the error code doesn't always 
+exists. In some cases, it can be absent.

+ 45 - 0
doc/malloc.md

@@ -0,0 +1,45 @@
+[参考链接1](https://blog.codinglabs.org/articles/a-malloc-tutorial.html#212-%E9%A1%B5%E4%B8%8E%E5%9C%B0%E5%9D%80%E6%9E%84%E6%88%90)
+[malloc的glibc实现](https://repo.or.cz/glibc.git/blob/HEAD:/malloc/malloc.c)
+[How the kernel manage your memory](https://manybutfinite.com/post/how-the-kernel-manages-your-memory/)
+
+## 地址空间分区
+从0x00000000到0x3fffffff为内核空间
+
+从0x40000000到0xffffffff为用户空间
+
+### 内核空间:
+0x00000000到0x2fffffff为动态映射区
+0x30000000到0x3fffffff为永久映射区,这个区域的内存在与物理页进行映射后不会被交换出地址空间
+
+## 物理内存分配
+0x00000000-0x00000fff:内核页目录
+0x00001000-0x00001fff:空白页
+
+## 大致思路:
+每个进程(包括内核)拥有一个struct mm,用于记录自身的虚拟地址映射状况
+
+struct mm拥有struct page的链表,对应虚拟地址实际映射的物理页
+
+struct mm的项目还可包括copy on write的页
+
+发生缺页中断时,内核通过该触发中断的进程的struct mm检查页权限、是否需要复制页等
+
+若因权限不足而触发中断,则内核中断用户进程执行,或内核panic
+
+若因页已被交换出内存,则内核将页换回内存,继续进程执行
+
+若因页为copy on write页,写入时触发中断,则将页复制一份,继续进程执行
+
+### 内核提供几个接口
+1. alloc_page从页位图中找出未被使用的物理页返回
+2. p_map用于将物理页映射到指定的虚拟地址
+3. kmap用于给出物理页,将其映射到一个未被该进程使用的虚拟地址
+
+### 分配内存
+通过kmap将空白页映射到某虚拟地址上,并开启copy on write,
+随后则可以直接对该页进行读写,写入时内核中断自动进行页的分配
+
+因此,换页中断的处理非常重要
+
+## 注
+分页相关的内存数据结构应始终被映射到永久映射区,并且该映射应在页表创建时被完成

+ 33 - 0
doc/mem_layout.txt

@@ -0,0 +1,33 @@
+physical memory
+
+0x0000 - 0x1000 : GDT for kernel initialization use and some early kernel data
+0x1000 - 0x2000 : kernel stage1
+0x2000 - 0x3000 : kernel space PML4
+0x3000 - 0x4000 : kernel PDPT for physical memory mappings
+0x4000 - 0x5000 : kernel PDPT for kernel space
+0x5000 - 0x6000 : kernel PD for kernel image
+0x6000 - 0x7000 : kernel PT for kernel image
+0x7000 - 0x8000 : kernel PD for struct page array#1
+
+0x100000 - 0x200000 : unused
+0x200000 - 0x400000 : first kernel bss page (2MB)
+0x400000 - ?        : kernel image
+?        - ?        : struct page array
+
+
+virtual address space
+
+0xffff ff0 000 000 000 - 0xffff ff3 fff fff fff  256GB physical memory (cached)
+0xffff ff4 000 000 000 - 0xffff ff7 fff fff fff  256GB physical memory (not cached)
+0xffff ff8 000 000 000 - 0xffff ff8 03f fff fff    1GB unused
+0xffff ff8 040 000 000 - 0xffff ff8 13f fff fff    4GB struct page array
+0xffff ff8 140 000 000 - 0xffff ff8 17f fff fff    1GB unused
+0xffff ff8 180 000 000 - 0xffff ffb fff fff fff  250GB kernel heap
+
+0xffff ffc 000 000 000 - 0xffff fff fbf fff fff  255GB unused
+
+0xffff fff fc0 000 000 - 0xffff fff fc0 1ff fff    2MB unused
+0xffff fff fc0 200 000 - 0xffff fff fff 9ff fff 1016MB kernel bss
+0xffff fff fff a00 000 - 0xffff fff fff bff fff    2MB unused
+0xffff fff fff c00 000 - 0xffff fff fff dff fff    2MB kernel image
+0xffff fff fff e00 000 - 0xffff fff fff fff fff    2MB unused

+ 97 - 0
doc/memory.md

@@ -0,0 +1,97 @@
+# 内存管理
+
+## 物理内存组织
+Eonix 采用 **FLATMEM 平坦内存模型**以及 **UMA 架构**,把可用于分配的物理内存统一纳入 Zone 进行管理。Zone 所管理的物理内存页会被进一步划分成不同阶数的 FreeArea。其中,每一个 FreeArea 均由大小为 2^i^ 的物理内存块所构成,这些物理块作为内存分配与管理的基础单元,在整个物理内存的组织架构中起着关键作用,用于实现高效的内存管理操作。
+![物理内存组织](images/mm_zone.png)
+
+## 物理内存分配
+物理内存分配可根据所需内存大小分为**页分配**和**字节块分配**,整个物理内存分配由**伙伴系统**和**slab分配器**合作完成。
+
+### 页分配
+Eonix 使用伙伴系统管理内存页的分配,其工作原理是将内存块按照 2 的幂次方大小分为多个层级,并通过合并和分解有效减少外部碎片。**分配物理页时**,伙伴系统从最小适合该请求的层级开始查找。通过检查和计算伙伴块的地址,可以快速地进行内存分割与合并。当需要分配的内存块小于当前可用最小块时,将当前块一分为二,直到找到合适大小的块为止。**回收物理页时**,若其伙伴块也空闲,则将两个块合并为一个更大的块,迭代进行直到不能再合并为止。伙伴分配器的优点在于分配和释放内存块的操作非常快速,且通过内存块大小的选择和合并操作,有效减少了外部碎片。
+
+### 字节块分配
+Eonix 采用 slab 分配器来实现字节块分配。slab 分配器针对不同大小的常用内存对象预先分配一系列内存块,这些内存块组织成**缓存池**。当有特定字节大小的内存块分配请求时,首先在对应的 slab 缓存池中查找空闲内存块。若找到,则直接分配;若未找到,slab 分配器依据既定策略向伙伴系统申请一定数量页面,将这些页面划分成所需大小的字节块并加入对应的 slab 缓存池,然后从中取出字节块分配。slab 分配器的优势显著,尤其在频繁申请和释放相同大小字节块的场景下,它能极大减少内存碎片的产生,大幅提升内存分配与释放效率。这对于内核中诸如进程控制块、文件描述符等众多小内存对象频繁的分配回收需求极为关键,有力保障了系统整体稳定高效运行。
+
+## 地址空间布局
+Eonix 地址空间布局借鉴了 Linux 的设计,采用**用户空间和内核空间统一布局**方式。
+![地址空间](images/mm_layout.png)
+**Kernel Image**
+Kernel Image 位于内核虚拟内存空间的最上方,其中包含了内核的可执行代码和内核数据结构,是内核运行的核心部分。
+**Memory Map 区**
+Memory Map 区用于存储描述物理页的数据结构 PageArray,此结构对于物理内存管理至关重要。
+**直接映射区**
+直接映射区将物理内存直接映射到内核虚拟地址空间,使得内核可以方便地访问物理内存。例如,物理地址加上固定的一个偏移量 PHYS_OFFSET 即可得到其在内核中的虚拟地址,
+
+## 缺页异常处理
+Eonix 能够有效利用缺页异常处理来实现**写时复制(Copy on write)**、**懒分配(Lazy page allocation)** 以及**高效用户态内存拷贝**技术。
+**写时复制**
+在PageFault处理中,内核会根据COW标志位该页是否进行写时复制,并根据 Page 结构体中的原子引用计数判断是否为最后一个持有者,如果不是最后一个持有者,会新分配一个页并复制原始页的数据并恢复写标志位重新映射,如果是最后一个持有者,直接恢复读写标志位。
+``` rust
+if attributes & PA_COW as usize != 0 {
+            attributes &= !PA_COW as usize;
+            if area.permission.write {
+                attributes |= PA_RW as usize;
+            } else {
+                attributes &= !PA_RW as usize;
+            }
+
+            let page = unsafe { Page::take_pfn(pfn, 0) };
+            if page.load_refcount() == 1 {
+                // SAFETY: This is actually safe. If we read `1` here and we have `MMList` lock
+                // held, there couldn't be neither other processes sharing the page, nor other
+                // threads making the page COW at the same time.
+                pte.set_attributes(attributes);
+                core::mem::forget(page);
+                return Ok(());
+            }
+
+            let new_page = Page::alloc_one();
+            if attributes & PA_ANON as usize != 0 {
+                new_page.zero();
+            } else {
+                new_page
+                    .as_cached()
+                    .as_mut_slice::<u8>(0x1000)
+                    .copy_from_slice(CachedPP::new(pfn).as_slice(0x1000));
+            }
+
+            attributes &= !(PA_A | PA_ANON) as usize;
+
+            pfn = new_page.into_pfn();
+            pte.set(pfn, attributes);
+        }
+```
+
+**懒分配**
+懒分配技术主要用于堆栈分配以及 mmap 匿名映射或文件映射。在传统的内存分配方法中,操作系统在进程请求内存时会立即为其分配实际的物理内存。然而,这种方法在某些情况下可能导致资源的浪费,因为进程可能并不会立即使用全部分配的内存。
+懒分配技术的核心思想是推迟实际物理内存的分配,直到进程真正访问到该内存区域。这样可以优化内存使用,提高系统性能。对于内存的懒分配,比如堆栈分配,mmap 匿名内存分配,Eonix 将许可分配的范围记录下来,但并不进行实际分配操作,当用户访问到许诺分配但未分配的页面时会触发缺页异常,缺页异常处理函数会进行实际的分配操作。
+
+**高效用户态内存拷贝**
+在系统调用过程中,内核需要频繁与用户态指针指向的数据进行交互,例如 read、write 系统调用。在 Eonix 中,用户和内核共享地址空间,因此在访问用户态的内存时不需要同 xv6/rcore 那样通过软件查询页表,而是可以直接解引用用户态指针。
+然而,用户态指针(例如,read 系统调用参数中指向的用户态buf的指针)并不总是有效的,有可能指向非法内存,在这种情况下,仅通过类似 memcpy 简单拷贝操作可能导致内核的panic。Eonix 内核的用户态内存拷贝参考了 Linux copy_from_user 的实现思路,利用 PageFault 实现内核访问用户态内存的高效拷贝和错误处理。具体实现为当内核访问用户态指针出现 PageFault,会在 PageFault 处理函数中调用 try_page_fault_fix,此函数会修改进程中断上下文的 pc 值,使 PageFault 处理完毕后跳转到拷贝结束处,并可以根据拷贝字节数判断拷贝过程中是否出现异常状况。该处理方法在用户指针正常时速度极快,同时还能完全复用用户缺页异常处理的代码来处理用户指针懒加载/写时复制的情况。并且为了进一步方便内核使用用户态指针,Eonix 定义了 UserBuffer、UserString、UserPointer 结构体。
+``` rust
+/// Try to fix the page fault by jumping to the `error` address.
+///
+/// Panic if we can't find the `ip` in the fix list.
+fn try_page_fault_fix(int_stack: &mut InterruptContext, addr: VAddr) {
+    let ip = int_stack.rip as u64;
+
+    // SAFETY: `FIX_START` and `FIX_END` are defined in the linker script in `.rodata` section.
+    let entries = unsafe {
+        core::slice::from_raw_parts(
+            FIX_START,
+            (FIX_END as usize - FIX_START as usize) / size_of::<FixEntry>(),
+        )
+    };
+
+    for entry in entries.iter() {
+        if ip >= entry.start && ip < entry.start + entry.length {
+            int_stack.rip = entry.jump_address as u64;
+            return;
+        }
+    }
+
+    kernel_page_fault_die(addr, ip as usize)
+}
+```

+ 90 - 0
doc/multi_arch.md

@@ -0,0 +1,90 @@
+# 多架构支持
+Eonix 目前仅支持x86-64架构,但为了后续多架构的支持,在 Eonix 开发过程中尽可能的将架构相关的操作进行抽象,并充分利用 rust 包管理机制,将架构相关代码统一置于 arch crate 中,便于后续多架构扩展。Eonix 通过 cfg-if 实现不同架构的条件编译。
+``` rust
+cfg_if::cfg_if! {
+    if #[cfg(target_arch = "x86_64")] {
+        mod x86_64;
+        pub use self::x86_64::*;
+    } else if #[cfg(target_arch = "riscv64")] {
+        mod riscv64;
+        pub use self::riscv64::*;
+    } else if #[cfg(target_arch = "aarch64")]{
+        mod aarch64;
+        pub use self::aarch64::*;
+    }
+}
+```
+## 进程相关抽象
+### 进程上下文抽象
+进程上下文是内核调度的关键结构,但由于不同的体系结构在进程上下文的保存上存在差异,例如,x86-64 只能将上下文存储在内核栈上,而 riscv64 可以定义相关结构体存储上下文内容,所以我们将进程上下文及其相关操作,如上下文初始化,上下文切换等统一进行抽象,这样内核处理上下文时只需要 TaskContext 提供的统一接口。
+``` rust
+// x86-64
+pub struct TaskContext {
+    /// The kernel stack pointer
+    pub rsp: u64,
+    // Extended states, i.e., FP/SIMD states to do!
+}
+
+impl TaskContext {
+    pub const fn new() -> Self {
+        Self { rsp: 0 }
+    }
+
+    pub fn init(&mut self, entry: usize, kstack_top: usize) {
+        unsafe {
+            let frame_ptr = (kstack_top as *mut ContextSwitchFrame).sub(1);
+            core::ptr::write(
+                frame_ptr,
+                ContextSwitchFrame {
+                    rip: entry as u64,
+                    eflags: 0x200,
+                    ..Default::default()
+                },
+            );
+            self.rsp = frame_ptr as u64;
+        }
+    }
+
+    #[inline(always)]
+    pub fn switch_to(&mut self, next_task: &mut Self) {
+        unsafe { _switch_to(&mut self.rsp, &mut next_task.rsp) }
+    }
+}
+```
+## 内存相关抽象
+页表根目录的修改和获取,tlb的刷新等都是内核必须的内存操作,提供有关抽象很有必要。
+
+## IO相关抽象
+### 中断上下文抽象
+中断上下文需要保存中断前CPU所有信息,为了多架构的统一,将中断上下文抽象为InterruptContext,这样内核再进行中断相关操作时无需考虑架构上的差异。
+``` rust
+// x86-64
+pub struct InterruptContext {
+    pub rax: u64,
+    pub rbx: u64,
+    pub rcx: u64,
+    pub rdx: u64,
+    pub rdi: u64,
+    pub rsi: u64,
+    pub r8: u64,
+    pub r9: u64,
+    pub r10: u64,
+    pub r11: u64,
+    pub r12: u64,
+    pub r13: u64,
+    pub r14: u64,
+    pub r15: u64,
+    pub rbp: u64,
+
+    pub int_no: u64,
+    pub error_code: u64,
+
+    // Pushed by CPU
+    pub rip: u64,
+    pub cs: u64,
+    pub eflags: u64,
+    pub rsp: u64,
+    pub ss: u64,
+}
+```
+## 杂项

+ 148 - 0
doc/task.md

@@ -0,0 +1,148 @@
+### Eonix内核的任务管理
+
+Eonix内核的任务管理系统通过线程、进程、进程组、会话和信号机制,构建了一个高效、灵活的多任务管理框架。以下是对其任务管理部分的全面介绍:
+
+---
+
+### 1. 核心设计概述
+任务管理是内核调度和进程间通信的基础,其核心组件包括:
+- 线程(`Thread`): 是调度的基本单位。
+- 进程(`Process`): 是资源分配的基本单位,包含线程的集合。
+- 进程组(`ProcessGroup`): 组织和管理一组相关进程,通常用于信号广播。
+- 会话(`Session`): 包含多个进程组,为作业控制和终端管理提供支持。
+- 信号机制: 负责进程间通信、异常处理和任务状态控制。
+  
+Eonix的任务管理通过统一的接口和模块化设计,支持复杂的任务调度、资源管理和进程间交互。
+
+---
+
+### 2. 线程管理
+
+线程是Eonix内核调度的基本单位,由`Thread`结构体表示,每个线程包含独立的内核栈(`KernelStack`)、文件系统上下文和文件描述符表等资源。线程的状态管理(如`Running`、`ISleep`、`USleep`等)通过调度器接口完成,支持线程在用户态和内核态之间高效切换。线程中有进程的指针,这样可以做到多个线程共享一部分资源。通过`InterruptContext`和`TaskContext`实现上下文保存与切换,确保任务运行的连续性和调度的高效性。
+
+每个线程由`Thread`结构体表示,包含:
+- TID(`tid`): 唯一标识。
+- 线程状态(`state`): 包括`Preparing`、`Running`、`Ready`、`Zombie`等多种状态,用于调度器管理。
+- 内核栈(`kstack`): 为每个线程分配一个独立的内核栈,用于上下文切换和异常处理。
+- 文件系统上下文(`fs_context`)和文件描述符表(`files`): 提供线程的独立资源管理。
+
+#### 线程的生命周期
+
+线程的创建方面,初始线程通过`Thread::new_for_init`创建。像在`clone`或`exec`等中复制的线程通过`Thread::new_cloned`创建,和父线程一起共享一个进程的资源。状态管理通过调度器(`Scheduler`)接口完成,支持从`Running`切换到`ISleep`或`USleep`等状态。 上下文切换使用`InterruptContext`和`TaskContext`保存线程的寄存器状态,支持线程在内核和用户态间切换。
+
+---
+
+### 3. 进程管理
+
+进程是资源分配的基本单位,由`Process`结构体表示。每个进程具有唯一的PID,并包含线程集合、父子关系、内存管理信息(`MMList`)以及所属的进程组和会话。进程的创建通过克隆现有进程实现,支持资源继承,同时初始进程(如`init`进程或闲置进程)通过专门方法生成。进程支持多线程资源共享,通过`WaitList`等待子进程状态变化(如退出或收到信号),并结合信号机制实现进程间通信和同步操作。进程的多线程安全性由锁机制保障。
+
+#### 进程的基本结构
+每个进程由Process结构体表示,包含:
+
+- PID(`pid`): 每个进程都有一个唯一的标识符,用于区分其他进程。
+- 线程集合(`threads`): 用`BTreeMap`储存一个包含属于该进程的所有线程的列表。
+- 子进程(`children`): 使用`BTreeMap`存储该进程的所有子进程,支持高效查找和管理。
+- 内存管理信息(`mm_list`): 使用`MMList`表示进程的内存映射,管理用户态和内核态的地址空间。
+- 父进程(`parent`): 引用父进程,支持动态更新和安全访问。
+- 所属进程组(`pgroup`): 每个进程都属于一个进程组,用于协作管理和信号广播。
+- 会话(`session`): 进程所属的会话,支持终端绑定和作业控制。
+
+#### 进程的生命周期
+
+进程创建通过`Process::new_cloned`方法实现新进程的创建,子进程会继承父进程的大部分资源(如内存和会话)。对于系统初始化的特殊进程(如init进程),通过`Process::new_for_init`创建。
+
+进程终止时,调用`ProcessList::do_kill_process`方法将进程标记为`Zombie`状态,并清理相关资源,包括用户态内存、子进程管理以及从进程组和会话中移除。如果终止的是会话领导进程,关联的控制终端也会被释放。同时,其没有退出的所有子进程都会被收容到init进程中,确保每个进程都可以正常地被回收。
+
+#### 进程管理与多线程支持
+
+`ProcessList`是管理所有进程的核心结构,通过全局实例`GLOBAL_PROC_LIST`维护。`ProcessList`使用`BTreeMap`存储所有的进程、线程、进程组和会话,并通过`RwSemaphore`实现线程安全访问。关键操作包括:
+1. 添加与移除: 通过`add_process`和`remove_process`方法实现进程的动态添加与移除。在移除进程时,还会同步清理其线程、会话和进程组信息。
+2. 查询: 提供`try_find_process`、`try_find_pgroup`等方法,支持高效查找进程和相关结构。
+调度整合: 结合调度器`Scheduler`,支持线程和进程的动态调度,确保高效的多任务管理。
+
+---
+
+### 4. 信号管理
+
+信号是Eonix内核进程间通信和异常处理的核心机制,用于实现进程控制、任务协作和异常处理。信号通过`Signal`结构体表示,并结合`SignalList`和`SignalAction`实现挂起、屏蔽和处理机制。信号的设计符合POSIX标准,支持多种信号类型(如`SIGKILL`、`SIGSTOP`等),并通过进程组和会话实现信号广播和作业控制。
+
+#### 信号的基本结构
+
+信号由`Signal`结构体表示,包含信号类型,即每个信号通过唯一的数字标识,支持常见的POSIX信号类型,包括:
+- 终止信号: 如`SIGTERM`、`SIGKILL`,用于立即终止进程。
+- 停止信号: 如`SIGSTOP`、`SIGTSTP`,用于暂停进程。
+- 用户自定义信号: 如`SIGUSR1`、`SIGUSR2`,用于用户进程间通信。
+- 忽略信号: 如`SIGCHLD`,默认行为是被内核忽略。
+- 核心转储信号: 如`SIGSEGV`、`SIGFPE`,会生成核心转储文件并终止进程。
+
+#### 信号管理与挂起
+
+信号管理由`SignalList`完成,负责信号的挂起、屏蔽和优先级管理。挂起信号存储在`BinaryHeap`中,按照优先级排序,以确保高优先级信号优先处理。通过`SignalList::mask`和`SignalList::unmask`动态管理信号掩码,决定哪些信号会被屏蔽。对于线程或进程接收到的信号,会首先判断其屏蔽状态,屏蔽信号会进入挂起队列,等待后续处理。
+
+#### 信号处理与分发
+
+信号的处理方式由`SignalAction`定义,支持以下三种模式:
+- 默认行为: 系统为每种信号定义的默认处理方式,如终止进程、暂停进程或忽略信号。
+- 自定义Handler: 用户可以为特定信号设置自定义处理器,在用户态执行信号处理逻辑。
+- 忽略信号: 指定某些信号被忽略,如`SIGCHLD`默认不会影响进程运行。
+
+信号分发可以针对单个线程、进程组或会话的前台进程组进行广播。通过`SignalList::raise`方法,信号被加入目标对象的挂起信号队列,并根据优先级等待处理。
+
+#### 信号与上下文切换
+
+信号处理与上下文切换紧密结合。当线程被调度器切换到运行状态时,内核会检测其挂起信号列表,并调用相应的信号处理器。信号处理器通过`SignalAction::handle`加载到用户堆栈中,修改`InterruptContext`返回地址,将执行跳转到用户态的信号处理函数中。
+
+对于不可屏蔽信号(如`SIGKILL`、`SIGSTOP`),内核会立即终止或暂停目标进程,不会经过挂起队列或信号处理器。
+
+#### 信号的进程间通信
+
+信号是进程间通信的重要机制,支持通过进程组和会话范围实现信号广播。例如:
+- 通过`ProcessGroup::raise`将信号发送给整个进程组。
+- 使用`Session::raise_foreground`向会话的前台进程组发送信号,实现作业控制。
+
+信号分发结合进程组和会话机制,为任务管理中的状态同步和协作提供了基础设施。
+
+Eonix内核的信号管理模块通过模块化设计和POSIX标准兼容,实现了灵活的进程间通信和异常处理。挂起信号、屏蔽机制和优先级队列确保信号的高效处理,自定义处理器扩展了信号的适用场景。信号与上下文切换和调度器紧密结合,为系统的异常响应和作业控制提供了强大支持,同时通过进程组和会话的广播功能增强了信号的可扩展性。
+
+---
+
+### 5. 会话、进程组与作业控制
+
+Eonix内核中的会话和进程组机制是任务管理系统的重要组成部分,为进程的组织管理、信号广播和作业控制提供了基础。会话通过将多个进程组归为一个集合,结合控制终端(`Terminal`)实现用户与作业的交互。作业控制支持前台/后台作业切换、暂停与恢复等操作,使内核能够高效管理任务协作。
+
+#### 会话的基本结构
+
+会话由`Session`结构体表示,通过`SessionJobControl`管理前台进程组和控制终端,使用读写信号量(`RwSemaphore`)确保多线程安全访问。包含以下核心组件:
+
+- SID(`sid`): 由会话领导进程的PID决定,是会话的唯一标识。
+- 领导进程(`leader`): 会话的创建者,负责初始化会话并管理其生命周期。
+- 前台进程组(`foreground`): 当前与用户交互的进程组,用户输入和信号优先发送到此进程组。
+- 控制终端(`control_terminal`): 绑定到会话的终端设备,用于用户与前台进程组的交互。
+- 进程组集合(`groups`): 存储会话中的所有进程组,支持动态添加和移除。
+
+#### 进程组的基本结构
+
+进程组由`ProcessGroup`结构体表示,是进程的集合,主要用于信号广播和作业管理。支持成员的动态添加和移除,并通过所属会话与控制终端关联。。每个进程组包含以下部分:
+
+- 进程组ID(`pgid`): 用于唯一标识进程组,通常等于其领导进程的PID。
+- 领导进程(`leader`): 进程组的创建者,负责管理该组的资源和信号。
+- 所属会话(`session`): 进程组所属的会话,确保跨进程组的协作一致性。
+- 成员进程(`processes`): 使用`BTreeMap`存储进程组内的所有进程,支持快速查找和广播信号。
+
+#### 作业控制
+
+作业控制是通过会话的前台进程组和控制终端实现的,支持以下功能:
+
+1. 前后台作业切换: 通过`Session::set_foreground_pgid`设置前台进程组,使用户输入和信号优先发送到新的作业。
+2. 信号广播: 通过`Session::raise_foreground`将信号发送给前台进程组,常用于暂停(`SIGSTOP`)或恢复(`SIGCONT`)前台作业。
+3. 终端绑定: 使用`Session::set_control_terminal`将终端绑定到会话,确保用户输入输出只影响绑定的会话。会话领导进程拥有设置和释放控制终端的权限。
+
+会话与进程组的管理由`ProcessList`模块实现,新会话通过`Session::new`创建,进程组通过`Session::new_group`添加到会话。移除进程组时,如果会话中无其他进程组,会自动解除与控制终端的绑定。`ProcessList`提供方法查找会话和进程组,如`try_find_session`和`try_find_pgroup`。信号通过`ProcessGroup::raise`广播到整个进程组,或通过`Session::raise_foreground`广播到前台进程组。
+
+会话和进程组与信号机制紧密协作,提供多层次的任务控制能力。会话通过前台进程组分发信号,实现广播,可以控制用户当前交互作业。用户可以通过绑定的终端发送信号(如`SIGSTOP`或`SIGCONT`)控制作业状态切换。当会话领导进程终止时,内核会自动释放绑定的控制终端,并将会话中所有进程移至后台。
+
+## 实现中遇到的问题
+
+当前实现中,进程中对于其子线程、子进程,以及会话和进程组中对于所有成员的引用的设计可能会造成不一致。比如我们在移除一个进程的时候,需要将这个进程从其父进程的子进程表中删除,还需要将其从进程组和会话的成员列表中删除。同时在添加进程的时候要注意把这个进程加到这些表里。我们在这些过程当中有多个位置都要注意,一不小心就会导致内核崩溃。想到的一个解决办法就是用侵入式链表改良,将这几个过程合起来,降低复杂性。
+
+还需要实现`clone`系统调用,用于实现 *POSIX* 标准中的线程。

+ 71 - 0
gblibc/CMakeLists.txt

@@ -0,0 +1,71 @@
+cmake_minimum_required(VERSION 3.15)
+project(gblibc)
+
+add_library(gblibc STATIC
+    src/stdio.c
+    src/arithmetic.c
+    src/string.c
+    src/fcntl.c
+    src/unistd.c
+    src/wait.c
+    src/assert.c
+    src/dirent.c
+    src/ctype.c
+    src/stdlib.c
+    src/errno.c
+    src/init.c
+    src/internal.c
+    src/stat.c
+    src/time.c
+    src/signal.c
+    src/platform-independent.s
+)
+
+add_library(gblibc_32 STATIC
+    src/stdio.c
+    src/arithmetic.c
+    src/string.c
+    src/fcntl.c
+    src/unistd.c
+    src/wait.c
+    src/assert.c
+    src/dirent.c
+    src/ctype.c
+    src/stdlib.c
+    src/errno.c
+    src/init.c
+    src/internal.c
+    src/stat.c
+    src/time.c
+    src/signal.c
+    src/platform-independent.s
+)
+
+add_library(crt0_32 OBJECT
+    src/crt0.s
+)
+
+target_compile_options(gblibc_32 PRIVATE "-fno-pic")
+target_compile_options(gblibc_32 PRIVATE "-mcmodel=32")
+target_compile_options(gblibc_32 PRIVATE "-m32")
+target_compile_options(crt0_32 PRIVATE "-fno-pic")
+target_compile_options(crt0_32 PRIVATE "-m32")
+target_compile_options(crt0_32 PRIVATE "-mcmodel=32")
+target_link_options(gblibc_32 PRIVATE "LINKER:-melf_i386")
+target_link_options(crt0_32 PRIVATE "LINKER:-melf_i386")
+
+file(GLOB_RECURSE GBLIBC_PUBLIC_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include)
+
+target_include_directories(gblibc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
+                                  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/private-include)
+
+set_target_properties(gblibc PROPERTIES PRIVATE_HEADER
+    "private-include/devutil.h,private-include/syscall.h")
+set_target_properties(gblibc PROPERTIES PUBLIC_HEADER "${GBLIBC_PUBLIC_HEADERS}")
+
+target_include_directories(gblibc_32 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
+                                  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/private-include)
+
+set_target_properties(gblibc_32 PROPERTIES PRIVATE_HEADER
+    "private-include/devutil.h,private-include/syscall.h")
+set_target_properties(gblibc_32 PROPERTIES PUBLIC_HEADER "${GBLIBC_PUBLIC_HEADERS}")

+ 16 - 0
gblibc/include/alloca.h

@@ -0,0 +1,16 @@
+#ifndef __GBLIBC_ALLOCA_H_
+#define __GBLIBC_ALLOCA_H_
+
+#include <stdint.h>
+
+#define alloca(size) __builtin_alloca(size)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 21 - 0
gblibc/include/assert.h

@@ -0,0 +1,21 @@
+#ifndef __GBLIBC_ASSERT_H_
+#define __GBLIBC_ASSERT_H_
+
+#ifdef NDEBUG
+#define assert(st) ((void)(st))
+#else
+#define assert(st) ((void)((st) || (__assert_fail(#st, __FILE__, __LINE__, __func__), 0)))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void __attribute__((noreturn))
+__assert_fail(const char* statement, const char* file, int line, const char* func);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 32 - 0
gblibc/include/bits/alltypes.h

@@ -0,0 +1,32 @@
+#ifndef __GBLIBC_BITS_ALLTYPES_H_
+#define __GBLIBC_BITS_ALLTYPES_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef size_t blksize_t;
+typedef size_t blkcnt_t;
+
+struct timespec {
+    time_t tv_sec;
+    long tv_nsec;
+};
+
+struct timeval {
+    time_t tv_sec;
+    size_t tv_usec;
+};
+
+struct timezone {
+    int tz_minuteswest;
+    int tz_dsttime;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 27 - 0
gblibc/include/bits/ioctl.h

@@ -0,0 +1,27 @@
+#ifndef __GBLIBC_BITS_IOCTL_H_
+#define __GBLIBC_BITS_IOCTL_H_
+
+#include <sys/uio.h>
+
+#define TCGETS (0x5401)
+#define TCSETS (0x5402)
+#define TIOCGPGRP (0x540f)
+#define TIOCSPGRP (0x5410)
+#define TIOCGWINSZ (0x5413)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct winsize {
+    unsigned short ws_row;
+    unsigned short ws_col;
+    unsigned short ws_xpixel;
+    unsigned short ws_ypixel;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 18 - 0
gblibc/include/ctype.h

@@ -0,0 +1,18 @@
+#ifndef __GBLIBC_CTYPE_H_
+#define __GBLIBC_CTYPE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int islower(int c);
+int isupper(int c);
+
+int tolower(int c);
+int toupper(int c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 35 - 0
gblibc/include/dirent.h

@@ -0,0 +1,35 @@
+#ifndef __GBLIBC_DIRENT_H_
+#define __GBLIBC_DIRENT_H_
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct dirent {
+    ino_t d_ino;
+    off_t d_off;
+    unsigned short d_reclen;
+    unsigned char d_type;
+    char d_name[256];
+};
+
+typedef struct _DIR {
+    int fd;
+    struct dirent dent;
+    char buffer[232];
+    int bpos;
+    int blen;
+} DIR;
+
+DIR* opendir(const char* name);
+DIR* fdopendir(int fd);
+
+struct dirent* readdir(DIR* dirp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 41 - 0
gblibc/include/errno.h

@@ -0,0 +1,41 @@
+#ifndef __GBLIBC_ERRNO_H_
+#define __GBLIBC_ERRNO_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int* __errno_location(void);
+
+#undef errno
+#define errno (*__errno_location())
+
+#define EPERM 1
+#define ENOENT 2
+#define ESRCH 3
+#define EINTR 4
+#define EIO 5
+#define EBADF 9
+#define ECHILD 10
+#define EAGAIN 11
+#define ENOMEM 12
+#define EACCES 13
+#define EFAULT 14
+#define EEXIST 17
+#define ENODEV 19
+#define ENOTDIR 20
+#define EISDIR 21
+#define EINVAL 22
+#define ENOTTY 25
+#define ESPIPE 29
+#define EROFS 30
+#define EPIPE 32
+#define ERANGE 34
+#define ELOOP 40
+#define EOVERFLOW 75
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 49 - 0
gblibc/include/fcntl.h

@@ -0,0 +1,49 @@
+#ifndef __GBLIBC_FCNTL_H_
+#define __GBLIBC_FCNTL_H_
+
+#include <stdint.h>
+
+#define O_RDONLY          00
+#define O_WRONLY          01
+#define O_RDWR            02
+#define O_CREAT         0100
+#define O_EXCL          0200
+#define O_TRUNC        01000
+#define O_APPEND       02000
+#define O_DIRECTORY  0200000
+#define O_CLOEXEC   02000000
+
+#define F_DUPFD 0
+#define F_GETFD 1
+#define F_SETFD 2
+#define F_GETFL 3
+#define F_SETFL 4
+#define F_DUPFD_CLOEXEC 1030
+// TODO: more flags
+
+#define FD_CLOEXEC 1
+
+#define AT_FDCWD (-100)
+#define AT_SYMLINK_NOFOLLOW   0x100
+#define AT_REMOVEDIR          0x200
+#define AT_SYMLINK_FOLLOW     0x400
+#define AT_STATX_SYNC_AS_STAT 0x0000
+#define AT_STATX_SYNC_TYPE    0x6000
+#define AT_STATX_SYNC_FORCE   0x8000
+#define AT_STATX_DONT_SYNC    0x2000
+
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int open(const char* filename, int flags, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 35 - 0
gblibc/include/poll.h

@@ -0,0 +1,35 @@
+#ifndef __GBLIBC_POLL_H_
+#define __GBLIBC_POLL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned int nfds_t;
+
+#define POLLIN          0x0001          /* any readable data available */
+#define POLLPRI         0x0002          /* OOB/Urgent readable data */
+#define POLLOUT         0x0004          /* file descriptor is writeable */
+#define POLLRDNORM      0x0040          /* non-OOB/URG data available */
+#define POLLWRNORM      POLLOUT         /* no write type differentiation */
+#define POLLRDBAND      0x0080          /* OOB/Urgent readable data */
+#define POLLWRBAND      0x0100          /* OOB/Urgent data can be written */
+
+#define POLLERR         0x0008          /* some poll error occurred */
+#define POLLHUP         0x0010          /* file descriptor was "hung up" */
+#define POLLNVAL        0x0020          /* requested events "invalid" */
+
+#define POLLSTANDARD    (POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND|\
+	                 POLLWRBAND|POLLERR|POLLHUP|POLLNVAL)
+
+struct pollfd {
+	int     fd;
+	short   events;
+	short   revents;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 69 - 0
gblibc/include/signal.h

@@ -0,0 +1,69 @@
+#ifndef __GBLIBC_SIGNAL_H_
+#define __GBLIBC_SIGNAL_H_
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SIGHUP    1
+#define SIGINT    2
+#define SIGQUIT   3
+#define SIGILL    4
+#define SIGTRAP   5
+#define SIGABRT   6
+#define SIGIOT    SIGABRT
+#define SIGBUS    7
+#define SIGFPE    8
+#define SIGKILL   9
+#define SIGUSR1   10
+#define SIGSEGV   11
+#define SIGUSR2   12
+#define SIGPIPE   13
+#define SIGALRM   14
+#define SIGTERM   15
+#define SIGSTKFLT 16
+#define SIGCHLD   17
+#define SIGCONT   18
+#define SIGSTOP   19
+#define SIGTSTP   20
+#define SIGTTIN   21
+#define SIGTTOU   22
+#define SIGURG    23
+#define SIGXCPU   24
+#define SIGXFSZ   25
+#define SIGVTALRM 26
+#define SIGPROF   27
+#define SIGWINCH  28
+#define SIGIO     29
+#define SIGPOLL   29
+#define SIGPWR    30
+#define SIGSYS    31
+#define SIGUNUSED SIGSYS
+#define SIGRTMIN  32
+#define SIGRTMAX  64
+
+#define SIG_BLOCK 0
+#define SIG_UNBLOCK 1
+#define SIG_SETMASK 2
+
+#define SA_RESTORER 0x04000000
+#define SA_ONSTACK  0x08000000
+#define SA_RESTART  0x10000000
+#define SA_NODEFER  0x40000000
+
+#define SIG_DFL ((sighandler_t)0)
+#define SIG_IGN ((sighandler_t)1)
+
+typedef void (*sighandler_t)(int);
+typedef void (*sigrestorer_t)(void);
+
+int kill(pid_t pid, int sig);
+int raise(int sig);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 11 - 0
gblibc/include/stdarg.h

@@ -0,0 +1,11 @@
+#ifndef __GBLIBC_STDARG_H_
+#define __GBLIBC_STDARG_H_
+
+typedef __builtin_va_list va_list;
+
+#define va_start(v, l) __builtin_va_start(v, l)
+#define va_arg(v, l) __builtin_va_arg(v, l)
+#define va_end(v) __builtin_va_end(v)
+#define va_copy(v, l) __builtin_va_copy(v, l)
+
+#endif

+ 30 - 0
gblibc/include/stdint.h

@@ -0,0 +1,30 @@
+#ifndef __GBLIBC_STDINT_H_
+#define __GBLIBC_STDINT_H_
+
+#undef NULL
+#ifdef __cplusplus
+#define NULL (nullptr)
+#else
+#define NULL ((void*)0)
+#endif
+
+typedef __INT8_TYPE__ int8_t;
+typedef __INT16_TYPE__ int16_t;
+typedef __INT32_TYPE__ int32_t;
+typedef __INT64_TYPE__ int64_t;
+
+typedef __UINT8_TYPE__ uint8_t;
+typedef __UINT16_TYPE__ uint16_t;
+typedef __UINT32_TYPE__ uint32_t;
+typedef __UINT64_TYPE__ uint64_t;
+
+typedef __UINTPTR_TYPE__ uintptr_t;
+typedef __INTPTR_TYPE__ intptr_t;
+
+typedef __SIZE_TYPE__ size_t;
+typedef int64_t ssize_t;
+
+typedef uint64_t time_t;
+typedef int64_t time_diff_t;
+
+#endif

+ 80 - 0
gblibc/include/stdio.h

@@ -0,0 +1,80 @@
+#ifndef __GBLIBC_STDIO_H_
+#define __GBLIBC_STDIO_H_
+
+#include <stdarg.h>
+#include <stdint.h>
+
+#undef EOF
+#define EOF (-1)
+
+#undef BUFSIZ
+#define BUFSIZ (1024)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct __io_file {
+    int fd;
+    uint32_t flags;
+
+    char* rbuf;
+    size_t rpos;
+    size_t rcnt;
+    size_t rbsz;
+
+    char* wbuf;
+    size_t wpos;
+    size_t wbsz;
+} FILE;
+
+int putchar(int character);
+int getchar(void);
+
+int puts(const char* str);
+char* gets(char* str);
+
+int vsnprintf(char* buf, size_t bufsize, const char* fmt, va_list args);
+int snprintf(char* buf, size_t bufsize, const char* fmt, ...);
+int sprintf(char* buf, const char* fmt, ...);
+int vasprintf(char** strp, const char* fmt, va_list args);
+int asprintf(char** strp, const char* fmt, ...);
+
+int vfprintf(FILE* stream, const char* fmt, va_list args);
+int fprintf(FILE* stream, const char* fmt, ...);
+
+int vprintf(const char* fmt, va_list args);
+int printf(const char* fmt, ...);
+
+FILE* fopen(const char* path, const char* mode);
+int fflush(FILE* stream);
+int fclose(FILE* stream);
+
+int getc_unlocked(FILE* stream);
+int putc_unlocked(int character, FILE* stream);
+int fputs_unlocked(const char* s, FILE* stream);
+int fputc_unlocked(int character, FILE* stream);
+int fputs(const char* s, FILE* stream);
+int fgetc(FILE* stream);
+int fputc(int character, FILE* stream);
+
+int ferror(FILE* stream);
+int ferror_unlocked(FILE* stream);
+int feof(FILE* stream);
+void clearerr(FILE* stream);
+
+extern FILE* stdout;
+extern FILE* stdin;
+extern FILE* stderr;
+#undef stdout
+#undef stdin
+#undef stderr
+#define stdout (stdout)
+#define stdin (stdin)
+#define stderr (stderr)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 37 - 0
gblibc/include/stdlib.h

@@ -0,0 +1,37 @@
+#ifndef __GBLIBC_STDLIB_H_
+#define __GBLIBC_STDLIB_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int atoi(const char* str);
+
+void __attribute__((noreturn)) exit(int status);
+
+void* malloc(size_t size);
+void* realloc(void* ptr, size_t newsize);
+void free(void* ptr);
+
+typedef int (*comparator_t)(const void* a, const void* b);
+void qsort(void* base, size_t num, size_t size, comparator_t comparator);
+void* bsearch(
+    const void* key,
+    const void* base,
+    size_t num,
+    size_t size,
+    comparator_t comparator);
+
+int rand(void);
+int rand_r(unsigned int* seedp);
+void srand(unsigned int seed);
+
+int setenv(const char* name, const char* value, int overwrite);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 50 - 0
gblibc/include/string.h

@@ -0,0 +1,50 @@
+#ifndef __GBLIBC_STRING_H_
+#define __GBLIBC_STRING_H_
+
+#include <stdint.h>
+
+#undef CR
+#undef LF
+#define CR ('\r')
+#define LF ('\n')
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int memcmp(const void* ptr1, const void* ptr2, size_t num);
+
+void* memmove(void* dst, const void* src, size_t n);
+void* memcpy(void* dst, const void* src, size_t n);
+void* mempcpy(void* dst, const void* src, size_t n);
+void* memset(void* dst, int c, size_t n);
+
+char* strerror(int errnum);
+
+int strcmp(const char* s1, const char* s2);
+int strncmp(const char* s1, const char* s2, size_t n);
+int strcasecmp(const char* s1, const char* s2);
+int strncasecmp(const char* s1, const char* s2, size_t n);
+size_t strlen(const char* str);
+char* strchr(const char* str, int character);
+char* strrchr(const char* str, int character);
+char* strchrnul(const char* str, int character);
+size_t strcspn(const char* str1, const char* str2);
+char* strstr(const char* str1, const char* str2);
+char* strpbrk(const char* str1, const char* str2);
+
+char* strcpy(char* dst, const char* src);
+char* strncpy(char* dst, const char* src, size_t n);
+char* stpcpy(char* dst, const char* src);
+char* stpncpy(char* dst, const char* src, size_t n);
+
+char* strdup(const char* str);
+char* strndup(const char* str, size_t n);
+
+char* strsignal(int sig);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 16 - 0
gblibc/include/sys/ioctl.h

@@ -0,0 +1,16 @@
+#ifndef __GBLIBC_SYS_IOCTL_H_
+#define __GBLIBC_SYS_IOCTL_H_
+
+#include <bits/ioctl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ioctl(int fd, unsigned long request, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 24 - 0
gblibc/include/sys/mman.h

@@ -0,0 +1,24 @@
+#ifndef __GBLIBC_SYS_MMAN_H
+#define __GBLIBC_SYS_MMAN_H
+
+#include <sys/types.h>
+
+#define MAP_SHARED 0x01
+#define MAP_PRIVATE 0x02
+#define MAP_FIXED 0x10
+#define MAP_ANONYMOUS 0x20
+
+#define PROT_NONE 0
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define PROT_EXEC 4
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 21 - 0
gblibc/include/sys/mount.h

@@ -0,0 +1,21 @@
+#ifndef __GBLIBC_SYS_MOUNT_H
+#define __GBLIBC_SYS_MOUNT_H
+
+#define MS_RDONLY      (1 <<  0)
+#define MS_NOSUID      (1 <<  1)
+#define MS_NODEV       (1 <<  2)
+#define MS_NOEXEC      (1 <<  3)
+#define MS_NOATIME     (1 << 10)
+#define MS_RELATIME    (1 << 21)
+#define MS_STRICTATIME (1 << 24)
+#define MS_LAZYTIME    (1 << 25)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 17 - 0
gblibc/include/sys/prctl.h

@@ -0,0 +1,17 @@
+#ifndef __GBLIBC_SYS_PRCTL_H
+#define __GBLIBC_SYS_PRCTL_H
+
+#include <sys/types.h>
+
+#define PR_SET_NAME 15
+#define PR_GET_NAME 16
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 105 - 0
gblibc/include/sys/stat.h

@@ -0,0 +1,105 @@
+#ifndef __GBLIBC_SYS_STAT_H
+#define __GBLIBC_SYS_STAT_H
+
+#include <stdint.h>
+#include <bits/alltypes.h>
+#include <sys/types.h>
+
+#define STATX_TYPE (1 << 0)
+#define STATX_MODE (1 << 1)
+#define STATX_NLINK (1 << 2)
+#define STATX_UID (1 << 3)
+#define STATX_GID (1 << 4)
+#define STATX_ATIME (1 << 5)
+#define STATX_MTIME (1 << 6)
+#define STATX_CTIME (1 << 7)
+#define STATX_INO (1 << 8)
+#define STATX_SIZE (1 << 9)
+#define STATX_BLOCKS (1 << 10)
+#define STATX_BASIC_STATS (0x7ff)
+#define STATX_BTIME (1 << 11)
+
+#define S_IFMT 0170000
+
+#define S_IFSOCK 0140000
+#define S_IFLNK 0120000
+#define S_IFREG 0100000
+#define S_IFBLK 0060000
+#define S_IFDIR 0040000
+#define S_IFCHR 0020000
+#define S_IFIFO 0010000
+
+#define S_ISSOCK(m) (((m)&S_IFMT) == S_IFSOCK)
+#define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK)
+#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
+#define S_ISBLK(m) (((m)&S_IFMT) == S_IFBLK)
+#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
+#define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR)
+#define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct statx_timestamp {
+    int64_t tv_sec;
+    uint32_t tv_nsec;
+    int32_t __reserved;
+};
+
+struct statx {
+    uint32_t stx_mask;
+    uint32_t stx_blksize;
+    uint64_t stx_attributes;
+    uint32_t stx_nlink;
+    uint32_t stx_uid;
+    uint32_t stx_gid;
+    uint16_t stx_mode;
+    uint16_t __spare0[1];
+    uint64_t stx_ino;
+    uint64_t stx_size;
+    uint64_t stx_blocks;
+    uint64_t stx_attributes_mask;
+    struct statx_timestamp stx_atime;
+    struct statx_timestamp stx_btime;
+    struct statx_timestamp stx_ctime;
+    struct statx_timestamp stx_mtime;
+    uint32_t stx_rdev_major;
+    uint32_t stx_rdev_minor;
+    uint32_t stx_dev_major;
+    uint32_t stx_dev_minor;
+    uint64_t stx_mnt_id;
+    uint64_t stx_dio_alignment[13];
+};
+
+struct stat {
+    dev_t st_dev;
+    ino_t st_ino;
+    nlink_t st_nlink;
+
+    mode_t st_mode;
+    uid_t st_uid;
+    gid_t st_gid;
+
+    dev_t st_rdev;
+    off_t st_size;
+    blksize_t st_blksize;
+    blkcnt_t st_blocks;
+
+    struct timespec st_atim;
+    struct timespec st_mtim;
+    struct timespec st_ctim;
+
+    long __padding[3];
+};
+
+int stat(const char* pathname, struct stat* statbuf);
+int fstat(int fd, struct stat* statbuf);
+
+mode_t umask(mode_t mask);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 16 - 0
gblibc/include/sys/time.h

@@ -0,0 +1,16 @@
+#ifndef __GBLIBC_SYS_TIME_H_
+#define __GBLIBC_SYS_TIME_H_
+
+#include <bits/alltypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int gettimeofday(struct timeval* tv, struct timezone* tz);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 28 - 0
gblibc/include/sys/types.h

@@ -0,0 +1,28 @@
+#ifndef __GBLIBC_SYS_TYPES_H
+#define __GBLIBC_SYS_TYPES_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int pid_t;
+typedef unsigned long ino_t;
+typedef long off_t;
+typedef unsigned dev_t;
+typedef unsigned uid_t;
+typedef unsigned gid_t;
+typedef unsigned short mode_t;
+typedef unsigned long nlink_t;
+
+typedef unsigned long long ino64_t;
+typedef long long off64_t;
+
+typedef off64_t loff_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 19 - 0
gblibc/include/sys/uio.h

@@ -0,0 +1,19 @@
+#ifndef __GBLIBC_SYS_UIO_H
+#define __GBLIBC_SYS_UIO_H
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct iovec {
+    void* iov_base;
+    size_t iov_len;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 43 - 0
gblibc/include/sys/utsname.h

@@ -0,0 +1,43 @@
+#ifndef __GBLIBC_SYS_UTSNAME_H
+#define __GBLIBC_SYS_UTSNAME_H
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define OLD_UTSNAME_LENGTH 8
+
+struct oldold_utsname {
+    char sysname[9];
+    char nodename[9];
+    char release[9];
+    char version[9];
+    char machine[9];
+};
+
+#define UTSNAME_LENGTH 64
+
+struct old_utsname {
+    char sysname[65];
+    char nodename[65];
+    char release[65];
+    char version[65];
+    char machine[65];
+};
+
+struct new_utsname {
+    char sysname[65];
+    char nodename[65];
+    char release[65];
+    char version[65];
+    char machine[65];
+    char domainname[65];
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 29 - 0
gblibc/include/sys/wait.h

@@ -0,0 +1,29 @@
+#ifndef __GBLIBC_SYS_WAIT_H
+#define __GBLIBC_SYS_WAIT_H
+
+#include <sys/types.h>
+
+#define WNOHANG 1
+#define WUNTRACED 2
+
+#define WEXISTATUS(s) (((s) & 0xff00) >> 8)
+#define WTERMSIG(s) ((s) & 0x7f)
+#define WSTOPSIG(s) WEXITSTATUS(s)
+#define WCOREDUMP(s) ((s) & 0x80)
+#define WIFEXITED(s) (!WTERMSIG(s))
+#define WIFSTOPPED(s) (((s) & 0x7f) == 0x7f)
+#define WIFSIGNALED(s) (WTERMSIG(s) && !WIFSTOPPED(s))
+#define WIFCONTINUED(s) ((s) == 0xffff)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+pid_t wait(int* code);
+pid_t waitpid(pid_t pid, int* code, int options);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 182 - 0
gblibc/include/termios.h

@@ -0,0 +1,182 @@
+#ifndef __GBLIBC_TERMIOS_H_
+#define __GBLIBC_TERMIOS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NCCS 32
+
+typedef unsigned char cc_t;
+typedef unsigned int speed_t;
+typedef unsigned int tcflag_t;
+
+struct termios {
+    tcflag_t c_iflag;
+    tcflag_t c_oflag;
+    tcflag_t c_cflag;
+    tcflag_t c_lflag;
+
+    cc_t c_line;
+    cc_t c_cc[NCCS];
+
+    speed_t c_ispeed;
+    speed_t c_ospeed;
+};
+
+// taken from linux kernel code
+
+/* c_cc characters */
+#define VINTR		 0
+#define VQUIT		 1
+#define VERASE		 2
+#define VKILL		 3
+#define VEOF		 4
+#define VTIME		 5
+#define VMIN		 6
+#define VSWTC		 7
+#define VSTART		 8
+#define VSTOP		 9
+#define VSUSP		10
+#define VEOL		11
+#define VREPRINT	12
+#define VDISCARD	13
+#define VWERASE		14
+#define VLNEXT		15
+#define VEOL2		16
+
+/* c_iflag bits */
+#define IGNBRK	0x0001			/* Ignore break condition */
+#define BRKINT	0x0002			/* Signal interrupt on break */
+#define IGNPAR	0x0004			/* Ignore characters with parity errors */
+#define PARMRK	0x0008			/* Mark parity and framing errors */
+#define INPCK	0x0010			/* Enable input parity check */
+#define ISTRIP	0x0020			/* Strip 8th bit off characters */
+#define INLCR	0x0040			/* Map NL to CR on input */
+#define IGNCR	0x0080			/* Ignore CR */
+#define ICRNL	0x0100			/* Map CR to NL on input */
+#define IUCLC	0x0200
+#define IXON	0x0400
+#define IXANY	0x0800			/* Any character will restart after stop */
+#define IXOFF	0x1000
+#define IMAXBEL	0x2000
+#define IUTF8	0x4000
+
+/* c_oflag bits */
+#define OPOST	0x00001			/* Perform output processing */
+#define OLCUC	0x00002
+#define ONLCR	0x00004
+#define OCRNL	0x00008
+#define ONOCR	0x00010
+#define ONLRET	0x00020
+#define OFILL	0x00040
+#define OFDEL	0x00080
+#define NLDLY	0x00100
+#define   NL0	0x00000
+#define   NL1	0x00100
+#define CRDLY	0x00600
+#define   CR0	0x00000
+#define   CR1	0x00200
+#define   CR2	0x00400
+#define   CR3	0x00600
+#define TABDLY	0x01800
+#define   TAB0	0x00000
+#define   TAB1	0x00800
+#define   TAB2	0x01000
+#define   TAB3	0x01800
+#define   XTABS	0x01800
+#define BSDLY	0x02000
+#define   BS0	0x00000
+#define   BS1	0x02000
+#define VTDLY	0x04000
+#define   VT0	0x00000
+#define   VT1	0x04000
+#define FFDLY	0x08000
+#define   FF0	0x00000
+#define   FF1	0x08000
+
+/* c_cflag bit meaning */
+/* Common CBAUD rates */
+#define     B0		0x00000000	/* hang up */
+#define    B50		0x00000001
+#define    B75		0x00000002
+#define   B110		0x00000003
+#define   B134		0x00000004
+#define   B150		0x00000005
+#define   B200		0x00000006
+#define   B300		0x00000007
+#define   B600		0x00000008
+#define  B1200		0x00000009
+#define  B1800		0x0000000a
+#define  B2400		0x0000000b
+#define  B4800		0x0000000c
+#define  B9600		0x0000000d
+#define B19200		0x0000000e
+#define B38400		0x0000000f
+#define EXTA		B19200
+#define EXTB		B38400
+
+#define ADDRB		0x20000000	/* address bit */
+#define CMSPAR		0x40000000	/* mark or space (stick) parity */
+#define CRTSCTS		0x80000000	/* flow control */
+
+#define IBSHIFT		16		/* Shift from CBAUD to CIBAUD */
+
+#define CBAUD		0x0000100f
+#define CSIZE		0x00000030
+#define   CS5		0x00000000
+#define   CS6		0x00000010
+#define   CS7		0x00000020
+#define   CS8		0x00000030
+#define CSTOPB		0x00000040
+#define CREAD		0x00000080
+#define PARENB		0x00000100
+#define PARODD		0x00000200
+#define HUPCL		0x00000400
+#define CLOCAL		0x00000800
+#define CBAUDEX		0x00001000
+#define BOTHER		0x00001000
+#define     B57600	0x00001001
+#define    B115200	0x00001002
+#define    B230400	0x00001003
+#define    B460800	0x00001004
+#define    B500000	0x00001005
+#define    B576000	0x00001006
+#define    B921600	0x00001007
+#define   B1000000	0x00001008
+#define   B1152000	0x00001009
+#define   B1500000	0x0000100a
+#define   B2000000	0x0000100b
+#define   B2500000	0x0000100c
+#define   B3000000	0x0000100d
+#define   B3500000	0x0000100e
+#define   B4000000	0x0000100f
+#define CIBAUD		0x100f0000	/* input baud rate */
+
+/* c_lflag bits */
+#define ISIG	0x00001
+#define ICANON	0x00002
+#define XCASE	0x00004
+#define ECHO	0x00008
+#define ECHOE	0x00010
+#define ECHOK	0x00020
+#define ECHONL	0x00040
+#define NOFLSH	0x00080
+#define TOSTOP	0x00100
+#define ECHOCTL	0x00200
+#define ECHOPRT	0x00400
+#define ECHOKE	0x00800
+#define FLUSHO	0x01000
+#define PENDIN	0x04000
+#define IEXTEN	0x08000
+#define EXTPROC	0x10000
+
+// line disciplines
+
+#define N_TTY 0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 19 - 0
gblibc/include/time.h

@@ -0,0 +1,19 @@
+#ifndef __GBLIBC_TIME_H_
+#define __GBLIBC_TIME_H_
+
+#include <stdint.h>
+#include <bits/alltypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CLOCK_REALTIME 0
+#define CLOCK_MONOTONIC 1
+typedef int clockid_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 63 - 0
gblibc/include/unistd.h

@@ -0,0 +1,63 @@
+#ifndef __GBLIBC_UNISTD_H_
+#define __GBLIBC_UNISTD_H_
+
+#include <sys/types.h>
+
+#undef STDOUT_FILENO
+#undef STDIN_FILENO
+#undef STDERR_FILENO
+#define STDIN_FILENO (0)
+#define STDOUT_FILENO (1)
+#define STDERR_FILENO (2)
+
+#define F_OK 0
+#define R_OK 1
+#define W_OK 2
+#define X_OK 4
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ssize_t read(int fd, void* buf, size_t count);
+ssize_t write(int fd, const void* buf, size_t count);
+
+int dup(int oldfd);
+int dup2(int oldfd, int newfd);
+
+int pipe(int pipefd[2]);
+
+int close(int fd);
+
+void __attribute__((noreturn)) _exit(int code);
+pid_t fork(void);
+int execve(const char* pathname, char* const argv[], char* const envp[]);
+
+unsigned int sleep(unsigned int seconds);
+
+int chdir(const char* path);
+char* getcwd(char* buf, size_t bufsize);
+
+pid_t getpid(void);
+pid_t getppid(void);
+
+int setpgid(pid_t pid, pid_t pgid);
+
+pid_t setsid(void);
+pid_t getsid(pid_t pid);
+
+pid_t tcgetpgrp(int fd);
+int tcsetpgrp(int fd, pid_t pgrp);
+
+int brk(void* addr);
+void* sbrk(ssize_t increment);
+
+int isatty(int fd);
+
+extern char** environ;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 11 - 0
gblibc/private-include/devutil.h

@@ -0,0 +1,11 @@
+#ifndef __GBLIBC_DEVUTIL_H_
+#define __GBLIBC_DEVUTIL_H_
+
+#ifdef __i386__
+
+#define __GBLIBC__X86_SYSTEM_
+#define __32bit_system
+
+#endif
+
+#endif

+ 34 - 0
gblibc/private-include/list.h

@@ -0,0 +1,34 @@
+#ifndef __GBLIBC_LIST_H_
+#define __GBLIBC_LIST_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct list_node {
+    struct list_node* prev;
+    struct list_node* next;
+    char data[];
+};
+
+typedef struct list_node list_node;
+typedef list_node list_head;
+
+#define NDDATA(node, type) (*((type*)((node).data)))
+#define NDPREV(node) ((node).prev)
+#define NDNEXT(node) ((node).next)
+#define NDISEND(node) (!((node).next))
+#define NEWNODE(type) ((struct list_node*)malloc(sizeof(list_node) + sizeof(type)))
+#define NDPTR(p_data) ((list_node*)((char*)p_data - sizeof(list_node)))
+
+void __node_insert(list_node* node, list_node* new_node);
+void __node_erase(list_node* node);
+
+#define NDINSERT(node, newnode) __node_insert(node, newnode)
+#define NDERASE(p_node) __node_erase(p_node)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 41 - 0
gblibc/private-include/priv-vars.h

@@ -0,0 +1,41 @@
+#ifndef __GBLIBC_PRIV_VARS_H_
+#define __GBLIBC_PRIV_VARS_H_
+
+#include <list.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct mem {
+    uint32_t sz;
+    uint32_t flag;
+};
+
+#define FILE_READ (1 << 0)
+#define FILE_WRITE (1 << 1)
+#define FILE_ERROR (1 << 2)
+#define FILE_EOF (1 << 3)
+
+void** __start_brk_location(void);
+void** __curr_brk_location(void);
+list_head* __io_files_location(void);
+size_t* __environ_size_location(void);
+
+#undef start_brk
+#define start_brk (*__start_brk_location())
+#undef curr_brk
+#define curr_brk (*__curr_brk_location())
+
+#undef iofiles
+#define iofiles (*__io_files_location())
+
+#undef environ_size
+#define environ_size (*__environ_size_location())
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 97 - 0
gblibc/private-include/syscall.h

@@ -0,0 +1,97 @@
+#ifndef __GBLIBC_SYSCALL_H_
+#define __GBLIBC_SYSCALL_H_
+
+#include <stdint.h>
+
+#define SYS_exit (0x01)
+#define SYS_fork (0x02)
+#define SYS_read (0x03)
+#define SYS_write (0x04)
+#define SYS_open (0x05)
+#define SYS_close (0x06)
+#define SYS_waitpid (0x07)
+#define SYS_execve (0x0b)
+#define SYS_chdir (0x0c)
+#define SYS_stat (0x12)
+#define SYS_getpid (0x14)
+#define SYS_fstat (0x1c)
+#define SYS_kill (0x25)
+#define SYS_dup (0x29)
+#define SYS_pipe (0x2a)
+#define SYS_brk (0x2d)
+#define SYS_ioctl (0x36)
+#define SYS_setpgid (0x39)
+#define SYS_dup2 (0x3f)
+#define SYS_umask (0x3c)
+#define SYS_getppid (0x40)
+#define SYS_setsid (0x42)
+#define SYS_gettimeofday (0x4e)
+#define SYS_getdents (0x84)
+#define SYS_writev (0x92)
+#define SYS_getsid (0x93)
+#define SYS_nanosleep (0xa2)
+#define SYS_getcwd (0xb7)
+#define SYS_set_thread_area (0xf3)
+#define SYS_exit_group (0xfc)
+#define SYS_set_tid_address (0x102)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline uint32_t syscall0(uint32_t no)
+{
+    asm volatile(
+        "movl %1, %%eax\n"
+        "int $0x80\n"
+        "movl %%eax, %0"
+        : "=g"(no)
+        : "g"(no)
+        : "eax");
+    return no;
+}
+static inline uint32_t syscall1(uint32_t no, uint32_t arg)
+{
+    asm volatile(
+        "movl %1, %%ebx\n"
+        "movl %2, %%eax\n"
+        "int $0x80\n"
+        "movl %%eax, %0"
+        : "=g"(no)
+        : "g"(arg), "g"(no)
+        : "eax", "ebx");
+    return no;
+}
+static inline uint32_t syscall2(uint32_t no, uint32_t arg1, uint32_t arg2)
+{
+    asm volatile(
+        "movl %1, %%ebx\n"
+        "movl %2, %%ecx\n"
+        "movl %3, %%eax\n"
+        "int $0x80\n"
+        "movl %%eax, %0"
+        : "=g"(no)
+        : "g"(arg1), "g"(arg2), "g"(no)
+        : "eax", "ebx", "ecx");
+    return no;
+}
+static inline uint32_t syscall3(uint32_t no, uint32_t arg1, uint32_t arg2, uint32_t arg3)
+{
+    asm volatile(
+        "movl %1, %%ebx\n"
+        "movl %2, %%ecx\n"
+        "movl %3, %%edx\n"
+        "movl %4, %%eax\n"
+        "int $0x80\n"
+        "movl %%eax, %0"
+        : "=g"(no)
+        : "g"(arg1), "g"(arg2), "g"(arg3), "g"(no)
+        : "eax", "ebx", "ecx", "edx");
+    return no;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 65 - 0
gblibc/src/arithmetic.c

@@ -0,0 +1,65 @@
+#include <devutil.h>
+#include <stdint.h>
+
+static inline uint64_t do_div(uint64_t a, uint64_t b, uint64_t* remainder)
+{
+    uint64_t r = 0, q = 0;
+    for (int32_t i = 0; i < 64; i++) {
+        r = (r << 1) + (a >> 63);
+        a <<= 1;
+        q <<= 1;
+        if (r >= b) {
+            r -= b;
+            q += 1;
+        }
+    }
+    if (remainder)
+        *remainder = r;
+    return q;
+}
+
+static inline int64_t do_div_s(int64_t a, int64_t b, uint64_t* remainder)
+{
+    int32_t qf = 0, rf = 0;
+    if (a < 0) {
+        qf = rf = 1;
+        a = -a;
+    }
+    if (b < 0) {
+        qf ^= 1;
+        b = -b;
+    }
+
+    int64_t quotient = do_div(a, b, (uint64_t*)remainder);
+
+    if (qf)
+        quotient = -quotient;
+    if (remainder && rf)
+        *remainder = -*remainder;
+
+    return quotient;
+}
+
+int64_t __divdi3(int64_t a, int64_t b)
+{
+    return do_div_s(a, b, (uint64_t*)0);
+}
+
+int64_t __moddi3(int64_t a, int64_t b)
+{
+    uint64_t remainder = 0;
+    do_div_s(a, b, &remainder);
+    return remainder;
+}
+
+uint64_t __udivdi3(uint64_t a, uint64_t b)
+{
+    return do_div(a, b, NULL);
+}
+
+uint64_t __umoddi3(uint64_t a, uint64_t b)
+{
+    uint64_t rem = 0;
+    do_div(a, b, &rem);
+    return rem;
+}

+ 12 - 0
gblibc/src/assert.c

@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <unistd.h>
+
+_Noreturn void __attribute__((weak))
+__assert_fail(const char* statement, const char* file, int line, const char* func)
+{
+    char buf[256] = {};
+    int len = snprintf(buf, sizeof(buf), "Assertion failed: (%s) in %s:%d, %s\n",
+        statement, file, line, func);
+    write(STDERR_FILENO, buf, len);
+    _exit(-1);
+}

+ 35 - 0
gblibc/src/crt0.s

@@ -0,0 +1,35 @@
+.code32
+
+.text
+
+# TODO: call .init and .fini, initialize c standard library
+.globl _start
+.type  _start @function
+_start:
+    movl %esp, %ebx     # initial stack
+    andl $0xfffffff0, %esp
+    pushl $0
+    movl %esp, %ebp
+
+    movl (%ebx), %eax           # %eax = argc
+
+    leal 8(%ebx, %eax, 4), %ecx # %ecx = envp
+    pushl %ecx
+
+    leal 4(%ebx), %ecx          # %ecx = argv
+    pushl %ecx
+
+    pushl %eax
+
+    call __init_gblibc
+
+    movl (%ebx), %eax # %eax = argc
+    movl %eax, (%esp)
+    leal 4(%ebx), %eax
+    movl %eax, 4(%esp)
+
+    call main
+
+    movl %eax, %ebx  # code
+    movl $0xfc, %eax # SYS_exit_group
+    int $0x80        # syscall

+ 25 - 0
gblibc/src/ctype.c

@@ -0,0 +1,25 @@
+#include <ctype.h>
+
+int islower(int c)
+{
+    return c >= 'a' && c <= 'z';
+}
+
+int isupper(int c)
+{
+    return c >= 'A' && c <= 'Z';
+}
+
+int tolower(int c)
+{
+    if (isupper(c))
+        return c - 'A' + 'a';
+    return c;
+}
+
+int toupper(int c)
+{
+    if (islower(c))
+        return c - 'a' + 'A';
+    return c;
+}

+ 77 - 0
gblibc/src/dirent.c

@@ -0,0 +1,77 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+#include <syscall.h>
+
+DIR* opendir(const char* name)
+{
+    // TODO: set flags
+    int fd = open(name, O_DIRECTORY);
+
+    if (fd < 0)
+        return NULL;
+
+    return fdopendir(fd);
+}
+
+DIR* fdopendir(int fd)
+{
+    static DIR dirs[64];
+    static int next = 0;
+
+    dirs[next].fd = fd;
+    dirs[next].bpos = 0;
+
+    return dirs + next++;
+}
+
+struct kernel_dirent {
+    ino_t d_ino; // inode number
+    uint32_t d_off; // ignored
+    uint16_t d_reclen; // length of this struct user_dirent
+    char d_name[1]; // file name with a padding zero
+    // uint8_t d_type; // file type, with offset of (d_reclen - 1)
+};
+
+size_t fill_dirent(struct dirent* dent, char* buffer, size_t bpos)
+{
+    struct kernel_dirent* dp = (struct kernel_dirent*)(buffer + bpos);
+    dent->d_ino = dp->d_ino;
+    dent->d_off = dp->d_off;
+    dent->d_reclen = dp->d_reclen;
+    dent->d_type = buffer[bpos + dp->d_reclen - 1];
+    strncpy(dent->d_name, dp->d_name, sizeof(dent->d_name));
+    dent->d_name[sizeof(dent->d_name) - 1] = 0;
+
+    return bpos + dp->d_reclen;
+}
+
+struct dirent* readdir(DIR* dirp)
+{
+    if (dirp->bpos) {
+        if (dirp->bpos >= dirp->blen) {
+            dirp->bpos = 0;
+        } else {
+            goto fill;
+        }
+    }
+
+    dirp->blen = syscall3(SYS_getdents,
+        dirp->fd,
+        (uint32_t)dirp->buffer,
+        sizeof(dirp->buffer)
+    );
+
+    if (dirp->blen <= 0) {
+        if (dirp->blen < 0) {
+            errno = -dirp->blen;
+            dirp->blen = 0;
+        }
+        return NULL;
+    }
+
+fill:
+    dirp->bpos = fill_dirent(&dirp->dent, dirp->buffer, dirp->bpos);
+    return &dirp->dent;
+}

+ 37 - 0
gblibc/src/errno.c

@@ -0,0 +1,37 @@
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int* __errno_location(void)
+{
+    static int __errno = 0;
+    return &__errno;
+}
+
+static size_t _strlen(const char* str)
+{
+    size_t len = 0;
+    while (str[len] != '\0') {
+        len++;
+    }
+    return len;
+}
+
+void
+__attribute__((noreturn))
+__attribute__((weak))
+__stack_chk_fail(void)
+{
+    const char* msg = "***** stack overflow detected *****\n"
+                      "quiting...\n";
+    write(STDERR_FILENO, msg, _strlen(msg));
+    exit(-1);
+}
+
+void
+__attribute__((noreturn))
+__attribute__((weak))
+__stack_chk_fail_local(void)
+{
+    __stack_chk_fail();
+}

+ 27 - 0
gblibc/src/fcntl.c

@@ -0,0 +1,27 @@
+#include <stdarg.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <syscall.h>
+
+#include <sys/types.h>
+
+int open(const char* filename, int flags, ...)
+{
+    int ret;
+    if (flags | O_CREAT) {
+        va_list vl;
+        va_start(vl, flags);
+
+        ret = syscall3(SYS_open, (uint32_t)filename, flags, va_arg(vl, int));
+
+        va_end(vl);
+    }
+    else
+        ret = syscall2(SYS_open, (uint32_t)filename, flags);
+
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}

+ 116 - 0
gblibc/src/init.c

@@ -0,0 +1,116 @@
+#include <assert.h>
+#include <priv-vars.h>
+#include <stdlib.h>
+#include <syscall.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <list.h>
+
+FILE* stdout;
+FILE* stdin;
+FILE* stderr;
+
+#define BYTES_PER_MAX_COPY_UNIT (sizeof(uint32_t) / sizeof(uint8_t))
+static void* _memset(void* _dst, int c, size_t n)
+{
+    uint8_t* dst = (uint8_t*)_dst;
+    c &= 0xff;
+    int cc = (c + (c << 8) + (c << 16) + (c << 24));
+    for (size_t i = 0; i < n / BYTES_PER_MAX_COPY_UNIT; ++i) {
+        *(uint32_t*)dst = cc;
+        dst += BYTES_PER_MAX_COPY_UNIT;
+    }
+    for (size_t i = 0; i < (n % BYTES_PER_MAX_COPY_UNIT); ++i) {
+        *((char*)dst++) = c;
+    }
+    return dst;
+}
+
+static char* strchr(const char* s, int c)
+{
+    while (*s) {
+        if (*s == c)
+            return (char*)s;
+        ++s;
+    }
+    return NULL;
+}
+
+list_head* __io_files_location(void)
+{
+    static list_head __io_files;
+    return &__io_files;
+}
+
+size_t* __environ_size_location(void)
+{
+    static size_t __environ_size;
+    return &__environ_size;
+}
+
+void __init_gblibc(int argc, char** argv, char** envp)
+{
+    (void)argc, (void)argv;
+    // initialize program break position and heap
+    start_brk = curr_brk = (void*)syscall1(SYS_brk, (uint32_t)NULL);
+
+    sbrk(128 * 1024);
+    struct mem* first = start_brk;
+    first->sz = 0;
+    first->flag = 0;
+
+    // save environ vector
+    environ_size = 4;
+    environ = malloc(environ_size * sizeof(char*));
+    assert(environ);
+
+    while (*envp) {
+        char* eqp = strchr(*envp, '=');
+        if (!eqp || eqp == *envp)
+            goto next;
+
+        *eqp = 0;
+        char* value = eqp + 1;
+        setenv(*envp, value, 1);
+
+    next:;
+        ++envp;
+    }
+
+    // stdout, stdin, stderr objects
+    list_node* node = NULL;
+
+    // stdout
+    node = NEWNODE(FILE);
+    stdout = &NDDATA(*node, FILE);
+    _memset(stdout, 0x00, sizeof(FILE));
+
+    stdout->fd = STDOUT_FILENO;
+    stdout->flags = FILE_WRITE;
+    stdout->wbuf = malloc(BUFSIZ);
+    stdout->wbsz = BUFSIZ;
+
+    NDINSERT(&iofiles, node);
+
+    // stdin
+    node = NEWNODE(FILE);
+    stdin = &NDDATA(*node, FILE);
+    _memset(stdin, 0x00, sizeof(FILE));
+
+    stdin->fd = STDIN_FILENO;
+    stdin->flags = FILE_READ;
+    stdin->rbuf = malloc(BUFSIZ);
+    stdin->rbsz = BUFSIZ;
+
+    NDINSERT(&iofiles, node);
+
+    // stderr
+    node = NEWNODE(FILE);
+    stderr = &NDDATA(*node, FILE);
+    _memset(stderr, 0x00, sizeof(FILE));
+
+    stderr->fd = STDERR_FILENO;
+    stderr->flags = FILE_WRITE;
+
+    NDINSERT(&iofiles, node);
+}

+ 20 - 0
gblibc/src/internal.c

@@ -0,0 +1,20 @@
+#include <list.h>
+#include <stdlib.h>
+
+void __node_insert(list_node* node, list_node* newnode)
+{
+    NDNEXT(*newnode) = NDNEXT(*node);
+    if (NDNEXT(*node))
+        NDPREV(*NDNEXT(*node)) = newnode;
+    NDNEXT(*node) = newnode;
+    NDPREV(*newnode) = node;
+}
+
+void __node_erase(list_node* node)
+{
+    if (NDPREV(*node))
+        NDNEXT(*NDPREV(*node)) = NDNEXT(*node);
+    if (NDNEXT(*node))
+        NDPREV(*NDNEXT(*node)) = NDPREV(*node);
+    free(node);
+}

+ 5 - 0
gblibc/src/platform-independent.s

@@ -0,0 +1,5 @@
+.section .rodata
+
+.globl __stack_chk_guard
+__stack_chk_guard:
+    .long 0x19198101

+ 23 - 0
gblibc/src/signal.c

@@ -0,0 +1,23 @@
+#include <syscall.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+
+int kill(pid_t pid, int sig)
+{
+    int ret = syscall2(SYS_kill, pid, sig);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+int raise(int sig)
+{
+    pid_t pid = getpid();
+    if (pid < 0)
+        return -1;
+
+    return kill(pid, sig);
+}

+ 29 - 0
gblibc/src/stat.c

@@ -0,0 +1,29 @@
+#include <stdint.h>
+#include <errno.h>
+#include <syscall.h>
+#include <sys/stat.h>
+
+int stat(const char* pathname, struct stat* statbuf)
+{
+    int ret = syscall2(SYS_stat, (uint32_t)pathname, (uint32_t)statbuf);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+int fstat(int fd, struct stat* statbuf)
+{
+    int ret = syscall2(SYS_fstat, fd, (uint32_t)statbuf);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+mode_t umask(mode_t mask)
+{
+    return syscall1(SYS_umask, mask);
+}

+ 845 - 0
gblibc/src/stdio.c

@@ -0,0 +1,845 @@
+#include <assert.h>
+#include <devutil.h>
+#include <fcntl.h>
+#include <list.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <priv-vars.h>
+
+static inline int __feof_or_error(FILE* stream)
+{
+    return !!(stream->flags & (FILE_ERROR | FILE_EOF));
+}
+
+// where n is in the range of [0, 9]
+static inline char d_to_c(int32_t n)
+{
+    return '0' + n;
+}
+
+// where n is between 0 and 15
+// base is either 'a' of 'A',
+// depending on you want capitalized
+// or not
+static inline char hex_to_c(int32_t n, char base)
+{
+    if (n < 10) {
+        // n belongs to [0, 9]
+        return d_to_c(n);
+    } else {
+        // n belongs to [10, 15]
+        return base + (n - 10);
+    }
+}
+
+static inline char x_to_c(int32_t n)
+{
+    return hex_to_c(n, 'a');
+}
+
+static inline char X_to_c(int32_t n)
+{
+    return hex_to_c(n, 'A');
+}
+
+// this will check if there is still free space
+// in the buffer. if so, push the char into it,
+// change the value of buf_size and move pointer
+// forward
+//
+// x: char* buf
+// y: size_t buf_size
+// z: char c
+#define do_write_if_free(x, y, z) \
+    if ((y) > 1) {                \
+        *((x)++) = (z);           \
+        --(y);                    \
+    }
+
+static inline ssize_t
+snprint_decimal32(
+    char* buf,
+    size_t buf_size,
+    int32_t num)
+{
+    ssize_t n_write = 0;
+
+    if (num < 0) {
+        do_write_if_free(buf, buf_size, '-');
+        ++n_write;
+        num *= (-1);
+    }
+
+    char* orig_buf = buf;
+
+    do {
+        do_write_if_free(buf, buf_size, d_to_c(num % 10));
+        num /= 10;
+        ++n_write;
+    } while (num != 0);
+
+    // prepend trailing '\0'
+    if (buf_size > 0)
+        *buf = 0x00;
+
+    // move buf pointer to the last digit of number
+    --buf;
+
+    // reverse output
+    while (orig_buf < buf) {
+        char c = *buf;
+        *buf = *orig_buf;
+        *orig_buf = c;
+        --buf;
+        ++orig_buf;
+    }
+
+    return n_write;
+}
+
+static inline ssize_t
+snprint_decimal64(
+    char* buf,
+    size_t buf_size,
+    int64_t num)
+{
+    ssize_t n_write = 0;
+
+    if (num < 0) {
+        do_write_if_free(buf, buf_size, '-');
+        ++n_write;
+        num *= (-1);
+    }
+
+    char* orig_buf = buf;
+
+    do {
+        do_write_if_free(buf, buf_size, d_to_c(num % 10));
+        num /= 10;
+        ++n_write;
+    } while (num != 0);
+
+    // prepend trailing '\0'
+    if (buf_size > 0)
+        *buf = 0x00;
+
+    // move buf pointer to the last digit of number
+    --buf;
+
+    // reverse output
+    while (orig_buf < buf) {
+        char c = *buf;
+        *buf = *orig_buf;
+        *orig_buf = c;
+        --buf;
+        ++orig_buf;
+    }
+
+    return n_write;
+}
+
+static inline ssize_t
+snprint_hex32(
+    char* buf,
+    size_t buf_size,
+    uint32_t num,
+    int32_t capitalized)
+{
+    ssize_t n_write = 0;
+
+    do_write_if_free(buf, buf_size, '0');
+    if (capitalized) {
+        do_write_if_free(buf, buf_size, 'X');
+    } else {
+        do_write_if_free(buf, buf_size, 'x');
+    }
+    n_write += 2;
+
+    char* orig_buf = buf;
+
+    do {
+        if (capitalized) {
+            do_write_if_free(buf, buf_size, X_to_c(num % 16));
+        } else {
+            do_write_if_free(buf, buf_size, x_to_c(num % 16));
+        }
+        num /= 16;
+        ++n_write;
+    } while (num != 0);
+
+    // prepend trailing '\0'
+    if (buf_size > 0)
+        *buf = 0x00;
+
+    // move buf pointer to the last digit of number
+    --buf;
+
+    // reverse output
+    while (orig_buf < buf) {
+        char c = *buf;
+        *buf = *orig_buf;
+        *orig_buf = c;
+        --buf;
+        ++orig_buf;
+    }
+
+    return n_write;
+}
+
+static inline ssize_t
+snprint_hex64(
+    char* buf,
+    size_t buf_size,
+    uint64_t num,
+    int32_t capitalized)
+{
+    ssize_t n_write = 0;
+
+    do_write_if_free(buf, buf_size, '0');
+    if (capitalized) {
+        do_write_if_free(buf, buf_size, 'X');
+    } else {
+        do_write_if_free(buf, buf_size, 'x');
+    }
+    n_write += 2;
+
+    char* orig_buf = buf;
+
+    do {
+        if (capitalized) {
+            do_write_if_free(buf, buf_size, X_to_c(num % 16));
+        } else {
+            do_write_if_free(buf, buf_size, x_to_c(num % 16));
+        }
+        num /= 16;
+        ++n_write;
+    } while (num != 0);
+
+    // prepend trailing '\0'
+    if (buf_size > 0)
+        *buf = 0x00;
+
+    // move buf pointer to the last digit of number
+    --buf;
+
+    // reverse output
+    while (orig_buf < buf) {
+        char c = *buf;
+        *buf = *orig_buf;
+        *orig_buf = c;
+        --buf;
+        ++orig_buf;
+    }
+
+    return n_write;
+}
+
+static inline ssize_t
+snprint_char(
+    char* buf,
+    size_t buf_size,
+    char c)
+{
+    if (buf_size > 1)
+        *buf = c;
+    return sizeof(c);
+}
+
+int snprintf(char* buf, size_t bufsize, const char* fmt, ...)
+{
+    va_list lst;
+    va_start(lst, fmt);
+
+    int ret = vsnprintf(buf, bufsize, fmt, lst);
+
+    va_end(lst);
+
+    return ret;
+}
+
+int vsnprintf(char* buf, size_t buf_size, const char* fmt, va_list arg)
+{
+    ssize_t n_write = 0;
+
+    for (char c; (c = *fmt) != 0x00; ++fmt) {
+        if (c == '%') {
+            size_t n_tmp_write = 0;
+
+            switch (*(++fmt)) {
+
+            // int
+            case 'd':
+                n_tmp_write = snprint_decimal32(buf, buf_size, va_arg(arg, int));
+                break;
+
+            case 'x':
+                n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, unsigned int), 0);
+                break;
+
+            case 'X':
+                n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, unsigned int), 1);
+                break;
+
+            // long decimal
+            case 'l':
+                switch (*(++fmt)) {
+                // long long aka int64
+                case 'l':
+                    switch (*(++fmt)) {
+                    case 'd':
+                        n_tmp_write = snprint_decimal64(buf, buf_size, va_arg(arg, long long));
+                        break;
+                    case 'x':
+                        n_tmp_write = snprint_hex64(buf, buf_size, va_arg(arg, unsigned long long), 0);
+                        break;
+                    case 'X':
+                        n_tmp_write = snprint_hex64(buf, buf_size, va_arg(arg, unsigned long long), 1);
+                        break;
+                    }
+                    break;
+                // long int aka int32
+                case 'd':
+                    n_tmp_write = snprint_decimal32(buf, buf_size, va_arg(arg, long));
+                    break;
+                case 'x':
+                    n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, unsigned long), 0);
+                    break;
+
+                case 'X':
+                    n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, unsigned long), 1);
+                    break;
+                }
+                break;
+
+            // c string
+            case 's':
+                n_tmp_write = snprintf(buf, buf_size, va_arg(arg, const char*));
+                break;
+
+            // int8 char
+            case 'c':
+                n_tmp_write = snprint_char(buf, buf_size, va_arg(arg, int));
+                break;
+
+            // pointer
+            case 'p':
+#ifdef __32bit_system
+                n_tmp_write = snprint_hex32(buf, buf_size, va_arg(arg, size_t), 0);
+#else
+                n_tmp_write = snprint_hex64(buf, buf_size, va_arg(arg, size_t), 0);
+#endif
+                break;
+
+            default:
+                n_tmp_write = snprint_char(buf, buf_size, *(fmt - 1));
+                break;
+            }
+
+            n_write += n_tmp_write;
+            if (buf_size > 1) {
+                if (buf_size > n_tmp_write) {
+                    buf += n_tmp_write;
+                    buf_size -= n_tmp_write;
+                } else {
+                    // no enough space
+                    // shrink buf_size to one
+                    buf += (buf_size - 1);
+                    buf_size = 1;
+                }
+            }
+
+        } else {
+            ++n_write;
+            do_write_if_free(buf, buf_size, c);
+        }
+    }
+
+    if (buf_size > 0)
+        *buf = 0x00;
+
+    return n_write;
+}
+
+int sprintf(char* buf, const char* fmt, ...)
+{
+    va_list lst;
+    va_start(lst, fmt);
+
+    int ret = vsnprintf(buf, __SIZE_MAX__, fmt, lst);
+
+    va_end(lst);
+
+    return ret;
+}
+
+int puts(const char* str)
+{
+    return fputs(str, stdout);
+}
+
+char* gets(char* buf)
+{
+    int c, num = 0;
+    while ((c = getchar()) != EOF && c != '\n')
+        buf[num++] = c;
+    buf[num] = 0;
+
+    if (c == EOF)
+        return NULL;
+    return buf;
+}
+
+int vfprintf_u32(uint32_t num, FILE* stream)
+{
+    if (num <= 9) {
+        fputc(d_to_c(num), stream);
+        return 1;
+    }
+
+    int ret = vfprintf_u32(num / 10, stream);
+    fputc(d_to_c(num % 10), stream);
+    return ret + 1;
+}
+
+int vfprintf_d32(int32_t num, FILE* stream)
+{
+    if (num < 0) {
+        fputc('-', stream);
+        return vfprintf_u32(-num, stream) + 1;
+    }
+    return vfprintf_u32(num, stream);
+}
+
+int vfprintf_u64(uint64_t num, FILE* stream)
+{
+    if (num <= 9) {
+        fputc(d_to_c(num), stream);
+        return 1;
+    }
+
+    int ret = vfprintf_u64(num / 10, stream);
+    fputc(d_to_c(num % 10), stream);
+    return ret + 1;
+}
+
+int vfprintf_d64(int64_t num, FILE* stream)
+{
+    if (num < 0) {
+        fputc('-', stream);
+        return vfprintf_u64(-num, stream) + 1;
+    }
+    return vfprintf_u64(num, stream);
+}
+
+int vfprintf_x32(uint32_t num, int off, FILE* stream)
+{
+    // print leading 0x
+    if (off & 1) {
+        --off;
+        fputc('0', stream);
+        fputc('X' + off, stream);
+        return vfprintf_x32(num, off, stream) + 2;
+    }
+
+    if (num <= 15) {
+        fputc(X_to_c(num) + off, stream);
+        return 1;
+    }
+
+    int ret = vfprintf_x32(num >> 4, off, stream);
+    fputc(X_to_c(num & 0xf) + off, stream);
+    return ret + 1;
+}
+
+int vfprintf_x64(uint64_t num, int off, FILE* stream)
+{
+    // print leading 0x
+    if (off & 1) {
+        --off;
+        fputc('0', stream);
+        fputc('X' + off, stream);
+        return vfprintf_x64(num, off, stream) + 2;
+    }
+
+    if (num <= 15) {
+        fputc(X_to_c(num) + off, stream);
+        return 1;
+    }
+
+    int ret = vfprintf_x64(num >> 4, off, stream);
+    fputc(X_to_c(num & 0xf) + off, stream);
+    return ret + 1;
+}
+
+int vfprintf(FILE* stream, const char* fmt, va_list args)
+{
+    int n = 0;
+
+    for (char c = 0; (c = *fmt) != 0x00; ++fmt) {
+        if (c == '%') {
+            switch (*(++fmt)) {
+
+            // int
+            case 'd':
+                n += vfprintf_d32(va_arg(args, int), stream);
+                break;
+
+            case 'x':
+                n += vfprintf_x32(va_arg(args, unsigned int), 'a' - 'A' + 1, stream);
+                break;
+
+            case 'X':
+                n += vfprintf_x32(va_arg(args, unsigned int), 1, stream);
+                break;
+
+            // long decimal
+            case 'l':
+                switch (*(++fmt)) {
+                // long long aka int64
+                case 'l':
+                    switch (*(++fmt)) {
+                    case 'd':
+                        n += vfprintf_d64(va_arg(args, long long), stream);
+                        break;
+                    case 'x':
+                        n += vfprintf_x64(va_arg(args, unsigned long long), 'a' - 'A' + 1, stream);
+                        break;
+                    case 'X':
+                        n += vfprintf_x64(va_arg(args, unsigned long long), 'a' - 'A' + 1, stream);
+                        break;
+                    }
+                    break;
+                // long int aka int32
+                case 'd':
+                    n += vfprintf_d32(va_arg(args, int), stream);
+                    break;
+                case 'x':
+                    n += vfprintf_x32(va_arg(args, unsigned int), 'a' - 'A' + 1, stream);
+                    break;
+
+                case 'X':
+                    n += vfprintf_x32(va_arg(args, unsigned int), 1, stream);
+                    break;
+                }
+                break;
+
+            // c string
+            case 's':
+                n += fprintf(stream, va_arg(args, const char*));
+                break;
+
+            // int8 char
+            case 'c':
+                ++n;
+                fputc(va_arg(args, int), stream);
+                break;
+
+            // pointer
+            case 'p':
+#ifdef __32bit_system
+                n += vfprintf_x32(va_arg(args, size_t), 'a' - 'A' + 1, stream);
+#else
+                n += vfprintf_x64(va_arg(args, size_t), 'a' - 'A' + 1, stream);
+#endif
+                break;
+
+            default:
+                ++n;
+                fputc(*(fmt - 1), stream);
+                break;
+            }
+        } else {
+            ++n;
+            fputc(c, stream);
+        }
+    }
+
+    return n;
+}
+
+int fprintf(FILE* stream, const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+
+    int ret = vfprintf(stream, fmt, args);
+
+    va_end(args);
+    return ret;
+}
+
+int vprintf(const char* fmt, va_list args)
+{
+    return vfprintf(stdout, fmt, args);
+}
+
+int printf(const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+
+    int ret = vprintf(fmt, args);
+
+    va_end(args);
+    return ret;
+}
+
+int putchar(int c)
+{
+    fputc(c, stdout);
+    return c;
+}
+
+FILE* fopen(const char* path, const char* mode)
+{
+    uint32_t flags = 0, file_flags = 0;
+
+    if (strcmp(mode, "r") == 0)
+        flags = O_RDONLY, file_flags = FILE_READ;
+
+    if (strcmp(mode, "r+") == 0)
+        flags = O_RDWR, file_flags = FILE_READ | FILE_WRITE;
+
+    if (strcmp(mode, "w") == 0)
+        flags = O_WRONLY | O_CREAT | O_TRUNC, file_flags = FILE_WRITE;
+
+    if (strcmp(mode, "w+") == 0)
+        flags = O_RDWR | O_CREAT | O_TRUNC, file_flags = FILE_READ | FILE_WRITE;
+    
+    assert(flags);
+
+    int fd = open(path, flags, 0644);
+    if (fd < 0)
+        goto open_fail;
+    
+    FILE* file = malloc(sizeof(FILE));
+    if (!file)
+        goto file_malloc_fail;
+    
+    file->fd = fd;
+    file->flags = file_flags;
+
+    if (file_flags & FILE_READ) {
+        file->rbuf = malloc(BUFSIZ);
+        if (!file->rbuf)
+            goto rbuf_malloc_fail;
+        file->rbsz = BUFSIZ;
+    }
+
+    if (file_flags & FILE_WRITE) {
+        file->wbuf = malloc(BUFSIZ);
+        if (!file->wbuf)
+            goto wbuf_malloc_fail;
+        file->wbsz = BUFSIZ;
+    }
+
+    return file;
+
+wbuf_malloc_fail:
+    free(file->rbuf);
+
+rbuf_malloc_fail:
+    free(file);
+
+file_malloc_fail:
+    close(fd);
+
+open_fail:
+    return NULL;
+}
+
+int fflush(FILE* stream)
+{
+    if (__feof_or_error(stream))
+        return EOF;
+
+    if (stream->wbuf && stream->wpos) {
+        int ret = write(stream->fd, stream->wbuf, stream->wpos);
+        if (ret < 0) {
+            stream->flags |= FILE_ERROR;
+            return EOF;
+        }
+        if (ret == 0) {
+            stream->flags |= FILE_EOF;
+            return EOF;
+        }
+        stream->wpos = 0;
+    }
+
+    // TODO: call flush()
+
+    return 0;
+}
+
+int fclose(FILE* stream)
+{
+    if (fflush(stream) == EOF)
+        return EOF;
+    
+    free(stream->rbuf);
+    free(stream->wbuf);
+    stream->rbsz = 0;
+    stream->wbsz = 0;
+    
+    if (close(stream->fd) < 0)
+        return EOF;
+    
+    NDERASE(NDPTR(stream));
+    
+    return 0;
+}
+
+int fputc_unlocked(int c, FILE* stream)
+{
+    return putc_unlocked(c, stream);
+}
+
+int fputs_unlocked(const char* s, FILE* stream)
+{
+    // 1 is for the trailing '\n'
+    int len = 1;
+    for (const char* p = s; *p; ++p, ++len)
+        fputc_unlocked(*p, stream);
+    fputc_unlocked('\n', stream);
+    return len;
+}
+
+int fputc(int c, FILE* stream)
+{
+    // TODO: lock the stream
+    return putc_unlocked(c, stream);
+}
+
+int fputs(const char* s, FILE* stream)
+{
+    // TODO: lock the stream
+    return fputs_unlocked(s, stream);
+}
+
+static inline int __fillbuf(FILE* stream)
+{
+    if ((stream->rcnt = read(stream->fd, stream->rbuf, stream->rbsz)) >= 2147483648U) {
+        stream->rcnt = 0;
+        stream->flags |= FILE_ERROR;
+        return EOF;
+    }
+    if (stream->rcnt == 0) {
+        stream->flags |= FILE_EOF;
+        return EOF;
+    }
+    stream->rpos = 0;
+    return 0;
+}
+
+int getc_unlocked(FILE* stream)
+{
+    if (__feof_or_error(stream))
+        return EOF;
+
+    if (stream->rbuf) {
+        if (stream->rpos == stream->rcnt) {
+            if (__fillbuf(stream) < 0)
+                return EOF;
+        }
+        return stream->rbuf[stream->rpos++];
+    } else {
+        int c;
+        int ret = read(stream->fd, &c, 1);
+        if (ret < 0) {
+            stream->flags |= FILE_ERROR;
+            return EOF;
+        }
+        if (ret == 0) {
+            stream->flags |= FILE_EOF;
+            return EOF;
+        }
+        return c;
+    }
+}
+
+int putc_unlocked(int c, FILE* stream)
+{
+    if (__feof_or_error(stream))
+        return EOF;
+
+    if (stream->wbuf) {
+        stream->wbuf[stream->wpos++] = c;
+        if (stream->wpos == stream->wbsz || c == '\n')
+            if (fflush(stream) == EOF)
+                return EOF;
+    } else {
+        if (write(stream->fd, &c, 1) < 0) {
+            stream->flags |= FILE_ERROR;
+            return EOF;
+        }
+    }
+
+    return c;
+}
+
+int getchar(void)
+{
+    return fgetc(stdin);
+}
+
+int fgetc(FILE* stream)
+{
+    return getc_unlocked(stream);
+}
+
+int ferror(FILE* stream)
+{
+    // TODO: lock the stream
+    return ferror_unlocked(stream);
+}
+
+int ferror_unlocked(FILE* stream)
+{
+    return stream->flags & FILE_ERROR;
+}
+
+int feof(FILE* stream)
+{
+    return stream->flags & FILE_EOF;
+}
+
+void clearerr(FILE* stream)
+{
+    stream->flags &= ~FILE_ERROR;
+}
+
+int vasprintf(char** strp, const char* fmt, va_list args)
+{
+    // TODO: this is WAY TOO SLOWWWWWWWWW
+    int sz = 8, n;
+    char* buf = NULL;
+
+    do {
+        buf = realloc(buf, sz *= 2);
+        if (!buf)
+            return -1;
+        
+        n = vsnprintf(buf, sz, fmt, args);
+        if (sz > n)
+            break;
+    } while (1);
+    
+    *strp = buf;
+    return n;
+}
+
+int asprintf(char** strp, const char* fmt, ...)
+{
+    va_list lst;
+    va_start(lst, fmt);
+
+    int ret = vasprintf(strp, fmt, lst);
+
+    va_end(lst);
+
+    return ret;
+}

+ 286 - 0
gblibc/src/stdlib.c

@@ -0,0 +1,286 @@
+#include <alloca.h>
+#include <priv-vars.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syscall.h>
+#include <unistd.h>
+#include <string.h>
+
+#define BYTES_PER_MAX_COPY_UNIT (sizeof(uint32_t) / sizeof(uint8_t))
+
+static void* _memcpy(void* _dst, const void* _src, size_t n)
+{
+    void* orig_dst = _dst;
+    uint8_t* dst = (uint8_t*)_dst;
+    const uint8_t* src = (const uint8_t*)_src;
+    for (size_t i = 0; i < n / BYTES_PER_MAX_COPY_UNIT; ++i) {
+        *(uint32_t*)dst = *(uint32_t*)src;
+        dst += BYTES_PER_MAX_COPY_UNIT;
+        src += BYTES_PER_MAX_COPY_UNIT;
+    }
+    for (size_t i = 0; i < (n % BYTES_PER_MAX_COPY_UNIT); ++i) {
+        *((char*)dst++) = *((char*)src++);
+    }
+    return orig_dst;
+}
+
+int atoi(const char* str)
+{
+    int ret = 0;
+    while (*str) {
+        ret *= 10;
+        ret += *str - '0';
+    }
+    return ret;
+}
+
+void __attribute__((noreturn)) exit(int status)
+{
+    syscall1(SYS_exit, status);
+    for (;;)
+        ;
+}
+
+#define MINIMUM_ALLOCATION_SIZE (8)
+#define MEM_ALLOCATED (1)
+
+static inline int _is_end(struct mem* p)
+{
+    return p->sz == 0;
+}
+
+static inline int _is_allocated(struct mem* p)
+{
+    return !!(p->flag & MEM_ALLOCATED);
+}
+
+static inline size_t _max(size_t a, size_t b)
+{
+    return a > b ? a : b;
+}
+
+static inline size_t _size(struct mem* from)
+{
+    if (!_is_end(from))
+        return from->sz;
+    
+    size_t sz = curr_brk - (void*)from;
+    if (sz < sizeof(struct mem))
+        return 0;
+
+    return sz - sizeof(struct mem);
+}
+
+static inline struct mem* _next(struct mem* p, size_t sz)
+{
+    return (void*)p + sizeof(struct mem) + sz;
+}
+
+static inline void _union(struct mem* p)
+{
+    if (_is_end(p))
+        return;
+
+    for (struct mem* next = _next(p, p->sz);
+        !(next->flag & MEM_ALLOCATED);
+        next = _next(p, p->sz)) {
+
+        if (_is_end(next)) {
+            p->sz = 0;
+            break;
+        }
+
+        p->sz += sizeof(struct mem);
+        p->sz += next->sz;
+    }
+}
+
+static inline void _cut_block(struct mem* p, size_t mem_size, size_t block_size)
+{
+    if (block_size >= mem_size + sizeof(struct mem) + MINIMUM_ALLOCATION_SIZE) {
+        p->sz = mem_size;
+
+        struct mem* next = _next(p, mem_size);
+        next->flag = 0;
+        next->sz = block_size - mem_size - sizeof(struct mem);
+    }
+}
+
+void* malloc(size_t size)
+{
+    if (size < MINIMUM_ALLOCATION_SIZE)
+        size = MINIMUM_ALLOCATION_SIZE;
+
+    struct mem* p = start_brk;
+    size_t sz = 0;
+    for (;; p = _next(p, p->sz)) {
+        if (_is_allocated(p))
+            continue;
+
+        _union(p);
+
+        sz = _size(p);
+        if (_is_end(p)) {
+            if (sz < size + sizeof(struct mem))
+                sbrk(_max(128 * 1024, size + sizeof(struct mem)));
+
+            sz = p->sz = size;
+            struct mem* next = _next(p, size);
+            next->flag = 0;
+            next->sz = 0;
+
+            break;
+        }
+
+        if (sz >= size)
+            break;
+    }
+
+    p->flag |= MEM_ALLOCATED;
+    _cut_block(p, size, sz);
+
+    return _next(p, 0);
+}
+
+void* realloc(void* ptr, size_t newsize)
+{
+    if (!ptr)
+        return malloc(newsize);
+
+    struct mem* p = ptr - sizeof(struct mem);
+    size_t oldsize = p->sz;
+
+    _union(p);
+    if (_is_end(p)) {
+        if (_size(p) < newsize + sizeof(struct mem))
+            sbrk(_max(128 * 1024, newsize + sizeof(struct mem)));
+
+        p->sz = newsize;
+        struct mem* next = _next(p, newsize);
+        next->flag = 0;
+        next->sz = 0;
+
+        return ptr;
+    }
+
+    if (p->sz >= newsize) {
+        _cut_block(p, newsize, p->sz);
+        return ptr;
+    }
+
+    void* newptr = malloc(newsize);
+    if (!newptr)
+        return NULL;
+    
+    _memcpy(newptr, ptr, oldsize);
+    free(ptr);
+    return newptr;
+}
+
+void free(void* ptr)
+{
+    struct mem* p = ptr - sizeof(struct mem);
+    p->flag &= ~MEM_ALLOCATED;
+    _union(p);
+}
+
+static inline void _swap(void* a, void* b, size_t sz)
+{
+    void* tmp = alloca(sz);
+    _memcpy(tmp, a, sz);
+    _memcpy(a, b, sz);
+    _memcpy(b, tmp, sz);
+}
+
+void qsort(void* arr, size_t len, size_t sz, comparator_t cmp) {
+    if (len <= 1)
+        return;
+
+    char* pivot = alloca(sz);
+    _memcpy(pivot, arr + sz * (rand() % len), sz);
+
+    int i = 0, j = 0, k = len;
+    while (i < k) {
+        int res = cmp(arr + sz * i, pivot);
+        if (res < 0)
+            _swap(arr + sz * i++, arr + sz * j++, sz);
+        else if (res > 0)
+            _swap(arr + sz * i, arr + sz * --k, sz);
+        else
+            i++;
+    }
+
+    qsort(arr, j, sz, cmp);
+    qsort(arr + sz * k, len - k, sz, cmp);
+}
+
+static unsigned int __next_rand;
+int rand(void)
+{
+    return rand_r(&__next_rand);
+}
+
+int rand_r(unsigned int* seedp)
+{
+    *seedp = *seedp * 1103515245 + 12345;
+    return (unsigned int) (*seedp / 65536) % 32768;
+}
+
+void srand(unsigned int seed)
+{
+    __next_rand = seed;
+    rand();
+}
+
+void* bsearch(const void* key, const void* base, size_t num, size_t size, comparator_t cmp)
+{
+    if (num == 0)
+        return NULL;
+
+    size_t mid = num / 2;
+    int result = cmp(key, base + size * mid);
+
+    if (result == 0)
+        return (void*)base + size * mid;
+    
+    if (result > 0) {
+        ++mid;
+        return bsearch(key, base + size * mid, num - mid, size, cmp);
+    }
+    
+    return bsearch(key, base, mid, size, cmp);
+}
+
+int setenv(const char* name, const char* value, int overwrite)
+{
+    size_t i = 0;
+    for (; environ[i]; ++i) {
+        char* eqpos = strchr(environ[i], '=');
+        if (strncmp(name, environ[i], eqpos - environ[i]) == 0) {
+            if (overwrite)
+                goto fill_p;
+            return 0;
+        }
+    }
+
+    if (i + 2 == environ_size) {
+        environ_size *= 2;
+        char** newarr = malloc(environ_size * sizeof(char*));
+        if (!newarr)
+            return -1;
+        
+        _memcpy(newarr, environ, sizeof(char*) * environ_size / 2);
+        free(environ);
+        environ = newarr;
+    }
+    environ[i + 1] = NULL;
+
+fill_p:;
+    char* newenv = NULL;
+    if (asprintf(&newenv, "%s=%s", name, value) < 0)
+        return -1;
+
+    environ[i] = newenv;
+    return 0;
+}

+ 269 - 0
gblibc/src/string.c

@@ -0,0 +1,269 @@
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#define BYTES_PER_MAX_COPY_UNIT (sizeof(uint32_t) / sizeof(uint8_t))
+
+static void* _memcpy(void* _dst, const void* _src, size_t n)
+{
+    void* orig_dst = _dst;
+    uint8_t* dst = (uint8_t*)_dst;
+    const uint8_t* src = (const uint8_t*)_src;
+    for (size_t i = 0; i < n / BYTES_PER_MAX_COPY_UNIT; ++i) {
+        *(uint32_t*)dst = *(uint32_t*)src;
+        dst += BYTES_PER_MAX_COPY_UNIT;
+        src += BYTES_PER_MAX_COPY_UNIT;
+    }
+    for (size_t i = 0; i < (n % BYTES_PER_MAX_COPY_UNIT); ++i) {
+        *((char*)dst++) = *((char*)src++);
+    }
+    return orig_dst;
+}
+
+static void* _memset(void* _dst, int c, size_t n)
+{
+    uint8_t* dst = (uint8_t*)_dst;
+    c &= 0xff;
+    int cc = (c + (c << 8) + (c << 16) + (c << 24));
+    for (size_t i = 0; i < n / BYTES_PER_MAX_COPY_UNIT; ++i) {
+        *(uint32_t*)dst = cc;
+        dst += BYTES_PER_MAX_COPY_UNIT;
+    }
+    for (size_t i = 0; i < (n % BYTES_PER_MAX_COPY_UNIT); ++i) {
+        *((char*)dst++) = c;
+    }
+    return dst;
+}
+
+static size_t _strlen(const char* str)
+{
+    size_t n = 0;
+    while (*(str++) != '\0')
+        ++n;
+    return n;
+}
+
+char* strchr(const char* str, int c)
+{
+    const char* p = str;
+    while (*p) {
+        if (*p == c)
+            return (char*)p;
+        ++p;
+    }
+    return NULL;
+}
+
+char* strrchr(const char* str, int c)
+{
+    const char* p = str + _strlen(str) - 1;
+    while (p >= str) {
+        if (*p == c)
+            return (char*)p;
+        --p;
+    }
+    return NULL;
+}
+
+char* strchrnul(const char* str, int c)
+{
+    char* ret = strchr(str, c);
+    if (ret)
+        return ret;
+    return (char*)str + _strlen(str);
+}
+
+char* strcpy(char* dst, const char* src)
+{
+    return _memcpy(dst, src, _strlen(src) + 1);
+}
+
+char* strncpy(char* dst, const char* src, size_t n)
+{
+    size_t len = _strlen(src);
+
+    if (len < n) {
+        _memset(dst + len, 0x00, n - len);
+        _memcpy(dst, src, len);
+    } else {
+        _memcpy(dst, src, n);
+    }
+
+    return dst;
+}
+
+char* stpcpy(char* restrict dst, const char* restrict src)
+{
+    return _memcpy(dst, src, _strlen(src) + 1) + _strlen(src);
+}
+
+char* stpncpy(char* restrict dst, const char* restrict src, size_t n)
+{
+    size_t len = _strlen(src);
+
+    if (len < n) {
+        _memset(dst + len, 0x00, n - len);
+        _memcpy(dst, src, len);
+    } else {
+        _memcpy(dst, src, n);
+    }
+
+    return dst + len;
+}
+
+int strncmp(const char* s1, const char* s2, size_t n)
+{
+    if (n == 0)
+        return 0;
+
+    int c;
+    while (n-- && (c = *s1 - *s2) == 0 && *s1) {
+        ++s1;
+        ++s2;
+    }
+    return c;
+}
+
+int strcmp(const char* s1, const char* s2)
+{
+    return strncmp(s1, s2, __SIZE_MAX__);
+}
+
+int strncasecmp(const char* s1, const char* s2, size_t n)
+{
+    if (n == 0)
+        return 0;
+
+    int c;
+    while (n-- && (c = tolower(*s1) - tolower(*s2)) == 0 && *s1) {
+        ++s1;
+        ++s2;
+    }
+    return c;
+}
+
+int strcasecmp(const char* s1, const char* s2)
+{
+    return strncasecmp(s1, s2, __SIZE_MAX__);
+}
+
+size_t strcspn(const char* str1, const char* str2)
+{
+    size_t ret = 0;
+    while (*str1) {
+        ++ret;
+        for (const char* p = str2; *p; ++p) {
+            if (*str1 == *p)
+                return ret;
+        }
+        ++str1;
+    }
+    return ret;
+}
+
+char* strstr(const char* str1, const char* str2)
+{
+    const char* p = str1;
+
+    while (*p) {
+        if (*p != *str2) {
+            ++p;
+            continue;
+        }
+
+        const char* p1 = p;
+        const char* q = str2;
+        while (*q) {
+            if (*p1 != *q)
+                break;
+            ++p1;
+            ++q;
+        }
+        if (!*q)
+            break;
+        p = p1;
+    }
+
+    if (*p)
+        return (char*)p;
+    return NULL;
+}
+
+char* strpbrk(const char* str1, const char* str2)
+{
+    size_t n = strcspn(str1, str2);
+    if (str1[n])
+        return (char*)str1 + n;
+    return NULL;
+}
+
+char* strerror(int errnum)
+{
+    switch (errnum) {
+    case EPERM:
+        return "Operation not permitted";
+    case ENOENT:
+        return "No such file or directory";
+    case ESRCH:
+        return "No such process";
+    case EINTR:
+        return "Interrupted system call";
+    case EBADF:
+        return "Bad file descriptor";
+    case ECHILD:
+        return "No child process";
+    case ENOMEM:
+        return "Out of memory";
+    case EEXIST:
+        return "File exists";
+    case ENOTDIR:
+        return "Not a directory";
+    case EISDIR:
+        return "Is a directory";
+    case EINVAL:
+        return "Invalid argument";
+    case ENOTTY:
+        return "Not a tty";
+    case EPIPE:
+        return "Broken pipe";
+    default:
+        return "No error information";
+    }
+}
+
+char* strndup(const char* str, size_t n)
+{
+    size_t len = _strlen(str);
+    if (len > n)
+        len = n;
+    char* ret = malloc(len + 1);
+    if (!ret)
+        return NULL;
+    
+    _memcpy(ret, str, len);
+    ret[len] = 0;
+    return ret;
+}
+
+char* strdup(const char* str)
+{
+    return strndup(str, __SIZE_MAX__);
+}
+
+char* strsignal(int sig)
+{
+    switch (sig) {
+    default:
+        return "Unknown signal";
+    case SIGINT:
+        return "Interrupt";
+    case SIGQUIT:
+        return "Quit";
+    case SIGSTOP:
+        return "Stopped (signal)";
+    case SIGPIPE:
+        return "Broken pipe";
+    }
+}

+ 20 - 0
gblibc/src/time.c

@@ -0,0 +1,20 @@
+#include <errno.h>
+#include <sys/time.h>
+#include <syscall.h>
+
+int gettimeofday(struct timeval* tv, struct timezone* tz)
+{
+    if (tz) {
+        errno = -EINVAL;
+        return -1;
+    }
+
+    int ret = syscall2(SYS_gettimeofday, (uint32_t)tv, 0);
+
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+
+    return ret;
+}

+ 249 - 0
gblibc/src/unistd.c

@@ -0,0 +1,249 @@
+#include <errno.h>
+#include <priv-vars.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <syscall.h>
+
+ssize_t read(int fd, void* buf, size_t count)
+{
+    ssize_t ret = syscall3(SYS_read, fd, (uint32_t)buf, count);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+ssize_t write(int fd, const void* buf, size_t count)
+{
+    ssize_t ret = syscall3(SYS_write, fd, (uint32_t)buf, count);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+int dup(int oldfd)
+{
+    int ret = syscall1(SYS_dup, oldfd);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+int dup2(int oldfd, int newfd)
+{
+    int ret = syscall2(SYS_dup2, oldfd, newfd);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+int pipe(int pipefd[2])
+{
+    int ret = syscall1(SYS_pipe, (uint32_t)pipefd);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+int close(int fd)
+{
+    int ret = syscall1(SYS_close, fd);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+_Noreturn void _exit(int code)
+{
+    (void)syscall1(SYS_exit, code);
+    // if syscall failed
+    for (;;);
+}
+
+pid_t fork(void)
+{
+    pid_t ret = syscall0(SYS_fork);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+int execve(const char* pathname, char* const argv[], char* const envp[])
+{
+    int ret = syscall3(SYS_execve, (uint32_t)pathname, (uint32_t)argv, (uint32_t)envp);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+// unsigned int sleep(unsigned int seconds)
+// {
+//     return syscall1(SYS_sleep, seconds);
+// }
+
+int chdir(const char* path)
+{
+    int ret = syscall1(SYS_chdir, (uint32_t)path);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+char* getcwd(char* buf, size_t bufsize)
+{
+    return (char*)syscall2(SYS_getcwd, (uint32_t)buf, bufsize);
+}
+
+pid_t getpid(void)
+{
+    pid_t ret = syscall0(SYS_getpid);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+pid_t getppid(void)
+{
+    pid_t ret = syscall0(SYS_getppid);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+int setpgid(pid_t pid, pid_t pgid)
+{
+    int ret = syscall2(SYS_setpgid, pid, pgid);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+pid_t setsid(void)
+{
+    pid_t ret = syscall0(SYS_setsid);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+pid_t getsid(pid_t pid)
+{
+    pid_t ret = syscall1(SYS_getsid, pid);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
+pid_t tcgetpgrp(int fd)
+{
+    pid_t pgrp;
+    return ioctl(fd, TIOCGPGRP, &pgrp);
+}
+
+int tcsetpgrp(int fd, pid_t pgrp)
+{
+    return ioctl(fd, TIOCSPGRP, &pgrp);
+}
+
+int ioctl(int fd, unsigned long request, ...)
+{
+    int ret = -EINVAL;
+
+    va_list args;
+    va_start(args, request);
+
+    switch (request) {
+    case TIOCGPGRP:
+        ret = syscall3(SYS_ioctl, fd, request, va_arg(args, uint32_t));
+        break;
+    case TIOCSPGRP:
+        ret = syscall3(SYS_ioctl, fd, request, va_arg(args, uint32_t));
+        break;
+    default:
+        break;
+    }
+
+    va_end(args);
+
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+
+    return ret;
+}
+
+static inline void* _sys_brk(void* addr)
+{
+    return (void*)syscall1(SYS_brk, (uint32_t)addr);
+}
+
+void** __start_brk_location(void)
+{
+    static void* __start_brk = NULL;
+    return &__start_brk;
+}
+void** __curr_brk_location(void)
+{
+    static void* __curr_brk = NULL;
+    return &__curr_brk;
+}
+
+int brk(void* addr)
+{
+    void* new_brk = _sys_brk(addr);
+    if (new_brk == curr_brk) {
+        errno = 0;
+        return -1;
+    }
+
+    if (new_brk != addr) {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    return 0;
+}
+
+void* sbrk(ssize_t increment)
+{
+    if (brk(curr_brk + increment) == 0)
+        return curr_brk += increment;
+    return (void*)-1;
+}
+
+int isatty(int fd)
+{
+    return tcgetpgrp(fd) != -1;
+}
+
+char** environ;

+ 12 - 0
gblibc/src/wait.c

@@ -0,0 +1,12 @@
+#include <sys/wait.h>
+#include <syscall.h>
+
+pid_t waitpid(pid_t pid, int* code, int options)
+{
+    return syscall3(SYS_waitpid, (uint32_t)pid, (uint32_t)code, (uint32_t)options);
+}
+
+pid_t wait(int* code)
+{
+    return waitpid(-1, code, 0);
+}

+ 41 - 0
gblibstdc++/CMakeLists.txt

@@ -0,0 +1,41 @@
+cmake_minimum_required(VERSION 3.15)
+project(gblibstdc++)
+
+set(CMAKE_CXX_STANDARD 20)
+
+add_library(gblibstdc++ STATIC src/stdc++.cpp)
+
+set(GBSTDLIBCPP_PUBLIC_HEADERS
+    gblibstdc++/include
+    gblibstdc++/include/bit
+    gblibstdc++/include/memory
+    gblibstdc++/include/tuple
+    gblibstdc++/include/type_traits
+    gblibstdc++/include/algorithm
+    gblibstdc++/include/cstddef
+    gblibstdc++/include/map
+    gblibstdc++/include/bits
+    gblibstdc++/include/bits/compressed_pair
+    gblibstdc++/include/bits/fwd_functional
+    gblibstdc++/include/bits/rbtree
+    gblibstdc++/include/bits/iter_ops
+    gblibstdc++/include/bits/type_traits
+    gblibstdc++/include/bits/type_traits/is_es
+    gblibstdc++/include/bits/type_traits/remove_add
+    gblibstdc++/include/bits/type_traits/base
+    gblibstdc++/include/bits/tuple_tools
+    gblibstdc++/include/bits/sequence
+    gblibstdc++/include/bits/forward
+    gblibstdc++/include/list
+    gblibstdc++/include/initializer_list
+    gblibstdc++/include/new
+    gblibstdc++/include/queue
+    gblibstdc++/include/string
+    gblibstdc++/include/set
+    gblibstdc++/include/vector
+    gblibstdc++/include/functional
+    gblibstdc++/include/utility
+    )
+
+target_include_directories(gblibstdc++ PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
+set_target_properties(gblibstdc++ PROPERTIES PUBLIC_HEADER "${GBSTDLIBCPP_PUBLIC_HEADERS}")

+ 214 - 0
gblibstdc++/include/algorithm

@@ -0,0 +1,214 @@
+#ifndef __GBLIBCPP_ALGORITHM__
+#define __GBLIBCPP_ALGORITHM__
+
+#include <functional>
+#include <utility>
+#include <initializer_list>
+#include <cstddef>
+
+namespace std {
+
+template <typename RandomIter, typename Compare>
+constexpr void make_heap(RandomIter first, RandomIter last, Compare comp)
+{
+    auto len = last - first;
+    if (len < 2)
+        return;
+
+    auto idx = len / 2 - 1;
+    for (;;) {
+        auto& val = first[idx];
+        auto left = idx * 2 + 1;
+        auto right = left + 1;
+
+        if (right < len) {
+            auto& left_val = first[left];
+            auto& right_val = first[right];
+
+            if (comp(left_val, right_val)) {
+                if (comp(val, right_val)) {
+                    std::swap(val, right_val);
+                    idx = right;
+                    continue;
+                }
+            } else {
+                if (comp(val, left_val)) {
+                    std::swap(val, left_val);
+                    idx = left;
+                    continue;
+                }
+            }
+        } else if (left < len) {
+            auto& left_val = first[left];
+
+            if (comp(val, left_val)) {
+                std::swap(val, left_val);
+                idx = left;
+                continue;
+            }
+        }
+
+        if (idx == 0)
+            break;
+        --idx;
+    }
+}
+template <typename RandomIter>
+constexpr void make_heap(RandomIter first, RandomIter last)
+{
+    make_heap(first, last, std::less<typename std::decay_t<decltype(*first)>>());
+}
+
+template <typename RandomIter, typename Compare>
+constexpr void push_heap(RandomIter first, RandomIter last, Compare comp)
+{
+    auto len = last - first;
+    if (len < 2)
+        return;
+
+    auto idx = len - 1;
+    for (;;) {
+        auto parent = (idx - 1) / 2;
+        if (parent == idx)
+            break;
+
+        auto& val = first[idx];
+        auto& parent_val = first[parent];
+
+        if (comp(parent_val, val)) {
+            std::swap(val, parent_val);
+            idx = parent;
+            continue;
+        }
+
+        break;
+    }
+}
+template <typename RandomIter>
+constexpr void push_heap(RandomIter first, RandomIter last)
+{
+    push_heap(first, last, std::less<typename std::decay_t<decltype(*first)>>());
+}
+
+template <typename RandomIter, typename Compare>
+constexpr void pop_heap(RandomIter first, RandomIter last, Compare comp)
+{
+    auto len = last - first;
+    if (len < 2)
+        return;
+
+    std::swap(first[0], first[len - 1]);
+
+    auto idx = 0;
+    for (;;) {
+        auto& val = first[idx];
+        auto left = idx * 2 + 1;
+        auto right = left + 1;
+
+        if (right < len - 1) {
+            auto& left_val = first[left];
+            auto& right_val = first[right];
+
+            if (comp(left_val, right_val)) {
+                if (comp(val, right_val)) {
+                    std::swap(val, right_val);
+                    idx = right;
+                    continue;
+                }
+            } else {
+                if (comp(val, left_val)) {
+                    std::swap(val, left_val);
+                    idx = left;
+                    continue;
+                }
+            }
+        } else if (left < len - 1) {
+            auto& left_val = first[left];
+
+            if (comp(val, left_val)) {
+                std::swap(val, left_val);
+                idx = left;
+                continue;
+            }
+        }
+
+        if (idx == 0)
+            break;
+        --idx;
+    }
+}
+template <typename RandomIter>
+constexpr void pop_heap(RandomIter first, RandomIter last)
+{
+    pop_heap(first, last, std::less<typename std::decay_t<decltype(*first)>>());
+}
+
+template <typename RandomIter, typename Compare>
+constexpr void sort(RandomIter first, RandomIter last, Compare comp)
+{
+    auto len = last - first;
+    std::make_heap(first, last, comp);
+
+    for (auto i = len - 1; i > 0; --i) {
+        std::swap(first[0], first[i]);
+
+        auto idx = 0;
+        for (;;) {
+            auto& val = first[idx];
+            auto left = idx * 2 + 1;
+            auto right = left + 1;
+
+            if (right < i) {
+                auto& left_val = first[left];
+                auto& right_val = first[right];
+
+                if (comp(left_val, right_val)) {
+                    if (comp(val, right_val)) {
+                        std::swap(val, right_val);
+                        idx = right;
+                        continue;
+                    }
+                } else {
+                    if (comp(val, left_val)) {
+                        std::swap(val, left_val);
+                        idx = left;
+                        continue;
+                    }
+                }
+            } else if (left < i) {
+                auto& left_val = first[left];
+
+                if (comp(val, left_val)) {
+                    std::swap(val, left_val);
+                    idx = left;
+                    continue;
+                }
+            }
+
+            if (idx == 0)
+                break;
+            --idx;
+        }
+    }
+}
+template <typename RandomIter>
+constexpr void sort(RandomIter first, RandomIter last)
+{
+    sort(first, last, std::less<typename std::decay_t<decltype(*first)>>());
+}
+
+template <typename T>
+constexpr const T& min(const T& a, const T& b)
+{
+    return a < b ? a : b;
+}
+
+template <typename T>
+constexpr const T& max(const T& a, const T& b)
+{
+    return a > b ? a : b;
+}
+
+} // namespace std
+
+#endif

+ 14 - 0
gblibstdc++/include/bit

@@ -0,0 +1,14 @@
+#ifndef __GBLIBCPP_BIT__
+#define __GBLIBCPP_BIT__
+
+namespace std {
+
+template <typename To, typename From>
+constexpr To bit_cast(const From& from) noexcept
+{
+    return __builtin_bit_cast(To, from);
+}
+
+} // namespace std
+
+#endif

+ 70 - 0
gblibstdc++/include/bits/compressed_pair

@@ -0,0 +1,70 @@
+#ifndef __GBLIBCPP_BITS_COMPRESSED_PAIR__
+#define __GBLIBCPP_BITS_COMPRESSED_PAIR__
+
+#include <utility>
+
+namespace std::impl {
+
+struct default_construct_t { };
+
+template <typename T, int, bool is_empty = __is_empty(T)>
+struct compressed_pair_element
+{
+    constexpr compressed_pair_element() = default;
+    constexpr compressed_pair_element(const compressed_pair_element&) = default;
+    constexpr compressed_pair_element(compressed_pair_element&&) = default;
+    constexpr compressed_pair_element& operator=(const compressed_pair_element&) = default;
+    constexpr compressed_pair_element& operator=(compressed_pair_element&&) = default;
+
+    constexpr compressed_pair_element(default_construct_t): value{} { }
+    constexpr compressed_pair_element(const T& x): value{x} { }
+    constexpr compressed_pair_element(T&& x): value{std::move(x)} { }
+
+    constexpr T& get() noexcept { return value; }
+    constexpr const T& get() const noexcept { return value; }
+
+    T value;
+};
+
+template <typename T, int N>
+struct compressed_pair_element<T, N, true> : private T
+{
+    constexpr compressed_pair_element() = default;
+    constexpr compressed_pair_element(const compressed_pair_element&) = default;
+    constexpr compressed_pair_element(compressed_pair_element&&) = default;
+    constexpr compressed_pair_element& operator=(const compressed_pair_element&) = default;
+    constexpr compressed_pair_element& operator=(compressed_pair_element&&) = default;
+
+    constexpr compressed_pair_element(default_construct_t): T{} { }
+    constexpr compressed_pair_element(const T& x): T{x} { }
+    constexpr compressed_pair_element(T&& x): T{std::move(x)} { }
+
+    constexpr T& get() noexcept { return *this; }
+    constexpr const T& get() const noexcept { return *this; }
+};
+
+template <typename T1, typename T2>
+struct compressed_pair
+    : private compressed_pair_element<T1, 0>, private compressed_pair_element<T2, 1> {
+    using Base1 = compressed_pair_element<T1, 0>;
+    using Base2 = compressed_pair_element<T2, 1>;
+
+    constexpr compressed_pair() = default;
+    constexpr compressed_pair(const compressed_pair&) = default;
+    constexpr compressed_pair(compressed_pair&&) = default;
+    constexpr compressed_pair& operator=(const compressed_pair&) = default;
+    constexpr compressed_pair& operator=(compressed_pair&&) = default;
+
+    constexpr compressed_pair(default_construct_t): Base1{default_construct_t{}}, Base2{default_construct_t{}} { }
+    constexpr compressed_pair(const T1& x, const T2& y): Base1{x}, Base2{y} { }
+    constexpr compressed_pair(T1&& x, T2&& y): Base1{std::move(x)}, Base2{std::move(y)} { }
+
+    constexpr T1& first() noexcept { return Base1::get(); }
+    constexpr const T1& first() const noexcept { return Base1::get(); }
+    constexpr T2& second() noexcept { return Base2::get(); }
+    constexpr const T2& second() const noexcept { return Base2::get(); }
+};
+
+} // namespace std::impl
+
+#endif

+ 34 - 0
gblibstdc++/include/bits/forward

@@ -0,0 +1,34 @@
+#ifndef __GBLIBCPP_BITS_FORWARD__
+#define __GBLIBCPP_BITS_FORWARD__
+
+#include <bits/type_traits/remove_add>
+
+namespace std {
+
+template <typename T>
+constexpr std::remove_reference_t<T>&& move(T&& val) noexcept
+{
+    return static_cast<std::remove_reference_t<T>&&>(val);
+}
+
+template <typename T>
+constexpr T&& forward(std::remove_reference_t<T>& val) noexcept
+{
+    return static_cast<T&&>(val);
+}
+template <typename T>
+constexpr T&& forward(std::remove_reference_t<T>&& val) noexcept
+{
+    return static_cast<T&&>(val);
+}
+
+template <typename T>
+add_rvalue_reference_t<T> declval(void) noexcept
+{
+    static_assert(__helpers::template_false_type<T>::value,
+        "declval cannot be evaluated.");
+}
+
+} // namespace std
+
+#endif

Some files were not shown because too many files changed in this diff