Inter-VM Communication
VMs on a cockpit SoC are deliberately isolated: separate memory, separate kernels, separate device views. Yet QNX must push vehicle speed to VHAL, route audio, and share camera frames with AAOS. Inter-VM communication uses layered mechanisms: VirtIO (standardized virtual devices over shared queues), vsock (socket-like VM-to-VM addressing), gRPC over vsock (structured RPC for VHAL and services), and shared memory / RTISM (zero-copy bulk data). Pick the wrong mechanism and you get latency spikes, security holes, or fragile integrations.
Vehicle speed in your Android app didn’t magically cross from CAN. It traveled QNX gateway → IPC → VHAL → CarService → your app, mostly across VM boundaries. This page maps that pipe.
Why Not Just Share a Pointer?
Section titled “Why Not Just Share a Pointer?”Guest VMs have separate stage-2 address spaces. AAOS cannot dereference a QNX pointer. The hypervisor would trap and kill the access. All cross-VM data exchange must go through hypervisor-approved channels:
- Explicit shared memory regions (carved at boot)
- Virtual devices (VirtIO) with queue-based I/O
- Socket abstraction (vsock) over hypervisor-mediated transport
VMs are air-gapped computers. Communication goes through diplomatic channels, not shared walls.
Two embassy buildings (VMs) in the same city (SoC). Staff cannot walk through walls. They exchange:
- Formal letters (gRPC messages over vsock) for structured requests
- Parcel drops (VirtIO queues) for standard device I/O
- Shared courier lockers (RTISM shared memory) for bulky packages (audio buffers, camera frames)
The hypervisor is the diplomatic corps — inspects every channel, no unauthorized tunnels.
VirtIO: Standardized Virtual Devices
Section titled “VirtIO: Standardized Virtual Devices”VirtIO is an open standard for paravirtualized devices. Guests use a common driver model instead of emulating legacy hardware register-by-register.
| Component | Role |
|---|---|
| Virtqueue | Ring buffer in shared memory: host/guest post requests and completions |
| VirtIO device | Block, network, console, socket, custom vendor devices |
| Transport | MMIO or modern virtio-vsock, virtio-gpu variants |
On automotive QNX + AAOS stacks, VirtIO often backs:
- Console / logging taps between host and guest
- Block device access to shared storage regions
- Network-style pipes where full TCP stack is overkill
VirtIO is virtual I/O with a common standard: write once, run on any hypervisor that supports it.
VirtIO is not “free IPC.” Each virtqueue operation has notify/trap overhead. High-frequency, small messages (1000 Hz vehicle signals) may need shared memory rings or batching, not per-signal VirtIO block requests.
vsock: VM-to-VM Sockets
Section titled “vsock: VM-to-VM Sockets”vsock (Virtual Socket) provides socket semantics between VMs and between guest and host, without real network hardware.
| Property | Detail |
|---|---|
| Addressing | CID (Context ID) per VM + port number, not IP addresses |
| Typical CIDs | Host (QNX) = CID 2, first guest (AAOS) = CID 3 (platform-specific) |
| API | BSD sockets-like: socket(AF_VSOCK, ...), connect, bind, listen |
| Isolation | Hypervisor routes; VMs cannot spoof arbitrary CIDs without config |
vsock is VM-to-VM socket addressing over the hypervisor, not over real network hardware.
Example mental model (not literal API):
AAOS (CID 3, port 5000) ──vsock──▶ QNX (CID 2, port 5000) "connect to host VHAL proxy"vsock is the transport. What you send over it defines the protocol, often gRPC.
gRPC over vsock: The VHAL Highway
Section titled “gRPC over vsock: The VHAL Highway”gRPC (HTTP/2 + Protobuf) gives typed, versioned RPC, ideal for Vehicle HAL (VHAL) property get/set/subscribe across VM boundaries.
Typical flow for vehicle speed:
sequenceDiagram participant CAN as CAN Bus / Gateway participant QNX as QNX Host (VM0) participant VSOCK as vsock Channel participant VHAL as VHAL Proxy (AAOS) participant CS as CarService participant APP as Android App
CAN->>QNX: Vehicle speed frame QNX->>QNX: Parse signal · update property cache VHAL->>VSOCK: gRPC Get / Subscribe (PERF_VEHICLE_SPEED) VSOCK->>QNX: Forward request QNX->>VSOCK: gRPC response (speed = 72.4 km/h) VSOCK->>VHAL: Return property value VHAL->>CS: AIDL property update CS->>APP: OnChangeListener callback| Layer | Technology | Purpose |
|---|---|---|
| Physical signal | CAN / Ethernet | Raw vehicle data |
| QNX side | Gateway service, property store | Parse, validate, rate-limit |
| Transport | vsock | VM-safe byte stream |
| RPC | gRPC + Protobuf | Typed VHAL property access |
| AAOS side | VHAL implementation → AIDL → CarService | Android-facing API |
When VHAL returns WRONG_VALUE or TIMEOUT:
- Check QNX gateway: is the CAN signal arriving? (
slog2info, gateway logs) - Check vsock connectivity: is AAOS CID reaching QNX CID? (port conflicts, firewall rules in VM config)
- Check gRPC service: is
VehicleHalproxy running on QNX side post-boot? - Don’t assume Android bug first. Most VHAL issues are host-side signal or IPC, not app code.
adb shell dumpsys android.automotive.evs and vendor VHAL test tools help, but QNX serial often tells the truth first.
Shared Memory: RTISM and Zero-Copy Paths
Section titled “Shared Memory: RTISM and Zero-Copy Paths”For high bandwidth, low latency data (audio PCM rings, camera frame buffers, large sensor blobs), shared memory (SHM) beats socket copy loops.
| Mechanism | Typical Use |
|---|---|
| RTISM (Real-Time IPC Shared Memory) | QNX ↔ guest bulk IPC regions configured at hypervisor boot |
| ION / dma-buf (Android side) | Graphics and media buffer sharing, often mediated by host |
| Hypervisor-carved SHM | Fixed physical pages mapped into multiple VM address spaces |
Properties:
- Zero-copy (after setup): producer writes, consumer reads same physical frames
- Synchronization required: doorbells, futexes, or QNX pulse events
- Security-critical: only explicitly shared regions are mapped; size and VM access are fixed at integration
RTISM (Real-Time IPC Shared Memory) is the high-throughput path when setup and sync are done right.
Shared memory without a sync protocol = data races. Audio glitches and torn camera frames often trace to missing doorbell interrupts or cache coherency assumptions, not buffer size alone.
Mechanism Selection Table
Section titled “Mechanism Selection Table”| Need | Mechanism | Why |
|---|---|---|
| VHAL property get/set/subscribe | gRPC over vsock | Typed, versioned, moderate frequency |
| Audio PCM streaming | Shared memory (RTISM) + doorbell | Zero-copy, low latency, high bandwidth |
| Camera / display buffer handoff | Shared memory + ION/dma-buf mediation | Large frames, GPU alignment requirements |
| Console / debug tap | VirtIO console | Standard, simple |
| Bulk logging to host | VirtIO console or vsock stream | Fire-and-forget tolerance |
| Modem ↔ AP communication | SMD / GLink / QRTR (not inter-VM) | Cross-processor, not QHEE guest IPC |
| QNX ↔ AAOS generic service RPC | gRPC over vsock | Extensible beyond VHAL |
| High-rate sensor fan-in (100+ Hz) | Shared memory ring or batched gRPC | Avoid per-sample syscall overhead |
| OTA status / low-rate events | gRPC over vsock or vsock datagram | Small payloads, reliability matters |
Communication Paths Diagram
Section titled “Communication Paths Diagram”flowchart LR subgraph VM0["QNX Host VM (CID 2)"] GW["CAN / Ethernet Gateway"] PROP["VHAL Property Service"] AUD["Audio Manager"] CAM["Camera / ISP Bridge"] end
subgraph IPC["Hypervisor-Mediated IPC"] VSOCK["vsock<br/>(CID + port routing)"] VIRTIO["VirtIO Queues"] SHM["Shared Memory<br/>(RTISM regions)"] end
subgraph VM1["AAOS Guest VM (CID 3)"] VHAL["VHAL Implementation"] CS["CarService"] AF["AudioFlinger"] HAL["Camera HAL"] end
subgraph MP["Modem (Separate Processor)"] AMSS["AMSS / Telephony"] end
GW --> PROP PROP <-->|"gRPC"| VSOCK VSOCK <-->|"gRPC"| VHAL VHAL --> CS
AUD <-->|"PCM buffers"| SHM SHM <-->|"PCM buffers"| AF
CAM <-->|"Frame buffers"| SHM SHM <-->|"Frame buffers"| HAL
VIRTIO <-->|"Console / misc I/O"| VM0 VIRTIO <-->|"Console / misc I/O"| VM1
GW <-->|"SMD / QRTR<br/>(not vsock)"| AMSSSecurity and Attack Surface
Every IPC channel is a trust boundary. vsock ports must be allowlisted in VM config. A compromised AAOS guest shouldn’t reach arbitrary QNX services. gRPC services should authenticate callers where OEM policy requires. Shared memory regions must be read-only on one side when possible (e.g., AAOS reads speed ring, QNX writes). Threat modeling treats guest → host as hostile direction by default.
Page 5.4 showed QNX and AAOS as separate VMs. This page explains the wires between them, the path Module 6’s VHAL rides on. Module 3’s service-oriented thinking (RPC, typed contracts) reappears here as gRPC over vsock. Module 7’s AMSS path uses SMD/QRTR, not VirtIO: different processor, different rules.
Remember
Section titled “Remember”- VMs cannot share pointers. Use VirtIO, vsock, gRPC, or shared memory.
- VHAL typically uses gRPC over vsock for typed property access QNX → AAOS.
- Audio and camera use shared memory (RTISM) for zero-copy throughput.
- AMSS uses SMD/GLink/QRTR: cross-processor IPC, not inter-VM vsock.
Check Your Understanding
1. Which IPC stack is the standard path for AAOS VHAL to request vehicle speed from the QNX host?
2. Why is shared memory (RTISM) preferred over gRPC for audio PCM streaming between QNX and AAOS?
3. How does AMSS on the modem processor communicate with the applications processor?