qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 00/19] target/arm/hvf: Consolidate
@ 2025-11-14 20:04 Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 01/19] accel/hvf: Create hvf_protect_clean_range, hvf_unprotect_dirty_range Philippe Mathieu-Daudé
                   ` (19 more replies)
  0 siblings, 20 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

Missing review: #8

- Patches 1-11 fix migration on HVF
- Patches 12-14 remove a signal race with WFI
- Patches 15-18 correct guest timer frequency

Since v4:
- Rename gva -> gpa in hvf_set_phys_mem (Akihiko)
- Dropped missing VTimer synchronization patches for 10.2

Since v3:
- Call qemu_real_host_page_mask/size once (rth)

Since v2:
- Improve host page size/mask uses (rth)
- Remove cpu_test_interrupt in hvf_wfi (rth)

Since v1:
- Addressed Mads & Richard comments
- Fixed migration by reworking memory listeners
  (unfortunately the current broken code has been
   used as base for WHPX)
- Sync CNTV_CTL/CVAL_EL0
- Remove WFI racy signal implementation
- Simplify PSCI Suspend (I expect the same can be
  done for the other hvf_psci_cpu_off() calls).
- Emulate more missing registers (PMU & Monitor Dbg)

From v1:
- Fix a pair of memory leak
- Check a pair of return values
- Mention calls which must be run on vCPU thread
- Force MIDR
- Use hv_vcpu_config_create/hv_vcpu_config_get_feature_reg
  when not running on vCPU thread
- Factor hvf_handle_vmexit() / hvf_handle_exception(() out
- Call hv_vcpu_run() in loop
- Guard hv_vcpu_run() between cpu_exec_start/end()
- Restrict ARM specific in AccelCPUState

Based-on: <20250829152909.1589668-14-pbonzini@redhat.com>

Philippe Mathieu-Daudé (10):
  target/i386/hvf: Use host page alignment in ept_emulation_fault()
  accel/hvf: Enforce host alignment in hv_vm_protect()
  accel/hvf: Skip WFI if CPU has work to do
  accel/hvf: Implement WFI without using pselect()
  accel/hvf: Have PSCI CPU_SUSPEND halt the vCPU
  accel: Introduce AccelOpsClass::cpu_target_realize() hook
  accel/hvf: Add hvf_arch_cpu_realize() stubs
  target/arm: Create GTimers *after* features finalized / accel realized
  target/arm/hvf: Really set Generic Timer counter frequency
  target/arm: Only allow disabling NEON when using TCG

Richard Henderson (9):
  accel/hvf: Create hvf_protect_clean_range, hvf_unprotect_dirty_range
  target/i386/hvf: Use hvf_unprotect_dirty_range
  target/i386/hvf: Use address_space_translate in ept_emulation_fault
  accel/hvf: Simplify hvf_log_*
  accel/hvf: Move hvf_log_sync to hvf_log_clear
  accel/hvf: Simplify hvf_set_phys_mem
  accel/hvf: Drop hvf_slot and hvf_find_overlap_slot
  accel/hvf: Remove mac_slots
  target/arm/hvf: Implement dirty page tracking

 include/accel/accel-cpu-ops.h |   1 +
 include/system/hvf_int.h      |  22 +---
 accel/accel-common.c          |   5 +
 accel/hvf/hvf-accel-ops.c     |  19 +---
 accel/hvf/hvf-all.c           | 186 ++++++++++------------------------
 target/arm/cpu.c              |  67 ++++++------
 target/arm/hvf/hvf.c          | 167 +++++++++++++++---------------
 target/i386/hvf/hvf.c         |  44 ++++----
 accel/hvf/trace-events        |   1 +
 9 files changed, 208 insertions(+), 304 deletions(-)

-- 
2.51.0



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

* [PATCH v5 01/19] accel/hvf: Create hvf_protect_clean_range, hvf_unprotect_dirty_range
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 02/19] target/i386/hvf: Use host page alignment in ept_emulation_fault() Philippe Mathieu-Daudé
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

From: Richard Henderson <richard.henderson@linaro.org>

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 include/system/hvf_int.h |  3 +++
 accel/hvf/hvf-all.c      | 25 +++++++++++++++++++++++++
 accel/hvf/trace-events   |  1 +
 3 files changed, 29 insertions(+)

diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h
index 3d2be4092ef..5a57691885f 100644
--- a/include/system/hvf_int.h
+++ b/include/system/hvf_int.h
@@ -89,6 +89,9 @@ int hvf_arch_get_registers(CPUState *);
 /* Must be called by the owning thread */
 void hvf_arch_update_guest_debug(CPUState *cpu);
 
+void hvf_protect_clean_range(hwaddr addr, size_t size);
+void hvf_unprotect_dirty_range(hwaddr addr, size_t size);
+
 struct hvf_sw_breakpoint {
     vaddr pc;
     vaddr saved_insn;
diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c
index 0a4b498e836..e13abddbd9c 100644
--- a/accel/hvf/hvf-all.c
+++ b/accel/hvf/hvf-all.c
@@ -58,6 +58,31 @@ void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line,
     abort();
 }
 
+static void do_hv_vm_protect(hwaddr start, size_t size,
+                             hv_memory_flags_t flags)
+{
+    hv_return_t ret;
+
+    trace_hvf_vm_protect(start, size, flags,
+                         flags & HV_MEMORY_READ  ? 'R' : '-',
+                         flags & HV_MEMORY_WRITE ? 'W' : '-',
+                         flags & HV_MEMORY_EXEC  ? 'X' : '-');
+
+    ret = hv_vm_protect(start, size, flags);
+    assert_hvf_ok(ret);
+}
+
+void hvf_protect_clean_range(hwaddr addr, size_t size)
+{
+    do_hv_vm_protect(addr, size, HV_MEMORY_READ | HV_MEMORY_EXEC);
+}
+
+void hvf_unprotect_dirty_range(hwaddr addr, size_t size)
+{
+    do_hv_vm_protect(addr, size,
+                     HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC);
+}
+
 static int do_hvf_set_memory(hvf_slot *slot, hv_memory_flags_t flags)
 {
     struct mac_slot *macslot;
diff --git a/accel/hvf/trace-events b/accel/hvf/trace-events
index 2fd3e127c74..f989da59492 100644
--- a/accel/hvf/trace-events
+++ b/accel/hvf/trace-events
@@ -5,3 +5,4 @@
 # hvf-accel-ops.c
 hvf_vm_map(uint64_t paddr, uint64_t size, void *vaddr, uint8_t flags, const char r, const char w, const char e) "paddr:0x%016"PRIx64" size:0x%08"PRIx64" vaddr:%p flags:0x%02x/%c%c%c"
 hvf_vm_unmap(uint64_t paddr, uint64_t size) "paddr:0x%016"PRIx64" size:0x%08"PRIx64
+hvf_vm_protect(uint64_t paddr, size_t size, uint8_t flags, const char r, const char w, const char e) "paddr:0x%016"PRIx64" size:0x%08zx flags:0x%02x/%c%c%c"
-- 
2.51.0



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

* [PATCH v5 02/19] target/i386/hvf: Use host page alignment in ept_emulation_fault()
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 01/19] accel/hvf: Create hvf_protect_clean_range, hvf_unprotect_dirty_range Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 03/19] accel/hvf: Enforce host alignment in hv_vm_protect() Philippe Mathieu-Daudé
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

While on x86 the host page size is fixed to 4KB, it is
better to call qemu_real_host_page_size() for consistency.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 target/i386/hvf/hvf.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index 16febbac48f..9a1bf026a4a 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -76,7 +76,7 @@
 #include "qemu/main-loop.h"
 #include "qemu/accel.h"
 #include "target/i386/cpu.h"
-#include "exec/target_page.h"
+#include "exec/cpu-common.h"
 
 static Error *invtsc_mig_blocker;
 
@@ -137,9 +137,12 @@ static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual)
 
     if (write && slot) {
         if (slot->flags & HVF_SLOT_LOG) {
-            uint64_t dirty_page_start = gpa & ~(TARGET_PAGE_SIZE - 1u);
+            uintptr_t page_size = qemu_real_host_page_size();
+            intptr_t page_mask = -(intptr_t)page_size;
+            uint64_t dirty_page_start = gpa & page_mask;
+
             memory_region_set_dirty(slot->region, gpa - slot->start, 1);
-            hv_vm_protect(dirty_page_start, TARGET_PAGE_SIZE,
+            hv_vm_protect(dirty_page_start, page_size,
                           HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC);
         }
     }
-- 
2.51.0



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

* [PATCH v5 03/19] accel/hvf: Enforce host alignment in hv_vm_protect()
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 01/19] accel/hvf: Create hvf_protect_clean_range, hvf_unprotect_dirty_range Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 02/19] target/i386/hvf: Use host page alignment in ept_emulation_fault() Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 04/19] target/i386/hvf: Use hvf_unprotect_dirty_range Philippe Mathieu-Daudé
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

hv_vm_protect() arguments must be aligned to host page.

Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 accel/hvf/hvf-all.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c
index e13abddbd9c..cb029e4dd4b 100644
--- a/accel/hvf/hvf-all.c
+++ b/accel/hvf/hvf-all.c
@@ -11,6 +11,7 @@
 #include "qemu/osdep.h"
 #include "qemu/error-report.h"
 #include "accel/accel-ops.h"
+#include "exec/cpu-common.h"
 #include "system/address-spaces.h"
 #include "system/memory.h"
 #include "system/hvf.h"
@@ -61,12 +62,15 @@ void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line,
 static void do_hv_vm_protect(hwaddr start, size_t size,
                              hv_memory_flags_t flags)
 {
+    intptr_t page_mask = qemu_real_host_page_mask();
     hv_return_t ret;
 
     trace_hvf_vm_protect(start, size, flags,
                          flags & HV_MEMORY_READ  ? 'R' : '-',
                          flags & HV_MEMORY_WRITE ? 'W' : '-',
                          flags & HV_MEMORY_EXEC  ? 'X' : '-');
+    g_assert(!((uintptr_t)start & ~page_mask));
+    g_assert(!(size & ~page_mask));
 
     ret = hv_vm_protect(start, size, flags);
     assert_hvf_ok(ret);
-- 
2.51.0



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

* [PATCH v5 04/19] target/i386/hvf: Use hvf_unprotect_dirty_range
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (2 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 03/19] accel/hvf: Enforce host alignment in hv_vm_protect() Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 05/19] target/i386/hvf: Use address_space_translate in ept_emulation_fault Philippe Mathieu-Daudé
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

From: Richard Henderson <richard.henderson@linaro.org>

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 target/i386/hvf/hvf.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index 9a1bf026a4a..de06ec6125f 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -142,8 +142,7 @@ static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual)
             uint64_t dirty_page_start = gpa & page_mask;
 
             memory_region_set_dirty(slot->region, gpa - slot->start, 1);
-            hv_vm_protect(dirty_page_start, page_size,
-                          HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC);
+            hvf_unprotect_dirty_range(dirty_page_start, page_size);
         }
     }
 
-- 
2.51.0



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

* [PATCH v5 05/19] target/i386/hvf: Use address_space_translate in ept_emulation_fault
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (3 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 04/19] target/i386/hvf: Use hvf_unprotect_dirty_range Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 06/19] accel/hvf: Simplify hvf_log_* Philippe Mathieu-Daudé
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

From: Richard Henderson <richard.henderson@linaro.org>

The hvf_slot structure is a poor replacement for properly
looking up a memory region in the address space.
Use memory_region_get_dirty_log_mask instead of HVF_SLOT_LOG.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 target/i386/hvf/hvf.c | 37 ++++++++++++++++++-------------------
 1 file changed, 18 insertions(+), 19 deletions(-)

diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index de06ec6125f..d0ee00425f0 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -119,9 +119,12 @@ void hvf_handle_io(CPUState *env, uint16_t port, void *buffer,
     }
 }
 
-static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual)
+static bool ept_emulation_fault(CPUState *cs, uint64_t gpa, uint64_t ept_qual)
 {
-    int read, write;
+    bool read, write;
+    MemoryRegion *mr;
+    hwaddr gpa_page = gpa & qemu_real_host_page_mask();
+    hwaddr xlat;
 
     /* EPT fault on an instruction fetch doesn't make sense here */
     if (ept_qual & EPT_VIOLATION_INST_FETCH) {
@@ -129,21 +132,22 @@ static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual)
     }
 
     /* EPT fault must be a read fault or a write fault */
-    read = ept_qual & EPT_VIOLATION_DATA_READ ? 1 : 0;
-    write = ept_qual & EPT_VIOLATION_DATA_WRITE ? 1 : 0;
-    if ((read | write) == 0) {
+    read = ept_qual & EPT_VIOLATION_DATA_READ;
+    write = ept_qual & EPT_VIOLATION_DATA_WRITE;
+    if (!read && !write) {
         return false;
     }
 
-    if (write && slot) {
-        if (slot->flags & HVF_SLOT_LOG) {
-            uintptr_t page_size = qemu_real_host_page_size();
-            intptr_t page_mask = -(intptr_t)page_size;
-            uint64_t dirty_page_start = gpa & page_mask;
+    mr = address_space_translate(cpu_get_address_space(cs, X86ASIdx_MEM),
+                                 gpa_page, &xlat, NULL, write,
+                                 MEMTXATTRS_UNSPECIFIED);
 
-            memory_region_set_dirty(slot->region, gpa - slot->start, 1);
-            hvf_unprotect_dirty_range(dirty_page_start, page_size);
-        }
+    /* Handle dirty page logging for ram. */
+    if (write && memory_region_get_dirty_log_mask(mr)) {
+        uintptr_t page_size = qemu_real_host_page_size();
+
+        memory_region_set_dirty(mr, gpa_page + xlat, page_size);
+        hvf_unprotect_dirty_range(gpa_page, page_size);
     }
 
     /*
@@ -156,9 +160,6 @@ static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual)
         return false;
     }
 
-    if (!slot) {
-        return true;
-    }
     if (!memory_region_is_ram(slot->region) &&
         !(read && memory_region_is_romd(slot->region))) {
         return true;
@@ -764,7 +765,6 @@ static int hvf_handle_vmexit(CPUState *cpu)
     /* Need to check if MMIO or unmapped fault */
     case EXIT_REASON_EPT_FAULT:
     {
-        hvf_slot *slot;
         uint64_t gpa = rvmcs(cpu->accel->fd, VMCS_GUEST_PHYSICAL_ADDRESS);
 
         if (((idtvec_info & VMCS_IDT_VEC_VALID) == 0) &&
@@ -772,9 +772,8 @@ static int hvf_handle_vmexit(CPUState *cpu)
             vmx_set_nmi_blocking(cpu);
         }
 
-        slot = hvf_find_overlap_slot(gpa, 1);
         /* mmio */
-        if (ept_emulation_fault(slot, gpa, exit_qual)) {
+        if (ept_emulation_fault(cpu, gpa, exit_qual)) {
             struct x86_decode decode;
 
             hvf_load_regs(cpu);
-- 
2.51.0



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

* [PATCH v5 06/19] accel/hvf: Simplify hvf_log_*
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (4 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 05/19] target/i386/hvf: Use address_space_translate in ept_emulation_fault Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 07/19] accel/hvf: Move hvf_log_sync to hvf_log_clear Philippe Mathieu-Daudé
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

From: Richard Henderson <richard.henderson@linaro.org>

Rely on the AddressSpace and MemoryRegion structures
rather than hvf_slot.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 include/system/hvf_int.h |  3 ---
 accel/hvf/hvf-all.c      | 40 ++++++++++------------------------------
 2 files changed, 10 insertions(+), 33 deletions(-)

diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h
index 5a57691885f..ee7ab689f45 100644
--- a/include/system/hvf_int.h
+++ b/include/system/hvf_int.h
@@ -24,9 +24,6 @@ typedef hv_vcpu_t hvf_vcpuid;
 typedef hv_vcpuid_t hvf_vcpuid;
 #endif
 
-/* hvf_slot flags */
-#define HVF_SLOT_LOG (1 << 0)
-
 typedef struct hvf_slot {
     uint64_t start;
     uint64_t size;
diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c
index cb029e4dd4b..601e63c7f9a 100644
--- a/accel/hvf/hvf-all.c
+++ b/accel/hvf/hvf-all.c
@@ -204,45 +204,24 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
     }
 }
 
-static void hvf_set_dirty_tracking(MemoryRegionSection *section, bool on)
-{
-    hvf_slot *slot;
-
-    slot = hvf_find_overlap_slot(
-            section->offset_within_address_space,
-            int128_get64(section->size));
-
-    /* protect region against writes; begin tracking it */
-    if (on) {
-        slot->flags |= HVF_SLOT_LOG;
-        hv_vm_protect((uintptr_t)slot->start, (size_t)slot->size,
-                      HV_MEMORY_READ | HV_MEMORY_EXEC);
-    /* stop tracking region*/
-    } else {
-        slot->flags &= ~HVF_SLOT_LOG;
-        hv_vm_protect((uintptr_t)slot->start, (size_t)slot->size,
-                      HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC);
-    }
-}
-
 static void hvf_log_start(MemoryListener *listener,
                           MemoryRegionSection *section, int old, int new)
 {
-    if (old != 0) {
-        return;
+    assert(new != 0);
+    if (old == 0) {
+        hvf_protect_clean_range(section->offset_within_address_space,
+                                int128_get64(section->size));
     }
-
-    hvf_set_dirty_tracking(section, 1);
 }
 
 static void hvf_log_stop(MemoryListener *listener,
                          MemoryRegionSection *section, int old, int new)
 {
-    if (new != 0) {
-        return;
+    assert(old != 0);
+    if (new == 0) {
+        hvf_unprotect_dirty_range(section->offset_within_address_space,
+                                  int128_get64(section->size));
     }
-
-    hvf_set_dirty_tracking(section, 0);
 }
 
 static void hvf_log_sync(MemoryListener *listener,
@@ -252,7 +231,8 @@ static void hvf_log_sync(MemoryListener *listener,
      * sync of dirty pages is handled elsewhere; just make sure we keep
      * tracking the region.
      */
-    hvf_set_dirty_tracking(section, 1);
+    hvf_protect_clean_range(section->offset_within_address_space,
+                            int128_get64(section->size));
 }
 
 static void hvf_region_add(MemoryListener *listener,
-- 
2.51.0



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

* [PATCH v5 07/19] accel/hvf: Move hvf_log_sync to hvf_log_clear
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (5 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 06/19] accel/hvf: Simplify hvf_log_* Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 08/19] accel/hvf: Simplify hvf_set_phys_mem Philippe Mathieu-Daudé
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

From: Richard Henderson <richard.henderson@linaro.org>

Right idea, wrong hook.  log_sync is called before using
dirty bit data (which for hvf is already up-to-date),
whereas log_clear is called before cleaning the range.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 accel/hvf/hvf-all.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c
index 601e63c7f9a..f203a6251f0 100644
--- a/accel/hvf/hvf-all.c
+++ b/accel/hvf/hvf-all.c
@@ -224,12 +224,13 @@ static void hvf_log_stop(MemoryListener *listener,
     }
 }
 
-static void hvf_log_sync(MemoryListener *listener,
-                         MemoryRegionSection *section)
+static void hvf_log_clear(MemoryListener *listener,
+                          MemoryRegionSection *section)
 {
     /*
-     * sync of dirty pages is handled elsewhere; just make sure we keep
-     * tracking the region.
+     * The dirty page bits within section are being cleared.
+     * Some number of those pages may have been dirtied and
+     * the write permission enabled.  Reset the range read-only.
      */
     hvf_protect_clean_range(section->offset_within_address_space,
                             int128_get64(section->size));
@@ -254,7 +255,7 @@ static MemoryListener hvf_memory_listener = {
     .region_del = hvf_region_del,
     .log_start = hvf_log_start,
     .log_stop = hvf_log_stop,
-    .log_sync = hvf_log_sync,
+    .log_clear = hvf_log_clear,
 };
 
 static int hvf_accel_init(AccelState *as, MachineState *ms)
-- 
2.51.0



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

* [PATCH v5 08/19] accel/hvf: Simplify hvf_set_phys_mem
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (6 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 07/19] accel/hvf: Move hvf_log_sync to hvf_log_clear Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 09/19] accel/hvf: Drop hvf_slot and hvf_find_overlap_slot Philippe Mathieu-Daudé
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

From: Richard Henderson <richard.henderson@linaro.org>

All of the complicated parts of updating the address space
are handled by address_space_update_topology_pass.
Do not create or use hvf_slot structures.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
v5: s/gva/gpa/ (Akihiko)
---
 accel/hvf/hvf-all.c | 111 +++++++-------------------------------------
 1 file changed, 17 insertions(+), 94 deletions(-)

diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c
index f203a6251f0..5781b17fa4e 100644
--- a/accel/hvf/hvf-all.c
+++ b/accel/hvf/hvf-all.c
@@ -87,45 +87,16 @@ void hvf_unprotect_dirty_range(hwaddr addr, size_t size)
                      HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC);
 }
 
-static int do_hvf_set_memory(hvf_slot *slot, hv_memory_flags_t flags)
-{
-    struct mac_slot *macslot;
-    hv_return_t ret;
-
-    macslot = &mac_slots[slot->slot_id];
-
-    if (macslot->present) {
-        if (macslot->size != slot->size) {
-            macslot->present = 0;
-            trace_hvf_vm_unmap(macslot->gpa_start, macslot->size);
-            ret = hv_vm_unmap(macslot->gpa_start, macslot->size);
-            assert_hvf_ok(ret);
-        }
-    }
-
-    if (!slot->size) {
-        return 0;
-    }
-
-    macslot->present = 1;
-    macslot->gpa_start = slot->start;
-    macslot->size = slot->size;
-    trace_hvf_vm_map(slot->start, slot->size, slot->mem, flags,
-                     flags & HV_MEMORY_READ ?  'R' : '-',
-                     flags & HV_MEMORY_WRITE ? 'W' : '-',
-                     flags & HV_MEMORY_EXEC ?  'X' : '-');
-    ret = hv_vm_map(slot->mem, slot->start, slot->size, flags);
-    assert_hvf_ok(ret);
-    return 0;
-}
-
 static void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
 {
-    hvf_slot *mem;
     MemoryRegion *area = section->mr;
     bool writable = !area->readonly && !area->rom_device;
     hv_memory_flags_t flags;
     uint64_t page_size = qemu_real_host_page_size();
+    uint64_t gpa = section->offset_within_address_space;
+    uint64_t size = int128_get64(section->size);
+    hv_return_t ret;
+    void *mem;
 
     if (!memory_region_is_ram(area)) {
         if (writable) {
@@ -139,69 +110,28 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
         }
     }
 
-    if (!QEMU_IS_ALIGNED(int128_get64(section->size), page_size) ||
-        !QEMU_IS_ALIGNED(section->offset_within_address_space, page_size)) {
+    if (!QEMU_IS_ALIGNED(size, page_size) ||
+        !QEMU_IS_ALIGNED(gpa, page_size)) {
         /* Not page aligned, so we can not map as RAM */
         add = false;
     }
 
-    mem = hvf_find_overlap_slot(
-            section->offset_within_address_space,
-            int128_get64(section->size));
-
-    if (mem && add) {
-        if (mem->size == int128_get64(section->size) &&
-            mem->start == section->offset_within_address_space &&
-            mem->mem == (memory_region_get_ram_ptr(area) +
-            section->offset_within_region)) {
-            return; /* Same region was attempted to register, go away. */
-        }
-    }
-
-    /* Region needs to be reset. set the size to 0 and remap it. */
-    if (mem) {
-        mem->size = 0;
-        if (do_hvf_set_memory(mem, 0)) {
-            error_report("Failed to reset overlapping slot");
-            abort();
-        }
-    }
-
     if (!add) {
+        trace_hvf_vm_unmap(gpa, size);
+        ret = hv_vm_unmap(gpa, size);
+        assert_hvf_ok(ret);
         return;
     }
 
-    if (area->readonly ||
-        (!memory_region_is_ram(area) && memory_region_is_romd(area))) {
-        flags = HV_MEMORY_READ | HV_MEMORY_EXEC;
-    } else {
-        flags = HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC;
-    }
+    flags = HV_MEMORY_READ | HV_MEMORY_EXEC | (writable ? HV_MEMORY_WRITE : 0);
+    mem = memory_region_get_ram_ptr(area) + section->offset_within_region;
 
-    /* Now make a new slot. */
-    int x;
-
-    for (x = 0; x < hvf_state->num_slots; ++x) {
-        mem = &hvf_state->slots[x];
-        if (!mem->size) {
-            break;
-        }
-    }
-
-    if (x == hvf_state->num_slots) {
-        error_report("No free slots");
-        abort();
-    }
-
-    mem->size = int128_get64(section->size);
-    mem->mem = memory_region_get_ram_ptr(area) + section->offset_within_region;
-    mem->start = section->offset_within_address_space;
-    mem->region = area;
-
-    if (do_hvf_set_memory(mem, flags)) {
-        error_report("Error registering new memory slot");
-        abort();
-    }
+    trace_hvf_vm_map(gpa, size, mem, flags,
+                     flags & HV_MEMORY_READ ?  'R' : '-',
+                     flags & HV_MEMORY_WRITE ? 'W' : '-',
+                     flags & HV_MEMORY_EXEC ?  'X' : '-');
+    ret = hv_vm_map(mem, gpa, size, flags);
+    assert_hvf_ok(ret);
 }
 
 static void hvf_log_start(MemoryListener *listener,
@@ -260,7 +190,6 @@ static MemoryListener hvf_memory_listener = {
 
 static int hvf_accel_init(AccelState *as, MachineState *ms)
 {
-    int x;
     hv_return_t ret;
     HVFState *s = HVF_STATE(as);
     int pa_range = 36;
@@ -281,12 +210,6 @@ static int hvf_accel_init(AccelState *as, MachineState *ms)
     }
     assert_hvf_ok(ret);
 
-    s->num_slots = ARRAY_SIZE(s->slots);
-    for (x = 0; x < s->num_slots; ++x) {
-        s->slots[x].size = 0;
-        s->slots[x].slot_id = x;
-    }
-
     QTAILQ_INIT(&s->hvf_sw_breakpoints);
 
     hvf_state = s;
-- 
2.51.0



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

* [PATCH v5 09/19] accel/hvf: Drop hvf_slot and hvf_find_overlap_slot
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (7 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 08/19] accel/hvf: Simplify hvf_set_phys_mem Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 10/19] accel/hvf: Remove mac_slots Philippe Mathieu-Daudé
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

From: Richard Henderson <richard.henderson@linaro.org>

These are now unused.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 include/system/hvf_int.h  | 13 -------------
 accel/hvf/hvf-accel-ops.c | 14 --------------
 2 files changed, 27 deletions(-)

diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h
index ee7ab689f45..d842d4b2b99 100644
--- a/include/system/hvf_int.h
+++ b/include/system/hvf_int.h
@@ -24,15 +24,6 @@ typedef hv_vcpu_t hvf_vcpuid;
 typedef hv_vcpuid_t hvf_vcpuid;
 #endif
 
-typedef struct hvf_slot {
-    uint64_t start;
-    uint64_t size;
-    uint8_t *mem;
-    int slot_id;
-    uint32_t flags;
-    MemoryRegion *region;
-} hvf_slot;
-
 typedef struct hvf_vcpu_caps {
     uint64_t vmx_cap_pinbased;
     uint64_t vmx_cap_procbased;
@@ -45,9 +36,6 @@ typedef struct hvf_vcpu_caps {
 struct HVFState {
     AccelState parent_obj;
 
-    hvf_slot slots[32];
-    int num_slots;
-
     hvf_vcpu_caps *hvf_caps;
     uint64_t vtimer_offset;
     QTAILQ_HEAD(, hvf_sw_breakpoint) hvf_sw_breakpoints;
@@ -70,7 +58,6 @@ void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line,
 const char *hvf_return_string(hv_return_t ret);
 int hvf_arch_init(void);
 hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range);
-hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t);
 void hvf_kick_vcpu_thread(CPUState *cpu);
 
 /* Must be called by the owning thread */
diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c
index 3e5feecd8a7..bbb0b385fe9 100644
--- a/accel/hvf/hvf-accel-ops.c
+++ b/accel/hvf/hvf-accel-ops.c
@@ -64,20 +64,6 @@ HVFState *hvf_state;
 
 /* Memory slots */
 
-hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t size)
-{
-    hvf_slot *slot;
-    int x;
-    for (x = 0; x < hvf_state->num_slots; ++x) {
-        slot = &hvf_state->slots[x];
-        if (slot->size && start < (slot->start + slot->size) &&
-            (start + size) > slot->start) {
-            return slot;
-        }
-    }
-    return NULL;
-}
-
 static void do_hvf_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
 {
     if (!cpu->vcpu_dirty) {
-- 
2.51.0



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

* [PATCH v5 10/19] accel/hvf: Remove mac_slots
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (8 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 09/19] accel/hvf: Drop hvf_slot and hvf_find_overlap_slot Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 11/19] target/arm/hvf: Implement dirty page tracking Philippe Mathieu-Daudé
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

From: Richard Henderson <richard.henderson@linaro.org>

This data structure is no longer used.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 accel/hvf/hvf-all.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c
index 5781b17fa4e..ed28e073643 100644
--- a/accel/hvf/hvf-all.c
+++ b/accel/hvf/hvf-all.c
@@ -22,15 +22,6 @@
 
 bool hvf_allowed;
 
-struct mac_slot {
-    int present;
-    uint64_t size;
-    uint64_t gpa_start;
-    uint64_t gva;
-};
-
-struct mac_slot mac_slots[32];
-
 const char *hvf_return_string(hv_return_t ret)
 {
     switch (ret) {
-- 
2.51.0



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

* [PATCH v5 11/19] target/arm/hvf: Implement dirty page tracking
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (9 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 10/19] accel/hvf: Remove mac_slots Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 12/19] accel/hvf: Skip WFI if CPU has work to do Philippe Mathieu-Daudé
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

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>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@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 de1e8fb8a05..0f584b8137a 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -1869,9 +1869,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) {
@@ -1880,23 +1881,56 @@ 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)) {
+                uintptr_t page_size = qemu_real_host_page_size();
+                intptr_t page_mask = -(intptr_t)page_size;
+                uint64_t ipa_page = ipa & 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, page_size);
+                    hvf_unprotect_dirty_range(ipa_page, 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



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

* [PATCH v5 12/19] accel/hvf: Skip WFI if CPU has work to do
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (10 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 11/19] target/arm/hvf: Implement dirty page tracking Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 13/19] accel/hvf: Implement WFI without using pselect() Philippe Mathieu-Daudé
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal,
	Alex Bennée

Avoid sleeping vCPU thread for any pending work, not just IRQs.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/hvf/hvf.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index 0f584b8137a..5e46e8bf4dd 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -1737,8 +1737,11 @@ static void hvf_wfi(CPUState *cpu)
     uint64_t nanos;
     uint32_t cntfrq;
 
-    if (cpu_test_interrupt(cpu, CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIQ)) {
-        /* Interrupt pending, no need to wait */
+    if (cpu_has_work(cpu)) {
+        /*
+         * Don't bother to go into our "low power state" if
+         * we would just wake up immediately.
+         */
         return;
     }
 
-- 
2.51.0



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

* [PATCH v5 13/19] accel/hvf: Implement WFI without using pselect()
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (11 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 12/19] accel/hvf: Skip WFI if CPU has work to do Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 14/19] accel/hvf: Have PSCI CPU_SUSPEND halt the vCPU Philippe Mathieu-Daudé
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

Return to the main loop where we'll be waken again.
This avoid a tricky race with signals introduced in
commit 219c101fa7f ("Add HVF WFI handler").

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
---
 include/system/hvf_int.h  |  1 -
 accel/hvf/hvf-accel-ops.c |  3 --
 target/arm/hvf/hvf.c      | 74 +++------------------------------------
 3 files changed, 5 insertions(+), 73 deletions(-)

diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h
index d842d4b2b99..c8e407a1463 100644
--- a/include/system/hvf_int.h
+++ b/include/system/hvf_int.h
@@ -47,7 +47,6 @@ struct AccelCPUState {
 #ifdef __aarch64__
     hv_vcpu_exit_t *exit;
     bool vtimer_masked;
-    sigset_t unblock_ipi_mask;
     bool guest_debug_enabled;
 #endif
 };
diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c
index bbb0b385fe9..5922eb02e70 100644
--- a/accel/hvf/hvf-accel-ops.c
+++ b/accel/hvf/hvf-accel-ops.c
@@ -134,9 +134,6 @@ static int hvf_init_vcpu(CPUState *cpu)
     sigact.sa_handler = dummy_signal;
     sigaction(SIG_IPI, &sigact, NULL);
 
-    pthread_sigmask(SIG_BLOCK, NULL, &cpu->accel->unblock_ipi_mask);
-    sigdelset(&cpu->accel->unblock_ipi_mask, SIG_IPI);
-
 #ifdef __aarch64__
     r = hv_vcpu_create(&cpu->accel->fd,
                        (hv_vcpu_exit_t **)&cpu->accel->exit, NULL);
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index 5e46e8bf4dd..51fd8c7175b 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -301,7 +301,7 @@ void hvf_arm_init_debug(void)
 #define TMR_CTL_IMASK   (1 << 1)
 #define TMR_CTL_ISTATUS (1 << 2)
 
-static void hvf_wfi(CPUState *cpu);
+static int hvf_wfi(CPUState *cpu);
 
 static uint32_t chosen_ipa_bit_size;
 
@@ -1703,81 +1703,17 @@ static uint64_t hvf_vtimer_val_raw(void)
     return mach_absolute_time() - hvf_state->vtimer_offset;
 }
 
-static uint64_t hvf_vtimer_val(void)
+static int hvf_wfi(CPUState *cpu)
 {
-    if (!runstate_is_running()) {
-        /* VM is paused, the vtimer value is in vtimer.vtimer_val */
-        return vtimer.vtimer_val;
-    }
-
-    return hvf_vtimer_val_raw();
-}
-
-static void hvf_wait_for_ipi(CPUState *cpu, struct timespec *ts)
-{
-    /*
-     * Use pselect to sleep so that other threads can IPI us while we're
-     * sleeping.
-     */
-    qatomic_set_mb(&cpu->thread_kicked, false);
-    bql_unlock();
-    pselect(0, 0, 0, 0, ts, &cpu->accel->unblock_ipi_mask);
-    bql_lock();
-}
-
-static void hvf_wfi(CPUState *cpu)
-{
-    ARMCPU *arm_cpu = ARM_CPU(cpu);
-    struct timespec ts;
-    hv_return_t r;
-    uint64_t ctl;
-    uint64_t cval;
-    int64_t ticks_to_sleep;
-    uint64_t seconds;
-    uint64_t nanos;
-    uint32_t cntfrq;
-
     if (cpu_has_work(cpu)) {
         /*
          * Don't bother to go into our "low power state" if
          * we would just wake up immediately.
          */
-        return;
+        return 0;
     }
 
-    r = hv_vcpu_get_sys_reg(cpu->accel->fd, HV_SYS_REG_CNTV_CTL_EL0, &ctl);
-    assert_hvf_ok(r);
-
-    if (!(ctl & 1) || (ctl & 2)) {
-        /* Timer disabled or masked, just wait for an IPI. */
-        hvf_wait_for_ipi(cpu, NULL);
-        return;
-    }
-
-    r = hv_vcpu_get_sys_reg(cpu->accel->fd, HV_SYS_REG_CNTV_CVAL_EL0, &cval);
-    assert_hvf_ok(r);
-
-    ticks_to_sleep = cval - hvf_vtimer_val();
-    if (ticks_to_sleep < 0) {
-        return;
-    }
-
-    cntfrq = gt_cntfrq_period_ns(arm_cpu);
-    seconds = muldiv64(ticks_to_sleep, cntfrq, NANOSECONDS_PER_SECOND);
-    ticks_to_sleep -= muldiv64(seconds, NANOSECONDS_PER_SECOND, cntfrq);
-    nanos = ticks_to_sleep * cntfrq;
-
-    /*
-     * Don't sleep for less than the time a context switch would take,
-     * so that we can satisfy fast timer requests on the same CPU.
-     * Measurements on M1 show the sweet spot to be ~2ms.
-     */
-    if (!seconds && nanos < (2 * SCALE_MS)) {
-        return;
-    }
-
-    ts = (struct timespec) { seconds, nanos };
-    hvf_wait_for_ipi(cpu, &ts);
+    return EXCP_HLT;
 }
 
 /* Must be called by the owning thread */
@@ -1967,7 +1903,7 @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp)
     case EC_WFX_TRAP:
         advance_pc = true;
         if (!(syndrome & WFX_IS_WFE)) {
-            hvf_wfi(cpu);
+            ret = hvf_wfi(cpu);
         }
         break;
     case EC_AA64_HVC:
-- 
2.51.0



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

* [PATCH v5 14/19] accel/hvf: Have PSCI CPU_SUSPEND halt the vCPU
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (12 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 13/19] accel/hvf: Implement WFI without using pselect() Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 15/19] accel: Introduce AccelOpsClass::cpu_target_realize() hook Philippe Mathieu-Daudé
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

Return EXCP_HLT to the main loop.

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

diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index 51fd8c7175b..59a2ef53629 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -301,8 +301,6 @@ void hvf_arm_init_debug(void)
 #define TMR_CTL_IMASK   (1 << 1)
 #define TMR_CTL_ISTATUS (1 << 2)
 
-static int hvf_wfi(CPUState *cpu);
-
 static uint32_t chosen_ipa_bit_size;
 
 typedef struct HVFVTimer {
@@ -1008,7 +1006,7 @@ static void hvf_psci_cpu_off(ARMCPU *arm_cpu)
  * Returns 0 on success
  *         -1 when the PSCI call is unknown,
  */
-static bool hvf_handle_psci_call(CPUState *cpu)
+static bool hvf_handle_psci_call(CPUState *cpu, int *excp_ret)
 {
     ARMCPU *arm_cpu = ARM_CPU(cpu);
     CPUARMState *env = &arm_cpu->env;
@@ -1091,9 +1089,8 @@ static bool hvf_handle_psci_call(CPUState *cpu)
             ret = QEMU_PSCI_RET_INVALID_PARAMS;
             break;
         }
-        /* Powerdown is not supported, we always go into WFI */
         env->xregs[0] = 0;
-        hvf_wfi(cpu);
+        *excp_ret = EXCP_HLT;
         break;
     case QEMU_PSCI_0_1_FN_MIGRATE:
     case QEMU_PSCI_0_2_FN_MIGRATE:
@@ -1910,7 +1907,7 @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp)
         cpu_synchronize_state(cpu);
         if (arm_is_psci_call(arm_cpu, EXCP_HVC)) {
             /* Do NOT advance $pc for HVC */
-            if (!hvf_handle_psci_call(cpu)) {
+            if (!hvf_handle_psci_call(cpu, &ret)) {
                 trace_hvf_unknown_hvc(env->pc, env->xregs[0]);
                 /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */
                 env->xregs[0] = -1;
@@ -1926,7 +1923,7 @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp)
             /* Secure Monitor Call exception, we need to advance $pc */
             advance_pc = true;
 
-            if (!hvf_handle_psci_call(cpu)) {
+            if (!hvf_handle_psci_call(cpu, &ret)) {
                 trace_hvf_unknown_smc(env->xregs[0]);
                 /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */
                 env->xregs[0] = -1;
-- 
2.51.0



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

* [PATCH v5 15/19] accel: Introduce AccelOpsClass::cpu_target_realize() hook
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (13 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 14/19] accel/hvf: Have PSCI CPU_SUSPEND halt the vCPU Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 16/19] accel/hvf: Add hvf_arch_cpu_realize() stubs Philippe Mathieu-Daudé
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

Allow accelerators to set vCPU properties before its realization.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/accel/accel-cpu-ops.h | 1 +
 accel/accel-common.c          | 5 +++++
 2 files changed, 6 insertions(+)

diff --git a/include/accel/accel-cpu-ops.h b/include/accel/accel-cpu-ops.h
index 0674764914f..9c07a903ea0 100644
--- a/include/accel/accel-cpu-ops.h
+++ b/include/accel/accel-cpu-ops.h
@@ -34,6 +34,7 @@ struct AccelOpsClass {
     /* initialization function called when accel is chosen */
     void (*ops_init)(AccelClass *ac);
 
+    bool (*cpu_target_realize)(CPUState *cpu, Error **errp);
     bool (*cpus_are_resettable)(void);
     void (*cpu_reset_hold)(CPUState *cpu);
 
diff --git a/accel/accel-common.c b/accel/accel-common.c
index 850c5ab4b8e..eecb2a292af 100644
--- a/accel/accel-common.c
+++ b/accel/accel-common.c
@@ -106,6 +106,11 @@ bool accel_cpu_common_realize(CPUState *cpu, Error **errp)
     if (acc->cpu_common_realize && !acc->cpu_common_realize(cpu, errp)) {
         return false;
     }
+    if (acc->ops
+        && acc->ops->cpu_target_realize
+        && !acc->ops->cpu_target_realize(cpu, errp)) {
+        return false;
+    }
 
     return true;
 }
-- 
2.51.0



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

* [PATCH v5 16/19] accel/hvf: Add hvf_arch_cpu_realize() stubs
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (14 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 15/19] accel: Introduce AccelOpsClass::cpu_target_realize() hook Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 17/19] target/arm: Create GTimers *after* features finalized / accel realized Philippe Mathieu-Daudé
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

Implement HVF AccelOpsClass::cpu_target_realize() hook as
empty stubs. Target implementations will come separately.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/system/hvf_int.h  | 2 ++
 accel/hvf/hvf-accel-ops.c | 2 ++
 target/arm/hvf/hvf.c      | 5 +++++
 target/i386/hvf/hvf.c     | 5 +++++
 4 files changed, 14 insertions(+)

diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h
index c8e407a1463..96790b49386 100644
--- a/include/system/hvf_int.h
+++ b/include/system/hvf_int.h
@@ -106,4 +106,6 @@ int hvf_update_guest_debug(CPUState *cpu);
  */
 bool hvf_arch_supports_guest_debug(void);
 
+bool hvf_arch_cpu_realize(CPUState *cpu, Error **errp);
+
 #endif
diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c
index 5922eb02e70..02c5d01670d 100644
--- a/accel/hvf/hvf-accel-ops.c
+++ b/accel/hvf/hvf-accel-ops.c
@@ -356,6 +356,8 @@ static void hvf_accel_ops_class_init(ObjectClass *oc, const void *data)
 {
     AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
 
+    ops->cpu_target_realize = hvf_arch_cpu_realize;
+
     ops->create_vcpu_thread = hvf_start_vcpu_thread;
     ops->kick_vcpu_thread = hvf_kick_vcpu_thread;
     ops->handle_interrupt = generic_handle_interrupt;
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index 59a2ef53629..8208d345daa 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -972,6 +972,11 @@ int hvf_arch_init_vcpu(CPUState *cpu)
     return 0;
 }
 
+bool hvf_arch_cpu_realize(CPUState *cs, Error **errp)
+{
+    return true;
+}
+
 void hvf_kick_vcpu_thread(CPUState *cpu)
 {
     hv_return_t ret;
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index d0ee00425f0..1b189efb4c7 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -370,6 +370,11 @@ int hvf_arch_init_vcpu(CPUState *cpu)
     return 0;
 }
 
+bool hvf_arch_cpu_realize(CPUState *cs, Error **errp)
+{
+    return true;
+}
+
 static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_info)
 {
     X86CPU *x86_cpu = X86_CPU(cpu);
-- 
2.51.0



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

* [PATCH v5 17/19] target/arm: Create GTimers *after* features finalized / accel realized
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (15 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 16/19] accel/hvf: Add hvf_arch_cpu_realize() stubs Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 18/19] target/arm/hvf: Really set Generic Timer counter frequency Philippe Mathieu-Daudé
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

Call generic (including accelerator) cpu_realize() handlers
*before* setting @gt_cntfrq_hz default

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/cpu.c | 65 ++++++++++++++++++++++++------------------------
 1 file changed, 33 insertions(+), 32 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 39292fb9bc1..b392374df98 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1636,26 +1636,6 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         return;
     }
 
-    if (!cpu->gt_cntfrq_hz) {
-        /*
-         * 0 means "the board didn't set a value, use the default". (We also
-         * get here for the CONFIG_USER_ONLY case.)
-         * ARMv8.6 and later CPUs architecturally must use a 1GHz timer; before
-         * that it was an IMPDEF choice, and QEMU initially picked 62.5MHz,
-         * which gives a 16ns tick period.
-         *
-         * We will use the back-compat value:
-         *  - for QEMU CPU types added before we standardized on 1GHz
-         *  - for versioned machine types with a version of 9.0 or earlier
-         */
-        if (arm_feature(env, ARM_FEATURE_BACKCOMPAT_CNTFRQ) ||
-            cpu->backcompat_cntfrq) {
-            cpu->gt_cntfrq_hz = GTIMER_BACKCOMPAT_HZ;
-        } else {
-            cpu->gt_cntfrq_hz = GTIMER_DEFAULT_HZ;
-        }
-    }
-
 #ifndef CONFIG_USER_ONLY
     /* The NVIC and M-profile CPU are two halves of a single piece of
      * hardware; trying to use one without the other is a command line
@@ -1702,7 +1682,40 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
             return;
         }
     }
+#endif
 
+    cpu_exec_realizefn(cs, &local_err);
+    if (local_err != NULL) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    arm_cpu_finalize_features(cpu, &local_err);
+    if (local_err != NULL) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (!cpu->gt_cntfrq_hz) {
+        /*
+         * 0 means "the board didn't set a value, use the default". (We also
+         * get here for the CONFIG_USER_ONLY case.)
+         * ARMv8.6 and later CPUs architecturally must use a 1GHz timer; before
+         * that it was an IMPDEF choice, and QEMU initially picked 62.5MHz,
+         * which gives a 16ns tick period.
+         *
+         * We will use the back-compat value:
+         *  - for QEMU CPU types added before we standardized on 1GHz
+         *  - for versioned machine types with a version of 9.0 or earlier
+         */
+        if (arm_feature(env, ARM_FEATURE_BACKCOMPAT_CNTFRQ) ||
+            cpu->backcompat_cntfrq) {
+            cpu->gt_cntfrq_hz = GTIMER_BACKCOMPAT_HZ;
+        } else {
+            cpu->gt_cntfrq_hz = GTIMER_DEFAULT_HZ;
+        }
+    }
+#ifndef CONFIG_USER_ONLY
     {
         uint64_t scale = gt_cntfrq_period_ns(cpu);
 
@@ -1723,18 +1736,6 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
     }
 #endif
 
-    cpu_exec_realizefn(cs, &local_err);
-    if (local_err != NULL) {
-        error_propagate(errp, local_err);
-        return;
-    }
-
-    arm_cpu_finalize_features(cpu, &local_err);
-    if (local_err != NULL) {
-        error_propagate(errp, local_err);
-        return;
-    }
-
 #ifdef CONFIG_USER_ONLY
     /*
      * User mode relies on IC IVAU instructions to catch modification of
-- 
2.51.0



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

* [PATCH v5 18/19] target/arm/hvf: Really set Generic Timer counter frequency
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (16 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 17/19] target/arm: Create GTimers *after* features finalized / accel realized Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-14 20:04 ` [PATCH v5 19/19] target/arm: Only allow disabling NEON when using TCG Philippe Mathieu-Daudé
  2025-11-15  2:22 ` [PATCH v5 00/19] target/arm/hvf: Consolidate Akihiko Odaki
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

Setting ARMCPU::gt_cntfrq_hz in hvf_arch_init_vcpu() is
not correct because the timers have already be initialized
with the default frequency.

Set it earlier in the AccelOpsClass::cpu_target_realize()
handler instead, and assert the value is correct when
reaching hvf_arch_init_vcpu().

Fixes: a1477da3dde ("hvf: Add Apple Silicon support")
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/hvf/hvf.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index 8208d345daa..e1113e3d6ca 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -897,6 +897,13 @@ cleanup:
     return ret;
 }
 
+static uint64_t get_cntfrq_el0(void)
+{
+    uint64_t freq_hz = 0;
+    asm volatile("mrs %0, cntfrq_el0" : "=r"(freq_hz));
+    return freq_hz;
+}
+
 int hvf_arch_init_vcpu(CPUState *cpu)
 {
     ARMCPU *arm_cpu = ARM_CPU(cpu);
@@ -908,7 +915,9 @@ int hvf_arch_init_vcpu(CPUState *cpu)
     int i;
 
     env->aarch64 = true;
-    asm volatile("mrs %0, cntfrq_el0" : "=r"(arm_cpu->gt_cntfrq_hz));
+
+    /* system count frequency sanity check */
+    assert(arm_cpu->gt_cntfrq_hz == get_cntfrq_el0());
 
     /* Allocate enough space for our sysreg sync */
     arm_cpu->cpreg_indexes = g_renew(uint64_t, arm_cpu->cpreg_indexes,
@@ -974,6 +983,15 @@ int hvf_arch_init_vcpu(CPUState *cpu)
 
 bool hvf_arch_cpu_realize(CPUState *cs, Error **errp)
 {
+    ARMCPU *cpu = ARM_CPU(cs);
+
+    /*
+     * We must set the counter frequency HVF will be using
+     * early, before arm_cpu_realizefn initializes the timers
+     * with it.
+     */
+    cpu->gt_cntfrq_hz = get_cntfrq_el0();
+
     return true;
 }
 
-- 
2.51.0



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

* [PATCH v5 19/19] target/arm: Only allow disabling NEON when using TCG
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (17 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 18/19] target/arm/hvf: Really set Generic Timer counter frequency Philippe Mathieu-Daudé
@ 2025-11-14 20:04 ` Philippe Mathieu-Daudé
  2025-11-15  2:22 ` [PATCH v5 00/19] target/arm/hvf: Consolidate Akihiko Odaki
  19 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-14 20:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Akihiko Odaki,
	Philippe Mathieu-Daudé, Roman Bolshakov, Mads Ynddal

Only allow disabling NEON when using TCG.

This avoids confusing user experience:

  $ qemu-system-aarch64 -M virt -accel hvf \
                        -cpu host,neon=off,vfp=off,vfp-d32=off
  qemu-system-aarch64: AArch64 CPUs must have both VFP and Neon or neither

  $ qemu-system-aarch64 -M virt -accel hvf \
                        -cpu host,neon=off,vfp=off,vfp-d32=off
  qemu-system-aarch64: ARM CPUs must have both VFP-D32 and Neon or neither

  $ qemu-system-aarch64 -M virt -accel hvf \
                        -cpu host,neon=off,vfp=off,vfp-d32=off
  qemu-system-aarch64: can't apply global host-arm-cpu.vfp-d32=off: Property 'host-arm-cpu.vfp-d32' not found

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index b392374df98..eaf76532eca 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1460,7 +1460,7 @@ static void arm_cpu_post_init(Object *obj)
 
     if (arm_feature(&cpu->env, ARM_FEATURE_NEON)) {
         cpu->has_neon = true;
-        if (!kvm_enabled()) {
+        if (tcg_enabled() || qtest_enabled()) {
             qdev_property_add_static(DEVICE(obj), &arm_cpu_has_neon_property);
         }
     }
-- 
2.51.0



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

* Re: [PATCH v5 00/19] target/arm/hvf: Consolidate
  2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
                   ` (18 preceding siblings ...)
  2025-11-14 20:04 ` [PATCH v5 19/19] target/arm: Only allow disabling NEON when using TCG Philippe Mathieu-Daudé
@ 2025-11-15  2:22 ` Akihiko Odaki
  2025-11-17  9:25   ` Philippe Mathieu-Daudé
  19 siblings, 1 reply; 22+ messages in thread
From: Akihiko Odaki @ 2025-11-15  2:22 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Roman Bolshakov, Mads Ynddal

On 2025/11/15 5:04, Philippe Mathieu-Daudé wrote:
> Missing review: #8
> 
> - Patches 1-11 fix migration on HVF
> - Patches 12-14 remove a signal race with WFI
> - Patches 15-18 correct guest timer frequency
> 
> Since v4:
> - Rename gva -> gpa in hvf_set_phys_mem (Akihiko)
> - Dropped missing VTimer synchronization patches for 10.2
> 
> Since v3:
> - Call qemu_real_host_page_mask/size once (rth)
> 
> Since v2:
> - Improve host page size/mask uses (rth)
> - Remove cpu_test_interrupt in hvf_wfi (rth)
> 
> Since v1:
> - Addressed Mads & Richard comments
> - Fixed migration by reworking memory listeners
>    (unfortunately the current broken code has been
>     used as base for WHPX)
> - Sync CNTV_CTL/CVAL_EL0
> - Remove WFI racy signal implementation
> - Simplify PSCI Suspend (I expect the same can be
>    done for the other hvf_psci_cpu_off() calls).
> - Emulate more missing registers (PMU & Monitor Dbg)
> 
>  From v1:
> - Fix a pair of memory leak
> - Check a pair of return values
> - Mention calls which must be run on vCPU thread
> - Force MIDR
> - Use hv_vcpu_config_create/hv_vcpu_config_get_feature_reg
>    when not running on vCPU thread
> - Factor hvf_handle_vmexit() / hvf_handle_exception(() out
> - Call hv_vcpu_run() in loop
> - Guard hv_vcpu_run() between cpu_exec_start/end()
> - Restrict ARM specific in AccelCPUState
> 
> Based-on: <20250829152909.1589668-14-pbonzini@redhat.com>
> 
> Philippe Mathieu-Daudé (10):
>    target/i386/hvf: Use host page alignment in ept_emulation_fault()
>    accel/hvf: Enforce host alignment in hv_vm_protect()
>    accel/hvf: Skip WFI if CPU has work to do
>    accel/hvf: Implement WFI without using pselect()
>    accel/hvf: Have PSCI CPU_SUSPEND halt the vCPU
>    accel: Introduce AccelOpsClass::cpu_target_realize() hook
>    accel/hvf: Add hvf_arch_cpu_realize() stubs
>    target/arm: Create GTimers *after* features finalized / accel realized
>    target/arm/hvf: Really set Generic Timer counter frequency
>    target/arm: Only allow disabling NEON when using TCG
> 
> Richard Henderson (9):
>    accel/hvf: Create hvf_protect_clean_range, hvf_unprotect_dirty_range
>    target/i386/hvf: Use hvf_unprotect_dirty_range
>    target/i386/hvf: Use address_space_translate in ept_emulation_fault
>    accel/hvf: Simplify hvf_log_*
>    accel/hvf: Move hvf_log_sync to hvf_log_clear
>    accel/hvf: Simplify hvf_set_phys_mem
>    accel/hvf: Drop hvf_slot and hvf_find_overlap_slot
>    accel/hvf: Remove mac_slots
>    target/arm/hvf: Implement dirty page tracking
> 
>   include/accel/accel-cpu-ops.h |   1 +
>   include/system/hvf_int.h      |  22 +---
>   accel/accel-common.c          |   5 +
>   accel/hvf/hvf-accel-ops.c     |  19 +---
>   accel/hvf/hvf-all.c           | 186 ++++++++++------------------------
>   target/arm/cpu.c              |  67 ++++++------
>   target/arm/hvf/hvf.c          | 167 +++++++++++++++---------------
>   target/i386/hvf/hvf.c         |  44 ++++----
>   accel/hvf/trace-events        |   1 +
>   9 files changed, 208 insertions(+), 304 deletions(-)
> 

For the whole series:
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>


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

* Re: [PATCH v5 00/19] target/arm/hvf: Consolidate
  2025-11-15  2:22 ` [PATCH v5 00/19] target/arm/hvf: Consolidate Akihiko Odaki
@ 2025-11-17  9:25   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-17  9:25 UTC (permalink / raw)
  To: Akihiko Odaki, qemu-devel
  Cc: Alexander Graf, qemu-arm, Phil Dennis-Jordan, Paolo Bonzini,
	Richard Henderson, Peter Collingbourne, Cameron Esfahani,
	Mohamed Mediouni, Peter Maydell, Roman Bolshakov, Mads Ynddal

On 15/11/25 03:22, Akihiko Odaki wrote:
> On 2025/11/15 5:04, Philippe Mathieu-Daudé wrote:

>> Philippe Mathieu-Daudé (10):
>>    target/i386/hvf: Use host page alignment in ept_emulation_fault()
>>    accel/hvf: Enforce host alignment in hv_vm_protect()
>>    accel/hvf: Skip WFI if CPU has work to do
>>    accel/hvf: Implement WFI without using pselect()
>>    accel/hvf: Have PSCI CPU_SUSPEND halt the vCPU
>>    accel: Introduce AccelOpsClass::cpu_target_realize() hook
>>    accel/hvf: Add hvf_arch_cpu_realize() stubs
>>    target/arm: Create GTimers *after* features finalized / accel realized
>>    target/arm/hvf: Really set Generic Timer counter frequency
>>    target/arm: Only allow disabling NEON when using TCG
>>
>> Richard Henderson (9):
>>    accel/hvf: Create hvf_protect_clean_range, hvf_unprotect_dirty_range
>>    target/i386/hvf: Use hvf_unprotect_dirty_range
>>    target/i386/hvf: Use address_space_translate in ept_emulation_fault
>>    accel/hvf: Simplify hvf_log_*
>>    accel/hvf: Move hvf_log_sync to hvf_log_clear
>>    accel/hvf: Simplify hvf_set_phys_mem
>>    accel/hvf: Drop hvf_slot and hvf_find_overlap_slot
>>    accel/hvf: Remove mac_slots
>>    target/arm/hvf: Implement dirty page tracking


> For the whole series:
> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>

Thanks Akihiko :)



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

end of thread, other threads:[~2025-11-17  9:26 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-14 20:04 [PATCH v5 00/19] target/arm/hvf: Consolidate Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 01/19] accel/hvf: Create hvf_protect_clean_range, hvf_unprotect_dirty_range Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 02/19] target/i386/hvf: Use host page alignment in ept_emulation_fault() Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 03/19] accel/hvf: Enforce host alignment in hv_vm_protect() Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 04/19] target/i386/hvf: Use hvf_unprotect_dirty_range Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 05/19] target/i386/hvf: Use address_space_translate in ept_emulation_fault Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 06/19] accel/hvf: Simplify hvf_log_* Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 07/19] accel/hvf: Move hvf_log_sync to hvf_log_clear Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 08/19] accel/hvf: Simplify hvf_set_phys_mem Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 09/19] accel/hvf: Drop hvf_slot and hvf_find_overlap_slot Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 10/19] accel/hvf: Remove mac_slots Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 11/19] target/arm/hvf: Implement dirty page tracking Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 12/19] accel/hvf: Skip WFI if CPU has work to do Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 13/19] accel/hvf: Implement WFI without using pselect() Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 14/19] accel/hvf: Have PSCI CPU_SUSPEND halt the vCPU Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 15/19] accel: Introduce AccelOpsClass::cpu_target_realize() hook Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 16/19] accel/hvf: Add hvf_arch_cpu_realize() stubs Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 17/19] target/arm: Create GTimers *after* features finalized / accel realized Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 18/19] target/arm/hvf: Really set Generic Timer counter frequency Philippe Mathieu-Daudé
2025-11-14 20:04 ` [PATCH v5 19/19] target/arm: Only allow disabling NEON when using TCG Philippe Mathieu-Daudé
2025-11-15  2:22 ` [PATCH v5 00/19] target/arm/hvf: Consolidate Akihiko Odaki
2025-11-17  9:25   ` Philippe Mathieu-Daudé

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).