* [PATCH 0/2] iommu/amd-vi: remove zeroing of MMIO region @ 2026-05-06 7:37 Roger Pau Monne 2026-05-06 7:37 ` [PATCH 1/2] iommu/amd-vi: allow disable_iommu() against non-initialized IOMMUs Roger Pau Monne 2026-05-06 7:37 ` [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region Roger Pau Monne 0 siblings, 2 replies; 15+ messages in thread From: Roger Pau Monne @ 2026-05-06 7:37 UTC (permalink / raw) To: xen-devel Cc: Roger Pau Monne, Jan Beulich, Andrew Cooper, Jason Andryuk, Teddy Astie Hello, Unconditionally zeroing the whole IOMMU MMIO region is dangerous, at least on an upcoming platform this puts the IOMMU in a broken state that's not recovered by the init procedure in Xen. Get rid of the zeroing, and instead attempt to disable the IOMMU ahead of enabling it. Thanks, Roger. Roger Pau Monne (2): iommu/amd-vi: allow disable_iommu() against non-initialized IOMMUs iommu/amd-vi: do not zero IOMMU MMIO region xen/drivers/passthrough/amd/iommu_init.c | 34 +++++++++++------------- 1 file changed, 15 insertions(+), 19 deletions(-) -- 2.53.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/2] iommu/amd-vi: allow disable_iommu() against non-initialized IOMMUs 2026-05-06 7:37 [PATCH 0/2] iommu/amd-vi: remove zeroing of MMIO region Roger Pau Monne @ 2026-05-06 7:37 ` Roger Pau Monne 2026-05-06 8:19 ` Jan Beulich 2026-05-06 7:37 ` [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region Roger Pau Monne 1 sibling, 1 reply; 15+ messages in thread From: Roger Pau Monne @ 2026-05-06 7:37 UTC (permalink / raw) To: xen-devel Cc: Roger Pau Monne, Jan Beulich, Andrew Cooper, Jason Andryuk, Teddy Astie Introduce a force option to disable_iommu() that allows it to disable the IOMMU, even when ->enabled is not set. While there remove the unlikely(), this is not a hot path anyway. No functional change, as there are no current callers that pass force == true. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> --- xen/drivers/passthrough/amd/iommu_init.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c index d77dd8511288..76ae78e5ea53 100644 --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -929,13 +929,13 @@ static void enable_iommu(struct amd_iommu *iommu) amd_iommu_flush_all_caches(iommu); } -static void disable_iommu(struct amd_iommu *iommu) +static void disable_iommu(struct amd_iommu *iommu, bool force) { unsigned long flags; spin_lock_irqsave(&iommu->lock, flags); - if ( unlikely(!iommu->enabled) ) + if ( !iommu->enabled && !force ) goto out; if ( !iommu->ctrl.int_cap_xt_en ) @@ -1139,7 +1139,7 @@ static void __init amd_iommu_init_cleanup(void) iommu->ctrl.int_cap_xt_en = 0; if ( iommu->enabled ) - disable_iommu(iommu); + disable_iommu(iommu, false); else if ( iommu->mmio_base ) writeq(iommu->ctrl.raw, iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); @@ -1584,7 +1584,7 @@ void cf_check amd_iommu_crash_shutdown(void) struct amd_iommu *iommu; for_each_amd_iommu ( iommu ) - disable_iommu(iommu); + disable_iommu(iommu, false); } void cf_check amd_iommu_resume(void) @@ -1598,7 +1598,7 @@ void cf_check amd_iommu_resume(void) * To make sure that iommus have not been touched * before re-enablement */ - disable_iommu(iommu); + disable_iommu(iommu, false); enable_iommu(iommu); if ( !iommu->features.flds.ia_sup ) invalidate_all = false; -- 2.53.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] iommu/amd-vi: allow disable_iommu() against non-initialized IOMMUs 2026-05-06 7:37 ` [PATCH 1/2] iommu/amd-vi: allow disable_iommu() against non-initialized IOMMUs Roger Pau Monne @ 2026-05-06 8:19 ` Jan Beulich 0 siblings, 0 replies; 15+ messages in thread From: Jan Beulich @ 2026-05-06 8:19 UTC (permalink / raw) To: Roger Pau Monne; +Cc: Andrew Cooper, Jason Andryuk, Teddy Astie, xen-devel On 06.05.2026 09:37, Roger Pau Monne wrote: > Introduce a force option to disable_iommu() that allows it to disable the > IOMMU, even when ->enabled is not set. While there remove the unlikely(), > this is not a hot path anyway. > > No functional change, as there are no current callers that pass force == > true. > > Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Acked-by: Jan Beulich <jbeulich@suse.com> ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region 2026-05-06 7:37 [PATCH 0/2] iommu/amd-vi: remove zeroing of MMIO region Roger Pau Monne 2026-05-06 7:37 ` [PATCH 1/2] iommu/amd-vi: allow disable_iommu() against non-initialized IOMMUs Roger Pau Monne @ 2026-05-06 7:37 ` Roger Pau Monne 2026-05-06 8:20 ` Andrew Cooper 2026-05-06 8:28 ` Jan Beulich 1 sibling, 2 replies; 15+ messages in thread From: Roger Pau Monne @ 2026-05-06 7:37 UTC (permalink / raw) To: xen-devel Cc: Roger Pau Monne, Jan Beulich, Andrew Cooper, Jason Andryuk, Teddy Astie Attempting to memset the whole IOMMU MMIO region to zero is dangerous to say the least. We don't know what registers might be there, neither what values might be safe for those registers. On a forthcoming platform doing the zeroing of the MMIO region can put the IOMMU in a broken state, which is not recovered by the IOMMU initialization procedure in Xen. Instead attempt to forcefully disable the IOMMU ahead of enabling it. Fold map_iommu_mmio_region() into it's only caller, as the function body is just an ioremap() call after the removal of the memset(). Fixes: 0700c962ac2d ("Add AMD IOMMU support into hypervisor") Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> --- xen/drivers/passthrough/amd/iommu_init.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c index 76ae78e5ea53..8bf5ca4de18f 100644 --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -42,18 +42,6 @@ static bool iommu_has_ht_flag(struct amd_iommu *iommu, u8 mask) return iommu->ht_flags & mask; } -static int __init map_iommu_mmio_region(struct amd_iommu *iommu) -{ - iommu->mmio_base = ioremap(iommu->mmio_base_phys, - IOMMU_MMIO_REGION_LENGTH); - if ( !iommu->mmio_base ) - return -ENOMEM; - - memset(iommu->mmio_base, 0, IOMMU_MMIO_REGION_LENGTH); - - return 0; -} - static void __init unmap_iommu_mmio_region(struct amd_iommu *iommu) { if ( iommu->mmio_base ) @@ -1367,11 +1355,14 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) { int rc = alloc_ivrs_mappings(iommu->sbdf.seg); - if ( !rc ) - rc = map_iommu_mmio_region(iommu); if ( rc ) return rc; + iommu->mmio_base = ioremap(iommu->mmio_base_phys, + IOMMU_MMIO_REGION_LENGTH); + if ( !iommu->mmio_base ) + return -ENOMEM; + get_iommu_features(iommu); /* @@ -1381,6 +1372,11 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) if ( amd_iommu_max_paging_mode < amd_iommu_min_paging_mode ) return -ERANGE; + /* Read current control register and forcefully disable the IOMMU. */ + iommu->ctrl.raw = readq(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); + disable_iommu(iommu, true); + iommu->ctrl.raw = 0; + return 0; } -- 2.53.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region 2026-05-06 7:37 ` [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region Roger Pau Monne @ 2026-05-06 8:20 ` Andrew Cooper 2026-05-06 8:32 ` Jan Beulich 2026-05-06 8:58 ` Roger Pau Monné 2026-05-06 8:28 ` Jan Beulich 1 sibling, 2 replies; 15+ messages in thread From: Andrew Cooper @ 2026-05-06 8:20 UTC (permalink / raw) To: Roger Pau Monne, xen-devel Cc: Andrew Cooper, Jan Beulich, Jason Andryuk, Teddy Astie On 06/05/2026 8:37 am, Roger Pau Monne wrote: > Attempting to memset the whole IOMMU MMIO region to zero is dangerous to > say the least. We don't know what registers might be there, neither what > values might be safe for those registers. Minor grammar. "there, nor which values". > On a forthcoming platform doing > the zeroing of the MMIO region can put the IOMMU in a broken state, "does put" > which is not recovered by the IOMMU initialization procedure in Xen. "recoverable". > diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c > index 76ae78e5ea53..8bf5ca4de18f 100644 > --- a/xen/drivers/passthrough/amd/iommu_init.c > +++ b/xen/drivers/passthrough/amd/iommu_init.c > @@ -1367,11 +1355,14 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) > { > int rc = alloc_ivrs_mappings(iommu->sbdf.seg); > > - if ( !rc ) > - rc = map_iommu_mmio_region(iommu); > if ( rc ) > return rc; > > + iommu->mmio_base = ioremap(iommu->mmio_base_phys, > + IOMMU_MMIO_REGION_LENGTH); > + if ( !iommu->mmio_base ) > + return -ENOMEM; > + > get_iommu_features(iommu); > > /* > @@ -1381,6 +1372,11 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) > if ( amd_iommu_max_paging_mode < amd_iommu_min_paging_mode ) > return -ERANGE; > > + /* Read current control register and forcefully disable the IOMMU. */ > + iommu->ctrl.raw = readq(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); > + disable_iommu(iommu, true); > + iommu->ctrl.raw = 0; > + > return 0; > } These two things are unrelated at want splitting into separate patches at a minimum. The removal of memset() critically needs backporting. As for disabling the IOMMU, I'm not certain it's wise. Linux can already "bring up" an already-live IOMMU and Xen needs to gain this ability in due course. This is mainly for supporting PreBoot DMA Protection, but also for things like the kexec environment. ~Andrew ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region 2026-05-06 8:20 ` Andrew Cooper @ 2026-05-06 8:32 ` Jan Beulich 2026-05-06 9:02 ` Andrew Cooper 2026-05-06 8:58 ` Roger Pau Monné 1 sibling, 1 reply; 15+ messages in thread From: Jan Beulich @ 2026-05-06 8:32 UTC (permalink / raw) To: Andrew Cooper; +Cc: Jason Andryuk, Teddy Astie, Roger Pau Monne, xen-devel On 06.05.2026 10:20, Andrew Cooper wrote: > On 06/05/2026 8:37 am, Roger Pau Monne wrote: >> @@ -1367,11 +1355,14 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) >> { >> int rc = alloc_ivrs_mappings(iommu->sbdf.seg); >> >> - if ( !rc ) >> - rc = map_iommu_mmio_region(iommu); >> if ( rc ) >> return rc; >> >> + iommu->mmio_base = ioremap(iommu->mmio_base_phys, >> + IOMMU_MMIO_REGION_LENGTH); >> + if ( !iommu->mmio_base ) >> + return -ENOMEM; >> + >> get_iommu_features(iommu); >> >> /* >> @@ -1381,6 +1372,11 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) >> if ( amd_iommu_max_paging_mode < amd_iommu_min_paging_mode ) >> return -ERANGE; >> >> + /* Read current control register and forcefully disable the IOMMU. */ >> + iommu->ctrl.raw = readq(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); >> + disable_iommu(iommu, true); >> + iommu->ctrl.raw = 0; >> + >> return 0; >> } > > These two things are unrelated at want splitting into separate patches > at a minimum. The removal of memset() critically needs backporting. > > As for disabling the IOMMU, I'm not certain it's wise. > > Linux can already "bring up" an already-live IOMMU and Xen needs to gain > this ability in due course. This is mainly for supporting PreBoot DMA > Protection, but also for things like the kexec environment. While I agree we would better support this, as per my reply to Roger: How is that going to work if the IOMMU has features enabled we may not even be aware of? We'd still need to blindly clear everything we can't drive ourselves. Jan ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region 2026-05-06 8:32 ` Jan Beulich @ 2026-05-06 9:02 ` Andrew Cooper 2026-05-06 9:27 ` Jan Beulich 0 siblings, 1 reply; 15+ messages in thread From: Andrew Cooper @ 2026-05-06 9:02 UTC (permalink / raw) To: Jan Beulich Cc: Andrew Cooper, Jason Andryuk, Teddy Astie, Roger Pau Monne, xen-devel On 06/05/2026 9:32 am, Jan Beulich wrote: > On 06.05.2026 10:20, Andrew Cooper wrote: >> On 06/05/2026 8:37 am, Roger Pau Monne wrote: >>> @@ -1367,11 +1355,14 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) >>> { >>> int rc = alloc_ivrs_mappings(iommu->sbdf.seg); >>> >>> - if ( !rc ) >>> - rc = map_iommu_mmio_region(iommu); >>> if ( rc ) >>> return rc; >>> >>> + iommu->mmio_base = ioremap(iommu->mmio_base_phys, >>> + IOMMU_MMIO_REGION_LENGTH); >>> + if ( !iommu->mmio_base ) >>> + return -ENOMEM; >>> + >>> get_iommu_features(iommu); >>> >>> /* >>> @@ -1381,6 +1372,11 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) >>> if ( amd_iommu_max_paging_mode < amd_iommu_min_paging_mode ) >>> return -ERANGE; >>> >>> + /* Read current control register and forcefully disable the IOMMU. */ >>> + iommu->ctrl.raw = readq(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); >>> + disable_iommu(iommu, true); >>> + iommu->ctrl.raw = 0; >>> + >>> return 0; >>> } >> These two things are unrelated at want splitting into separate patches >> at a minimum. The removal of memset() critically needs backporting. >> >> As for disabling the IOMMU, I'm not certain it's wise. >> >> Linux can already "bring up" an already-live IOMMU and Xen needs to gain >> this ability in due course. This is mainly for supporting PreBoot DMA >> Protection, but also for things like the kexec environment. > While I agree we would better support this, as per my reply to Roger: How > is that going to work if the IOMMU has features enabled we may not even > be aware of? We'd still need to blindly clear everything we can't drive > ourselves. Zeroing 16k of unknown MMIO is completely unreasonable. It is not RAM, and 0 is not a safe thing to write into an unknown register. But to the AMD IOMMU specifically, the spec makes it clear that there are registers configured by firmware that we are expected to leave alone. ~Andrew ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region 2026-05-06 9:02 ` Andrew Cooper @ 2026-05-06 9:27 ` Jan Beulich 0 siblings, 0 replies; 15+ messages in thread From: Jan Beulich @ 2026-05-06 9:27 UTC (permalink / raw) To: Andrew Cooper; +Cc: Jason Andryuk, Teddy Astie, Roger Pau Monne, xen-devel On 06.05.2026 11:02, Andrew Cooper wrote: > On 06/05/2026 9:32 am, Jan Beulich wrote: >> On 06.05.2026 10:20, Andrew Cooper wrote: >>> On 06/05/2026 8:37 am, Roger Pau Monne wrote: >>>> @@ -1367,11 +1355,14 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) >>>> { >>>> int rc = alloc_ivrs_mappings(iommu->sbdf.seg); >>>> >>>> - if ( !rc ) >>>> - rc = map_iommu_mmio_region(iommu); >>>> if ( rc ) >>>> return rc; >>>> >>>> + iommu->mmio_base = ioremap(iommu->mmio_base_phys, >>>> + IOMMU_MMIO_REGION_LENGTH); >>>> + if ( !iommu->mmio_base ) >>>> + return -ENOMEM; >>>> + >>>> get_iommu_features(iommu); >>>> >>>> /* >>>> @@ -1381,6 +1372,11 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) >>>> if ( amd_iommu_max_paging_mode < amd_iommu_min_paging_mode ) >>>> return -ERANGE; >>>> >>>> + /* Read current control register and forcefully disable the IOMMU. */ >>>> + iommu->ctrl.raw = readq(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); >>>> + disable_iommu(iommu, true); >>>> + iommu->ctrl.raw = 0; >>>> + >>>> return 0; >>>> } >>> These two things are unrelated at want splitting into separate patches >>> at a minimum. The removal of memset() critically needs backporting. >>> >>> As for disabling the IOMMU, I'm not certain it's wise. >>> >>> Linux can already "bring up" an already-live IOMMU and Xen needs to gain >>> this ability in due course. This is mainly for supporting PreBoot DMA >>> Protection, but also for things like the kexec environment. >> While I agree we would better support this, as per my reply to Roger: How >> is that going to work if the IOMMU has features enabled we may not even >> be aware of? We'd still need to blindly clear everything we can't drive >> ourselves. > > Zeroing 16k of unknown MMIO is completely unreasonable. It is not RAM, > and 0 is not a safe thing to write into an unknown register. From a very general perspective I agree. However, when adding new registers (or new bits in existing ones), having them default to 0 (and hence making 0 be a valid value) is common practice. > But to the AMD IOMMU specifically, the spec makes it clear that there > are registers configured by firmware that we are expected to leave alone. Well, okay. For firmware settings I think we can assume these would indeed be settings, not enables of any features which would typically require driving by an OS. Yet that still leaves the question (along the lines of what I had raised before) of how we'd deal with being invoked with unknown to us features enabled. We need to disable them, yet how do you suggest doing that without blindly clearing most (if not all) registers? The only clean way of doing that would look to be a "soft reset" command to the IOMMU (of course not to be issued via the command queue). I'm unaware of anything like this, though. Jan ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region 2026-05-06 8:20 ` Andrew Cooper 2026-05-06 8:32 ` Jan Beulich @ 2026-05-06 8:58 ` Roger Pau Monné 2026-05-06 9:41 ` Andrew Cooper 1 sibling, 1 reply; 15+ messages in thread From: Roger Pau Monné @ 2026-05-06 8:58 UTC (permalink / raw) To: Andrew Cooper; +Cc: xen-devel, Jan Beulich, Jason Andryuk, Teddy Astie On Wed, May 06, 2026 at 09:20:07AM +0100, Andrew Cooper wrote: > On 06/05/2026 8:37 am, Roger Pau Monne wrote: > > Attempting to memset the whole IOMMU MMIO region to zero is dangerous to > > say the least. We don't know what registers might be there, neither what > > values might be safe for those registers. > > Minor grammar. "there, nor which values". > > > On a forthcoming platform doing > > the zeroing of the MMIO region can put the IOMMU in a broken state, > > "does put" > > > which is not recovered by the IOMMU initialization procedure in Xen. > > "recoverable". > > > diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c > > index 76ae78e5ea53..8bf5ca4de18f 100644 > > --- a/xen/drivers/passthrough/amd/iommu_init.c > > +++ b/xen/drivers/passthrough/amd/iommu_init.c > > @@ -1367,11 +1355,14 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) > > { > > int rc = alloc_ivrs_mappings(iommu->sbdf.seg); > > > > - if ( !rc ) > > - rc = map_iommu_mmio_region(iommu); > > if ( rc ) > > return rc; > > > > + iommu->mmio_base = ioremap(iommu->mmio_base_phys, > > + IOMMU_MMIO_REGION_LENGTH); > > + if ( !iommu->mmio_base ) > > + return -ENOMEM; > > + > > get_iommu_features(iommu); > > > > /* > > @@ -1381,6 +1372,11 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) > > if ( amd_iommu_max_paging_mode < amd_iommu_min_paging_mode ) > > return -ERANGE; > > > > + /* Read current control register and forcefully disable the IOMMU. */ > > + iommu->ctrl.raw = readq(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); > > + disable_iommu(iommu, true); > > + iommu->ctrl.raw = 0; > > + > > return 0; > > } > > These two things are unrelated at want splitting into separate patches > at a minimum. The removal of memset() critically needs backporting. But is it safe to backport the memset without also backporting the disabling side? We might then be dealing with an enabled IOMMU which could lead to all sorts of fun. > As for disabling the IOMMU, I'm not certain it's wise. > > Linux can already "bring up" an already-live IOMMU and Xen needs to gain > this ability in due course. This is mainly for supporting PreBoot DMA > Protection, but also for things like the kexec environment. Note that Linux (when not booted from kdump) will do a similar sequence of what I'm attempting to do here for Xen and will call iommu_disable() ahead of attempting to enable the IOMMU. I understand that when Xen supports kdump or preboot DMA protection we would need to be more careful there, but going from zeroing the whole MMIO area (which disables everything) to not doing any kind of disabling is IMO a dangerous approach, and I would rather backport a change that at least attempts to make sure the IOMMU is disabled. Thanks, Roger. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region 2026-05-06 8:58 ` Roger Pau Monné @ 2026-05-06 9:41 ` Andrew Cooper 0 siblings, 0 replies; 15+ messages in thread From: Andrew Cooper @ 2026-05-06 9:41 UTC (permalink / raw) To: Roger Pau Monné Cc: Andrew Cooper, xen-devel, Jan Beulich, Jason Andryuk, Teddy Astie On 06/05/2026 9:58 am, Roger Pau Monné wrote: > On Wed, May 06, 2026 at 09:20:07AM +0100, Andrew Cooper wrote: >> On 06/05/2026 8:37 am, Roger Pau Monne wrote: >>> Attempting to memset the whole IOMMU MMIO region to zero is dangerous to >>> say the least. We don't know what registers might be there, neither what >>> values might be safe for those registers. >> Minor grammar. "there, nor which values". >> >>> On a forthcoming platform doing >>> the zeroing of the MMIO region can put the IOMMU in a broken state, >> "does put" >> >>> which is not recovered by the IOMMU initialization procedure in Xen. >> "recoverable". >> >>> diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c >>> index 76ae78e5ea53..8bf5ca4de18f 100644 >>> --- a/xen/drivers/passthrough/amd/iommu_init.c >>> +++ b/xen/drivers/passthrough/amd/iommu_init.c >>> @@ -1367,11 +1355,14 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) >>> { >>> int rc = alloc_ivrs_mappings(iommu->sbdf.seg); >>> >>> - if ( !rc ) >>> - rc = map_iommu_mmio_region(iommu); >>> if ( rc ) >>> return rc; >>> >>> + iommu->mmio_base = ioremap(iommu->mmio_base_phys, >>> + IOMMU_MMIO_REGION_LENGTH); >>> + if ( !iommu->mmio_base ) >>> + return -ENOMEM; >>> + >>> get_iommu_features(iommu); >>> >>> /* >>> @@ -1381,6 +1372,11 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) >>> if ( amd_iommu_max_paging_mode < amd_iommu_min_paging_mode ) >>> return -ERANGE; >>> >>> + /* Read current control register and forcefully disable the IOMMU. */ >>> + iommu->ctrl.raw = readq(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); >>> + disable_iommu(iommu, true); >>> + iommu->ctrl.raw = 0; >>> + >>> return 0; >>> } >> These two things are unrelated at want splitting into separate patches >> at a minimum. The removal of memset() critically needs backporting. > But is it safe to backport the memset without also backporting the > disabling side? We might then be dealing with an enabled IOMMU which > could lead to all sorts of fun. I would absolutely take working with a potentially active IOMMU over zeroing the registers which don't appear in the public documentation. This is where BIOS norms save us. The IOMMU can't be enabled without active OS negotiation, or DoS wouldn't be able to boot. It is only in the past couple of years where this has not been the base compatibility case on all systems. But I see your point. Given that we were clearing the main enable bit, we ought to continue to do so for backport purposes. It would be nice to have a printk_once() in there so we can spot when the IOMMU is enabled. I expect it not to trigger but if it does trigger, we've got more investigation to do. >> As for disabling the IOMMU, I'm not certain it's wise. >> >> Linux can already "bring up" an already-live IOMMU and Xen needs to gain >> this ability in due course. This is mainly for supporting PreBoot DMA >> Protection, but also for things like the kexec environment. > Note that Linux (when not booted from kdump) will do a similar sequence of > what I'm attempting to do here for Xen and will call iommu_disable() > ahead of attempting to enable the IOMMU. Lovely... That's broken. The AMD IOMMU makes this especially easy to do. Each of the ring buffers have enable bits separate to the general IOMMU enable, so you can temporary disable, move the buffer and clear the ring pointers, then re-enable. What is critical for Preboot DMA protection is that DMA translation doesn't get turned off. ~Andrew ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region 2026-05-06 7:37 ` [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region Roger Pau Monne 2026-05-06 8:20 ` Andrew Cooper @ 2026-05-06 8:28 ` Jan Beulich 2026-05-06 8:43 ` Roger Pau Monné 1 sibling, 1 reply; 15+ messages in thread From: Jan Beulich @ 2026-05-06 8:28 UTC (permalink / raw) To: Roger Pau Monne; +Cc: Andrew Cooper, Jason Andryuk, Teddy Astie, xen-devel On 06.05.2026 09:37, Roger Pau Monne wrote: > @@ -1381,6 +1372,11 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) > if ( amd_iommu_max_paging_mode < amd_iommu_min_paging_mode ) > return -ERANGE; > > + /* Read current control register and forcefully disable the IOMMU. */ > + iommu->ctrl.raw = readq(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); > + disable_iommu(iommu, true); Don't you also need to pre-fill iommu->features? And with that field's use in disable_iommu(), won't we be at risk of leaving stuff enabled which we are entirely unaware of? Even if we fully cleared the control register (which would eliminate the need to fetch features), down the road a 2nd control register could appear. Has it become clear which register(s) or bit(s) it really is that are causing the observed issue? IOW is there truly something we may not clear? Or is it maybe that memset() really isn't suitable for use against MMIO, especially after having switched to use of REP MOVSB when ERMS is available? Jan ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region 2026-05-06 8:28 ` Jan Beulich @ 2026-05-06 8:43 ` Roger Pau Monné 2026-05-06 9:17 ` Jan Beulich 0 siblings, 1 reply; 15+ messages in thread From: Roger Pau Monné @ 2026-05-06 8:43 UTC (permalink / raw) To: Jan Beulich; +Cc: Andrew Cooper, Jason Andryuk, Teddy Astie, xen-devel On Wed, May 06, 2026 at 10:28:52AM +0200, Jan Beulich wrote: > On 06.05.2026 09:37, Roger Pau Monne wrote: > > @@ -1381,6 +1372,11 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) > > if ( amd_iommu_max_paging_mode < amd_iommu_min_paging_mode ) > > return -ERANGE; > > > > + /* Read current control register and forcefully disable the IOMMU. */ > > + iommu->ctrl.raw = readq(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); > > + disable_iommu(iommu, true); > > Don't you also need to pre-fill iommu->features? Indeed, that's done just ahead of this chunk, in the get_iommu_features() call. > And with that field's use in > disable_iommu(), won't we be at risk of leaving stuff enabled which we are > entirely unaware of? Possibly, yes, that's always a risk. > Even if we fully cleared the control register (which > would eliminate the need to fetch features), down the road a 2nd control > register could appear. We do clear the control register, it's indirectly done by us setting iommu->ctrl.raw = 0 after the disable_iommu() call. I did wonder about just doing a write of 0 to the control register, but I think it's best if we try to gracefully disable the features (as done in disable_iommu()), and then reset the cached control state to 0. Future writes to the control register will clear any bits not directly set by Xen. > Has it become clear which register(s) or bit(s) it > really is that are causing the observed issue? IOW is there truly something > we may not clear? It's not so much as not clearing something, but rather the clearing itself putting the IOMMU in a broken state which we then can't recover from using the initialization procedure in Xen. Thanks, Roger. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region 2026-05-06 8:43 ` Roger Pau Monné @ 2026-05-06 9:17 ` Jan Beulich 2026-05-06 9:20 ` Roger Pau Monné 0 siblings, 1 reply; 15+ messages in thread From: Jan Beulich @ 2026-05-06 9:17 UTC (permalink / raw) To: Roger Pau Monné; +Cc: Andrew Cooper, Jason Andryuk, Teddy Astie, xen-devel On 06.05.2026 10:43, Roger Pau Monné wrote: > On Wed, May 06, 2026 at 10:28:52AM +0200, Jan Beulich wrote: >> On 06.05.2026 09:37, Roger Pau Monne wrote: >>> @@ -1381,6 +1372,11 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) >>> if ( amd_iommu_max_paging_mode < amd_iommu_min_paging_mode ) >>> return -ERANGE; >>> >>> + /* Read current control register and forcefully disable the IOMMU. */ >>> + iommu->ctrl.raw = readq(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); >>> + disable_iommu(iommu, true); >> >> Don't you also need to pre-fill iommu->features? > > Indeed, that's done just ahead of this chunk, in the > get_iommu_features() call. > >> And with that field's use in >> disable_iommu(), won't we be at risk of leaving stuff enabled which we are >> entirely unaware of? > > Possibly, yes, that's always a risk. > >> Even if we fully cleared the control register (which >> would eliminate the need to fetch features), down the road a 2nd control >> register could appear. > > We do clear the control register, it's indirectly done by us setting > iommu->ctrl.raw = 0 after the disable_iommu() call. > > I did wonder about just doing a write of 0 to the control register, > but I think it's best if we try to gracefully disable the features (as > done in disable_iommu()), and then reset the cached control state to > 0. Future writes to the control register will clear any bits not > directly set by Xen. Maybe better to explicitly write out that 0 right away, even if you want to keep using disable_iommu()? Jan ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region 2026-05-06 9:17 ` Jan Beulich @ 2026-05-06 9:20 ` Roger Pau Monné 2026-05-06 9:28 ` Jan Beulich 0 siblings, 1 reply; 15+ messages in thread From: Roger Pau Monné @ 2026-05-06 9:20 UTC (permalink / raw) To: Jan Beulich; +Cc: Andrew Cooper, Jason Andryuk, Teddy Astie, xen-devel On Wed, May 06, 2026 at 11:17:25AM +0200, Jan Beulich wrote: > On 06.05.2026 10:43, Roger Pau Monné wrote: > > On Wed, May 06, 2026 at 10:28:52AM +0200, Jan Beulich wrote: > >> On 06.05.2026 09:37, Roger Pau Monne wrote: > >>> @@ -1381,6 +1372,11 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) > >>> if ( amd_iommu_max_paging_mode < amd_iommu_min_paging_mode ) > >>> return -ERANGE; > >>> > >>> + /* Read current control register and forcefully disable the IOMMU. */ > >>> + iommu->ctrl.raw = readq(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); > >>> + disable_iommu(iommu, true); > >> > >> Don't you also need to pre-fill iommu->features? > > > > Indeed, that's done just ahead of this chunk, in the > > get_iommu_features() call. > > > >> And with that field's use in > >> disable_iommu(), won't we be at risk of leaving stuff enabled which we are > >> entirely unaware of? > > > > Possibly, yes, that's always a risk. > > > >> Even if we fully cleared the control register (which > >> would eliminate the need to fetch features), down the road a 2nd control > >> register could appear. > > > > We do clear the control register, it's indirectly done by us setting > > iommu->ctrl.raw = 0 after the disable_iommu() call. > > > > I did wonder about just doing a write of 0 to the control register, > > but I think it's best if we try to gracefully disable the features (as > > done in disable_iommu()), and then reset the cached control state to > > 0. Future writes to the control register will clear any bits not > > directly set by Xen. > > Maybe better to explicitly write out that 0 right away, even if you want > to keep using disable_iommu()? Yeah, I also considered that. So after disable_iommu() set the cached control state to 0 and also zero the control register right there. Can do in the next version, unless there are further objections. Thanks, Roger. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region 2026-05-06 9:20 ` Roger Pau Monné @ 2026-05-06 9:28 ` Jan Beulich 0 siblings, 0 replies; 15+ messages in thread From: Jan Beulich @ 2026-05-06 9:28 UTC (permalink / raw) To: Roger Pau Monné; +Cc: Andrew Cooper, Jason Andryuk, Teddy Astie, xen-devel On 06.05.2026 11:20, Roger Pau Monné wrote: > On Wed, May 06, 2026 at 11:17:25AM +0200, Jan Beulich wrote: >> On 06.05.2026 10:43, Roger Pau Monné wrote: >>> On Wed, May 06, 2026 at 10:28:52AM +0200, Jan Beulich wrote: >>>> On 06.05.2026 09:37, Roger Pau Monne wrote: >>>>> @@ -1381,6 +1372,11 @@ static int __init amd_iommu_prepare_one(struct amd_iommu *iommu) >>>>> if ( amd_iommu_max_paging_mode < amd_iommu_min_paging_mode ) >>>>> return -ERANGE; >>>>> >>>>> + /* Read current control register and forcefully disable the IOMMU. */ >>>>> + iommu->ctrl.raw = readq(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); >>>>> + disable_iommu(iommu, true); >>>> >>>> Don't you also need to pre-fill iommu->features? >>> >>> Indeed, that's done just ahead of this chunk, in the >>> get_iommu_features() call. >>> >>>> And with that field's use in >>>> disable_iommu(), won't we be at risk of leaving stuff enabled which we are >>>> entirely unaware of? >>> >>> Possibly, yes, that's always a risk. >>> >>>> Even if we fully cleared the control register (which >>>> would eliminate the need to fetch features), down the road a 2nd control >>>> register could appear. >>> >>> We do clear the control register, it's indirectly done by us setting >>> iommu->ctrl.raw = 0 after the disable_iommu() call. >>> >>> I did wonder about just doing a write of 0 to the control register, >>> but I think it's best if we try to gracefully disable the features (as >>> done in disable_iommu()), and then reset the cached control state to >>> 0. Future writes to the control register will clear any bits not >>> directly set by Xen. >> >> Maybe better to explicitly write out that 0 right away, even if you want >> to keep using disable_iommu()? > > Yeah, I also considered that. So after disable_iommu() set the cached > control state to 0 and also zero the control register right there. > Can do in the next version, unless there are further objections. Well, as said - I'm wary of fully dropping the memset(). It may help now, but it could easily cause issues later. Jan ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-05-06 9:42 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-06 7:37 [PATCH 0/2] iommu/amd-vi: remove zeroing of MMIO region Roger Pau Monne 2026-05-06 7:37 ` [PATCH 1/2] iommu/amd-vi: allow disable_iommu() against non-initialized IOMMUs Roger Pau Monne 2026-05-06 8:19 ` Jan Beulich 2026-05-06 7:37 ` [PATCH 2/2] iommu/amd-vi: do not zero IOMMU MMIO region Roger Pau Monne 2026-05-06 8:20 ` Andrew Cooper 2026-05-06 8:32 ` Jan Beulich 2026-05-06 9:02 ` Andrew Cooper 2026-05-06 9:27 ` Jan Beulich 2026-05-06 8:58 ` Roger Pau Monné 2026-05-06 9:41 ` Andrew Cooper 2026-05-06 8:28 ` Jan Beulich 2026-05-06 8:43 ` Roger Pau Monné 2026-05-06 9:17 ` Jan Beulich 2026-05-06 9:20 ` Roger Pau Monné 2026-05-06 9:28 ` Jan Beulich
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.