mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-25 16:52:29 +00:00
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
This commit is contained in:
1 parent
70d5925b16
commit
7b646c8cc4
30 files changed
+964
-24
No files matched your search
@@ -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:
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,60 @@
|
||||
#include <arch/arch.h>
|
||||
#include <arch/armv8i/cpu.h>
|
||||
#include <arch/armv8i/gic.h>
|
||||
#include <arch/armv8i/timer.h>
|
||||
#include <arch/armv8i/uart.h>
|
||||
#include <arch/armv8i/mmu.h>
|
||||
#include <arch/x86_64/cpuid.h>
|
||||
#include <kernel/printk.h>
|
||||
#include <lib/string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#include <arch/armv8i/cpu.h>
|
||||
#include <lib/string.h>
|
||||
#include <kernel/printk.h>
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SUB-OS ARMv8i Division-by-Zero and POSIX Signal Stub
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int raise(int sig) {
|
||||
(void)sig;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __aeabi_idiv0(void) {
|
||||
}
|
||||
|
||||
void __aeabi_ldiv0(void) {
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#include <arch/armv8i/arch.h>
|
||||
#include <arch/armv8i/gic.h>
|
||||
#include <arch/armv8i/timer.h>
|
||||
#include <arch/armv8i/uart.h>
|
||||
#include <kernel/printk.h>
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
#include <arch/armv8i/gic.h>
|
||||
#include <arch/armv8i/io.h>
|
||||
#include <kernel/printk.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#include <arch/armv8i/timer.h>
|
||||
#include <arch/armv8i/gic.h>
|
||||
#include <kernel/timer.h>
|
||||
#include <kernel/printk.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <arch/armv8i/uart.h>
|
||||
#include <arch/armv8i/io.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -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 = .;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include <arch/armv8i/mmu.h>
|
||||
#include <arch/armv8i/io.h>
|
||||
#include <lib/string.h>
|
||||
#include <kernel/printk.h>
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -125,10 +125,12 @@ void keyboard_init(void) {
|
||||
|
||||
#if defined(__aarch64__)
|
||||
#include <arch/aarch64/uart.h>
|
||||
#elif defined(__arm__) || defined(__armv8i__)
|
||||
#include <arch/armv8i/uart.h>
|
||||
#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';
|
||||
|
||||
+42
-1
@@ -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 <arch/armv8i/arch.h>
|
||||
#include <arch/armv8i/cpu.h>
|
||||
#include <arch/armv8i/gic.h>
|
||||
#include <arch/armv8i/timer.h>
|
||||
#include <arch/armv8i/mmu.h>
|
||||
#include <arch/armv8i/uart.h>
|
||||
#include <arch/armv8i/io.h>
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef _ARCH_ARMV8I_ARCH_H
|
||||
#define _ARCH_ARMV8I_ARCH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef _ARCH_ARMV8I_CPU_H
|
||||
#define _ARCH_ARMV8I_CPU_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
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
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef _ARCH_ARMV8I_GIC_H
|
||||
#define _ARCH_ARMV8I_GIC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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
|
||||
@@ -0,0 +1,75 @@
|
||||
#ifndef _ARCH_ARMV8I_IO_H
|
||||
#define _ARCH_ARMV8I_IO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef _ARCH_ARMV8I_MMU_H
|
||||
#define _ARCH_ARMV8I_MMU_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef _ARCH_ARMV8I_TIMER_H
|
||||
#define _ARCH_ARMV8I_TIMER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef _ARCH_ARMV8I_UART_H
|
||||
#define _ARCH_ARMV8I_UART_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
+14
-6
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
+2
-2
@@ -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]);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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} ***")
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in new issue
Block a user