mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-26 00:52:50 +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
@@ -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
|
||||
Reference in new issue
Block a user