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
master
韩天峰 4 weeks ago
parent 6340433fbe
commit 9c44d0c692
  1. 2
      examples/typephp-os/Makefile
  2. 32
      examples/typephp-os/README.md
  3. 8
      examples/typephp-os/ROADMAP.md
  4. 5
      examples/typephp-os/boot/boot.S
  5. 2
      examples/typephp-os/boot/kernel64.ld
  6. 8
      examples/typephp-os/kernel/core/ata.c
  7. 2
      examples/typephp-os/kernel/core/memory.c
  8. 6
      examples/typephp-os/tools/test-qemu.sh
  9. 15
      examples/typephp-os/user/README.md
  10. 2
      examples/typephp-os/user/runtime/crt0.S
  11. 2
      examples/typephp-os/user/runtime/host.cc

@ -169,7 +169,7 @@ $(KERNEL): payload
$(BOOTSTRAP_OBJECT) $(PAYLOAD_OBJECT) $(BOOTSTRAP_OBJECT) $(PAYLOAD_OBJECT)
run: all 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 \ -drive file=$(DISK),format=raw,if=ide,index=0 \
-display none -serial stdio -monitor none -no-reboot -no-shutdown -display none -serial stdio -monitor none -no-reboot -no-shutdown

@ -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 `make thirdparty-smoke`. This is an integration audit, not part of the boot
image. 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 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` entry object is injected into tpc's final link through the generic `objects`
setting. The Makefile also builds the setting. The Makefile also builds the
@ -124,7 +125,7 @@ the payload linked at 2 MiB.
To invoke QEMU manually: To invoke QEMU manually:
```shell ```shell
qemu-system-x86_64 -m 160M \ qemu-system-x86_64 -m 512M \
-kernel examples/typephp-os/build/typephp-os.elf \ -kernel examples/typephp-os/build/typephp-os.elf \
-drive file=examples/typephp-os/build/typephp-os.img,format=raw,if=ide,index=0 \ -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 -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()`; - RTC-derived UTC time exposed to userspace through `time()`;
- Linux-compatible `uname(2)` shared by the `uname` command and PHP's - Linux-compatible `uname(2)` shared by the `uname` command and PHP's
`php_uname()` implementation; `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 TypePHP FAT16 implementation with DOS 8.3 files, nested traversal and
mutation, including automatic directory-chain growth; mutation, including automatic directory-chain growth;
- PHP's unchanged plain file stream and `php_stat()` paths, including - 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 - user-mode file creation, reading, writing, seeking, closing, removal, and
nested directory creation/removal through the TypePHP FAT16 implementation. nested directory creation/removal through the TypePHP FAT16 implementation.
The 64-bit payload currently occupies about 7 MiB. The first 40 MiB is kept The loadable 64-bit payload is followed by a large zero-filled block cache in
away from both allocators for the kernel payload, bootstrap state, and early kernel BSS. The first 64 MiB is kept away from both allocators for the kernel
host arena. Userspace has a separate 0x40000000–0x50000000 virtual region. 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. Entire Zend chunks are not yet returned to the physical-page pool.
The current filesystem deliberately supports only DOS 8.3 names. Reading, The current filesystem deliberately supports only DOS 8.3 names. Reading,
directory enumeration, `stat`, executable loading, and file/directory mutation directory enumeration, `stat`, executable loading, and file/directory mutation
traverse nested FAT16 directory chains. Full directories grow by linking a new traverse nested FAT16 directory chains. Full directories grow by linking a new
cluster. The current ATA cache is deliberately small, synchronous, and cluster. The current ATA cache is synchronous and write-through. Its 65,536
write-through; it is not yet a general virtual-filesystem page cache. Rename 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, currently stays within one parent directory; cross-directory rename,
replacement semantics, long filenames, timestamps, permissions, and a general replacement semantics, long filenames, timestamps, permissions, and a general
block-device layer remain future work. block-device layer remain future work.
@ -203,23 +208,26 @@ APIs that execute host commands remain unavailable.
## Single-task userspace ## Single-task userspace
After the TypePHP self-check, the kernel opens `/BIN/SH.ELF` from FAT16, 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 validates and loads its `PT_LOAD` segments, installs a 64-bit TSS, IDT and
gate, and enters Ring 3 with `iretq`. The resident shell and each transient `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 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 from recyclable 4 KiB pages; the shared identity-mapped kernel remains
supervisor-only. The CPU has write protection and no-execute enabled, and the 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 loader applies the final ELF `PF_W` and `PF_X` permissions after copying each
segment. 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`, `lseek`, `openat`, `exit`/`exit_group`, `getcwd`, `chdir`, `mkdir`, `rmdir`,
`unlink`, file stat/access/persistence/truncation families, fixed identity `unlink`, file stat/access/persistence/truncation families, fixed identity
queries, `time`, `gettimeofday`, `clock_gettime`, `clock_getres`, `brk`, queries, `time`, `gettimeofday`, `clock_gettime`, `clock_getres`, `brk`,
anonymous private `mmap`, `mprotect`, `munmap`, `getdents64`, the initial 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 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 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 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`. 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 Userspace programs now expose standard C `main(argc, argv)` functions. A shared
`crt0.S` consumes a Linux-style initial stack containing `argc`, `argv`, an `crt0.S` consumes a Linux-style initial stack containing `argc`, `argv`, an

@ -49,14 +49,14 @@ behavior.
directory/stat operations, and PHP's local file stream API. DOS 8.3 path directory/stat operations, and PHP's local file stream API. DOS 8.3 path
lookup, file reads, directory enumeration, file/directory mutation, and lookup, file reads, directory enumeration, file/directory mutation, and
same-parent rename traverse nested cluster chains. Directories grow by same-parent rename traverse nested cluster chains. Directories grow by
allocating and linking additional clusters. A fixed 128-sector LRU allocating and linking additional clusters. A 32 MiB direct-mapped
read/write-through cache now avoids repeated ATA PIO reads while preserving read/write-through cache covers the current disk image while preserving
synchronous persistence. A general VFS page cache, cross-directory rename, synchronous persistence. A general VFS page cache, cross-directory rename,
replacement semantics, and long filenames are next. replacement semantics, and long filenames are next.
6. **Single-task userspace — fifth slice complete.** Disk-backed ELF64 6. **Single-task userspace — fifth slice complete.** Disk-backed ELF64
validation/loading from FAT16, validation/loading from FAT16,
GDT/TSS, Ring-3 entry, synchronous 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[]` syscall definitions, complete `argv[]`
delivery, and independent freestanding C shell/command programs. The first delivery, and independent freestanding C shell/command programs. The first
Linux-compatible file syscalls cover `openat`, `read`, `write`, `lseek`, 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++ ABI, and math support is compiled once into `libtypephp-os.a`; both the
C commands and multiple tpc projects link the same platform archive. C commands and multiple tpc projects link the same platform archive.
Unavailable ABI functions remain explicit panic stubs. 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 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 helper symbols. A five-applet Toybox build is pinned as a porting probe but
does not yet replace the working userspace commands. does not yet replace the working userspace commands.

@ -19,7 +19,10 @@ pd_table:
.align 16 .align 16
stack_bottom: 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: stack_top:
.section .text .section .text

@ -30,7 +30,7 @@ SECTIONS
__bss_end = .; __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/ : /DISCARD/ :
{ {

@ -33,10 +33,10 @@ enum {
ATA_COMMAND_CACHE_FLUSH = 0xe7, ATA_COMMAND_CACHE_FLUSH = 0xe7,
ATA_SECTOR_SIZE = 512, ATA_SECTOR_SIZE = 512,
ATA_TIMEOUT = 10000000, ATA_TIMEOUT = 10000000,
/* TNHELLO.ELF is currently about 5 MiB. A power-of-two 8 MiB cache keeps /* QEMU uses a 32 MiB FAT16 image. One direct-mapped entry per image
* one complete image resident so a second launch avoids ATA PIO, while a * sector turns the current disk into an effective whole-device cache;
* direct mapping keeps every sector lookup O(1). */ * larger future disks remain correct and use the same O(1) mapping. */
ATA_CACHE_CAPACITY = 16384, ATA_CACHE_CAPACITY = 65536,
PCI_CONFIG_ADDRESS = 0xcf8, PCI_CONFIG_ADDRESS = 0xcf8,
PCI_CONFIG_DATA = 0xcfc, PCI_CONFIG_DATA = 0xcfc,
}; };

@ -13,7 +13,7 @@ static const uint64_t PAGE_SIZE = 4096ul;
/* Keep the payload, bootstrap data, and early host arena away from the two /* Keep the payload, bootstrap data, and early host arena away from the two
* physical allocators. User programs occupy a separate high virtual region * physical allocators. User programs occupy a separate high virtual region
* in their own CR3, so they no longer overlap this identity-mapped range. */ * 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; static const uint64_t IDENTITY_MAP_END = 1024ul * 1024ul * 1024ul;
typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) {

@ -11,7 +11,7 @@ trap 'rm -f "${qemu_disk}"' EXIT
cp "${disk}" "${qemu_disk}" cp "${disk}" "${qemu_disk}"
if timeout 35 qemu-system-x86_64 \ if timeout 35 qemu-system-x86_64 \
-m 160M \ -m 512M \
-kernel "${kernel}" \ -kernel "${kernel}" \
-drive file="${qemu_disk}",format=raw,if=ide,index=0 \ -drive file="${qemu_disk}",format=raw,if=ide,index=0 \
-display none \ -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 echo "the Nano smoke program reached an unsupported userspace ABI" >&2
exit 1 exit 1
fi 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: missing: No such file or directory' "${log}"
grep -q '^sh: bad: Exec format error' "${log}" grep -q '^sh: bad: Exec format error' "${log}"
grep -q '^/BIN' "${log}" grep -q '^/BIN' "${log}"

@ -26,8 +26,8 @@ The following rules are normative for this directory:
6. New kernel services should first consider the remaining interfaces needed 6. New kernel services should first consider the remaining interfaces needed
by a static libc and PHP Nano: memory mapping, files and directories, by a static libc and PHP Nano: memory mapping, files and directories,
clocks, TLS, and single-task lifecycle. Socket support remains out of clocks, TLS, and single-task lifecycle. Socket support remains out of
scope. `ioctl` and `termios` are also intentionally deferred; basic console scope. The fixed console supports `ioctl(TIOCGWINSZ)`; a complete termios
`read`/`write` is the supported terminal contract. subsystem remains intentionally deferred.
7. Freestanding test programs remain hosted-libc-free only as a bootstrap 7. Freestanding test programs remain hosted-libc-free only as a bootstrap
constraint; it is not the final userspace programming model. C and TypePHP constraint; it is not the final userspace programming model. C and TypePHP
programs must link the same `libtypephp-os.a` platform runtime instead of 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`, `getpid`, `getppid`, `gettid`, the root UID/GID queries, `brk`, `sbrk`, `mmap`,
`mprotect`, `munmap`, `opendir`, `fdopendir`, `readdir`, `rewinddir`, `mprotect`, `munmap`, `opendir`, `fdopendir`, `readdir`, `rewinddir`,
`closedir`, `dirfd`, the `F_GETFD`/`F_SETFD`/`F_GETFL`/`F_SETFL` subset of `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 libc-compatible C signatures. Directory streams are backed by Linux x86-64
`getdents64`; no TypePHP-OS-private directory syscall is exposed. It also `getdents64`; no TypePHP-OS-private directory syscall is exposed. It also
translates kernel `-errno` results into `-1` plus the single-task userspace 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 even when they use overlapping virtual addresses. Adding a compatible command
file does not require relinking the kernel. file does not require relinking the kernel.
The current `int 0x80` entry is transitional. Before linking an ordinary Userspace enters the kernel with the x86-64 `SYSCALL` instruction and Linux
x86-64 glibc build, the kernel must also accept the `syscall` instruction with register convention (`rax`, `rdi`, `rsi`, `rdx`, `r10`, `r8`, `r9`). Kernel
the Linux register convention (`rax`, `rdi`, `rsi`, `rdx`, `r10`, `r8`, `r9`), entry switches to a dedicated stack, returns negative errno values, and
negative errno returns, and the expected `rcx`/`r11` clobbers. 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 Using unmodified upstream glibc will require substantially more than matching
syscall numbers. The kernel must eventually provide the expected ELF process syscall numbers. The kernel must eventually provide the expected ELF process

@ -17,7 +17,7 @@ _start:
mov %eax, %edi mov %eax, %edi
# Linux x86-64 exit_group(2); TypePHP-OS keeps the same number and ABI. # Linux x86-64 exit_group(2); TypePHP-OS keeps the same number and ABI.
mov $231, %eax mov $231, %eax
int $0x80 syscall
ud2 ud2
.size _start, . - _start .size _start, . - _start

@ -13,7 +13,7 @@ namespace {
/* Zend MM acquires aligned 2 MiB chunks while PHPX's native object GC also /* 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 * 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; constexpr std::uintptr_t arena_size = 48u * 1024u * 1024u;
[[noreturn]] void raw_exit(int status) [[noreturn]] void raw_exit(int status)

Loading…
Cancel
Save