From 7b646c8cc45e48678f517be5b44310281cf30ae2 Mon Sep 17 00:00:00 2001 From: subhobhai943 Date: Tue, 18 Aug 2026 11:13:23 +0530 Subject: [PATCH] feat(arch): Add armv8i (32-bit ARM/AArch32) architecture & complete TUI configurator - Support ARMv8i / ARM32 (AArch32) baremetal target with arm-linux-gnueabihf toolchain - Implement ARMv8i boot entry point, banked exception mode stacks (IRQ, ABT, UND, SVC) - Implement 8 exception vectors, GICv2 distributor/CPU interface, CP15 Generic Timer (100 Hz), flat Section MMU - Support PL011 UART for early console & interactive LazyBox TTY input - Update Makefile with make armv8i_defconfig and automated cross-compilation - Update scripts/kconfig/menuconfig.py with dedicated armv8i options --- Makefile | 47 ++++++++++++++--- arch/armv8i/boot/entry.S | 61 ++++++++++++++++++++++ arch/armv8i/configs/defconfig | 37 ++++++++++++++ arch/armv8i/cpu/arch.c | 60 ++++++++++++++++++++++ arch/armv8i/cpu/cpu.c | 41 +++++++++++++++ arch/armv8i/cpu/div0.c | 16 ++++++ arch/armv8i/cpu/exceptions.c | 68 +++++++++++++++++++++++++ arch/armv8i/cpu/gic.c | 62 +++++++++++++++++++++++ arch/armv8i/cpu/timer.c | 45 +++++++++++++++++ arch/armv8i/cpu/vectors.S | 87 ++++++++++++++++++++++++++++++++ arch/armv8i/drivers/uart_pl011.c | 38 ++++++++++++++ arch/armv8i/linker.ld | 51 +++++++++++++++++++ arch/armv8i/mm/mmu.c | 42 +++++++++++++++ drivers/char/keyboard.c | 6 ++- include/arch/arch.h | 43 +++++++++++++++- include/arch/armv8i/arch.h | 23 +++++++++ include/arch/armv8i/cpu.h | 21 ++++++++ include/arch/armv8i/gic.h | 37 ++++++++++++++ include/arch/armv8i/io.h | 75 +++++++++++++++++++++++++++ include/arch/armv8i/mmu.h | 20 ++++++++ include/arch/armv8i/timer.h | 13 +++++ include/arch/armv8i/uart.h | 24 +++++++++ include/config/autoconf.h | 4 +- include/init/version.h | 4 ++ include/kernel/sync.h | 20 +++++--- kernel/main.c | 24 +++++++++ kernel/printk.c | 4 +- mm/pmm.c | 2 +- scripts/kconfig/menuconfig.py | 8 ++- userland/lazybox/shell.c | 5 +- 30 files changed, 964 insertions(+), 24 deletions(-) create mode 100644 arch/armv8i/boot/entry.S create mode 100644 arch/armv8i/configs/defconfig create mode 100644 arch/armv8i/cpu/arch.c create mode 100644 arch/armv8i/cpu/cpu.c create mode 100644 arch/armv8i/cpu/div0.c create mode 100644 arch/armv8i/cpu/exceptions.c create mode 100644 arch/armv8i/cpu/gic.c create mode 100644 arch/armv8i/cpu/timer.c create mode 100644 arch/armv8i/cpu/vectors.S create mode 100644 arch/armv8i/drivers/uart_pl011.c create mode 100644 arch/armv8i/linker.ld create mode 100644 arch/armv8i/mm/mmu.c create mode 100644 include/arch/armv8i/arch.h create mode 100644 include/arch/armv8i/cpu.h create mode 100644 include/arch/armv8i/gic.h create mode 100644 include/arch/armv8i/io.h create mode 100644 include/arch/armv8i/mmu.h create mode 100644 include/arch/armv8i/timer.h create mode 100644 include/arch/armv8i/uart.h diff --git a/Makefile b/Makefile index 44576b9..f99937c 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,6 @@ ifeq ($(ARCH), x86_64) ASMFLAGS_BOOT = -f bin -I$(BOOT_DIR)/ LDFLAGS = -nostdlib -no-pie -T linker.ld - # 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 @@ -56,7 +55,7 @@ ifeq ($(ARCH), x86_64) -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),) +else ifneq ($(filter $(ARCH), aarch64 arm64),) CROSS_COMPILE ?= aarch64-linux-gnu- CC = $(CROSS_COMPILE)gcc LD = $(CROSS_COMPILE)ld @@ -78,13 +77,43 @@ else ifneq ($(filter $(ARCH), aarch64 armv8 armv8i),) 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 ifneq ($(filter $(ARCH), armv8i arm32 arm),) + CROSS_COMPILE ?= arm-linux-gnueabihf- + 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 \ + -O2 \ + -Iinclude \ + -D__arm__ \ + -D__armv8i__ \ + -mcpu=cortex-a15 \ + -mfpu=neon-vfpv4 \ + -mfloat-abi=hard \ + -marm + + LDFLAGS = -nostdlib -no-pie -T arch/armv8i/linker.ld + + ARCH_C_SRCS = $(shell find arch/armv8i -name '*.c' 2>/dev/null) + ARCH_S_SRCS = $(shell find arch/armv8i -name '*.S' 2>/dev/null) + ENTRY_OBJ = $(BUILD_DIR)/arch/armv8i/boot/entry.o + TARGET = $(BUILD_DIR)/kernel.elf + QEMU_CMD = qemu-system-arm -M virt -cpu cortex-a15 -m 128M -nographic -kernel $(BUILD_DIR)/kernel.elf + else $(error Unsupported Architecture '$(ARCH)'. Supported: x86_64, aarch64, armv8i) endif @@ -145,7 +174,7 @@ x86_64_defconfig: aarch64_defconfig: @python3 scripts/kconfig/menuconfig.py --aarch64 -armv8_defconfig armv8i_defconfig: +armv8_defconfig armv8i_defconfig arm32_defconfig: @python3 scripts/kconfig/menuconfig.py --armv8i # ----------------------------------------------------------------------------- @@ -161,7 +190,7 @@ $(BUILD_DIR)/%.o: %.asm @mkdir -p $(dir $@) $(ASM) $(ASMFLAGS_ELF) $< -o $@ -# AArch64 GNU Assembly Files (.S) +# ARM/AArch64 GNU Assembly Files (.S) $(BUILD_DIR)/%.o: %.S @mkdir -p $(dir $@) $(CC) $(CFLAGS) -c $< -o $@ @@ -178,8 +207,10 @@ $(BUILD_DIR)/boot/stage2.bin: $(BOOT_DIR)/stage2.asm $(BOOT_DIR)/gdt.asm | $(BUI $(BUILD_DIR)/boot: mkdir -p $(BUILD_DIR)/boot +LIBGCC ?= $(shell $(CC) $(CFLAGS) -print-libgcc-file-name 2>/dev/null) + $(BUILD_DIR)/kernel.elf: $(ENTRY_OBJ) $(OTHER_OBJS) - $(LD) $(LDFLAGS) -o $@ $(ENTRY_OBJ) $(OTHER_OBJS) + $(LD) $(LDFLAGS) -o $@ $(ENTRY_OBJ) $(OTHER_OBJS) $(LIBGCC) @echo "=== [Kernel ELF Linked: $@ (Architecture: $(ARCH))] ===" $(BUILD_DIR)/kernel.bin: $(BUILD_DIR)/kernel.elf @@ -208,8 +239,10 @@ 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 +else ifneq ($(filter $(ARCH), aarch64 arm64),) qemu-system-aarch64 -M virt -cpu cortex-a57 -m 128M -nographic -kernel $(BUILD_DIR)/kernel.elf -s -S +else + qemu-system-arm -M virt -cpu cortex-a15 -m 128M -nographic -kernel $(BUILD_DIR)/kernel.elf -s -S endif info: diff --git a/arch/armv8i/boot/entry.S b/arch/armv8i/boot/entry.S new file mode 100644 index 0000000..359646d --- /dev/null +++ b/arch/armv8i/boot/entry.S @@ -0,0 +1,61 @@ +/* + * SUB-OS ARMv8i (AArch32 / 32-Bit ARMv8) Bootstrap Entry Point + */ + +.syntax unified +.arm +.section ".text.boot" +.global _start +.global armv8i_entry + +_start: +armv8i_entry: + // 1. Enable VFP and NEON Coprocessors (CP10 & CP11 Full Access) + mrc p15, 0, r0, c1, c0, 2 // Read CPACR + orr r0, r0, #(0xF << 20) // Enable CP10 and CP11 + mcr p15, 0, r0, c1, c0, 2 // Write CPACR + isb + + // Enable VFP extension run (FPEXC.EN = 1) + mov r0, #(1 << 30) + vmsr fpexc, r0 + + // 2. Clear SCTLR.V bit (bit 13) to use VBAR for exception vectors + mrc p15, 0, r0, c1, c0, 0 // Read SCTLR + bic r0, r0, #(1 << 13) // Clear Hivecs (V=0) + mcr p15, 0, r0, c1, c0, 0 // Write SCTLR + isb + + // 3. Set Vector Base Address Register (VBAR) + ldr r0, =vectors + mcr p15, 0, r0, c12, c0, 0 // Write VBAR + isb + + // 4. Setup Banked Stack Pointers for Exception Modes + cpsid if, #0x12 // Switch to IRQ mode + ldr sp, =irq_stack_top + + cpsid if, #0x17 // Switch to Abort mode + ldr sp, =abt_stack_top + + cpsid if, #0x1B // Switch to Undefined mode + ldr sp, =und_stack_top + + cpsid if, #0x13 // Switch back to Supervisor mode (SVC) + ldr sp, =stack_top + + // 5. Zero out BSS section + ldr r0, =__bss_start + ldr r1, =__bss_end + mov r2, #0 +.bss_loop: + cmp r0, r1 + strlt r2, [r0], #4 + blt .bss_loop + + // 6. Branch to ARMv8i C Kernel Entry + bl kernel_main_armv8i + +.hang: + wfi + b .hang diff --git a/arch/armv8i/configs/defconfig b/arch/armv8i/configs/defconfig new file mode 100644 index 0000000..8f02772 --- /dev/null +++ b/arch/armv8i/configs/defconfig @@ -0,0 +1,37 @@ +# +# Automatically generated by SUB-OS Kconfig for armv8i +# +CONFIG_ARCH=armv8i +CONFIG_ARCH_ARMV8I=y +# CONFIG_ARCH_X86_64 is not set +# CONFIG_ARCH_AARCH64 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/armv8i/cpu/arch.c b/arch/armv8i/cpu/arch.c new file mode 100644 index 0000000..92fc7c1 --- /dev/null +++ b/arch/armv8i/cpu/arch.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static cpu_info_t armv8i_compat_cpu; + +void arch_early_init(void) { + uart_pl011_init(); + armv8i_mmu_init(); +} + +void arch_init(void) { + armv8i_cpu_init(); + gic_init(); + armv8i_timer_init(100); + + // Populate compatibility CPU info structure for procfs / uname + memset(&armv8i_compat_cpu, 0, sizeof(armv8i_compat_cpu)); + const armv8i_cpu_info_t* info = armv8i_get_cpu_info(); + strncpy(armv8i_compat_cpu.vendor, "ARM Ltd", sizeof(armv8i_compat_cpu.vendor) - 1); + strncpy(armv8i_compat_cpu.model, info->model_name, sizeof(armv8i_compat_cpu.model) - 1); + armv8i_compat_cpu.has_fpu = true; + + arch_enable_interrupts(); +} + +const char* arch_get_name(void) { + return "armv8i (AArch32)"; +} + +uint32_t arch_get_cpu_id(void) { + return armv8i_get_mpidr() & 0xFF; +} + +// Timer Compatibility Layer +uint64_t pit_get_ticks(void) { + return armv8i_timer_get_ticks(); +} + +void pit_sleep(uint32_t ms) { + uint64_t count = (ms > 10) ? (ms / 10) : 1; + uint64_t target = armv8i_timer_get_ticks() + count; + while (armv8i_timer_get_ticks() < target) { + __asm__ volatile("wfi"); + } +} + +// Stubs for x86-specific driver compatibility +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 &armv8i_compat_cpu; +} diff --git a/arch/armv8i/cpu/cpu.c b/arch/armv8i/cpu/cpu.c new file mode 100644 index 0000000..1ca6839 --- /dev/null +++ b/arch/armv8i/cpu/cpu.c @@ -0,0 +1,41 @@ +#include +#include +#include + +static armv8i_cpu_info_t global_cpu_info; + +uint32_t armv8i_get_midr(void) { + uint32_t midr; + __asm__ volatile("mrc p15, 0, %0, c0, c0, 0" : "=r"(midr)); + return midr; +} + +uint32_t armv8i_get_mpidr(void) { + uint32_t mpidr; + __asm__ volatile("mrc p15, 0, %0, c0, c0, 5" : "=r"(mpidr)); + return mpidr; +} + +void armv8i_cpu_init(void) { + memset(&global_cpu_info, 0, sizeof(global_cpu_info)); + global_cpu_info.midr = armv8i_get_midr(); + global_cpu_info.mpidr = armv8i_get_mpidr(); + global_cpu_info.implementer = (global_cpu_info.midr >> 24) & 0xFF; + global_cpu_info.part_number = (global_cpu_info.midr >> 4) & 0xFFF; + global_cpu_info.architecture = (global_cpu_info.midr >> 16) & 0xF; + + const char* part_str = "ARM Cortex-A (ARMv8i 32-Bit)"; + if (global_cpu_info.part_number == 0xC0F) part_str = "ARM Cortex-A15 (ARMv7-A/v8i)"; + else if (global_cpu_info.part_number == 0xC07) part_str = "ARM Cortex-A7 (ARMv7-A/v8i)"; + else if (global_cpu_info.part_number == 0xD03) part_str = "ARM Cortex-A53 (AArch32)"; + else if (global_cpu_info.part_number == 0xD07) part_str = "ARM Cortex-A57 (AArch32)"; + + strncpy(global_cpu_info.model_name, part_str, sizeof(global_cpu_info.model_name) - 1); + + printk(KERN_INFO "CPU: %s (Implementer: 0x%02x, Part: 0x%03x, AArch32)\n", + global_cpu_info.model_name, global_cpu_info.implementer, global_cpu_info.part_number); +} + +const armv8i_cpu_info_t* armv8i_get_cpu_info(void) { + return &global_cpu_info; +} diff --git a/arch/armv8i/cpu/div0.c b/arch/armv8i/cpu/div0.c new file mode 100644 index 0000000..fcfc030 --- /dev/null +++ b/arch/armv8i/cpu/div0.c @@ -0,0 +1,16 @@ +/* + * SUB-OS ARMv8i Division-by-Zero and POSIX Signal Stub + */ + +#include + +int raise(int sig) { + (void)sig; + return 0; +} + +void __aeabi_idiv0(void) { +} + +void __aeabi_ldiv0(void) { +} diff --git a/arch/armv8i/cpu/exceptions.c b/arch/armv8i/cpu/exceptions.c new file mode 100644 index 0000000..329c228 --- /dev/null +++ b/arch/armv8i/cpu/exceptions.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include + +typedef struct { + uint32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12; + uint32_t lr; + uint32_t spsr; +} armv8i_registers_t; + +static void hex_to_str(uint32_t val, char* out) { + const char hex_chars[] = "0123456789ABCDEF"; + out[0] = '0'; out[1] = 'x'; + for (int i = 7; i >= 0; i--) { + out[2 + (7 - i)] = hex_chars[(val >> (i * 4)) & 0xF]; + } + out[10] = '\0'; +} + +void armv8i_undef_handler(armv8i_registers_t* regs) { + char buf[16]; + hex_to_str(regs->lr, buf); + uart_pl011_puts("\n[KERNEL PANIC] ARMv8i Undefined Instruction at PC="); + uart_pl011_puts(buf); + uart_pl011_puts("\n"); + while (1) { __asm__ volatile("wfi"); } +} + +void armv8i_svc_handler(armv8i_registers_t* regs) { + (void)regs; +} + +void armv8i_pabt_handler(armv8i_registers_t* regs) { + char buf[16]; + hex_to_str(regs->lr, buf); + uart_pl011_puts("\n[KERNEL PANIC] ARMv8i Prefetch Abort at PC="); + uart_pl011_puts(buf); + uart_pl011_puts("\n"); + while (1) { __asm__ volatile("wfi"); } +} + +void armv8i_dabt_handler(armv8i_registers_t* regs) { + char buf[16]; + hex_to_str(regs->lr, buf); + uart_pl011_puts("\n[KERNEL PANIC] ARMv8i Data Abort at PC="); + uart_pl011_puts(buf); + uart_pl011_puts("\n"); + while (1) { __asm__ volatile("wfi"); } +} + +void armv8i_irq_handler(armv8i_registers_t* regs) { + (void)regs; + uint32_t iar = *(volatile uint32_t*)GICC_IAR; + uint32_t irq = iar & 0x3FF; + + if (irq < 1020) { + if (irq == ARMV8I_TIMER_VIRT_IRQ) { + armv8i_timer_handle_irq(); + } + *(volatile uint32_t*)GICC_EOIR = iar; + } +} + +void armv8i_fiq_handler(armv8i_registers_t* regs) { + (void)regs; +} diff --git a/arch/armv8i/cpu/gic.c b/arch/armv8i/cpu/gic.c new file mode 100644 index 0000000..899da08 --- /dev/null +++ b/arch/armv8i/cpu/gic.c @@ -0,0 +1,62 @@ +#include +#include +#include + +void gic_init(void) { + // 1. Disable Distributor and CPU interface during configuration + mmio_write32(GICD_CTLR, 0); + mmio_write32(GICC_CTLR, 0); + + // 2. Query lines count (TYPER ITLinesNumber) + uint32_t typer = mmio_read32(GICD_TYPER); + uint32_t lines = 32 * ((typer & 0x1F) + 1); + + // 3. Disable all interrupts & clear pending + for (uint32_t i = 0; i < lines / 32; i++) { + mmio_write32(GICD_ICENABLER(i), 0xFFFFFFFF); + mmio_write32(GICD_ICPENDR(i), 0xFFFFFFFF); + } + + // 4. Default priority 0xA0 and target CPU 0 (0x01) + for (uint32_t i = 0; i < lines / 4; i++) { + mmio_write32(GICD_IPRIORITYR(i), 0xA0A0A0A0); + } + for (uint32_t i = 8; i < lines / 4; i++) { + mmio_write32(GICD_ITARGETSR(i), 0x01010101); + } + + // 5. Enable Distributor (Group 0 & 1) + mmio_write32(GICD_CTLR, 3); + + // 6. Set CPU Interface Priority Mask to allow all interrupts (0xF0) + mmio_write32(GICC_PMR, 0xF0); + + // 7. Enable CPU Interface (Group 0 & 1) + mmio_write32(GICC_CTLR, 3); + + // 8. Unmask Virtual Timer PPI 27 + gic_enable_irq(27); + + printk(KERN_INFO "GIC: ARM Generic Interrupt Controller v2 initialized (%u IRQ lines)\n", lines); +} + +void gic_enable_irq(uint32_t irq) { + uint32_t reg_idx = irq / 32; + uint32_t bit_idx = irq % 32; + mmio_write32(GICD_ISENABLER(reg_idx), (1 << bit_idx)); +} + +void gic_disable_irq(uint32_t irq) { + uint32_t reg_idx = irq / 32; + uint32_t bit_idx = irq % 32; + mmio_write32(GICD_ICENABLER(reg_idx), (1 << bit_idx)); +} + +void gic_set_priority(uint32_t irq, uint8_t prio) { + uint32_t reg_idx = irq / 4; + uint32_t shift = (irq % 4) * 8; + uint32_t val = mmio_read32(GICD_IPRIORITYR(reg_idx)); + val &= ~(0xFF << shift); + val |= ((uint32_t)prio << shift); + mmio_write32(GICD_IPRIORITYR(reg_idx), val); +} diff --git a/arch/armv8i/cpu/timer.c b/arch/armv8i/cpu/timer.c new file mode 100644 index 0000000..098ac63 --- /dev/null +++ b/arch/armv8i/cpu/timer.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +static volatile uint64_t armv8i_timer_ticks = 0; +static uint32_t timer_freq = 0; +static uint32_t tick_interval = 0; + +uint64_t armv8i_timer_get_ticks(void) { + return armv8i_timer_ticks; +} + +uint64_t armv8i_timer_get_frequency(void) { + return timer_freq; +} + +void armv8i_timer_handle_irq(void) { + armv8i_timer_ticks++; + + // Reset comparator for next tick + __asm__ volatile("mcr p15, 0, %0, c14, c3, 0" :: "r"(tick_interval)); + + timer_tick(); +} + +void armv8i_timer_init(uint32_t freq_hz) { + // 1. Read base counter frequency (CNTFRQ) + __asm__ volatile("mrc p15, 0, %0, c14, c0, 0" : "=r"(timer_freq)); + if (timer_freq == 0) { + timer_freq = 62500000; // 62.5 MHz default in QEMU virt + } + + tick_interval = timer_freq / (freq_hz ? freq_hz : 100); + + // 2. Set interval in CNTV_TVAL + __asm__ volatile("mcr p15, 0, %0, c14, c3, 0" :: "r"(tick_interval)); + + // 3. Enable Virtual Timer (ENABLE=1, IMASK=0 in CNTV_CTL) + uint32_t ctl = 1; + __asm__ volatile("mcr p15, 0, %0, c14, c3, 1" :: "r"(ctl)); + + printk(KERN_INFO "Timer: ARM Generic Arch Timer active (%u Hz, Base Clock: %u MHz)\n", + freq_hz, timer_freq / 1000000); +} diff --git a/arch/armv8i/cpu/vectors.S b/arch/armv8i/cpu/vectors.S new file mode 100644 index 0000000..83d51b9 --- /dev/null +++ b/arch/armv8i/cpu/vectors.S @@ -0,0 +1,87 @@ +/* + * SUB-OS ARMv8i (AArch32) Exception Vector Table + */ + +.syntax unified +.arm +.section ".vectors", "ax" +.align 5 +.global vectors + +vectors: + ldr pc, =reset_handler + ldr pc, =undef_handler + ldr pc, =svc_handler + ldr pc, =pabt_handler + ldr pc, =dabt_handler + ldr pc, =hyp_handler + ldr pc, =irq_handler + ldr pc, =fiq_handler + +.macro SAVE_REGS + sub sp, sp, #72 + stmia sp, {r0 - r12} + str lr, [sp, #52] + mrs r0, spsr + str r0, [sp, #56] +.endm + +.macro RESTORE_REGS + ldr r0, [sp, #56] + msr spsr_cxsf, r0 + ldr lr, [sp, #52] + ldmia sp, {r0 - r12} + add sp, sp, #72 +.endm + +reset_handler: + b _start + +undef_handler: + SAVE_REGS + mov r0, sp + bl armv8i_undef_handler + RESTORE_REGS + movs pc, lr + +svc_handler: + SAVE_REGS + mov r0, sp + bl armv8i_svc_handler + RESTORE_REGS + movs pc, lr + +pabt_handler: + sub lr, lr, #4 + SAVE_REGS + mov r0, sp + bl armv8i_pabt_handler + RESTORE_REGS + movs pc, lr + +dabt_handler: + sub lr, lr, #8 + SAVE_REGS + mov r0, sp + bl armv8i_dabt_handler + RESTORE_REGS + movs pc, lr + +hyp_handler: + b . + +irq_handler: + sub lr, lr, #4 + SAVE_REGS + mov r0, sp + bl armv8i_irq_handler + RESTORE_REGS + movs pc, lr + +fiq_handler: + sub lr, lr, #4 + SAVE_REGS + mov r0, sp + bl armv8i_fiq_handler + RESTORE_REGS + movs pc, lr diff --git a/arch/armv8i/drivers/uart_pl011.c b/arch/armv8i/drivers/uart_pl011.c new file mode 100644 index 0000000..8f6656c --- /dev/null +++ b/arch/armv8i/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/armv8i/linker.ld b/arch/armv8i/linker.ld new file mode 100644 index 0000000..0c553b9 --- /dev/null +++ b/arch/armv8i/linker.ld @@ -0,0 +1,51 @@ +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +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) { + . += 0x4000; /* 16 KB IRQ Stack */ + irq_stack_top = .; + . += 0x2000; /* 8 KB ABT Stack */ + abt_stack_top = .; + . += 0x2000; /* 8 KB UND Stack */ + und_stack_top = .; + . += 0x10000; /* 64 KB SVC Kernel Stack */ + stack_top = .; + } + + __kernel_end = .; +} diff --git a/arch/armv8i/mm/mmu.c b/arch/armv8i/mm/mmu.c new file mode 100644 index 0000000..88cdf35 --- /dev/null +++ b/arch/armv8i/mm/mmu.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include + +static uint32_t __attribute__((aligned(16384))) l1_page_table[4096]; + +void armv8i_mmu_init(void) { + // 1. Identity map the entire 4GB flat space with 1MB sections + for (uint32_t i = 0; i < 4096; i++) { + uint32_t phys = i * 0x100000; + l1_page_table[i] = phys | (3 << 10) | (2 << 0); + } + + // 2. Set Domain Access Control Register (DACR = 0xFFFFFFFF: All Manager) + uint32_t dacr = 0xFFFFFFFF; + __asm__ volatile("mcr p15, 0, %0, c3, c0, 0" :: "r"(dacr)); + + // 3. Set Translation Table Base Control Register (TTBCR = 0) + uint32_t ttbcr = 0; + __asm__ volatile("mcr p15, 0, %0, c2, c0, 2" :: "r"(ttbcr)); + + // 4. Set Translation Table Base Register 0 (TTBR0) + uint32_t ttbr0 = (uint32_t)l1_page_table; + __asm__ volatile("mcr p15, 0, %0, c2, c0, 0" :: "r"(ttbr0)); + + // 5. Invalidate TLB & ICache + uint32_t zero = 0; + __asm__ volatile("mcr p15, 0, %0, c8, c7, 0" :: "r"(zero)); + __asm__ volatile("mcr p15, 0, %0, c7, c5, 0" :: "r"(zero)); + isb(); + dsb(); + + // 6. Enable MMU and Branch Prediction in SCTLR + uint32_t sctlr; + __asm__ volatile("mrc p15, 0, %0, c1, c0, 0" : "=r"(sctlr)); + sctlr |= (1 << 0) | (1 << 11); + __asm__ volatile("mcr p15, 0, %0, c1, c0, 0" :: "r"(sctlr)); + + isb(); + dsb(); +} diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 0874f22..cce6fe5 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -125,10 +125,12 @@ void keyboard_init(void) { #if defined(__aarch64__) #include +#elif defined(__arm__) || defined(__armv8i__) +#include #endif bool keyboard_has_key(void) { -#if defined(__aarch64__) +#if defined(__aarch64__) || defined(__arm__) || defined(__armv8i__) if (uart_pl011_has_data()) return true; #endif return buffer_head != buffer_tail; @@ -138,7 +140,7 @@ uint16_t keyboard_get_key(void) { while (!keyboard_has_key()) { arch_halt(); } -#if defined(__aarch64__) +#if defined(__aarch64__) || defined(__arm__) || defined(__armv8i__) if (uart_pl011_has_data()) { char c = uart_pl011_getc(); if (c == '\r') c = '\n'; diff --git a/include/arch/arch.h b/include/arch/arch.h index 8a81221..4de0911 100644 --- a/include/arch/arch.h +++ b/include/arch/arch.h @@ -79,7 +79,48 @@ static inline void arch_sleep(uint32_t ms) { } } -// Prototype declarations for timer/interrupt compatibility +uint64_t pit_get_ticks(void); +void pit_sleep(uint32_t ms); + +#elif defined(__arm__) || defined(__armv8i__) +#define ARCH_NAME "armv8i" +#define ARCH_IS_64BIT 0 +#include +#include +#include +#include +#include +#include +#include + +static inline void arch_enable_interrupts(void) { + __asm__ volatile("cpsie i" ::: "memory"); +} + +static inline void arch_disable_interrupts(void) { + __asm__ volatile("cpsid i" ::: "memory"); +} + +static inline void arch_halt(void) { + __asm__ volatile("wfi"); +} + +static inline void arch_wait_for_interrupt(void) { + __asm__ volatile("cpsie i; wfi" ::: "memory"); +} + +static inline uint64_t arch_get_ticks(void) { + return armv8i_timer_get_ticks(); +} + +static inline void arch_sleep(uint32_t ms) { + uint64_t count = (ms > 10) ? (ms / 10) : 1; + uint64_t target = armv8i_timer_get_ticks() + count; + while (armv8i_timer_get_ticks() < target) { + __asm__ volatile("wfi"); + } +} + uint64_t pit_get_ticks(void); void pit_sleep(uint32_t ms); diff --git a/include/arch/armv8i/arch.h b/include/arch/armv8i/arch.h new file mode 100644 index 0000000..d70621e --- /dev/null +++ b/include/arch/armv8i/arch.h @@ -0,0 +1,23 @@ +#ifndef _ARCH_ARMV8I_ARCH_H +#define _ARCH_ARMV8I_ARCH_H + +#include +#include + +#define ARMV8I_PAGE_SIZE 4096 + +// Mode bits in CPSR +#define CPSR_MODE_USR 0x10 +#define CPSR_MODE_FIQ 0x11 +#define CPSR_MODE_IRQ 0x12 +#define CPSR_MODE_SVC 0x13 +#define CPSR_MODE_MON 0x16 +#define CPSR_MODE_ABT 0x17 +#define CPSR_MODE_HYP 0x1A +#define CPSR_MODE_UND 0x1B +#define CPSR_MODE_SYS 0x1F + +#define CPSR_IRQ_DISABLE (1 << 7) +#define CPSR_FIQ_DISABLE (1 << 6) + +#endif // _ARCH_ARMV8I_ARCH_H diff --git a/include/arch/armv8i/cpu.h b/include/arch/armv8i/cpu.h new file mode 100644 index 0000000..181ef64 --- /dev/null +++ b/include/arch/armv8i/cpu.h @@ -0,0 +1,21 @@ +#ifndef _ARCH_ARMV8I_CPU_H +#define _ARCH_ARMV8I_CPU_H + +#include +#include + +typedef struct { + uint32_t midr; + uint32_t mpidr; + uint32_t implementer; + uint32_t part_number; + uint32_t architecture; + char model_name[64]; +} armv8i_cpu_info_t; + +void armv8i_cpu_init(void); +const armv8i_cpu_info_t* armv8i_get_cpu_info(void); +uint32_t armv8i_get_midr(void); +uint32_t armv8i_get_mpidr(void); + +#endif // _ARCH_ARMV8I_CPU_H diff --git a/include/arch/armv8i/gic.h b/include/arch/armv8i/gic.h new file mode 100644 index 0000000..671e478 --- /dev/null +++ b/include/arch/armv8i/gic.h @@ -0,0 +1,37 @@ +#ifndef _ARCH_ARMV8I_GIC_H +#define _ARCH_ARMV8I_GIC_H + +#include +#include + +#define GICD_BASE 0x08000000 +#define GICC_BASE 0x08010000 + +// Distributor Registers +#define GICD_CTLR (GICD_BASE + 0x000) +#define GICD_TYPER (GICD_BASE + 0x004) +#define GICD_IIDR (GICD_BASE + 0x008) +#define GICD_ISENABLER(n) (GICD_BASE + 0x100 + ((n) * 4)) +#define GICD_ICENABLER(n) (GICD_BASE + 0x180 + ((n) * 4)) +#define GICD_ISPENDR(n) (GICD_BASE + 0x200 + ((n) * 4)) +#define GICD_ICPENDR(n) (GICD_BASE + 0x280 + ((n) * 4)) +#define GICD_IPRIORITYR(n) (GICD_BASE + 0x400 + ((n) * 4)) +#define GICD_ITARGETSR(n) (GICD_BASE + 0x800 + ((n) * 4)) +#define GICD_ICFGR(n) (GICD_BASE + 0xC00 + ((n) * 4)) + +// CPU Interface Registers +#define GICC_CTLR (GICC_BASE + 0x000) +#define GICC_PMR (GICC_BASE + 0x004) +#define GICC_BPR (GICC_BASE + 0x008) +#define GICC_IAR (GICC_BASE + 0x00C) +#define GICC_EOIR (GICC_BASE + 0x010) + +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_set_priority(uint32_t irq, uint8_t prio); +void gic_register_handler(uint32_t irq, gic_irq_handler_t handler); + +#endif // _ARCH_ARMV8I_GIC_H diff --git a/include/arch/armv8i/io.h b/include/arch/armv8i/io.h new file mode 100644 index 0000000..9491715 --- /dev/null +++ b/include/arch/armv8i/io.h @@ -0,0 +1,75 @@ +#ifndef _ARCH_ARMV8I_IO_H +#define _ARCH_ARMV8I_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 uint32_t*)reg = (uint32_t)(val & 0xFFFFFFFF); + *(volatile uint32_t*)(reg + 4) = (uint32_t)(val >> 32); +} + +static inline uint64_t mmio_read64(uintptr_t reg) { + uint32_t low = *(volatile uint32_t*)reg; + uint32_t high = *(volatile uint32_t*)(reg + 4); + return ((uint64_t)high << 32) | low; +} + +// Memory barriers +static inline void dsb(void) { + __asm__ volatile("dsb" ::: "memory"); +} + +static inline void dmb(void) { + __asm__ volatile("dmb" ::: "memory"); +} + +static inline void isb(void) { + __asm__ volatile("isb" ::: "memory"); +} + +// x86 Port I/O Stubs +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("cpsid i" ::: "memory"); +} + +static inline void sti(void) { + __asm__ volatile("cpsie i" ::: "memory"); +} + +static inline void hlt(void) { + __asm__ volatile("wfi"); +} + +#endif // _ARCH_ARMV8I_IO_H diff --git a/include/arch/armv8i/mmu.h b/include/arch/armv8i/mmu.h new file mode 100644 index 0000000..c2c5176 --- /dev/null +++ b/include/arch/armv8i/mmu.h @@ -0,0 +1,20 @@ +#ifndef _ARCH_ARMV8I_MMU_H +#define _ARCH_ARMV8I_MMU_H + +#include + +// VMSAv7 1MB Section Descriptor Flags +#define SECTION_TYPE_MASK (3 << 0) +#define SECTION_TYPE_FAULT (0 << 0) +#define SECTION_TYPE_SECTION (2 << 0) +#define SECTION_BUFFERABLE (1 << 2) +#define SECTION_CACHEABLE (1 << 3) +#define SECTION_AP_RW_ALL (3 << 10) +#define SECTION_TEX_DEVICE (0 << 12) +#define SECTION_TEX_NORMAL (1 << 12) +#define SECTION_SHAREABLE (1 << 16) +#define SECTION_NON_GLOBAL (1 << 17) + +void armv8i_mmu_init(void); + +#endif // _ARCH_ARMV8I_MMU_H diff --git a/include/arch/armv8i/timer.h b/include/arch/armv8i/timer.h new file mode 100644 index 0000000..cc3f751 --- /dev/null +++ b/include/arch/armv8i/timer.h @@ -0,0 +1,13 @@ +#ifndef _ARCH_ARMV8I_TIMER_H +#define _ARCH_ARMV8I_TIMER_H + +#include + +#define ARMV8I_TIMER_VIRT_IRQ 27 + +void armv8i_timer_init(uint32_t freq_hz); +uint64_t armv8i_timer_get_ticks(void); +uint64_t armv8i_timer_get_frequency(void); +void armv8i_timer_handle_irq(void); + +#endif // _ARCH_ARMV8I_TIMER_H diff --git a/include/arch/armv8i/uart.h b/include/arch/armv8i/uart.h new file mode 100644 index 0000000..f4f0e00 --- /dev/null +++ b/include/arch/armv8i/uart.h @@ -0,0 +1,24 @@ +#ifndef _ARCH_ARMV8I_UART_H +#define _ARCH_ARMV8I_UART_H + +#include + +#define PL011_UART0_BASE 0x09000000 + +#define UARTDR 0x000 +#define UARTRSR 0x004 +#define UARTFR 0x018 +#define UARTCR 0x030 +#define UARTIMSC 0x038 +#define UARTICR 0x044 + +#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_ARMV8I_UART_H diff --git a/include/config/autoconf.h b/include/config/autoconf.h index 515a6ed..60cb873 100644 --- a/include/config/autoconf.h +++ b/include/config/autoconf.h @@ -2,8 +2,8 @@ #ifndef _AUTOCONF_H #define _AUTOCONF_H -#define CONFIG_ARCH "aarch64" -#define CONFIG_ARCH_AARCH64 1 +#define CONFIG_ARCH "armv8i" +#define CONFIG_ARCH_ARMV8I 1 #define CONFIG_BPF_VM 1 #define CONFIG_DRV_AHCI 1 #define CONFIG_DRV_ATA 1 diff --git a/include/init/version.h b/include/init/version.h index 0a056de..d38aaf9 100644 --- a/include/init/version.h +++ b/include/init/version.h @@ -14,6 +14,10 @@ #define SUBOS_VERSION_STRING "0.2.0-lts (aarch64)" #define SUBOS_BUILD_TARGET "aarch64-linux-gnu-baremetal" #define SUBOS_COMPILER "aarch64-linux-gnu-gcc" +#elif defined(__arm__) || defined(__armv8i__) +#define SUBOS_VERSION_STRING "0.2.0-lts (armv8i)" +#define SUBOS_BUILD_TARGET "arm-linux-gnueabihf-baremetal" +#define SUBOS_COMPILER "arm-linux-gnueabihf-gcc" #else #define SUBOS_VERSION_STRING "0.2.0-lts (generic)" #define SUBOS_BUILD_TARGET "generic-elf-baremetal" diff --git a/include/kernel/sync.h b/include/kernel/sync.h index 6fb6e21..13bd746 100644 --- a/include/kernel/sync.h +++ b/include/kernel/sync.h @@ -15,15 +15,23 @@ 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__) + while (__atomic_test_and_set(&lock->lock, __ATOMIC_ACQUIRE)) { __asm__ volatile ("pause"); -#elif defined(__aarch64__) - __asm__ volatile ("yield"); -#else - __asm__ volatile (""); -#endif } +#elif defined(__aarch64__) + while (__atomic_test_and_set(&lock->lock, __ATOMIC_ACQUIRE)) { + __asm__ volatile ("yield"); + } +#elif defined(__arm__) || defined(__armv8i__) + while (__atomic_test_and_set(&lock->lock, __ATOMIC_ACQUIRE)) { + __asm__ volatile ("nop"); + } +#else + while (__atomic_test_and_set(&lock->lock, __ATOMIC_ACQUIRE)) { + __asm__ volatile (""); + } +#endif } static inline void spin_unlock(spinlock_t* lock) { diff --git a/kernel/main.c b/kernel/main.c index b9c28be..56a8f5a 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -258,4 +258,28 @@ void kernel_main_aarch64(void) { subos_modular_core_boot(); } +#elif defined(__arm__) || defined(__armv8i__) +void kernel_main_armv8i(void) { + arch_early_init(); + printk_init(); + + printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET); + printk(ANSI_BRIGHT_CYAN " SUB-OS 32-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 ARMv8i 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/printk.c b/kernel/printk.c index 2822883..3758158 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -45,8 +45,8 @@ int vprintk(const char* fmt, va_list args) { // 1. Output to active TTY console tty_write(display_ptr, (size_t)len); - // 2. Output to serial console (COM1 on x86, PL011 on AArch64) -#if defined(__aarch64__) + // 2. Output to serial console (COM1 on x86, PL011 on ARM/AArch64) +#if defined(__aarch64__) || defined(__arm__) || defined(__armv8i__) extern void uart_pl011_putc(char c); for (int i = 0; i < len; i++) { uart_pl011_putc(display_ptr[i]); diff --git a/mm/pmm.c b/mm/pmm.c index e9ca15f..6454fe7 100644 --- a/mm/pmm.c +++ b/mm/pmm.c @@ -49,7 +49,7 @@ 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__) +#if defined(__aarch64__) || defined(__arm__) || defined(__armv8i__) uint64_t dram_start = 0x40000000; uint64_t dram_size = 128ULL * 1024 * 1024; uint64_t start_page = dram_start / PMM_PAGE_SIZE; diff --git a/scripts/kconfig/menuconfig.py b/scripts/kconfig/menuconfig.py index c3ddb53..ef9f744 100755 --- a/scripts/kconfig/menuconfig.py +++ b/scripts/kconfig/menuconfig.py @@ -355,10 +355,14 @@ def defconfig(arch="x86_64"): cfg["CONFIG_ARCH_X86_64"] = True cfg["CONFIG_ARCH_AARCH64"] = False cfg["CONFIG_ARCH_ARMV8I"] = False - elif arch in ["aarch64", "armv8", "armv8i"]: + elif arch in ["aarch64", "arm64"]: cfg["CONFIG_ARCH_X86_64"] = False cfg["CONFIG_ARCH_AARCH64"] = True - cfg["CONFIG_ARCH_ARMV8I"] = (arch == "armv8i") + cfg["CONFIG_ARCH_ARMV8I"] = False + elif arch in ["armv8i", "arm32", "arm", "armv8"]: + cfg["CONFIG_ARCH_X86_64"] = False + cfg["CONFIG_ARCH_AARCH64"] = False + cfg["CONFIG_ARCH_ARMV8I"] = True save_config(cfg) print(f"*** Default configuration for '{arch}' written to {CONFIG_FILE} and {AUTOCONF_HEADER} ***") diff --git a/userland/lazybox/shell.c b/userland/lazybox/shell.c index 03ec37a..1df1c20 100644 --- a/userland/lazybox/shell.c +++ b/userland/lazybox/shell.c @@ -109,9 +109,12 @@ static void cmd_neofetch(void) { #elif defined(__aarch64__) const aarch64_cpu_info_t* cpu = aarch64_get_cpu_info(); printk(ANSI_BRIGHT_CYAN " \\___ \\| | | | _ < " ANSI_BRIGHT_GREEN "CPU: " ANSI_RESET "%s (EL%u)\n", cpu->model_name, cpu->current_el); +#elif defined(__arm__) || defined(__armv8i__) + const armv8i_cpu_info_t* cpu = armv8i_get_cpu_info(); + printk(ANSI_BRIGHT_CYAN " \\___ \\| | | | _ < " ANSI_BRIGHT_GREEN "CPU: " ANSI_RESET "%s (AArch32)\n", cpu->model_name); #endif printk(ANSI_BRIGHT_CYAN " ____) | |__| | |_) | " ANSI_BRIGHT_GREEN "Memory: " ANSI_RESET "%llu MB / %llu MB (Free: %llu MB)\n", used_mb, total_mb, (free * 4096) / (1024 * 1024)); - printk(ANSI_BRIGHT_CYAN " |_____/ \\____/|____/ " ANSI_BRIGHT_GREEN "Heap: " ANSI_RESET "%llu KB used / %llu KB total\n", heap_get_used_bytes() / 1024, (heap_get_used_bytes() + heap_get_free_bytes()) / 1024); + printk(ANSI_BRIGHT_CYAN " |_____/ \\____/|____/ " ANSI_BRIGHT_GREEN "Heap: " ANSI_RESET "%llu KB used / %llu KB total\n", (uint64_t)(heap_get_used_bytes() / 1024), (uint64_t)((heap_get_used_bytes() + heap_get_free_bytes()) / 1024)); printk(ANSI_BRIGHT_CYAN " " ANSI_BRIGHT_GREEN "Uptime: " ANSI_RESET "%02llu:%02llu:%02llu\n", hours, mins, secs); printk(ANSI_BRIGHT_CYAN " " ANSI_BRIGHT_GREEN "TTY: " ANSI_RESET "tty%d (Alt+F1-F4 to switch)\n", tty_get_current() + 1); printk(" \n");