iommu/arm-smmu-v3: Fix device crash on kdump kernel
Subsystems (3)
v7 cover iommu/arm-smmu-v3: Fix device crash on kdump kernel
When transitioning to a kdump kernel, the primary kernel might have crashed while endpoint devices were actively bus-mastering DMA. Currently, the SMMU driver aggressively resets the hardware during probe by clearing CR0_SMMUEN and setting the Global Bypass Attribute (GBPA) to ABORT.
In a kdump scenario, this aggressive reset is highly destructive:
a) If GBPA is set to ABORT, in-flight DMA will be aborted, generating fatal PCIe AER or SErrors that may panic the kdump kernel
b) If GBPA is set to BYPASS, in-flight DMA targeting some IOVAs will bypass the SMMU and corrupt the physical memory at those 1:1 mapped IOVAs.
To safely absorb in-flight DMA, the kdump kernel must leave SMMUEN=1 intact and avoid modifying STRTAB_BASE. This allows HW to continue translating in- flight DMA using the crashed kernel's page tables until the endpoint device drivers probe and quiesce their respective hardware.
However, the ARM SMMUv3 architecture specification states that updating the SMMU_STRTAB_BASE register while SMMUEN == 1 is UNPREDICTABLE or ignored.
This leaves a kdump kernel no choice but to adopt the stream table from the crashed kernel.
In this series:
- Introduce an ARM_SMMU_OPT_KDUMP_ADOPT
- Skip SMMUEN and STRTAB_BASE resets in arm_smmu_device_reset()
- Skip EVENTQ/PRIQ setup including interrupts and their handlers
- Memremap the crashed kernel's stream tables into the kdump kernel [*]
- Defer any default domain attachment to retain STEs until device drivers explicitly request it.
[*] For verification reasons, this series only fixes coherent SMMUs.
For non-ARM_SMMU_OPT_KDUMP_ADOPT cases, keep a status quo since the commit 3f54c447df34f ("iommu/arm-smmu-v3: Don't disable SMMU in kdump kernel"):
full reset followed by driver-initiated reattach, potentially rejecting any in-flight DMA.
Note that the series requires Jason's work that was merged in v6.12: commit 85196f54743d ("iommu/arm-smmu-v3: Reorganize struct arm_smmu_strtab_cfg"). I have a backported version that is verified with a v6.8 kernel. I can send if we see a strong need after this version is accepted.
This is on Github:
https://github.com/nicolinc/iommufd/commits/smmuv3_kdump-v7
Changelog
v7
* Rebase v7.2-rc1
* Add Reviewed-by from Pranjal
* Reword the linear stream table adoption comment
* Use dev_dbg for the stream table adoption message
* Document why the lazy L2 adoption uses devm_memremap()
* Drop redundant FEAT_COHERENCY checks in the adopt functions
* Use feature bit instead of STRTAB_BASE_CFG in adopt cleanup
* Skip CR0_ATSCHK update in adopt mode to retain the crashed policy
* Restore FEAT_2_LVL_STRTAB if the cleanup action fails to register
v6
https://lore.kernel.org/all/[email protected]/
* Rebase v7.1-rc3
* Add Reviewed-by from Jason
* Replace dma_addr_t with phys_addr_t
* Drop arm_smmu_kdump_phys_is_corrupted()
* Skip threaded IRQ handlers for EVTQ and PRIQ
* Bypass arm_smmu_rmr_install_bypass_ste() in kdump case
* Drop devm_ for adopt-time allocations; set up cleanup function via devm_add_action_or_reset()
v5
https://lore.kernel.org/all/[email protected]/
* Add Reviewed-by from Kevin
* Drop READ_ONCE on lazy-attach L1 read
* Split "Skip EVTQ/PRIQ setup" into two patches
* Tighten kdump probe comment and dev_warn message
* Use MEM + BUSY in arm_smmu_kdump_phys_is_corrupted
v4
https://lore.kernel.org/all/[email protected]/
* Rebase v7.1-rc1
* s/arm_smmu_adopt/arm_smmu_kdump_adopt
* Revert alloc/memremap/fmt on fallback
* Reorder patches to avoid bisect regression
* Use IRQ_NONE for spurious evtq/priq entries
* Cap linear log2size by kdump's allocation bound
* Defer clearing FEAT_2_LVL_STRTAB on linear adopt
* Add arm_smmu_kdump_phys_is_corrupted() validation
* Defer l2 stream table memremap till master inserts
* Re-validate L1 desc on master insert with READ_ONCE
v3
https://lore.kernel.org/all/[email protected]/
* s/OPT_KDUMP/OPT_KDUMP_ADOPT
* Do not adopt if GERROR_SFM_ERR
* Retain CR0_ATSCHK beside CR0_SMMUEN
* Clear latched GERROR bits (e.g. CMDQ_ERR)
* Assert ARM_SMMU_FEAT_COHERENCY in adopt functions
* Add STE.Cfg check in arm_smmu_is_attach_deferred()
* Fix validations on return codes from devm_memremap()
* Sanitize crashed kernel register values in adopt functions
* Drop unnecessary l2ptrs guard in arm_smmu_is_attach_deferred()
* Don't enable PRIQ/EVTQ irqs and guard the irq functions for combined irq cases
v2
https://lore.kernel.org/all/[email protected]/
* Add warning in non-coherent SMMU cases
* Keep eventq/priq disabled vs. enabling-and-disabling-later
* Check KDUMP option in the beginning of arm_smmu_device_reset()
* Validate STRTAB format matches HW capability instead of forcing flags
v1:
https://lore.kernel.org/all/[email protected]/
Nicolin Chen (7):
iommu/arm-smmu-v3: Add arm_smmu_kdump_adopt_strtab() for kdump iommu/arm-smmu-v3: Implement is_attach_deferred() for kdump iommu/arm-smmu-v3: Do not enable EVTQ/PRIQ interrupts in kdump kernel iommu/arm-smmu-v3: Skip EVTQ/PRIQ setup in kdump kernel iommu/arm-smmu-v3: Retain CR0_SMMUEN during kdump device reset iommu/arm-smmu-v3: Skip RMR bypass for kdump adoption iommu/arm-smmu-v3: Detect ARM_SMMU_OPT_KDUMP_ADOPT in probe()
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 + drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 467 ++++++++++++++++++-- 2 files changed, 422 insertions(+), 46 deletions(-)
Signature · 1 line
2.43.0
PATCH v7 1/7 iommu/arm-smmu-v3: Add arm_smmu_kdump_adopt_strtab() for kdump
When transitioning to a kdump kernel, the primary kernel might have crashed while endpoint devices were actively bus-mastering DMA. Currently, the SMMU driver aggressively resets the hardware during probe by clearing CR0_SMMUEN and setting the Global Bypass Attribute (GBPA) to ABORT.
In a kdump scenario, this aggressive reset is highly destructive:
a) If GBPA is set to ABORT, in-flight DMA will be aborted, generating fatal PCIe AER or SErrors that may panic the kdump kernel
b) If GBPA is set to BYPASS, in-flight DMA targeting some IOVAs will bypass the SMMU and corrupt the physical memory at those 1:1 mapped IOVAs.
To safely absorb in-flight DMAs, a kdump kernel will have to leave SMMUEN=1 intact and avoid modifying STRTAB_BASE, allowing HW to continue translating in-flight DMAs reusing the crashed kernel's page tables until the endpoint device drivers probe and quiesce their respective hardware.
However, the ARM SMMUv3 architecture specification states that updating the SMMU_STRTAB_BASE register while SMMUEN == 1 is UNPREDICTABLE or ignored.
This leaves a kdump kernel no choice but to adopt the stream table from the crashed kernel.
Introduce ARM_SMMU_OPT_KDUMP_ADOPT and adopt functions memremapping all the stream tables extracted from STRTAB_BASE and STRTAB_BASE_CFG.
Note that the adoption of the crashed kernel's stream table follows certain strict rules, since the old stream table might be compromised. Thus, apply some basic validations against the values read from the registers. If tests fail, it means the stream table cannot be trusted, so toss it entirely. To avoid OOM due to a potentially corrupted stream table, the memremap for l2 tables is done on the kdump kernel's demand.
The new option will be set in a following change.
--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 + drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 244 +++++++++++++++++++- 2 files changed, 242 insertions(+), 3 deletions(-)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +1 -0
@@ -928,6 +928,7 @@ struct arm_smmu_device {#define ARM_SMMU_OPT_MSIPOLL (1 << 2)#define ARM_SMMU_OPT_CMDQ_FORCE_SYNC (1 << 3)#define ARM_SMMU_OPT_TEGRA241_CMDQV (1 << 4) +#define ARM_SMMU_OPT_KDUMP_ADOPT (1 << 5)u32 options;struct arm_smmu_cmdq cmdq;
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +241 -3
281 lines not on this page · raw message
Signature · 1 line
2.43.0
PATCH v7 2/7 iommu/arm-smmu-v3: Implement is_attach_deferred() for kdump
In reply to Nicolin ChenThough the kdump kernel adopts the crashed kernel's stream table, the iommu core will still try to attach each probed device to a default domain, which overwrites the adopted STE and breaks in-flight DMA from that device.
Implement an is_attach_deferred() callback to prevent this. For each device that has STE.V=1 and STE.Cfg!=Abort in the adopted table, defer the default domain attachment, until the device driver explicitly requests it.
--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 24 +++++++++++++++++++++ 1 file changed, 24 insertions(+)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +24 -0
@@ -4198,6 +4198,29 @@ static int arm_smmu_master_prepare_ats(struct arm_smmu_master *master)return arm_smmu_alloc_cd_tables (master); } +static bool arm_smmu_is_attach_deferred (struct device *dev) +{ +struct arm_smmu_master *master =dev_iommu_priv_get (dev); +struct arm_smmu_device *smmu = master->smmu; +int i; + +if (!(smmu->options &ARM_SMMU_OPT_KDUMP_ADOPT )) +return false; + +for (i =0 ; i < master->num_streams; i++) { +struct arm_smmu_ste *ste = +arm_smmu_get_step_for_sid (smmu, master->streams[i].id); +u64 ent0 =le64_to_cpu (ste->data[0 ]); + +/* Defer only when there might be in-flight DMAs */ +if ((ent0 &STRTAB_STE_0_V ) && +FIELD_GET (STRTAB_STE_0_CFG , ent0) !=STRTAB_STE_0_CFG_ABORT ) +return true; + } + +return false; +} +static struct iommu_device *arm_smmu_probe_device (struct device *dev) {int ret;
@@ -4361,6 +4384,7 @@ static const struct iommu_ops arm_smmu_ops = { .hw_info = arm_smmu_hw_info, .domain_alloc_sva = arm_smmu_sva_domain_alloc, .domain_alloc_paging_flags = arm_smmu_domain_alloc_paging_flags, + .is_attach_deferred = arm_smmu_is_attach_deferred, .probe_device = arm_smmu_probe_device, .release_device = arm_smmu_release_device, .device_group = arm_smmu_device_group,
Signature · 1 line
2.43.0
PATCH v7 3/7 iommu/arm-smmu-v3: Do not enable EVTQ/PRIQ interrupts in kdump kernel
In reply to Nicolin ChenIn kdump cases, the crashed kernel's CDs and page tables can be corrupted, which could trigger event spamming. Also, we cannot serve page requests.
Skip the IRQ setup for EVTQ/PRIQ in arm_smmu_setup_irqs().
Skip their IRQ handler registration in unique-IRQ and combined-IRQ cases.
--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 58 ++++++++++++++------- 1 file changed, 39 insertions(+), 19 deletions(-)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +39 -19
@@ -2344,7 +2344,11 @@ static irqreturn_t arm_smmu_combined_irq_thread(int irq, void *dev)static irqreturn_t arm_smmu_combined_irq_handler (int irq,void *dev) { -arm_smmu_gerror_handler (irq, dev); +irqreturn_t ret =arm_smmu_gerror_handler (irq, dev); + +/* In kdump, EVTQ/PRIQ are disabled and there is no thread to wake */ +if (is_kdump_kernel ()) +return ret;return IRQ_WAKE_THREAD ; }
@@ -4887,6 +4891,21 @@ static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu)arm_smmu_setup_msis (smmu);/* Request interrupt lines */ + irq = smmu->gerr_irq; +if (irq) { + ret =devm_request_irq (smmu->dev, irq, arm_smmu_gerror_handler, +0 ,"arm-smmu-v3-gerror" , smmu); +if (ret <0 ) +dev_warn (smmu->dev,"failed to enable gerror irq\n" ); + }else { +dev_warn (smmu->dev, +"no gerr irq - errors will not be reported!\n" ); + } + +/* No EVTQ/PRIQ interrupts in kdump -- queues are disabled */ +if (is_kdump_kernel ()) +return ; + irq = smmu->evtq.q.irq;if (irq) { ret = devm_request_threaded_irq(smmu->dev, irq, NULL,
@@ -4899,16 +4918,6 @@ static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu)dev_warn (smmu->dev,"no evtq irq - events will not be reported!\n" ); } - irq = smmu->gerr_irq; -if (irq) { - ret =devm_request_irq (smmu->dev, irq, arm_smmu_gerror_handler, -0 ,"arm-smmu-v3-gerror" , smmu); -if (ret <0 ) -dev_warn (smmu->dev,"failed to enable gerror irq\n" ); - }else { -dev_warn (smmu->dev,"no gerr irq - errors will not be reported!\n" ); - } -if (smmu->features &ARM_SMMU_FEAT_PRI ) { irq = smmu->priq.q.irq;if (irq) {
@@ -4929,7 +4938,7 @@ static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu)static int arm_smmu_setup_irqs (struct arm_smmu_device *smmu) {int ret, irq; -u32 irqen_flags =IRQ_CTRL_EVTQ_IRQEN |IRQ_CTRL_GERROR_IRQEN ; +u32 irqen_flags =IRQ_CTRL_GERROR_IRQEN ;/* Disable IRQs first */ ret = arm_smmu_write_reg_sync(smmu, 0, ARM_SMMU_IRQ_CTRL,
@@ -4944,19 +4953,30 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)/* * Cavium ThunderX2 implementation doesn't support unique irq * lines. Use a single irq line for all the SMMUv3 interrupts. +* +* In kdump, EVTQ/PRIQ are disabled, so no threaded handling. */ - ret =devm_request_threaded_irq (smmu->dev, irq, - arm_smmu_combined_irq_handler, - arm_smmu_combined_irq_thread, -IRQF_ONESHOT , -"arm-smmu-v3-combined-irq" , smmu); +if (is_kdump_kernel ()) + ret =devm_request_irq (smmu->dev, irq, + arm_smmu_combined_irq_handler,0 , +"arm-smmu-v3-combined-irq" , + smmu); +else + ret =devm_request_threaded_irq ( + smmu->dev, irq, arm_smmu_combined_irq_handler, + arm_smmu_combined_irq_thread,IRQF_ONESHOT , +"arm-smmu-v3-combined-irq" , smmu);if (ret <0 )dev_warn (smmu->dev,"failed to enable combined irq\n" ); }else arm_smmu_setup_unique_irqs (smmu); -if (smmu->features &ARM_SMMU_FEAT_PRI ) - irqen_flags |=IRQ_CTRL_PRIQ_IRQEN ; +/* No EVTQ/PRIQ IRQ generation in kdump -- queues are disabled */ +if (!is_kdump_kernel ()) { + irqen_flags |=IRQ_CTRL_EVTQ_IRQEN ; +if (smmu->features &ARM_SMMU_FEAT_PRI ) + irqen_flags |=IRQ_CTRL_PRIQ_IRQEN ; + }/* Enable interrupt generation on the SMMU */ ret = arm_smmu_write_reg_sync(smmu, irqen_flags,
Signature · 1 line
2.43.0
PATCH v7 4/7 iommu/arm-smmu-v3: Skip EVTQ/PRIQ setup in kdump kernel
In reply to Nicolin ChenIn kdump cases, the crashed kernel's CDs and page tables can be corrupted, which could trigger event spamming. Also, we cannot serve page requests.
Skip the EVTQ/PRIQ setup entirely rather than enabling then disabling them.
Also add some inline comments explaining that.
--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 43 +++++++++++++-------- 1 file changed, 27 insertions(+), 16 deletions(-)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +27 -16
@@ -5083,21 +5083,35 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu)arm_smmu_cmdq_issue_cmd_with_sync ( smmu,arm_smmu_make_cmd_op (CMDQ_OP_TLBI_NSNH_ALL )); -/* Event queue */ -writeq_relaxed (smmu->evtq.q.q_base, smmu->base +ARM_SMMU_EVTQ_BASE ); -writel_relaxed (smmu->evtq.q.llq.prod, smmu->page1 +ARM_SMMU_EVTQ_PROD ); -writel_relaxed (smmu->evtq.q.llq.cons, smmu->page1 +ARM_SMMU_EVTQ_CONS ); - - enables |=CR0_EVTQEN ; - ret =arm_smmu_write_reg_sync (smmu, enables,ARM_SMMU_CR0 , -ARM_SMMU_CR0ACK ); -if (ret) { -dev_err (smmu->dev,"failed to enable event queue\n" ); -return ret; +/* +* Event queue +* +* Do not enable in a kdump case, as the crashed kernel's CDs and page +* tables might be corrupted, triggering event spamming. +*/ +if (!is_kdump_kernel ()) { +writeq_relaxed (smmu->evtq.q.q_base, + smmu->base +ARM_SMMU_EVTQ_BASE ); +writel_relaxed (smmu->evtq.q.llq.prod, + smmu->page1 +ARM_SMMU_EVTQ_PROD ); +writel_relaxed (smmu->evtq.q.llq.cons, + smmu->page1 +ARM_SMMU_EVTQ_CONS ); + + enables |=CR0_EVTQEN ; + ret =arm_smmu_write_reg_sync (smmu, enables,ARM_SMMU_CR0 , +ARM_SMMU_CR0ACK ); +if (ret) { +dev_err (smmu->dev,"failed to enable event queue\n" ); +return ret; + } } -/* PRI queue */ -if (smmu->features &ARM_SMMU_FEAT_PRI ) { +/* +* PRI queue +* +* Do not enable in a kdump case, as we cannot serve page requests. +*/ +if (!is_kdump_kernel () && (smmu->features &ARM_SMMU_FEAT_PRI )) {writeq_relaxed (smmu->priq.q.q_base, smmu->base +ARM_SMMU_PRIQ_BASE ); writel_relaxed(smmu->priq.q.llq.prod,
@@ -5130,9 +5144,6 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu)return ret; } -if (is_kdump_kernel ()) - enables &= ~(CR0_EVTQEN |CR0_PRIQEN ); -/* Enable the SMMU interface */ enables |=CR0_SMMUEN ; ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
Signature · 1 line
2.43.0
PATCH v7 5/7 iommu/arm-smmu-v3: Retain CR0_SMMUEN during kdump device reset
In reply to Nicolin ChenWhen ARM_SMMU_OPT_KDUMP_ADOPT is detected, do not disable SMMUEN and skip the CR1/CR2/STRTAB_BASE update sequence in arm_smmu_device_reset(). Those register writes are all CONSTRAINED UNPREDICTABLE while CR0_SMMUEN==1, so leaving them intact lets in-flight DMAs continue to be translated by the adopted stream table.
Initialize 'enables' to 0 so it can carry CR0_SMMUEN in kdump case. Then, preserve that when enabling the command queue.
Clear latched gerror bits if necessary.
--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 54 +++++++++++++++++++-- 1 file changed, 50 insertions(+), 4 deletions(-)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +50 -4
@@ -5025,10 +5025,27 @@ static void arm_smmu_write_strtab(struct arm_smmu_device *smmu)static int arm_smmu_device_reset (struct arm_smmu_device *smmu) {int ret; -u32 reg, enables; +u32 reg, enables =0 ; -/* Clear CR0 and sync (disables SMMU and queue processing) */ reg =readl_relaxed (smmu->base +ARM_SMMU_CR0 ); + +/* +* In a kdump case (set when CR0_SMMUEN=1 and !GERROR_SFM_ERR), retain +* CR0_SMMUEN to avoid aborting in-flight DMA, and CR0_ATSCHK to carry +* on the ATS-check policy. +* +* According to spec, updating STRTAB_BASE/CR1/CR2 when CR0_SMMUEN=1 is +* CONSTRAINED UNPREDICTABLE. So, skip those register updates and rely +* on the adopted stream table from the crashed kernel. +*/ +if (smmu->options &ARM_SMMU_OPT_KDUMP_ADOPT ) { +dev_info (smmu->dev, +"kdump: retaining SMMUEN for in-flight DMA\n" ); + enables = reg & (CR0_SMMUEN |CR0_ATSCHK ); + goto reset_queues; + } + +/* Clear CR0 and sync (disables SMMU and queue processing) */ if (reg &CR0_SMMUEN ) {dev_warn (smmu->dev,"SMMU currently enabled! Resetting...\n" );arm_smmu_update_gbpa (smmu,GBPA_ABORT ,0 );
@@ -5058,12 +5075,36 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu)/* Stream table */ arm_smmu_write_strtab (smmu); +reset_queues: +if (smmu->options &ARM_SMMU_OPT_KDUMP_ADOPT ) { +/* Disable queues since arm_smmu_device_disable() was skipped */ + ret =arm_smmu_write_reg_sync (smmu, enables,ARM_SMMU_CR0 , +ARM_SMMU_CR0ACK ); +if (ret) { +dev_err (smmu->dev,"failed to disable queues\n" ); +return ret; + } + } + +/* +* GERROR bits are latched. Read after queue disabling so that unhandled +* errors would be visible. Ack everything prior to re-enabling the CMDQ +* as a stale CMDQ_ERR would halt the CMDQ and new command will timeout. +*/ +if (is_kdump_kernel ()) { +u32 gerror =readl_relaxed (smmu->base +ARM_SMMU_GERROR ); +u32 gerrorn =readl_relaxed (smmu->base +ARM_SMMU_GERRORN ); + +if ((gerror ^ gerrorn) &GERROR_ERR_MASK ) +writel (gerror, smmu->base +ARM_SMMU_GERRORN ); + } +/* Command queue */ writeq_relaxed (smmu->cmdq.q.q_base, smmu->base +ARM_SMMU_CMDQ_BASE );writel_relaxed (smmu->cmdq.q.llq.prod, smmu->base +ARM_SMMU_CMDQ_PROD );writel_relaxed (smmu->cmdq.q.llq.cons, smmu->base +ARM_SMMU_CMDQ_CONS ); - enables =CR0_CMDQEN ; + enables |=CR0_CMDQEN ; ret =arm_smmu_write_reg_sync (smmu, enables,ARM_SMMU_CR0 ,ARM_SMMU_CR0ACK );if (ret) {
@@ -5128,7 +5169,12 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu) } } -if (smmu->features &ARM_SMMU_FEAT_ATS ) { +/* +* In a kdump adopt case, retain the crashed kernel's ATS-check policy +* captured above rather than forcing it on. +*/ +if (!(smmu->options &ARM_SMMU_OPT_KDUMP_ADOPT ) && + (smmu->features &ARM_SMMU_FEAT_ATS )) { enables |=CR0_ATSCHK ; ret =arm_smmu_write_reg_sync (smmu, enables,ARM_SMMU_CR0 ,ARM_SMMU_CR0ACK );
Signature · 1 line
2.43.0
PATCH v7 6/7 iommu/arm-smmu-v3: Skip RMR bypass for kdump adoption
In reply to Nicolin ChenRMR bypass STEs are installed during SMMUv3 probe for StreamIDs listed by IORT RMR nodes. A normal boot switches the driver to a fresh stream table whose initial STEs abort, so those RMR SIDs need bypass entries before it becomes live. This preserves firmware/guest-owned traffic, including vSMMU guest MSI cases built around RMR-described SIDs.
ARM_SMMU_OPT_KDUMP_ADOPT is the opposite case: the driver keeps SMMUEN set and adopts the crashed kernel's stream table, so RMR SIDs already have the only translation state known to be safe for active in-flight DMA. Replacing an adopted STE with bypass can turn translated DMA into physical DMA, then point it at the wrong memory.
arm_smmu_make_bypass_ste() also rewrites the STE in place after clearing it first. While the table is live, a concurrent hardware STE fetch can observe V=0 or mixed old/new state.
Leaving the adopted STE unmodified keeps the kdump kernel using the crashed kernel's translation. That gives the endpoint driver a chance to probe and quiesce the device.
If the old STE was already abort or invalid, installing bypass would create new DMA permission; leaving it alone is a safer failure mode. Later domain setup still gets the RMR direct mappings through the reserved-region path.
--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +9 -4
@@ -5658,6 +5658,14 @@ static void arm_smmu_rmr_install_bypass_ste(struct arm_smmu_device *smmu)struct list_head rmr_list;struct iommu_resv_region *e; +/* +* Kdump adoption keeps the crashed kernel's table live. Rewriting the +* adopted STE here could expose an in-flight fetch to a transient V=0 +* entry, or change Cfg=translate to Cfg=bypass. Must skip here. +*/ +if (smmu->options &ARM_SMMU_OPT_KDUMP_ADOPT ) +return ; +INIT_LIST_HEAD (&rmr_list);iort_get_rmr_sids (dev_fwnode (smmu->dev), &rmr_list);
@@ -5674,10 +5682,7 @@ static void arm_smmu_rmr_install_bypass_ste(struct arm_smmu_device *smmu)continue ; } -/* -* STE table is not programmed to HW, see -* arm_smmu_initial_bypass_stes() -*/ +/* The fresh stream table is not yet live. */ arm_smmu_make_bypass_ste (smmu,arm_smmu_get_step_for_sid (smmu, rmr->sids[i])); }
Signature · 1 line
2.43.0
PATCH v7 7/7 iommu/arm-smmu-v3: Detect ARM_SMMU_OPT_KDUMP_ADOPT in probe()
In reply to Nicolin Chenarm_smmu_device_hw_probe() runs before arm_smmu_init_structures(), so it's natural to decide whether the kdump kernel must adopt the crashed kernel's stream table.
Given that memremap is used to adopt the old stream table, set this option only on a coherent SMMU.
And make sure SMMU isn't in Service Failure Mode.
--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 31 +++++++++++++++++++++ 1 file changed, 31 insertions(+)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +31 -0
@@ -5280,6 +5280,33 @@ static void arm_smmu_get_httu(struct arm_smmu_device *smmu, u32 reg) hw_features, fw_features); } +static void arm_smmu_device_hw_probe_kdump (struct arm_smmu_device *smmu) +{ +u32 gerror, gerrorn, active; + +/* No adoption if SMMU is disabled (i.e., there is no in-flight DMA) */ +if (!(readl_relaxed (smmu->base +ARM_SMMU_CR0 ) &CR0_SMMUEN )) +return ; + +/* For now, only support a coherent SMMU that works with MEMREMAP_WB */ +if (!(smmu->features &ARM_SMMU_FEAT_COHERENCY )) { +dev_warn (smmu->dev, +"kdump: non-coherent SMMU unsupported; reset to block all DMAs\n" ); +return ; + } + + gerror =readl_relaxed (smmu->base +ARM_SMMU_GERROR ); + gerrorn =readl_relaxed (smmu->base +ARM_SMMU_GERRORN ); + active = gerror ^ gerrorn; +if (active &GERROR_SFM_ERR ) { +dev_warn (smmu->dev, +"kdump: SMMU in Service Failure Mode, must reset\n" ); +return ; + } + + smmu->options |=ARM_SMMU_OPT_KDUMP_ADOPT ; +} +static int arm_smmu_device_hw_probe (struct arm_smmu_device *smmu) {u32 reg;
@@ -5494,6 +5521,10 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)dev_info (smmu->dev,"oas %lu-bit (features 0x%08x)\n" , smmu->oas, smmu->features); + +if (is_kdump_kernel ()) +arm_smmu_device_hw_probe_kdump (smmu); +return 0 ; }
Signature · 1 line
2.43.0
Quoted 8 lines · Nicolin Chen
When transitioning to a kdump kernel, the primary kernel might have crashed while endpoint devices were actively bus-mastering DMA. Currently, the SMMU driver aggressively resets the hardware during probe by clearing
CR0_SMMUENand setting the Global Bypass Attribute (GBPA) to ABORT.In a kdump scenario, this aggressive reset is highly destructive:
a) If GBPA is set to ABORT, in-flight DMA will be aborted, generating fatal PCIe AER or SErrors that may panic the kdump kernel
Can you please clarify more on those errors, what conditions will trigger that?
For example, patch 4 disables the EVTQ to avoid events as there might be a lot, why are they not fatal also?
Quoted 8 lines
b) If GBPA is set to BYPASS, in-flight DMA targeting some IOVAs will bypass the SMMU and corrupt the physical memory at those 1:1 mapped IOVAs.
To safely absorb in-flight DMA, the kdump kernel must leave SMMUEN=1 intact and avoid modifying
STRTAB_BASE. This allows HW to continue translating in- flight DMA using the crashed kernel's page tables until the endpoint device drivers probe and quiesce their respective hardware.
Quoted 5 lines
However, the ARM SMMUv3 architecture specification states that updating the
SMMU_STRTAB_BASEregister while SMMUEN == 1 is UNPREDICTABLE or ignored.This leaves a kdump kernel no choice but to adopt the stream table from the crashed kernel.
In many cases the patches assume that the CDs/STE might be corrupted, but still attempt to retrieve them with some validation (log2size/split...)
However, the base address might be broken, TLBs state is unknown...
IMO, although that might improve the status quo, there are still heuristics, in addition to noticeable complexity to transition the stream tables. I wonder if FW can deal with AER in that case before booting the kdump kernel.
Thanks,
Mostafa
Quoted 102 lines
In this series:
- Introduce anARM_SMMU_OPT_KDUMP_ADOPT
- Skip SMMUEN andSTRTAB_BASEresets inarm_smmu_device_reset()
- Skip EVENTQ/PRIQ setup including interrupts and their handlers
- Memremap the crashed kernel's stream tables into the kdump kernel [*]
- Defer any default domain attachment to retain STEs until device drivers explicitly request it.[*] For verification reasons, this series only fixes coherent SMMUs.
For non-ARM_SMMU_OPT_KDUMP_ADOPT cases, keep a status quo since the commit
3f54c447df34f("iommu/arm-smmu-v3: Don't disable SMMU in kdump kernel"):
full reset followed by driver-initiated reattach, potentially rejecting any in-flight DMA.Note that the series requires Jason's work that was merged in v6.12: commit
85196f54743d("iommu/arm-smmu-v3: Reorganize structarm_smmu_strtab_cfg"). I have a backported version that is verified with a v6.8 kernel. I can send if we see a strong need after this version is accepted.This is on Github:
https://github.com/nicolinc/iommufd/commits/smmuv3_kdump-v7Changelog
v7
* Rebase v7.2-rc1
* Add Reviewed-by from Pranjal
* Reword the linear stream table adoption comment
* Usedev_dbgfor the stream table adoption message
* Document why the lazy L2 adoption usesdevm_memremap()
* Drop redundantFEAT_COHERENCYchecks in the adopt functions
* Use feature bit instead ofSTRTAB_BASE_CFGin adopt cleanup
* SkipCR0_ATSCHKupdate in adopt mode to retain the crashed policy
* RestoreFEAT_2_LVL_STRTABif the cleanup action fails to register
v6
https://lore.kernel.org/all/[email protected]/
* Rebase v7.1-rc3
* Add Reviewed-by from Jason
* Replacedma_addr_twithphys_addr_t
* Droparm_smmu_kdump_phys_is_corrupted()
* Skip threaded IRQ handlers for EVTQ and PRIQ
* Bypassarm_smmu_rmr_install_bypass_ste()in kdump case
* Dropdevm_for adopt-time allocations; set up cleanup function viadevm_add_action_or_reset()
v5
https://lore.kernel.org/all/[email protected]/
* Add Reviewed-by from Kevin
* DropREAD_ONCEon lazy-attach L1 read
* Split "Skip EVTQ/PRIQ setup" into two patches
* Tighten kdump probe comment anddev_warnmessage
* Use MEM + BUSY inarm_smmu_kdump_phys_is_corrupted
v4
https://lore.kernel.org/all/[email protected]/
* Rebase v7.1-rc1
* s/arm_smmu_adopt/arm_smmu_kdump_adopt
* Revert alloc/memremap/fmt on fallback
* Reorder patches to avoid bisect regression
* UseIRQ_NONEfor spurious evtq/priq entries
* Cap linear log2size by kdump's allocation bound
* Defer clearingFEAT_2_LVL_STRTABon linear adopt
* Addarm_smmu_kdump_phys_is_corrupted()validation
* Defer l2 stream table memremap till master inserts
* Re-validate L1 desc on master insert withREAD_ONCE
v3
https://lore.kernel.org/all/[email protected]/
* s/OPT_KDUMP/OPT_KDUMP_ADOPT
* Do not adopt ifGERROR_SFM_ERR
* RetainCR0_ATSCHKbesideCR0_SMMUEN
* Clear latched GERROR bits (e.g.CMDQ_ERR)
* AssertARM_SMMU_FEAT_COHERENCYin adopt functions
* Add STE.Cfg check inarm_smmu_is_attach_deferred()
* Fix validations on return codes fromdevm_memremap()
* Sanitize crashed kernel register values in adopt functions
* Drop unnecessary l2ptrs guard inarm_smmu_is_attach_deferred()
* Don't enable PRIQ/EVTQ irqs and guard the irq functions for combined irq cases
v2
https://lore.kernel.org/all/[email protected]/
* Add warning in non-coherent SMMU cases
* Keep eventq/priq disabled vs. enabling-and-disabling-later
* Check KDUMP option in the beginning ofarm_smmu_device_reset()
* Validate STRTAB format matches HW capability instead of forcing flags
v1:
https://lore.kernel.org/all/[email protected]/Nicolin Chen (7):
iommu/arm-smmu-v3: Addarm_smmu_kdump_adopt_strtab()for kdump iommu/arm-smmu-v3: Implementis_attach_deferred()for kdump iommu/arm-smmu-v3: Do not enable EVTQ/PRIQ interrupts in kdump kernel iommu/arm-smmu-v3: Skip EVTQ/PRIQ setup in kdump kernel iommu/arm-smmu-v3: RetainCR0_SMMUENduring kdump device reset iommu/arm-smmu-v3: Skip RMR bypass for kdump adoption iommu/arm-smmu-v3: DetectARM_SMMU_OPT_KDUMP_ADOPTinprobe()drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 + drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 467 ++++++++++++++++++-- 2 files changed, 422 insertions(+), 46 deletions(-)Signature · 1 line
2.43.0
Quoted 34 lines · Mostafa Saleh
Quoted 8 lines · Nicolin Chen
When transitioning to a kdump kernel, the primary kernel might have crashed while endpoint devices were actively bus-mastering DMA. Currently, the SMMU driver aggressively resets the hardware during probe by clearing
CR0_SMMUENand setting the Global Bypass Attribute (GBPA) to ABORT.In a kdump scenario, this aggressive reset is highly destructive:
a) If GBPA is set to ABORT, in-flight DMA will be aborted, generating fatal PCIe AER or SErrors that may panic the kdump kernelCan you please clarify more on those errors, what conditions will trigger that?
For example, patch 4 disables the EVTQ to avoid events as there might be a lot, why are they not fatal also?Quoted 8 lines
b) If GBPA is set to BYPASS, in-flight DMA targeting some IOVAs will bypass the SMMU and corrupt the physical memory at those 1:1 mapped IOVAs.
To safely absorb in-flight DMA, the kdump kernel must leave SMMUEN=1 intact and avoid modifying
STRTAB_BASE. This allows HW to continue translating in- flight DMA using the crashed kernel's page tables until the endpoint device drivers probe and quiesce their respective hardware.Quoted 5 lines
However, the ARM SMMUv3 architecture specification states that updating the
SMMU_STRTAB_BASEregister while SMMUEN == 1 is UNPREDICTABLE or ignored.This leaves a kdump kernel no choice but to adopt the stream table from the crashed kernel.
In many cases the patches assume that the CDs/STE might be corrupted, but still attempt to retrieve them with some validation (log2size/split...)
However, the base address might be broken, TLBs state is unknown...
Quoted 4 lines
IMO, although that might improve the status quo, there are still heuristics, in addition to noticeable complexity to transition the stream tables. I wonder if FW can deal with AER in that case before booting the kdump kernel.
I guess we're reading the base address from the HW register itself so that should be fine? CDs are in-memory so that's why they could be corrupted?
About the TLB state, I'm not sure what might pollute it, since this is a kexec, I don't expect any non-kernel entity to gain program control before the kdump kernel.. Hence, IMO, we can't configure FW to deal with AER here..
Thanks,
Praan
Quoted 35 lines · Pranjal Shrivastava
Quoted 34 lines · Mostafa Saleh
Quoted 8 lines · Nicolin Chen
When transitioning to a kdump kernel, the primary kernel might have crashed while endpoint devices were actively bus-mastering DMA. Currently, the SMMU driver aggressively resets the hardware during probe by clearing
CR0_SMMUENand setting the Global Bypass Attribute (GBPA) to ABORT.In a kdump scenario, this aggressive reset is highly destructive:
a) If GBPA is set to ABORT, in-flight DMA will be aborted, generating fatal PCIe AER or SErrors that may panic the kdump kernelCan you please clarify more on those errors, what conditions will trigger that?
For example, patch 4 disables the EVTQ to avoid events as there might be a lot, why are they not fatal also?Quoted 8 lines
b) If GBPA is set to BYPASS, in-flight DMA targeting some IOVAs will bypass the SMMU and corrupt the physical memory at those 1:1 mapped IOVAs.
To safely absorb in-flight DMA, the kdump kernel must leave SMMUEN=1 intact and avoid modifying
STRTAB_BASE. This allows HW to continue translating in- flight DMA using the crashed kernel's page tables until the endpoint device drivers probe and quiesce their respective hardware.Quoted 5 lines
However, the ARM SMMUv3 architecture specification states that updating the
SMMU_STRTAB_BASEregister while SMMUEN == 1 is UNPREDICTABLE or ignored.This leaves a kdump kernel no choice but to adopt the stream table from the crashed kernel.
In many cases the patches assume that the CDs/STE might be corrupted, but still attempt to retrieve them with some validation (log2size/split...)
However, the base address might be broken, TLBs state is unknown...
Quoted 8 lines
Quoted 4 lines
IMO, although that might improve the status quo, there are still heuristics, in addition to noticeable complexity to transition the stream tables. I wonder if FW can deal with AER in that case before booting the kdump kernel.
I guess we're reading the base address from the HW register itself so that should be fine? CDs are in-memory so that's why they could be corrupted?
For example patch#1 verifies log2size and split and both are read from HW registers. Same for the base address or other addresses as the page tables, they might be corrupted due to a buggy driver. My point is that, it is really hard to assume that the previous state of registers/STE/page-tables were valid or even consistent, when the kernel crashed and did not transition the state gracefully.
Quoted 5 lines
About the TLB state, I'm not sure what might pollute it, since this is a kexec, I don't expect any non-kernel entity to gain program control before the kdump kernel.. Hence, IMO, we can't configure FW to deal with AER here..
Similarly for TLBs, the kernel might have panicked in the middle of an unmap or free domain. (not to mention what that means for RPM where a device reset with unknown TLBs)
Why can't the FW deal with it? As I mentioned above in the previous reply I am not sure I understand what situation leads into this, when does a device trigger SError to the system vs when not which is observed as an event in that case.
Thanks,
Mostafa
Quoted 3 lines
Thanks,
Praan
Quoted 58 lines · Mostafa Saleh
Quoted 35 lines · Pranjal Shrivastava
Quoted 34 lines · Mostafa Saleh
Quoted 8 lines · Nicolin Chen
When transitioning to a kdump kernel, the primary kernel might have crashed while endpoint devices were actively bus-mastering DMA. Currently, the SMMU driver aggressively resets the hardware during probe by clearing
CR0_SMMUENand setting the Global Bypass Attribute (GBPA) to ABORT.In a kdump scenario, this aggressive reset is highly destructive:
a) If GBPA is set to ABORT, in-flight DMA will be aborted, generating fatal PCIe AER or SErrors that may panic the kdump kernelCan you please clarify more on those errors, what conditions will trigger that?
For example, patch 4 disables the EVTQ to avoid events as there might be a lot, why are they not fatal also?Quoted 8 lines
b) If GBPA is set to BYPASS, in-flight DMA targeting some IOVAs will bypass the SMMU and corrupt the physical memory at those 1:1 mapped IOVAs.
To safely absorb in-flight DMA, the kdump kernel must leave SMMUEN=1 intact and avoid modifying
STRTAB_BASE. This allows HW to continue translating in- flight DMA using the crashed kernel's page tables until the endpoint device drivers probe and quiesce their respective hardware.Quoted 5 lines
However, the ARM SMMUv3 architecture specification states that updating the
SMMU_STRTAB_BASEregister while SMMUEN == 1 is UNPREDICTABLE or ignored.This leaves a kdump kernel no choice but to adopt the stream table from the crashed kernel.
In many cases the patches assume that the CDs/STE might be corrupted, but still attempt to retrieve them with some validation (log2size/split...)
However, the base address might be broken, TLBs state is unknown...Quoted 8 lines
Quoted 4 lines
IMO, although that might improve the status quo, there are still heuristics, in addition to noticeable complexity to transition the stream tables. I wonder if FW can deal with AER in that case before booting the kdump kernel.
I guess we're reading the base address from the HW register itself so that should be fine? CDs are in-memory so that's why they could be corrupted?
For example patch#1 verifies log2size and split and both are read from HW registers. Same for the base address or other addresses as the page tables, they might be corrupted due to a buggy driver. My point is that, it is really hard to assume that the previous state of registers/STE/page-tables were valid or even consistent, when the kernel crashed and did not transition the state gracefully.
Quoted 5 lines
About the TLB state, I'm not sure what might pollute it, since this is a kexec, I don't expect any non-kernel entity to gain program control before the kdump kernel.. Hence, IMO, we can't configure FW to deal with AER here..
Quoted 5 lines
Similarly for TLBs, the kernel might have panicked in the middle of an unmap or free domain. (not to mention what that means for RPM where a device reset with unknown TLBs?
Why can't the FW deal with it?
The FW can't handle it because between a kexec from main kernel -> kdump there's no FW-based handoff hence wee can't setup a handler in FW..
Quoted 5 lines
As I mentioned above in the previous
reply I am not sure I understand what situation leads into this, when does a device trigger SError to the system vs when not which is observed as an event in that case.
Ack. I see what you mean now.. How does a DMA fault raise an SError?
I'm guessing the HW (PCIe RC) is wired in a way to raise an SError on an error? But I agree that sounds pretty unusual, why should a DMA abort panic the CPU? Is the DMA happening between a platform device & PCIe EP? Even if that's true, why would it raise an SError? (No CPU was involved) Unless, we have a fabric that raises an Serror on a SLVERR or something
Thanks,
Praan
Quoted 6 lines · Pranjal Shrivastava
Quoted 4 lines
As I mentioned above in the previous
reply I am not sure I understand what situation leads into this, when does a device trigger SError to the system vs when not which is observed as an event in that case.Ack. I see what you mean now.. How does a DMA fault raise an SError?
As I gave an example to Robin if the unhandled failure escalates into RAS emergency unplugging CXL memory then the system is going to explode when kdump touches that CXL memory as part of the dumping. It is not quite so simple that a DMA abort is triggering SError.
I don't know exactly the sequence of events that lead up to the kdump kernel crashing (I imagine it is hard to debug that one), but it is something related to the new kernel not participating in the RAS and the RAS flow escalating to something fatal.
Jason
Quoted 6 lines · Jason Gunthorpe
Quoted 5 lines · Pranjal Shrivastava
Quoted 4 lines
As I mentioned above in the previous
reply I am not sure I understand what situation leads into this, when does a device trigger SError to the system vs when not which is observed as an event in that case.
Quoted 6 lines
Quoted 1 line
Ack. I see what you mean now.. How does a DMA fault raise an SError?
As I gave an example to Robin if the unhandled failure escalates into RAS emergency unplugging CXL memory then the system is going to explode when kdump touches that CXL memory as part of the dumping. It is not quite so simple that a DMA abort is triggering SError.
Here is link to that email:
https://lore.kernel.org/all/[email protected]/
Quoted 4 lines
I don't know exactly the sequence of events that lead up to the kdump kernel crashing (I imagine it is hard to debug that one), but it is something related to the new kernel not participating in the RAS and the RAS flow escalating to something fatal.
Here is the original bug report:
- kernel boots into a crash kernel
- crash kernel hits OOM do to insufficient reserved memory and panics
- PCIe errors are observed during this failure flow
Thanks
Nicolin
Quoted 10 lines · Nicolin Chen
Quoted 4 lines
I don't know exactly the sequence of events that lead up to the kdump kernel crashing (I imagine it is hard to debug that one), but it is something related to the new kernel not participating in the RAS and the RAS flow escalating to something fatal.
Here is the original bug report:
- kernel boots into a crash kernel
- crash kernel hits OOM do to insufficient reserved memory and panics
- PCIe errors are observed during this failure flow
Maybe the RAS events hits some bugs and OOMs the kdump kernel?
Regardless more general cases like CXL are still things where you don't want to cause unexpected ATS failures..
Jason
Quoted 6 lines · Mostafa Saleh
For example patch#1 verifies log2size and split and both are read from HW registers. Same for the base address or other addresses as the page tables, they might be corrupted due to a buggy driver. My point is that, it is really hard to assume that the previous state of registers/STE/page-tables were valid or even consistent, when the kernel crashed and did not transition the state gracefully.
Sure, and this mechanism is probably not very useful for debugging these kinds of errors in the SMMU driver. Oh well, that isn't a common source of kernel crashes :)
Quoted 3 lines
Similarly for TLBs, the kernel might have panicked in the middle of an unmap or free domain. (not to mention what that means for RPM where a device reset with unknown TLBs)
TLB is fine. kdump works by carving out a chunk of memory for the future crash kernel. When the kernel boots it ignores all the memory used by the prior kernel. So DMA can keep running into the old kernels memory with no issue. It doesn't matter if the TLBs are inconsistent or not.
Jason
Quoted 9 lines · Jason Gunthorpe
Quoted 6 lines · Mostafa Saleh
For example patch#1 verifies log2size and split and both are read from HW registers. Same for the base address or other addresses as the page tables, they might be corrupted due to a buggy driver. My point is that, it is really hard to assume that the previous state of registers/STE/page-tables were valid or even consistent, when the kernel crashed and did not transition the state gracefully.
Quoted 3 lines
Sure, and this mechanism is probably not very useful for debugging these kinds of errors in the SMMU driver. Oh well, that isn't a common source of kernel crashes :)
I hope not! Although memory corruption can happen due to many other reasons :/
I am not trying to bikeshed, but I wondering if there is a more reliable way rather than doing archaeology from a panicked kernel SMMUv3 configuration, as I am worried that will be even harder to debug if it goes wrong.
Quoted 10 lines
Quoted 4 lines
Similarly for TLBs, the kernel might have panicked in the middle of an unmap or free domain. (not to mention what that means for RPM where a device reset with unknown TLBs)
TLB is fine. kdump works by carving out a chunk of memory for the future crash kernel. When the kernel boots it ignores all the memory used by the prior kernel. So DMA can keep running into the old kernels memory with no issue. It doesn't matter if the TLBs are inconsistent or not.
Ideally if a TLB is to be missed (because of the panic), it should not point to kdump memory as it is carved-out. However, it is still a leap to assume that the TLBs are in a good shape as I mentioned with RPM (or even if the device resets transiently for some reason) it can end up with garbage in its TLBs.
Thanks,
Mostafa
Quoted 2 lines
Jason
Quoted 33 lines · Mostafa Saleh
Quoted 9 lines · Jason Gunthorpe
Quoted 6 lines · Mostafa Saleh
For example patch#1 verifies log2size and split and both are read from HW registers. Same for the base address or other addresses as the page tables, they might be corrupted due to a buggy driver. My point is that, it is really hard to assume that the previous state of registers/STE/page-tables were valid or even consistent, when the kernel crashed and did not transition the state gracefully.
Quoted 3 lines
Sure, and this mechanism is probably not very useful for debugging these kinds of errors in the SMMU driver. Oh well, that isn't a common source of kernel crashes :)
I hope not! Although memory corruption can happen due to many other reasons :/
I am not trying to bikeshed, but I wondering if there is a more reliable way rather than doing archaeology from a panicked kernel SMMUv3 configuration, as I am worried that will be even harder to debug if it goes wrong.
Quoted 10 lines
Quoted 4 lines
Similarly for TLBs, the kernel might have panicked in the middle of an unmap or free domain. (not to mention what that means for RPM where a device reset with unknown TLBs)
TLB is fine. kdump works by carving out a chunk of memory for the future crash kernel. When the kernel boots it ignores all the memory used by the prior kernel. So DMA can keep running into the old kernels memory with no issue. It doesn't matter if the TLBs are inconsistent or not.
Quoted 5 lines
Ideally if a TLB is to be missed (because of the panic), it should not point to kdump memory as it is carved-out. However, it is still a leap to assume that the TLBs are in a good shape as I mentioned with RPM (or even if the device resets transiently for some reason) it can end up with garbage in its TLBs.
Regarding RPM, I can say that even if we panicked while SMMU was off in the previous kernel, when we call device_reset() in the new kernel we still issue the TLBI_ALL with the reset.
However, I agree with the overall problem, i.e. IF an active device unmaps the DMA addr after the transaction in the previous kernel, (with the SMMU powered ON) but the TLBI was missed due to a crash/panic, Any new DMA in the new kernel may alias onto a memory in the previous (crashed) kernel, not the kdump kernel.
That way, I agree that continuing DMA could be problematic as we may corrupt the very memory we'd wanna analyze for a crash.
Thanks,
Praan
Quoted 5 lines · Pranjal Shrivastava
However, I agree with the overall problem, i.e. IF an active device unmaps the DMA addr after the transaction in the previous kernel, (with the SMMU powered ON) but the TLBI was missed due to a crash/panic, Any new DMA in the new kernel may alias onto a memory in the previous (crashed) kernel, not the kdump kernel.
It looks like there is an issue in this series, it isn't doing anything with the VMIDs.
The VMIDs that are in-used by the adopted stream table have to be removed from the idr as well (and similarly for ASID if we don't have VMID HW support).
Then the VMIDs that may be dirtied by the prior kernel remain isolated and are never re-used by the new kernel. When the new kernel wants to do DMA it will replace the STE with a new, clean VMID, and there is no problem.
Jason
Quoted 11 lines · Jason Gunthorpe
Quoted 5 lines · Pranjal Shrivastava
However, I agree with the overall problem, i.e. IF an active device unmaps the DMA addr after the transaction in the previous kernel, (with the SMMU powered ON) but the TLBI was missed due to a crash/panic, Any new DMA in the new kernel may alias onto a memory in the previous (crashed) kernel, not the kdump kernel.
It looks like there is an issue in this series, it isn't doing anything with the VMIDs.
Quoted 8 lines
The VMIDs that are in-used by the adopted stream table have to be removed from the idr as well (and similarly for ASID if we don't have VMID HW support).
Then the VMIDs that may be dirtied by the prior kernel remain isolated and are never re-used by the new kernel. When the new kernel wants to do DMA it will replace the STE with a new, clean VMID, and there is no problem.
I see. I assume the reserved VMID for the kdump kernel will be a clean VMID (!=0). That should guarantee different cache tags.
But, do we have to scan CDs for ASID? I wonder if we could limit to ARM_SMMU_FEAT_TRANS_S2 only, as this series does not memremap CDs at all..
Nicolin
Quoted 16 lines · Nicolin Chen
Quoted 15 lines · Jason Gunthorpe
Quoted 5 lines · Pranjal Shrivastava
However, I agree with the overall problem, i.e. IF an active device unmaps the DMA addr after the transaction in the previous kernel, (with the SMMU powered ON) but the TLBI was missed due to a crash/panic, Any new DMA in the new kernel may alias onto a memory in the previous (crashed) kernel, not the kdump kernel.
It looks like there is an issue in this series, it isn't doing anything with the VMIDs.
The VMIDs that are in-used by the adopted stream table have to be removed from the idr as well (and similarly for ASID if we don't have VMID HW support).
Quoted 7 lines
Quoted 4 lines
Then the VMIDs that may be dirtied by the prior kernel remain isolated and are never re-used by the new kernel. When the new kernel wants to do DMA it will replace the STE with a new, clean VMID, and there is no problem.
I see. I assume the reserved VMID for the kdump kernel will be a clean VMID (!=0). That should guarantee different cache tags.
You will also have to change things to allocate the kernel global vmid from the IDR, it will usually be 0 but not for kdump. Then you have to find all the places where the 0 is implicitly placed and put in the actual value.
Quoted 3 lines
But, do we have to scan CDs for ASID? I wonder if we could limit to
ARM_SMMU_FEAT_TRANS_S2only, as this series does not memremap CDs at all..
Yeah, I would limit to S2 for now
Jason
Quoted 11 lines · Jason Gunthorpe
Quoted 10 lines · Nicolin Chen
Quoted 8 lines · Jason Gunthorpe
The VMIDs that are in-used by the adopted stream table have to be removed from the idr as well (and similarly for ASID if we don't have VMID HW support).
Then the VMIDs that may be dirtied by the prior kernel remain isolated and are never re-used by the new kernel. When the new kernel wants to do DMA it will replace the STE with a new, clean VMID, and there is no problem.
Quoted 7 lines
Quoted 2 lines
I see. I assume the reserved VMID for the kdump kernel will be a clean VMID (!=0). That should guarantee different cache tags.
You will also have to change things to allocate the kernel global vmid from the IDR, it will usually be 0 but not for kdump. Then you have to find all the places where the 0 is implicitly placed and put in the actual value.
Hmm, I just realized that all the EL2 commands do not take VMID.
Looks like we have no choice but to scan through all the CDs for the ASID too..
Nicolin
Quoted 15 lines · Nicolin Chen
Quoted 14 lines · Jason Gunthorpe
Quoted 12 lines · Nicolin Chen
Quoted 8 lines · Jason Gunthorpe
The VMIDs that are in-used by the adopted stream table have to be removed from the idr as well (and similarly for ASID if we don't have VMID HW support).
Then the VMIDs that may be dirtied by the prior kernel remain isolated and are never re-used by the new kernel. When the new kernel wants to do DMA it will replace the STE with a new, clean VMID, and there is no problem.
I see. I assume the reserved VMID for the kdump kernel will be a clean VMID (!=0). That should guarantee different cache tags.
Quoted 6 lines
Quoted 4 lines
You will also have to change things to allocate the kernel global vmid from the IDR, it will usually be 0 but not for kdump. Then you have to find all the places where the 0 is implicitly placed and put in the actual value.
Hmm, I just realized that all the EL2 commands do not take VMID.
If the EL2 commands are being used then there is no S2 support and no VMID support.
So if you disable kdump when S2 is not supported it also disables it when EL2 would be used, which effectively means it is not supported in a VM.
Jason
Quoted 21 lines · Jason Gunthorpe
Quoted 20 lines · Nicolin Chen
Quoted 18 lines · Jason Gunthorpe
Quoted 5 lines · Nicolin Chen
Quoted 4 lines · Jason Gunthorpe
The VMIDs that are in-used by the adopted stream table have to be removed from the idr as well (and similarly for ASID if we don't have VMID HW support).
Quoted 7 lines
Quoted 4 lines
Then the VMIDs that may be dirtied by the prior kernel remain isolated and are never re-used by the new kernel. When the new kernel wants to do DMA it will replace the STE with a new, clean VMID, and there is no problem.
I see. I assume the reserved VMID for the kdump kernel will be a clean VMID (!=0). That should guarantee different cache tags.
You will also have to change things to allocate the kernel global vmid from the IDR, it will usually be 0 but not for kdump. Then you have to find all the places where the 0 is implicitly placed and put in the actual value.
Quoted 8 lines
Quoted 1 line
Hmm, I just realized that all the EL2 commands do not take VMID.
If the EL2 commands are being used then there is no S2 support and no VMID support.
So if you disable kdump when S2 is not supported it also disables it when EL2 would be used, which effectively means it is not supported in a VM.
Hmm, they are actually not exclusive: e.g. Grace has both.
EL2 is from FEAT_E2H, which is set when
1. IDR0.HYP=1
2. cpus_have_cap(ARM64_HAS_VIRT_HOST_EXTN)
VMID is from FEAT_TRANS_S2, which is set When
1. IDR0_S2P=1
So, host-level stage-1 TLBIs use EL2 commands (no VMID); guest-level TLBIs use NH_ commands (with VMID).
Scanning through CDs seems inevitable...
Thanks
Nicolin
Quoted 10 lines · Nicolin Chen
Quoted 3 lines
So if you disable kdump when S2 is not supported it also disables it when EL2 would be used, which effectively means it is not supported in a VM.
Hmm, they are actually not exclusive: e.g. Grace has both.
EL2 is from
FEAT_E2H, which is set when
1. IDR0.HYP=1
2.cpus_have_cap(ARM64_HAS_VIRT_HOST_EXTN)
Quoted 5 lines
VMID is from
FEAT_TRANS_S2, which is set When
1. IDR0_S2P=1So, host-level stage-1 TLBIs use EL2 commands (no VMID); guest-level TLBIs use
NH_commands (with VMID).
Oh... I see the half baked BTM stuff pushes STRW it into the NH mode because the CPU runs in that mode so we loose the VMID :\
I guess VM support is important anyhow so you do have to scan the CD tables and extract the ASIDs, carefully considering the STRW and VMID of the STE :\
Jason
Quoted 8 lines · Mostafa Saleh
In many cases the patches assume that the CDs/STE might be corrupted, but still attempt to retrieve them with some validation (log2size/split...)
However, the base address might be broken, TLBs state is unknown...IMO, although that might improve the status quo, there are still heuristics, in addition to noticeable complexity to transition the stream tables.
That's basically what kdump is all about, try to improve the chances that the kdump kernel functions enough to retrieve the dump. There are many reasons kdump can fail, but nevertheless it works well enough and often enough to still be highly useful.
So, the cases which are frequent and problematic should be addressed. On this HW kdump has a high failure rate because of the errors.
Given that non-disruption is exactly what the Intel and AMD drivers both implement SMMU should also.
Jason
(I think Jason has answered most of the questions here.)
Quoted 2 lines · Mostafa Saleh
For example, patch 4 disables the EVTQ to avoid events as there might be a lot, why are they not fatal also?
FWIW, the PATCH-4 doesn't disable the EVTQ: EVTQ is disabled in kdump case prior to the series; PATCH-4 just makes sure it won't get enabled transiently.
Nicolin
Quoted 9 lines · Nicolin Chen
(I think Jason has answered most of the questions here.)
Quoted 2 lines · Mostafa Saleh
For example, patch 4 disables the EVTQ to avoid events as there might be a lot, why are they not fatal also?
FWIW, the PATCH-4 doesn't disable the EVTQ: EVTQ is disabled in kdump case prior to the series; PATCH-4 just makes sure it won't get enabled transiently.
Yes, I meant the patch disabling it even transiently because of DMA faults, which was confusing to me because I though they are fatal anyway, but I see Jason’s explanation now.
Thanks,
Mostafa
Quoted 2 lines
Nicolin