The modification of the CPU attributes are done through a monitor command. It allows to move the core inside the topology tree to optimise 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 is made experimental for the moment. Signed-off-by: Pierre Morel <pmorel@xxxxxxxxxxxxx> --- qapi/machine-target.json | 29 +++++++++++++ include/monitor/hmp.h | 1 + hw/s390x/cpu-topology.c | 88 ++++++++++++++++++++++++++++++++++++++++ hmp-commands.hx | 16 ++++++++ 4 files changed, 134 insertions(+) diff --git a/qapi/machine-target.json b/qapi/machine-target.json index 2e267fa458..58df0f5061 100644 --- a/qapi/machine-target.json +++ b/qapi/machine-target.json @@ -342,3 +342,32 @@ 'TARGET_S390X', 'TARGET_MIPS', 'TARGET_LOONGARCH64' ] } } + +## +# @x-set-cpu-topology: +# +# @core: the vCPU ID to be moved +# @socket: the destination socket where to move the vCPU +# @book: the destination book where to move the vCPU +# @drawer: the destination drawer where to move the vCPU +# @polarity: optional polarity, default is last polarity set by the guest +# @dedicated: optional, if the vCPU is dedicated to a real CPU +# +# Modifies the topology by moving the CPU inside the topology +# tree or by changing a modifier attribute of a CPU. +# +# Returns: Nothing on success, the reason on failure. +# +# Since: <next qemu stable release, eg. 1.0> +## +{ 'command': 'x-set-cpu-topology', + 'data': { + 'core': 'int', + 'socket': 'int', + 'book': 'int', + 'drawer': 'int', + '*polarity': 'int', + '*dedicated': 'bool' + }, + 'if': { 'all': [ 'TARGET_S390X', 'CONFIG_KVM' ] } +} diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h index 1b3bdcb446..12827479cf 100644 --- a/include/monitor/hmp.h +++ b/include/monitor/hmp.h @@ -151,5 +151,6 @@ void hmp_human_readable_text_helper(Monitor *mon, HumanReadableText *(*qmp_handler)(Error **)); void hmp_info_stats(Monitor *mon, const QDict *qdict); void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict); +void hmp_x_set_cpu_topology(Monitor *mon, const QDict *qdict); #endif diff --git a/hw/s390x/cpu-topology.c b/hw/s390x/cpu-topology.c index c33378577b..6c50050991 100644 --- a/hw/s390x/cpu-topology.c +++ b/hw/s390x/cpu-topology.c @@ -18,6 +18,10 @@ #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" +#include "qapi/qmp/qdict.h" +#include "monitor/hmp.h" +#include "monitor/monitor.h" /* * s390_topology is used to keep the topology information. @@ -379,3 +383,87 @@ void s390_topology_set_cpu(MachineState *ms, S390CPU *cpu, Error **errp) /* topology tree is reflected in props */ s390_update_cpu_props(ms, cpu); } + +/* + * qmp and hmp implementations + */ + +static void s390_change_topology(int64_t core_id, int64_t socket_id, + int64_t book_id, int64_t drawer_id, + int64_t polarity, bool dedicated, + Error **errp) +{ + MachineState *ms = current_machine; + S390CPU *cpu; + ERRP_GUARD(); + + cpu = (S390CPU *)ms->possible_cpus->cpus[core_id].cpu; + if (!cpu) { + error_setg(errp, "Core-id %ld does not exist!", core_id); + return; + } + + /* Verify the new topology */ + s390_topology_check(cpu, errp); + if (*errp) { + return; + } + + /* Move the CPU into its new socket */ + s390_set_core_in_socket(cpu, drawer_id, book_id, socket_id, true, errp); + + /* All checks done, report topology in environment */ + 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 = polarity; + + /* topology tree is reflected in props */ + s390_update_cpu_props(ms, cpu); + + /* Advertise the topology change */ + s390_cpu_topology_set_modified(); +} + +void qmp_x_set_cpu_topology(int64_t core, int64_t socket, + int64_t book, int64_t drawer, + bool has_polarity, int64_t polarity, + bool has_dedicated, bool dedicated, + Error **errp) +{ + ERRP_GUARD(); + + if (!s390_has_topology()) { + error_setg(errp, "This machine doesn't support topology"); + return; + } + if (!has_polarity) { + polarity = POLARITY_VERTICAL_MEDIUM; + } + if (!has_dedicated) { + dedicated = false; + } + s390_change_topology(core, socket, book, drawer, polarity, dedicated, errp); +} + +void hmp_x_set_cpu_topology(Monitor *mon, const QDict *qdict) +{ + const int64_t core = qdict_get_int(qdict, "core"); + const int64_t socket = qdict_get_int(qdict, "socket"); + const int64_t book = qdict_get_int(qdict, "book"); + const int64_t drawer = qdict_get_int(qdict, "drawer"); + bool has_polarity = qdict_haskey(qdict, "polarity"); + const int64_t polarity = qdict_get_try_int(qdict, "polarity", 0); + bool has_dedicated = qdict_haskey(qdict, "dedicated"); + const bool dedicated = qdict_get_try_bool(qdict, "dedicated", false); + Error *local_err = NULL; + + qmp_x_set_cpu_topology(core, socket, book, drawer, + has_polarity, polarity, + has_dedicated, dedicated, + &local_err); + if (hmp_handle_error(mon, local_err)) { + return; + } +} diff --git a/hmp-commands.hx b/hmp-commands.hx index 673e39a697..bb3c908356 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1815,3 +1815,19 @@ SRST Dump the FDT in dtb format to *filename*. ERST #endif + +#if defined(TARGET_S390X) && defined(CONFIG_KVM) + { + .name = "x-set-cpu-topology", + .args_type = "core:l,socket:l,book:l,drawer:l,polarity:l?,dedicated:b?", + .params = "core socket book drawer [polarity] [dedicated]", + .help = "Move CPU 'core' to 'socket/book/drawer' " + "optionaly modifies polarity and dedication", + .cmd = hmp_x_set_cpu_topology, + }, + +SRST +``x-set-cpu-topology`` *core* *socket* *book* *drawer* *polarity* *dedicated* + Moves the CPU *core* to *socket* *book* *drawer* with *polarity* *dedicated*. +ERST +#endif -- 2.31.1