From: Lucas Amaral <lucaaamaral@gmail.com>
To: qemu-devel@nongnu.org
Cc: qemu-arm@nongnu.org, agraf@csgraf.de,
Lucas Amaral <lucaaamaral@gmail.com>
Subject: [PATCH v2 3/3] target/arm: wire ISV=0 emulation into HVF and WHPX
Date: Thu, 12 Mar 2026 23:18:50 -0300 [thread overview]
Message-ID: <20260313021850.42379-4-lucaaamaral@gmail.com> (raw)
In-Reply-To: <20260313021850.42379-1-lucaaamaral@gmail.com>
Connect the ISV=0 emulation library to the HVF and WHPX backends.
Each implements arm_emul_ops callbacks over CPUARMState and
cpu_memory_rw_debug(). Replaces the assert(isv) with instruction
fetch, decode, and emulation via arm_emul_insn().
Signed-off-by: Lucas Amaral <lucaaamaral@gmail.com>
---
target/arm/hvf/hvf.c | 94 ++++++++++++++++++++++++++++++++++++--
target/arm/whpx/whpx-all.c | 86 +++++++++++++++++++++++++++++++++-
2 files changed, 176 insertions(+), 4 deletions(-)
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index d79469c..2a57b97 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -30,6 +30,7 @@
#include "qemu/main-loop.h"
#include "system/cpus.h"
#include "arm-powerctl.h"
+#include "emulate/arm_emulate.h"
#include "target/arm/cpu.h"
#include "target/arm/internals.h"
#include "target/arm/multiprocessing.h"
@@ -797,6 +798,59 @@ static uint64_t hvf_get_reg(CPUState *cpu, int rt)
return val;
}
+/*
+ * arm_emul_ops callbacks for HVF
+ *
+ * State must already be synchronized (cpu_synchronize_state) before
+ * calling arm_emul_insn(). Reads/writes env->xregs[] directly to
+ * correctly handle register 31 as SP and avoid redundant HVF API calls.
+ */
+
+static uint64_t hvf_emul_read_gpr(CPUState *cpu, int reg)
+{
+ return ARM_CPU(cpu)->env.xregs[reg];
+}
+
+static void hvf_emul_write_gpr(CPUState *cpu, int reg, uint64_t val)
+{
+ ARM_CPU(cpu)->env.xregs[reg] = val;
+ cpu->vcpu_dirty = true;
+}
+
+static void hvf_emul_read_fpreg(CPUState *cpu, int reg, void *buf, int size)
+{
+ memcpy(buf, &ARM_CPU(cpu)->env.vfp.zregs[reg], size);
+}
+
+static void hvf_emul_write_fpreg(CPUState *cpu, int reg,
+ const void *buf, int size)
+{
+ CPUARMState *env = &ARM_CPU(cpu)->env;
+ memset(&env->vfp.zregs[reg], 0, sizeof(env->vfp.zregs[reg]));
+ memcpy(&env->vfp.zregs[reg], buf, size);
+ cpu->vcpu_dirty = true;
+}
+
+static int hvf_emul_read_mem(CPUState *cpu, uint64_t va, void *buf, int size)
+{
+ return cpu_memory_rw_debug(cpu, va, buf, size, false);
+}
+
+static int hvf_emul_write_mem(CPUState *cpu, uint64_t va,
+ const void *buf, int size)
+{
+ return cpu_memory_rw_debug(cpu, va, (void *)buf, size, true);
+}
+
+static const struct arm_emul_ops hvf_arm_emul_ops = {
+ .read_gpr = hvf_emul_read_gpr,
+ .write_gpr = hvf_emul_write_gpr,
+ .read_fpreg = hvf_emul_read_fpreg,
+ .write_fpreg = hvf_emul_write_fpreg,
+ .read_mem = hvf_emul_read_mem,
+ .write_mem = hvf_emul_write_mem,
+};
+
static void clamp_id_aa64mmfr0_parange_to_ipa_size(ARMISARegisters *isar)
{
uint32_t ipa_size = chosen_ipa_bit_size ?
@@ -1871,10 +1925,44 @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp)
assert(!s1ptw);
/*
- * TODO: ISV will be 0 for SIMD or SVE accesses.
- * Inject the exception into the guest.
+ * ISV=0: syndrome doesn't carry access size/register info.
+ * Fetch and emulate via target/arm/emulate/.
+ * Unhandled instructions log an error and advance PC.
*/
- assert(isv);
+ if (!isv) {
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
+ CPUARMState *env = &arm_cpu->env;
+ uint32_t insn;
+ ArmEmulResult r;
+
+ cpu_synchronize_state(cpu);
+
+ if (cpu_memory_rw_debug(cpu, env->pc,
+ (uint8_t *)&insn, 4, false) != 0) {
+ error_report("HVF: cannot read insn at pc=0x%" PRIx64,
+ (uint64_t)env->pc);
+ advance_pc = true;
+ break;
+ }
+
+ r = arm_emul_insn(cpu, &hvf_arm_emul_ops, insn);
+ if (r == ARM_EMUL_UNHANDLED) {
+ /*
+ * TODO: Inject data abort into guest instead of
+ * advancing PC. Requires setting ESR_EL1/FAR_EL1/
+ * ELR_EL1/SPSR_EL1 and redirecting to VBAR_EL1.
+ */
+ error_report("HVF: ISV=0 unhandled insn 0x%08x at "
+ "pc=0x%" PRIx64, insn, (uint64_t)env->pc);
+ } else if (r == ARM_EMUL_ERR_MEM) {
+ error_report("HVF: ISV=0 memory error emulating "
+ "insn 0x%08x at pc=0x%" PRIx64,
+ insn, (uint64_t)env->pc);
+ }
+
+ advance_pc = true;
+ break;
+ }
/*
* Emulate MMIO.
diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c
index 40ada2d..c57abef 100644
--- a/target/arm/whpx/whpx-all.c
+++ b/target/arm/whpx/whpx-all.c
@@ -37,6 +37,7 @@
#include "whpx_arm.h"
#include "hw/arm/bsa.h"
#include "arm-powerctl.h"
+#include "emulate/arm_emulate.h"
#include <winhvplatform.h>
#include <winhvplatformdefs.h>
@@ -377,6 +378,53 @@ static void whpx_set_gp_reg(CPUState *cpu, int rt, uint64_t val)
whpx_set_reg(cpu, reg, reg_val);
}
+/* arm_emul_ops callbacks for WHPX */
+
+static uint64_t whpx_emul_read_gpr(CPUState *cpu, int reg)
+{
+ return ARM_CPU(cpu)->env.xregs[reg];
+}
+
+static void whpx_emul_write_gpr(CPUState *cpu, int reg, uint64_t val)
+{
+ ARM_CPU(cpu)->env.xregs[reg] = val;
+ cpu->vcpu_dirty = true;
+}
+
+static void whpx_emul_read_fpreg(CPUState *cpu, int reg, void *buf, int size)
+{
+ memcpy(buf, &ARM_CPU(cpu)->env.vfp.zregs[reg], size);
+}
+
+static void whpx_emul_write_fpreg(CPUState *cpu, int reg,
+ const void *buf, int size)
+{
+ CPUARMState *env = &ARM_CPU(cpu)->env;
+ memset(&env->vfp.zregs[reg], 0, sizeof(env->vfp.zregs[reg]));
+ memcpy(&env->vfp.zregs[reg], buf, size);
+ cpu->vcpu_dirty = true;
+}
+
+static int whpx_emul_read_mem(CPUState *cpu, uint64_t va, void *buf, int size)
+{
+ return cpu_memory_rw_debug(cpu, va, buf, size, false);
+}
+
+static int whpx_emul_write_mem(CPUState *cpu, uint64_t va,
+ const void *buf, int size)
+{
+ return cpu_memory_rw_debug(cpu, va, (void *)buf, size, true);
+}
+
+static const struct arm_emul_ops whpx_arm_emul_ops = {
+ .read_gpr = whpx_emul_read_gpr,
+ .write_gpr = whpx_emul_write_gpr,
+ .read_fpreg = whpx_emul_read_fpreg,
+ .write_fpreg = whpx_emul_write_fpreg,
+ .read_mem = whpx_emul_read_mem,
+ .write_mem = whpx_emul_write_mem,
+};
+
static int whpx_handle_mmio(CPUState *cpu, WHV_MEMORY_ACCESS_CONTEXT *ctx)
{
uint64_t syndrome = ctx->Syndrome;
@@ -391,7 +439,43 @@ static int whpx_handle_mmio(CPUState *cpu, WHV_MEMORY_ACCESS_CONTEXT *ctx)
uint64_t val = 0;
assert(!cm);
- assert(isv);
+
+ /*
+ * ISV=0: syndrome doesn't carry access size/register info.
+ * Fetch and decode the faulting instruction via the emulation library.
+ */
+ if (!isv) {
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
+ CPUARMState *env = &arm_cpu->env;
+ uint32_t insn;
+ ArmEmulResult r;
+
+ cpu_synchronize_state(cpu);
+
+ if (cpu_memory_rw_debug(cpu, env->pc,
+ (uint8_t *)&insn, 4, false) != 0) {
+ error_report("WHPX: cannot read insn at pc=0x%" PRIx64,
+ (uint64_t)env->pc);
+ return 0;
+ }
+
+ r = arm_emul_insn(cpu, &whpx_arm_emul_ops, insn);
+ if (r == ARM_EMUL_UNHANDLED) {
+ /*
+ * TODO: Inject data abort into guest instead of
+ * advancing PC. Requires setting ESR_EL1/FAR_EL1/
+ * ELR_EL1/SPSR_EL1 and redirecting to VBAR_EL1.
+ */
+ error_report("WHPX: ISV=0 unhandled insn 0x%08x at "
+ "pc=0x%" PRIx64, insn, (uint64_t)env->pc);
+ } else if (r == ARM_EMUL_ERR_MEM) {
+ error_report("WHPX: ISV=0 memory error emulating "
+ "insn 0x%08x at pc=0x%" PRIx64,
+ insn, (uint64_t)env->pc);
+ }
+
+ return 0;
+ }
if (iswrite) {
val = whpx_get_gp_reg(cpu, srt);
--
2.52.0
next prev parent reply other threads:[~2026-03-13 2:19 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-09 21:48 [PATCH] target/arm/hvf: emulate ISV=0 data abort instructions Lucas Amaral
2026-03-10 1:28 ` Mohamed Mediouni
2026-03-10 9:23 ` Peter Maydell
2026-03-13 2:18 ` [PATCH v2 0/3] target/arm: ISV=0 data abort emulation library Lucas Amaral
2026-03-13 2:18 ` [PATCH v2 1/3] target/arm: add AArch64 ISV=0 instruction " Lucas Amaral
2026-03-13 6:33 ` Mohamed Mediouni
2026-03-13 8:59 ` Peter Maydell
2026-03-13 2:18 ` [PATCH v2 2/3] tests: add unit tests for ISV=0 " Lucas Amaral
2026-03-13 2:18 ` Lucas Amaral [this message]
2026-03-15 3:41 ` [PATCH v3 0/6] target/arm: ISV=0 data abort " Lucas Amaral
2026-03-15 3:41 ` [PATCH v3 1/6] target/arm/emulate: add ISV=0 emulation library with load/store immediate Lucas Amaral
2026-03-15 3:41 ` [PATCH v3 2/6] target/arm/emulate: add load/store register offset Lucas Amaral
2026-03-15 3:41 ` [PATCH v3 3/6] target/arm/emulate: add load/store pair Lucas Amaral
2026-03-15 3:41 ` [PATCH v3 4/6] target/arm/emulate: add load/store exclusive Lucas Amaral
2026-03-15 3:41 ` [PATCH v3 5/6] target/arm/emulate: add atomic, compare-and-swap, and PAC load Lucas Amaral
2026-03-15 3:41 ` [PATCH v3 6/6] target/arm/hvf, whpx: wire ISV=0 emulation for data aborts Lucas Amaral
2026-03-16 2:50 ` [PATCH v4 0/6] target/arm: ISV=0 data abort emulation library Lucas Amaral
2026-03-16 2:50 ` [PATCH v4 1/6] target/arm/emulate: add ISV=0 emulation library with load/store immediate Lucas Amaral
2026-03-19 22:00 ` Richard Henderson
2026-03-16 2:50 ` [PATCH v4 2/6] target/arm/emulate: add load/store register offset Lucas Amaral
2026-03-16 2:50 ` [PATCH v4 3/6] target/arm/emulate: add load/store pair Lucas Amaral
2026-03-16 2:50 ` [PATCH v4 4/6] target/arm/emulate: add load/store exclusive Lucas Amaral
2026-03-16 2:50 ` [PATCH v4 5/6] target/arm/emulate: add atomic, compare-and-swap, and PAC load Lucas Amaral
2026-03-16 2:50 ` [PATCH v4 6/6] target/arm/hvf, whpx: wire ISV=0 emulation for data aborts Lucas Amaral
2026-03-17 14:27 ` [PATCH v4 0/6] target/arm: ISV=0 data abort emulation library Alex Bennée
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260313021850.42379-4-lucaaamaral@gmail.com \
--to=lucaaamaral@gmail.com \
--cc=agraf@csgraf.de \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.