================================================ Base kernel device tree (the SoC boot contract) ================================================ ``artifacts/boot_a/board.dts`` is the decompiled base device tree carried inside ``boot_a`` (``dtb.img``, 407,904 B). It is the **SoC-level** description the kernel is handed at EL1 — before the board-specific overlay is applied. ABL reads this base DTB, selects one of the three PCB overlays and applies it on top (:doc:`/boot/dtbo`), fixes up ``/chosen`` and ``/memory``, then enters the kernel with ``x0 = physical FDT`` (:doc:`/boot/below-uefi`, :doc:`/abl/bootlinux`). This page documents the DTB's **structural / boot-contract** nodes — the machine the kernel is told it is running on, and the interfaces it uses to talk to the firmware below it: SoC identity, CPU topology, the PSCI/EL3 power interface, the physical ``reserved-memory`` carve-out map, the IMEM boot-handshake cells, ``/chosen``, the Android verified-boot ``firmware`` node, and the GIC/timer/ apps-SMMU interfaces the kernel inherits live from XBL. It deliberately does **not** re-enumerate the UFS, GENI/QUP or clocks/pins register surface — that is :doc:`/soc/storage`, :doc:`/boot/qup-buses`, :doc:`/soc/clocks` and :doc:`/soc/pinctrl`. Nor does it cover what the overlays add — that is :doc:`/boot/dtbo`. Everything below is read directly from the decompiled DTB. SoC identity ============ The root node fixes the silicon this DTB targets:: model = "Qualcomm Technologies, Inc. Lagoon SoC"; compatible = "qcom,lagoon"; qcom,msm-id = <0x1b2 0x10000 0x1cb 0x10000>; qcom,board-id = <0x00 0x00>; - ``qcom,msm-id`` is a list of **(soc-id, hw-version)** pairs: ``0x1b2`` (434) and ``0x1cb`` (459), both hw-version ``0x10000`` (major 1, minor 0). SoC-ID 434 is **lagoon** (the SM6350 / Snapdragon 690 platform, confirmed by ``model`` and ``compatible``); 459 is a sibling ID in the same lagoon family, so this single base DTB serves more than one SoC-ID. ABL matches the running SoC's fused soc-id/hw-version against this list before accepting the DTB. - ``qcom,board-id = <0 0>`` here is the **generic base**; the real board/PCB identity (``onyx,pcbver-id`` v10/v20/v30) is carried by the overlays and is how ABL picks one (:doc:`/boot/dtbo`). The platform ("Bitra") vs SoC-codename ("lagoon") relationship is covered in :doc:`/index`. CPU topology and DVFS ===================== Eight cores in two clusters, all ``compatible = "arm,armv8"``, all ``enable-method = "psci"`` (no ``spin-table`` fallback, below): .. list-table:: :header-rows: 1 :widths: 16 10 22 20 32 * - Cores - ``reg`` (MPIDR) - ``capacity-dmips-mhz`` - ``dynamic-power-coefficient`` - ``qcom,freq-domain`` / LMh * - cluster0 — cpu@0…@500 (6 cores) - ``0x0``…``0x500`` - ``0x400`` = 1024 - ``0x64`` = 100 - domain **0**, 6 cores; ``lmh-dcvs`` phandle ``0x05`` * - cluster1 — cpu@600, cpu@700 (2 cores) - ``0x600``, ``0x700`` - ``0x766`` = 1894 - ``0x2bf`` = 703 - domain **1**, 2 cores; ``lmh-dcvs`` phandle ``0x0d`` This is the standard SM6350 **Kryo 660** configuration: a 6-core efficiency cluster (Silver, Cortex-A55 class — the ``1024`` unit-capacity, low-leakage cores) and a 2-core performance cluster (Gold, Cortex-A77 class — capacity 1894, 7× the dynamic-power coefficient). The 6+2 split, capacities and power coefficients are read from the DTB; the Silver/Gold ↔ A55/A77 mapping is the known SM6350 core assignment, not something the generic ``arm,armv8`` compatible encodes. Cache hierarchy (from the ``cpu`` sub-nodes): per-core **L1 I/D** and **L2**, with a **shared L3** (``arm,arch-cache`` cache-level 3, phandle ``0x06``) that every core's L2 chains to via ``next-level-cache``. ``cpu-map`` groups the cores into ``cluster0``/``cluster1`` for the scheduler. DVFS/thermal hardware backing the two domains (in the RPMh MMIO band): - ``qcom,cpufreq-hw`` @ **``0x18323000``** (``freq-domain0``, little) + **``0x18325800``** (``freq-domain1``, big) — the EPSS/OSM hardware frequency-domain controller; clocks are the RPMh ``xo`` (phandle ``0x1e``) and a GCC ``alternate`` (``0x1f``). - ``qcom,limits-dcvs`` (``qcom,msm-hw-limits``, **LMh**) @ **``0x18358800``** (affinity 0 = little) and **``0x18350800``** (affinity 1 = big) — the Limits Management hardware that throttles each cluster's frequency under current/thermal limit, coordinated with the AOP/RPMh (:doc:`/soc/aop`). The on-flash LMh limit table is the tiny ``limits`` partition (``limits.bin`` — a small binary header, e.g. ``12 98 34 20``, then zero pad); the companion ``limits-cdsp`` partition is blank (:doc:`/partition-map`). PSCI — the kernel↔EL3 power interface ===================================== :: psci { compatible = "arm,psci-1.0"; method = "smc"; }; Every CPU carries ``enable-method = "psci"``, so **all** CPU power operations — releasing the secondary cores at boot (``CPU_ON``), idle/suspend (``CPU_SUSPEND``), hotplug-down (``CPU_OFF``) and ``SYSTEM_RESET``/``SYSTEM_OFF`` — are issued as **SMC calls trapping to EL3**. On this SoC EL3 is owned by the resident TZ/QSEE monitor (``tz_a`` at entry ``0x14680000``, :doc:`/trustzone/secure-world`), so PSCI is the concrete, DTB-declared channel through which the EL1 kernel drives the secure-world power manager. There is no spin-table; a kernel (or a bootloader replacement) that wants the secondary CPUs online must speak PSCI-over-SMC to the stock EL3 monitor. This is the runtime counterpart to the boot-chain EL ladder in :doc:`/boot/boot-chain`. Physical reserved-memory carve-out map ====================================== The ``/reserved-memory`` node is the DTB's physical DRAM carve-out map. DRAM base is **``0x80000000``** (2 GiB), and two bands of ``no-map`` / ``removed-dma-pool`` regions sit at the bottom of RAM — a low band at the DRAM base and the large **PIL** band from ``0x86000000`` — followed by reusable (``shared-dma-pool`` / CMA) pools and the display framebuffers. Each fixed region maps to a firmware image or coprocessor documented elsewhere: .. list-table:: Fixed (``no-map``) regions :header-rows: 1 :widths: 30 16 12 42 * - Region - Base - Size - Consumer * - ``hyp_region`` - ``0x80000000`` - ``0x600000`` (6 MiB) - HYP / QHEE runtime (``hyp_a`` entry ``0x8004a000`` lands here) — :doc:`/trustzone/secure-world` * - ``xbl_aop_mem`` - ``0x80700000`` - ``0x160000`` (1.375 MiB) - XBL↔AOP shared/message RAM (``aop_a``) * - ``reserved-memory`` (cmd-db) - ``0x80860000`` - ``0x20000`` (128 KiB) - RPMh **Command DB** (``qcom,cmd-db``), published by AOP, read by the AP RPMh driver * - ``sec_apps_region`` - ``0x808ff000`` - ``0x1000`` (4 KiB) - secure-apps hand-off page * - ``smem`` - ``0x80900000`` - ``0x200000`` (2 MiB) - SMEM — inter-subsystem shared memory * - ``cdsp_sec_regions`` - ``0x80b00000`` - ``0x1e00000`` (30 MiB) - CDSP secure region * - ``camera_region`` - ``0x86000000`` - ``0x500000`` (5 MiB) - camera (present; no camera on this e-reader) * - ``pil_npu_region`` - ``0x86500000`` - ``0x500000`` (5 MiB) - NPU PIL (``NPU.FW.2.3`` in ``modem_a``) — :doc:`/audio/dsp-firmware` * - ``pil_video_region`` - ``0x86a00000`` - ``0x500000`` (5 MiB) - Venus video PIL * - ``cdsp_regions`` - ``0x86f00000`` - ``0x1e00000`` (30 MiB) - CDSP (``CDSP.VT.2.6``, ``dsp_a``) — :doc:`/audio/dsp-firmware` * - ``pil_adsp_region`` - ``0x88d00000`` - ``0x2800000`` (40 MiB) - ADSP PIL (``ADSP.VT.5.6`` in ``modem_a``) — :doc:`/audio/dsp-firmware` * - ``wlan_fw_region`` - ``0x8b500000`` - ``0x200000`` (2 MiB) - WLAN firmware (``WLAN.HL.3.3.1`` in ``core_nhlos_a``) * - ``ipa_fw_region`` / ``ipa_gsi_region`` - ``0x8b700000`` - ``0x10000`` + ``0x5400`` - IPA (IP Accelerator) FW + GSI * - ``gpu_region`` - ``0x8b715400`` - ``0x2000`` (8 KiB) - GPU (Adreno) microcode scratch * - ``modem_region`` - ``0x8b800000`` - ``0xf800000`` (248 MiB) - MPSS modem (``MPSS.HI.2.5.1``) — the large, **dormant** baseband carve-out * - ``removed_region`` - ``0xc0000000`` - ``0x3900000`` (57 MiB) - generic removed pool .. list-table:: Reusable (``shared-dma-pool`` / CMA) and display regions :header-rows: 1 :widths: 30 20 50 * - Region - Size / base - Purpose * - ``qseecom_region`` - ``0x1400000`` (20 MiB) - QSEECom shared buffers (TZ command path) * - ``qseecom_ta_region`` - ``0x1000000`` (16 MiB) - QSEE trustlet (TA) working memory — :doc:`/trustzone/secure-world` * - ``secure_display_region`` - ``0x8c00000`` (140 MiB) - secure display / protected buffers (Widevine, CDSP SecurePD — :doc:`/audio/dsp-firmware`) * - ``mem_dump_region`` - ``0x2800000`` (40 MiB) - RAM-dump capture buffer * - ``adsp_region`` / ``linux,cma`` - ``0x800000`` / ``0x2000000`` - generic ADSP DMA pool (8 MiB) and the default 32 MiB CMA * - ``cont_splash_region`` - ``0xa0000000`` ``0x2300000`` (35 MiB) - continuous-splash framebuffer (:doc:`/display/splash`) * - ``disp_rdump_region`` - ``0xa0000000`` ``0x2300000`` - display RAM-dump — **overlaps** the splash region (reused after splash) * - ``dfps_data_region`` - ``0xa2300000`` ``0x100000`` (1 MiB) - dynamic-FPS panel data Cross-check with XBL: the DTB's PIL band ``0x86000000`` → ``0x9b000000`` (``modem_region`` end) sits inside XBL's single coarse **PIL Reserved** window ``0x86000000`` size ``0x15800000`` (→ ``0x9b800000``) from :doc:`/xbl/handoff` Q4 — i.e. XBL reserves one block and the DTB subdivides it into the named ``pil_*`` / ``modem`` / ``cdsp`` regions. The gap above ``modem_region`` (``0x9b000000`` … ``0xa0000000``) is where XBL's ABOOT FV (``0x9FA00000``) and MMU page-tables (``0x9FF8D000``) live (:doc:`/boot/below-uefi`); the OS load window ``0xA2400000`` sits just above the splash/dfps regions. The ``/memory`` node itself is a placeholder (``reg = <0 0 0 0>``); how the actual DRAM base/size gets filled in at runtime is in :doc:`/boot/below-uefi`. A separate ``mem-offline`` node (``qcom,mem-offline``, granule ``0x200``) declares which DDR banks may be power-collapsed offline. IMEM boot-handshake cells ========================= ``qcom,msm-imem@146aa000`` (``reg = <0x146aa000 0x1000>``) is the always-on SoC IMEM cookie page shared across boot stages — the same ``0x146xxxxx`` on-chip SRAM band that holds the TZ EL3 stub (``0x14680000``) and XBL Sec (``0x14950000``, :doc:`/boot/boot-chain`). Its offsets are the software hand-shake between the kernel, the bootloader and PBL: .. list-table:: :header-rows: 1 :widths: 26 12 62 * - Cell - Offset - Role * - ``dload_type`` - ``+0x1c`` - **download-mode cookie** — a magic written here requests EDL/download at the next reset; read by the loader/PBL (the software path complementing the hardware EDL entry, :doc:`/edl/entry`) * - ``diag_dload`` - ``+0xc8`` - diag download-mode config block * - ``restart_reason`` - ``+0x65c`` - **reboot-reason cookie** — the kernel writes it (``reboot bootloader`` / ``recovery`` / ``edl`` …); the bootloader reads it to branch (distinct from the ``misc`` BCB in :doc:`/partition-map`) * - ``boot_stats`` - ``+0x6b0`` - boot-timing counters (XO ticks) captured across stages * - ``kaslr_offset`` - ``+0x6d0`` - where the kernel publishes its KASLR slide (for RAM-dump tooling) * - ``pil`` - ``+0x94c`` - PIL subsystem state/status table * - ``mem_dump_table`` - ``+0x10`` - pointer to the mem-dump descriptor table (RAM-dump collection) ``/chosen`` and early boot config ================================= :: chosen { bootargs = "rcupdate.rcu_expedited=1 rcu_nocbs=0-7 earlycon=msm_geni_serial,0x98c000 kpti=off"; }; - ``earlycon=msm_geni_serial,0x98c000`` — the early console is the **GENI/QUP serial engine at ``0x98c000``** (the ``serial0`` alias, ``qcom,qup_uart@98c000``). This is the debug UART referenced in :doc:`/boot/below-uefi`. - ``kpti=off`` — kernel page-table isolation disabled (the A55/A77 cores are not affected by the Meltdown variant KPTI mitigates). - ``rcu_nocbs=0-7`` + ``rcu_expedited=1`` — RCU callback offload across all 8 cores, expedited grace periods. ABL overwrites/extends ``bootargs`` at boot (androidboot.* slot, serialno, verifiedbootstate, …) before entering the kernel — see :doc:`/abl/bootlinux`. Android verified-boot ``firmware`` node ======================================= :: firmware { android { compatible = "android,firmware"; vbmeta { compatible = "android,vbmeta"; parts = "vbmeta,boot,system,vendor,dtbo"; }; fstab { compatible = "android,fstab"; vendor { dev = ".../soc/1d84000.ufshc/by-name/vendor"; type = "ext4"; mnt_flags = "ro,barrier=1,discard"; fsmgr_flags = "wait,slotselect,avb"; }; }; }; }; This is the device-tree side of Android Verified Boot. ``vbmeta/parts`` names the partitions chained from the top-level ``vbmeta`` descriptor (``vbmeta,boot,system,vendor,dtbo``) — the same chain proven test-key-signed in :doc:`/abl/verified-boot`. The ``fstab`` entry declares ``vendor`` as an early-mount ext4 volume, read-only, with ``slotselect`` (A/B, resolved from the GPT slot bits in :doc:`/partition-map`) and ``avb`` (dm-verity / AVB enforced). Only ``vendor`` is early-mounted from the DT here; ``system`` and the rest are dynamic partitions inside ``super`` mounted later by first-stage init. Core firmware-facing infrastructure =================================== Beyond the GIC/timer/SMMU interfaces above, three more nodes are the kernel's structural interfaces to the always-on/secure firmware: - ``qcom,rpmh-rsc`` @ **``0x18200000``** (``drv-0/1/2`` at ``0x18200000`` / ``0x18210000`` / ``0x18220000``, ``qcom,drv-id = 2`` = the APSS DRV, ``tcs-offset 0xd00``) — the AP-side **RPMh Resource State Coordinator**: the kernel votes for clocks, regulators and bus/DDR states through TCS command slots that the **AOP** services (:doc:`/soc/aop`). The large RPMh regulator tree and ``qcom,lagoon-rpmh-clk`` hang off this node. - ``qcom,cmd-db`` (``reserved-memory@80860000``) — the command DB that resolves RPMh resource names to addresses, populated by AOP (see the carve-out table above). - ``arm,gic-v3`` @ **``0x17a00000``** (redistributors @ ``0x17a60000``, stride ``0x20000`` × 8 cores), ``interrupt-controller@b220000`` (the **PDC** wakeup/power-domain controller) and ``arm,armv8-timer`` (``clock-frequency`` ``0x124f800`` = **19.2 MHz**, the XO rate) — the interrupt and time base the kernel inherits live from XBL (:doc:`/boot/below-uefi`). - **apps-SMMU** @ **``0x15000000``** size ``0x100000`` (``NS_DEVICE`` in XBL's map; a second ``tcu-base`` window at ``0x15182000`` size ``0x20``) — UFS, QUP and most NoC masters issue DMA as IOVAs through this SMMU and its TBUs (``anoc_1_tbu@15185000``, ``anoc_2_tbu@15189000``); the GPU has its own, separate SMMU (``arm,smmu-kgsl@3d40000``, :doc:`/soc/gpu`). XBL configures the UFS stream (``UfsSmmuConfigForOtherBootDev = 1``); the state of other streams below the OS is not characterised here (:doc:`/boot/below-uefi`). Provenance ========== :Source: ``artifacts/boot_a/board.dts`` — the decompiled base DTB extracted from ``boot_a`` (``dtb.img``). All node names, addresses, sizes, ``reg`` values, capacities and property strings are quoted directly from that file. :Method: Structural read of the root, ``cpus``/``cpu-map``, ``psci``, ``reserved-memory``, ``qcom,msm-imem``, ``chosen``, ``firmware`` and the ``cpufreq-hw`` / ``rpmh-rsc`` / GIC / timer nodes; hex sizes converted to binary units; carve-out bases cross-checked against XBL's memory map. No code executed. :Cross-refs: :doc:`/boot/below-uefi` (execution state at hand-off), :doc:`/soc/gpu` (the separate GPU SMMU), :doc:`/boot/dtbo` (PCB overlays applied over this base), :doc:`/xbl/handoff` (XBL PIL Reserved window, kernel load window), :doc:`/trustzone/secure-world` (EL3 PSCI target, trustlet memory), :doc:`/audio/dsp-firmware` (coprocessor images ↔ carve-outs), :doc:`/xbl/platform-state` (board identity), :doc:`/partition-map` (A/B slotselect), :doc:`/abl/verified-boot` (vbmeta chain), :doc:`/edl/entry` (``dload_type`` cookie), :doc:`/abl/bootlinux` (bootargs fix-up, kernel entry).