On Wed, Feb 18, 2026 at 06:21:32PM +0100, Anton Johansson wrote:
> Replaces the only remaining use of TARGET_PHYS_ADDR_SPACE_BITS for RISCV
> with a property RISCVIOMMUState::pas_bits that gets written to the
> capabilities field upon device realization. This write needs to happen
> at realize-time to ensure the property has been set.
>
> For the virt machine and sysbus device, pas_bits is set by
> virt_machine_init() to either 34 or 56 bits, retaining previous behaviour.
> However, for the PCI device we do not have access to the CPU state, and
> instead use the maximum riscv64 value of 56 bits.
>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Anton Johansson <anjo@rev.ng>
> ---
> hw/riscv/riscv-iommu.h | 1 +
> hw/riscv/riscv-iommu-pci.c | 3 +++
> hw/riscv/riscv-iommu.c | 8 ++++----
> hw/riscv/virt.c | 7 +++++++
> 4 files changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/hw/riscv/riscv-iommu.h b/hw/riscv/riscv-iommu.h
> index 2dabd86941..2a9f6fccd5 100644
> --- a/hw/riscv/riscv-iommu.h
> +++ b/hw/riscv/riscv-iommu.h
> @@ -34,6 +34,7 @@ struct RISCVIOMMUState {
> /*< public >*/
> uint32_t version; /* Reported interface version number */
> uint32_t pid_bits; /* process identifier width */
> + uint32_t pas_bits; /* physical address bits */
> uint32_t bus; /* PCI bus mapping for non-root endpoints */
>
> uint64_t cap; /* IOMMU supported capabilities */
> diff --git a/hw/riscv/riscv-iommu-pci.c b/hw/riscv/riscv-iommu-pci.c
> index 5f7d359204..14dd5f3857 100644
> --- a/hw/riscv/riscv-iommu-pci.c
> +++ b/hw/riscv/riscv-iommu-pci.c
> @@ -158,6 +158,9 @@ static void riscv_iommu_pci_init(Object *obj)
>
> iommu->icvec_avail_vectors = RISCV_IOMMU_PCI_ICVEC_VECTORS;
> riscv_iommu_set_cap_igs(iommu, RISCV_IOMMU_CAP_IGS_MSI);
> +
> + /* Report maximum physical address size of riscv64 */
> + iommu->pas_bits = 56;
> }
>
> static const Property riscv_iommu_pci_properties[] = {
> diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
> index b46b337375..98345b1280 100644
> --- a/hw/riscv/riscv-iommu.c
> +++ b/hw/riscv/riscv-iommu.c
> @@ -2453,10 +2453,6 @@ static void riscv_iommu_instance_init(Object *obj)
> /* Enable translation debug interface */
> s->cap = RISCV_IOMMU_CAP_DBG;
>
> - /* Report QEMU target physical address space limits */
> - s->cap = set_field(s->cap, RISCV_IOMMU_CAP_PAS,
> - TARGET_PHYS_ADDR_SPACE_BITS);
> -
> /* TODO: method to report supported PID bits */
> s->pid_bits = 8; /* restricted to size of MemTxAttrs.pid */
> s->cap |= RISCV_IOMMU_CAP_PD8;
> @@ -2487,6 +2483,9 @@ static void riscv_iommu_realize(DeviceState *dev, Error **errp)
> {
> RISCVIOMMUState *s = RISCV_IOMMU(dev);
>
> + /* Report QEMU target physical address space limits. */
> + s->cap = set_field(s->cap, RISCV_IOMMU_CAP_PAS, s->pas_bits);
> +
> s->cap |= s->version & RISCV_IOMMU_CAP_VERSION;
> if (s->enable_msi) {
> s->cap |= RISCV_IOMMU_CAP_MSI_FLAT | RISCV_IOMMU_CAP_MSI_MRIF;
> @@ -2645,6 +2644,7 @@ void riscv_iommu_reset(RISCVIOMMUState *s)
> static const Property riscv_iommu_properties[] = {
> DEFINE_PROP_UINT32("version", RISCVIOMMUState, version,
> RISCV_IOMMU_SPEC_DOT_VER),
> + DEFINE_PROP_UINT32("pas-bits", RISCVIOMMUState, pas_bits, 0),
> DEFINE_PROP_UINT32("bus", RISCVIOMMUState, bus, 0x0),
> DEFINE_PROP_UINT32("ioatc-limit", RISCVIOMMUState, iot_limit,
> LIMIT_CACHE_IOT),
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 07e66b3936..bbce2fb667 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -1739,6 +1739,13 @@ static void virt_machine_init(MachineState *machine)
> object_property_set_link(OBJECT(iommu_sys), "irqchip",
> OBJECT(mmio_irqchip),
> &error_fatal);
> + /*
> + * For riscv64 use a physical address size of 56 bits (44 bit PPN),
> + * and for riscv32 use 34 bits (22 bit PPN).
> + */
> + object_property_set_uint(OBJECT(iommu_sys), "pas-bits",
> + riscv_is_32bit(&s->soc[0]) ? 34 : 56,
> + &error_fatal);
>
> sysbus_realize_and_unref(SYS_BUS_DEVICE(iommu_sys), &error_fatal);
> }
>
> --
> 2.52.0
>
LGTM :)
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Thanks,
Chao