Bug: PHYS_OFFSET no longer points to DRAM physical starting address with CONFIG_ARM64_VA_BITS_52

Chen-Yu Tsai wens at kernel.org
Sat Aug 22 06:47:12 PDT 2026


On Sat, Aug 22, 2026 at 9:40 PM Ard Biesheuvel <ardb at kernel.org> wrote:
>
>
>
> On Sat, 22 Aug 2026, at 16:28, Chen-Yu Tsai wrote:
> > On Sat, Aug 22, 2026 at 8:50 PM Ard Biesheuvel <ardb at kernel.org> wrote:
> >>
> >> Hello Chen-Yu,
> >>
> >> On Sat, 22 Aug 2026, at 15:39, Chen-Yu Tsai wrote:
> >> > Hi,
> >> >
> >> > On the Allwinner H6 & H616 SoC (and likely others), if running a kernel
> >> > compiled with CONFIG_ARM64_VA_BITS_52 and CONFIG_ARM64_PA_BITS_52,
> >> > PHYS_OFFSET no longer points to the start of DRAM (0x40000000) but instead
> >> > points to 0xfff1000040000000.
> >> >
> >> >
> >> > I've observed this for quite some time but hadn't really nailed down what
> >> > was going on. For context: the IOMMU on these SoCs can only do 32-bit
> >> > addresses, and that's pretty fine since the SoC only supports up to 4 GB
> >> > DRAM. However the DRAM starts at 1GB offset in the physical address space.
> >> > We want to be able to map the highest 1GB I/O virtual address space and
> >> > thus need to check if the physical address is within 4GB without the
> >> > offset. Having only 32-bits addressing, the address will wrap around fine.
> >> > So we check the address against PHYS_OFFSE, which breaks with the mangled
> >> > address.
> >> >
> >> >
> >> > I suspect this is the result of the following commits:
> >> >
> >> >     7bc1a0f9e176 arm64: mm: use single quantity to represent the PA to
> >> > VA translation
> >> >     9684ec186f8f arm64: Enable LPA2 at boot if supported by the system
> >> >
> >> > The first commit introduces a negative (wrapped around) offset to
> >> > memstart_addr (PHYS_OFFSET) to work around mapping restrictions, and the
> >> > second commit makes the offset dependent on hardware.
> >> >
> >> >
> >> > I hope that Ard and the maintainers can look into it and make PHYS_OFFSET
> >> > always point to the physical start of DRAM.
> >> >
> >>
> >> On what basis are you claiming that PHYS_OFFSET must always point to the
> >> start of physical, non-secure DRAM?
> >
> > AFAIK we've been using this since armv7 in our older drivers to deal with
> > PA <-> IOVA offsets. This was then concentrated into one interconnect
> > driver: drivers/soc/sunxi/sunxi_mbus.c
> >
> > The driver applies PHYS_OFFSET as the DMA address offset for a class of
> > devices when the system is using an older device tree that lacks interconnect
> > properties.
> >
>
> That sounds like a hack to me tbh.

There was little documentation around the actual interconnect, and the offset
only really caused issues for devices with 2 GB DRAM, which was quite rare
back in the day. So the driver "workarounds" were added as issues were found.

> >
> > There's also Documentation/admin-guide/kdump/vmcoreinfo.rst which states:
> >
> > ARM64
> > =====
> >
> > PHYS_OFFSET
> > -----------
> >
> > Indicates the physical address of the start of memory. Similar to
> > kimage_voffset, which is used to translate virtual to physical
> > addresses.
> >
>
> This information is inaccurate. kimage_voffset is the offset between the
> kernel mapping in the vmalloc space and the associated physical memory.
> It has nothing to do with PHYS_OFFSET or with the start of memory.
>
> >> On arm64, PHYS_OFFSET is the physical address of the start of memory,
> >> where 'start of memory' == PAGE_OFFSET, i.e., the start of the linear
> >> map. When running a 52-bit VA kernel on hardware that is not LPA2 capable,
> >> the hardware does not support mapping memory at PAGE_OFFSET, so it is moved
> >> upward in the linear map.
> >
> > So it held true until 52-bit VA support was introduced?
> >
>
> It still holds true.

Well, yes. I guess I meant the physical start of the linear map == PHYS_OFFSET.

> >> I don't quite follow why you need to compare with PHYS_OFFSET in your IOMMU
> >> driver: could you elaborate?
> >
> > Our IOMMU only supports 32-bit of address space. On our SoCs, DRAM physically
> > starts at 0x40000000 (1 GB offset), meaning any physical DRAM above 3GB
> > would wrap around. However putting this number in drivers was discouraged
> > in the past and we were told to use PHYS_OFFSET (on ARMv7) instead. Also,
> > in the past there was this one chip that put DRAM at a different offset,
> > so using a fixed number in the driver won't always work.
> >
> > Right now we're just blocking any physical address above 32 bits. Ideally
> > we want to allow up to "start of DRAM + 4GB". So we need to know the DRAM
> > start address. (And we probably want to block anything below start of DRAM
> > as well.)
> >
>
> Should you be using memblock_start_of_DRAM() instead perhaps?

That seems like the thing we want. Thanks for the pointer, and sorry for the
noise.


ChenYu



More information about the linux-arm-kernel mailing list