From 9c44d0c6928377d1e36d894766fa2af34fbf1311 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Fri, 11 Sep 2026 17:43:26 +0800 Subject: [PATCH] perf(kernel): increase memory allocation and update syscall interface - Increased ATA cache capacity from 16384 to 65536 sectors for 32 MiB direct-mapped cache - Expanded bootstrap stack from 16 KiB to 256 KiB with proper headroom for identity-map tables - Updated userspace syscall interface from int 0x80 to native x86-64 SYSCALL instruction - Raised QEMU memory allocation from 160M to 512M for improved runtime performance - Increased kernel reserved memory from 40 MiB to 64 MiB with updated linker script assertion - Added fixed-console ioctl(TIOCGWINSZ) support for VGA dimension reporting - Enhanced ATA --- examples/typephp-os/Makefile | 2 +- examples/typephp-os/README.md | 32 +++++++++++++++--------- examples/typephp-os/ROADMAP.md | 8 +++--- examples/typephp-os/boot/boot.S | 5 +++- examples/typephp-os/boot/kernel64.ld | 2 +- examples/typephp-os/kernel/core/ata.c | 8 +++--- examples/typephp-os/kernel/core/memory.c | 2 +- examples/typephp-os/tools/test-qemu.sh | 6 ++++- examples/typephp-os/user/README.md | 15 +++++------ examples/typephp-os/user/runtime/crt0.S | 2 +- examples/typephp-os/user/runtime/host.cc | 2 +- 11 files changed, 51 insertions(+), 33 deletions(-) diff --git a/examples/typephp-os/Makefile b/examples/typephp-os/Makefile index 73416368..7cfb635f 100644 --- a/examples/typephp-os/Makefile +++ b/examples/typephp-os/Makefile @@ -169,7 +169,7 @@ $(KERNEL): payload $(BOOTSTRAP_OBJECT) $(PAYLOAD_OBJECT) run: all - qemu-system-x86_64 -m 160M -kernel $(KERNEL) \ + qemu-system-x86_64 -m 512M -kernel $(KERNEL) \ -drive file=$(DISK),format=raw,if=ide,index=0 \ -display none -serial stdio -monitor none -no-reboot -no-shutdown diff --git a/examples/typephp-os/README.md b/examples/typephp-os/README.md index dcb251e2..a9f2519f 100644 --- a/examples/typephp-os/README.md +++ b/examples/typephp-os/README.md @@ -103,7 +103,8 @@ To build and audit the restricted hosted Toybox applet set, run `make thirdparty-smoke`. This is an integration audit, not part of the boot image. -The Makefile compiles the startup sources under `boot/` directly. The 32-bit +The Makefile compiles the startup sources under `boot/` directly. Its 256 KiB +early kernel stack is kept separate from the adjacent identity-map tables. The 32-bit Multiboot bootstrap cannot participate in the 64-bit payload link; the 64-bit entry object is injected into tpc's final link through the generic `objects` setting. The Makefile also builds the @@ -124,7 +125,7 @@ the payload linked at 2 MiB. To invoke QEMU manually: ```shell -qemu-system-x86_64 -m 160M \ +qemu-system-x86_64 -m 512M \ -kernel examples/typephp-os/build/typephp-os.elf \ -drive file=examples/typephp-os/build/typephp-os.img,format=raw,if=ide,index=0 \ -display none -serial stdio -monitor none -no-reboot -no-shutdown @@ -154,7 +155,7 @@ The QEMU smoke test currently verifies: - RTC-derived UTC time exposed to userspace through `time()`; - Linux-compatible `uname(2)` shared by the `uname` command and PHP's `php_uname()` implementation; -- ATA PIO sector I/O, a fixed 128-sector LRU read/write-through cache, and a +- ATA PIO sector I/O, a 32 MiB direct-mapped read/write-through cache, and a TypePHP FAT16 implementation with DOS 8.3 files, nested traversal and mutation, including automatic directory-chain growth; - PHP's unchanged plain file stream and `php_stat()` paths, including @@ -184,16 +185,20 @@ The QEMU smoke test currently verifies: - user-mode file creation, reading, writing, seeking, closing, removal, and nested directory creation/removal through the TypePHP FAT16 implementation. -The 64-bit payload currently occupies about 7 MiB. The first 40 MiB is kept -away from both allocators for the kernel payload, bootstrap state, and early -host arena. Userspace has a separate 0x40000000–0x50000000 virtual region. +The loadable 64-bit payload is followed by a large zero-filled block cache in +kernel BSS. The first 64 MiB is kept away from both allocators for the kernel +payload, cache, bootstrap state, and early host arena. Userspace has a separate +0x40000000–0x50000000 virtual region. Entire Zend chunks are not yet returned to the physical-page pool. The current filesystem deliberately supports only DOS 8.3 names. Reading, directory enumeration, `stat`, executable loading, and file/directory mutation traverse nested FAT16 directory chains. Full directories grow by linking a new -cluster. The current ATA cache is deliberately small, synchronous, and -write-through; it is not yet a general virtual-filesystem page cache. Rename +cluster. The current ATA cache is synchronous and write-through. Its 65,536 +direct-mapped sector entries cover the complete current 32 MiB disk image, so +repeated Nano ELF loads no longer return to ATA PIO. It is still a block cache, +not a general virtual-filesystem page cache, and every Nano process still +performs its own runtime initialization. Rename currently stays within one parent directory; cross-directory rename, replacement semantics, long filenames, timestamps, permissions, and a general block-device layer remain future work. @@ -203,23 +208,26 @@ APIs that execute host commands remain unavailable. ## Single-task userspace After the TypePHP self-check, the kernel opens `/BIN/SH.ELF` from FAT16, -validates and loads its `PT_LOAD` segments, installs a 64-bit TSS and an IDT -gate, and enters Ring 3 with `iretq`. The resident shell and each transient +validates and loads its `PT_LOAD` segments, installs a 64-bit TSS, IDT and +`SYSCALL` MSRs, and enters Ring 3 with `iretq`. The resident shell and each transient command receive an independent CR3. Their 1–1.25 GiB virtual window is composed from recyclable 4 KiB pages; the shared identity-mapped kernel remains supervisor-only. The CPU has write protection and no-execute enabled, and the loader applies the final ELF `PF_W` and `PF_X` permissions after copying each segment. -An `int 0x80` boundary currently provides synchronous `read`, `write`, `close`, +The native x86-64 `SYSCALL` boundary provides synchronous `read`, `write`, `close`, `lseek`, `openat`, `exit`/`exit_group`, `getcwd`, `chdir`, `mkdir`, `rmdir`, `unlink`, file stat/access/persistence/truncation families, fixed identity queries, `time`, `gettimeofday`, `clock_gettime`, `clock_getres`, `brk`, anonymous private `mmap`, `mprotect`, `munmap`, `getdents64`, the initial -`fcntl` flag operations, and private +`fcntl` flag operations, fixed-console `ioctl(TIOCGWINSZ)`, and private spawn and same-directory rename operations. The former private directory-list syscall has been removed; `ls` and PHP Nano use the standard directory ABI. Standard input and output are backed by QEMU's COM1 serial console. Syscall numbers are shared by the kernel and userspace through `typephp_os_syscall.h`. +Entry immediately switches from the untrusted user RSP to a dedicated kernel +stack. Return uses `iretq`, allowing synchronous spawn/exit to replace the +complete saved user context. Userspace programs now expose standard C `main(argc, argv)` functions. A shared `crt0.S` consumes a Linux-style initial stack containing `argc`, `argv`, an diff --git a/examples/typephp-os/ROADMAP.md b/examples/typephp-os/ROADMAP.md index ea73699f..34e9977e 100644 --- a/examples/typephp-os/ROADMAP.md +++ b/examples/typephp-os/ROADMAP.md @@ -49,14 +49,14 @@ behavior. directory/stat operations, and PHP's local file stream API. DOS 8.3 path lookup, file reads, directory enumeration, file/directory mutation, and same-parent rename traverse nested cluster chains. Directories grow by - allocating and linking additional clusters. A fixed 128-sector LRU - read/write-through cache now avoids repeated ATA PIO reads while preserving + allocating and linking additional clusters. A 32 MiB direct-mapped + read/write-through cache covers the current disk image while preserving synchronous persistence. A general VFS page cache, cross-directory rename, replacement semantics, and long filenames are next. 6. **Single-task userspace — fifth slice complete.** Disk-backed ELF64 validation/loading from FAT16, GDT/TSS, Ring-3 entry, synchronous - `int 0x80` system calls, COM1 standard I/O, saved parent context, shared + native x86-64 `SYSCALL` entry, COM1 standard I/O, saved parent context, shared syscall definitions, complete `argv[]` delivery, and independent freestanding C shell/command programs. The first Linux-compatible file syscalls cover `openat`, `read`, `write`, `lseek`, @@ -88,6 +88,8 @@ behavior. C++ ABI, and math support is compiled once into `libtypephp-os.a`; both the C commands and multiple tpc projects link the same platform archive. Unavailable ABI functions remain explicit panic stubs. + Fixed-console `ioctl(TIOCGWINSZ)` reports the VGA dimensions while other + terminal requests return `ENOTTY`; a complete termios subsystem is not implied. Selected upstream LLVM compiler-rt builtins now provide 128-bit integer helper symbols. A five-applet Toybox build is pinned as a porting probe but does not yet replace the working userspace commands. diff --git a/examples/typephp-os/boot/boot.S b/examples/typephp-os/boot/boot.S index cbcf4aca..e928e2fc 100644 --- a/examples/typephp-os/boot/boot.S +++ b/examples/typephp-os/boot/boot.S @@ -19,7 +19,10 @@ pd_table: .align 16 stack_bottom: -.skip 16384 +/* PHP Nano and the TypePHP startup self-check use more than the original + * 16 KiB bootstrap stack before Ring-3 is entered. Keep enough headroom that + * downward growth cannot overwrite the adjacent identity-map page tables. */ +.skip 262144 stack_top: .section .text diff --git a/examples/typephp-os/boot/kernel64.ld b/examples/typephp-os/boot/kernel64.ld index eb345a82..dc2fe846 100644 --- a/examples/typephp-os/boot/kernel64.ld +++ b/examples/typephp-os/boot/kernel64.ld @@ -30,7 +30,7 @@ SECTIONS __bss_end = .; } - ASSERT(__bss_end <= 16M, "64-bit kernel exceeds its reserved boot memory") + ASSERT(__bss_end <= 64M, "64-bit kernel exceeds its reserved boot memory") /DISCARD/ : { diff --git a/examples/typephp-os/kernel/core/ata.c b/examples/typephp-os/kernel/core/ata.c index 86175fbf..f68ca087 100644 --- a/examples/typephp-os/kernel/core/ata.c +++ b/examples/typephp-os/kernel/core/ata.c @@ -33,10 +33,10 @@ enum { ATA_COMMAND_CACHE_FLUSH = 0xe7, ATA_SECTOR_SIZE = 512, ATA_TIMEOUT = 10000000, - /* TNHELLO.ELF is currently about 5 MiB. A power-of-two 8 MiB cache keeps - * one complete image resident so a second launch avoids ATA PIO, while a - * direct mapping keeps every sector lookup O(1). */ - ATA_CACHE_CAPACITY = 16384, + /* QEMU uses a 32 MiB FAT16 image. One direct-mapped entry per image + * sector turns the current disk into an effective whole-device cache; + * larger future disks remain correct and use the same O(1) mapping. */ + ATA_CACHE_CAPACITY = 65536, PCI_CONFIG_ADDRESS = 0xcf8, PCI_CONFIG_DATA = 0xcfc, }; diff --git a/examples/typephp-os/kernel/core/memory.c b/examples/typephp-os/kernel/core/memory.c index 51be7313..8c17e856 100644 --- a/examples/typephp-os/kernel/core/memory.c +++ b/examples/typephp-os/kernel/core/memory.c @@ -13,7 +13,7 @@ static const uint64_t PAGE_SIZE = 4096ul; /* Keep the payload, bootstrap data, and early host arena away from the two * physical allocators. User programs occupy a separate high virtual region * in their own CR3, so they no longer overlap this identity-mapped range. */ -static const uint64_t KERNEL_RESERVED_END = 40ul * 1024ul * 1024ul; +static const uint64_t KERNEL_RESERVED_END = 64ul * 1024ul * 1024ul; static const uint64_t IDENTITY_MAP_END = 1024ul * 1024ul * 1024ul; typedef struct __attribute__((packed)) { diff --git a/examples/typephp-os/tools/test-qemu.sh b/examples/typephp-os/tools/test-qemu.sh index ba453cd1..ba29490e 100755 --- a/examples/typephp-os/tools/test-qemu.sh +++ b/examples/typephp-os/tools/test-qemu.sh @@ -11,7 +11,7 @@ trap 'rm -f "${qemu_disk}"' EXIT cp "${disk}" "${qemu_disk}" if timeout 35 qemu-system-x86_64 \ - -m 160M \ + -m 512M \ -kernel "${kernel}" \ -drive file="${qemu_disk}",format=raw,if=ide,index=0 \ -display none \ @@ -75,6 +75,10 @@ if grep -q 'unsupported TypePHP-OS user ABI' "${log}"; then echo "the Nano smoke program reached an unsupported userspace ABI" >&2 exit 1 fi +if grep -q 'general protection (#13)' "${log}"; then + echo "a userspace command caused an unexpected general-protection fault" >&2 + exit 1 +fi grep -q '^sh: missing: No such file or directory' "${log}" grep -q '^sh: bad: Exec format error' "${log}" grep -q '^/BIN' "${log}" diff --git a/examples/typephp-os/user/README.md b/examples/typephp-os/user/README.md index 0979e9e7..cbb67dfb 100644 --- a/examples/typephp-os/user/README.md +++ b/examples/typephp-os/user/README.md @@ -26,8 +26,8 @@ The following rules are normative for this directory: 6. New kernel services should first consider the remaining interfaces needed by a static libc and PHP Nano: memory mapping, files and directories, clocks, TLS, and single-task lifecycle. Socket support remains out of - scope. `ioctl` and `termios` are also intentionally deferred; basic console - `read`/`write` is the supported terminal contract. + scope. The fixed console supports `ioctl(TIOCGWINSZ)`; a complete termios + subsystem remains intentionally deferred. 7. Freestanding test programs remain hosted-libc-free only as a bootstrap constraint; it is not the final userspace programming model. C and TypePHP programs must link the same `libtypephp-os.a` platform runtime instead of @@ -44,7 +44,7 @@ The current shared userspace runtime provides `syscall`, `read`, `write`, `opena `getpid`, `getppid`, `gettid`, the root UID/GID queries, `brk`, `sbrk`, `mmap`, `mprotect`, `munmap`, `opendir`, `fdopendir`, `readdir`, `rewinddir`, `closedir`, `dirfd`, the `F_GETFD`/`F_SETFD`/`F_GETFL`/`F_SETFL` subset of -`fcntl`, `strlen`, `strerror`, `perror`, and `_exit` with +`fcntl`, fixed-console `ioctl(TIOCGWINSZ)`, `strlen`, `strerror`, `perror`, and `_exit` with libc-compatible C signatures. Directory streams are backed by Linux x86-64 `getdents64`; no TypePHP-OS-private directory syscall is exposed. It also translates kernel `-errno` results into `-1` plus the single-task userspace @@ -93,10 +93,11 @@ and confines the resident shell and transient command to separate page tables, even when they use overlapping virtual addresses. Adding a compatible command file does not require relinking the kernel. -The current `int 0x80` entry is transitional. Before linking an ordinary -x86-64 glibc build, the kernel must also accept the `syscall` instruction with -the Linux register convention (`rax`, `rdi`, `rsi`, `rdx`, `r10`, `r8`, `r9`), -negative errno returns, and the expected `rcx`/`r11` clobbers. +Userspace enters the kernel with the x86-64 `SYSCALL` instruction and Linux +register convention (`rax`, `rdi`, `rsi`, `rdx`, `r10`, `r8`, `r9`). Kernel +entry switches to a dedicated stack, returns negative errno values, and +preserves the standard `rcx`/`r11` clobber contract. Return currently uses +`iretq` because synchronous spawn/exit may replace the complete saved context. Using unmodified upstream glibc will require substantially more than matching syscall numbers. The kernel must eventually provide the expected ELF process diff --git a/examples/typephp-os/user/runtime/crt0.S b/examples/typephp-os/user/runtime/crt0.S index cfa5166a..2b3b57b9 100644 --- a/examples/typephp-os/user/runtime/crt0.S +++ b/examples/typephp-os/user/runtime/crt0.S @@ -17,7 +17,7 @@ _start: mov %eax, %edi # Linux x86-64 exit_group(2); TypePHP-OS keeps the same number and ABI. mov $231, %eax - int $0x80 + syscall ud2 .size _start, . - _start diff --git a/examples/typephp-os/user/runtime/host.cc b/examples/typephp-os/user/runtime/host.cc index 252cfb1a..1ff1cfdb 100644 --- a/examples/typephp-os/user/runtime/host.cc +++ b/examples/typephp-os/user/runtime/host.cc @@ -13,7 +13,7 @@ namespace { /* Zend MM acquires aligned 2 MiB chunks while PHPX's native object GC also * keeps process-lifetime metadata. A 48 MiB arena leaves enough headroom for - * the complete Nano module startup in the current 160 MiB QEMU machine. */ + * the complete Nano module startup in the current 512 MiB QEMU machine. */ constexpr std::uintptr_t arena_size = 48u * 1024u * 1024u; [[noreturn]] void raw_exit(int status)