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)
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

@ -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

@ -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.

@ -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

@ -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/ :
{

@ -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,
};

@ -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)) {

@ -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}"

@ -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

@ -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

@ -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)

Loading…
Cancel
Save