Skip to content

Inter-VM Communication

Advanced10 min read
Assumes: 5.4 Multi-OS Layout
TL;DR

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. Think of it as two coworkers communicating only through carefully audited mail slots.

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:

  1. Explicit shared memory regions (carved at boot)
  2. Virtual devices (VirtIO) with queue-based I/O
  3. Socket abstraction (vsock) over hypervisor-mediated transport

VMs are air-gapped computers. Communication goes through diplomatic channels, not shared walls.

Mental Model

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.

Mnemonic: VirtIO for bulk, vsock for control, shared mem for speed — the three doors.

Think About It

QNX sends vehicle speed to AAOS 100 times per second. Should you use VirtIO, vsock, or shared memory? Why?

Reveal Answer

Use a shared-memory ring (RTISM region) with QNX writing speed into a fixed struct and AAOS VHAL reading via a doorbell — zero per-sample copy and no VirtIO trap overhead at 100 Hz. gRPC over vsock fits VHAL subscribe/setup and lower-rate properties, not continuous high-frequency streaming; per-sample VirtIO queue ops add too much latency. On bench, verify the ring is mapped in both VM configs and timestamp updates on QNX vs AAOS before blaming CarService.

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.

Common Gotcha

Beginner thinks VirtIO is “free IPC” — just share a queue and go. Reality: 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 (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 (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
Where You'll See This

When VHAL returns WRONG_VALUE or TIMEOUT:

  1. Check QNX gateway: is the CAN signal arriving? (slog2info, gateway logs)
  2. Check vsock connectivity: is AAOS CID reaching QNX CID? (port conflicts, firewall rules in VM config)
  3. Check gRPC service: is VehicleHal proxy running on QNX side post-boot?
  4. 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.

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.

Common Gotcha

If you use shared memory without a sync protocol, you get data races. Audio glitches and torn camera frames often trace to missing doorbell interrupts or cache coherency assumptions, not buffer size alone.

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
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)"| AMSS
Security 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.

Connect the Dots

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.

  1. VMs cannot share pointers. Use VirtIO, vsock, gRPC, or shared memory.
  2. VHAL typically uses gRPC over vsock for typed property access QNX → AAOS.
  3. Audio and camera use shared memory (RTISM) for zero-copy throughput.
  4. 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?

Recall

2. Why is shared memory (RTISM) preferred over gRPC for audio PCM streaming between QNX and AAOS?

Applied

3. How does AMSS on the modem processor communicate with the applications processor?

Recall

4. QNX sends vehicle speed to AAOS at 100 Hz. Which mechanism is most appropriate?

Applied

5. What addressing scheme does vsock use for VM-to-VM communication?

Applied

6. An integration team proposes running VHAL gRPC over vehicle Ethernet (SOME/IP) instead of vsock between QNX and AAOS on the same SoC. What is the key trade-off?

Synthesis

Connects to: Module 3 — Signals to Services

Further Reading
  • VirtIO Specification v1.2 (OASIS) — Standard virtual I/O device specification defining virtio-gpu, virtio-snd, virtio-vsock, and shared-queue transport used for inter-VM communication on hypervisor platforms.
  • QNX Advanced Virtualization Frameworks — Virtual Socket — QNX documentation for virtio-vsock and gRPC-over-TCP/IP between hypervisor host and Android guest, matching the VHAL communication pattern on this page.
  • QNX Neutrino IPC — QNX inter-process communication primitives (message passing, pulses, shared memory) that underpin host-side service architecture before data crosses VM boundaries.
  • gRPC Documentation — Official gRPC guides for structured RPC over various transports, relevant to the Protobuf-over-vsock pattern used for VHAL property access between QNX and AAOS.
  • Android Virtualization Framework Architecture — AOSP documentation for protected VMs, hypervisor integration, and cross-VM communication patterns on ARM platforms including Qualcomm Gunyah support.
  • QNX Advanced Virtualization Frameworks — Graphics and Audio Sharing — Architecture for zero-copy graphics (virtio-gpu) and audio (virtio-snd) sharing that parallels the shared-memory/RTISM patterns described for high-bandwidth data.
  • Linux vsock Documentation — Kernel documentation for the AF_VSOCK address family that provides VM-to-VM socket communication with CID-based addressing used in cockpit inter-VM stacks.