diff --git a/kernel/gpu_unlock/falcon.c b/kernel/gpu_unlock/falcon.c
index 53a9c23..114661f 100644
--- a/kernel/gpu_unlock/falcon.c
+++ b/kernel/gpu_unlock/falcon.c
@@ -158,6 +158,10 @@ int gu_falcon_reset(const struct gu_falcon_io *io, const struct gu_falcon_engine
 	}
 	if (falcon_read(io, GU_PMC_BOOT_0_OFFSET, &chip) || inaccessible(chip))
 		return -ENODEV;
+	/* kflcnReset_TU102 writes pGpu->chipId0 — the architecture field of
+	 * PMC_BOOT_0 (bits 27:20, 0x170 on GA100) — not the whole register
+	 * with its revision byte. The generic BL consults this register. */
+	chip = (chip >> 20) & 0xfff;
 	falcon_write(io, eng->base + GU_FALCON_RM_OFFSET, chip);
 	dev_dbg(io->dev, "Falcon reset done: base=%#x hwcfg=%#x chip=%#x\n", eng->base, hwcfg, chip);
 	return 0;
@@ -205,6 +209,82 @@ int gu_falcon_dma(const struct gu_falcon_io *io, u32 base, u32 dest, u32 mem_off
 	return gu_falcon_poll(io, base + GU_FALCON_DMATRFCMD_OFFSET, 2, 2, 1000000, true, NULL);
 }
 
+/* PIO IMEM loader (defined below; used by the GA100 Booter BL launch). */
+static void falcon_pio_imem(const struct gu_falcon_io *io, u32 base, const u32 *image,
+			    u32 offset, u32 size, bool secure);
+
+/* GA100/TU10x SEC2 Booter launch (nouveau tu102_gsp_booter_ctor +
+ * gm200_flcn_fw recipe): the image's 256-byte os_code stub is the
+ * plaintext entry (BOOTVEC 0); it consumes the PKC signature at DMEM
+ * patch_loc-os_data_off (patched by gpu_unlock_booter_patch) and
+ * decrypts/starts the secure app code itself. No BROM registers are
+ * used. Loads via PIO — proven on this silicon (the app executes when
+ * PIO-loaded; DMATRF SEC=01 loads leave the core faulting at the app's
+ * first instruction, observed 2026-10-24). os_code at VA 0 non-secure,
+ * app code at VA 0x100 secure, os_data (with signature) at DMEM 0. */
+int gu_falcon_booter_bl(const struct gu_falcon_io *io, const struct gu_falcon_engine *eng,
+			const u8 *image, const struct gpu_unlock_booter_hdr *hdr,
+			u32 mailbox0, u32 mailbox1,
+			struct gu_falcon_evidence *evidence)
+{
+	const u32 *words = (const u32 *)image;
+	u32 trans, cpuctl, i;
+	int ret;
+
+	memset(evidence, 0, sizeof(*evidence));
+	if (!image || hdr->os_code_off || (hdr->app_code_off & 255) ||
+	    hdr->app_data_size || (hdr->os_data_off & 255) || (hdr->os_data_size & 255) ||
+	    (hdr->os_data_size & 3))
+		return -EINVAL;
+	ret = gu_falcon_reset(io, eng, evidence);
+	if (ret)
+		return ret;
+	/* GA100 falcons stay halted after reset; tolerate (as in the loader). */
+	ret = gu_falcon_poll(io, eng->base + GU_FALCON_CPUCTL_OFFSET, 16, 0, 1000, false, NULL);
+	if (ret && ret != -ETIMEDOUT)
+		return ret;
+	/* gm200_flcn_fw_load prep (proven by nouveau on GA100): FBIF_CTL
+	 * ALLOW_PHYS_NO_CTX + DMACTL=0. Without the FBIF aperture the app's
+	 * first sysmem xfer (the WprMeta DMA) fails and it exits with
+	 * error 5 before doing anything. */
+	if (falcon_read(io, eng->base + GU_FALCON_DMACTL_OFFSET, &trans) || inaccessible(trans))
+		return -ENODEV;
+	falcon_write(io, eng->base + GU_FALCON_DMACTL_OFFSET, 0);
+	if (falcon_read(io, eng->fbif + GU_FBIF_CTL_OFFSET, &trans) || inaccessible(trans))
+		return -ENODEV;
+	falcon_write(io, eng->fbif + GU_FBIF_CTL_OFFSET, trans | (1u << 7));
+	/* os_code: plaintext stub, physical/VA 0, non-secure. */
+	falcon_pio_imem(io, eng->base, words, hdr->os_code_off, hdr->os_code_size, false);
+	/* app code: encrypted, physical/VA 0x100, secure. */
+	falcon_pio_imem(io, eng->base, words, hdr->app_code_off, hdr->app_code_size, true);
+	/* os_data at DMEM 0 (signature already patched at patch_loc). */
+	falcon_write(io, eng->base + GU_FALCON_DMEMC_OFFSET, 1u << 24);
+	for (i = 0; i < hdr->os_data_size; i += 4)
+		falcon_write(io, eng->base + GU_FALCON_DMEMD_OFFSET,
+			     words[(hdr->os_data_off + i) / 4]);
+	evidence->reloaded = true;
+	falcon_write(io, eng->base + GU_FALCON_BOOTVEC_OFFSET, 0);
+	falcon_write(io, eng->base + GU_FALCON_MAILBOX0_OFFSET, mailbox0);
+	falcon_write(io, eng->base + GU_FALCON_MAILBOX1_OFFSET, mailbox1);
+	if (falcon_read(io, eng->base + GU_FALCON_CPUCTL_OFFSET, &cpuctl) || inaccessible(cpuctl))
+		return -EIO;
+	dev_dbg(io->dev, "Booter BL start: base=%#x cpuctl=%#x code=%#x+%#x data=%#x+%#x mailbox=%#x:%#x\n",
+		eng->base, cpuctl, hdr->app_code_off, hdr->app_code_size,
+		hdr->os_data_off, hdr->os_data_size, mailbox1, mailbox0);
+	dma_wmb();
+	evidence->started = true;
+	if (cpuctl & (1u << 6))
+		falcon_write(io, eng->base + GU_FALCON_CPUCTL_ALIAS_OFFSET, 1u << 1);
+	else
+		falcon_write(io, eng->base + GU_FALCON_CPUCTL_OFFSET, 1u << 1);
+	ret = gu_falcon_poll(io, eng->base + GU_FALCON_CPUCTL_OFFSET,
+			     1u << 4, 1u << 4, 60000000, true, NULL);
+	if (ret)
+		return ret;
+	evidence->halted = true;
+	return 0;
+}
+
 int gu_falcon_hs(const struct gu_falcon_io *io, const struct gu_falcon_engine *eng,
 		 const struct gu_falcon_hs_image *program,
 		 struct gu_falcon_evidence *evidence)
@@ -226,8 +306,8 @@ int gu_falcon_hs(const struct gu_falcon_io *io, const struct gu_falcon_engine *e
 	ret = gu_falcon_reset(io, eng, evidence);
 	if (ret)
 		return ret;
-	ret = gu_falcon_poll(io, eng->base + GU_FALCON_CPUCTL_OFFSET, 16, 0, 1000, true, NULL);
-	if (ret)
+	ret = gu_falcon_poll(io, eng->base + GU_FALCON_CPUCTL_OFFSET, 16, 0, 1000, false, NULL);
+	if (ret && ret != -ETIMEDOUT)
 		return ret;
 	if (falcon_read(io, eng->fbif + GU_FBIF_CTL_OFFSET, &trans) || inaccessible(trans))
 		return -EIO;
@@ -271,9 +351,12 @@ int gu_falcon_hs(const struct gu_falcon_io *io, const struct gu_falcon_engine *e
 
 	ret = gu_falcon_poll(io, eng->base + GU_FALCON_CPUCTL_OFFSET,
 			     1u << 4, 1u << 4, 5000000, true, NULL);
-	if (ret)
+	if (ret && ret != -ETIMEDOUT)
 		return ret;
-	evidence->halted = true;
+	/* GA10x stock Booter: keeps running after the ROP write (observed on
+	 * GA107/A2 2026-10-25 — the write lands, the falcon never halts). The
+	 * non-halt is not a failure; the caller verifies the write readback. */
+	evidence->halted = !ret;
 	return 0;
 }
 
@@ -285,8 +368,7 @@ int gu_falcon_loader(const struct gu_falcon_io *io, const struct gu_falcon_engin
 		     const struct gu_falcon_loader_image *program,
 		     struct gu_falcon_evidence *evidence)
 {
-	u32 desc[21] = { 0 }, hwcfg, trans, ctl, i, dst;
-	const u32 *code;
+	u32 hwcfg, trans, ctl, dst;
 	int ret;
 
 	memset(evidence, 0, sizeof(*evidence));
@@ -294,40 +376,85 @@ int gu_falcon_loader(const struct gu_falcon_io *io, const struct gu_falcon_engin
 	    (program->dma & 255) || program->dma > ~0ull - program->data_off ||
 	    (program->data_off & 255))
 		return -EINVAL;
-	code = program->loader;
 	ret = gu_falcon_reset(io, eng, evidence);
 	if (ret)
 		return ret;
-	if (falcon_read(io, eng->base + GU_FALCON_CPUCTL_OFFSET, &ctl) || inaccessible(ctl) || (ctl & 16) ||
+	/* CPUCTL 4:4 is HALTED, a read-only status (dev_falcon_v4.h). A
+	 * halted falcon is the normal post-reset idle on GA100 and is a
+	 * loadable state: IMEM/DMEM ports and BOOTVEC work while halted, and
+	 * the STARTCPU launch below unhalts. Only the read itself failing is
+	 * fatal here. */
+	if (falcon_read(io, eng->base + GU_FALCON_CPUCTL_OFFSET, &ctl) || inaccessible(ctl) ||
 	    falcon_read(io, eng->base + GU_FALCON_HWCFG_OFFSET, &hwcfg) || inaccessible(hwcfg) ||
 	    falcon_read(io, eng->base + GU_FALCON_DMACTL_OFFSET, &trans) || inaccessible(trans))
 		return -ENODEV;
 	if ((hwcfg & 0x1ff) < 2)
 		return -ERANGE;
 	dst = ((hwcfg & 0x1ff) - 2) << 8;
-	falcon_write(io, eng->base + GU_FALCON_DMACTL_OFFSET, trans & ~1u);
+	/* kflcnDisableCtxReq: DMACTL=0 and FBIF_CTL.ALLOW_PHYS_NO_CTX, so the
+	 * generic BL can fetch its image from coherent sysmem via ctxDma 4
+	 * without a bound context. */
+	falcon_write(io, eng->base + GU_FALCON_DMACTL_OFFSET, 0);
+	if (falcon_read(io, eng->fbif + GU_FBIF_CTL_OFFSET, &trans) || inaccessible(trans))
+		return -ENODEV;
+	falcon_write(io, eng->fbif + GU_FBIF_CTL_OFFSET, trans | (1u << 7));
+	/* Two apertures: index 0 serves the DMATRF engine's own no-ctx
+	 * fetches (what gu_falcon_hs uses on GA10x); index 4 serves the
+	 * generic BL's ctxDma-4 image fetches from coherent sysmem. Both
+	 * must be physical for this boot path. */
+	if (falcon_read(io, eng->fbif + GU_FBIF_TRANSCFG(0), &trans) || inaccessible(trans))
+		return -ENODEV;
+	falcon_write(io, eng->fbif + GU_FBIF_TRANSCFG(0), (trans & ~7u) | 5u);
 	if (falcon_read(io, eng->fbif + GU_FBIF_TRANSCFG(4), &trans) || inaccessible(trans))
 		return -ENODEV;
 	falcon_write(io, eng->fbif + GU_FBIF_TRANSCFG(4), (trans & ~7u) | 5u);
-	desc[8] = 4;
-	desc[9] = lower_32_bits(program->dma);
-	desc[10] = upper_32_bits(program->dma);
-	desc[11] = program->imem_pa;
-	desc[12] = program->imem_ns_size;
-	desc[13] = program->imem_sec_pa;
-	desc[14] = program->imem_sec_size;
-	desc[16] = lower_32_bits(program->dma + program->data_off);
-	desc[17] = upper_32_bits(program->dma + program->data_off);
-	desc[18] = program->dmem_size;
-	falcon_write(io, eng->base + GU_FALCON_DMEMC_OFFSET, 1u << 24);
-	for (i = 0; i < 21; i++)
-		falcon_write(io, eng->base + GU_FALCON_DMEMD_OFFSET, desc[i]);
-	falcon_write(io, eng->base + GU_FALCON_IMEMC_OFFSET, dst | (1u << 24));
-	for (i = 0; i < 512; i += 4) {
-		if (!(i & 255))
-			falcon_write(io, eng->base + GU_FALCON_IMEMT_OFFSET, 0xfd + (i >> 8));
-		falcon_write(io, eng->base + GU_FALCON_IMEMD_OFFSET, code[i / 4]);
+	/* The GA100 GSP falcon (hybrid RISC-V core) gates the IMEM/DMEM PIO
+	 * data ports from the host: the ports read back zero and no write
+	 * lands, while ordinary registers (mailboxes, CPUCTL, ENGINE) accept
+	 * writes. Stage the descriptor and the generic BL through the DMATRF
+	 * engine instead — the same mechanism the GA10x BROM path proves on
+	 * this hardware family. Descriptor at DMEM offset 0 (per the pinned
+	 * SEC2 generic-BL layout: blDmemDescLoadOff 0), BL at the top of
+	 * IMEM, non-secure, 256-byte blocks. */
+	if (!program->desc_mem || !program->desc_dma || !program->bl_dma)
+		return -EINVAL;
+	{
+		u32 desc[21] = { 0 };
+
+		desc[8] = 4;
+		desc[9] = lower_32_bits(program->dma);
+		desc[10] = upper_32_bits(program->dma);
+		desc[11] = program->imem_pa;
+		desc[12] = program->imem_ns_size;
+		desc[13] = program->imem_sec_pa;
+		desc[14] = program->imem_sec_size;
+		desc[16] = lower_32_bits(program->dma + program->data_off);
+		desc[17] = upper_32_bits(program->dma + program->data_off);
+		desc[18] = program->dmem_size;
+		memset(program->desc_mem, 0, 256);
+		memcpy(program->desc_mem, desc, sizeof(desc));
+		dma_wmb();
 	}
+	ret = gu_falcon_dma(io, eng->base, 0, 0, program->desc_dma, 256,
+			     gpu_unlock_dma_cmd(false));
+	if (ret)
+		return ret;
+	/* Per the falcon xfer spec (and gu_falcon_hs's source compensation):
+	 * for code loads DMATRFMOFFS is the LOCAL physical address while
+	 * DMATRFFBOFFS is the EXTERNAL offset AND the v3+ virtual address the
+	 * block is mapped to — the fetch reads (DMATRFBASE + FBOFFS), so the
+	 * sysmem base compensates for the VA. Load the BL code (512 bytes =
+	 * blCodeSize; NVIDIA never loads the BL's data section, and a third
+	 * 256B block would fall off the 256-block IMEM) so it maps at VA
+	 * 0xfd00 (tag 0xfd) at the top two IMEM blocks. */
+	if (program->bl_dma < 0xfd00)
+		return -ERANGE;
+	ret = gu_falcon_dma(io, eng->base, dst, 0xfd00, program->bl_dma - 0xfd00, 512,
+			     (6u << 8) | (1u << 4));
+	if (ret)
+		return ret;
+	dev_dbg(io->dev, "generic BL DMA-staged: dst=%#x desc_dma=%pad bl_dma=%pad\n",
+		dst, &program->desc_dma, &program->bl_dma);
 	evidence->reloaded = true;
 	falcon_write(io, eng->base + GU_FALCON_BOOTVEC_OFFSET, 0xfd00);
 	falcon_write(io, eng->base + GU_FALCON_MAILBOX0_OFFSET, 0);
@@ -335,8 +462,44 @@ int gu_falcon_loader(const struct gu_falcon_io *io, const struct gu_falcon_engin
 	dma_wmb();
 	evidence->started = true;
 	falcon_write(io, eng->base + ((ctl & 64) ? GU_FALCON_CPUCTL_ALIAS_OFFSET :
-						GU_FALCON_CPUCTL_OFFSET), 2);
-	ret = gu_falcon_poll(io, eng->base + GU_FALCON_CPUCTL_OFFSET, 16, 16, 5000000, true, NULL);
+					GU_FALCON_CPUCTL_OFFSET), 2);
+	/* FWSEC runs a full FRTS scrub pass on boards with a hardware
+	 * scrubber (GA100); that can outlast the 5s budget Turing boards
+	 * needed. Poll up to 60s and, on timeout, read the mailboxes and
+	 * CPUCTL so a FWSEC error code is recorded instead of a bare -110. */
+	ret = gu_falcon_poll(io, eng->base + GU_FALCON_CPUCTL_OFFSET, 16, 16, 60000000, true, NULL);
+	if (ret == -ETIMEDOUT) {
+		u32 mb0 = ~0u, mb1 = ~0u, ctl2 = ~0u, irq = ~0u, dcmd = ~0u, d[24], im[4];
+		u32 i2;
+
+		falcon_read(io, eng->base + GU_FALCON_MAILBOX0_OFFSET, &mb0);
+		falcon_read(io, eng->base + GU_FALCON_MAILBOX1_OFFSET, &mb1);
+		falcon_read(io, eng->base + GU_FALCON_CPUCTL_OFFSET, &ctl2);
+		falcon_read(io, eng->base + GU_FALCON_IRQSTAT_OFFSET, &irq);
+		falcon_read(io, eng->base + GU_FALCON_DMATRFCMD_OFFSET, &dcmd);
+		/* DMEM@0 read-back: word 8 is still ctxDma=4 if the generic BL
+		 * never ran; a BL that ran rewrites its scratch there. */
+		falcon_write(io, eng->base + GU_FALCON_DMEMC_OFFSET, 1u << 24);
+		for (i2 = 0; i2 < 24; i2++)
+			falcon_read(io, eng->base + GU_FALCON_DMEMD_OFFSET, &d[i2]);
+		falcon_write(io, eng->base + GU_FALCON_IMEMT_OFFSET, 0xfd);
+		falcon_write(io, eng->base + GU_FALCON_IMEMC_OFFSET, 0xfd00 | (1u << 24));
+		for (i2 = 0; i2 < 4; i2++)
+			falcon_read(io, eng->base + GU_FALCON_IMEMD_OFFSET, &im[i2]);
+		dev_err(io->dev,
+			"FWSEC launch timeout: mailbox0=%#x mailbox1=%#x cpuctl=%#x irqstat=%#x dmatrfcmd=%#x\n",
+			mb0, mb1, ctl2, irq, dcmd);
+		dev_err(io->dev,
+			"FWSEC DMEM@0: %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
+			d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
+			d[8], d[9], d[10], d[11]);
+		dev_err(io->dev,
+			"FWSEC DMEM@48: %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
+			d[12], d[13], d[14], d[15], d[16], d[17], d[18], d[19],
+			d[20], d[21], d[22], d[23]);
+		dev_err(io->dev,
+			"FWSEC IMEM@fd00: %08x %08x %08x %08x\n", im[0], im[1], im[2], im[3]);
+	}
 	evidence->halted = !ret;
 	return ret;
 }
@@ -371,8 +534,8 @@ int gu_falcon_direct(const struct gu_falcon_io *io, const struct gu_falcon_engin
 	ret = gu_falcon_reset(io, eng, evidence);
 	if (ret)
 		return ret;
-	ret = gu_falcon_poll(io, eng->base + GU_FALCON_CPUCTL_OFFSET, 16, 0, 1000, true, NULL);
-	if (ret)
+	ret = gu_falcon_poll(io, eng->base + GU_FALCON_CPUCTL_OFFSET, 16, 0, 1000, false, NULL);
+	if (ret && ret != -ETIMEDOUT)
 		return ret;
 	/* REQUIRE_CTX=false, matching kflcnDisableCtxReq. */
 	if (falcon_read(io, eng->base + GU_FALCON_DMACTL_OFFSET, &ctl) || inaccessible(ctl))
diff --git a/kernel/gpu_unlock/falcon.h b/kernel/gpu_unlock/falcon.h
index d69df1a..772914e 100644
--- a/kernel/gpu_unlock/falcon.h
+++ b/kernel/gpu_unlock/falcon.h
@@ -6,6 +6,8 @@
 
 struct device;
 
+struct gpu_unlock_booter_hdr;
+
 /* Borrowed hardware access only: no PCI, allocation or transaction ownership. */
 struct gu_falcon_io {
 	struct device *dev;
@@ -42,6 +44,12 @@ struct gu_falcon_loader_image {
 	size_t loader_size;
 	dma_addr_t dma;
 	u32 data_off, imem_pa, imem_ns_size, imem_sec_pa, imem_sec_size, dmem_size;
+	/* DMA-staged copies: the GA100 GSP falcon gates the IMEM/DMEM PIO
+	 * data ports, so the generic BL and its descriptor must be staged
+	 * into falcon memory through the DMATRF engine instead. */
+	dma_addr_t bl_dma;
+	u8 *desc_mem;
+	dma_addr_t desc_dma;
 };
 
 int gu_falcon_poll(const struct gu_falcon_io *io, u32 offset, u32 mask, u32 expect,
@@ -54,6 +62,10 @@ int gu_falcon_reset(const struct gu_falcon_io *io, const struct gu_falcon_engine
 		    struct gu_falcon_evidence *evidence);
 int gu_falcon_hs(const struct gu_falcon_io *io, const struct gu_falcon_engine *eng,
 		 const struct gu_falcon_hs_image *image, struct gu_falcon_evidence *evidence);
+int gu_falcon_booter_bl(const struct gu_falcon_io *io, const struct gu_falcon_engine *eng,
+			const u8 *image, const struct gpu_unlock_booter_hdr *hdr,
+			u32 mailbox0, u32 mailbox1,
+			struct gu_falcon_evidence *evidence);
 int gu_falcon_direct(const struct gu_falcon_io *io, const struct gu_falcon_engine *eng,
 		     const struct gu_falcon_direct_image *image, struct gu_falcon_evidence *evidence);
 int gu_falcon_loader(const struct gu_falcon_io *io, const struct gu_falcon_engine *eng,
diff --git a/kernel/gpu_unlock/firmware_610.c b/kernel/gpu_unlock/firmware_610.c
index ee50593..1e829ff 100644
--- a/kernel/gpu_unlock/firmware_610.c
+++ b/kernel/gpu_unlock/firmware_610.c
@@ -12,6 +12,7 @@
 
 #define BOOTER_MAGIC 0x314c5442u
 #define SEC2_BOOTER_FILE "gpu-unlock/610.43.03/booter_load_ga100.bin"
+#define SEC2_BOOTER_GA10X_FILE "gpu-unlock/610.43.03/booter_load_ga102.bin"
 #define GSP_FILE "gpu-unlock/610.43.03/gsp_ga10x.bin"
 #define GSP_BOOT_FILE "gpu-unlock/610.43.03/gsp_boot_ga102.bin"
 #define GSP_BOOT_DESC_FILE "gpu-unlock/610.43.03/gsp_boot_desc_ga102.bin"
@@ -20,9 +21,11 @@
 #define BOOT_GA100_FILE "gpu-unlock/610.43.03/gsp_boot_ga100.bin"
 #define BOOT_DESC_GA100_FILE "gpu-unlock/610.43.03/gsp_boot_desc_ga100.bin"
 #define FALCON_LOADER_FILE "gpu-unlock/610.43.03/falcon_loader.bin"
+/* GA100 boots the same SEC2 Booter via BROM HS as GA10x; only FWSEC
+ * uses the v2 generic-BL loader, which no longer depends on .direct. */
 static const struct gpu_unlock_610_fw_desc ga100_load = {
 	.gsp = GSP_GA100_FILE, .boot = BOOT_GA100_FILE, .desc = BOOT_DESC_GA100_FILE,
-	.signature_section = ".fwsignature_ga100", .boot_size = 4096, .direct = true,
+	.signature_section = ".fwsignature_ga100", .boot_size = 4096, .direct = false,
 };
 static const struct gpu_unlock_610_fw_desc ga10x_load = {
 	.gsp = GSP_FILE, .boot = GSP_BOOT_FILE, .desc = GSP_BOOT_DESC_FILE,
@@ -87,16 +90,24 @@ static int validate_booter(const struct firmware *fw, struct gpu_unlock_booter_h
 	memcpy(&image_size, data + 8 + sizeof(hdr), sizeof(image_size));
 	memcpy(&sig_bytes, data + 12 + sizeof(hdr), sizeof(sig_bytes));
 	if (!hdr.ucode_id || hdr.num_apps != 1 || sig_bytes != hdr.sig_bytes ||
-	    image_size != GU_BOOTER_IMAGE_SIZE ||
 	    fw->size != 72u + image_size + sig_bytes)
 		return GU_DIAG(-EINVAL);
-	/* Pinned signed GA100 Booter geometry, used by both launch paths. */
-	if (hdr.ucode_id != 3 || hdr.engine_id != 1 || hdr.num_sigs != 1 ||
-	    sig_bytes != GU_BOOTER_SIG_TOTAL || hdr.os_code_off != 0 ||
-	    hdr.os_code_size != 256 || hdr.os_data_off != 34560 ||
-	    hdr.os_data_size != 25600 || hdr.app_code_off != 256 ||
-	    hdr.app_code_size != 34304 || hdr.app_data_off != 256 ||
-	    hdr.app_data_size != 0 || hdr.patch_loc != 35072)
+	/* Two pinned signed geometries: the GA100 Booter (A30-proven) and the
+	 * GA102 Booter (upstream-proven on 3090s and the A2 — the GA100 image's
+	 * signature does not validate on GA10x SEC2, so its write phase never
+	 * executes there). Shared invariants first, then per-family pins. */
+	if (hdr.ucode_id != 3 || hdr.engine_id != 1 || hdr.os_code_off != 0 ||
+	    hdr.os_code_size != 256 || hdr.app_code_off != 256 ||
+	    hdr.app_data_off != 256 || hdr.app_data_size != 0)
+		return GU_DIAG(-EINVAL);
+	if (!((hdr.os_data_off == 34560 && hdr.os_data_size == 25600 &&
+	       hdr.app_code_size == 34304 && hdr.patch_loc == 35072 &&
+	       hdr.num_sigs == 1 && sig_bytes == GU_BOOTER_SIG_TOTAL &&
+	       image_size == GU_BOOTER_IMAGE_SIZE) ||
+	      (hdr.os_data_off == 0x8a00 && hdr.os_data_size == 0x6200 &&
+	       hdr.app_code_size == 0x8900 && hdr.patch_loc == 0x8a10 &&
+	       hdr.num_sigs == 2 && sig_bytes == 0x300 &&
+	       image_size == 0xec00)))
 		return GU_DIAG(-EINVAL);
 	*out = hdr;
 	return 0;
@@ -179,7 +190,23 @@ int gpu_unlock_610_load_shared(const struct gu_device *device, struct gpu_unlock
 		}
 		shared->booter = booter;
 	}
-	if (load->direct && !shared->loader) {
+	/* GA10x cards need the GA102 Booter; only load it when a GA10x card is
+	 * actually targeted so A30-only boots never require the extra asset. */
+	if (!device->recipe->direct_boot && !shared->booter_ga10x) {
+		const struct firmware *booter_ga10x = NULL;
+
+		ret = request_scoped(&pdev->dev, &booter_ga10x, SEC2_BOOTER_GA10X_FILE);
+		if (ret)
+			goto out;
+		ret = validate_booter(booter_ga10x, &shared->booter_hdr_ga10x);
+		if (ret) {
+			dev_err(&pdev->dev, "invalid GA10x SEC2 Booter bundle: error=%d\n", ret);
+			release_firmware(booter_ga10x);
+			goto out;
+		}
+		shared->booter_ga10x = booter_ga10x;
+	}
+	if (!shared->loader) {
 		ret = request_scoped(&pdev->dev, &loader, FALCON_LOADER_FILE);
 		if (ret)
 			goto out;
@@ -205,10 +232,12 @@ void gpu_unlock_610_release_shared(struct gpu_unlock_610_shared *shared)
 	release_family(&shared->ga10x);
 	release_firmware(shared->loader);
 	release_firmware(shared->booter);
+	release_firmware(shared->booter_ga10x);
 	memset(shared, 0, sizeof(*shared));
 }
 
 MODULE_FIRMWARE(SEC2_BOOTER_FILE);
+MODULE_FIRMWARE(SEC2_BOOTER_GA10X_FILE);
 MODULE_FIRMWARE(FALCON_LOADER_FILE);
 MODULE_FIRMWARE(GSP_FILE);
 MODULE_FIRMWARE(GSP_BOOT_FILE);
diff --git a/kernel/gpu_unlock/firmware_610.h b/kernel/gpu_unlock/firmware_610.h
index 4550936..eeb2ad0 100644
--- a/kernel/gpu_unlock/firmware_610.h
+++ b/kernel/gpu_unlock/firmware_610.h
@@ -31,6 +31,10 @@ struct gpu_unlock_610_shared {
 	struct gpu_unlock_610_firmware ga100, ga10x;
 	const struct firmware *booter, *loader;
 	struct gpu_unlock_booter_hdr booter_hdr;
+	/* GA10x (GA102 Booter) payload base — the GA100 Booter's signature
+	 * does not validate on GA10x SEC2, so the write phase never runs. */
+	const struct firmware *booter_ga10x;
+	struct gpu_unlock_booter_hdr booter_hdr_ga10x;
 };
 
 /* Serial preparation only; no workers may run until all calls have returned.
diff --git a/kernel/gpu_unlock/layout_610.c b/kernel/gpu_unlock/layout_610.c
index 0c91328..ebe6d7e 100644
--- a/kernel/gpu_unlock/layout_610.c
+++ b/kernel/gpu_unlock/layout_610.c
@@ -47,7 +47,7 @@ int gpu_unlock_layout(const struct gpu_unlock_layout_in *in,
 
 	if (!in || !out)
 		return GU_DIAG(-EINVAL);
-	if (!in->usable_fb || !in->vga_base || !in->frts_size || !in->boot_size ||
+	if (!in->usable_fb || !in->vga_base || !in->boot_size ||
 	    !in->image_size)
 		return GU_DIAG(-EINVAL);
 	reserved = in->vga_base;
@@ -93,7 +93,7 @@ int gpu_unlock_layout(const struct gpu_unlock_layout_in *in,
 	if (ret)
 		return GU_DIAG(ret);
 	if (nonwpr_start >= in->usable_fb || wpr_end > in->usable_fb ||
-	    wpr_start >= wpr_end || gsp >= boot || boot >= frts || frts >= wpr_end)
+	    wpr_start >= wpr_end || gsp >= boot || boot >= frts || frts > wpr_end)
 		return GU_DIAG(-ERANGE);
 	out->reserved_top = reserved;
 	out->wpr_end = wpr_end;
diff --git a/kernel/gpu_unlock/payload_610.c b/kernel/gpu_unlock/payload_610.c
index 527f2a2..de4ec04 100644
--- a/kernel/gpu_unlock/payload_610.c
+++ b/kernel/gpu_unlock/payload_610.c
@@ -17,3 +17,15 @@ void gu_payload_fill(u8 *image, u32 address, u32 value)
 	put32(image, 0xf754, value);
 	put32(image, 0xf76c, address);
 }
+
+void gu_payload_fill_ga10x(u8 *image, u32 address, u32 value)
+{
+	u32 offset;
+	for (offset = 0; offset < GU_PAYLOAD_SIZE_GA10X; offset += 4)
+		put32(image, offset, 0x19c);
+#define GU_PAYLOAD_WORD(offset, value) put32(image, offset, value);
+#include "payload_words_ga10x.h"
+#undef GU_PAYLOAD_WORD
+	put32(image, 0xF948, value);
+	put32(image, 0xF960, address);
+}
diff --git a/kernel/gpu_unlock/payload_610.h b/kernel/gpu_unlock/payload_610.h
index c35365f..8de4823 100644
--- a/kernel/gpu_unlock/payload_610.h
+++ b/kernel/gpu_unlock/payload_610.h
@@ -3,4 +3,5 @@
 #define GPU_UNLOCK_PAYLOAD_610_H
 #include "prep_610.h"
 void gu_payload_fill(u8 *image, u32 address, u32 value);
+void gu_payload_fill_ga10x(u8 *image, u32 address, u32 value);
 #endif
diff --git a/kernel/gpu_unlock/payload_words_ga10x.h b/kernel/gpu_unlock/payload_words_ga10x.h
new file mode 100644
index 0000000..17b4283
--- /dev/null
+++ b/kernel/gpu_unlock/payload_words_ga10x.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* GA10x V67 words: upstream Zagitta generate_v67.py (c274e94) PATCHED_WORDS,
+ * pinned against v67-ga102-610.43.03.bin. The (value, address) pair slots
+ * at 0xF948/0xF960 carry the default FEAT PLM write and are overwritten at
+ * runtime by gu_payload_fill_ga10x() for each table entry. */
+GU_PAYLOAD_WORD(0x1100, 0x00000007)
+GU_PAYLOAD_WORD(0xF948, 0xFFFFFFFF)
+GU_PAYLOAD_WORD(0xF950, 0x00000D44)
+GU_PAYLOAD_WORD(0xF960, 0x00823804)
+GU_PAYLOAD_WORD(0xF968, 0x00001FCE)
+GU_PAYLOAD_WORD(0xF974, 0x00000000)
+GU_PAYLOAD_WORD(0xF97C, 0x00001101)
+GU_PAYLOAD_WORD(0xF980, 0x000084C8)
+GU_PAYLOAD_WORD(0xF984, 0x00008E18)
+GU_PAYLOAD_WORD(0xF98C, 0x000084C8)
+GU_PAYLOAD_WORD(0xF990, 0x00000000)
+GU_PAYLOAD_WORD(0xF998, 0x00001FCE)
+GU_PAYLOAD_WORD(0xF9A4, 0x0000FFBC)
+GU_PAYLOAD_WORD(0xF9AC, 0x00005789)
+GU_PAYLOAD_WORD(0xF9BC, 0x00000D44)
+GU_PAYLOAD_WORD(0xF9CC, 0x00000003)
+GU_PAYLOAD_WORD(0xF9D4, 0x00001FCE)
+GU_PAYLOAD_WORD(0xF9E8, 0x00000D52)
+GU_PAYLOAD_WORD(0xF9EC, 0x000081EE)
diff --git a/kernel/gpu_unlock/prep_610.c b/kernel/gpu_unlock/prep_610.c
index f0e673e..55f5ce4 100644
--- a/kernel/gpu_unlock/prep_610.c
+++ b/kernel/gpu_unlock/prep_610.c
@@ -225,7 +225,7 @@ int gpu_unlock_wpr_meta_pack(u8 out[GU_WPR_META_SIZE],
 			     const struct gpu_unlock_wpr_args *a)
 {
 	if (!out || !layout || !a || !a->signature_size || !a->image_size ||
-	    !a->boot.image_size || !a->fb_size || !a->frts_size ||
+	    !a->boot.image_size || !a->fb_size ||
 	    a->vga_offset >= a->fb_size ||
 	    a->boot.code_offset >= a->boot.image_size ||
 	    a->boot.data_offset >= a->boot.image_size ||
@@ -239,7 +239,7 @@ int gpu_unlock_wpr_meta_pack(u8 out[GU_WPR_META_SIZE],
 	    a->image_size > layout->boot_offset - layout->gsp_offset ||
 	    layout->boot_offset >= layout->frts_offset ||
 	    a->boot.image_size > layout->frts_offset - layout->boot_offset ||
-	    layout->frts_offset >= layout->wpr_end ||
+	    layout->frts_offset > layout->wpr_end ||
 	    a->frts_size != layout->wpr_end - layout->frts_offset ||
 	    layout->wpr_end > a->vga_offset)
 		return GU_DIAG(-EINVAL);
diff --git a/kernel/gpu_unlock/prep_610.h b/kernel/gpu_unlock/prep_610.h
index 086b9f2..f13142b 100644
--- a/kernel/gpu_unlock/prep_610.h
+++ b/kernel/gpu_unlock/prep_610.h
@@ -20,6 +20,9 @@ typedef uint64_t u64;
 #define GU_BOOTER_IMAGE_SIZE 60160u
 #define GU_BOOTER_SIG_TOTAL 384u
 #define GU_PAYLOAD_SIZE 0xf800u
+/* GA10x (GA102 Booter) V67 payload: upstream generate_v67.py layout. */
+#define GU_PAYLOAD_SIZE_GA10X 0xfa00u
+#define GU_PAYLOAD_SIZE_MAX 0xfa00u
 #define GU_WPR_META_SIZE 256u
 #define GU_WPR_META_MAGIC 0xdc3aae21371a60b3ull
 #define GU_RADIX_PAGE 4096u
diff --git a/kernel/gpu_unlock/recipes.c b/kernel/gpu_unlock/recipes.c
index 721fc64..6d9cde8 100644
--- a/kernel/gpu_unlock/recipes.c
+++ b/kernel/gpu_unlock/recipes.c
@@ -11,8 +11,27 @@ static const struct gu_reg_write ga10x_plm[] = {
 	{ GU_WPR_CFG_PLM_OFFSET, 0xfffff0ff },
 	{ GU_FEAT_PLM_OFFSET,    0xffffffff },
 };
+/* GA107 harvest probe, post-driver-boot variant. The driver's GSP-RM
+ * re-secures the PAPU trio (wpr_cfg 0x1fa7cc / wpr 0x1fa7c4 / mmu_lock
+ * 0x1fa7c8) to 0x0004cb8f on every boot and locks them against further
+ * privileged writes — observed identically on the unlocked A30 (driver up:
+ * FEAT/FEAT2/OPT/RECONFIG still 0xffffffff from our payload, PAPU trio
+ * 0x4cb8f) and the A2 (post-driver chain: wpr_cfg write bounces, readback
+ * 0x4cb8f, measured 2026-10-25). We do not need the PAPU PLMs post-boot
+ * (WPR2 is built by FWSEC; selectors are host-side writes gated by FEAT),
+ * so skip them entirely. FEAT first (selectors), RECONFIG second (per-GPC
+ * TPC overrides 0x820a40+ — never opened by the historical 2-entry GA10x
+ * table). FBPA/OPT/FEAT2/XVE dropped: speculative, and a bounce aborts
+ * the whole table before the selector writes. */
+static const struct gu_reg_write ga107_plm[] = {
+	{ GU_FEAT_PLM_OFFSET,     0xffffffff },
+	{ GU_RECONFIG_PLM_OFFSET, 0xffffffff },
+};
+/* cmpunlocker (GA100 A100/CMP170HX, device 0x20c2/0x2082) writes wpr_cfg at
+ * 0x1fa7cc — same offset as GA10x. 0x1fa7c8 is the separate FB MMU LOCK PLM. */
+#define GU_WPR_CFG_PLM_OFFSET_GA100 0x001fa7ccu
 static const struct gu_reg_write ga100_plm[] = {
-	{ GU_WPR_CFG_PLM_OFFSET,   0xfffff0ff },
+	{ GU_WPR_CFG_PLM_OFFSET_GA100, 0xfffff0ff },
 	{ GU_FBPA_PLM_OFFSET,      0xffffffff },
 	{ GU_WPR_PLM_OFFSET,       0xffffffff },
 	{ GU_FEAT_PLM_OFFSET,      0xffffffff },
@@ -36,13 +55,22 @@ static const struct gu_family_writes ga10x = {
 	.name = "GA102/GA103/GA104/GA106",
 	.privileged = GU_WRITE_TABLE(ga10x_plm), .host = GU_WRITE_TABLE(selectors),
 };
+static const struct gu_family_writes ga107 = {
+	.name = "GA107",
+	.privileged = GU_WRITE_TABLE(ga107_plm), .host = GU_WRITE_TABLE(selectors),
+};
 #define GA100(id) { id, 0x170, true, &ga100 }
 #define GA102(id) { id, 0x172, false, &ga10x }
 #define GA103(id) { id, 0x173, false, &ga10x }
 #define GA104(id) { id, 0x174, false, &ga10x }
 #define GA106(id) { id, 0x176, false, &ga10x }
+#define GA107(id) { id, 0x177, false, &ga107 }
 static const struct gu_card cards[] = {
-	GA100(0x20c2), GA100(0x2082),
+	/* GA100: A100 variants + A30 PCIe (local experimental addition:
+	 * 0x20b7 is the A30 GA100GL; selectors are expected already full-rate —
+	 * the goal is opening the GA100 PLM set for privileged geometry/GPC
+	 * probing, not rate gains). */
+	GA100(0x20c2), GA100(0x2082), GA100(0x20b7),
 	GA102(0x2200), GA102(0x2203), GA102(0x2204), GA102(0x2205),
 	GA102(0x2206), GA102(0x2207), GA102(0x2208), GA102(0x220a),
 	GA102(0x220d), GA102(0x2216), GA102(0x222b), GA102(0x222f),
@@ -57,6 +85,8 @@ static const struct gu_card cards[] = {
 	GA106(0x2501), GA106(0x2503), GA106(0x2504), GA106(0x2505),
 	GA106(0x2507), GA106(0x2508), GA106(0x2509), GA106(0x252f),
 	GA106(0x2544),
+	/* GA107: NVIDIA A2 (GA107GL 0x25b6) — extended-PLM harvest probe. */
+	GA107(0x25b6),
 };
 const struct gu_card *gu_card_find(u16 device)
 {
diff --git a/kernel/gpu_unlock/registers.h b/kernel/gpu_unlock/registers.h
index 578c447..b5eaf7b 100644
--- a/kernel/gpu_unlock/registers.h
+++ b/kernel/gpu_unlock/registers.h
@@ -23,6 +23,7 @@
 #define GU_FALCON_MAILBOX1_OFFSET     0x00000044u
 #define GU_FALCON_RM_OFFSET           0x00000084u
 #define GU_FALCON_HWCFG2_OFFSET       0x000000f4u
+#define GU_FALCON_IRQSTAT_OFFSET      0x00000008u
 #define GU_FALCON_CPUCTL_OFFSET       0x00000100u
 #define GU_FALCON_BOOTVEC_OFFSET      0x00000104u
 #define GU_FALCON_HWCFG_OFFSET        0x00000108u
diff --git a/kernel/gpu_unlock/unlock_610.c b/kernel/gpu_unlock/unlock_610.c
index 83c960e..6b700d5 100644
--- a/kernel/gpu_unlock/unlock_610.c
+++ b/kernel/gpu_unlock/unlock_610.c
@@ -61,6 +61,7 @@ struct unlock_transaction_work {
 	struct gpu_unlock_booter_hdr booter_hdr;
 	void *payload_cpu;
 	dma_addr_t payload_dma;
+	u32 payload_size;
 	void *stock_cpu;
 	dma_addr_t stock_dma;
 	u64 stock_size;
@@ -245,10 +246,10 @@ static void free_coherent(struct unlock_transaction_work *work)
 		work->fwsec_cpu = NULL;
 	}
 	if (work->booter_cpu)
-		dma_free_coherent(&work->pdev->dev, GU_BOOTER_IMAGE_SIZE,
+		dma_free_coherent(&work->pdev->dev, work->booter_image_size,
 				  work->booter_cpu, work->booter_dma);
 	if (work->payload_cpu)
-		dma_free_coherent(&work->pdev->dev, GU_PAYLOAD_SIZE, work->payload_cpu,
+		dma_free_coherent(&work->pdev->dev, GU_PAYLOAD_SIZE_MAX, work->payload_cpu,
 				  work->payload_dma);
 	if (work->stock_cpu)
 		dma_free_coherent(&work->pdev->dev, work->stock_size,
@@ -262,10 +263,163 @@ static void free_coherent(struct unlock_transaction_work *work)
 	work->meta_cpu = NULL;
 }
 
-static int unlock_transaction_unwind(struct unlock_transaction_work *work)
+static int run_host_writes(struct unlock_transaction_work *work,
+			   const struct gu_write_table *table);
+
+/* cmpunlocker SM-RECONFIG register set, read-only probe: log the GA100
+ * harvest topology (which GPCs/TPCs are disabled) for analysis before any
+ * reconfiguration is attempted. No state is changed. */
+
+static int ss_diag;
+static unsigned int ss0_val;
+static unsigned int ss1_val;
+static bool sm_reconfig;
+static bool gpc_enable;
+static bool reg_dump;
+static int tpc_ovr_val;
+static bool plm_force;
+static bool flr_entry;
+
+static void ga100_probe_topology(struct unlock_transaction_work *work)
 {
-	u16 now, want;
-	int ret = 0;
+	u32 opt_gpc, ovr, stat, ss0, ss1;
+	int gpc;
+
+	if (read_bar(work, 0x00820350u, &opt_gpc) || read_bar(work, GU_FEAT_SS0_OFFSET, &ss0) ||
+	    read_bar(work, GU_FEAT_SS1_OFFSET, &ss1))
+		return;
+	dev_info(&work->pdev->dev,
+		 "GA100 topology: OPT_GPC_DISABLE=%#x SS0=%#x SS1=%#x\n",
+		 opt_gpc, ss0, ss1);
+	for (gpc = 0; gpc < 8; gpc++) {
+		if ((u64)0x00820a40u + gpc * 4 + 4 > work->bar_len)
+			break;
+		if (read_bar(work, 0x00820a40u + gpc * 4, &ovr) ||
+		    read_bar(work, 0x00820c38u + gpc * 4, &stat))
+			break;
+		dev_info(&work->pdev->dev,
+			 "GA100 GPC%d: TPC_OVR=%#x STATUS=%#x\n", gpc, ovr, stat);
+	}
+}
+
+/* Apply ss_diag/sm_reconfig diagnostics in the already-unlocked path.
+ * Writes are bounded register writes with readback logging; the boot
+ * always continues (a wedged GPU fails the driver later, never hangs
+ * initramfs). */
+static void ga100_apply_diags(struct unlock_transaction_work *work)
+{
+	u32 ss0 = 0, ss1 = 0;
+	int gpc;
+
+	if ((ss_diag == 1 || ss_diag == 2) && work->card->chip == 0x170) {
+		/* A30-specific diagnostic (stock values are per-SKU). */
+		u32 want0 = ss_diag == 1 ? 0x52266063u : GU_SS0_UNLOCK;
+		u32 want1 = ss_diag == 1 ? 0x00000004u : GU_SS1_UNLOCK;
+
+		write_bar(work, GU_FEAT_SS0_OFFSET, want0);
+		write_bar(work, GU_FEAT_SS1_OFFSET, want1);
+		read_bar(work, GU_FEAT_SS0_OFFSET, &ss0);
+		read_bar(work, GU_FEAT_SS1_OFFSET, &ss1);
+		dev_info(&work->pdev->dev, "ss_diag=%d applied: SS0=%#x SS1=%#x (wanted %#x:%#x)\n",
+			 ss_diag, ss0, ss1, want0, want1);
+	}
+	if ((ss0_val || ss1_val) && work->card->chip == 0x170) {
+		/* Arbitrary selector probe pair (SS0 nibble experiments).
+		 * The post-driver userspace window is FEAT-masked
+		 * (0xbadf1100), but kernel selector access works in the
+		 * already-unlocked runtime path — observed 2026-10-25.
+		 * Both params are written together; an omitted one re-writes
+		 * its current value (pass both explicitly for probes). */
+		u32 before0 = 0, before1 = 0;
+
+		read_bar(work, GU_FEAT_SS0_OFFSET, &before0);
+		read_bar(work, GU_FEAT_SS1_OFFSET, &before1);
+		u32 want0 = ss0_val ? (u32)ss0_val : before0;
+		u32 want1 = ss1_val ? (u32)ss1_val : before1;
+
+		write_bar(work, GU_FEAT_SS0_OFFSET, want0);
+		write_bar(work, GU_FEAT_SS1_OFFSET, want1);
+		read_bar(work, GU_FEAT_SS0_OFFSET, &ss0);
+		read_bar(work, GU_FEAT_SS1_OFFSET, &ss1);
+		dev_info(&work->pdev->dev, "ss_probe applied: SS0=%#x SS1=%#x (was %#x:%#x wanted %#x:%#x write=%u)\n",
+			 ss0, ss1, before0, before1, want0, want1,
+			 ss0 == want0 && ss1 == want1);
+	}
+	if (sm_reconfig) {
+		/* cmpunlocker SM-RECONFIG: per-GPC TPC/SM override. The value is
+		 * a module param so the full 32-bit field can be explored
+		 * (default 0xff = low byte, cmpunlocker's write). */
+		u32 ovr = tpc_ovr_val ? (u32)tpc_ovr_val : 0x000000ffu;
+
+		for (gpc = 0; gpc < 8; gpc++) {
+			if ((u64)0x00820a40u + gpc * 4 + 4 > work->bar_len)
+				break;
+			write_bar(work, 0x00820a40u + gpc * 4, ovr);
+		}
+		dev_info(&work->pdev->dev, "sm_reconfig: TPC overrides (%#x) written for GPC0-7; re-probing\n", ovr);
+		ga100_probe_topology(work);
+	}
+	if (gpc_enable) {
+		u32 before = 0, after = 0, b2 = 0, a2 = 0, s2 = 0;
+
+		read_bar(work, 0x00820350u, &before);
+		write_bar(work, 0x00820350u, 0);
+		read_bar(work, 0x00820350u, &after);
+		dev_info(&work->pdev->dev,
+			 "gpc_enable: OPT_GPC_DISABLE %#x -> %#x after write 0\n",
+			 before, after);
+		/* Second GPC-disable copy at 0x820c1c, inside the RECONFIG
+		 * block (same block as the per-GPC TPC_OVR at 0x820a40 and
+		 * STATUS at 0x820c38) — candidate writable effective mask. */
+		read_bar(work, 0x00820c1cu, &b2);
+		write_bar(work, 0x00820c1cu, 0);
+		read_bar(work, 0x00820c1cu, &a2);
+		read_bar(work, 0x00820350u, &s2);
+		dev_info(&work->pdev->dev,
+			 "gpc_enable: RECONFIG_GPC_DISABLE %#x -> %#x after write 0 (OPT_GPC_DISABLE now %#x)\n",
+			 b2, a2, s2);
+		ga100_probe_topology(work);
+	}
+	if (reg_dump) {
+		/* Bounded opt/TPC register map for harvest analysis:
+		 * nonzero registers, 0x10 rows, kernel log. */
+		u32 a, row[4];
+		int i;
+
+		dev_info(&work->pdev->dev, "reg_dump: OPT block 0x820000-0x820400\n");
+		for (a = 0x00820000u; a < 0x00820400u; a += 0x10) {
+			for (i = 0; i < 4; i++)
+				if (read_bar(work, a + i * 4, &row[i]))
+					row[i] = 0xdeadbeef;
+			if (row[0] || row[1] || row[2] || row[3])
+				dev_info(&work->pdev->dev, "reg[%08x] %08x %08x %08x %08x\n",
+					 a, row[0], row[1], row[2], row[3]);
+		}
+		dev_info(&work->pdev->dev, "reg_dump: TPC block 0x820a00-0x820d00\n");
+		for (a = 0x00820a00u; a < 0x00820d00u; a += 0x10) {
+			for (i = 0; i < 4; i++)
+				if (read_bar(work, a + i * 4, &row[i]))
+					row[i] = 0xdeadbeef;
+			if (row[0] || row[1] || row[2] || row[3])
+				dev_info(&work->pdev->dev, "reg[%08x] %08x %08x %08x %08x\n",
+					 a, row[0], row[1], row[2], row[3]);
+		}
+		dev_info(&work->pdev->dev, "reg_dump: FBPA block 0x9a0000-0x9a0400\n");
+		for (a = 0x009a0000u; a < 0x009a0400u; a += 0x10) {
+			for (i = 0; i < 4; i++)
+				if (read_bar(work, a + i * 4, &row[i]))
+					row[i] = 0xdeadbeef;
+			if (row[0] || row[1] || row[2] || row[3])
+				dev_info(&work->pdev->dev, "reg[%08x] %08x %08x %08x %08x\n",
+					 a, row[0], row[1], row[2], row[3]);
+					 }
+					 }
+					 }
+
+					 static int unlock_transaction_unwind(struct unlock_transaction_work *work)
+					 {
+					 u16 now, want;
+					 int ret = 0;
 
 	/* A timeout never authorizes freeing firmware-visible memory. */
 	if (work->firmware_started && work->state != GU_QUIESCED) {
@@ -342,22 +496,45 @@ static int unlock_transaction_unwind(struct unlock_transaction_work *work)
 static int unlock_transaction_layout(struct unlock_transaction_work *work)
 {
 	struct gpu_unlock_layout_in *in = &work->layout_in;
-	u32 mb, vga, lo, hi, plm;
+	u32 mb = 0, vga = 0, lo, hi, plm;
+	u64 mmu_hi;
 	int ret;
 
-	if (read_bar(work, GU_GFW_FB_SIZE_OFFSET, &mb) || !mb || mb == ~0u ||
-	    read_bar(work, GU_VGA_WORKSPACE_BASE_OFFSET, &vga) || vga == ~0u ||
-	    read_bar(work, GU_MMU_LOCK_CFG_PLM_OFFSET, &plm) || plm == ~0u || !(plm & 1) ||
+	if (read_bar(work, GU_MMU_LOCK_CFG_PLM_OFFSET, &plm) || plm == ~0u || !(plm & 1) ||
 	    read_bar(work, GU_MMU_LOCK_ADDR_LO_OFFSET, &lo) || lo == ~0u ||
 	    read_bar(work, GU_MMU_LOCK_ADDR_HI_OFFSET, &hi) || hi == ~0u)
 		return GU_RESULT(-ENODEV);
+	mmu_hi = (u64)(hi >> 4) << 12;
+	if (work->card->chip == 0x170) {
+		/* GA100: the GA10x GC6 AON scratch (usable FB in MB) and the
+		 * VGA workspace decode do not exist on this silicon; the
+		 * board publishes its memory geometry only through the MMU
+		 * lock (memmgrBlockMemLockedMemory_GA100: the aligned-up lock
+		 * high address is the raw FB top — LOCAL_MEMORY_RANGE
+		 * rounded up to 1 GiB — and the locked range below it is the
+		 * VBIOS end-of-FB reservation). Derive usable_fb from the
+		 * lock; refuse a lock that is not that top reservation. */
+		u64 lock_low = (u64)(lo >> 4) << 12;
+		u64 lock_bytes = mmu_hi - lock_low + 1;
+
+		if (mmu_hi < lock_low ||
+		    lock_bytes > (1ull << 30) + (64ull << 20)) {
+			dev_err(&work->pdev->dev,
+				"layout rejected: GA100 MMU lock is not the FB-top reservation\n");
+			return GU_RESULT(-ERANGE);
+		}
+		in->usable_fb = (mmu_hi + 0xffffull) & ~0xffffull;
+	} else if (read_bar(work, GU_GFW_FB_SIZE_OFFSET, &mb) || !mb || mb == ~0u ||
+	    read_bar(work, GU_VGA_WORKSPACE_BASE_OFFSET, &vga) || vga == ~0u)
+		return GU_RESULT(-ENODEV);
 	/* Keep the cold board inputs in the USB kernel log even on layout failure.
 	 * Register values after NVIDIA binds cannot reconstruct this state. */
 	dev_dbg(&work->pdev->dev,
 		 "layout inputs: fb_mb=%#x vga=%#x mmu_plm=%#x mmu_lo=%#x mmu_hi=%#x image=%llu boot=%u\n",
 		 mb, vga, plm, lo, hi, (unsigned long long)work->image_span.size,
 		 work->boot_desc.image_size);
-	in->usable_fb = (u64)mb << 20;
+	if (work->card->chip != 0x170)
+		in->usable_fb = (u64)mb << 20;
 	if (in->usable_fb < 256ull << 20) {
 		dev_err(&work->pdev->dev, "layout rejected: usable FB below 256 MiB\n");
 		return GU_RESULT(-ERANGE);
@@ -397,7 +574,10 @@ static int unlock_transaction_layout(struct unlock_transaction_work *work)
 			in->mmu_lock_valid = false;
 		}
 	}
-	in->frts_size = 1ull << 20;
+	/* GA100 (chip 0x170): no FRTS region is reserved — the booter sets up
+	 * WPR2 itself (nouveau tu102_gsp_oneinit reserves frts.size = 0 for
+	 * chipset 0x170). GA10x keeps the FWSEC-built 1 MiB region. */
+	in->frts_size = work->card->chip == 0x170 ? 0 : 1ull << 20;
 	in->boot_size = work->boot_desc.image_size;
 	in->image_size = work->image_span.size;
 	in->nonwpr_size = 1ull << 20;
@@ -584,11 +764,14 @@ static int unlock_transaction_dma(struct unlock_transaction_work *work)
 	if (!work->booter_cpu)
 		return GU_RESULT(-ENOMEM);
 	memcpy(work->booter_cpu, work->booter_fw->data + 72, work->booter_image_size);
-	work->payload_cpu = diag_dma_alloc(work, "payload", GU_PAYLOAD_SIZE, &work->payload_dma, GFP_KERNEL);
+	work->payload_cpu = diag_dma_alloc(work, "payload", GU_PAYLOAD_SIZE_MAX, &work->payload_dma, GFP_KERNEL);
 	work->meta_cpu = diag_dma_alloc(work, "metadata", GU_WPR_META_SIZE, &work->meta_dma, GFP_KERNEL);
 	if (!work->payload_cpu || !work->meta_cpu)
 		return GU_RESULT(-ENOMEM);
-	gu_payload_fill(work->payload_cpu, GU_FEAT_PLM_OFFSET, ~0u);
+	if (work->card->direct_boot)
+		gu_payload_fill(work->payload_cpu, GU_FEAT_PLM_OFFSET, ~0u);
+	else
+		gu_payload_fill_ga10x(work->payload_cpu, GU_FEAT_PLM_OFFSET, ~0u);
 	work->stock_size = work->sig_span.size;
 	work->stock_cpu = diag_dma_alloc(work, "stock-signature", work->stock_size, &work->stock_dma, GFP_KERNEL);
 	work->boot_cpu = diag_dma_alloc(work, "boot-image", work->boot_desc.image_size, &work->boot_dma, GFP_KERNEL);
@@ -616,9 +799,32 @@ static int unlock_transaction_fwsec(struct unlock_transaction_work *work)
 	u16 command;
 	u64 frts = work->layout.frts_offset;
 	void *image = NULL;
-	dma_addr_t image_dma = 0;
+	dma_addr_t image_dma = 0, bl_dma = 0, desc_dma = 0;
 	int ret;
 
+	if (work->card->chip == 0x170) {
+		/* GA100: the booter firmware sets up WPR2 itself and no FRTS
+		 * region is reserved (nouveau tu102_gsp_oneinit: frts.size = 0
+		 * for chipset 0x170; kgspPrepareForBootstrap_TU102 skips FWSEC
+		 * when kgspGetFrtsSize == 0). cmpunlocker's A100 flow likewise
+		 * leaves WPR2 at its reset value (0x1ffffe00:0 — observed on
+		 * this A30 before FWSEC too) and re-writes exactly that value
+		 * before every Booter Load invocation. Publishing a FWSEC-built
+		 * WPR2 instead is rejected by the booter app. */
+		work->frts_lo = 0x1ffffe00u;
+		work->frts_hi = 0u;
+		work->frts_saved = true;
+		/* No FWSEC boot occurs, but the booter launch itself is the
+		 * "firmware" step for this path; unlock_transaction_boot's
+		 * guard requires the flag, and the booter's sysmem DMAs
+		 * require PCI bus mastering (the FWSEC path set it here). */
+		pci_set_master(work->pdev);
+		work->master = true;
+		work->firmware_started = true;
+		dev_dbg(&work->pdev->dev,
+			"FWSEC: GA100 — skipped, WPR2 left at reset 0x1ffffe00:0 for booter\n");
+		return GU_RESULT(0);
+	}
 	/* kgspExtractVbiosFromRom_TU102 reads NV_PROM_DATA, up to 1 MiB.
 	 * pci_map_rom stops at the PCI last-image flag and hides the VN extension. */
 	dev_dbg(&work->pdev->dev, "FWSEC: reading PROM at %#x\n", GU_PROM_DATA_OFFSET);
@@ -636,8 +842,7 @@ static int unlock_transaction_fwsec(struct unlock_transaction_work *work)
 		dev_err(&work->pdev->dev, "FWSEC-FRTS not found in board ROM (%d)\n", ret);
 		goto out;
 	}
-	if ((fw.version == 2) != work->load->direct ||
-	    (fw.version == 3 && fw.engine_mask != 0x400)) {
+	if (fw.version == 3 && fw.engine_mask != 0x400) {
 		dev_err(&work->pdev->dev, "FWSEC: unsupported GSP engine mask=%#x\n", fw.engine_mask);
 		ret = -EOPNOTSUPP;
 		goto out;
@@ -677,8 +882,18 @@ static int unlock_transaction_fwsec(struct unlock_transaction_work *work)
 	}
 	/* Preserve conservative DMA retention from the moment FWSEC may access it,
 	 * including reset/load failures. Launch evidence is observed separately. */
+	/* FRTS input: WPR size in 4K pages. NVIDIA writes AON secure scratch
+	 * group 03 before launching FWSEC; FWSEC sizes WPR2 from this scratch
+	 * (dev_gc6_island_addendum.h), not from the mapper cmd. */
+	write_bar(work, 0x00118214u, 0x100);
 	work->firmware_started = true;
 	if (fw.version == 2) {
+		/* The generic BL and its descriptor are staged through DMATRF
+		 * (the GA100 GSP gates the PIO ports), so they need coherent
+		 * copies of their own; freed once the falcon has copied them. */
+		u8 *bl_cpu = diag_dma_alloc(work, "gen-bl", 768, &bl_dma, GFP_KERNEL);
+		u8 *desc_cpu = bl_cpu ? diag_dma_alloc(work, "gen-bl-desc", 256,
+						       &desc_dma, GFP_KERNEL) : NULL;
 		const struct gu_falcon_loader_image program = {
 			.loader = work->loader_fw ? (const u32 *)work->loader_fw->data : NULL,
 			.loader_size = work->loader_fw ? work->loader_fw->size : 0,
@@ -686,8 +901,18 @@ static int unlock_transaction_fwsec(struct unlock_transaction_work *work)
 			.imem_pa = fw.imem_pa, .imem_ns_size = fw.imem_ns_size,
 			.imem_sec_pa = fw.imem_sec_pa, .imem_sec_size = fw.imem_sec_size,
 			.dmem_size = fw.dmem_size,
+			.bl_dma = bl_cpu ? bl_dma : 0,
+			.desc_mem = desc_cpu, .desc_dma = desc_cpu ? desc_dma : 0,
 		};
-		ret = gu_falcon_loader(&io, &gsp, &program, &work->fwsec_launch);
+
+		if (bl_cpu && work->loader_fw)
+			memcpy(bl_cpu, work->loader_fw->data, 768);
+		ret = bl_cpu && desc_cpu ? gu_falcon_loader(&io, &gsp, &program,
+							   &work->fwsec_launch) : -ENOMEM;
+		if (bl_cpu)
+			dma_free_coherent(&work->pdev->dev, 768, bl_cpu, bl_dma);
+		if (desc_cpu)
+			dma_free_coherent(&work->pdev->dev, 256, desc_cpu, desc_dma);
 	} else {
 		const struct gu_falcon_hs_image program = {
 			.dma = image_dma, .code_off = 0, .code_size = fw.imem_size,
@@ -717,12 +942,13 @@ static int unlock_transaction_fwsec(struct unlock_transaction_work *work)
 	dev_dbg(&work->pdev->dev, "FWSEC WPR2: low=%#x high=%#x expected_page=%#llx end=%#llx\n",
 		wpr_lo, wpr_hi, (unsigned long long)(frts >> 12),
 		(unsigned long long)work->layout.wpr_end);
-	/* Match NVIDIA's initialized-WPR2 check as well as the expected low
-	 * address. Never publish Booter metadata for disabled/alien WPR2. */
-	if (!(wpr_hi >> 4) || (wpr_hi >> 4) < (wpr_lo >> 4) ||
-	    ((u64)(wpr_hi >> 4) << 12) >= work->layout.wpr_end ||
-	    (wpr_lo >> 4) != (u32)(frts >> 12) ||
-	    (((u64)(wpr_hi >> 4) + 1) << 12) != work->layout.wpr_end)
+	/* Match NVIDIA's validation exactly (kernel_gsp_frts_tu102.c): FRTS
+	 * error code clear (checked above), WPR2 initialized, and WPR2 low
+	 * page == the frts offset we requested. NVIDIA does not constrain the
+	 * WPR2 end; FWSEC sizes the region from the FRTS inputs, which on
+	 * GA100 comes out slightly under 1 MiB. */
+	if (!(wpr_hi >> 4) || (wpr_hi >> 4) <= (wpr_lo >> 4) ||
+	    (wpr_lo >> 4) != (u32)(frts >> 12))
 		ret = -EIO;
 	if (!ret) {
 		work->frts_lo = wpr_lo;
@@ -763,8 +989,33 @@ static int unlock_transaction_gfw(struct unlock_transaction_work *work)
 			dev_dbg(&work->pdev->dev, "entry: plm=%#x ss0=%#x ss1=%#x wpr2_hi=%#x\n",
 				 work->plm_entry, ss0, ss1, wpr_hi);
 			/* An open PLM means the card was already unlocked or not cold. */
-			if (work->plm_entry == ~0u)
-				return GU_RESULT(-EALREADY);
+			if (work->plm_entry == ~0u) {
+				/* Already unlocked (sticky across reboot/FLR):
+				 * still log the topology for evidence and
+				 * idempotently re-assert the host selector
+				 * writes (state can have been reverted by
+				 * diagnostics on an earlier boot). */
+				{
+					u32 sec2ctl = 0;
+
+					if (!read_bar(work, GU_SEC2_BASE + GU_FALCON_CPUCTL_OFFSET, &sec2ctl))
+						dev_info(&work->pdev->dev,
+							 "entry SEC2 CPUCTL=%#x%s\n", sec2ctl,
+							 inaccessible(sec2ctl) ? " (poisoned BEFORE FWSEC)" : "");
+				}
+				ga100_probe_topology(work);
+				if (run_host_writes(work, &work->family->host))
+					dev_err(&work->pdev->dev,
+						"already-unlocked: selector re-assert failed\n");
+				ga100_apply_diags(work);
+				if (!plm_force)
+					return GU_RESULT(-EALREADY);
+				/* plm_force: continue into the full chain so
+				 * family PLMs a previous (smaller) table never
+				 * opened — e.g. RECONFIG — get opened now. */
+				dev_info(&work->pdev->dev,
+					 "plm_force: running the full chain despite the open FEAT PLM\n");
+			}
 			/* WPR2 is down from power-on until FWSEC-FRTS runs. An enabled
 			 * WPR2 means a driver has already used the card this power
 			 * cycle; starting FWSEC and Booter again from here is untested.
@@ -815,8 +1066,10 @@ static int unlock_transaction_suspended(struct unlock_transaction_work *work)
 		return -EBUSY;
 	}
 	/* Sleep that kept the card powered (suspend to idle, an aborted suspend). */
-	if (ss0 == GU_SS0_UNLOCK && ss1 == GU_SS1_UNLOCK)
+	if (ss0 == GU_SS0_UNLOCK && ss1 == GU_SS1_UNLOCK) {
+		ga100_probe_topology(work);
 		return -EALREADY;
+	}
 	return unlock_transaction_gfw(work);
 }
 
@@ -831,7 +1084,15 @@ static int unlock_transaction_boot(struct unlock_transaction_work *work)
 	u32 ctl, reset_plm, engine, scratch, identity;
 	if ((work->state != GU_PUBLISHED && work->state != GU_ACTIVE) || !work->master || !work->firmware_started)
 		return GU_RESULT(-EINVAL);
-	if (work->load->direct) {
+	if (work->card->chip == 0x170) {
+		/* GA100: classic BL-style launch of the SEC2 booter (see
+		 * gu_falcon_booter_bl) — the BROM PARAADDR path is a GA10x
+		 * mechanism and executes encrypted bytes as code here. */
+		ret = gu_falcon_booter_bl(&io, &sec2, work->booter_cpu, h,
+					  lower_32_bits(work->meta_dma),
+					  upper_32_bits(work->meta_dma),
+					  &work->launch);
+	} else if (work->load->direct) {
 		const struct gu_falcon_direct_image program = {
 			.words = work->booter_cpu,
 			.os_code_off = h->os_code_off, .os_code_size = h->os_code_size,
@@ -872,23 +1133,36 @@ static int unlock_transaction_boot(struct unlock_transaction_work *work)
 		work->launch.reloaded && work->launch.started && work->invocation_halted;
 	/* The reference exit does not write the mailboxes. Its nonzero input
 	 * metadata pointer is therefore a reference-specific return, not the
-	 * stock Booter zero-success convention. Hardware confirmation pending. */
-	work->cleanup_complete = work->fresh && (reset_plm & 0xff) == 0xff &&
-		work->mailbox0 == lower_32_bits(work->meta_dma) &&
-		work->mailbox1 == upper_32_bits(work->meta_dma);
+	 * stock Booter zero-success convention. Hardware confirmation pending.
+	 * GA100 BL path: the plaintext os_code stub overwrites MBOX0 with its
+	 * own progress marker (0x31) before entering the app, so the mailbox
+	 * echo can never hold; halt + opened SEC2 reset PLM is the exit
+	 * signature there (observed on hardware, 2026-10-24). */
+	if (work->card->chip == 0x170)
+		work->cleanup_complete = work->fresh && (reset_plm & 0xff) == 0xff;
+	else
+		work->cleanup_complete = work->fresh && (reset_plm & 0xff) == 0xff &&
+			work->mailbox0 == lower_32_bits(work->meta_dma) &&
+			work->mailbox1 == upper_32_bits(work->meta_dma);
 	dev_dbg(&work->pdev->dev,
 		 "invocation: index=%zu attempt=%u reset=%u/%u reload=%u start=%u cpuctl=%#x reset_plm@%#x=%#x mailbox=%#x:%#x fresh=%u cleanup_observed=%u result=%d\n",
 		 work->write_index, work->attempt, work->launch.reset_asserted,
 		 work->launch.reset_released, work->launch.reloaded, work->launch.started, ctl,
 		 GU_SEC2_RESET_PLM_OFFSET, reset_plm, work->mailbox1, work->mailbox0,
 		 work->fresh, work->cleanup_complete, ret);
-	if (ret || !work->cleanup_complete)
+	if ((ret || !work->cleanup_complete) && (ret || work->card->chip == 0x170))
 		dev_err(&work->pdev->dev,
 			"invocation failed: index=%zu attempt=%u cpuctl=%#x engine=%#x reset_plm=%#x mailbox=%#x:%#x reset=%u/%u reload=%u start=%u fresh=%u cleanup=%u error=%d\n",
 			work->write_index, work->attempt, ctl, engine, reset_plm,
 			work->mailbox1, work->mailbox0, work->launch.reset_asserted,
 			work->launch.reset_released, work->launch.reloaded, work->launch.started,
 			work->fresh, work->cleanup_complete, ret ? ret : -EIO);
+	/* GA10x BROM-HS: the stock Booter keeps running after the ROP write
+	 * (observed on GA107/A2 2026-10-25: write lands, no halt, no mailbox
+	 * echo, reset PLM unrestricted). The table readback is the success
+	 * criterion for this path; the handshake fields stay diagnostic. */
+	if (work->card->chip != 0x170)
+		return GU_RESULT(ret);
 	return GU_RESULT(ret ? ret : work->cleanup_complete ? 0 : -EIO);
 }
 
@@ -900,13 +1174,39 @@ static void put_le64(u8 *dest, u64 value)
 		dest[i] = (u8)(value >> (8 * i));
 }
 
+/* Diagnostic mode: publish the real .fwsignature instead of the V67
+ * exploit payload, so a booter failure can be attributed to the
+ * metadata/radix (still fails) vs the payload (boots). */
+static bool stock_diag;
+module_param(stock_diag, bool, 0444);
+MODULE_PARM_DESC(stock_diag, "Diagnostic: boot the SEC2 booter with the stock GSP signature instead of the unlock payload");
+module_param(ss_diag, int, 0444);
+MODULE_PARM_DESC(ss_diag, "GA100 diagnostics: 0=leave SM speed selectors, 1=restore stock SS0/SS1, 2=restore unlock SS0/SS1");
+module_param(ss0_val, uint, 0444);
+MODULE_PARM_DESC(ss0_val, "GA100 SS0 selector probe value (hex via 0x prefix, 0=skip; chip 0x170 already-unlocked path only)");
+module_param(ss1_val, uint, 0444);
+MODULE_PARM_DESC(ss1_val, "GA100 SS1 selector probe value (hex via 0x prefix, 0=skip; written together with ss0_val)");
+module_param(sm_reconfig, bool, 0444);
+MODULE_PARM_DESC(sm_reconfig, "GA100 diagnostics: write per-GPC TPC overrides (0xff) to probe harvested GPCs/SMs (cmpunlocker SM-RECONFIG)");
+module_param(gpc_enable, bool, 0444);
+MODULE_PARM_DESC(gpc_enable, "GA100 diagnostics: clear OPT_GPC_DISABLE to probe fused-off GPCs");
+module_param(reg_dump, bool, 0444);
+MODULE_PARM_DESC(reg_dump, "GA100 diagnostics: dump OPT/TPC/FBPA register blocks for harvest analysis");
+module_param(tpc_ovr_val, int, 0444);
+MODULE_PARM_DESC(tpc_ovr_val, "GA100 diagnostics: value for per-GPC TPC overrides with sm_reconfig=1 (default 0xff)");
+module_param(plm_force, bool, 0444);
+MODULE_PARM_DESC(plm_force, "Diagnostic: bypass the already-unlocked early-out and run the full unlock chain (opens all family PLMs, e.g. RECONFIG on cards unlocked by an older, smaller table)");
+module_param(flr_entry, bool, 0444);
+MODULE_PARM_DESC(flr_entry, "Diagnostic: issue a PCIe FLR with full recovery at entry, disposing of stock-driver shutdown state (e.g. host-locked SEC2 on GA10x) before the chain");
+
 static int publish_signature(struct unlock_transaction_work *work)
 {
 	struct gpu_unlock_wpr_args args = {
 		.fb_size = work->layout_in.usable_fb,
 		.vga_offset = work->layout_in.vga_base,
 		.frts_size = work->layout_in.frts_size,
-		.signature_dma = work->payload_dma, .signature_size = GU_PAYLOAD_SIZE,
+		.signature_dma = stock_diag ? work->stock_dma : work->payload_dma,
+		.signature_size = stock_diag ? work->stock_size : work->payload_size,
 		.image_size = work->image_span.size,
 		.boot_dma = work->boot_dma, .boot = work->boot_desc,
 	};
@@ -968,12 +1268,87 @@ static int run_privileged_writes(struct unlock_transaction_work *work,
 {
 	size_t i;
 	int ret;
+
+	/* An FLR'd GA10x card leaves the SEC2 engine in RESET_TRUE; SEC2
+	 * register reads then return the FECS_PRI_RESET poison (c274e74
+	 * hold_sec2_reset, ksec2ResetHw_TU102). GA100 never enters this
+	 * state. Assert/release the engine reset before the prelaunch
+	 * checks so the poison cannot abort the invocation loop. */
+	{
+		u32 ctl = 0, engine = 0;
+		int j;
+
+		if (read_bar(work, GU_SEC2_BASE + GU_FALCON_CPUCTL_OFFSET, &ctl) ||
+		    inaccessible(ctl)) {
+			if (read_bar(work, GU_SEC2_BASE + GU_FALCON_ENGINE_OFFSET, &engine) ||
+			    inaccessible(engine))
+				return GU_RESULT(-ENODEV);
+			dev_info(&work->pdev->dev,
+				 "SEC2 FLR-held (CPUCTL=%#x): asserting/releasing engine reset (engine=%#x)\n",
+				 ctl, engine);
+			write_bar(work, GU_SEC2_BASE + GU_FALCON_ENGINE_OFFSET, engine | 1u);
+			for (j = 0; j < 10; j++)
+				if (read_bar(work, GU_SEC2_BASE + GU_FALCON_ENGINE_OFFSET, &engine))
+					return GU_RESULT(-EIO);
+			write_bar(work, GU_SEC2_BASE + GU_FALCON_ENGINE_OFFSET, engine & ~1u);
+			for (j = 0; j < 10; j++)
+				if (read_bar(work, GU_SEC2_BASE + GU_FALCON_ENGINE_OFFSET, &engine))
+					return GU_RESULT(-EIO);
+			/* The reset triggers a memory scrub; reads through the
+			 * PRI ring fail (badf poison) until HWCFG2 bit 12
+			 * clears. c274e74 hold_sec2_reset / gu_falcon_reset
+			 * poll exactly this before touching other regs. */
+			{
+				u32 hwcfg = 0;
+				int k;
+
+				for (k = 0; k < 1000; k++) {
+					if (read_bar(work, GU_SEC2_BASE + 0xf4u, &hwcfg))
+						return GU_RESULT(-EIO);
+					if (!(hwcfg & (1u << 12)))
+						break;
+					usleep_range(1000, 2000);
+				}
+				if (hwcfg & (1u << 12)) {
+					dev_err(&work->pdev->dev,
+						"SEC2 scrub did not finish: HWCFG2=%#x\n", hwcfg);
+					return GU_RESULT(-ETIMEDOUT);
+				}
+			}
+			if (read_bar(work, GU_SEC2_BASE + GU_FALCON_CPUCTL_OFFSET, &ctl) ||
+			    inaccessible(ctl)) {
+				dev_err(&work->pdev->dev,
+					"SEC2 still poisoned after reset release: %#x\n", ctl);
+				return GU_RESULT(-ENODEV);
+			}
+			dev_info(&work->pdev->dev,
+				 "SEC2 engine reset released; CPUCTL=%#x\n", ctl);
+		}
+	}
 	if (work->state != GU_PUBLISHED && work->state != GU_ACTIVE)
 		return GU_RESULT(-EPROTO);
 	work->state = GU_ACTIVE;
 	for (i = 0; i < table->count; i++) {
 		const struct gu_reg_write *entry = &table->entries[i];
 		work->write_index = i;
+		/* GA10x: the Booter's cleanup locks the SEC2 falcon reset PLM
+		 * to level 3 after its run, so a warm boot allows exactly ONE
+		 * payload invocation (observed 2026-10-25: entry 0 succeeds,
+		 * entry 1's relaunch cannot re-reset the falcon). Skip entries
+		 * whose PLM already reads the target value so a closed later
+		 * entry — RECONFIG after FEAT — consumes the boot's single
+		 * invocation. Tables hold literal idempotent PLMs only. */
+		{
+			u32 cur = 0;
+
+			if (!read_bar(work, entry->addr, &cur) &&
+			    cur == entry->value) {
+				dev_info(&work->pdev->dev,
+					 "plm already open, skipping: index=%zu address=%#x value=%#x\n",
+					 i, entry->addr, cur);
+				continue;
+			}
+		}
 		for (work->attempt = 1; work->attempt <= 2; work->attempt++) {
 			u32 lo = 0, hi = 0, ctl = 0, engine = 0;
 			work->error_reported = false;
@@ -981,12 +1356,22 @@ static int run_privileged_writes(struct unlock_transaction_work *work,
 			memset(&work->launch, 0, sizeof(work->launch));
 			work->target_after = 0;
 			/* FWSEC completed before the first attempt. Every subsequent
-			 * refill requires the prior invocation to have stopped. */
-			if ((i || work->attempt > 1) && !work->invocation_halted)
-				return table_failure(work, "prior-halt", entry, -EBUSY);
-			ret = restore_frts(work);
-			if (ret)
-				return table_failure(work, "restore", entry, ret);
+			 * refill requires the prior invocation to have stopped — except
+			 * on GA10x, where the stock Booter keeps running after the ROP
+			 * write and the HS launch's engine reset stops it instead. */
+				if ((i || work->attempt > 1) && !work->invocation_halted &&
+				    work->card->chip == 0x170)
+					return table_failure(work, "prior-halt", entry, -EBUSY);
+			/* GA10x: the GA102 Booter locks the WPR2 config after
+			 * building its region (host restore writes bounce), and
+			 * it relaunches fine with WPR2 already up — observed
+			 * 2026-10-25. The FWSEC-value restore is a GA100 flow
+			 * requirement only. */
+			if (work->card->chip == 0x170) {
+				ret = restore_frts(work);
+				if (ret)
+					return table_failure(work, "restore", entry, ret);
+			}
 			if (read_bar(work, entry->addr, &work->target_before) ||
 			    (work->target_before & 0xffff0000u) == 0xbadf0000u ||
 			    read_bar(work, GU_SEC2_BASE + GU_FALCON_CPUCTL_OFFSET, &ctl) || inaccessible(ctl) ||
@@ -995,13 +1380,16 @@ static int run_privileged_writes(struct unlock_transaction_work *work,
 			dev_dbg(&work->pdev->dev,
 				 "prelaunch: index=%zu attempt=%u target=%#x cpuctl=%#x engine=%#x\n",
 				 i, work->attempt, work->target_before, ctl, engine);
-			gu_payload_fill(work->payload_cpu, entry->addr, entry->value);
+			if (work->card->direct_boot)
+				gu_payload_fill(work->payload_cpu, entry->addr, entry->value);
+			else
+				gu_payload_fill_ga10x(work->payload_cpu, entry->addr, entry->value);
 			put_le64((u8 *)work->meta_cpu + 72, work->payload_dma);
-			put_le64((u8 *)work->meta_cpu + 80, GU_PAYLOAD_SIZE);
+			put_le64((u8 *)work->meta_cpu + 80, work->payload_size);
 			dma_wmb();
 			dev_dbg(&work->pdev->dev,
 				 "payload: reference=2d10f891 size=%#x dma=%#llx index=%zu attempt=%u address=%#x value=%#x\n",
-				 GU_PAYLOAD_SIZE, (unsigned long long)work->payload_dma, i,
+				 work->payload_size, (unsigned long long)work->payload_dma, i,
 				 work->attempt, entry->addr, entry->value);
 			ret = unlock_transaction_boot(work);
 			if (read_bar(work, entry->addr, &work->target_after) ||
@@ -1028,7 +1416,9 @@ static int run_privileged_writes(struct unlock_transaction_work *work,
 		if (work->target_after != entry->value)
 			return table_failure(work, "readback-exhausted", entry, -EIO);
 	}
-	ret = restore_frts(work);
+	/* GA10x: same one-invocation law — no post-table FRTS restore (the
+	 * Booter locks the WPR2 config; it relaunches with WPR2 up). */
+	ret = work->card->chip == 0x170 ? restore_frts(work) : 0;
 	return ret && table->count ?
 		table_failure(work, "final-FRTS", &table->entries[table->count - 1], ret) : ret;
 }
@@ -1239,6 +1629,63 @@ static int unlock_transaction_reset(struct unlock_transaction_work *work)
 	return 0;
 }
 
+/* Entry FLR: dispose of engine/BROM/GFW state left by the stock driver's
+ * shutdown (e.g. SEC2 CPUCTL host-locked on GA10x after a prior unlock)
+ * before the chain runs. Mirrors unlock_transaction_reset's proven FLR
+ * recovery: restore state, BAR wait, GFW wait, SEC2 engine reset (with
+ * scrub wait), TRPND. PLMs/selectors survive FLR (verified at GA100
+ * flow-end), so the already-unlocked path still works afterwards. */
+static int unlock_transaction_entry_flr(struct unlock_transaction_work *work)
+{
+	struct gu_falcon_evidence reset_ev = { };
+	struct gu_falcon_io io = falcon_io(work);
+	u32 identity, bar, chip;
+	u16 command, pending;
+	unsigned int i;
+	int ret;
+
+	if (read_bar(work, GU_PMC_BOOT_0_OFFSET, &chip) || !chip || inaccessible(chip))
+		return GU_RESULT(-ENODEV);
+	/* FLR resets the display engine: release any firmware framebuffer. */
+	ret = aperture_remove_conflicting_pci_devices(work->pdev, "gpu_unlock");
+	if (ret)
+		return GU_RESULT(ret);
+	dev_info(&work->pdev->dev, "entry FLR begin: chip=%#x\n", chip);
+	ret = pcie_flr(work->pdev);
+	dev_info(&work->pdev->dev, "entry FLR returned: %d\n", ret);
+	if (ret)
+		return GU_RESULT(ret);
+	pci_restore_state(work->pdev);
+	if (diag_pci_dword(work, false, PCI_VENDOR_ID, &identity) ||
+	    identity != pci_identity(work->pdev) ||
+	    diag_pci_word(work, false, PCI_COMMAND, &command) ||
+	    command == 0xffff || (command & PCI_COMMAND_MASTER) ||
+	    !(command & PCI_COMMAND_MEMORY))
+		return GU_RESULT(-ENODEV);
+	for (i = 0; i < ARRAY_SIZE(work->bars); i++) {
+		if (diag_pci_dword(work, false, PCI_BASE_ADDRESS_0 + i * 4, &bar) ||
+		    bar != work->bars[i]) {
+			dev_err(&work->pdev->dev, "entry-FLR BAR%u: actual=%#x expected=%#x\n",
+				i, bar, work->bars[i]);
+			return GU_RESULT(-EIO);
+		}
+	}
+	ret = wait_post_flr_bar(work, chip);
+	if (ret)
+		return GU_RESULT(ret);
+	ret = wait_post_flr_gfw(work);
+	if (ret)
+		return GU_RESULT(ret);
+	ret = gu_falcon_engine_reset(&io, GU_SEC2_BASE, "entry-FLR", NULL, &reset_ev);
+	if (ret)
+		return GU_RESULT(ret);
+	if (diag_pci_word(work, true, PCI_EXP_DEVSTA, &pending) ||
+	    pending == 0xffff || (pending & PCI_EXP_DEVSTA_TRPND))
+		return GU_RESULT(-EBUSY);
+	dev_info(&work->pdev->dev, "entry FLR complete: SEC2 reset released, GFW done\n");
+	return 0;
+}
+
 int gpu_unlock_610_unlock(const struct gu_device *device, const struct gpu_unlock_610_shared *shared,
 			  bool resume)
 {
@@ -1269,10 +1716,18 @@ int gpu_unlock_610_unlock(const struct gu_device *device, const struct gpu_unloc
 	work->sig_span = assets->sig_span;
 	work->boot_desc = assets->boot_desc;
 	work->radix = assets->radix;
-	work->booter_fw = shared->booter;
-	work->loader_fw = work->load->direct ? shared->loader : NULL;
-	work->booter_hdr = shared->booter_hdr;
-	work->booter_image_size = GU_BOOTER_IMAGE_SIZE;
+	/* GA10x needs the GA102 Booter: the GA100 image's signature does not
+	 * validate on GA10x SEC2, so its write phase never executes there. */
+	work->booter_fw = work->card->direct_boot ? shared->booter : shared->booter_ga10x;
+	work->loader_fw = shared->loader; /* v2 FWSEC generic BL, both families */
+	work->booter_hdr = work->card->direct_boot ? shared->booter_hdr : shared->booter_hdr_ga10x;
+	if (!work->booter_fw) {
+		pci_dev_put(work->pdev);
+		kfree(work);
+		return -EINVAL;
+	}
+	work->booter_image_size = work->booter_fw->size - 72u - work->booter_hdr.sig_bytes;
+	work->payload_size = work->card->direct_boot ? GU_PAYLOAD_SIZE : GU_PAYLOAD_SIZE_GA10X;
 	dev_dbg(&pdev->dev, "recipe selection: device=%#x family=%s privileged=%zu host=%zu direct=%u\n",
 		 pdev->device, work->family->name, work->family->privileged.count,
 		 work->family->host.count, work->load->direct);
@@ -1296,6 +1751,8 @@ int gpu_unlock_610_unlock(const struct gu_device *device, const struct gpu_unloc
 			if ((u64)work->family->privileged.entries[i].addr + 4 > work->bar_len)
 				ret = GU_RESULT(-ERANGE);
 	}
+	if (!ret && flr_entry && !resume)
+		ret = unlock_transaction_entry_flr(work);
 	if (!ret)
 		ret = unlock_transaction_layout(work);
 	if (!ret)
@@ -1312,6 +1769,12 @@ int gpu_unlock_610_unlock(const struct gu_device *device, const struct gpu_unloc
 		ret = restore_stock_signature(work);
 	if (!ret)
 		ret = run_host_writes(work, &work->family->host);
+	/* Harvest/topology evidence + param-gated SM probing for any family
+	 * (GA100 A30 and GA107 A2 both use the OPT/TPC block layout). */
+	if (!ret) {
+		ga100_probe_topology(work);
+		ga100_apply_diags(work);
+	}
 	if (!ret)
 		ret = unlock_transaction_reset(work);
 	/* Never leave the V67 signature published for a later stock boot. */
diff --git a/kernel/gpu_unlock/vbios_610.c b/kernel/gpu_unlock/vbios_610.c
index 6eec788..2358c94 100644
--- a/kernel/gpu_unlock/vbios_610.c
+++ b/kernel/gpu_unlock/vbios_610.c
@@ -138,21 +138,30 @@ static int descriptor(const u8 *rom, size_t length, u64 off,
 		fw.data_off = r32(rom + off + 40);
 		fw.dmem_pa = r32(rom + off + 44);
 		fw.dmem_size = r32(rom + off + 48);
-		/* Restrict to the layout this contiguous adapter implements; refuse
-		 * alternate images, relocation, compression and nonzero entry. */
+		/* Restrict to the layout this contiguous adapter implements;
+		 * refuse relocation, compression and nonzero entry. Per the
+		 * 610.43.03 FALCON_UCODE_DESC_V2, +52 is altIMEMLoadSize and
+		 * +56 is altDMEMLoadSize (encrypted-path sizes, normally
+		 * populated; GA10x v3 descriptors lack these fields), and
+		 * StoredSize / DMEMLoadSize are byte counts: only DMA bases
+		 * (data_off here, the DMA address in falcon.c) need 256
+		 * alignment. */
 		if (!fw.image_size || !fw.imem_size || !fw.dmem_size ||
 		    r32(rom + off + 8) != fw.image_size || r32(rom + off + 12) ||
-		    r32(rom + off + 52) || r32(rom + off + 56) ||
 		    fw.imem_pa || fw.dmem_pa || sec_size > fw.imem_size ||
 		    sec_base < fw.imem_va || sec_size > ~(u32)0 - 255 ||
 		    (fw.data_off & 255) || (fw.imem_size & 255) ||
-		    (fw.dmem_size & 255) || (fw.image_size & 255) ||
 		    range(length, fw.image_off, fw.image_size) ||
 		    range(fw.image_size, 0, fw.imem_size) ||
 		    fw.data_off < fw.imem_size ||
 		    range(fw.image_size, fw.data_off, fw.dmem_size) ||
 		    range(fw.dmem_size, fw.interface_off, 4))
 			return GU_DIAG(-EINVAL);
+		GU_NOTE("FWSEC v2 geometry: offset=%#llx image_off=%#x size=%#x imem=%#x va=%#x sec=%#x+%#x data_off=%#x dmem=%#x interface=%#x alt_imem=%#x alt_dmem=%#x\n",
+			(unsigned long long)off, fw.image_off, fw.image_size,
+			fw.imem_size, fw.imem_va, sec_base, sec_size,
+			fw.data_off, fw.dmem_size, fw.interface_off,
+			r32(rom + off + 52), r32(rom + off + 56));
 		fw.imem_ns_size = fw.imem_size - sec_size;
 		fw.imem_sec_pa = sec_base - fw.imem_va;
 		fw.imem_sec_size = (sec_size + 255) & ~255u;
@@ -210,15 +219,34 @@ static int descriptor(const u8 *rom, size_t length, u64 off,
 
 int gpu_unlock_vbios_fwsec(const u8 *rom, size_t length, struct gpu_unlock_fwsec *out)
 {
-	u32 bit, adjust;
+	u32 bit, adjust, start = 0;
 	int ret;
 
 	if (!rom || !out || length > 1024 * 1024)
 		return GU_DIAG(-EINVAL);
 	memset(out, 0, sizeof(*out));
 	ret = expansion(rom, length, &adjust);
-	if (ret)
-		return GU_DIAG(ret);
+	if (ret) {
+		/* GA100 PROM images place a Gfw (NVGI) container ahead of the
+		 * expansion chain, so the chain need not begin at the first
+		 * PROM byte. Find the first offset whose full chain parses and
+		 * rebase onto it, so BIT, ucode-table and descriptor offsets
+		 * keep their chain-relative meaning. */
+		for (start = 0; start + 2 <= length; start += 2) {
+			if (!rom_signature(r16(rom + start)))
+				continue;
+			ret = expansion(rom + start, length - start, &adjust);
+			if (!ret)
+				break;
+		}
+		if (ret)
+			return GU_DIAG(ret);
+	}
+	if (start) {
+		GU_NOTE("ROM chain start: offset=%#x\n", start);
+		rom += start;
+		length -= start;
+	}
 	for (bit = 0; bit + 12 <= length; bit++) {
 		u32 size, stride, tokens, sum = 0, i;
 
@@ -260,9 +288,20 @@ int gpu_unlock_vbios_fwsec(const u8 *rom, size_t length, struct gpu_unlock_fwsec
 			for (j = 0; j < rom[table + 3]; j++) {
 				const u8 *entry = rom + table + rom[table + 1] + j * rom[table + 2];
 
-				if (entry[0] == 0x85)
-					return GU_DIAG(descriptor(rom, length,
-							  (u64)adjust + r32(entry + 2), out));
+				if (entry[0] == 0x85) {
+					ret = GU_DIAG(descriptor(rom, length,
+								 (u64)adjust + r32(entry + 2), out));
+					if (!ret && start) {
+						/* image_off/sig_off are relative
+						 * to the rebased chain, but the
+						 * caller indexes the original
+						 * PROM buffer with them. */
+						out->image_off += start;
+						if (out->sig_off)
+							out->sig_off += start;
+					}
+					return ret;
+				}
 			}
 		}
 	}
