* [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
* [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 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 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
* 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
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