From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f53.google.com (mail-wm1-f53.google.com [209.85.128.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 16FE73DB63F for ; Mon, 15 Jun 2026 10:00:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.53 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781517604; cv=none; b=nOnZitLKiQmXWTF5QpknxmzqdevUTI4rDlRKZlJawRi3iXMzaWzO0yxxVmwfIlaTLowpZk1MHJUJifROz+zvsTb+Ij1SHqy4cdLvHVLcwK7wQfcfFcIIuOoyuhJo3DSBwf26rV09STCCM0U6m26iYIjboMIspw0T6yNLdZvTBVE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781517604; c=relaxed/simple; bh=3wXcpfM+S5tmyfpHkwf6cFdOFFat2m79jZMaL5c6R8E=; h=Date:From:To:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ogV8613mAQBaucnTjqkhj1vENVNKELgK74pNwr/mY+cFmixMXuEVDfXt5O74PjUCofYeHSHgXQuLefJyBkl7qo2aW4x3JPXmXQ5p82xGiTO8VvUudTVTaMzOELMf6Di7vU+zPFadFCmd2ALRumYmARj8vO1sFU5WfeuwHaTuzNE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=KUzs10XD; arc=none smtp.client-ip=209.85.128.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KUzs10XD" Received: by mail-wm1-f53.google.com with SMTP id 5b1f17b1804b1-490ac10e337so21412765e9.3 for ; Mon, 15 Jun 2026 03:00:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1781517601; x=1782122401; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:subject:cc:to:from:date:from:to:cc:subject:date :message-id:reply-to; bh=/40NyX5fmI7vs0/LA5CZV+IOaV0U2Xfp7EO4Khsh9Vc=; b=KUzs10XD6+lhj5joTn47fNZD8wzv1CgJcPq7QqSRanPIVjSL9yQ+otCx8G9asb9rJZ MFwFkVCRTXqpyujz7Qz9VBYD7tupzMLCyA6CFBoUw9U0I/uJS3DeINjT18HS0vBkungx CB1K6tT2PB3HVNWzQNaYn725IpYjTfdu5/qzZ7b+MM8yE/+iazXtvrH9U8jZYZ+82Z8c ZQKZRxNCC9ZiAQ2AFvP8+ZAhA9FSNpYvOFZG4FB7qZaPFJhvB/6avg0QSrwQNlY8tKQ9 wuWdRCqrYvYqgdCuPPS7wlUIl8AK+KdtW0EhLsuNAZt1/Y3+9Jkmf7lyVIrxox5dDO44 GEDA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781517601; x=1782122401; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=/40NyX5fmI7vs0/LA5CZV+IOaV0U2Xfp7EO4Khsh9Vc=; b=GLt6W0J1RNuv+D5v4XJLntFrA86iPknAMWf/5OHucQcC7ENUg2ktRC1Edvsctja3fe BCeM6FGS/ULZBqOBBRcyRS6ciRAVo6tZK19jTjdBndEKjG8rJYrdneWU1JTon82MJgrx y1O61iwQAmaqR5eGS9GwiL0G0cqKFiX9RgnM6TKYFoJEZGaHtd3dL2PJQ1F4TpONxGZs bhTpOkEwZq+GZLcTWmC59+IwiLsYIFq6kYgicHXQcbsRp/6ojrmO58ixc3zyg5dzhEGi vtPhYuS1hikLQT/pttHzNmJQ7SKnnPpozkE0/VuZqpCZOIB1n+Y+Mw0fNkn8kKPSIAua lVRw== X-Forwarded-Encrypted: i=1; AFNElJ/epxGWSbhOIDJQxNlo0cEYzBeZ0rSnnZNKcwRtRfcg4/Z43g7r14SIWloclFg3aUCjjLcmR0vJxl13Ito=@vger.kernel.org X-Gm-Message-State: AOJu0YwVKwb37X+nnETsKUiip3NiKRHeDpaKWOs5FJLNvs/ZlzrZ4l44 ZLBMhruAkq5hZtcQsU0I2Nuv+F53w+wvU46zjv9DVjxt9+YmPV4g8nyt X-Gm-Gg: Acq92OFtCyU9eEwWEe+z/Fn9WaYi/LDq2p7i859Zewrax0nLSjBSKfF+oK7z/UcQcpg pWU/qU1MssZyNYUzE4AoBCaYTMYpxdfWdn/dEH3272usbKMtLqZB+9OWumaLRlTGjO7sL7H2hUG c+80hDTQaCoSEvEoA5vKRebiu44rwTFoUoW3yEhebbolpYwSt35tQzC8AXwHulIojbjEli0gghh /aj9DYVdvvG6AVfaDTFI3G2JSXOdk1qipGr+mukmvB0oaHKZmkVq/4HuTzKFtfCBOUYQOzYQw8T JF+0Raxd7sEDP7ktIT35hYKgHOJv80B7EimP2WXxCEVMLORJRyA/OSOY8SbyvvF2q3VJhU95KUB Sgf+/TlLYRIH6W1qcAYx4B30yXyKP3UgWQKlSV0aupvu2pWXdLCz4ZkXrLJip7Vm7+UZ2WpOHdF C86M1T15dH10sEBEJwkQhpw2n+/gczHt8+I160kf/8GXpRi0VqGXKYWA7mzi49FNuxjTGicro= X-Received: by 2002:a05:600c:6d8b:b0:492:1e36:bb03 with SMTP id 5b1f17b1804b1-4922011dfd7mr98130405e9.36.1781517600965; Mon, 15 Jun 2026 03:00:00 -0700 (PDT) Received: from pumpkin (82-69-66-36.dsl.in-addr.zen.co.uk. [82.69.66.36]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-4619b9b7750sm5526943f8f.6.2026.06.15.03.00.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jun 2026 03:00:00 -0700 (PDT) Date: Mon, 15 Jun 2026 10:59:59 +0100 From: David Laight To: Zhanpeng Zhang Cc: Tomasz Jeznach , Joerg Roedel , Will Deacon , Robin Murphy , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , iommu@lists.linux.dev, linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, Xu Lu , cuiyunhui@bytedance.com, yuanzhu@bytedance.com Subject: Re: [PATCH v1] iommu/riscv: Support 32-bit register accesses Message-ID: <20260615105959.136698e8@pumpkin> In-Reply-To: <20260615064855.90316-1-zhangzhanpeng.jasper@bytedance.com> References: <20260615064855.90316-1-zhangzhanpeng.jasper@bytedance.com> X-Mailer: Claws Mail 4.1.1 (GTK 3.24.38; arm-unknown-linux-gnueabihf) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Mon, 15 Jun 2026 14:48:55 +0800 Zhanpeng Zhang wrote: > Some RISC-V IOMMU implementations cannot perform 64-bit MMIO accesses > to the IOMMU register file. The RISC-V IOMMU architecture allows 64-bit > registers to be accessed using 32-bit accesses, provided the accesses are > properly aligned and do not span multiple registers. > > Add a config option for such implementations and access 64-bit IOMMU > registers as paired 32-bit MMIO operations when it is enabled. Serialize > the paired accesses so the high and low halves cannot interleave with > another CPU. Full 64-bit register programming writes the high half before > the low half. > > This option describes the register access width. It is not an RV32 kernel > mode and does not describe a 32-bit IOMMU architecture. > > Co-developed-by: Xu Lu > Signed-off-by: Xu Lu > Signed-off-by: Zhanpeng Zhang > --- > This is needed for platforms whose RISC-V IOMMU register window does not > support naturally aligned 64-bit MMIO accesses. > > drivers/iommu/riscv/Kconfig | 11 ++++++++ > drivers/iommu/riscv/iommu.c | 4 +++ > drivers/iommu/riscv/iommu.h | 55 +++++++++++++++++++++++++++++++++---- > 3 files changed, 64 insertions(+), 6 deletions(-) > > diff --git a/drivers/iommu/riscv/Kconfig b/drivers/iommu/riscv/Kconfig > index b86e5ab94183..54d624b9b2ef 100644 > --- a/drivers/iommu/riscv/Kconfig > +++ b/drivers/iommu/riscv/Kconfig > @@ -22,3 +22,14 @@ config RISCV_IOMMU_PCI > def_bool y if RISCV_IOMMU && PCI_MSI > help > Support for the PCIe implementation of RISC-V IOMMU architecture. > + > +config RISCV_IOMMU_32BIT_ACCESS > + bool "Use 32-bit accesses for RISC-V IOMMU registers" > + depends on RISCV_IOMMU > + help > + Say Y when the RISC-V IOMMU MMIO window cannot be accessed > + using naturally aligned 64-bit loads and stores. > + > + When enabled, 64-bit IOMMU registers are accessed as paired > + 32-bit MMIO operations. This option does not describe an RV32 > + kernel or a 32-bit IOMMU architecture. > diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c > index a31f50bbad35..7fa1721b5728 100644 > --- a/drivers/iommu/riscv/iommu.c > +++ b/drivers/iommu/riscv/iommu.c > @@ -53,6 +53,10 @@ struct riscv_iommu_devres { > void *addr; > }; > > +#ifdef CONFIG_RISCV_IOMMU_32BIT_ACCESS > +DEFINE_RAW_SPINLOCK(riscv_iommu_32bit_access_lock); > +#endif > + > static void riscv_iommu_devres_pages_release(struct device *dev, void *res) > { > struct riscv_iommu_devres *devres = res; > diff --git a/drivers/iommu/riscv/iommu.h b/drivers/iommu/riscv/iommu.h > index 46df79dd5495..ba78ef1858c5 100644 > --- a/drivers/iommu/riscv/iommu.h > +++ b/drivers/iommu/riscv/iommu.h > @@ -14,6 +14,9 @@ > #include > #include > #include > +#ifdef CONFIG_RISCV_IOMMU_32BIT_ACCESS > +#include > +#endif > > #include "iommu-bits.h" > > @@ -69,21 +72,61 @@ void riscv_iommu_disable(struct riscv_iommu_device *iommu); > #define riscv_iommu_readl(iommu, addr) \ > readl_relaxed((iommu)->reg + (addr)) > > -#define riscv_iommu_readq(iommu, addr) \ > - readq_relaxed((iommu)->reg + (addr)) > - > #define riscv_iommu_writel(iommu, addr, val) \ > writel_relaxed((val), (iommu)->reg + (addr)) > > +#define riscv_iommu_readl_timeout(iommu, addr, val, cond, delay_us, timeout_us) \ > + readx_poll_timeout(readl_relaxed, (iommu)->reg + (addr), val, cond, \ > + delay_us, timeout_us) > + > +#ifndef CONFIG_RISCV_IOMMU_32BIT_ACCESS > +#define riscv_iommu_readq(iommu, addr) \ > + readq_relaxed((iommu)->reg + (addr)) > + > #define riscv_iommu_writeq(iommu, addr, val) \ > writeq_relaxed((val), (iommu)->reg + (addr)) > > #define riscv_iommu_readq_timeout(iommu, addr, val, cond, delay_us, timeout_us) \ > readx_poll_timeout(readq_relaxed, (iommu)->reg + (addr), val, cond, \ > delay_us, timeout_us) > +#else /* CONFIG_RISCV_IOMMU_32BIT_ACCESS */ > > -#define riscv_iommu_readl_timeout(iommu, addr, val, cond, delay_us, timeout_us) \ > - readx_poll_timeout(readl_relaxed, (iommu)->reg + (addr), val, cond, \ > - delay_us, timeout_us) > +extern raw_spinlock_t riscv_iommu_32bit_access_lock; > + > +static inline u64 __riscv_iommu_readq_relaxed(void __iomem *addr) > +{ > + u32 lo, hi; > + unsigned long flags; > + > + raw_spin_lock_irqsave(&riscv_iommu_32bit_access_lock, flags); > + do { > + hi = readl_relaxed(addr + sizeof(u32)); > + lo = readl_relaxed(addr); > + } while (hi != readl_relaxed(addr + sizeof(u32))); > + raw_spin_unlock_irqrestore(&riscv_iommu_32bit_access_lock, flags); Why the lock and the loop? If you need the loop (for places where the hardware might be changing both words?) then there is no need to read 'hi' twice when you loop. But does it make any sense to be reading the value either while the hardware is updating it (does that happen?) or concurrently with a write. > + > + return ((u64)hi << 32) | (u64)lo; > +} > + > +static inline void __riscv_iommu_writeq_relaxed(u64 value, void __iomem *addr) > +{ > + unsigned long flags; > + > + raw_spin_lock_irqsave(&riscv_iommu_32bit_access_lock, flags); > + writel_relaxed((u32)(value >> 32), addr + sizeof(u32)); > + writel_relaxed((u32)value, addr); > + raw_spin_unlock_irqrestore(&riscv_iommu_32bit_access_lock, flags); What are you actually locking against? I'm pretty sure it doesn't make any sense for two cpu to be writing to the same entry at the same time. Can't the writel_relaxed() be re-ordered, so you aren't guaranteeing they'll be done high-low. Same with the reads. David > +} > + > +#define riscv_iommu_readq(iommu, addr) \ > + __riscv_iommu_readq_relaxed((iommu)->reg + (addr)) > + > +#define riscv_iommu_writeq(iommu, addr, val) \ > + __riscv_iommu_writeq_relaxed((val), (iommu)->reg + (addr)) > + > +#define riscv_iommu_readq_timeout(iommu, addr, val, cond, delay_us, timeout_us) \ > + readx_poll_timeout(__riscv_iommu_readq_relaxed, (iommu)->reg + (addr), \ > + val, cond, delay_us, timeout_us) > +#endif /* CONFIG_RISCV_IOMMU_32BIT_ACCESS */ > > #endif