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
>
>

Reply via email to