feat(arch): Add AArch64 / ARMv8i CPU support, cross-compilation & Linux Kconfig TUI

- Implement AArch64 HAL, vector table (16 aligned vectors), GICv2, Generic Timer, Stage-1 MMU (39-bit VA), PL011 UART
- Build unified multi-architecture abstraction layer in include/arch/arch.h
- Create interactive Linux-like Kconfig TUI menuconfig in scripts/kconfig/menuconfig.py
- Support make menuconfig, defconfig, x86_64_defconfig, aarch64_defconfig
- Update master Makefile for cross-compiling x86_64 (x86_64-elf-) and AArch64 (aarch64-linux-gnu-)
- Dynamic architecture awareness across printk, uname, neofetch, and LazyBox
This commit is contained in:
subhobhai943 committed 2026-08-18 10:50:58 +05:30
1 parent 125a891621
commit 70d5925b16
41 files changed
+1926 -187

No files matched your search

+65
View File
@@ -0,0 +1,65 @@
#include <arch/arch.h>
#include <arch/aarch64/cpu.h>
#include <arch/aarch64/gic.h>
#include <arch/aarch64/timer.h>
#include <arch/aarch64/uart.h>
#include <arch/aarch64/mmu.h>
#include <arch/x86_64/cpuid.h>
#include <kernel/printk.h>
#include <lib/string.h>
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;
}
+58
View File
@@ -0,0 +1,58 @@
#include <arch/aarch64/cpu.h>
#include <lib/string.h>
#include <kernel/printk.h>
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;
}
+42
View File
@@ -0,0 +1,42 @@
#include <arch/aarch64/arch.h>
#include <arch/aarch64/gic.h>
#include <kernel/printk.h>
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");
}
}
+71
View File
@@ -0,0 +1,71 @@
#include <arch/aarch64/gic.h>
#include <arch/aarch64/io.h>
#include <lib/string.h>
#include <kernel/printk.h>
#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);
}
}
+49
View File
@@ -0,0 +1,49 @@
#include <arch/aarch64/timer.h>
#include <arch/aarch64/gic.h>
#include <kernel/timer.h>
#include <kernel/printk.h>
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;
}
+117
View File
@@ -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