mirror of
https://github.com/qemu/qemu.git
synced 2025-08-13 18:46:38 +00:00
Accelerators patches
- Unify x86/arm hw/xen/arch_hvm.h header
- Move non-system-specific 'accel/accel-ops.h' and 'accel-cpu-ops.h' to accel/
- Move KVM definitions qapi/accelerator.json
- Add @qom-type field to CpuInfoFast QAPI structure
- Display CPU model name in 'info cpus' HMP command
- Introduce @x-accel-stats QMP command
- Add 'info accel' on HMP
- Improve qemu_add_vm_change_state_handler*() docstring
- Extract TCG statistic related code to tcg-stats.c
- Implement AccelClass::get_[vcpu]_stats() handlers for TCG and HVF
- Do not dump NaN in TCG statistics
- Revert incomplete "accel/tcg: Unregister the RCU before exiting RR thread"
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmh2r4UACgkQ4+MsLN6t
wN5i6xAAkOvwFh1GmsPUdz5RxzsWoIUDvyENg6E8Axwe5tSEMRFiPjabbTQJomQg
GZt75XIS24LZFZ+hvqrLSA+dFgXTgWv08ZE81EjwjmAMBlLCOPhCgeN6C1p8100Y
scSvRJbP9k9lpA5K7et/1X4AkK2cZyh+LGJgCjr2Al2mbERpPueDF8fxqeohFvXQ
nTSks4XlA0yQ06+9r49aQAiuXvgg9lDT1wIglD2HEV7vOVs/ud+yyL8+z5YMeFzx
pSIc6wDu4PqdA46w4MZs90uTy7S/PMvBiYDEiV3tKzg0MLttvFGlT58/YjVtguTP
mNkfwIEwQtDQzoxsFIJO7yBTlTRBs95V4aIVk3pB+Gb/bideRPIkeVQvgMSEBKj7
N0pEXWOxfB9iIWO6b1utYpQ4uxeDOU/8DPUCit1IBbNgKTaJkJb77fboYk7NaB0K
KEtObAk6jMatB/xr+vUFWc4sMk9wlm72w8wcQzgKZ0xV2U3d1/Y/9nS4GvI510ev
TRQ3mKj7N319uCeId1czF6W8rillCJ2u8ZK53u+Nfp7R3PbsRSMc6IDJ1UdDUlyR
HFcWHxbcbEGhe8SnFGab4Qd6fWChcn2EaEoAJJz+Rqv0k3zcwqccNM5waCABAjTE
0S22JIHePJKcpkMLGq3EOUAQuu+8Zsol7gPCLxSAMclVqPTl9ck=
=rAav
-----END PGP SIGNATURE-----
Merge tag 'accel-20250715' of https://github.com/philmd/qemu into staging
Accelerators patches
- Unify x86/arm hw/xen/arch_hvm.h header
- Move non-system-specific 'accel/accel-ops.h' and 'accel-cpu-ops.h' to accel/
- Move KVM definitions qapi/accelerator.json
- Add @qom-type field to CpuInfoFast QAPI structure
- Display CPU model name in 'info cpus' HMP command
- Introduce @x-accel-stats QMP command
- Add 'info accel' on HMP
- Improve qemu_add_vm_change_state_handler*() docstring
- Extract TCG statistic related code to tcg-stats.c
- Implement AccelClass::get_[vcpu]_stats() handlers for TCG and HVF
- Do not dump NaN in TCG statistics
- Revert incomplete "accel/tcg: Unregister the RCU before exiting RR thread"
# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmh2r4UACgkQ4+MsLN6t
# wN5i6xAAkOvwFh1GmsPUdz5RxzsWoIUDvyENg6E8Axwe5tSEMRFiPjabbTQJomQg
# GZt75XIS24LZFZ+hvqrLSA+dFgXTgWv08ZE81EjwjmAMBlLCOPhCgeN6C1p8100Y
# scSvRJbP9k9lpA5K7et/1X4AkK2cZyh+LGJgCjr2Al2mbERpPueDF8fxqeohFvXQ
# nTSks4XlA0yQ06+9r49aQAiuXvgg9lDT1wIglD2HEV7vOVs/ud+yyL8+z5YMeFzx
# pSIc6wDu4PqdA46w4MZs90uTy7S/PMvBiYDEiV3tKzg0MLttvFGlT58/YjVtguTP
# mNkfwIEwQtDQzoxsFIJO7yBTlTRBs95V4aIVk3pB+Gb/bideRPIkeVQvgMSEBKj7
# N0pEXWOxfB9iIWO6b1utYpQ4uxeDOU/8DPUCit1IBbNgKTaJkJb77fboYk7NaB0K
# KEtObAk6jMatB/xr+vUFWc4sMk9wlm72w8wcQzgKZ0xV2U3d1/Y/9nS4GvI510ev
# TRQ3mKj7N319uCeId1czF6W8rillCJ2u8ZK53u+Nfp7R3PbsRSMc6IDJ1UdDUlyR
# HFcWHxbcbEGhe8SnFGab4Qd6fWChcn2EaEoAJJz+Rqv0k3zcwqccNM5waCABAjTE
# 0S22JIHePJKcpkMLGq3EOUAQuu+8Zsol7gPCLxSAMclVqPTl9ck=
# =rAav
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 15 Jul 2025 15:44:05 EDT
# gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE
* tag 'accel-20250715' of https://github.com/philmd/qemu:
system/runstate: Document qemu_add_vm_change_state_handler_prio* in hdr
system/runstate: Document qemu_add_vm_change_state_handler()
accel/hvf: Implement AccelClass::get_vcpu_stats() handler
accel/tcg: Implement AccelClass::get_stats() handler
accel/tcg: Propagate AccelState to dump_accel_info()
accel/system: Add 'info accel' on human monitor
accel/system: Introduce @x-accel-stats QMP command
accel/tcg: Extract statistic related code to tcg-stats.c
Revert "accel/tcg: Unregister the RCU before exiting RR thread"
accel: Extract AccelClass definition to 'accel/accel-ops.h'
accel: Rename 'system/accel-ops.h' -> 'accel/accel-cpu-ops.h'
accel/tcg: Do not dump NaN statistics
hw/core/machine: Display CPU model name in 'info cpus' command
qapi/machine: Add @qom-type field to CpuInfoFast structure
qapi/accel: Move definitions related to accelerators in their own file
hw/arm/xen-pvh: Remove unnecessary 'hw/xen/arch_hvm.h' header
hw/xen/arch_hvm: Unify x86 and ARM variants
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Conflicts:
qapi/machine.json
Commit 0462da9d6b
("qapi: remove trivial "Returns:" sections")
removed trivial "Returns:". This caused a conflict with the move from
machine.json to accelerator.json.
This commit is contained in:
commit
f96b157ebb
@ -502,13 +502,14 @@ F: include/exec/target_long.h
|
|||||||
F: include/qemu/accel.h
|
F: include/qemu/accel.h
|
||||||
F: include/system/accel-*.h
|
F: include/system/accel-*.h
|
||||||
F: include/system/cpus.h
|
F: include/system/cpus.h
|
||||||
F: include/accel/accel-cpu*.h
|
F: include/accel/accel-*.h
|
||||||
F: accel/accel-*.?
|
F: accel/accel-*.?
|
||||||
F: accel/dummy-cpus.?
|
F: accel/dummy-cpus.?
|
||||||
F: accel/Makefile.objs
|
F: accel/Makefile.objs
|
||||||
F: accel/stubs/Makefile.objs
|
F: accel/stubs/Makefile.objs
|
||||||
F: cpu-common.c
|
F: cpu-common.c
|
||||||
F: cpu-target.c
|
F: cpu-target.c
|
||||||
|
F: qapi/accelerator.json
|
||||||
F: system/cpus.c
|
F: system/cpus.c
|
||||||
|
|
||||||
Apple Silicon HVF CPUs
|
Apple Silicon HVF CPUs
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/accel.h"
|
#include "qemu/accel.h"
|
||||||
#include "qemu/target-info.h"
|
#include "qemu/target-info.h"
|
||||||
|
#include "accel/accel-ops.h"
|
||||||
#include "accel/accel-cpu.h"
|
#include "accel/accel-cpu.h"
|
||||||
|
#include "accel/accel-cpu-ops.h"
|
||||||
#include "accel-internal.h"
|
#include "accel-internal.h"
|
||||||
|
|
||||||
/* Lookup AccelClass from opt_name. Returns NULL if not found */
|
/* Lookup AccelClass from opt_name. Returns NULL if not found */
|
||||||
|
35
accel/accel-qmp.c
Normal file
35
accel/accel-qmp.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* QMP commands related to accelerators
|
||||||
|
*
|
||||||
|
* Copyright (c) Linaro
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/accel.h"
|
||||||
|
#include "qapi/type-helpers.h"
|
||||||
|
#include "qapi/qapi-commands-accelerator.h"
|
||||||
|
#include "accel/accel-ops.h"
|
||||||
|
#include "accel/accel-cpu-ops.h"
|
||||||
|
#include "hw/core/cpu.h"
|
||||||
|
|
||||||
|
HumanReadableText *qmp_x_accel_stats(Error **errp)
|
||||||
|
{
|
||||||
|
AccelState *accel = current_accel();
|
||||||
|
AccelClass *acc = ACCEL_GET_CLASS(accel);
|
||||||
|
g_autoptr(GString) buf = g_string_new("");
|
||||||
|
|
||||||
|
if (acc->get_stats) {
|
||||||
|
acc->get_stats(accel, buf);
|
||||||
|
}
|
||||||
|
if (acc->ops->get_vcpu_stats) {
|
||||||
|
CPUState *cpu;
|
||||||
|
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
acc->ops->get_vcpu_stats(cpu, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return human_readable_text_from_str(buf);
|
||||||
|
}
|
@ -25,8 +25,12 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/accel.h"
|
#include "qemu/accel.h"
|
||||||
|
#include "qapi/qapi-commands-accelerator.h"
|
||||||
|
#include "monitor/monitor.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "system/accel-ops.h"
|
#include "hw/core/cpu.h"
|
||||||
|
#include "accel/accel-ops.h"
|
||||||
|
#include "accel/accel-cpu-ops.h"
|
||||||
#include "system/cpus.h"
|
#include "system/cpus.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "accel-internal.h"
|
#include "accel-internal.h"
|
||||||
@ -101,11 +105,17 @@ void accel_init_ops_interfaces(AccelClass *ac)
|
|||||||
cpus_register_accel(ops);
|
cpus_register_accel(ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void accel_ops_class_init(ObjectClass *oc, const void *data)
|
||||||
|
{
|
||||||
|
monitor_register_hmp_info_hrt("accel", qmp_x_accel_stats);
|
||||||
|
}
|
||||||
|
|
||||||
static const TypeInfo accel_ops_type_info = {
|
static const TypeInfo accel_ops_type_info = {
|
||||||
.name = TYPE_ACCEL_OPS,
|
.name = TYPE_ACCEL_OPS,
|
||||||
.parent = TYPE_OBJECT,
|
.parent = TYPE_OBJECT,
|
||||||
.abstract = true,
|
.abstract = true,
|
||||||
.class_size = sizeof(AccelOpsClass),
|
.class_size = sizeof(AccelOpsClass),
|
||||||
|
.class_init = accel_ops_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void accel_system_register_types(void)
|
static void accel_system_register_types(void)
|
||||||
|
@ -54,10 +54,11 @@
|
|||||||
#include "gdbstub/enums.h"
|
#include "gdbstub/enums.h"
|
||||||
#include "exec/cpu-common.h"
|
#include "exec/cpu-common.h"
|
||||||
#include "hw/core/cpu.h"
|
#include "hw/core/cpu.h"
|
||||||
#include "system/accel-ops.h"
|
#include "accel/accel-cpu-ops.h"
|
||||||
#include "system/cpus.h"
|
#include "system/cpus.h"
|
||||||
#include "system/hvf.h"
|
#include "system/hvf.h"
|
||||||
#include "system/hvf_int.h"
|
#include "system/hvf_int.h"
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
|
||||||
HVFState *hvf_state;
|
HVFState *hvf_state;
|
||||||
|
|
||||||
@ -118,6 +119,12 @@ static void dummy_signal(int sig)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void do_hvf_get_vcpu_exec_time(CPUState *cpu, run_on_cpu_data arg)
|
||||||
|
{
|
||||||
|
int r = hv_vcpu_get_exec_time(cpu->accel->fd, arg.host_ptr);
|
||||||
|
assert_hvf_ok(r);
|
||||||
|
}
|
||||||
|
|
||||||
static void hvf_vcpu_destroy(CPUState *cpu)
|
static void hvf_vcpu_destroy(CPUState *cpu)
|
||||||
{
|
{
|
||||||
hv_return_t ret = hv_vcpu_destroy(cpu->accel->fd);
|
hv_return_t ret = hv_vcpu_destroy(cpu->accel->fd);
|
||||||
@ -347,6 +354,21 @@ static void hvf_remove_all_breakpoints(CPUState *cpu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hvf_get_vcpu_stats(CPUState *cpu, GString *buf)
|
||||||
|
{
|
||||||
|
uint64_t time_mach; /* units of mach_absolute_time() */
|
||||||
|
|
||||||
|
run_on_cpu(cpu, do_hvf_get_vcpu_exec_time, RUN_ON_CPU_HOST_PTR(&time_mach));
|
||||||
|
|
||||||
|
mach_timebase_info_data_t timebase;
|
||||||
|
mach_timebase_info(&timebase);
|
||||||
|
uint64_t time_ns = time_mach * timebase.numer / timebase.denom;
|
||||||
|
|
||||||
|
g_string_append_printf(buf, "HVF cumulative execution time: %llu.%.3llus\n",
|
||||||
|
time_ns / 1000000000,
|
||||||
|
(time_ns % 1000000000) / 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
static void hvf_accel_ops_class_init(ObjectClass *oc, const void *data)
|
static void hvf_accel_ops_class_init(ObjectClass *oc, const void *data)
|
||||||
{
|
{
|
||||||
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||||
@ -365,7 +387,10 @@ static void hvf_accel_ops_class_init(ObjectClass *oc, const void *data)
|
|||||||
ops->remove_all_breakpoints = hvf_remove_all_breakpoints;
|
ops->remove_all_breakpoints = hvf_remove_all_breakpoints;
|
||||||
ops->update_guest_debug = hvf_update_guest_debug;
|
ops->update_guest_debug = hvf_update_guest_debug;
|
||||||
ops->supports_guest_debug = hvf_arch_supports_guest_debug;
|
ops->supports_guest_debug = hvf_arch_supports_guest_debug;
|
||||||
|
|
||||||
|
ops->get_vcpu_stats = hvf_get_vcpu_stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const TypeInfo hvf_accel_ops_type = {
|
static const TypeInfo hvf_accel_ops_type = {
|
||||||
.name = ACCEL_OPS_NAME("hvf"),
|
.name = ACCEL_OPS_NAME("hvf"),
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
#include "accel/accel-ops.h"
|
||||||
#include "system/address-spaces.h"
|
#include "system/address-spaces.h"
|
||||||
#include "system/memory.h"
|
#include "system/memory.h"
|
||||||
#include "system/hvf.h"
|
#include "system/hvf.h"
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
#include "system/accel-ops.h"
|
#include "accel/accel-cpu-ops.h"
|
||||||
#include "system/kvm.h"
|
#include "system/kvm.h"
|
||||||
#include "system/kvm_int.h"
|
#include "system/kvm_int.h"
|
||||||
#include "system/runstate.h"
|
#include "system/runstate.h"
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "system/runstate.h"
|
#include "system/runstate.h"
|
||||||
#include "system/cpus.h"
|
#include "system/cpus.h"
|
||||||
#include "system/accel-blocker.h"
|
#include "system/accel-blocker.h"
|
||||||
|
#include "accel/accel-ops.h"
|
||||||
#include "qemu/bswap.h"
|
#include "qemu/bswap.h"
|
||||||
#include "exec/tswap.h"
|
#include "exec/tswap.h"
|
||||||
#include "system/memory.h"
|
#include "system/memory.h"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
common_ss.add(files('accel-common.c'))
|
common_ss.add(files('accel-common.c'))
|
||||||
specific_ss.add(files('accel-target.c'))
|
specific_ss.add(files('accel-target.c'))
|
||||||
system_ss.add(files('accel-system.c', 'accel-blocker.c'))
|
system_ss.add(files('accel-system.c', 'accel-blocker.c', 'accel-qmp.c'))
|
||||||
user_ss.add(files('accel-user.c'))
|
user_ss.add(files('accel-user.c'))
|
||||||
|
|
||||||
subdir('tcg')
|
subdir('tcg')
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
#include "qemu/option.h"
|
#include "qemu/option.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
#include "qemu/accel.h"
|
#include "qemu/accel.h"
|
||||||
#include "system/accel-ops.h"
|
#include "accel/accel-ops.h"
|
||||||
|
#include "accel/accel-cpu-ops.h"
|
||||||
#include "system/qtest.h"
|
#include "system/qtest.h"
|
||||||
#include "system/cpus.h"
|
#include "system/cpus.h"
|
||||||
#include "qemu/guest-random.h"
|
#include "qemu/guest-random.h"
|
||||||
|
@ -139,6 +139,6 @@ G_NORETURN void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr);
|
|||||||
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
|
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
|
||||||
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr);
|
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr);
|
||||||
|
|
||||||
void tcg_dump_stats(GString *buf);
|
void tcg_get_stats(AccelState *accel, GString *buf);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,6 +11,7 @@ tcg_ss.add(files(
|
|||||||
'tcg-runtime-gvec.c',
|
'tcg-runtime-gvec.c',
|
||||||
'tb-maint.c',
|
'tb-maint.c',
|
||||||
'tcg-all.c',
|
'tcg-all.c',
|
||||||
|
'tcg-stats.c',
|
||||||
'translate-all.c',
|
'translate-all.c',
|
||||||
'translator.c',
|
'translator.c',
|
||||||
))
|
))
|
||||||
|
@ -7,205 +7,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/accel.h"
|
|
||||||
#include "qemu/qht.h"
|
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qapi/type-helpers.h"
|
#include "qapi/type-helpers.h"
|
||||||
#include "qapi/qapi-commands-machine.h"
|
#include "qapi/qapi-commands-machine.h"
|
||||||
#include "monitor/monitor.h"
|
#include "monitor/monitor.h"
|
||||||
#include "system/cpu-timers.h"
|
|
||||||
#include "exec/icount.h"
|
|
||||||
#include "system/tcg.h"
|
#include "system/tcg.h"
|
||||||
#include "tcg/tcg.h"
|
#include "tcg/tcg.h"
|
||||||
#include "internal-common.h"
|
#include "internal-common.h"
|
||||||
#include "tb-context.h"
|
|
||||||
|
|
||||||
|
|
||||||
static void dump_drift_info(GString *buf)
|
|
||||||
{
|
|
||||||
if (!icount_enabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_string_append_printf(buf, "Host - Guest clock %"PRIi64" ms\n",
|
|
||||||
(cpu_get_clock() - icount_get()) / SCALE_MS);
|
|
||||||
if (icount_align_option) {
|
|
||||||
g_string_append_printf(buf, "Max guest delay %"PRIi64" ms\n",
|
|
||||||
-max_delay / SCALE_MS);
|
|
||||||
g_string_append_printf(buf, "Max guest advance %"PRIi64" ms\n",
|
|
||||||
max_advance / SCALE_MS);
|
|
||||||
} else {
|
|
||||||
g_string_append_printf(buf, "Max guest delay NA\n");
|
|
||||||
g_string_append_printf(buf, "Max guest advance NA\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dump_accel_info(GString *buf)
|
|
||||||
{
|
|
||||||
AccelState *accel = current_accel();
|
|
||||||
bool one_insn_per_tb = object_property_get_bool(OBJECT(accel),
|
|
||||||
"one-insn-per-tb",
|
|
||||||
&error_fatal);
|
|
||||||
|
|
||||||
g_string_append_printf(buf, "Accelerator settings:\n");
|
|
||||||
g_string_append_printf(buf, "one-insn-per-tb: %s\n\n",
|
|
||||||
one_insn_per_tb ? "on" : "off");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_qht_statistics(struct qht_stats hst, GString *buf)
|
|
||||||
{
|
|
||||||
uint32_t hgram_opts;
|
|
||||||
size_t hgram_bins;
|
|
||||||
char *hgram;
|
|
||||||
|
|
||||||
if (!hst.head_buckets) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
g_string_append_printf(buf, "TB hash buckets %zu/%zu "
|
|
||||||
"(%0.2f%% head buckets used)\n",
|
|
||||||
hst.used_head_buckets, hst.head_buckets,
|
|
||||||
(double)hst.used_head_buckets /
|
|
||||||
hst.head_buckets * 100);
|
|
||||||
|
|
||||||
hgram_opts = QDIST_PR_BORDER | QDIST_PR_LABELS;
|
|
||||||
hgram_opts |= QDIST_PR_100X | QDIST_PR_PERCENT;
|
|
||||||
if (qdist_xmax(&hst.occupancy) - qdist_xmin(&hst.occupancy) == 1) {
|
|
||||||
hgram_opts |= QDIST_PR_NODECIMAL;
|
|
||||||
}
|
|
||||||
hgram = qdist_pr(&hst.occupancy, 10, hgram_opts);
|
|
||||||
g_string_append_printf(buf, "TB hash occupancy %0.2f%% avg chain occ. "
|
|
||||||
"Histogram: %s\n",
|
|
||||||
qdist_avg(&hst.occupancy) * 100, hgram);
|
|
||||||
g_free(hgram);
|
|
||||||
|
|
||||||
hgram_opts = QDIST_PR_BORDER | QDIST_PR_LABELS;
|
|
||||||
hgram_bins = qdist_xmax(&hst.chain) - qdist_xmin(&hst.chain);
|
|
||||||
if (hgram_bins > 10) {
|
|
||||||
hgram_bins = 10;
|
|
||||||
} else {
|
|
||||||
hgram_bins = 0;
|
|
||||||
hgram_opts |= QDIST_PR_NODECIMAL | QDIST_PR_NOBINRANGE;
|
|
||||||
}
|
|
||||||
hgram = qdist_pr(&hst.chain, hgram_bins, hgram_opts);
|
|
||||||
g_string_append_printf(buf, "TB hash avg chain %0.3f buckets. "
|
|
||||||
"Histogram: %s\n",
|
|
||||||
qdist_avg(&hst.chain), hgram);
|
|
||||||
g_free(hgram);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct tb_tree_stats {
|
|
||||||
size_t nb_tbs;
|
|
||||||
size_t host_size;
|
|
||||||
size_t target_size;
|
|
||||||
size_t max_target_size;
|
|
||||||
size_t direct_jmp_count;
|
|
||||||
size_t direct_jmp2_count;
|
|
||||||
size_t cross_page;
|
|
||||||
};
|
|
||||||
|
|
||||||
static gboolean tb_tree_stats_iter(gpointer key, gpointer value, gpointer data)
|
|
||||||
{
|
|
||||||
const TranslationBlock *tb = value;
|
|
||||||
struct tb_tree_stats *tst = data;
|
|
||||||
|
|
||||||
tst->nb_tbs++;
|
|
||||||
tst->host_size += tb->tc.size;
|
|
||||||
tst->target_size += tb->size;
|
|
||||||
if (tb->size > tst->max_target_size) {
|
|
||||||
tst->max_target_size = tb->size;
|
|
||||||
}
|
|
||||||
if (tb->page_addr[1] != -1) {
|
|
||||||
tst->cross_page++;
|
|
||||||
}
|
|
||||||
if (tb->jmp_reset_offset[0] != TB_JMP_OFFSET_INVALID) {
|
|
||||||
tst->direct_jmp_count++;
|
|
||||||
if (tb->jmp_reset_offset[1] != TB_JMP_OFFSET_INVALID) {
|
|
||||||
tst->direct_jmp2_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tlb_flush_counts(size_t *pfull, size_t *ppart, size_t *pelide)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
size_t full = 0, part = 0, elide = 0;
|
|
||||||
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
full += qatomic_read(&cpu->neg.tlb.c.full_flush_count);
|
|
||||||
part += qatomic_read(&cpu->neg.tlb.c.part_flush_count);
|
|
||||||
elide += qatomic_read(&cpu->neg.tlb.c.elide_flush_count);
|
|
||||||
}
|
|
||||||
*pfull = full;
|
|
||||||
*ppart = part;
|
|
||||||
*pelide = elide;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tcg_dump_flush_info(GString *buf)
|
|
||||||
{
|
|
||||||
size_t flush_full, flush_part, flush_elide;
|
|
||||||
|
|
||||||
g_string_append_printf(buf, "TB flush count %u\n",
|
|
||||||
qatomic_read(&tb_ctx.tb_flush_count));
|
|
||||||
g_string_append_printf(buf, "TB invalidate count %u\n",
|
|
||||||
qatomic_read(&tb_ctx.tb_phys_invalidate_count));
|
|
||||||
|
|
||||||
tlb_flush_counts(&flush_full, &flush_part, &flush_elide);
|
|
||||||
g_string_append_printf(buf, "TLB full flushes %zu\n", flush_full);
|
|
||||||
g_string_append_printf(buf, "TLB partial flushes %zu\n", flush_part);
|
|
||||||
g_string_append_printf(buf, "TLB elided flushes %zu\n", flush_elide);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dump_exec_info(GString *buf)
|
|
||||||
{
|
|
||||||
struct tb_tree_stats tst = {};
|
|
||||||
struct qht_stats hst;
|
|
||||||
size_t nb_tbs;
|
|
||||||
|
|
||||||
tcg_tb_foreach(tb_tree_stats_iter, &tst);
|
|
||||||
nb_tbs = tst.nb_tbs;
|
|
||||||
/* XXX: avoid using doubles ? */
|
|
||||||
g_string_append_printf(buf, "Translation buffer state:\n");
|
|
||||||
/*
|
|
||||||
* Report total code size including the padding and TB structs;
|
|
||||||
* otherwise users might think "-accel tcg,tb-size" is not honoured.
|
|
||||||
* For avg host size we use the precise numbers from tb_tree_stats though.
|
|
||||||
*/
|
|
||||||
g_string_append_printf(buf, "gen code size %zu/%zu\n",
|
|
||||||
tcg_code_size(), tcg_code_capacity());
|
|
||||||
g_string_append_printf(buf, "TB count %zu\n", nb_tbs);
|
|
||||||
g_string_append_printf(buf, "TB avg target size %zu max=%zu bytes\n",
|
|
||||||
nb_tbs ? tst.target_size / nb_tbs : 0,
|
|
||||||
tst.max_target_size);
|
|
||||||
g_string_append_printf(buf, "TB avg host size %zu bytes "
|
|
||||||
"(expansion ratio: %0.1f)\n",
|
|
||||||
nb_tbs ? tst.host_size / nb_tbs : 0,
|
|
||||||
tst.target_size ?
|
|
||||||
(double)tst.host_size / tst.target_size : 0);
|
|
||||||
g_string_append_printf(buf, "cross page TB count %zu (%zu%%)\n",
|
|
||||||
tst.cross_page,
|
|
||||||
nb_tbs ? (tst.cross_page * 100) / nb_tbs : 0);
|
|
||||||
g_string_append_printf(buf, "direct jump count %zu (%zu%%) "
|
|
||||||
"(2 jumps=%zu %zu%%)\n",
|
|
||||||
tst.direct_jmp_count,
|
|
||||||
nb_tbs ? (tst.direct_jmp_count * 100) / nb_tbs : 0,
|
|
||||||
tst.direct_jmp2_count,
|
|
||||||
nb_tbs ? (tst.direct_jmp2_count * 100) / nb_tbs : 0);
|
|
||||||
|
|
||||||
qht_statistics_init(&tb_ctx.htable, &hst);
|
|
||||||
print_qht_statistics(hst, buf);
|
|
||||||
qht_statistics_destroy(&hst);
|
|
||||||
|
|
||||||
g_string_append_printf(buf, "\nStatistics:\n");
|
|
||||||
tcg_dump_flush_info(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tcg_dump_stats(GString *buf)
|
|
||||||
{
|
|
||||||
dump_accel_info(buf);
|
|
||||||
dump_exec_info(buf);
|
|
||||||
dump_drift_info(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
HumanReadableText *qmp_x_query_jit(Error **errp)
|
HumanReadableText *qmp_x_query_jit(Error **errp)
|
||||||
{
|
{
|
||||||
|
@ -302,8 +302,6 @@ static void *rr_cpu_thread_fn(void *arg)
|
|||||||
rr_deal_with_unplugged_cpus();
|
rr_deal_with_unplugged_cpus();
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_unregister_thread();
|
|
||||||
|
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "system/accel-ops.h"
|
#include "accel/accel-ops.h"
|
||||||
|
#include "accel/accel-cpu-ops.h"
|
||||||
#include "system/tcg.h"
|
#include "system/tcg.h"
|
||||||
#include "system/replay.h"
|
#include "system/replay.h"
|
||||||
#include "exec/icount.h"
|
#include "exec/icount.h"
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "accel/accel-ops.h"
|
||||||
|
#include "accel/accel-cpu-ops.h"
|
||||||
#include "accel/tcg/cpu-ops.h"
|
#include "accel/tcg/cpu-ops.h"
|
||||||
#include "internal-common.h"
|
#include "internal-common.h"
|
||||||
|
|
||||||
@ -241,6 +243,7 @@ static void tcg_accel_class_init(ObjectClass *oc, const void *data)
|
|||||||
ac->init_machine = tcg_init_machine;
|
ac->init_machine = tcg_init_machine;
|
||||||
ac->cpu_common_realize = tcg_exec_realizefn;
|
ac->cpu_common_realize = tcg_exec_realizefn;
|
||||||
ac->cpu_common_unrealize = tcg_exec_unrealizefn;
|
ac->cpu_common_unrealize = tcg_exec_unrealizefn;
|
||||||
|
ac->get_stats = tcg_get_stats;
|
||||||
ac->allowed = &tcg_allowed;
|
ac->allowed = &tcg_allowed;
|
||||||
ac->gdbstub_supported_sstep_flags = tcg_gdbstub_supported_sstep_flags;
|
ac->gdbstub_supported_sstep_flags = tcg_gdbstub_supported_sstep_flags;
|
||||||
|
|
||||||
|
219
accel/tcg/tcg-stats.c
Normal file
219
accel/tcg/tcg-stats.c
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
*
|
||||||
|
* QEMU TCG statistics
|
||||||
|
*
|
||||||
|
* Copyright (c) 2003-2005 Fabrice Bellard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/accel.h"
|
||||||
|
#include "qemu/qht.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "system/cpu-timers.h"
|
||||||
|
#include "exec/icount.h"
|
||||||
|
#include "hw/core/cpu.h"
|
||||||
|
#include "tcg/tcg.h"
|
||||||
|
#include "internal-common.h"
|
||||||
|
#include "tb-context.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
static void dump_drift_info(GString *buf)
|
||||||
|
{
|
||||||
|
if (!icount_enabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_string_append_printf(buf, "Host - Guest clock %"PRIi64" ms\n",
|
||||||
|
(cpu_get_clock() - icount_get()) / SCALE_MS);
|
||||||
|
if (icount_align_option) {
|
||||||
|
g_string_append_printf(buf, "Max guest delay %"PRIi64" ms\n",
|
||||||
|
-max_delay / SCALE_MS);
|
||||||
|
g_string_append_printf(buf, "Max guest advance %"PRIi64" ms\n",
|
||||||
|
max_advance / SCALE_MS);
|
||||||
|
} else {
|
||||||
|
g_string_append_printf(buf, "Max guest delay NA\n");
|
||||||
|
g_string_append_printf(buf, "Max guest advance NA\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_accel_info(AccelState *accel, GString *buf)
|
||||||
|
{
|
||||||
|
bool one_insn_per_tb = object_property_get_bool(OBJECT(accel),
|
||||||
|
"one-insn-per-tb",
|
||||||
|
&error_fatal);
|
||||||
|
|
||||||
|
g_string_append_printf(buf, "Accelerator settings:\n");
|
||||||
|
g_string_append_printf(buf, "one-insn-per-tb: %s\n\n",
|
||||||
|
one_insn_per_tb ? "on" : "off");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_qht_statistics(struct qht_stats hst, GString *buf)
|
||||||
|
{
|
||||||
|
uint32_t hgram_opts;
|
||||||
|
size_t hgram_bins;
|
||||||
|
char *hgram;
|
||||||
|
double avg;
|
||||||
|
|
||||||
|
if (!hst.head_buckets) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_string_append_printf(buf, "TB hash buckets %zu/%zu "
|
||||||
|
"(%0.2f%% head buckets used)\n",
|
||||||
|
hst.used_head_buckets, hst.head_buckets,
|
||||||
|
(double)hst.used_head_buckets /
|
||||||
|
hst.head_buckets * 100);
|
||||||
|
|
||||||
|
hgram_opts = QDIST_PR_BORDER | QDIST_PR_LABELS;
|
||||||
|
hgram_opts |= QDIST_PR_100X | QDIST_PR_PERCENT;
|
||||||
|
if (qdist_xmax(&hst.occupancy) - qdist_xmin(&hst.occupancy) == 1) {
|
||||||
|
hgram_opts |= QDIST_PR_NODECIMAL;
|
||||||
|
}
|
||||||
|
hgram = qdist_pr(&hst.occupancy, 10, hgram_opts);
|
||||||
|
avg = qdist_avg(&hst.occupancy);
|
||||||
|
if (!isnan(avg)) {
|
||||||
|
g_string_append_printf(buf, "TB hash occupancy "
|
||||||
|
"%0.2f%% avg chain occ. "
|
||||||
|
"Histogram: %s\n",
|
||||||
|
avg * 100, hgram);
|
||||||
|
}
|
||||||
|
g_free(hgram);
|
||||||
|
|
||||||
|
hgram_opts = QDIST_PR_BORDER | QDIST_PR_LABELS;
|
||||||
|
hgram_bins = qdist_xmax(&hst.chain) - qdist_xmin(&hst.chain);
|
||||||
|
if (hgram_bins > 10) {
|
||||||
|
hgram_bins = 10;
|
||||||
|
} else {
|
||||||
|
hgram_bins = 0;
|
||||||
|
hgram_opts |= QDIST_PR_NODECIMAL | QDIST_PR_NOBINRANGE;
|
||||||
|
}
|
||||||
|
hgram = qdist_pr(&hst.chain, hgram_bins, hgram_opts);
|
||||||
|
avg = qdist_avg(&hst.chain);
|
||||||
|
if (!isnan(avg)) {
|
||||||
|
g_string_append_printf(buf, "TB hash avg chain %0.3f buckets. "
|
||||||
|
"Histogram: %s\n",
|
||||||
|
avg, hgram);
|
||||||
|
}
|
||||||
|
g_free(hgram);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tb_tree_stats {
|
||||||
|
size_t nb_tbs;
|
||||||
|
size_t host_size;
|
||||||
|
size_t target_size;
|
||||||
|
size_t max_target_size;
|
||||||
|
size_t direct_jmp_count;
|
||||||
|
size_t direct_jmp2_count;
|
||||||
|
size_t cross_page;
|
||||||
|
};
|
||||||
|
|
||||||
|
static gboolean tb_tree_stats_iter(gpointer key, gpointer value, gpointer data)
|
||||||
|
{
|
||||||
|
const TranslationBlock *tb = value;
|
||||||
|
struct tb_tree_stats *tst = data;
|
||||||
|
|
||||||
|
tst->nb_tbs++;
|
||||||
|
tst->host_size += tb->tc.size;
|
||||||
|
tst->target_size += tb->size;
|
||||||
|
if (tb->size > tst->max_target_size) {
|
||||||
|
tst->max_target_size = tb->size;
|
||||||
|
}
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
if (tb->page_addr[1] != -1) {
|
||||||
|
tst->cross_page++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (tb->jmp_reset_offset[0] != TB_JMP_OFFSET_INVALID) {
|
||||||
|
tst->direct_jmp_count++;
|
||||||
|
if (tb->jmp_reset_offset[1] != TB_JMP_OFFSET_INVALID) {
|
||||||
|
tst->direct_jmp2_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tlb_flush_counts(size_t *pfull, size_t *ppart, size_t *pelide)
|
||||||
|
{
|
||||||
|
CPUState *cpu;
|
||||||
|
size_t full = 0, part = 0, elide = 0;
|
||||||
|
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
full += qatomic_read(&cpu->neg.tlb.c.full_flush_count);
|
||||||
|
part += qatomic_read(&cpu->neg.tlb.c.part_flush_count);
|
||||||
|
elide += qatomic_read(&cpu->neg.tlb.c.elide_flush_count);
|
||||||
|
}
|
||||||
|
*pfull = full;
|
||||||
|
*ppart = part;
|
||||||
|
*pelide = elide;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_dump_flush_info(GString *buf)
|
||||||
|
{
|
||||||
|
size_t flush_full, flush_part, flush_elide;
|
||||||
|
|
||||||
|
g_string_append_printf(buf, "TB flush count %u\n",
|
||||||
|
qatomic_read(&tb_ctx.tb_flush_count));
|
||||||
|
g_string_append_printf(buf, "TB invalidate count %u\n",
|
||||||
|
qatomic_read(&tb_ctx.tb_phys_invalidate_count));
|
||||||
|
|
||||||
|
tlb_flush_counts(&flush_full, &flush_part, &flush_elide);
|
||||||
|
g_string_append_printf(buf, "TLB full flushes %zu\n", flush_full);
|
||||||
|
g_string_append_printf(buf, "TLB partial flushes %zu\n", flush_part);
|
||||||
|
g_string_append_printf(buf, "TLB elided flushes %zu\n", flush_elide);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_exec_info(GString *buf)
|
||||||
|
{
|
||||||
|
struct tb_tree_stats tst = {};
|
||||||
|
struct qht_stats hst;
|
||||||
|
size_t nb_tbs;
|
||||||
|
|
||||||
|
tcg_tb_foreach(tb_tree_stats_iter, &tst);
|
||||||
|
nb_tbs = tst.nb_tbs;
|
||||||
|
/* XXX: avoid using doubles ? */
|
||||||
|
g_string_append_printf(buf, "Translation buffer state:\n");
|
||||||
|
/*
|
||||||
|
* Report total code size including the padding and TB structs;
|
||||||
|
* otherwise users might think "-accel tcg,tb-size" is not honoured.
|
||||||
|
* For avg host size we use the precise numbers from tb_tree_stats though.
|
||||||
|
*/
|
||||||
|
g_string_append_printf(buf, "gen code size %zu/%zu\n",
|
||||||
|
tcg_code_size(), tcg_code_capacity());
|
||||||
|
g_string_append_printf(buf, "TB count %zu\n", nb_tbs);
|
||||||
|
g_string_append_printf(buf, "TB avg target size %zu max=%zu bytes\n",
|
||||||
|
nb_tbs ? tst.target_size / nb_tbs : 0,
|
||||||
|
tst.max_target_size);
|
||||||
|
g_string_append_printf(buf, "TB avg host size %zu bytes "
|
||||||
|
"(expansion ratio: %0.1f)\n",
|
||||||
|
nb_tbs ? tst.host_size / nb_tbs : 0,
|
||||||
|
tst.target_size ?
|
||||||
|
(double)tst.host_size / tst.target_size : 0);
|
||||||
|
g_string_append_printf(buf, "cross page TB count %zu (%zu%%)\n",
|
||||||
|
tst.cross_page,
|
||||||
|
nb_tbs ? (tst.cross_page * 100) / nb_tbs : 0);
|
||||||
|
g_string_append_printf(buf, "direct jump count %zu (%zu%%) "
|
||||||
|
"(2 jumps=%zu %zu%%)\n",
|
||||||
|
tst.direct_jmp_count,
|
||||||
|
nb_tbs ? (tst.direct_jmp_count * 100) / nb_tbs : 0,
|
||||||
|
tst.direct_jmp2_count,
|
||||||
|
nb_tbs ? (tst.direct_jmp2_count * 100) / nb_tbs : 0);
|
||||||
|
|
||||||
|
qht_statistics_init(&tb_ctx.htable, &hst);
|
||||||
|
print_qht_statistics(hst, buf);
|
||||||
|
qht_statistics_destroy(&hst);
|
||||||
|
|
||||||
|
g_string_append_printf(buf, "\nStatistics:\n");
|
||||||
|
tcg_dump_flush_info(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcg_get_stats(AccelState *accel, GString *buf)
|
||||||
|
{
|
||||||
|
dump_accel_info(accel, buf);
|
||||||
|
dump_exec_info(buf);
|
||||||
|
dump_drift_info(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcg_dump_stats(GString *buf)
|
||||||
|
{
|
||||||
|
tcg_get_stats(current_accel(), buf);
|
||||||
|
}
|
@ -19,7 +19,8 @@
|
|||||||
#include "chardev/char.h"
|
#include "chardev/char.h"
|
||||||
#include "qemu/accel.h"
|
#include "qemu/accel.h"
|
||||||
#include "accel/dummy-cpus.h"
|
#include "accel/dummy-cpus.h"
|
||||||
#include "system/accel-ops.h"
|
#include "accel/accel-ops.h"
|
||||||
|
#include "accel/accel-cpu-ops.h"
|
||||||
#include "system/cpus.h"
|
#include "system/cpus.h"
|
||||||
#include "system/xen.h"
|
#include "system/xen.h"
|
||||||
#include "system/runstate.h"
|
#include "system/runstate.h"
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include "qemu/plugin.h"
|
#include "qemu/plugin.h"
|
||||||
#include "user/guest-base.h"
|
#include "user/guest-base.h"
|
||||||
#include "user/page-protection.h"
|
#include "user/page-protection.h"
|
||||||
|
#include "accel/accel-ops.h"
|
||||||
#include "tcg/startup.h"
|
#include "tcg/startup.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
#include "qemu/envlist.h"
|
#include "qemu/envlist.h"
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "system/accel-ops.h"
|
#include "accel/accel-cpu-ops.h"
|
||||||
#include "system/cpus.h"
|
#include "system/cpus.h"
|
||||||
#include "exec/cpu-common.h"
|
#include "exec/cpu-common.h"
|
||||||
#include "exec/replay-core.h"
|
#include "exec/replay-core.h"
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
#include "gdbstub/commands.h"
|
#include "gdbstub/commands.h"
|
||||||
#include "exec/hwaddr.h"
|
#include "exec/hwaddr.h"
|
||||||
#include "exec/tb-flush.h"
|
#include "exec/tb-flush.h"
|
||||||
#include "system/accel-ops.h"
|
#include "accel/accel-ops.h"
|
||||||
|
#include "accel/accel-cpu-ops.h"
|
||||||
#include "system/cpus.h"
|
#include "system/cpus.h"
|
||||||
#include "system/runstate.h"
|
#include "system/runstate.h"
|
||||||
#include "system/replay.h"
|
#include "system/replay.h"
|
||||||
|
@ -267,6 +267,18 @@ ERST
|
|||||||
.cmd = hmp_info_sync_profile,
|
.cmd = hmp_info_sync_profile,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "accel",
|
||||||
|
.args_type = "",
|
||||||
|
.params = "",
|
||||||
|
.help = "show accelerator info",
|
||||||
|
},
|
||||||
|
|
||||||
|
SRST
|
||||||
|
``info accel``
|
||||||
|
Show accelerator info.
|
||||||
|
ERST
|
||||||
|
|
||||||
SRST
|
SRST
|
||||||
``info sync-profile [-m|-n]`` [*max*]
|
``info sync-profile [-m|-n]`` [*max*]
|
||||||
Show synchronization profiling info, up to *max* entries (default: 10),
|
Show synchronization profiling info, up to *max* entries (default: 10),
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "system/system.h"
|
#include "system/system.h"
|
||||||
#include "hw/xen/xen-pvh-common.h"
|
#include "hw/xen/xen-pvh-common.h"
|
||||||
#include "hw/xen/arch_hvm.h"
|
|
||||||
|
|
||||||
#define TYPE_XEN_ARM MACHINE_TYPE_NAME("xenpvh")
|
#define TYPE_XEN_ARM MACHINE_TYPE_NAME("xenpvh")
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "monitor/monitor.h"
|
#include "monitor/monitor.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qapi/qapi-builtin-visit.h"
|
#include "qapi/qapi-builtin-visit.h"
|
||||||
|
#include "qapi/qapi-commands-accelerator.h"
|
||||||
#include "qapi/qapi-commands-machine.h"
|
#include "qapi/qapi-commands-machine.h"
|
||||||
#include "qobject/qdict.h"
|
#include "qobject/qdict.h"
|
||||||
#include "qapi/string-output-visitor.h"
|
#include "qapi/string-output-visitor.h"
|
||||||
@ -32,6 +33,7 @@ void hmp_info_cpus(Monitor *mon, const QDict *qdict)
|
|||||||
cpu_list = qmp_query_cpus_fast(NULL);
|
cpu_list = qmp_query_cpus_fast(NULL);
|
||||||
|
|
||||||
for (cpu = cpu_list; cpu; cpu = cpu->next) {
|
for (cpu = cpu_list; cpu; cpu = cpu->next) {
|
||||||
|
g_autofree char *cpu_model = cpu_model_from_type(cpu->value->qom_type);
|
||||||
int active = ' ';
|
int active = ' ';
|
||||||
|
|
||||||
if (cpu->value->cpu_index == monitor_get_cpu_index(mon)) {
|
if (cpu->value->cpu_index == monitor_get_cpu_index(mon)) {
|
||||||
@ -40,7 +42,8 @@ void hmp_info_cpus(Monitor *mon, const QDict *qdict)
|
|||||||
|
|
||||||
monitor_printf(mon, "%c CPU #%" PRId64 ":", active,
|
monitor_printf(mon, "%c CPU #%" PRId64 ":", active,
|
||||||
cpu->value->cpu_index);
|
cpu->value->cpu_index);
|
||||||
monitor_printf(mon, " thread_id=%" PRId64 "\n", cpu->value->thread_id);
|
monitor_printf(mon, " thread_id=%" PRId64 " model=%s\n",
|
||||||
|
cpu->value->thread_id, cpu_model);
|
||||||
}
|
}
|
||||||
|
|
||||||
qapi_free_CpuInfoFastList(cpu_list);
|
qapi_free_CpuInfoFastList(cpu_list);
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "hw/mem/memory-device.h"
|
#include "hw/mem/memory-device.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qapi/qapi-builtin-visit.h"
|
#include "qapi/qapi-builtin-visit.h"
|
||||||
|
#include "qapi/qapi-commands-accelerator.h"
|
||||||
#include "qapi/qapi-commands-machine.h"
|
#include "qapi/qapi-commands-machine.h"
|
||||||
#include "qobject/qobject.h"
|
#include "qobject/qobject.h"
|
||||||
#include "qapi/qobject-input-visitor.h"
|
#include "qapi/qobject-input-visitor.h"
|
||||||
@ -46,6 +47,7 @@ CpuInfoFastList *qmp_query_cpus_fast(Error **errp)
|
|||||||
value->cpu_index = cpu->cpu_index;
|
value->cpu_index = cpu->cpu_index;
|
||||||
value->qom_path = object_get_canonical_path(OBJECT(cpu));
|
value->qom_path = object_get_canonical_path(OBJECT(cpu));
|
||||||
value->thread_id = cpu->thread_id;
|
value->thread_id = cpu->thread_id;
|
||||||
|
value->qom_type = g_strdup(object_get_typename(OBJECT(cpu)));
|
||||||
|
|
||||||
if (mc->cpu_index_to_instance_props) {
|
if (mc->cpu_index_to_instance_props) {
|
||||||
CpuInstanceProperties *props;
|
CpuInstanceProperties *props;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Accelerator OPS, used for cpus.c module
|
* Accelerator per-vCPU handlers
|
||||||
*
|
*
|
||||||
* Copyright 2021 SUSE LLC
|
* Copyright 2021 SUSE LLC
|
||||||
*
|
*
|
||||||
@ -7,8 +7,8 @@
|
|||||||
* See the COPYING file in the top-level directory.
|
* See the COPYING file in the top-level directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ACCEL_OPS_H
|
#ifndef QEMU_ACCEL_CPU_OPS_H
|
||||||
#define ACCEL_OPS_H
|
#define QEMU_ACCEL_CPU_OPS_H
|
||||||
|
|
||||||
#include "qemu/accel.h"
|
#include "qemu/accel.h"
|
||||||
#include "exec/vaddr.h"
|
#include "exec/vaddr.h"
|
||||||
@ -65,6 +65,9 @@ struct AccelOpsClass {
|
|||||||
/* handle_interrupt is mandatory. */
|
/* handle_interrupt is mandatory. */
|
||||||
void (*handle_interrupt)(CPUState *cpu, int mask);
|
void (*handle_interrupt)(CPUState *cpu, int mask);
|
||||||
|
|
||||||
|
/* get_vcpu_stats: Append statistics of this @cpu to @buf */
|
||||||
|
void (*get_vcpu_stats)(CPUState *cpu, GString *buf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @get_virtual_clock: fetch virtual clock
|
* @get_virtual_clock: fetch virtual clock
|
||||||
* @set_virtual_clock: set virtual clock
|
* @set_virtual_clock: set virtual clock
|
||||||
@ -89,4 +92,4 @@ struct AccelOpsClass {
|
|||||||
|
|
||||||
void generic_handle_interrupt(CPUState *cpu, int mask);
|
void generic_handle_interrupt(CPUState *cpu, int mask);
|
||||||
|
|
||||||
#endif /* ACCEL_OPS_H */
|
#endif /* QEMU_ACCEL_CPU_OPS_H */
|
51
include/accel/accel-ops.h
Normal file
51
include/accel/accel-ops.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Accelerator handlers
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ACCEL_OPS_H
|
||||||
|
#define ACCEL_OPS_H
|
||||||
|
|
||||||
|
#include "exec/hwaddr.h"
|
||||||
|
#include "qemu/accel.h"
|
||||||
|
#include "qom/object.h"
|
||||||
|
|
||||||
|
struct AccelState {
|
||||||
|
Object parent_obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AccelClass {
|
||||||
|
ObjectClass parent_class;
|
||||||
|
|
||||||
|
const char *name;
|
||||||
|
/* Cached by accel_init_ops_interfaces() when created */
|
||||||
|
AccelOpsClass *ops;
|
||||||
|
|
||||||
|
int (*init_machine)(AccelState *as, MachineState *ms);
|
||||||
|
bool (*cpu_common_realize)(CPUState *cpu, Error **errp);
|
||||||
|
void (*cpu_common_unrealize)(CPUState *cpu);
|
||||||
|
/* get_stats: Append statistics to @buf */
|
||||||
|
void (*get_stats)(AccelState *as, GString *buf);
|
||||||
|
|
||||||
|
/* system related hooks */
|
||||||
|
void (*setup_post)(AccelState *as);
|
||||||
|
void (*pre_resume_vm)(AccelState *as, bool step_pending);
|
||||||
|
bool (*has_memory)(AccelState *accel, AddressSpace *as,
|
||||||
|
hwaddr start_addr, hwaddr size);
|
||||||
|
|
||||||
|
/* gdbstub related hooks */
|
||||||
|
int (*gdbstub_supported_sstep_flags)(AccelState *as);
|
||||||
|
|
||||||
|
bool *allowed;
|
||||||
|
/*
|
||||||
|
* Array of global properties that would be applied when specific
|
||||||
|
* accelerator is chosen. It works like MachineClass.compat_props
|
||||||
|
* but it's for accelerators not machines. Accelerator-provided
|
||||||
|
* global properties may be overridden by machine-type
|
||||||
|
* compat_props or user-provided global properties.
|
||||||
|
*/
|
||||||
|
GPtrArray *compat_props;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* ACCEL_OPS_H */
|
@ -1,9 +0,0 @@
|
|||||||
#ifndef HW_XEN_ARCH_ARM_HVM_H
|
|
||||||
#define HW_XEN_ARCH_ARM_HVM_H
|
|
||||||
|
|
||||||
#include <xen/hvm/ioreq.h>
|
|
||||||
void arch_handle_ioreq(XenIOState *state, ioreq_t *req);
|
|
||||||
void arch_xen_set_memory(XenIOState *state,
|
|
||||||
MemoryRegionSection *section,
|
|
||||||
bool add);
|
|
||||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||||||
#ifndef HW_XEN_ARCH_I386_HVM_H
|
|
||||||
#define HW_XEN_ARCH_I386_HVM_H
|
|
||||||
|
|
||||||
#include <xen/hvm/ioreq.h>
|
|
||||||
#include "hw/xen/xen-hvm-common.h"
|
|
||||||
|
|
||||||
void arch_handle_ioreq(XenIOState *state, ioreq_t *req);
|
|
||||||
void arch_xen_set_memory(XenIOState *state,
|
|
||||||
MemoryRegionSection *section,
|
|
||||||
bool add);
|
|
||||||
#endif
|
|
@ -1,5 +1,11 @@
|
|||||||
#if defined(TARGET_I386) || defined(TARGET_X86_64)
|
#ifndef HW_XEN_ARCH_HVM_H
|
||||||
#include "hw/i386/xen_arch_hvm.h"
|
#define HW_XEN_ARCH_HVM_H
|
||||||
#elif defined(TARGET_ARM) || defined(TARGET_AARCH64)
|
|
||||||
#include "hw/arm/xen_arch_hvm.h"
|
#include <xen/hvm/ioreq.h>
|
||||||
|
#include "hw/xen/xen-hvm-common.h"
|
||||||
|
|
||||||
|
void arch_handle_ioreq(XenIOState *state, ioreq_t *req);
|
||||||
|
void arch_xen_set_memory(XenIOState *state,
|
||||||
|
MemoryRegionSection *section,
|
||||||
|
bool add);
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,43 +26,8 @@
|
|||||||
#include "qom/object.h"
|
#include "qom/object.h"
|
||||||
#include "exec/hwaddr.h"
|
#include "exec/hwaddr.h"
|
||||||
|
|
||||||
struct AccelState {
|
typedef struct AccelState AccelState;
|
||||||
/*< private >*/
|
typedef struct AccelClass AccelClass;
|
||||||
Object parent_obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct AccelClass {
|
|
||||||
/*< private >*/
|
|
||||||
ObjectClass parent_class;
|
|
||||||
/*< public >*/
|
|
||||||
|
|
||||||
const char *name;
|
|
||||||
/* Cached by accel_init_ops_interfaces() when created */
|
|
||||||
AccelOpsClass *ops;
|
|
||||||
|
|
||||||
int (*init_machine)(AccelState *as, MachineState *ms);
|
|
||||||
bool (*cpu_common_realize)(CPUState *cpu, Error **errp);
|
|
||||||
void (*cpu_common_unrealize)(CPUState *cpu);
|
|
||||||
|
|
||||||
/* system related hooks */
|
|
||||||
void (*setup_post)(AccelState *as);
|
|
||||||
void (*pre_resume_vm)(AccelState *as, bool step_pending);
|
|
||||||
bool (*has_memory)(AccelState *accel, AddressSpace *as,
|
|
||||||
hwaddr start_addr, hwaddr size);
|
|
||||||
|
|
||||||
/* gdbstub related hooks */
|
|
||||||
int (*gdbstub_supported_sstep_flags)(AccelState *as);
|
|
||||||
|
|
||||||
bool *allowed;
|
|
||||||
/*
|
|
||||||
* Array of global properties that would be applied when specific
|
|
||||||
* accelerator is chosen. It works like MachineClass.compat_props
|
|
||||||
* but it's for accelerators not machines. Accelerator-provided
|
|
||||||
* global properties may be overridden by machine-type
|
|
||||||
* compat_props or user-provided global properties.
|
|
||||||
*/
|
|
||||||
GPtrArray *compat_props;
|
|
||||||
} AccelClass;
|
|
||||||
|
|
||||||
#define TYPE_ACCEL "accel"
|
#define TYPE_ACCEL "accel"
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "qemu/queue.h"
|
#include "qemu/queue.h"
|
||||||
#include "exec/vaddr.h"
|
#include "exec/vaddr.h"
|
||||||
#include "qom/object.h"
|
#include "qom/object.h"
|
||||||
|
#include "accel/accel-ops.h"
|
||||||
|
|
||||||
#ifdef __aarch64__
|
#ifdef __aarch64__
|
||||||
#include <Hypervisor/Hypervisor.h>
|
#include <Hypervisor/Hypervisor.h>
|
||||||
@ -45,7 +46,7 @@ typedef struct hvf_vcpu_caps {
|
|||||||
} hvf_vcpu_caps;
|
} hvf_vcpu_caps;
|
||||||
|
|
||||||
struct HVFState {
|
struct HVFState {
|
||||||
AccelState parent;
|
AccelState parent_obj;
|
||||||
|
|
||||||
hvf_slot slots[32];
|
hvf_slot slots[32];
|
||||||
int num_slots;
|
int num_slots;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "qemu/accel.h"
|
#include "qemu/accel.h"
|
||||||
#include "qemu/queue.h"
|
#include "qemu/queue.h"
|
||||||
#include "system/kvm.h"
|
#include "system/kvm.h"
|
||||||
|
#include "accel/accel-ops.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "hw/i386/topology.h"
|
#include "hw/i386/topology.h"
|
||||||
#include "io/channel-socket.h"
|
#include "io/channel-socket.h"
|
||||||
|
@ -14,11 +14,51 @@ void runstate_replay_enable(void);
|
|||||||
typedef void VMChangeStateHandler(void *opaque, bool running, RunState state);
|
typedef void VMChangeStateHandler(void *opaque, bool running, RunState state);
|
||||||
typedef int VMChangeStateHandlerWithRet(void *opaque, bool running, RunState state);
|
typedef int VMChangeStateHandlerWithRet(void *opaque, bool running, RunState state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemu_add_vm_change_state_handler:
|
||||||
|
* @cb: the callback to invoke
|
||||||
|
* @opaque: user data passed to the callback
|
||||||
|
*
|
||||||
|
* Register a callback function that is invoked when the vm starts or stops
|
||||||
|
* running.
|
||||||
|
*
|
||||||
|
* Returns: an entry to be freed using qemu_del_vm_change_state_handler()
|
||||||
|
*/
|
||||||
VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
|
VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
/**
|
||||||
|
* qemu_add_vm_change_state_handler_prio:
|
||||||
|
* @cb: the callback to invoke
|
||||||
|
* @opaque: user data passed to the callback
|
||||||
|
* @priority: low priorities execute first when the vm runs and the reverse is
|
||||||
|
* true when the vm stops
|
||||||
|
*
|
||||||
|
* Register a callback function that is invoked when the vm starts or stops
|
||||||
|
* running.
|
||||||
|
*
|
||||||
|
* Returns: an entry to be freed using qemu_del_vm_change_state_handler()
|
||||||
|
*/
|
||||||
VMChangeStateEntry *qemu_add_vm_change_state_handler_prio(
|
VMChangeStateEntry *qemu_add_vm_change_state_handler_prio(
|
||||||
VMChangeStateHandler *cb, void *opaque, int priority);
|
VMChangeStateHandler *cb, void *opaque, int priority);
|
||||||
VMChangeStateEntry *
|
VMChangeStateEntry *
|
||||||
|
/**
|
||||||
|
* qemu_add_vm_change_state_handler_prio_full:
|
||||||
|
* @cb: the main callback to invoke
|
||||||
|
* @prepare_cb: a callback to invoke before the main callback
|
||||||
|
* @cb_ret: the main callback to invoke with return value
|
||||||
|
* @opaque: user data passed to the callbacks
|
||||||
|
* @priority: low priorities execute first when the vm runs and the reverse is
|
||||||
|
* true when the vm stops
|
||||||
|
*
|
||||||
|
* Register a main callback function and an optional prepare callback function
|
||||||
|
* that are invoked when the vm starts or stops running. The main callback and
|
||||||
|
* the prepare callback are called in two separate phases: First all prepare
|
||||||
|
* callbacks are called and only then all main callbacks are called. As its
|
||||||
|
* name suggests, the prepare callback can be used to do some preparatory work
|
||||||
|
* before invoking the main callback.
|
||||||
|
*
|
||||||
|
* Returns: an entry to be freed using qemu_del_vm_change_state_handler()
|
||||||
|
*/
|
||||||
qemu_add_vm_change_state_handler_prio_full(VMChangeStateHandler *cb,
|
qemu_add_vm_change_state_handler_prio_full(VMChangeStateHandler *cb,
|
||||||
VMChangeStateHandler *prepare_cb,
|
VMChangeStateHandler *prepare_cb,
|
||||||
VMChangeStateHandlerWithRet *cb_ret,
|
VMChangeStateHandlerWithRet *cb_ret,
|
||||||
|
@ -1005,5 +1005,7 @@ static inline const TCGOpcode *tcg_swap_vecop_list(const TCGOpcode *n)
|
|||||||
|
|
||||||
bool tcg_can_emit_vecop_list(const TCGOpcode *, TCGType, unsigned);
|
bool tcg_can_emit_vecop_list(const TCGOpcode *, TCGType, unsigned);
|
||||||
void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs);
|
void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs);
|
||||||
|
/* tcg_dump_stats: Append TCG statistics to @buf */
|
||||||
|
void tcg_dump_stats(GString *buf);
|
||||||
|
|
||||||
#endif /* TCG_H */
|
#endif /* TCG_H */
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "user/page-protection.h"
|
#include "user/page-protection.h"
|
||||||
#include "exec/gdbstub.h"
|
#include "exec/gdbstub.h"
|
||||||
#include "gdbstub/user.h"
|
#include "gdbstub/user.h"
|
||||||
|
#include "accel/accel-ops.h"
|
||||||
#include "tcg/startup.h"
|
#include "tcg/startup.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
#include "qemu/envlist.h"
|
#include "qemu/envlist.h"
|
||||||
|
54
qapi/accelerator.json
Normal file
54
qapi/accelerator.json
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# -*- Mode: Python -*-
|
||||||
|
# vim: filetype=python
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
##
|
||||||
|
# = Accelerators
|
||||||
|
##
|
||||||
|
|
||||||
|
{ 'include': 'common.json' }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @KvmInfo:
|
||||||
|
#
|
||||||
|
# Information about support for KVM acceleration
|
||||||
|
#
|
||||||
|
# @enabled: true if KVM acceleration is active
|
||||||
|
#
|
||||||
|
# @present: true if KVM acceleration is built into this executable
|
||||||
|
#
|
||||||
|
# Since: 0.14
|
||||||
|
##
|
||||||
|
{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @query-kvm:
|
||||||
|
#
|
||||||
|
# Return information about KVM acceleration
|
||||||
|
#
|
||||||
|
# Since: 0.14
|
||||||
|
#
|
||||||
|
# .. qmp-example::
|
||||||
|
#
|
||||||
|
# -> { "execute": "query-kvm" }
|
||||||
|
# <- { "return": { "enabled": true, "present": true } }
|
||||||
|
##
|
||||||
|
{ 'command': 'query-kvm', 'returns': 'KvmInfo' }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @x-accel-stats:
|
||||||
|
#
|
||||||
|
# Query accelerator statistics
|
||||||
|
#
|
||||||
|
# Features:
|
||||||
|
#
|
||||||
|
# @unstable: This command is meant for debugging.
|
||||||
|
#
|
||||||
|
# Returns: accelerator statistics
|
||||||
|
#
|
||||||
|
# Since: 10.1
|
||||||
|
##
|
||||||
|
{ 'command': 'x-accel-stats',
|
||||||
|
'returns': 'HumanReadableText',
|
||||||
|
'features': [ 'unstable' ] }
|
@ -78,6 +78,8 @@
|
|||||||
#
|
#
|
||||||
# @cpu-index: index of the virtual CPU
|
# @cpu-index: index of the virtual CPU
|
||||||
#
|
#
|
||||||
|
# @qom-type: QOM type name of the CPU (since 10.1)
|
||||||
|
#
|
||||||
# @qom-path: path to the CPU object in the QOM tree
|
# @qom-path: path to the CPU object in the QOM tree
|
||||||
#
|
#
|
||||||
# @thread-id: ID of the underlying host thread
|
# @thread-id: ID of the underlying host thread
|
||||||
@ -91,6 +93,7 @@
|
|||||||
##
|
##
|
||||||
{ 'union' : 'CpuInfoFast',
|
{ 'union' : 'CpuInfoFast',
|
||||||
'base' : { 'cpu-index' : 'int',
|
'base' : { 'cpu-index' : 'int',
|
||||||
|
'qom-type' : 'str',
|
||||||
'qom-path' : 'str',
|
'qom-path' : 'str',
|
||||||
'thread-id' : 'int',
|
'thread-id' : 'int',
|
||||||
'*props' : 'CpuInstanceProperties',
|
'*props' : 'CpuInstanceProperties',
|
||||||
@ -443,33 +446,6 @@
|
|||||||
##
|
##
|
||||||
{ 'command': 'inject-nmi' }
|
{ 'command': 'inject-nmi' }
|
||||||
|
|
||||||
##
|
|
||||||
# @KvmInfo:
|
|
||||||
#
|
|
||||||
# Information about support for KVM acceleration
|
|
||||||
#
|
|
||||||
# @enabled: true if KVM acceleration is active
|
|
||||||
#
|
|
||||||
# @present: true if KVM acceleration is built into this executable
|
|
||||||
#
|
|
||||||
# Since: 0.14
|
|
||||||
##
|
|
||||||
{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
|
|
||||||
|
|
||||||
##
|
|
||||||
# @query-kvm:
|
|
||||||
#
|
|
||||||
# Return information about KVM acceleration
|
|
||||||
#
|
|
||||||
# Since: 0.14
|
|
||||||
#
|
|
||||||
# .. qmp-example::
|
|
||||||
#
|
|
||||||
# -> { "execute": "query-kvm" }
|
|
||||||
# <- { "return": { "enabled": true, "present": true } }
|
|
||||||
##
|
|
||||||
{ 'command': 'query-kvm', 'returns': 'KvmInfo' }
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# @NumaOptionsType:
|
# @NumaOptionsType:
|
||||||
#
|
#
|
||||||
|
@ -57,6 +57,7 @@ qapi_all_modules = [
|
|||||||
]
|
]
|
||||||
if have_system
|
if have_system
|
||||||
qapi_all_modules += [
|
qapi_all_modules += [
|
||||||
|
'accelerator',
|
||||||
'acpi',
|
'acpi',
|
||||||
'audio',
|
'audio',
|
||||||
'cryptodev',
|
'cryptodev',
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
{ 'include': 'run-state.json' }
|
{ 'include': 'run-state.json' }
|
||||||
{ 'include': 'crypto.json' }
|
{ 'include': 'crypto.json' }
|
||||||
{ 'include': 'job.json' }
|
{ 'include': 'job.json' }
|
||||||
|
{ 'include': 'accelerator.json' }
|
||||||
{ 'include': 'block.json' }
|
{ 'include': 'block.json' }
|
||||||
{ 'include': 'block-export.json' }
|
{ 'include': 'block-export.json' }
|
||||||
{ 'include': 'char.json' }
|
{ 'include': 'char.json' }
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include "qapi/qapi-events-run-state.h"
|
#include "qapi/qapi-events-run-state.h"
|
||||||
#include "qapi/qmp/qerror.h"
|
#include "qapi/qmp/qerror.h"
|
||||||
#include "exec/gdbstub.h"
|
#include "exec/gdbstub.h"
|
||||||
#include "system/accel-ops.h"
|
#include "accel/accel-cpu-ops.h"
|
||||||
#include "system/hw_accel.h"
|
#include "system/hw_accel.h"
|
||||||
#include "exec/cpu-common.h"
|
#include "exec/cpu-common.h"
|
||||||
#include "qemu/thread.h"
|
#include "qemu/thread.h"
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "system/runstate.h"
|
#include "system/runstate.h"
|
||||||
#include "system/tcg.h"
|
#include "system/tcg.h"
|
||||||
#include "qemu/accel.h"
|
#include "qemu/accel.h"
|
||||||
|
#include "accel/accel-ops.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
#include "system/address-spaces.h"
|
#include "system/address-spaces.h"
|
||||||
|
@ -306,18 +306,6 @@ struct VMChangeStateEntry {
|
|||||||
static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head =
|
static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head =
|
||||||
QTAILQ_HEAD_INITIALIZER(vm_change_state_head);
|
QTAILQ_HEAD_INITIALIZER(vm_change_state_head);
|
||||||
|
|
||||||
/**
|
|
||||||
* qemu_add_vm_change_state_handler_prio:
|
|
||||||
* @cb: the callback to invoke
|
|
||||||
* @opaque: user data passed to the callback
|
|
||||||
* @priority: low priorities execute first when the vm runs and the reverse is
|
|
||||||
* true when the vm stops
|
|
||||||
*
|
|
||||||
* Register a callback function that is invoked when the vm starts or stops
|
|
||||||
* running.
|
|
||||||
*
|
|
||||||
* Returns: an entry to be freed using qemu_del_vm_change_state_handler()
|
|
||||||
*/
|
|
||||||
VMChangeStateEntry *qemu_add_vm_change_state_handler_prio(
|
VMChangeStateEntry *qemu_add_vm_change_state_handler_prio(
|
||||||
VMChangeStateHandler *cb, void *opaque, int priority)
|
VMChangeStateHandler *cb, void *opaque, int priority)
|
||||||
{
|
{
|
||||||
@ -325,24 +313,6 @@ VMChangeStateEntry *qemu_add_vm_change_state_handler_prio(
|
|||||||
opaque, priority);
|
opaque, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* qemu_add_vm_change_state_handler_prio_full:
|
|
||||||
* @cb: the main callback to invoke
|
|
||||||
* @prepare_cb: a callback to invoke before the main callback
|
|
||||||
* @cb_ret: the main callback to invoke with return value
|
|
||||||
* @opaque: user data passed to the callbacks
|
|
||||||
* @priority: low priorities execute first when the vm runs and the reverse is
|
|
||||||
* true when the vm stops
|
|
||||||
*
|
|
||||||
* Register a main callback function and an optional prepare callback function
|
|
||||||
* that are invoked when the vm starts or stops running. The main callback and
|
|
||||||
* the prepare callback are called in two separate phases: First all prepare
|
|
||||||
* callbacks are called and only then all main callbacks are called. As its
|
|
||||||
* name suggests, the prepare callback can be used to do some preparatory work
|
|
||||||
* before invoking the main callback.
|
|
||||||
*
|
|
||||||
* Returns: an entry to be freed using qemu_del_vm_change_state_handler()
|
|
||||||
*/
|
|
||||||
VMChangeStateEntry *
|
VMChangeStateEntry *
|
||||||
qemu_add_vm_change_state_handler_prio_full(VMChangeStateHandler *cb,
|
qemu_add_vm_change_state_handler_prio_full(VMChangeStateHandler *cb,
|
||||||
VMChangeStateHandler *prepare_cb,
|
VMChangeStateHandler *prepare_cb,
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "system/kvm_int.h"
|
#include "system/kvm_int.h"
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
#include "system/accel-ops.h"
|
#include "accel/accel-cpu-ops.h"
|
||||||
#include "system/cpus.h"
|
#include "system/cpus.h"
|
||||||
#include "qemu/guest-random.h"
|
#include "qemu/guest-random.h"
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "system/address-spaces.h"
|
#include "system/address-spaces.h"
|
||||||
#include "system/ioport.h"
|
#include "system/ioport.h"
|
||||||
#include "qemu/accel.h"
|
#include "qemu/accel.h"
|
||||||
|
#include "accel/accel-ops.h"
|
||||||
#include "system/nvmm.h"
|
#include "system/nvmm.h"
|
||||||
#include "system/cpus.h"
|
#include "system/cpus.h"
|
||||||
#include "system/runstate.h"
|
#include "system/runstate.h"
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "system/kvm_int.h"
|
#include "system/kvm_int.h"
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
#include "system/accel-ops.h"
|
#include "accel/accel-cpu-ops.h"
|
||||||
#include "system/cpus.h"
|
#include "system/cpus.h"
|
||||||
#include "qemu/guest-random.h"
|
#include "qemu/guest-random.h"
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "system/ioport.h"
|
#include "system/ioport.h"
|
||||||
#include "gdbstub/helpers.h"
|
#include "gdbstub/helpers.h"
|
||||||
#include "qemu/accel.h"
|
#include "qemu/accel.h"
|
||||||
|
#include "accel/accel-ops.h"
|
||||||
#include "system/whpx.h"
|
#include "system/whpx.h"
|
||||||
#include "system/cpus.h"
|
#include "system/cpus.h"
|
||||||
#include "system/runstate.h"
|
#include "system/runstate.h"
|
||||||
|
Loading…
Reference in New Issue
Block a user