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>
89 lines
3.4 KiB
C
89 lines
3.4 KiB
C
/*
|
|
* Universalisos per-VM address-space management (uos_adspace.h)
|
|
*
|
|
* 1:1 adaptation of PikeOS arch/arm/src/adspace.c. Each guest/VM gets an
|
|
* independent TTBR0 user page directory (half-size: UOS_PD_ENTRIES/2 entries,
|
|
* covering [0, UOS_MEM_USR_END)). uos_arch_adspace_set_active() performs the
|
|
* TTBR0 + ASID + BTAC switch on guest entry — the core of per-VM isolation.
|
|
*
|
|
* CP15 primitives (set_asid/set_ttbr0/inval_btac/tlb_inval_asid) and the global
|
|
* per-VM pgdir pool are supplied by uos_cmm.cpp.
|
|
*
|
|
* Author: PortugalFuturista Hypervisor Development Team (adapted from SYSGO PikeOS)
|
|
*/
|
|
#ifndef UOS_ADSPACE_H
|
|
#define UOS_ADSPACE_H
|
|
|
|
#include <stdint.h>
|
|
#include "uos_armmmu_v6.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* Per-VM isolation model (D-1 pragmatic approach):
|
|
* TTBCR=0 (no TTBR0/TTBR1 split); TTBR0 covers all 4 GB. Each guest gets a
|
|
* FULL-SIZE 16 KB pgdir cloned from the kernel flat map — kernel/device
|
|
* sections carry AP=privileged-only (UOS_PD_AP0) so user-mode guests fault on
|
|
* them, while supervisor-mode kernel code can access everything. Guest-specific
|
|
* user pages are added with AP=user-RW. Isolation is via AP bits + per-guest
|
|
* ASID-tagged TLB, not VA-range split. This avoids the risky 0x80000000 kernel
|
|
* relocation; a future hardening can switch to the full PikeOS split (TTBCR=1). */
|
|
#define UOS_MEM_USR_BASE 0x00000000u
|
|
#define UOS_MEM_USR_END 0x40000000u /* guest user space: 1 GB below kernel */
|
|
#define UOS_MEM_KERN_BASE 0x40000000u /* kernel + devices live here (identity-mapped) */
|
|
|
|
/* With TTBCR=0 (identity), KERN_TO_PHYS/PHYS_TO_KERN are no-ops. */
|
|
#define UOS_KERN_TO_PHYS(x) ((uint32_t)(x))
|
|
#define UOS_PHYS_TO_KERN(x) ((uint32_t)(x))
|
|
|
|
/* Per-task MMU context (PikeOS P4k_task_mmuctxt_t). */
|
|
typedef struct {
|
|
uint32_t *pgdir; /* points into uos_user_pgdirs[]; NULL == kernel/idle task */
|
|
} uos_task_mmuctxt_t;
|
|
|
|
/* Minimal taskinfo carrying the adspace + a task number used as the ASID. */
|
|
typedef struct {
|
|
uos_task_mmuctxt_t adspace;
|
|
uint32_t taskno;
|
|
} uos_taskinfo_t;
|
|
|
|
/* --- CP15 primitives (implemented in uos_cmm.cpp) --- */
|
|
void uos_arm_dsb(void);
|
|
void uos_arm_set_asid(uint32_t asid);
|
|
void uos_arm_set_ttbr0(uint32_t ttbr0);
|
|
void uos_arm_inval_btac(void);
|
|
void uos_arm_tlb_inval_all(void);
|
|
void uos_arm_tlb_inval_asid(uint32_t asid);
|
|
void uos_arm_tlb_inval_page(uint32_t mva);
|
|
|
|
/* --- Global per-VM user page-directory pool (allocated in uos_arm_init_mmu) --- */
|
|
extern uint32_t *uos_user_pgdirs;
|
|
|
|
/* Free an L2 page table behind a user VA (implemented in uos_mmu_walk.cpp). */
|
|
void uos_arm_free_pt(uos_taskinfo_t *td, uint32_t vaddr);
|
|
|
|
/* --- Address-space lifecycle (PikeOS adspace.c) --- */
|
|
|
|
/** Switch TTBR0/ASID to the task's address space. */
|
|
void uos_arch_adspace_set_active(uos_taskinfo_t *td, uos_taskinfo_t *prev);
|
|
|
|
/** Set up the idle/kernel task (runs purely on TTBR1). */
|
|
void uos_arch_adspace_register_kernel(uos_taskinfo_t *td);
|
|
|
|
/** Initialise a new address space (pgdir deferred). Returns 0 on success. */
|
|
int uos_arch_adspace_init(uos_taskinfo_t *td);
|
|
|
|
/** Assign the task its half-size user pgdir out of the global pool. */
|
|
void uos_arch_adspace_register_user(uos_taskinfo_t *td);
|
|
|
|
/** Unused callback (PikeOS leaves empty). */
|
|
void uos_arch_adspace_free(uos_taskinfo_t *td);
|
|
|
|
/** Unmap + free the task's entire user address space; flush its ASID TLB. */
|
|
void uos_arch_adspace_unmap_user(uos_taskinfo_t *td);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif /* UOS_ADSPACE_H */
|