Re: [PATCH v5 05/15] KVM: arm64: Harvest stage-2 dirty state into the host folio account
From: Tian Zheng
Date: Thu Oct 29 2026 - 10:11:05 EST
On 10/27/2026 2:05 AM, Leonardo Bras wrote:
Hi Tian,
Sorry for the delay in reviewing...
On Tue, Sep 29, 2026 at 06:36:45PM +0800, Tian Zheng wrote:
With VTCR_EL2.HD set, hardware promotes writable-clean descriptors to
writable-dirty without any VM exit, and the only record of the write
is the S2AP[1] bit in the stage-2 PTE. The write never passed through
the host stage-1, and no unmap path reads the bit, so the record dies
with the PTE and reclaim may discard written guest data (silent
corruption).
Sorry, I didn't get what you are trying to achieve here.
On your patch, I see you marking backing pages dirty at wrprotect and unmap
walkers, and it's very confusing to me on why you are doing this.
IIUC, what you are trying to do is make sure a page does not lose it's
contents in case it is reclaimed by the OS.
IIUC, when a page is reclaimed, it will unmap the S2 PTE, and save it's
contents to swap, so when the guest read or write to that page will cause
it to fault.
The page can never be just unmaped, as if there was a single write to it,
the backing pages should be writable, and the contents need to be saved
somewhere.
So, if I was able to understand your suggestion, we don't need to worry
about this, and this patch wouldn't be necessary.
Did you hit this issue?
Can you please expand on your issue, if I could not describe it above?
Thanks!
Leo
Hi Leo,
Thanks for the review. I haven't hit this in practice, and based on your
analysis the patch doesn't look necessary.
Reclaim only writes back folios whose PG_dirty flag is set; a clean
folio is simply freed. A stage-2 write never touches the host
stage-1, so the folio depends entirely on kvm_release_faultin_page()
at fault-in to be marked as dirty; without it, the page stays clean from
the host's perspective and reclaim drops the data.
Your **RFC v1** patch 2 changed that marking from writable to dirty:
```
- kvm_release_faultin_page(kvm, s2vi->page, !!ret, writable);
+ kvm_release_faultin_page(kvm, s2vi->page, !!ret, dirty);
```
During logging, a read fault maps the page as WC: the folio is not
marked PG_dirty in kvm_s2_fault_map() and hardware promotes the PTE to
WD on write without any fault, so reclaim frees the page without saving
it (the folio was treated as clean).
Therefore, **HDBSS v5** patch 2 reverted to marking the folio for any
write-permitting mapping:
```
kvm_release_faultin_page(kvm, s2vi->page, !!ret, writable);
```
Together with the v5 scheme, this makes patch 5 unnecessary:
- kvm_s2_fault_compute_prot: always set PROT_W when map_writable
- stage2_set_prot_attr: PROT_W -> DBM unconditionally
---------
On a related note, I'd like to discuss the next version of the DBM
scheme, following Oliver's suggestion [1].
Oliver asked for the write bit to be selected by the system capability:
FEAT_HAFDBS: PROT_W => DBM, PROT_DIRTY => S2AP[1]
!FEAT_HAFDBS: both => S2AP[1]
However, our v5 kvm_s2_fault_compute_prot() granted PROT_W
unconditionally. With PROT_W => S2AP[1] on !FEAT_HAFDBS, a read fault on
a dirty-tracked memslot would install a writable page. Since dirty-
logging relies on the write fault to observe the page, we would fail to
track it.
So we also need to fix kvm_s2_fault_compute_prot():
```
if (s2vi->map_writable) {
if (s2vi->device ||
!memslot_is_logging(s2fd->memslot) ||
kvm_is_write_fault(s2fd->vcpu)) {
*prot |= KVM_PGTABLE_PROT_W |
KVM_PGTABLE_PROT_DIRTY;
} else if (kvm_supports_hafdbs()) {
*prot |= KVM_PGTABLE_PROT_W;
}
}
```
For normal RAM on a system without FEAT_HAFDBS:
logging + read fault -> PTE read-only
logging + write fault -> PTE S2AP[1]=1
[1] https://lore.kernel.org/all/ff218960-c412-4283-aa41-b7af2a7048b8@xxxxxxxxxx/
Thanks,
Tian