feat(kernel): add memory information system call and free command

- Add typephp_os_disk_cache_bytes function to return ATA cache size
- Implement C++ terminate function with typephp_os_panic call
- Create new free.cc with php_os_memory_value native function
- Add free.php memory reporting command with pool accounting
- Define free.yml build configuration for the new command
- Update hello.yml with additional compiler flags
- Add syscall declaration to ioctl.c
- Introduce arena_begin variable and typephp_os_memory_total function
- Implement vfprintf function using vprintf
- Add typephp_os_longjmp implementation with proper asm annotation
- Update fprintf to use v
master
韩天峰 4 weeks ago
parent 9c44d0c692
commit 875c726810
  1. 44
      examples/typephp-os/Makefile
  2. 16
      examples/typephp-os/README.md
  3. 9
      examples/typephp-os/ROADMAP.md
  4. 5
      examples/typephp-os/kernel/core/abi/cxx.cpp
  5. 32
      examples/typephp-os/kernel/core/abi/libc.c
  6. 1
      examples/typephp-os/kernel/core/abi/typephp_os_abi.h
  7. 24
      examples/typephp-os/kernel/core/abi/typephp_os_memory.h
  8. 1
      examples/typephp-os/kernel/core/abi/typephp_os_syscall.h
  9. 5
      examples/typephp-os/kernel/core/ata.c
  10. 20
      examples/typephp-os/kernel/core/memory.c
  11. 24
      examples/typephp-os/kernel/core/process.c
  12. 6
      examples/typephp-os/project.yml
  13. 9
      examples/typephp-os/tools/test-qemu.sh
  14. 6
      examples/typephp-os/user/README.md
  15. 4
      examples/typephp-os/user/cmd/sh.c
  16. 1
      examples/typephp-os/user/include/sys/syscall.h
  17. 20
      examples/typephp-os/user/nano/free.cc
  18. 49
      examples/typephp-os/user/nano/free.php
  19. 67
      examples/typephp-os/user/nano/free.yml
  20. 6
      examples/typephp-os/user/nano/hello.yml
  21. 5
      examples/typephp-os/user/nano/memory.stub.php
  22. 2
      examples/typephp-os/user/runtime/ioctl.c
  23. 9
      examples/typephp-os/user/runtime/memory.c

@ -12,6 +12,7 @@ USER_PROGRAMS := sh $(USER_COMMANDS)
USER_SH_ELF := $(BUILD)/sh.elf
USER_COMMAND_ELFS := $(addprefix $(BUILD)/,$(addsuffix .elf,$(USER_COMMANDS)))
NANO_USER_ELF := $(BUILD)/tnhello.elf
TYPEPHP_FREE_ELF := $(BUILD)/free.elf
TYPEPHP_OS_LIBRARY := $(BUILD)/libtypephp-os.a
TYPEPHP_OS_LIBRARY_OBJECT_DIR := $(BUILD)/libtypephp-os
COMPILER_RT_LIBRARY := $(BUILD)/libcompiler-rt-builtins.a
@ -23,7 +24,7 @@ COMPILER_RT_SOURCES := $(shell awk '$$2 ~ /\.c$$/ { print "thirdparty/compiler-r
COMPILER_RT_OBJECTS := $(patsubst thirdparty/compiler-rt/lib/builtins/%.c,$(COMPILER_RT_OBJECT_DIR)/%.o,$(COMPILER_RT_SOURCES))
TYPEPHP_OS_LIBRARY_C_SOURCES := user/runtime/posix.c user/runtime/dirent.c \
user/runtime/fcntl.c user/runtime/ioctl.c kernel/core/abi/error.c kernel/core/abi/string.c \
kernel/core/abi/libc.c $(OPENLIBM_SOURCES)
user/runtime/memory.c kernel/core/abi/libc.c $(OPENLIBM_SOURCES)
TYPEPHP_OS_LIBRARY_CXX_SOURCES := user/runtime/host.cc kernel/core/abi/cxx.cpp
TYPEPHP_OS_LIBRARY_ASM_SOURCES := user/runtime/crt0.S user/runtime/syscall.S \
kernel/core/abi/unimplemented.S
@ -35,12 +36,15 @@ TYPEPHP_OS_LIBRARY_OBJECTS := \
TYPEPHP_OS_LIBRARY_DEPFILES := $(addsuffix .d,$(TYPEPHP_OS_LIBRARY_OBJECTS))
NANO_USER_SOURCES := user/nano/hello.php user/nano/hello.yml user/runtime/linker.ld \
$(TYPEPHP_OS_LIBRARY) $(COMPILER_RT_LIBRARY)
TYPEPHP_FREE_SOURCES := user/nano/free.php user/nano/memory.stub.php \
user/nano/free.cc user/nano/free.yml user/runtime/linker.ld \
$(TYPEPHP_OS_LIBRARY) $(COMPILER_RT_LIBRARY)
BOOTFLAGS := -m32 -O2 -ffreestanding -fno-pic -fno-pie \
BOOTFLAGS := -m32 -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -ffreestanding -fno-pic -fno-pie \
-fno-stack-protector -Wall -Wextra
KERNEL64_BOOTFLAGS := -m64 -O2 -ffreestanding -fno-builtin -fno-pic -fno-pie \
KERNEL64_BOOTFLAGS := -m64 -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -ffreestanding -fno-builtin -fno-pic -fno-pie \
-fno-stack-protector -mno-red-zone -mcmodel=small -Wall -Wextra
USER_CFLAGS := -m64 -O2 -ffreestanding -fno-builtin -fno-pic -fno-pie \
USER_CFLAGS := -m64 -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -ffreestanding -fno-builtin -fno-pic -fno-pie \
-fno-stack-protector -mno-red-zone -Wall -Wextra -Iuser/include -Ikernel/core/abi
USER_HEADERS := $(shell find user/include -type f)
USER_LDFLAGS := -m elf_x86_64 -nostdlib -static --undefined=_start \
@ -56,11 +60,13 @@ TYPEPHP_OS_RUNTIME_INCLUDES := -Ikernel/core/abi \
-I$(PHP_NANO_DIR)/include -I$(PHP_NANO_DIR)/main -I$(PHP_NANO_DIR)/TSRM \
-I$(PHP_NANO_DIR)/ext/date/lib -I$(PHP_NANO_DIR)/ext/pcre/pcre2lib \
-I$(PHPX_DIR)/include -I$(PHPX_DIR)/thirdparty/wren-gc/include
TYPEPHP_OS_RUNTIME_CFLAGS := -m64 -O0 -std=c11 -ffreestanding -fno-builtin \
TYPEPHP_OS_RUNTIME_CFLAGS := -m64 -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 \
-std=c11 -ffreestanding -fno-builtin \
-fno-pic -fno-pie -fno-stack-protector -mno-red-zone -mcmodel=small \
-ffunction-sections -fdata-sections -Wall -Wextra \
$(TYPEPHP_OS_RUNTIME_DEFINES) $(TYPEPHP_OS_RUNTIME_INCLUDES)
TYPEPHP_OS_RUNTIME_CXXFLAGS := -m64 -O0 -std=c++17 -ffreestanding -fno-builtin \
TYPEPHP_OS_RUNTIME_CXXFLAGS := -m64 -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 \
-std=c++17 -ffreestanding -fno-builtin \
-fno-pic -fno-pie -fno-stack-protector -mno-red-zone -mcmodel=small \
-fno-rtti -fno-threadsafe-statics -ffunction-sections -fdata-sections \
-Wall -Wextra \
@ -69,6 +75,15 @@ TYPEPHP_OS_RUNTIME_ASMFLAGS := -m64 -ffreestanding -fno-pic -fno-pie \
-fno-stack-protector -mno-red-zone -mcmodel=small
ARFLAGS := rcs
# Keep symbol information on the host while installing only compact runtime
# ELF files into the FAT16 image. GDB can discover the adjacent .debug file
# through the GNU debug link retained in the stripped executable.
define STRIP_ELF
objcopy --only-keep-debug $(1) $(1).debug
strip --strip-all $(1)
objcopy --add-gnu-debuglink=$(1).debug $(1)
endef
.PHONY: all thirdparty thirdparty-smoke compiler-rt-builtins payload objects user-runtime nano-user disk run test clean
all: $(KERNEL) $(DISK)
@ -83,6 +98,7 @@ compiler-rt-builtins: $(COMPILER_RT_LIBRARY)
payload: thirdparty objects $(COMPILER_RT_LIBRARY)
cd ../.. && ./bin/tpc.php --nano examples/typephp-os/project.yml
$(call STRIP_ELF,$(PAYLOAD_ELF))
# Startup sources are built explicitly by Make. The 64-bit entry object is
# injected into tpc's final link through project.yml; the 32-bit Multiboot
@ -91,11 +107,11 @@ objects: $(BOOTSTRAP_OBJECT) $(KERNEL64_ENTRY_OBJECT)
user-runtime: $(TYPEPHP_OS_LIBRARY)
nano-user: $(TYPEPHP_OS_LIBRARY) $(NANO_USER_ELF)
nano-user: $(TYPEPHP_OS_LIBRARY) $(NANO_USER_ELF) $(TYPEPHP_FREE_ELF)
disk: $(DISK)
$(DISK): $(USER_SH_ELF) $(USER_COMMAND_ELFS) $(NANO_USER_ELF) | $(BUILD)
$(DISK): $(USER_SH_ELF) $(USER_COMMAND_ELFS) $(NANO_USER_ELF) $(TYPEPHP_FREE_ELF) | $(BUILD)
truncate -s 32M $@
mkfs.fat -F 16 -n TYPEPHPOS $@
mmd -i $@ ::/BIN
@ -103,6 +119,7 @@ $(DISK): $(USER_SH_ELF) $(USER_COMMAND_ELFS) $(NANO_USER_ELF) | $(BUILD)
mcopy -o -i $@ $(BUILD)/$$program.elf ::/BIN/$$program.elf; \
done
mcopy -o -i $@ $(NANO_USER_ELF) ::/BIN/TNHELLO.ELF
mcopy -o -i $@ $(TYPEPHP_FREE_ELF) ::/BIN/FREE.ELF
$(BUILD):
mkdir -p $@
@ -151,14 +168,21 @@ $(TYPEPHP_OS_LIBRARY): $(TYPEPHP_OS_LIBRARY_OBJECTS) | $(BUILD)
$(NANO_USER_ELF): $(NANO_USER_SOURCES) | thirdparty $(BUILD)
cd ../.. && ./bin/tpc.php --nano examples/typephp-os/user/nano/hello.yml
$(call STRIP_ELF,$@)
$(TYPEPHP_FREE_ELF): $(TYPEPHP_FREE_SOURCES) | thirdparty $(BUILD)
cd ../.. && ./bin/tpc.php --nano examples/typephp-os/user/nano/free.yml
$(call STRIP_ELF,$@)
$(USER_SH_ELF): $(OBJECT_DIR)/sh.o $(TYPEPHP_OS_LIBRARY) $(COMPILER_RT_LIBRARY) user/runtime/linker.ld Makefile | $(BUILD)
ld $(USER_LDFLAGS) --defsym USER_BASE=0x40000000 -o $@ \
$(OBJECT_DIR)/sh.o $(TYPEPHP_OS_LIBRARY) $(COMPILER_RT_LIBRARY)
$(call STRIP_ELF,$@)
$(USER_COMMAND_ELFS): $(BUILD)/%.elf: $(OBJECT_DIR)/%.o $(TYPEPHP_OS_LIBRARY) $(COMPILER_RT_LIBRARY) user/runtime/linker.ld Makefile | $(BUILD)
ld $(USER_LDFLAGS) --defsym USER_BASE=0x41000000 -o $@ \
$(OBJECT_DIR)/$*.o $(TYPEPHP_OS_LIBRARY) $(COMPILER_RT_LIBRARY)
$(call STRIP_ELF,$@)
$(KERNEL): payload
objcopy -O binary $(PAYLOAD_ELF) $(PAYLOAD_BIN)
@ -167,13 +191,14 @@ $(KERNEL): payload
$(PAYLOAD_BIN) $(PAYLOAD_OBJECT)
ld -m elf_i386 -T boot/linker.ld -o $@ \
$(BOOTSTRAP_OBJECT) $(PAYLOAD_OBJECT)
$(call STRIP_ELF,$@)
run: all
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
test: $(KERNEL) $(USER_SH_ELF) $(USER_COMMAND_ELFS) $(NANO_USER_ELF)
test: $(KERNEL) $(USER_SH_ELF) $(USER_COMMAND_ELFS) $(NANO_USER_ELF) $(TYPEPHP_FREE_ELF)
truncate -s 32M $(DISK)
mkfs.fat -F 16 -n TYPEPHPOS $(DISK)
mmd -i $(DISK) ::/BIN
@ -181,6 +206,7 @@ test: $(KERNEL) $(USER_SH_ELF) $(USER_COMMAND_ELFS) $(NANO_USER_ELF)
mcopy -o -i $(DISK) $(BUILD)/$$program.elf ::/BIN/$$program.elf; \
done
mcopy -o -i $(DISK) $(NANO_USER_ELF) ::/BIN/TNHELLO.ELF
mcopy -o -i $(DISK) $(TYPEPHP_FREE_ELF) ::/BIN/FREE.ELF
# An alias not known while linking the kernel verifies disk-based discovery.
mcopy -o -i $(DISK) $(BUILD)/echo.elf ::/BIN/hello.elf
mcopy -o -i $(DISK) tools/invalid-elf.txt ::/BIN/bad.elf

@ -87,6 +87,9 @@ The build produces these useful files:
linked with the shared TypePHP-OS runtime rather than a hosted libc.
- `build/tnhello.elf`: a full TypePHP + PHPX + PHP Nano Ring-3 executable
generated by tpc from `user/nano/hello.php`.
- `build/free.elf`: the tpc-generated TypePHP memory-reporting command.
- matching `build/*.elf.debug` files: host-side symbols removed from runtime
ELF files; keep these beside the binaries when debugging with GDB.
- `build/libtypephp-os.a`: the sole reusable userspace platform archive linked
by both C programs and every tpc-generated TypePHP program. Static archive
member selection keeps small C commands from pulling in the PHP Nano host.
@ -165,6 +168,9 @@ The QEMU smoke test currently verifies:
- a TypePHP prime calculation for 0–100;
- disk-backed ELF64 loading, Linux-style `argc/argv` startup, and libc-shaped
userspace calls, including a complete PHP Nano program generated by tpc;
- an independently compiled TypePHP `free` command reporting usable RAM,
kernel Zend-arena usage, physical-page usage, the kernel reservation, and
block-cache storage through a small private memory-information ABI;
- a separate x86-64 address space for the resident shell and every command,
4 KiB user mappings, a guarded 64 KiB stack, NX/WP enforcement, and ELF
`RX`/`RW` segment permissions;
@ -236,6 +242,16 @@ userspace compatibility rules are recorded in [`user/README.md`](user/README.md)
the long-term target is GCC/glibc-compatible userspace, and Linux syscall
numbers are reserved for genuinely compatible semantics.
The kernel, PHP Nano/PHPX sources, shared userspace runtime, bootstrap, and
small C commands are release-built with `-O2`. Because the host compiler may
enable glibc fortification by default, freestanding builds explicitly disable
`_FORTIFY_SOURCE`; TypePHP-OS supplies and audits its own libc/POSIX boundary.
Runtime ELF files are stripped before installation into FAT16, while adjacent
`.debug` files retain their host-side symbols for GDB. Hardware access, CPU
context entry, and the syscall trampoline remain C or assembly. Filesystem
policy, FAT16, startup checks, demonstrations, and the `free` command's
calculations and presentation are implemented in TypePHP.
The shell synchronously executes separate command ELF files from FAT16.
Entering `name` requests `/BIN/<name>.ELF`; the kernel validates the ELF header,
program table, file bounds, target address range, and entry point before

@ -90,6 +90,9 @@ behavior.
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.
A private memory-information snapshot now supports a tpc-built TypePHP
`free` command with kernel Zend-arena, page-pool, reservation, and block-cache
accounting. Release builds use `-O2` across the kernel and userspace.
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.
@ -108,3 +111,9 @@ behavior.
Later architectures may provide different bootstraps and host ABI adapters.
Generated TypePHP code and PHPX values remain 64-bit on every target.
Pure policy and data-processing work should continue moving to TypePHP. C is
kept for php-src reuse and narrow ABI/hardware adapters; assembly is kept only
where the CPU contract requires it. Suitable next migrations include shell
tokenization/dispatch and higher-level VFS/page-cache policy after the required
stream and console primitives are exposed to TypePHP userspace.

@ -185,6 +185,11 @@ namespace std {
const nothrow_t nothrow{};
[[noreturn]] void terminate() noexcept
{
typephp_os_panic("C++ termination");
}
[[noreturn]] void __throw_length_error(const char *)
{
typephp_os_panic("C++ container length error");

@ -35,6 +35,7 @@ typedef struct typephp_os_aligned_block {
enum { TYPEPHP_OS_ALIGNED_BLOCK_CAPACITY = 64 };
static uintptr_t arena_cursor;
static uintptr_t arena_begin;
static uintptr_t arena_end;
static typephp_os_aligned_block aligned_blocks[TYPEPHP_OS_ALIGNED_BLOCK_CAPACITY];
@ -95,14 +96,21 @@ void typephp_os_memory_init(void *address, size_t size)
aligned_blocks[index].allocated = 0;
}
if (size > UINTPTR_MAX - begin) {
arena_begin = 0;
arena_cursor = 0;
arena_end = 0;
return;
}
arena_begin = begin;
arena_cursor = begin;
arena_end = begin + size;
}
size_t typephp_os_memory_total(void)
{
return arena_end >= arena_begin ? (size_t) (arena_end - arena_begin) : 0;
}
size_t typephp_os_memory_available(void)
{
return arena_end >= arena_cursor ? (size_t) (arena_end - arena_cursor) : 0;
@ -594,6 +602,12 @@ int vprintf(const char *format, va_list args)
return written;
}
int vfprintf(void *stream, const char *format, va_list args)
{
(void) stream;
return vprintf(format, args);
}
int printf(const char *format, ...)
{
va_list args;
@ -653,7 +667,13 @@ __attribute__((noreturn)) void __longjmp_chk(void *environment, int value)
typephp_os_panic("zend_bailout");
}
__attribute__((noreturn)) void longjmp(jmp_buf environment, int value)
/* glibc's fortified setjmp header gives the longjmp C identifier an
* __longjmp_chk assembler name at -O2. Use a private C identifier so the
* freestanding runtime can intentionally provide both public ABI symbols. */
__attribute__((noreturn)) void typephp_os_longjmp(jmp_buf environment, int value)
__asm__("longjmp");
__attribute__((noreturn)) void typephp_os_longjmp(jmp_buf environment, int value)
{
(void) environment;
(void) value;
@ -687,11 +707,11 @@ size_t fwrite(const void *data, size_t size, size_t count, void *stream)
int fprintf(void *stream, const char *format, ...)
{
(void) stream;
/* Zend's allocator only uses this on fatal paths. Keep the implementation
* allocation-free; the complete formatter belongs to the standard layer. */
typephp_os_write(format, strlen(format));
return (int) strlen(format);
va_list args;
va_start(args, format);
const int result = vfprintf(stream, format, args);
va_end(args);
return result;
}
int __fprintf_chk(void *stream, int flag, const char *format, ...)

@ -19,6 +19,7 @@ extern "C" {
/* Install the contiguous physical-memory arena used by the libc/POSIX shim.
* The caller owns page-table setup and must keep the whole region mapped. */
void typephp_os_memory_init(void *address, size_t size);
size_t typephp_os_memory_total(void);
size_t typephp_os_memory_available(void);
/* C++17 global new/delete are supplied by TypePHP OS and allocate

@ -0,0 +1,24 @@
#ifndef TYPEPHP_OS_MEMORY_H
#define TYPEPHP_OS_MEMORY_H
#include <stdint.h>
typedef struct {
uint64_t total_bytes;
uint64_t kernel_reserved_bytes;
uint64_t zend_total_bytes;
uint64_t zend_free_bytes;
uint64_t page_total_bytes;
uint64_t page_free_bytes;
uint64_t block_cache_bytes;
} typephp_os_memory_info;
#ifdef __cplusplus
extern "C" {
#endif
int typephp_os_get_memory_info(typephp_os_memory_info *info);
#ifdef __cplusplus
}
#endif
#endif

@ -48,6 +48,7 @@ enum typephp_os_syscall_number {
TYPEPHP_SYS_FACCESSAT = 269,
TYPEPHP_SYS_SPAWN = 0x54500001,
TYPEPHP_SYS_RENAME = 0x54500003,
TYPEPHP_SYS_MEMORY_INFO = 0x54500004,
};
#endif

@ -260,6 +260,11 @@ unsigned long typephp_os_disk_cache_misses(void)
return (unsigned long) ata_cache_miss_count;
}
unsigned long typephp_os_disk_cache_bytes(void)
{
return (unsigned long) sizeof(ata_cache);
}
int typephp_os_disk_flush(void)
{
if (!ata_wait_not_busy()) {

@ -43,6 +43,7 @@ static uint64_t page_cursor;
static uint64_t page_begin;
static uint64_t page_end;
static uint64_t free_page_head;
static uint64_t total_pages;
static uint64_t available_pages;
static uint64_t align_up(uint64_t value, uint64_t alignment)
@ -61,6 +62,7 @@ void physical_memory_init(uint64_t multiboot_info_address)
page_begin = 0;
page_end = 0;
free_page_head = 0;
total_pages = 0;
available_pages = 0;
if ((info->flags & MULTIBOOT_INFO_MEMORY_MAP) == 0) {
@ -110,7 +112,8 @@ void physical_memory_init(uint64_t multiboot_info_address)
page_begin = page_cursor;
page_end = chunk_end & ~(PAGE_SIZE - 1);
if (page_end > page_cursor) {
available_pages = (page_end - page_cursor) / PAGE_SIZE;
total_pages = (page_end - page_cursor) / PAGE_SIZE;
available_pages = total_pages;
}
}
}
@ -151,6 +154,21 @@ uint64_t physical_page_available(void)
return available_pages;
}
uint64_t physical_page_total(void)
{
return total_pages;
}
uint64_t physical_memory_bytes(void)
{
return usable_memory_bytes;
}
uint64_t physical_kernel_reserved_bytes(void)
{
return KERNEL_RESERVED_END;
}
uint64_t physical_memory_megabytes(void)
{
return usable_memory_bytes >> 20;

@ -8,6 +8,7 @@
*/
#include "typephp_os_abi.h"
#include "typephp_os_memory.h"
#include "typephp_os_syscall.h"
#include "vm.h"
@ -217,6 +218,10 @@ extern void typephp_os_exception_13(void);
extern void typephp_os_exception_14(void);
extern int rename(const char *old_path, const char *new_path);
extern uint64_t physical_page_available(void);
extern uint64_t physical_page_total(void);
extern uint64_t physical_memory_bytes(void);
extern uint64_t physical_kernel_reserved_bytes(void);
extern unsigned long typephp_os_disk_cache_bytes(void);
static uint64_t gdt[7] __attribute__((aligned(16)));
static idt_gate idt[256] __attribute__((aligned(16)));
@ -844,6 +849,23 @@ static long syscall_ioctl(int fd, unsigned long request, void *argument)
}
}
static long syscall_memory_info(typephp_os_memory_info *result)
{
typephp_os_memory_info info;
if (!user_buffer(result, sizeof(*result))) {
return -EFAULT;
}
info.total_bytes = physical_memory_bytes();
info.kernel_reserved_bytes = physical_kernel_reserved_bytes();
info.zend_total_bytes = typephp_os_memory_total();
info.zend_free_bytes = typephp_os_memory_available();
info.page_total_bytes = physical_page_total() * UINT64_C(4096);
info.page_free_bytes = physical_page_available() * UINT64_C(4096);
info.block_cache_bytes = typephp_os_disk_cache_bytes();
memcpy(result, &info, sizeof(info));
return 0;
}
static unsigned int vm_protection(int protection)
{
unsigned int flags = 0;
@ -1331,6 +1353,8 @@ long typephp_os_syscall_dispatch(syscall_frame *frame)
return syscall_exit(frame, (long) frame->rdi);
case TYPEPHP_SYS_UNAME:
return syscall_uname((user_utsname *) frame->rdi);
case TYPEPHP_SYS_MEMORY_INFO:
return syscall_memory_info((typephp_os_memory_info *) frame->rdi);
default:
return -ENOSYS;
}

@ -28,6 +28,9 @@ defines:
- ASSEMBLER=1
- __BSD_VISIBLE=1
cxx-flags:
- -O2
- -U_FORTIFY_SOURCE
- -D_FORTIFY_SOURCE=0
- -ffreestanding
- -fno-builtin
- -fno-stack-protector
@ -39,6 +42,9 @@ cxx-flags:
- -fno-rtti
- -fno-threadsafe-statics
c-flags:
- -O2
- -U_FORTIFY_SOURCE
- -D_FORTIFY_SOURCE=0
- -ffreestanding
- -fno-builtin
- -fno-stack-protector

@ -21,7 +21,7 @@ if timeout 35 qemu-system-x86_64 \
-no-shutdown \
-device isa-debug-exit,iobase=0xf4,iosize=0x04 \
>"${log}" 2>&1 \
<<< $'\ndate\nuname\nuname -a\necho Hello TypePHP userspace\nhello Dynamically loaded\ntnhello alpha beta\nsystest\nbuiltins\nmissing\nbad\nls /BIN\ncat HELLO.TXT\ntouch /EXPAND/F62.TXT\nls /EXPAND\nwrite NOTE.TXT Hello from Ring 3\ncat NOTE.TXT\ntouch EMPTY.TXT\nmkdir TMP\nls\nrm NOTE.TXT\ncat NOTE.TXT\nrmdir TMP\ncd TMP\nmkdir WORK\ncd WORK\nwrite NOTE.TXT Nested directory write\ncat NOTE.TXT\nmkdir SUB\ncd SUB\nwrite DEEP.TXT Deep directory write\nmv DEEP.TXT MOVED.TXT\ncat MOVED.TXT\ncat DEEP.TXT\npwd\ncd ..\nrmdir SUB\nrm SUB/MOVED.TXT\nrmdir SUB\nls\nrm NOTE.TXT\ncd ..\nrmdir WORK\ncd WORK\nmemtest\nfault\nvmfault\nwrfault\ndate\npwd\ncd BIN\npwd\nls\ncd ..\ncd DOCS\npwd\nls\ncd ..\nls\n'; then
<<< $'\ndate\nuname\nuname -a\nfree\necho Hello TypePHP userspace\nhello Dynamically loaded\ntnhello alpha beta\nsystest\nbuiltins\nmissing\nbad\nls /BIN\ncat HELLO.TXT\ntouch /EXPAND/F62.TXT\nls /EXPAND\nwrite NOTE.TXT Hello from Ring 3\ncat NOTE.TXT\ntouch EMPTY.TXT\nmkdir TMP\nls\nrm NOTE.TXT\ncat NOTE.TXT\nrmdir TMP\ncd TMP\nmkdir WORK\ncd WORK\nwrite NOTE.TXT Nested directory write\ncat NOTE.TXT\nmkdir SUB\ncd SUB\nwrite DEEP.TXT Deep directory write\nmv DEEP.TXT MOVED.TXT\ncat MOVED.TXT\ncat DEEP.TXT\npwd\ncd ..\nrmdir SUB\nrm SUB/MOVED.TXT\nrmdir SUB\nls\nrm NOTE.TXT\ncd ..\nrmdir WORK\ncd WORK\nmemtest\nfault\nvmfault\nwrfault\ndate\npwd\ncd BIN\npwd\nls\ncd ..\ncd DOCS\npwd\nls\ncd ..\nls\n'; then
status=0
else
status=$?
@ -51,10 +51,15 @@ grep -q "Prime list: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
grep -q "Process 1: sh.elf (Ring 3)" "${log}"
grep -q "TypePHP-OS user shell" "${log}"
grep -q "Ring 3 confirmed" "${log}"
grep -q "Commands: ls, cd, pwd, date, uname, cat, echo, write, touch, mkdir, rm, rmdir, mv, memtest, systest, builtins, fault, vmfault, wrfault" "${log}"
grep -q "Commands: ls, cd, pwd, date, uname, free, cat, echo, write, touch, mkdir, rm, rmdir, mv, memtest, systest, builtins, fault, vmfault, wrfault" "${log}"
grep -Eq '^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} UTC' "${log}"
grep -Fq $'TypePHP-OS\r' "${log}"
grep -Fq $'TypePHP-OS typephp-os 0.1 TypePHP Nano user mode x86_64\r' "${log}"
grep -q '^TypePHP-OS memory' "${log}"
grep -q '^RAM: total=.*used=.*free=' "${log}"
grep -q '^Kernel Zend arena: total=.*used=.*free=' "${log}"
grep -q '^Physical page pool: total=.*used=.*free=' "${log}"
grep -q '^ATA block cache: ' "${log}"
grep -q '^Hello TypePHP userspace' "${log}"
grep -q '^Dynamically loaded' "${log}"
grep -Fq 'Hello World!string(6) "8.4.14"' "${log}"

@ -37,6 +37,12 @@ The resident shell and its standalone C command sources live under `cmd/`.
Reusable startup, syscall, POSIX/libc, C++ ABI, and math support lives under
`runtime/` and is emitted only as `build/libtypephp-os.a`.
`nano/free.php` is the first ordinary shell command implemented primarily in
TypePHP. Its NativeFunction bridge only retrieves the kernel memory snapshot;
unit conversion, pool accounting, and presentation remain TypePHP code. This
is the preferred split for future commands: TypePHP owns policy and application
logic, while C/C++ is limited to the syscall or PHPX boundary.
The current shared userspace runtime provides `syscall`, `read`, `write`, `openat`,
`open`, `close`, `lseek`, `getcwd`, `chdir`, `mkdir`, `rmdir`, `unlink`,
`rename`, `stat`, `lstat`, `fstat`, `access`, `fsync`, `fdatasync`, `truncate`,

@ -61,8 +61,8 @@ int main(int argc, char **argv)
(void) write(STDOUT_FILENO, "Ring 3 confirmed\n",
sizeof("Ring 3 confirmed\n") - 1);
(void) write(STDOUT_FILENO,
"Commands: ls, cd, pwd, date, uname, cat, echo, write, touch, mkdir, rm, rmdir, mv, memtest, systest, builtins, fault, vmfault, wrfault\n",
sizeof("Commands: ls, cd, pwd, date, uname, cat, echo, write, touch, mkdir, rm, rmdir, mv, memtest, systest, builtins, fault, vmfault, wrfault\n") - 1);
"Commands: ls, cd, pwd, date, uname, free, cat, echo, write, touch, mkdir, rm, rmdir, mv, memtest, systest, builtins, fault, vmfault, wrfault\n",
sizeof("Commands: ls, cd, pwd, date, uname, free, cat, echo, write, touch, mkdir, rm, rmdir, mv, memtest, systest, builtins, fault, vmfault, wrfault\n") - 1);
for (;;) {
char *arguments[9];
int argument_count = 0;

@ -49,6 +49,7 @@
* numbers or semantics. */
#define SYS_typephp_spawn TYPEPHP_SYS_SPAWN
#define SYS_typephp_rename TYPEPHP_SYS_RENAME
#define SYS_typephp_memory_info TYPEPHP_SYS_MEMORY_INFO
long syscall(long number, ...);

@ -0,0 +1,20 @@
#include <phpx.h>
#include <typephp_os_memory.h>
php::Int php_os_memory_value(php::Int field)
{
typephp_os_memory_info info;
if (typephp_os_get_memory_info(&info) != 0) {
return -1;
}
switch (field) {
case 0: return static_cast<php::Int>(info.total_bytes);
case 1: return static_cast<php::Int>(info.kernel_reserved_bytes);
case 2: return static_cast<php::Int>(info.zend_total_bytes);
case 3: return static_cast<php::Int>(info.zend_free_bytes);
case 4: return static_cast<php::Int>(info.page_total_bytes);
case 5: return static_cast<php::Int>(info.page_free_bytes);
case 6: return static_cast<php::Int>(info.block_cache_bytes);
default: return -1;
}
}

@ -0,0 +1,49 @@
<?php
function writeMiB(int $bytes): void
{
$tenths = (int) (($bytes * 10) / 1048576);
$fraction = $tenths % 10;
$whole = (int) (($tenths - $fraction) / 10);
echo $whole, '.', $fraction, ' MiB';
}
function writePool(string $name, int $total, int $free): void
{
$used = $total - $free;
echo $name, ': total=';
writeMiB($total);
echo ', used=';
writeMiB($used);
echo ', free=';
writeMiB($free);
echo "\n";
}
function main(int $argc, array $argv): void
{
$total = os_memory_value(0);
$reserved = os_memory_value(1);
$zendTotal = os_memory_value(2);
$zendFree = os_memory_value(3);
$pageTotal = os_memory_value(4);
$pageFree = os_memory_value(5);
$cache = os_memory_value(6);
if ($total < 0 || $reserved < 0 || $zendTotal < 0 || $zendFree < 0
|| $pageTotal < 0 || $pageFree < 0 || $cache < 0) {
echo "free: memory information unavailable\n";
return;
}
$available = $zendFree + $pageFree;
echo "TypePHP-OS memory\n";
writePool('RAM', $total, $available);
writePool('Kernel Zend arena', $zendTotal, $zendFree);
writePool('Physical page pool', $pageTotal, $pageFree);
echo 'Kernel reservation: ';
writeMiB($reserved);
echo "\nATA block cache: ";
writeMiB($cache);
echo "\nSwap: 0.0 MiB\n";
echo "Note: page-pool usage includes this TypePHP command and its Nano runtime.\n";
}

@ -0,0 +1,67 @@
name: typephp_os_user_free
mode: bin
sources:
- free.php
- memory.stub.php
- free.cc
build-dir: ../../build/generated-user-free
output: ../../build/free.elf
cxx-std: c++17
include-paths:
- ../../kernel/core/abi
- ../../thirdparty/openlibm/include
- ../../thirdparty/openlibm/src
- ../../thirdparty/openlibm/amd64
defines:
- TYPEPHP_NO_MAIN=1
- PHPX_NO_EXCEPTION=1
- PHPX_NO_RTTI=1
- PHP_NANO_NO_LIBC=1
- HAVE_SYS_UTSNAME_H=1
- __NO_CTYPE=1
- ZEND_MM_ERROR=0
- ZEND_MM_CUSTOM=0
- ASSEMBLER=1
- __BSD_VISIBLE=1
cxx-flags:
- -O2
- -U_FORTIFY_SOURCE
- -D_FORTIFY_SOURCE=0
- -ffreestanding
- -fno-builtin
- -fno-stack-protector
- -fno-pic
- -fno-pie
- -m64
- -mno-red-zone
- -mcmodel=small
- -fno-rtti
- -fno-threadsafe-statics
c-flags:
- -O2
- -U_FORTIFY_SOURCE
- -D_FORTIFY_SOURCE=0
- -ffreestanding
- -fno-builtin
- -fno-stack-protector
- -fno-pic
- -fno-pie
- -m64
- -mno-red-zone
- -mcmodel=small
asm-flags:
- -m64
- -mno-red-zone
- -mcmodel=small
ld-flags:
- -nostdlib
- -no-pie
- -Wl,-m,elf_x86_64
- -Wl,--build-id=none
- -Wl,-T,examples/typephp-os/user/runtime/linker.ld
- -Wl,--defsym,USER_BASE=0x41000000
link-paths:
- ../../build
link-libs:
- typephp-os
- compiler-rt-builtins

@ -22,6 +22,9 @@ defines:
- ASSEMBLER=1
- __BSD_VISIBLE=1
cxx-flags:
- -O2
- -U_FORTIFY_SOURCE
- -D_FORTIFY_SOURCE=0
- -ffreestanding
- -fno-builtin
- -fno-stack-protector
@ -33,6 +36,9 @@ cxx-flags:
- -fno-rtti
- -fno-threadsafe-statics
c-flags:
- -O2
- -U_FORTIFY_SOURCE
- -D_FORTIFY_SOURCE=0
- -ffreestanding
- -fno-builtin
- -fno-stack-protector

@ -0,0 +1,5 @@
<?php
/** Read one field from the TypePHP-OS kernel memory snapshot. */
#[NativeFunction]
function os_memory_value(int $field): int { return -1; }

@ -2,6 +2,8 @@
#include <sys/ioctl.h>
#include <sys/syscall.h>
long syscall(long number, ...);
int ioctl(int fd, unsigned long request, ...)
{
void *argument = 0;

@ -0,0 +1,9 @@
#include <typephp_os_syscall.h>
#include <typephp_os_memory.h>
long syscall(long number, ...);
int typephp_os_get_memory_info(typephp_os_memory_info *info)
{
return (int) syscall(TYPEPHP_SYS_MEMORY_INFO, info);
}
Loading…
Cancel
Save