Phase B (Core Device Support) — all drivers verified in QEMU: - Network: virtio-net cleanup, RTL8139, E1000, clause-22 MDIO PHY management, CAN bus, industrial protocols (Modbus/Profibus/EtherCAT), controller probe+dispatch - Block storage: RAM disk backend (write->read->verify PASSED), virtio-blk transport, backend dispatch, real MBR+GPT partition parsers, SD/eMMC command framework - GPIO: PL061 (verified), I2C: DesignWare (verified), SPI: PL022 (verified) Phase C (Advanced Features): - PCI: FULL PikeOS ARMv7 replica — transport-agnostic uos_pci_ops, config-address encoding, BAR sizing, capability walk, enumeration+bridge recursion, MSI/MSI-X - USB: PikeOS-style layered stack — usb.h contract, usb_core.cpp (enumeration state machine), usb_ehci.cpp (EHCI transport) - Display: FULL 1:1 PikeOS fbcon replica + copied font_8x16 Build foundation fixes: - Freestanding aeabi_runtime.cpp (__aeabi_uidiv/__aeabi_uldivmod) - PikeOS-style flat 4GB MMU section map + proper enable (unblocked device MMIO) - guest.h MAX_GUEST_IMAGE_SIZE 256MB->16MB (BSS was 259MB) - C/C++ linkage fixes, duplicate-virtio_net_init, MMIO access-size handling Phase D (PikeOS ARMv7 Microkernel Port): - D-1: Per-VM address spaces — cloned pgdirs, ASID-tagged TLB, 4K page walker, isolation PASSED (two guests, same VA->different PAs), guest fault recovery - D-2: IRQ dispatch backbone — 1024-slot dispatch table, real GICv2 hardware (GICD_CTLR/GICC_CTLR/GICC_PMR/GICC_IAR/GICC_EOIR), arm_irq_handler wired - D-3: Time subsystem — CNTVCT ns-since-boot, CNTP periodic ticker via D-2 - D-4: KDEV framework — linker-section driver registration, uos_kdev_init_all, name lookup - D-5: VFP/NEON — lazy enable (undef trap->CPACR+FPEXC.EN), FPEXC=0x40000000 - D-6: SMP — per-CPU state, MPIDR, IPI/SGI framework (reschedule+TLB flush) All uos_ naming (PikeOS p4_ convention adapted). Compiles -Werror freestanding C++17. Co-Authored-By: Claude <noreply@anthropic.com>
88 lines
2.6 KiB
C++
88 lines
2.6 KiB
C++
/*
|
|
* Universalisos AEABI Runtime Helpers
|
|
*
|
|
* Freestanding implementations of the integer division/modulo helpers that the
|
|
* ARM EABI expects the compiler to be able to call (gcc lowers 64-bit and
|
|
* variable-32-bit division into these). Because the kernel is built with
|
|
* -nostdlib, libgcc is not linked, so we provide minimal, branch-free long
|
|
* division routines here.
|
|
*
|
|
* Calling convention (AAPCS):
|
|
* __aeabi_uidiv(n, d) -> quotient in r0
|
|
* __aeabi_uldivmod(n, d) -> quotient in r0:r1, remainder in r2:r3
|
|
*
|
|
* The uldivmod return maps cleanly to a struct {uint64_t, uint64_t} returned by
|
|
* value, which AAPCS places in r0-r3.
|
|
*
|
|
* MISRA note: divide-by-zero is undefined behaviour; we trap it defensively by
|
|
* returning zero rather than corrupting state, and the routines never recurse
|
|
* (they use only shifts, OR, subtract and compare — no further division).
|
|
*
|
|
* Author: PortugalFuturista Hypervisor Development Team
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
|
|
extern "C" {
|
|
|
|
/**
|
|
* 32-bit unsigned division (quotient only).
|
|
* Used by the compiler for variable-divisor uint32_t division.
|
|
*/
|
|
uint32_t __aeabi_uidiv(uint32_t numerator, uint32_t denominator) {
|
|
if (denominator == 0U) {
|
|
/* Defensive: divide-by-zero is undefined; return 0 rather than fault. */
|
|
return 0U;
|
|
}
|
|
|
|
uint32_t quotient = 0U;
|
|
/* rem can grow to (2*denominator - 1), which requires 33 bits. */
|
|
uint64_t rem = 0U;
|
|
|
|
for (int32_t i = 31; i >= 0; i--) {
|
|
rem = (rem << 1) | (uint64_t)((numerator >> i) & 1U);
|
|
if (rem >= (uint64_t)denominator) {
|
|
rem -= (uint64_t)denominator;
|
|
quotient |= (1UL << (uint32_t)i);
|
|
}
|
|
}
|
|
|
|
return quotient;
|
|
}
|
|
|
|
/**
|
|
* 64-bit unsigned division with remainder.
|
|
* Result layout matches AAPCS: {quotient in r0:r1, remainder in r2:r3}.
|
|
*/
|
|
typedef struct {
|
|
uint64_t quotient;
|
|
uint64_t remainder;
|
|
} u64_divmod_result_t;
|
|
|
|
u64_divmod_result_t __aeabi_uldivmod(uint64_t numerator, uint64_t denominator) {
|
|
u64_divmod_result_t result;
|
|
result.quotient = 0U;
|
|
result.remainder = 0U;
|
|
|
|
if (denominator == 0U) {
|
|
/* Defensive: divide-by-zero is undefined; return {0, 0}. */
|
|
return result;
|
|
}
|
|
|
|
uint64_t quotient = 0U;
|
|
uint64_t rem = 0U;
|
|
|
|
for (int32_t i = 63; i >= 0; i--) {
|
|
rem = (rem << 1) | ((numerator >> (uint32_t)i) & 1ULL);
|
|
if (rem >= denominator) {
|
|
rem -= denominator;
|
|
quotient |= (1ULL << (uint32_t)i);
|
|
}
|
|
}
|
|
|
|
result.quotient = quotient;
|
|
result.remainder = rem;
|
|
return result;
|
|
}
|
|
|
|
} /* extern "C" */
|