[PATCH v2 42/58] target/arm/hvf: Implement dirty page tracking

Philippe Mathieu-Daudé posted 58 patches 3 weeks, 1 day ago
Maintainers: Richard Henderson <richard.henderson@linaro.org>, Paolo Bonzini <pbonzini@redhat.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Cameron Esfahani <dirty@apple.com>, Roman Bolshakov <rbolshakov@ddn.com>, Phil Dennis-Jordan <phil@philjordan.eu>, Mads Ynddal <mads@ynddal.dk>, Peter Maydell <peter.maydell@linaro.org>, Alexander Graf <agraf@csgraf.de>, Stefan Hajnoczi <stefanha@redhat.com>
There is a newer version of this series
[PATCH v2 42/58] target/arm/hvf: Implement dirty page tracking
Posted by Philippe Mathieu-Daudé 3 weeks, 1 day ago
From: Richard Henderson <richard.henderson@linaro.org>

Notice writes to pages which are being monitored.  Mark the page dirty,
re-enable writes, and retry the instruction without emulation.

Assert the fault is not from a stage1 page table walk.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 target/arm/hvf/hvf.c | 52 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 43 insertions(+), 9 deletions(-)

diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index 77998ab90a6..cf4746c344a 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -37,6 +37,7 @@
 #include "target/arm/trace.h"
 #include "trace.h"
 #include "migration/vmstate.h"
+#include "exec/target_page.h"
 
 #include "gdbstub/enums.h"
 
@@ -1880,9 +1881,10 @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp)
         uint32_t srt = (syndrome >> 16) & 0x1f;
         uint32_t cm = (syndrome >> 8) & 0x1;
         uint64_t val = 0;
+        uint64_t ipa = excp->physical_address;
+        AddressSpace *as = cpu_get_address_space(cpu, ARMASIdx_NS);
 
-        trace_hvf_data_abort(excp->virtual_address,
-                             excp->physical_address, isv,
+        trace_hvf_data_abort(excp->virtual_address, ipa, isv,
                              iswrite, s1ptw, len, srt);
 
         if (cm) {
@@ -1891,23 +1893,55 @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp)
             break;
         }
 
+        /* Handle dirty page logging for ram. */
+        if (iswrite) {
+            hwaddr xlat;
+            MemoryRegion *mr = address_space_translate(as, ipa, &xlat,
+                                                       NULL, true,
+                                                       MEMTXATTRS_UNSPECIFIED);
+            if (memory_region_is_ram(mr)) {
+                uint64_t ipa_page = ipa & TARGET_PAGE_MASK;
+
+                /* TODO: Inject exception to the guest. */
+                assert(!mr->readonly);
+
+                if (memory_region_get_dirty_log_mask(mr)) {
+                    memory_region_set_dirty(mr, ipa_page + xlat,
+                                            TARGET_PAGE_SIZE);
+                    hvf_unprotect_dirty_range(ipa_page, TARGET_PAGE_SIZE);
+                }
+
+                /* Retry with page writes enabled. */
+                break;
+            }
+        }
+
+        /*
+         * TODO: If s1ptw, this is an error in the guest os page tables.
+         * Inject the exception into the guest.
+         */
+        assert(!s1ptw);
+
+        /*
+         * TODO: ISV will be 0 for SIMD or SVE accesses.
+         * Inject the exception into the guest.
+         */
         assert(isv);
 
+        /*
+         * Emulate MMIO.
+         * TODO: Inject faults for errors.
+         */
         if (iswrite) {
             val = hvf_get_reg(cpu, srt);
-            address_space_write(&address_space_memory,
-                                excp->physical_address,
-                                MEMTXATTRS_UNSPECIFIED, &val, len);
+            address_space_write(as, ipa, MEMTXATTRS_UNSPECIFIED, &val, len);
         } else {
-            address_space_read(&address_space_memory,
-                               excp->physical_address,
-                               MEMTXATTRS_UNSPECIFIED, &val, len);
+            address_space_read(as, ipa, MEMTXATTRS_UNSPECIFIED, &val, len);
             if (sse) {
                 val = sextract64(val, 0, len * 8);
             }
             hvf_set_reg(cpu, srt, val);
         }
-
         advance_pc = true;
         break;
     }
-- 
2.51.0


Re: [PATCH v2 42/58] target/arm/hvf: Implement dirty page tracking
Posted by Richard Henderson 2 weeks, 5 days ago
On 10/23/25 15:06, Philippe Mathieu-Daudé wrote:
> +        /* Handle dirty page logging for ram. */
> +        if (iswrite) {
> +            hwaddr xlat;
> +            MemoryRegion *mr = address_space_translate(as, ipa, &xlat,
> +                                                       NULL, true,
> +                                                       MEMTXATTRS_UNSPECIFIED);
> +            if (memory_region_is_ram(mr)) {
> +                uint64_t ipa_page = ipa & TARGET_PAGE_MASK;
> +
> +                /* TODO: Inject exception to the guest. */
> +                assert(!mr->readonly);
> +
> +                if (memory_region_get_dirty_log_mask(mr)) {
> +                    memory_region_set_dirty(mr, ipa_page + xlat,
> +                                            TARGET_PAGE_SIZE);
> +                    hvf_unprotect_dirty_range(ipa_page, TARGET_PAGE_SIZE);
> +                }

We need to use the host page size/mask, not TARGET_PAGE_SIZE/MASK here.

r~

Re: [PATCH v2 42/58] target/arm/hvf: Implement dirty page tracking
Posted by Philippe Mathieu-Daudé 3 weeks, 1 day ago
On 23/10/25 15:06, Philippe Mathieu-Daudé wrote:
> From: Richard Henderson <richard.henderson@linaro.org>
> 
> Notice writes to pages which are being monitored.  Mark the page dirty,
> re-enable writes, and retry the instruction without emulation.
> 
> Assert the fault is not from a stage1 page table walk.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> ---
>   target/arm/hvf/hvf.c | 52 ++++++++++++++++++++++++++++++++++++--------
>   1 file changed, 43 insertions(+), 9 deletions(-)

Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>