Message ID | 20220420115745.13696-11-pmorel@linux.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | s390x: CPU Topology | expand |
On 20/04/2022 13.57, 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 hypervizor 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 hypervizor. > > Signed-off-by: Pierre Morel <pmorel@linux.ibm.com> > --- > hw/s390x/s390-virtio-ccw.c | 50 ++++++++++++++++++++++++++++++ > include/hw/s390x/s390-virtio-ccw.h | 6 ++++ > target/s390x/kvm/kvm.c | 14 +++++++++ > 3 files changed, 70 insertions(+) > > diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c > index 93d1a43583..1ffaddebcc 100644 > --- a/hw/s390x/s390-virtio-ccw.c > +++ b/hw/s390x/s390-virtio-ccw.c Why do you put this into s390-virtio-ccw.c and not into cpu_topology.c ? > @@ -434,6 +434,56 @@ static void s390_pv_prepare_reset(S390CcwMachineState *ms) > s390_pv_prep_reset(); > } > > +/* > + * s390_handle_ptf: > + * > + * @register 1: contains the function code > + * > + * Function codes 0 and 1 handle the CPU polarization. > + * We assume an horizontal topology, the only one supported currently > + * by Linux, consequently we answer to function code 0, requesting > + * horizontal polarization that it is already the current polarization > + * and reject vertical polarization request without further explanation. > + * > + * Function code 2 is handling topology changes and is interpreted > + * by the SIE. > + */ > +int s390_handle_ptf(S390CPU *cpu, uint8_t r1, uintptr_t ra) > +{ > + CPUS390XState *env = &cpu->env; > + uint64_t reg = env->regs[r1]; > + uint8_t fc = reg & S390_TOPO_FC_MASK; > + > + if (!s390_has_feat(S390_FEAT_CONFIGURATION_TOPOLOGY)) { > + s390_program_interrupt(env, PGM_OPERATION, ra); > + return 0; > + } > + > + if (env->psw.mask & PSW_MASK_PSTATE) { > + s390_program_interrupt(env, PGM_PRIVILEGED, ra); > + return 0; > + } > + > + if (reg & ~S390_TOPO_FC_MASK) { > + s390_program_interrupt(env, PGM_SPECIFICATION, ra); > + return 0; > + } > + > + switch (fc) { > + case 0: /* Horizontal polarization is already set */ > + env->regs[r1] |= S390_PTF_REASON_DONE; > + return 2; > + case 1: /* Vertical polarization is not supported */ > + env->regs[r1] |= S390_PTF_REASON_NONE; > + return 2; > + default: > + /* Note that fc == 2 is interpreted by the SIE */ > + s390_program_interrupt(env, PGM_SPECIFICATION, ra); > + } > + > + return 0; > +} > + > static void s390_machine_reset(MachineState *machine) > { > S390CcwMachineState *ms = S390_CCW_MACHINE(machine); > diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h > index 3331990e02..ac4b4a92e7 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 > +int s390_handle_ptf(S390CPU *cpu, uint8_t r1, uintptr_t ra); > + > struct S390CcwMachineClass { > /*< private >*/ > MachineClass parent_class; > diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c > index 27b3fbfa09..e3792e52c2 100644 > --- a/target/s390x/kvm/kvm.c > +++ b/target/s390x/kvm/kvm.c > @@ -98,6 +98,7 @@ > > #define PRIV_B9_EQBS 0x9c > #define PRIV_B9_CLP 0xa0 > +#define PRIV_B9_PTF 0xa2 > #define PRIV_B9_PCISTG 0xd0 > #define PRIV_B9_PCILG 0xd2 > #define PRIV_B9_RPCIT 0xd3 > @@ -1453,6 +1454,16 @@ static int kvm_mpcifc_service_call(S390CPU *cpu, struct kvm_run *run) > } > } > > +static int kvm_handle_ptf(S390CPU *cpu, struct kvm_run *run) > +{ > + uint8_t r1 = (run->s390_sieic.ipb >> 20) & 0x0f; > + int ret; > + > + ret = s390_handle_ptf(cpu, r1, RA_IGNORED); > + setcc(cpu, ret); So you're still setting the CC in case the s390_handle_ptf() function injected a program interrupt? ... feels wrong. Maybe the CC should be set within s390_handle_ptf() instead? Thomas > + return 0; > +} > + > static int handle_b9(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) > { > int r = 0; > @@ -1470,6 +1481,9 @@ static int handle_b9(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) > case PRIV_B9_RPCIT: > r = kvm_rpcit_service_call(cpu, run); > break; > + case PRIV_B9_PTF: > + r = kvm_handle_ptf(cpu, run); > + break; > case PRIV_B9_EQBS: > /* just inject exception */ > r = -1;
On 5/24/22 13:27, Thomas Huth wrote: > On 20/04/2022 13.57, 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 hypervizor 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 hypervizor. >> >> Signed-off-by: Pierre Morel <pmorel@linux.ibm.com> >> --- >> hw/s390x/s390-virtio-ccw.c | 50 ++++++++++++++++++++++++++++++ >> include/hw/s390x/s390-virtio-ccw.h | 6 ++++ >> target/s390x/kvm/kvm.c | 14 +++++++++ >> 3 files changed, 70 insertions(+) >> >> diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c >> index 93d1a43583..1ffaddebcc 100644 >> --- a/hw/s390x/s390-virtio-ccw.c >> +++ b/hw/s390x/s390-virtio-ccw.c > > Why do you put this into s390-virtio-ccw.c and not into cpu_topology.c ? Should have historical reason I forgot in between. I will move it in cpu_topology.c > >> @@ -434,6 +434,56 @@ static void >> s390_pv_prepare_reset(S390CcwMachineState *ms) >> s390_pv_prep_reset(); >> } >> +/* >> + * s390_handle_ptf: >> + * >> + * @register 1: contains the function code >> + * >> + * Function codes 0 and 1 handle the CPU polarization. >> + * We assume an horizontal topology, the only one supported currently >> + * by Linux, consequently we answer to function code 0, requesting >> + * horizontal polarization that it is already the current polarization >> + * and reject vertical polarization request without further explanation. >> + * >> + * Function code 2 is handling topology changes and is interpreted >> + * by the SIE. >> + */ >> +int s390_has390_handle_ptfndle_ptf(S390CPU *cpu, uint8_t r1, uintptr_t ra) >> +{ >> + CPUS390XState *env = &cpu->env; >> + uint64_t reg = env->regs[r1]; >> + uint8_t fc = reg & S390_TOPO_FC_MASK; >> + >> + if (!s390_has_feat(S390_FEAT_CONFIGURATION_TOPOLOGY)) { >> + s390_program_interrupt(env, PGM_OPERATION, ra); >> + return 0; >> + } >> + >> + if (env->psw.mask & PSW_MASK_PSTATE) { >> + s390_program_interrupt(env, PGM_PRIVILEGED, ra); >> + return 0; >> + } >> + >> + if (reg & ~S390_TOPO_FC_MASK) { >> + s390_program_interrupt(env, PGM_SPECIFICATION, ra); >> + return 0; >> + } >> + >> + switch (fc) { >> + case 0: /* Horizontal polarization is already set */ >> + env->regs[r1] |= S390_PTF_REASON_DONE; >> + return 2; >> + case 1: /* Vertical polarization is not supported */ >> + env->regs[r1] |= S390_PTF_REASON_NONE; >> + return 2; >> + default: >> + /* Note that fc == 2 is interpreted by the SIE */ >> + s390_program_interrupt(env, PGM_SPECIFICATION, ra); >> + } >> + >> + return 0; >> +} >> + >> static void s390_machine_reset(MachineState *machine) >> { >> S390CcwMachineState *ms = S390_CCW_MACHINE(machine); >> diff --git a/include/hw/s390x/s390-virtio-ccw.h >> b/include/hw/s390x/s390-virtio-ccw.h >> index 3331990e02..ac4b4a92e7 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 >> +int s390_handle_ptf(S390CPU *cpu, uint8_t r1, uintptr_t ra); >> + >> struct S390CcwMachineClass { >> /*< private >*/ >> MachineClass parent_class; >> diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c >> index 27b3fbfa09..e3792e52c2 100644 >> --- a/target/s390x/kvm/kvm.c >> +++ b/target/s390x/kvm/kvm.c >> @@ -98,6 +98,7 @@ >> #define PRIV_B9_EQBS 0x9c >> #define PRIV_B9_CLP 0xa0 >> +#define PRIV_B9_PTF 0xa2 >> #define PRIV_B9_PCISTG 0xd0 >> #define PRIV_B9_PCILG 0xd2 >> #define PRIV_B9_RPCIT 0xd3 >> @@ -1453,6 +1454,16 @@ static int kvm_mpcifc_service_call(S390CPU >> *cpu, struct kvm_run *run) >> } >> } >> +static int kvm_handle_ptf(S390CPU *cpu, struct kvm_run *run) >> +{ >> + uint8_t r1 = (run->s390_sieic.ipb >> 20) & 0x0f; >> + int ret; >> + >> + ret = s390_handle_ptf(cpu, r1, RA_IGNORED); >> + setcc(cpu, ret); > > So you're still setting the CC in case the s390_handle_ptf() function > injected a program interrupt? ... feels wrong. Maybe the CC should be > set within s390_handle_ptf() instead? OK, I will have a look and change it. Thanks, Pierre > > Thomas > > >> + return 0; >> +} >> + >> static int handle_b9(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) >> { >> int r = 0; >> @@ -1470,6 +1481,9 @@ static int handle_b9(S390CPU *cpu, struct >> kvm_run *run, uint8_t ipa1) >> case PRIV_B9_RPCIT: >> r = kvm_rpcit_service_call(cpu, run); >> break; >> + case PRIV_B9_PTF: >> + r = kvm_handle_ptf(cpu, run); >> + break; >> case PRIV_B9_EQBS: >> /* just inject exception */ >> r = -1; >
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 93d1a43583..1ffaddebcc 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -434,6 +434,56 @@ static void s390_pv_prepare_reset(S390CcwMachineState *ms) s390_pv_prep_reset(); } +/* + * s390_handle_ptf: + * + * @register 1: contains the function code + * + * Function codes 0 and 1 handle the CPU polarization. + * We assume an horizontal topology, the only one supported currently + * by Linux, consequently we answer to function code 0, requesting + * horizontal polarization that it is already the current polarization + * and reject vertical polarization request without further explanation. + * + * Function code 2 is handling topology changes and is interpreted + * by the SIE. + */ +int s390_handle_ptf(S390CPU *cpu, uint8_t r1, uintptr_t ra) +{ + CPUS390XState *env = &cpu->env; + uint64_t reg = env->regs[r1]; + uint8_t fc = reg & S390_TOPO_FC_MASK; + + if (!s390_has_feat(S390_FEAT_CONFIGURATION_TOPOLOGY)) { + s390_program_interrupt(env, PGM_OPERATION, ra); + return 0; + } + + if (env->psw.mask & PSW_MASK_PSTATE) { + s390_program_interrupt(env, PGM_PRIVILEGED, ra); + return 0; + } + + if (reg & ~S390_TOPO_FC_MASK) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return 0; + } + + switch (fc) { + case 0: /* Horizontal polarization is already set */ + env->regs[r1] |= S390_PTF_REASON_DONE; + return 2; + case 1: /* Vertical polarization is not supported */ + env->regs[r1] |= S390_PTF_REASON_NONE; + return 2; + default: + /* Note that fc == 2 is interpreted by the SIE */ + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + } + + return 0; +} + static void s390_machine_reset(MachineState *machine) { S390CcwMachineState *ms = S390_CCW_MACHINE(machine); diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h index 3331990e02..ac4b4a92e7 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 +int s390_handle_ptf(S390CPU *cpu, uint8_t r1, uintptr_t ra); + struct S390CcwMachineClass { /*< private >*/ MachineClass parent_class; diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c index 27b3fbfa09..e3792e52c2 100644 --- a/target/s390x/kvm/kvm.c +++ b/target/s390x/kvm/kvm.c @@ -98,6 +98,7 @@ #define PRIV_B9_EQBS 0x9c #define PRIV_B9_CLP 0xa0 +#define PRIV_B9_PTF 0xa2 #define PRIV_B9_PCISTG 0xd0 #define PRIV_B9_PCILG 0xd2 #define PRIV_B9_RPCIT 0xd3 @@ -1453,6 +1454,16 @@ static int kvm_mpcifc_service_call(S390CPU *cpu, struct kvm_run *run) } } +static int kvm_handle_ptf(S390CPU *cpu, struct kvm_run *run) +{ + uint8_t r1 = (run->s390_sieic.ipb >> 20) & 0x0f; + int ret; + + ret = s390_handle_ptf(cpu, r1, RA_IGNORED); + setcc(cpu, ret); + return 0; +} + static int handle_b9(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) { int r = 0; @@ -1470,6 +1481,9 @@ static int handle_b9(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) case PRIV_B9_RPCIT: r = kvm_rpcit_service_call(cpu, run); break; + case PRIV_B9_PTF: + r = kvm_handle_ptf(cpu, run); + break; case PRIV_B9_EQBS: /* just inject exception */ r = -1;
When the host supports the CPU topology facility, the PTF instruction with function code 2 is interpreted by the SIE, provided that the userland hypervizor 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 hypervizor. Signed-off-by: Pierre Morel <pmorel@linux.ibm.com> --- hw/s390x/s390-virtio-ccw.c | 50 ++++++++++++++++++++++++++++++ include/hw/s390x/s390-virtio-ccw.h | 6 ++++ target/s390x/kvm/kvm.c | 14 +++++++++ 3 files changed, 70 insertions(+)