On Tue, 2023-04-25 at 18:14 +0200, Pierre Morel wrote: > When the host supports the CPU topology facility, the PTF > instruction with function code 2 is interpreted by the SIE, > provided that the userland hypervisor activates the interpretation > by using the KVM_CAP_S390_CPU_TOPOLOGY KVM extension. > > The PTF instructions with function code 0 and 1 are intercepted > and must be emulated by the userland hypervisor. > > During RESET all CPU of the configuration are placed in > horizontal polarity. > > Signed-off-by: Pierre Morel <pmorel@xxxxxxxxxxxxx> Reviewed-by: Nina Schoetterl-Glausch <nsg@xxxxxxxxxxxxx> See nit below. > --- > include/hw/s390x/s390-virtio-ccw.h | 6 ++++ > hw/s390x/cpu-topology.c | 51 ++++++++++++++++++++++++++++++ > target/s390x/kvm/kvm.c | 11 +++++++ > 3 files changed, 68 insertions(+) > > diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h > index 9bba21a916..c1d46e78af 100644 > --- a/include/hw/s390x/s390-virtio-ccw.h > +++ b/include/hw/s390x/s390-virtio-ccw.h > @@ -30,6 +30,12 @@ struct S390CcwMachineState { > uint8_t loadparm[8]; > }; > > +#define S390_PTF_REASON_NONE (0x00 << 8) > +#define S390_PTF_REASON_DONE (0x01 << 8) > +#define S390_PTF_REASON_BUSY (0x02 << 8) > +#define S390_TOPO_FC_MASK 0xffUL > +void s390_handle_ptf(S390CPU *cpu, uint8_t r1, uintptr_t ra); > + > struct S390CcwMachineClass { > /*< private >*/ > MachineClass parent_class; > diff --git a/hw/s390x/cpu-topology.c b/hw/s390x/cpu-topology.c > index c98439ff7a..3c7bbff4bc 100644 > --- a/hw/s390x/cpu-topology.c > +++ b/hw/s390x/cpu-topology.c > @@ -96,6 +96,56 @@ static void s390_topology_init(MachineState *ms) > QTAILQ_INSERT_HEAD(&s390_topology.list, entry, next); > } > > +/* > + * s390_handle_ptf: > + * > + * @register 1: contains the function code > + * > + * Function codes 0 (horizontal) and 1 (vertical) define the CPU > + * polarization requested by the guest. > + * > + * Function code 2 is handling topology changes and is interpreted > + * by the SIE. > + */ > +void s390_handle_ptf(S390CPU *cpu, uint8_t r1, uintptr_t ra) > +{ > + CPUS390XState *env = &cpu->env; > + uint64_t reg = env->regs[r1]; > + int fc = reg & S390_TOPO_FC_MASK; > + > + if (!s390_has_feat(S390_FEAT_CONFIGURATION_TOPOLOGY)) { > + s390_program_interrupt(env, PGM_OPERATION, ra); > + return; > + } > + > + if (env->psw.mask & PSW_MASK_PSTATE) { > + s390_program_interrupt(env, PGM_PRIVILEGED, ra); > + return; > + } > + > + if (reg & ~S390_TOPO_FC_MASK) { > + s390_program_interrupt(env, PGM_SPECIFICATION, ra); > + return; > + } > + > + switch (fc) { > + case S390_CPU_POLARIZATION_VERTICAL: > + case S390_CPU_POLARIZATION_HORIZONTAL: I'd give this a name. bool requested_vertical = !!fc; > + if (s390_topology.vertical_polarization == !!fc) { > + env->regs[r1] |= S390_PTF_REASON_DONE; > + setcc(cpu, 2); > + } else { > + s390_topology.vertical_polarization = !!fc; > + s390_cpu_topology_set_changed(true); > + setcc(cpu, 0); > + } > + break; > + default: > + /* Note that fc == 2 is interpreted by the SIE */ > + s390_program_interrupt(env, PGM_SPECIFICATION, ra); > + } > +} > + [...]