Message ID | 20230914120650.1318932-9-nsg@linux.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | s390x: CPU Topology | expand |
Nina Schoetterl-Glausch <nsg@linux.ibm.com> writes: > From: Pierre Morel <pmorel@linux.ibm.com> > > The modification of the CPU attributes are done through a monitor > command. > > It allows to move the core inside the topology tree to optimize > the cache usage in the case the host's hypervisor previously > moved the CPU. > > The same command allows to modify the CPU attributes modifiers > like polarization entitlement and the dedicated attribute to notify > the guest if the host admin modified scheduling or dedication of a vCPU. > > With this knowledge the guest has the possibility to optimize the > usage of the vCPUs. > > The command has a feature unstable for the moment. > > Signed-off-by: Pierre Morel <pmorel@linux.ibm.com> > Reviewed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com> > Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com> > Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com> > --- > qapi/machine-target.json | 37 +++++++++++ > hw/s390x/cpu-topology.c | 132 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 169 insertions(+) > > diff --git a/qapi/machine-target.json b/qapi/machine-target.json > index 0d45a590ce..e47a252bd9 100644 > --- a/qapi/machine-target.json > +++ b/qapi/machine-target.json > @@ -4,6 +4,8 @@ > # This work is licensed under the terms of the GNU GPL, version 2 or later. > # See the COPYING file in the top-level directory. > > +{ 'include': 'machine-common.json' } > + > ## > # @CpuModelInfo: > # > @@ -375,3 +377,38 @@ > 'data': [ 'horizontal', 'vertical' ], > 'if': 'TARGET_S390X' > } > + > +## > +# @set-cpu-topology: Move the overview here from [*] below. > +# > +# @core-id: the vCPU ID to be moved > +# @socket-id: optional destination socket where to move the vCPU > +# @book-id: optional destination book where to move the vCPU > +# @drawer-id: optional destination drawer where to move the vCPU > +# @entitlement: optional entitlement > +# @dedicated: optional, if the vCPU is dedicated to a real CPU Separate the members with blank lines, please. The doc generator adds optional automatically, so this will come out like "socket-id": "int" (optional) optional destination socket where to move the vCPU "book-id": "int" (optional) optional destination book where to move the vCPU "drawer-id": "int" (optional) optional destination drawer where to move the vCPU "entitlement": "CpuS390Entitlement" (optional) optional entitlement "dedicated": "boolean" (optional) optional, if the vCPU is dedicated to a real CPU Drop the optional from the text. Suggest # @dedicated: whether the vCPU is dedicated to a real CPU (whatever that may mean; I'm an S390 noob) > +# > +# Features: Another blank line, please. > +# @unstable: This command may still be modified. > +# [*] The overview: > +# Modifies the topology by moving the CPU inside the topology > +# tree or by changing a modifier attribute of a CPU. > +# Default value for optional parameter is the current value > +# used by the CPU. So, anything absent will not be changed. Maybe that's a clearer way to put it. What do you think? > +# > +# Returns: Nothing on success, the reason on failure. > +# > +# Since: 8.2 > +## > +{ 'command': 'set-cpu-topology', > + 'data': { > + 'core-id': 'uint16', > + '*socket-id': 'uint16', > + '*book-id': 'uint16', > + '*drawer-id': 'uint16', CpuInstanceProperties uses 'int' for these. Any particular reason for the difference? > + '*entitlement': 'CpuS390Entitlement', > + '*dedicated': 'bool' > + }, > + 'features': [ 'unstable' ], > + 'if': { 'all': [ 'TARGET_S390X' , 'CONFIG_KVM' ] } > +} [...]
On Wed, 2023-09-20 at 13:36 +0200, Markus Armbruster wrote: > Nina Schoetterl-Glausch <nsg@linux.ibm.com> writes: > > > From: Pierre Morel <pmorel@linux.ibm.com> > > > > The modification of the CPU attributes are done through a monitor > > command. > > > > It allows to move the core inside the topology tree to optimize > > the cache usage in the case the host's hypervisor previously > > moved the CPU. > > > > The same command allows to modify the CPU attributes modifiers > > like polarization entitlement and the dedicated attribute to notify > > the guest if the host admin modified scheduling or dedication of a vCPU. > > > > With this knowledge the guest has the possibility to optimize the > > usage of the vCPUs. > > > > The command has a feature unstable for the moment. > > > > Signed-off-by: Pierre Morel <pmorel@linux.ibm.com> > > Reviewed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com> > > Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com> > > Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com> > > --- > > qapi/machine-target.json | 37 +++++++++++ > > hw/s390x/cpu-topology.c | 132 +++++++++++++++++++++++++++++++++++++++ > > 2 files changed, 169 insertions(+) > > > > diff --git a/qapi/machine-target.json b/qapi/machine-target.json > > index 0d45a590ce..e47a252bd9 100644 > > --- a/qapi/machine-target.json > > +++ b/qapi/machine-target.json [...] > > +# Modifies the topology by moving the CPU inside the topology > > +# tree or by changing a modifier attribute of a CPU. > > +# Default value for optional parameter is the current value > > +# used by the CPU. > > So, anything absent will not be changed. Maybe that's a clearer way to > put it. What do you think? Yes. > > > +# > > +# Returns: Nothing on success, the reason on failure. > > +# > > +# Since: 8.2 > > +## > > +{ 'command': 'set-cpu-topology', > > + 'data': { > > + 'core-id': 'uint16', > > + '*socket-id': 'uint16', > > + '*book-id': 'uint16', > > + '*drawer-id': 'uint16', > > CpuInstanceProperties uses 'int' for these. Any particular reason for > the difference? unsigned -> no need to check if >0 16bit is also the width the hardware uses for these values on s390. > > + '*entitlement': 'CpuS390Entitlement', > > + '*dedicated': 'bool' > > + }, > > + 'features': [ 'unstable' ], > > + 'if': { 'all': [ 'TARGET_S390X' , 'CONFIG_KVM' ] } > > +} > > [...] >
diff --git a/qapi/machine-target.json b/qapi/machine-target.json index 0d45a590ce..e47a252bd9 100644 --- a/qapi/machine-target.json +++ b/qapi/machine-target.json @@ -4,6 +4,8 @@ # This work is licensed under the terms of the GNU GPL, version 2 or later. # See the COPYING file in the top-level directory. +{ 'include': 'machine-common.json' } + ## # @CpuModelInfo: # @@ -375,3 +377,38 @@ 'data': [ 'horizontal', 'vertical' ], 'if': 'TARGET_S390X' } + +## +# @set-cpu-topology: +# +# @core-id: the vCPU ID to be moved +# @socket-id: optional destination socket where to move the vCPU +# @book-id: optional destination book where to move the vCPU +# @drawer-id: optional destination drawer where to move the vCPU +# @entitlement: optional entitlement +# @dedicated: optional, if the vCPU is dedicated to a real CPU +# +# Features: +# @unstable: This command may still be modified. +# +# Modifies the topology by moving the CPU inside the topology +# tree or by changing a modifier attribute of a CPU. +# Default value for optional parameter is the current value +# used by the CPU. +# +# Returns: Nothing on success, the reason on failure. +# +# Since: 8.2 +## +{ 'command': 'set-cpu-topology', + 'data': { + 'core-id': 'uint16', + '*socket-id': 'uint16', + '*book-id': 'uint16', + '*drawer-id': 'uint16', + '*entitlement': 'CpuS390Entitlement', + '*dedicated': 'bool' + }, + 'features': [ 'unstable' ], + 'if': { 'all': [ 'TARGET_S390X' , 'CONFIG_KVM' ] } +} diff --git a/hw/s390x/cpu-topology.c b/hw/s390x/cpu-topology.c index 13f404a0d7..28adfb3f84 100644 --- a/hw/s390x/cpu-topology.c +++ b/hw/s390x/cpu-topology.c @@ -23,6 +23,7 @@ #include "target/s390x/cpu.h" #include "hw/s390x/s390-virtio-ccw.h" #include "hw/s390x/cpu-topology.h" +#include "qapi/qapi-commands-machine-target.h" /* * s390_topology is used to keep the topology information. @@ -257,6 +258,29 @@ static bool s390_topology_check(uint16_t socket_id, uint16_t book_id, return true; } +/** + * s390_topology_need_report + * @cpu: Current cpu + * @drawer_id: future drawer ID + * @book_id: future book ID + * @socket_id: future socket ID + * @entitlement: future entitlement + * @dedicated: future dedicated + * + * A modified topology change report is needed if the topology + * tree or the topology attributes change. + */ +static bool s390_topology_need_report(S390CPU *cpu, int drawer_id, + int book_id, int socket_id, + uint16_t entitlement, bool dedicated) +{ + return cpu->env.drawer_id != drawer_id || + cpu->env.book_id != book_id || + cpu->env.socket_id != socket_id || + cpu->env.entitlement != entitlement || + cpu->env.dedicated != dedicated; +} + /** * s390_update_cpu_props: * @ms: the machine state @@ -325,3 +349,111 @@ void s390_topology_setup_cpu(MachineState *ms, S390CPU *cpu, Error **errp) /* topology tree is reflected in props */ s390_update_cpu_props(ms, cpu); } + +static void s390_change_topology(uint16_t core_id, + bool has_socket_id, uint16_t socket_id, + bool has_book_id, uint16_t book_id, + bool has_drawer_id, uint16_t drawer_id, + bool has_entitlement, + CpuS390Entitlement entitlement, + bool has_dedicated, bool dedicated, + Error **errp) +{ + MachineState *ms = current_machine; + int old_socket_entry; + int new_socket_entry; + bool report_needed; + S390CPU *cpu; + + cpu = s390_cpu_addr2state(core_id); + if (!cpu) { + error_setg(errp, "Core-id %d does not exist!", core_id); + return; + } + + /* Get attributes not provided from cpu and verify the new topology */ + if (!has_socket_id) { + socket_id = cpu->env.socket_id; + } + if (!has_book_id) { + book_id = cpu->env.book_id; + } + if (!has_drawer_id) { + drawer_id = cpu->env.drawer_id; + } + if (!has_dedicated) { + dedicated = cpu->env.dedicated; + } + + /* + * When the user specifies the entitlement as 'auto' on the command line, + * QEMU will set the entitlement as: + * Medium when the CPU is not dedicated. + * High when dedicated is true. + */ + if (!has_entitlement || entitlement == S390_CPU_ENTITLEMENT_AUTO) { + if (dedicated) { + entitlement = S390_CPU_ENTITLEMENT_HIGH; + } else { + entitlement = S390_CPU_ENTITLEMENT_MEDIUM; + } + } + + if (!s390_topology_check(socket_id, book_id, drawer_id, + entitlement, dedicated, errp)) { + return; + } + + /* Check for space on new socket */ + old_socket_entry = s390_socket_nb(cpu); + new_socket_entry = s390_socket_nb_from_ids(drawer_id, book_id, socket_id); + + if (new_socket_entry != old_socket_entry) { + if (s390_topology.cores_per_socket[new_socket_entry] >= + ms->smp.cores) { + error_setg(errp, "No more space on this socket"); + return; + } + /* Update the count of cores in sockets */ + s390_topology.cores_per_socket[new_socket_entry] += 1; + s390_topology.cores_per_socket[old_socket_entry] -= 1; + } + + /* Check if we will need to report the modified topology */ + report_needed = s390_topology_need_report(cpu, drawer_id, book_id, + socket_id, entitlement, + dedicated); + + /* All checks done, report new topology into the vCPU */ + cpu->env.drawer_id = drawer_id; + cpu->env.book_id = book_id; + cpu->env.socket_id = socket_id; + cpu->env.dedicated = dedicated; + cpu->env.entitlement = entitlement; + + /* topology tree is reflected in props */ + s390_update_cpu_props(ms, cpu); + + /* Advertise the topology change */ + if (report_needed) { + s390_cpu_topology_set_changed(true); + } +} + +void qmp_set_cpu_topology(uint16_t core, + bool has_socket, uint16_t socket, + bool has_book, uint16_t book, + bool has_drawer, uint16_t drawer, + bool has_entitlement, CpuS390Entitlement entitlement, + bool has_dedicated, bool dedicated, + Error **errp) +{ + if (!s390_has_topology()) { + error_setg(errp, "This machine doesn't support topology"); + return; + } + + s390_change_topology(core, has_socket, socket, has_book, book, + has_drawer, drawer, has_entitlement, entitlement, + has_dedicated, dedicated, errp); +}