diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 9bfe045ac9d5..2b5351cbf6bd 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -63,6 +63,7 @@ extern int ima_hash_algo_idx __ro_after_init;
 extern int ima_extra_slots __ro_after_init;
 extern struct ima_algo_desc *ima_algo_array __ro_after_init;
 extern unsigned long ima_unsupported_pcr_banks_mask __ro_after_init;
+extern unsigned long ima_discontinued_pcr_banks_mask __ro_after_init;
 
 extern unsigned long ima_extended_pcrs_mask;
 
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 716bb302e75d..58829c98a69b 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -69,6 +69,12 @@ struct ima_algo_desc *ima_algo_array __ro_after_init;
 
 unsigned long ima_unsupported_pcr_banks_mask __ro_after_init;
 
+/*
+ * Subset of unsupported banks that had (possibly) been supported and
+ * maintained by some previous kernel in a kexec chain.
+ */
+unsigned long ima_discontinued_pcr_banks_mask __ro_after_init;
+
 static int __init ima_init_ima_crypto(void)
 {
 	long rc;
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 83d5c7034919..4aa94584957e 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -156,7 +156,14 @@ static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr)
 		return 0;
 
 #if !IS_ENABLED(CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND)
-	pcr_banks_skip_mask = ima_unsupported_pcr_banks_mask;
+	/*
+	 * Don't invalidate unsupported PCR banks more than once in
+	 * general, with the exception of discontinued banks possibly
+	 * maintained by a previous kernel in a kexec chain and now in
+	 * indeterminate state.
+	 */
+	pcr_banks_skip_mask = ima_unsupported_pcr_banks_mask &
+		~ima_discontinued_pcr_banks_mask;
 	if (!(ima_extended_pcrs_mask & BIT(pcr))) {
 		/*
 		 * Invalidate unsupported banks once upon a PCR's
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index 04c49f05cb74..4584cfc416f4 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -428,7 +428,9 @@ int ima_restore_measurement_list(loff_t size, void *buf)
 	struct ima_template_desc *template_desc;
 	DECLARE_BITMAP(hdr_mask, HDR__LAST);
 	unsigned long count = 0;
-	int ret = 0;
+	unsigned long always_invalidated_pcrs_banks_mask = ~0UL;
+	unsigned long ever_invalidated_pcrs_banks_mask = 0;
+	int i, ret = 0;
 
 	if (!buf || size < sizeof(*khdr))
 		return 0;
@@ -527,10 +529,90 @@ int ima_restore_measurement_list(loff_t size, void *buf)
 
 		entry->pcr = !ima_canonical_fmt ? *(u32 *)(hdr[HDR_PCR].data) :
 			     le32_to_cpu(*(__le32 *)(hdr[HDR_PCR].data));
+		if (IMA_INVALID_PCR(entry->pcr)) {
+			pr_err("invalid measurement PCR index");
+			ret = -EINVAL;
+			break;
+		}
+
 		ret = ima_restore_measurement_entry(entry);
 		if (ret < 0)
 			break;
 
+#if !IS_ENABLED(CONFIG_IMA_COMPAT_FALLBACK_TPM_EXTEND)
+		if (ima_tpm_chip &&
+		    !(ima_extended_pcrs_mask & BIT(entry->pcr))) {
+			unsigned long invalidated_pcr_banks_mask;
+
+			invalidated_pcr_banks_mask =
+				ima_pcr_invalidated_banks(entry->pcr);
+			always_invalidated_pcrs_banks_mask &=
+				invalidated_pcr_banks_mask;
+			ever_invalidated_pcrs_banks_mask |=
+				invalidated_pcr_banks_mask;
+		}
+		ima_extended_pcrs_mask |= BIT(entry->pcr);
+#endif
 	}
+
+	always_invalidated_pcrs_banks_mask &= ever_invalidated_pcrs_banks_mask;
+	/*
+	 * Banks that had (possibly) been maintained by a previous
+	 * kernel in the kexec chain, but aren't anymore now, are
+	 * considered "discontinued" and in indeterminate
+	 * state. Re-invalidate unconditionally at each PCR extend.
+	 */
+	if (ima_extended_pcrs_mask != 0) {
+		ima_discontinued_pcr_banks_mask = ima_unsupported_pcr_banks_mask
+			& ~always_invalidated_pcrs_banks_mask;
+	}
+
+	/*
+	 * Banks consistently found invalidated for having been
+	 * unsupported before, are kept in the "unsupported" state and
+	 * never re-invalidated again, so that they retain their
+	 * easily recognizable, well-known digest value.
+	 */
+	ima_unsupported_pcr_banks_mask |= always_invalidated_pcrs_banks_mask;
+
+	for (i = 0; i < NR_BANKS(ima_tpm_chip); ++i) {
+		if (i >= BITS_PER_LONG)
+			break;
+
+		/*
+		 * Don't clutter the logs with unrecognized algos,
+		 * these would always get reported as "discontinued"
+		 * otherwise.
+		 */
+		if (ima_algo_array[i].algo == HASH_ALGO__LAST)
+			continue;
+
+		if (ima_discontinued_pcr_banks_mask & BIT(i)) {
+			pr_warn("Discontinuing unsupported TPM %s PCR bank\n",
+				hash_algo_name[ima_algo_array[i].algo]);
+		} else if (i == ima_hash_algo_idx &&
+			   ever_invalidated_pcrs_banks_mask & BIT(i)) {
+			pr_err("Continuing on stale ima_hash TPM PCR bank\n");
+
+			/* Force back to supported. */
+			ima_unsupported_pcr_banks_mask &= ~BIT(i);
+		} else if (always_invalidated_pcrs_banks_mask & BIT(i)) {
+			struct crypto_shash *tfm;
+
+			pr_info("Masking previously unsupported TPM %s PCR bank\n",
+				hash_algo_name[ima_algo_array[i].algo]);
+
+			/*
+			 * Remove the ->tfm so that any not yet
+			 * extended PCRs will get their corresponding
+			 * bank invalidated as well upon first use.
+			 */
+			tfm = ima_algo_array[i].tfm;
+			ima_algo_array[i].tfm = NULL;
+			if (tfm)
+				ima_free_tfm(tfm);
+		}
+	}
+
 	return ret;
 }
