On Fri, Aug 22, 2025 at 10:13 AM Philippe Mathieu-Daudé <phi...@linaro.org> wrote: > > On 17/6/25 18:33, Alex Bennée wrote: > > For now just deal with the basic version probe we see during startup. > > > > Signed-off-by: Alex Bennée <alex.ben...@linaro.org> > > --- > > target/arm/kvm.c | 44 +++++++++++++++++++++++++++++++++++++++++ > > target/arm/trace-events | 1 + > > 2 files changed, 45 insertions(+) > > > > diff --git a/target/arm/kvm.c b/target/arm/kvm.c > > index 0a852af126..1280e2c1e8 100644 > > --- a/target/arm/kvm.c > > +++ b/target/arm/kvm.c > > @@ -1507,6 +1507,43 @@ static int kvm_arm_handle_sysreg_trap(ARMCPU *cpu, > > return -1; > > } > > > > +/* > > + * The guest is making a hypercall or firmware call. We can handle a > > + * limited number of them (e.g. PSCI) but we can't emulate a true > > + * firmware. This is an abbreviated version of > > + * kvm_smccc_call_handler() in the kernel and the TCG only > > arm_handle_psci_call(). > > + * > > + * In the SplitAccel case we would be transitioning to execute EL2+ > > + * under TCG. > > + */ > > +static int kvm_arm_handle_hypercall(ARMCPU *cpu, > > + int esr_ec) > > +{ > > + CPUARMState *env = &cpu->env; > > + int32_t ret = 0; > > + > > + trace_kvm_hypercall(esr_ec, env->xregs[0]); > > + > > + switch (env->xregs[0]) { > > + case QEMU_PSCI_0_2_FN_PSCI_VERSION: > > + ret = QEMU_PSCI_VERSION_1_1; > > + break; > > + case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE: > > + ret = QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED; /* No trusted > > OS */ > > + break; > > + case QEMU_PSCI_1_0_FN_PSCI_FEATURES: > > + ret = QEMU_PSCI_RET_NOT_SUPPORTED; > > + break; > > + default: > > + qemu_log_mask(LOG_UNIMP, "%s: unhandled hypercall %"PRIx64"\n", > > + __func__, env->xregs[0]); > > + return -1; > > + } > > + > > + env->xregs[0] = ret; > > + return 0; > > +} > > + > > /** > > * kvm_arm_handle_hard_trap: > > * @cpu: ARMCPU > > @@ -1538,6 +1575,13 @@ static int kvm_arm_handle_hard_trap(ARMCPU *cpu, > > switch (esr_ec) { > > case EC_SYSTEMREGISTERTRAP: > > return kvm_arm_handle_sysreg_trap(cpu, esr_iss, elr); > > + case EC_AA32_SVC: > > + case EC_AA32_HVC: > > + case EC_AA32_SMC: > > + case EC_AA64_SVC: > > + case EC_AA64_HVC: > > + case EC_AA64_SMC: > > Should we increment $pc for SVC/SMC? > The instruction operation pseudocode [*] is: > > preferred_exception_return = ThisInstrAddr(64); >
Here's what the trusted firmware handler does. The exception return address is modified by the : https://github.com/ARM-software/arm-trusted-firmware/blob/da6b3a181c03a492ee52182b0466d0b7cc4091dd/bl31/aarch64/runtime_exceptions.S#L456-L480 > * returns: > * -1: unhandled trap, UNDEF injection into lower EL > * 0: handled trap, return to the trapping instruction (repeating it) > * 1: handled trap, return to the next instruction An SMC-aware trap handler should do the same > [*] > https://developer.arm.com/documentation/ddi0602/2022-06/Shared-Pseudocode/AArch64-Exceptions?lang=en > > > + return kvm_arm_handle_hypercall(cpu, esr_ec); > > default: > > qemu_log_mask(LOG_UNIMP, "%s: unhandled EC: %x/%x/%x/%d\n", > > __func__, esr_ec, esr_iss, esr_iss2, esr_il); > > diff --git a/target/arm/trace-events b/target/arm/trace-events > > index 69bb4d370d..10cdba92a3 100644 > > --- a/target/arm/trace-events > > +++ b/target/arm/trace-events > > @@ -15,3 +15,4 @@ arm_gt_update_irq(int timer, int irqstate) > > "gt_update_irq: timer %d irqstate %d" > > kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = > > 0x%"PRIx64" is translated into 0x%"PRIx64 > > kvm_sysreg_read(const char *name, uint64_t val) "%s => 0x%" PRIx64 > > kvm_sysreg_write(const char *name, uint64_t val) "%s <= 0x%" PRIx64 > > +kvm_hypercall(int ec, uint64_t arg0) "%d: %"PRIx64 > >