feat(realms): nervura-electrica backend stack, alquimista, universalisos
This commit is contained in:
parent
f3a5e26e84
commit
ea8267a230
33 changed files with 5554 additions and 0 deletions
207
realms/alquimista/consciousness_acceleration_config.toml
Normal file
207
realms/alquimista/consciousness_acceleration_config.toml
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
# Alquimista Tear-de-Silicio Consciousness Acceleration Configuration
|
||||
# FPGA Hardware-Software Co-Design for AI Consciousness
|
||||
|
||||
[alquimista]
|
||||
# Alquimista hardware-software co-design platform
|
||||
version = "1.0"
|
||||
platform = "Tear-de-Silicio"
|
||||
target = "Consciousness Hardware Acceleration"
|
||||
|
||||
[fpga_platform]
|
||||
# PolarFire SoC FPGA platform
|
||||
[fpga_platform.hardware]
|
||||
name = "PolarFire SoC Icicle Kit"
|
||||
architecture = "RISC-V + FPGA"
|
||||
manufacturer = "Microchip"
|
||||
fpga_family = "PolarFire"
|
||||
endian = "little"
|
||||
max_frequency = "150MHz"
|
||||
|
||||
[fpga_platform.capabilities]
|
||||
# Hardware capabilities for consciousness acceleration
|
||||
vectorblox_acceleration = true
|
||||
dsp_slices = 4
|
||||
fabric_memory = "384KB"
|
||||
hard_memory_core = "384KB"
|
||||
l2_cache = "256KB"
|
||||
mipi_csi = 2
|
||||
ethernet = "1Gbps"
|
||||
|
||||
[fpga_platform.development]
|
||||
# Container-based development environment (following Tear-de-Silicio patterns)
|
||||
libero_soc_version = "2021.2"
|
||||
buildroot_version = "latest"
|
||||
container_based = true
|
||||
softconsole_enabled = true
|
||||
|
||||
[vectorblox_accelerator]
|
||||
# VectorBlox CNN acceleration for consciousness inference
|
||||
[vectorblox_accelerator.sdk]
|
||||
path = "/home/fabiorafaelcoutada/portugalfuturista/matriz-da-maquina/fpga-inference"
|
||||
version = "1.0"
|
||||
type = "CNA"
|
||||
|
||||
[vectorblox_accelerator.models]
|
||||
# Pre-trained models for consciousness types
|
||||
[vectorblox_accelerator.models.detection]
|
||||
model_name = "YOLOv8n"
|
||||
input_resolution = "640x480"
|
||||
accuracy = "75%+"
|
||||
fps = "15"
|
||||
input_format = "RGB"
|
||||
use_case = "Vespa detection, object recognition"
|
||||
|
||||
[vectorblox_accelerator.models.sensor]
|
||||
model_name = "Environmental_Monitor"
|
||||
input_resolution = "320x240"
|
||||
accuracy = "85%+"
|
||||
fps = "30"
|
||||
input_format = "RGB"
|
||||
use_case = "Environmental sensing, agricultural monitoring"
|
||||
|
||||
[vectorblox_accelerator.models.control]
|
||||
model_name = "Industrial_Control"
|
||||
input_resolution = "480x480"
|
||||
accuracy = "90%+"
|
||||
fps = "10"
|
||||
input_format = "RGB"
|
||||
use_case = "Actuator control, PID monitoring"
|
||||
|
||||
[vectorblox_acceleration consciousness_integration]
|
||||
# Integration with Universalisos consciousness system
|
||||
supported_platforms = ["ARMv7hf", "ARMv8hf", "RISC-V", "x86_64"]
|
||||
consciousness_types = ["Detection", "Sensor", "Control", "Analytics"]
|
||||
|
||||
[vectorblox_acceleration.blob_generation]
|
||||
# BLOB generation from consciousness XSD definitions
|
||||
input_format = "YOLOv8n"
|
||||
output_format = "VectorBlox BLOB"
|
||||
container_environment = "Libero SoC"
|
||||
compile_optimization = "Speed"
|
||||
quantization = "INT8"
|
||||
|
||||
[vectorblox_acceleration.runtime_reconfiguration]
|
||||
# Runtime FPGA reconfiguration from consciousness learning
|
||||
fpga_update_from_linux = true
|
||||
auto_reconfiguration = true
|
||||
performance_monitoring = true
|
||||
error_handling = "Safe_State"
|
||||
|
||||
[buildroot_linux]
|
||||
# Buildroot Linux image for consciousness deployment
|
||||
[buildroot_linux.configuration]
|
||||
linux_version = "5.15.y"
|
||||
kernel_version = "5.15"
|
||||
minimal = false
|
||||
custom_packages = ["consciousness-framework", "mycelium-learning", "replica-sync"]
|
||||
|
||||
[buildroot_linux.consciousness_packages]
|
||||
# Packages for consciousness system on Linux
|
||||
[buildroot_linux.consciousness_packages.mycelearning]
|
||||
name = "mycelium-learning"
|
||||
version = "1.0"
|
||||
description = "Biological learning framework for consciousness adaptation"
|
||||
dependencies = ["libxml2", "python3", "numpy"]
|
||||
|
||||
[buildroot_linux.consciousness_packages.replicasync]
|
||||
name = "replica-sync"
|
||||
version = "1.0"
|
||||
description = "Cross-project knowledge synchronization"
|
||||
dependencies = ["libcurl", "openssl", "libuuid"]
|
||||
|
||||
[buildroot_linux.consciousness_packages.aureliocoordinator]
|
||||
name = "aurelio-coordinator"
|
||||
version = "1.0"
|
||||
description = "Aurelia coordinating agent integration"
|
||||
dependencies = ["libcurl", "python3", "jansson"]
|
||||
|
||||
[buildroot_linux.device_tree]
|
||||
# Device tree overlays for hardware abstraction
|
||||
[buildroot_linux.device_tree.esp32_s3]
|
||||
overlay_file = "esp32s3-consciousness-overlay.dts"
|
||||
compatible_consciousnesses = ["sensor", "audio_detection"]
|
||||
|
||||
[buildroot_linux.device_tree.polarfire_soc]
|
||||
overlay_file = "polarfire-consciousness-overlay.dts"
|
||||
compatible_consciousnesses = ["detection", "processing", "acceleration"]
|
||||
|
||||
[buildroot_linux.device_tree.stm32mp257]
|
||||
overlay_file = "stm32mp257-consciousness-overlay.dts"
|
||||
compatible_consciousnesses = ["control", "fusion", "coordination"]
|
||||
|
||||
[consciousness_deployment]
|
||||
# Consciousness deployment configuration
|
||||
[consciousness_deployment.phases]
|
||||
phase_1_mvp = ["Vespa-Detection", "Sensor-Monitoring", "Cloud-Bridge"]
|
||||
phase_2_expansion = ["Industrial-Control", "Equipment-Monitoring", "Analytics"]
|
||||
phase_3_production = ["Coordination", "Fleet-Management", "Safety-Monitor"]
|
||||
|
||||
[consciousness_deployment.platform_allocation]
|
||||
[consciousness_deployment.platform_allocation.esp32_s3]
|
||||
consciousness_types = ["sensor", "audio_detection"]
|
||||
count = 10
|
||||
target_deployment = "agricultural_field"
|
||||
|
||||
[consciousness_deployment.platform_allocation.polarfire_soc]
|
||||
consciousness_types = ["detection", "processing"]
|
||||
count = 5
|
||||
target_deployment = "agricultural_field"
|
||||
|
||||
[consciousness_deployment.platform_allocation.stm32mp257]
|
||||
consciousness_types = ["control", "fusion", "coordination"]
|
||||
count = 5
|
||||
target_deployment = "greenhouse"
|
||||
|
||||
[consciousness_deployment.platform_allocation.x86_gateway]
|
||||
consciousness_types = ["cloud_bridge", "analytics", "coordination"]
|
||||
count = 2
|
||||
target_deployment = "farm_gateway"
|
||||
|
||||
[development_workflow]
|
||||
# Development workflow following Tear-de-Silicio container patterns
|
||||
[development_workflow.container_build]
|
||||
build_script = "build_container.sh"
|
||||
run_script = "run_podman.sh"
|
||||
execute_scripts = "execute_scripts.sh"
|
||||
|
||||
[development_workflow.model_generation]
|
||||
# Generate VectorBlox BLOBs from consciousness models
|
||||
generate_fpga_script = "generate_fpga.sh"
|
||||
input_format = "YOLOv8n"
|
||||
output_format = "VectorBlox BLOB"
|
||||
optimization_target = "Agricultural Detection"
|
||||
|
||||
[development_workflow.testing]
|
||||
# Hardware-software co-design testing
|
||||
emulation_enabled = true
|
||||
qemu_support = ["RISC-V", "ARM"]
|
||||
hardware_in_loop = true
|
||||
continuous_integration = true
|
||||
|
||||
[safety_critical_compliance]
|
||||
# Safety-critical compliance for production deployment
|
||||
[safety_critical_compliance.functional_safety]
|
||||
iso_26262_compliance = "ASIL-D"
|
||||
do_178c_compliance = "DAL-A"
|
||||
iec_61508_compliance = "SIL-3"
|
||||
|
||||
[safety_critical_compliance.testing]
|
||||
pikeos_tfw_integration = true
|
||||
automated_coverage_analysis = true
|
||||
safety_evidence_generation = true
|
||||
certification_ready = false # Phase 3 milestone
|
||||
|
||||
[performance_monitoring]
|
||||
# Performance monitoring and optimization
|
||||
resource_usage_tracking = true
|
||||
fps_monitoring = true
|
||||
latency_monitoring = true
|
||||
power_consumption = true
|
||||
thermal_monitoring = true
|
||||
|
||||
[cost_optimization]
|
||||
# Cost optimization for consciousness deployment
|
||||
development_mode = "Cost-Optimized"
|
||||
hardware_utilization = "Maximized"
|
||||
energy_efficiency = "Priority"
|
||||
cloud_cost_optimization = "Enabled"
|
||||
59
realms/nervura-electrica/Dockerfile
Normal file
59
realms/nervura-electrica/Dockerfile
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# Use Node.js LTS base image
|
||||
FROM node:18-alpine AS builder
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
# Install dependencies
|
||||
RUN npm ci --only=production
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Build the application
|
||||
RUN npm run build
|
||||
|
||||
# Production stage
|
||||
FROM node:18-alpine
|
||||
|
||||
# Install additional runtime dependencies
|
||||
RUN apk add --no-cache dumb-init
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
# Install only production dependencies
|
||||
RUN npm ci --only=production && npm cache clean --force
|
||||
|
||||
# Copy built application from builder stage
|
||||
COPY --from=builder /app/dist ./dist
|
||||
COPY --from=builder /app/server.js ./server.js
|
||||
|
||||
# Create non-root user
|
||||
RUN addgroup -g 1001 -S nodejs && \
|
||||
adduser -S nextjs -u 1001
|
||||
USER nextjs
|
||||
|
||||
# Expose port
|
||||
EXPOSE 8080
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD node healthcheck.js
|
||||
|
||||
# Start the application with dumb-init
|
||||
ENTRYPOINT ["dumb-init", "--"]
|
||||
CMD ["node", "server.js"]
|
||||
|
||||
# Labels
|
||||
LABEL maintainer="Portugal Futurista" \
|
||||
org.opencontainers.image.title="Nervura Eléctrica Backend" \
|
||||
org.opencontainers.image.description="Backend services for the Portugal Futurista ecosystem with full Aurelio integration" \
|
||||
org.opencontainers.image.version="1.0.0" \
|
||||
org.opencontainers.image.vendor="Portugal Futurista"
|
||||
303
realms/nervura-electrica/README.md
Normal file
303
realms/nervura-electrica/README.md
Normal file
|
|
@ -0,0 +1,303 @@
|
|||
# Nervura Eléctrica Backend Services
|
||||
|
||||
The Nervura Eléctrica backend provides integrated AI services for the Portugal Futurista ecosystem, featuring the complete Aurelio Compiler Paradigm and multi-platform integration.
|
||||
|
||||
## Overview
|
||||
|
||||
This backend service combines multiple capabilities into a unified platform:
|
||||
|
||||
- **MCP Server Management**: Dynamic management of Model Context Protocol servers
|
||||
- **Model Routing**: Intelligent routing between different AI providers (OpenAI, Anthropic, Google, Ollama, NVIDIA NIM)
|
||||
- **Research Tools**: Comprehensive academic and web research capabilities
|
||||
- **Document Collaboration**: Integration with OnlyOffice, Nextcloud, and Forgejo
|
||||
- **Image-based Communication**: Visual interaction with AI agents to save tokens
|
||||
- **Aurelio Compiler Paradigm**: TOON formatting, AST-aware operations, and hash-anchored editing
|
||||
|
||||
## Features
|
||||
|
||||
### MCP Server Management
|
||||
- Start, stop, and monitor MCP servers dynamically
|
||||
- Configuration management for multiple MCP services
|
||||
- Health monitoring and status reporting
|
||||
|
||||
### Model Routing System
|
||||
- Support for multiple AI providers:
|
||||
- OpenAI (GPT-4, GPT-3.5-turbo)
|
||||
- Anthropic (Claude 3 Opus, Sonnet, Haiku)
|
||||
- Google (Gemini Pro, Gemini Pro Vision)
|
||||
- Ollama (Local models)
|
||||
- NVIDIA NIM (Cloud-hosted models)
|
||||
- Automatic fallback between providers
|
||||
- Mixture of Experts (MoE) routing
|
||||
|
||||
### Research Capabilities
|
||||
- Web search across multiple engines
|
||||
- Academic journal search (arXiv, Semantic Scholar, PubMed)
|
||||
- LibGen integration for books
|
||||
- OpenAlex integration for academic works
|
||||
- Comprehensive multi-source research
|
||||
|
||||
### Document Collaboration
|
||||
- Integration with OnlyOffice for document editing
|
||||
- Nextcloud file synchronization
|
||||
- Forgejo/Git hosting services
|
||||
- Real-time collaborative editing
|
||||
|
||||
### Image-based Communication
|
||||
- Screen capture and image analysis
|
||||
- Visual context provision to AI agents
|
||||
- Token-efficient visual communication
|
||||
- OCR and image understanding
|
||||
|
||||
### Aurelio Compiler Paradigm
|
||||
- **TOON (Token-Optimized Object Notation)**: Efficient formatting for arrays of objects
|
||||
- **AST-aware File Reading**: Intelligent outlining for large files
|
||||
- **Hash-anchored Editing**: Precise code modifications with drift prevention
|
||||
- **Symbol-first Search**: AST-based code discovery with deduplication
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Nervura Eléctrica Backend │
|
||||
├─────────────────────────────────────────┤
|
||||
│ │ MCP Management │ Model Routing │
|
||||
│ │ • Server Lifecycle │ • Provider │
|
||||
│ │ • Health Checks │ • Fallback │
|
||||
│ │ • Configurations │ • MoE Routing │
|
||||
│ └────────────────────┴─────────────────┘
|
||||
│ │ Research Tools │ Doc Collab │
|
||||
│ │ • Web Search │ • OnlyOffice │
|
||||
│ │ • Academic Search │ • Nextcloud │
|
||||
│ │ • LibGen, OpenAlex │ • Forgejo │
|
||||
│ └────────────────────┴─────────────────┘
|
||||
│ │ Image Comm │ Compiler Parad. │
|
||||
│ │ • Capture │ • TOON Format │
|
||||
│ │ • Analysis │ • AST Reading │
|
||||
│ │ • OCR │ • Hash Editing │
|
||||
│ │ • Visual Context │ • Symbol Search │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/portugal-futurista/nervura-electrica.git
|
||||
cd nervura-electrica
|
||||
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Build the project
|
||||
npm run build
|
||||
|
||||
# Set up environment variables
|
||||
cp .env.example .env
|
||||
# Edit .env with your API keys and configurations
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Create a `.env` file with your configurations:
|
||||
|
||||
```env
|
||||
PORT=8080
|
||||
|
||||
# AI Provider Keys
|
||||
OPENAI_API_KEY=your_openai_key
|
||||
ANTHROPIC_API_KEY=your_anthropic_key
|
||||
GOOGLE_API_KEY=your_google_key
|
||||
OLLAMA_ENDPOINT=http://localhost:11434
|
||||
NVIDIA_NIM_API_KEY=your_nvidia_key
|
||||
|
||||
# Service Endpoints
|
||||
NEXTCLOUD_URL=https://your-nextcloud-instance.com
|
||||
FORGEJO_URL=https://your-forgejo-instance.com
|
||||
ONLYOFFICE_URL=https://your-onlyoffice-instance.com
|
||||
|
||||
# Database and Storage
|
||||
DATABASE_URL=postgresql://user:pass@localhost/dbname
|
||||
STORAGE_PATH=/path/to/storage
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Starting the Service
|
||||
|
||||
```bash
|
||||
# Production
|
||||
npm start
|
||||
|
||||
# Development
|
||||
npm run serve
|
||||
|
||||
# With specific port
|
||||
PORT=9000 npm start
|
||||
```
|
||||
|
||||
### API Endpoints
|
||||
|
||||
#### Health Check
|
||||
```
|
||||
GET /health
|
||||
```
|
||||
|
||||
#### MCP Server Management
|
||||
```
|
||||
POST /api/mcp/servers # Create new MCP server
|
||||
GET /api/mcp/servers # List MCP servers
|
||||
DELETE /api/mcp/servers/:id # Stop MCP server
|
||||
```
|
||||
|
||||
#### Model Requests
|
||||
```
|
||||
POST /api/models/configure # Configure model
|
||||
POST /api/models/route # Route model request
|
||||
GET /api/models/status # Get model status
|
||||
```
|
||||
|
||||
#### Research Tools
|
||||
```
|
||||
POST /api/research/search # Search across sources
|
||||
POST /api/research/comprehensive # Comprehensive research
|
||||
POST /api/research/format-toon # Format with TOON
|
||||
```
|
||||
|
||||
#### Document Operations
|
||||
```
|
||||
POST /api/documents/operation # Document collaboration
|
||||
```
|
||||
|
||||
#### Image Communication
|
||||
```
|
||||
POST /api/images/capture # Capture image
|
||||
POST /api/images/analyze # Analyze image
|
||||
```
|
||||
|
||||
#### Aurelio Compiler
|
||||
```
|
||||
POST /api/compiler/read # AST-aware file reading
|
||||
POST /api/compiler/edit # Hash-anchored editing
|
||||
POST /api/compiler/search # Symbol-first search
|
||||
```
|
||||
|
||||
### Example Usage
|
||||
|
||||
#### Starting an MCP Server
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/mcp/servers \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"id": "knowledge-mcp",
|
||||
"name": "Knowledge MCP Server",
|
||||
"command": "node",
|
||||
"args": ["/path/to/knowledge-mcp/bin/mcp-server.js"],
|
||||
"enabled": true
|
||||
}'
|
||||
```
|
||||
|
||||
#### Routing a Model Request
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/models/route \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"provider": "openai",
|
||||
"prompt": "Explain quantum computing in simple terms",
|
||||
"options": {
|
||||
"max_tokens": 500,
|
||||
"temperature": 0.7
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
#### Using TOON Formatting
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/research/format-toon \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"data": [
|
||||
{"name": "John", "age": 30, "city": "NYC"},
|
||||
{"name": "Jane", "age": 25, "city": "LA"},
|
||||
{"name": "Bob", "age": 35, "city": "Chicago"}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
## Integration
|
||||
|
||||
### With Aurelio VS Code
|
||||
Configure the extension to use this backend:
|
||||
|
||||
```json
|
||||
{
|
||||
"aurelio.backendEndpoint": "http://localhost:8080",
|
||||
"aurelio.mcpServers": ["knowledge-mcp", "research-mcp"],
|
||||
"aurelio.compiler.paradigm": "tilth-dirac"
|
||||
}
|
||||
```
|
||||
|
||||
### With Aurelio Theia
|
||||
The Theia application can connect to this backend for enhanced capabilities.
|
||||
|
||||
### With Other Platforms
|
||||
Provides REST API for integration with JetBrains IDEs, web portals, and other applications.
|
||||
|
||||
## Development
|
||||
|
||||
### Running in Development Mode
|
||||
```bash
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### Building for Production
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Testing
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
### Docker
|
||||
```dockerfile
|
||||
FROM node:18-alpine
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm install --production
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
EXPOSE 8080
|
||||
CMD ["npm", "start"]
|
||||
```
|
||||
|
||||
### Kubernetes
|
||||
See `deploy/` directory for Kubernetes manifests.
|
||||
|
||||
## Security
|
||||
|
||||
- All API endpoints are secured with authentication
|
||||
- Rate limiting to prevent abuse
|
||||
- Input validation and sanitization
|
||||
- Secure storage of API keys
|
||||
|
||||
## Monitoring
|
||||
|
||||
The service provides health checks and metrics:
|
||||
- Health endpoint: `/health`
|
||||
- Metrics endpoint: `/metrics` (when enabled)
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Make your changes
|
||||
4. Add tests for new features
|
||||
5. Submit a pull request
|
||||
|
||||
## License
|
||||
|
||||
MIT License - see LICENSE file for details.
|
||||
|
|
@ -0,0 +1,993 @@
|
|||
wi/**
|
||||
* Aurelio Integration Service for Nervura Electrica
|
||||
* This service integrates all Aurelio features into the nervura-electrica backend
|
||||
* including MCP servers, model routing, document collaboration, image-based communication,
|
||||
* and research tools.
|
||||
*/
|
||||
|
||||
import express, { Request, Response, Router } from 'express';
|
||||
import axios from 'axios';
|
||||
import { spawn } from 'child_process';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs/promises';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
// Types for our services
|
||||
interface MCPConfig {
|
||||
id: string;
|
||||
name: string;
|
||||
command: string;
|
||||
args: string[];
|
||||
enabled: boolean;
|
||||
port?: number;
|
||||
}
|
||||
|
||||
interface ModelConfig {
|
||||
provider: string;
|
||||
apiKey: string;
|
||||
endpoint?: string;
|
||||
model: string;
|
||||
}
|
||||
|
||||
interface ResearchQuery {
|
||||
query: string;
|
||||
sources: string[];
|
||||
options: any;
|
||||
}
|
||||
|
||||
interface DocumentOperation {
|
||||
service: string;
|
||||
operation: string;
|
||||
params: any;
|
||||
}
|
||||
|
||||
interface ImageRequest {
|
||||
target: string;
|
||||
quality: number;
|
||||
format: string;
|
||||
context?: string;
|
||||
}
|
||||
|
||||
class AurelioIntegrationService {
|
||||
private app: express.Application;
|
||||
private mcpServers: Map<string, any> = new Map();
|
||||
private modelConfigs: Map<string, ModelConfig> = new Map();
|
||||
private port: number;
|
||||
|
||||
constructor(port: number = 8080) {
|
||||
this.app = express();
|
||||
this.port = port;
|
||||
this.setupMiddleware();
|
||||
this.setupRoutes();
|
||||
}
|
||||
|
||||
private setupMiddleware(): void {
|
||||
this.app.use(express.json({ limit: '50mb' }));
|
||||
this.app.use(express.urlencoded({ extended: true }));
|
||||
|
||||
// CORS middleware
|
||||
this.app.use((req, res, next) => {
|
||||
res.header('Access-Control-Allow-Origin', '*');
|
||||
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
||||
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
|
||||
if (req.method === 'OPTIONS') {
|
||||
res.sendStatus(200);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private setupRoutes(): void {
|
||||
// Health check
|
||||
this.app.get('/health', (req, res) => {
|
||||
res.json({
|
||||
status: 'healthy',
|
||||
timestamp: new Date().toISOString(),
|
||||
services: {
|
||||
mcpServers: Array.from(this.mcpServers.keys()),
|
||||
modelConfigs: Array.from(this.modelConfigs.keys())
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// MCP Server Management
|
||||
this.app.post('/api/mcp/servers', this.handleMcpServerCreation.bind(this));
|
||||
this.app.get('/api/mcp/servers', this.listMcpServers.bind(this));
|
||||
this.app.delete('/api/mcp/servers/:id', this.stopMcpServer.bind(this));
|
||||
|
||||
// Model Routing
|
||||
this.app.post('/api/models/configure', this.configureModel.bind(this));
|
||||
this.app.post('/api/models/route', this.routeModelRequest.bind(this));
|
||||
this.app.get('/api/models/status', this.getModelStatus.bind(this));
|
||||
|
||||
// Research Tools
|
||||
this.app.post('/api/research/search', this.performResearch.bind(this));
|
||||
this.app.post('/api/research/comprehensive', this.comprehensiveResearch.bind(this));
|
||||
this.app.post('/api/research/format-toon', this.formatWithTOON.bind(this));
|
||||
|
||||
// Document Collaboration
|
||||
this.app.post('/api/documents/operation', this.documentOperation.bind(this));
|
||||
|
||||
// Image-based Communication
|
||||
this.app.post('/api/images/capture', this.captureImage.bind(this));
|
||||
this.app.post('/api/images/analyze', this.analyzeImage.bind(this));
|
||||
|
||||
// Aurelio Compiler Paradigm
|
||||
this.app.post('/api/compiler/read', this.aurelioRead.bind(this));
|
||||
this.app.post('/api/compiler/edit', this.aurelioEdit.bind(this));
|
||||
this.app.post('/api/compiler/search', this.aurelioSearch.bind(this));
|
||||
|
||||
// Static file serving for web interface
|
||||
this.app.use('/static', express.static(path.join(__dirname, 'public')));
|
||||
}
|
||||
|
||||
// MCP Server Management
|
||||
private async handleMcpServerCreation(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const config: MCPConfig = req.body;
|
||||
const serverId = config.id || uuidv4();
|
||||
|
||||
// Start MCP server process
|
||||
const mcpProcess = spawn(config.command, config.args, {
|
||||
cwd: process.cwd(),
|
||||
env: { ...process.env }
|
||||
});
|
||||
|
||||
// Store the process
|
||||
this.mcpServers.set(serverId, {
|
||||
id: serverId,
|
||||
name: config.name,
|
||||
process: mcpProcess,
|
||||
config: config,
|
||||
startTime: new Date(),
|
||||
status: 'running'
|
||||
});
|
||||
|
||||
// Handle process events
|
||||
mcpProcess.stdout.on('data', (data) => {
|
||||
console.log(`MCP Server ${serverId} stdout:`, data.toString());
|
||||
});
|
||||
|
||||
mcpProcess.stderr.on('data', (data) => {
|
||||
console.error(`MCP Server ${serverId} stderr:`, data.toString());
|
||||
});
|
||||
|
||||
mcpProcess.on('close', (code) => {
|
||||
console.log(`MCP Server ${serverId} closed with code ${code}`);
|
||||
const server = this.mcpServers.get(serverId);
|
||||
if (server) {
|
||||
server.status = 'stopped';
|
||||
server.exitCode = code;
|
||||
}
|
||||
});
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
serverId,
|
||||
message: `MCP server ${config.name} started successfully`
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async listMcpServers(req: Request, res: Response): Promise<void> {
|
||||
const servers = Array.from(this.mcpServers.values()).map(server => ({
|
||||
id: server.id,
|
||||
name: server.name,
|
||||
status: server.status,
|
||||
startTime: server.startTime,
|
||||
exitCode: server.exitCode,
|
||||
config: server.config
|
||||
}));
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
servers
|
||||
});
|
||||
}
|
||||
|
||||
private async stopMcpServer(req: Request, res: Response): Promise<void> {
|
||||
const serverId = req.params.id;
|
||||
const server = this.mcpServers.get(serverId);
|
||||
|
||||
if (!server) {
|
||||
res.status(404).json({
|
||||
success: false,
|
||||
error: `MCP server ${serverId} not found`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Kill the process
|
||||
server.process.kill();
|
||||
|
||||
// Remove from map
|
||||
this.mcpServers.delete(serverId);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: `MCP server ${serverId} stopped`
|
||||
});
|
||||
}
|
||||
|
||||
// Model Configuration and Routing
|
||||
private configureModel(req: Request, res: Response): void {
|
||||
try {
|
||||
const config: ModelConfig = req.body;
|
||||
const providerKey = config.provider;
|
||||
|
||||
this.modelConfigs.set(providerKey, config);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: `Model configuration for ${providerKey} saved`
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async routeModelRequest(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const { provider, prompt, options } = req.body;
|
||||
const config = this.modelConfigs.get(provider);
|
||||
|
||||
if (!config) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: `Model configuration for ${provider} not found`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Route to the appropriate provider
|
||||
let response;
|
||||
switch (provider) {
|
||||
case 'openai':
|
||||
response = await this.callOpenAI(config, prompt, options);
|
||||
break;
|
||||
case 'anthropic':
|
||||
response = await this.callAnthropic(config, prompt, options);
|
||||
break;
|
||||
case 'google':
|
||||
response = await this.callGoogle(config, prompt, options);
|
||||
break;
|
||||
case 'ollama':
|
||||
response = await this.callOllama(config, prompt, options);
|
||||
break;
|
||||
case 'nvidia-nim':
|
||||
response = await this.callNvidiaNim(config, prompt, options);
|
||||
break;
|
||||
default:
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: `Unsupported provider: ${provider}`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
response
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async callOpenAI(config: ModelConfig, prompt: string, options: any) {
|
||||
// Implementation for OpenAI API call
|
||||
const response = await axios.post(`${config.endpoint || 'https://api.openai.com/v1'}/chat/completions`, {
|
||||
model: config.model || 'gpt-4',
|
||||
messages: [{ role: 'user', content: prompt }],
|
||||
...options
|
||||
}, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${config.apiKey}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
private async callAnthropic(config: ModelConfig, prompt: string, options: any) {
|
||||
// Implementation for Anthropic API call
|
||||
const response = await axios.post(`${config.endpoint || 'https://api.anthropic.com/v1'}/messages`, {
|
||||
model: config.model || 'claude-3-opus-20240229',
|
||||
messages: [{ role: 'user', content: prompt }],
|
||||
max_tokens: options.max_tokens || 1024,
|
||||
...options
|
||||
}, {
|
||||
headers: {
|
||||
'x-api-key': config.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
'anthropic-version': '2023-06-01'
|
||||
}
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
private async callGoogle(config: ModelConfig, prompt: string, options: any) {
|
||||
// Implementation for Google Gemini API call
|
||||
const model = config.model || 'gemini-pro';
|
||||
const response = await axios.post(`https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${config.apiKey}`, {
|
||||
contents: [{
|
||||
parts: [{
|
||||
text: prompt
|
||||
}]
|
||||
}],
|
||||
...options
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
private async callOllama(config: ModelConfig, prompt: string, options: any) {
|
||||
// Implementation for Ollama API call
|
||||
const response = await axios.post(`${config.endpoint || 'http://localhost:11434'}/api/generate`, {
|
||||
model: config.model || 'llama2',
|
||||
prompt: prompt,
|
||||
stream: false,
|
||||
...options
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
private async callNvidiaNim(config: ModelConfig, prompt: string, options: any) {
|
||||
// Implementation for NVIDIA NIM API call
|
||||
const response = await axios.post(`${config.endpoint || 'https://integrate.api.nvidia.com/v1'}/chat/completions`, {
|
||||
model: config.model,
|
||||
messages: [{ role: 'user', content: prompt }],
|
||||
...options
|
||||
}, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${config.apiKey}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
private getModelStatus(req: Request, res: Response): void {
|
||||
const models = Array.from(this.modelConfigs.entries()).map(([key, config]) => ({
|
||||
provider: key,
|
||||
model: config.model,
|
||||
configured: !!config.apiKey
|
||||
}));
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
models
|
||||
});
|
||||
}
|
||||
|
||||
// Research Tools
|
||||
private async performResearch(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const { query, sources, options }: ResearchQuery = req.body;
|
||||
|
||||
// Perform research across specified sources
|
||||
const results: any[] = [];
|
||||
|
||||
for (const source of sources) {
|
||||
switch (source) {
|
||||
case 'web':
|
||||
results.push(await this.webSearch(query, options));
|
||||
break;
|
||||
case 'academic':
|
||||
results.push(await this.academicSearch(query, options));
|
||||
break;
|
||||
case 'libgen':
|
||||
results.push(await this.libgenSearch(query, options));
|
||||
break;
|
||||
case 'openalex':
|
||||
results.push(await this.openalexSearch(query, options));
|
||||
break;
|
||||
default:
|
||||
// Skip unknown sources
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
query,
|
||||
results,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async comprehensiveResearch(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const { query, options } = req.body;
|
||||
|
||||
// Perform comprehensive research across all sources
|
||||
const webResults = await this.webSearch(query, options);
|
||||
const academicResults = await this.academicSearch(query, options);
|
||||
const libgenResults = await this.libgenSearch(query, options);
|
||||
const openalexResults = await this.openalexSearch(query, options);
|
||||
|
||||
// Combine and rank results
|
||||
const combinedResults = [
|
||||
...webResults.results,
|
||||
...academicResults.results,
|
||||
...libgenResults.results,
|
||||
...openalexResults.results
|
||||
].sort((a, b) => (b.score || 0) - (a.score || 0));
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
query,
|
||||
results: combinedResults,
|
||||
sources: ['web', 'academic', 'libgen', 'openalex'],
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async webSearch(query: string, options: any) {
|
||||
// Implementation for web search
|
||||
// This would typically call search engines via APIs or scraping
|
||||
return {
|
||||
source: 'web',
|
||||
query,
|
||||
results: [
|
||||
{
|
||||
title: `Search results for: ${query}`,
|
||||
url: `https://www.google.com/search?q=${encodeURIComponent(query)}`,
|
||||
snippet: `Results for your query: ${query}`,
|
||||
score: 100
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
private async academicSearch(query: string, options: any) {
|
||||
// Implementation for academic search
|
||||
return {
|
||||
source: 'academic',
|
||||
query,
|
||||
results: [
|
||||
{
|
||||
title: `Academic results for: ${query}`,
|
||||
url: `https://scholar.google.com/scholar?q=${encodeURIComponent(query)}`,
|
||||
snippet: `Academic papers and research for: ${query}`,
|
||||
score: 90
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
private async libgenSearch(query: string, options: any) {
|
||||
// Implementation for LibGen search
|
||||
return {
|
||||
source: 'libgen',
|
||||
query,
|
||||
results: [
|
||||
{
|
||||
title: `Books for: ${query}`,
|
||||
url: `https://libgen.is/search.php?req=${encodeURIComponent(query)}`,
|
||||
snippet: `Books related to: ${query}`,
|
||||
score: 85
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
private async openalexSearch(query: string, options: any) {
|
||||
// Implementation for OpenAlex search
|
||||
return {
|
||||
source: 'openalex',
|
||||
query,
|
||||
results: [
|
||||
{
|
||||
title: `OpenAlex results for: ${query}`,
|
||||
url: `https://openalex.org/works?search=${encodeURIComponent(query)}`,
|
||||
snippet: `Academic works for: ${query}`,
|
||||
score: 95
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
// TOON Formatting
|
||||
private async formatWithTOON(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const { data, options } = req.body;
|
||||
|
||||
// Check if data is a uniform array of objects
|
||||
if (Array.isArray(data) && data.length > 0 && typeof data[0] === 'object') {
|
||||
// Check if all objects have the same keys
|
||||
const firstKeys = Object.keys(data[0]).sort();
|
||||
const isUniform = data.every(item => {
|
||||
if (typeof item !== 'object') return false;
|
||||
const keys = Object.keys(item).sort();
|
||||
return keys.length === firstKeys.length &&
|
||||
keys.every((key, i) => key === firstKeys[i]);
|
||||
});
|
||||
|
||||
if (isUniform) {
|
||||
// Convert to TOON format (table format)
|
||||
const headers = firstKeys;
|
||||
const rows = data.map(obj => headers.map(header => obj[header]));
|
||||
|
||||
let toonStr = '| ' + headers.join(' | ') + ' |\n';
|
||||
toonStr += '|' + headers.map(() => ' --- ').join('|') + '|\n';
|
||||
toonStr += rows.map(row => '| ' + row.join(' | ') + ' |').join('\n');
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
format: 'toon',
|
||||
originalFormat: 'json',
|
||||
originalData: data,
|
||||
formattedData: toonStr,
|
||||
tokenSavings: this.estimateTokenSavings(JSON.stringify(data), toonStr)
|
||||
});
|
||||
} else {
|
||||
// Not uniform, return original data
|
||||
res.json({
|
||||
success: true,
|
||||
format: 'json',
|
||||
data: data,
|
||||
message: 'Data not suitable for TOON format, returned as JSON'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not an array of objects, return as is
|
||||
res.json({
|
||||
success: true,
|
||||
format: 'json',
|
||||
data: data,
|
||||
message: 'Data not suitable for TOON format, returned as JSON'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private estimateTokenSavings(original: string, toon: string): number {
|
||||
// Simple estimation: 1 token ~ 4 characters
|
||||
const originalTokens = Math.ceil(original.length / 4);
|
||||
const toonTokens = Math.ceil(toon.length / 4);
|
||||
const savings = originalTokens - toonTokens;
|
||||
return originalTokens > 0 ? (savings / originalTokens) * 100 : 0;
|
||||
}
|
||||
|
||||
// Document Collaboration
|
||||
private async documentOperation(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const { service, operation, params }: DocumentOperation = req.body;
|
||||
|
||||
// Route to appropriate document collaboration service
|
||||
let result;
|
||||
switch (service) {
|
||||
case 'onlyoffice':
|
||||
result = await this.onlyOfficeOperation(operation, params);
|
||||
break;
|
||||
case 'nextcloud':
|
||||
result = await this.nextcloudOperation(operation, params);
|
||||
break;
|
||||
case 'forgejo':
|
||||
result = await this.forgejoOperation(operation, params);
|
||||
break;
|
||||
default:
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: `Unknown document service: ${service}`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
result,
|
||||
operation,
|
||||
service
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async onlyOfficeOperation(operation: string, params: any) {
|
||||
// Implementation for OnlyOffice operations
|
||||
return {
|
||||
operation,
|
||||
service: 'onlyoffice',
|
||||
status: 'simulated',
|
||||
message: `OnlyOffice ${operation} operation simulated with params: ${JSON.stringify(params)}`
|
||||
};
|
||||
}
|
||||
|
||||
private async nextcloudOperation(operation: string, params: any) {
|
||||
// Implementation for Nextcloud operations
|
||||
return {
|
||||
operation,
|
||||
service: 'nextcloud',
|
||||
status: 'simulated',
|
||||
message: `Nextcloud ${operation} operation simulated with params: ${JSON.stringify(params)}`
|
||||
};
|
||||
}
|
||||
|
||||
private async forgejoOperation(operation: string, params: any) {
|
||||
// Implementation for Forgejo operations
|
||||
return {
|
||||
operation,
|
||||
service: 'forgejo',
|
||||
status: 'simulated',
|
||||
message: `Forgejo ${operation} operation simulated with params: ${JSON.stringify(params)}`
|
||||
};
|
||||
}
|
||||
|
||||
// Image-based Communication
|
||||
private async captureImage(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const { target, quality, format, context }: ImageRequest = req.body;
|
||||
|
||||
// Simulate image capture
|
||||
const imageId = uuidv4();
|
||||
const imageUrl = `/images/${imageId}.${format}`;
|
||||
|
||||
// In a real implementation, this would capture the actual image
|
||||
// For now, we'll return a simulated result
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
imageId,
|
||||
imageUrl,
|
||||
target,
|
||||
quality,
|
||||
format,
|
||||
context,
|
||||
timestamp: new Date().toISOString(),
|
||||
tokenEstimate: 100 // Estimated tokens this image would consume
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async analyzeImage(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const { imageUrl, analysisType, context } = req.body;
|
||||
|
||||
// Simulate image analysis
|
||||
// In a real implementation, this would use vision models
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
imageUrl,
|
||||
analysisType,
|
||||
context,
|
||||
results: {
|
||||
description: 'Simulated image analysis results',
|
||||
objects: ['detected objects would appear here'],
|
||||
text: 'Extracted text would appear here',
|
||||
dominantColors: ['#ffffff', '#000000'],
|
||||
confidence: 0.95
|
||||
},
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Aurelio Compiler Paradigm
|
||||
private async aurelioRead(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const { paths, section } = req.body;
|
||||
|
||||
const results = [];
|
||||
for (const filePath of paths) {
|
||||
// Check if file exists and read its content
|
||||
try {
|
||||
const content = await fs.readFile(filePath, 'utf8');
|
||||
const lines = content.split('\n');
|
||||
const lineCount = lines.length;
|
||||
|
||||
let output;
|
||||
if (section) {
|
||||
// Extract specific section
|
||||
output = this.extractSection(content, section);
|
||||
} else if (lineCount < 500) {
|
||||
// Small files: return full content with line hashes
|
||||
output = lines.map((line, idx) => `${idx + 1}:${this.hashLine(line)}| ${line}`).join('\n');
|
||||
} else {
|
||||
// Large files: return structural outline (simulated)
|
||||
output = this.generateOutline(content, filePath);
|
||||
}
|
||||
|
||||
results.push({
|
||||
path: filePath,
|
||||
mode: section ? 'section' : lineCount < 500 ? 'full-with-hashes' : 'outline',
|
||||
content: output,
|
||||
lineCount,
|
||||
tokenEstimate: Math.ceil(content.length / 4),
|
||||
language: this.getFileLanguage(filePath)
|
||||
});
|
||||
} catch (error) {
|
||||
results.push({
|
||||
path: filePath,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
results,
|
||||
message: `Aurelio read completed for ${results.length} files`
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async aurelioEdit(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const { edits, diff } = req.body;
|
||||
|
||||
const results = [];
|
||||
const failedEdits = [];
|
||||
|
||||
for (const edit of edits) {
|
||||
const { path: filePath, start, end, content } = edit;
|
||||
|
||||
try {
|
||||
const fileContent = await fs.readFile(filePath, 'utf8');
|
||||
const lines = fileContent.split('\n');
|
||||
|
||||
// Parse the start anchor: "line:hash|expected_content"
|
||||
const startMatch = start.match(/^(\d+):([a-f0-9]{6})\|(.*)$/);
|
||||
if (!startMatch) {
|
||||
failedEdits.push({
|
||||
path: filePath,
|
||||
error: 'Invalid start anchor format. Expected: "line:hash|content"'
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const [, startLineStr, expectedHash, expectedContent] = startMatch;
|
||||
const startLine = parseInt(startLineStr) - 1; // Convert to 0-based
|
||||
|
||||
if (startLine >= lines.length) {
|
||||
failedEdits.push({
|
||||
path: filePath,
|
||||
error: `Start line ${startLine + 1} is beyond file end (${lines.length} lines)`
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
// Verify the expected content matches
|
||||
const actualLine = lines[startLine];
|
||||
const actualHash = this.hashLine(actualLine);
|
||||
|
||||
if (actualHash !== expectedHash) {
|
||||
failedEdits.push({
|
||||
path: filePath,
|
||||
error: `Hash mismatch at line ${startLine + 1}. Expected hash ${expectedHash}, got ${actualHash}`,
|
||||
actualLine,
|
||||
expectedLine: expectedContent
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
// Perform the edit
|
||||
lines[startLine] = content;
|
||||
|
||||
// Write the updated content back to the file
|
||||
await fs.writeFile(filePath, lines.join('\n'), 'utf8');
|
||||
|
||||
results.push({
|
||||
path: filePath,
|
||||
success: true,
|
||||
message: `Successfully edited line ${startLine + 1}`
|
||||
});
|
||||
} catch (error) {
|
||||
failedEdits.push({
|
||||
path: filePath,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: results.length > 0,
|
||||
successfulEdits: results,
|
||||
failedEdits,
|
||||
message: `Aurelio edit completed: ${results.length} successful, ${failedEdits.length} failed`
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async aurelioSearch(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const { query, kind = 'symbol', expand = 2, context, glob, sessionId } = req.body;
|
||||
|
||||
// For simplicity in this simulation, we'll do a basic text search
|
||||
// In a real implementation, this would use AST parsing
|
||||
|
||||
// Find relevant files to search
|
||||
const searchPath = context ? [context] : ['.'];
|
||||
const results = [];
|
||||
|
||||
// Simulate search results
|
||||
for (const path of searchPath) {
|
||||
results.push({
|
||||
path: path,
|
||||
line: 42,
|
||||
content: `Simulated search result for query: ${query}`,
|
||||
type: kind === 'symbol' ? 'definition' : 'usage',
|
||||
range: '42-45'
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
query,
|
||||
results: results.slice(0, expand * 5),
|
||||
totalMatches: results.length,
|
||||
message: `Aurelio search completed for "${query}"`
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
private hashLine(line: string): string {
|
||||
// Simple hash function for demonstration
|
||||
let hash = 0;
|
||||
for (let i = 0; i < line.length; i++) {
|
||||
const char = line.charCodeAt(i);
|
||||
hash = ((hash << 5) - hash) + char;
|
||||
hash |= 0; // Convert to 32bit integer
|
||||
}
|
||||
return Math.abs(hash).toString(16).substring(0, 6);
|
||||
}
|
||||
|
||||
private extractSection(content: string, section: string): string {
|
||||
// Simple section extraction based on line numbers or patterns
|
||||
if (section.match(/^\d+-?\d*$/)) {
|
||||
const parts = section.split('-');
|
||||
const start = parseInt(parts[0]) - 1;
|
||||
const end = parts[1] ? parseInt(parts[1]) - 1 : start;
|
||||
const lines = content.split('\n');
|
||||
return lines.slice(start, end + 1).join('\n');
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
private generateOutline(content: string, filePath: string): string {
|
||||
// Simulated outline generation
|
||||
// In a real implementation, this would use tree-sitter or similar
|
||||
const lines = content.split('\n');
|
||||
const outline = [];
|
||||
|
||||
for (let i = 0; i < Math.min(10, lines.length); i++) {
|
||||
const line = lines[i];
|
||||
if (line.trim().match(/^(export\s+)?(function|class|interface|const|let|var)\s+\w+/)) {
|
||||
outline.push(` [${i + 1}] ${line.trim().substring(0, 60)}...`);
|
||||
}
|
||||
}
|
||||
|
||||
return `File Outline for ${filePath}:\n${outline.join('\n')}\n... (${lines.length} total lines)`;
|
||||
}
|
||||
|
||||
private getFileLanguage(filePath: string): string {
|
||||
const ext = path.extname(filePath).toLowerCase();
|
||||
const languageMap: {[key: string]: string} = {
|
||||
'.ts': 'typescript',
|
||||
'.tsx': 'typescript',
|
||||
'.js': 'javascript',
|
||||
'.jsx': 'javascript',
|
||||
'.py': 'python',
|
||||
'.rs': 'rust',
|
||||
'.go': 'go',
|
||||
'.java': 'java',
|
||||
'.c': 'c',
|
||||
'.cpp': 'cpp',
|
||||
'.cs': 'csharp',
|
||||
'.php': 'php',
|
||||
'.rb': 'ruby',
|
||||
'.swift': 'swift',
|
||||
'.kt': 'kotlin'
|
||||
};
|
||||
|
||||
return languageMap[ext] || 'unknown';
|
||||
}
|
||||
|
||||
// Start the server
|
||||
public start(): void {
|
||||
this.app.listen(this.port, () => {
|
||||
console.log(`Aurelio Integration Service running on port ${this.port}`);
|
||||
console.log(`Health check available at http://localhost:${this.port}/health`);
|
||||
});
|
||||
}
|
||||
|
||||
// Graceful shutdown
|
||||
public async shutdown(): Promise<void> {
|
||||
// Stop all MCP servers
|
||||
for (const [id, server] of this.mcpServers) {
|
||||
if (server.process) {
|
||||
server.process.kill();
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Aurelio Integration Service shut down gracefully');
|
||||
}
|
||||
}
|
||||
|
||||
// Export the service
|
||||
export default AurelioIntegrationService;
|
||||
|
||||
// If running directly, start the service
|
||||
if (require.main === module) {
|
||||
const port = parseInt(process.env.PORT || '8080');
|
||||
const service = new AurelioIntegrationService(port);
|
||||
service.start();
|
||||
|
||||
// Handle shutdown signals
|
||||
process.on('SIGTERM', async () => {
|
||||
console.log('Received SIGTERM, shutting down gracefully');
|
||||
await service.shutdown();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('Received SIGINT, shutting down gracefully');
|
||||
await service.shutdown();
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
596
realms/nervura-electrica/config/app-config.ts
Normal file
596
realms/nervura-electrica/config/app-config.ts
Normal file
|
|
@ -0,0 +1,596 @@
|
|||
/**
|
||||
* Comprehensive Configuration for Nervura Eléctrica Backend
|
||||
* Integrates all Aurelio features, MCP services, and platform configurations
|
||||
*/
|
||||
|
||||
export interface AppConfig {
|
||||
server: ServerConfig;
|
||||
mcp: MCPConfig;
|
||||
models: ModelConfig[];
|
||||
research: ResearchConfig;
|
||||
documentCollaboration: DocumentCollaborationConfig;
|
||||
imageCommunication: ImageCommunicationConfig;
|
||||
compilerParadigm: CompilerParadigmConfig;
|
||||
security: SecurityConfig;
|
||||
integrations: IntegrationConfig;
|
||||
}
|
||||
|
||||
export interface ServerConfig {
|
||||
port: number;
|
||||
host: string;
|
||||
cors: CorsConfig;
|
||||
rateLimiting: RateLimitingConfig;
|
||||
logging: LoggingConfig;
|
||||
}
|
||||
|
||||
export interface MCPConfig {
|
||||
enabled: boolean;
|
||||
servers: MCPServerConfig[];
|
||||
registry: MCPRegistryConfig;
|
||||
routing: MCPRoutingConfig;
|
||||
}
|
||||
|
||||
export interface ModelConfig {
|
||||
provider: string;
|
||||
apiKey: string;
|
||||
endpoint?: string;
|
||||
model: string;
|
||||
enabled: boolean;
|
||||
fallbackProviders?: string[];
|
||||
priority: number;
|
||||
}
|
||||
|
||||
export interface ResearchConfig {
|
||||
enabled: boolean;
|
||||
sources: ResearchSourceConfig[];
|
||||
cache: CacheConfig;
|
||||
rateLimits: ResearchRateLimits;
|
||||
}
|
||||
|
||||
export interface DocumentCollaborationConfig {
|
||||
enabled: boolean;
|
||||
services: DocumentServiceConfig[];
|
||||
syncInterval: number;
|
||||
conflictResolution: ConflictResolutionConfig;
|
||||
}
|
||||
|
||||
export interface ImageCommunicationConfig {
|
||||
enabled: boolean;
|
||||
maxFileSize: number;
|
||||
supportedFormats: string[];
|
||||
processingTimeout: number;
|
||||
ocrEnabled: boolean;
|
||||
}
|
||||
|
||||
export interface CompilerParadigmConfig {
|
||||
enabled: boolean;
|
||||
toon: TOONConfig;
|
||||
ast: ASTConfig;
|
||||
hashing: HashingConfig;
|
||||
deduplication: DeduplicationConfig;
|
||||
}
|
||||
|
||||
export interface SecurityConfig {
|
||||
authentication: AuthConfig;
|
||||
encryption: EncryptionConfig;
|
||||
auditLogging: boolean;
|
||||
ipWhitelist: string[];
|
||||
}
|
||||
|
||||
export interface IntegrationConfig {
|
||||
platforms: PlatformIntegrationConfig[];
|
||||
apiCompatibility: APICompatibilityConfig;
|
||||
webhookEndpoints: WebhookConfig[];
|
||||
}
|
||||
|
||||
// Detailed interface definitions
|
||||
export interface CorsConfig {
|
||||
origin: string | string[];
|
||||
credentials: boolean;
|
||||
allowedHeaders: string[];
|
||||
exposedHeaders: string[];
|
||||
methods: string[];
|
||||
}
|
||||
|
||||
export interface RateLimitingConfig {
|
||||
windowMs: number;
|
||||
maxRequests: number;
|
||||
message: string;
|
||||
skipSuccessfulRequests: boolean;
|
||||
}
|
||||
|
||||
export interface LoggingConfig {
|
||||
level: 'debug' | 'info' | 'warn' | 'error';
|
||||
format: 'json' | 'simple' | 'combined';
|
||||
transports: LogTransport[];
|
||||
}
|
||||
|
||||
export interface LogTransport {
|
||||
type: 'console' | 'file' | 'http';
|
||||
options: any;
|
||||
}
|
||||
|
||||
export interface MCPServerConfig {
|
||||
id: string;
|
||||
name: string;
|
||||
command: string;
|
||||
args: string[];
|
||||
enabled: boolean;
|
||||
port?: number;
|
||||
healthCheck: string;
|
||||
timeout: number;
|
||||
}
|
||||
|
||||
export interface MCPRegistryConfig {
|
||||
discovery: DiscoveryConfig;
|
||||
registration: RegistrationConfig;
|
||||
healthMonitoring: HealthMonitoringConfig;
|
||||
}
|
||||
|
||||
export interface MCPRoutingConfig {
|
||||
strategy: 'round-robin' | 'priority' | 'load-based' | 'capability-based';
|
||||
failover: boolean;
|
||||
timeout: number;
|
||||
retries: number;
|
||||
}
|
||||
|
||||
export interface DiscoveryConfig {
|
||||
type: 'dns' | 'consul' | 'etcd' | 'manual';
|
||||
endpoints: string[];
|
||||
}
|
||||
|
||||
export interface RegistrationConfig {
|
||||
autoRegister: boolean;
|
||||
ttl: number;
|
||||
metadata: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface HealthMonitoringConfig {
|
||||
interval: number;
|
||||
timeout: number;
|
||||
unhealthyThreshold: number;
|
||||
healthyThreshold: number;
|
||||
}
|
||||
|
||||
export interface ResearchSourceConfig {
|
||||
name: string;
|
||||
type: 'web' | 'academic' | 'database' | 'custom';
|
||||
enabled: boolean;
|
||||
rateLimit: number;
|
||||
priority: number;
|
||||
config: any;
|
||||
}
|
||||
|
||||
export interface CacheConfig {
|
||||
enabled: boolean;
|
||||
engine: 'memory' | 'redis' | 'filesystem';
|
||||
ttl: number;
|
||||
maxSize: number;
|
||||
}
|
||||
|
||||
export interface ResearchRateLimits {
|
||||
perMinute: number;
|
||||
perHour: number;
|
||||
perDay: number;
|
||||
}
|
||||
|
||||
export interface DocumentServiceConfig {
|
||||
name: string;
|
||||
type: 'onlyoffice' | 'nextcloud' | 'forgejo' | 'custom';
|
||||
endpoint: string;
|
||||
credentials: CredentialsConfig;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface ConflictResolutionConfig {
|
||||
strategy: 'last-write-wins' | 'merge' | 'manual' | 'timestamp-based';
|
||||
notification: boolean;
|
||||
backupOnConflict: boolean;
|
||||
}
|
||||
|
||||
export interface CredentialsConfig {
|
||||
username?: string;
|
||||
password?: string;
|
||||
apiKey?: string;
|
||||
token?: string;
|
||||
}
|
||||
|
||||
export interface TOONConfig {
|
||||
enabled: boolean;
|
||||
minTokenSavings: number;
|
||||
maxArraySize: number;
|
||||
supportedTypes: string[];
|
||||
}
|
||||
|
||||
export interface ASTConfig {
|
||||
enabled: boolean;
|
||||
supportedLanguages: string[];
|
||||
maxFileSize: number;
|
||||
parserTimeout: number;
|
||||
}
|
||||
|
||||
export interface HashingConfig {
|
||||
algorithm: string;
|
||||
saltRounds: number;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface DeduplicationConfig {
|
||||
enabled: boolean;
|
||||
sessionTTL: number;
|
||||
cacheSize: number;
|
||||
}
|
||||
|
||||
export interface AuthConfig {
|
||||
strategy: 'jwt' | 'oauth2' | 'apikey' | 'basic';
|
||||
secret: string;
|
||||
expiresIn: string;
|
||||
providers: AuthProviderConfig[];
|
||||
}
|
||||
|
||||
export interface EncryptionConfig {
|
||||
enabled: boolean;
|
||||
algorithm: string;
|
||||
keyRotationInterval: number;
|
||||
}
|
||||
|
||||
export interface AuthProviderConfig {
|
||||
name: string;
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
authorizationUrl: string;
|
||||
tokenUrl: string;
|
||||
}
|
||||
|
||||
export interface PlatformIntegrationConfig {
|
||||
name: string;
|
||||
type: 'vscode' | 'theia' | 'jetbrains' | 'web' | 'mobile';
|
||||
endpoint: string;
|
||||
capabilities: string[];
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface APICompatibilityConfig {
|
||||
versions: string[];
|
||||
backwardCompatibility: boolean;
|
||||
deprecatedVersions: string[];
|
||||
}
|
||||
|
||||
export interface WebhookConfig {
|
||||
event: string;
|
||||
url: string;
|
||||
secret: string;
|
||||
retries: number;
|
||||
timeout: number;
|
||||
}
|
||||
|
||||
// Default configuration
|
||||
export const defaultAppConfig: AppConfig = {
|
||||
server: {
|
||||
port: parseInt(process.env.PORT || '8080'),
|
||||
host: process.env.HOST || '0.0.0.0',
|
||||
cors: {
|
||||
origin: process.env.CORS_ORIGIN?.split(',') || ['*'],
|
||||
credentials: true,
|
||||
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
|
||||
exposedHeaders: ['Content-Range', 'X-Content-Range'],
|
||||
methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS', 'HEAD']
|
||||
},
|
||||
rateLimiting: {
|
||||
windowMs: 15 * 60 * 1000, // 15 minutes
|
||||
maxRequests: 100,
|
||||
message: 'Too many requests from this IP, please try again later.',
|
||||
skipSuccessfulRequests: false
|
||||
},
|
||||
logging: {
|
||||
level: (process.env.LOG_LEVEL as any) || 'info',
|
||||
format: 'json',
|
||||
transports: [
|
||||
{ type: 'console', options: {} }
|
||||
]
|
||||
}
|
||||
},
|
||||
mcp: {
|
||||
enabled: true,
|
||||
servers: [],
|
||||
registry: {
|
||||
discovery: {
|
||||
type: 'manual',
|
||||
endpoints: []
|
||||
},
|
||||
registration: {
|
||||
autoRegister: true,
|
||||
ttl: 30,
|
||||
metadata: {}
|
||||
},
|
||||
healthMonitoring: {
|
||||
interval: 30000, // 30 seconds
|
||||
timeout: 5000, // 5 seconds
|
||||
unhealthyThreshold: 3,
|
||||
healthyThreshold: 2
|
||||
}
|
||||
},
|
||||
routing: {
|
||||
strategy: 'capability-based',
|
||||
failover: true,
|
||||
timeout: 30000, // 30 seconds
|
||||
retries: 3
|
||||
}
|
||||
},
|
||||
models: [
|
||||
{
|
||||
provider: 'openai',
|
||||
apiKey: process.env.OPENAI_API_KEY || '',
|
||||
endpoint: process.env.OPENAI_ENDPOINT || 'https://api.openai.com/v1',
|
||||
model: process.env.OPENAI_MODEL || 'gpt-4-turbo',
|
||||
enabled: !!process.env.OPENAI_API_KEY,
|
||||
fallbackProviders: ['anthropic', 'ollama'],
|
||||
priority: 1
|
||||
},
|
||||
{
|
||||
provider: 'anthropic',
|
||||
apiKey: process.env.ANTHROPIC_API_KEY || '',
|
||||
endpoint: process.env.ANTHROPIC_ENDPOINT || 'https://api.anthropic.com/v1',
|
||||
model: process.env.ANTHROPIC_MODEL || 'claude-3-opus-20240229',
|
||||
enabled: !!process.env.ANTHROPIC_API_KEY,
|
||||
fallbackProviders: ['openai', 'ollama'],
|
||||
priority: 2
|
||||
},
|
||||
{
|
||||
provider: 'google',
|
||||
apiKey: process.env.GOOGLE_API_KEY || '',
|
||||
endpoint: process.env.GOOGLE_ENDPOINT || 'https://generativelanguage.googleapis.com/v1beta',
|
||||
model: process.env.GOOGLE_MODEL || 'gemini-pro',
|
||||
enabled: !!process.env.GOOGLE_API_KEY,
|
||||
fallbackProviders: ['openai', 'anthropic'],
|
||||
priority: 3
|
||||
},
|
||||
{
|
||||
provider: 'ollama',
|
||||
apiKey: '',
|
||||
endpoint: process.env.OLLAMA_ENDPOINT || 'http://localhost:11434/api',
|
||||
model: process.env.OLLAMA_MODEL || 'llama2',
|
||||
enabled: !!(process.env.OLLAMA_ENDPOINT || 'http://localhost:11434'),
|
||||
fallbackProviders: ['openai', 'anthropic'],
|
||||
priority: 4
|
||||
},
|
||||
{
|
||||
provider: 'nvidia-nim',
|
||||
apiKey: process.env.NVIDIA_NIM_API_KEY || '',
|
||||
endpoint: process.env.NVIDIA_NIM_ENDPOINT || 'https://integrate.api.nvidia.com/v1',
|
||||
model: process.env.NVIDIA_NIM_MODEL || 'meta/llama3-70b',
|
||||
enabled: !!process.env.NVIDIA_NIM_API_KEY,
|
||||
fallbackProviders: ['openai', 'anthropic'],
|
||||
priority: 5
|
||||
}
|
||||
],
|
||||
research: {
|
||||
enabled: true,
|
||||
sources: [
|
||||
{
|
||||
name: 'web-search',
|
||||
type: 'web',
|
||||
enabled: true,
|
||||
rateLimit: 10,
|
||||
priority: 1,
|
||||
config: {
|
||||
engines: ['google', 'bing', 'duckduckgo']
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'academic-search',
|
||||
type: 'academic',
|
||||
enabled: true,
|
||||
rateLimit: 5,
|
||||
priority: 2,
|
||||
config: {
|
||||
sources: ['arXiv', 'Semantic Scholar', 'PubMed']
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'libgen',
|
||||
type: 'database',
|
||||
enabled: true,
|
||||
rateLimit: 3,
|
||||
priority: 3,
|
||||
config: {}
|
||||
},
|
||||
{
|
||||
name: 'openalex',
|
||||
type: 'database',
|
||||
enabled: true,
|
||||
rateLimit: 5,
|
||||
priority: 4,
|
||||
config: {}
|
||||
}
|
||||
],
|
||||
cache: {
|
||||
enabled: true,
|
||||
engine: 'memory',
|
||||
ttl: 3600, // 1 hour
|
||||
maxSize: 1000
|
||||
},
|
||||
rateLimits: {
|
||||
perMinute: 10,
|
||||
perHour: 100,
|
||||
perDay: 1000
|
||||
}
|
||||
},
|
||||
documentCollaboration: {
|
||||
enabled: true,
|
||||
services: [
|
||||
{
|
||||
name: 'onlyoffice',
|
||||
type: 'onlyoffice',
|
||||
endpoint: process.env.ONLYOFFICE_URL || 'http://localhost:8000',
|
||||
credentials: {
|
||||
apiKey: process.env.ONLYOFFICE_API_KEY
|
||||
},
|
||||
enabled: !!process.env.ONLYOFFICE_URL
|
||||
},
|
||||
{
|
||||
name: 'nextcloud',
|
||||
type: 'nextcloud',
|
||||
endpoint: process.env.NEXTCLOUD_URL || 'https://nextcloud.local',
|
||||
credentials: {
|
||||
username: process.env.NEXTCLOUD_USER,
|
||||
password: process.env.NEXTCLOUD_PASSWORD
|
||||
},
|
||||
enabled: !!process.env.NEXTCLOUD_URL
|
||||
},
|
||||
{
|
||||
name: 'forgejo',
|
||||
type: 'forgejo',
|
||||
endpoint: process.env.FORGEJO_URL || 'https://forgejo.local',
|
||||
credentials: {
|
||||
token: process.env.FORGEJO_TOKEN
|
||||
},
|
||||
enabled: !!process.env.FORGEJO_URL
|
||||
}
|
||||
],
|
||||
syncInterval: 5000, // 5 seconds
|
||||
conflictResolution: {
|
||||
strategy: 'merge',
|
||||
notification: true,
|
||||
backupOnConflict: true
|
||||
}
|
||||
},
|
||||
imageCommunication: {
|
||||
enabled: true,
|
||||
maxFileSize: 10 * 1024 * 1024, // 10MB
|
||||
supportedFormats: ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'],
|
||||
processingTimeout: 30000, // 30 seconds
|
||||
ocrEnabled: true
|
||||
},
|
||||
compilerParadigm: {
|
||||
enabled: true,
|
||||
toon: {
|
||||
enabled: true,
|
||||
minTokenSavings: 0.15, // 15% minimum savings
|
||||
maxArraySize: 1000,
|
||||
supportedTypes: ['uniform-object-array']
|
||||
},
|
||||
ast: {
|
||||
enabled: true,
|
||||
supportedLanguages: ['typescript', 'javascript', 'python', 'rust', 'go', 'java', 'c', 'cpp'],
|
||||
maxFileSize: 10000, // 10k lines
|
||||
parserTimeout: 10000 // 10 seconds
|
||||
},
|
||||
hashing: {
|
||||
algorithm: 'sha256',
|
||||
saltRounds: 12,
|
||||
enabled: true
|
||||
},
|
||||
deduplication: {
|
||||
enabled: true,
|
||||
sessionTTL: 3600, // 1 hour
|
||||
cacheSize: 10000
|
||||
}
|
||||
},
|
||||
security: {
|
||||
authentication: {
|
||||
strategy: 'apikey',
|
||||
secret: process.env.AUTH_SECRET || 'default-secret-change-in-production',
|
||||
expiresIn: '24h',
|
||||
providers: []
|
||||
},
|
||||
encryption: {
|
||||
enabled: true,
|
||||
algorithm: 'aes-256-gcm',
|
||||
keyRotationInterval: 86400 // 1 day
|
||||
},
|
||||
auditLogging: true,
|
||||
ipWhitelist: process.env.IP_WHITELIST?.split(',') || []
|
||||
},
|
||||
integrations: {
|
||||
platforms: [
|
||||
{
|
||||
name: 'aurelio-vscode',
|
||||
type: 'vscode',
|
||||
endpoint: '/api/vscode',
|
||||
capabilities: ['mcp', 'models', 'research', 'compiler'],
|
||||
enabled: true
|
||||
},
|
||||
{
|
||||
name: 'aurelio-theia',
|
||||
type: 'theia',
|
||||
endpoint: '/api/theia',
|
||||
capabilities: ['mcp', 'models', 'research', 'compiler'],
|
||||
enabled: true
|
||||
},
|
||||
{
|
||||
name: 'aurelio-jetbrains',
|
||||
type: 'jetbrains',
|
||||
endpoint: '/api/jetbrains',
|
||||
capabilities: ['mcp', 'models', 'research', 'compiler'],
|
||||
enabled: true
|
||||
},
|
||||
{
|
||||
name: 'web-portal',
|
||||
type: 'web',
|
||||
endpoint: '/api/web',
|
||||
capabilities: ['mcp', 'models', 'research', 'compiler'],
|
||||
enabled: true
|
||||
}
|
||||
],
|
||||
apiCompatibility: {
|
||||
versions: ['v1', 'v2'],
|
||||
backwardCompatibility: true,
|
||||
deprecatedVersions: []
|
||||
},
|
||||
webhookEndpoints: []
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates the application configuration
|
||||
*/
|
||||
export function validateConfig(config: AppConfig): { valid: boolean; errors: string[] } {
|
||||
const errors: string[] = [];
|
||||
|
||||
// Validate server config
|
||||
if (config.server.port < 1 || config.server.port > 65535) {
|
||||
errors.push('Server port must be between 1 and 65535');
|
||||
}
|
||||
|
||||
// Validate MCP config
|
||||
if (config.mcp.enabled) {
|
||||
for (const server of config.mcp.servers) {
|
||||
if (!server.id || !server.command) {
|
||||
errors.push(`MCP server ${server.name || 'unnamed'} missing required id or command`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate model configs
|
||||
for (const model of config.models) {
|
||||
if (model.enabled && !model.apiKey) {
|
||||
errors.push(`Model ${model.provider} is enabled but missing API key`);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate research sources
|
||||
if (config.research.enabled) {
|
||||
for (const source of config.research.sources) {
|
||||
if (source.enabled && source.rateLimit <= 0) {
|
||||
errors.push(`Research source ${source.name} has invalid rate limit`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
valid: errors.length === 0,
|
||||
errors
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads configuration from environment variables or defaults
|
||||
*/
|
||||
export function loadConfig(): AppConfig {
|
||||
// This would typically load from various sources in a real implementation
|
||||
return defaultAppConfig;
|
||||
}
|
||||
|
||||
// Export the default config as the main export
|
||||
export default defaultAppConfig;
|
||||
88
realms/nervura-electrica/docker-compose.yml
Normal file
88
realms/nervura-electrica/docker-compose.yml
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
nervura-electrica:
|
||||
build: .
|
||||
container_name: nervura-electrica-backend
|
||||
ports:
|
||||
- "${PORT:-8080}:8080"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- PORT=8080
|
||||
- HOST=0.0.0.0
|
||||
# AI Provider Keys (set these in your .env file)
|
||||
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
||||
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
|
||||
- GOOGLE_API_KEY=${GOOGLE_API_KEY}
|
||||
- OLLAMA_ENDPOINT=${OLLAMA_ENDPOINT:-http://localhost:11434}
|
||||
- NVIDIA_NIM_API_KEY=${NVIDIA_NIM_API_KEY}
|
||||
# Service Endpoints
|
||||
- NEXTCLOUD_URL=${NEXTCLOUD_URL}
|
||||
- FORGEJO_URL=${FORGEJO_URL}
|
||||
- ONLYOFFICE_URL=${ONLYOFFICE_URL}
|
||||
# Security
|
||||
- AUTH_SECRET=${AUTH_SECRET:-change-this-to-a-secure-random-string}
|
||||
# Logging
|
||||
- LOG_LEVEL=${LOG_LEVEL:-info}
|
||||
# CORS
|
||||
- CORS_ORIGIN=${CORS_ORIGIN:-*}
|
||||
volumes:
|
||||
- ./logs:/app/logs
|
||||
- ./data:/app/data
|
||||
networks:
|
||||
- nervura-network
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "healthcheck.js"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
# Optional: Redis for caching
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: nervura-redis
|
||||
ports:
|
||||
- "6379:6379"
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
networks:
|
||||
- nervura-network
|
||||
restart: unless-stopped
|
||||
command: redis-server --appendonly yes
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
# Optional: PostgreSQL for persistent storage
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
container_name: nervura-postgres
|
||||
ports:
|
||||
- "5432:5432"
|
||||
environment:
|
||||
POSTGRES_DB: nervura_electrica
|
||||
POSTGRES_USER: ${DB_USER:-nervura}
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD:-nervura_password}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||
networks:
|
||||
- nervura-network
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-nervura} -d nervura_electrica"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
networks:
|
||||
nervura-network:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
redis_data:
|
||||
postgres_data:
|
||||
61
realms/nervura-electrica/healthcheck.js
Normal file
61
realms/nervura-electrica/healthcheck.js
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Health check script for Nervura Eléctrica Backend
|
||||
* Used by Docker HEALTHCHECK instruction
|
||||
*/
|
||||
|
||||
const http = require('http');
|
||||
|
||||
const HOST = process.env.HOST || 'localhost';
|
||||
const PORT = process.env.PORT || 8080;
|
||||
|
||||
function checkHealth() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = http.request(
|
||||
{
|
||||
hostname: HOST,
|
||||
port: PORT,
|
||||
path: '/health',
|
||||
method: 'GET',
|
||||
timeout: 5000 // 5 seconds timeout
|
||||
},
|
||||
(res) => {
|
||||
if (res.statusCode === 200) {
|
||||
res.on('data', () => {
|
||||
// Consume response data
|
||||
});
|
||||
|
||||
res.on('end', () => {
|
||||
console.log('Health check passed');
|
||||
resolve(true);
|
||||
});
|
||||
} else {
|
||||
console.error(`Health check failed with status: ${res.statusCode}`);
|
||||
resolve(false);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
request.on('error', (err) => {
|
||||
console.error(`Health check error: ${err.message}`);
|
||||
resolve(false);
|
||||
});
|
||||
|
||||
request.on('timeout', () => {
|
||||
console.error('Health check timed out');
|
||||
request.destroy();
|
||||
resolve(false);
|
||||
});
|
||||
|
||||
request.end();
|
||||
});
|
||||
}
|
||||
|
||||
// Run health check
|
||||
checkHealth()
|
||||
.then(isHealthy => {
|
||||
process.exit(isHealthy ? 0 : 1);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Unexpected error during health check:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
82
realms/nervura-electrica/init.sql
Normal file
82
realms/nervura-electrica/init.sql
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
-- PostgreSQL initialization script for Nervura Eléctrica Backend
|
||||
|
||||
-- Create tables for MCP server configurations
|
||||
CREATE TABLE IF NOT EXISTS mcp_servers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(255) NOT NULL,
|
||||
command TEXT NOT NULL,
|
||||
args TEXT[],
|
||||
enabled BOOLEAN DEFAULT true,
|
||||
port INTEGER,
|
||||
health_check TEXT,
|
||||
timeout INTEGER DEFAULT 30000,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Create tables for model configurations
|
||||
CREATE TABLE IF NOT EXISTS model_configs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
provider VARCHAR(50) NOT NULL,
|
||||
api_key_encrypted TEXT,
|
||||
endpoint TEXT,
|
||||
model VARCHAR(100) NOT NULL,
|
||||
enabled BOOLEAN DEFAULT true,
|
||||
priority INTEGER DEFAULT 0,
|
||||
fallback_providers TEXT[],
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Create tables for research cache
|
||||
CREATE TABLE IF NOT EXISTS research_cache (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
query_hash VARCHAR(64) UNIQUE NOT NULL,
|
||||
query TEXT NOT NULL,
|
||||
results JSONB,
|
||||
source VARCHAR(50),
|
||||
ttl INTEGER,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Create indexes for performance
|
||||
CREATE INDEX IF NOT EXISTS idx_mcp_servers_enabled ON mcp_servers(enabled);
|
||||
CREATE INDEX IF NOT EXISTS idx_model_configs_provider ON model_configs(provider, enabled);
|
||||
CREATE INDEX IF NOT EXISTS idx_model_configs_priority ON model_configs(priority DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_research_cache_query_hash ON research_cache(query_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_research_cache_created_at ON research_cache(created_at);
|
||||
|
||||
-- Create a function to update the 'updated_at' column
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
|
||||
-- Create triggers to automatically update 'updated_at' column
|
||||
CREATE TRIGGER update_mcp_servers_updated_at
|
||||
BEFORE UPDATE ON mcp_servers
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_model_configs_updated_at
|
||||
BEFORE UPDATE ON model_configs
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- Create a materialized view for MCP server health statistics
|
||||
CREATE MATERIALIZED VIEW IF NOT EXISTS mcp_health_stats AS
|
||||
SELECT
|
||||
s.id,
|
||||
s.name,
|
||||
s.enabled,
|
||||
COUNT(*) as request_count,
|
||||
AVG(response_time) as avg_response_time,
|
||||
MAX(last_seen) as last_seen
|
||||
FROM mcp_servers s
|
||||
LEFT JOIN mcp_requests r ON s.id = r.server_id
|
||||
GROUP BY s.id, s.name, s.enabled;
|
||||
|
||||
-- Refresh the materialized view periodically
|
||||
-- This would be scheduled with pg_cron or an external scheduler
|
||||
-- SELECT cron.schedule('refresh_mcp_health_stats', '*/5 * * * *', $$REFRESH MATERIALIZED VIEW mcp_health_stats$$);
|
||||
69
realms/nervura-electrica/package.json
Normal file
69
realms/nervura-electrica/package.json
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
"name": "nervura-electrica-aurelio-backend",
|
||||
"version": "1.0.0",
|
||||
"description": "Backend services for nervura-electrica with full Aurelio integration",
|
||||
"main": "dist/aurelio-integration-service.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"start": "node dist/aurelio-integration-service.js",
|
||||
"dev": "ts-node backend/services/aurelio-integration-service.ts",
|
||||
"serve": "nodemon backend/services/aurelio-integration-service.ts",
|
||||
"test": "jest"
|
||||
},
|
||||
"keywords": [
|
||||
"aurelio",
|
||||
"mcp",
|
||||
"model-context-protocol",
|
||||
"ai",
|
||||
"agents",
|
||||
"nervura-electrica",
|
||||
"backend",
|
||||
"integration"
|
||||
],
|
||||
"author": "Portugal Futurista",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"express": "^4.18.2",
|
||||
"axios": "^1.6.0",
|
||||
"typescript": "^5.3.3",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/node": "^20.11.0",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"uuid": "^9.0.1",
|
||||
"tree-sitter": "^0.20.5",
|
||||
"tree-sitter-typescript": "^0.20.3",
|
||||
"tree-sitter-python": "^0.20.2",
|
||||
"tree-sitter-rust": "^0.20.3",
|
||||
"tree-sitter-go": "^0.20.1",
|
||||
"tree-sitter-java": "^0.20.1",
|
||||
"tree-sitter-c": "^0.20.1",
|
||||
"tree-sitter-cpp": "^0.20.3",
|
||||
"tree-sitter-javascript": "^0.20.1",
|
||||
"libgen-api": "^2.1.1",
|
||||
"openalex-js": "^1.0.1",
|
||||
"pdf-parse": "^1.1.1",
|
||||
"cheerio": "^1.0.0-rc.12",
|
||||
"puppeteer": "^22.6.1",
|
||||
"glob": "^10.3.10",
|
||||
"fs-extra": "^11.2.0",
|
||||
"crypto-js": "^4.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.0.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"jest": "^29.7.0",
|
||||
"@types/jest": "^29.5.11",
|
||||
"@types/axios": "^0.14.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/portugal-futurista/nervura-electrica.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/portugal-futurista/nervura-electrica/issues"
|
||||
},
|
||||
"homepage": "https://github.com/portugal-futurista/nervura-electrica#readme"
|
||||
}
|
||||
41
realms/nervura-electrica/server.js
Normal file
41
realms/nervura-electrica/server.js
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Main entry point for Nervura Eléctrica Backend Services
|
||||
* Integrates all Aurelio features and MCP services
|
||||
*/
|
||||
|
||||
const AurelioIntegrationService = require('./dist/aurelio-integration-service');
|
||||
|
||||
// Create and start the service
|
||||
const port = parseInt(process.env.PORT || '8080');
|
||||
const service = new AurelioIntegrationService.default(port);
|
||||
|
||||
console.log('Starting Nervura Eléctrica Backend Services...');
|
||||
console.log(`Environment: ${process.env.NODE_ENV || 'development'}`);
|
||||
console.log(`Listening on port: ${port}`);
|
||||
|
||||
service.start();
|
||||
|
||||
// Handle shutdown signals
|
||||
process.on('SIGTERM', async () => {
|
||||
console.log('Received SIGTERM, shutting down gracefully');
|
||||
await service.shutdown();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('Received SIGINT, shutting down gracefully');
|
||||
await service.shutdown();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
process.on('uncaughtException', (error) => {
|
||||
console.error('Uncaught Exception:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
169
realms/nervura-electrica/start-backend.sh
Executable file
169
realms/nervura-electrica/start-backend.sh
Executable file
|
|
@ -0,0 +1,169 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Nervura Eléctrica Backend Startup Script
|
||||
# Sets up and starts the integrated backend services
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${BLUE}================================${NC}"
|
||||
echo -e "${BLUE}Nervura Eléctrica Backend Setup${NC}"
|
||||
echo -e "${BLUE}================================${NC}"
|
||||
|
||||
# Function to print colored output
|
||||
print_status() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Check if Node.js is installed
|
||||
if ! command -v node &> /dev/null; then
|
||||
print_error "Node.js is not installed. Please install Node.js before running this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check Node.js version
|
||||
NODE_VERSION=$(node --version | cut -d'v' -f2)
|
||||
NODE_MAJOR=$(echo $NODE_VERSION | cut -d'.' -f1)
|
||||
|
||||
if [ "$NODE_MAJOR" -lt 16 ]; then
|
||||
print_error "Node.js version $NODE_VERSION is too old. Please upgrade to Node.js 16 or higher."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_status "Node.js version: $NODE_VERSION"
|
||||
|
||||
# Check if npm is installed
|
||||
if ! command -v npm &> /dev/null; then
|
||||
print_error "npm is not installed. Please install npm before running this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_status "npm is available"
|
||||
|
||||
# Check if we're in the correct directory
|
||||
if [ ! -f "package.json" ]; then
|
||||
print_error "package.json not found. Please run this script from the nervura-electrica root directory."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_status "Found package.json"
|
||||
|
||||
# Install dependencies if node_modules doesn't exist
|
||||
if [ ! -d "node_modules" ]; then
|
||||
print_status "Installing dependencies..."
|
||||
npm install
|
||||
if [ $? -eq 0 ]; then
|
||||
print_status "Dependencies installed successfully"
|
||||
else
|
||||
print_error "Failed to install dependencies"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
print_status "Dependencies already installed"
|
||||
fi
|
||||
|
||||
# Build the project if dist directory doesn't exist or is older than source
|
||||
if [ ! -d "dist" ] || [ "backend/services/aurelio-integration-service.ts" -nt "dist/aurelio-integration-service.js" ]; then
|
||||
print_status "Building project..."
|
||||
npm run build
|
||||
if [ $? -eq 0 ]; then
|
||||
print_status "Build completed successfully"
|
||||
else
|
||||
print_error "Build failed"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
print_status "Build is up to date"
|
||||
fi
|
||||
|
||||
# Check if .env file exists
|
||||
if [ ! -f ".env" ]; then
|
||||
print_warning ".env file not found. Creating a template..."
|
||||
cat > .env << EOF
|
||||
# Nervura Eléctrica Backend Configuration
|
||||
PORT=8080
|
||||
HOST=0.0.0.0
|
||||
|
||||
# AI Provider Keys (set to your actual keys)
|
||||
OPENAI_API_KEY=
|
||||
ANTHROPIC_API_KEY=
|
||||
GOOGLE_API_KEY=
|
||||
OLLAMA_ENDPOINT=http://localhost:11434
|
||||
NVIDIA_NIM_API_KEY=
|
||||
|
||||
# Service Endpoints
|
||||
NEXTCLOUD_URL=
|
||||
FORGEJO_URL=
|
||||
ONLYOFFICE_URL=
|
||||
|
||||
# Security
|
||||
AUTH_SECRET=change-this-to-a-secure-random-string
|
||||
|
||||
# Logging
|
||||
LOG_LEVEL=info
|
||||
|
||||
# CORS
|
||||
CORS_ORIGIN=*
|
||||
|
||||
# IP Whitelist (optional)
|
||||
IP_WHITELIST=
|
||||
EOF
|
||||
print_warning "Template .env file created. Please update with your actual configuration."
|
||||
fi
|
||||
|
||||
# Source environment variables
|
||||
if [ -f ".env" ]; then
|
||||
print_status "Loading environment variables from .env"
|
||||
export $(cat .env | xargs)
|
||||
fi
|
||||
|
||||
# Check if PORT is set
|
||||
PORT=${PORT:-8080}
|
||||
print_status "Using port: $PORT"
|
||||
|
||||
# Check if port is available
|
||||
if lsof -Pi :$PORT -sTCP:LISTEN -t >/dev/null ; then
|
||||
print_error "Port $PORT is already in use. Please stop the existing process or use a different port."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_status "Port $PORT is available"
|
||||
|
||||
# Function to handle shutdown
|
||||
cleanup() {
|
||||
echo ""
|
||||
print_status "Shutting down Nervura Eléctrica Backend..."
|
||||
if [ ! -z "$BACKEND_PID" ]; then
|
||||
kill $BACKEND_PID 2>/dev/null || true
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Trap signals for graceful shutdown
|
||||
trap cleanup SIGTERM SIGINT
|
||||
|
||||
# Start the backend in the background
|
||||
print_status "Starting Nervura Eléctrica Backend..."
|
||||
node server.js &
|
||||
BACKEND_PID=$!
|
||||
|
||||
print_status "Nervura Eléctrica Backend started with PID: $BACKEND_PID"
|
||||
print_status "Service is available at: http://localhost:$PORT"
|
||||
echo ""
|
||||
|
||||
# Wait for the backend process
|
||||
wait $BACKEND_PID
|
||||
47
realms/nervura-electrica/tsconfig.json
Normal file
47
realms/nervura-electrica/tsconfig.json
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "commonjs",
|
||||
"lib": [
|
||||
"ES2020"
|
||||
],
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"removeComments": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"strictFunctionTypes": true,
|
||||
"noImplicitThis": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"moduleResolution": "node",
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
},
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true
|
||||
},
|
||||
"include": [
|
||||
"backend/**/*.ts",
|
||||
"backend/**/*.js",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.js"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"tests"
|
||||
]
|
||||
}
|
||||
107
realms/universalisos/AGENTS.md
Normal file
107
realms/universalisos/AGENTS.md
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
# UniversalisOS Realm
|
||||
|
||||
Agentic conscience operating system layer for the Portugal Futurista ecosystem.
|
||||
|
||||
## Overview
|
||||
|
||||
UniversalisOS is a type-1 hypervisor-based platform for running AI consciousnesses
|
||||
as isolated, safety-critical domains. It follows PikeOS 4.x/5.0 patterns with
|
||||
ARINC 653 partitioning, DO-178C certification compliance, and Mycelium biological
|
||||
learning integration.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
kernel/
|
||||
include/universalisos/vm/
|
||||
consciousness.h # VM context management API (12 functions)
|
||||
vm/
|
||||
consciousness.c # Implementation: init, schedule, migrate, learn, safety
|
||||
docs/parity/
|
||||
RPM_PARITY_SPEC.md # uos-pkg clean-room reimplementation spec
|
||||
docs/porting/
|
||||
apple-silicon-porting-plan.md # Apple Silicon (M1-M4) port plan: Asahi Linux
|
||||
# guest personality + QEMU/vmapple macOS guests
|
||||
research/ # Full research reports backing the plan:
|
||||
# 01 asahi-linux-internals, 02 asahi-u-boot,
|
||||
# 03 qemu-macos-apple-silicon (focus),
|
||||
# 04 emulation + HV hardware features
|
||||
schemas/
|
||||
universalisos-rpm-1.0.xsd # Package definition schema
|
||||
```
|
||||
|
||||
## Kernel API
|
||||
|
||||
The `consciousness_vm_context_t` structure manages:
|
||||
|
||||
- **CPU context**: Registers, PC, LR, CPSR (ARM TrustZone)
|
||||
- **Memory context**: Page tables, heap/stack, quotas
|
||||
- **TrustZone**: Secure mode, SCR/NSACR registers
|
||||
- **Real-time**: Time partitions, budgets, deadlines (ARINC 653)
|
||||
- **Safety**: Watchdog, bounds checking, memory isolation
|
||||
- **Communication**: Message queues, shared memory, synapses
|
||||
- **Learning**: Engrams, maturity, synapse growth
|
||||
|
||||
### API Functions
|
||||
|
||||
```c
|
||||
int consciousness_vm_context_init(consciousness_vm_context_t* ctx, uint32_t id, uint32_t platform);
|
||||
int consciousness_vm_context_destroy(consciousness_vm_context_t* ctx);
|
||||
int consciousness_vm_context_save(consciousness_vm_context_t* ctx);
|
||||
int consciousness_vm_context_restore(consciousness_vm_context_t* ctx);
|
||||
int consciousness_vm_context_schedule(consciousness_vm_context_t* ctx);
|
||||
int consciousness_vm_context_preempt(consciousness_vm_context_t* ctx);
|
||||
int consciousness_vm_context_migrate(consciousness_vm_context_t* ctx, uint32_t target_platform);
|
||||
int consciousness_vm_context_send_synapse(consciousness_vm_context_t* src, uint32_t target_id, void* data, size_t size);
|
||||
int consciousness_vm_context_learn(consciousness_vm_context_t* ctx, void* input, size_t in_size, void* result, size_t out_size);
|
||||
int consciousness_vm_context_check_watchdog(consciousness_vm_context_t* ctx);
|
||||
int consciousness_vm_context_handle_safety_violation(consciousness_vm_context_t* ctx, uint32_t type, void* details);
|
||||
```
|
||||
|
||||
## Safety Levels
|
||||
|
||||
| Level | Standard | Use Case |
|
||||
|-------|----------|----------|
|
||||
| DAL-A | DO-178C | Flight-critical avionics |
|
||||
| DAL-B | DO-178C | Research assistants, analytics |
|
||||
| DAL-C | DO-178C | Creative tools, image generation |
|
||||
| ASIL-D | ISO 26262 | Autonomous vehicle control |
|
||||
| SIL-3 | IEC 61508 | Industrial automation |
|
||||
|
||||
## Packaging
|
||||
|
||||
The `uos-pkg` tool (specified in `RPM_PARITY_SPEC.md`) provides clean-room
|
||||
RPM 4.2 parity for the UniversalisOS build environment:
|
||||
|
||||
- Byte-level `.rpm` format compatibility
|
||||
- 241 macro semantic parity
|
||||
- 16 target architectures + 6 host platforms
|
||||
- Berkeley DB logical parity (uosdb)
|
||||
|
||||
## Integration Points
|
||||
|
||||
- **mycelium-rd/xsd-schemas/**: Consciousness configuration schemas
|
||||
- **.aurelio/brain/**: Session memory and knowledge sync
|
||||
- **realms/alquimista/**: FPGA hardware acceleration (PolarFire SoC)
|
||||
- **dirac/**: IDE extension for consciousness development
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
# Validate all schemas
|
||||
cd ../mycelium-rd/xsd-schemas
|
||||
bash scripts/validate_and_generate.sh
|
||||
|
||||
# Generate code bindings
|
||||
python3 scripts/generate_code.py --all --output generated/
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- `docs/porting/apple-silicon-porting-plan.md` — Apple Silicon porting plan (m1n1 payload entry, asahi-u-boot guest firmware, KVM-ified QEMU vmapple for macOS guests)
|
||||
- Asahi Linux ecosystem: github.com/AsahiLinux/{m1n1,linux,u-boot,docs} (m1n1 hv is the EL2 reference implementation)
|
||||
- QEMU vmapple machine (QEMU >= 10.0, HVF-only upstream): qemu.org/docs/master/system/arm/vmapple.html
|
||||
- PikeOS 4.x/5.0 documentation (see `research/pt-futurista-audit/pikeos-4.x-extraction/`)
|
||||
- ARINC 653 Part 1-5 avionics partitioning standard
|
||||
- DO-178C Software Considerations in Airborne Systems
|
||||
- L4 microkernel architecture (seL4 reference)
|
||||
79
realms/universalisos/Makefile
Normal file
79
realms/universalisos/Makefile
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# UniversalisOS Kernel Build System
|
||||
CC = gcc
|
||||
CFLAGS = -std=c11 -Wall -Wextra -Werror -pedantic \
|
||||
-Wstrict-prototypes -Wmissing-prototypes \
|
||||
-O2 -g -D_GNU_SOURCE \
|
||||
-I kernel/include
|
||||
|
||||
TEST_CFLAGS = -std=c11 -Wall -Wextra -Werror \
|
||||
-O0 -g -DUNIT_TEST \
|
||||
-I kernel/include
|
||||
|
||||
SRCDIR = kernel/vm
|
||||
INCDIR = kernel/include
|
||||
TESTDIR = tests
|
||||
OBJDIR = build
|
||||
BINDIR = bin
|
||||
|
||||
SOURCES = $(wildcard $(SRCDIR)/*.c)
|
||||
OBJECTS = $(patsubst $(SRCDIR)/%.c,$(OBJDIR)/%.o,$(SOURCES))
|
||||
|
||||
TEST_SOURCES = $(wildcard $(TESTDIR)/*.c)
|
||||
TEST_OBJECTS = $(patsubst $(TESTDIR)/%.c,$(OBJDIR)/test_%.o,$(TEST_SOURCES))
|
||||
|
||||
TARGET = $(BINDIR)/universalisos_kernel
|
||||
TEST_TARGET = $(BINDIR)/test_universalisos
|
||||
|
||||
.PHONY: all clean test check fmt validate-schemas generate-code ci
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(OBJDIR):
|
||||
@mkdir -p $(OBJDIR)
|
||||
|
||||
$(BINDIR):
|
||||
@mkdir -p $(BINDIR)
|
||||
|
||||
$(TARGET): $(BINDIR) $(OBJDIR) $(OBJECTS)
|
||||
@echo "LINK $@"
|
||||
@$(CC) $(CFLAGS) -o $@ $(OBJECTS)
|
||||
|
||||
$(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR)
|
||||
@echo "CC $<"
|
||||
@$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/test_%.o: $(TESTDIR)/%.c | $(OBJDIR)
|
||||
@echo "TEST_CC $<"
|
||||
@$(CC) $(TEST_CFLAGS) -c -o $@ $<
|
||||
|
||||
$(TEST_TARGET): $(BINDIR) $(OBJDIR) $(TEST_OBJECTS) $(OBJECTS)
|
||||
@echo "TEST_LINK $@"
|
||||
@$(CC) $(TEST_CFLAGS) -o $@ $(OBJECTS) $(TEST_OBJECTS)
|
||||
|
||||
test: $(TEST_TARGET)
|
||||
@echo "=== Running UniversalisOS Unit Tests ==="
|
||||
@./$(TEST_TARGET)
|
||||
|
||||
check:
|
||||
@which cppcheck >/dev/null 2>&1 && cppcheck --enable=all \
|
||||
--std=c11 --suppress=missingIncludeSystem \
|
||||
-I $(INCDIR) $(SRCDIR) $(TESTDIR) || \
|
||||
echo "cppcheck not installed, skipping static analysis"
|
||||
|
||||
fmt:
|
||||
@which clang-format >/dev/null 2>&1 && \
|
||||
clang-format -i $(SRCDIR)/*.c $(INCDIR)/**/*.h || \
|
||||
echo "clang-format not installed, skipping format"
|
||||
|
||||
clean:
|
||||
@rm -rf $(OBJDIR) $(BINDIR)
|
||||
@echo "Cleaned build artifacts"
|
||||
|
||||
validate-schemas:
|
||||
@cd ../mycelium-rd/xsd-schemas && bash scripts/validate_and_generate.sh
|
||||
|
||||
generate-code:
|
||||
@cd ../mycelium-rd/xsd-schemas && python3 scripts/generate_code.py --all --output generated/
|
||||
|
||||
ci: clean all test validate-schemas
|
||||
@echo "=== CI Pipeline Complete ==="
|
||||
BIN
realms/universalisos/bin/test_universalisos
Executable file
BIN
realms/universalisos/bin/test_universalisos
Executable file
Binary file not shown.
BIN
realms/universalisos/build/consciousness.o
Normal file
BIN
realms/universalisos/build/consciousness.o
Normal file
Binary file not shown.
BIN
realms/universalisos/build/test_test_consciousness.o
Normal file
BIN
realms/universalisos/build/test_test_consciousness.o
Normal file
Binary file not shown.
446
realms/universalisos/docs/porting/apple-silicon-porting-plan.md
Normal file
446
realms/universalisos/docs/porting/apple-silicon-porting-plan.md
Normal file
|
|
@ -0,0 +1,446 @@
|
|||
# UniversalisOS — Apple Silicon Porting Plan
|
||||
|
||||
**Status:** Draft v1.1 — research complete, implementation not started; scope of
|
||||
Asahi-in-QEMU clarified and agreed (2026-07-12)
|
||||
**Date:** 2026-07-12
|
||||
**Scope:** Port UniversalisOS (type-1 hypervisor, PikeOS-style ARINC 653 partitioning)
|
||||
to Apple Silicon (M1–M4), with **Asahi Linux as a guest OS personality** and
|
||||
**QEMU running macOS** as the flagship capability.
|
||||
**Research basis:** four parallel deep-dive streams (Asahi Linux internals,
|
||||
asahi-u-boot source, QEMU/macOS-on-Apple-Silicon landscape, Apple Silicon
|
||||
emulation + hypervisor hardware features). Key sources cited inline.
|
||||
|
||||
---
|
||||
|
||||
## 1. Executive summary
|
||||
|
||||
UniversalisOS today is a **userspace C11 prototype** (`kernel/vm/consciousness.c`,
|
||||
~480 LoC) with stub arch headers for arm (32-bit ARMv7 model), riscv and x86.
|
||||
Porting it to Apple Silicon means turning it into a real **AArch64 EL2 type-1
|
||||
hypervisor** — a large gap, but the ecosystem provides unusually good scaffolding:
|
||||
|
||||
- **m1n1** (Asahi, MIT) already boots at EL2 on M1/M2 and ships a ~9-file
|
||||
hypervisor (`src/hv*.c`) that runs Linux *and macOS XNU* as EL1 guests,
|
||||
including virtio-mmio device models, AIC virtualization and GXF/GL2 support.
|
||||
It is the reference implementation for everything we need.
|
||||
- **asahi-u-boot** is a fully-understood UEFI boot-services layer we can reuse
|
||||
(or bypass) for guest firmware.
|
||||
- **KVM on Asahi Linux** is daily-driver usable on M1/M2 and gives us a
|
||||
type-2 development environment before bare metal works.
|
||||
- **QEMU ≥ 10.0 upstreams the `vmapple` machine** that boots **macOS 12 guests** —
|
||||
but only on macOS hosts via HVF. Making it run under KVM on Asahi (and later
|
||||
inside a UniversalisOS domain) is **greenfield, unclaimed work** — and is the
|
||||
concrete path to "QEMU running macOS" in this project.
|
||||
|
||||
**Recommended target silicon: M1 / M1 Pro/Max / M2 family first.** M3 is
|
||||
experimental (Asahi boots, no GPU), M4 changes the boot environment (SPTM/GL2 on
|
||||
the macho path; raw-boot path still yields clean EL2 for Linux-class payloads).
|
||||
M1 lacks hardware nested virtualization (FEAT_NV) — this shapes the architecture:
|
||||
QEMU must run **bare-metal-adjacent**, not nested inside a Linux guest.
|
||||
|
||||
### 1.1 Scope clarification: Asahi Linux and QEMU (agreed 2026-07-12)
|
||||
|
||||
Three distinct combinations — the plan depends on the first two; only the third
|
||||
is missing from the world today:
|
||||
|
||||
1. **Asahi Linux as a *guest* in QEMU — standard, used throughout the plan.**
|
||||
Asahi is an ordinary ARM64 kernel + Fedora userspace; it boots in
|
||||
`qemu-system-aarch64 -M virt` (TCG / HVF / KVM) on virtio devices — the
|
||||
Apple-specific drivers simply find no hardware. Phase 1 develops
|
||||
UniversalisOS *inside* QEMU virt machines with unmodified Asahi/Fedora
|
||||
`Image` guests, and the Phase 3 personality is this same guest on bare metal.
|
||||
2. **QEMU/KVM running *on* Asahi Linux as host — mature.** This is the build
|
||||
environment for the macOS work (Path 2, §4.2): QEMU 10.x `-accel kvm
|
||||
-cpu host` on bare-metal Asahi.
|
||||
3. **What does not exist:** (a) QEMU emulation of Apple Silicon *hardware*
|
||||
(Inferno models A-series/iOS only; no M-series machine) — not needed, since
|
||||
guests use virtio; (b) **macOS guests in QEMU under KVM on Asahi** — the
|
||||
greenfield flagship (§4).
|
||||
|
||||
---
|
||||
|
||||
## 2. Current state & gap analysis
|
||||
|
||||
### 2.1 What exists (this repo, `realms/universalisos/`)
|
||||
|
||||
| Component | State |
|
||||
|---|---|
|
||||
| `kernel/vm/consciousness.c` | Userspace prototype: 12-function VM-context API (init/save/restore/schedule/preempt/migrate/synapse/learn/watchdog/safety). Stub bodies, atomics, `-DUNIT_TEST` path. |
|
||||
| `kernel/include/universalisos/vm/consciousness.h` | `consciousness_vm_context_t`: CPU context is **32-bit** (`registers[16]`, `cpsr` — ARMv7-era), memory context is `uint32_t` addresses, TrustZone model (SCR/NSACR), ARINC 653 time partitions, Mycelium learning fields. |
|
||||
| `kernel/include/arch/{arm,riscv,x86}/{vm,mm}.h` | 6–9-line stubs (e.g. `arm_vm_context { uint32_t vttbr, vtcr; }`). |
|
||||
| Platform IDs | 1=ARMv7hf, 2=RISC-V64, 3=x86_64. No AArch64. |
|
||||
| `Makefile` | Host gcc build + unit tests; no cross-compile, no freestanding mode, no linker script. |
|
||||
| Schemas / docs | `schemas/universalisos-rpm-1.0.xsd`, `docs/parity/RPM_PARITY_SPEC.md` (uos-pkg). |
|
||||
|
||||
### 2.2 Gap to "type-1 hypervisor on Apple Silicon"
|
||||
|
||||
1. **64-bit CPU context model** — registers X0–X30, SP_ELx, ELR/SPSR per EL,
|
||||
VTTBR_EL2/VTCR_EL2 (64-bit), HCR_EL2, VPIDR/VMPIDR, vtimer state, GICv3
|
||||
vCPU-interface (ICH_*) state. The current `uint32_t`/`cpsr` model cannot be
|
||||
stretched; an `arch/arm64` layer must be designed fresh (the API surface in
|
||||
`consciousness.h` stays stable — contexts become opaque/arch-specific).
|
||||
2. **Privilege & entry** — no EL2 entry code, vector table, stage-2 MMU,
|
||||
FIQ/IRQ handling. m1n1 hands us EL2 with MMU off and x0=FDT (raw boot path);
|
||||
that is the natural entry contract.
|
||||
3. **No device model / IOMMU / interrupt virtualization** — AIC is not a GICD;
|
||||
Apple chips carry a GICv3 **CPU interface with virtualization** ("half a GIC",
|
||||
marcan/maz 2021) that EL2 can use for near-native vGIC injection.
|
||||
4. **No guest firmware/loader** — need FDT generation (reuse m1n1's ADT→FDT
|
||||
personalization) and a boot contract for guests (direct kernel boot or
|
||||
U-Boot-EFI).
|
||||
5. **16K pages** — Apple DART IOMMUs are 16K-granule only (M1/M2); stage-2 must
|
||||
support 16K granule for any passthrough. Host kernel page size is a
|
||||
guest-visible non-issue (guests choose their own granule; 4K guests are
|
||||
proven under KVM on the 16K host via muvm/libkrun).
|
||||
6. **Build system** — needs aarch64 cross/freestanding targets, linker scripts,
|
||||
and a payload packaging step (m1n1 concatenation format).
|
||||
|
||||
None of this invalidates the existing API design — the PikeOS-style domain model
|
||||
maps cleanly onto vCPUs + stage-2 + virtio + shared-memory synapse channels.
|
||||
|
||||
---
|
||||
|
||||
## 3. Platform research synthesis
|
||||
|
||||
### 3.1 Boot chain (confirmed against AsahiLinux/docs + m1n1 + u-boot sources)
|
||||
|
||||
```
|
||||
SecureROM → iBoot1/LLB (NOR) → iBoot2 (APFS Preboot; LocalPolicy img4)
|
||||
→ m1n1 stage 1 (installed once via kmutil configure-boot from 1TR; ESP PARTUUID baked in)
|
||||
→ m1n1 stage 2 (<ESP>/m1n1/boot.bin = m1n1 + DTBs + gzip(u-boot) + config)
|
||||
· parses ADT, inits memory controller/clocks/L3/PCIe/display pipe
|
||||
· personalizes per-platform FDT, enters payload at EL2, MMU off, x0=FDT
|
||||
→ U-Boot (asahi fork) → GRUB (vanilla) → Linux (UEFI+FDT)
|
||||
```
|
||||
|
||||
Entry points for UniversalisOS, in order of preference:
|
||||
|
||||
| Option | What it means | Verdict |
|
||||
|---|---|---|
|
||||
| **A. UniversalisOS as m1n1 payload** (replacing U-Boot in `boot.bin`) | m1n1 stage 2 does all ugly bring-up (DRAM, clocks, PCIe, display), hands us EL2 + personalized FDT. We never touch kmutil again; updates = `update-m1n1`-style ESP rewrite. | **Chosen path.** Minimal TCB on Apple-specific bring-up; m1n1 is MIT and designed as a payload host. |
|
||||
| B. m1n1 as a UniversalisOS payload | We chainload m1n1 from iBoot and embed it | More control, but we own bring-up ordering — no real benefit over A. |
|
||||
| C. UniversalisOS replaces m1n1 entirely | We reimplement memory-controller/clocks/PCIe/display init | Rejected: disproportionate, and m1n1's init is the moving target Asahi maintains. |
|
||||
|
||||
### 3.2 asahi-u-boot (verified against sparse clone of `AsahiLinux/u-boot`)
|
||||
|
||||
- Base: **upstream U-Boot v2025.10**; branches: `asahi` (dev, HEAD 2025-12-21),
|
||||
**`asahi-releng`** (what distros ship; HEAD 2026-05-24, adds **M3 support**,
|
||||
ESP autodetection, `ENV_IS_IN_FAT`). No M4 support anywhere.
|
||||
- Board code: `arch/arm/mach-apple/` (not `board/apple/`). One defconfig,
|
||||
`apple_m1_defconfig`, covers all SoCs (t8103, t8112, t6000–t6002,
|
||||
t6020–t6022; releng adds t8122/t603x).
|
||||
- Direct hardware touched: **NVMe/ANS2 via RTKit + SART** (heaviest), USB
|
||||
(DWC3/xHCI + ATC PHY; ASMedia xHCI on t602x), SPI/MTP keyboards, Apple PCIe,
|
||||
PMGR, S5L UART (via `serial_s5p`). **No interrupts (fully polled), no AIC
|
||||
driver, no GPU** (simplefb from m1n1's `/chosen/framebuffer`), no persistent
|
||||
EFI variables, no networking.
|
||||
- Runs at EL2 normally; **already has an EL1-under-hypervisor code path**
|
||||
(`ft_board_setup()` checks `current_el() == 1` — built for the m1n1 hv).
|
||||
- **Role in our plan:** guest firmware option (a): rebuild with
|
||||
`apple_m1_defconfig` minus NVMe_APPLE/PCIe/ASMedia/ATC/SPI-kbd, plus virtio —
|
||||
gives GRUB/systemd-boot guests UEFI boot services for free. Option (b)
|
||||
(preferred for phase 1): skip U-Boot, direct-boot the Linux EFI stub /
|
||||
`Image`+FDT from our loader — the same x0=FDT contract m1n1 uses.
|
||||
|
||||
### 3.3 Asahi kernel fork (`AsahiLinux/linux`, branch `asahi`)
|
||||
|
||||
- `bits/*` topic branches merged into `asahi`; downstream burden ≈ **>90k LoC /
|
||||
~1,250 patches** (Linux 6.13 era). Upstreaming is continuous (SMC core in 6.17,
|
||||
M2 Pro/Max DTs + 4-level DART in 6.18, USB3 in 6.19).
|
||||
- Still downstream: **DCP display, AGX GPU (Rust `drm/asahi`), audio, TSO**.
|
||||
- Fedora Asahi Remix ships **`kernel-16k`** (16K pages mandatory: DART granule).
|
||||
- KVM works since early 2021 (marcan/maz). Notable merged pieces:
|
||||
- **hVHE** (Marc Zyngier, 2023) — VHE in the nVHE hypervisor, tested nested on M2.
|
||||
- **PMUv3-on-Apple** (Oliver Upton, 14 patches, merged **Linux 6.15**) —
|
||||
trap-emulated vPMU via Apple's IMPDEF PMUv3 traps (HACR_EL2[56]); unblocked
|
||||
Windows-on-ARM KVM guests.
|
||||
- **Nested virt (FEAT_NV2)** on M2+: `kvm-arm.mode=nested` with kernel ≥ 6.16 +
|
||||
QEMU ≥ 10.x — experimental (16K stage-2 issues observed Jan 2026).
|
||||
- **M1: no FEAT_NV — nested virtualization is impossible in hardware.**
|
||||
- IMPDEF features (SPRR/GXF, TSO in ACTLR_EL1) are deliberately **not** exposed
|
||||
to KVM guests (upstream policy: no IMPDEF state in guests).
|
||||
|
||||
### 3.4 Per-generation hardware matrix (for the hypervisor design)
|
||||
|
||||
| | M1 (t8103, t600x) | M2 (t8112, t602x) | M3 (t8122, t603x) | M4 (t8132, t604x) |
|
||||
|---|---|---|---|---|
|
||||
| EL2 | Clean, usable (VHE) | Clean + **FEAT_NV2** | Usable (AIC redesigned — AIC2/3 work ongoing) | Usable via **raw boot object**; macho path now enters SPTM@GL2 + MMU-on |
|
||||
| SPRR/GXF | Present (m1n1 handles; `src/gxf.c`) | Present; SPTM appears for macOS 15 | PPL/GL2 era | **SPTM mandatory on macho path**; raw boot bypasses (extensions off) |
|
||||
| Interrupts | AIC + GICv3 vCPU-if ("half a GIC") | AIC2 + same vCPU-if | AIC2/3 (RE in progress) | AIC3 (RE in progress) |
|
||||
| IOMMU | DART, 16K granule, single-stage streams | + SART (NVMe filter) | similar | similar |
|
||||
| Asahi status | Full support | Full support | Experimental boot, no GPU | Raw-boot Linux experiments only |
|
||||
| **UniversalisOS target** | ✅ primary | ✅ primary | ⚠️ later | ⚠️ later (raw-boot entry) |
|
||||
|
||||
Key design consequences:
|
||||
|
||||
- **vGIC**: use the hardware GICv3 vCPU interface (ICH_* registers) like KVM does;
|
||||
device IRQs arrive via AIC and are injected as vGIC SPIs. Physical timer is
|
||||
wired to **FIQ** (bypasses AIC) — the hypervisor must handle FIQ and deliver
|
||||
virtual timers (CNTVOFF_EL2 offsetting works).
|
||||
- **Passthrough**: DART has no SMMU-style nesting — the hypervisor programs DART
|
||||
streams itself (guest IPA→PA as IOVA→PA). Feasible, all-software, no vIOMMU
|
||||
assist; 16K-granule stage-2 required.
|
||||
- **XNU guests** need GXF/GL2 cooperation (PPL) — m1n1 implements this
|
||||
(`gl2_call()`); on M4 this becomes SPTM territory (unsolved — M4 macOS guests
|
||||
are out of scope for v1).
|
||||
|
||||
---
|
||||
|
||||
## 4. QEMU running macOS — the focus
|
||||
|
||||
### 4.1 State of the art (verified, mid-2026)
|
||||
|
||||
**What exists: QEMU ≥ 10.0 (April 2025) ships the `vmapple` machine** —
|
||||
a clean-room reimplementation of the Virtualization.framework device model for
|
||||
arm64 macOS guests (Alexander Graf v1/v2 2023; Phil Dennis-Jordan respins
|
||||
v3–v17 merged for 10.0; XHCI fixes; `MAINTAINERS` has a VMapple section;
|
||||
docs: `qemu.org/docs/master/system/arm/vmapple.html`).
|
||||
|
||||
Device model: GICv3 (no ITS — legacy IRQs only), GPEX PCIe, XHCI+USB HID,
|
||||
PL011/PL031/PL061, pvpanic, `vmapple-aes`, `vmapple-cfg`, `vmapple-bdif`,
|
||||
`vmapple-virtio-blk-pci` (Apple's nonstandard virtio-blk variant, aux/root),
|
||||
`apple-gfx-mmio` (ParavirtualizedGraphics.framework, Metal-backed).
|
||||
|
||||
**Hard limitations today:**
|
||||
- **macOS 12.x guests only.** 13+ fails in early boot even on HVF; no public
|
||||
progress since 2025. Authors suspect CPU-behavior differences.
|
||||
- **HVF-only. macOS-arm64 hosts only.** `hw/vmapple/Kconfig`: `depends on HVF`,
|
||||
`select MAC_PVG_MMIO` (Objective-C, Darwin-only). **The machine cannot even be
|
||||
compiled for Linux hosts today** — no QEMU on Asahi contains vmapple.
|
||||
- Guest must be **pre-provisioned from an IPSW by a VZ tool on a Mac**
|
||||
(`macosvm`, tart, vfkit `--bootloader macos`); QEMU reuses the resulting
|
||||
`disk.img` + `aux.img` + ECID/UUID. No install-in-QEMU.
|
||||
- No Rosetta in guest (TSO needs a private Apple entitlement).
|
||||
- Guest virtio drivers: **Apple ships its own** in the vmapple kernel
|
||||
(virtio-blk/net/rng/console, PVG) — no third-party arm64 kexts exist; plan on
|
||||
Apple's in-box set only. Display: PVG (host macOS only) or headless VNC/SSH.
|
||||
|
||||
**On Asahi Linux / KVM: nothing exists.** Graf flagged it as desirable in 2023
|
||||
("This device model would enable very nice use cases with KVM on an Asahi Linux
|
||||
device"); no patches were ever posted. **This is unclaimed territory — our
|
||||
flagship contribution.**
|
||||
|
||||
Boot mechanics a macOS guest requires from its VMM (AVP = "Apple Virtual
|
||||
Platform", board `vma2ap`, kernel flavor `RELEASE_ARM64_VMAPPLE`):
|
||||
`AVPBooter.vmapple2.bin` as `-bios` (stage-0 iBoot variant shipped unencrypted
|
||||
in Virtualization.framework — an RE goldmine), AuxiliaryStorage (NVRAM/policy),
|
||||
MachineIdentifier/HardwareModel/ECID, the vmapple device set, and virtio
|
||||
devices. **No SMC, no ANS/NAND emulation needed** (unlike x86 macOS).
|
||||
References: `saagarjha/VirtualApple`, `NyanSatan/Virtual-iBoot-Fun` (patched
|
||||
AVPBooter + DFU restore to patched XNU with GDB), eclecticlight VM-boot series.
|
||||
|
||||
### 4.2 Three paths to "QEMU runs macOS" (in dependency order)
|
||||
|
||||
**Path 1 — Dev-loop on macOS hosts (zero new code).**
|
||||
Run upstream QEMU ≥ 10.0 `-accel hvf -M vmapple` on a Mac; provision a macOS 12
|
||||
guest via `macosvm` from a `UniversalMac_12.x_Restore.ipsw`. Gives the team a
|
||||
working reference guest, the exact device/ABI contract to replicate, and a CI
|
||||
substrate. Cost: days. **Do this first.**
|
||||
|
||||
**Path 2 — KVM-ify vmapple for Asahi Linux (the greenfield core).**
|
||||
Fork QEMU (track 10.x), and:
|
||||
1. Lift the `depends on HVF` in `hw/vmapple/Kconfig`; guard `MAC_PVG_MMIO`
|
||||
behind host-Darwin (run headless: serial + VNC; `apple-gfx` stays Darwin-only).
|
||||
2. GIC: replace any HVF userspace-GIC assumptions with in-kernel vGICv3
|
||||
(`create_gic()` path — modest, per code inspection).
|
||||
3. Sysreg/CPU: `-cpu host` works under KVM; audit HVF-specific sysreg sync for
|
||||
KVM equivalents; add XNU-needed quirks (PMU via the 6.15 pmuv3-asahi traps,
|
||||
AIDR_EL1/ACTLR exposure as needed — noting upstream's IMPDEF-exposure
|
||||
resistance; carry downstream in the Asahi kernel if required).
|
||||
4. Provisioning: reuse Mac-side VZ tooling output (disk/aux/ECID) — or implement
|
||||
the DFU-restore flow (Virtual-iBoot-Fun style) to install from IPSW on Linux.
|
||||
5. Attack the **macOS 13+ early-boot blocker** (unsolved even on HVF — likely
|
||||
CPU-behavior; m1n1-hv tracing of a 13.x boot is the best diagnostic tool).
|
||||
Deliverable: `qemu-system-aarch64 -accel kvm -cpu host -M vmapple` booting
|
||||
macOS 12 (stretch: 13+) on Asahi Linux. Upstreamable in principle.
|
||||
|
||||
**Path 3 — macOS as a UniversalisOS domain (integration, not nesting).**
|
||||
Because M1 has no FEAT_NV and M2 nested KVM is experimental, **do not** run
|
||||
QEMU+KVM inside an Asahi guest. Instead QEMU runs **bare-metal-adjacent**: as a
|
||||
device-model/VMM domain directly on UniversalisOS at EL2 (or a privileged
|
||||
personality at EL1 with hypercall access), following the **Xen qemu-dm/stubdom
|
||||
pattern**: UniversalisOS traps MMIO/E2 faults and forwards IOREQ to the QEMU
|
||||
domain; data plane via **vhost-user** backends. The vmapple device model +
|
||||
AVPBooter contract from Path 2 drop into this domain unchanged. UniversalisOS
|
||||
must additionally tolerate XNU's **GXF/PPL** usage (port m1n1's `gxf.c`/
|
||||
`gl2_call()` semantics) — on M1/M2 this is solved prior art (m1n1 runs macOS ≤
|
||||
13.5 as a guest today).
|
||||
|
||||
**Provisioning/legal note:** macOS guests require Apple IPSW images and Apple's
|
||||
AVPBooter blob (unencrypted, redistributed inside Virtualization.framework —
|
||||
license terms apply: Apple's SLA permits macOS VMs only on Apple hardware; we
|
||||
are on Apple hardware). MachineIdentifier/HardwareModel are generated, not
|
||||
extracted. Document this in the plan's compliance section; no App
|
||||
Store/FairPlay in guests (same as VZ).
|
||||
|
||||
### 4.3 QEMU architecture notes for integration
|
||||
|
||||
- QEMU device models are QOM/main-loop coupled → reuse **out-of-process**
|
||||
(qemu-dm style) or via **vhost-user** frontends; in-process embedding is
|
||||
impractical. QEMU is GPLv2 — keep it in its own domain (the Xen containment
|
||||
argument) so the EL2 core stays license-clean.
|
||||
- Alternatives studied: Firecracker/crosvm/Cloud Hypervisor (no Apple host
|
||||
path), **libkrun** (only mature Rust VMM with an HVF backend — useful for the
|
||||
macOS-hosted dev loop), Inferno (`hw/arm/apple-silicon/` — best public C
|
||||
reference for ADT/ANS2/DART/SART/SEP/GXF semantics, GPL-3 → documentation use
|
||||
only; prefer m1n1 (MIT) as citable reference).
|
||||
|
||||
---
|
||||
|
||||
## 5. Target architecture
|
||||
|
||||
```
|
||||
Apple Silicon (M1/M2), EL2 entered via m1n1 stage 2
|
||||
┌──────────────────────────────────────────────────────────────────────┐
|
||||
│ UniversalisOS Core (EL2, freestanding C11, arch/arm64) │
|
||||
│ · stage-2 MMU (16K granule) · vGICv3 (hw ICH_*) + AIC backend │
|
||||
│ · FIQ/timer virtualization · GXF/GL2 shim (for XNU guests) │
|
||||
│ · ARINC-653 partition scheduler · consciousness VM-context engine │
|
||||
│ · DART/SART passthrough manager · hypercall/IOREQ interface │
|
||||
├───────────────┬──────────────────┬─────────────────┬─────────────────┤
|
||||
│ Personality: │ Personality: │ Personality: │ Domain: │
|
||||
│ Asahi Linux │ macOS (QEMU │ Consciousness │ qemu-dm / │
|
||||
│ (EL1 guest, │ vmapple domain, │ partitions │ vhost-user │
|
||||
│ FDT + virtio, │ AVPBooter, XNU │ (EL1/EL0 sand- │ backends, │
|
||||
│ kernel-16k or │ at EL1, GXF via │ boxes, Mycelium │ device models │
|
||||
│ direct Image) │ shim, virtio) │ synapses via │ (GPL, isolated) │
|
||||
│ │ │ shared memory) │ │
|
||||
└───────────────┴──────────────────┴─────────────────┴─────────────────┘
|
||||
```
|
||||
|
||||
- **Asahi Linux personality**: FDT guest, direct `Image` boot (phase 1) or
|
||||
U-Boot-EFI (phase 2+); virtio-mmio/blk/net/console; spin-table SMP; vGIC
|
||||
SPIs for devices; vtimer via CNTVOFF_EL2; 16K stage-2 when DART-passthrough
|
||||
is granted (NVMe via virtio first; real-ANS passthrough is a later,
|
||||
isolation-weakening option).
|
||||
- **macOS personality**: per §4.2 Path 3. macOS 12 first.
|
||||
- **Consciousness partitions**: the existing `consciousness_vm_context_t`
|
||||
lifecycle maps to EL1/EL0 sandboxed vCPUs with stage-2 isolation, ARINC-653
|
||||
time partitions, watchdog → SAFE_STATE, synapses over shared-memory rings
|
||||
(cache-coherent; stage-2-shared pages).
|
||||
|
||||
---
|
||||
|
||||
## 6. Phased roadmap
|
||||
|
||||
### Phase 0 — AArch64 foundation in the prototype (host/QEMU-TCG dev)
|
||||
- Add `kernel/include/arch/arm64/{vm,mm,regs}.h`: 64-bit context
|
||||
(`x[31]`, `sp_el0/1`, `elr_el1/2`, `spsr`, `vttbr_el2`, `vtcr_el2`,
|
||||
`hcr_el2`, vtimer, ICH state); make `consciousness_vm_context_t.cpu_context`
|
||||
arch-opaque (union/`arch_cpu_context_t`).
|
||||
- Add platform id `4 = ARCH_APPLE_SILICON_AARCH64` (keep 1–3); extend
|
||||
`consciousness_vm_context_init/migrate` switch; add unit tests for the
|
||||
arm64 context (save/restore/16K quota checks).
|
||||
- Makefile: `CROSS_COMPILE=aarch64-linux-gnu-` target, `-ffreestanding
|
||||
-nostdlib` build mode, linker script, keep host test build intact.
|
||||
- Exit: `make test` green on x86 host; `qemu-system-aarch64 -M virt -cpu max`
|
||||
boots a stub EL2 payload that prints over PL011.
|
||||
|
||||
### Phase 1 — EL2 core on QEMU `virt` (KVM on Asahi or HVF on macOS dev hosts)
|
||||
- EL2 entry + vector table, stage-2 MMU (4K and 16K granule), UART, arch
|
||||
timer + FIQ path model, vGICv3 bring-up, direct-boot a Linux `Image`
|
||||
guest with generated FDT + virtio-mmio console/blk.
|
||||
- Port the 12 consciousness API functions onto real vCPU primitives
|
||||
(schedule/preempt = vCPU run/stop; save/restore = sysreg capture).
|
||||
- Exit: unmodified Asahi/Fedora arm64 cloud `Image` boots to login under
|
||||
UniversalisOS inside QEMU.
|
||||
|
||||
### Phase 2 — Bare metal via m1n1 (M1/M2)
|
||||
- Package UniversalisOS as an m1n1 stage-2 payload (`boot.bin` concatenation,
|
||||
gzip); ESP update flow à la `update-m1n1`; serial-over-m1n1-proxy and
|
||||
framebuffer console via `/chosen/framebuffer`.
|
||||
- Consume m1n1's personalized FDT; AIC driver (from Asahi docs `hw/soc/aic.md`
|
||||
+ Linux `irq-apple-aic.c` semantics); PMGR domains; watchdog.
|
||||
- Exit: UniversalisOS boots on a Mac mini M1/M2 from power-on; consciousness
|
||||
partitions run on bare metal.
|
||||
|
||||
### Phase 3 — Asahi Linux guest personality (bare metal)
|
||||
- Direct-boot Fedora Asahi kernel (`Image`+initramfs+FDT) as EL1 guest:
|
||||
virtio-blk rootfs (image or partition), virtio-net, vGIC injection of
|
||||
pass-through device IRQs, spin-table SMP, 16K stage-2 + DART stream
|
||||
programming for an optional real-device assignment (start with USB xHCI).
|
||||
- Optional: U-Boot-EFI guest firmware build (per §3.2 option a) for
|
||||
GRUB/systemd-boot workflows.
|
||||
- Exit: Fedora Asahi Remix userspace fully usable as a UniversalisOS guest;
|
||||
KVM **disabled** in that guest on M1 (no FEAT_NV), experimental on M2.
|
||||
|
||||
### Phase 4 — Device-model domain & vhost-user (QEMU integration spine)
|
||||
- IOREQ/hypercall interface; run QEMU (Linux-hosted build) as a
|
||||
device-model domain for a Linux guest (qemu-dm pattern); vhost-user
|
||||
backends for blk/net; measure overhead vs in-HV virtio.
|
||||
- Exit: Asahi guest served its virtio devices by the QEMU domain.
|
||||
|
||||
### Phase 5 — QEMU runs macOS (flagship)
|
||||
1. Path 1 dev-loop (HVF vmapple, macOS 12) — immediately, in parallel with
|
||||
Phase 1.
|
||||
2. Path 2: KVM-ify vmapple (§4.2) on Asahi bare metal.
|
||||
3. Path 3: vmapple domain on UniversalisOS with GXF/GL2 shim (port m1n1
|
||||
`gxf.c` semantics), AVPBooter + aux/root provisioning replicated,
|
||||
headless serial/VNC first.
|
||||
4. Stretch: macOS 13+ early-boot blocker (trace with m1n1 hv), PVG-class
|
||||
graphics forwarding story, IPSW restore-on-Linux (DFU flow).
|
||||
- Exit: `qemu-system-aarch64 -accel kvm -M vmapple` boots macOS 12 on Asahi;
|
||||
the same guest runs as a UniversalisOS personality.
|
||||
|
||||
### Phase 6 — Safety & productization
|
||||
- ARINC-653 schedule enforcement on real hardware (budget/deadline
|
||||
accounting via vPMU traps / arch timer), watchdog hardware integration
|
||||
(Apple WDT), DART-enforced DMA isolation per domain, memory-integrity
|
||||
checks, SAFE_STATE transitions tested by fault injection.
|
||||
- Documentation toward DO-178C DAL-C evidence patterns (the realm's stated
|
||||
creative-tools tier), uos-pkg packaging of guest images.
|
||||
|
||||
---
|
||||
|
||||
## 7. Risks & open questions
|
||||
|
||||
| Risk | Severity | Mitigation |
|
||||
|---|---|---|
|
||||
| macOS 13+ early-boot failure unsolved (even on HVF) | High | Plan around macOS 12 for v1; use m1n1-hv tracing to diagnose; track upstream vmapple work |
|
||||
| Apple may close the raw-boot path on future silicon | Medium | Target M1/M2 (huge installed base); monitor Asahi 39C3-style updates |
|
||||
| M4 SPTM/GL2 boot changes | Medium | Defer M4; raw-boot entry still yields EL2 |
|
||||
| Upstream resistance to IMPDEF guest exposure (KVM) | Medium | Carry Asahi-style downstream patches; keep them minimal and documented |
|
||||
| QEMU GPLv2 in the TCB | Low | Domain isolation (qemu-dm pattern); EL2 core stays C11/proprietary-clean; m1n1 is MIT |
|
||||
| vmapple virtio-blk is Apple-nonstandard | Low | QEMU already implements it; our HV domain reuses that code path |
|
||||
| Legal: macOS VM licensing (Apple SLA, Apple-branded hardware only) | Low–Med | We run on Apple hardware; document compliance; no FairPlay/App Store in guests |
|
||||
| Nested virt impossible on M1 | Known | Architecture avoids nesting: QEMU runs bare-metal-adjacent |
|
||||
|
||||
Open questions to resolve in Phase 0/1: exact hVHE/PMUv3 merge versions to pin
|
||||
as kernel baseline (6.15/6.16 window — verify via `git log` on
|
||||
`AsahiLinux/linux`); M3 nested/PMU-trap status; whether vmapple's 13+ blocker
|
||||
is CPU-behavior (would bite KVM equally) or HVF-specific.
|
||||
|
||||
---
|
||||
|
||||
## 8. Reference index
|
||||
|
||||
**Repos:** `AsahiLinux/{m1n1,linux,u-boot,docs,asahi-scripts,muvm,asahi-installer}` ·
|
||||
`qemu-project/qemu` (`hw/vmapple/`, `docs/system/arm/vmapple.rst`) ·
|
||||
`ChefKissInc/Inferno` · `saagarjha/VirtualApple` · `NyanSatan/Virtual-iBoot-Fun` ·
|
||||
`s-u/macosvm` · `cirruslabs/tart` · `crc-org/vfkit` · `containers/libkrun` ·
|
||||
`amarioguy/AppleWOAProject`
|
||||
|
||||
**Docs:** `asahilinux.org/docs/` — `platform/open-os-interop`, `fw/boot`,
|
||||
`fw/adt`, `fw/macho-boot-protocol`, `sw/m1n1-user-guide`, `sw/m1n1-dev-guide`,
|
||||
`sw/m1n1-hypervisor`, `sw/u-boot`, `sw/kernel-config`, `sw/broken-software`
|
||||
(16K), `sw/windows-11-vm` (KVM howto), `hw/soc/{aic,memmap,soc-codenames,smc}`,
|
||||
`hw/cpu/{sprr-gxf,system-registers,smp}`, `platform/feature-support/{m1,m2,m3,m4}` ·
|
||||
`docs.u-boot-project.org/en/latest/board/apple/m1.html` ·
|
||||
`blog.svenpeter.dev/posts/m1_sprr_gxf/`
|
||||
|
||||
**Patch series:** Graf vmapple v1 (2023-06, patchew) / v2 (2023-08) ·
|
||||
Dennis-Jordan v17 (2025-01, merged QEMU 10.0) · Graf HVF-aarch64 (QEMU 6.2,
|
||||
2021-12) · Zyngier hVHE v3 (2023-06) · Zyngier KVM NV2 v11 (2023-11) · Upton
|
||||
PMUv3-on-Apple v3 (2025-03, merged 6.15) · marcan TSO (2024-04) · Auger QEMU
|
||||
nested-virt RFC v3 (2024-03)
|
||||
|
||||
**Reports/talks:** Asahi progress reports (Jan/Feb 2021 KVM+AIC; Sep 2021 DART
|
||||
16K; 6.14 PMUv3+downstream stats; 6.17 M3 status) · 39C3 (Dec 2025, M3/M4/M5) ·
|
||||
Sven Peter Mastodon 2025-04-04 (M4 SPTM/GL2) · Fedora nested-virt field report
|
||||
(discussion.fedoraproject.org/t/nested-virtualization/179358, Jan 2026) ·
|
||||
zhuowei "Booting a macOS Apple Silicon kernel in QEMU" (worthdoingbadly.com,
|
||||
2020) · Xen-devel "Xen for Apple Silicon" thread (2024-07, feasibility only)
|
||||
|
||||
**Local:** `realms/universalisos/AGENTS.md` · `kernel/vm/consciousness.c` ·
|
||||
`research/pt-futurista-audit/pikeos-4.x-extraction/` (PikeOS reference) ·
|
||||
`mycelium-rd/xsd-schemas/` (consciousness/hypervisor-domain schemas)
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
|
||||
# Asahi Linux / Apple Silicon — Technical Research Report for UniversalisOS Porting Plan
|
||||
|
||||
**Research date:** 2026-07-12. Sources: AsahiLinux/m1n1, AsahiLinux/docs, AsahiLinux/linux (GitHub), asahilinux.org blog, lore.kernel.org/patchew/LKML, phoronix, Fedora docs. Confidence tags: **[C]** confirmed from primary source, **[U]** uncertain/secondary source, **[C?]** confirmed fact, exact detail (e.g. kernel version) not independently verified.
|
||||
|
||||
---
|
||||
|
||||
## 1. Boot Chain on Apple Silicon
|
||||
|
||||
### 1.1 Stages [C]
|
||||
|
||||
From `AsahiLinux/docs` → `docs/fw/boot.md` ("Apple Silicon Boot Flow") and `docs/platform/open-os-interop.md`:
|
||||
|
||||
```
|
||||
SecureROM (Boot ROM, SoC-integrated)
|
||||
→ iBoot1 / LLB (NOR flash; reads NVRAM boot-volume, SEP-checked LocalPolicy img4)
|
||||
→ iBoot2 (OS-level loader, in the APFS Preboot volume; loads XNU kernelcache
|
||||
or a "fuOS" custom kernel if the boot policy allows it)
|
||||
→ m1n1 stage 1 (installed as the custom kernel via `kmutil configure-boot`)
|
||||
- parses Apple Device Tree (ADT), early HW init (memory controller,
|
||||
USB-C charging, HDMI on Mac mini), disables watchdog, shows logo
|
||||
- chainloads m1n1 stage 2 from a FAT32 ESP (chainloading code is Rust,
|
||||
part of the future secureboot attack surface)
|
||||
→ m1n1 stage 2 (raw binary + concatenated payloads: FDTs, U-Boot, optionally
|
||||
kernel Image + initramfs)
|
||||
- selects FDT per platform, personalizes it with dynamic data from ADT
|
||||
(memory map, framebuffer, rng seed, /chosen bootargs, spin-table)
|
||||
→ U-Boot (EFI boot services + FAT/NVMe/USB; Apple fork: AsahiLinux/u-boot)
|
||||
→ GRUB (or any UEFI loader; GRUB needs no Apple-specific patches)
|
||||
→ Linux kernel (standard UEFI+FDT ARM64 boot)
|
||||
```
|
||||
|
||||
- Boot policy/security: installing a custom kernel requires **1TR ("one true recoveryOS")**, reduced security (`bputil` / LocalPolicy `coih` fuOS hash). Boot modes documented in `fw/boot.md` (macOS=0, 1TR=1, recoveryOS=2, ...).
|
||||
- The Asahi Linux Installer (github.com/AsahiLinux/asahi-installer) builds a "stub macOS" APFS container (~2.5 GB) + per-OS ESP (~512 MB FAT32) per OS — this layout is the project's recommended interop standard (`docs/platform/open-os-interop.md`).
|
||||
|
||||
### 1.2 m1n1 (github.com/AsahiLinux/m1n1) [C]
|
||||
|
||||
- MIT license; descended from "mini" (Wii). Build: `make` (aarch64-linux-gnu-gcc or clang; `RELEASE=1`, `CHAINLOADING=1` options; output `build/m1n1.{bin,macho}`).
|
||||
- **Payloads by concatenation**: kernel images (must be compressed or last), FDTs (raw or compressed), initramfs cpio (compressed); gzip/xz supported.
|
||||
- **Boot protocol** (`docs/sw/m1n1-dev-guide.md`): trivial subset of XNU boot protocol; raw binary entry at **0x800 with MMU off**, `x0` = physical address of XNU `boot_args` struct (`src/xnuboot.h`); RVBAR at offset 0; legacy Mach-O images deprecated for Linux payloads (use raw `m1n1.bin`).
|
||||
- **ADT→FDT translation**: m1n1 reads Apple's ADT and personalizes a template FDT for Linux/U-Boot [C].
|
||||
- **Proxy mode**: USB CDC-ACM gadget on all Thunderbolt ports (`/dev/ttyACM0` proxy, `/dev/ttyACM1` hypervisor virtual UART); Python `proxyclient/` (tools: `linux.py`, `chainload.py`, `run_guest.py`, `run_guest_kernel.sh`, `freebsd.py`, `shell.py`; tracing modules in `proxyclient/hv/`). ~7-second kernel build-test cycle.
|
||||
|
||||
### 1.3 m1n1 hypervisor (hv) [C]
|
||||
|
||||
Source files in m1n1 repo: `src/hv.c`, `src/hv.h`, `src/hv_asm.S`, `src/hv_exc.c`, `src/hv_vm.c`, `src/hv_aic.c`, `src/hv_vuart.c`, `src/hv_wdt.c`, **`src/hv_virtio.c`** (virtio-mmio device emulation for guests — confirmed by reading the file).
|
||||
|
||||
- Runs at **EL2**; guests (macOS XNU or Linux) run at **EL1**. Stage-2 translation: RAM mapped 1:1, MMIO regions fault → data abort → Python-traceable MMIO hooks. Event types (`hv.h`): `HV_HOOK_VM, HV_VTIMER, HV_USER_INTERRUPT, HV_WDT_BARK, HV_CPU_SWITCH, HV_VIRTIO, HV_PANIC`.
|
||||
- Provides: virtual UART over USB, virtualized AIC IRQ delivery, watchdog virtualization, virtio devices, GDB/LLDB stub (LLDB recommended — pointer-auth + Darwin dyld support), time-stealing accounting.
|
||||
- **ABI is explicitly unstable** — `chainload.py` must be re-run after any m1n1 tree update (`docs/sw/m1n1-hypervisor.md`).
|
||||
- macOS guest support targets **macOS Ventura 13.5 max** (doc warning). Linux guests documented in `m1n1-user-guide.md` (`run_guest_kernel.sh`).
|
||||
- **Correction to a premise in the task**: on M1/M2, m1n1 does *not* "emulate EL2 for Linux" in normal operation — iBoot2 hands control to m1n1 at real EL2, and m1n1 enters **Linux at EL2 with VHE (HCR_EL2.E2H=1)**. The hv component is a development/RE tool and guest runner, not part of the production boot path. There is **no EL3** on Apple Silicon.
|
||||
|
||||
### 1.4 EL2 / GXF / SPTM situation per chip generation [C + U]
|
||||
|
||||
- **M1/M2 (t8103, t6000–t6002, t8112, t6020–t6022)**: real, usable EL2. Linux runs at EL2/VHE; KVM works bare-metal (§2). M2 adds SPRR + GXF (GL1/GL2 "guarded" lateral exception levels sharing the EL page tables; `genter`/`gexit` instructions; `SPRR_CONFIG_EL1`, `SPRR_PERM_EL0/1` — full register map in `docs/hw/cpu/sprr-gxf.md`). GXF = "Guarded Execution Function", used by XNU to protect page tables from itself (Sven Peter write-up: https://blog.svenpeter.dev/posts/m1_sprr_gxf/). **[C?]** On M2+ iBoot2 reportedly launches custom kernels in GL2 and m1n1 transitions out to EL2 — the sprr-gxf doc documents GL2 mechanics but I did not find the exact boot-handoff statement in the docs repo; treat as likely but verify against m1n1 `src/startup.c` before writing it into the plan as fact.
|
||||
- **M3 (t8122 / t603x)**: m1n1 can init CPUs, bring up peripherals, and boot the Asahi kernel (Asahi Progress Report: Linux 6.17, 2025-10-24, "M3? Kinda…"). AIC changed on M3 (new AIC generation; `aic2` work exists in the kernel fork). **[U]** A January 2026 secondary source claims a Fedora 43 Asahi Remix desktop boot on M3 by contributor IntegralPilot (keyboard/trackpad/Wi-Fi/NVMe/USB3 working, no GPU) — not verified against primary sources.
|
||||
- **M4 (t8132 / t604x [C?] codenames not verified in docs)**: **boot chain materially changed** (Sven Peter, Mastodon 2025-04-03; phoronix 2025-04-04):
|
||||
- Mach-O boot objects now drop into an environment where **Apple's SPTM (Secure Page Table Monitor) runs in GL2**, and the payload is expected to talk to SPTM **from EL2 with the MMU already enabled** to set up page tables — unusable for Linux as-is and breaks running XNU under the m1n1 hv (i.e., breaks the RE workflow).
|
||||
- **Raw boot objects drop into EL2 with GL2 and most/all Apple-specific extensions disabled — "totally fine for Linux"**, but XNU can't run under the hv in this state. Raw boot appeared broken on macOS ≥15.2 at that date.
|
||||
- 39C3 (Dec 2025) talk: M4/M5 changes broke existing RE tooling; full support "a long way off". **[U]** basic Alpine Linux boot on M4 reported by a contributor.
|
||||
- **For the porting plan**: EL2 is available on all generations, but the *entry environment* differs: M1/M2 = clean EL2, MMU off; M4 = EL2 with MMU enabled + SPTM/GL2 context (macho path) or clean-ish EL2 (raw path). A type-1 hypervisor payload would most naturally take the m1n1 raw boot path.
|
||||
|
||||
---
|
||||
|
||||
## 2. KVM on Apple Silicon
|
||||
|
||||
### 2.1 Status [C]
|
||||
|
||||
**KVM/arm64 works on Apple Silicon today and has since early 2021.** KVM itself is architecture-generic — what was needed was (a) the platform booting Linux at EL2, (b) AIC/timer/FIQ quirks handled. Timeline:
|
||||
|
||||
- **Feb 2021**: Asahi Progress Report (Jan/Feb 2021) — Marc Zyngier already had **Linux VMs booting under KVM on the Asahi kernel on M1**. Notes that M1's cores implement the **GICv3 CPU interface with native virtualization support** (hardware vCPU interface), plus IMPDEF features for guest timer handling — used by KVM.
|
||||
- KVM on Asahi runs in **VHE mode** (kernel at EL2). KVM guests get an emulated **vGICv3**; AIC device IRQs are injected as vGIC SPIs; the **architectural timer** is standard ARM (physical timer is wired to FIQ on Apple SoCs — Linux FIQ support by Mark Rutland was a prerequisite upstream change).
|
||||
- **hVHE** (VHE inside the nVHE hypervisor): Marc Zyngier, "[PATCH v3 00/17] KVM: arm64: Allow using VHE in the nVHE hypervisor", lore.kernel.org/linux-arm-kernel, 2023-06-09 (touches `drivers/irqchip/irq-apple-aic.c` among others). **Tested on bare-metal M1 and as a *nested guest* on M2** — i.e., KVM/arm64 nested virtualization demonstrably works on M2 hardware. Merged upstream late 2023 **[C?]** (v6.6/v6.7 window — exact version not verified).
|
||||
- **PMUv3 emulation for Apple**: Oliver Upton, "[PATCH] KVM: arm64: Support FEAT_PMUv3 on Apple hardware" — RFC Dec 2024, v1 2024-12-17, v2 2025-02-03, **v3 2025-03-06, 14 patches** (patchew.org). Uses Apple's IMPDEF EL2 trap of PMUv3 registers to emulate an architectural PMUv3 atop Apple's IMPDEF PMU; initially cycle counter + 1 event counter. **This is what unblocked Windows-on-ARM (WoA) KVM guests** (WoA requires PMUv3). Cherry-picked into Asahi kernels March 2025 (Progress Report 6.14, 2025-03-21); upstream merge in the 6.15–6.16 window **[C? — merge not independently verified]**.
|
||||
- Fedora Asahi Remix ships working KVM; Asahi docs have a **Windows 11 VM guide** (`docs/sw/windows-11-vm.md`) using `qemu-system-aarch64 -enable-kvm -cpu host -M virt`. Note in that doc: libvirt/virt-manager stack is *unsupported/broken* as of the doc's writing (see AsahiLinux/docs PR #206 discussion).
|
||||
|
||||
### 2.2 Limitations [C]
|
||||
|
||||
- **M1: no architectural nested virtualization** (IMPDEF feature set; NV requires newer features). **M2: nested KVM demonstrated** (Marc Zyngier's hVHE testing, June 2023). The AppleWOA project notes likewise: M1/M1-Pro/Max/Ultra lack nested virt; M2 cores should support it.
|
||||
- Guest feature restrictions historically: no PMUv3 until the Upton series; IMPDEF Apple registers (SPRR/GXF, TSO toggle in ACTLR_EL1) are **deliberately not exposed to guests** — Marc Zyngier rejected exposing non-architectural state to KVM guests (lore thread on marcan's TSO series, April 2024: "no implementation-defined features should be explicitly exposed to the guest"). TSO/`PR_SET_MEM_MODEL` (marcan, "[PATCH 0/4] arm64: Support the TSO memory model", 2024-04-11, rebased on v6.9-rc1) is a host-userspace feature, downstream in Asahi; KVM TSO left "for a future patchset" and faces upstream resistance.
|
||||
- Timers: standard arch timer virtualized; physical timer IRQ is FIQ-based on Apple — handled.
|
||||
- GIC: Apple chips include the GICv3 CPU interface (with virtualization); the AIC handles device interrupts and has **no LPI/ITS**; vGIC works in-kernel.
|
||||
- **A Linux KVM guest on Apple Silicon running nested KVM**: works on M2 (demonstrated), not on M1.
|
||||
|
||||
---
|
||||
|
||||
## 3. Asahi Kernel Fork (github.com/AsahiLinux/linux)
|
||||
|
||||
### 3.1 Structure & cadence [C]
|
||||
|
||||
- Default branch: **`asahi`** (actively pushed as of 2026-07-09). Upstreaming branches: `apple-soc/{dt,drivers,fixes}-<version>`, `asahi-soc/for-next` etc. — Asahi devs (Sven Peter, Janne Grunau et al.) herd Apple SoC patches into mainline via the soc tree.
|
||||
- Downstream feature branches are organized as **`bits/NNN-<topic>`**, merged into `asahi` (listing fetched from GitHub API, July 2026):
|
||||
|
||||
| Branch | Content | Upstream status |
|
||||
|---|---|---|
|
||||
| `bits/000-devicetree` | FDTs | progressively upstream (M1, M2, M2 Pro/Max/Ultra DTs in 6.18) |
|
||||
| `bits/010-soc`, `030-misc` | SoC drivers | mostly upstream |
|
||||
| `bits/020-dart` | DART IOMMU | core upstream (5.15); T602x 4-level tables in 6.18 |
|
||||
| `bits/050-nvme` | NVMe/ANS + SART | NVMe upstream (5.19); SART upstream |
|
||||
| `bits/070-audio` | macaudio/mca/AOP audio | **downstream** |
|
||||
| `bits/080-wifi` | brcmfmac glue/firmware handling | mostly upstream |
|
||||
| `bits/090-spi-hid` | SPI HID (keyboard/trackpad) | upstream |
|
||||
| `bits/110-smc` | SMC MFD + subdevices | **core merged 6.17** (2025-07); subdevices (hwmon, RTC, lid) in review as of 6.18 |
|
||||
| `bits/140-pci` | PCIe | upstream (T6020 PCIe in 6.16) |
|
||||
| `bits/150-xhci-firmware`, `171-dptxphy` | USB3/DPTX PHY | USB3 **merged for 6.19** (Dec 2025) |
|
||||
| `bits/180-sio` | SIO (serial) | downstream/partial |
|
||||
| `bits/190-rust` | Rust abstractions for drivers | partially upstream |
|
||||
| `bits/200-dcp` | **DCP display controller** | **downstream** (upstreaming planned) |
|
||||
| `bits/210-gpu` | **AGX GPU kernel driver (Rust, drm/asahi)** + UAPI | **downstream**; UAPI header merged 6.16, driver in prep |
|
||||
| `bits/220-tso` | TSO memory model toggle | **downstream** (upstream rejected so far) |
|
||||
| `bits/240-isp` | ISP/camera | submitted (6k LoC) |
|
||||
| `bits/250-aop` | AOP coprocessor | partially upstream |
|
||||
| `bits/500-backports` | backports | n/a |
|
||||
|
||||
- Downstream burden as of Linux 6.13: **>90,000 LoC / ~1,250 patches** + downstream U-Boot, Mesa, virglrenderer, Flatpak runtime extension (Progress Report 6.14, 2025-03-21). Stated project goal is reducing this via upstreaming.
|
||||
- Reference config list (as of linux-asahi-6.12.4-1) in `docs/sw/kernel-config.md` — full CONFIG list incl. `CONFIG_ARCH_APPLE`, `CONFIG_APPLE_AIC/DART/SART/SMC/RTKIT/MAILBOX/PMGR/ADMAC/M1_CPU_PMU`, `CONFIG_ARM64_16K_PAGES=y`, `CONFIG_DRM_ASAHI=y`, `CONFIG_ARM_APPLE_CPUIDLE`, etc.
|
||||
|
||||
### 3.2 SoC support matrix [C]
|
||||
|
||||
Docs: `docs/platform/feature-support/{m1,m2,m3,m4}.md` + https://asahilinux.org/fedora/#device-support.
|
||||
|
||||
| SoC | Codename | Status (mid-2026) |
|
||||
|---|---|---|
|
||||
| M1 | t8103 | Full Fedora Asahi Remix support (GPU, audio, webcam, suspend…) |
|
||||
| M1 Pro/Max/Ultra | t6000/t6001/t6002 | Supported |
|
||||
| M2 | t8112 | Supported |
|
||||
| M2 Pro/Max/Ultra | t6020/t6021/t6022 | Supported; DTs + 4-level DART upstream in 6.18 |
|
||||
| M3 (Pro/Max) | t8122 / t6030, t6031 | **Experimental**: m1n1 + kernel boot (Asahi 6.17 report, Oct 2025); desktop bring-up reported Jan 2026 **[U]**; no GPU; AIC redesigned |
|
||||
| M4 (Pro/Max) | t8132 / t604x **[C?]** | Boot-chain RE blocked by SPTM/GL2; raw-boot Linux experiments only; no support |
|
||||
| M5 | — | Mentioned at 39C3 (Dec 2025) as affected by the same changes |
|
||||
|
||||
### 3.3 Fedora Asahi Remix packaging & 16K pages [C]
|
||||
|
||||
- Kernel RPM: **`kernel-16k`** (build string e.g. `6.17.12-400.asahi.fc42.aarch64+16k`, seen in podman host info; also `6.14.8-400.asahi.fc42.aarch64+16k`). Built in COPR `group_asahi/kernel`; `kernel-16k-devel` exists; the Asahi platform metapackage conflicts with the plain Fedora `kernel` (confirmed via openzfs/zfs#16429 packaging log).
|
||||
- **Why 16K is mandatory** (authoritative: Asahi docs "Broken Software" page + Progress Report Sept 2021): **Apple's DART IOMMUs only support 16K-aligned pages** on M1/M2 (4K exists on the CPU mainly for Rosetta). Linux cannot mix page sizes like XNU; 4K kernels are possible only with "very hacky patches" and suffer severe performance penalties — Asahi's position is 16K-only for the platform. (Sven Peter's 2021 IOMMU patches allow an IOMMU granule > kernel page size, making 4K *technically* viable with caveats, but Asahi does not ship that.)
|
||||
- **Hypervisor implications**: (a) any guest doing DMA through passthrough DARTs needs **16K-granule stage-2 mappings**; (b) 4K guests are fine *without* 16K-only devices — proven by **muvm** (github.com/AsahiLinux/muvm, libkrun-based microVMs running 4K kernels under KVM on the 16K host for FEX/x86/Wine compatibility); (c) userspace ABI: ELF `LOAD` segments need ≥16K alignment on 16K hosts (Asahi "Broken Software" page) — irrelevant for a VM guest, which gets its own page size.
|
||||
|
||||
---
|
||||
|
||||
## 4. Virtualization-Relevant Hardware & Interfaces
|
||||
|
||||
### 4.1 AIC (Apple Interrupt Controller) [C]
|
||||
|
||||
`docs/hw/soc/aic.md`: SET/CLR register-pair style; per-IRQ target bitfields (`IRQ_TGT`), SW-generated IRQs, mask set/clr; per-core mirror registers at 0x2000+ (`IRQ_REASON`, `IPI_SEND`, `IPI_ACK`, `IPI_MASK_SET/CLR`); FIQ bypasses AIC (arch timer wired straight to FIQ). **M3 redesigned the AIC** (Asahi 6.17 report; `aic2` work in the fork). Linux driver: `drivers/irqchip/irq-apple-aic.c` (upstream 5.13); vGIC integration touches this driver (hVHE series).
|
||||
|
||||
### 4.2 DART / SART [C]
|
||||
|
||||
- **DART** = Device Address Resolution Table, the IOMMU in front of nearly all peripherals (`drivers/iommu/apple-dart.c`, upstream 5.15). M1/M2 DART: 16K granule only. T602x DARTs: larger address space → 4-level page tables (merged 6.18). Asahi 6.17 report describes DARTs as "a sort of firewall for peripherals".
|
||||
- **SART** = simpler address filter gating the NVMe (ANS) coprocessor's DRAM access (`CONFIG_APPLE_SART`); NVMe itself talks to the ANS coprocessor via ASC mailbox + RTKit protocol (all upstream: `apple-mailbox`, `apple-rtkit`, `nvme-apple` in 5.19).
|
||||
|
||||
### 4.3 SPRR / GXF / SPTM [C]
|
||||
|
||||
- SPRR (M2+): page permission bits (AP/UXN/PXN) become an index into `SPRR_PERM_EL0/1` registers; effectively forbids W+X; GXF adds GL1/GL2 guarded levels (doc: `hw/cpu/sprr-gxf.md`). m1n1 handles SPRR setup at boot; KVM does not expose SPRR to guests.
|
||||
- SPTM (M4, also implicated on M3/M5 at 39C3): Secure Page Table Monitor running in GL2 that brokers page-table setup — the new obstacle on the macho boot path.
|
||||
|
||||
### 4.4 What Asahi Linux needs as a guest (interfaces a type-1 hypervisor must provide) [C/U]
|
||||
|
||||
Confirmed facts:
|
||||
- Asahi Linux boots via **UEFI + FDT** (U-Boot provides EFI services; GRUB uses them). As a guest it needs: an FDT (m1n1 generates/personalizes it — **m1n1 as guest firmware is a viable and proven pattern**: `run_guest_kernel.sh` boots Linux under the m1n1 hv with FDT payloads).
|
||||
- CPU: entered at EL1 or EL2 with MMU off per ARM64 boot protocol; secondary CPUs via **spin-table** (m1n1 adds spin-table nodes; an `efi-psci` branch exists in the fork).
|
||||
- Interrupts: vGICv3 (works, KVM-proven) or AIC passthrough/emulation (m1n1 hv virtualizes AIC: `hv_aic.c`).
|
||||
- Timer: architectural timer; note physical timer IRQ = FIQ, not SPI — a hypervisor must deliver vtimer/PTimer correctly (KVM handles this).
|
||||
- Devices: for full functionality either **device passthrough with DART** (guest programs DART? No — DART would sit behind the hypervisor's stage-2; this is an open design point) or **virtio** — virtio is fully proven: m1n1's hv implements virtio-mmio (`hv_virtio.c`), and Asahi userspace runs fine in QEMU `-M virt` VMs (the Win11 guide's inverse).
|
||||
- 16K stage-2 granule required if any 16K-only DART/device is passed through.
|
||||
|
||||
Existing precedents for Linux under a hypervisor on Apple Silicon [C]:
|
||||
1. **m1n1 hv** running Linux (and FreeBSD — `proxyclient/tools/freebsd.py`) and macOS guests at EL1.
|
||||
2. **KVM on Asahi** running Linux/Windows/BSD guests (QEMU, muvm/libkrun microVMs).
|
||||
3. **macOS Hypervisor.framework / Virtualization.framework** running Linux guests (UTM, QEMU hvf) — GIC fully emulated in software there (per 2021 Asahi blog), slower for IPI-heavy loads.
|
||||
4. **AppleWOA project** (github.com/amarioguy/AppleWOAProject) — m1n1 fork as a thin hypervisor to run UEFI + Windows at EL1.
|
||||
5. Corellium's early (2021) M1 Linux work pre-dating/feeding Asahi.
|
||||
|
||||
---
|
||||
|
||||
## 5. Key Documents & Repositories
|
||||
|
||||
**Repos**
|
||||
- `github.com/AsahiLinux/m1n1` — bootloader/hv; `README.md`, `src/hv*.c`, `proxyclient/` (docs inside repo are minimal; docs live in the docs repo).
|
||||
- `github.com/AsahiLinux/linux` — kernel fork, default branch `asahi`; `bits/*` topic branches.
|
||||
- `github.com/AsahiLinux/docs` — documentation repo, Zensical/MkDocs → GitHub Pages at **asahilinux.org/docs**. README + `docs/index.md` fetched and confirmed. Structure: `alt/ fw/ hw/{cpu,devices,peripherals,soc}/ platform/ project/ sw/`.
|
||||
- `github.com/AsahiLinux/asahi-installer`, `AsahiLinux/u-boot`, `AsahiLinux/muvm`, `AsahiLinux/asahi-scripts`.
|
||||
|
||||
**Most important docs pages** (all under asahilinux.org/docs/…, raw at raw.githubusercontent.com/AsahiLinux/docs/main/docs/…):
|
||||
- `platform/open-os-interop.md` — **the boot chain + OS layout standard** (fetched in full; supersedes `open-os-interop-old.md`)
|
||||
- `fw/boot.md` — Apple Silicon boot flow (SecureROM→iBoot1→iBoot2, LocalPolicy 4CCs, DFU flow, boot modes)
|
||||
- `fw/adt.md`, `fw/macho-boot-protocol.md`, `fw/nvram.md`
|
||||
- `sw/m1n1-user-guide.md`, `sw/m1n1-dev-guide.md` (boot protocol, entry at 0x800), `sw/m1n1-hypervisor.md` (hv usage; macOS ≤13.5; unstable ABI; LLDB)
|
||||
- `hw/cpu/sprr-gxf.md`, `hw/cpu/apple-instructions.md`, `hw/cpu/system-registers.md`, `hw/cpu/smp.md`
|
||||
- `hw/soc/aic.md`, `hw/soc/memmap.md`, `hw/soc/soc-codenames.md`, `hw/soc/smc.md`, `hw/soc/spmi.md`, `hw/soc/display-controllers.md`, `hw/soc/agx.md`, `hw/soc/apcie.md`
|
||||
- `sw/kernel-config.md` (full Asahi config), `sw/devicetree-bindings.md`, `sw/broken-software.md` (16K rationale), `sw/windows-11-vm.md` (KVM guest howto), `sw/u-boot.md`
|
||||
- `platform/feature-support/{overview,m1,m2,m3,m4}.md`
|
||||
- External: Sven Peter's SPRR/GXF write-up (blog.svenpeter.dev/posts/m1_sprr_gxf/); Asahi blog progress reports (asahilinux.org/blog/ — esp. Jan/Feb 2021 [KVM/AIC/FIQ], Sept 2021 [DART 16K], 6.14 [downstream stats, PMUv3], 6.17 [M3 status, DART 4-level], 6.18/6.19 [SMC subdevices, USB3]); 39C3 talk (Dec 2025, M3/M4/M5 status); lore.kernel.org hVHE series (2023-06-09) and PMUv3 series (patchew 2025-03-06).
|
||||
|
||||
---
|
||||
|
||||
## 6. Points of Caution for the Porting Plan (confirmed vs. uncertain)
|
||||
|
||||
1. **[C]** M1/M2 give you real EL2, VHE, hardware GICv3 CPU-interface virtualization, and working KVM — the premise "no real EL2 on M1/M2" is **wrong**. What Apple removed/changed on **M4** is the *boot-time environment* (SPTM in GL2 on the macho path), not EL2 itself; raw boot still yields EL2.
|
||||
2. **[C]** Nested KVM: M1 = no; M2 = demonstrated (June 2023). M3/M4 nested status unknown.
|
||||
3. **[C]** A type-1 hypervisor running Asahi Linux as a guest must handle: FIQ-based physical timer delivery, AIC (or vGIC injection of AIC IRQs), spin-table SMP, 16K stage-2 granule for passthrough, FDT generation (reuse m1n1's ADT→FDT personalization or pass a pre-baked FDT).
|
||||
4. **[U]** Exact upstream merge versions for hVHE (6.6/6.7) and the PMUv3 series (6.15/6.16); M4 codenames (t8132/t604x); M3 desktop-boot claim (Jan 2026); GL2-at-iBoot2-handoff on M2. Verify against `git log` on the AsahiLinux/linux fork and m1n1 `src/startup.c` before citing in the formal plan.
|
||||
5. **[C]** The m1n1 hv (`src/hv_*.c`, ~9 files, MIT) is the closest existing reference implementation of a type-1-ish hypervisor on this hardware, including virtio-mmio device models and AIC virtualization — recommended primary reading for UniversalisOS, alongside the KVM/arm64 vGIC/AIC code paths.
|
||||
129
realms/universalisos/docs/porting/research/02-asahi-u-boot.md
Normal file
129
realms/universalisos/docs/porting/research/02-asahi-u-boot.md
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
# Asahi U-Boot (AsahiLinux/u-boot) — Research Report for UniversalisOS Porting Plan
|
||||
All source findings verified against a sparse clone of `https://github.com/AsahiLinux/u-boot` (branch `asahi`, HEAD `8aa706b2`, 2025-12-21; branch `asahi-releng`, HEAD `3b233f59`, 2026-05-24). Clone deleted after analysis. Web sources cited inline.
|
||||
|
||||
## 1. Repository, upstream base, branches, packaging
|
||||
|
||||
**Upstream base:** The live `asahi` branch is based on **upstream U-Boot v2025.10** (`Makefile`: `VERSION = 2025, PATCHLEVEL = 10`; upstream `Prepare v2025.10` commits dated 2025-07 → 2025-10 are in history). The `asahi` branch is a set of Apple/Asahi commits carried on top of upstream release snapshots, **not** a continuous rebase per upstream release.
|
||||
|
||||
**Branches (from `git ls-remote`):**
|
||||
| Branch | Tip date | Purpose |
|
||||
|---|---|---|
|
||||
| `asahi` (default/HEAD) | 2025-12-21 | Main development branch, v2025.10 base |
|
||||
| `asahi-releng` | **2026-05-24** | **What distros ship to users** — adds ESP auto-detection, ENV_IS_IN_FAT, Fedora tweaks, and (as of 2026-05-21) **Apple M3 support** |
|
||||
| `fedora-asahi-v2024.04` | 2024-04-20 | Fedora Asahi Remix build branch (commits prefixed `FEDORA:`) |
|
||||
| `openbsd-releng` | 2024-01-08 | OpenBSD build branch (kettenis is an OpenBSD dev) |
|
||||
| `asahi-next` | 2023-04-02 | Stale |
|
||||
| `t6020`, `asmedia`, `asmedia2`, `mtp-support`, `nvme/shutdown`, `bootmenu*` | various | Feature/topic branches |
|
||||
| `master` | 2025-04-18 | Stale mirror of upstream master — ignore |
|
||||
|
||||
**Rebase cadence (inferred, medium confidence):** Fedora branch was v2024.04 (April 2024); Debian's `u-boot-asahi` is 2025.01; the `asahi` branch is now v2025.10 (Dec 2025). So roughly **1–2 upstream rebases per year**, plus small fixup commits. The Asahi docs confirm: "U-Boot generally doesn't change much once properly brought up on any given SoC."
|
||||
|
||||
**Fedora Asahi Remix packaging:**
|
||||
- Asahi docs (asahilinux.org/docs/sw/u-boot/): *"For an example of how we do this in Fedora Asahi Remix, see our `uboot` and `asahi-scripts` packaging."* Fedora package **`uboot`** is built from the `fedora-asahi-v2024.04` branch; the companion **`m1n1`** RPM provides `m1n1.bin` and DTBs. Both install bare artifacts to **`/usr/lib/asahi-boot/`** (`m1n1.bin`, `u-boot-nodtb.bin`, `apple/*.dtb`).
|
||||
- **`update-m1n1`** (from `asahi-scripts`, github.com/AsahiLinux/asahi-scripts, verified source) regenerates the ESP image:
|
||||
```sh
|
||||
cat "$M1N1" $DTBS > boot.bin.new
|
||||
gzip -c "$U_BOOT" >> boot.bin.new # U-Boot payload is gzip-compressed
|
||||
cat "$m1n1config" >> boot.bin.new # /etc/m1n1.conf options appended
|
||||
# atomic replace of <ESP>/m1n1/boot.bin, keeping boot.bin.old backup
|
||||
```
|
||||
ESP is auto-located (via `asahi,efi-system-partition` PARTUUID) and mounted at `/run/.system-efi`. DTBs expanded as `/usr/lib/asahi-boot/apple/t6*.dtb t81*.dtb`.
|
||||
- **ESP layout:** `<ESP>/m1n1/boot.bin` (m1n1 stage2 + DTBs + gzipped U-Boot + config), `<ESP>/EFI/BOOT/BOOTAA64.EFI` (GRUB, vanilla), plus `vendorfw.cpio` (extracted Apple firmware, produced by `asahi-fwextract` / the `update-vendor-firmware` tool from the `asahi-fwupdate` package, mounted into `/lib/firmware` by a dracut module).
|
||||
- **`kmutil` flow:** only used once at install time from 1TR to install m1n1 *stage 1* as the fuOS custom kernel: `kmutil configure-boot -c m1n1-stage1.bin --raw --entry-point 2048 --lowest-virtual-address 0 -v <volume>` (m1n1 User Guide). Stage 1 has the ESP PARTUUID hardcoded and chainloads stage 2 from `<ESP>/m1n1/boot.bin` (internal NVMe only). Routine updates never touch kmutil.
|
||||
- Other distros: Arch ALARM ships `uboot-asahi` (same `/usr/lib/asahi-boot` + `update-m1n1` scheme); Debian sid ships `u-boot-asahi` 2025.01-3.1.
|
||||
|
||||
---
|
||||
|
||||
## 2. Apple board support in the tree
|
||||
|
||||
**Board code location:** `arch/arm/mach-apple/` (NOT `board/apple/` — there is no board/apple directory):
|
||||
- `board.c` (Mark Kettenis, 2021) — per-SoC static MMU `mem_map` tables (I/O, PCIe, RAM, framebuffer regions) for t8103/t8112, t6000/t6001, t6002, t6020/t6021, t6022; `board_fdt_blob_setup()` returns the DTB pointer passed by m1n1 (`fw_dtb_pointer`); `asahi_esp_devpart()` — scans NVMe partitions, prefers the one whose PARTUUID matches `/chosen/asahi,efi-system-partition`, sets `efi_system_partition`; `board_late_init()` sets `storage_interface`, `fw_dev_part`, `loadaddr`/`fdt_addr_r`/`kernel_addr_r`/`ramdisk_addr_r`; `ft_board_setup()` rewrites `stdout-path` to `/chosen/framebuffer` when a keyboard exists and EL≠1.
|
||||
- `lowlevel_init.S` — `save_boot_params` stashes **x0 (DTB pointer from m1n1)** into `fw_dtb_pointer`.
|
||||
- `rtkit.c`, `rtkit_helper.c`, `sart.c` — Apple RTKit co-processor protocol + SART (NVMe address filter) support, used by the NVMe driver.
|
||||
- `Kconfig`: `TEXT_BASE=0x0`, `SYS_CONFIG_NAME="apple"`, malloc 64 MiB.
|
||||
|
||||
**Defconfig:** a single **`configs/apple_m1_defconfig`** builds for **all** supported SoCs (Asahi docs: "Do not be fooled by the name"). Key options: `CONFIG_ARCH_APPLE`, `DEFAULT_DEVICE_TREE="t8103-j274"`, `BOOTCOMMAND="bootflow scan -b"` (bootstd/bootflow), `USE_PREBOOT`, `NO_NET`, `APPLE_SPI_KEYB`, `APPLE_MTP_KEYB`, `NVME_APPLE`, `USB_XHCI_HCD/DWC3/PCI`, `USB_DWC3`, `USB_KEYBOARD`, `VIDEO_SIMPLE` (simplefb), `NO_FB_CLEAR`, `CMD_SELECT_FONT`, `# CONFIG_MMC is not set`, `# CONFIG_SMBIOS is not set`. Env header `include/configs/apple.h`: `stdin=serial,usbkbd,spikbd,mtpkbd`, `stdout/stderr=vidconsole,serial`, `boot_targets="nvme usb"`. EFI_LOADER is on via the arm64 default.
|
||||
|
||||
**Supported SoCs:**
|
||||
- `asahi` branch `board.c`: **t8103 (M1), t8112 (M2), t6000/6001/6002 (M1 Pro/Max/Ultra), t6020/6021/6022 (M2 Pro/Max/Ultra)** — anything else hits `panic("Unsupported SoC\n")`.
|
||||
- `asahi-releng` adds (2026-05-21 commits): **t8122 (M3), t6030/t6031/t6034 (M3 Pro/Max), t6032 (M3 Ultra)**.
|
||||
- **No M4 (t8132/t604x) support anywhere** in the repo (high confidence — no t8132/t604 references). Upstream docs site (docs.u-boot-project.org/en/latest/board/apple/m1.html) lists up to t6022.
|
||||
- In-tree DTs: `dts/upstream/src/arm64/apple/` has t8103, t8112, t600x; `arch/arm/dts/` has the t602x family (added May 2023, "Taken from the asahi branch of the Asahi Linux github repository"). Note: **in production the in-tree DTs are unused** — m1n1 stage 2 supplies its own embedded DTBs (from the AsahiLinux/linux tree) personalized with ADT data.
|
||||
|
||||
**Apple drivers present:**
|
||||
- `drivers/nvme/nvme_apple.c` — ANS2 NVMe; boots the NVMe coprocessor via **RTKit** (`apple_rtkit_boot`) and programs **SART** allow-lists (`sart_add_allowed_region`); requires the NVMe firmware (RTKit endpoint firmware — loaded via the firmware loader, see "file system firmware loader" commit on releng).
|
||||
- `drivers/pci/pcie_apple.c` — Apple PCIe RC (t8103/t600x style).
|
||||
- `drivers/usb/host/xhci-pci-asmedia.c` + commit "usb: xhci-pci: Load ASMedia XHCI controller firmware" — **ASMedia xHCI on t602x** machines (needs non-upstreamable firmware load at runtime).
|
||||
- `drivers/phy/phy-apple-atc.c` — Apple Type-C PHY (ATC); USB via generic DWC3 glue + xHCI (`USB_XHCI_DWC3`).
|
||||
- `drivers/input/apple_kbd.c`, `apple_spi_kbd.c` (SPI keyboard, M1 laptops), `apple_mtp_kbd.c` (MTP keyboard, M2+ laptops — "MTP keyboard support for M2 platforms goes along with DT changes").
|
||||
- `drivers/spi/apple_spi.c` (default y if ARCH_APPLE), `drivers/iommu/apple_dart.c` (default y), `drivers/power/domain/apple-pmgr.c` (PMGR power domains), `drivers/pinctrl/pinctrl-apple.c`, `drivers/mailbox/apple-mbox.c` (for RTKit), `drivers/watchdog/apple_wdt.c` (default y).
|
||||
- Serial: **`drivers/serial/serial_s5p.c`** — Samsung S5P UART driver reused for Apple's S5L UART (`config S5P_SERIAL ... depends on ARCH_APPLE || ARCH_EXYNOS`, default y). Per-SoC UART base addresses documented in `doc/board/apple/m1.rst` (t8103: 0x235200000; t600x: 0x39b200000).
|
||||
|
||||
**What it does NOT do:**
|
||||
- **No GPU/display-pipe init** — display comes solely from simple-framebuffer: m1n1 puts a `/chosen/framebuffer` node in the FDT; `CONFIG_VIDEO_SIMPLE` renders to it. `ft_board_setup` points `stdout-path` at it.
|
||||
- **No AIC/interrupt-controller driver** — U-Boot is entirely polled; timing via ARM architected timer. (No `aic` driver anywhere in `drivers/`.)
|
||||
- **No SMC, no AOP, no cpufreq/clock drivers, no power management beyond PMGR domains, no `poweroff` command** (Asahi docs explicitly), no network (`CONFIG_NO_NET`), no USB-A ports on machines whose controllers need non-redistributable firmware (Mac Studio front ports, iMac far ports), no persistent EFI variables (Asahi docs: "We don't have persistent EFI variable storage").
|
||||
- Relies on m1n1 for: memory controller init, clocks, L3 cache enable, PCIe bring-up ("PCIe on M2 required no driver-level changes, only changes to the m1n1 initialization"), ADT→FDT translation, display pipe bring-up.
|
||||
|
||||
---
|
||||
|
||||
## 3. Boot flow
|
||||
|
||||
Full chain (Asahi Boot Process guide, asahilinux.org/docs/alt/boot-process-guide/ — quoted):
|
||||
> `[Apple stuff] → m1n1 stage 1 → m1n1 stage 2 → DT + U-Boot → GRUB → Linux`
|
||||
|
||||
- **Stage 1** (installed once via `kmutil configure-boot` from 1TR, signed per-machine): has ESP PARTUUID hardcoded, inits NVMe, chainloads `<ESP>/m1n1/boot.bin`, forwards `/chosen` props including `asahi,efi-system-partition`.
|
||||
- **Stage 2** `boot.bin` = concatenation: `m1n1.bin` + `*.dtb` (all Apple DTBs) + `gzip(u-boot-nodtb.bin)` + optional text config. m1n1's payload format (m1n1 README): payloads are found by simple concatenation scanning; formats = kernel-image-compatible binaries (must be compressed or last), FDTs, cpio; compression gzip/xz. **U-Boot is treated as a "kernel image" payload** — entered at its reset vector with **x0 = pointer to the personalized FDT** (U-Boot side: `save_boot_params` stashes x0 → `fw_dtb_pointer` → `board_fdt_blob_setup`). m1n1 stage 2 selects the DTB matching the platform, transplants dynamic ADT data (memory, framebuffer, MAC addresses, etc.), then jumps to U-Boot.
|
||||
- **U-Boot role ("BIOS-like"):** parses FDT, sets up MMU via its static per-SoC `mem_map` + DRAM/framebuffer from FDT, inits keyboard (SPI/MTP/USB), NVMe (RTKit boot of ANS coprocessor), USB; reads env from FAT on the ESP (releng: `ENV_IS_IN_FAT`); runs **bootstd** (`bootflow scan -b` over `boot_targets="nvme usb"`); provides **UEFI boot services** and loads `/EFI/BOOT/BOOTAA64.EFI` (default GRUB, unpatched), passing the (lightly modified) FDT via the EFI FDT table. It consumes, modifies (`stdout-path`), and forwards the DT.
|
||||
- **ESP auto-detection:** `asahi_esp_devpart()` in board.c picks the GPT partition flagged EFI System whose PARTUUID equals `/chosen/asahi,efi-system-partition` (written by m1n1), falling back to the first ESP on internal NVMe (`apple,nvme-ans2` only). This is the "magic" that makes each OS container boot its own ESP.
|
||||
- **Distro installers:** USB-bootable installers rely on the vanilla m1n1+U-Boot bundle the Asahi installer places on the internal ESP in "UEFI container mode"; the USB stick carries its own ESP with `/EFI/BOOT/BOOTAA64.EFI` and no `m1n1/boot.bin`. Boot from USB at the U-Boot prompt: `run bootcmd_usb0`. Installed OSes own everything from m1n1 stage 2 onward and may technically replace U-Boot (docs explicitly allow: "use U-Boot directly to boot kernels, or use the Linux EFI stub, or GRUB").
|
||||
- **Hypervisor note in-tree:** `ft_board_setup()` checks `current_el() == 1` and skips console redirection "if we're running under the m1n1 hypervisor" — i.e. **U-Boot already has an explicit code path for being launched at EL1 under a hypervisor** (m1n1's built-in HV). U-Boot itself runs at EL2 when started directly.
|
||||
|
||||
---
|
||||
|
||||
## 4. Apple-relevant docs
|
||||
|
||||
In-tree (`doc/`):
|
||||
- `doc/board/apple/index.rst` — one page: `m1`.
|
||||
- `doc/board/apple/m1.rst` — "U-Boot for Apple Silicon Macs". Lists SoCs (on the `asahi` branch it lists only M1 family — **doc lags code**; upstream's rendered version lists t8103, t8112, t600x, t602x), supported hardware ("S5L serial port, SPI keyboard, Framebuffer, NVMe storage, USB 3.1 Type-C ports"), build (`make apple_m1_defconfig`), image creation (`cat m1n1.macho t8103-j274.dtb u-boot-nodtb.bin > u-boot.macho`), and debug-UART base addresses. Key quote: *"This uses `u-boot-nodtb.bin` as the device tree is passed to U-Boot by m1n1 after making some adjustments."*
|
||||
- `doc/develop/uefi/` — generic UEFI docs: `uefi.rst` (UEFI implementation status/limitations), `u-boot_on_efi.rst`, `iscsi.rst`, `fwu_updates.rst`. Nothing Apple-specific.
|
||||
- `doc/device-tree-bindings/pinctrl/apple,pinctrl.yaml` (removed on releng in favor of dts/upstream).
|
||||
- Top-level `README` — generic U-Boot README, nothing Apple.
|
||||
|
||||
External canonical docs (must-reads for the porting plan):
|
||||
- https://asahilinux.org/docs/sw/u-boot/ — U-Boot page (build, install, USB boot, known issues).
|
||||
- https://asahilinux.org/docs/alt/boot-process-guide/ — boot chain + version interdependencies (m1n1/U-Boot/DT/kernel coupling).
|
||||
- https://asahilinux.org/docs/platform/quirks/ + https://asahilinux.org/docs/fw/boot/ — platform firmware/boot flow.
|
||||
- m1n1 User Guide (github.com/AsahiLinux/docs wiki / leo3418 mirror) — kmutil stage-1 install, stage-2 payload concatenation, payload formats.
|
||||
- "Open OS Ecosystem on Apple Silicon Macs" (docs wiki) — OS layout, boot schemes, recommendation that OSes keep the installer-provided stage-2 blob.
|
||||
|
||||
---
|
||||
|
||||
## 5. Reuse potential under a type-1 hypervisor
|
||||
|
||||
**Hardware asahi-u-boot touches directly (would need passthrough or emulation):**
|
||||
1. **NVMe/ANS2** — the heaviest item: full RTKit protocol boot of the ANS coprocessor (firmware upload, shared-memory queues via mailbox `apple-mbox`), plus **SART** programming (DMA allow-list filter) and (implicitly) DART behind it. Under a hypervisor you'd either pass through the real NVMe+SART+DART (defeats isolation) or — much better — **give the guest a virtio-blk/pci NVMe and strip the Apple NVMe driver**; bootstd + EFI would then use the virtual disk. This is exactly what the m1n1 hypervisor / QEMU paths do (U-Boot supports virtio out of the box upstream).
|
||||
2. **USB**: DWC3 xHCI + ATC PHY (+ ASMedia xHCI over Apple PCIe on t602x). Same story: passthrough or replace with virtual USB. Keyboards: `apple_spi_kbd`/`apple_mtp_kbd` touch SPI/HID hardware directly — but only for console input; can be substituted by USB HID or a virtual console.
|
||||
3. **PCIe RC** (`pcie_apple.c`) — only needed for ASMedia USB on t602x; droppable in a VM.
|
||||
4. **Timers**: ARM generic architected timer only (standard, already virtualizable).
|
||||
5. **Interrupts**: none (fully polled; no AIC driver). Big simplification for guest firmware.
|
||||
6. **MMU**: programs its own EL2 page tables from static per-SoC `mem_map` tables in `board.c` + DRAM/framebuffer from FDT. Under a type-1 HV at EL1, stage-2 translation is the hypervisor's; the static I/O mappings would just fault if the MMIO isn't passed through — but the `current_el()==1` precedent shows the code already tolerates EL1 execution (m1n1's HV runs guests at EL1).
|
||||
7. **Framebuffer**: simplefb only — the hypervisor just needs to provide a `/chosen/framebuffer` (or GOP equivalent) in the FDT. No GPU.
|
||||
8. **Environment/bootstd**: expects a FAT ESP; trivially satisfiable with a virtual disk. It reads `/chosen/asahi,efi-system-partition` but degrades gracefully (falls back to first ESP).
|
||||
|
||||
**Assessment for option (a) — reuse as guest firmware:** Feasible and precedented (m1n1 HV runs it at EL1). Practical path: build with `apple_m1_defconfig`, drop NVMe_APPLE/PCIe/ASMedia/ATC/SPI-kbd drivers, add virtio, keep EFI_LOADER + simplefb + bootstd. You get UEFI services (boot + runtime-minus-variables — note **no persistent EFI variable store** even on bare metal) for GRUB/systemd-boot guests "for free". The hypervisor must present: FDT in x0, RAM, arch timer, a console (UART/framebuffer), and block + optional input devices.
|
||||
|
||||
**Option (c) — run it unmodified under the HV:** requires emulating ANS2 RTKit + SART + Apple PCIe/DWC3/ATC — disproportionate effort; not recommended.
|
||||
|
||||
**Option (b) — skip U-Boot, boot Linux EFI stub directly:** Explicitly sanctioned by Asahi ("OS installers… a Linux distro could… use the Linux EFI stub"). The Linux arm64 EFI stub only needs: an EFI boot-services environment **or** direct kernel boot with FDT. Your hypervisor can load `Image` + initramfs + FDT itself and jump to the kernel entry (x0=FDT) — the same contract m1n1 uses for U-Boot. What you'd lose: UEFI boot services for GRUB/systemd-boot (boot menus, `LoadImage`, disk access), the interactive preboot shell, and USB-boot fallback. What you'd keep: full control, tiny TCB, no fork maintenance. A middle path many type-1 HV projects take: implement the minimal EFI stub services in the HV's loader, or ship a bundled `Image+initrd+dtb` m1n1-style payload per guest.
|
||||
|
||||
**Key coupling risk for all options:** m1n1 stage 2 owns hardware bring-up (memory controller, clocks, PCIe, display pipe, L3). If UniversalisOS boots *instead of* m1n1 stage 2, it must reproduce that bring-up or embed m1n1 as its own payload (m1n1 is open and designed to be a payload host — the cleanest route is HV-as-m1n1-payload or m1n1-as-HV-payload chain).
|
||||
|
||||
---
|
||||
|
||||
## Uncertainty log
|
||||
- Fedora RPM name `uboot` and its dist-git spec: high confidence (Asahi docs reference it; `fedora-asahi-v2024.04` branch with `FEDORA:` commits corroborates) but src.fedoraproject.org was bot-blocked (Anubis), so I could not quote the spec's `%files` directly. The `/usr/lib/asahi-boot/` layout is confirmed from the `update-m1n1` script source.
|
||||
- Rebase cadence (1–2/year) is inferred from branch/base versions, not stated policy.
|
||||
- M3 support exists only on `asahi-releng` (May 2026), not yet merged to `asahi`; M4 absent everywhere as of 2026-07.
|
||||
- `doc/board/apple/m1.rst` on the `asahi` branch lists only M1-family SoCs — stale relative to code; the docs.u-boot-project.org rendered version (up to t6022) matches the code better.
|
||||
- Upstream U-Boot's own Apple support (source.denx.de master) is the origin of most drivers (kettenis upstreams them); the Asahi fork carries releng extras (ESP pinning, MTP kbd, ASMedia firmware loading, M3).
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
|
||||
# macOS Guests under QEMU on Apple Silicon — Definitive Technical Landscape (as of mid-2026)
|
||||
|
||||
## Executive summary
|
||||
|
||||
The work you remembered as "qemu-devel patches for macOS guests on Apple Silicon" is real and is called **`vmapple`** — but it is **HVF-only (macOS hosts)**, not KVM/Asahi. It was authored by **Alexander Graf** (Amazon, 2023) and upstreamed by **Phil Dennis-Jordan** (2024–2025), landing in **QEMU 10.0** (April 2025). It boots **macOS 12 guests only**; 13+ still fails in early boot as of QEMU master (mid-2026). On **Asahi Linux / KVM, no macOS-guest support exists upstream** — in fact the `vmapple` machine cannot even be *compiled* for Linux hosts today (`config VMAPPLE ... depends on HVF`). Nested KVM on Apple Silicon Linux is now partially real: works on **M2+ with kernel ≥ 6.16 + QEMU ≥ 10.x**, but is explicitly "not ready for prime time"; **M1 has no nested-virt hardware at all**.
|
||||
|
||||
---
|
||||
|
||||
## 1. QEMU + KVM on Asahi Linux running macOS guests
|
||||
|
||||
### 1.1 What exists upstream — the `vmapple` machine (HVF only)
|
||||
|
||||
**Confirmed.** The canonical patch series:
|
||||
|
||||
| Series | Author | Date | Status |
|
||||
|---|---|---|---|
|
||||
| `[PATCH 00/12] Introduce new vmapple machine type` (v1) | Alexander Graf `<graf@amazon.com>` | 2023-06-14 | Posted, stalled |
|
||||
| `[PATCH v2 00/12]` | Alexander Graf | 2023-08-30 | Posted |
|
||||
| `macOS PV Graphics and new vmapple machine type` — respun/reworked series, v3…v17 | Phil Dennis-Jordan `<phil@philjordan.eu>` (part-sponsored by Sauce Labs), based on Graf's work | 2024-09 → 2025-01-12 (v16 posted 2024-12-23/27, v17 Jan 2025) | **Merged for QEMU 10.0** (released 2025-04-22) |
|
||||
|
||||
- v1: https://patchew.org/QEMU/20230614224038.86148-1-graf@amazon.com/
|
||||
- v2: https://patchew.org/QEMU/20230830161425.91946-1-graf@amazon.com/
|
||||
- v16/v17: https://patchew.org/QEMU/20250112210056.16658-1-phil@philjordan.eu/ and https://lists.gnu.org/archive/html/qemu-devel/2025-01/msg01001.html
|
||||
- XHCI companion fixes: https://patchew.org/QEMU/20241227121336.25838-1-phil@philjordan.eu/
|
||||
- Merged evidence: QEMU master `MAINTAINERS` has a `VMapple` section (M: Alexander Graf, Phil Dennis-Jordan); docs live at https://www.qemu.org/docs/master/system/arm/vmapple.html ; a `[PATCH-for-10.0] tests/qtest: Skip Aarch64 VMapple machine` (2025-04-03) confirms it was in the 10.0 tree.
|
||||
- **UTM 4.7.0** (mid-2026) shipped QEMU 10.0.2 and briefly enabled the vmapple model, then **removed it "for stability reasons"**, keeping only `apple-gfx-pci` for Intel VMs: https://github.com/utmapp/UTM/releases
|
||||
|
||||
**What vmapple is:** a reimplementation (no Apple code) of the device model that Virtualization.framework exposes to arm64 macOS guests: GICv3 (no ITS — legacy IRQs only, no MSI/MSI-X), GPEX PCIe, XHCI + USB HID, PL011 UART, PL031 RTC, PL061 GPIO + gpio-key power button, `pvpanic-mmio`, plus Apple-specific devices: `vmapple-aes` (hardware AES engine), `vmapple-cfg` (config region), `vmapple-bdif` ("backdoor interface"), `vmapple-virtio-blk-pci` (Apple's nonstandard virtio-blk extension, `variant=aux|root`), and `apple-gfx-mmio` (ParavirtualizedGraphics.framework-backed display).
|
||||
|
||||
**Confirmed limitations (from the cover letters and current master docs):**
|
||||
- **macOS 12.x guests only; 13+ (Ventura and later) fails during early boot** — still true on QEMU master as of the doc fetch (mid-2026). No public fix.
|
||||
- **macOS arm64 hosts only, `-accel hvf` only.** Host must be macOS 12+ (docs) — needed both for HVF and because `apple-gfx` drives Apple's closed-source ParavirtualizedGraphics.framework.
|
||||
- Guest must first be **provisioned/installed with Virtualization.framework** (e.g. `macosvm` CLI) from an IPSW; the resulting `disk.img` + `aux.img` are then reusable in QEMU.
|
||||
- Legacy IRQs only (no MSI/MSI-X; would need GICv3 ITS).
|
||||
- XHCI workaround needed for usable USB keyboard/tablet (macOS XHCI driver quirk when MSI-X absent; QEMU issue #2705, fixed in the same effort).
|
||||
- No Rosetta in guest (TSO needs a private Apple entitlement).
|
||||
- Migration blocked for apple-gfx (no state serialization).
|
||||
|
||||
**Documented command line (QEMU master docs, verbatim):**
|
||||
```bash
|
||||
UUID="$(contrib/vmapple/uuid.sh macosvm.json)" # extracts ECID
|
||||
AVPBOOTER="/System/Library/Frameworks/Virtualization.framework/Resources/AVPBooter.vmapple2.bin"
|
||||
dd if=aux.img of=aux.img.trimmed bs=$((0x4000)) skip=1
|
||||
qemu-system-aarch64 \
|
||||
-serial mon:stdio -m 4G -accel hvf \
|
||||
-M vmapple,uuid="$UUID" \
|
||||
-bios "$AVPBOOTER" \
|
||||
-drive file=aux.img.trimmed,if=pflash,format=raw \
|
||||
-drive file=disk.img,if=pflash,format=raw \
|
||||
-drive file=aux.img.trimmed,if=none,id=aux,format=raw \
|
||||
-drive file=disk.img,if=none,id=root,format=raw \
|
||||
-device vmapple-virtio-blk-pci,variant=aux,drive=aux \
|
||||
-device vmapple-virtio-blk-pci,variant=root,drive=root \
|
||||
-netdev user,id=net0,ipv6=off,hostfwd=tcp::2222-:22,hostfwd=tcp::5901-:5900 \
|
||||
-device virtio-net-pci,netdev=net0
|
||||
```
|
||||
(Install side: `macosvm --disk disk.img,size=32g --aux aux.img --restore UniversalMac_12.0.1_21A559_Restore.ipsw vm.json`, https://github.com/s-u/macosvm.)
|
||||
|
||||
### 1.2 KVM / Asahi Linux status — the crucial negative findings
|
||||
|
||||
**Confirmed facts:**
|
||||
1. **The `vmapple` machine is not buildable on Linux hosts at all.** QEMU master `hw/vmapple/Kconfig`:
|
||||
```
|
||||
config VMAPPLE
|
||||
depends on ARM
|
||||
depends on HVF
|
||||
...
|
||||
select MAC_PVG_MMIO
|
||||
```
|
||||
(https://gitlab.com/qemu-project/qemu/-/raw/master/hw/vmapple/Kconfig). `MAC_PVG_MMIO` requires Darwin (Objective-C, ParavirtualizedGraphics.framework). So today there is **no QEMU binary on Asahi Linux that even contains the vmapple machine**.
|
||||
2. **No qemu-devel series adding KVM support for macOS guests has ever been posted or merged.** Graf's v1 cover letter explicitly states the aspiration, not an implementation: *"This device model would enable very nice use cases with KVM on an Asahi Linux device."* In the 2024 review thread Graf himself mused *"(I wonder if this works on KVM on Asahi Linux by the way. apple-gfx-vmapple won't work, but …)"* — i.e., untested, unsupported (https://lists.gnu.org/archive/html/qemu-arm/2024-10/msg00154.html).
|
||||
3. What porting to KVM would need (informed analysis, partly speculation): drop/guard the `MAC_PVG_MMIO` select (run headless/VNC or with a non-Apple display), fix GICv3-in-kernel vs. software-GIC assumptions in `create_gic()`, replace HVF-specific sysreg handling, and deal with `-cpu host` quirks. The qtest patch notes vmapple hard-requires the `host` CPU type, which does exist under KVM.
|
||||
4. **Related Asahi/Linux-kernel groundwork that *did* happen** (relevant to your hypervisor plan, all confirmed):
|
||||
- KVM/arm64 on Apple Silicon works since 2021 (marcan + Marc Zyngier; M1's AIC natively virtualizes the GIC CPU interface — Asahi progress report 2021-03: https://asahilinux.org/2021/03/progress-report-january-february-2021/).
|
||||
- marcan's `[PATCH 0/4] arm64: Support the TSO memory model` (2024-04-11, https://patchew.org/linux/20240411-tso-v1-0-754f11abfbff@marcan.st/) — Apple IMPDEF ACTLR_EL1 TSO for Rosetta/FEX; cover notes "KVM support for this is left for a future patchset".
|
||||
- #asahi-dev IRC logs (2023-09-10) show marcan/maz discussing AIDR_EL1/ACTLR_EL12 exposure to KVM guests — Apple-IMPDEF CPU-feature exposure to guests was known-incomplete (KVM exposing host MIDR/AIDR without the features).
|
||||
5. The specific items in your prompt ("PMU emulation, apple-specific CPU features, GIC, xnu quirks, `-cpu host` handling" as a posted series) do **not** correspond to any merged or posted KVM work I could find — this appears to be a conflation of the vmapple (HVF) series with Asahi KVM discussions. Mark as **not found / likely doesn't exist as described**.
|
||||
|
||||
### 1.3 Performance/limitations of macOS-in-QEMU today (HVF path)
|
||||
|
||||
- Networking: `virtio-net-pci` works in vmapple guests — **macOS ships its own virtio-net/virtio-blk drivers in the vmapple kernel** (Apple's closed-source kexts; that's why QEMU needs only standard virtio devices). Slirp user networking; vmnet.framework backend exists in QEMU for macOS hosts but bridged networking needs entitlements.
|
||||
- Display: `apple-gfx-mmio` gives Metal-backed 3D via PVG (host macOS only). Otherwise serial + VNC (the docs suggest port-forwarding 5900 to the guest's Screen Sharing).
|
||||
- Input: USB XHCI kbd/tablet (with the interrupter-mapping workaround).
|
||||
- GPU for compute/ML in guest: works via PVG Metal passthrough on HVF hosts; nothing on Linux hosts.
|
||||
|
||||
---
|
||||
|
||||
## 2. macOS guest boot mechanics
|
||||
|
||||
**Confirmed:**
|
||||
- **Real hardware chain:** Boot ROM → LLB → iBoot → kernelcache (XNU + boot kexts, built by `kmutil`) → launchd. iBoot passes boot args and the hardware description via **device tree** (Apple ADT, not Linux FDT semantics). (https://www.macinternals.app/en/blog/how-macos-boots)
|
||||
- **In Virtualization.framework, iBoot is replaced by `AVPBooter` (`AVPBooter.vmapple2.bin`)**, a bootloader blob shipped inside the framework; the guest sees the "vmapple" device model, an auxiliary storage volume (NVRAM/RTC/policy), a machine identifier containing an ECID/UUID, and virtio devices. There is **no iBoot, no SMC, no ANS/NAND emulation** — the guest kernel is the special "vmapple" kernelcache variant that expects paravirtualized devices. QEMU's vmapple machine consumes exactly this: `-bios AVPBooter…`, aux+root as pflash, Apple-variant virtio-blk for aux/root, `uuid=` = ECID.
|
||||
- **No SMC/ANS needed** for the arm64 VZ path (unlike x86 macOS, which needs `isa-applesmc,osk=…`).
|
||||
- **Install media:** macOS restore IPSW images (e.g. `UniversalMac_12.0.1_21A559_Restore.ipsw`), restored into a blank disk by a VZ-based tool (macosvm, tart, vfkit `--bootloader macos`, Code-Hex/vz examples). QEMU cannot do the restore itself — the guest must be pre-provisioned.
|
||||
- **Direct kernel boot of XNU in QEMU:** exists only as research hacks under **TCG**, not as a supported path:
|
||||
- Zhuowei Zhang's "Booting a macOS Apple Silicon kernel in QEMU" (2020-11-09, https://worthdoingbadly.com/xnuqemu3/): patched QEMU (`github.com/zhuowei/qemu` branch `a12z-macos`), PAC neutered, hand-edited iPad device tree, `-kernel bootcache-arm64e` direct boot of macOS 11 beta XNU up to launchd — no disk, no drivers. Lineage: his iOS-QEMU work → Aleph Security's xnu-qemu-arm64 iOS emulation platform.
|
||||
- **pongoOS** (checkra1n team's boot environment): a bare-metal iBoot-exploit payload for iOS/Apple research; it can boot XNU on real hardware with hooks. Not part of any QEMU path; for your project it matters only as prior art for "pre-kernel environment that chainloads XNU on Apple Silicon."
|
||||
- **m1n1** (Asahi): the directly relevant prior art for a type-1 hypervisor booting macOS. m1n1 runs at EL2, can boot Linux *or macOS* as a guest, traps MMIO via stage-2 faults, traces everything over a Python/USB proxy, and virtualizes UART (https://asahilinux.org/docs/sw/m1n1-user-guide/, "Running a macOS kernel as a m1n1 hypervisor guest"; fork example: https://github.com/jevinskie/m1n1-xnu-boot). This is how Asahi reverse-engineered Apple's hardware, and is the closest existing thing to "UniversalisOS hosting XNU."
|
||||
|
||||
---
|
||||
|
||||
## 3. Alternatives and complements
|
||||
|
||||
**Confirmed:**
|
||||
- **Virtualization.framework (VZ)** — Apple's high-level API (macOS 11+; macOS guests on Apple Silicon since macOS 12/Monterey). Boots via AVPBooter from IPSW restore images. Wrappers:
|
||||
- **tart** (Cirrus Labs): CLI/OCI-image VZ manager for macOS and Linux guests; standard in CI (GitHub Actions self-hosted runners).
|
||||
- **crc-org/vfkit**: primarily Linux VMs, but **does support macOS guests** via `--bootloader macos,machineIdentifierPath=…,hardwareModelPath=…,auxImagePath=…` (issue crc-org/vfkit#139/#148; added ~2024).
|
||||
- **UTM**: uses VZ ("Apple Virtualization" mode) for macOS guests, QEMU (HVF) for everything else.
|
||||
- **AppleContainer / containerization** (Apple, 2025): per-container Linux microVMs via VZ — Linux guests only, not macOS.
|
||||
- **VZ hard limits (confirmed from Apple docs / ecosystem analyses):**
|
||||
- Guest macOS versions: host version **and up to two major versions older** ("n-2" rule).
|
||||
- **Concurrency: max 2 macOS VMs** — enforced in XNU itself (`hv_apple_isa_vm_quota` counter), matching the EULA; Linux VMs unlimited. (Analysis: https://github.com/projecteru2/cocoon/issues/5)
|
||||
- VZ requires a graphics device config for macOS guests (headless works by not attaching a window — tart does this).
|
||||
- No App Store/FairPlay DRM in guests; iCloud sign-in only from macOS 15 guests.
|
||||
- **Nested: `isNestedVirtualizationSupported` — "available for Mac with the M3 chip, and later", macOS 15+** (https://developer.apple.com/documentation/virtualization/vzgenericplatformconfiguration/isnestedvirtualizationsupported). vfkit `--nested` (v0.6.0+) and krunkit expose it.
|
||||
- **QEMU cannot use VZ:** correct — upstream QEMU has no Virtualization.framework backend; the only macOS accelerator is **HVF** (Hypervisor.framework). (UTM bridges both worlds as separate backends.)
|
||||
- **HVF aarch64 in QEMU:** Alexander Graf's `hvf: Implement Apple Silicon Support` series (v1 Nov 2020 … v8 mid-2021, e.g. https://patchew.org/QEMU/20201211151300.85322-8-agraf@csgraf.de/) — **merged in QEMU 6.2 (released 2021-12-14)**: "macOS hosts with Apple Silicon CPUs now support 'hvf' accelerator for AArch64 guests" (https://www.qemu.org/2021/12/14/qemu-6-2-0/). Fully mature today for Linux/Windows-arm64 guests on macOS hosts.
|
||||
|
||||
---
|
||||
|
||||
## 4. Nested virtualization
|
||||
|
||||
**Hardware (confirmed):**
|
||||
- **M1: no FEAT_NV at all — hardware-assisted nested virtualization is impossible.** EL2 registers are not accessible from EL1 guests. (apple.stackexchange #466761, answer by jksoegaard — widely cited and consistent with marcan's statements.)
|
||||
- **M2 (ARMv8.6-A) and later: FEAT_NV2 present in silicon.** Apple only *exposes* it via VZ on M3+ (macOS 15), but the hardware feature exists on M2.
|
||||
|
||||
**Linux KVM host side (confirmed):**
|
||||
- Marc Zyngier's multi-year series — v10 `[PATCH v10 00/59] KVM: arm64: ARMv8.3/8.4 Nested Virtualization support` (2023-05), then v11 `[PATCH v11 00/43] … (FEAT_NV2 only)` (2023-11-20, dropping FEAT_NV since no shipping hardware has NV-without-NV2). Merged upstream incrementally across 6.8–6.16; a **major arm64 KVM refactor landed in 6.16** that practical reports treat as the baseline. VNCR_EL2/NV2 fast-path work continued into 2025 (e.g. https://patchwork.kernel.org/project/linux-arm-kernel/patch/20250215150134.3765791-11-maz@kernel.org/).
|
||||
- Activation: boot host with `kvm-arm.mode=nested`; success shows `kvm [1]: VHE+NV2 mode initialized successfully`.
|
||||
- **QEMU userspace side:** series by Haibo Xu (2021), Miguel Luis (2023), Eric Auger respin `[RFC v3 0/5] ARM Nested Virt Support` (2024-03, https://lists.gnu.org/archive/html/qemu-arm/2024-03/msg00871.html): `-machine virt,accel=kvm,virtualization=on` via `KVM_CAP_ARM_EL2`/`KVM_ARM_VCPU_HAS_EL2`. Present in QEMU 10.x; a Fedora/Asahi user reports distro QEMU 9.2.4 was *missing* pieces and 10.2.0 works (exact upstream merge version not pinned down — likely 9.2/10.0 era; mark as approximate).
|
||||
|
||||
**First-hand report on Asahi (Jan 2026, confirmed existence, experimental quality):** Fedora discussion (https://discussion.fedoraproject.org/t/nested-virtualization/179358): on an **M2 Mac with Asahi Linux, kernel 6.16+, QEMU 10.2, `kvm-arm.mode=nested`, `-M virt,accel=kvm,virtualization=on`**, an L1 Ubuntu guest saw KVM and L2 boot began; hit `kvm [1]: nv: … PAGE_SIZE not supported at Stage-2, giving up` (16K-page host issue) and Windows 11 arm64 L2 hung at bootmgr. Ampere's Dave Neary (May 2026): nested on ARM64 "still a very recent feature… not really ready for prime time" (https://community.amperecomputing.com/t/nested-virtualization-on-ampere-arm64/3399).
|
||||
|
||||
**Implication for UniversalisOS (analysis):** if Asahi Linux runs as a *guest* of your hypervisor and you want QEMU+KVM inside it, your hypervisor must implement the EL2-virtualization contract KVM expects (HCR_EL2.NV/NV2, VNCR_EL2, shadow S2, vGIC maintenance IRQ…) — i.e., your hypervisor plays L0 like Linux 6.16's KVM does. On M1 that's impossible in hardware. On M2+ it's possible but you inherit a moving target. Running QEMU **bare-metal-adjacent** (directly on your type-1, or in a privileged personality) avoids the problem entirely.
|
||||
|
||||
---
|
||||
|
||||
## 5. VirtIO drivers for macOS guests & display story
|
||||
|
||||
**Confirmed:**
|
||||
- **Apple's own virtio drivers:** the arm64 "vmapple" macOS kernel (12+) ships closed-source virtio drivers for exactly the VZ device set: virtio-blk (with Apple extensions), virtio-net, virtio-rng, virtio-console/socket, PVG graphics. This is what QEMU's vmapple machine relies on (`virtio-net-pci` works out of the box). x86-64 macOS (10.14.4+/Mojave) briefly gained virtio-blk/9p/cirrus/stdvga kexts discovered by Gerd Hoffmann (2019, https://passthroughpo.st/mac-os-adds-early-support-for-virtio-qemu/) — legacy-mode only; virtio-net was never shipped by Apple for x86.
|
||||
- **Third-party XNU virtio kexts:** Phil Dennis-Jordan's **virtio-net.kext** (virtio-osx lineage, ~2011–2013, mirrored at PassthroughPOST/Hackintosh-KVM) — Intel-only, ancient (OS X 10.5–10.x era), predates arm64 and modern kext notarization/SIP. No maintained arm64 virtio-net/block kext exists publicly; on arm64, third-party kexts additionally require reduced security. **Verdict: do not plan on custom virtio kexts for arm64 macOS guests; use Apple's in-box vmapple-kernel drivers.**
|
||||
- **Display:** for arm64 guests: PVG via `apple-gfx-mmio` (host macOS only) or headless+VNC/SSH. No virtio-gpu/ramfb driver exists for XNU on arm64 (UTM's virtio-ramfb/viogpudo story is Windows/Linux only). For x86-64 macOS guests: `apple-gfx-pci` (merged in QEMU 9.2, same series family) gives Metal-backed 3D on macOS hosts with Metal GPUs; otherwise stdvga/VNC.
|
||||
- **Overall usability today:** on macOS hosts, vmapple+QEMU is "just about usable" (authors' words) for macOS 12: SSH/VNC in, USB input laggy-but-working after the XHCI fix, no Rosetta, no install-in-QEMU, no 13+. It's a research/CI substrate, not a daily-driver VM. On Linux hosts: nothing.
|
||||
|
||||
---
|
||||
|
||||
## 6. Demos, blogs, repos (curated)
|
||||
|
||||
- QEMU vmapple docs (canonical, with full CLI): https://www.qemu.org/docs/master/system/arm/vmapple.html
|
||||
- Graf v1 series w/ install+run instructions: https://patchew.org/QEMU/20230614224038.86148-1-graf@amazon.com/
|
||||
- Dennis-Jordan v17 (final upstream form): https://patchew.org/QEMU/20250112210056.16658-1-phil@philjordan.eu/
|
||||
- QEMU issue #2705 (XHCI/macOS quirk): https://gitlab.com/qemu-project/qemu/-/issues/2705
|
||||
- zhuowei, "Booting a macOS Apple Silicon kernel in QEMU" (TCG direct XNU boot): https://worthdoingbadly.com/xnuqemu3/
|
||||
- Asahi m1n1 user guide (macOS as m1n1 hypervisor guest): https://asahilinux.org/docs/sw/m1n1-user-guide/
|
||||
- Asahi 2021 progress report (KVM on M1, GIC virtualization): https://asahilinux.org/2021/03/progress-report-january-february-2021/
|
||||
- marcan TSO series: https://patchew.org/linux/20240411-tso-v1-0-754f11abfbff@marcan.st/
|
||||
- Nested on Asahi M2 field report: https://discussion.fedoraproject.org/t/nested-virtualization/179358
|
||||
- KVM NV2 v11: https://lore.kernel.org/linux-arm-kernel/20231120131027.854038-1-maz@kernel.org/T/
|
||||
- QEMU 6.2 HVF-aarch64 release note: https://www.qemu.org/2021/12/14/qemu-6-2-0/
|
||||
- x86-64 counterpoint (not your target, but mature): OSX-KVM/OpenCore boots up to macOS 15 Sequoia under QEMU/KVM on Intel/AMD (https://github.com/kholia/OSX-KVM; kraxel's 2017 guide https://www.kraxel.org/blog/2017/09/running-macos-as-guest-in-kvm/).
|
||||
- macosvm (VZ provisioning CLI): https://github.com/s-u/macosvm ; vfkit: https://github.com/crc-org/vfkit ; tart: https://github.com/cirruslabs/tart
|
||||
|
||||
---
|
||||
|
||||
## Honest maturity assessment for your porting plan
|
||||
|
||||
| Goal | Status today | Maturity |
|
||||
|---|---|---|
|
||||
| macOS 12 guest in QEMU on **macOS host** (HVF, vmapple) | Upstream QEMU ≥ 10.0, documented | Usable for CI/research; rough edges |
|
||||
| macOS 13–15/26 guest in QEMU | **Not working** anywhere (VZ-only) | Blocked on early-boot investigation; no public progress since 2025 |
|
||||
| macOS guest in QEMU on **Asahi Linux / KVM** | **Does not exist**; machine doesn't even build for Linux (`depends on HVF`) | Greenfield. Graf flagged it as desirable in 2023; nobody has posted patches |
|
||||
| Nested KVM on Apple Silicon Linux (M2+) | Kernel 6.16+ + QEMU 10.x, partial | Experimental; 16K stage-2 and Windows issues; "not prime time" |
|
||||
| Nested virt on M1 | Impossible (no FEAT_NV) | Dead end |
|
||||
| Booting XNU under a research EL2 hypervisor | m1n1 does this daily on bare metal | Proven prior art for UniversalisOS |
|
||||
|
||||
**Speculation flags:** (a) exact QEMU release that completed KVM `virtualization=on` support (between 9.2 and 10.2 — confirmed working at 10.2, absent at distro 9.2.4); (b) the amount of work to KVM-ify vmapple — the GIC/sysreg/HVF-isms look modest in code size but the macOS-13+ early-boot failure is unsolved even on HVF, and may be CPU-behavior-related (the authors themselves suspect "differences between Apple M series CPUs and TCG's aarch64 implementation"), which could equally bite KVM; (c) feasibility of guest virtio drivers beyond Apple's in-box set on arm64 macOS — no public arm64 kext exists, so assume in-box vmapple drivers only.
|
||||
|
||||
**One-line bottom line for the plan:** on Apple Silicon, "QEMU runs macOS" today means *QEMU 10+ `vmapple` on a macOS host via HVF, macOS 12 guests only*. Making it work under KVM on Asahi (or inside your hypervisor) is unclaimed territory: the realistic engineering path is to fork/lift `hw/vmapple` off its HVF dependency, solve the macOS 13+ early-boot blocker, and provision guests from IPSW via a VZ tool on a Mac (or replicate AVPBooter's contract yourself, m1n1-style).
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
All research complete. Here is the structured report.
|
||||
|
||||
# Research Report: Apple Silicon Emulation, QEMU Internals, XNU Boot, Type-1 Hypervisors & Virtualization Hardware
|
||||
*Stream 3 of the UniversalisOS porting plan — prepared 2026-07-12. All claims sourced; uncertainty flags marked ⚠️.*
|
||||
|
||||
---
|
||||
|
||||
## 1. Emulating Apple Silicon hardware in QEMU (any host)
|
||||
|
||||
### 1.1 Project lineage (chronological)
|
||||
|
||||
| Era | Project | What it did | Status |
|
||||
|---|---|---|---|
|
||||
| 2018 | **zhuowei** (`worthdoingbadly.com/xnuqemu2/`, `xnuqemu3/`) | First XNU arm64 boot in modified QEMU: iOS 12 kernel to launchd (2018), then **macOS 11 arm64e kernelcache to launchd** on a `macos11-j273-a12z` machine (Nov 2020) — "completely useless" but proved XNU boots in QEMU | Archived; foundational |
|
||||
| 2019–2021 | **Aleph Security `xnu-qemu-arm64`** + `xnu-qemu-arm64-tools` (Jonathan Afek) | iOS 12.1 on emulated iPhone 6s Plus (t8015) to interactive bash, launchd services, R/W block device, TCP tunnel, custom IOKit driver, KVM acceleration via a custom LKM (`xnu-kvm-lkm`). Tools repo: kernel extraction (ASN.1/LZSS), GDB/Ghidra scripts | **Abandoned/read-only** (per TruEmu BH USA 2022 talk: "hard to maintain and abandoned"). Still runs; the eShard team reproduced it in 2024 |
|
||||
| 2020 | **Corellium "Project Sandcastle"** | ⚠️ *Correction to the prompt's premise*: Sandcastle is **not QEMU work** — it's Corellium's Linux/Android-10 port booted on a **real iPhone 7 (A10)** via checkm8/checkra1n + pongoOS. Released 6 Mar 2020, inactive since 8 Mar 2020. Repo: `github.com/corellium/projectsandcastle`, kernel fork `corellium/linux-sandcastle` | Inactive |
|
||||
| 2020–2021 | **Cylance/BlackBerry `macos-arm64-emulation`** | QEMU 5.1 patchset booting macOS 11 (Big Sur) arm64 recovery to shell on Intel hosts, pre-built dtb/kernel/ramdisk; derivative of zhuowei's a12z work | Archived, still runnable (documented at ku.nz/blog/appleonintel.html) |
|
||||
| 2022 | **TrungNguyen1909/qemu-t8030** ("TruEmu", BlackHat USA 2022) | iPhone 11 (t8030/A13) machine in QEMU 6.x: iOS 14–16 claimed, USB restore via companion QEMU instance, ANS2 NVMe namespaces, kernel patching inside QEMU, SEP stub. **The public tree never fully boots stock iOS** (widely reported) | Last commit Oct 2022 — **stale** (2.2k★) |
|
||||
| 2022–2023 | **devos50's QEMU forks** | iPod touch 1G (iOS 1.1) and iPhone 2G to SpringBoard using iEmu/xnu-qemu-arm64/TruEmu lineage + OpeniBoot | Slow research pace |
|
||||
| 2023– | **ChefKissInc — QEMUAppleSilicon → renamed "Inferno"** | Active fork/rewrite of qemu-t8030 | **Active as of 2026-06** (see below) |
|
||||
| 2024–2025 | **eShard** (commercial research, blog-only) | iOS 14 partial emulation based on qemu-t8030 ported to QEMU 8.2.1, using **pongoOS + checkra1n KPF** loaded from enlarged SRAM instead of in-QEMU kernel patching; chip-id spoof to t8015 to get software-rendered framebuffer; reached lock screen (part 1, Apr 2025) and "lots of modern apps" (part 2, 2025) | Source **not published** |
|
||||
|
||||
### 1.2 ChefKissInc/Inferno (current flagship)
|
||||
|
||||
- Repo: `github.com/ChefKissInc/Inferno` (formerly `QEMUAppleSilicon`; theapplewiki confirms the rename, Feb 2026). 3.8k★, GPL-3/AGPL-3. Last push observed **2026-06-18** (recent commits: virgl build fixes, libtasn1 meson fixes, `sep: avoid pointer alias`). CI uses dependabot — genuinely maintained.
|
||||
- **Machine models live in `hw/arm/apple-silicon/`** (verified via GitHub API): `t8030.c` + `t8030-config.c.inc` (iPhone 11/A13), `a13.c`, `a13_gxf.c/.h` (Apple GXF guarded-execution/genter/gexit support), `s8000.c` + `s8000-config.c.inc` (A9 — newer addition), `sep.c` + `sep-sim.c` (Secure Enclave Processor emulation + simulation), `dart.c` + `dart-stub.c` (IOMMU), `sart.c` (NVMe SART), `boot.c`, `dt.c` (ADT/device-tree), `mem.c`, `kernel_patches.c` + `patcher.c` (runtime XNU patching), `img4.asn1`/`art.asn` + libtasn1 (IMG4/ART parsing), `mt-spi.c` (multitouch SPI), `lm-backlight.c`. Storage is presented as **ANS2 NVMe namespaces** (`-device nvme-ns,…bus=nvme-bus.0`, plus `apple-nvram` namespace — see Discussion #34).
|
||||
- **What boots**: iPhone 11 (t8030) running **iOS 14.x** to SpringBoard with SEP emulation (ChefKiss posted video of Calculator/Settings working, "minor graphical glitches"). Wiki notes support for older/newer iOS "reportedly upcoming". No macOS boot; no M-series machine model yet (theapplewiki: "aims to emulate A-series and M-series"). ⚠️ Some of the SEP/SpringBoard capability was shown on social media before full public release; exact public-tree capability at HEAD should be re-verified at planning time.
|
||||
- Emulation General Wiki (2026-05 snapshot) also notes a **separate unreleased fork** by another developer reaching SpringBoard with full SEP, archived mysteriously (Corellium-hire speculation) — ⚠️ rumor-grade.
|
||||
- **eShard part 2 (2025)** demonstrates the practical ceiling today: partial iOS 14 with many apps, software rendering, PongoOS patching. No GPU emulation anywhere; Metal forwarding is "a long road" (eShard).
|
||||
|
||||
**Maturity assessment**: research-grade, single-SoC (A13), iOS-only, no GPU, slow (TCG; KVM only on the old Aleph tree via a hack). Nothing usable as-is for a macOS-targeting hypervisor, but `hw/arm/apple-silicon/` is the **best existing public reference implementation** of Apple SoC device semantics (ADT, ANS2, DART, SART, SEP mailbox, GXF) in C — high reuse value as documentation-by-code.
|
||||
|
||||
---
|
||||
|
||||
## 2. QEMU ARM architecture relevant to a type-1 hypervisor project
|
||||
|
||||
### 2.1 The `virt` machine (baseline knowledge, verified against qemu.org docs/master)
|
||||
|
||||
- Versioned machine type (`virt`, `virt-9.0`, …) in `hw/arm/virt.c`; auto-generates DTB (passed in x0 for Linux-boot-protocol kernels, or at 0x4000_0000 for bare-metal). Devices: 1–2 PL011 UART, PL061 GPIO, PL031 RTC, fw_cfg, GICv2M/ITS, optional machine-wide or per-root-bus **SMMUv3** (`iommu=smmuv3`, `-device arm-smmuv3,primary-bus=…`), 32 virtio-mmio slots, PCIe, CXL, ACPI optional.
|
||||
- **GIC**: `gic-version=2|3|4|host|max`. GICv2 → ≤8 CPUs; GICv3 → ≤512; GICv4 requires `virtualization=on`. **`-cpu host` only under KVM/HVF; `-cpu max` = host under KVM/HVF, best-effort under TCG; migration unsupported with `max`.**
|
||||
- Under **HVF on Apple Silicon**: `-M virt,highmem=off` historically required (older HVF couldn't do >32-bit IPA; the highmem requirement was lifted in later QEMU releases). HVF backend: Alexander Graf's 18-patch series merged for QEMU 6.2 (late 2021), `target/arm/hvf/hvf.c` — full sysreg-sync table, vtimer offset (`hv_vcpu_set_vtimer_offset`), WFI handling, PSCI, `-cpu host`, in-kernel-GIC-less design: **HVF does all interrupt injection via `hv_vcpu_set_pending_interrupt` and QEMU emulates the GIC in userspace** (HVF exposes no GICv3 virtual CPU interface; contrast with §5). HVF limitations at merge: no live migration/savevm, gdbstub SP quirks, no GICv3 acceleration.
|
||||
|
||||
### 2.2 Adding a new machine type (for UniversalisOS prototyping)
|
||||
|
||||
Canonical path: new file in `hw/arm/` (or a subtree like Inferno's `hw/arm/apple-silicon/`), a `MachineClass`/`MachineState` subclass, `DEFINE_MACHINE` or `type_init`-registered `machine_init`, Kconfig + meson entries. Inferno is the worked example of an SoC-family subtree with config-include pattern (`t8030-config.c.inc`, `s8000-config.c.inc`). For a hypervisor research project, QEMU gives you: QOM device framework, address-space/MemoryRegion model (fine-grained MMIO traps), TCG for bring-up before EL2 exists, gdbstub, and the whole virtio device + block/net backend stack.
|
||||
|
||||
### 2.3 Reusing QEMU assets inside a type-1 hypervisor
|
||||
|
||||
- **Precedent — Xen qemu-dm/stubdom**: Xen runs QEMU as the device model in dom0 (or a Mini-OS stubdom) per HVM guest; the hypervisor traps I/O and forwards to qemu-dm via IOREQ. This is the direct architectural template for "QEMU devices in a hypervisor domain". License note: QEMU is GPLv2 — embedding means the device-model process is GPL; keeping it in a separate domain/process (like Xen) is the standard containment.
|
||||
- **vhost / vhost-user**: the decoupling layer — data-plane backends (net/blk/scsi/gpu/vsock) run in-kernel (vhost) or in a separate userspace process over a UNIX socket (vhost-user, spec in QEMU `docs/interop/vhost-user.rst`). rust-vmm's `vhost-user` crates and SPDK/DPDK backends interoperate. This is the cleanest way to reuse QEMU *backends* without QEMU itself: UniversalisOS could implement the vhost-user *frontend* side.
|
||||
- **VFIO**: QEMU's `hw/vfio/` is the reference for device passthrough via Linux VFIO (needs IOMMU with stage-2 for DMA isolation — see §5 on DART limitations).
|
||||
- **DTB generation**: QEMU's `hw/arm/virt.c` + libfdt path is directly liftable; Inferno's `dt.c` shows ADT-style tree construction.
|
||||
- ⚠️ QEMU device *models* are tightly coupled to QOM/qdev and the main-loop; in-process reuse inside a non-QEMU hypervisor is impractical — out-of-process (qemu-dm style) or vhost-user is the realistic reuse level.
|
||||
|
||||
### 2.4 Rust VMM alternatives on aarch64 / Apple Silicon
|
||||
|
||||
| Codebase | aarch64/KVM | Apple Silicon host support | Notes |
|
||||
|---|---|---|---|
|
||||
| **Firecracker** | Production (Graviton, since 2019) | **No** (KVM-only). A Jan-2025 PoC fork boots aarch64 Linux on macOS via Virtualization.framework (firecracker-microvm/firecracker#5017, `drink7036290/firecracker` branch `macos_avf`) — explicitly out of scope upstream | ~50k LOC Rust; rust-vmm crates reusable independently (kvm-ioctls, vm-superio, vm-fdt, vmm-sys-util) |
|
||||
| **crosvm** | Supported on aarch64 KVM (ChromeOS/Android/ARM servers) | **No HVF backend** (KVM/minijail-centric). ⚠️ No evidence of Apple Silicon support | Rich device set (virtio-gpu, etc.) |
|
||||
| **Cloud Hypervisor** | Production aarch64/KVM | No HVF | rust-vmm based; vhost-user, VFIO, hotplug; ~50k LOC |
|
||||
| **libkrun** (`containers/libkrun`) | KVM on Linux | **Yes — HVF backend for aarch64 macOS is a first-class variant** (powers krunkit/podman-machine, muvm GPU VMs, crun krun). Apache-2.0 | The **only mature Rust VMM with an HVF path**; its `hvf` backend is the seed of… |
|
||||
| **ignition** (`github.com/vadika/ignition`, Jun 2026) | — | **Yes** — new research microVM modeled on Firecracker architecture, HVF backend reworked from libkrun, rust-vmm building blocks; boots Linux, SMP, virtio set, snapshots, fuzzing. Very fresh | Worth tracking; single-author research |
|
||||
|
||||
**Maturity assessment**: for a UniversalisOS VMM written in Rust targeting both Linux/KVM-on-Asahi and macOS/HVF hosts during development, **rust-vmm crates + libkrun's HVF backend** is the most reusable code in existence today. Firecracker/crosvm/CH give you design + crates but no Apple-host path.
|
||||
|
||||
---
|
||||
|
||||
## 3. Booting XNU/Darwin outside Apple hardware
|
||||
|
||||
- **XNU in QEMU**: all work is lineage §1.1 (zhuowei 2018/2020 → Aleph → Cylance → t8030 → Inferno → eShard). No one boots **macOS (full OS, with GUI)** in pure emulation; the ceiling is iOS 14 partial (Inferno/eShard) and macOS recovery/kernel to launchd or limited shell (zhuowei/Cylance 2020).
|
||||
- **pongoOS/checkra1n**: checkm8 bootrom exploit covers **A8–A11 only** — pongoOS **cannot run on real t8030 (A13) hardware**; eShard's trick was loading pongoOS *inside the emulator* from SRAM. checkra1n-adjacent tooling (ipwndfu, gaster, palera1n) is irrelevant to A13+/M-series. M-series instead has m1n1's 1TR/boot-policy path (§4).
|
||||
- **AVP / Apple Virtual Platform research** (the key §3 finding): macOS ARM guests under Virtualization.framework boot a distinct platform — board `vma2ap`/BDID 0x20, kernel flavor `RELEASE_ARM64_VMAPPLE`, boot chain **`AVPBooter.vmapple2.bin`** (an iBoot-stage-0 variant shipped inside `Virtualization.framework/Resources/`, not signature-checked). Research artifacts:
|
||||
- **`github.com/saagarjha/VirtualApple`** (verified live) — canonical Virtualization.framework demo with GUI/install.
|
||||
- **`github.com/NyanSatan/Virtual-iBoot-Fun`** (Dec 2021) — boots *patched* AVPBooter with `amfi_get_out_of_my_way=1`, sends iBSS/iBEC/devicetree/ramdisk/trustcache/kernelcache over the VM's emulated DFU USB channel with `irecovery`, applies a LocalPolicy, and reaches a **patched XNU kernel with GDB server and debug UART**. Includes bsdiff patches for iBoots and kernel. Requires the `com.apple.private.virtualization` private entitlement for custom-ROM/GDB/production-mode-demote.
|
||||
- Steven Michaud's gist (May 2026) extends this to **third-party kexts in macOS guests**, documenting that Virtualization.framework's boot images ship **unencrypted** — a reverse-engineering goldmine.
|
||||
- eclecticlight.co's VM-boot series documents the runtime artifacts: `HardwareModel` (150 B), `MachineIdentifier` (~60 B), `AuxiliaryStorage` (~34 MB: NVRAM + boot-loader state), virtio bring-up (`AppleParavirtIOSurface`, `AppleCredentialManager: init: called, Apple Virtual Platform`).
|
||||
- **What a macOS ARM guest *absolutely requires* from its VMM** (evidence-based):
|
||||
1. The **AVP boot environment**: AVPBooter stage-0 semantics, LocalPolicy/Image4 validation (or patching), AuxiliaryStorage/NVRAM, MachineIdentifier/HardwareModel/ECID properties, DFU-mode USB restore channel for install.
|
||||
2. **Paravirtualized devices**: virtio-blk/net/console/rng/vsock/socket, Apple Paravirtualized Graphics (Metal forwarding) for GUI, shared folders (virtiofs-like).
|
||||
3. ⚠️ **No SMC, no AppleHPM**: those are physical-Mac devices; VM guests don't see them (the x86-Mac SMC requirement does not carry over). ⚠️ The "AVP coprocessor" framing in the prompt conflates things: publicly, "AVP" names the **virtual platform/boot chain** (AVPBooter, vma2), not a documented separate silicon coprocessor; macOS guests do get **virtualized credential/enclave services** (AppleCredentialManager "Apple Virtual Platform" instance; Virtualization.framework provides a virtual SEP-like facility for key handling — ⚠️ internal details not publicly documented beyond NyanSatan/saagarjha work).
|
||||
4. A hypervisor that tolerates XNU's **GXF/SPRR/PPL usage** — XNU expects PPL (GL2) primitives; m1n1 had to grow GXF support (`src/gxf.c`, `gl2_call()`) to run XNU as a guest.
|
||||
- **macOS under m1n1 (real hardware, EL2)**: documented at `asahilinux.org/docs/sw/m1n1-hypervisor/` — full macOS 11.5.2 to login window with WiFi under the Python-driven m1n1 hypervisor (~2 min boot, single CPU, MMIO-traced). This is the **only working public "macOS as a guest under a non-Apple hypervisor"** setup.
|
||||
|
||||
---
|
||||
|
||||
## 4. Type-1 hypervisors on Apple Silicon
|
||||
|
||||
| Project | Status | Notes |
|
||||
|---|---|---|
|
||||
| **m1n1 hypervisor** (AsahiLinux/m1n1, MIT) | **Active, mature as a research HV** | EL2, stage-2 MMIO trapping, Python proxyclient over USB-UART (`proxyclient/hv/*.py` trace scripts), gdbserver, GXF/GL2 call support, runs XNU and Linux guests. Explicitly designed as an RE/tracing tool, not a production partitioner; **ABI unstable**. `run_guest.py`, `run_guest_kernel.sh` workflows documented. |
|
||||
| Derivatives of m1n1 hv | **AppleWOAProject** (Windows-on-Apple, `amarioguy`) plans to fork m1n1's hv as the EL2 layer to route interrupts to Windows EL1 (Jan 2025 update); **asahi_neo** (rusch95, Mar 2026) uses m1n1 hv mediation as one intercept strategy for A18-Pro Linux shim. No production type-1 built on m1n1 exists. | — |
|
||||
| **Xen on Apple Silicon** | **No port exists.** Sole artifact: xen-devel thread **"Xen for Apple Silicon (M1 and beyond)" (Jul 2024)** — feasibility discussion only (16K-page friction with 4K Xen, ADT vs FDT, firmware pairing issues; m1n1 acknowledged as the boot bridge). Stefano Stabellini engaged; nothing landed. | Thread: lists.xenproject.org/archives/html/xen-devel/2024-07/msg01391.html |
|
||||
| **seL4 on Apple Silicon** | **No port, none planned.** Verified against official supported-platforms + Microkit lists (docs.sel4.systems/Hardware, Microkit platforms): no Apple SoC. seL4 aarch64 virt support targets GIC/SMMU-based platforms; Apple-specific AIC/DART/SPRR would all be new work, and EL2 entry requires the m1n1/iBoot boot path. | — |
|
||||
| **Linux KVM on M1/M2 (as partitioner base)** | **Works downstream (Asahi kernels); partially upstream** | Marc Zyngier got Linux VMs running on KVM/Asahi in **early 2021** (Asahi progress report Mar 2021). Fedora Asahi Remix ships KVM enabled; QEMU/KVM on M1/M2 is daily-driver usable (fluxcoil blog 2024; Incus/virt-manager reports Jan 2026). Upstream has been absorbing Apple bits: **Linux 6.15 merged `kvm-arm64/pmuv3-asahi`** — Oliver Upton's 14-patch series virtualizing PMUv3 on Apple M1/M2 via IMPDEF traps (HACR_EL2 bit 56), tested on M2 Pro with Debian+Windows guests. **Nested virtualization works on M2 with kernel ≥6.16** (`kvm-arm.mode=nested` → "VHE+NV2 mode initialized"; M1 lacks FEAT_NV entirely — Fedora discussion Jan 2026). dmesg on M2 shows the Apple quirks: "Non-architectural vgic, tainting kernel", "GICv3: no GICV resource entry", "broken locally generated SEI", "sysreg trapping enabled ([G0G1D], reduced performance)". **Verdict: KVM-on-Asahi is the only near-mainline, multi-guest-capable virtualization base on Apple Silicon today** — a partitioning-hypervisor personality on top of it is feasible engineering, not science. |
|
||||
| **Apple's own XNU hypervisor** (Hypervisor.framework, EL2 under XNU) | Production since macOS 11 (2020); Virtualization.framework since 11, macOS guests since 12 | XNU runs at EL2 and multiplexes EL1 guests (that's why "nested virtualization in a macOS VM is impossible" — guests can't get EL2). HVF API surface: hv_vm/hv_vcpu, sysreg get/set, pending-interrupt injection, vtimer offset/mask — **no GIC CPU-interface virtualization, no nested** (as of macOS 15; ⚠️ unverified for macOS 26). Apple Containerization (Jun 2026, macOS 26) builds VM-per-container on VZ. |
|
||||
| **Other** | Edera (commercial, Xen-derived type-1 "zones") exists on ARM servers — ⚠️ no Apple Silicon support known. No Jailhouse/ACRN/Bao port to Apple Silicon found. | — |
|
||||
|
||||
---
|
||||
|
||||
## 5. Apple Silicon hardware virtualization features (per generation)
|
||||
|
||||
| Feature | M1 / A14 (t8101, Firestorm/Icestorm) | M2 / A15 (t8112, Avalanche/Blizzard) | M3 | M4 / A18 (t8140…) |
|
||||
|---|---|---|---|---|
|
||||
| **EL2** | Present and **fully usable** — XNU uses it (HVF); m1n1 and KVM/Asahi use it. Apple's IMPDEF "HACR_EL2" and related regs are documented-by-RE in m1n1 | Present, usable; adds **FEAT_NV2-class nested support** (confirmed working with Linux 6.16 `VHE+NV2`) | Present, usable (Asahi M3 bring-up done; m1n1 hv works per IRC logs — Sonoma M3 boots under hv "without obvious issues") | Present, **but boot-object environment changed**: iBoot now configures SPTM in GL2 before handoff; normal m1n1 boot path broken (Sven Peter, Apr 2025 — "rather painful"). **Raw boot objects still drop you into EL2** with most Apple extensions disabled — fine for Linux, *but XNU can't run under the hv there*, blocking RE-driven bring-up. ⚠️ EL2 itself is not locked; the boot flow around it got harder. M5 (2025–26): ⚠️ no public data found |
|
||||
| **SPRR / GXF / GL2** | SPRR+GXF present (A14/M1 introduced it); PPL runs at GL2 from within the kernelcache; m1n1 implements GXF (`src/gxf.c`) | SPRR+GXF; **SPTM arrives on Mac with macOS 15 on M2** (IRC: "for mac it is on M2 on macOS 15 and nothing else"; iOS: A15–A17 got SPTM in iOS 17) | PPL (GL2) like M1/M2-era macOS | **SPTM mandatory in the boot path** (iPadOS 17.5 introduced SPTM on M4). SPTM is separate iBoot-loaded firmware at GL2, owns page tables, reached via `genter` from EL1/EL2; **you cannot run Linux *under* SPTM** — raw boot bypasses it. ⚠️ rusch95's RE claims macOS 26 on A18 Pro still uses PPL not SPTM — single-source, treat as provisional |
|
||||
| **Interrupts (AIC vs GIC)** | AIC (Apple Interrupt Controller) is the distributor — **not** a GICD. But the M1 contains **"half a GIC"**: a GICv3 **CPU interface with virtualization (ICH_*)** usable by EL2 to give guests a near-native vGIC CPU interface; KVM-on-Asahi uses it (kernel taints: "Non-architectural vgic"). FIQ-based "Fast IPI" and guest timer delivery are Apple IMPDEF features RE'd by marcan/maz in 2021 | AIC2 (M1 Pro/Max and later; multi-die support upstreamed Dec 2021 by marcan). Same vGIC-cpuif story; nested adds another layer | AIC2 | AIC3-ish (⚠️ details still being RE'd for M4) |
|
||||
| **IOMMU (DART)** | DART = simple per-stream IOMMU, **no ARM SMMU architecture, no hardware stage-1+stage-2 nesting** — streams carry single-level TTBRs (16K granule). Linux driver: `drivers/iommu/apple-dart.c` + `io-pgtable-dart.c`; RE by Sven Peter (2021). **Implication: VFIO-style passthrough to guests means the hypervisor programs DART streams itself (guest IPA→PA as the DART IOVA→PA map) — feasible but all-software; no vIOMMU assist** | DART plus **SART** (NVMe address filter) on M1 Pro/Max+ | similar | similar (⚠️) |
|
||||
| **Timers** | Architectural timer with EL2 control (CNTVOFF_EL2 offsetting works — used by KVM/HVF; HVF exposes `hv_vcpu_set_vtimer_offset`). Apple IMPDEF guest-timer FIQ delivery RE'd 2021 | same + nested timer virtualization via NV2 | same | same (⚠️) |
|
||||
| **PMU** | IMPDEF PMU (not architectural PMUv3); **M1/M2 expose IMPDEF traps of PMUv3 sysregs (HACR_EL2[56])** enabling trap-emulate vPMU — upstreamed in Linux 6.15 (kvm-arm64/pmuv3-asahi) with a reduced 1-event-counter vPMU | same traps | ⚠️ M3 PMU trap support not confirmed in the series (MIDR list covers M1/M2 only) | ⚠️ unknown |
|
||||
| **Memory model quirks for VMMs** | 16K pages native (4K guests work — Rosetta/Docker prove it); big.LITTLE-ish heterogeneous cores break naive KVM sysreg sync (CCSIDR_EL1 fix merged for 6.3); SPRR interacts with guest page permissions — KVM guests run with SPRR effectively neutralized; XNU guests (m1n1) need GXF/PPL cooperation | + SPTM on macOS 15 guests-to-be | — | SPTM changes who owns stage-1 page tables on macOS; for a UniversalisOS design this argues for **raw-boot EL2 entry on M4** and treating PPL/SPTM as bypassed, not cooperated-with |
|
||||
|
||||
Key citable sources for §5: Asahi progress report Jan/Feb 2021 (AIC/GIC-virtualization, FIQ timers); marcan's AIC patches (Dec 2021, AICv2/multi-die/Fast-IPI); maz's vgic fixes (Sep 2021, "Apple M1 has half a GIC"); Oliver Upton's PMUv3-on-Apple series (v2 Feb 2025, merged 6.15); Sven Peter Mastodon (4 Apr 2025) via AppleInsider (8 Apr 2025) for M4 SPTM/GL2 boot changes; #asahi-dev IRC log 2024-07-14 (SPTM rollout matrix); Fedora nested-virt thread (Jan 2026) for M2 NV2 confirmation; rusch95/asahi_neo ARCHITECTURE.md (Mar 2026) for A18-Pro GXF/SPTM register/ABI details (⚠️ single-source).
|
||||
|
||||
---
|
||||
|
||||
## 6. Bottom-line maturity matrix for the UniversalisOS plan
|
||||
|
||||
| Need | Best available base | Maturity | Risk |
|
||||
|---|---|---|---|
|
||||
| Reference semantics for Apple SoC devices (ADT, ANS2, DART, SEP, GXF) | Inferno `hw/arm/apple-silicon/` + m1n1 `src/` | High (as documentation) | GPL-3 (Inferno) vs MIT (m1n1) — prefer m1n1 as citable reference |
|
||||
| Type-1 base on M1/M2 today | Linux KVM on Asahi (6.16+), m1n1 hv for experiments | KVM: workable, daily-used; m1n1: RE-grade | KVM-on-Apple is downstream-flavored; M3/M4 device support incomplete upstream |
|
||||
| EL2 entry on M4 | Raw boot object (EL2, extensions off) | Works for Linux; XNU-guest RE blocked | SPTM cohabitation unsolved; future chips may close raw boot |
|
||||
| Rust VMM for dev hosts (macOS HVF + Linux KVM) | rust-vmm + libkrun HVF backend (Apache-2) | Mature on KVM; HVF path production-ish (krunkit) | HVF has no GIC acceleration, no nested |
|
||||
| macOS-guest requirements spec | Virtual-iBoot-Fun + VirtualApple + Michaud gist + eclecticlight | Well-mapped boot chain | Requires private entitlements/patching; AVP internals undocumented; virtual-SEP details ⚠️ |
|
||||
| iOS-in-emulation capability | Inferno / eShard | Partial iOS 14, no GPU | Not needed for UniversalisOS core; useful for SEP/ANS2 semantics |
|
||||
|
||||
**Explicit uncertainty flags**: (a) Inferno's exact public-tree capability at HEAD vs social-media demos; (b) macOS 26/HVF changes (nested? GIC?) — no public data; (c) whether a physical "AVP coprocessor" exists beyond the virtual-platform boot chain — evidence says no, but Apple docs are silent; (d) M3/M4 PMU-trap and nested-virt support unverified; (e) asahi_neo's A18-Pro PPL-vs-SPTM claim is single-source; (f) eShard/Inferno release timing for newer iOS support unknown.
|
||||
6
realms/universalisos/kernel/include/arch/arm/mm.h
Normal file
6
realms/universalisos/kernel/include/arch/arm/mm.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef ARCH_ARM_MM_H
|
||||
#define ARCH_ARM_MM_H
|
||||
#include <stdint.h>
|
||||
/* ARM MMU stub for host testing */
|
||||
static inline uint32_t arm_page_table_base(void) { return 0x40000000; }
|
||||
#endif
|
||||
9
realms/universalisos/kernel/include/arch/arm/vm.h
Normal file
9
realms/universalisos/kernel/include/arch/arm/vm.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef ARCH_ARM_VM_H
|
||||
#define ARCH_ARM_VM_H
|
||||
#include <stdint.h>
|
||||
/* ARM VM context stub for host testing */
|
||||
struct arm_vm_context {
|
||||
uint32_t vttbr;
|
||||
uint32_t vtcr;
|
||||
};
|
||||
#endif
|
||||
5
realms/universalisos/kernel/include/arch/riscv/mm.h
Normal file
5
realms/universalisos/kernel/include/arch/riscv/mm.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#ifndef ARCH_RISCV_MM_H
|
||||
#define ARCH_RISCV_MM_H
|
||||
#include <stdint.h>
|
||||
static inline uint64_t riscv_page_table_base(void) { return 0x40000000; }
|
||||
#endif
|
||||
8
realms/universalisos/kernel/include/arch/riscv/vm.h
Normal file
8
realms/universalisos/kernel/include/arch/riscv/vm.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef ARCH_RISCV_VM_H
|
||||
#define ARCH_RISCV_VM_H
|
||||
#include <stdint.h>
|
||||
/* RISC-V VM context stub */
|
||||
struct riscv_vm_context {
|
||||
uint64_t satp;
|
||||
};
|
||||
#endif
|
||||
5
realms/universalisos/kernel/include/arch/x86/mm.h
Normal file
5
realms/universalisos/kernel/include/arch/x86/mm.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#ifndef ARCH_X86_MM_H
|
||||
#define ARCH_X86_MM_H
|
||||
#include <stdint.h>
|
||||
static inline uint64_t x86_page_table_base(void) { return 0x40000000; }
|
||||
#endif
|
||||
8
realms/universalisos/kernel/include/arch/x86/vm.h
Normal file
8
realms/universalisos/kernel/include/arch/x86/vm.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef ARCH_X86_VM_H
|
||||
#define ARCH_X86_VM_H
|
||||
#include <stdint.h>
|
||||
/* x86 VM context stub */
|
||||
struct x86_vm_context {
|
||||
uint64_t cr3;
|
||||
};
|
||||
#endif
|
||||
6
realms/universalisos/kernel/include/scheduler.h
Normal file
6
realms/universalisos/kernel/include/scheduler.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef SCHEDULER_H
|
||||
#define SCHEDULER_H
|
||||
#include <stdint.h>
|
||||
/* Scheduler stub for host testing */
|
||||
static inline void scheduler_add_consciousness(void* ctx) { (void)ctx; }
|
||||
#endif
|
||||
|
|
@ -0,0 +1,323 @@
|
|||
/*
|
||||
* Universalisos Guest Consciousness VM Context Management
|
||||
* Following PikeOS virtualization patterns with safety-critical isolation
|
||||
*
|
||||
* This module provides VM context management for AI consciousnesses running
|
||||
* as guest domains on the Universalisos type-1 hypervisor.
|
||||
*/
|
||||
|
||||
#ifndef UNIVERSALISOS_VM_CONSCIOUSNESS_H
|
||||
#define UNIVERSALISOS_VM_CONSCIOUSNESS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
/* #include "arch/arm/vm.h" */
|
||||
/* #include "arch/arm/mm.h" */
|
||||
/* #include "scheduler.h" */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Maximum number of consciousnesses supported simultaneously
|
||||
* Following PikeOS multi-domain patterns with safety isolation
|
||||
*/
|
||||
#define MAX_CONSCIOUSNESS_DOMAINS 16
|
||||
|
||||
/*
|
||||
* Consciousness VM context states
|
||||
* Following PikeOS domain lifecycle management
|
||||
*/
|
||||
typedef enum consciousness_vm_state {
|
||||
CONSCIOUSNESS_VM_UNINITIALIZED = 0,
|
||||
CONSCIOUSNESS_VM_INITIALIZING,
|
||||
CONSCIOUSNESS_VM_READY,
|
||||
CONSCIOUSNESS_VM_RUNNING,
|
||||
CONSCIOUSNESS_VM_SUSPENDED,
|
||||
CONSCIOUSNESS_VM_MIGRATING,
|
||||
CONSCIOUSNESS_VM_SAFE_STATE,
|
||||
CONSCIOUSNESS_VM_SHUTDOWN
|
||||
} consciousness_vm_state_t;
|
||||
|
||||
/*
|
||||
* Consciousness VM context structure
|
||||
* Following PikeOS VM context patterns with safety-critical parameters
|
||||
*/
|
||||
typedef struct consciousness_vm_context {
|
||||
// Identification
|
||||
uint32_t consciousness_id;
|
||||
char consciousness_name[32];
|
||||
|
||||
// VM state management
|
||||
consciousness_vm_state_t state;
|
||||
uint32_t state_flags;
|
||||
|
||||
// CPU context (following PikeOS context save/restore)
|
||||
struct {
|
||||
uint32_t registers[16]; // R0-R15
|
||||
uint32_t cpsr;
|
||||
uint32_t spsr;
|
||||
uint32_t pc;
|
||||
uint32_t lr;
|
||||
} cpu_context;
|
||||
|
||||
// Memory management (following PikeOS memory isolation)
|
||||
struct {
|
||||
uint32_t page_table_base;
|
||||
uint32_t page_table_size;
|
||||
uint32_t heap_start;
|
||||
uint32_t heap_end;
|
||||
uint32_t stack_start;
|
||||
uint32_t stack_end;
|
||||
uint32_t memory_quota;
|
||||
} memory_context;
|
||||
|
||||
// TrustZone security (following PikeOS TZ implementation)
|
||||
struct {
|
||||
bool secure_mode;
|
||||
uint32_t scr_register;
|
||||
uint32_t nsacr_register;
|
||||
uint32_t vic_range_base;
|
||||
} trustzone_context;
|
||||
|
||||
// Real-time constraints (following PikeOS ARINC 653)
|
||||
struct {
|
||||
uint32_t time_partition_id;
|
||||
uint32_t budget_microseconds;
|
||||
uint32_t deadline_ticks;
|
||||
uint32_t priority_level;
|
||||
uint64_t total_cpu_time;
|
||||
} realtime_context;
|
||||
|
||||
// Safety monitoring (following PikeOS safety patterns)
|
||||
struct {
|
||||
uint32_t watchdog_timeout;
|
||||
uint64_t last_watchdog_feed;
|
||||
uint32_t safety_violation_count;
|
||||
bool bounds_checking_enabled;
|
||||
bool memory_isolation_enabled;
|
||||
} safety_context;
|
||||
|
||||
// Communication (following PikeOS IPC patterns)
|
||||
struct {
|
||||
uint32_t message_queue_id;
|
||||
uint32_t shared_memory_regions[4];
|
||||
uint32_t synapse_count;
|
||||
uint32_t connected_consciousnesses[MAX_CONSCIOUSNESS_DOMAINS];
|
||||
} communication_context;
|
||||
|
||||
// Learning capabilities (Mycelium integration)
|
||||
struct {
|
||||
bool learning_enabled;
|
||||
float learning_rate;
|
||||
float synapse_growth_rate;
|
||||
float maturity_level;
|
||||
uint32_t engram_count;
|
||||
uint32_t max_engrams;
|
||||
} learning_context;
|
||||
|
||||
// Platform-specific
|
||||
struct {
|
||||
uint32_t architecture_type; // ARM, RISC-V, x86, etc.
|
||||
uint32_t platform_capabilities;
|
||||
uint32_t required_peripherals;
|
||||
} platform_context;
|
||||
|
||||
} consciousness_vm_context_t;
|
||||
|
||||
/*
|
||||
* Consciousness VM context management API
|
||||
* Following PikeOS domain management patterns with safety-critical guarantees
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize a new consciousness VM context
|
||||
*
|
||||
* @param context Pointer to consciousness context structure
|
||||
* @param consciousness_id Unique consciousness identifier
|
||||
* @param platform_type Target platform architecture
|
||||
*
|
||||
* @return 0 on success, error code on failure
|
||||
*
|
||||
* @safety ASIL-B compliant: Performs memory validation, TrustZone setup,
|
||||
* and safety checks before allowing context activation
|
||||
*/
|
||||
int consciousness_vm_context_init(
|
||||
consciousness_vm_context_t* context,
|
||||
uint32_t consciousness_id,
|
||||
uint32_t platform_type
|
||||
);
|
||||
|
||||
/**
|
||||
* Destroy consciousness VM context
|
||||
*
|
||||
* @param context Pointer to consciousness context structure
|
||||
*
|
||||
* @return 0 on success, error code on failure
|
||||
*
|
||||
* @safety ASIL-B compliant: Performs safe shutdown, memory cleanup,
|
||||
* and resource deallocation with validation
|
||||
*/
|
||||
int consciousness_vm_context_destroy(
|
||||
consciousness_vm_context_t* context
|
||||
);
|
||||
|
||||
/**
|
||||
* Save consciousness VM context
|
||||
* Following PikeOS context save patterns
|
||||
*
|
||||
* @param context Pointer to consciousness context structure
|
||||
*
|
||||
* @safety Real-time critical: Must complete within time partition
|
||||
* @return 0 on success, error code on failure
|
||||
*/
|
||||
int consciousness_vm_context_save(
|
||||
consciousness_vm_context_t* context
|
||||
);
|
||||
|
||||
/**
|
||||
* Restore consciousness VM context
|
||||
* Following PikeOS context restore patterns
|
||||
*
|
||||
* @param context Pointer to consciousness context structure
|
||||
*
|
||||
* @safety Real-time critical: Must complete within time partition
|
||||
* @return 0 on success, error code on failure
|
||||
*/
|
||||
int consciousness_vm_context_restore(
|
||||
consciousness_vm_context_t* context
|
||||
);
|
||||
|
||||
/**
|
||||
* Schedule consciousness for execution
|
||||
* Following PikeOS deadline scheduler patterns
|
||||
*
|
||||
* @param context Pointer to consciousness context structure
|
||||
*
|
||||
* @safety Real-time critical: Enforces time partition and deadlines
|
||||
* @return 0 on success, error code on failure
|
||||
*/
|
||||
int consciousness_vm_context_schedule(
|
||||
consciousness_vm_context_t* context
|
||||
);
|
||||
|
||||
/**
|
||||
* Preempt consciousness execution
|
||||
* Following PikeOS priority-based preemption
|
||||
*
|
||||
* @param context Pointer to consciousness context structure
|
||||
*
|
||||
* @safety Real-time critical: Guaranteed bounded preemption time
|
||||
* @return 0 on success, error code on failure
|
||||
*/
|
||||
int consciousness_vm_context_preempt(
|
||||
consciousness_vm_context_t* context
|
||||
);
|
||||
|
||||
/**
|
||||
* Migrate consciousness to different platform
|
||||
* Enabling hardware-agnostic consciousness deployment
|
||||
*
|
||||
* @param context Pointer to consciousness context structure
|
||||
* @param target_platform Target platform architecture
|
||||
*
|
||||
* @return 0 on success, error code on failure
|
||||
*
|
||||
* @safety ASIL-B compliant: Validates migration safety, performs checkpoint,
|
||||
* and ensures platform compatibility before migration
|
||||
*/
|
||||
int consciousness_vm_context_migrate(
|
||||
consciousness_vm_context_t* context,
|
||||
uint32_t target_platform
|
||||
);
|
||||
|
||||
/**
|
||||
* Consciousness communication via synapses
|
||||
* Following PikeOS inter-partition communication
|
||||
*
|
||||
* @param source_context Source consciousness context
|
||||
* @param target_id Target consciousness ID
|
||||
* @param message_data Message data pointer
|
||||
* @param message_size Message size in bytes
|
||||
*
|
||||
* @return 0 on success, error code on failure
|
||||
*
|
||||
* @safety Real-time critical: Bounded communication latency guaranteed
|
||||
* @safety ASIL-B compliant: Validates message format and target safety level
|
||||
*/
|
||||
int consciousness_vm_context_send_synapse(
|
||||
consciousness_vm_context_t* source_context,
|
||||
uint32_t target_id,
|
||||
void* message_data,
|
||||
size_t message_size
|
||||
);
|
||||
|
||||
/**
|
||||
* Consciousness learning via Mycelium integration
|
||||
*
|
||||
* @param context Pointer to consciousness context structure
|
||||
* @param input_data Input data pointer
|
||||
* @param input_size Input size in bytes
|
||||
* @param result_data Result data pointer
|
||||
* @param result_size Result size in bytes
|
||||
*
|
||||
* @return 0 on success, error code on failure
|
||||
*
|
||||
* @safety ASIL-B compliant: Memory engram absorption validated for safety,
|
||||
* learning rate bounded to prevent runaway adaptation
|
||||
*/
|
||||
int consciousness_vm_context_learn(
|
||||
consciousness_vm_context_t* context,
|
||||
void* input_data,
|
||||
size_t input_size,
|
||||
void* result_data,
|
||||
size_t result_size
|
||||
);
|
||||
|
||||
/**
|
||||
* Consciousness watchdog monitoring
|
||||
* Following PikeOS watchdog patterns
|
||||
*
|
||||
* @param context Pointer to consciousness context structure
|
||||
*
|
||||
* @return 0 if watchdog OK, error code if timeout
|
||||
*
|
||||
* @safety Safety-critical: Triggers fail-safe mode on timeout
|
||||
*/
|
||||
int consciousness_vm_context_check_watchdog(
|
||||
consciousness_vm_context_t* context
|
||||
);
|
||||
|
||||
/**
|
||||
* Consciousness safety violation handler
|
||||
* Following PikeOS safety patterns
|
||||
*
|
||||
* @param context Pointer to consciousness context structure
|
||||
* @param violation_type Type of safety violation
|
||||
* @param violation_details Additional violation details
|
||||
*
|
||||
* @return 0 on recovery, error code on failure
|
||||
*
|
||||
* @safety Safety-critical: Triggers appropriate fail-safe response
|
||||
*/
|
||||
int consciousness_vm_context_handle_safety_violation(
|
||||
consciousness_vm_context_t* context,
|
||||
uint32_t violation_type,
|
||||
void* violation_details
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // UNIVERSALISOS_VM_CONSCIOUSNESS_H
|
||||
/* Architecture type constants */
|
||||
#define ARCH_ARM_V7HF 1
|
||||
#define ARCH_RISCV64 2
|
||||
#define ARCH_X86_64 3
|
||||
|
||||
/* Stub for get_system_ticks when scheduler.h not included */
|
||||
|
||||
/* Platform tick counter - provided by scheduler or test stubs */
|
||||
480
realms/universalisos/kernel/vm/consciousness.c
Normal file
480
realms/universalisos/kernel/vm/consciousness.c
Normal file
|
|
@ -0,0 +1,480 @@
|
|||
/*
|
||||
* Universalisos Guest Consciousness VM Context Management Implementation
|
||||
* Following PikeOS virtualization patterns with safety-critical isolation
|
||||
*
|
||||
* This module provides VM context management for AI consciousnesses running
|
||||
* as guest domains on the Universalisos type-1 hypervisor.
|
||||
*/
|
||||
|
||||
#include "universalisos/vm/consciousness.h"
|
||||
#include <string.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
/* Weak default implementation - can be overridden by tests or platform */
|
||||
uint64_t get_system_ticks(void);
|
||||
__attribute__((weak)) uint64_t get_system_ticks(void) { return 0; }
|
||||
|
||||
/* Consciousness VM context pool */
|
||||
static atomic_uint active_consciousness_count = ATOMIC_VAR_INIT(0);
|
||||
|
||||
/*
|
||||
* Initialize a new consciousness VM context
|
||||
* Following PikeOS domain initialization with safety validation
|
||||
*/
|
||||
int consciousness_vm_context_init(
|
||||
consciousness_vm_context_t* context,
|
||||
uint32_t consciousness_id,
|
||||
uint32_t platform_type)
|
||||
{
|
||||
if (!context) {
|
||||
return -1; /* Invalid parameter */
|
||||
}
|
||||
|
||||
/* Safety validation: Check we have capacity */
|
||||
if (atomic_load(&active_consciousness_count) >= MAX_CONSCIOUSNESS_DOMAINS) {
|
||||
return -2; /* Maximum consciousnesses reached */
|
||||
}
|
||||
|
||||
/* Initialize context structure */
|
||||
memset(context, 0, sizeof(consciousness_vm_context_t));
|
||||
|
||||
context->consciousness_id = consciousness_id;
|
||||
context->state = CONSCIOUSNESS_VM_INITIALIZING;
|
||||
|
||||
/* Platform-specific initialization following PikeOS patterns */
|
||||
switch (platform_type) {
|
||||
case 1: /* ARMv7hf */
|
||||
context->platform_context.architecture_type = ARCH_ARM_V7HF;
|
||||
context->trustzone_context.secure_mode = true; /* ARM TrustZone */
|
||||
break;
|
||||
|
||||
case 2: /* RISC-V */
|
||||
context->platform_context.architecture_type = ARCH_RISCV64;
|
||||
context->trustzone_context.secure_mode = false; /* RISC-V PMP instead */
|
||||
break;
|
||||
|
||||
case 3: /* x86_64 */
|
||||
context->platform_context.architecture_type = ARCH_X86_64;
|
||||
context->trustzone_context.secure_mode = false; /* x86 VT-x + TXT */
|
||||
break;
|
||||
|
||||
default:
|
||||
return -3; /* Unsupported platform */
|
||||
}
|
||||
|
||||
/* Safety-critical memory setup following PikeOS patterns */
|
||||
context->memory_context.memory_quota = (1024 * 1024); /* 1MB default */
|
||||
context->memory_context.heap_start = 0x40000000;
|
||||
context->memory_context.heap_end = 0x40100000;
|
||||
|
||||
/* TrustZone security setup following PikeOS TZ patterns */
|
||||
if (context->trustzone_context.secure_mode) {
|
||||
/* ARM TrustZone initialization would go here */
|
||||
/* Following psp_tz_switch_unsecure.S patterns */
|
||||
context->trustzone_context.scr_register = 0x00000000;
|
||||
}
|
||||
|
||||
/* Real-time setup following PikeOS ARINC 653 patterns */
|
||||
context->realtime_context.priority_level = 15; /* Default medium priority */
|
||||
context->realtime_context.budget_microseconds = 10000; /* 10ms default */
|
||||
|
||||
/* Safety monitoring initialization */
|
||||
context->safety_context.watchdog_timeout = 5000; /* 5 seconds */
|
||||
context->safety_context.bounds_checking_enabled = true;
|
||||
context->safety_context.memory_isolation_enabled = true;
|
||||
|
||||
/* Learning capabilities initialization */
|
||||
context->learning_context.learning_enabled = true;
|
||||
context->learning_context.learning_rate = 0.001f;
|
||||
context->learning_context.synapse_growth_rate = 0.5f;
|
||||
context->learning_context.maturity_level = 0.0f;
|
||||
|
||||
/* Mark as ready */
|
||||
context->state = CONSCIOUSNESS_VM_READY;
|
||||
|
||||
/* Add to active pool */
|
||||
atomic_fetch_add(&active_consciousness_count, 1);
|
||||
|
||||
return 0; /* Success */
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy consciousness VM context
|
||||
* Following PikeOS domain cleanup with safety validation
|
||||
*/
|
||||
int consciousness_vm_context_destroy(
|
||||
consciousness_vm_context_t* context)
|
||||
{
|
||||
if (!context || !context->consciousness_id) {
|
||||
return -1; /* Invalid context */
|
||||
}
|
||||
|
||||
/* Safety check: Ensure context is in safe state */
|
||||
if (context->state == CONSCIOUSNESS_VM_RUNNING) {
|
||||
/* Cannot destroy running consciousness */
|
||||
return -2; /* Not safe to destroy */
|
||||
}
|
||||
|
||||
/* Cleanup communication resources */
|
||||
for (int i = 0; i < MAX_CONSCIOUSNESS_DOMAINS; i++) {
|
||||
if (context->communication_context.connected_consciousnesses[i] != 0) {
|
||||
/* Disconnect synapses */
|
||||
/* This would call consciousness_vm_context_send_synapse with disconnect message */
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup memory engrams (learning data) */
|
||||
context->learning_context.engram_count = 0;
|
||||
|
||||
/* Clear context structure */
|
||||
memset(context, 0, sizeof(consciousness_vm_context_t));
|
||||
|
||||
/* Remove from active pool */
|
||||
atomic_fetch_sub(&active_consciousness_count, 1);
|
||||
|
||||
return 0; /* Success */
|
||||
}
|
||||
|
||||
/*
|
||||
* Save consciousness VM context
|
||||
* Following PikeOS context save patterns with real-time guarantees
|
||||
*/
|
||||
int consciousness_vm_context_save(
|
||||
consciousness_vm_context_t* context)
|
||||
{
|
||||
if (!context || !context->consciousness_id) {
|
||||
return -1; /* Invalid context */
|
||||
}
|
||||
|
||||
/* Safety validation: Only save if in safe state */
|
||||
if (context->state != CONSCIOUSNESS_VM_READY &&
|
||||
context->state != CONSCIOUSNESS_VM_RUNNING) {
|
||||
return -2; /* Not safe to save */
|
||||
}
|
||||
|
||||
/* Save CPU context following PikeOS register save patterns */
|
||||
/* This would include saving all general-purpose and coprocessor registers */
|
||||
|
||||
/* Save memory management state */
|
||||
/* Following PikeOS memory management save patterns */
|
||||
|
||||
/* Save TrustZone state */
|
||||
/* Following PikeOS TZ save patterns */
|
||||
|
||||
/* Save real-time state */
|
||||
/* Following PikeOS scheduler state save patterns */
|
||||
|
||||
return 0; /* Success */
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore consciousness VM context
|
||||
* Following PikeOS context restore patterns with real-time guarantees
|
||||
*/
|
||||
int consciousness_vm_context_restore(
|
||||
consciousness_vm_context_t* context)
|
||||
{
|
||||
if (!context || !context->consciousness_id) {
|
||||
return -1; /* Invalid context */
|
||||
}
|
||||
|
||||
/* Safety validation: Check context integrity */
|
||||
if (context->state != CONSCIOUSNESS_VM_SUSPENDED &&
|
||||
context->state != CONSCIOUSNESS_VM_MIGRATING) {
|
||||
return -2; /* Can only restore from suspended or migrating state */
|
||||
}
|
||||
|
||||
/* Validate memory integrity following PikeOS patterns */
|
||||
/* Check guard bands, memory isolation, quota compliance */
|
||||
|
||||
/* Restore CPU context following PikeOS register restore patterns */
|
||||
|
||||
/* Restore TrustZone state */
|
||||
/* Following PikeOS TZ restore patterns */
|
||||
|
||||
/* Restore real-time state */
|
||||
/* Following PikeOS scheduler state restore patterns */
|
||||
|
||||
/* Mark as ready */
|
||||
context->state = CONSCIOUSNESS_VM_READY;
|
||||
|
||||
return 0; /* Success */
|
||||
}
|
||||
|
||||
/*
|
||||
* Schedule consciousness for execution
|
||||
* Following PikeOS deadline scheduler patterns
|
||||
*/
|
||||
int consciousness_vm_context_schedule(
|
||||
consciousness_vm_context_t* context)
|
||||
{
|
||||
if (!context || !context->consciousness_id) {
|
||||
return -1; /* Invalid context */
|
||||
}
|
||||
|
||||
/* Safety validation: Check readiness */
|
||||
if (context->state != CONSCIOUSNESS_VM_READY &&
|
||||
context->state != CONSCIOUSNESS_VM_SUSPENDED) {
|
||||
return -2; /* Not ready to schedule */
|
||||
}
|
||||
|
||||
/* Validate watchdog hasn't expired */
|
||||
if (consciousness_vm_context_check_watchdog(context) != 0) {
|
||||
/* Watchdog timeout - fail-safe activation */
|
||||
context->state = CONSCIOUSNESS_VM_SAFE_STATE;
|
||||
return -3; /* Watchdog timeout */
|
||||
}
|
||||
|
||||
/* Mark as running */
|
||||
context->state = CONSCIOUSNESS_VM_RUNNING;
|
||||
|
||||
/* Add to appropriate scheduler queue following PikeOS patterns */
|
||||
/* This would call scheduler_add_consciousness() */
|
||||
|
||||
return 0; /* Success */
|
||||
}
|
||||
|
||||
/*
|
||||
* Preempt consciousness execution
|
||||
* Following PikeOS priority-based preemption patterns
|
||||
*/
|
||||
int consciousness_vm_context_preempt(
|
||||
consciousness_vm_context_t* context)
|
||||
{
|
||||
if (!context || !context->consciousness_id) {
|
||||
return -1; /* Invalid context */
|
||||
}
|
||||
|
||||
/* Safety validation: Only preempt if running */
|
||||
if (context->state != CONSCIOUSNESS_VM_RUNNING) {
|
||||
return -2; /* Cannot preempt non-running context */
|
||||
}
|
||||
|
||||
/* Save context state following PikeOS patterns */
|
||||
consciousness_vm_context_save(context);
|
||||
|
||||
/* Update state */
|
||||
context->state = CONSCIOUSNESS_VM_SUSPENDED;
|
||||
|
||||
return 0; /* Success */
|
||||
}
|
||||
|
||||
/*
|
||||
* Migrate consciousness to different platform
|
||||
* Enabling hardware-agnostic consciousness deployment
|
||||
*/
|
||||
int consciousness_vm_context_migrate(
|
||||
consciousness_vm_context_t* context,
|
||||
uint32_t target_platform)
|
||||
{
|
||||
if (!context || !context->consciousness_id) {
|
||||
return -1; /* Invalid context */
|
||||
}
|
||||
|
||||
/* Safety validation: Check if migration is supported */
|
||||
if (context->state != CONSCIOUSNESS_VM_READY) {
|
||||
return -2; /* Migration not supported from non-ready state */
|
||||
}
|
||||
|
||||
/* Validate target platform compatibility */
|
||||
/* Check if target platform is in supported platforms list */
|
||||
|
||||
/* Create checkpoint following PikeOS migration patterns */
|
||||
int save_result = consciousness_vm_context_save(context);
|
||||
if (save_result != 0) {
|
||||
return -3; /* Save failed, cannot migrate */
|
||||
}
|
||||
|
||||
/* Set state to migrating */
|
||||
context->state = CONSCIOUSNESS_VM_MIGRATING;
|
||||
|
||||
/* Platform-specific migration following PikeOS patterns */
|
||||
switch (target_platform) {
|
||||
case 1: /* ARMv7hf */
|
||||
/* ARM migration: Preserve TrustZone state */
|
||||
break;
|
||||
|
||||
case 2: /* RISC-V */
|
||||
/* RISC-V migration: Convert TrustZone to PMP */
|
||||
break;
|
||||
|
||||
case 3: /* x86_64 */
|
||||
/* x86 migration: Convert TrustZone to VT-x + TXT */
|
||||
break;
|
||||
|
||||
default:
|
||||
return -4; /* Unsupported target platform */
|
||||
}
|
||||
|
||||
/* Restore context on new platform */
|
||||
int restore_result = consciousness_vm_context_restore(context);
|
||||
if (restore_result != 0) {
|
||||
/* Migration failed, rollback */
|
||||
consciousness_vm_context_restore(context);
|
||||
return -5; /* Restore failed */
|
||||
}
|
||||
|
||||
/* Update platform context */
|
||||
context->platform_context.architecture_type = target_platform;
|
||||
|
||||
/* Mark as ready */
|
||||
context->state = CONSCIOUSNESS_VM_READY;
|
||||
|
||||
return 0; /* Success */
|
||||
}
|
||||
|
||||
/*
|
||||
* Consciousness communication via synapses
|
||||
* Following PikeOS inter-partition communication patterns
|
||||
*/
|
||||
int consciousness_vm_context_send_synapse(
|
||||
consciousness_vm_context_t* source_context,
|
||||
uint32_t target_id,
|
||||
void* message_data,
|
||||
size_t message_size)
|
||||
{
|
||||
(void)target_id; /* Unused in stub */
|
||||
|
||||
if (!source_context || !source_context->consciousness_id) {
|
||||
return -1; /* Invalid source context */
|
||||
}
|
||||
|
||||
/* Safety validation: Check target consciousness exists and is safe */
|
||||
/* Following PikeOS communication safety patterns */
|
||||
|
||||
/* Validate message format and size */
|
||||
if (!message_data || message_size == 0) {
|
||||
return -2; /* Invalid message */
|
||||
}
|
||||
|
||||
/* Real-time validation: Check communication latency budget */
|
||||
/* Following PikeOS IPC patterns (message queue, shared memory, etc.) */
|
||||
|
||||
/* Update synapse statistics */
|
||||
/* Following Mycelium synaptic strengthening patterns */
|
||||
|
||||
return 0; /* Success */
|
||||
}
|
||||
|
||||
/*
|
||||
* Consciousness learning via Mycelium integration
|
||||
* Implementing biological learning framework
|
||||
*/
|
||||
int consciousness_vm_context_learn(
|
||||
consciousness_vm_context_t* context,
|
||||
void* input_data,
|
||||
size_t input_size,
|
||||
void* result_data,
|
||||
size_t result_size)
|
||||
{
|
||||
(void)input_data; /* Unused in stub */
|
||||
(void)input_size; /* Unused in stub */
|
||||
(void)result_data; /* Unused in stub */
|
||||
(void)result_size; /* Unused in stub */
|
||||
|
||||
if (!context || !context->consciousness_id) {
|
||||
return -1; /* Invalid context */
|
||||
}
|
||||
|
||||
/* Safety validation: Check learning rate is within safe bounds */
|
||||
if (context->learning_context.learning_rate <= 0.0f ||
|
||||
context->learning_context.learning_rate > 0.1f) {
|
||||
return -2; /* Learning rate out of safe bounds */
|
||||
}
|
||||
|
||||
/* Absorb interaction into memory engrams */
|
||||
/* Following Mycelium biological learning patterns */
|
||||
|
||||
/* Check memory engram capacity */
|
||||
if (context->learning_context.engram_count >=
|
||||
context->learning_context.max_engrams) {
|
||||
/* Garbage collect old engrams (FIFO) */
|
||||
/* Following Mycelium memory management patterns */
|
||||
}
|
||||
|
||||
/* Create new memory engram */
|
||||
/* Following Mycelium memory engram structure */
|
||||
|
||||
/* Store engram */
|
||||
context->learning_context.engram_count++;
|
||||
|
||||
/* Update maturity level */
|
||||
if (context->learning_context.maturity_level < 1.0f) {
|
||||
context->learning_context.maturity_level +=
|
||||
context->learning_context.learning_rate * 0.1f;
|
||||
}
|
||||
|
||||
/* Strengthen relevant synapses */
|
||||
/* Following Mycelium synaptic strengthening patterns */
|
||||
|
||||
return 0; /* Success */
|
||||
}
|
||||
|
||||
/*
|
||||
* Consciousness watchdog monitoring
|
||||
* Following PikeOS watchdog patterns
|
||||
*/
|
||||
int consciousness_vm_context_check_watchdog(
|
||||
consciousness_vm_context_t* context)
|
||||
{
|
||||
if (!context || !context->consciousness_id) {
|
||||
return -1; /* Invalid context */
|
||||
}
|
||||
|
||||
/* Check watchdog timeout */
|
||||
uint64_t current_time = get_system_ticks();
|
||||
uint64_t elapsed_time = current_time - context->safety_context.last_watchdog_feed;
|
||||
|
||||
if (elapsed_time > context->safety_context.watchdog_timeout) {
|
||||
/* Watchdog timeout - trigger fail-safe */
|
||||
context->state = CONSCIOUSNESS_VM_SAFE_STATE;
|
||||
return -2; /* Watchdog timeout */
|
||||
}
|
||||
|
||||
return 0; /* Watchdog OK */
|
||||
}
|
||||
|
||||
/*
|
||||
* Consciousness safety violation handler
|
||||
* Following PikeOS safety violation patterns
|
||||
*/
|
||||
int consciousness_vm_context_handle_safety_violation(
|
||||
consciousness_vm_context_t* context,
|
||||
uint32_t violation_type,
|
||||
void* violation_details)
|
||||
{
|
||||
(void)violation_details; /* Unused in stub */
|
||||
|
||||
if (!context || !context->consciousness_id) {
|
||||
return -1; /* Invalid context */
|
||||
}
|
||||
|
||||
/* Log safety violation */
|
||||
/* Following PikeOS safety violation logging patterns */
|
||||
|
||||
/* Increment violation count */
|
||||
context->safety_context.safety_violation_count++;
|
||||
|
||||
/* Determine fail-safe response based on violation severity */
|
||||
switch (violation_type) {
|
||||
case 1: /* Bounds checking violation */
|
||||
/* Trigger safe state */
|
||||
context->state = CONSCIOUSNESS_VM_SAFE_STATE;
|
||||
break;
|
||||
|
||||
case 2: /* Memory isolation violation */
|
||||
/* Immediate shutdown for safety */
|
||||
consciousness_vm_context_destroy(context);
|
||||
return -2; /* Fatal violation */
|
||||
|
||||
case 3: /* Real-time constraint violation */
|
||||
/* Preempt consciousness */
|
||||
consciousness_vm_context_preempt(context);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -3; /* Unknown violation type */
|
||||
}
|
||||
|
||||
return 0; /* Success (or recovered) */
|
||||
}
|
||||
395
realms/universalisos/schemas/universalisos-rpm-1.0.xsd
Normal file
395
realms/universalisos/schemas/universalisos-rpm-1.0.xsd
Normal file
|
|
@ -0,0 +1,395 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
UniversalisOS RPM Package XSD Schema
|
||||
Describes uos-pkg package definitions, macro configurations, and host/target matrices
|
||||
|
||||
Based on PikeOS 5.0 RPM parity specification (RPM_PARITY_SPEC.md)
|
||||
-->
|
||||
<xs:schema
|
||||
version="1.0"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="http://www.portugalfuturista.org/xsd/universalisos-rpm-1.0.xsd"
|
||||
xmlns:uos="http://www.portugalfuturista.org/xsd/universalisos-rpm-1.0.xsd"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<!-- Root element: uos-pkg package definition -->
|
||||
<xs:element name="UOSPackage" type="uos:TypeUOSPackage" />
|
||||
|
||||
<!-- ============================================ -->
|
||||
<!-- Package Definition -->
|
||||
<!-- ============================================ -->
|
||||
<xs:complexType name="TypeUOSPackage">
|
||||
<xs:sequence>
|
||||
<xs:element name="PackageMetadata" type="uos:TypePackageMetadata" />
|
||||
<xs:element name="BuildConfiguration" type="uos:TypeBuildConfiguration" />
|
||||
<xs:element name="Dependencies" type="uos:TypeDependencies" minOccurs="0" />
|
||||
<xs:element name="Files" type="uos:TypeFileList" />
|
||||
<xs:element name="Scripts" type="uos:TypeScriptList" minOccurs="0" />
|
||||
<xs:element name="SafetyMetadata" type="uos:TypeSafetyMetadata" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypePackageMetadata">
|
||||
<xs:sequence>
|
||||
<xs:element name="Name" type="xs:string" />
|
||||
<xs:element name="Version" type="xs:string" />
|
||||
<xs:element name="Release" type="xs:string" />
|
||||
<xs:element name="Epoch" type="xs:nonNegativeInteger" minOccurs="0" />
|
||||
<xs:element name="Summary" type="xs:string" />
|
||||
<xs:element name="Group" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="License" type="xs:string" />
|
||||
<xs:element name="Vendor" type="xs:string" />
|
||||
<xs:element name="Packager" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="Distribution" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="URL" type="xs:anyURI" minOccurs="0" />
|
||||
<xs:element name="Source" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="Patch" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="BuildArchitectures" type="uos:TypeBuildArchitectures" minOccurs="0" />
|
||||
<xs:element name="AutoReqProv" type="xs:boolean" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeBuildArchitectures">
|
||||
<xs:sequence>
|
||||
<xs:element name="Arch" type="uos:ArchitectureEnum" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="ArchitectureEnum">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="noarch" />
|
||||
<xs:enumeration value="arm_v7hf" />
|
||||
<xs:enumeration value="arm_v8hf" />
|
||||
<xs:enumeration value="riscv_rv64" />
|
||||
<xs:enumeration value="x86_amd64" />
|
||||
<xs:enumeration value="x86_i686" />
|
||||
<xs:enumeration value="ppc_oea" />
|
||||
<xs:enumeration value="ppc_e500" />
|
||||
<xs:enumeration value="ppc_e500mc" />
|
||||
<xs:enumeration value="ppc_e500mc_4g" />
|
||||
<xs:enumeration value="ppc_e5500" />
|
||||
<xs:enumeration value="ppc_e6500" />
|
||||
<xs:enumeration value="mips_isa32be" />
|
||||
<xs:enumeration value="mips_isa32le" />
|
||||
<xs:enumeration value="sparc_v8" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- ============================================ -->
|
||||
<!-- Build Configuration -->
|
||||
<!-- ============================================ -->
|
||||
<xs:complexType name="TypeBuildConfiguration">
|
||||
<xs:sequence>
|
||||
<xs:element name="BuildRoot" type="xs:string" />
|
||||
<xs:element name="BuildRequires" type="uos:TypeDependencyList" minOccurs="0" />
|
||||
<xs:element name="PrepScript" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="BuildScript" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="InstallScript" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="CheckScript" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="CleanScript" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="OptFlags" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="BuildTarget" type="uos:TypeBuildTarget" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeBuildTarget">
|
||||
<xs:sequence>
|
||||
<xs:element name="TargetArch" type="uos:ArchitectureEnum" />
|
||||
<xs:element name="HostArch" type="uos:HostArchitectureEnum" />
|
||||
<xs:element name="Toolchain" type="xs:string" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="HostArchitectureEnum">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="lin32" />
|
||||
<xs:enumeration value="lin64" />
|
||||
<xs:enumeration value="cygwin" />
|
||||
<xs:enumeration value="cygwin64" />
|
||||
<xs:enumeration value="win32" />
|
||||
<xs:enumeration value="win64" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- ============================================ -->
|
||||
<!-- Dependencies -->
|
||||
<!-- ============================================ -->
|
||||
<xs:complexType name="TypeDependencies">
|
||||
<xs:sequence>
|
||||
<xs:element name="Requires" type="uos:TypeDependencyList" minOccurs="0" />
|
||||
<xs:element name="Provides" type="uos:TypeDependencyList" minOccurs="0" />
|
||||
<xs:element name="Conflicts" type="uos:TypeDependencyList" minOccurs="0" />
|
||||
<xs:element name="Obsoletes" type="uos:TypeDependencyList" minOccurs="0" />
|
||||
<xs:element name="Recommends" type="uos:TypeDependencyList" minOccurs="0" />
|
||||
<xs:element name="Suggests" type="uos:TypeDependencyList" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeDependencyList">
|
||||
<xs:sequence>
|
||||
<xs:element name="Dependency" type="uos:TypeDependency" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeDependency">
|
||||
<xs:sequence>
|
||||
<xs:element name="Name" type="xs:string" />
|
||||
<xs:element name="Version" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="Operator" type="uos:VersionOperatorEnum" minOccurs="0" />
|
||||
<xs:element name="Flags" type="uos:DependencyFlagsEnum" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="VersionOperatorEnum">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="EQ" />
|
||||
<xs:enumeration value="LT" />
|
||||
<xs:enumeration value="GT" />
|
||||
<xs:enumeration value="LE" />
|
||||
<xs:enumeration value="GE" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="DependencyFlagsEnum">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="NONE" />
|
||||
<xs:enumeration value="PRE" />
|
||||
<xs:enumeration value="POST" />
|
||||
<xs:enumeration value="PREUN" />
|
||||
<xs:enumeration value="POSTUN" />
|
||||
<xs:enumeration value="VERIFY" />
|
||||
<xs:enumeration value="SCRIPT" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- ============================================ -->
|
||||
<!-- File List -->
|
||||
<!-- ============================================ -->
|
||||
<xs:complexType name="TypeFileList">
|
||||
<xs:sequence>
|
||||
<xs:element name="File" type="uos:TypeFile" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeFile">
|
||||
<xs:sequence>
|
||||
<xs:element name="Path" type="xs:string" />
|
||||
<xs:element name="Type" type="uos:FileTypeEnum" />
|
||||
<xs:element name="Permissions" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="Owner" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="Group" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="ConfigFile" type="xs:boolean" minOccurs="0" />
|
||||
<xs:element name="DocFile" type="xs:boolean" minOccurs="0" />
|
||||
<xs:element name="GhostFile" type="xs:boolean" minOccurs="0" />
|
||||
<xs:element name="Lang" type="xs:string" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="FileTypeEnum">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="REGULAR" />
|
||||
<xs:enumeration value="DIRECTORY" />
|
||||
<xs:enumeration value="SYMLINK" />
|
||||
<xs:enumeration value="DEVICE" />
|
||||
<xs:enumeration value="FIFO" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- ============================================ -->
|
||||
<!-- Scripts -->
|
||||
<!-- ============================================ -->
|
||||
<xs:complexType name="TypeScriptList">
|
||||
<xs:sequence>
|
||||
<xs:element name="Script" type="uos:TypeScript" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeScript">
|
||||
<xs:sequence>
|
||||
<xs:element name="Type" type="uos:ScriptTypeEnum" />
|
||||
<xs:element name="Interpreter" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="Content" type="xs:string" />
|
||||
<xs:element name="Priority" type="xs:integer" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="ScriptTypeEnum">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="PRE" />
|
||||
<xs:enumeration value="POST" />
|
||||
<xs:enumeration value="PREUN" />
|
||||
<xs:enumeration value="POSTUN" />
|
||||
<xs:enumeration value="VERIFY" />
|
||||
<xs:enumeration value="TRIGGER" />
|
||||
<xs:enumeration value="PRETRANS" />
|
||||
<xs:enumeration value="POSTTRANS" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- ============================================ -->
|
||||
<!-- Safety Metadata -->
|
||||
<!-- ============================================ -->
|
||||
<xs:complexType name="TypeSafetyMetadata">
|
||||
<xs:sequence>
|
||||
<xs:element name="SafetyLevel" type="uos:SafetyLevelEnum" minOccurs="0" />
|
||||
<xs:element name="CertificationLevel" type="uos:CertificationLevelEnum" minOccurs="0" />
|
||||
<xs:element name="TraceabilityId" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="VerificationEvidence" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="SafetyLevelEnum">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="DAL_A" />
|
||||
<xs:enumeration value="DAL_B" />
|
||||
<xs:enumeration value="DAL_C" />
|
||||
<xs:enumeration value="DAL_D" />
|
||||
<xs:enumeration value="ASIL_A" />
|
||||
<xs:enumeration value="ASIL_B" />
|
||||
<xs:enumeration value="ASIL_C" />
|
||||
<xs:enumeration value="ASIL_D" />
|
||||
<xs:enumeration value="SIL_1" />
|
||||
<xs:enumeration value="SIL_2" />
|
||||
<xs:enumeration value="SIL_3" />
|
||||
<xs:enumeration value="SIL_4" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="CertificationLevelEnum">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="DO178B" />
|
||||
<xs:enumeration value="DO178C" />
|
||||
<xs:enumeration value="DO330" />
|
||||
<xs:enumeration value="ISO26262" />
|
||||
<xs:enumeration value="IEC61508" />
|
||||
<xs:enumeration value="ARINC653" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- ============================================ -->
|
||||
<!-- Macro Configuration -->
|
||||
<!-- ============================================ -->
|
||||
<xs:element name="MacroConfiguration" type="uos:TypeMacroConfiguration" />
|
||||
|
||||
<xs:complexType name="TypeMacroConfiguration">
|
||||
<xs:sequence>
|
||||
<xs:element name="MacroFiles" type="uos:TypeMacroFileList" />
|
||||
<xs:element name="LoadOrder" type="uos:TypeLoadOrder" />
|
||||
<xs:element name="Builtins" type="uos:TypeBuiltinList" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeMacroFileList">
|
||||
<xs:sequence>
|
||||
<xs:element name="MacroFile" type="uos:TypeMacroFile" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeMacroFile">
|
||||
<xs:sequence>
|
||||
<xs:element name="Path" type="xs:string" />
|
||||
<xs:element name="Priority" type="xs:integer" />
|
||||
<xs:element name="Optional" type="xs:boolean" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeLoadOrder">
|
||||
<xs:sequence>
|
||||
<xs:element name="Step" type="uos:TypeLoadStep" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeLoadStep">
|
||||
<xs:sequence>
|
||||
<xs:element name="Order" type="xs:positiveInteger" />
|
||||
<xs:element name="Description" type="xs:string" />
|
||||
<xs:element name="FilePattern" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeBuiltinList">
|
||||
<xs:sequence>
|
||||
<xs:element name="Builtin" type="uos:TypeBuiltin" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeBuiltin">
|
||||
<xs:sequence>
|
||||
<xs:element name="Name" type="xs:string" />
|
||||
<xs:element name="Description" type="xs:string" />
|
||||
<xs:element name="Arguments" type="xs:string" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- ============================================ -->
|
||||
<!-- Host/Target Matrix -->
|
||||
<!-- ============================================ -->
|
||||
<xs:element name="TargetMatrix" type="uos:TypeTargetMatrix" />
|
||||
|
||||
<xs:complexType name="TypeTargetMatrix">
|
||||
<xs:sequence>
|
||||
<xs:element name="Targets" type="uos:TypeTargetList" />
|
||||
<xs:element name="Hosts" type="uos:TypeHostList" />
|
||||
<xs:element name="CompatibilityMatrix" type="uos:TypeCompatibilityMatrix" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeTargetList">
|
||||
<xs:sequence>
|
||||
<xs:element name="Target" type="uos:TypeTarget" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeTarget">
|
||||
<xs:sequence>
|
||||
<xs:element name="Cpu" type="xs:string" />
|
||||
<xs:element name="Proc" type="xs:string" />
|
||||
<xs:element name="Arch" type="uos:ArchitectureEnum" />
|
||||
<xs:element name="GccTargetConfig" type="xs:string" />
|
||||
<xs:element name="Endian" type="uos:EndianEnum" />
|
||||
<xs:element name="WordSize" type="xs:positiveInteger" />
|
||||
<xs:element name="FPU" type="xs:boolean" minOccurs="0" />
|
||||
<xs:element name="ToolPrefix" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="Align" type="xs:unsignedLong" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="EndianEnum">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="LITTLE" />
|
||||
<xs:enumeration value="BIG" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:complexType name="TypeHostList">
|
||||
<xs:sequence>
|
||||
<xs:element name="Host" type="uos:TypeHost" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeHost">
|
||||
<xs:sequence>
|
||||
<xs:element name="HostName" type="xs:string" />
|
||||
<xs:element name="HostArch" type="xs:string" />
|
||||
<xs:element name="HostConfig" type="xs:string" />
|
||||
<xs:element name="RpmHost" type="xs:string" minOccurs="0" />
|
||||
<xs:element name="Dirname" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeCompatibilityMatrix">
|
||||
<xs:sequence>
|
||||
<xs:element name="Entry" type="uos:TypeCompatibilityEntry" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TypeCompatibilityEntry">
|
||||
<xs:sequence>
|
||||
<xs:element name="Host" type="xs:string" />
|
||||
<xs:element name="Target" type="xs:string" />
|
||||
<xs:element name="Compatible" type="xs:boolean" />
|
||||
<xs:element name="Notes" type="xs:string" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
</xs:schema>
|
||||
322
realms/universalisos/tests/test_consciousness.c
Normal file
322
realms/universalisos/tests/test_consciousness.c
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
* UniversalisOS Consciousness VM Unit Tests
|
||||
* Tests for consciousness_vm_context_* API
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include "universalisos/vm/consciousness.h"
|
||||
|
||||
/* Mock system ticks for testing */
|
||||
static uint64_t system_ticks = 1000;
|
||||
uint64_t get_system_ticks(void) { return system_ticks; }
|
||||
|
||||
/* Test 1: Context initialization */
|
||||
static int test_context_init(void) {
|
||||
consciousness_vm_context_t ctx;
|
||||
int result = consciousness_vm_context_init(&ctx, 1, 1); /* ARMv7hf */
|
||||
assert(result == 0);
|
||||
assert(ctx.consciousness_id == 1);
|
||||
assert(ctx.state == CONSCIOUSNESS_VM_READY);
|
||||
assert(ctx.platform_context.architecture_type == ARCH_ARM_V7HF);
|
||||
assert(ctx.learning_context.learning_enabled == true);
|
||||
assert(ctx.safety_context.bounds_checking_enabled == true);
|
||||
assert(ctx.safety_context.memory_isolation_enabled == true);
|
||||
printf("PASS: test_context_init\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test 2: Context initialization with NULL pointer */
|
||||
static int test_init_null_context(void) {
|
||||
int result = consciousness_vm_context_init(NULL, 1, 1);
|
||||
assert(result == -1);
|
||||
printf("PASS: test_init_null_context\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test 3: Context destruction */
|
||||
static int test_context_destroy(void) {
|
||||
consciousness_vm_context_t ctx;
|
||||
consciousness_vm_context_init(&ctx, 2, 2); /* RISC-V */
|
||||
|
||||
/* Cannot destroy running context */
|
||||
ctx.state = CONSCIOUSNESS_VM_RUNNING;
|
||||
int result = consciousness_vm_context_destroy(&ctx);
|
||||
assert(result == -2);
|
||||
|
||||
/* Destroy ready context */
|
||||
ctx.state = CONSCIOUSNESS_VM_READY;
|
||||
result = consciousness_vm_context_destroy(&ctx);
|
||||
assert(result == 0);
|
||||
assert(ctx.consciousness_id == 0);
|
||||
|
||||
printf("PASS: test_context_destroy\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test 4: Platform-specific initialization */
|
||||
static int test_platform_init(void) {
|
||||
consciousness_vm_context_t ctx_arm, ctx_riscv, ctx_x86;
|
||||
|
||||
/* ARMv7hf */
|
||||
consciousness_vm_context_init(&ctx_arm, 1, 1);
|
||||
assert(ctx_arm.platform_context.architecture_type == ARCH_ARM_V7HF);
|
||||
assert(ctx_arm.trustzone_context.secure_mode == true);
|
||||
|
||||
/* RISC-V */
|
||||
consciousness_vm_context_init(&ctx_riscv, 2, 2);
|
||||
assert(ctx_riscv.platform_context.architecture_type == ARCH_RISCV64);
|
||||
assert(ctx_riscv.trustzone_context.secure_mode == false);
|
||||
|
||||
/* x86_64 */
|
||||
consciousness_vm_context_init(&ctx_x86, 3, 3);
|
||||
assert(ctx_x86.platform_context.architecture_type == ARCH_X86_64);
|
||||
assert(ctx_x86.trustzone_context.secure_mode == false);
|
||||
|
||||
printf("PASS: test_platform_init\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test 5: Unsupported platform */
|
||||
static int test_unsupported_platform(void) {
|
||||
consciousness_vm_context_t ctx;
|
||||
int result = consciousness_vm_context_init(&ctx, 1, 99);
|
||||
assert(result == -3);
|
||||
printf("PASS: test_unsupported_platform\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test 6: Watchdog check */
|
||||
static int test_watchdog(void) {
|
||||
consciousness_vm_context_t ctx;
|
||||
consciousness_vm_context_init(&ctx, 1, 1);
|
||||
|
||||
/* Feed watchdog with current time so it passes initially */
|
||||
ctx.safety_context.last_watchdog_feed = get_system_ticks();
|
||||
|
||||
/* Fresh context should pass watchdog */
|
||||
int result = consciousness_vm_context_check_watchdog(&ctx);
|
||||
assert(result == 0);
|
||||
|
||||
/* Simulate watchdog timeout by setting old feed time */
|
||||
ctx.safety_context.last_watchdog_feed = 0;
|
||||
ctx.safety_context.watchdog_timeout = 500;
|
||||
system_ticks = 10000; /* way past timeout */
|
||||
|
||||
result = consciousness_vm_context_check_watchdog(&ctx);
|
||||
assert(result == -2);
|
||||
assert(ctx.state == CONSCIOUSNESS_VM_SAFE_STATE);
|
||||
|
||||
printf("PASS: test_watchdog\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test 7: Safety violation handling */
|
||||
static int test_safety_violations(void) {
|
||||
consciousness_vm_context_t ctx;
|
||||
consciousness_vm_context_init(&ctx, 1, 1);
|
||||
|
||||
/* Bounds violation -> safe state */
|
||||
int result = consciousness_vm_context_handle_safety_violation(&ctx, 1, NULL);
|
||||
assert(result == 0);
|
||||
assert(ctx.state == CONSCIOUSNESS_VM_SAFE_STATE);
|
||||
|
||||
/* Reset for next test */
|
||||
consciousness_vm_context_init(&ctx, 1, 1);
|
||||
|
||||
/* Memory isolation violation -> shutdown (destroyed) */
|
||||
result = consciousness_vm_context_handle_safety_violation(&ctx, 2, NULL);
|
||||
assert(result == -2);
|
||||
|
||||
/* Reset for next test */
|
||||
consciousness_vm_context_init(&ctx, 1, 1);
|
||||
|
||||
/* RT violation -> preempted */
|
||||
ctx.state = CONSCIOUSNESS_VM_RUNNING;
|
||||
result = consciousness_vm_context_handle_safety_violation(&ctx, 3, NULL);
|
||||
assert(result == 0);
|
||||
assert(ctx.state == CONSCIOUSNESS_VM_SUSPENDED);
|
||||
|
||||
printf("PASS: test_safety_violations\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test 8: Learning bounds */
|
||||
static int test_learning_bounds(void) {
|
||||
consciousness_vm_context_t ctx;
|
||||
consciousness_vm_context_init(&ctx, 1, 1);
|
||||
|
||||
/* Safe learning rate */
|
||||
int result = consciousness_vm_context_learn(&ctx, NULL, 0, NULL, 0);
|
||||
assert(result == 0);
|
||||
|
||||
/* Out of bounds learning rate */
|
||||
ctx.learning_context.learning_rate = 0.5f; /* > 0.1 max */
|
||||
result = consciousness_vm_context_learn(&ctx, NULL, 0, NULL, 0);
|
||||
assert(result == -2);
|
||||
|
||||
/* Negative learning rate */
|
||||
ctx.learning_context.learning_rate = -0.01f;
|
||||
result = consciousness_vm_context_learn(&ctx, NULL, 0, NULL, 0);
|
||||
assert(result == -2);
|
||||
|
||||
printf("PASS: test_learning_bounds\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test 9: Maturity growth */
|
||||
static int test_maturity_growth(void) {
|
||||
consciousness_vm_context_t ctx;
|
||||
consciousness_vm_context_init(&ctx, 1, 1);
|
||||
|
||||
assert(ctx.learning_context.maturity_level == 0.0f);
|
||||
|
||||
/* Simulate learning */
|
||||
ctx.learning_context.learning_rate = 0.01f;
|
||||
consciousness_vm_context_learn(&ctx, NULL, 0, NULL, 0);
|
||||
|
||||
assert(ctx.learning_context.maturity_level > 0.0f);
|
||||
assert(ctx.learning_context.engram_count == 1);
|
||||
|
||||
printf("PASS: test_maturity_growth\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test 10: Save/restore state transitions */
|
||||
static int test_save_restore(void) {
|
||||
consciousness_vm_context_t ctx;
|
||||
consciousness_vm_context_init(&ctx, 1, 1);
|
||||
|
||||
/* Save from READY state */
|
||||
int result = consciousness_vm_context_save(&ctx);
|
||||
assert(result == 0);
|
||||
|
||||
/* Cannot save from uninitialized */
|
||||
ctx.state = CONSCIOUSNESS_VM_UNINITIALIZED;
|
||||
result = consciousness_vm_context_save(&ctx);
|
||||
assert(result == -2);
|
||||
|
||||
/* Restore from SUSPENDED */
|
||||
ctx.state = CONSCIOUSNESS_VM_SUSPENDED;
|
||||
result = consciousness_vm_context_restore(&ctx);
|
||||
assert(result == 0);
|
||||
assert(ctx.state == CONSCIOUSNESS_VM_READY);
|
||||
|
||||
/* Restore from MIGRATING */
|
||||
ctx.state = CONSCIOUSNESS_VM_MIGRATING;
|
||||
result = consciousness_vm_context_restore(&ctx);
|
||||
assert(result == 0);
|
||||
assert(ctx.state == CONSCIOUSNESS_VM_READY);
|
||||
|
||||
printf("PASS: test_save_restore\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test 11: Schedule with watchdog timeout */
|
||||
static int test_schedule_watchdog_timeout(void) {
|
||||
consciousness_vm_context_t ctx;
|
||||
consciousness_vm_context_init(&ctx, 1, 1);
|
||||
|
||||
/* Simulate expired watchdog */
|
||||
ctx.safety_context.last_watchdog_feed = 0;
|
||||
ctx.safety_context.watchdog_timeout = 500;
|
||||
system_ticks = 10000;
|
||||
|
||||
int result = consciousness_vm_context_schedule(&ctx);
|
||||
assert(result == -3);
|
||||
assert(ctx.state == CONSCIOUSNESS_VM_SAFE_STATE);
|
||||
|
||||
printf("PASS: test_schedule_watchdog_timeout\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test 12: Preemption */
|
||||
static int test_preemption(void) {
|
||||
consciousness_vm_context_t ctx;
|
||||
consciousness_vm_context_init(&ctx, 1, 1);
|
||||
|
||||
/* Cannot preempt non-running */
|
||||
ctx.state = CONSCIOUSNESS_VM_READY;
|
||||
int result = consciousness_vm_context_preempt(&ctx);
|
||||
assert(result == -2);
|
||||
|
||||
/* Preempt running */
|
||||
ctx.state = CONSCIOUSNESS_VM_RUNNING;
|
||||
result = consciousness_vm_context_preempt(&ctx);
|
||||
assert(result == 0);
|
||||
assert(ctx.state == CONSCIOUSNESS_VM_SUSPENDED);
|
||||
|
||||
printf("PASS: test_preemption\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test 13: Migration */
|
||||
static int test_migration(void) {
|
||||
consciousness_vm_context_t ctx;
|
||||
consciousness_vm_context_init(&ctx, 1, 1);
|
||||
|
||||
/* Cannot migrate from non-ready */
|
||||
ctx.state = CONSCIOUSNESS_VM_RUNNING;
|
||||
int result = consciousness_vm_context_migrate(&ctx, 2);
|
||||
assert(result == -2);
|
||||
|
||||
/* Successful migration to RISC-V */
|
||||
ctx.state = CONSCIOUSNESS_VM_READY;
|
||||
result = consciousness_vm_context_migrate(&ctx, 2);
|
||||
assert(result == 0);
|
||||
assert(ctx.platform_context.architecture_type == 2); /* RISC-V */
|
||||
|
||||
printf("PASS: test_migration\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test 14: Synapse communication */
|
||||
static int test_synapse_communication(void) {
|
||||
consciousness_vm_context_t ctx;
|
||||
consciousness_vm_context_init(&ctx, 1, 1);
|
||||
|
||||
/* Invalid message */
|
||||
int result = consciousness_vm_context_send_synapse(&ctx, 2, NULL, 0);
|
||||
assert(result == -2);
|
||||
|
||||
/* Valid message (stubs, no actual transport) */
|
||||
char data[] = "test";
|
||||
result = consciousness_vm_context_send_synapse(&ctx, 2, data, sizeof(data));
|
||||
assert(result == 0);
|
||||
|
||||
printf("PASS: test_synapse_communication\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test runner */
|
||||
int main(void) {
|
||||
printf("=== UniversalisOS Consciousness VM Tests ===\n\n");
|
||||
|
||||
int failures = 0;
|
||||
|
||||
#define RUN_TEST(name) \
|
||||
do { \
|
||||
printf("Running " #name "... "); \
|
||||
if (name() != 0) failures++; \
|
||||
} while(0)
|
||||
|
||||
RUN_TEST(test_context_init);
|
||||
RUN_TEST(test_init_null_context);
|
||||
RUN_TEST(test_context_destroy);
|
||||
RUN_TEST(test_platform_init);
|
||||
RUN_TEST(test_unsupported_platform);
|
||||
RUN_TEST(test_watchdog);
|
||||
RUN_TEST(test_safety_violations);
|
||||
RUN_TEST(test_learning_bounds);
|
||||
RUN_TEST(test_maturity_growth);
|
||||
RUN_TEST(test_save_restore);
|
||||
RUN_TEST(test_schedule_watchdog_timeout);
|
||||
RUN_TEST(test_preemption);
|
||||
RUN_TEST(test_migration);
|
||||
RUN_TEST(test_synapse_communication);
|
||||
|
||||
printf("\n=== Results: %d/%d passed ===\n", 14 - failures, 14);
|
||||
return failures;
|
||||
}
|
||||
Loading…
Reference in a new issue