mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/3] Set DBM bit on writable pages
@ 2026-10-26 14:44 Leonardo Bras
  2026-10-26 14:44 ` [RFC PATCH v2 1/3] KVM: arm64: pgtables: Set DBM attribute on writable Stage-2 PTEs Leonardo Bras
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Leonardo Bras @ 2026-10-26 14:44 UTC (permalink / raw)
  To: Oliver Upton, Marc Zyngier, Fuad Tabba, Joey Gouly,
	Steffen Eiden, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mark Rutland, Leonardo Bras, Raghavendra Rao Ananta,
	Tian Zheng
  Cc: linux-arm-kernel, kvmarm, linux-kernel

When HAFDBS is enabled (VTCR_EL2.{HA,HD}={1,1}), having a DBM bit allows 
hardware to promote a non-writable page to writable by setting (S2AP[1]=1),
without having to take a fault.

The reason for this patchset is to add the DBM bit when setting-up writable 
pages, so the code is prepared for future patches that make use of 
HDBSS/HACDBS to accelerate dirty-tracking. Write-bit detection still 
happens based only in S2AP[1], so no change in that aspect.

Having DBM set on block entries is undesired, as we benefit from the first 
fault for splitting it in PAGE_SIZE entries, which is the granularity used 
to track the dirty pages in KVM. So introduce a new walker that, on top of 
clearing S2AP[1] for every entry, also clear DBM for block entries.

Also introduce a new VCPU request to reload Stage2, as it will be needed on 
future HDBSS/HAFDBS patchsets. 

Please let me know of what do you think!

Changes since RFCv1:
- Dropped patch #5 on enabling HAFDBS on non-dirty-tracking guests, as it 
  proved to be counter-productive on wrprotect, contrary to expectations
- No more moving writable-bit to DBM. That does not seem to be the intended 
  use. It makes sense and it's easier to convert code to new DBM approach.
- No new PROT_DIRTY, so drop patch #2
- Tried adding a PROT_DBM, but does not seem necessary to fault a page as 
  writable-clean. 
- KVM_REQ_RELOAD_STAGE2 now depends on VHE, as it already reloads Stage2 on 
  guest entry otherwise. 
Link: https://lore.kernel.org/all/20260901171558.2674031-1-leo.bras@arm.com/

Thanks!
Leo

Leonardo Bras (3):
  KVM: arm64: pgtables: Set DBM attribute on writable Stage-2 PTEs
  KVM: arm64: Introduce a dedicated walker for stage2 write-protect
  KVM: arm64: Add KVM_REQ_RELOAD_STAGE2

 arch/arm64/include/asm/kvm_host.h    |  2 ++
 arch/arm64/include/asm/kvm_pgtable.h |  3 +++
 arch/arm64/kvm/arm.c                 | 10 ++++++++++
 arch/arm64/kvm/hyp/pgtable.c         | 30 ++++++++++++++++++++++------
 4 files changed, 39 insertions(+), 6 deletions(-)


base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
-- 
2.56.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC PATCH v2 1/3] KVM: arm64: pgtables: Set DBM attribute on writable Stage-2 PTEs
  2026-10-26 14:44 [RFC PATCH v2 0/3] Set DBM bit on writable pages Leonardo Bras
@ 2026-10-26 14:44 ` Leonardo Bras
  2026-10-26 14:44 ` [RFC PATCH v2 2/3] KVM: arm64: Introduce a dedicated walker for stage2 write-protect Leonardo Bras
  2026-10-26 14:44 ` [RFC PATCH v2 3/3] KVM: arm64: Add KVM_REQ_RELOAD_STAGE2 Leonardo Bras
  2 siblings, 0 replies; 4+ messages in thread
From: Leonardo Bras @ 2026-10-26 14:44 UTC (permalink / raw)
  To: Oliver Upton, Marc Zyngier, Fuad Tabba, Joey Gouly,
	Steffen Eiden, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mark Rutland, Leonardo Bras, Raghavendra Rao Ananta,
	Tian Zheng
  Cc: linux-arm-kernel, kvmarm, linux-kernel

As a preparation to the introduction of HAFDBS-based features, set the DBM
bit (along with S2AP[1]) to all writable PTEs. Also unset DBM and S2AP[1]
when a PTE is made read-only again.

DBM bit works as following:
- If HAFDBS is disabled, DBM bit is ignored.
- If HAFDBS is enabled, and DBM bit is set, a write to non-writable page
  can promote it's PTE to writable (S2AP[1]=1) without taking a fault.

Since it's being set on writable and unset on read-only, it should cause no
functional change.

Signed-off-by: Leonardo Bras <leo.bras@arm.com>
---
 arch/arm64/include/asm/kvm_pgtable.h | 3 +++
 arch/arm64/kvm/hyp/pgtable.c         | 5 +++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h
index 41a8687938eb..37baa86d6fd8 100644
--- a/arch/arm64/include/asm/kvm_pgtable.h
+++ b/arch/arm64/include/asm/kvm_pgtable.h
@@ -91,14 +91,17 @@ typedef u64 kvm_pte_t;
 #define KVM_PTE_LEAF_ATTR_HI_S1_UXN	BIT(54)
 #define KVM_PTE_LEAF_ATTR_HI_S1_PXN	BIT(53)
 
 #define KVM_PTE_LEAF_ATTR_HI_S2_XN	GENMASK(54, 53)
 
+#define KVM_PTE_LEAF_ATTR_HI_S2_DBM	BIT(51)
+
 #define KVM_PTE_LEAF_ATTR_HI_S1_GP	BIT(50)
 
 #define KVM_PTE_LEAF_ATTR_S2_PERMS	(KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R | \
 					 KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W | \
+					 KVM_PTE_LEAF_ATTR_HI_S2_DBM | \
 					 KVM_PTE_LEAF_ATTR_HI_S2_XN)
 
 /* pKVM invalid pte encodings */
 #define KVM_INVALID_PTE_TYPE_MASK	GENMASK(63, 60)
 #define KVM_INVALID_PTE_ANNOT_MASK	~(KVM_PTE_VALID | \
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index b74dd5ce1efd..8c2320c6a7f1 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -730,11 +730,11 @@ static int stage2_set_prot_attr(struct kvm_pgtable *pgt, enum kvm_pgtable_prot p
 
 	if (prot & KVM_PGTABLE_PROT_R)
 		attr |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R;
 
 	if (prot & KVM_PGTABLE_PROT_W)
-		attr |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
+		attr |= KVM_PTE_LEAF_ATTR_HI_S2_DBM | KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
 
 	if (!kvm_lpa2_is_enabled())
 		attr |= FIELD_PREP(KVM_PTE_LEAF_ATTR_LO_S2_SH, sh);
 
 	attr |= KVM_PTE_LEAF_ATTR_LO_S2_AF;
@@ -1286,10 +1286,11 @@ static int stage2_update_leaf_attrs(struct kvm_pgtable *pgt, u64 addr,
 }
 
 int kvm_pgtable_stage2_wrprotect(struct kvm_pgtable *pgt, u64 addr, u64 size)
 {
 	return stage2_update_leaf_attrs(pgt, addr, size, 0,
+					KVM_PTE_LEAF_ATTR_HI_S2_DBM |
 					KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W,
 					NULL, NULL,
 					KVM_PGTABLE_WALK_IGNORE_EAGAIN);
 }
 
@@ -1366,11 +1367,11 @@ int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr,
 
 	if (prot & KVM_PGTABLE_PROT_R)
 		set |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R;
 
 	if (prot & KVM_PGTABLE_PROT_W)
-		set |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
+		set |= KVM_PTE_LEAF_ATTR_HI_S2_DBM | KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
 
 	if (prot & KVM_PGTABLE_PROT_X) {
 		ret = stage2_set_xn_attr(prot, &xn);
 		if (ret)
 			return ret;
-- 
2.56.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC PATCH v2 2/3] KVM: arm64: Introduce a dedicated walker for stage2 write-protect
  2026-10-26 14:44 [RFC PATCH v2 0/3] Set DBM bit on writable pages Leonardo Bras
  2026-10-26 14:44 ` [RFC PATCH v2 1/3] KVM: arm64: pgtables: Set DBM attribute on writable Stage-2 PTEs Leonardo Bras
@ 2026-10-26 14:44 ` Leonardo Bras
  2026-10-26 14:44 ` [RFC PATCH v2 3/3] KVM: arm64: Add KVM_REQ_RELOAD_STAGE2 Leonardo Bras
  2 siblings, 0 replies; 4+ messages in thread
From: Leonardo Bras @ 2026-10-26 14:44 UTC (permalink / raw)
  To: Oliver Upton, Marc Zyngier, Fuad Tabba, Joey Gouly,
	Steffen Eiden, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mark Rutland, Leonardo Bras, Raghavendra Rao Ananta,
	Tian Zheng
  Cc: linux-arm-kernel, kvmarm, linux-kernel

When write-protecting a range, clean the writable bit (S2AP[1]) and keep
the DBM bit set for pages, so on HDBSS-enabled systems we can skip the
fault for making it writable again.

On block entries clean both the writable bit and the DBM bit, so we fault
even on HDBSS-enabled systems, in order to have hugepage splitting.

With disabled HDBSS, there should be no change in faulting behavior.

Signed-off-by: Leonardo Bras <leo.bras@arm.com>
---
 arch/arm64/kvm/hyp/pgtable.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index 8c2320c6a7f1..837546be5c13 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -1283,17 +1283,34 @@ static int stage2_update_leaf_attrs(struct kvm_pgtable *pgt, u64 addr,
 	if (level)
 		*level = data.level;
 	return 0;
 }
 
+static int stage2_wrprotect_walker(const struct kvm_pgtable_visit_ctx *ctx,
+				   enum kvm_pgtable_walk_flags visit)
+{
+	kvm_pte_t new = ctx->old & ~KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
+
+	/* We remove DBM on blocks so they can fault and get split */
+	if (ctx->level < KVM_PGTABLE_LAST_LEVEL)
+		new &= ~KVM_PTE_LEAF_ATTR_HI_S2_DBM;
+
+	if (kvm_pte_valid(ctx->old) && ctx->old != new)
+		WRITE_ONCE(*ctx->ptep, new);
+
+	return 0;
+}
+
+
 int kvm_pgtable_stage2_wrprotect(struct kvm_pgtable *pgt, u64 addr, u64 size)
 {
-	return stage2_update_leaf_attrs(pgt, addr, size, 0,
-					KVM_PTE_LEAF_ATTR_HI_S2_DBM |
-					KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W,
-					NULL, NULL,
-					KVM_PGTABLE_WALK_IGNORE_EAGAIN);
+	struct kvm_pgtable_walker walker = {
+		.cb	= stage2_wrprotect_walker,
+		.flags	= KVM_PGTABLE_WALK_LEAF,
+	};
+
+	return kvm_pgtable_walk(pgt, addr, size, &walker);
 }
 
 void kvm_pgtable_stage2_mkyoung(struct kvm_pgtable *pgt, u64 addr,
 				enum kvm_pgtable_walk_flags flags)
 {
-- 
2.56.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC PATCH v2 3/3] KVM: arm64: Add KVM_REQ_RELOAD_STAGE2
  2026-10-26 14:44 [RFC PATCH v2 0/3] Set DBM bit on writable pages Leonardo Bras
  2026-10-26 14:44 ` [RFC PATCH v2 1/3] KVM: arm64: pgtables: Set DBM attribute on writable Stage-2 PTEs Leonardo Bras
  2026-10-26 14:44 ` [RFC PATCH v2 2/3] KVM: arm64: Introduce a dedicated walker for stage2 write-protect Leonardo Bras
@ 2026-10-26 14:44 ` Leonardo Bras
  2 siblings, 0 replies; 4+ messages in thread
From: Leonardo Bras @ 2026-10-26 14:44 UTC (permalink / raw)
  To: Oliver Upton, Marc Zyngier, Fuad Tabba, Joey Gouly,
	Steffen Eiden, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mark Rutland, Leonardo Bras, Raghavendra Rao Ananta,
	Tian Zheng
  Cc: linux-arm-kernel, kvmarm, linux-kernel

Add a vcpu request to exit guest, reload Stage2, and then come back to
guest.

This will be used on future patches that enable HDBSS, as they may need to
change VTCR bits for enabling/disabling the feature when the vcpus are
still running.

On non-VHE systems, just skip this request as Stage2 is being reloaded
on every guest entry.

Signed-off-by: Leonardo Bras <leo.bras@arm.com>
---
 arch/arm64/include/asm/kvm_host.h |  2 ++
 arch/arm64/kvm/arm.c              | 10 ++++++++++
 2 files changed, 12 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index cd9b9d2462f9..86a4d6e50934 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -53,10 +53,12 @@
 #define KVM_REQ_RESYNC_PMU_EL0		KVM_ARCH_REQ(7)
 #define KVM_REQ_NESTED_S2_UNMAP		KVM_ARCH_REQ(8)
 #define KVM_REQ_GUEST_HYP_IRQ_PENDING	KVM_ARCH_REQ(9)
 #define KVM_REQ_MAP_L1_VNCR_EL2		KVM_ARCH_REQ(10)
 #define KVM_REQ_VGIC_PROCESS_UPDATE	KVM_ARCH_REQ(11)
+#define KVM_REQ_RELOAD_STAGE2 \
+	KVM_ARCH_REQ_FLAGS(12, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
 
 #define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
 				     KVM_DIRTY_LOG_INITIALLY_SET)
 
 #define KVM_HAVE_MMU_RWLOCK
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 0576c2022ef5..d311637e0b13 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1173,10 +1173,20 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
 			return kvm_vcpu_suspend(vcpu);
 
 		if (kvm_dirty_ring_check_request(vcpu))
 			return 0;
 
+		/* Non-vhe systems already reload Stage2 on guest entry */
+		if (kvm_check_request(KVM_REQ_RELOAD_STAGE2, vcpu) &&
+		    has_vhe()) {
+			unsigned long flags;
+
+			local_irq_save(flags);
+			__load_stage2(vcpu->arch.hw_mmu);
+			local_irq_restore(flags);
+		}
+
 		check_nested_vcpu_requests(vcpu);
 	}
 
 	return 1;
 }
-- 
2.56.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-10-26 14:44 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-26 14:44 [RFC PATCH v2 0/3] Set DBM bit on writable pages Leonardo Bras
2026-10-26 14:44 ` [RFC PATCH v2 1/3] KVM: arm64: pgtables: Set DBM attribute on writable Stage-2 PTEs Leonardo Bras
2026-10-26 14:44 ` [RFC PATCH v2 2/3] KVM: arm64: Introduce a dedicated walker for stage2 write-protect Leonardo Bras
2026-10-26 14:44 ` [RFC PATCH v2 3/3] KVM: arm64: Add KVM_REQ_RELOAD_STAGE2 Leonardo Bras

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®