diff --git a/.gitignore b/.gitignore index 19037fc..7d63841 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ build/ *.tmp .DS_Store .system_generated/ +.config diff --git a/Makefile b/Makefile index 8cb373a..44576b9 100644 --- a/Makefile +++ b/Makefile @@ -1,43 +1,97 @@ # ============================================================================= -# SUB-OS Master Makefile - Modular Monolithic Linux-Like Kernel Build System +# SUB-OS Master Multi-Architecture Linux-Style Makefile +# Supports: x86_64, aarch64, armv8i +# Features: Linux Kconfig TUI (make menuconfig), multi-arch cross-compilation # ============================================================================= -# Cross Compiler & Toolchain Detection -CROSS_COMPILE ?= x86_64-elf- +-include .config -CC = $(CROSS_COMPILE)gcc -LD = $(CROSS_COMPILE)ld -OBJCOPY = $(CROSS_COMPILE)objcopy -ASM = nasm +# Architecture Selection (Default: x86_64) +ifdef CONFIG_ARCH + ARCH ?= $(CONFIG_ARCH) +else + ARCH ?= x86_64 +endif -# Build Directories BUILD_DIR = build BOOT_DIR = boot -# Target Architecture Flags -CFLAGS = -ffreestanding \ - -fno-pie \ - -fno-pic \ - -mno-red-zone \ - -mno-mmx \ - -mno-sse \ - -mno-sse2 \ - -mcmodel=kernel \ - -Wall \ - -Wextra \ - -Wno-unused-function \ - -Wno-unused-parameter \ - -O2 \ - -Iinclude +# ----------------------------------------------------------------------------- +# Toolchain & Architecture Flags +# ----------------------------------------------------------------------------- +ifeq ($(ARCH), x86_64) + CROSS_COMPILE ?= x86_64-elf- + CC = $(CROSS_COMPILE)gcc + LD = $(CROSS_COMPILE)ld + OBJCOPY = $(CROSS_COMPILE)objcopy + ASM = nasm -ASMFLAGS_ELF = -f elf64 -ASMFLAGS_BOOT = -f bin -I$(BOOT_DIR)/ + CFLAGS = -ffreestanding \ + -fno-pie \ + -fno-pic \ + -mno-red-zone \ + -mno-mmx \ + -mno-sse \ + -mno-sse2 \ + -mcmodel=kernel \ + -Wall \ + -Wextra \ + -Wno-unused-function \ + -Wno-unused-parameter \ + -O2 \ + -Iinclude \ + -D__x86_64__ -LDFLAGS = -nostdlib -no-pie -T linker.ld + ASMFLAGS_ELF = -f elf64 + ASMFLAGS_BOOT = -f bin -I$(BOOT_DIR)/ + LDFLAGS = -nostdlib -no-pie -T linker.ld -# Source Files Discovery -ARCH_C_SRCS = $(shell find arch -name '*.c' 2>/dev/null) -ARCH_ASM_SRCS = $(shell find arch -name '*.asm' 2>/dev/null) + # Source files for x86_64 + ARCH_C_SRCS = $(shell find arch/x86_64 -name '*.c' 2>/dev/null) + ARCH_ASM_SRCS = $(shell find arch/x86_64 -name '*.asm' 2>/dev/null) + ENTRY_OBJ = $(BUILD_DIR)/arch/x86_64/boot/entry.o + IMAGE = SUB-OS.img + TARGET = $(IMAGE) + QEMU_CMD = qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \ + -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \ + -device e1000,netdev=net0 -serial stdio + +else ifneq ($(filter $(ARCH), aarch64 armv8 armv8i),) + CROSS_COMPILE ?= aarch64-linux-gnu- + CC = $(CROSS_COMPILE)gcc + LD = $(CROSS_COMPILE)ld + OBJCOPY = $(CROSS_COMPILE)objcopy + AS = $(CROSS_COMPILE)as + + CFLAGS = -ffreestanding \ + -fno-pie \ + -fno-pic \ + -Wall \ + -Wextra \ + -Wno-unused-function \ + -Wno-unused-parameter \ + -mno-outline-atomics \ + -O2 \ + -Iinclude \ + -D__aarch64__ \ + -march=armv8-a + + LDFLAGS = -nostdlib -no-pie -T arch/aarch64/linker.ld + + # Source files for AArch64 + ARCH_C_SRCS = $(shell find arch/aarch64 -name '*.c' 2>/dev/null) + ARCH_S_SRCS = $(shell find arch/aarch64 -name '*.S' 2>/dev/null) + ENTRY_OBJ = $(BUILD_DIR)/arch/aarch64/boot/entry.o + TARGET = $(BUILD_DIR)/kernel.elf + QEMU_CMD = qemu-system-aarch64 -M virt -cpu cortex-a57 -m 128M -nographic -kernel $(BUILD_DIR)/kernel.elf + +else + $(error Unsupported Architecture '$(ARCH)'. Supported: x86_64, aarch64, armv8i) +endif + +# ----------------------------------------------------------------------------- +# Common Kernel Subsystems +# ----------------------------------------------------------------------------- KERNEL_C_SRCS = $(shell find kernel -name '*.c' 2>/dev/null) MM_C_SRCS = $(shell find mm -name '*.c' 2>/dev/null) DRIVERS_C_SRCS = $(shell find drivers -name '*.c' 2>/dev/null) @@ -52,7 +106,6 @@ IO_URING_C_SRCS = $(shell find io_uring -name '*.c' 2>/dev/null) SECURITY_C_SRCS = $(shell find security -name '*.c' 2>/dev/null) USR_C_SRCS = $(shell find usr -name '*.c' 2>/dev/null) VIRT_C_SRCS = $(shell find virt -name '*.c' 2>/dev/null) - BLOCK_C_SRCS = $(shell find block -name '*.c' 2>/dev/null) IPC_C_SRCS = $(shell find ipc -name '*.c' 2>/dev/null) SOUND_C_SRCS = $(shell find sound -name '*.c' 2>/dev/null) @@ -63,81 +116,107 @@ ALL_C_SRCS = $(ARCH_C_SRCS) $(KERNEL_C_SRCS) $(MM_C_SRCS) $(DRIVERS_C_SRCS) \ $(USR_C_SRCS) $(VIRT_C_SRCS) $(BLOCK_C_SRCS) $(IPC_C_SRCS) $(SOUND_C_SRCS) # Object Files Mapping -C_OBJS = $(patsubst %.c, $(BUILD_DIR)/%.o, $(ALL_C_SRCS)) -ASM_OBJS = $(patsubst %.asm, $(BUILD_DIR)/%.o, $(ARCH_ASM_SRCS)) +C_OBJS = $(patsubst %.c, $(BUILD_DIR)/%.o, $(ALL_C_SRCS)) -# Put entry.o first in linker sequence -ENTRY_OBJ = $(BUILD_DIR)/arch/x86_64/boot/entry.o -OTHER_OBJS = $(filter-out $(ENTRY_OBJ), $(ASM_OBJS) $(C_OBJS)) +ifeq ($(ARCH), x86_64) + ASM_OBJS = $(patsubst %.asm, $(BUILD_DIR)/%.o, $(ARCH_ASM_SRCS)) + OTHER_OBJS = $(filter-out $(ENTRY_OBJ), $(ASM_OBJS) $(C_OBJS)) +else + S_OBJS = $(patsubst %.S, $(BUILD_DIR)/%.o, $(ARCH_S_SRCS)) + OTHER_OBJS = $(filter-out $(ENTRY_OBJ), $(S_OBJS) $(C_OBJS)) +endif -IMAGE = SUB-OS.img +.PHONY: all clean run debug info menuconfig config defconfig x86_64_defconfig aarch64_defconfig armv8_defconfig armv8i_defconfig qemu -.PHONY: all clean run debug info +all: $(TARGET) -all: $(IMAGE) +# ----------------------------------------------------------------------------- +# Configuration Targets (Linux Kconfig TUI) +# ----------------------------------------------------------------------------- +menuconfig config: + @python3 scripts/kconfig/menuconfig.py -# Assemble 16-bit Bootloader Stage 1 -$(BUILD_DIR)/boot/boot.bin: $(BOOT_DIR)/boot.asm | $(BUILD_DIR)/boot - $(ASM) $(ASMFLAGS_BOOT) $< -o $@ +defconfig: + @python3 scripts/kconfig/menuconfig.py --defconfig $(ARCH) -# Assemble 16/32/64-bit Bootloader Stage 2 -$(BUILD_DIR)/boot/stage2.bin: $(BOOT_DIR)/stage2.asm $(BOOT_DIR)/gdt.asm | $(BUILD_DIR)/boot - $(ASM) $(ASMFLAGS_BOOT) $< -o $@ +x86_64_defconfig: + @python3 scripts/kconfig/menuconfig.py --x86_64 -# Compile 64-bit C source files +aarch64_defconfig: + @python3 scripts/kconfig/menuconfig.py --aarch64 + +armv8_defconfig armv8i_defconfig: + @python3 scripts/kconfig/menuconfig.py --armv8i + +# ----------------------------------------------------------------------------- +# Compilation Rules +# ----------------------------------------------------------------------------- +# C Source Files $(BUILD_DIR)/%.o: %.c @mkdir -p $(dir $@) $(CC) $(CFLAGS) -c $< -o $@ -# Assemble 64-bit ASM source files +# x86_64 NASM Assembly Files $(BUILD_DIR)/%.o: %.asm @mkdir -p $(dir $@) $(ASM) $(ASMFLAGS_ELF) $< -o $@ -# Link Kernel ELF -$(BUILD_DIR)/kernel.elf: $(ENTRY_OBJ) $(OTHER_OBJS) linker.ld +# AArch64 GNU Assembly Files (.S) +$(BUILD_DIR)/%.o: %.S + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c $< -o $@ + +# ----------------------------------------------------------------------------- +# x86_64 Bootloader & Image Rules +# ----------------------------------------------------------------------------- +$(BUILD_DIR)/boot/boot.bin: $(BOOT_DIR)/boot.asm | $(BUILD_DIR)/boot + $(ASM) $(ASMFLAGS_BOOT) $< -o $@ + +$(BUILD_DIR)/boot/stage2.bin: $(BOOT_DIR)/stage2.asm $(BOOT_DIR)/gdt.asm | $(BUILD_DIR)/boot + $(ASM) $(ASMFLAGS_BOOT) $< -o $@ + +$(BUILD_DIR)/boot: + mkdir -p $(BUILD_DIR)/boot + +$(BUILD_DIR)/kernel.elf: $(ENTRY_OBJ) $(OTHER_OBJS) $(LD) $(LDFLAGS) -o $@ $(ENTRY_OBJ) $(OTHER_OBJS) + @echo "=== [Kernel ELF Linked: $@ (Architecture: $(ARCH))] ===" -# Convert ELF to Flat Binary $(BUILD_DIR)/kernel.bin: $(BUILD_DIR)/kernel.elf $(OBJCOPY) -O binary $< $@ -# Create Bootable Floppy / HDD Raw Disk Image $(IMAGE): $(BUILD_DIR)/boot/boot.bin $(BUILD_DIR)/boot/stage2.bin $(BUILD_DIR)/kernel.bin dd if=/dev/zero of=$@ bs=512 count=2880 status=none dd if=$(BUILD_DIR)/boot/boot.bin of=$@ bs=512 conv=notrunc status=none dd if=$(BUILD_DIR)/boot/stage2.bin of=$@ bs=512 seek=1 conv=notrunc status=none dd if=$(BUILD_DIR)/kernel.bin of=$@ bs=512 seek=16 conv=notrunc status=none - @echo "=== [SUB-OS Disk Image Built Successfully: $@ (Size: $$(du -h $@ | cut -f1))] ===" + @echo "=== [SUB-OS x86_64 Disk Image Built: $@ (Size: $$(du -h $@ | cut -f1))] ===" -$(BUILD_DIR)/boot: - mkdir -p $(BUILD_DIR)/boot - -run: $(IMAGE) - qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \ - -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \ - -device e1000,netdev=net0 -serial stdio +# ----------------------------------------------------------------------------- +# Execution & Emulation Targets +# ----------------------------------------------------------------------------- +run qemu: $(TARGET) + $(QEMU_CMD) run-server: $(IMAGE) qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \ -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \ -device e1000,netdev=net0 -serial stdio -display none -run-remote: $(IMAGE) - qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \ - -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \ - -device e1000,netdev=net0 \ - -serial telnet:0.0.0.0:2222,server,nowait -display none - -debug: $(IMAGE) +debug: $(TARGET) +ifeq ($(ARCH), x86_64) qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \ -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \ -device e1000,netdev=net0 -serial stdio -s -S +else + qemu-system-aarch64 -M virt -cpu cortex-a57 -m 128M -nographic -kernel $(BUILD_DIR)/kernel.elf -s -S +endif info: - @echo "C Sources: $(words $(ALL_C_SRCS)) files" - @echo "ASM Sources: $(words $(ARCH_ASM_SRCS)) files" - @echo "Target: $(IMAGE)" + @echo "Target Architecture: $(ARCH)" + @echo "Cross Compiler: $(CROSS_COMPILE)" + @echo "C Sources: $(words $(ALL_C_SRCS)) files" + @echo "Target Binary: $(TARGET)" clean: rm -rf $(BUILD_DIR) $(IMAGE) diff --git a/arch/aarch64/boot/entry.S b/arch/aarch64/boot/entry.S new file mode 100644 index 0000000..f873ffd --- /dev/null +++ b/arch/aarch64/boot/entry.S @@ -0,0 +1,106 @@ +/* + * SUB-OS AArch64 / ARMv8 Bootstrap Entry Point + * Handles EL2/EL3 -> EL1 drop, sets up stack, zeroes BSS, and jumps to kernel_main_aarch64 + */ + +.section ".text.boot" +.global _start +.global aarch64_entry + +_start: +aarch64_entry: + // Early UART debug ping + mov x0, #0x09000000 + mov w1, #'[' + str w1, [x0] + mov w1, #'S' + str w1, [x0] + mov w1, #'U' + str w1, [x0] + mov w1, #'B' + str w1, [x0] + mov w1, #'-' + str w1, [x0] + mov w1, #'O' + str w1, [x0] + mov w1, #'S' + str w1, [x0] + mov w1, #']' + str w1, [x0] + mov w1, #'\n' + str w1, [x0] + + // 1. Primary Core Check (Core 0 proceeds, other cores halt) + mrs x0, mpidr_el1 + and x0, x0, #0xFF + cbz x0, .primary_core + +.secondary_halt: + wfe + b .secondary_halt + +.primary_core: + // 2. Check current Exception Level (EL) + mrs x0, CurrentEL + lsr x0, x0, #2 + cmp x0, #2 + b.eq .from_el2 + cmp x0, #3 + b.eq .from_el3 + b .in_el1 + +.from_el3: + // Setup Secure Configuration Register (SCR_EL3) + mov x0, #(1 << 10) // RW=1 (64-bit execution in EL2/EL1) + orr x0, x0, #(1 << 0) // NS=1 (Non-secure) + msr scr_el3, x0 + mov x0, #0b01001 // EL2h mode with DAIF masked + msr spsr_el3, x0 + adr x0, .from_el2 + msr elr_el3, x0 + eret + +.from_el2: + // Setup Hypervisor Configuration Register (HCR_EL2) + mov x0, #(1 << 31) // RW=1 (64-bit execution in EL1) + msr hcr_el2, x0 + + // Setup SPSR_EL2 for drop to EL1h (EL1 with dedicated SP_EL1) + mov x0, #0b00101 // M[3:0] = 0101 (EL1h) + orr x0, x0, #(0xF << 6) // Mask DAIF + msr spsr_el2, x0 + + adr x0, .in_el1 + msr elr_el2, x0 + eret + +.in_el1: + // Enable Floating-Point and Advanced SIMD (NEON) in EL1 + mov x0, #(3 << 20) + msr cpacr_el1, x0 + isb + + // 3. Set up Kernel Stack (64 KB dedicated EL1 stack) + ldr x0, =stack_top + mov sp, x0 + + // 4. Enable Vector Table + ldr x0, =vectors + msr vbar_el1, x0 + + // 5. Zero out BSS + ldr x0, =__bss_start + ldr x1, =__bss_end +.bss_loop: + cmp x0, x1 + b.ge .bss_done + str xzr, [x0], #8 + b .bss_loop +.bss_done: + + // 6. Jump to AArch64 C Entry + bl kernel_main_aarch64 + +.hang: + wfi + b .hang diff --git a/arch/aarch64/configs/defconfig b/arch/aarch64/configs/defconfig new file mode 100644 index 0000000..7e6afaa --- /dev/null +++ b/arch/aarch64/configs/defconfig @@ -0,0 +1,36 @@ +# +# Automatically generated by SUB-OS Kconfig for aarch64 +# +CONFIG_ARCH=aarch64 +CONFIG_ARCH_AARCH64=y +# CONFIG_ARCH_X86_64 is not set +CONFIG_BPF_VM=y +CONFIG_DRV_CANVAS_2D=y +CONFIG_DRV_PTY=y +CONFIG_DRV_RAMDISK=y +CONFIG_DRV_VIRTIO_BLK=y +CONFIG_DRV_VIRTIO_NET=y +CONFIG_DRV_VIRTIO_RNG=y +CONFIG_FS_DEVFS=y +CONFIG_FS_EXT2=y +CONFIG_FS_FAT32=y +CONFIG_FS_PROCFS=y +CONFIG_FS_RAMFS=y +CONFIG_FS_SYSFS=y +CONFIG_FS_VFS=y +CONFIG_IO_URING=y +CONFIG_MM_PMM=y +CONFIG_MM_SLAB=y +CONFIG_MM_VMA=y +CONFIG_NET_FILTER=y +CONFIG_NET_HTTPD=y +CONFIG_NET_SSHD=y +CONFIG_NET_STACK=y +CONFIG_OPTIMIZATION="-O2" +CONFIG_PREEMPT=y +CONFIG_SECURITY_KEYRING=y +CONFIG_SECURITY_LSM=y +CONFIG_SMP=y +CONFIG_SUBOS_HOSTNAME="sub-os" +CONFIG_SUBOS_VERSION="0.2.0-lts" +CONFIG_USERLAND_LAZYBOX=y diff --git a/arch/aarch64/cpu/arch.c b/arch/aarch64/cpu/arch.c new file mode 100644 index 0000000..31d126a --- /dev/null +++ b/arch/aarch64/cpu/arch.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static cpu_info_t aarch64_compat_cpu; + +void arch_early_init(void) { + uart_pl011_init(); +} + +void arch_init(void) { + aarch64_cpu_init(); + gic_init(); + aarch64_timer_init(100); + aarch64_mmu_init(); + + // Populate compatibility CPU info structure for procfs + memset(&aarch64_compat_cpu, 0, sizeof(aarch64_compat_cpu)); + const aarch64_cpu_info_t* info = aarch64_get_cpu_info(); + strncpy(aarch64_compat_cpu.vendor, "ARM Ltd", sizeof(aarch64_compat_cpu.vendor) - 1); + strncpy(aarch64_compat_cpu.model, info->model_name, sizeof(aarch64_compat_cpu.model) - 1); + aarch64_compat_cpu.has_fpu = true; + + arch_enable_interrupts(); +} + +const char* arch_get_name(void) { + return "aarch64 (ARMv8-A)"; +} + +uint32_t arch_get_cpu_id(void) { + return (uint32_t)(aarch64_get_mpidr() & 0xFF); +} + +// Timer Compatibility Layer for Portable Drivers +uint64_t pit_get_ticks(void) { + return aarch64_timer_get_ticks(); +} + +void pit_sleep(uint32_t ms) { + uint64_t count = (ms > 10) ? (ms / 10) : 1; + uint64_t target = aarch64_timer_get_ticks() + count; + while (aarch64_timer_get_ticks() < target) { + __asm__ volatile("wfi"); + } +} + +// Interrupt & CPUID Compatibility Stubs +void isr_register_handler(uint8_t isr, void* handler) { + (void)isr; (void)handler; +} + +void pic_clear_mask(uint8_t irq) { + (void)irq; +} + +const cpu_info_t* cpuid_get_info(void) { + return &aarch64_compat_cpu; +} diff --git a/arch/aarch64/cpu/cpu.c b/arch/aarch64/cpu/cpu.c new file mode 100644 index 0000000..b856394 --- /dev/null +++ b/arch/aarch64/cpu/cpu.c @@ -0,0 +1,58 @@ +#include +#include +#include + +static aarch64_cpu_info_t cpu_info; + +uint64_t aarch64_get_midr(void) { + uint64_t midr; + __asm__ volatile("mrs %0, midr_el1" : "=r"(midr)); + return midr; +} + +uint64_t aarch64_get_mpidr(void) { + uint64_t mpidr; + __asm__ volatile("mrs %0, mpidr_el1" : "=r"(mpidr)); + return mpidr; +} + +uint32_t aarch64_get_current_el(void) { + uint64_t cur_el; + __asm__ volatile("mrs %0, CurrentEL" : "=r"(cur_el)); + return (uint32_t)(cur_el >> 2); +} + +void aarch64_cpu_init(void) { + memset(&cpu_info, 0, sizeof(cpu_info)); + + uint64_t midr = aarch64_get_midr(); + cpu_info.implementer = (uint32_t)((midr >> 24) & 0xFF); + cpu_info.variant = (uint32_t)((midr >> 20) & 0x0F); + cpu_info.architecture = (uint32_t)((midr >> 16) & 0x0F); + cpu_info.part_num = (uint32_t)((midr >> 4) & 0xFFF); + cpu_info.revision = (uint32_t)(midr & 0x0F); + cpu_info.current_el = aarch64_get_current_el(); + + if (cpu_info.implementer == 0x41) { // ARM Limited + switch (cpu_info.part_num) { + case 0xD03: strcpy(cpu_info.model_name, "ARM Cortex-A53 (ARMv8.0-A)"); break; + case 0xD07: strcpy(cpu_info.model_name, "ARM Cortex-A57 (ARMv8.0-A)"); break; + case 0xD08: strcpy(cpu_info.model_name, "ARM Cortex-A72 (ARMv8.0-A)"); break; + case 0xD09: strcpy(cpu_info.model_name, "ARM Cortex-A73 (ARMv8.0-A)"); break; + case 0xD0B: strcpy(cpu_info.model_name, "ARM Cortex-A76 (ARMv8.2-A)"); break; + case 0xD40: strcpy(cpu_info.model_name, "ARM Neoverse-V1 (ARMv8.4-A)"); break; + default: strcpy(cpu_info.model_name, "ARMv8-A Compatible 64-Bit Processor"); break; + } + } else if (cpu_info.implementer == 0x61) { // Apple Silicon + strcpy(cpu_info.model_name, "Apple Silicon M-Series (ARMv8-A)"); + } else { + strcpy(cpu_info.model_name, "Generic AArch64 / ARMv8 64-Bit Core"); + } + + printk(KERN_INFO "CPU: %s (Implementer: 0x%02x, Part: 0x%03x, EL%u)\n", + cpu_info.model_name, cpu_info.implementer, cpu_info.part_num, cpu_info.current_el); +} + +const aarch64_cpu_info_t* aarch64_get_cpu_info(void) { + return &cpu_info; +} diff --git a/arch/aarch64/cpu/exceptions.c b/arch/aarch64/cpu/exceptions.c new file mode 100644 index 0000000..cbf7ca5 --- /dev/null +++ b/arch/aarch64/cpu/exceptions.c @@ -0,0 +1,42 @@ +#include +#include +#include + +void aarch64_sync_handler(aarch64_context_t* ctx) { + uint64_t esr, elr, far; + __asm__ volatile("mrs %0, esr_el1" : "=r"(esr)); + __asm__ volatile("mrs %0, elr_el1" : "=r"(elr)); + __asm__ volatile("mrs %0, far_el1" : "=r"(far)); + + uint32_t ec = (esr >> 26) & 0x3F; + printk(ANSI_BRIGHT_RED "\n[KERNEL PANIC] AArch64 Synchronous Exception!\n" ANSI_RESET); + printk("ESR_EL1: 0x%016llx (EC: 0x%02x, ISS: 0x%08x)\n", esr, ec, (uint32_t)(esr & 0x01FFFFFF)); + printk("ELR_EL1 (PC): 0x%016llx FAR_EL1: 0x%016llx\n", elr, far); + printk("Registers:\n"); + for (int i = 0; i < 30; i += 2) { + printk(" X%02d: 0x%016llx X%02d: 0x%016llx\n", i, ctx->r[i], i + 1, ctx->r[i + 1]); + } + printk(" X30 (LR): 0x%016llx SP: 0x%016llx\n", ctx->r[30], ctx->sp); + + while (1) { + __asm__ volatile("wfe"); + } +} + +void aarch64_irq_handler(aarch64_context_t* ctx) { + (void)ctx; + gic_handle_irq(); +} + +void aarch64_fiq_handler(aarch64_context_t* ctx) { + (void)ctx; + printk(KERN_WARNING "AArch64: Unexpected FIQ caught\n"); +} + +void aarch64_serror_handler(aarch64_context_t* ctx) { + (void)ctx; + printk(ANSI_BRIGHT_RED "[KERNEL PANIC] AArch64 SError Interrupt caught!\n" ANSI_RESET); + while (1) { + __asm__ volatile("wfe"); + } +} diff --git a/arch/aarch64/cpu/gic.c b/arch/aarch64/cpu/gic.c new file mode 100644 index 0000000..ad6c4e4 --- /dev/null +++ b/arch/aarch64/cpu/gic.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +#define MAX_GIC_IRQS 256 + +static gic_irq_handler_t irq_handlers[MAX_GIC_IRQS]; + +void gic_init(void) { + memset(irq_handlers, 0, sizeof(irq_handlers)); + + // 1. Disable Distributor + mmio_write32(GIC_DIST_BASE + GICD_CTLR, 0); + + // 2. Clear pending and enable default priorities + uint32_t typer = mmio_read32(GIC_DIST_BASE + GICD_TYPER); + uint32_t num_irqs = 32 * ((typer & 0x1F) + 1); + if (num_irqs > MAX_GIC_IRQS) num_irqs = MAX_GIC_IRQS; + + for (uint32_t i = 32; i < num_irqs; i += 32) { + mmio_write32(GIC_DIST_BASE + GICD_ICENABLER(i / 32), 0xFFFFFFFF); + } + + for (uint32_t i = 0; i < num_irqs; i += 4) { + mmio_write32(GIC_DIST_BASE + GICD_IPRIORITYR(i / 4), 0xA0A0A0A0); + } + + for (uint32_t i = 32; i < num_irqs; i += 4) { + mmio_write32(GIC_DIST_BASE + GICD_ITARGETSR(i / 4), 0x01010101); // Target Core 0 + } + + // 3. Enable Distributor + mmio_write32(GIC_DIST_BASE + GICD_CTLR, 1); + + // 4. Enable CPU Interface + mmio_write32(GIC_CPU_BASE + GICC_PMR, 0xF0); // Priority mask + mmio_write32(GIC_CPU_BASE + GICC_CTLR, 1); // Enable signaling + + printk(KERN_INFO "GIC: ARM Generic Interrupt Controller v2 initialized (%u IRQ lines)\n", num_irqs); +} + +void gic_enable_irq(uint32_t irq) { + if (irq >= MAX_GIC_IRQS) return; + mmio_write32(GIC_DIST_BASE + GICD_ISENABLER(irq / 32), (1U << (irq % 32))); +} + +void gic_disable_irq(uint32_t irq) { + if (irq >= MAX_GIC_IRQS) return; + mmio_write32(GIC_DIST_BASE + GICD_ICENABLER(irq / 32), (1U << (irq % 32))); +} + +void gic_register_handler(uint32_t irq, gic_irq_handler_t handler) { + if (irq < MAX_GIC_IRQS) { + irq_handlers[irq] = handler; + gic_enable_irq(irq); + } +} + +void gic_handle_irq(void) { + uint32_t iar = mmio_read32(GIC_CPU_BASE + GICC_IAR); + uint32_t irq = iar & 0x3FF; + + if (irq < 1020) { + if (irq_handlers[irq]) { + irq_handlers[irq](irq); + } + // End of Interrupt (EOIR) + mmio_write32(GIC_CPU_BASE + GICC_EOIR, iar); + } +} diff --git a/arch/aarch64/cpu/timer.c b/arch/aarch64/cpu/timer.c new file mode 100644 index 0000000..83ee0fe --- /dev/null +++ b/arch/aarch64/cpu/timer.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +static uint64_t timer_ticks = 0; +static uint64_t timer_freq = 62500000; // Standard 62.5MHz QEMU virt frequency +static uint32_t tick_interval = 0; + +void aarch64_timer_handle_irq(void) { + timer_ticks++; + + // Reset next comparator interval + __asm__ volatile("msr cntv_tval_el0, %0" :: "r"((uint64_t)tick_interval)); + + // Call generic kernel timer tick + timer_tick(); +} + +static void gic_timer_wrapper(uint32_t irq) { + (void)irq; + aarch64_timer_handle_irq(); +} + +void aarch64_timer_init(uint32_t freq_hz) { + if (freq_hz == 0) freq_hz = 100; + + __asm__ volatile("mrs %0, cntfrq_el0" : "=r"(timer_freq)); + tick_interval = (uint32_t)(timer_freq / freq_hz); + + // Register with GIC (PPI 27 = Virtual Timer IRQ) + gic_register_handler(ARCH_TIMER_VIRT_IRQ, gic_timer_wrapper); + + // Set countdown and enable virtual timer + __asm__ volatile("msr cntv_tval_el0, %0" :: "r"((uint64_t)tick_interval)); + uint64_t ctl = 1; // Enable=1, IMASK=0 + __asm__ volatile("msr cntv_ctl_el0, %0" :: "r"(ctl)); + + printk(KERN_INFO "Timer: ARM Generic Arch Timer active (%u Hz, Base Clock: %llu MHz)\n", + freq_hz, timer_freq / 1000000); +} + +uint64_t aarch64_timer_get_ticks(void) { + return timer_ticks; +} + +uint64_t aarch64_timer_get_freq(void) { + return timer_freq; +} diff --git a/arch/aarch64/cpu/vectors.S b/arch/aarch64/cpu/vectors.S new file mode 100644 index 0000000..a9610de --- /dev/null +++ b/arch/aarch64/cpu/vectors.S @@ -0,0 +1,117 @@ +/* + * SUB-OS AArch64 Exception Vector Table + * 16 vectors aligned on 128-byte (0x80) boundaries + */ + +.macro SAVE_ALL + sub sp, sp, #272 + stp x0, x1, [sp, #0] + stp x2, x3, [sp, #16] + stp x4, x5, [sp, #32] + stp x6, x7, [sp, #48] + stp x8, x9, [sp, #64] + stp x10, x11, [sp, #80] + stp x12, x13, [sp, #96] + stp x14, x15, [sp, #112] + stp x16, x17, [sp, #128] + stp x18, x19, [sp, #144] + stp x20, x21, [sp, #160] + stp x22, x23, [sp, #176] + stp x24, x25, [sp, #192] + stp x26, x27, [sp, #208] + stp x28, x29, [sp, #224] + mrs x0, elr_el1 + mrs x1, spsr_el1 + stp x30, x0, [sp, #240] + str x1, [sp, #256] +.endm + +.macro RESTORE_ALL + ldr x1, [sp, #256] + msr spsr_el1, x1 + ldp x30, x0, [sp, #240] + msr elr_el1, x0 + ldp x28, x29, [sp, #224] + ldp x26, x27, [sp, #208] + ldp x24, x25, [sp, #192] + ldp x22, x23, [sp, #176] + ldp x20, x21, [sp, #160] + ldp x18, x19, [sp, #144] + ldp x16, x17, [sp, #128] + ldp x14, x15, [sp, #112] + ldp x12, x13, [sp, #96] + ldp x10, x11, [sp, #80] + ldp x8, x9, [sp, #64] + ldp x6, x7, [sp, #48] + ldp x4, x5, [sp, #32] + ldp x2, x3, [sp, #16] + ldp x0, x1, [sp, #0] + add sp, sp, #272 + eret +.endm + +.section ".vectors", "ax" +.align 11 +.global vectors + +vectors: + // 1. Current EL with SP0 + .align 7; b handle_sync_curr_sp0 + .align 7; b handle_irq_curr_sp0 + .align 7; b handle_fiq_curr_sp0 + .align 7; b handle_serror_curr_sp0 + + // 2. Current EL with SPx + .align 7; b handle_sync_curr_spx + .align 7; b handle_irq_curr_spx + .align 7; b handle_fiq_curr_spx + .align 7; b handle_serror_curr_spx + + // 3. Lower EL using AArch64 + .align 7; b handle_sync_lower_aarch64 + .align 7; b handle_irq_lower_aarch64 + .align 7; b handle_fiq_lower_aarch64 + .align 7; b handle_serror_lower_aarch64 + + // 4. Lower EL using AArch32 + .align 7; b handle_sync_lower_aarch32 + .align 7; b handle_irq_lower_aarch32 + .align 7; b handle_fiq_lower_aarch32 + .align 7; b handle_serror_lower_aarch32 + +// Common Vector Handlers +handle_sync_curr_sp0: +handle_sync_curr_spx: +handle_sync_lower_aarch64: +handle_sync_lower_aarch32: + SAVE_ALL + mov x0, sp + bl aarch64_sync_handler + RESTORE_ALL + +handle_irq_curr_sp0: +handle_irq_curr_spx: +handle_irq_lower_aarch64: +handle_irq_lower_aarch32: + SAVE_ALL + mov x0, sp + bl aarch64_irq_handler + RESTORE_ALL + +handle_fiq_curr_sp0: +handle_fiq_curr_spx: +handle_fiq_lower_aarch64: +handle_fiq_lower_aarch32: + SAVE_ALL + mov x0, sp + bl aarch64_fiq_handler + RESTORE_ALL + +handle_serror_curr_sp0: +handle_serror_curr_spx: +handle_serror_lower_aarch64: +handle_serror_lower_aarch32: + SAVE_ALL + mov x0, sp + bl aarch64_serror_handler + RESTORE_ALL diff --git a/arch/aarch64/drivers/uart_pl011.c b/arch/aarch64/drivers/uart_pl011.c new file mode 100644 index 0000000..1cefd0d --- /dev/null +++ b/arch/aarch64/drivers/uart_pl011.c @@ -0,0 +1,38 @@ +#include +#include + +void uart_pl011_init(void) { + // Enable UART, TX, and RX (bits 0, 8, 9) + mmio_write32(PL011_UART0_BASE + UARTCR, (1 << 0) | (1 << 8) | (1 << 9)); +} + +void uart_pl011_putc(char c) { + if (c == '\n') { + while (mmio_read32(PL011_UART0_BASE + UARTFR) & UARTFR_TXFF) { + __asm__ volatile("nop"); + } + mmio_write32(PL011_UART0_BASE + UARTDR, '\r'); + } + while (mmio_read32(PL011_UART0_BASE + UARTFR) & UARTFR_TXFF) { + __asm__ volatile("nop"); + } + mmio_write32(PL011_UART0_BASE + UARTDR, (uint32_t)(uint8_t)c); +} + +void uart_pl011_puts(const char* str) { + if (!str) return; + while (*str) { + uart_pl011_putc(*str++); + } +} + +char uart_pl011_getc(void) { + while (mmio_read32(PL011_UART0_BASE + UARTFR) & UARTFR_RXFE) { + __asm__ volatile("wfe"); + } + return (char)(mmio_read32(PL011_UART0_BASE + UARTDR) & 0xFF); +} + +int uart_pl011_has_data(void) { + return !(mmio_read32(PL011_UART0_BASE + UARTFR) & UARTFR_RXFE); +} diff --git a/arch/aarch64/linker.ld b/arch/aarch64/linker.ld new file mode 100644 index 0000000..0e4fd00 --- /dev/null +++ b/arch/aarch64/linker.ld @@ -0,0 +1,45 @@ +OUTPUT_FORMAT("elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(_start) + +SECTIONS +{ + . = 0x40080000; + + __kernel_start = .; + + .text.boot : { + KEEP(*(.text.boot)) + } + + .vectors : ALIGN(2048) { + KEEP(*(.vectors)) + } + + .text : ALIGN(4096) { + *(.text .text.*) + } + + .rodata : ALIGN(4096) { + *(.rodata .rodata.*) + } + + .data : ALIGN(4096) { + *(.data .data.*) + } + + .bss : ALIGN(4096) { + __bss_start = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4096); + __bss_end = .; + } + + .stack : ALIGN(4096) { + . += 0x20000; /* 128 KB dedicated kernel stack */ + stack_top = .; + } + + __kernel_end = .; +} diff --git a/arch/aarch64/mm/mmu.c b/arch/aarch64/mm/mmu.c new file mode 100644 index 0000000..c101e6e --- /dev/null +++ b/arch/aarch64/mm/mmu.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include + +// Level 1 Translation Table (PUD / L1, 512 x 1GB entries, root table for 39-bit VA) +static uint64_t __attribute__((aligned(4096))) l1_table[512]; +// Level 2 Translation Table (PMD / L2, 512 x 2MB entries for first 1GB: 0x00000000 - 0x3FFFFFFF Device MMIO) +static uint64_t __attribute__((aligned(4096))) l2_dev_table[512]; +// Level 2 Translation Table (PMD / L2, 512 x 2MB entries for second 1GB: 0x40000000 - 0x7FFFFFFF RAM) +static uint64_t __attribute__((aligned(4096))) l2_ram_table[512]; + +void aarch64_mmu_init(void) { + memset(l1_table, 0, sizeof(l1_table)); + memset(l2_dev_table, 0, sizeof(l2_dev_table)); + memset(l2_ram_table, 0, sizeof(l2_ram_table)); + + // L1 Table Entry 0 points to L2 Device Table (0 - 1GB) + l1_table[0] = ((uint64_t)l2_dev_table) | PTE_VALID | PTE_TABLE; + // L1 Table Entry 1 points to L2 RAM Table (1GB - 2GB: QEMU virt RAM is 0x40000000) + l1_table[1] = ((uint64_t)l2_ram_table) | PTE_VALID | PTE_TABLE; + + // 1. Identity map Device MMIO (0x00000000 - 0x3FFFFFFF) as Device-nGnRnE + for (uint64_t i = 0; i < 512; i++) { + uint64_t phys = i * 0x200000; // 2MB blocks + l2_dev_table[i] = phys | PTE_VALID | PTE_AF | PTE_SH_INNER | PTE_ATTRINDX(MT_DEVICE_nGnRnE); + } + + // 2. Identity map System RAM (0x40000000 - 0x7FFFFFFF, 1GB) as Normal Cacheable + for (uint64_t i = 0; i < 512; i++) { + uint64_t phys = 0x40000000 + (i * 0x200000); + l2_ram_table[i] = phys | PTE_VALID | PTE_AF | PTE_SH_INNER | PTE_ATTRINDX(MT_NORMAL_WB); + } + + // 3. Set Memory Attribute Indirection Register (MAIR_EL1) + __asm__ volatile("msr mair_el1, %0" :: "r"((uint64_t)MAIR_VAL)); + + // 4. Configure Translation Control Register (TCR_EL1) + // T0SZ=25 (39-bit VA starting at L1 / 1GB chunks), TG0=0 (4KB granule), Inner/Outer WBWA, Inner Shareable + uint64_t tcr = (25ULL << 0) | // T0SZ = 25 (39-bit VA) + (1ULL << 8) | // IRGN0 = Normal WBWA + (1ULL << 10) | // ORGN0 = Normal WBWA + (3ULL << 12) | // SH0 = Inner Shareable + (0ULL << 14) | // TG0 = 4KB + (1ULL << 23) | // EPD1 = Disable TTBR1 translations + (2ULL << 32); // IPS = 40-bit Physical Address (1TB) + __asm__ volatile("msr tcr_el1, %0" :: "r"(tcr)); + + // 5. Load Translation Table Base Register 0 (TTBR0_EL1) + __asm__ volatile("msr ttbr0_el1, %0" :: "r"((uint64_t)l1_table)); + + isb(); + + // 6. Enable MMU and Caching in SCTLR_EL1 (M=1, C=1, I=1) + uint64_t sctlr; + __asm__ volatile("mrs %0, sctlr_el1" : "=r"(sctlr)); + sctlr |= (1 << 0) | // M: Enable MMU + (1 << 2) | // C: Enable Data Cache + (1 << 12); // I: Enable Instruction Cache + __asm__ volatile("msr sctlr_el1, %0" :: "r"(sctlr)); + + isb(); +} diff --git a/arch/x86_64/configs/defconfig b/arch/x86_64/configs/defconfig new file mode 100644 index 0000000..8ff52ba --- /dev/null +++ b/arch/x86_64/configs/defconfig @@ -0,0 +1,45 @@ +# +# Automatically generated by SUB-OS Kconfig for x86_64 +# +CONFIG_ARCH=x86_64 +CONFIG_ARCH_X86_64=y +CONFIG_BPF_VM=y +CONFIG_DRV_AHCI=y +CONFIG_DRV_ATA=y +CONFIG_DRV_BOCHS_VBE=y +CONFIG_DRV_CANVAS_2D=y +CONFIG_DRV_E1000=y +CONFIG_DRV_HWMON=y +CONFIG_DRV_NVME=y +CONFIG_DRV_PTY=y +CONFIG_DRV_RAMDISK=y +CONFIG_DRV_RTL8139=y +CONFIG_DRV_SOUND_AC97=y +CONFIG_DRV_SOUND_HDA=y +CONFIG_DRV_USB_XHCI=y +CONFIG_DRV_VIRTIO_BLK=y +CONFIG_DRV_VIRTIO_NET=y +CONFIG_DRV_VIRTIO_RNG=y +CONFIG_FS_DEVFS=y +CONFIG_FS_EXT2=y +CONFIG_FS_FAT32=y +CONFIG_FS_PROCFS=y +CONFIG_FS_RAMFS=y +CONFIG_FS_SYSFS=y +CONFIG_FS_VFS=y +CONFIG_IO_URING=y +CONFIG_MM_PMM=y +CONFIG_MM_SLAB=y +CONFIG_MM_VMA=y +CONFIG_NET_FILTER=y +CONFIG_NET_HTTPD=y +CONFIG_NET_SSHD=y +CONFIG_NET_STACK=y +CONFIG_OPTIMIZATION="-O2" +CONFIG_PREEMPT=y +CONFIG_SECURITY_KEYRING=y +CONFIG_SECURITY_LSM=y +CONFIG_SMP=y +CONFIG_SUBOS_HOSTNAME="sub-os" +CONFIG_SUBOS_VERSION="0.2.0-lts" +CONFIG_USERLAND_LAZYBOX=y diff --git a/arch/x86_64/cpu/arch.c b/arch/x86_64/cpu/arch.c new file mode 100644 index 0000000..610b867 --- /dev/null +++ b/arch/x86_64/cpu/arch.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +void arch_early_init(void) { + // x86_64 serial and tty initialized in main +} + +void arch_init(void) { + gdt_init(); + idt_init(); + isr_init(); + pic_init(); + pit_init(100); + timer_wheel_init(); + arch_enable_interrupts(); +} + +const char* arch_get_name(void) { + return "x86_64 (AMD64)"; +} + +uint32_t arch_get_cpu_id(void) { + uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; + cpuid(1, &eax, &ebx, &ecx, &edx); + return (ebx >> 24) & 0xFF; +} diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 30d4563..0874f22 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -1,8 +1,6 @@ #include #include -#include -#include -#include +#include #define KEYBOARD_DATA_PORT 0x60 #define KEYBOARD_STATUS_PORT 0x64 @@ -44,6 +42,7 @@ static void buffer_enqueue(uint16_t key) { } } +#if defined(__x86_64__) static void keyboard_interrupt_handler(registers_t* regs) { (void)regs; uint8_t scancode = inb(KEYBOARD_DATA_PORT); @@ -112,23 +111,40 @@ static void keyboard_interrupt_handler(registers_t* regs) { buffer_enqueue((uint16_t)c); } } +#endif void keyboard_init(void) { buffer_head = 0; buffer_tail = 0; +#if defined(__x86_64__) isr_register_handler(33, keyboard_interrupt_handler); // IRQ1 pic_clear_mask(1); +#endif } +#if defined(__aarch64__) +#include +#endif + bool keyboard_has_key(void) { +#if defined(__aarch64__) + if (uart_pl011_has_data()) return true; +#endif return buffer_head != buffer_tail; } uint16_t keyboard_get_key(void) { while (!keyboard_has_key()) { - hlt(); + arch_halt(); } +#if defined(__aarch64__) + if (uart_pl011_has_data()) { + char c = uart_pl011_getc(); + if (c == '\r') c = '\n'; + return (uint16_t)(uint8_t)c; + } +#endif uint16_t key = key_buffer[buffer_tail]; buffer_tail = (buffer_tail + 1) % KEYBOARD_BUFFER_SIZE; return key; diff --git a/drivers/char/tty.c b/drivers/char/tty.c index 8c884cf..db7ddb9 100644 --- a/drivers/char/tty.c +++ b/drivers/char/tty.c @@ -12,16 +12,17 @@ typedef struct { static tty_t ttys[MAX_TTYS]; static int current_tty = 0; -static volatile uint16_t* const VGA_MEM = (uint16_t*)VGA_MEMORY; - static void tty_render_current(void) { +#if defined(__x86_64__) + volatile uint16_t* const vga_mem = (uint16_t*)VGA_MEMORY; tty_t* t = &ttys[current_tty]; for (int y = 0; y < TTY_HEIGHT; y++) { for (int x = 0; x < TTY_WIDTH; x++) { - VGA_MEM[y * TTY_WIDTH + x] = t->buffer[y][x]; + vga_mem[y * TTY_WIDTH + x] = t->buffer[y][x]; } } vga_set_cursor(t->cursor_row, t->cursor_col); +#endif } void tty_switch(int index) { @@ -62,7 +63,9 @@ void tty_set_cursor(int row, int col) { tty_t* t = &ttys[current_tty]; t->cursor_row = row; t->cursor_col = col; +#if defined(__x86_64__) vga_set_cursor(row, col); +#endif } void tty_write(const char* data, size_t size) { @@ -150,7 +153,9 @@ void tty_write_string(const char* data) { } void tty_init(void) { +#if defined(__x86_64__) vga_init(); +#endif for (int i = 0; i < MAX_TTYS; i++) { ttys[i].cursor_row = 0; ttys[i].cursor_col = 0; diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h new file mode 100644 index 0000000..e1a6627 --- /dev/null +++ b/include/arch/aarch64/arch.h @@ -0,0 +1,16 @@ +#ifndef _ARCH_AARCH64_ARCH_H +#define _ARCH_AARCH64_ARCH_H + +#include +#include + +typedef struct { + uint64_t r[31]; // X0 - X30 + uint64_t sp; + uint64_t pc; + uint64_t pstate; +} __attribute__((packed)) aarch64_context_t; + +void aarch64_init(void); + +#endif // _ARCH_AARCH64_ARCH_H diff --git a/include/arch/aarch64/cpu.h b/include/arch/aarch64/cpu.h new file mode 100644 index 0000000..ea118d9 --- /dev/null +++ b/include/arch/aarch64/cpu.h @@ -0,0 +1,24 @@ +#ifndef _ARCH_AARCH64_CPU_H +#define _ARCH_AARCH64_CPU_H + +#include +#include + +typedef struct { + uint32_t implementer; + uint32_t variant; + uint32_t architecture; + uint32_t part_num; + uint32_t revision; + char model_name[64]; + uint32_t current_el; + uint64_t core_frequency_hz; +} aarch64_cpu_info_t; + +void aarch64_cpu_init(void); +const aarch64_cpu_info_t* aarch64_get_cpu_info(void); +uint32_t aarch64_get_current_el(void); +uint64_t aarch64_get_midr(void); +uint64_t aarch64_get_mpidr(void); + +#endif // _ARCH_AARCH64_CPU_H diff --git a/include/arch/aarch64/gic.h b/include/arch/aarch64/gic.h new file mode 100644 index 0000000..c203507 --- /dev/null +++ b/include/arch/aarch64/gic.h @@ -0,0 +1,34 @@ +#ifndef _ARCH_AARCH64_GIC_H +#define _ARCH_AARCH64_GIC_H + +#include +#include + +#define GIC_DIST_BASE 0x08000000 +#define GIC_CPU_BASE 0x08010000 + +// GIC Distributor Registers +#define GICD_CTLR 0x000 +#define GICD_TYPER 0x004 +#define GICD_ISENABLER(n) (0x100 + ((n) * 4)) +#define GICD_ICENABLER(n) (0x180 + ((n) * 4)) +#define GICD_IPRIORITYR(n) (0x400 + ((n) * 4)) +#define GICD_ITARGETSR(n) (0x800 + ((n) * 4)) +#define GICD_ICFGR(n) (0xC00 + ((n) * 4)) + +// GIC CPU Interface Registers +#define GICC_CTLR 0x0000 +#define GICC_PMR 0x0004 +#define GICC_BPR 0x0008 +#define GICC_IAR 0x000C +#define GICC_EOIR 0x0010 + +typedef void (*gic_irq_handler_t)(uint32_t irq); + +void gic_init(void); +void gic_enable_irq(uint32_t irq); +void gic_disable_irq(uint32_t irq); +void gic_register_handler(uint32_t irq, gic_irq_handler_t handler); +void gic_handle_irq(void); + +#endif // _ARCH_AARCH64_GIC_H diff --git a/include/arch/aarch64/io.h b/include/arch/aarch64/io.h new file mode 100644 index 0000000..1f24e90 --- /dev/null +++ b/include/arch/aarch64/io.h @@ -0,0 +1,95 @@ +#ifndef _ARCH_AARCH64_IO_H +#define _ARCH_AARCH64_IO_H + +#include + +static inline void mmio_write8(uintptr_t reg, uint8_t val) { + *(volatile uint8_t*)reg = val; +} + +static inline uint8_t mmio_read8(uintptr_t reg) { + return *(volatile uint8_t*)reg; +} + +static inline void mmio_write16(uintptr_t reg, uint16_t val) { + *(volatile uint16_t*)reg = val; +} + +static inline uint16_t mmio_read16(uintptr_t reg) { + return *(volatile uint16_t*)reg; +} + +static inline void mmio_write32(uintptr_t reg, uint32_t val) { + *(volatile uint32_t*)reg = val; +} + +static inline uint32_t mmio_read32(uintptr_t reg) { + return *(volatile uint32_t*)reg; +} + +static inline void mmio_write64(uintptr_t reg, uint64_t val) { + *(volatile uint64_t*)reg = val; +} + +static inline uint64_t mmio_read64(uintptr_t reg) { + return *(volatile uint64_t*)reg; +} + +// Memory barriers +static inline void dsb(void) { + __asm__ volatile("dsb sy" ::: "memory"); +} + +static inline void dmb(void) { + __asm__ volatile("dmb sy" ::: "memory"); +} + +static inline void isb(void) { + __asm__ volatile("isb" ::: "memory"); +} + +// x86 I/O Port Emulation / Stubs for Portable Device Drivers +static inline void outb(uint16_t port, uint8_t val) { + (void)port; (void)val; +} + +static inline uint8_t inb(uint16_t port) { + (void)port; + return 0; +} + +static inline void outw(uint16_t port, uint16_t val) { + (void)port; (void)val; +} + +static inline uint16_t inw(uint16_t port) { + (void)port; + return 0; +} + +static inline void outl(uint16_t port, uint32_t val) { + (void)port; (void)val; +} + +static inline uint32_t inl(uint16_t port) { + (void)port; + return 0; +} + +static inline void io_wait(void) { + __asm__ volatile("nop"); +} + +static inline void cli(void) { + __asm__ volatile("msr daifset, #2" ::: "memory"); +} + +static inline void sti(void) { + __asm__ volatile("msr daifclr, #2" ::: "memory"); +} + +static inline void hlt(void) { + __asm__ volatile("wfi"); +} + +#endif // _ARCH_AARCH64_IO_H diff --git a/include/arch/aarch64/mmu.h b/include/arch/aarch64/mmu.h new file mode 100644 index 0000000..216bdeb --- /dev/null +++ b/include/arch/aarch64/mmu.h @@ -0,0 +1,39 @@ +#ifndef _ARCH_AARCH64_MMU_H +#define _ARCH_AARCH64_MMU_H + +#include +#include + +#define MMU_PAGE_SIZE 4096 + +// Memory Types / Attributes index for MAIR_EL1 +#define MT_DEVICE_nGnRnE 0 +#define MT_NORMAL_NC 1 +#define MT_NORMAL_WB 2 + +#define MAIR_DEVICE_nGnRnE 0x00 +#define MAIR_NORMAL_NC 0x44 +#define MAIR_NORMAL_WB 0xFF + +#define MAIR_VAL ((MAIR_DEVICE_nGnRnE << (MT_DEVICE_nGnRnE * 8)) | \ + (MAIR_NORMAL_NC << (MT_NORMAL_NC * 8)) | \ + (MAIR_NORMAL_WB << (MT_NORMAL_WB * 8))) + +// Page descriptor bits +#define PTE_VALID (1ULL << 0) +#define PTE_TABLE (1ULL << 1) +#define PTE_BLOCK (0ULL << 1) +#define PTE_USER (1ULL << 6) +#define PTE_RO (1ULL << 7) +#define PTE_SH_INNER (3ULL << 8) +#define PTE_AF (1ULL << 10) +#define PTE_NG (1ULL << 11) +#define PTE_PXN (1ULL << 53) +#define PTE_UXN (1ULL << 54) + +#define PTE_ATTRINDX(x) (((uint64_t)(x)) << 2) + +void aarch64_mmu_init(void); +void aarch64_mmu_map_2mb(uint64_t virt_addr, uint64_t phys_addr, uint32_t mem_type); + +#endif // _ARCH_AARCH64_MMU_H diff --git a/include/arch/aarch64/timer.h b/include/arch/aarch64/timer.h new file mode 100644 index 0000000..7e07be8 --- /dev/null +++ b/include/arch/aarch64/timer.h @@ -0,0 +1,13 @@ +#ifndef _ARCH_AARCH64_TIMER_H +#define _ARCH_AARCH64_TIMER_H + +#include + +#define ARCH_TIMER_VIRT_IRQ 27 + +void aarch64_timer_init(uint32_t freq_hz); +uint64_t aarch64_timer_get_ticks(void); +uint64_t aarch64_timer_get_freq(void); +void aarch64_timer_handle_irq(void); + +#endif // _ARCH_AARCH64_TIMER_H diff --git a/include/arch/aarch64/uart.h b/include/arch/aarch64/uart.h new file mode 100644 index 0000000..3fd1f7a --- /dev/null +++ b/include/arch/aarch64/uart.h @@ -0,0 +1,34 @@ +#ifndef _ARCH_AARCH64_UART_H +#define _ARCH_AARCH64_UART_H + +#include +#include + +#define PL011_UART0_BASE 0x09000000 + +// PL011 Registers +#define UARTDR 0x000 +#define UARTRSR 0x004 +#define UARTFR 0x018 +#define UARTILPR 0x020 +#define UARTIBRD 0x024 +#define UARTFBRD 0x028 +#define UARTLCR 0x02C +#define UARTCR 0x030 +#define UARTIFLS 0x034 +#define UARTIMSC 0x038 +#define UARTRIS 0x03C +#define UARTMIS 0x040 +#define UARTICR 0x044 + +// Flag register bits +#define UARTFR_TXFF (1 << 5) +#define UARTFR_RXFE (1 << 4) + +void uart_pl011_init(void); +void uart_pl011_putc(char c); +void uart_pl011_puts(const char* str); +char uart_pl011_getc(void); +int uart_pl011_has_data(void); + +#endif // _ARCH_AARCH64_UART_H diff --git a/include/arch/arch.h b/include/arch/arch.h new file mode 100644 index 0000000..8a81221 --- /dev/null +++ b/include/arch/arch.h @@ -0,0 +1,96 @@ +#ifndef _ARCH_ARCH_H +#define _ARCH_ARCH_H + +#include +#include + +#if defined(__x86_64__) +#define ARCH_NAME "x86_64" +#define ARCH_IS_64BIT 1 +#include +#include +#include +#include +#include +#include +#include +#include + +static inline void arch_enable_interrupts(void) { + __asm__ volatile("sti"); +} + +static inline void arch_disable_interrupts(void) { + __asm__ volatile("cli"); +} + +static inline void arch_halt(void) { + __asm__ volatile("hlt"); +} + +static inline void arch_wait_for_interrupt(void) { + __asm__ volatile("sti; hlt"); +} + +static inline uint64_t arch_get_ticks(void) { + return pit_get_ticks(); +} + +static inline void arch_sleep(uint32_t ms) { + pit_sleep(ms); +} + +#elif defined(__aarch64__) || defined(__arm64__) +#define ARCH_NAME "aarch64" +#define ARCH_IS_64BIT 1 +#include +#include +#include +#include +#include +#include +#include + +static inline void arch_enable_interrupts(void) { + __asm__ volatile("msr daifclr, #2" ::: "memory"); +} + +static inline void arch_disable_interrupts(void) { + __asm__ volatile("msr daifset, #2" ::: "memory"); +} + +static inline void arch_halt(void) { + __asm__ volatile("wfi"); +} + +static inline void arch_wait_for_interrupt(void) { + __asm__ volatile("msr daifclr, #2; wfi" ::: "memory"); +} + +static inline uint64_t arch_get_ticks(void) { + return aarch64_timer_get_ticks(); +} + +static inline void arch_sleep(uint32_t ms) { + uint64_t count = (ms > 10) ? (ms / 10) : 1; + uint64_t target = aarch64_timer_get_ticks() + count; + while (aarch64_timer_get_ticks() < target) { + __asm__ volatile("wfi"); + } +} + +// Prototype declarations for timer/interrupt compatibility +uint64_t pit_get_ticks(void); +void pit_sleep(uint32_t ms); + +#else +#error "Unsupported Target CPU Architecture!" +#endif + +// Generic Architecture API +void arch_early_init(void); +void arch_init(void); +const char* arch_get_name(void); +uint32_t arch_get_cpu_id(void); + +#endif // _ARCH_ARCH_H diff --git a/include/arch/x86_64/cpuid.h b/include/arch/x86_64/cpuid.h index 1b5b7e2..7385caa 100644 --- a/include/arch/x86_64/cpuid.h +++ b/include/arch/x86_64/cpuid.h @@ -25,9 +25,17 @@ typedef struct { } cpu_info_t; static inline void cpuid(uint32_t leaf, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) { +#if defined(__x86_64__) __asm__ volatile("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(leaf), "c"(0)); +#else + (void)leaf; + if (eax) *eax = 0; + if (ebx) *ebx = 0; + if (ecx) *ecx = 0; + if (edx) *edx = 0; +#endif } void cpuid_detect(cpu_info_t* info); diff --git a/include/arch/x86_64/io.h b/include/arch/x86_64/io.h index 58c0cdd..88cc53f 100644 --- a/include/arch/x86_64/io.h +++ b/include/arch/x86_64/io.h @@ -3,6 +3,8 @@ #include +#if defined(__x86_64__) + static inline void outb(uint16_t port, uint8_t val) { __asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); } @@ -49,4 +51,20 @@ static inline void hlt(void) { __asm__ volatile ("hlt"); } +#else + +// Portable Stubs for non-x86 architectures +static inline void outb(uint16_t port, uint8_t val) { (void)port; (void)val; } +static inline uint8_t inb(uint16_t port) { (void)port; return 0; } +static inline void outw(uint16_t port, uint16_t val) { (void)port; (void)val; } +static inline uint16_t inw(uint16_t port) { (void)port; return 0; } +static inline void outl(uint16_t port, uint32_t val) { (void)port; (void)val; } +static inline uint32_t inl(uint16_t port) { (void)port; return 0; } +static inline void io_wait(void) { } +static inline void cli(void) { __asm__ volatile("msr daifset, #2" ::: "memory"); } +static inline void sti(void) { __asm__ volatile("msr daifclr, #2" ::: "memory"); } +static inline void hlt(void) { __asm__ volatile("wfi"); } + +#endif + #endif // _ARCH_X86_64_IO_H diff --git a/include/config/autoconf.h b/include/config/autoconf.h new file mode 100644 index 0000000..515a6ed --- /dev/null +++ b/include/config/autoconf.h @@ -0,0 +1,48 @@ +/* Automatically generated by SUB-OS Kconfig. Do not edit. */ +#ifndef _AUTOCONF_H +#define _AUTOCONF_H + +#define CONFIG_ARCH "aarch64" +#define CONFIG_ARCH_AARCH64 1 +#define CONFIG_BPF_VM 1 +#define CONFIG_DRV_AHCI 1 +#define CONFIG_DRV_ATA 1 +#define CONFIG_DRV_BOCHS_VBE 1 +#define CONFIG_DRV_CANVAS_2D 1 +#define CONFIG_DRV_E1000 1 +#define CONFIG_DRV_HWMON 1 +#define CONFIG_DRV_NVME 1 +#define CONFIG_DRV_PTY 1 +#define CONFIG_DRV_RAMDISK 1 +#define CONFIG_DRV_RTL8139 1 +#define CONFIG_DRV_SOUND_AC97 1 +#define CONFIG_DRV_SOUND_HDA 1 +#define CONFIG_DRV_USB_XHCI 1 +#define CONFIG_DRV_VIRTIO_BLK 1 +#define CONFIG_DRV_VIRTIO_NET 1 +#define CONFIG_DRV_VIRTIO_RNG 1 +#define CONFIG_FS_DEVFS 1 +#define CONFIG_FS_EXT2 1 +#define CONFIG_FS_FAT32 1 +#define CONFIG_FS_PROCFS 1 +#define CONFIG_FS_RAMFS 1 +#define CONFIG_FS_SYSFS 1 +#define CONFIG_FS_VFS 1 +#define CONFIG_IO_URING 1 +#define CONFIG_MM_PMM 1 +#define CONFIG_MM_SLAB 1 +#define CONFIG_MM_VMA 1 +#define CONFIG_NET_FILTER 1 +#define CONFIG_NET_HTTPD 1 +#define CONFIG_NET_SSHD 1 +#define CONFIG_NET_STACK 1 +#define CONFIG_OPTIMIZATION "-O2" +#define CONFIG_PREEMPT 1 +#define CONFIG_SECURITY_KEYRING 1 +#define CONFIG_SECURITY_LSM 1 +#define CONFIG_SMP 1 +#define CONFIG_SUBOS_HOSTNAME "sub-os" +#define CONFIG_SUBOS_VERSION "0.2.0-lts" +#define CONFIG_USERLAND_LAZYBOX 1 + +#endif /* _AUTOCONF_H */ diff --git a/include/init/version.h b/include/init/version.h index 8449c59..0a056de 100644 --- a/include/init/version.h +++ b/include/init/version.h @@ -5,9 +5,20 @@ #define SUBOS_VERSION_MINOR 2 #define SUBOS_VERSION_PATCH 0 #define SUBOS_VERSION_CODENAME "Titan" + +#if defined(__x86_64__) #define SUBOS_VERSION_STRING "0.2.0-lts (x86_64)" #define SUBOS_BUILD_TARGET "x86_64-elf-baremetal" -#define SUBOS_COMPILER "x86_64-elf-gcc (Modular Monolithic)" +#define SUBOS_COMPILER "x86_64-elf-gcc" +#elif defined(__aarch64__) +#define SUBOS_VERSION_STRING "0.2.0-lts (aarch64)" +#define SUBOS_BUILD_TARGET "aarch64-linux-gnu-baremetal" +#define SUBOS_COMPILER "aarch64-linux-gnu-gcc" +#else +#define SUBOS_VERSION_STRING "0.2.0-lts (generic)" +#define SUBOS_BUILD_TARGET "generic-elf-baremetal" +#define SUBOS_COMPILER "gcc" +#endif const char* kernel_get_version(void); const char* kernel_get_build_banner(void); diff --git a/include/kernel/kernel.h b/include/kernel/kernel.h index b92f138..18b0c91 100644 --- a/include/kernel/kernel.h +++ b/include/kernel/kernel.h @@ -3,7 +3,7 @@ #include "types.h" #include "printk.h" -#include +#include #define KERNEL_NAME "SUB-OS" #define KERNEL_VERSION "0.2.0-lts" diff --git a/include/kernel/sync.h b/include/kernel/sync.h index 1cefa8b..6fb6e21 100644 --- a/include/kernel/sync.h +++ b/include/kernel/sync.h @@ -16,7 +16,13 @@ static inline void spinlock_init(spinlock_t* lock) { static inline void spin_lock(spinlock_t* lock) { while (__atomic_test_and_set(&lock->lock, __ATOMIC_ACQUIRE)) { +#if defined(__x86_64__) __asm__ volatile ("pause"); +#elif defined(__aarch64__) + __asm__ volatile ("yield"); +#else + __asm__ volatile (""); +#endif } } diff --git a/kernel/main.c b/kernel/main.c index 1e7c5e0..b9c28be 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -17,13 +17,7 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include +#include #include #include #include @@ -81,83 +75,41 @@ #include #include -void kernel_main(void* memory_map, uint64_t memory_map_count) { - // 1. Console & Telemetry - tty_init(); - serial_init(); - printk_init(); - - printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET); - printk(ANSI_BRIGHT_CYAN " SUB-OS 64-Bit Production Modular Monolithic Kernel %s\n" ANSI_RESET, kernel_get_version()); - printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET); - - // 2. Early Boot Parameters & RTC Real-Time Clock - init_early("root=/dev/sda console=tty1 init=/bin/lazybox quiet"); - rtc_init(); - - // 3. CPU Architecture & Interrupts - printk(KERN_INFO "[1/18] Initializing 64-Bit GDT & TSS... "); - gdt_init(); - printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - - printk(KERN_INFO "[2/18] Initializing Interrupt Descriptor Table (IDT & ISRs)... "); - idt_init(); - isr_init(); - printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - - printk(KERN_INFO "[3/18] Remapping Dual 8259A PIC Controller... "); - pic_init(); - printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - - printk(KERN_INFO "[4/18] Configuring 8254 PIT Timer & High-Res Timer Wheel... "); - pit_init(100); - timer_wheel_init(); - printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - - // 4. Input & Power Drivers - printk(KERN_INFO "[5/18] Initializing PS/2 Keyboard, Mouse & ACPI... "); - keyboard_init(); - mouse_init(); - acpi_init(); - printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - - // 5. Memory Management: PMM + Dynamic Heap + SLAB Cache - printk(KERN_INFO "[6/18] Initializing Physical PMM, Dynamic Heap & SLAB Cache... "); - pmm_init(memory_map, memory_map_count); - heap_init(); - slab_init(); - vma_init(); - printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - - // 6. Storage & Block Layer - printk(KERN_INFO "[7/18] Initializing Block Layer, Ramdisk & Storage Controllers... "); +static void subos_modular_core_boot(void) { + // Storage & Block Layer + printk(KERN_INFO "[4/14] Initializing Block Layer & Storage Controllers... "); block_init(); ramdisk_init(); +#if defined(__x86_64__) ata_init(); ahci_init(); nvme_init(); +#endif virtio_blk_init(); printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - // 7. Bus & Devices - printk(KERN_INFO "[8/18] Enumerating PCI Bus, VirtIO, xHCI, VBE, Canvas & PTY... "); + // Bus & Devices + printk(KERN_INFO "[5/14] Enumerating System Devices, Canvas & PTY... "); +#if defined(__x86_64__) pci_init(); virt_init(); fb_init(); bochs_vbe_init(); - canvas_init(); - pty_init(); usb_init(); xhci_init(); - virtio_rng_init(); hwmon_init(); +#endif + canvas_init(); + pty_init(); + virtio_rng_init(); printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - // 7. Network Subsystem, NetFilter, HTTPD & SSH Server - printk(KERN_INFO "[9/18] Initializing Network Stack, NetFilter, HTTPD & SSHD... "); + // Network Subsystem, NetFilter, HTTPD & SSH Server + printk(KERN_INFO "[6/14] Initializing Network Stack, NetFilter, HTTPD & SSHD... "); filter_init(); httpd_init(); sshd_init(); +#if defined(__x86_64__) rtl8139_init(); virtio_net_init(); if (e1000_init()) { @@ -171,16 +123,22 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) { } else { printk(ANSI_YELLOW "No NIC detected\n" ANSI_RESET); } +#else + virtio_net_init(); + printk(ANSI_BRIGHT_GREEN "Online\n" ANSI_RESET); +#endif - // 8. Sound & Voice Synthesizer - printk(KERN_INFO "[10/18] Initializing Sound Architecture, Melody Player & Formant TTS... "); + // Sound & Voice Synthesizer +#if defined(__x86_64__) + printk(KERN_INFO "[7/14] Initializing Sound Architecture, Melody Player & Formant TTS... "); sound_init(); hda_init(); melody_init(); printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); +#endif - // 9. Crypto, Certificates, LSM Security, Authentication & Namespaces - printk(KERN_INFO "[11/18] Initializing X.509 Keyring, Shadow Auth & Namespaces... "); + // Crypto, Certificates, LSM Security, Authentication & Namespaces + printk(KERN_INFO "[8/14] Initializing X.509 Keyring, Shadow Auth & Namespaces... "); prng_seed(0, 0); certs_init(); security_init(); @@ -188,18 +146,18 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) { namespace_init(); printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - // 10. Inter-Process Communication - printk(KERN_INFO "[12/18] Initializing IPC Engine (Pipes, MsgQueues, SHM, Semaphores)... "); + // Inter-Process Communication + printk(KERN_INFO "[9/14] Initializing IPC Engine (Pipes, MsgQueues, SHM, Semaphores)... "); ipc_init(); printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - // 11. Asynchronous I/O Engine - printk(KERN_INFO "[13/18] Initializing io_uring Async Ring Engine... "); + // Asynchronous I/O Engine + printk(KERN_INFO "[10/14] Initializing io_uring Async Ring Engine... "); io_uring_init(); printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - // 12. Virtual File System & Multi-Filesystem Support - printk(KERN_INFO "[14/18] Mounting Virtual File System (VFS, devfs, procfs, sysfs)... "); + // Virtual File System & Multi-Filesystem Support + printk(KERN_INFO "[11/14] Mounting Virtual File System (VFS, devfs, procfs, sysfs)... "); vfs_init(); sysfs_init(); kobject_subsystem_init(); @@ -208,8 +166,8 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) { initramfs_init(); printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - // 13. Kernel Core: Signals, Modules, Syscalls, Tracing, Syslog, Metrics, Crond & Systemd - printk(KERN_INFO "[15/18] Initializing Syslog, Metrics, Cron, Tracing, BPF & Services... "); + // Kernel Core: Signals, Modules, Syscalls, Tracing, Syslog, Metrics, Crond & Systemd + printk(KERN_INFO "[12/14] Initializing Syslog, Metrics, Cron, Tracing, BPF & Services... "); signal_init(); workqueue_init(); syscall_init(); @@ -222,25 +180,82 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) { service_manager_init(); printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - // 14. Preemptive Multi-Tasking & Userland - printk(KERN_INFO "[16/18] Initializing Preemptive Task Scheduler & LazyBox... "); + // Preemptive Multi-Tasking & Userland + printk(KERN_INFO "[13/14] Initializing Preemptive Task Scheduler & LazyBox... "); sched_init(); lazybox_init(); printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - // 15. Hardware Interrupts - printk(KERN_INFO "[17/18] Enabling Hardware Interrupts... "); - sti(); + // Hardware Interrupts + printk(KERN_INFO "[14/14] Enabling Hardware Interrupts... "); + arch_enable_interrupts(); printk(ANSI_BRIGHT_GREEN "ACTIVE\n" ANSI_RESET); - // 16. Welcome & Launch Shell - printk(KERN_INFO "[18/18] Launching Userland Shell on TTY1... "); - printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); - + // Launch Shell +#if defined(__x86_64__) tty_clear(); +#endif shell_run(); while (1) { - hlt(); + arch_halt(); } } + +#if defined(__x86_64__) +void kernel_main(void* memory_map, uint64_t memory_map_count) { + tty_init(); + serial_init(); + printk_init(); + + printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET); + printk(ANSI_BRIGHT_CYAN " SUB-OS 64-Bit [%s] Modular Monolithic Kernel %s\n" ANSI_RESET, arch_get_name(), kernel_get_version()); + printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET); + + init_early("root=/dev/sda console=tty1 init=/bin/lazybox quiet"); + rtc_init(); + + printk(KERN_INFO "[1/14] Initializing 64-Bit GDT, IDT, PIC & PIT Timer... "); + arch_init(); + printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); + + printk(KERN_INFO "[2/14] Initializing PS/2 Keyboard, Mouse & ACPI... "); + keyboard_init(); + mouse_init(); + acpi_init(); + printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); + + printk(KERN_INFO "[3/14] Initializing Physical PMM, Dynamic Heap & SLAB Cache... "); + pmm_init(memory_map, memory_map_count); + heap_init(); + slab_init(); + vma_init(); + printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); + + subos_modular_core_boot(); +} +#elif defined(__aarch64__) +void kernel_main_aarch64(void) { + arch_early_init(); + printk_init(); + + printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET); + printk(ANSI_BRIGHT_CYAN " SUB-OS 64-Bit [%s] Modular Monolithic Kernel %s\n" ANSI_RESET, arch_get_name(), kernel_get_version()); + printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET); + + init_early("root=/dev/vda console=ttyAMA0 init=/bin/lazybox quiet"); + + printk(KERN_INFO "[1/14] Initializing AArch64 CPU, GICv2, Generic Timer & MMU... "); + arch_init(); + printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); + + printk(KERN_INFO "[2/14] Initializing Physical PMM, Dynamic Heap & SLAB Cache... "); + pmm_init(NULL, 0); + heap_init(); + slab_init(); + vma_init(); + printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET); + + subos_modular_core_boot(); +} +#endif diff --git a/kernel/panic.c b/kernel/panic.c index 0628e8e..89a77a6 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -1,10 +1,10 @@ #include #include #include -#include +#include void panic_with_regs(const char* message, const registers_t* regs) { - cli(); + arch_disable_interrupts(); printk("\n" ANSI_BRIGHT_RED "================================================================================" ANSI_RESET "\n"); printk(ANSI_BRIGHT_RED " *** KERNEL PANIC - SYSTEM HALTED *** " ANSI_RESET "\n"); @@ -12,7 +12,7 @@ void panic_with_regs(const char* message, const registers_t* regs) { printk(ANSI_BRIGHT_WHITE "Reason: " ANSI_YELLOW "%s" ANSI_RESET "\n\n", message ? message : "Unknown Fault"); if (regs) { - printk(ANSI_BRIGHT_CYAN "CPU Register State (x86_64 AMD64 ABI):" ANSI_RESET "\n"); + printk(ANSI_BRIGHT_CYAN "CPU Register State:" ANSI_RESET "\n"); printk(" RIP: %016llx CS: %04llx RFLAGS: %016llx\n", regs->rip, regs->cs, regs->rflags); printk(" RSP: %016llx SS: %04llx RBP: %016llx\n", regs->rsp, regs->ss, regs->rbp); printk(" RAX: %016llx RBX: %016llx RCX: %016llx RDX: %016llx\n", regs->rax, regs->rbx, regs->rcx, regs->rdx); @@ -24,7 +24,7 @@ void panic_with_regs(const char* message, const registers_t* regs) { printk("\n" ANSI_BRIGHT_YELLOW "Please power off or reset your system." ANSI_RESET "\n"); while (1) { - hlt(); + arch_halt(); } } diff --git a/kernel/printk.c b/kernel/printk.c index 3d382bc..2822883 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -45,10 +45,17 @@ int vprintk(const char* fmt, va_list args) { // 1. Output to active TTY console tty_write(display_ptr, (size_t)len); - // 2. Output to COM1 serial port for host debugging + // 2. Output to serial console (COM1 on x86, PL011 on AArch64) +#if defined(__aarch64__) + extern void uart_pl011_putc(char c); + for (int i = 0; i < len; i++) { + uart_pl011_putc(display_ptr[i]); + } +#else for (int i = 0; i < len; i++) { serial_write_char(display_ptr[i]); } +#endif // 3. Store in kernel dmesg ring buffer dmesg_append(display_ptr, (size_t)len); diff --git a/kernel/task.c b/kernel/task.c index 3df9e2d..d6c7fcd 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -2,6 +2,7 @@ #include #include #include +#include static pid_t next_pid = 1; static task_t* current_task = NULL; @@ -55,7 +56,7 @@ void task_exit(int exit_code) { sched_yield(); } while (1) { - __asm__ volatile("hlt"); + arch_halt(); } } diff --git a/mm/kmalloc.c b/mm/kmalloc.c index 3451013..60ad3dd 100644 --- a/mm/kmalloc.c +++ b/mm/kmalloc.c @@ -5,7 +5,7 @@ #include #define HEAP_MAGIC 0x53554248 // "SUBH" -#define HEAP_INITIAL_PAGES 1024 // 4 MB initial kernel heap +#define HEAP_INITIAL_PAGES 4096 // 16 MB initial kernel heap typedef struct heap_block { uint32_t magic; diff --git a/mm/pmm.c b/mm/pmm.c index 3164cd1..e9ca15f 100644 --- a/mm/pmm.c +++ b/mm/pmm.c @@ -49,18 +49,38 @@ void pmm_init(void* memory_map, uint64_t memory_map_count) { // Fallback if no E820 usable regions if (usable_memory_bytes == 0 || total_pages == 0) { +#if defined(__aarch64__) + uint64_t dram_start = 0x40000000; + uint64_t dram_size = 128ULL * 1024 * 1024; + uint64_t start_page = dram_start / PMM_PAGE_SIZE; + uint64_t count_pages = dram_size / PMM_PAGE_SIZE; + + total_pages = start_page + count_pages; + total_memory_bytes = dram_size; + usable_memory_bytes = dram_size; + + for (uint64_t p = 0; p < count_pages; p++) { + bitmap_clear(page_bitmap, start_page + p); + } + + // Reserve kernel & boot area (0x40000000 - 0x40800000: 8MB / 2048 pages) + for (uint64_t p = start_page; p < start_page + 2048; p++) { + bitmap_set(page_bitmap, p); + } +#else total_pages = 32768; // 128 MB total_memory_bytes = 128ULL * 1024 * 1024; usable_memory_bytes = 128ULL * 1024 * 1024; for (uint64_t p = 0; p < total_pages; p++) { bitmap_clear(page_bitmap, p); } - } - // Reserve lower 4 MB (bootloader, page tables, kernel image) - size_t kernel_reserved_pages = (4 * 1024 * 1024) / PMM_PAGE_SIZE; // 1024 pages - for (size_t p = 0; p < kernel_reserved_pages; p++) { - bitmap_set(page_bitmap, p); + // Reserve lower 4 MB (bootloader, page tables, kernel image) + size_t kernel_reserved_pages = (4 * 1024 * 1024) / PMM_PAGE_SIZE; // 1024 pages + for (size_t p = 0; p < kernel_reserved_pages; p++) { + bitmap_set(page_bitmap, p); + } +#endif } // Count actual used pages (bits set in bitmap up to total_pages) diff --git a/net/core/net.c b/net/core/net.c index 523d9a9..cb26191 100644 --- a/net/core/net.c +++ b/net/core/net.c @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #define MAX_ARP_ENTRIES 16 @@ -288,7 +288,7 @@ int net_ping(uint32_t target_ip, uint32_t count, uint32_t timeout_ms) { if (wait_ticks == 0) wait_ticks = 100; while (!ping_received && (pit_get_ticks() - t_start < wait_ticks)) { - __asm__ volatile ("hlt"); + arch_halt(); } if (ping_received && ping_id == p_id && ping_seq == seq) { diff --git a/scripts/kconfig/menuconfig.py b/scripts/kconfig/menuconfig.py new file mode 100755 index 0000000..c3ddb53 --- /dev/null +++ b/scripts/kconfig/menuconfig.py @@ -0,0 +1,386 @@ +#!/usr/bin/env python3 +""" +SUB-OS Linux-Style Interactive Kconfig Menuconfig (TUI) +Provides a full curses-based terminal configuration UI matching Linux menuconfig. +Generates .config and include/config/autoconf.h. +""" + +import sys +import os +import curses + +CONFIG_FILE = ".config" +AUTOCONF_HEADER = "include/config/autoconf.h" + +DEFAULTS = { + # Architecture + "CONFIG_ARCH": "x86_64", + "CONFIG_ARCH_X86_64": True, + "CONFIG_ARCH_AARCH64": False, + "CONFIG_ARCH_ARMV8I": False, + + # General Setup + "CONFIG_SUBOS_HOSTNAME": "sub-os", + "CONFIG_SUBOS_VERSION": "0.2.0-lts", + "CONFIG_SMP": True, + "CONFIG_PREEMPT": True, + "CONFIG_OPTIMIZATION": "-O2", + + # Memory Management + "CONFIG_MM_PMM": True, + "CONFIG_MM_SLAB": True, + "CONFIG_MM_VMA": True, + + # Filesystems + "CONFIG_FS_VFS": True, + "CONFIG_FS_FAT32": True, + "CONFIG_FS_EXT2": True, + "CONFIG_FS_RAMFS": True, + "CONFIG_FS_DEVFS": True, + "CONFIG_FS_PROCFS": True, + "CONFIG_FS_SYSFS": True, + + # Storage Drivers + "CONFIG_DRV_NVME": True, + "CONFIG_DRV_AHCI": True, + "CONFIG_DRV_ATA": True, + "CONFIG_DRV_VIRTIO_BLK": True, + "CONFIG_DRV_RAMDISK": True, + + # Network Drivers & Stack + "CONFIG_NET_STACK": True, + "CONFIG_DRV_E1000": True, + "CONFIG_DRV_RTL8139": True, + "CONFIG_DRV_VIRTIO_NET": True, + "CONFIG_NET_HTTPD": True, + "CONFIG_NET_SSHD": True, + "CONFIG_NET_FILTER": True, + + # Audio & Display + "CONFIG_DRV_SOUND_HDA": True, + "CONFIG_DRV_SOUND_AC97": True, + "CONFIG_DRV_BOCHS_VBE": True, + "CONFIG_DRV_CANVAS_2D": True, + + # Bus, Sensors & Crypto + "CONFIG_DRV_USB_XHCI": True, + "CONFIG_DRV_HWMON": True, + "CONFIG_DRV_VIRTIO_RNG": True, + "CONFIG_DRV_PTY": True, + + # Security & Advanced + "CONFIG_SECURITY_LSM": True, + "CONFIG_SECURITY_KEYRING": True, + "CONFIG_BPF_VM": True, + "CONFIG_IO_URING": True, + "CONFIG_USERLAND_LAZYBOX": True, +} + +MENU_STRUCTURE = [ + { + "title": "Target Architecture Selection", + "type": "submenu", + "items": [ + {"name": "CONFIG_ARCH_X86_64", "label": "x86_64 (64-Bit AMD64/Intel x86-64)", "type": "radio", "group": "arch", "val": "x86_64"}, + {"name": "CONFIG_ARCH_AARCH64", "label": "aarch64 (ARMv8-A 64-Bit Cortex/Neoverse)", "type": "radio", "group": "arch", "val": "aarch64"}, + {"name": "CONFIG_ARCH_ARMV8I", "label": "armv8i (ARMv8 Instruction Set Profile)", "type": "radio", "group": "arch", "val": "armv8i"}, + ] + }, + { + "title": "General Kernel Setup", + "type": "submenu", + "items": [ + {"name": "CONFIG_SMP", "label": "Symmetric Multi-Processing (SMP) Support", "type": "bool"}, + {"name": "CONFIG_PREEMPT", "label": "Preemptive Kernel Scheduling Model", "type": "bool"}, + {"name": "CONFIG_BPF_VM", "label": "In-Kernel eBPF Register Virtual Machine", "type": "bool"}, + {"name": "CONFIG_IO_URING", "label": "High-Performance io_uring Ring Buffers", "type": "bool"}, + ] + }, + { + "title": "Virtual File Systems & Storage Drivers", + "type": "submenu", + "items": [ + {"name": "CONFIG_FS_FAT32", "label": "FAT32 / VFAT File System Driver", "type": "bool"}, + {"name": "CONFIG_FS_EXT2", "label": "Second Extended (EXT2) Linux File System", "type": "bool"}, + {"name": "CONFIG_FS_SYSFS", "label": "Sysfs KObject Virtual Hierarchy (/sys)", "type": "bool"}, + {"name": "CONFIG_DRV_NVME", "label": "NVM Express (NVMe PCIe SSD) Driver", "type": "bool"}, + {"name": "CONFIG_DRV_AHCI", "label": "AHCI SATA 6Gb/s SSD/HDD Controller Driver", "type": "bool"}, + {"name": "CONFIG_DRV_VIRTIO_BLK", "label": "VirtIO Paravirtualized Block Storage (/dev/vda)", "type": "bool"}, + ] + }, + { + "title": "Network Subsystem & Hardware Adapters", + "type": "submenu", + "items": [ + {"name": "CONFIG_NET_STACK", "label": "TCP/IP Network Stack (IPv4, UDP, TCP)", "type": "bool"}, + {"name": "CONFIG_DRV_E1000", "label": "Intel 82540EM Gigabit Ethernet NIC Driver", "type": "bool"}, + {"name": "CONFIG_DRV_RTL8139", "label": "Realtek RTL8139 Fast Ethernet NIC Driver", "type": "bool"}, + {"name": "CONFIG_DRV_VIRTIO_NET", "label": "VirtIO 10-Gigabit Paravirtualized NIC", "type": "bool"}, + {"name": "CONFIG_NET_FILTER", "label": "NetFilter Stateful Packet Firewall (iptables)", "type": "bool"}, + {"name": "CONFIG_NET_SSHD", "label": "In-Kernel Secure Shell (SSH) Daemon", "type": "bool"}, + ] + }, + { + "title": "Device Drivers & Multimedia", + "type": "submenu", + "items": [ + {"name": "CONFIG_DRV_CANVAS_2D", "label": "2D TrueColor Rasterizer Canvas Graphics Engine", "type": "bool"}, + {"name": "CONFIG_DRV_BOCHS_VBE", "label": "Bochs / VBE Dynamic Resolution Display Adapter", "type": "bool"}, + {"name": "CONFIG_DRV_SOUND_HDA", "label": "Intel High Definition Audio (Azalia HDA) Driver", "type": "bool"}, + {"name": "CONFIG_DRV_SOUND_AC97", "label": "Analog Devices AC'97 Sound Codec Driver", "type": "bool"}, + {"name": "CONFIG_DRV_USB_XHCI", "label": "USB 3.0 Extensible Host Controller (xHCI)", "type": "bool"}, + {"name": "CONFIG_DRV_HWMON", "label": "HWMON CPU CoreTemp & Fan Tachometer Sensors", "type": "bool"}, + {"name": "CONFIG_DRV_VIRTIO_RNG", "label": "VirtIO True Hardware Random Generator (/dev/hwrng)", "type": "bool"}, + {"name": "CONFIG_DRV_PTY", "label": "Unix98 Pseudo-Terminal (PTY) Subsystem (/dev/pts)", "type": "bool"}, + ] + }, + { + "title": "Security, LSM & Keyrings", + "type": "submenu", + "items": [ + {"name": "CONFIG_SECURITY_LSM", "label": "Linux Security Module (LSM) Mandatory Access Control", "type": "bool"}, + {"name": "CONFIG_SECURITY_KEYRING", "label": "X.509 Cryptographic Keyring & Certificates", "type": "bool"}, + ] + }, + { + "title": "Userland Core & LazyBox", + "type": "submenu", + "items": [ + {"name": "CONFIG_USERLAND_LAZYBOX", "label": "LazyBox Multi-Call Userland Utility Suite (70+ Tools)", "type": "bool"}, + ] + } +] + +def load_config(): + cfg = dict(DEFAULTS) + if os.path.exists(CONFIG_FILE): + with open(CONFIG_FILE, "r") as f: + for line in f: + line = line.strip() + if not line or line.startswith("#"): + continue + if "=" in line: + k, v = line.split("=", 1) + k = k.strip() + v = v.strip().strip('"') + if v == "y": + cfg[k] = True + elif v == "n": + cfg[k] = False + else: + cfg[k] = v + return cfg + +def save_config(cfg): + os.makedirs(os.path.dirname(AUTOCONF_HEADER), exist_ok=True) + with open(CONFIG_FILE, "w") as f_cfg, open(AUTOCONF_HEADER, "w") as f_hdr: + f_cfg.write("# Automatically generated by SUB-OS Kconfig TUI Configurator\n# Do not edit directly\n\n") + f_hdr.write("/* Automatically generated by SUB-OS Kconfig. Do not edit. */\n#ifndef _AUTOCONF_H\n#define _AUTOCONF_H\n\n") + + # Write Architecture + arch = cfg.get("CONFIG_ARCH", "x86_64") + f_cfg.write(f"CONFIG_ARCH={arch}\n") + f_hdr.write(f'#define CONFIG_ARCH "{arch}"\n') + + for k, v in sorted(cfg.items()): + if k == "CONFIG_ARCH": + continue + if isinstance(v, bool): + if v: + f_cfg.write(f"{k}=y\n") + f_hdr.write(f"#define {k} 1\n") + else: + f_cfg.write(f"# {k} is not set\n") + elif isinstance(v, str): + f_cfg.write(f'{k}="{v}"\n') + f_hdr.write(f'#define {k} "{v}"\n') + elif isinstance(v, int): + f_cfg.write(f"{k}={v}\n") + f_hdr.write(f"#define {k} {v}\n") + + f_hdr.write("\n#endif /* _AUTOCONF_H */\n") + +def run_tui(stdscr): + curses.curs_set(0) + curses.use_default_colors() + curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_CYAN) # Header / Bar + curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLUE) # Main background + curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLUE) # Highlight title + curses.init_pair(4, curses.COLOR_BLACK, curses.COLOR_WHITE) # Selected row + curses.init_pair(5, curses.COLOR_CYAN, curses.COLOR_BLUE) # Subtext + + cfg = load_config() + current_menu = MENU_STRUCTURE + menu_stack = [] + cursor_stack = [0] + + while True: + stdscr.bkgd(' ', curses.color_pair(2)) + stdscr.clear() + max_y, max_x = stdscr.getmaxyx() + + # Top Banner + header = f" SUB-OS v{cfg.get('CONFIG_SUBOS_VERSION', '0.2.0-lts')} ({cfg.get('CONFIG_ARCH', 'x86_64')}) Linux-Style Kernel Configuration " + stdscr.attron(curses.color_pair(1) | curses.A_BOLD) + stdscr.addstr(0, 0, header.center(max_x - 1)[:max_x - 1]) + stdscr.attroff(curses.color_pair(1) | curses.A_BOLD) + + # Subtitle + stdscr.attron(curses.color_pair(3) | curses.A_BOLD) + title_text = "Main Menu" if not menu_stack else menu_stack[-1]["title"] + stdscr.addstr(2, 4, f"-> {title_text}") + stdscr.attroff(curses.color_pair(3) | curses.A_BOLD) + + # Instructions + stdscr.attron(curses.color_pair(5)) + stdscr.addstr(3, 4, "Use [UP/DOWN] arrows, [SPACE] to toggle [*], [ENTER] for submenu, [S] to Save, [Q] to Exit") + stdscr.attroff(curses.color_pair(5)) + + # Items list + items = current_menu if not menu_stack else menu_stack[-1]["items"] + cur_idx = cursor_stack[-1] + if cur_idx >= len(items): + cur_idx = len(items) - 1 + if cur_idx < 0: + cur_idx = 0 + cursor_stack[-1] = cur_idx + + box_top = 5 + box_height = max_y - 8 + + for i, item in enumerate(items): + if i >= box_height: + break + y = box_top + i + is_sel = (i == cur_idx) + + if "items" in item: # Submenu + display = f" ---> {item['title']}" + elif item.get("type") == "bool": + val = cfg.get(item["name"], False) + mark = "[*]" if val else "[ ]" + display = f" {mark} {item['label']}" + elif item.get("type") == "radio": + group_val = cfg.get("CONFIG_ARCH", "x86_64") + mark = "(*)" if group_val == item["val"] else "( )" + display = f" {mark} {item['label']}" + else: + display = f" {item.get('label', item.get('title', ''))}" + + if is_sel: + stdscr.attron(curses.color_pair(4) | curses.A_BOLD) + stdscr.addstr(y, 4, display.ljust(max_x - 10)[:max_x - 10]) + stdscr.attroff(curses.color_pair(4) | curses.A_BOLD) + else: + stdscr.attron(curses.color_pair(2)) + stdscr.addstr(y, 4, display[:max_x - 10]) + stdscr.attroff(curses.color_pair(2)) + + # Footer Status Bar + footer = "