* [PATCH 0/2] drm/xe/nvm: add survivabilty partiton
@ 2026-07-15 13:45 Alexander Usyskin
2026-07-15 13:45 ` [PATCH 1/2] mtd: mtd_intel_dg: add survivability partition Alexander Usyskin
2026-07-15 13:45 ` [PATCH 2/2] drm/xe/nvm: define survivabilty partition Alexander Usyskin
0 siblings, 2 replies; 6+ messages in thread
From: Alexander Usyskin @ 2026-07-15 13:45 UTC (permalink / raw)
To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
Matthew Brost, Thomas Hellström, Rodrigo Vivi, David Airlie,
Simona Vetter
Cc: linux-mtd, linux-kernel, intel-xe, dri-devel, Alexander Usyskin
One of the reasons for the CRI to enter survivability mode
is corrupted storage.
A corrupted storage partition table can make recovery impossible.
A new partition with a pre-defined size, covering the entire storage,
should be added when the card is in survivability mode to allow a full
memory update.
This series intended to be merged via drm tree for consistency
and requires ack from MTD maintainer.
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
---
Alexander Usyskin (2):
mtd: mtd_intel_dg: add survivability partition
drm/xe/nvm: define survivabilty partition
drivers/gpu/drm/xe/xe_nvm.c | 13 +++++--
drivers/mtd/devices/mtd_intel_dg.c | 80 +++++++++++++++++++++++++++-----------
include/linux/intel_dg_nvm_aux.h | 1 +
3 files changed, 69 insertions(+), 25 deletions(-)
---
base-commit: acc744fa62fb098358f371bfb38e6b32032459c7
change-id: 20260715-cri_surviv-5a6faf7586f1
Best regards,
--
Alexander Usyskin <alexander.usyskin@intel.com>
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 1/2] mtd: mtd_intel_dg: add survivability partition 2026-07-15 13:45 [PATCH 0/2] drm/xe/nvm: add survivabilty partiton Alexander Usyskin @ 2026-07-15 13:45 ` Alexander Usyskin 2026-07-15 14:19 ` sashiko-bot 2026-07-17 9:42 ` Miquel Raynal 2026-07-15 13:45 ` [PATCH 2/2] drm/xe/nvm: define survivabilty partition Alexander Usyskin 1 sibling, 2 replies; 6+ messages in thread From: Alexander Usyskin @ 2026-07-15 13:45 UTC (permalink / raw) To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra, Matthew Brost, Thomas Hellström, Rodrigo Vivi, David Airlie, Simona Vetter Cc: linux-mtd, linux-kernel, intel-xe, dri-devel, Alexander Usyskin Add option to expose additional fixed-sized partition starting from the beginning of storage. Xe driver can request this partition exposure if firmware or hardware have detected failure that may involve corrupted partition table. Fixed-sized partition allows full storage re-write in this situation. Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> --- drivers/mtd/devices/mtd_intel_dg.c | 80 +++++++++++++++++++++++++++----------- include/linux/intel_dg_nvm_aux.h | 1 + 2 files changed, 59 insertions(+), 22 deletions(-) diff --git a/drivers/mtd/devices/mtd_intel_dg.c b/drivers/mtd/devices/mtd_intel_dg.c index f2fa8f68d190..d11ddc687c4a 100644 --- a/drivers/mtd/devices/mtd_intel_dg.c +++ b/drivers/mtd/devices/mtd_intel_dg.c @@ -31,6 +31,7 @@ struct intel_dg_nvm { void __iomem *base; void __iomem *base2; bool non_posted_erase; + bool survivability_enabled; size_t size; unsigned int nregions; @@ -205,6 +206,13 @@ static unsigned int idg_nvm_get_region(const struct intel_dg_nvm *nvm, loff_t fr { unsigned int i; + /* + * When survivability region is enabled it positioned on index 0 and has region_id = 0 + * Region 0 is special, via this region whole device memory can be accessed. + */ + if (nvm->survivability_enabled) + return 0; + for (i = 0; i < nvm->nregions; i++) { if ((nvm->regions[i].offset + nvm->regions[i].size - 1) >= from && nvm->regions[i].offset <= from && @@ -443,32 +451,39 @@ static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *device, u32 address, base, limit, region; u8 id = nvm->regions[i].id; - address = NVM_FLREG(id); - region = idg_nvm_read32(nvm, address); + if (nvm->regions[i].size) { /* pre-defined survivability region */ + limit = nvm->regions[i].offset + nvm->regions[i].size - 1; - base = FIELD_GET(NVM_FREG_BASE_MASK, region) << NVM_FREG_ADDR_SHIFT; - limit = (FIELD_GET(NVM_FREG_ADDR_MASK, region) << NVM_FREG_ADDR_SHIFT) | - NVM_FREG_MIN_REGION_SIZE; + if (nvm->size < limit) + nvm->size = limit; + } else { + address = NVM_FLREG(id); + region = idg_nvm_read32(nvm, address); - dev_dbg(device, "[%d] %s: region: 0x%08X base: 0x%08x limit: 0x%08x\n", - id, nvm->regions[i].name, region, base, limit); + base = FIELD_GET(NVM_FREG_BASE_MASK, region) << NVM_FREG_ADDR_SHIFT; + limit = (FIELD_GET(NVM_FREG_ADDR_MASK, region) << NVM_FREG_ADDR_SHIFT) | + NVM_FREG_MIN_REGION_SIZE; - if (base >= limit || (i > 0 && limit == 0)) { - dev_dbg(device, "[%d] %s: disabled\n", - id, nvm->regions[i].name); - nvm->regions[i].is_readable = 0; - continue; - } + dev_dbg(device, "[%d] %s: region: 0x%08X base: 0x%08x limit: 0x%08x\n", + id, nvm->regions[i].name, region, base, limit); - if (nvm->size < limit) - nvm->size = limit; + if (base >= limit || (i > 0 && limit == 0)) { + dev_dbg(device, "[%d] %s: disabled\n", + id, nvm->regions[i].name); + nvm->regions[i].is_readable = 0; + continue; + } - nvm->regions[i].offset = base; - nvm->regions[i].size = limit - base + 1; - /* No write access to descriptor; mask it out*/ - nvm->regions[i].is_writable = idg_nvm_region_writable(access_map, id); + if (nvm->size < limit) + nvm->size = limit; - nvm->regions[i].is_readable = idg_nvm_region_readable(access_map, id); + nvm->regions[i].offset = base; + nvm->regions[i].size = limit - base + 1; + /* No write access to descriptor; mask it out*/ + nvm->regions[i].is_writable = idg_nvm_region_writable(access_map, id); + + nvm->regions[i].is_readable = idg_nvm_region_readable(access_map, id); + } dev_dbg(device, "Registered, %s id=%d offset=%lld size=%lld rd=%d wr=%d\n", nvm->regions[i].name, nvm->regions[i].id, @@ -748,7 +763,7 @@ static int intel_dg_mtd_probe(struct auxiliary_device *aux_dev, struct intel_dg_nvm *nvm; struct device *device; unsigned int nregions; - unsigned int i, n; + unsigned int i, n = 0; int ret; device = &aux_dev->dev; @@ -764,6 +779,9 @@ static int intel_dg_mtd_probe(struct auxiliary_device *aux_dev, return -ENODEV; } + if (invm->survivability_size) + nregions++; + nvm = kzalloc_flex(*nvm, regions, nregions); if (!nvm) return -ENOMEM; @@ -771,8 +789,26 @@ static int intel_dg_mtd_probe(struct auxiliary_device *aux_dev, kref_init(&nvm->refcnt); mutex_init(&nvm->lock); nvm->nregions = nregions; + nvm->survivability_enabled = !!invm->survivability_size; + + if (invm->survivability_size) { /* this partition should be at idx 0 */ + char *name = kasprintf(GFP_KERNEL, "%s.%s", + dev_name(&aux_dev->dev), "DATA"); + if (!name) { + ret = -ENOMEM; + goto err_norpm; + } + + nvm->regions[n].name = name; + nvm->regions[n].id = 0; + nvm->regions[n].offset = 0; + nvm->regions[n].size = invm->survivability_size; + nvm->regions[n].is_readable = true; + nvm->regions[n].is_writable = true; + n++; + } - for (n = 0, i = 0; i < INTEL_DG_NVM_REGIONS; i++) { + for (i = 0; i < INTEL_DG_NVM_REGIONS; i++) { if (!invm->regions[i].name) continue; diff --git a/include/linux/intel_dg_nvm_aux.h b/include/linux/intel_dg_nvm_aux.h index 625d46a6b96e..84b5b6e0c4ea 100644 --- a/include/linux/intel_dg_nvm_aux.h +++ b/include/linux/intel_dg_nvm_aux.h @@ -21,6 +21,7 @@ struct intel_dg_nvm_dev { struct auxiliary_device aux_dev; bool writable_override; bool non_posted_erase; + size_t survivability_size; struct resource bar; struct resource bar2; const struct intel_dg_nvm_region *regions; -- 2.53.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] mtd: mtd_intel_dg: add survivability partition 2026-07-15 13:45 ` [PATCH 1/2] mtd: mtd_intel_dg: add survivability partition Alexander Usyskin @ 2026-07-15 14:19 ` sashiko-bot 2026-07-17 9:42 ` Miquel Raynal 1 sibling, 0 replies; 6+ messages in thread From: sashiko-bot @ 2026-07-15 14:19 UTC (permalink / raw) To: Alexander Usyskin; +Cc: dri-devel Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] Unsigned integer underflow in bounds checks allows out-of-bounds hardware memory accesses when survivability mode is enabled. -- --- Patch [1]: [PATCH 1/2] mtd: mtd_intel_dg: add survivability partition --- commit 9f27e4e8d4c741d1106f13ea61bac2daf3838cad Author: Alexander Usyskin <alexander.usyskin@intel.com> mtd: mtd_intel_dg: add survivability partition This commit adds an option to expose a fixed-sized survivability partition starting from the beginning of storage. This can be used when the firmware or hardware detects a failure involving a corrupted partition table, allowing a full storage re-write. > diff --git a/drivers/mtd/devices/mtd_intel_dg.c b/drivers/mtd/devices/mtd_intel_dg.c > index f2fa8f68d1905..d11ddc687c4ac 100644 > --- a/drivers/mtd/devices/mtd_intel_dg.c > +++ b/drivers/mtd/devices/mtd_intel_dg.c [ ... ] > @@ -205,6 +206,13 @@ static unsigned int idg_nvm_get_region(const struct intel_dg_nvm *nvm, loff_t fr > { > unsigned int i; > > + /* > + * When survivability region is enabled it positioned on index 0 and has region_id = 0 > + * Region 0 is special, via this region whole device memory can be accessed. > + */ > + if (nvm->survivability_enabled) > + return 0; > + [Severity: High] Does this unconditional return of 0 create an underflow risk in the read, write, and erase paths? When survivability is enabled, idg_nvm_get_region() will always return index 0. If nvm->size was inflated during initialization by parsing limits from a corrupted partition table, a request could arrive with an offset larger than nvm->regions[0].size. In drivers/mtd/devices/mtd_intel_dg.c:intel_dg_mtd_read(), the bounds check subtracts the offset from the region size: idx = idg_nvm_get_region(nvm, from); if (len > nvm->regions[idx].size - from) len = nvm->regions[idx].size - from; If the from offset exceeds nvm->regions[0].size, the unsigned subtraction will underflow, resulting in a very large value. This bypasses the length truncation and allows out-of-bounds hardware memory accesses. Could the same underflow occur in the bounds checks in intel_dg_mtd_write() and intel_dg_mtd_erase()? > for (i = 0; i < nvm->nregions; i++) { > if ((nvm->regions[i].offset + nvm->regions[i].size - 1) >= from && -- Sashiko AI review · https://sashiko.dev/#/patchset/20260715-cri_surviv-v1-0-61763a6f1076@intel.com?part=1 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] mtd: mtd_intel_dg: add survivability partition 2026-07-15 13:45 ` [PATCH 1/2] mtd: mtd_intel_dg: add survivability partition Alexander Usyskin 2026-07-15 14:19 ` sashiko-bot @ 2026-07-17 9:42 ` Miquel Raynal 1 sibling, 0 replies; 6+ messages in thread From: Miquel Raynal @ 2026-07-17 9:42 UTC (permalink / raw) To: Alexander Usyskin Cc: Richard Weinberger, Vignesh Raghavendra, Matthew Brost, Thomas Hellström, Rodrigo Vivi, David Airlie, Simona Vetter, linux-mtd, linux-kernel, intel-xe, dri-devel Hello Alexander, On 15/07/2026 at 16:45:29 +03, Alexander Usyskin <alexander.usyskin@intel.com> wrote: > Add option to expose additional fixed-sized partition starting > from the beginning of storage. > Xe driver can request this partition exposure if firmware or hardware > have detected failure that may involve corrupted partition table. > Fixed-sized partition allows full storage re-write in this situation. > > Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Acked-by: Miquel Raynal <miquel.raynal@bootlin.com> I'm not sure I follow the exact use case, but I don't see any major show stopper from an MTD standpoint, so feel free to take this through drm. Thanks, Miquèl ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] drm/xe/nvm: define survivabilty partition 2026-07-15 13:45 [PATCH 0/2] drm/xe/nvm: add survivabilty partiton Alexander Usyskin 2026-07-15 13:45 ` [PATCH 1/2] mtd: mtd_intel_dg: add survivability partition Alexander Usyskin @ 2026-07-15 13:45 ` Alexander Usyskin 2026-07-15 14:32 ` sashiko-bot 1 sibling, 1 reply; 6+ messages in thread From: Alexander Usyskin @ 2026-07-15 13:45 UTC (permalink / raw) To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra, Matthew Brost, Thomas Hellström, Rodrigo Vivi, David Airlie, Simona Vetter Cc: linux-mtd, linux-kernel, intel-xe, dri-devel, Alexander Usyskin Define 8M survivability partition for CRI when storage is open for write. Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> --- drivers/gpu/drm/xe/xe_nvm.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_nvm.c b/drivers/gpu/drm/xe/xe_nvm.c index 1ea67eaeae24..54de0dbe1fa4 100644 --- a/drivers/gpu/drm/xe/xe_nvm.c +++ b/drivers/gpu/drm/xe/xe_nvm.c @@ -55,10 +55,11 @@ static bool xe_nvm_non_posted_erase(struct xe_device *xe) } } -static bool xe_nvm_writable_override(struct xe_device *xe) +static bool xe_nvm_writable_override(struct xe_device *xe, size_t *survivability_size) { struct xe_mmio *mmio = xe_root_tile_mmio(xe); bool writable_override; + size_t s_size = 0; struct xe_reg reg; u32 test_bit, test_val; @@ -67,6 +68,7 @@ static bool xe_nvm_writable_override(struct xe_device *xe) reg = PCODE_SCRATCH(0); test_bit = FDO_MODE; test_val = FDO_MODE; + s_size = SZ_8M; break; case XE_BATTLEMAGE: reg = HECI_FWSTS2(DG2_GSC_HECI2_BASE); @@ -90,12 +92,17 @@ static bool xe_nvm_writable_override(struct xe_device *xe) break; default: drm_err(&xe->drm, "Unknown platform\n"); + *survivability_size = 0; return true; } writable_override = (xe_mmio_read32(mmio, reg) & test_bit) == test_val; - if (writable_override) + if (writable_override) { drm_info(&xe->drm, "NVM access overridden by jumper\n"); + *survivability_size = s_size; + } else { + *survivability_size = 0; + } return writable_override; } @@ -142,7 +149,7 @@ int xe_nvm_init(struct xe_device *xe) if (!nvm) return -ENOMEM; - nvm->writable_override = xe_nvm_writable_override(xe); + nvm->writable_override = xe_nvm_writable_override(xe, &nvm->survivability_size); nvm->non_posted_erase = xe_nvm_non_posted_erase(xe); nvm->bar.parent = &pdev->resource[0]; nvm->bar.start = GEN12_GUNIT_NVM_BASE + pdev->resource[0].start; -- 2.53.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] drm/xe/nvm: define survivabilty partition 2026-07-15 13:45 ` [PATCH 2/2] drm/xe/nvm: define survivabilty partition Alexander Usyskin @ 2026-07-15 14:32 ` sashiko-bot 0 siblings, 0 replies; 6+ messages in thread From: sashiko-bot @ 2026-07-15 14:32 UTC (permalink / raw) To: Alexander Usyskin; +Cc: dri-devel Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] Enabling the survivability region causes an infinite loop during erase operations at the 8MB boundary, and bypasses bounds checks via integer underflow on reads and writes. -- --- Patch [2]: [PATCH 2/2] drm/xe/nvm: define survivabilty partition --- commit b38b020b9c762ee5ac9265db46b43fe2139de54d Author: Alexander Usyskin <alexander.usyskin@intel.com> drm/xe/nvm: define survivabilty partition Define 8M survivability partition for CRI when storage is open for write. > diff --git a/drivers/gpu/drm/xe/xe_nvm.c b/drivers/gpu/drm/xe/xe_nvm.c > index 1ea67eaeae243..54de0dbe1fa4d 100644 > --- a/drivers/gpu/drm/xe/xe_nvm.c > +++ b/drivers/gpu/drm/xe/xe_nvm.c [ ... ] > @@ -67,6 +68,7 @@ static bool xe_nvm_writable_override(struct xe_device *xe) > reg = PCODE_SCRATCH(0); > test_bit = FDO_MODE; > test_val = FDO_MODE; > + s_size = SZ_8M; [Severity: High] Does enabling this survivability region cause an infinite loop during erase operations in the MTD driver? When this patch sets the size to 8MB and survivability is enabled, all accesses are forced to use region 0, which has a hardcoded size of 8MB: drivers/mtd/devices/mtd_intel_dg.c:idg_nvm_get_region() { ... if (nvm->survivability_enabled) return 0; ... } If a user performs an erase operation at or crossing the 8MB boundary, it can trigger an infinite loop in intel_dg_mtd_erase(): drivers/mtd/devices/mtd_intel_dg.c:intel_dg_mtd_erase() { ... if (len > nvm->regions[idx].size - from) len = nvm->regions[idx].size - from; ... } When from reaches 8MB (the size of region 0), size - from evaluates to 0. This sets len to 0. This can cause the operation to return 0 immediately without decreasing total_len, leading to an infinite while (total_len > 0) loop. Additionally, read and write operations starting beyond 8MB might cause size - from to underflow to a massive positive number, bypassing bounds checks. > break; > case XE_BATTLEMAGE: > reg = HECI_FWSTS2(DG2_GSC_HECI2_BASE); -- Sashiko AI review · https://sashiko.dev/#/patchset/20260715-cri_surviv-v1-0-61763a6f1076@intel.com?part=2 ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-07-17 9:43 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-15 13:45 [PATCH 0/2] drm/xe/nvm: add survivabilty partiton Alexander Usyskin 2026-07-15 13:45 ` [PATCH 1/2] mtd: mtd_intel_dg: add survivability partition Alexander Usyskin 2026-07-15 14:19 ` sashiko-bot 2026-07-17 9:42 ` Miquel Raynal 2026-07-15 13:45 ` [PATCH 2/2] drm/xe/nvm: define survivabilty partition Alexander Usyskin 2026-07-15 14:32 ` sashiko-bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox