From: Greg Kroah-Hartman Date: Tue, 21 Jul 2026 10:23:04 +0000 (+0200) Subject: 6.18-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3571b73dcf81f9e01bd161facd4c2488c8a81364;p=thirdparty%2Fkernel%2Fstable-queue.git 6.18-stable patches added patches: kvm-arm64-deduplicate-asid-retrieval-code.patch kvm-arm64-ensure-level-is-always-initialized-when-relaxing-perms.patch kvm-arm64-fix-propagation-of-tlbi-level-in-kvm_pgtable_stage2_relax_perms.patch kvm-arm64-nv-re-translate-vncr-before-injecting-abort.patch mm-damon-core-always-put-unsuccessfully-committed-target-pids.patch mm-damon-core-trace-esz-at-first-setup.patch samples-damon-mtier-fail-early-if-address-range-parameters-are-invalid.patch --- diff --git a/queue-6.18/kvm-arm64-deduplicate-asid-retrieval-code.patch b/queue-6.18/kvm-arm64-deduplicate-asid-retrieval-code.patch new file mode 100644 index 0000000000..6d0bdc78f2 --- /dev/null +++ b/queue-6.18/kvm-arm64-deduplicate-asid-retrieval-code.patch @@ -0,0 +1,158 @@ +From 54e367cb94d6bef941bbc1132d9959dc73bd4b6f Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Wed, 25 Feb 2026 10:47:18 +0000 +Subject: KVM: arm64: Deduplicate ASID retrieval code + +From: Marc Zyngier + +commit 54e367cb94d6bef941bbc1132d9959dc73bd4b6f upstream. + +We currently have three versions of the ASID retrieval code, one +in the S1 walker, and two in the VNCR handling (although the last +two are limited to the EL2&0 translation regime). + +Make this code common, and take this opportunity to also simplify +the code a bit while switching over to the TTBRx_EL1_ASID macro. + +Reviewed-by: Joey Gouly +Reviewed-by: Jonathan Cameron +Link: https://patch.msgid.link/20260225104718.14209-1-maz@kernel.org +[maz: cherry-pick as dependency of bb645aa0a4caeaf7f9cd32e9a948594d434c1a8f] +Signed-off-by: Marc Zyngier +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/include/asm/kvm_nested.h | 2 + + arch/arm64/kvm/at.c | 27 +--------------- + arch/arm64/kvm/nested.c | 60 ++++++++++++++++++------------------ + 3 files changed, 35 insertions(+), 54 deletions(-) + +--- a/arch/arm64/include/asm/kvm_nested.h ++++ b/arch/arm64/include/asm/kvm_nested.h +@@ -371,6 +371,8 @@ int kvm_vcpu_allocate_vncr_tlb(struct kv + int kvm_handle_vncr_abort(struct kvm_vcpu *vcpu); + void kvm_handle_s1e2_tlbi(struct kvm_vcpu *vcpu, u32 inst, u64 val); + ++u16 get_asid_by_regime(struct kvm_vcpu *vcpu, enum trans_regime regime); ++ + #define vncr_fixmap(c) \ + ({ \ + u32 __c = (c); \ +--- a/arch/arm64/kvm/at.c ++++ b/arch/arm64/kvm/at.c +@@ -483,31 +483,8 @@ static int walk_s1(struct kvm_vcpu *vcpu + wr->pa |= va & GENMASK_ULL(va_bottom - 1, 0); + + wr->nG = (wi->regime != TR_EL2) && (desc & PTE_NG); +- if (wr->nG) { +- u64 asid_ttbr, tcr; +- +- switch (wi->regime) { +- case TR_EL10: +- tcr = vcpu_read_sys_reg(vcpu, TCR_EL1); +- asid_ttbr = ((tcr & TCR_A1) ? +- vcpu_read_sys_reg(vcpu, TTBR1_EL1) : +- vcpu_read_sys_reg(vcpu, TTBR0_EL1)); +- break; +- case TR_EL20: +- tcr = vcpu_read_sys_reg(vcpu, TCR_EL2); +- asid_ttbr = ((tcr & TCR_A1) ? +- vcpu_read_sys_reg(vcpu, TTBR1_EL2) : +- vcpu_read_sys_reg(vcpu, TTBR0_EL2)); +- break; +- default: +- BUG(); +- } +- +- wr->asid = FIELD_GET(TTBR_ASID_MASK, asid_ttbr); +- if (!kvm_has_feat_enum(vcpu->kvm, ID_AA64MMFR0_EL1, ASIDBITS, 16) || +- !(tcr & TCR_ASID16)) +- wr->asid &= GENMASK(7, 0); +- } ++ if (wr->nG) ++ wr->asid = get_asid_by_regime(vcpu, wi->regime); + + return 0; + +--- a/arch/arm64/kvm/nested.c ++++ b/arch/arm64/kvm/nested.c +@@ -818,6 +818,33 @@ int kvm_inject_s2_fault(struct kvm_vcpu + return kvm_inject_nested_sync(vcpu, esr_el2); + } + ++u16 get_asid_by_regime(struct kvm_vcpu *vcpu, enum trans_regime regime) ++{ ++ enum vcpu_sysreg ttbr_elx; ++ u64 tcr; ++ u16 asid; ++ ++ switch (regime) { ++ case TR_EL10: ++ tcr = vcpu_read_sys_reg(vcpu, TCR_EL1); ++ ttbr_elx = (tcr & TCR_A1) ? TTBR1_EL1 : TTBR0_EL1; ++ break; ++ case TR_EL20: ++ tcr = vcpu_read_sys_reg(vcpu, TCR_EL2); ++ ttbr_elx = (tcr & TCR_A1) ? TTBR1_EL2 : TTBR0_EL2; ++ break; ++ default: ++ BUG(); ++ } ++ ++ asid = FIELD_GET(TTBRx_EL1_ASID, vcpu_read_sys_reg(vcpu, ttbr_elx)); ++ if (!kvm_has_feat_enum(vcpu->kvm, ID_AA64MMFR0_EL1, ASIDBITS, 16) || ++ !(tcr & TCR_ASID16)) ++ asid &= GENMASK(7, 0); ++ ++ return asid; ++} ++ + static void invalidate_vncr(struct vncr_tlb *vt) + { + vt->valid = false; +@@ -1314,20 +1341,8 @@ static bool kvm_vncr_tlb_lookup(struct k + if (read_vncr_el2(vcpu) != vt->gva) + return false; + +- if (vt->wr.nG) { +- u64 tcr = vcpu_read_sys_reg(vcpu, TCR_EL2); +- u64 ttbr = ((tcr & TCR_A1) ? +- vcpu_read_sys_reg(vcpu, TTBR1_EL2) : +- vcpu_read_sys_reg(vcpu, TTBR0_EL2)); +- u16 asid; +- +- asid = FIELD_GET(TTBR_ASID_MASK, ttbr); +- if (!kvm_has_feat_enum(vcpu->kvm, ID_AA64MMFR0_EL1, ASIDBITS, 16) || +- !(tcr & TCR_ASID16)) +- asid &= GENMASK(7, 0); +- +- return asid == vt->wr.asid; +- } ++ if (vt->wr.nG) ++ return get_asid_by_regime(vcpu, TR_EL20) == vt->wr.asid; + + return true; + } +@@ -1428,21 +1443,8 @@ static void kvm_map_l1_vncr(struct kvm_v + if (read_vncr_el2(vcpu) != vt->gva) + return; + +- if (vt->wr.nG) { +- u64 tcr = vcpu_read_sys_reg(vcpu, TCR_EL2); +- u64 ttbr = ((tcr & TCR_A1) ? +- vcpu_read_sys_reg(vcpu, TTBR1_EL2) : +- vcpu_read_sys_reg(vcpu, TTBR0_EL2)); +- u16 asid; +- +- asid = FIELD_GET(TTBR_ASID_MASK, ttbr); +- if (!kvm_has_feat_enum(vcpu->kvm, ID_AA64MMFR0_EL1, ASIDBITS, 16) || +- !(tcr & TCR_ASID16)) +- asid &= GENMASK(7, 0); +- +- if (asid != vt->wr.asid) +- return; +- } ++ if (vt->wr.nG && get_asid_by_regime(vcpu, TR_EL20) != vt->wr.asid) ++ return; + + vt->cpu = smp_processor_id(); + diff --git a/queue-6.18/kvm-arm64-ensure-level-is-always-initialized-when-relaxing-perms.patch b/queue-6.18/kvm-arm64-ensure-level-is-always-initialized-when-relaxing-perms.patch new file mode 100644 index 0000000000..dbdf08deba --- /dev/null +++ b/queue-6.18/kvm-arm64-ensure-level-is-always-initialized-when-relaxing-perms.patch @@ -0,0 +1,39 @@ +From 100baf0184896f859290a684f864b8200d8ac872 Mon Sep 17 00:00:00 2001 +From: Oliver Upton +Date: Wed, 1 Jul 2026 16:16:19 -0700 +Subject: KVM: arm64: Ensure level is always initialized when relaxing perms + +From: Oliver Upton + +commit 100baf0184896f859290a684f864b8200d8ac872 upstream. + +stage2_update_leaf_attrs() returns early before writing to @level if the +table walker returned an error. At the same time, +kvm_pgtable_stage2_relax_perms() uses the level as a TLBI TTL hint when the +error was EAGAIN, indicating the vCPU raced with a table update and the TLB +entry it hit is now stale. + +Fall back to an unknown TTL if none was provided by the walk. + +Cc: stable@vger.kernel.org +Fixes: be097997a273 ("KVM: arm64: Always invalidate TLB for stage-2 permission faults") +Signed-off-by: Oliver Upton +Reviewed-by: Wei-Lin Chang +Link: https://patch.msgid.link/20260701231620.3300204-2-oupton@kernel.org +Signed-off-by: Marc Zyngier +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kvm/hyp/pgtable.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/kvm/hyp/pgtable.c ++++ b/arch/arm64/kvm/hyp/pgtable.c +@@ -1291,7 +1291,7 @@ int kvm_pgtable_stage2_relax_perms(struc + enum kvm_pgtable_prot prot, enum kvm_pgtable_walk_flags flags) + { + int ret; +- s8 level; ++ s8 level = TLBI_TTL_UNKNOWN; + kvm_pte_t set = 0, clr = 0; + + if (prot & KVM_PTE_LEAF_ATTR_HI_SW) diff --git a/queue-6.18/kvm-arm64-fix-propagation-of-tlbi-level-in-kvm_pgtable_stage2_relax_perms.patch b/queue-6.18/kvm-arm64-fix-propagation-of-tlbi-level-in-kvm_pgtable_stage2_relax_perms.patch new file mode 100644 index 0000000000..da6eb4b9c2 --- /dev/null +++ b/queue-6.18/kvm-arm64-fix-propagation-of-tlbi-level-in-kvm_pgtable_stage2_relax_perms.patch @@ -0,0 +1,46 @@ +From 8d187d4b33c262c0f3e44842553521151d8629e8 Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Tue, 7 Jul 2026 17:29:35 +0100 +Subject: KVM: arm64: Fix propagation of TLBI level in kvm_pgtable_stage2_relax_perms() + +From: Marc Zyngier + +commit 8d187d4b33c262c0f3e44842553521151d8629e8 upstream. + +Assigning the invalidation level (an s8 value) with TLBI_TTL_UNKNOWN +(a 32bit signed value) is not ideal, to say the least. Instead of +this, only pass TLBI_TTL_UNKNOWN to __kvm_tlb_flush_vmid_ipa_nsh() +when we know for sure that we don't have a provided level. + +Fixes: 100baf0184896 ("KVM: arm64: Ensure level is always initialized when relaxing perms") +Reported-by: Mark Brown +Reviewed-by: Oliver Upton +Link: https://lore.kernel.org/r/akztC7H2IsEKaq4i@sirena.org.uk +Link: https://patch.msgid.link/20260707162935.1900874-1-maz@kernel.org +Signed-off-by: Marc Zyngier +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kvm/hyp/pgtable.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/arch/arm64/kvm/hyp/pgtable.c ++++ b/arch/arm64/kvm/hyp/pgtable.c +@@ -1291,7 +1291,7 @@ int kvm_pgtable_stage2_relax_perms(struc + enum kvm_pgtable_prot prot, enum kvm_pgtable_walk_flags flags) + { + int ret; +- s8 level = TLBI_TTL_UNKNOWN; ++ s8 level; + kvm_pte_t set = 0, clr = 0; + + if (prot & KVM_PTE_LEAF_ATTR_HI_SW) +@@ -1308,7 +1308,8 @@ int kvm_pgtable_stage2_relax_perms(struc + + ret = stage2_update_leaf_attrs(pgt, addr, 1, set, clr, NULL, &level, flags); + if (!ret || ret == -EAGAIN) +- kvm_call_hyp(__kvm_tlb_flush_vmid_ipa_nsh, pgt->mmu, addr, level); ++ kvm_call_hyp(__kvm_tlb_flush_vmid_ipa_nsh, pgt->mmu, addr, ++ (ret == -EAGAIN) ? TLBI_TTL_UNKNOWN : level); + return ret; + } + diff --git a/queue-6.18/kvm-arm64-nv-re-translate-vncr-before-injecting-abort.patch b/queue-6.18/kvm-arm64-nv-re-translate-vncr-before-injecting-abort.patch new file mode 100644 index 0000000000..78b17e17a3 --- /dev/null +++ b/queue-6.18/kvm-arm64-nv-re-translate-vncr-before-injecting-abort.patch @@ -0,0 +1,165 @@ +From bb645aa0a4caeaf7f9cd32e9a948594d434c1a8f Mon Sep 17 00:00:00 2001 +From: Oliver Upton +Date: Thu, 18 Jun 2026 16:42:04 -0700 +Subject: KVM: arm64: nv: Re-translate VNCR before injecting abort + +From: Oliver Upton + +commit bb645aa0a4caeaf7f9cd32e9a948594d434c1a8f upstream. + +KVM faults in the VNCR page with FOLL_WRITE whenever the guest aborts +for a write, similar to how a regular stage-2 mapping is handled. It is +entirely possible that the guest reads from the VNCR before writing to +it, in which case the PFN could only be read-only. + +Invalidate the VNCR TLB and re-fetch the translation upon taking a VNCR +abort, allowing the host mapping to be faulted in for write the second +time around. Interestingly enough, this also satisfies the ordering +requirements of FEAT_ETS2/3 between descriptor updates and MMU faults. + +Cc: stable@vger.kernel.org +Fixes: 2a359e072596 ("KVM: arm64: nv: Handle mapping of VNCR_EL2 at EL2") +Reported-by: Sashiko +Signed-off-by: Oliver Upton +Link: https://patch.msgid.link/20260618234207.1063941-4-oupton@kernel.org +Signed-off-by: Marc Zyngier +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kvm/nested.c | 115 ++++++++++++++++++------------------------------ + 1 file changed, 44 insertions(+), 71 deletions(-) + +--- a/arch/arm64/kvm/nested.c ++++ b/arch/arm64/kvm/nested.c +@@ -1329,88 +1329,61 @@ static void handle_vncr_perm(struct kvm_ + kvm_inject_nested_sync(vcpu, esr); + } + +-static bool kvm_vncr_tlb_lookup(struct kvm_vcpu *vcpu) +-{ +- struct vncr_tlb *vt = vcpu->arch.vncr_tlb; +- +- lockdep_assert_held_read(&vcpu->kvm->mmu_lock); +- +- if (!vt->valid) +- return false; +- +- if (read_vncr_el2(vcpu) != vt->gva) +- return false; +- +- if (vt->wr.nG) +- return get_asid_by_regime(vcpu, TR_EL20) == vt->wr.asid; +- +- return true; +-} +- + int kvm_handle_vncr_abort(struct kvm_vcpu *vcpu) + { + struct vncr_tlb *vt = vcpu->arch.vncr_tlb; + u64 esr = kvm_vcpu_get_esr(vcpu); ++ bool is_gmem = false; ++ bool perm; ++ int ret; + + WARN_ON_ONCE(!(esr & ESR_ELx_VNCR)); + + if (kvm_vcpu_abt_issea(vcpu)) + return kvm_handle_guest_sea(vcpu); + +- if (esr_fsc_is_permission_fault(esr)) { +- handle_vncr_perm(vcpu); +- } else if (esr_fsc_is_translation_fault(esr)) { +- bool valid, is_gmem = false; +- int ret; +- +- scoped_guard(read_lock, &vcpu->kvm->mmu_lock) +- valid = kvm_vncr_tlb_lookup(vcpu); +- +- if (!valid) +- ret = kvm_translate_vncr(vcpu, &is_gmem); +- else +- ret = -EPERM; +- +- switch (ret) { +- case -EAGAIN: +- /* Let's try again... */ +- break; +- case -ENOMEM: +- /* +- * For guest_memfd, this indicates that it failed to +- * create a folio to back the memory. Inform userspace. +- */ +- if (is_gmem) +- return 0; +- /* Otherwise, let's try again... */ +- break; +- case -EFAULT: +- case -EIO: +- case -EHWPOISON: +- if (is_gmem) +- return 0; +- fallthrough; +- case -EINVAL: +- case -ENOENT: +- case -EACCES: +- /* +- * Translation failed, inject the corresponding +- * exception back to EL2. +- */ +- esr &= ~ESR_ELx_FSC; +- esr |= FIELD_PREP(ESR_ELx_FSC, vt->wr.fst); +- +- kvm_inject_nested_sync(vcpu, esr); +- break; +- case -EPERM: +- /* Hack to deal with POE until we get kernel support */ +- handle_vncr_perm(vcpu); +- break; +- case 0: +- break; +- } +- } else { ++ if (!esr_fsc_is_translation_fault(esr) && !esr_fsc_is_permission_fault(esr)) { + WARN_ONCE(1, "Unhandled VNCR abort, ESR=%llx\n", esr); ++ return 1; ++ } ++ ++ ret = kvm_translate_vncr(vcpu, &is_gmem); ++ switch (ret) { ++ case -EAGAIN: ++ /* Let's try again... */ ++ return 1; ++ case -ENOMEM: ++ /* ++ * For guest_memfd, this indicates that it failed to ++ * create a folio to back the memory. Inform userspace. ++ */ ++ if (is_gmem) ++ return 0; ++ /* Otherwise, let's try again... */ ++ break; ++ case -EFAULT: ++ case -EIO: ++ case -EHWPOISON: ++ if (is_gmem) ++ return 0; ++ fallthrough; ++ case -EINVAL: ++ case -ENOENT: ++ case -EACCES: ++ /* ++ * Translation failed, inject the corresponding ++ * exception back to EL2. ++ */ ++ esr &= ~ESR_ELx_FSC; ++ esr |= FIELD_PREP(ESR_ELx_FSC, vt->wr.fst); ++ ++ kvm_inject_nested_sync(vcpu, esr); ++ break; ++ case 0: ++ perm = kvm_is_write_fault(vcpu) ? vt->wr.pw && vt->hpa_writable : vt->wr.pr; ++ if (!perm) ++ handle_vncr_perm(vcpu); ++ break; + } + + return 1; diff --git a/queue-6.18/mm-damon-core-always-put-unsuccessfully-committed-target-pids.patch b/queue-6.18/mm-damon-core-always-put-unsuccessfully-committed-target-pids.patch new file mode 100644 index 0000000000..8b0cce86f4 --- /dev/null +++ b/queue-6.18/mm-damon-core-always-put-unsuccessfully-committed-target-pids.patch @@ -0,0 +1,154 @@ +From 6a66c557a2ab2609575bafd15e093669c05f9711 Mon Sep 17 00:00:00 2001 +From: SeongJae Park +Date: Thu, 4 Jun 2026 18:38:48 -0700 +Subject: mm/damon/core: always put unsuccessfully committed target pids + +From: SeongJae Park + +commit 6a66c557a2ab2609575bafd15e093669c05f9711 upstream. + +damon_commit_target() puts and gets the destination and the source target +pids. It puts the destination target pid because it will be overwritten +by the source target pid. It gets the source pid because the caller is +supposed to eventually put the pids. In more detail, the caller will call +damon_destroy_ctx() after damon_commit_ctx() to destroy the entire source +context. And in this case, [f]vaddr operation set's cleanup_target() +callback will put the pids. + +The commit operation is made at the context level. The operation can fail +in multiple places including in the middle and after the targets commit +operations. For any such failures, immediately the error is returned to +the damon_commit_ctx() caller. If some or all of the source target pids +were committed to the destination during the unsuccessful context commit +attempt, those pids should be put twice. + +The source context will do the put operations using the above explained +routine. However, let's suppose the destination context was not +originally using [f]vaddr operation set and the commit failed before the +ops of the source context is committed. The destination does not have the +cleanup_target() ops callback, so it cannot put the pids via the +damon_destroy_ctx(). + +As a result, the pids are leaked. The issue in the real world would be +not very common. The commit feature is for changing parameters of running +DAMON context while inheriting internal status like the monitoring +results. The monitoring results of a physical address range ain't have +things that are beneficial to be inherited to a virtual address ranges +monitoring. So the problem-causing DAMON control would be not very common +in the real world. That said, it is a supported feature. And +damon_commit_target() failure due to memory allocation is relatively +realistic [1] if there are a huge number of target regions. + +Fix by putting the pids in the commit operation in case of the failures. + +The issue was discovered [2] by Sashiko. + +Link: https://lore.kernel.org/20260605013849.83750-1-sj@kernel.org +Link: https://lore.kernel.org/20260603112306.58490-1-akinobu.mita@gmail.com [1] +Link: https://lore.kernel.org/20260320020056.835-1-sj@kernel.org [2] +Fixes: 83dc7bbaecae ("mm/damon/sysfs: use damon_commit_ctx()") +Signed-off-by: SeongJae Park +Cc: # 6.11.x +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/damon/core.c | 49 +++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 43 insertions(+), 6 deletions(-) + +--- a/mm/damon/core.c ++++ b/mm/damon/core.c +@@ -1173,10 +1173,36 @@ static int damon_commit_target( + return 0; + } + ++/* ++ * damon_revert_target_commits() - revert unsuccessful target commits. ++ * @dst: Commit destination context ++ * @failed: Commit failed destination target ++ * @src: Commit source context ++ * ++ * Revert target states that changed by damon_commit_target(), and cannot be ++ * cleaned up by the destination context's ops.cleanup_target(). ++ */ ++static void damon_revert_target_commits(struct damon_ctx *dst, ++ struct damon_target *failed, struct damon_ctx *src) ++{ ++ struct damon_target *target; ++ ++ if (!damon_target_has_pid(src)) ++ return; ++ if (dst->ops.cleanup_target) ++ return; ++ damon_for_each_target(target, dst) { ++ if (target == failed) ++ return; ++ put_pid(target->pid); ++ } ++} ++ + static int damon_commit_targets( + struct damon_ctx *dst, struct damon_ctx *src) + { + struct damon_target *dst_target, *next, *src_target, *new_target; ++ struct damon_target *failed; + int i = 0, j = 0, err; + + damon_for_each_target_safe(dst_target, next, dst) { +@@ -1186,8 +1212,10 @@ static int damon_commit_targets( + dst_target, damon_target_has_pid(dst), + src_target, damon_target_has_pid(src), + src->min_sz_region); +- if (err) +- return err; ++ if (err) { ++ failed = dst_target; ++ goto out; ++ } + } else { + struct damos *s; + +@@ -1201,22 +1229,29 @@ static int damon_commit_targets( + } + } + ++ failed = NULL; + damon_for_each_target_safe(src_target, next, src) { + if (j++ < i) + continue; + new_target = damon_new_target(); +- if (!new_target) +- return -ENOMEM; ++ if (!new_target) { ++ err = -ENOMEM; ++ goto out; ++ } + err = damon_commit_target(new_target, false, + src_target, damon_target_has_pid(src), + src->min_sz_region); + if (err) { + damon_destroy_target(new_target, NULL); +- return err; ++ goto out; + } + damon_add_target(dst, new_target); + } + return 0; ++ ++out: ++ damon_revert_target_commits(dst, failed, src); ++ return err; + } + + /** +@@ -1255,8 +1290,10 @@ int damon_commit_ctx(struct damon_ctx *d + */ + if (!damon_attrs_equals(&dst->attrs, &src->attrs)) { + err = damon_set_attrs(dst, &src->attrs); +- if (err) ++ if (err) { ++ damon_revert_target_commits(dst, NULL, src); + return err; ++ } + } + dst->ops = src->ops; + dst->addr_unit = src->addr_unit; diff --git a/queue-6.18/mm-damon-core-trace-esz-at-first-setup.patch b/queue-6.18/mm-damon-core-trace-esz-at-first-setup.patch new file mode 100644 index 0000000000..8be687938a --- /dev/null +++ b/queue-6.18/mm-damon-core-trace-esz-at-first-setup.patch @@ -0,0 +1,56 @@ +From 7e6cc35f5283eab81a14231a64ecd640b690c48c Mon Sep 17 00:00:00 2001 +From: SeongJae Park +Date: Wed, 20 May 2026 08:03:10 -0700 +Subject: mm/damon/core: trace esz at first setup + +From: SeongJae Park + +commit 7e6cc35f5283eab81a14231a64ecd640b690c48c upstream. + +DAMON traces effective size quota from the second update, only if a change +has been made by the update. Tracing only changed updates was an +intentional decision to avoid unnecessary same value tracing. Always +skipping the first value is just an unintended mistake. + +The mistake makes the tracepoint based investigation incomplete, because +the first effective size quota is never traced. It is not a big issue +when the 'consist' quota tuner is used, because it keeps changing the +quota in the usual setup. + +However, when the 'temporal' tuner is used, the quota value is not changed +before the goal achievement status is completely changed. For example, if +the DAMOS scheme is started with an under-achieved goal, the quota is set +to the maximum value, and kept the same value until the goal is achieved. +Because DAMON skips the first value, the user cannot know what effective +quota the current scheme is using. Only after the goal is achieved, the +effective quota is changed to zero, and traced. + +Unconditionally trace the initial quota value to fix this problem. + +Note that the 'temporal' quota tuner was introduced by commit af738a6a00c1 +("mm/damon/core: introduce DAMOS_QUOTA_GOAL_TUNER_TEMPORAL"), which was +added to 7.1-rc1. But even with the 'consist' quota tuner, the tracing is +unintentionally incomplete. Hence this commit marks the introduction of +the trace event as the broken commit. + +Link: https://lore.kernel.org/20260520150311.80925-1-sj@kernel.org +Fixes: a86d695193bf ("mm/damon: add trace event for effective size quota") +Signed-off-by: SeongJae Park +Cc: # 6.17.x +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/damon/core.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/mm/damon/core.c ++++ b/mm/damon/core.c +@@ -2237,6 +2237,8 @@ static void damos_adjust_quota(struct da + if (!quota->total_charged_sz && !quota->charged_from) { + quota->charged_from = jiffies; + damos_set_effective_quota(quota, c); ++ if (trace_damos_esz_enabled()) ++ damos_trace_esz(c, s, quota); + } + + /* New charge window starts */ diff --git a/queue-6.18/samples-damon-mtier-fail-early-if-address-range-parameters-are-invalid.patch b/queue-6.18/samples-damon-mtier-fail-early-if-address-range-parameters-are-invalid.patch new file mode 100644 index 0000000000..c56afb71af --- /dev/null +++ b/queue-6.18/samples-damon-mtier-fail-early-if-address-range-parameters-are-invalid.patch @@ -0,0 +1,72 @@ +From 7746d72c64054976887928d64d2caf25c5a6dcc0 Mon Sep 17 00:00:00 2001 +From: Zenghui Yu +Date: Mon, 29 Jun 2026 07:44:31 -0700 +Subject: samples/damon/mtier: fail early if address range parameters are invalid + +From: Zenghui Yu + +commit 7746d72c64054976887928d64d2caf25c5a6dcc0 upstream. + +The comment on top of `struct damon_region` clearly says that + + For any use case, @ar should be non-zero positive size. + +which is now verified in damon_verify_new_region() if the kernel is built +with DAMON_DEBUG_SANITY. + +The WARN_ONCE() can be triggered if the mtier sample module is enabled +before node{0,1}_{start,end}_addr have been properly initialized, which is +obviously not good. + + ------------[ cut here ]------------ + start 0 >= end 0 + WARNING: mm/damon/core.c:217 at damon_new_region+0xf4/0x118, CPU#59: bash/341468 + Call trace: + damon_new_region+0xf4/0x118 (P) + damon_set_regions+0xfc/0x3c0 + damon_sample_mtier_build_ctx+0xe8/0x3a8 + damon_sample_mtier_start+0x1c/0x90 + damon_sample_mtier_enable_store+0x98/0xb0 + param_attr_store+0xb4/0x128 + module_attr_store+0x2c/0x50 + sysfs_kf_write+0x58/0x90 + kernfs_fop_write_iter+0x16c/0x238 + vfs_write+0x2c0/0x370 + ksys_write+0x74/0x118 + __arm64_sys_write+0x24/0x38 + invoke_syscall+0xa8/0x118 + el0_svc_common.constprop.0+0x48/0xf0 + do_el0_svc+0x24/0x38 + el0_svc+0x54/0x370 + el0t_64_sync_handler+0xa0/0xe8 + el0t_64_sync+0x1ac/0x1b0 + ---[ end trace 0000000000000000 ]--- + +Note that the same issue can happen if detect_node_addresses is true, and +node 0 or 1 is memoryless. Fix it together by checking the validity of +parameters right before damon_new_region() and fail early if they're +invalid. + +Link: https://lore.kernel.org/20260629144432.133962-1-sj@kernel.org +Fixes: 82a08bde3cf7 ("samples/damon: implement a DAMON module for memory tiering") +Signed-off-by: Zenghui Yu +Signed-off-by: SJ Park +Reviewed-by: SJ Park +Cc: # 6.16.x +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + samples/damon/mtier.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/samples/damon/mtier.c ++++ b/samples/damon/mtier.c +@@ -120,6 +120,8 @@ static struct damon_ctx *damon_sample_mt + addr.end = promote ? node1_end_addr : node0_end_addr; + } + ++ if (addr.start >= addr.end) ++ goto free_out; + region = damon_new_region(addr.start, addr.end); + if (!region) + goto free_out; diff --git a/queue-6.18/series b/queue-6.18/series index 236af89c16..43b66aa29b 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -1592,3 +1592,10 @@ btrfs-remove-folio-parameter-from-ordered-io-related-functions.patch crypto-qat-fix-restarting-state-leak-on-allocation-failure.patch btrfs-fix-false-io-failure-after-falling-back-to-buffered-write.patch btrfs-fix-incorrect-buffered-io-fallback-for-append-direct-writes.patch +kvm-arm64-ensure-level-is-always-initialized-when-relaxing-perms.patch +kvm-arm64-fix-propagation-of-tlbi-level-in-kvm_pgtable_stage2_relax_perms.patch +mm-damon-core-always-put-unsuccessfully-committed-target-pids.patch +mm-damon-core-trace-esz-at-first-setup.patch +samples-damon-mtier-fail-early-if-address-range-parameters-are-invalid.patch +kvm-arm64-deduplicate-asid-retrieval-code.patch +kvm-arm64-nv-re-translate-vncr-before-injecting-abort.patch