From postmarketOS
📱 This user's main device is a Google Pixel 3a (google-sargo).
GitLab logo This user has a GitLab profile.
Element logo This user has a Matrix account.
This user has ported postmarketOS to 1 device.
This user mainlined 1 devices.

The tools that I have for debugging are a USB cable, a screwdriver, and a chair.

Owns Devices

Device Notes
Google Pixel 3a (google-sargo) PVT 1.0, daily driver + mainlining target

Various information I found for mainlining


There are 7 valid IOMMU stream match registers on the Pixel 3a provided by the bootloader:

<&apps_smmu 0x140 0xf> // for eMMC
<&apps_smmu 0xa0 0xf> // unknown, might be for SD card
<&apps_smmu 0xc0 0xf> // unknown
<&apps_smmu 0x100 0xf> // unknown, might be for UFS HC
<&apps_smmu 0x740 0x0> // for USB
<&apps_smmu 0x880 0x8> // for MDSS
<&apps_smmu 0xc80 0x8> // for MDSS

The vendor kernel preserves the bootloader's settings on these streams and doesn't specify what all of them are used for. If you're experiencing insane behaviour trying to add a device node (reboot not initiated by the kernel, bring down of all peripherals, etc.), then you might have some luck trying these.

Patch used to fetch these (this patch can also be used under GPL v2):

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 2ff7a72cf377..e2c7e123285d 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -2057,6 +2057,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
 	int num_irqs, i, err;
 	u32 global_irqs, pmu_irqs;
 	irqreturn_t (*global_fault)(int irq, void *dev);
+	u32 smr;
 	smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
 	if (!smmu) {
@@ -2174,6 +2175,15 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
 	/* Check for RMRs and install bypass SMRs if any */
+	for (i = 0; i < smmu->num_mapping_groups; i++) {
+		smr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(i));
+		if (smr & ARM_SMMU_SMR_VALID)
+			dev_info(dev, "Stream match register: <&apps_smmu 0x%lx 0x%lx>",
+				      FIELD_GET(ARM_SMMU_SMR_ID, smr),
+	}

Dissecting the device tree on Android

It might be hard to find device tree nodes that prevent crashes on remote processors in the downstream device tree. For example, the Pixel 3a (SDM670) needs a modemsmem and smp2p sleepstate node for modem and audio, emitting unintelligible fatal error messages otherwise. To find these, it's useful to set up an environment where you can remove each device tree node (or a few at once, don't hold back too much!) from the same file and quickly pack a boot image. If the crash is caused by a missing device tree node, you'll see some crashes pop up in Android dmesg after a while.

Here is a Makefile and the commands to set up such an environment.


boot.img: cmdline dtb kernel ramdisk
	mkbootimg --output boot.img $(file < cmdline)

flash: boot.img
	fastboot flash boot boot.img

dtb: sdm670-google-sargo.dts
	gcc -E -x assembler-with-cpp $< | dtc -o $@

Command line:

$ unpack_bootimg --boot_img ../boot.img --out . --format mkbootimg > cmdline
$ fdtoverlay -i dtb -o sdm670-google-sargo.dtb ../android_kernel_google_msm-4.9/.output/arch/arm64/boot/dts/google/sdm670-s4-pvt.dtbo
$ dtc sdm670-google-sargo.dtb -o sdm670-google-sargo.dts
$ fastboot erase dtbo

The C preprocessor is run on the DTS because it lets you use the #if 0 and #endif directives and nest them.

DTBO masking

The DTBO on Android devices has virtually no use in mainline Linux, as the entire device tree is included in the boot.img. It often prevents devices from booting mainline when the DTBO fails to apply, and it is generally recommended to remove it for devices running mainline.

It is also possible to keep the DTBO without substantially affecting the device tree, although this is a bit hacky and unacceptable upstream. This could make netboot a bit more convenient to use.

Shell script:


syms="$(awk '/};/ { echo = 0 } { if (echo == 1) print $1 } /__fixups__ {/ { echo = 1 }' "$1")"

cat <<EOF
// SPDX-License-Identifier: GPL-2.0-only
 * Copyright (c) $(date +%Y), The Linux Foundation. All rights reserved.
 * FIXME: Change the copyright and license if desired. Consider licensing under
 * BSD-3-Clause if you are permitted to do so and adding the original copyright
 * headers.

/ {
	__symbols__ {

printf '%s' "$syms" | awk '{ print "\t\t" $1 " = \"/masked/" $1 "\";" }'

cat <<EOF

	masked {

printf '%s' "$syms" | awk '{ print "\t\tmasked_" $1 " = <&_masked_" $1 ">;" }'
printf '%s' "$syms" | awk '{ print "\t\t_masked_" $1 ": " $1 " { status = \"disabled\"; };" }'

cat <<EOF

Command line:

$ dtc -o device-tree-overlay.dts android_kernel_google_msm-4.9/.output/arch/arm64/boot/dts/google/sdm670-s4-pvt.dtbo
$ ./ device-tree-overlay.dts > sdm670-google-common-dtbo-mask.dtsi

The result can be included in the mainline device tree.

Restarting remote processors

The sensors registry is only probed when the SLPI/ADSP boots, so it can be useful to reboot a remote processor without rebooting the device.

First, you need to find the number identifying the remote processor through sysfs (the exact path will vary between SoCs):

$ ls /sys/devices/platform/soc@0/62400000.remoteproc/remoteproc/

Then, you can reboot the remote processor (until the device boots again and the drivers race to get a unique identifier):

$ sudo sh -c 'printf stop > /dev/remoteproc1'
$ sudo sh -c 'printf start > /dev/remoteproc1'