Re: Bug: PHYS_OFFSET no longer points to DRAM physical starting address with CONFIG_ARM64_VA_BITS_52
"Ard Biesheuvel" <[email protected]>
| Newsgroups | org.infradead.lists.linux-arm-kernel,dev.linux.lists.linux-sunxi |
|---|---|
| Message-ID | <[email protected]> |
On Sat, 22 Aug 2026, at 16:28, Chen-Yu Tsai wrote: > On Sat, Aug 22, 2026 at 8:50 PM Ard Biesheuvel <[email protected]> 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'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. >> 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?