Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/kernel-unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,19 @@ jobs:
if: steps.libcxx-cache.outputs.cache-hit != 'true'
run: make libcxx

- name: Cache compiler-rt builtins
uses: actions/cache@v4
id: compiler-rt-cache
with:
path: |
userland/sysroot/x86_64/lib/libclang_rt.builtins-x86_64.a
userland/sysroot/aarch64/lib/libclang_rt.builtins-aarch64.a
key: compiler-rt-builtins-18.1.8

- name: Build compiler-rt builtins
if: steps.compiler-rt-cache.outputs.cache-hit != 'true'
run: make compiler-rt

- name: Build kernel
run: |
make kernel ARCH=${{ matrix.arch }} \
Expand Down Expand Up @@ -191,6 +204,19 @@ jobs:
if: steps.libcxx-cache.outputs.cache-hit != 'true'
run: make libcxx

- name: Cache compiler-rt builtins
uses: actions/cache@v4
id: compiler-rt-cache
with:
path: |
userland/sysroot/x86_64/lib/libclang_rt.builtins-x86_64.a
userland/sysroot/aarch64/lib/libclang_rt.builtins-aarch64.a
key: compiler-rt-builtins-18.1.8

- name: Build compiler-rt builtins
if: steps.compiler-rt-cache.outputs.cache-hit != 'true'
run: make compiler-rt

- name: Run unit tests
run: make test ARCH=${{ matrix.arch }} 2>&1 | tee test-log-${{ matrix.arch }}.txt

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ userland/musl-*
userland/llvm-project-*
userland/build/
initrd/bin/*
initrd/usr/
!initrd/bin/.gitkeep

# OS files
Expand Down
114 changes: 100 additions & 14 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,80 @@ libcxx:
@echo ""
@echo "libc++ $(LLVM_VERSION) ready for both architectures."

# Build the compiler-rt builtins runtime for both supported architectures and
# install it into the per-arch sysroot as a flat archive
# (libclang_rt.builtins-<arch>.a alongside libc.a, libstlx.a, etc.). This frees
# downstream apps (notably the static CPython link) from depending on the host
# toolchain shipping cross-arch builtins, which Ubuntu's libclang-rt-dev does
# not provide for aarch64.
compiler-rt:
@echo "Building compiler-rt builtins $(LLVM_VERSION) for x86_64 and aarch64..."
@test -f userland/sysroot/x86_64/lib/libc.a || \
(echo "ERROR: musl sysroot not found. Run 'make musl' first." && exit 1)
@test -f userland/sysroot/aarch64/lib/libc.a || \
(echo "ERROR: musl sysroot not found. Run 'make musl' first." && exit 1)
@mkdir -p userland
@test -f $(LLVM_TARBALL) || \
(echo "Downloading LLVM $(LLVM_VERSION) source (~130MB)..." && \
curl -L -o $(LLVM_TARBALL) $(LLVM_URL))
@test -d $(LLVM_DIR) || \
(echo "Extracting..." && \
cd userland && tar xf llvm-project-$(LLVM_VERSION).src.tar.xz)
@echo ""
@echo "Building compiler-rt builtins for x86_64..."
@mkdir -p $(LLVM_DIR)/build-compiler-rt-x86_64
cd $(LLVM_DIR)/build-compiler-rt-x86_64 && cmake -G "Unix Makefiles" ../compiler-rt \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_ASM_COMPILER=clang \
-DCMAKE_C_COMPILER_TARGET=x86_64-linux-musl \
-DCMAKE_ASM_COMPILER_TARGET=x86_64-linux-musl \
-DCMAKE_SYSROOT=$(abspath userland/sysroot/x86_64) \
-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \
-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
-DCOMPILER_RT_BUILD_BUILTINS=ON \
-DCOMPILER_RT_BUILD_SANITIZERS=OFF \
-DCOMPILER_RT_BUILD_XRAY=OFF \
-DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
-DCOMPILER_RT_BUILD_PROFILE=OFF \
-DCOMPILER_RT_BUILD_MEMPROF=OFF \
-DCOMPILER_RT_BUILD_ORC=OFF \
-DCOMPILER_RT_INCLUDE_TESTS=OFF \
'-DCMAKE_C_FLAGS=--target=x86_64-linux-musl --sysroot=$(abspath userland/sysroot/x86_64) -nostdlibinc -isystem $(abspath userland/sysroot/x86_64)/include' \
'-DCMAKE_ASM_FLAGS=--target=x86_64-linux-musl --sysroot=$(abspath userland/sysroot/x86_64) -nostdlibinc -isystem $(abspath userland/sysroot/x86_64)/include' \
> /dev/null
$(MAKE) -C $(LLVM_DIR)/build-compiler-rt-x86_64 -j$$(nproc) builtins > /dev/null
@cp "$$(find $(LLVM_DIR)/build-compiler-rt-x86_64 -name 'libclang_rt.builtins*.a' -print -quit)" \
userland/sysroot/x86_64/lib/libclang_rt.builtins-x86_64.a
@echo "compiler-rt builtins x86_64 installed to userland/sysroot/x86_64/lib/"
@echo ""
@echo "Building compiler-rt builtins for aarch64..."
@mkdir -p $(LLVM_DIR)/build-compiler-rt-aarch64
cd $(LLVM_DIR)/build-compiler-rt-aarch64 && cmake -G "Unix Makefiles" ../compiler-rt \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_ASM_COMPILER=clang \
-DCMAKE_C_COMPILER_TARGET=aarch64-linux-musl \
-DCMAKE_ASM_COMPILER_TARGET=aarch64-linux-musl \
-DCMAKE_SYSROOT=$(abspath userland/sysroot/aarch64) \
-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \
-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
-DCOMPILER_RT_BUILD_BUILTINS=ON \
-DCOMPILER_RT_BUILD_SANITIZERS=OFF \
-DCOMPILER_RT_BUILD_XRAY=OFF \
-DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
-DCOMPILER_RT_BUILD_PROFILE=OFF \
-DCOMPILER_RT_BUILD_MEMPROF=OFF \
-DCOMPILER_RT_BUILD_ORC=OFF \
-DCOMPILER_RT_INCLUDE_TESTS=OFF \
'-DCMAKE_C_FLAGS=--target=aarch64-linux-musl --sysroot=$(abspath userland/sysroot/aarch64) -nostdlibinc -isystem $(abspath userland/sysroot/aarch64)/include' \
'-DCMAKE_ASM_FLAGS=--target=aarch64-linux-musl --sysroot=$(abspath userland/sysroot/aarch64) -nostdlibinc -isystem $(abspath userland/sysroot/aarch64)/include' \
> /dev/null
$(MAKE) -C $(LLVM_DIR)/build-compiler-rt-aarch64 -j$$(nproc) builtins > /dev/null
@cp "$$(find $(LLVM_DIR)/build-compiler-rt-aarch64 -name 'libclang_rt.builtins*.a' -print -quit)" \
userland/sysroot/aarch64/lib/libclang_rt.builtins-aarch64.a
@echo "compiler-rt builtins aarch64 installed to userland/sysroot/aarch64/lib/"
@echo ""
@echo "compiler-rt builtins $(LLVM_VERSION) ready for both architectures."

limine:
@echo "Downloading Limine ($(LIMINE_BRANCH))..."
@mkdir -p $(BOOT_DIR)
Expand Down Expand Up @@ -728,24 +802,34 @@ toolchain-check:
@printf "%-24s" "libc++ (aarch64):" && \
(test -f userland/sysroot/aarch64/lib/libc++.a && echo "OK" || echo "NOT FOUND - run 'make libcxx'")
@printf "%-24s" "builtins (x86_64):" && \
(BRT=$$(clang --target=x86_64-linux-musl --rtlib=compiler-rt -print-libgcc-file-name 2>/dev/null); \
if [ -f "$$BRT" ]; then \
echo "$$BRT"; \
elif which x86_64-linux-gnu-gcc > /dev/null 2>&1; then \
BGCC=$$(x86_64-linux-gnu-gcc -print-libgcc-file-name 2>/dev/null); \
[ -f "$$BGCC" ] && echo "$$BGCC" || echo "NOT FOUND"; \
(SR=userland/sysroot/x86_64/lib/libclang_rt.builtins-x86_64.a; \
if [ -f "$$SR" ]; then \
echo "$$SR"; \
else \
echo "NOT FOUND"; \
BRT=$$(clang --target=x86_64-linux-musl --rtlib=compiler-rt -print-libgcc-file-name 2>/dev/null); \
if [ -f "$$BRT" ]; then \
echo "$$BRT"; \
elif which x86_64-linux-gnu-gcc > /dev/null 2>&1; then \
BGCC=$$(x86_64-linux-gnu-gcc -print-libgcc-file-name 2>/dev/null); \
[ -f "$$BGCC" ] && echo "$$BGCC" || echo "NOT FOUND - run 'make compiler-rt'"; \
else \
echo "NOT FOUND - run 'make compiler-rt'"; \
fi; \
fi)
@printf "%-24s" "builtins (aarch64):" && \
(BRT=$$(clang --target=aarch64-linux-musl --rtlib=compiler-rt -print-libgcc-file-name 2>/dev/null); \
if [ -f "$$BRT" ]; then \
echo "$$BRT"; \
elif which aarch64-linux-gnu-gcc > /dev/null 2>&1; then \
BGCC=$$(aarch64-linux-gnu-gcc -print-libgcc-file-name 2>/dev/null); \
[ -f "$$BGCC" ] && echo "$$BGCC" || echo "NOT FOUND"; \
(SR=userland/sysroot/aarch64/lib/libclang_rt.builtins-aarch64.a; \
if [ -f "$$SR" ]; then \
echo "$$SR"; \
else \
echo "NOT FOUND"; \
BRT=$$(clang --target=aarch64-linux-musl --rtlib=compiler-rt -print-libgcc-file-name 2>/dev/null); \
if [ -f "$$BRT" ]; then \
echo "$$BRT"; \
elif which aarch64-linux-gnu-gcc > /dev/null 2>&1; then \
BGCC=$$(aarch64-linux-gnu-gcc -print-libgcc-file-name 2>/dev/null); \
[ -f "$$BGCC" ] && echo "$$BGCC" || echo "NOT FOUND - run 'make compiler-rt'"; \
else \
echo "NOT FOUND - run 'make compiler-rt'"; \
fi; \
fi)
@echo ""
@echo "If anything is NOT FOUND, run 'make deps', 'make limine', 'make musl', 'make libcxx', and/or 'make rpi4-firmware'"
Expand All @@ -762,6 +846,7 @@ help:
@echo " make limine Download Limine bootloader"
@echo " make musl Build musl libc for both architectures"
@echo " make libcxx Build libc++ for C++ userland support"
@echo " make compiler-rt Build compiler-rt builtins (required for cross-arch static linking)"
@echo " make rpi4-firmware Download RPi4 UEFI firmware"
@echo " make doom-wad Download DOOM1.WAD shareware"
@echo " make toolchain-check Verify tools are installed"
Expand Down Expand Up @@ -796,6 +881,7 @@ help:
@echo " 2. make limine"
@echo " 3. make musl"
@echo " 4. make libcxx"
@echo " 5. make compiler-rt"
@echo ""
@echo "Examples:"
@echo " make kernel ARCH=x86_64"
Expand Down
1 change: 1 addition & 0 deletions kernel/fs/fstypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ constexpr uint32_t O_EXCL = 0x80;
constexpr uint32_t O_TRUNC = 0x200;
constexpr uint32_t O_APPEND = 0x400;
constexpr uint32_t O_NONBLOCK = 0x800;
constexpr uint32_t O_CLOEXEC = 0x80000;

constexpr uint32_t ACCESS_MODE_MASK = 0x3;

Expand Down
2 changes: 1 addition & 1 deletion kernel/mm/vma.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ constexpr uint32_t VMA_FLAG_DEVICE = (1u << 5);

constexpr uintptr_t MMAP_BASE_DEFAULT = 0x00000080000000ULL;
constexpr uintptr_t USER_STACK_TOP = 0x00007FFFFFF00000ULL;
constexpr size_t USER_STACK_PAGES = 8; // 32 KiB
constexpr size_t USER_STACK_PAGES = 128; // 512 KiB
constexpr size_t USER_STACK_GUARD_PAGES = 1;

struct vma {
Expand Down
83 changes: 81 additions & 2 deletions kernel/pty/pty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,40 @@
#include "common/ring_buffer.h"
#include "fs/fstypes.h"
#include "mm/heap.h"
#include "mm/uaccess.h"
#include "dynpriv/dynpriv.h"
#include "sync/poll.h"
#include "sync/wait_queue.h"
#include "terminal/terminal.h"

namespace pty {

constexpr uint32_t TCGETS = 0x5401;
constexpr uint32_t TCSETS = 0x5402;
constexpr uint32_t TCSETSW = 0x5403;
constexpr uint32_t TCSETSF = 0x5404;
constexpr uint32_t TIOCGWINSZ = 0x5413;
constexpr uint32_t TIOCSWINSZ = 0x5414;

constexpr uint32_t LINUX_ECHO = 0x0008;
constexpr uint32_t LINUX_ICANON = 0x0002;

struct linux_termios {
uint32_t c_iflag;
uint32_t c_oflag;
uint32_t c_cflag;
uint32_t c_lflag;
uint8_t c_line;
uint8_t c_cc[19];
};

struct linux_winsize {
uint16_t ws_row;
uint16_t ws_col;
uint16_t ws_xpixel;
uint16_t ws_ypixel;
};

__PRIVILEGED_BSS static uint32_t g_next_pty_id;

__PRIVILEGED_CODE void pty_channel::ref_destroy(pty_channel* self) {
Expand Down Expand Up @@ -179,15 +207,66 @@ static void pty_slave_close(resource::resource_object* obj) {
obj->impl = nullptr;
}

static int32_t do_tcgets(pty_channel* chan, uint64_t arg) {
linux_termios t = {};

if (chan->m_ld.mode != terminal::LD_MODE_RAW) {
t.c_lflag = LINUX_ICANON | LINUX_ECHO;
}

int32_t rc = mm::uaccess::copy_to_user(
reinterpret_cast<void*>(arg), &t, sizeof(t));

return (rc == mm::uaccess::OK) ? resource::OK : resource::ERR_INVAL;
}

static int32_t do_tcsets(pty_channel* chan, uint64_t arg) {
linux_termios t = {};
int32_t rc = mm::uaccess::copy_from_user(
&t, reinterpret_cast<const void*>(arg), sizeof(t));

if (rc != mm::uaccess::OK) {
return resource::ERR_INVAL;
}

uint32_t mode = (t.c_lflag & LINUX_ICANON)
? terminal::STLX_TCSETS_COOKED
: terminal::STLX_TCSETS_RAW;

terminal::ld_set_mode(&chan->m_ld, mode);
return resource::OK;
}

static int32_t do_tiocgwinsz(uint64_t arg) {
linux_winsize w = { 24, 80, 0, 0 };
int32_t rc = mm::uaccess::copy_to_user(
reinterpret_cast<void*>(arg), &w, sizeof(w));

return (rc == mm::uaccess::OK) ? resource::OK : resource::ERR_INVAL;
}

static int32_t pty_termios_ioctl(pty_channel* chan, uint32_t cmd, uint64_t arg) {
switch (cmd) {
case TCGETS: return do_tcgets(chan, arg);
case TCSETS:
case TCSETSW:
case TCSETSF: return do_tcsets(chan, arg);
case TIOCGWINSZ: return do_tiocgwinsz(arg);
case TIOCSWINSZ: return resource::OK;
case terminal::STLX_TCSETS_RAW:
case terminal::STLX_TCSETS_COOKED: return terminal::ld_set_mode(&chan->m_ld, cmd);
default: return resource::ERR_INVAL;
}
}

static int32_t pty_slave_ioctl(
resource::resource_object* obj, uint32_t cmd, uint64_t arg
) {
(void)arg;
if (!obj || !obj->impl) {
return resource::ERR_INVAL;
}
auto* ep = static_cast<pty_endpoint*>(obj->impl);
return terminal::ld_set_mode(&ep->channel->m_ld, cmd);
return pty_termios_ioctl(ep->channel.ptr(), cmd, arg);
Comment thread
FlareCoding marked this conversation as resolved.
}

static uint32_t pty_master_poll(
Expand Down
3 changes: 3 additions & 0 deletions kernel/resource/handle_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ struct resource_object;

constexpr uint32_t MAX_TASK_HANDLES = 128;

// Private high bit in handle_entry::flags reserved for FD_CLOEXEC state
constexpr uint32_t RESOURCE_HANDLE_CLOEXEC = 0x80000000;

struct handle_entry {
bool used;
uint16_t generation;
Expand Down
7 changes: 7 additions & 0 deletions kernel/resource/resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ __PRIVILEGED_CODE int32_t open(
return (rc == HANDLE_ERR_NOSPC) ? ERR_TABLEFULL : ERR_IO;
}

if (flags & fs::O_CLOEXEC) {
uint32_t handle_flags = 0;
get_handle_flags(&owner->handles, *out_handle, &handle_flags);
set_handle_flags(&owner->handles, *out_handle,
handle_flags | RESOURCE_HANDLE_CLOEXEC);
}

// Table now owns one reference.
resource_release(obj);
return OK;
Expand Down
Loading
Loading