aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.d/buildtest.yml1
-rw-r--r--MAINTAINERS11
-rw-r--r--Makefile5
-rw-r--r--accel/hvf/hvf-accel-ops.c7
-rw-r--r--accel/tcg/cpu-exec.c51
-rw-r--r--accel/tcg/hmp.c22
-rw-r--r--accel/tcg/translate-all.c84
-rw-r--r--configs/targets/aarch64-softmmu.mak2
-rw-r--r--configs/targets/arm-linux-user.mak2
-rw-r--r--configs/targets/arm-softmmu.mak2
-rw-r--r--configs/targets/armeb-linux-user.mak2
-rw-r--r--configs/targets/i386-softmmu.mak1
-rw-r--r--configs/targets/x86_64-softmmu.mak1
-rwxr-xr-xconfigure113
-rw-r--r--docs/about/deprecated.rst15
-rw-r--r--docs/devel/index.rst2
-rw-r--r--docs/devel/writing-monitor-commands.rst (renamed from docs/devel/writing-qmp-commands.rst)167
-rw-r--r--gdb-xml/arm-m-profile-mve.xml19
-rw-r--r--hmp-commands-info.hx29
-rw-r--r--hw/arm/npcm7xx.c12
-rw-r--r--hw/arm/npcm7xx_boards.c20
-rw-r--r--hw/arm/virt.c4
-rw-r--r--hw/core/loader.c39
-rw-r--r--hw/core/machine-hmp-cmds.c38
-rw-r--r--hw/core/machine-qmp-cmds.c40
-rw-r--r--hw/core/machine.c3
-rw-r--r--hw/display/virtio-gpu-udmabuf.c2
-rw-r--r--hw/i386/intel_iommu.c2
-rw-r--r--hw/i386/meson.build2
-rw-r--r--hw/i386/microvm-dt.c341
-rw-r--r--hw/i386/microvm-dt.h8
-rw-r--r--hw/i386/microvm.c7
-rw-r--r--hw/i386/multiboot.c10
-rw-r--r--hw/i386/multiboot.h4
-rw-r--r--hw/i386/pc.c10
-rw-r--r--hw/i386/pc_piix.c3
-rw-r--r--hw/i386/pc_q35.c3
-rw-r--r--hw/i386/x86.c7
-rw-r--r--hw/input/lasips2.c8
-rw-r--r--hw/misc/sga.c2
-rw-r--r--hw/rdma/rdma_rm.c104
-rw-r--r--hw/rdma/rdma_rm.h2
-rw-r--r--hw/rdma/vmw/pvrdma_main.c31
-rw-r--r--hw/scsi/esp.c10
-rw-r--r--hw/sd/meson.build1
-rw-r--r--hw/sd/npcm7xx_sdhci.c182
-rw-r--r--hw/usb/bus.c24
-rw-r--r--hw/watchdog/sbsa_gwdt.c3
-rw-r--r--hw/watchdog/watchdog.c14
-rw-r--r--hw/watchdog/wdt_aspeed.c3
-rw-r--r--hw/watchdog/wdt_diag288.c3
-rw-r--r--hw/watchdog/wdt_i6300esb.c3
-rw-r--r--hw/watchdog/wdt_ib700.c3
-rw-r--r--hw/watchdog/wdt_imx2.c4
-rw-r--r--include/exec/cpu-all.h6
-rw-r--r--include/exec/ramlist.h2
-rw-r--r--include/hw/arm/npcm7xx.h2
-rw-r--r--include/hw/i386/microvm.h4
-rw-r--r--include/hw/i386/pc.h3
-rw-r--r--include/hw/i386/x86.h5
-rw-r--r--include/hw/qdev-core.h1
-rw-r--r--include/hw/rdma/rdma.h2
-rw-r--r--include/hw/sd/npcm7xx_sdhci.h65
-rw-r--r--include/hw/usb/msd.h2
-rw-r--r--include/monitor/hmp-target.h1
-rw-r--r--include/monitor/hmp.h5
-rw-r--r--include/monitor/monitor.h2
-rw-r--r--include/qapi/type-helpers.h14
-rw-r--r--include/qemu/iova-tree.h8
-rw-r--r--include/sysemu/watchdog.h1
-rw-r--r--include/tcg/tcg.h4
-rw-r--r--include/ui/console.h1
m---------meson0
-rw-r--r--meson.build30
-rw-r--r--meson_options.txt2
-rw-r--r--monitor/hmp-cmds.c101
-rw-r--r--monitor/hmp.c32
-rw-r--r--monitor/misc.c61
-rw-r--r--monitor/monitor-internal.h7
-rw-r--r--monitor/qmp-cmds.c116
-rw-r--r--net/meson.build4
-rw-r--r--pc-bios/meson.build1
-rw-r--r--pc-bios/multiboot_dma.binbin0 -> 1024 bytes
-rw-r--r--pc-bios/optionrom/Makefile9
-rw-r--r--pc-bios/optionrom/multiboot.S4
-rw-r--r--pc-bios/optionrom/multiboot_dma.S2
-rw-r--r--pc-bios/optionrom/optionrom.h66
-rw-r--r--qapi/common.json11
-rw-r--r--qapi/machine.json110
-rw-r--r--qapi/meson.build3
-rw-r--r--qapi/qapi-type-helpers.c23
-rwxr-xr-xscripts/meson-buildoptions.py16
-rw-r--r--scripts/meson-buildoptions.sh3
-rw-r--r--softmmu/physmem.c19
-rw-r--r--softmmu/qdev-monitor.c1
-rw-r--r--softmmu/vl.c11
-rw-r--r--stubs/usb-dev-stub.c8
-rw-r--r--target/arm/gdbstub.c25
-rw-r--r--target/arm/hvf/hvf.c7
-rw-r--r--target/arm/translate-a32.h3
-rw-r--r--target/arm/translate-sve.c17
-rw-r--r--target/arm/translate.c27
-rw-r--r--target/i386/cpu-dump.c4
-rw-r--r--target/i386/cpu.c7
-rw-r--r--target/i386/cpu.h4
-rw-r--r--target/i386/kvm/kvm.c15
-rw-r--r--target/i386/machine.c22
-rw-r--r--target/i386/monitor.c6
-rw-r--r--target/ppc/cpu_init.c2
-rw-r--r--target/s390x/cpu_models.c4
-rw-r--r--target/xtensa/mmu_helper.c2
-rw-r--r--tcg/tcg.c98
-rw-r--r--tests/qtest/am53c974-test.c36
-rw-r--r--tests/qtest/libqos/meson.build1
-rw-r--r--tests/qtest/libqos/sdhci-cmd.c116
-rw-r--r--tests/qtest/libqos/sdhci-cmd.h70
-rw-r--r--tests/qtest/qmp-cmd-test.c8
-rw-r--r--ui/console.c109
-rw-r--r--ui/gtk-egl.c40
-rw-r--r--ui/gtk-gl-area.c52
-rw-r--r--util/iova-tree.c12
121 files changed, 2148 insertions, 795 deletions
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index 5c378e35f9..6c1301e912 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -575,7 +575,6 @@ build-without-default-features:
CONFIGURE_ARGS:
--without-default-features
--disable-capstone
- --disable-fdt
--disable-pie
--disable-qom-cast-debug
--disable-slirp
diff --git a/MAINTAINERS b/MAINTAINERS
index d58885d9b9..7e31135768 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -211,10 +211,7 @@ HPPA (PA-RISC) TCG CPUs
M: Richard Henderson <richard.henderson@linaro.org>
S: Maintained
F: target/hppa/
-F: hw/hppa/
F: disas/hppa.c
-F: hw/net/*i82596*
-F: include/hw/net/lasi_82596.h
M68K TCG CPUs
M: Laurent Vivier <laurent@vivier.eu>
@@ -1095,6 +1092,8 @@ R: Helge Deller <deller@gmx.de>
S: Odd Fixes
F: configs/devices/hppa-softmmu/default.mak
F: hw/hppa/
+F: hw/net/*i82596*
+F: include/hw/net/lasi_82596.h
F: pc-bios/hppa-firmware.img
M68K Machines
@@ -1612,7 +1611,7 @@ microvm
M: Sergio Lopez <slp@redhat.com>
M: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
-F: docs/microvm.rst
+F: docs/system/i386/microvm.rst
F: hw/i386/microvm.c
F: include/hw/i386/microvm.h
F: pc-bios/bios-microvm.bin
@@ -2302,11 +2301,13 @@ F: qapi/audio.json
ALSA Audio backend
M: Gerd Hoffmann <kraxel@redhat.com>
+R: Christian Schoenebeck <qemu_oss@crudebyte.com>
S: Odd Fixes
F: audio/alsaaudio.c
Core Audio framework backend
M: Gerd Hoffmann <kraxel@redhat.com>
+R: Christian Schoenebeck <qemu_oss@crudebyte.com>
S: Odd Fixes
F: audio/coreaudio.c
@@ -2317,6 +2318,7 @@ F: audio/dsound*
JACK Audio Connection Kit backend
M: Gerd Hoffmann <kraxel@redhat.com>
+R: Christian Schoenebeck <qemu_oss@crudebyte.com>
S: Odd Fixes
F: audio/jackaudio.c
@@ -2332,6 +2334,7 @@ F: audio/paaudio.c
SDL Audio backend
M: Gerd Hoffmann <kraxel@redhat.com>
+R: Thomas Huth <huth@tuxfamily.org>
S: Odd Fixes
F: audio/sdlaudio.c
diff --git a/Makefile b/Makefile
index fe9415ac64..74c5b46d38 100644
--- a/Makefile
+++ b/Makefile
@@ -235,7 +235,8 @@ distclean: clean
rm -f linux-headers/asm
rm -Rf .sdk
-find-src-path = find "$(SRC_PATH)/" -path "$(SRC_PATH)/meson" -prune -o \( -name "*.[chsS]" -o -name "*.[ch].inc" \)
+find-src-path = find "$(SRC_PATH)" -path "$(SRC_PATH)/meson" -prune -o \
+ -type l -prune -o \( -name "*.[chsS]" -o -name "*.[ch].inc" \)
.PHONY: ctags
ctags:
@@ -256,7 +257,7 @@ gtags:
"GTAGS", "Remove old $@ files")
$(call quiet-command, \
(cd $(SRC_PATH) && \
- $(find-src-path) | gtags -f -), \
+ $(find-src-path) -print | gtags -f -), \
"GTAGS", "Re-index $(SRC_PATH)")
.PHONY: TAGS
diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c
index 2b2c411076..54457c76c2 100644
--- a/accel/hvf/hvf-accel-ops.c
+++ b/accel/hvf/hvf-accel-ops.c
@@ -122,6 +122,7 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
MemoryRegion *area = section->mr;
bool writeable = !area->readonly && !area->rom_device;
hv_memory_flags_t flags;
+ uint64_t page_size = qemu_real_host_page_size;
if (!memory_region_is_ram(area)) {
if (writeable) {
@@ -135,6 +136,12 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
}
}
+ if (!QEMU_IS_ALIGNED(int128_get64(section->size), page_size) ||
+ !QEMU_IS_ALIGNED(section->offset_within_address_space, page_size)) {
+ /* Not page aligned, so we can not map as RAM */
+ add = false;
+ }
+
mem = hvf_find_overlap_slot(
section->offset_within_address_space,
int128_get64(section->size));
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index bba4672632..2d14d02f6c 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -20,6 +20,9 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/qemu-print.h"
+#include "qapi/error.h"
+#include "qapi/qapi-commands-machine.h"
+#include "qapi/type-helpers.h"
#include "hw/core/tcg-cpu-ops.h"
#include "trace.h"
#include "disas/disas.h"
@@ -38,6 +41,7 @@
#include "exec/cpu-all.h"
#include "sysemu/cpu-timers.h"
#include "sysemu/replay.h"
+#include "sysemu/tcg.h"
#include "exec/helper-proto.h"
#include "tb-hash.h"
#include "tb-context.h"
@@ -1029,23 +1033,52 @@ void tcg_exec_unrealizefn(CPUState *cpu)
#ifndef CONFIG_USER_ONLY
-void dump_drift_info(void)
+void dump_drift_info(GString *buf)
{
if (!icount_enabled()) {
return;
}
- qemu_printf("Host - Guest clock %"PRIi64" ms\n",
- (cpu_get_clock() - icount_get()) / SCALE_MS);
+ g_string_append_printf(buf, "Host - Guest clock %"PRIi64" ms\n",
+ (cpu_get_clock() - icount_get()) / SCALE_MS);
if (icount_align_option) {
- qemu_printf("Max guest delay %"PRIi64" ms\n",
- -max_delay / SCALE_MS);
- qemu_printf("Max guest advance %"PRIi64" ms\n",
- max_advance / SCALE_MS);
+ 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 {
- qemu_printf("Max guest delay NA\n");
- qemu_printf("Max guest advance NA\n");
+ g_string_append_printf(buf, "Max guest delay NA\n");
+ g_string_append_printf(buf, "Max guest advance NA\n");
}
}
+HumanReadableText *qmp_x_query_jit(Error **errp)
+{
+ g_autoptr(GString) buf = g_string_new("");
+
+ if (!tcg_enabled()) {
+ error_setg(errp, "JIT information is only available with accel=tcg");
+ return NULL;
+ }
+
+ dump_exec_info(buf);
+ dump_drift_info(buf);
+
+ return human_readable_text_from_str(buf);
+}
+
+HumanReadableText *qmp_x_query_opcount(Error **errp)
+{
+ g_autoptr(GString) buf = g_string_new("");
+
+ if (!tcg_enabled()) {
+ error_setg(errp, "Opcode count information is only available with accel=tcg");
+ return NULL;
+ }
+
+ dump_opcount_info(buf);
+
+ return human_readable_text_from_str(buf);
+}
+
#endif /* !CONFIG_USER_ONLY */
diff --git a/accel/tcg/hmp.c b/accel/tcg/hmp.c
index a6e72fdb3e..d2ea352655 100644
--- a/accel/tcg/hmp.c
+++ b/accel/tcg/hmp.c
@@ -1,29 +1,15 @@
#include "qemu/osdep.h"
#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "qapi/qapi-commands-machine.h"
#include "exec/exec-all.h"
#include "monitor/monitor.h"
#include "sysemu/tcg.h"
-static void hmp_info_jit(Monitor *mon, const QDict *qdict)
-{
- if (!tcg_enabled()) {
- error_report("JIT information is only available with accel=tcg");
- return;
- }
-
- dump_exec_info();
- dump_drift_info();
-}
-
-static void hmp_info_opcount(Monitor *mon, const QDict *qdict)
-{
- dump_opcount_info();
-}
-
static void hmp_tcg_register(void)
{
- monitor_register_hmp("jit", true, hmp_info_jit);
- monitor_register_hmp("opcount", true, hmp_info_opcount);
+ monitor_register_hmp_info_hrt("jit", qmp_x_query_jit);
+ monitor_register_hmp_info_hrt("opcount", qmp_x_query_opcount);
}
type_init(hmp_tcg_register);
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index fb9ebfad9e..bd0bb81d08 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1991,7 +1991,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
cpu_loop_exit_noexc(cpu);
}
-static void print_qht_statistics(struct qht_stats hst)
+static void print_qht_statistics(struct qht_stats hst, GString *buf)
{
uint32_t hgram_opts;
size_t hgram_bins;
@@ -2000,9 +2000,11 @@ static void print_qht_statistics(struct qht_stats hst)
if (!hst.head_buckets) {
return;
}
- qemu_printf("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);
+ 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;
@@ -2010,8 +2012,9 @@ static void print_qht_statistics(struct qht_stats hst)
hgram_opts |= QDIST_PR_NODECIMAL;
}
hgram = qdist_pr(&hst.occupancy, 10, hgram_opts);
- qemu_printf("TB hash occupancy %0.2f%% avg chain occ. Histogram: %s\n",
- qdist_avg(&hst.occupancy) * 100, hgram);
+ 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;
@@ -2023,8 +2026,9 @@ static void print_qht_statistics(struct qht_stats hst)
hgram_opts |= QDIST_PR_NODECIMAL | QDIST_PR_NOBINRANGE;
}
hgram = qdist_pr(&hst.chain, hgram_bins, hgram_opts);
- qemu_printf("TB hash avg chain %0.3f buckets. Histogram: %s\n",
- qdist_avg(&hst.chain), hgram);
+ g_string_append_printf(buf, "TB hash avg chain %0.3f buckets. "
+ "Histogram: %s\n",
+ qdist_avg(&hst.chain), hgram);
g_free(hgram);
}
@@ -2061,7 +2065,7 @@ static gboolean tb_tree_stats_iter(gpointer key, gpointer value, gpointer data)
return false;
}
-void dump_exec_info(void)
+void dump_exec_info(GString *buf)
{
struct tb_tree_stats tst = {};
struct qht_stats hst;
@@ -2070,49 +2074,53 @@ void dump_exec_info(void)
tcg_tb_foreach(tb_tree_stats_iter, &tst);
nb_tbs = tst.nb_tbs;
/* XXX: avoid using doubles ? */
- qemu_printf("Translation buffer state:\n");
+ 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.
*/
- qemu_printf("gen code size %zu/%zu\n",
- tcg_code_size(), tcg_code_capacity());
- qemu_printf("TB count %zu\n", nb_tbs);
- qemu_printf("TB avg target size %zu max=%zu bytes\n",
- nb_tbs ? tst.target_size / nb_tbs : 0,
- tst.max_target_size);
- qemu_printf("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);
- qemu_printf("cross page TB count %zu (%zu%%)\n", tst.cross_page,
- nb_tbs ? (tst.cross_page * 100) / nb_tbs : 0);
- qemu_printf("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);
+ 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);
+ print_qht_statistics(hst, buf);
qht_statistics_destroy(&hst);
- qemu_printf("\nStatistics:\n");
- qemu_printf("TB flush count %u\n",
- qatomic_read(&tb_ctx.tb_flush_count));
- qemu_printf("TB invalidate count %u\n",
- qatomic_read(&tb_ctx.tb_phys_invalidate_count));
+ g_string_append_printf(buf, "\nStatistics:\n");
+ 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);
- qemu_printf("TLB full flushes %zu\n", flush_full);
- qemu_printf("TLB partial flushes %zu\n", flush_part);
- qemu_printf("TLB elided flushes %zu\n", flush_elide);
- tcg_dump_info();
+ 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);
+ tcg_dump_info(buf);
}
-void dump_opcount_info(void)
+void dump_opcount_info(GString *buf)
{
- tcg_dump_op_count();
+ tcg_dump_op_count(buf);
}
#else /* CONFIG_USER_ONLY */
diff --git a/configs/targets/aarch64-softmmu.mak b/configs/targets/aarch64-softmmu.mak
index 13d40b55e6..d489e6da83 100644
--- a/configs/targets/aarch64-softmmu.mak
+++ b/configs/targets/aarch64-softmmu.mak
@@ -1,5 +1,5 @@
TARGET_ARCH=aarch64
TARGET_BASE_ARCH=arm
TARGET_SUPPORTS_MTTCG=y
-TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
+TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
TARGET_NEED_FDT=y
diff --git a/configs/targets/arm-linux-user.mak b/configs/targets/arm-linux-user.mak
index acecc339e3..3e10d6b15d 100644
--- a/configs/targets/arm-linux-user.mak
+++ b/configs/targets/arm-linux-user.mak
@@ -1,6 +1,6 @@
TARGET_ARCH=arm
TARGET_SYSTBL_ABI=common,oabi
TARGET_SYSTBL=syscall.tbl
-TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
+TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
TARGET_HAS_BFLT=y
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
diff --git a/configs/targets/arm-softmmu.mak b/configs/targets/arm-softmmu.mak
index f6c95ba07a..92c8349b96 100644
--- a/configs/targets/arm-softmmu.mak
+++ b/configs/targets/arm-softmmu.mak
@@ -1,4 +1,4 @@
TARGET_ARCH=arm
TARGET_SUPPORTS_MTTCG=y
-TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
+TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
TARGET_NEED_FDT=y
diff --git a/configs/targets/armeb-linux-user.mak b/configs/targets/armeb-linux-user.mak
index 662c73d8fb..f81e5bf1fe 100644
--- a/configs/targets/armeb-linux-user.mak
+++ b/configs/targets/armeb-linux-user.mak
@@ -2,6 +2,6 @@ TARGET_ARCH=arm
TARGET_SYSTBL_ABI=common,oabi
TARGET_SYSTBL=syscall.tbl
TARGET_WORDS_BIGENDIAN=y
-TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
+TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
TARGET_HAS_BFLT=y
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
diff --git a/configs/targets/i386-softmmu.mak b/configs/targets/i386-softmmu.mak
index 5babf71895..6b3c99fc86 100644
--- a/configs/targets/i386-softmmu.mak
+++ b/configs/targets/i386-softmmu.mak
@@ -1,3 +1,4 @@
TARGET_ARCH=i386
TARGET_SUPPORTS_MTTCG=y
+TARGET_NEED_FDT=y
TARGET_XML_FILES= gdb-xml/i386-32bit.xml
diff --git a/configs/targets/x86_64-softmmu.mak b/configs/targets/x86_64-softmmu.mak
index 75e42bc840..197817c943 100644
--- a/configs/targets/x86_64-softmmu.mak
+++ b/configs/targets/x86_64-softmmu.mak
@@ -1,4 +1,5 @@
TARGET_ARCH=x86_64
TARGET_BASE_ARCH=i386
TARGET_SUPPORTS_MTTCG=y
+TARGET_NEED_FDT=y
TARGET_XML_FILES= gdb-xml/i386-64bit.xml
diff --git a/configure b/configure
index d57ad58342..33682cb971 100755
--- a/configure
+++ b/configure
@@ -1259,45 +1259,20 @@ firmwarepath="${firmwarepath:-$datadir/qemu-firmware}"
localedir="${localedir:-$datadir/locale}"
case "$cpu" in
- ppc)
- CPU_CFLAGS="-m32"
- QEMU_LDFLAGS="-m32 $QEMU_LDFLAGS"
- ;;
- ppc64)
- CPU_CFLAGS="-m64"
- QEMU_LDFLAGS="-m64 $QEMU_LDFLAGS"
- ;;
- sparc)
- CPU_CFLAGS="-m32 -mv8plus -mcpu=ultrasparc"
- QEMU_LDFLAGS="-m32 -mv8plus $QEMU_LDFLAGS"
- ;;
- sparc64)
- CPU_CFLAGS="-m64 -mcpu=ultrasparc"
- QEMU_LDFLAGS="-m64 $QEMU_LDFLAGS"
- ;;
- s390)
- CPU_CFLAGS="-m31"
- QEMU_LDFLAGS="-m31 $QEMU_LDFLAGS"
- ;;
- s390x)
- CPU_CFLAGS="-m64"
- QEMU_LDFLAGS="-m64 $QEMU_LDFLAGS"
- ;;
- i386)
- CPU_CFLAGS="-m32"
- QEMU_LDFLAGS="-m32 $QEMU_LDFLAGS"
- ;;
- x86_64)
- # ??? Only extremely old AMD cpus do not have cmpxchg16b.
- # If we truly care, we should simply detect this case at
- # runtime and generate the fallback to serial emulation.
- CPU_CFLAGS="-m64 -mcx16"
- QEMU_LDFLAGS="-m64 $QEMU_LDFLAGS"
- ;;
- x32)
- CPU_CFLAGS="-mx32"
- QEMU_LDFLAGS="-mx32 $QEMU_LDFLAGS"
- ;;
+ ppc) CPU_CFLAGS="-m32" ;;
+ ppc64) CPU_CFLAGS="-m64" ;;
+ sparc) CPU_CFLAGS="-m32 -mv8plus -mcpu=ultrasparc" ;;
+ sparc64) CPU_CFLAGS="-m64 -mcpu=ultrasparc" ;;
+ s390) CPU_CFLAGS="-m31" ;;
+ s390x) CPU_CFLAGS="-m64" ;;
+ i386) CPU_CFLAGS="-m32" ;;
+ x32) CPU_CFLAGS="-mx32" ;;
+
+ # ??? Only extremely old AMD cpus do not have cmpxchg16b.
+ # If we truly care, we should simply detect this case at
+ # runtime and generate the fallback to serial emulation.
+ x86_64) CPU_CFLAGS="-m64 -mcx16" ;;
+
# No special flags required for other host CPUs
esac
@@ -1411,7 +1386,7 @@ Advanced options (experts only):
--disable-strip disable stripping binaries
--disable-werror disable compilation abort on warning
--disable-stack-protector disable compiler-provided stack protection
- --audio-drv-list=LIST set audio drivers list
+ --audio-drv-list=LIST set audio drivers to try if -audiodev is not used
--block-drv-whitelist=L Same as --block-drv-rw-whitelist=L
--block-drv-rw-whitelist=L
set block driver read-write whitelist
@@ -1521,7 +1496,7 @@ python_version=$($python -c 'import sys; print("%d.%d.%d" % (sys.version_info[0]
python="$python -B"
if test -z "$meson"; then
- if test "$explicit_python" = no && has meson && version_ge "$(meson --version)" 0.59.2; then
+ if test "$explicit_python" = no && has meson && version_ge "$(meson --version)" 0.59.3; then
meson=meson
elif test $git_submodules_action != 'ignore' ; then
meson=git
@@ -1745,17 +1720,6 @@ if test "$static" = "yes" ; then
fi
fi
-# Unconditional check for compiler __thread support
- cat > $TMPC << EOF
-static __thread int tls_var;
-int main(void) { return tls_var; }
-EOF
-
-if ! compile_prog "-Werror" "" ; then
- error_exit "Your compiler does not support the __thread specifier for " \
- "Thread-Local Storage (TLS). Please upgrade to a version that does."
-fi
-
cat > $TMPC << EOF
#ifdef __linux__
@@ -1767,9 +1731,11 @@ static THREAD int tls_var;
int main(void) { return tls_var; }
EOF
-# Check we support --no-pie first; we will need this for building ROMs.
+# Check we support -fno-pie and -no-pie first; we will need the former for
+# building ROMs, and both for everything if --disable-pie is passed.
if compile_prog "-Werror -fno-pie" "-no-pie"; then
CFLAGS_NOPIE="-fno-pie"
+ LDFLAGS_NOPIE="-no-pie"
fi
if test "$static" = "yes"; then
@@ -1785,6 +1751,7 @@ if test "$static" = "yes"; then
fi
elif test "$pie" = "no"; then
CONFIGURE_CFLAGS="$CFLAGS_NOPIE $CONFIGURE_CFLAGS"
+ CONFIGURE_LDFLAGS="$LDFLAGS_NOPIE $CONFIGURE_LDFLAGS"
elif compile_prog "-Werror -fPIE -DPIE" "-pie"; then
CONFIGURE_CFLAGS="-fPIE -DPIE $CONFIGURE_CFLAGS"
CONFIGURE_LDFLAGS="-pie $CONFIGURE_LDFLAGS"
@@ -1914,20 +1881,6 @@ if test -z "$want_tools"; then
fi
fi
-##########################################
-# L2TPV3 probe
-
-cat > $TMPC <<EOF
-#include <sys/socket.h>
-#include <linux/ip.h>
-int main(void) { return sizeof(struct mmsghdr); }
-EOF
-if compile_prog "" "" ; then
- l2tpv3=yes
-else
- l2tpv3=no
-fi
-
#########################################
# vhost interdependencies and host support
@@ -1988,25 +1941,6 @@ if ! has "$pkg_config_exe"; then
fi
##########################################
-# NPTL probe
-
-if test "$linux_user" = "yes"; then
- cat > $TMPC <<EOF
-#include <sched.h>
-#include <linux/futex.h>
-int main(void) {
-#if !defined(CLONE_SETTLS) || !defined(FUTEX_WAIT)
-#error bork
-#endif
- return 0;
-}
-EOF
- if ! compile_object ; then
- feature_not_found "nptl" "Install glibc and linux kernel headers."
- fi
-fi
-
-##########################################
# xen probe
if test "$xen" != "disabled" ; then
@@ -3551,9 +3485,6 @@ if test "$slirp_smbd" = "yes" ; then
echo "CONFIG_SLIRP_SMBD=y" >> $config_host_mak
echo "CONFIG_SMBD_COMMAND=\"$smbd\"" >> $config_host_mak
fi
-if test "$l2tpv3" = "yes" ; then
- echo "CONFIG_L2TPV3=y" >> $config_host_mak
-fi
if test "$gprof" = "yes" ; then
echo "CONFIG_GPROF=y" >> $config_host_mak
fi
@@ -3956,6 +3887,10 @@ for rom in seabios; do
echo "RANLIB=$ranlib" >> $config_mak
done
+config_mak=pc-bios/optionrom/config.mak
+echo "# Automatically generated by configure - do not modify" > $config_mak
+echo "TOPSRC_DIR=$source_path" >> $config_mak
+
if test "$skip_meson" = no; then
cross="config-meson.cross.new"
meson_quote() {
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index be19317470..56f9ad15ab 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -160,6 +160,11 @@ Use ``-display sdl`` instead.
Use ``-display curses`` instead.
+``-watchdog`` (since 6.2)
+'''''''''''''''''''''''''
+
+Use ``-device`` instead.
+
``-smp`` ("parameter=0" SMP configurations) (since 6.2)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
@@ -313,6 +318,16 @@ full SCSI support. Use virtio-scsi instead when SCSI passthrough is required.
Note this also applies to ``-device virtio-blk-pci,scsi=on|off``, which is an
alias.
+``-device sga`` (since 6.2)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``sga`` device loads an option ROM for x86 targets which enables
+SeaBIOS to send messages to the serial console. SeaBIOS 1.11.0 onwards
+contains native support for this feature and thus use of the option
+ROM approach is obsolete. The native SeaBIOS support can be activated
+by using ``-machine graphics=off``.
+
+
Block device options
''''''''''''''''''''
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
index f95df10b3e..7c25177c5d 100644
--- a/docs/devel/index.rst
+++ b/docs/devel/index.rst
@@ -44,4 +44,4 @@ modifying QEMU's source code.
ebpf_rss
vfio-migration
qapi-code-gen
- writing-qmp-commands
+ writing-monitor-commands
diff --git a/docs/devel/writing-qmp-commands.rst b/docs/devel/writing-monitor-commands.rst
index 6a10a06c48..b3e2c8481d 100644
--- a/docs/devel/writing-qmp-commands.rst
+++ b/docs/devel/writing-monitor-commands.rst
@@ -1,8 +1,8 @@
-How to write QMP commands using the QAPI framework
-==================================================
+How to write monitor commands
+=============================
This document is a step-by-step guide on how to write new QMP commands using
-the QAPI framework. It also shows how to implement new style HMP commands.
+the QAPI framework and HMP commands.
This document doesn't discuss QMP protocol level details, nor does it dive
into the QAPI framework implementation.
@@ -11,6 +11,14 @@ For an in-depth introduction to the QAPI framework, please refer to
docs/devel/qapi-code-gen.txt. For documentation about the QMP protocol,
start with docs/interop/qmp-intro.txt.
+New commands may be implemented in QMP only. New HMP commands should be
+implemented on top of QMP. The typical HMP command wraps around an
+equivalent QMP command, but HMP convenience commands built from QMP
+building blocks are also fine. The long term goal is to make all
+existing HMP commands conform to this, to fully isolate HMP from the
+internals of QEMU. Refer to the `Writing a debugging aid returning
+unstructured text`_ section for further guidance on commands that
+would have traditionally been HMP only.
Overview
--------
@@ -85,8 +93,8 @@ any data". Now you're ready to enter the QMP example commands as explained in
the following sections.
-Writing a command that doesn't return data
-------------------------------------------
+Writing a simple command: hello-world
+-------------------------------------
That's the most simple QMP command that can be written. Usually, this kind of
command carries some meaningful action in QEMU but here it will just print
@@ -293,9 +301,7 @@ Here's the implementation of the "hello-world" HMP command::
Error *err = NULL;
qmp_hello_world(!!message, message, &err);
- if (err) {
- monitor_printf(mon, "%s\n", error_get_pretty(err));
- error_free(err);
+ if (hmp_handle_error(mon, err)) {
return;
}
}
@@ -307,9 +313,10 @@ There are three important points to be noticed:
1. The "mon" and "qdict" arguments are mandatory for all HMP functions. The
former is the monitor object. The latter is how the monitor passes
arguments entered by the user to the command implementation
-2. hmp_hello_world() performs error checking. In this example we just print
- the error description to the user, but we could do more, like taking
- different actions depending on the error qmp_hello_world() returns
+2. hmp_hello_world() performs error checking. In this example we just call
+ hmp_handle_error() which prints a message to the user, but we could do
+ more, like taking different actions depending on the error
+ qmp_hello_world() returns
3. The "err" variable must be initialized to NULL before performing the
QMP call
@@ -340,8 +347,8 @@ Please, check the "-monitor" command-line option to know how to open a user
monitor.
-Writing a command that returns data
------------------------------------
+Writing more complex commands
+-----------------------------
A QMP command is capable of returning any data the QAPI supports like integers,
strings, booleans, enumerations and user defined types.
@@ -350,6 +357,35 @@ In this section we will focus on user defined types. Please, check the QAPI
documentation for information about the other types.
+Modelling data in QAPI
+~~~~~~~~~~~~~~~~~~~~~~
+
+For a QMP command that to be considered stable and supported long term,
+there is a requirement returned data should be explicitly modelled
+using fine-grained QAPI types. As a general guide, a caller of the QMP
+command should never need to parse individual returned data fields. If
+a field appears to need parsing, then it should be split into separate
+fields corresponding to each distinct data item. This should be the
+common case for any new QMP command that is intended to be used by
+machines, as opposed to exclusively human operators.
+
+Some QMP commands, however, are only intended as ad hoc debugging aids
+for human operators. While they may return large amounts of formatted
+data, it is not expected that machines will need to parse the result.
+The overhead of defining a fine grained QAPI type for the data may not
+be justified by the potential benefit. In such cases, it is permitted
+to have a command return a simple string that contains formatted data,
+however, it is mandatory for the command to use the 'x-' name prefix.
+This indicates that the command is not guaranteed to be long term
+stable / liable to change in future and is not following QAPI design
+best practices. An example where this approach is taken is the QMP
+command "x-query-registers". This returns a formatted dump of the
+architecture specific CPU state. The way the data is formatted varies
+across QEMU targets, is liable to change over time, and is only
+intended to be consumed as an opaque string by machines. Refer to the
+`Writing a debugging aid returning unstructured text`_ section for
+an illustration.
+
User Defined Types
~~~~~~~~~~~~~~~~~~
@@ -466,9 +502,7 @@ Here's the HMP counterpart of the query-alarm-clock command::
Error *err = NULL;
clock = qmp_query_alarm_clock(&err);
- if (err) {
- monitor_printf(mon, "Could not query alarm clock information\n");
- error_free(err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -607,9 +641,7 @@ has to traverse the list, it's shown below for reference::
Error *err = NULL;
method_list = qmp_query_alarm_methods(&err);
- if (err) {
- monitor_printf(mon, "Could not query alarm methods\n");
- error_free(err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -620,3 +652,100 @@ has to traverse the list, it's shown below for reference::
qapi_free_TimerAlarmMethodList(method_list);
}
+
+Writing a debugging aid returning unstructured text
+---------------------------------------------------
+
+As discussed in section `Modelling data in QAPI`_, it is required that
+commands expecting machine usage be using fine-grained QAPI data types.
+The exception to this rule applies when the command is solely intended
+as a debugging aid and allows for returning unstructured text. This is
+commonly needed for query commands that report aspects of QEMU's
+internal state that are useful to human operators.
+
+In this example we will consider a simplified variant of the HMP
+command ``info roms``. Following the earlier rules, this command will
+need to live under the ``x-`` name prefix, so its QMP implementation
+will be called ``x-query-roms``. It will have no parameters and will
+return a single text string::
+
+ { 'struct': 'HumanReadableText',
+ 'data': { 'human-readable-text': 'str' } }
+
+ { 'command': 'x-query-roms',
+ 'returns': 'HumanReadableText' }
+
+The ``HumanReadableText`` struct is intended to be used for all
+commands, under the ``x-`` name prefix that are returning unstructured
+text targetted at humans. It should never be used for commands outside
+the ``x-`` name prefix, as those should be using structured QAPI types.
+
+Implementing the QMP command
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The QMP implementation will typically involve creating a ``GString``
+object and printing formatted data into it::
+
+ HumanReadableText *qmp_x_query_roms(Error **errp)
+ {
+ g_autoptr(GString) buf = g_string_new("");
+ Rom *rom;
+
+ QTAILQ_FOREACH(rom, &roms, next) {
+ g_string_append_printf("%s size=0x%06zx name=\"%s\"\n",
+ memory_region_name(rom->mr),
+ rom->romsize,
+ rom->name);
+ }
+
+ return human_readable_text_from_str(buf);
+ }
+
+
+Implementing the HMP command
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Now that the QMP command is in place, we can also make it available in
+the human monitor (HMP) as shown in previous examples. The HMP
+implementations will all look fairly similar, as all they need do is
+invoke the QMP command and then print the resulting text or error
+message. Here's the implementation of the "info roms" HMP command::
+
+ void hmp_info_roms(Monitor *mon, const QDict *qdict)
+ {
+ Error err = NULL;
+ g_autoptr(HumanReadableText) info = qmp_x_query_roms(&err);
+
+ if (hmp_handle_error(mon, err)) {
+ return;
+ }
+ monitor_printf(mon, "%s", info->human_readable_text);
+ }
+
+Also, you have to add the function's prototype to the hmp.h file.
+
+There's one last step to actually make the command available to
+monitor users, we should add it to the hmp-commands-info.hx file::
+
+ {
+ .name = "roms",
+ .args_type = "",
+ .params = "",
+ .help = "show roms",
+ .cmd = hmp_info_roms,
+ },
+
+The case of writing a HMP info handler that calls a no-parameter QMP query
+command is quite common. To simplify the implementation there is a general
+purpose HMP info handler for this scenario. All that is required to expose
+a no-parameter QMP query command via HMP is to declare it using the
+'.cmd_info_hrt' field to point to the QMP handler, and leave the '.cmd'
+field NULL::
+
+ {
+ .name = "roms",
+ .args_type = "",
+ .params = "",
+ .help = "show roms",
+ .cmd_info_hrt = qmp_x_query_roms,
+ },
diff --git a/gdb-xml/arm-m-profile-mve.xml b/gdb-xml/arm-m-profile-mve.xml
new file mode 100644
index 0000000000..cba664c4c5
--- /dev/null
+++ b/gdb-xml/arm-m-profile-mve.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2021 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.arm.m-profile-mve">
+ <flags id="vpr_reg" size="4">
+ <!-- ARMv8.1-M and MVE: Unprivileged and privileged Access. -->
+ <field name="P0" start="0" end="15"/>
+ <!-- ARMv8.1-M: Privileged Access only. -->
+ <field name="MASK01" start="16" end="19"/>
+ <!-- ARMv8.1-M: Privileged Access only. -->
+ <field name="MASK23" start="20" end="23"/>
+ </flags>
+ <reg name="vpr" bitsize="32" type="vpr_reg"/>
+</feature>
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index 4c966e8a6b..407a1da800 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -127,21 +127,6 @@ SRST
Show local APIC state
ERST
-#if defined(TARGET_I386)
- {
- .name = "ioapic",
- .args_type = "",
- .params = "",
- .help = "show io apic state",
- .cmd = hmp_info_io_apic,
- },
-#endif
-
-SRST
- ``info ioapic``
- Show io APIC state
-ERST
-
{
.name = "cpus",
.args_type = "",
@@ -174,7 +159,7 @@ ERST
.args_type = "",
.params = "",
.help = "show the interrupts statistics (if available)",
- .cmd = hmp_info_irq,
+ .cmd_info_hrt = qmp_x_query_irq,
},
SRST
@@ -200,7 +185,7 @@ ERST
.args_type = "",
.params = "",
.help = "show RDMA state",
- .cmd = hmp_info_rdma,
+ .cmd_info_hrt = qmp_x_query_rdma,
},
SRST
@@ -340,7 +325,7 @@ ERST
.args_type = "",
.params = "",
.help = "show NUMA information",
- .cmd = hmp_info_numa,
+ .cmd_info_hrt = qmp_x_query_numa,
},
SRST
@@ -353,7 +338,7 @@ ERST
.args_type = "",
.params = "",
.help = "show guest USB devices",
- .cmd = hmp_info_usb,
+ .cmd_info_hrt = qmp_x_query_usb,
},
SRST
@@ -378,7 +363,7 @@ ERST
.args_type = "",
.params = "",
.help = "show profiling information",
- .cmd = hmp_info_profile,
+ .cmd_info_hrt = qmp_x_query_profile,
},
SRST
@@ -609,7 +594,7 @@ ERST
.args_type = "",
.params = "",
.help = "show roms",
- .cmd = hmp_info_roms,
+ .cmd_info_hrt = qmp_x_query_roms,
},
SRST
@@ -787,7 +772,7 @@ ERST
.args_type = "",
.params = "",
.help = "Display system ramblock information",
- .cmd = hmp_info_ramblock,
+ .cmd_info_hrt = qmp_x_query_ramblock,
},
SRST
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 2ab0080e0b..878c2208e0 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -63,6 +63,8 @@
#define NPCM7XX_ROM_BA (0xffff0000)
#define NPCM7XX_ROM_SZ (64 * KiB)
+/* SDHCI Modules */
+#define NPCM7XX_MMC_BA (0xf0842000)
/* Clock configuration values to be fixed up when bypassing bootloader */
@@ -83,6 +85,7 @@ enum NPCM7xxInterrupt {
NPCM7XX_UART3_IRQ,
NPCM7XX_EMC1RX_IRQ = 15,
NPCM7XX_EMC1TX_IRQ,
+ NPCM7XX_MMC_IRQ = 26,
NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
NPCM7XX_TIMER1_IRQ,
NPCM7XX_TIMER2_IRQ,
@@ -443,6 +446,8 @@ static void npcm7xx_init(Object *obj)
for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
}
+
+ object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
}
static void npcm7xx_realize(DeviceState *dev, Error **errp)
@@ -707,6 +712,12 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
&error_abort);
memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom);
+ /* SDHCI */
+ sysbus_realize(SYS_BUS_DEVICE(&s->mmc), &error_abort);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc), 0, NPCM7XX_MMC_BA);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc), 0,
+ npcm7xx_irq(s, NPCM7XX_MMC_IRQ));
+
create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB);
create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
@@ -736,7 +747,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
create_unimplemented_device("npcm7xx.usbd[8]", 0xf0838000, 4 * KiB);
create_unimplemented_device("npcm7xx.usbd[9]", 0xf0839000, 4 * KiB);
create_unimplemented_device("npcm7xx.sd", 0xf0840000, 8 * KiB);
- create_unimplemented_device("npcm7xx.mmc", 0xf0842000, 8 * KiB);
create_unimplemented_device("npcm7xx.pcimbx", 0xf0848000, 512 * KiB);
create_unimplemented_device("npcm7xx.aes", 0xf0858000, 4 * KiB);
create_unimplemented_device("npcm7xx.des", 0xf0859000, 4 * KiB);
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index a656169f61..dec7d16ae5 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -27,6 +27,9 @@
#include "qemu-common.h"
#include "qemu/datadir.h"
#include "qemu/units.h"
+#include "sysemu/blockdev.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/block-backend.h"
#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
@@ -81,6 +84,22 @@ static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
&error_abort);
}
+static void sdhci_attach_drive(SDHCIState *sdhci)
+{
+ DriveInfo *di = drive_get_next(IF_SD);
+ BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
+
+ BusState *bus = qdev_get_child_bus(DEVICE(sdhci), "sd-bus");
+ if (bus == NULL) {
+ error_report("No SD bus found in SOC object");
+ exit(1);
+ }
+
+ DeviceState *carddev = qdev_new(TYPE_SD_CARD);
+ qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
+ qdev_realize_and_unref(carddev, bus, &error_fatal);
+}
+
static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
uint32_t hw_straps)
{
@@ -355,6 +374,7 @@ static void quanta_gbs_init(MachineState *machine)
drive_get(IF_MTD, 0, 0));
quanta_gbs_i2c_init(soc);
+ sdhci_attach_drive(&soc->mmc.sdhci);
npcm7xx_load_kernel(machine, soc);
}
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index ca433adb5b..369552ad45 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2737,10 +2737,10 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
"Set the IOMMU type. "
"Valid values are none and smmuv3");
- object_class_property_add_bool(oc, "default_bus_bypass_iommu",
+ object_class_property_add_bool(oc, "default-bus-bypass-iommu",
virt_get_default_bus_bypass_iommu,
virt_set_default_bus_bypass_iommu);
- object_class_property_set_description(oc, "default_bus_bypass_iommu",
+ object_class_property_set_description(oc, "default-bus-bypass-iommu",
"Set on/off to enable/disable "
"bypass_iommu for default root bus");
diff --git a/hw/core/loader.c b/hw/core/loader.c
index c7f97fdce8..052a0fd719 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -46,6 +46,8 @@
#include "qemu-common.h"
#include "qemu/datadir.h"
#include "qapi/error.h"
+#include "qapi/qapi-commands-machine.h"
+#include "qapi/type-helpers.h"
#include "trace.h"
#include "hw/hw.h"
#include "disas/disas.h"
@@ -1474,32 +1476,35 @@ void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size)
return cbdata.rom;
}
-void hmp_info_roms(Monitor *mon, const QDict *qdict)
+HumanReadableText *qmp_x_query_roms(Error **errp)
{
Rom *rom;
+ g_autoptr(GString) buf = g_string_new("");
QTAILQ_FOREACH(rom, &roms, next) {
if (rom->mr) {
- monitor_printf(mon, "%s"
- " size=0x%06zx name=\"%s\"\n",
- memory_region_name(rom->mr),
- rom->romsize,
- rom->name);
+ g_string_append_printf(buf, "%s"
+ " size=0x%06zx name=\"%s\"\n",
+ memory_region_name(rom->mr),
+ rom->romsize,
+ rom->name);
} else if (!rom->fw_file) {
- monitor_printf(mon, "addr=" TARGET_FMT_plx
- " size=0x%06zx mem=%s name=\"%s\"\n",
- rom->addr, rom->romsize,
- rom->isrom ? "rom" : "ram",
- rom->name);
+ g_string_append_printf(buf, "addr=" TARGET_FMT_plx
+ " size=0x%06zx mem=%s name=\"%s\"\n",
+ rom->addr, rom->romsize,
+ rom->isrom ? "rom" : "ram",
+ rom->name);
} else {
- monitor_printf(mon, "fw=%s/%s"
- " size=0x%06zx name=\"%s\"\n",
- rom->fw_dir,
- rom->fw_file,
- rom->romsize,
- rom->name);
+ g_string_append_printf(buf, "fw=%s/%s"
+ " size=0x%06zx name=\"%s\"\n",
+ rom->fw_dir,
+ rom->fw_file,
+ rom->romsize,
+ rom->name);
}
}
+
+ return human_readable_text_from_str(buf);
}
typedef enum HexRecord HexRecord;
diff --git a/hw/core/machine-hmp-cmds.c b/hw/core/machine-hmp-cmds.c
index 76b22b00d6..4e2f319aeb 100644
--- a/hw/core/machine-hmp-cmds.c
+++ b/hw/core/machine-hmp-cmds.c
@@ -53,8 +53,7 @@ void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict)
HotpluggableCPUList *saved = l;
CpuInstanceProperties *c;
- if (err != NULL) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -131,38 +130,3 @@ void hmp_info_memdev(Monitor *mon, const QDict *qdict)
qapi_free_MemdevList(memdev_list);
hmp_handle_error(mon, err);
}
-
-void hmp_info_numa(Monitor *mon, const QDict *qdict)
-{
- int i, nb_numa_nodes;
- NumaNodeMem *node_mem;
- CpuInfoFastList *cpu_list, *cpu;
- MachineState *ms = MACHINE(qdev_get_machine());
-
- nb_numa_nodes = ms->numa_state ? ms->numa_state->num_nodes : 0;
- monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
- if (!nb_numa_nodes) {
- return;
- }
-
- cpu_list = qmp_query_cpus_fast(&error_abort);
- node_mem = g_new0(NumaNodeMem, nb_numa_nodes);
-
- query_numa_node_mem(node_mem, ms);
- for (i = 0; i < nb_numa_nodes; i++) {
- monitor_printf(mon, "node %d cpus:", i);
- for (cpu = cpu_list; cpu; cpu = cpu->next) {
- if (cpu->value->has_props && cpu->value->props->has_node_id &&
- cpu->value->props->node_id == i) {
- monitor_printf(mon, " %" PRIi64, cpu->value->cpu_index);
- }
- }
- monitor_printf(mon, "\n");
- monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i,
- node_mem[i].node_mem >> 20);
- monitor_printf(mon, "node %d plugged: %" PRId64 " MB\n", i,
- node_mem[i].node_plugged_mem >> 20);
- }
- qapi_free_CpuInfoFastList(cpu_list);
- g_free(node_mem);
-}
diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
index 216fdfaf3a..4f4ab30f8c 100644
--- a/hw/core/machine-qmp-cmds.c
+++ b/hw/core/machine-qmp-cmds.c
@@ -15,6 +15,7 @@
#include "qapi/qmp/qerror.h"
#include "qapi/qmp/qobject.h"
#include "qapi/qobject-input-visitor.h"
+#include "qapi/type-helpers.h"
#include "qemu/main-loop.h"
#include "qom/qom-qobject.h"
#include "sysemu/hostmem.h"
@@ -204,3 +205,42 @@ MemdevList *qmp_query_memdev(Error **errp)
object_child_foreach(obj, query_memdev, &list);
return list;
}
+
+HumanReadableText *qmp_x_query_numa(Error **errp)
+{
+ g_autoptr(GString) buf = g_string_new("");
+ int i, nb_numa_nodes;
+ NumaNodeMem *node_mem;
+ CpuInfoFastList *cpu_list, *cpu;
+ MachineState *ms = MACHINE(qdev_get_machine());
+
+ nb_numa_nodes = ms->numa_state ? ms->numa_state->num_nodes : 0;
+ g_string_append_printf(buf, "%d nodes\n", nb_numa_nodes);
+ if (!nb_numa_nodes) {
+ goto done;
+ }
+
+ cpu_list = qmp_query_cpus_fast(&error_abort);
+ node_mem = g_new0(NumaNodeMem, nb_numa_nodes);
+
+ query_numa_node_mem(node_mem, ms);
+ for (i = 0; i < nb_numa_nodes; i++) {
+ g_string_append_printf(buf, "node %d cpus:", i);
+ for (cpu = cpu_list; cpu; cpu = cpu->next) {
+ if (cpu->value->has_props && cpu->value->props->has_node_id &&
+ cpu->value->props->node_id == i) {
+ g_string_append_printf(buf, " %" PRIi64, cpu->value->cpu_index);
+ }
+ }
+ g_string_append_printf(buf, "\n");
+ g_string_append_printf(buf, "node %d size: %" PRId64 " MB\n", i,
+ node_mem[i].node_mem >> 20);
+ g_string_append_printf(buf, "node %d plugged: %" PRId64 " MB\n", i,
+ node_mem[i].node_plugged_mem >> 20);
+ }
+ qapi_free_CpuInfoFastList(cpu_list);
+ g_free(node_mem);
+
+ done:
+ return human_readable_text_from_str(buf);
+}
diff --git a/hw/core/machine.c b/hw/core/machine.c
index e24e3e27db..948b3d9524 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -978,6 +978,9 @@ static char *cpu_slot_to_string(const CPUArchId *cpu)
g_string_append_printf(s, "socket-id: %"PRId64, cpu->props.socket_id);
}
if (cpu->props.has_die_id) {
+ if (s->len) {
+ g_string_append_printf(s, ", ");
+ }
g_string_append_printf(s, "die-id: %"PRId64, cpu->props.die_id);
}
if (cpu->props.has_core_id) {
diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
index c6f7f58784..60ea7f8f49 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -186,7 +186,7 @@ static VGPUDMABuf
dmabuf->buf.fourcc = qemu_pixman_to_drm_format(fb->format);
dmabuf->buf.fd = res->dmabuf_fd;
dmabuf->buf.allow_fences = true;
-
+ dmabuf->buf.draw_submitted = false;
dmabuf->scanout_id = scanout_id;
QTAILQ_INSERT_HEAD(&g->dmabuf.bufs, dmabuf, next);
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index c27b20090e..294499ee20 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -1105,7 +1105,7 @@ static int vtd_page_walk_one(IOMMUTLBEvent *event, vtd_page_walk_info *info)
.translated_addr = entry->translated_addr,
.perm = entry->perm,
};
- DMAMap *mapped = iova_tree_find(as->iova_tree, &target);
+ const DMAMap *mapped = iova_tree_find(as->iova_tree, &target);
if (event->type == IOMMU_NOTIFIER_UNMAP && !info->notify_unmap) {
trace_vtd_page_walk_one_skip_unmap(entry->iova, entry->addr_mask);
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index c502965219..213e2e82b3 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -11,7 +11,7 @@ i386_ss.add(when: 'CONFIG_X86_IOMMU', if_true: files('x86-iommu.c'),
if_false: files('x86-iommu-stub.c'))
i386_ss.add(when: 'CONFIG_AMD_IOMMU', if_true: files('amd_iommu.c'))
i386_ss.add(when: 'CONFIG_I440FX', if_true: files('pc_piix.c'))
-i386_ss.add(when: 'CONFIG_MICROVM', if_true: files('microvm.c', 'acpi-microvm.c'))
+i386_ss.add(when: 'CONFIG_MICROVM', if_true: files('microvm.c', 'acpi-microvm.c', 'microvm-dt.c'))
i386_ss.add(when: 'CONFIG_Q35', if_true: files('pc_q35.c'))
i386_ss.add(when: 'CONFIG_VMMOUSE', if_true: files('vmmouse.c'))
i386_ss.add(when: 'CONFIG_VMPORT', if_true: files('vmport.c'))
diff --git a/hw/i386/microvm-dt.c b/hw/i386/microvm-dt.c
new file mode 100644
index 0000000000..875ba91963
--- /dev/null
+++ b/hw/i386/microvm-dt.c
@@ -0,0 +1,341 @@
+/*
+ * microvm device tree support
+ *
+ * This generates an device tree for microvm and exports it via fw_cfg
+ * as "etc/fdt" to the firmware (edk2 specifically).
+ *
+ * The use case is to allow edk2 find the pcie ecam and the virtio
+ * devices, without adding an ACPI parser, reusing the fdt parser
+ * which is needed anyway for the arm platform.
+ *
+ * Note 1: The device tree is incomplete. CPUs and memory is missing
+ * for example, those can be detected using other fw_cfg files.
+ * Also pci ecam irq routing is not there, edk2 doesn't use
+ * interrupts.
+ *
+ * Note 2: This is for firmware only. OSes should use the more
+ * complete ACPI tables for hardware discovery.
+ *
+ * ----------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "qemu/osdep.h"
+#include "qemu/cutils.h"
+#include "sysemu/device_tree.h"
+#include "hw/char/serial.h"
+#include "hw/i386/fw_cfg.h"
+#include "hw/rtc/mc146818rtc.h"
+#include "hw/sysbus.h"
+#include "hw/virtio/virtio-mmio.h"
+#include "hw/usb/xhci.h"
+
+#include "microvm-dt.h"
+
+static bool debug;
+
+static void dt_add_microvm_irq(MicrovmMachineState *mms,
+ const char *nodename, uint32_t irq)
+{
+ int index = 0;
+
+ if (irq >= IO_APIC_SECONDARY_IRQBASE) {
+ irq -= IO_APIC_SECONDARY_IRQBASE;
+ index++;
+ }
+
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "interrupt-parent",
+ mms->ioapic_phandle[index]);
+ qemu_fdt_setprop_cells(mms->fdt, nodename, "interrupts", irq, 0);
+}
+
+static void dt_add_virtio(MicrovmMachineState *mms, VirtIOMMIOProxy *mmio)
+{
+ SysBusDevice *dev = SYS_BUS_DEVICE(mmio);
+ VirtioBusState *mmio_virtio_bus = &mmio->bus;
+ BusState *mmio_bus = &mmio_virtio_bus->parent_obj;
+ char *nodename;
+
+ if (QTAILQ_EMPTY(&mmio_bus->children)) {
+ return;
+ }
+
+ hwaddr base = dev->mmio[0].addr;
+ hwaddr size = 512;
+ unsigned index = (base - VIRTIO_MMIO_BASE) / size;
+ uint32_t irq = mms->virtio_irq_base + index;
+
+ nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
+ qemu_fdt_add_subnode(mms->fdt, nodename);
+ qemu_fdt_setprop_string(mms->fdt, nodename, "compatible", "virtio,mmio");
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "reg", 2, base, 2, size);
+ qemu_fdt_setprop(mms->fdt, nodename, "dma-coherent", NULL, 0);
+ dt_add_microvm_irq(mms, nodename, irq);
+ g_free(nodename);
+}
+
+static void dt_add_xhci(MicrovmMachineState *mms)
+{
+ const char compat[] = "generic-xhci";
+ uint32_t irq = MICROVM_XHCI_IRQ;
+ hwaddr base = MICROVM_XHCI_BASE;
+ hwaddr size = XHCI_LEN_REGS;
+ char *nodename;
+
+ nodename = g_strdup_printf("/usb@%" PRIx64, base);
+ qemu_fdt_add_subnode(mms->fdt, nodename);
+ qemu_fdt_setprop(mms->fdt, nodename, "compatible", compat, sizeof(compat));
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "reg", 2, base, 2, size);
+ qemu_fdt_setprop(mms->fdt, nodename, "dma-coherent", NULL, 0);
+ dt_add_microvm_irq(mms, nodename, irq);
+ g_free(nodename);
+}
+
+static void dt_add_pcie(MicrovmMachineState *mms)
+{
+ hwaddr base = PCIE_MMIO_BASE;
+ int nr_pcie_buses;
+ char *nodename;
+
+ nodename = g_strdup_printf("/pcie@%" PRIx64, base);
+ qemu_fdt_add_subnode(mms->fdt, nodename);
+ qemu_fdt_setprop_string(mms->fdt, nodename,
+ "compatible", "pci-host-ecam-generic");
+ qemu_fdt_setprop_string(mms->fdt, nodename, "device_type", "pci");
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "#address-cells", 3);
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "#size-cells", 2);
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "linux,pci-domain", 0);
+ qemu_fdt_setprop(mms->fdt, nodename, "dma-coherent", NULL, 0);
+
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "reg",
+ 2, PCIE_ECAM_BASE, 2, PCIE_ECAM_SIZE);
+ if (mms->gpex.mmio64.size) {
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "ranges",
+
+ 1, FDT_PCI_RANGE_MMIO,
+ 2, mms->gpex.mmio32.base,
+ 2, mms->gpex.mmio32.base,
+ 2, mms->gpex.mmio32.size,
+
+ 1, FDT_PCI_RANGE_MMIO_64BIT,
+ 2, mms->gpex.mmio64.base,
+ 2, mms->gpex.mmio64.base,
+ 2, mms->gpex.mmio64.size);
+ } else {
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "ranges",
+
+ 1, FDT_PCI_RANGE_MMIO,
+ 2, mms->gpex.mmio32.base,
+ 2, mms->gpex.mmio32.base,
+ 2, mms->gpex.mmio32.size);
+ }
+
+ nr_pcie_buses = PCIE_ECAM_SIZE / PCIE_MMCFG_SIZE_MIN;
+ qemu_fdt_setprop_cells(mms->fdt, nodename, "bus-range", 0,
+ nr_pcie_buses - 1);
+}
+
+static void dt_add_ioapic(MicrovmMachineState *mms, SysBusDevice *dev)
+{
+ hwaddr base = dev->mmio[0].addr;
+ char *nodename;
+ uint32_t ph;
+ int index;
+
+ switch (base) {
+ case IO_APIC_DEFAULT_ADDRESS:
+ index = 0;
+ break;
+ case IO_APIC_SECONDARY_ADDRESS:
+ index = 1;
+ break;
+ default:
+ fprintf(stderr, "unknown ioapic @ %" PRIx64 "\n", base);
+ return;
+ }
+
+ nodename = g_strdup_printf("/ioapic%d@%" PRIx64, index + 1, base);
+ qemu_fdt_add_subnode(mms->fdt, nodename);
+ qemu_fdt_setprop_string(mms->fdt, nodename,
+ "compatible", "intel,ce4100-ioapic");
+ qemu_fdt_setprop(mms->fdt, nodename, "interrupt-controller", NULL, 0);
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "#interrupt-cells", 0x2);
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "#address-cells", 0x2);
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "reg",
+ 2, base, 2, 0x1000);
+
+ ph = qemu_fdt_alloc_phandle(mms->fdt);
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "phandle", ph);
+ qemu_fdt_setprop_cell(mms->fdt, nodename, "linux,phandle", ph);
+ mms->ioapic_phandle[index] = ph;
+
+ g_free(nodename);
+}
+
+static void dt_add_isa_serial(MicrovmMachineState *mms, ISADevice *dev)
+{
+ const char compat[] = "ns16550";
+ uint32_t irq = object_property_get_int(OBJECT(dev), "irq", NULL);
+ hwaddr base = object_property_get_int(OBJECT(dev), "iobase", NULL);
+ hwaddr size = 8;
+ char *nodename;
+
+ nodename = g_strdup_printf("/serial@%" PRIx64, base);
+ qemu_fdt_add_subnode(mms->fdt, nodename);
+ qemu_fdt_setprop(mms->fdt, nodename, "compatible", compat, sizeof(compat));
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "reg", 2, base, 2, size);
+ dt_add_microvm_irq(mms, nodename, irq);
+
+ if (base == 0x3f8 /* com1 */) {
+ qemu_fdt_setprop_string(mms->fdt, "/chosen", "stdout-path", nodename);
+ }
+
+ g_free(nodename);
+}
+
+static void dt_add_isa_rtc(MicrovmMachineState *mms, ISADevice *dev)
+{
+ const char compat[] = "motorola,mc146818";
+ uint32_t irq = RTC_ISA_IRQ;
+ hwaddr base = RTC_ISA_BASE;
+ hwaddr size = 8;
+ char *nodename;
+
+ nodename = g_strdup_printf("/rtc@%" PRIx64, base);
+ qemu_fdt_add_subnode(mms->fdt, nodename);
+ qemu_fdt_setprop(mms->fdt, nodename, "compatible", compat, sizeof(compat));
+ qemu_fdt_setprop_sized_cells(mms->fdt, nodename, "reg", 2, base, 2, size);
+ dt_add_microvm_irq(mms, nodename, irq);
+ g_free(nodename);
+}
+
+static void dt_setup_isa_bus(MicrovmMachineState *mms, DeviceState *bridge)
+{
+ BusState *bus = qdev_get_child_bus(bridge, "isa.0");
+ BusChild *kid;
+ Object *obj;
+
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
+ DeviceState *dev = kid->child;
+
+ /* serial */
+ obj = object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL);
+ if (obj) {
+ dt_add_isa_serial(mms, ISA_DEVICE(obj));
+ continue;
+ }
+
+ /* rtc */
+ obj = object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC);
+ if (obj) {
+ dt_add_isa_rtc(mms, ISA_DEVICE(obj));
+ continue;
+ }
+
+ if (debug) {
+ fprintf(stderr, "%s: unhandled: %s\n", __func__,
+ object_get_typename(OBJECT(dev)));
+ }
+ }
+}
+
+static void dt_setup_sys_bus(MicrovmMachineState *mms)
+{
+ BusState *bus;
+ BusChild *kid;
+ Object *obj;
+
+ /* sysbus devices */
+ bus = sysbus_get_default();
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
+ DeviceState *dev = kid->child;
+
+ /* ioapic */
+ obj = object_dynamic_cast(OBJECT(dev), TYPE_IOAPIC);
+ if (obj) {
+ dt_add_ioapic(mms, SYS_BUS_DEVICE(obj));
+ continue;
+ }
+ }
+
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
+ DeviceState *dev = kid->child;
+
+ /* virtio */
+ obj = object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MMIO);
+ if (obj) {
+ dt_add_virtio(mms, VIRTIO_MMIO(obj));
+ continue;
+ }
+
+ /* xhci */
+ obj = object_dynamic_cast(OBJECT(dev), TYPE_XHCI_SYSBUS);
+ if (obj) {
+ dt_add_xhci(mms);
+ continue;
+ }
+
+ /* pcie */
+ obj = object_dynamic_cast(OBJECT(dev), TYPE_GPEX_HOST);
+ if (obj) {
+ dt_add_pcie(mms);
+ continue;
+ }
+
+ /* isa */
+ obj = object_dynamic_cast(OBJECT(dev), "isabus-bridge");
+ if (obj) {
+ dt_setup_isa_bus(mms, DEVICE(obj));
+ continue;
+ }
+
+ if (debug) {
+ obj = object_dynamic_cast(OBJECT(dev), TYPE_IOAPIC);
+ if (obj) {
+ /* ioapic already added in first pass */
+ continue;
+ }
+ fprintf(stderr, "%s: unhandled: %s\n", __func__,
+ object_get_typename(OBJECT(dev)));
+ }
+ }
+}
+
+void dt_setup_microvm(MicrovmMachineState *mms)
+{
+ X86MachineState *x86ms = X86_MACHINE(mms);
+ int size = 0;
+
+ mms->fdt = create_device_tree(&size);
+
+ /* root node */
+ qemu_fdt_setprop_string(mms->fdt, "/", "compatible", "linux,microvm");
+ qemu_fdt_setprop_cell(mms->fdt, "/", "#address-cells", 0x2);
+ qemu_fdt_setprop_cell(mms->fdt, "/", "#size-cells", 0x2);
+
+ qemu_fdt_add_subnode(mms->fdt, "/chosen");
+ dt_setup_sys_bus(mms);
+
+ /* add to fw_cfg */
+ fprintf(stderr, "%s: add etc/fdt to fw_cfg\n", __func__);
+ fw_cfg_add_file(x86ms->fw_cfg, "etc/fdt", mms->fdt, size);
+
+ if (debug) {
+ fprintf(stderr, "%s: writing microvm.fdt\n", __func__);
+ g_file_set_contents("microvm.fdt", mms->fdt, size, NULL);
+ int ret = system("dtc -I dtb -O dts microvm.fdt");
+ if (ret != 0) {
+ fprintf(stderr, "%s: oops, dtc not installed?\n", __func__);
+ }
+ }
+}
diff --git a/hw/i386/microvm-dt.h b/hw/i386/microvm-dt.h
new file mode 100644
index 0000000000..77c79cbdd9
--- /dev/null
+++ b/hw/i386/microvm-dt.h
@@ -0,0 +1,8 @@
+#ifndef HW_I386_MICROVM_DT_H
+#define HW_I386_MICROVM_DT_H
+
+#include "hw/i386/microvm.h"
+
+void dt_setup_microvm(MicrovmMachineState *mms);
+
+#endif
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index f257ec5a0b..4b3b1dd262 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -28,6 +28,7 @@
#include "sysemu/reset.h"
#include "sysemu/runstate.h"
#include "acpi-microvm.h"
+#include "microvm-dt.h"
#include "hw/loader.h"
#include "hw/irq.h"
@@ -331,7 +332,7 @@ static void microvm_memory_init(MicrovmMachineState *mms)
rom_set_fw(fw_cfg);
if (machine->kernel_filename != NULL) {
- x86_load_linux(x86ms, fw_cfg, 0, true, true);
+ x86_load_linux(x86ms, fw_cfg, 0, true);
}
if (mms->option_roms) {
@@ -626,6 +627,7 @@ static void microvm_machine_done(Notifier *notifier, void *data)
machine_done);
acpi_setup_microvm(mms);
+ dt_setup_microvm(mms);
}
static void microvm_powerdown_req(Notifier *notifier, void *data)
@@ -667,6 +669,7 @@ static void microvm_machine_initfn(Object *obj)
static void microvm_class_init(ObjectClass *oc, void *data)
{
+ X86MachineClass *x86mc = X86_MACHINE_CLASS(oc);
MachineClass *mc = MACHINE_CLASS(oc);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
@@ -697,6 +700,8 @@ static void microvm_class_init(ObjectClass *oc, void *data)
hc->unplug_request = microvm_device_unplug_request_cb;
hc->unplug = microvm_device_unplug_cb;
+ x86mc->fwcfg_dma_enabled = true;
+
object_class_property_add(oc, MICROVM_MACHINE_PIC, "OnOffAuto",
microvm_machine_get_pic,
microvm_machine_set_pic,
diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c
index 9e7d69d470..0a10089f14 100644
--- a/hw/i386/multiboot.c
+++ b/hw/i386/multiboot.c
@@ -143,7 +143,8 @@ static void mb_add_mod(MultibootState *s,
s->mb_mods_count++;
}
-int load_multiboot(FWCfgState *fw_cfg,
+int load_multiboot(X86MachineState *x86ms,
+ FWCfgState *fw_cfg,
FILE *f,
const char *kernel_filename,
const char *initrd_filename,
@@ -151,6 +152,7 @@ int load_multiboot(FWCfgState *fw_cfg,
int kernel_file_size,
uint8_t *header)
{
+ bool multiboot_dma_enabled = X86_MACHINE_GET_CLASS(x86ms)->fwcfg_dma_enabled;
int i, is_multiboot = 0;
uint32_t flags = 0;
uint32_t mh_entry_addr;
@@ -401,7 +403,11 @@ int load_multiboot(FWCfgState *fw_cfg,
fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, mb_bootinfo_data,
sizeof(bootinfo));
- option_rom[nb_option_roms].name = "multiboot.bin";
+ if (multiboot_dma_enabled) {
+ option_rom[nb_option_roms].name = "multiboot_dma.bin";
+ } else {
+ option_rom[nb_option_roms].name = "multiboot.bin";
+ }
option_rom[nb_option_roms].bootindex = 0;
nb_option_roms++;
diff --git a/hw/i386/multiboot.h b/hw/i386/multiboot.h
index 60de309cd1..2b9182a8ea 100644
--- a/hw/i386/multiboot.h
+++ b/hw/i386/multiboot.h
@@ -2,8 +2,10 @@
#define QEMU_MULTIBOOT_H
#include "hw/nvram/fw_cfg.h"
+#include "hw/i386/x86.h"
-int load_multiboot(FWCfgState *fw_cfg,
+int load_multiboot(X86MachineState *x86ms,
+ FWCfgState *fw_cfg,
FILE *f,
const char *kernel_filename,
const char *initrd_filename,
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e99017e662..2592a82148 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -776,12 +776,13 @@ void xen_load_linux(PCMachineState *pcms)
rom_set_fw(fw_cfg);
x86_load_linux(x86ms, fw_cfg, pcmc->acpi_data_size,
- pcmc->pvh_enabled, pcmc->linuxboot_dma_enabled);
+ pcmc->pvh_enabled);
for (i = 0; i < nb_option_roms; i++) {
assert(!strcmp(option_rom[i].name, "linuxboot.bin") ||
!strcmp(option_rom[i].name, "linuxboot_dma.bin") ||
!strcmp(option_rom[i].name, "pvh.bin") ||
- !strcmp(option_rom[i].name, "multiboot.bin"));
+ !strcmp(option_rom[i].name, "multiboot.bin") ||
+ !strcmp(option_rom[i].name, "multiboot_dma.bin"));
rom_add_option(option_rom[i].name, option_rom[i].bootindex);
}
x86ms->fw_cfg = fw_cfg;
@@ -928,7 +929,7 @@ void pc_memory_init(PCMachineState *pcms,
if (linux_boot) {
x86_load_linux(x86ms, fw_cfg, pcmc->acpi_data_size,
- pcmc->pvh_enabled, pcmc->linuxboot_dma_enabled);
+ pcmc->pvh_enabled);
}
for (i = 0; i < nb_option_roms; i++) {
@@ -1688,7 +1689,6 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
/* BIOS ACPI tables: 128K. Other BIOS datastructures: less than 4K reported
* to be used at the moment, 32K should be enough for a while. */
pcmc->acpi_data_size = 0x20000 + 0x8000;
- pcmc->linuxboot_dma_enabled = true;
pcmc->pvh_enabled = true;
pcmc->kvmclock_create_always = true;
assert(!mc->get_hotplug_handler);
@@ -1742,7 +1742,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
object_class_property_add_bool(oc, "hpet",
pc_machine_get_hpet, pc_machine_set_hpet);
- object_class_property_add_bool(oc, "default_bus_bypass_iommu",
+ object_class_property_add_bool(oc, "default-bus-bypass-iommu",
pc_machine_get_default_bus_bypass_iommu,
pc_machine_set_default_bus_bypass_iommu);
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 6ad0d763c5..223dd3e05d 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -620,11 +620,12 @@ DEFINE_I440FX_MACHINE(v2_7, "pc-i440fx-2.7", NULL,
static void pc_i440fx_2_6_machine_options(MachineClass *m)
{
+ X86MachineClass *x86mc = X86_MACHINE_CLASS(m);
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
pc_i440fx_2_7_machine_options(m);
pcmc->legacy_cpu_hotplug = true;
- pcmc->linuxboot_dma_enabled = false;
+ x86mc->fwcfg_dma_enabled = false;
compat_props_add(m->compat_props, hw_compat_2_6, hw_compat_2_6_len);
compat_props_add(m->compat_props, pc_compat_2_6, pc_compat_2_6_len);
}
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index fcc6e4eb2b..797e09500b 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -573,11 +573,12 @@ DEFINE_Q35_MACHINE(v2_7, "pc-q35-2.7", NULL,
static void pc_q35_2_6_machine_options(MachineClass *m)
{
+ X86MachineClass *x86mc = X86_MACHINE_CLASS(m);
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
pc_q35_2_7_machine_options(m);
pcmc->legacy_cpu_hotplug = true;
- pcmc->linuxboot_dma_enabled = false;
+ x86mc->fwcfg_dma_enabled = false;
compat_props_add(m->compat_props, hw_compat_2_6, hw_compat_2_6_len);
compat_props_add(m->compat_props, pc_compat_2_6, pc_compat_2_6_len);
}
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 76de7e2265..b84840a1bb 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -764,9 +764,9 @@ static bool load_elfboot(const char *kernel_filename,
void x86_load_linux(X86MachineState *x86ms,
FWCfgState *fw_cfg,
int acpi_data_size,
- bool pvh_enabled,
- bool linuxboot_dma_enabled)
+ bool pvh_enabled)
{
+ bool linuxboot_dma_enabled = X86_MACHINE_GET_CLASS(x86ms)->fwcfg_dma_enabled;
uint16_t protocol;
int setup_size, kernel_size, cmdline_size;
int dtb_size, setup_data_offset;
@@ -814,7 +814,7 @@ void x86_load_linux(X86MachineState *x86ms,
* PVH), so we try multiboot first since we check the multiboot magic
* header before to load it.
*/
- if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename,
+ if (load_multiboot(x86ms, fw_cfg, f, kernel_filename, initrd_filename,
kernel_cmdline, kernel_size, header)) {
return;
}
@@ -1332,6 +1332,7 @@ static void x86_machine_class_init(ObjectClass *oc, void *data)
mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids;
x86mc->compat_apic_id_mode = false;
x86mc->save_tsc_khz = true;
+ x86mc->fwcfg_dma_enabled = true;
nc->nmi_monitor_handler = x86_nmi;
object_class_property_add(oc, X86_MACHINE_SMM, "OnOffAuto",
diff --git a/hw/input/lasips2.c b/hw/input/lasips2.c
index e7faf24058..68d741d342 100644
--- a/hw/input/lasips2.c
+++ b/hw/input/lasips2.c
@@ -96,7 +96,7 @@ typedef enum {
LASIPS2_STATUS_CLKSHD = 0x80,
} lasips2_status_reg_t;
-static const char *artist_read_reg_name(uint64_t addr)
+static const char *lasips2_read_reg_name(uint64_t addr)
{
switch (addr & 0xc) {
case REG_PS2_ID:
@@ -116,7 +116,7 @@ static const char *artist_read_reg_name(uint64_t addr)
}
}
-static const char *artist_write_reg_name(uint64_t addr)
+static const char *lasips2_write_reg_name(uint64_t addr)
{
switch (addr & 0x0c) {
case REG_PS2_RESET:
@@ -145,7 +145,7 @@ static void lasips2_reg_write(void *opaque, hwaddr addr, uint64_t val,
LASIPS2Port *port = opaque;
trace_lasips2_reg_write(size, port->id, addr,
- artist_write_reg_name(addr), val);
+ lasips2_write_reg_name(addr), val);
switch (addr & 0xc) {
case REG_PS2_CONTROL:
@@ -239,7 +239,7 @@ static uint64_t lasips2_reg_read(void *opaque, hwaddr addr, unsigned size)
break;
}
trace_lasips2_reg_read(size, port->id, addr,
- artist_read_reg_name(addr), ret);
+ lasips2_read_reg_name(addr), ret);
return ret;
}
diff --git a/hw/misc/sga.c b/hw/misc/sga.c
index 4dbe6d78f9..1d04672b01 100644
--- a/hw/misc/sga.c
+++ b/hw/misc/sga.c
@@ -30,6 +30,7 @@
#include "hw/loader.h"
#include "qemu/module.h"
#include "qom/object.h"
+#include "qemu/error-report.h"
#define SGABIOS_FILENAME "sgabios.bin"
@@ -42,6 +43,7 @@ struct ISASGAState {
static void sga_realizefn(DeviceState *dev, Error **errp)
{
+ warn_report("-device sga is deprecated, use -machine graphics=off");
rom_add_vga(SGABIOS_FILENAME);
}
diff --git a/hw/rdma/rdma_rm.c b/hw/rdma/rdma_rm.c
index 49141d4074..cfd85de3e6 100644
--- a/hw/rdma/rdma_rm.c
+++ b/hw/rdma/rdma_rm.c
@@ -27,58 +27,58 @@
#define PG_DIR_SZ { TARGET_PAGE_SIZE / sizeof(__u64) }
#define PG_TBL_SZ { TARGET_PAGE_SIZE / sizeof(__u64) }
-void rdma_dump_device_counters(Monitor *mon, RdmaDeviceResources *dev_res)
-{
- monitor_printf(mon, "\ttx : %" PRId64 "\n",
- dev_res->stats.tx);
- monitor_printf(mon, "\ttx_len : %" PRId64 "\n",
- dev_res->stats.tx_len);
- monitor_printf(mon, "\ttx_err : %" PRId64 "\n",
- dev_res->stats.tx_err);
- monitor_printf(mon, "\trx_bufs : %" PRId64 "\n",
- dev_res->stats.rx_bufs);
- monitor_printf(mon, "\trx_srq : %" PRId64 "\n",
- dev_res->stats.rx_srq);
- monitor_printf(mon, "\trx_bufs_len : %" PRId64 "\n",
- dev_res->stats.rx_bufs_len);
- monitor_printf(mon, "\trx_bufs_err : %" PRId64 "\n",
- dev_res->stats.rx_bufs_err);
- monitor_printf(mon, "\tcomps : %" PRId64 "\n",
- dev_res->stats.completions);
- monitor_printf(mon, "\tmissing_comps : %" PRId32 "\n",
- dev_res->stats.missing_cqe);
- monitor_printf(mon, "\tpoll_cq (bk) : %" PRId64 "\n",
- dev_res->stats.poll_cq_from_bk);
- monitor_printf(mon, "\tpoll_cq_ppoll_to : %" PRId64 "\n",
- dev_res->stats.poll_cq_ppoll_to);
- monitor_printf(mon, "\tpoll_cq (fe) : %" PRId64 "\n",
- dev_res->stats.poll_cq_from_guest);
- monitor_printf(mon, "\tpoll_cq_empty : %" PRId64 "\n",
- dev_res->stats.poll_cq_from_guest_empty);
- monitor_printf(mon, "\tmad_tx : %" PRId64 "\n",
- dev_res->stats.mad_tx);
- monitor_printf(mon, "\tmad_tx_err : %" PRId64 "\n",
- dev_res->stats.mad_tx_err);
- monitor_printf(mon, "\tmad_rx : %" PRId64 "\n",
- dev_res->stats.mad_rx);
- monitor_printf(mon, "\tmad_rx_err : %" PRId64 "\n",
- dev_res->stats.mad_rx_err);
- monitor_printf(mon, "\tmad_rx_bufs : %" PRId64 "\n",
- dev_res->stats.mad_rx_bufs);
- monitor_printf(mon, "\tmad_rx_bufs_err : %" PRId64 "\n",
- dev_res->stats.mad_rx_bufs_err);
- monitor_printf(mon, "\tPDs : %" PRId32 "\n",
- dev_res->pd_tbl.used);
- monitor_printf(mon, "\tMRs : %" PRId32 "\n",
- dev_res->mr_tbl.used);
- monitor_printf(mon, "\tUCs : %" PRId32 "\n",
- dev_res->uc_tbl.used);
- monitor_printf(mon, "\tQPs : %" PRId32 "\n",
- dev_res->qp_tbl.used);
- monitor_printf(mon, "\tCQs : %" PRId32 "\n",
- dev_res->cq_tbl.used);
- monitor_printf(mon, "\tCEQ_CTXs : %" PRId32 "\n",
- dev_res->cqe_ctx_tbl.used);
+void rdma_format_device_counters(RdmaDeviceResources *dev_res, GString *buf)
+{
+ g_string_append_printf(buf, "\ttx : %" PRId64 "\n",
+ dev_res->stats.tx);
+ g_string_append_printf(buf, "\ttx_len : %" PRId64 "\n",
+ dev_res->stats.tx_len);
+ g_string_append_printf(buf, "\ttx_err : %" PRId64 "\n",
+ dev_res->stats.tx_err);
+ g_string_append_printf(buf, "\trx_bufs : %" PRId64 "\n",
+ dev_res->stats.rx_bufs);
+ g_string_append_printf(buf, "\trx_srq : %" PRId64 "\n",
+ dev_res->stats.rx_srq);
+ g_string_append_printf(buf, "\trx_bufs_len : %" PRId64 "\n",
+ dev_res->stats.rx_bufs_len);
+ g_string_append_printf(buf, "\trx_bufs_err : %" PRId64 "\n",
+ dev_res->stats.rx_bufs_err);
+ g_string_append_printf(buf, "\tcomps : %" PRId64 "\n",
+ dev_res->stats.completions);
+ g_string_append_printf(buf, "\tmissing_comps : %" PRId32 "\n",
+ dev_res->stats.missing_cqe);
+ g_string_append_printf(buf, "\tpoll_cq (bk) : %" PRId64 "\n",
+ dev_res->stats.poll_cq_from_bk);
+ g_string_append_printf(buf, "\tpoll_cq_ppoll_to : %" PRId64 "\n",
+ dev_res->stats.poll_cq_ppoll_to);
+ g_string_append_printf(buf, "\tpoll_cq (fe) : %" PRId64 "\n",
+ dev_res->stats.poll_cq_from_guest);
+ g_string_append_printf(buf, "\tpoll_cq_empty : %" PRId64 "\n",
+ dev_res->stats.poll_cq_from_guest_empty);
+ g_string_append_printf(buf, "\tmad_tx : %" PRId64 "\n",
+ dev_res->stats.mad_tx);
+ g_string_append_printf(buf, "\tmad_tx_err : %" PRId64 "\n",
+ dev_res->stats.mad_tx_err);
+ g_string_append_printf(buf, "\tmad_rx : %" PRId64 "\n",
+ dev_res->stats.mad_rx);
+ g_string_append_printf(buf, "\tmad_rx_err : %" PRId64 "\n",
+ dev_res->stats.mad_rx_err);
+ g_string_append_printf(buf, "\tmad_rx_bufs : %" PRId64 "\n",
+ dev_res->stats.mad_rx_bufs);
+ g_string_append_printf(buf, "\tmad_rx_bufs_err : %" PRId64 "\n",
+ dev_res->stats.mad_rx_bufs_err);
+ g_string_append_printf(buf, "\tPDs : %" PRId32 "\n",
+ dev_res->pd_tbl.used);
+ g_string_append_printf(buf, "\tMRs : %" PRId32 "\n",
+ dev_res->mr_tbl.used);
+ g_string_append_printf(buf, "\tUCs : %" PRId32 "\n",
+ dev_res->uc_tbl.used);
+ g_string_append_printf(buf, "\tQPs : %" PRId32 "\n",
+ dev_res->qp_tbl.used);
+ g_string_append_printf(buf, "\tCQs : %" PRId32 "\n",
+ dev_res->cq_tbl.used);
+ g_string_append_printf(buf, "\tCEQ_CTXs : %" PRId32 "\n",
+ dev_res->cqe_ctx_tbl.used);
}
static inline void res_tbl_init(const char *name, RdmaRmResTbl *tbl,
diff --git a/hw/rdma/rdma_rm.h b/hw/rdma/rdma_rm.h
index e8639909cd..d69a917795 100644
--- a/hw/rdma/rdma_rm.h
+++ b/hw/rdma/rdma_rm.h
@@ -92,6 +92,6 @@ static inline union ibv_gid *rdma_rm_get_gid(RdmaDeviceResources *dev_res,
{
return &dev_res->port.gid_tbl[sgid_idx].gid;
}
-void rdma_dump_device_counters(Monitor *mon, RdmaDeviceResources *dev_res);
+void rdma_format_device_counters(RdmaDeviceResources *dev_res, GString *buf);
#endif
diff --git a/hw/rdma/vmw/pvrdma_main.c b/hw/rdma/vmw/pvrdma_main.c
index 7c0c3551a8..91206dbb8e 100644
--- a/hw/rdma/vmw/pvrdma_main.c
+++ b/hw/rdma/vmw/pvrdma_main.c
@@ -58,24 +58,25 @@ static Property pvrdma_dev_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
-static void pvrdma_print_statistics(Monitor *mon, RdmaProvider *obj)
+static void pvrdma_format_statistics(RdmaProvider *obj, GString *buf)
{
PVRDMADev *dev = PVRDMA_DEV(obj);
PCIDevice *pdev = PCI_DEVICE(dev);
- monitor_printf(mon, "%s, %x.%x\n", pdev->name, PCI_SLOT(pdev->devfn),
- PCI_FUNC(pdev->devfn));
- monitor_printf(mon, "\tcommands : %" PRId64 "\n",
- dev->stats.commands);
- monitor_printf(mon, "\tregs_reads : %" PRId64 "\n",
- dev->stats.regs_reads);
- monitor_printf(mon, "\tregs_writes : %" PRId64 "\n",
- dev->stats.regs_writes);
- monitor_printf(mon, "\tuar_writes : %" PRId64 "\n",
- dev->stats.uar_writes);
- monitor_printf(mon, "\tinterrupts : %" PRId64 "\n",
- dev->stats.interrupts);
- rdma_dump_device_counters(mon, &dev->rdma_dev_res);
+ g_string_append_printf(buf, "%s, %x.%x\n",
+ pdev->name, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn));
+ g_string_append_printf(buf, "\tcommands : %" PRId64 "\n",
+ dev->stats.commands);
+ g_string_append_printf(buf, "\tregs_reads : %" PRId64 "\n",
+ dev->stats.regs_reads);
+ g_string_append_printf(buf, "\tregs_writes : %" PRId64 "\n",
+ dev->stats.regs_writes);
+ g_string_append_printf(buf, "\tuar_writes : %" PRId64 "\n",
+ dev->stats.uar_writes);
+ g_string_append_printf(buf, "\tinterrupts : %" PRId64 "\n",
+ dev->stats.interrupts);
+ rdma_format_device_counters(&dev->rdma_dev_res, buf);
}
static void free_dev_ring(PCIDevice *pci_dev, PvrdmaRing *ring,
@@ -699,7 +700,7 @@ static void pvrdma_class_init(ObjectClass *klass, void *data)
device_class_set_props(dc, pvrdma_dev_properties);
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
- ir->print_statistics = pvrdma_print_statistics;
+ ir->format_statistics = pvrdma_format_statistics;
}
static const TypeInfo pvrdma_info = {
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 8454ed1773..84f935b549 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -204,11 +204,6 @@ static int esp_select(ESPState *s)
s->ti_size = 0;
fifo8_reset(&s->fifo);
- if (s->current_req) {
- /* Started a new command before the old one finished. Cancel it. */
- scsi_req_cancel(s->current_req);
- }
-
s->current_dev = scsi_device_find(&s->bus, 0, target, 0);
if (!s->current_dev) {
/* No such drive */
@@ -235,6 +230,11 @@ static uint32_t get_cmd(ESPState *s, uint32_t maxlen)
uint32_t dmalen, n;
int target;
+ if (s->current_req) {
+ /* Started a new command before the old one finished. Cancel it. */
+ scsi_req_cancel(s->current_req);
+ }
+
target = s->wregs[ESP_WBUSID] & BUSID_DID;
if (s->dma) {
dmalen = MIN(esp_get_tc(s), maxlen);
diff --git a/hw/sd/meson.build b/hw/sd/meson.build
index f1ce357a3b..807ca07b7c 100644
--- a/hw/sd/meson.build
+++ b/hw/sd/meson.build
@@ -9,4 +9,5 @@ softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_mmci.c'))
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_sdhost.c'))
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_sdhci.c'))
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sdhost.c'))
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_sdhci.c'))
softmmu_ss.add(when: 'CONFIG_CADENCE_SDHCI', if_true: files('cadence_sdhci.c'))
diff --git a/hw/sd/npcm7xx_sdhci.c b/hw/sd/npcm7xx_sdhci.c
new file mode 100644
index 0000000000..ef503365df
--- /dev/null
+++ b/hw/sd/npcm7xx_sdhci.c
@@ -0,0 +1,182 @@
+/*
+ * NPCM7xx SD-3.0 / eMMC-4.51 Host Controller
+ *
+ * Copyright (c) 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/sd/npcm7xx_sdhci.h"
+#include "migration/vmstate.h"
+#include "sdhci-internal.h"
+#include "qemu/log.h"
+
+static uint64_t npcm7xx_sdhci_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ NPCM7xxSDHCIState *s = opaque;
+ uint64_t val = 0;
+
+ switch (addr) {
+ case NPCM7XX_PRSTVALS_0:
+ case NPCM7XX_PRSTVALS_1:
+ case NPCM7XX_PRSTVALS_2:
+ case NPCM7XX_PRSTVALS_3:
+ case NPCM7XX_PRSTVALS_4:
+ case NPCM7XX_PRSTVALS_5:
+ val = s->regs.prstvals[(addr - NPCM7XX_PRSTVALS_0) / 2];
+ break;
+ case NPCM7XX_BOOTTOCTRL:
+ val = s->regs.boottoctrl;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "SDHCI read of nonexistent reg: 0x%02"
+ HWADDR_PRIx, addr);
+ break;
+ }
+
+ return val;
+}
+
+static void npcm7xx_sdhci_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned int size)
+{
+ NPCM7xxSDHCIState *s = opaque;
+
+ switch (addr) {
+ case NPCM7XX_BOOTTOCTRL:
+ s->regs.boottoctrl = val;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "SDHCI write of nonexistent reg: 0x%02"
+ HWADDR_PRIx, addr);
+ break;
+ }
+}
+
+static bool npcm7xx_sdhci_check_mem_op(void *opaque, hwaddr addr,
+ unsigned size, bool is_write,
+ MemTxAttrs attrs)
+{
+ switch (addr) {
+ case NPCM7XX_PRSTVALS_0:
+ case NPCM7XX_PRSTVALS_1:
+ case NPCM7XX_PRSTVALS_2:
+ case NPCM7XX_PRSTVALS_3:
+ case NPCM7XX_PRSTVALS_4:
+ case NPCM7XX_PRSTVALS_5:
+ /* RO Word */
+ return !is_write && size == 2;
+ case NPCM7XX_BOOTTOCTRL:
+ /* R/W Dword */
+ return size == 4;
+ default:
+ return false;
+ }
+}
+
+static const MemoryRegionOps npcm7xx_sdhci_ops = {
+ .read = npcm7xx_sdhci_read,
+ .write = npcm7xx_sdhci_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 4,
+ .unaligned = false,
+ .accepts = npcm7xx_sdhci_check_mem_op,
+ },
+};
+
+static void npcm7xx_sdhci_realize(DeviceState *dev, Error **errp)
+{
+ NPCM7xxSDHCIState *s = NPCM7XX_SDHCI(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ SysBusDevice *sbd_sdhci = SYS_BUS_DEVICE(&s->sdhci);
+
+ memory_region_init(&s->container, OBJECT(s),
+ "npcm7xx.sdhci-container", 0x1000);
+ sysbus_init_mmio(sbd, &s->container);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_sdhci_ops, s,
+ TYPE_NPCM7XX_SDHCI, NPCM7XX_SDHCI_REGSIZE);
+ memory_region_add_subregion_overlap(&s->container, NPCM7XX_PRSTVALS,
+ &s->iomem, 1);
+
+ sysbus_realize(sbd_sdhci, errp);
+ memory_region_add_subregion(&s->container, 0,
+ sysbus_mmio_get_region(sbd_sdhci, 0));
+
+ /* propagate irq and "sd-bus" from generic-sdhci */
+ sysbus_pass_irq(sbd, sbd_sdhci);
+ s->bus = qdev_get_child_bus(DEVICE(sbd_sdhci), "sd-bus");
+
+ /* Set the read only preset values. */
+ memset(s->regs.prstvals, 0, sizeof(s->regs.prstvals));
+ s->regs.prstvals[0] = NPCM7XX_PRSTVALS_0_RESET;
+ s->regs.prstvals[1] = NPCM7XX_PRSTVALS_1_RESET;
+ s->regs.prstvals[3] = NPCM7XX_PRSTVALS_3_RESET;
+}
+
+static void npcm7xx_sdhci_reset(DeviceState *dev)
+{
+ NPCM7xxSDHCIState *s = NPCM7XX_SDHCI(dev);
+ device_cold_reset(DEVICE(&s->sdhci));
+ s->regs.boottoctrl = 0;
+
+ s->sdhci.prnsts = NPCM7XX_PRSNTS_RESET;
+ s->sdhci.blkgap = NPCM7XX_BLKGAP_RESET;
+ s->sdhci.capareg = NPCM7XX_CAPAB_RESET;
+ s->sdhci.maxcurr = NPCM7XX_MAXCURR_RESET;
+ s->sdhci.version = NPCM7XX_HCVER_RESET;
+}
+
+static const VMStateDescription vmstate_npcm7xx_sdhci = {
+ .name = TYPE_NPCM7XX_SDHCI,
+ .version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(regs.boottoctrl, NPCM7xxSDHCIState),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static void npcm7xx_sdhci_class_init(ObjectClass *classp, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(classp);
+
+ dc->desc = "NPCM7xx SD/eMMC Host Controller";
+ dc->realize = npcm7xx_sdhci_realize;
+ dc->reset = npcm7xx_sdhci_reset;
+ dc->vmsd = &vmstate_npcm7xx_sdhci;
+}
+
+static void npcm7xx_sdhci_instance_init(Object *obj)
+{
+ NPCM7xxSDHCIState *s = NPCM7XX_SDHCI(obj);
+
+ object_initialize_child(OBJECT(s), "generic-sdhci", &s->sdhci,
+ TYPE_SYSBUS_SDHCI);
+}
+
+static TypeInfo npcm7xx_sdhci_info = {
+ .name = TYPE_NPCM7XX_SDHCI,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(NPCM7xxSDHCIState),
+ .instance_init = npcm7xx_sdhci_instance_init,
+ .class_init = npcm7xx_sdhci_class_init,
+};
+
+static void npcm7xx_sdhci_register_types(void)
+{
+ type_register_static(&npcm7xx_sdhci_info);
+}
+
+type_init(npcm7xx_sdhci_register_types)
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index 5d441a7065..92d6ed5626 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -2,6 +2,8 @@
#include "hw/qdev-properties.h"
#include "hw/usb.h"
#include "qapi/error.h"
+#include "qapi/qapi-commands-machine.h"
+#include "qapi/type-helpers.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
#include "sysemu/sysemu.h"
@@ -631,15 +633,16 @@ static char *usb_get_fw_dev_path(DeviceState *qdev)
return fw_path;
}
-void hmp_info_usb(Monitor *mon, const QDict *qdict)
+HumanReadableText *qmp_x_query_usb(Error **errp)
{
+ g_autoptr(GString) buf = g_string_new("");
USBBus *bus;
USBDevice *dev;
USBPort *port;
if (QTAILQ_EMPTY(&busses)) {
- monitor_printf(mon, "USB support not enabled\n");
- return;
+ error_setg(errp, "USB support not enabled");
+ return NULL;
}
QTAILQ_FOREACH(bus, &busses, next) {
@@ -647,14 +650,17 @@ void hmp_info_usb(Monitor *mon, const QDict *qdict)
dev = port->dev;
if (!dev)
continue;
- monitor_printf(mon, " Device %d.%d, Port %s, Speed %s Mb/s, "
- "Product %s%s%s\n",
- bus->busnr, dev->addr, port->path,
- usb_speed(dev->speed), dev->product_desc,
- dev->qdev.id ? ", ID: " : "",
- dev->qdev.id ?: "");
+ g_string_append_printf(buf,
+ " Device %d.%d, Port %s, Speed %s Mb/s, "
+ "Product %s%s%s\n",
+ bus->busnr, dev->addr, port->path,
+ usb_speed(dev->speed), dev->product_desc,
+ dev->qdev.id ? ", ID: " : "",
+ dev->qdev.id ?: "");
}
}
+
+ return human_readable_text_from_str(buf);
}
/* handle legacy -usbdevice cmd line option */
diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
index d0998f8489..e49cacd0e2 100644
--- a/hw/watchdog/sbsa_gwdt.c
+++ b/hw/watchdog/sbsa_gwdt.c
@@ -273,8 +273,9 @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, void *data)
dc->realize = wdt_sbsa_gwdt_realize;
dc->reset = wdt_sbsa_gwdt_reset;
dc->hotpluggable = false;
- set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
dc->vmsd = &vmstate_sbsa_gwdt;
+ dc->desc = "SBSA-compliant generic watchdog device";
}
static const TypeInfo wdt_sbsa_gwdt_info = {
diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
index 0e98ffb73f..1437e6c5b6 100644
--- a/hw/watchdog/watchdog.c
+++ b/hw/watchdog/watchdog.c
@@ -76,20 +76,6 @@ int select_watchdog(const char *p)
return 1;
}
-int select_watchdog_action(const char *p)
-{
- int action;
- char *qapi_value;
-
- qapi_value = g_ascii_strdown(p, -1);
- action = qapi_enum_parse(&WatchdogAction_lookup, qapi_value, -1, NULL);
- g_free(qapi_value);
- if (action < 0)
- return -1;
- qmp_watchdog_set_action(action, &error_abort);
- return 0;
-}
-
WatchdogAction get_watchdog_action(void)
{
return watchdog_action;
diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
index 146ffcd713..6aa6f90b66 100644
--- a/hw/watchdog/wdt_aspeed.c
+++ b/hw/watchdog/wdt_aspeed.c
@@ -293,9 +293,10 @@ static void aspeed_wdt_class_init(ObjectClass *klass, void *data)
dc->desc = "ASPEED Watchdog Controller";
dc->realize = aspeed_wdt_realize;
dc->reset = aspeed_wdt_reset;
- set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
dc->vmsd = &vmstate_aspeed_wdt;
device_class_set_props(dc, aspeed_wdt_properties);
+ dc->desc = "Aspeed watchdog device";
}
static const TypeInfo aspeed_wdt_info = {
diff --git a/hw/watchdog/wdt_diag288.c b/hw/watchdog/wdt_diag288.c
index e135a4de8b..9e8882a11c 100644
--- a/hw/watchdog/wdt_diag288.c
+++ b/hw/watchdog/wdt_diag288.c
@@ -122,9 +122,10 @@ static void wdt_diag288_class_init(ObjectClass *klass, void *data)
dc->unrealize = wdt_diag288_unrealize;
dc->reset = wdt_diag288_reset;
dc->hotpluggable = false;
- set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
dc->vmsd = &vmstate_diag288;
diag288->handle_timer = wdt_diag288_handle_timer;
+ dc->desc = "diag288 device for s390x platform";
}
static const TypeInfo wdt_diag288_info = {
diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c
index 4c52e3bb9e..f99a1c9d29 100644
--- a/hw/watchdog/wdt_i6300esb.c
+++ b/hw/watchdog/wdt_i6300esb.c
@@ -476,7 +476,8 @@ static void i6300esb_class_init(ObjectClass *klass, void *data)
k->class_id = PCI_CLASS_SYSTEM_OTHER;
dc->reset = i6300esb_reset;
dc->vmsd = &vmstate_i6300esb;
- set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
+ dc->desc = "Intel 6300ESB";
}
static const TypeInfo i6300esb_info = {
diff --git a/hw/watchdog/wdt_ib700.c b/hw/watchdog/wdt_ib700.c
index 177aaa503f..91d1bdc0da 100644
--- a/hw/watchdog/wdt_ib700.c
+++ b/hw/watchdog/wdt_ib700.c
@@ -140,7 +140,8 @@ static void wdt_ib700_class_init(ObjectClass *klass, void *data)
dc->realize = wdt_ib700_realize;
dc->reset = wdt_ib700_reset;
dc->vmsd = &vmstate_ib700;
- set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
+ dc->desc = "iBASE 700";
}
static const TypeInfo wdt_ib700_info = {
diff --git a/hw/watchdog/wdt_imx2.c b/hw/watchdog/wdt_imx2.c
index a5fb76308f..c3128370b5 100644
--- a/hw/watchdog/wdt_imx2.c
+++ b/hw/watchdog/wdt_imx2.c
@@ -280,8 +280,8 @@ static void imx2_wdt_class_init(ObjectClass *klass, void *data)
dc->realize = imx2_wdt_realize;
dc->reset = imx2_wdt_reset;
dc->vmsd = &vmstate_imx2_wdt;
- dc->desc = "i.MX watchdog timer";
- set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ dc->desc = "i.MX2 watchdog timer";
+ set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
}
static const TypeInfo imx2_wdt_info = {
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 32cfb634c6..3c8e24292b 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -429,10 +429,10 @@ static inline bool tlb_hit(target_ulong tlb_addr, target_ulong addr)
#ifdef CONFIG_TCG
/* accel/tcg/cpu-exec.c */
-void dump_drift_info(void);
+void dump_drift_info(GString *buf);
/* accel/tcg/translate-all.c */
-void dump_exec_info(void);
-void dump_opcount_info(void);
+void dump_exec_info(GString *buf);
+void dump_opcount_info(GString *buf);
#endif /* CONFIG_TCG */
#endif /* !CONFIG_USER_ONLY */
diff --git a/include/exec/ramlist.h b/include/exec/ramlist.h
index ece6497ee2..2ad2a81acc 100644
--- a/include/exec/ramlist.h
+++ b/include/exec/ramlist.h
@@ -80,6 +80,6 @@ void ram_block_notify_add(void *host, size_t size, size_t max_size);
void ram_block_notify_remove(void *host, size_t size, size_t max_size);
void ram_block_notify_resize(void *host, size_t old_size, size_t new_size);
-void ram_block_dump(Monitor *mon);
+GString *ram_block_format(void);
#endif /* RAMLIST_H */
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 61ecc57ab9..ce593235d9 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -35,6 +35,7 @@
#include "hw/usb/hcd-ehci.h"
#include "hw/usb/hcd-ohci.h"
#include "target/arm/cpu.h"
+#include "hw/sd/npcm7xx_sdhci.h"
#define NPCM7XX_MAX_NUM_CPUS (2)
@@ -103,6 +104,7 @@ typedef struct NPCM7xxState {
OHCISysBusState ohci;
NPCM7xxFIUState fiu[2];
NPCM7xxEMCState emc[2];
+ NPCM7xxSDHCIState mmc;
} NPCM7xxState;
#define TYPE_NPCM7XX "npcm7xx"
diff --git a/include/hw/i386/microvm.h b/include/hw/i386/microvm.h
index f25f837441..4d9c732d4b 100644
--- a/include/hw/i386/microvm.h
+++ b/include/hw/i386/microvm.h
@@ -104,6 +104,10 @@ struct MicrovmMachineState {
Notifier machine_done;
Notifier powerdown_req;
struct GPEXConfig gpex;
+
+ /* device tree */
+ void *fdt;
+ uint32_t ioapic_phandle[2];
};
#define TYPE_MICROVM_MACHINE MACHINE_TYPE_NAME("microvm")
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index b72e5bf9d1..9ab39e428f 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -117,9 +117,6 @@ struct PCMachineClass {
/* generate legacy CPU hotplug AML */
bool legacy_cpu_hotplug;
- /* use DMA capable linuxboot option rom */
- bool linuxboot_dma_enabled;
-
/* use PVH to load kernels that support this feature */
bool pvh_enabled;
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index 23267a3674..bb1cfb8896 100644
--- a/include/hw/i386/x86.h
+++ b/include/hw/i386/x86.h
@@ -38,6 +38,8 @@ struct X86MachineClass {
bool save_tsc_khz;
/* Enables contiguous-apic-ID mode */
bool compat_apic_id_mode;
+ /* use DMA capable linuxboot option rom */
+ bool fwcfg_dma_enabled;
};
struct X86MachineState {
@@ -120,8 +122,7 @@ void x86_bios_rom_init(MachineState *ms, const char *default_firmware,
void x86_load_linux(X86MachineState *x86ms,
FWCfgState *fw_cfg,
int acpi_data_size,
- bool pvh_enabled,
- bool linuxboot_dma_enabled);
+ bool pvh_enabled);
bool x86_machine_is_smm_enabled(const X86MachineState *x86ms);
bool x86_machine_is_acpi_enabled(const X86MachineState *x86ms);
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 1bad07002d..72622bd337 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -26,6 +26,7 @@ typedef enum DeviceCategory {
DEVICE_CATEGORY_SOUND,
DEVICE_CATEGORY_MISC,
DEVICE_CATEGORY_CPU,
+ DEVICE_CATEGORY_WATCHDOG,
DEVICE_CATEGORY_MAX
} DeviceCategory;
diff --git a/include/hw/rdma/rdma.h b/include/hw/rdma/rdma.h
index e77e43a170..80b2e531c4 100644
--- a/include/hw/rdma/rdma.h
+++ b/include/hw/rdma/rdma.h
@@ -31,7 +31,7 @@ typedef struct RdmaProvider RdmaProvider;
struct RdmaProviderClass {
InterfaceClass parent;
- void (*print_statistics)(Monitor *mon, RdmaProvider *obj);
+ void (*format_statistics)(RdmaProvider *obj, GString *buf);
};
#endif
diff --git a/include/hw/sd/npcm7xx_sdhci.h b/include/hw/sd/npcm7xx_sdhci.h
new file mode 100644
index 0000000000..d728f0a40d
--- /dev/null
+++ b/include/hw/sd/npcm7xx_sdhci.h
@@ -0,0 +1,65 @@
+/*
+ * NPCM7xx SD-3.0 / eMMC-4.51 Host Controller
+ *
+ * Copyright (c) 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef NPCM7XX_SDHCI_H
+#define NPCM7XX_SDHCI_H
+
+#include "hw/sd/sdhci.h"
+#include "qom/object.h"
+
+#define TYPE_NPCM7XX_SDHCI "npcm7xx.sdhci"
+#define NPCM7XX_PRSTVALS_SIZE 6
+#define NPCM7XX_PRSTVALS 0x60
+#define NPCM7XX_PRSTVALS_0 0x0
+#define NPCM7XX_PRSTVALS_1 0x2
+#define NPCM7XX_PRSTVALS_2 0x4
+#define NPCM7XX_PRSTVALS_3 0x6
+#define NPCM7XX_PRSTVALS_4 0x8
+#define NPCM7XX_PRSTVALS_5 0xA
+#define NPCM7XX_BOOTTOCTRL 0x10
+#define NPCM7XX_SDHCI_REGSIZE 0x20
+
+#define NPCM7XX_PRSNTS_RESET 0x04A00000
+#define NPCM7XX_BLKGAP_RESET 0x80
+#define NPCM7XX_CAPAB_RESET 0x0100200161EE0399
+#define NPCM7XX_MAXCURR_RESET 0x0000000000000005
+#define NPCM7XX_HCVER_RESET 0x1002
+
+#define NPCM7XX_PRSTVALS_0_RESET 0x0040
+#define NPCM7XX_PRSTVALS_1_RESET 0x0001
+#define NPCM7XX_PRSTVALS_3_RESET 0x0001
+
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxSDHCIState, NPCM7XX_SDHCI)
+
+typedef struct NPCM7xxRegs {
+ /* Preset Values Register Field, read-only */
+ uint16_t prstvals[NPCM7XX_PRSTVALS_SIZE];
+ /* Boot Timeout Control Register, read-write */
+ uint32_t boottoctrl;
+} NPCM7xxRegisters;
+
+typedef struct NPCM7xxSDHCIState {
+ SysBusDevice parent;
+
+ MemoryRegion container;
+ MemoryRegion iomem;
+ BusState *bus;
+ NPCM7xxRegisters regs;
+
+ SDHCIState sdhci;
+} NPCM7xxSDHCIState;
+
+#endif /* NPCM7XX_SDHCI_H */
diff --git a/include/hw/usb/msd.h b/include/hw/usb/msd.h
index 7538c54569..54e9f38bda 100644
--- a/include/hw/usb/msd.h
+++ b/include/hw/usb/msd.h
@@ -17,7 +17,7 @@ enum USBMSDMode {
USB_MSDM_CSW /* Command Status. */
};
-struct usb_msd_csw {
+struct QEMU_PACKED usb_msd_csw {
uint32_t sig;
uint32_t tag;
uint32_t residue;
diff --git a/include/monitor/hmp-target.h b/include/monitor/hmp-target.h
index 96956d0fc4..ffdc15a34b 100644
--- a/include/monitor/hmp-target.h
+++ b/include/monitor/hmp-target.h
@@ -48,7 +48,6 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict);
void hmp_info_tlb(Monitor *mon, const QDict *qdict);
void hmp_mce(Monitor *mon, const QDict *qdict);
void hmp_info_local_apic(Monitor *mon, const QDict *qdict);
-void hmp_info_io_apic(Monitor *mon, const QDict *qdict);
void hmp_info_sev(Monitor *mon, const QDict *qdict);
void hmp_info_sgx(Monitor *mon, const QDict *qdict);
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
index 6bc27639e0..96d014826a 100644
--- a/include/monitor/hmp.h
+++ b/include/monitor/hmp.h
@@ -15,8 +15,9 @@
#define HMP_H
#include "qemu/readline.h"
+#include "qapi/qapi-types-common.h"
-void hmp_handle_error(Monitor *mon, Error *err);
+bool hmp_handle_error(Monitor *mon, Error *err);
void hmp_info_name(Monitor *mon, const QDict *qdict);
void hmp_info_version(Monitor *mon, const QDict *qdict);
@@ -130,5 +131,7 @@ void hmp_replay_delete_break(Monitor *mon, const QDict *qdict);
void hmp_replay_seek(Monitor *mon, const QDict *qdict);
void hmp_info_dirty_rate(Monitor *mon, const QDict *qdict);
void hmp_calc_dirty_rate(Monitor *mon, const QDict *qdict);
+void hmp_human_readable_text_helper(Monitor *mon,
+ HumanReadableText *(*qmp_handler)(Error **));
#endif
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 1a8a369b50..12d395d62d 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -53,5 +53,7 @@ int64_t monitor_fdset_dup_fd_find(int dup_fd);
void monitor_register_hmp(const char *name, bool info,
void (*cmd)(Monitor *mon, const QDict *qdict));
+void monitor_register_hmp_info_hrt(const char *name,
+ HumanReadableText *(*handler)(Error **errp));
#endif /* MONITOR_H */
diff --git a/include/qapi/type-helpers.h b/include/qapi/type-helpers.h
new file mode 100644
index 0000000000..be1f181526
--- /dev/null
+++ b/include/qapi/type-helpers.h
@@ -0,0 +1,14 @@
+/*
+ * QAPI common helper functions
+ *
+ * This file provides helper functions related to types defined
+ * in the QAPI schema.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qapi/qapi-types-common.h"
+
+HumanReadableText *human_readable_text_from_str(GString *str);
diff --git a/include/qemu/iova-tree.h b/include/qemu/iova-tree.h
index b66cf93c4b..8249edd764 100644
--- a/include/qemu/iova-tree.h
+++ b/include/qemu/iova-tree.h
@@ -59,7 +59,7 @@ IOVATree *iova_tree_new(void);
*
* Return: 0 if succeeded, or <0 if error.
*/
-int iova_tree_insert(IOVATree *tree, DMAMap *map);
+int iova_tree_insert(IOVATree *tree, const DMAMap *map);
/**
* iova_tree_remove:
@@ -74,7 +74,7 @@ int iova_tree_insert(IOVATree *tree, DMAMap *map);
*
* Return: 0 if succeeded, or <0 if error.
*/
-int iova_tree_remove(IOVATree *tree, DMAMap *map);
+int iova_tree_remove(IOVATree *tree, const DMAMap *map);
/**
* iova_tree_find:
@@ -92,7 +92,7 @@ int iova_tree_remove(IOVATree *tree, DMAMap *map);
* user is responsible to make sure the pointer is valid (say, no
* concurrent deletion in progress).
*/
-DMAMap *iova_tree_find(IOVATree *tree, DMAMap *map);
+const DMAMap *iova_tree_find(const IOVATree *tree, const DMAMap *map);
/**
* iova_tree_find_address:
@@ -105,7 +105,7 @@ DMAMap *iova_tree_find(IOVATree *tree, DMAMap *map);
*
* Return: same as iova_tree_find().
*/
-DMAMap *iova_tree_find_address(IOVATree *tree, hwaddr iova);
+const DMAMap *iova_tree_find_address(const IOVATree *tree, hwaddr iova);
/**
* iova_tree_foreach:
diff --git a/include/sysemu/watchdog.h b/include/sysemu/watchdog.h
index a08d16380d..d2d4901dbb 100644
--- a/include/sysemu/watchdog.h
+++ b/include/sysemu/watchdog.h
@@ -37,7 +37,6 @@ typedef struct WatchdogTimerModel WatchdogTimerModel;
/* in hw/watchdog.c */
int select_watchdog(const char *p);
-int select_watchdog_action(const char *action);
WatchdogAction get_watchdog_action(void);
void watchdog_add_model(WatchdogTimerModel *model);
void watchdog_perform_action(void);
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 7069a401f1..42f5b500ed 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -937,8 +937,8 @@ int tcg_check_temp_count(void);
#endif
int64_t tcg_cpu_exec_time(void);
-void tcg_dump_info(void);
-void tcg_dump_op_count(void);
+void tcg_dump_info(GString *buf);
+void tcg_dump_op_count(GString *buf);
#define TCG_CT_CONST 1 /* any constant of register size */
diff --git a/include/ui/console.h b/include/ui/console.h
index 244664d727..b6bedc5f41 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -171,6 +171,7 @@ typedef struct QemuDmaBuf {
void *sync;
int fence_fd;
bool allow_fences;
+ bool draw_submitted;
} QemuDmaBuf;
typedef struct DisplayState DisplayState;
diff --git a/meson b/meson
-Subproject b25d94e7c77fda05a7fdfe8afe562cf9760d69d
+Subproject 12f9f04ba0decfda425dbbf9a501084c153a2d1
diff --git a/meson.build b/meson.build
index 26c58123e9..c4aec7355a 100644
--- a/meson.build
+++ b/meson.build
@@ -909,7 +909,7 @@ if liblzfse.found() and not cc.links('''
endif
oss = not_found
-if not get_option('oss').auto() or have_system
+if have_system and not get_option('oss').disabled()
if not cc.has_header('sys/soundcard.h')
# not found
elif targetos == 'netbsd'
@@ -922,8 +922,6 @@ if not get_option('oss').auto() or have_system
if not oss.found()
if get_option('oss').enabled()
error('OSS not found')
- else
- warning('OSS not found, disabling')
endif
endif
endif
@@ -936,8 +934,6 @@ if not get_option('dsound').auto() or (targetos == 'windows' and have_system)
if not dsound.found()
if get_option('dsound').enabled()
error('DirectSound not found')
- else
- warning('DirectSound not found, disabling')
endif
endif
endif
@@ -946,22 +942,6 @@ coreaudio = not_found
if not get_option('coreaudio').auto() or (targetos == 'darwin' and have_system)
coreaudio = dependency('appleframeworks', modules: 'CoreAudio',
required: get_option('coreaudio'))
- if coreaudio.found() and not cc.links('''
- #include <CoreAudio/CoreAudio.h>
- int main(void)
- {
- return (int)AudioGetCurrentHostTime();
- }''')
- coreaudio = not_found
- endif
-
- if not coreaudio.found()
- if get_option('coreaudio').enabled()
- error('CoreAudio not found')
- else
- warning('CoreAudio not found, disabling')
- endif
- endif
endif
opengl = not_found
@@ -1676,6 +1656,13 @@ config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + '''
return mlockall(MCL_FUTURE);
}'''))
+have_l2tpv3 = false
+if not get_option('l2tpv3').disabled() and have_system
+ have_l2tpv3 = (cc.has_header_symbol('sys/socket.h', 'struct mmsghdr')
+ and cc.has_header('linux/ip.h'))
+endif
+config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
+
have_netmap = false
if not get_option('netmap').disabled() and have_system
have_netmap = cc.compiles('''
@@ -3395,6 +3382,7 @@ summary_info += {'JACK support': jack}
summary_info += {'brlapi support': brlapi}
summary_info += {'vde support': vde}
summary_info += {'netmap support': have_netmap}
+summary_info += {'l2tpv3 support': have_l2tpv3}
summary_info += {'Linux AIO support': libaio}
summary_info += {'Linux io_uring support': linux_io_uring}
summary_info += {'ATTR/XATTR support': libattr}
diff --git a/meson_options.txt b/meson_options.txt
index 4ab4570125..e740dce2a5 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -141,6 +141,8 @@ option('u2f', type : 'feature', value : 'auto',
description: 'U2F emulation support')
option('usb_redir', type : 'feature', value : 'auto',
description: 'libusbredir support')
+option('l2tpv3', type : 'feature', value : 'auto',
+ description: 'l2tpv3 network backend support')
option('netmap', type : 'feature', value : 'auto',
description: 'netmap network backend support')
option('vde', type : 'feature', value : 'auto',
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index bcaa41350e..9c91bf93e9 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -52,9 +52,7 @@
#include "ui/console.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
-#include "exec/ramlist.h"
#include "hw/intc/intc.h"
-#include "hw/rdma/rdma.h"
#include "migration/snapshot.h"
#include "migration/misc.h"
@@ -62,11 +60,13 @@
#include <spice/enums.h>
#endif
-void hmp_handle_error(Monitor *mon, Error *err)
+bool hmp_handle_error(Monitor *mon, Error *err)
{
if (err) {
error_reportf_err(err, "Error: ");
+ return true;
}
+ return false;
}
/*
@@ -577,8 +577,7 @@ void hmp_info_vnc(Monitor *mon, const QDict *qdict)
info2l = qmp_query_vnc_servers(&err);
info2l_head = info2l;
- if (err) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
if (!info2l) {
@@ -693,8 +692,7 @@ void hmp_info_balloon(Monitor *mon, const QDict *qdict)
Error *err = NULL;
info = qmp_query_balloon(&err);
- if (err) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -786,44 +784,6 @@ static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev)
}
}
-static int hmp_info_irq_foreach(Object *obj, void *opaque)
-{
- InterruptStatsProvider *intc;
- InterruptStatsProviderClass *k;
- Monitor *mon = opaque;
-
- if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) {
- intc = INTERRUPT_STATS_PROVIDER(obj);
- k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj);
- uint64_t *irq_counts;
- unsigned int nb_irqs, i;
- if (k->get_statistics &&
- k->get_statistics(intc, &irq_counts, &nb_irqs)) {
- if (nb_irqs > 0) {
- monitor_printf(mon, "IRQ statistics for %s:\n",
- object_get_typename(obj));
- for (i = 0; i < nb_irqs; i++) {
- if (irq_counts[i] > 0) {
- monitor_printf(mon, "%2d: %" PRId64 "\n", i,
- irq_counts[i]);
- }
- }
- }
- } else {
- monitor_printf(mon, "IRQ statistics not available for %s.\n",
- object_get_typename(obj));
- }
- }
-
- return 0;
-}
-
-void hmp_info_irq(Monitor *mon, const QDict *qdict)
-{
- object_child_foreach_recursive(object_get_root(),
- hmp_info_irq_foreach, mon);
-}
-
static int hmp_info_pic_foreach(Object *obj, void *opaque)
{
InterruptStatsProvider *intc;
@@ -850,32 +810,6 @@ void hmp_info_pic(Monitor *mon, const QDict *qdict)
hmp_info_pic_foreach, mon);
}
-static int hmp_info_rdma_foreach(Object *obj, void *opaque)
-{
- RdmaProvider *rdma;
- RdmaProviderClass *k;
- Monitor *mon = opaque;
-
- if (object_dynamic_cast(obj, INTERFACE_RDMA_PROVIDER)) {
- rdma = RDMA_PROVIDER(obj);
- k = RDMA_PROVIDER_GET_CLASS(obj);
- if (k->print_statistics) {
- k->print_statistics(mon, rdma);
- } else {
- monitor_printf(mon, "RDMA statistics not available for %s.\n",
- object_get_typename(obj));
- }
- }
-
- return 0;
-}
-
-void hmp_info_rdma(Monitor *mon, const QDict *qdict)
-{
- object_child_foreach_recursive(object_get_root(),
- hmp_info_rdma_foreach, mon);
-}
-
void hmp_info_pci(Monitor *mon, const QDict *qdict)
{
PciInfoList *info_list, *info;
@@ -1065,8 +999,7 @@ void hmp_ringbuf_read(Monitor *mon, const QDict *qdict)
int i;
data = qmp_ringbuf_read(chardev, size, false, 0, &err);
- if (err) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -1582,8 +1515,7 @@ void hmp_migrate(Monitor *mon, const QDict *qdict)
qmp_migrate(uri, !!blk, blk, !!inc, inc,
false, false, true, resume, &err);
- if (err) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -1917,8 +1849,7 @@ void hmp_rocker(Monitor *mon, const QDict *qdict)
Error *err = NULL;
rocker = qmp_query_rocker(name, &err);
- if (err != NULL) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -1936,8 +1867,7 @@ void hmp_rocker_ports(Monitor *mon, const QDict *qdict)
Error *err = NULL;
list = qmp_query_rocker_ports(name, &err);
- if (err != NULL) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -1945,7 +1875,7 @@ void hmp_rocker_ports(Monitor *mon, const QDict *qdict)
monitor_printf(mon, " port link duplex neg?\n");
for (port = list; port; port = port->next) {
- monitor_printf(mon, "%10s %-4s %-3s %2s %-3s\n",
+ monitor_printf(mon, "%10s %-4s %-3s %2s %s\n",
port->value->name,
port->value->enabled ? port->value->link_up ?
"up" : "down" : "!ena",
@@ -1965,8 +1895,7 @@ void hmp_rocker_of_dpa_flows(Monitor *mon, const QDict *qdict)
Error *err = NULL;
list = qmp_query_rocker_of_dpa_flows(name, tbl_id != -1, tbl_id, &err);
- if (err != NULL) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -2115,8 +2044,7 @@ void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict)
Error *err = NULL;
list = qmp_query_rocker_of_dpa_groups(name, type != 9, type, &err);
- if (err != NULL) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -2209,11 +2137,6 @@ void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict)
qapi_free_RockerOfDpaGroupList(list);
}
-void hmp_info_ramblock(Monitor *mon, const QDict *qdict)
-{
- ram_block_dump(mon);
-}
-
void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
diff --git a/monitor/hmp.c b/monitor/hmp.c
index d50c3124e1..b20737e63c 100644
--- a/monitor/hmp.c
+++ b/monitor/hmp.c
@@ -26,6 +26,7 @@
#include <dirent.h>
#include "hw/qdev-core.h"
#include "monitor-internal.h"
+#include "monitor/hmp.h"
#include "qapi/error.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qnum.h"
@@ -1061,6 +1062,31 @@ fail:
return NULL;
}
+static void hmp_info_human_readable_text(Monitor *mon,
+ HumanReadableText *(*handler)(Error **))
+{
+ Error *err = NULL;
+ g_autoptr(HumanReadableText) info = handler(&err);
+
+ if (hmp_handle_error(mon, err)) {
+ return;
+ }
+
+ monitor_printf(mon, "%s", info->human_readable_text);
+}
+
+static void handle_hmp_command_exec(Monitor *mon,
+ const HMPCommand *cmd,
+ QDict *qdict)
+{
+ if (cmd->cmd_info_hrt) {
+ hmp_info_human_readable_text(mon,
+ cmd->cmd_info_hrt);
+ } else {
+ cmd->cmd(mon, qdict);
+ }
+}
+
typedef struct HandleHmpCommandCo {
Monitor *mon;
const HMPCommand *cmd;
@@ -1071,7 +1097,7 @@ typedef struct HandleHmpCommandCo {
static void handle_hmp_command_co(void *opaque)
{
HandleHmpCommandCo *data = opaque;
- data->cmd->cmd(data->mon, data->qdict);
+ handle_hmp_command_exec(data->mon, data->cmd, data->qdict);
monitor_set_cur(qemu_coroutine_self(), NULL);
data->done = true;
}
@@ -1089,7 +1115,7 @@ void handle_hmp_command(MonitorHMP *mon, const char *cmdline)
return;
}
- if (!cmd->cmd) {
+ if (!cmd->cmd && !cmd->cmd_info_hrt) {
/* FIXME: is it useful to try autoload modules here ??? */
monitor_printf(&mon->common, "Command \"%.*s\" is not available.\n",
(int)(cmdline - cmd_start), cmd_start);
@@ -1109,7 +1135,7 @@ void handle_hmp_command(MonitorHMP *mon, const char *cmdline)
if (!cmd->coroutine) {
/* old_mon is non-NULL when called from qmp_human_monitor_command() */
Monitor *old_mon = monitor_set_cur(qemu_coroutine_self(), &mon->common);
- cmd->cmd(&mon->common, qdict);
+ handle_hmp_command_exec(&mon->common, cmd, qdict);
monitor_set_cur(qemu_coroutine_self(), old_mon);
} else {
HandleHmpCommandCo data = {
diff --git a/monitor/misc.c b/monitor/misc.c
index c2d227a07c..a3a6e47844 100644
--- a/monitor/misc.c
+++ b/monitor/misc.c
@@ -70,7 +70,9 @@
#include "qapi/qapi-commands-migration.h"
#include "qapi/qapi-commands-misc.h"
#include "qapi/qapi-commands-qom.h"
+#include "qapi/qapi-commands-run-state.h"
#include "qapi/qapi-commands-trace.h"
+#include "qapi/qapi-commands-machine.h"
#include "qapi/qapi-init-commands.h"
#include "qapi/error.h"
#include "qapi/qmp-event.h"
@@ -471,10 +473,18 @@ static void hmp_gdbserver(Monitor *mon, const QDict *qdict)
static void hmp_watchdog_action(Monitor *mon, const QDict *qdict)
{
- const char *action = qdict_get_str(qdict, "action");
- if (select_watchdog_action(action) == -1) {
- monitor_printf(mon, "Unknown watchdog action '%s'\n", action);
+ Error *err = NULL;
+ WatchdogAction action;
+ char *qapi_value;
+
+ qapi_value = g_ascii_strdown(qdict_get_str(qdict, "action"), -1);
+ action = qapi_enum_parse(&WatchdogAction_lookup, qapi_value, -1, &err);
+ g_free(qapi_value);
+ if (err) {
+ hmp_handle_error(mon, err);
+ return;
}
+ qmp_watchdog_set_action(action, &error_abort);
}
static void monitor_printc(Monitor *mon, int c)
@@ -930,33 +940,6 @@ static void hmp_info_mtree(Monitor *mon, const QDict *qdict)
mtree_info(flatview, dispatch_tree, owner, disabled);
}
-#ifdef CONFIG_PROFILER
-
-int64_t dev_time;
-
-static void hmp_info_profile(Monitor *mon, const QDict *qdict)
-{
- static int64_t last_cpu_exec_time;
- int64_t cpu_exec_time;
- int64_t delta;
-
- cpu_exec_time = tcg_cpu_exec_time();
- delta = cpu_exec_time - last_cpu_exec_time;
-
- monitor_printf(mon, "async time %" PRId64 " (%0.3f)\n",
- dev_time, dev_time / (double)NANOSECONDS_PER_SECOND);
- monitor_printf(mon, "qemu time %" PRId64 " (%0.3f)\n",
- delta, delta / (double)NANOSECONDS_PER_SECOND);
- last_cpu_exec_time = cpu_exec_time;
- dev_time = 0;
-}
-#else
-static void hmp_info_profile(Monitor *mon, const QDict *qdict)
-{
- monitor_printf(mon, "Internal profiler not compiled\n");
-}
-#endif
-
/* Capture support */
static QLIST_HEAD (capture_list_head, CaptureState) capture_head;
@@ -1964,7 +1947,7 @@ void monitor_register_hmp(const char *name, bool info,
while (table->name != NULL) {
if (strcmp(table->name, name) == 0) {
- g_assert(table->cmd == NULL);
+ g_assert(table->cmd == NULL && table->cmd_info_hrt == NULL);
table->cmd = cmd;
return;
}
@@ -1973,6 +1956,22 @@ void monitor_register_hmp(const char *name, bool info,
g_assert_not_reached();
}
+void monitor_register_hmp_info_hrt(const char *name,
+ HumanReadableText *(*handler)(Error **errp))
+{
+ HMPCommand *table = hmp_info_cmds;
+
+ while (table->name != NULL) {
+ if (strcmp(table->name, name) == 0) {
+ g_assert(table->cmd == NULL && table->cmd_info_hrt == NULL);
+ table->cmd_info_hrt = handler;
+ return;
+ }
+ table++;
+ }
+ g_assert_not_reached();
+}
+
void monitor_init_globals(void)
{
monitor_init_globals_core();
diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h
index 9c3a09cb01..3da3f86c6a 100644
--- a/monitor/monitor-internal.h
+++ b/monitor/monitor-internal.h
@@ -74,6 +74,13 @@ typedef struct HMPCommand {
const char *help;
const char *flags; /* p=preconfig */
void (*cmd)(Monitor *mon, const QDict *qdict);
+ /*
+ * If implementing a command that takes no arguments and simply
+ * prints formatted data, then leave @cmd NULL, and then set
+ * @cmd_info_hrt to the corresponding QMP handler that returns
+ * the formatted text.
+ */
+ HumanReadableText *(*cmd_info_hrt)(Error **errp);
bool coroutine;
/*
* @sub_table is a list of 2nd level of commands. If it does not exist,
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
index 5c0d5e116b..343353e27a 100644
--- a/monitor/qmp-cmds.c
+++ b/monitor/qmp-cmds.c
@@ -36,9 +36,13 @@
#include "qapi/qapi-commands-machine.h"
#include "qapi/qapi-commands-misc.h"
#include "qapi/qapi-commands-ui.h"
+#include "qapi/type-helpers.h"
#include "qapi/qmp/qerror.h"
+#include "exec/ramlist.h"
#include "hw/mem/memory-device.h"
#include "hw/acpi/acpi_dev_interface.h"
+#include "hw/intc/intc.h"
+#include "hw/rdma/rdma.h"
NameInfo *qmp_query_name(Error **errp)
{
@@ -350,3 +354,115 @@ void qmp_display_reload(DisplayReloadOptions *arg, Error **errp)
abort();
}
}
+
+#ifdef CONFIG_PROFILER
+
+int64_t dev_time;
+
+HumanReadableText *qmp_x_query_profile(Error **errp)
+{
+ g_autoptr(GString) buf = g_string_new("");
+ static int64_t last_cpu_exec_time;
+ int64_t cpu_exec_time;
+ int64_t delta;
+
+ cpu_exec_time = tcg_cpu_exec_time();
+ delta = cpu_exec_time - last_cpu_exec_time;
+
+ g_string_append_printf(buf, "async time %" PRId64 " (%0.3f)\n",
+ dev_time, dev_time / (double)NANOSECONDS_PER_SECOND);
+ g_string_append_printf(buf, "qemu time %" PRId64 " (%0.3f)\n",
+ delta, delta / (double)NANOSECONDS_PER_SECOND);
+ last_cpu_exec_time = cpu_exec_time;
+ dev_time = 0;
+
+ return human_readable_text_from_str(buf);
+}
+#else
+HumanReadableText *qmp_x_query_profile(Error **errp)
+{
+ error_setg(errp, "Internal profiler not compiled");
+ return NULL;
+}
+#endif
+
+static int qmp_x_query_rdma_foreach(Object *obj, void *opaque)
+{
+ RdmaProvider *rdma;
+ RdmaProviderClass *k;
+ GString *buf = opaque;
+
+ if (object_dynamic_cast(obj, INTERFACE_RDMA_PROVIDER)) {
+ rdma = RDMA_PROVIDER(obj);
+ k = RDMA_PROVIDER_GET_CLASS(obj);
+ if (k->format_statistics) {
+ k->format_statistics(rdma, buf);
+ } else {
+ g_string_append_printf(buf,
+ "RDMA statistics not available for %s.\n",
+ object_get_typename(obj));
+ }
+ }
+
+ return 0;
+}
+
+HumanReadableText *qmp_x_query_rdma(Error **errp)
+{
+ g_autoptr(GString) buf = g_string_new("");
+
+ object_child_foreach_recursive(object_get_root(),
+ qmp_x_query_rdma_foreach, buf);
+
+ return human_readable_text_from_str(buf);
+}
+
+HumanReadableText *qmp_x_query_ramblock(Error **errp)
+{
+ g_autoptr(GString) buf = ram_block_format();
+
+ return human_readable_text_from_str(buf);
+}
+
+static int qmp_x_query_irq_foreach(Object *obj, void *opaque)
+{
+ InterruptStatsProvider *intc;
+ InterruptStatsProviderClass *k;
+ GString *buf = opaque;
+
+ if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) {
+ intc = INTERRUPT_STATS_PROVIDER(obj);
+ k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj);
+ uint64_t *irq_counts;
+ unsigned int nb_irqs, i;
+ if (k->get_statistics &&
+ k->get_statistics(intc, &irq_counts, &nb_irqs)) {
+ if (nb_irqs > 0) {
+ g_string_append_printf(buf, "IRQ statistics for %s:\n",
+ object_get_typename(obj));
+ for (i = 0; i < nb_irqs; i++) {
+ if (irq_counts[i] > 0) {
+ g_string_append_printf(buf, "%2d: %" PRId64 "\n", i,
+ irq_counts[i]);
+ }
+ }
+ }
+ } else {
+ g_string_append_printf(buf,
+ "IRQ statistics not available for %s.\n",
+ object_get_typename(obj));
+ }
+ }
+
+ return 0;
+}
+
+HumanReadableText *qmp_x_query_irq(Error **errp)
+{
+ g_autoptr(GString) buf = g_string_new("");
+
+ object_child_foreach_recursive(object_get_root(),
+ qmp_x_query_irq_foreach, buf);
+
+ return human_readable_text_from_str(buf);
+}
diff --git a/net/meson.build b/net/meson.build
index 94383e7460..847bc2ac85 100644
--- a/net/meson.build
+++ b/net/meson.build
@@ -18,7 +18,9 @@ softmmu_ss.add(files(
softmmu_ss.add(when: 'CONFIG_TCG', if_true: files('filter-replay.c'))
-softmmu_ss.add(when: 'CONFIG_L2TPV3', if_true: files('l2tpv3.c'))
+if have_l2tpv3
+ softmmu_ss.add(files('l2tpv3.c'))
+endif
softmmu_ss.add(when: slirp, if_true: files('slirp.c'))
softmmu_ss.add(when: vde, if_true: files('vde.c'))
if have_netmap
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
index a44c9bc127..b40ff3f2bd 100644
--- a/pc-bios/meson.build
+++ b/pc-bios/meson.build
@@ -63,6 +63,7 @@ blobs = files(
'petalogix-s3adsp1800.dtb',
'petalogix-ml605.dtb',
'multiboot.bin',
+ 'multiboot_dma.bin',
'linuxboot.bin',
'linuxboot_dma.bin',
'kvmvapic.bin',
diff --git a/pc-bios/multiboot_dma.bin b/pc-bios/multiboot_dma.bin
new file mode 100644
index 0000000000..c0e2c3102a
--- /dev/null
+++ b/pc-bios/multiboot_dma.bin
Binary files differ
diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile
index 30771f8d17..5d55d25acc 100644
--- a/pc-bios/optionrom/Makefile
+++ b/pc-bios/optionrom/Makefile
@@ -1,9 +1,8 @@
-CURRENT_MAKEFILE := $(realpath $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))
-SRC_DIR := $(dir $(CURRENT_MAKEFILE))
-TOPSRC_DIR := $(SRC_DIR)/../..
+include config.mak
+SRC_DIR := $(TOPSRC_DIR)/pc-bios/optionrom
VPATH = $(SRC_DIR)
-all: multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin
+all: multiboot.bin multiboot_dma.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin
# Dummy command so that make thinks it has done something
@true
@@ -42,8 +41,6 @@ override CFLAGS += $(call cc-option, $(Wa)-32)
LD_I386_EMULATION ?= elf_i386
override LDFLAGS = -m $(LD_I386_EMULATION) -T $(SRC_DIR)/flat.lds
-all: multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin
-
pvh.img: pvh.o pvh_main.o
%.o: %.S
diff --git a/pc-bios/optionrom/multiboot.S b/pc-bios/optionrom/multiboot.S
index b7efe4de34..181a4b03a3 100644
--- a/pc-bios/optionrom/multiboot.S
+++ b/pc-bios/optionrom/multiboot.S
@@ -68,7 +68,7 @@ run_multiboot:
mov %eax, %es
/* Read the bootinfo struct into RAM */
- read_fw_blob(FW_CFG_INITRD)
+ read_fw_blob_dma(FW_CFG_INITRD)
/* FS = bootinfo_struct */
read_fw FW_CFG_INITRD_ADDR
@@ -188,7 +188,7 @@ prot_mode:
movl %eax, %gs
/* Read the kernel and modules into RAM */
- read_fw_blob(FW_CFG_KERNEL)
+ read_fw_blob_dma(FW_CFG_KERNEL)
/* Jump off to the kernel */
read_fw FW_CFG_KERNEL_ENTRY
diff --git a/pc-bios/optionrom/multiboot_dma.S b/pc-bios/optionrom/multiboot_dma.S
new file mode 100644
index 0000000000..d809af3e23
--- /dev/null
+++ b/pc-bios/optionrom/multiboot_dma.S
@@ -0,0 +1,2 @@
+#define USE_FW_CFG_DMA 1
+#include "multiboot.S"
diff --git a/pc-bios/optionrom/optionrom.h b/pc-bios/optionrom/optionrom.h
index a2b612f1a7..8d74c0ddf3 100644
--- a/pc-bios/optionrom/optionrom.h
+++ b/pc-bios/optionrom/optionrom.h
@@ -37,6 +37,17 @@
#define BIOS_CFG_IOPORT_CFG 0x510
#define BIOS_CFG_IOPORT_DATA 0x511
+#define FW_CFG_DMA_CTL_ERROR 0x01
+#define FW_CFG_DMA_CTL_READ 0x02
+#define FW_CFG_DMA_CTL_SKIP 0x04
+#define FW_CFG_DMA_CTL_SELECT 0x08
+#define FW_CFG_DMA_CTL_WRITE 0x10
+
+#define FW_CFG_DMA_SIGNATURE 0x51454d5520434647ULL /* "QEMU CFG" */
+
+#define BIOS_CFG_DMA_ADDR_HIGH 0x514
+#define BIOS_CFG_DMA_ADDR_LOW 0x518
+
/* Break the translation block flow so -d cpu shows us values */
#define DEBUG_HERE \
jmp 1f; \
@@ -62,6 +73,61 @@
bswap %eax
.endm
+
+/*
+ * Read data from the fw_cfg device using DMA.
+ * Clobbers: %edx, %eax, ADDR, SIZE, memory[%esp-16] to memory[%esp]
+ */
+.macro read_fw_dma VAR, SIZE, ADDR
+ /* Address */
+ bswapl \ADDR
+ pushl \ADDR
+
+ /* We only support 32 bit target addresses */
+ xorl %eax, %eax
+ pushl %eax
+ mov $BIOS_CFG_DMA_ADDR_HIGH, %dx
+ outl %eax, (%dx)
+
+ /* Size */
+ bswapl \SIZE
+ pushl \SIZE
+
+ /* Control */
+ movl $(\VAR << 16) | (FW_CFG_DMA_CTL_READ | FW_CFG_DMA_CTL_SELECT), %eax
+ bswapl %eax
+ pushl %eax
+
+ movl %esp, %eax /* Address of the struct we generated */
+ bswapl %eax
+ mov $BIOS_CFG_DMA_ADDR_LOW, %dx
+ outl %eax, (%dx) /* Initiate DMA */
+
+1: mov (%esp), %eax /* Wait for completion */
+ bswapl %eax
+ testl $~FW_CFG_DMA_CTL_ERROR, %eax
+ jnz 1b
+ addl $16, %esp
+.endm
+
+
+/*
+ * Read a blob from the fw_cfg device using DMA
+ * Requires _ADDR, _SIZE and _DATA values for the parameter.
+ *
+ * Clobbers: %eax, %edx, %es, %ecx, %edi and adresses %esp-20 to %esp
+ */
+#ifdef USE_FW_CFG_DMA
+#define read_fw_blob_dma(var) \
+ read_fw var ## _SIZE; \
+ mov %eax, %ecx; \
+ read_fw var ## _ADDR; \
+ mov %eax, %edi ;\
+ read_fw_dma var ## _DATA, %ecx, %edi
+#else
+#define read_fw_blob_dma(var) read_fw_blob(var)
+#endif
+
#define read_fw_blob_pre(var) \
read_fw var ## _SIZE; \
mov %eax, %ecx; \
diff --git a/qapi/common.json b/qapi/common.json
index 7c976296f0..412cc4f5ae 100644
--- a/qapi/common.json
+++ b/qapi/common.json
@@ -197,3 +197,14 @@
{ 'enum': 'GrabToggleKeys',
'data': [ 'ctrl-ctrl', 'alt-alt', 'shift-shift','meta-meta', 'scrolllock',
'ctrl-scrolllock' ] }
+
+##
+# @HumanReadableText:
+#
+# @human-readable-text: Formatted output intended for humans.
+#
+# Since: 6.2
+#
+##
+{ 'struct': 'HumanReadableText',
+ 'data': { 'human-readable-text': 'str' } }
diff --git a/qapi/machine.json b/qapi/machine.json
index 5db54df298..17794ef681 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -1411,3 +1411,113 @@
'*cores': 'int',
'*threads': 'int',
'*maxcpus': 'int' } }
+
+##
+# @x-query-irq:
+#
+# Query interrupt statistics
+#
+# Returns: interrupt statistics
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-irq',
+ 'returns': 'HumanReadableText' }
+
+##
+# @x-query-jit:
+#
+# Query TCG compiler statistics
+#
+# Returns: TCG compiler statistics
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-jit',
+ 'returns': 'HumanReadableText',
+ 'if': 'CONFIG_TCG' }
+
+##
+# @x-query-numa:
+#
+# Query NUMA topology information
+#
+# Returns: topology information
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-numa',
+ 'returns': 'HumanReadableText' }
+
+##
+# @x-query-opcount:
+#
+# Query TCG opcode counters
+#
+# Returns: TCG opcode counters
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-opcount',
+ 'returns': 'HumanReadableText',
+ 'if': 'CONFIG_TCG' }
+
+##
+# @x-query-profile:
+#
+# Query TCG profiling information
+#
+# Returns: profile information
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-profile',
+ 'returns': 'HumanReadableText' }
+
+##
+# @x-query-ramblock:
+#
+# Query system ramblock information
+#
+# Returns: system ramblock information
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-ramblock',
+ 'returns': 'HumanReadableText' }
+
+##
+# @x-query-rdma:
+#
+# Query RDMA state
+#
+# Returns: RDMA state
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-rdma',
+ 'returns': 'HumanReadableText' }
+
+##
+# @x-query-roms:
+#
+# Query information on the registered ROMS
+#
+# Returns: registered ROMs
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-roms',
+ 'returns': 'HumanReadableText' }
+
+##
+# @x-query-usb:
+#
+# Query information on the USB devices
+#
+# Returns: USB device information
+#
+# Since: 6.2
+##
+{ 'command': 'x-query-usb',
+ 'returns': 'HumanReadableText' }
diff --git a/qapi/meson.build b/qapi/meson.build
index c356a385e3..c0c49c15e4 100644
--- a/qapi/meson.build
+++ b/qapi/meson.build
@@ -10,6 +10,9 @@ util_ss.add(files(
'string-input-visitor.c',
'string-output-visitor.c',
))
+if have_system
+ util_ss.add(files('qapi-type-helpers.c'))
+endif
if have_system or have_tools
util_ss.add(files(
'qmp-dispatch.c',
diff --git a/qapi/qapi-type-helpers.c b/qapi/qapi-type-helpers.c
new file mode 100644
index 0000000000..f76b34f647
--- /dev/null
+++ b/qapi/qapi-type-helpers.c
@@ -0,0 +1,23 @@
+/*
+ * QAPI common helper functions
+ *
+ * This file provides helper functions related to types defined
+ * in the QAPI schema.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qapi/type-helpers.h"
+
+HumanReadableText *human_readable_text_from_str(GString *str)
+{
+ HumanReadableText *ret = g_new0(HumanReadableText, 1);
+
+ ret->human_readable_text = g_steal_pointer(&str->str);
+
+ return ret;
+}
diff --git a/scripts/meson-buildoptions.py b/scripts/meson-buildoptions.py
index 256523c09d..96969d89ee 100755
--- a/scripts/meson-buildoptions.py
+++ b/scripts/meson-buildoptions.py
@@ -150,23 +150,7 @@ def print_parse(options):
print("}")
-def fixup_options(options):
- # Meson <= 0.60 does not include the choices in array options, fix that up
- for opt in options:
- if opt["name"] == "trace_backends":
- opt["choices"] = [
- "dtrace",
- "ftrace",
- "log",
- "nop",
- "simple",
- "syslog",
- "ust",
- ]
-
-
options = load_options(json.load(sys.stdin))
-fixup_options(options)
print("# This file is generated by meson-buildoptions.py, do not edit!")
print_help(options)
print_parse(options)
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
index c795a13020..55b8a78560 100644
--- a/scripts/meson-buildoptions.sh
+++ b/scripts/meson-buildoptions.sh
@@ -49,6 +49,7 @@ meson_options_help() {
printf "%s\n" ' iconv Font glyph conversion support'
printf "%s\n" ' jack JACK sound support'
printf "%s\n" ' kvm KVM acceleration support'
+ printf "%s\n" ' l2tpv3 l2tpv3 network backend support'
printf "%s\n" ' libdaxctl libdaxctl support'
printf "%s\n" ' libiscsi libiscsi userspace initiator'
printf "%s\n" ' libnfs libnfs block device driver'
@@ -166,6 +167,8 @@ _meson_option_parse() {
--disable-jack) printf "%s" -Djack=disabled ;;
--enable-kvm) printf "%s" -Dkvm=enabled ;;
--disable-kvm) printf "%s" -Dkvm=disabled ;;
+ --enable-l2tpv3) printf "%s" -Dl2tpv3=enabled ;;
+ --disable-l2tpv3) printf "%s" -Dl2tpv3=disabled ;;
--enable-libdaxctl) printf "%s" -Dlibdaxctl=enabled ;;
--disable-libdaxctl) printf "%s" -Dlibdaxctl=disabled ;;
--enable-libiscsi) printf "%s" -Dlibiscsi=enabled ;;
diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index b9a8c1d1f4..314f8b439c 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -1296,23 +1296,26 @@ void qemu_mutex_unlock_ramlist(void)
qemu_mutex_unlock(&ram_list.mutex);
}
-void ram_block_dump(Monitor *mon)
+GString *ram_block_format(void)
{
RAMBlock *block;
char *psize;
+ GString *buf = g_string_new("");
RCU_READ_LOCK_GUARD();
- monitor_printf(mon, "%24s %8s %18s %18s %18s\n",
- "Block Name", "PSize", "Offset", "Used", "Total");
+ g_string_append_printf(buf, "%24s %8s %18s %18s %18s\n",
+ "Block Name", "PSize", "Offset", "Used", "Total");
RAMBLOCK_FOREACH(block) {
psize = size_to_str(block->page_size);
- monitor_printf(mon, "%24s %8s 0x%016" PRIx64 " 0x%016" PRIx64
- " 0x%016" PRIx64 "\n", block->idstr, psize,
- (uint64_t)block->offset,
- (uint64_t)block->used_length,
- (uint64_t)block->max_length);
+ g_string_append_printf(buf, "%24s %8s 0x%016" PRIx64 " 0x%016" PRIx64
+ " 0x%016" PRIx64 "\n", block->idstr, psize,
+ (uint64_t)block->offset,
+ (uint64_t)block->used_length,
+ (uint64_t)block->max_length);
g_free(psize);
}
+
+ return buf;
}
#ifdef __linux__
diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index e49d9773d2..f8b3a4cd82 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -165,6 +165,7 @@ static void qdev_print_devinfos(bool show_no_user)
[DEVICE_CATEGORY_SOUND] = "Sound",
[DEVICE_CATEGORY_MISC] = "Misc",
[DEVICE_CATEGORY_CPU] = "CPU",
+ [DEVICE_CATEGORY_WATCHDOG]= "Watchdog",
[DEVICE_CATEGORY_MAX] = "Uncategorized",
};
GSList *list, *elt;
diff --git a/softmmu/vl.c b/softmmu/vl.c
index af0c4cbd99..1159a64bce 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -3256,6 +3256,7 @@ void qemu_init(int argc, char **argv, char **envp)
error_report("only one watchdog option may be given");
exit(1);
}
+ warn_report("-watchdog is deprecated; use -device instead.");
watchdog = optarg;
break;
case QEMU_OPTION_action:
@@ -3264,12 +3265,12 @@ void qemu_init(int argc, char **argv, char **envp)
exit(1);
}
break;
- case QEMU_OPTION_watchdog_action:
- if (select_watchdog_action(optarg) == -1) {
- error_report("unknown -watchdog-action parameter");
- exit(1);
- }
+ case QEMU_OPTION_watchdog_action: {
+ QemuOpts *opts;
+ opts = qemu_opts_create(qemu_find_opts("action"), NULL, 0, &error_abort);
+ qemu_opt_set(opts, "watchdog", optarg, &error_abort);
break;
+ }
case QEMU_OPTION_parallel:
add_device_config(DEV_PARALLEL, optarg);
default_parallel = 0;
diff --git a/stubs/usb-dev-stub.c b/stubs/usb-dev-stub.c
index b1adeeb454..aa557692b7 100644
--- a/stubs/usb-dev-stub.c
+++ b/stubs/usb-dev-stub.c
@@ -8,6 +8,8 @@
#include "qemu/osdep.h"
#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "qapi/qapi-commands-machine.h"
#include "sysemu/sysemu.h"
#include "monitor/monitor.h"
#include "hw/usb.h"
@@ -19,6 +21,12 @@ USBDevice *usbdevice_create(const char *driver)
return NULL;
}
+HumanReadableText *qmp_x_query_usb(Error **errp)
+{
+ error_setg(errp, "Support for USB devices not built-in");
+ return NULL;
+}
+
void hmp_info_usb(Monitor *mon, const QDict *qdict)
{
monitor_printf(mon, "Support for USB devices not built-in\n");
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index e0dcb33e32..134da0d0ae 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -199,6 +199,27 @@ static int vfp_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
return 0;
}
+static int mve_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
+{
+ switch (reg) {
+ case 0:
+ return gdb_get_reg32(buf, env->v7m.vpr);
+ default:
+ return 0;
+ }
+}
+
+static int mve_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
+{
+ switch (reg) {
+ case 0:
+ env->v7m.vpr = ldl_p(buf);
+ return 4;
+ default:
+ return 0;
+ }
+}
+
/**
* arm_get/set_gdb_*: get/set a gdb register
* @env: the CPU state
@@ -468,6 +489,10 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
2, "arm-vfp-sysregs.xml", 0);
}
}
+ if (cpu_isar_feature(aa32_mve, cpu)) {
+ gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg,
+ 1, "arm-m-profile-mve.xml", 0);
+ }
gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
"system-registers.xml", 0);
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index bff3e0cde7..0dc96560d3 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -1150,12 +1150,19 @@ int hvf_vcpu_exec(CPUState *cpu)
uint32_t sas = (syndrome >> 22) & 3;
uint32_t len = 1 << sas;
uint32_t srt = (syndrome >> 16) & 0x1f;
+ uint32_t cm = (syndrome >> 8) & 0x1;
uint64_t val = 0;
trace_hvf_data_abort(env->pc, hvf_exit->exception.virtual_address,
hvf_exit->exception.physical_address, isv,
iswrite, s1ptw, len, srt);
+ if (cm) {
+ /* We don't cache MMIO regions */
+ advance_pc = true;
+ break;
+ }
+
assert(isv);
if (iswrite) {
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
index 88f15df60e..17af8dc95a 100644
--- a/target/arm/translate-a32.h
+++ b/target/arm/translate-a32.h
@@ -70,6 +70,9 @@ static inline void store_cpu_offset(TCGv_i32 var, int offset)
#define store_cpu_field(var, name) \
store_cpu_offset(var, offsetof(CPUARMState, name))
+#define store_cpu_field_constant(val, name) \
+ tcg_gen_st_i32(tcg_constant_i32(val), cpu_env, offsetof(CPUARMState, name))
+
/* Create a new temporary and set it to the value of a CPU register. */
static inline TCGv_i32 load_reg(DisasContext *s, int reg)
{
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
index bc91a64171..76b5fe9f31 100644
--- a/target/arm/translate-sve.c
+++ b/target/arm/translate-sve.c
@@ -1943,20 +1943,20 @@ static void do_sat_addsub_32(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
static void do_sat_addsub_64(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
{
TCGv_i64 t0 = tcg_temp_new_i64();
- TCGv_i64 t1 = tcg_temp_new_i64();
TCGv_i64 t2;
if (u) {
if (d) {
tcg_gen_sub_i64(t0, reg, val);
- tcg_gen_movi_i64(t1, 0);
- tcg_gen_movcond_i64(TCG_COND_LTU, reg, reg, val, t1, t0);
+ t2 = tcg_constant_i64(0);
+ tcg_gen_movcond_i64(TCG_COND_LTU, reg, reg, val, t2, t0);
} else {
tcg_gen_add_i64(t0, reg, val);
- tcg_gen_movi_i64(t1, -1);
- tcg_gen_movcond_i64(TCG_COND_LTU, reg, t0, reg, t1, t0);
+ t2 = tcg_constant_i64(-1);
+ tcg_gen_movcond_i64(TCG_COND_LTU, reg, t0, reg, t2, t0);
}
} else {
+ TCGv_i64 t1 = tcg_temp_new_i64();
if (d) {
/* Detect signed overflow for subtraction. */
tcg_gen_xor_i64(t0, reg, val);
@@ -1966,7 +1966,7 @@ static void do_sat_addsub_64(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
/* Bound the result. */
tcg_gen_movi_i64(reg, INT64_MIN);
- t2 = tcg_const_i64(0);
+ t2 = tcg_constant_i64(0);
tcg_gen_movcond_i64(TCG_COND_LT, reg, t0, t2, reg, t1);
} else {
/* Detect signed overflow for addition. */
@@ -1977,13 +1977,12 @@ static void do_sat_addsub_64(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
/* Bound the result. */
tcg_gen_movi_i64(t1, INT64_MAX);
- t2 = tcg_const_i64(0);
+ t2 = tcg_constant_i64(0);
tcg_gen_movcond_i64(TCG_COND_LT, reg, t0, t2, t1, reg);
}
- tcg_temp_free_i64(t2);
+ tcg_temp_free_i64(t1);
}
tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
}
/* Similarly with a vector and a scalar operand. */
diff --git a/target/arm/translate.c b/target/arm/translate.c
index d6af5b1b03..98f5925928 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -364,8 +364,7 @@ void clear_eci_state(DisasContext *s)
* multiple insn executes.
*/
if (s->eci) {
- TCGv_i32 tmp = tcg_const_i32(0);
- store_cpu_field(tmp, condexec_bits);
+ store_cpu_field_constant(0, condexec_bits);
s->eci = 0;
}
}
@@ -389,13 +388,12 @@ static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
void gen_rev16(TCGv_i32 dest, TCGv_i32 var)
{
TCGv_i32 tmp = tcg_temp_new_i32();
- TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
+ TCGv_i32 mask = tcg_constant_i32(0x00ff00ff);
tcg_gen_shri_i32(tmp, var, 8);
tcg_gen_and_i32(tmp, tmp, mask);
tcg_gen_and_i32(var, var, mask);
tcg_gen_shli_i32(var, var, 8);
tcg_gen_or_i32(dest, var, tmp);
- tcg_temp_free_i32(mask);
tcg_temp_free_i32(tmp);
}
@@ -740,9 +738,8 @@ void gen_set_condexec(DisasContext *s)
{
if (s->condexec_mask) {
uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
- TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_movi_i32(tmp, val);
- store_cpu_field(tmp, condexec_bits);
+
+ store_cpu_field_constant(val, condexec_bits);
}
}
@@ -7849,10 +7846,9 @@ static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
t3 = tcg_temp_new_i32();
tcg_gen_sari_i32(t3, t1, 31);
qf = load_cpu_field(QF);
- one = tcg_const_i32(1);
+ one = tcg_constant_i32(1);
tcg_gen_movcond_i32(TCG_COND_NE, qf, t2, t3, one, qf);
store_cpu_field(qf, QF);
- tcg_temp_free_i32(one);
tcg_temp_free_i32(t3);
tcg_temp_free_i32(t2);
}
@@ -8363,8 +8359,6 @@ static bool trans_BL(DisasContext *s, arg_i *a)
static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
{
- TCGv_i32 tmp;
-
/*
* BLX <imm> would be useless on M-profile; the encoding space
* is used for other insns from v8.1M onward, and UNDEFs before that.
@@ -8378,8 +8372,7 @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
return false;
}
tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
- tmp = tcg_const_i32(!s->thumb);
- store_cpu_field(tmp, thumb);
+ store_cpu_field_constant(!s->thumb, thumb);
gen_jmp(s, (read_pc(s) & ~3) + a->imm);
return true;
}
@@ -8678,7 +8671,6 @@ static bool trans_LCTP(DisasContext *s, arg_LCTP *a)
* doesn't cache branch information, all we need to do is reset
* FPSCR.LTPSIZE to 4.
*/
- TCGv_i32 ltpsize;
if (!dc_isar_feature(aa32_lob, s) ||
!dc_isar_feature(aa32_mve, s)) {
@@ -8689,8 +8681,7 @@ static bool trans_LCTP(DisasContext *s, arg_LCTP *a)
return true;
}
- ltpsize = tcg_const_i32(4);
- store_cpu_field(ltpsize, v7m.ltpsize);
+ store_cpu_field_constant(4, v7m.ltpsize);
return true;
}
@@ -9488,9 +9479,7 @@ static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
/* Reset the conditional execution bits immediately. This avoids
complications trying to do it at the end of the block. */
if (dc->condexec_mask || dc->condexec_cond) {
- TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_movi_i32(tmp, 0);
- store_cpu_field(tmp, condexec_bits);
+ store_cpu_field_constant(0, condexec_bits);
}
}
diff --git a/target/i386/cpu-dump.c b/target/i386/cpu-dump.c
index 02b635a52c..08ac957e99 100644
--- a/target/i386/cpu-dump.c
+++ b/target/i386/cpu-dump.c
@@ -464,13 +464,13 @@ void x86_cpu_dump_state(CPUState *cs, FILE *f, int flags)
snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
#ifdef TARGET_X86_64
if (env->hflags & HF_CS64_MASK) {
- qemu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
+ qemu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%s\n",
env->cc_src, env->cc_dst,
cc_op_name);
} else
#endif
{
- qemu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
+ qemu_fprintf(f, "CCS=%08x CCD=%08x CCO=%s\n",
(uint32_t)env->cc_src, (uint32_t)env->cc_dst,
cc_op_name);
}
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 598d451dcf..aa9e636800 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -4878,7 +4878,7 @@ static void x86_cpu_list_entry(gpointer data, gpointer user_data)
desc = g_strdup_printf("%s", model_id);
}
- qemu_printf("x86 %-20s %-58s\n", name, desc);
+ qemu_printf("x86 %-20s %s\n", name, desc);
}
/* list available CPU models and flags */
@@ -5928,6 +5928,11 @@ static void x86_cpu_reset(DeviceState *dev)
}
x86_cpu_set_sgxlepubkeyhash(env);
+
+ if (env->features[FEAT_SVM] & CPUID_SVM_TSCSCALE) {
+ env->amd_tsc_scale_msr = MSR_AMD64_TSC_RATIO_DEFAULT;
+ }
+
#endif
}
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 3edaad7688..04f2b790c9 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -499,6 +499,9 @@ typedef enum X86Seg {
#define MSR_GSBASE 0xc0000101
#define MSR_KERNELGSBASE 0xc0000102
#define MSR_TSC_AUX 0xc0000103
+#define MSR_AMD64_TSC_RATIO 0xc0000104
+
+#define MSR_AMD64_TSC_RATIO_DEFAULT 0x100000000ULL
#define MSR_VM_HSAVE_PA 0xc0010117
@@ -1536,6 +1539,7 @@ typedef struct CPUX86State {
uint32_t tsx_ctrl;
uint64_t spec_ctrl;
+ uint64_t amd_tsc_scale_msr;
uint64_t virt_ssbd;
/* End of state preserved by INIT (dummy marker). */
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 0eb7a0340c..5a698bde19 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -105,6 +105,7 @@ static bool has_msr_hv_reenlightenment;
static bool has_msr_xss;
static bool has_msr_umwait;
static bool has_msr_spec_ctrl;
+static bool has_tsc_scale_msr;
static bool has_msr_tsx_ctrl;
static bool has_msr_virt_ssbd;
static bool has_msr_smi_count;
@@ -2216,6 +2217,9 @@ static int kvm_get_supported_msrs(KVMState *s)
case MSR_IA32_SPEC_CTRL:
has_msr_spec_ctrl = true;
break;
+ case MSR_AMD64_TSC_RATIO:
+ has_tsc_scale_msr = true;
+ break;
case MSR_IA32_TSX_CTRL:
has_msr_tsx_ctrl = true;
break;
@@ -2972,6 +2976,10 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
if (has_msr_spec_ctrl) {
kvm_msr_entry_add(cpu, MSR_IA32_SPEC_CTRL, env->spec_ctrl);
}
+ if (has_tsc_scale_msr) {
+ kvm_msr_entry_add(cpu, MSR_AMD64_TSC_RATIO, env->amd_tsc_scale_msr);
+ }
+
if (has_msr_tsx_ctrl) {
kvm_msr_entry_add(cpu, MSR_IA32_TSX_CTRL, env->tsx_ctrl);
}
@@ -3377,6 +3385,10 @@ static int kvm_get_msrs(X86CPU *cpu)
if (has_msr_spec_ctrl) {
kvm_msr_entry_add(cpu, MSR_IA32_SPEC_CTRL, 0);
}
+ if (has_tsc_scale_msr) {
+ kvm_msr_entry_add(cpu, MSR_AMD64_TSC_RATIO, 0);
+ }
+
if (has_msr_tsx_ctrl) {
kvm_msr_entry_add(cpu, MSR_IA32_TSX_CTRL, 0);
}
@@ -3788,6 +3800,9 @@ static int kvm_get_msrs(X86CPU *cpu)
case MSR_IA32_SPEC_CTRL:
env->spec_ctrl = msrs[i].data;
break;
+ case MSR_AMD64_TSC_RATIO:
+ env->amd_tsc_scale_msr = msrs[i].data;
+ break;
case MSR_IA32_TSX_CTRL:
env->tsx_ctrl = msrs[i].data;
break;
diff --git a/target/i386/machine.c b/target/i386/machine.c
index 4367931623..83c2b91529 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -1280,6 +1280,27 @@ static const VMStateDescription vmstate_spec_ctrl = {
}
};
+
+static bool amd_tsc_scale_msr_needed(void *opaque)
+{
+ X86CPU *cpu = opaque;
+ CPUX86State *env = &cpu->env;
+
+ return (env->features[FEAT_SVM] & CPUID_SVM_TSCSCALE);
+}
+
+static const VMStateDescription amd_tsc_scale_msr_ctrl = {
+ .name = "cpu/amd_tsc_scale_msr",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = amd_tsc_scale_msr_needed,
+ .fields = (VMStateField[]){
+ VMSTATE_UINT64(env.amd_tsc_scale_msr, X86CPU),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+
static bool intel_pt_enable_needed(void *opaque)
{
X86CPU *cpu = opaque;
@@ -1558,6 +1579,7 @@ const VMStateDescription vmstate_x86_cpu = {
&vmstate_pkru,
&vmstate_pkrs,
&vmstate_spec_ctrl,
+ &amd_tsc_scale_msr_ctrl,
&vmstate_mcg_ext_ctl,
&vmstate_msr_intel_pt,
&vmstate_msr_virt_ssbd,
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 8166e17693..8e4b4d600c 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -667,9 +667,3 @@ void hmp_info_local_apic(Monitor *mon, const QDict *qdict)
}
x86_cpu_dump_local_apic_state(cs, CPU_DUMP_FPU);
}
-
-void hmp_info_io_apic(Monitor *mon, const QDict *qdict)
-{
- monitor_printf(mon, "This command is obsolete and will be "
- "removed soon. Please use 'info pic' instead.\n");
-}
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 1c7a7b4b38..6695985e9b 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -8734,7 +8734,7 @@ void ppc_cpu_list(void)
#ifdef CONFIG_KVM
qemu_printf("\n");
- qemu_printf("PowerPC %-16s\n", "host");
+ qemu_printf("PowerPC %s\n", "host");
#endif
}
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index 4e4598cc77..11e06cc51f 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -398,14 +398,14 @@ void s390_cpu_list(void)
for (feat = 0; feat < S390_FEAT_MAX; feat++) {
const S390FeatDef *def = s390_feat_def(feat);
- qemu_printf("%-20s %-50s\n", def->name, def->desc);
+ qemu_printf("%-20s %s\n", def->name, def->desc);
}
qemu_printf("\nRecognized feature groups:\n");
for (group = 0; group < S390_FEAT_GROUP_MAX; group++) {
const S390FeatGroupDef *def = s390_feat_group_def(group);
- qemu_printf("%-20s %-50s\n", def->name, def->desc);
+ qemu_printf("%-20s %s\n", def->name, def->desc);
}
}
diff --git a/target/xtensa/mmu_helper.c b/target/xtensa/mmu_helper.c
index b01ff9399a..57e319a1af 100644
--- a/target/xtensa/mmu_helper.c
+++ b/target/xtensa/mmu_helper.c
@@ -1098,7 +1098,7 @@ static void dump_tlb(CPUXtensaState *env, bool dtlb)
qemu_printf("\tVaddr Paddr ASID Attr RWX Cache\n"
"\t---------- ---------- ---- ---- --- -------\n");
}
- qemu_printf("\t0x%08x 0x%08x 0x%02x 0x%02x %c%c%c %-7s\n",
+ qemu_printf("\t0x%08x 0x%08x 0x%02x 0x%02x %c%c%c %s\n",
entry->vaddr,
entry->paddr,
entry->asid,
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 6332cdceca..57f17a4649 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -4116,15 +4116,15 @@ static void tcg_profile_snapshot_table(TCGProfile *prof)
tcg_profile_snapshot(prof, false, true);
}
-void tcg_dump_op_count(void)
+void tcg_dump_op_count(GString *buf)
{
TCGProfile prof = {};
int i;
tcg_profile_snapshot_table(&prof);
for (i = 0; i < NB_OPS; i++) {
- qemu_printf("%s %" PRId64 "\n", tcg_op_defs[i].name,
- prof.table_op_count[i]);
+ g_string_append_printf(buf, "%s %" PRId64 "\n", tcg_op_defs[i].name,
+ prof.table_op_count[i]);
}
}
@@ -4143,9 +4143,9 @@ int64_t tcg_cpu_exec_time(void)
return ret;
}
#else
-void tcg_dump_op_count(void)
+void tcg_dump_op_count(GString *buf)
{
- qemu_printf("[TCG profiler not compiled]\n");
+ g_string_append_printf(buf, "[TCG profiler not compiled]\n");
}
int64_t tcg_cpu_exec_time(void)
@@ -4383,7 +4383,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
}
#ifdef CONFIG_PROFILER
-void tcg_dump_info(void)
+void tcg_dump_info(GString *buf)
{
TCGProfile prof = {};
const TCGProfile *s;
@@ -4397,53 +4397,59 @@ void tcg_dump_info(void)
tb_div_count = tb_count ? tb_count : 1;
tot = s->interm_time + s->code_time;
- qemu_printf("JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
- tot, tot / 2.4e9);
- qemu_printf("translated TBs %" PRId64 " (aborted=%" PRId64
- " %0.1f%%)\n",
- tb_count, s->tb_count1 - tb_count,
- (double)(s->tb_count1 - s->tb_count)
- / (s->tb_count1 ? s->tb_count1 : 1) * 100.0);
- qemu_printf("avg ops/TB %0.1f max=%d\n",
- (double)s->op_count / tb_div_count, s->op_count_max);
- qemu_printf("deleted ops/TB %0.2f\n",
- (double)s->del_op_count / tb_div_count);
- qemu_printf("avg temps/TB %0.2f max=%d\n",
- (double)s->temp_count / tb_div_count, s->temp_count_max);
- qemu_printf("avg host code/TB %0.1f\n",
- (double)s->code_out_len / tb_div_count);
- qemu_printf("avg search data/TB %0.1f\n",
- (double)s->search_out_len / tb_div_count);
+ g_string_append_printf(buf, "JIT cycles %" PRId64
+ " (%0.3f s at 2.4 GHz)\n",
+ tot, tot / 2.4e9);
+ g_string_append_printf(buf, "translated TBs %" PRId64
+ " (aborted=%" PRId64 " %0.1f%%)\n",
+ tb_count, s->tb_count1 - tb_count,
+ (double)(s->tb_count1 - s->tb_count)
+ / (s->tb_count1 ? s->tb_count1 : 1) * 100.0);
+ g_string_append_printf(buf, "avg ops/TB %0.1f max=%d\n",
+ (double)s->op_count / tb_div_count, s->op_count_max);
+ g_string_append_printf(buf, "deleted ops/TB %0.2f\n",
+ (double)s->del_op_count / tb_div_count);
+ g_string_append_printf(buf, "avg temps/TB %0.2f max=%d\n",
+ (double)s->temp_count / tb_div_count,
+ s->temp_count_max);
+ g_string_append_printf(buf, "avg host code/TB %0.1f\n",
+ (double)s->code_out_len / tb_div_count);
+ g_string_append_printf(buf, "avg search data/TB %0.1f\n",
+ (double)s->search_out_len / tb_div_count);
- qemu_printf("cycles/op %0.1f\n",
- s->op_count ? (double)tot / s->op_count : 0);
- qemu_printf("cycles/in byte %0.1f\n",
- s->code_in_len ? (double)tot / s->code_in_len : 0);
- qemu_printf("cycles/out byte %0.1f\n",
- s->code_out_len ? (double)tot / s->code_out_len : 0);
- qemu_printf("cycles/search byte %0.1f\n",
- s->search_out_len ? (double)tot / s->search_out_len : 0);
+ g_string_append_printf(buf, "cycles/op %0.1f\n",
+ s->op_count ? (double)tot / s->op_count : 0);
+ g_string_append_printf(buf, "cycles/in byte %0.1f\n",
+ s->code_in_len ? (double)tot / s->code_in_len : 0);
+ g_string_append_printf(buf, "cycles/out byte %0.1f\n",
+ s->code_out_len ? (double)tot / s->code_out_len : 0);
+ g_string_append_printf(buf, "cycles/search byte %0.1f\n",
+ s->search_out_len ?
+ (double)tot / s->search_out_len : 0);
if (tot == 0) {
tot = 1;
}
- qemu_printf(" gen_interm time %0.1f%%\n",
- (double)s->interm_time / tot * 100.0);
- qemu_printf(" gen_code time %0.1f%%\n",
- (double)s->code_time / tot * 100.0);
- qemu_printf("optim./code time %0.1f%%\n",
- (double)s->opt_time / (s->code_time ? s->code_time : 1)
- * 100.0);
- qemu_printf("liveness/code time %0.1f%%\n",
- (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
- qemu_printf("cpu_restore count %" PRId64 "\n",
- s->restore_count);
- qemu_printf(" avg cycles %0.1f\n",
- s->restore_count ? (double)s->restore_time / s->restore_count : 0);
+ g_string_append_printf(buf, " gen_interm time %0.1f%%\n",
+ (double)s->interm_time / tot * 100.0);
+ g_string_append_printf(buf, " gen_code time %0.1f%%\n",
+ (double)s->code_time / tot * 100.0);
+ g_string_append_printf(buf, "optim./code time %0.1f%%\n",
+ (double)s->opt_time / (s->code_time ?
+ s->code_time : 1)
+ * 100.0);
+ g_string_append_printf(buf, "liveness/code time %0.1f%%\n",
+ (double)s->la_time / (s->code_time ?
+ s->code_time : 1) * 100.0);
+ g_string_append_printf(buf, "cpu_restore count %" PRId64 "\n",
+ s->restore_count);
+ g_string_append_printf(buf, " avg cycles %0.1f\n",
+ s->restore_count ?
+ (double)s->restore_time / s->restore_count : 0);
}
#else
-void tcg_dump_info(void)
+void tcg_dump_info(GString *buf)
{
- qemu_printf("[TCG profiler not compiled]\n");
+ g_string_append_printf(buf, "[TCG profiler not compiled]\n");
}
#endif
diff --git a/tests/qtest/am53c974-test.c b/tests/qtest/am53c974-test.c
index d996866cd4..9b1e4211bd 100644
--- a/tests/qtest/am53c974-test.c
+++ b/tests/qtest/am53c974-test.c
@@ -189,6 +189,40 @@ static void test_cancelled_request_ok(void)
qtest_quit(s);
}
+static void test_inflight_cancel_ok(void)
+{
+ QTestState *s = qtest_init(
+ "-device am53c974,id=scsi "
+ "-device scsi-hd,drive=disk0 -drive "
+ "id=disk0,if=none,file=null-co://,format=raw -nodefaults");
+ qtest_outl(s, 0xcf8, 0x80001000);
+ qtest_inw(s, 0xcfc);
+ qtest_outl(s, 0xcf8, 0x80001010);
+ qtest_outl(s, 0xcfc, 0xffffffff);
+ qtest_outl(s, 0xcf8, 0x80001010);
+ qtest_inl(s, 0xcfc);
+ qtest_outl(s, 0xcf8, 0x80001010);
+ qtest_outl(s, 0xcfc, 0xc001);
+ qtest_outl(s, 0xcf8, 0x80001004);
+ qtest_inw(s, 0xcfc);
+ qtest_outl(s, 0xcf8, 0x80001004);
+ qtest_outw(s, 0xcfc, 0x7);
+ qtest_outl(s, 0xcf8, 0x80001004);
+ qtest_inw(s, 0xcfc);
+ qtest_inb(s, 0xc000);
+ qtest_outb(s, 0xc008, 0x8);
+ qtest_outw(s, 0xc00b, 0x4100);
+ qtest_outb(s, 0xc009, 0x0);
+ qtest_outb(s, 0xc009, 0x0);
+ qtest_outw(s, 0xc00b, 0xc212);
+ qtest_outl(s, 0xc042, 0x2c2c5a88);
+ qtest_outw(s, 0xc00b, 0xc212);
+ qtest_outw(s, 0xc00b, 0x415a);
+ qtest_outl(s, 0xc03f, 0x3060303);
+ qtest_outl(s, 0xc00b, 0x5afa9054);
+ qtest_quit(s);
+}
+
int main(int argc, char **argv)
{
const char *arch = qtest_get_arch();
@@ -212,6 +246,8 @@ int main(int argc, char **argv)
test_fifo_underflow_on_write_ok);
qtest_add_func("am53c974/test_cancelled_request_ok",
test_cancelled_request_ok);
+ qtest_add_func("am53c974/test_inflight_cancel_ok",
+ test_inflight_cancel_ok);
}
return g_test_run();
diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build
index 1f5c8f1053..4af1f04787 100644
--- a/tests/qtest/libqos/meson.build
+++ b/tests/qtest/libqos/meson.build
@@ -5,6 +5,7 @@ libqos_srcs = files('../libqtest.c',
'fw_cfg.c',
'malloc.c',
'libqos.c',
+ 'sdhci-cmd.c',
# spapr
'malloc-spapr.c',
diff --git a/tests/qtest/libqos/sdhci-cmd.c b/tests/qtest/libqos/sdhci-cmd.c
new file mode 100644
index 0000000000..2d9e518341
--- /dev/null
+++ b/tests/qtest/libqos/sdhci-cmd.c
@@ -0,0 +1,116 @@
+/*
+ * MMC Host Controller Commands
+ *
+ * Copyright (c) 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+#include "sdhci-cmd.h"
+#include "libqtest.h"
+
+static ssize_t read_fifo(QTestState *qts, uint64_t reg, char *msg, size_t count)
+{
+ uint32_t mask = 0xff;
+ size_t index = 0;
+ uint32_t msg_frag;
+ int size;
+ while (index < count) {
+ size = count - index;
+ if (size > 4) {
+ size = 4;
+ }
+ msg_frag = qtest_readl(qts, reg);
+ while (size > 0) {
+ msg[index] = msg_frag & mask;
+ if (msg[index++] == 0) {
+ return index;
+ }
+ msg_frag >>= 8;
+ --size;
+ }
+ }
+ return index;
+}
+
+static void write_fifo(QTestState *qts, uint64_t reg, const char *msg,
+ size_t count)
+{
+ size_t index = 0;
+ uint32_t msg_frag;
+ int size;
+ int frag_i;
+ while (index < count) {
+ size = count - index;
+ if (size > 4) {
+ size = 4;
+ }
+ msg_frag = 0;
+ frag_i = 0;
+ while (frag_i < size) {
+ msg_frag |= ((uint32_t)msg[index++]) << (frag_i * 8);
+ ++frag_i;
+ }
+ qtest_writel(qts, reg, msg_frag);
+ }
+}
+
+static void fill_block(QTestState *qts, uint64_t reg, int count)
+{
+ while (--count >= 0) {
+ qtest_writel(qts, reg, 0);
+ }
+}
+
+void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize,
+ uint16_t blkcnt, uint32_t argument, uint16_t trnmod,
+ uint16_t cmdreg)
+{
+ qtest_writew(qts, base_addr + SDHC_BLKSIZE, blksize);
+ qtest_writew(qts, base_addr + SDHC_BLKCNT, blkcnt);
+ qtest_writel(qts, base_addr + SDHC_ARGUMENT, argument);
+ qtest_writew(qts, base_addr + SDHC_TRNMOD, trnmod);
+ qtest_writew(qts, base_addr + SDHC_CMDREG, cmdreg);
+}
+
+ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg,
+ size_t count)
+{
+ sdhci_cmd_regs(qts, base_addr, count, 1, 0,
+ SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN,
+ SDHC_READ_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT);
+
+ /* read sd fifo_buffer */
+ ssize_t bytes_read = read_fifo(qts, base_addr + SDHC_BDATA, msg, count);
+
+ sdhci_cmd_regs(qts, base_addr, 0, 0, 0,
+ SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN,
+ SDHC_STOP_TRANSMISSION);
+
+ return bytes_read;
+}
+
+void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg,
+ size_t count, size_t blksize)
+{
+ sdhci_cmd_regs(qts, base_addr, blksize, 1, 0,
+ SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN,
+ SDHC_WRITE_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT);
+
+ /* write to sd fifo_buffer */
+ write_fifo(qts, base_addr + SDHC_BDATA, msg, count);
+ fill_block(qts, base_addr + SDHC_BDATA, (blksize - count) / 4);
+
+ sdhci_cmd_regs(qts, base_addr, 0, 0, 0,
+ SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN,
+ SDHC_STOP_TRANSMISSION);
+}
diff --git a/tests/qtest/libqos/sdhci-cmd.h b/tests/qtest/libqos/sdhci-cmd.h
new file mode 100644
index 0000000000..64763c5a2a
--- /dev/null
+++ b/tests/qtest/libqos/sdhci-cmd.h
@@ -0,0 +1,70 @@
+/*
+ * MMC Host Controller Commands
+ *
+ * Copyright (c) 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "libqtest.h"
+
+/* more details at hw/sd/sdhci-internal.h */
+#define SDHC_BLKSIZE 0x04
+#define SDHC_BLKCNT 0x06
+#define SDHC_ARGUMENT 0x08
+#define SDHC_TRNMOD 0x0C
+#define SDHC_CMDREG 0x0E
+#define SDHC_BDATA 0x20
+#define SDHC_PRNSTS 0x24
+#define SDHC_BLKGAP 0x2A
+#define SDHC_CLKCON 0x2C
+#define SDHC_SWRST 0x2F
+#define SDHC_CAPAB 0x40
+#define SDHC_MAXCURR 0x48
+#define SDHC_HCVER 0xFE
+
+/* TRNSMOD Reg */
+#define SDHC_TRNS_BLK_CNT_EN 0x0002
+#define SDHC_TRNS_READ 0x0010
+#define SDHC_TRNS_WRITE 0x0000
+#define SDHC_TRNS_MULTI 0x0020
+
+/* CMD Reg */
+#define SDHC_CMD_DATA_PRESENT (1 << 5)
+#define SDHC_ALL_SEND_CID (2 << 8)
+#define SDHC_SEND_RELATIVE_ADDR (3 << 8)
+#define SDHC_SELECT_DESELECT_CARD (7 << 8)
+#define SDHC_SEND_CSD (9 << 8)
+#define SDHC_STOP_TRANSMISSION (12 << 8)
+#define SDHC_READ_MULTIPLE_BLOCK (18 << 8)
+#define SDHC_WRITE_MULTIPLE_BLOCK (25 << 8)
+#define SDHC_APP_CMD (55 << 8)
+
+/* SWRST Reg */
+#define SDHC_RESET_ALL 0x01
+
+/* CLKCTRL Reg */
+#define SDHC_CLOCK_INT_EN 0x0001
+#define SDHC_CLOCK_INT_STABLE 0x0002
+#define SDHC_CLOCK_SDCLK_EN (1 << 2)
+
+/* Set registers needed to send commands to SD */
+void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize,
+ uint16_t blkcnt, uint32_t argument, uint16_t trnmod,
+ uint16_t cmdreg);
+
+/* Read at most 1 block of SD using non-DMA */
+ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg,
+ size_t count);
+
+/* Write at most 1 block of SD using non-DMA */
+void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg,
+ size_t count, size_t blksize);
diff --git a/tests/qtest/qmp-cmd-test.c b/tests/qtest/qmp-cmd-test.c
index 1af2f74c28..7f103ea3fd 100644
--- a/tests/qtest/qmp-cmd-test.c
+++ b/tests/qtest/qmp-cmd-test.c
@@ -46,6 +46,14 @@ static int query_error_class(const char *cmd)
{ "query-balloon", ERROR_CLASS_DEVICE_NOT_ACTIVE },
{ "query-hotpluggable-cpus", ERROR_CLASS_GENERIC_ERROR },
{ "query-vm-generation-id", ERROR_CLASS_GENERIC_ERROR },
+#ifndef CONFIG_PROFILER
+ { "x-query-profile", ERROR_CLASS_GENERIC_ERROR },
+#endif
+ /* Only valid with a USB bus added */
+ { "x-query-usb", ERROR_CLASS_GENERIC_ERROR },
+ /* Only valid with accel=tcg */
+ { "x-query-jit", ERROR_CLASS_GENERIC_ERROR },
+ { "x-query-opcount", ERROR_CLASS_GENERIC_ERROR },
{ NULL, -1 }
};
int i;
diff --git a/ui/console.c b/ui/console.c
index eabbbc951c..29a3e3f0f5 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -27,10 +27,12 @@
#include "hw/qdev-core.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-ui.h"
+#include "qemu/fifo8.h"
+#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/timer.h"
-#include "chardev/char-fe.h"
+#include "chardev/char.h"
#include "trace.h"
#include "exec/memory.h"
#include "io/channel-file.h"
@@ -62,57 +64,6 @@ enum TTYState {
TTY_STATE_CSI,
};
-typedef struct QEMUFIFO {
- uint8_t *buf;
- int buf_size;
- int count, wptr, rptr;
-} QEMUFIFO;
-
-static int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1)
-{
- int l, len;
-
- l = f->buf_size - f->count;
- if (len1 > l)
- len1 = l;
- len = len1;
- while (len > 0) {
- l = f->buf_size - f->wptr;
- if (l > len)
- l = len;
- memcpy(f->buf + f->wptr, buf, l);
- f->wptr += l;
- if (f->wptr >= f->buf_size)
- f->wptr = 0;
- buf += l;
- len -= l;
- }
- f->count += len1;
- return len1;
-}
-
-static int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
-{
- int l, len;
-
- if (len1 > f->count)
- len1 = f->count;
- len = len1;
- while (len > 0) {
- l = f->buf_size - f->rptr;
- if (l > len)
- l = len;
- memcpy(buf, f->buf + f->rptr, l);
- f->rptr += l;
- if (f->rptr >= f->buf_size)
- f->rptr = 0;
- buf += l;
- len -= l;
- }
- f->count -= len1;
- return len1;
-}
-
typedef enum {
GRAPHIC_CONSOLE,
TEXT_CONSOLE,
@@ -165,9 +116,7 @@ struct QemuConsole {
Chardev *chr;
/* fifo for key pressed */
- QEMUFIFO out_fifo;
- uint8_t out_fifo_buf[16];
- QEMUTimer *kbd_timer;
+ Fifo8 out_fifo;
CoQueue dump_queue;
QTAILQ_ENTRY(QemuConsole) next;
@@ -1157,25 +1106,20 @@ static int vc_chr_write(Chardev *chr, const uint8_t *buf, int len)
return len;
}
-static void kbd_send_chars(void *opaque)
+static void kbd_send_chars(QemuConsole *s)
{
- QemuConsole *s = opaque;
- int len;
- uint8_t buf[16];
+ uint32_t len, avail;
len = qemu_chr_be_can_write(s->chr);
- if (len > s->out_fifo.count)
- len = s->out_fifo.count;
- if (len > 0) {
- if (len > sizeof(buf))
- len = sizeof(buf);
- qemu_fifo_read(&s->out_fifo, buf, len);
- qemu_chr_be_write(s->chr, buf, len);
- }
- /* characters are pending: we send them a bit later (XXX:
- horrible, should change char device API) */
- if (s->out_fifo.count > 0) {
- timer_mod(s->kbd_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1);
+ avail = fifo8_num_used(&s->out_fifo);
+ while (len > 0 && avail > 0) {
+ const uint8_t *buf;
+ uint32_t size;
+
+ buf = fifo8_pop_buf(&s->out_fifo, MIN(len, avail), &size);
+ qemu_chr_be_write(s->chr, (uint8_t *)buf, size);
+ len = qemu_chr_be_can_write(s->chr);
+ avail -= size;
}
}
@@ -1183,8 +1127,8 @@ static void kbd_send_chars(void *opaque)
void kbd_put_keysym_console(QemuConsole *s, int keysym)
{
uint8_t buf[16], *q;
- CharBackend *be;
int c;
+ uint32_t num_free;
if (!s || (s->console_type == GRAPHIC_CONSOLE))
return;
@@ -1226,11 +1170,9 @@ void kbd_put_keysym_console(QemuConsole *s, int keysym)
if (s->echo) {
vc_chr_write(s->chr, buf, q - buf);
}
- be = s->chr->be;
- if (be && be->chr_read) {
- qemu_fifo_write(&s->out_fifo, buf, q - buf);
- kbd_send_chars(s);
- }
+ num_free = fifo8_num_free(&s->out_fifo);
+ fifo8_push_all(&s->out_fifo, buf, MIN(num_free, q - buf));
+ kbd_send_chars(s);
break;
}
}
@@ -2186,6 +2128,14 @@ int qemu_console_get_height(QemuConsole *con, int fallback)
return con ? surface_height(con->surface) : fallback;
}
+static void vc_chr_accept_input(Chardev *chr)
+{
+ VCChardev *drv = VC_CHARDEV(chr);
+ QemuConsole *s = drv->console;
+
+ kbd_send_chars(s);
+}
+
static void vc_chr_set_echo(Chardev *chr, bool echo)
{
VCChardev *drv = VC_CHARDEV(chr);
@@ -2233,9 +2183,7 @@ static void text_console_do_init(Chardev *chr, DisplayState *ds)
int g_width = 80 * FONT_WIDTH;
int g_height = 24 * FONT_HEIGHT;
- s->out_fifo.buf = s->out_fifo_buf;
- s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
- s->kbd_timer = timer_new_ms(QEMU_CLOCK_REALTIME, kbd_send_chars, s);
+ fifo8_create(&s->out_fifo, 16);
s->ds = ds;
s->y_displayed = 0;
@@ -2485,6 +2433,7 @@ static void char_vc_class_init(ObjectClass *oc, void *data)
cc->parse = qemu_chr_parse_vc;
cc->open = vc_chr_open;
cc->chr_write = vc_chr_write;
+ cc->chr_accept_input = vc_chr_accept_input;
cc->chr_set_echo = vc_chr_set_echo;
}
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index 72ce5e1f8f..e912b20075 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -63,6 +63,9 @@ void gd_egl_init(VirtualConsole *vc)
void gd_egl_draw(VirtualConsole *vc)
{
GdkWindow *window;
+#ifdef CONFIG_GBM
+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+#endif
int ww, wh;
if (!vc->gfx.gls) {
@@ -74,10 +77,31 @@ void gd_egl_draw(VirtualConsole *vc)
wh = gdk_window_get_height(window);
if (vc->gfx.scanout_mode) {
+#ifdef CONFIG_GBM
+ if (dmabuf) {
+ if (!dmabuf->draw_submitted) {
+ return;
+ } else {
+ dmabuf->draw_submitted = false;
+ }
+ }
+#endif
gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h);
vc->gfx.scale_x = (double)ww / vc->gfx.w;
vc->gfx.scale_y = (double)wh / vc->gfx.h;
+
+ glFlush();
+#ifdef CONFIG_GBM
+ if (dmabuf) {
+ egl_dmabuf_create_fence(dmabuf);
+ if (dmabuf->fence_fd > 0) {
+ qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
+ return;
+ }
+ graphic_hw_gl_block(vc->gfx.dcl.con, false);
+ }
+#endif
} else {
if (!vc->gfx.ds) {
return;
@@ -92,21 +116,10 @@ void gd_egl_draw(VirtualConsole *vc)
vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds);
vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds);
- }
-
- glFlush();
-#ifdef CONFIG_GBM
- if (vc->gfx.guest_fb.dmabuf) {
- QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
- egl_dmabuf_create_fence(dmabuf);
- if (dmabuf->fence_fd > 0) {
- qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
- return;
- }
- graphic_hw_gl_block(vc->gfx.dcl.con, false);
+ glFlush();
}
-#endif
+
graphic_hw_gl_flushed(vc->gfx.dcl.con);
}
@@ -317,6 +330,7 @@ void gd_egl_flush(DisplayChangeListener *dcl,
if (vc->gfx.guest_fb.dmabuf) {
graphic_hw_gl_block(vc->gfx.dcl.con, true);
+ vc->gfx.guest_fb.dmabuf->draw_submitted = true;
gtk_widget_queue_draw_area(area, x, y, w, h);
return;
}
diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index b23523748e..461da7712f 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -38,6 +38,9 @@ static void gtk_gl_area_set_scanout_mode(VirtualConsole *vc, bool scanout)
void gd_gl_area_draw(VirtualConsole *vc)
{
+#ifdef CONFIG_GBM
+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+#endif
int ww, wh, y1, y2;
if (!vc->gfx.gls) {
@@ -53,6 +56,16 @@ void gd_gl_area_draw(VirtualConsole *vc)
return;
}
+#ifdef CONFIG_GBM
+ if (dmabuf) {
+ if (!dmabuf->draw_submitted) {
+ return;
+ } else {
+ dmabuf->draw_submitted = false;
+ }
+ }
+#endif
+
glBindFramebuffer(GL_READ_FRAMEBUFFER, vc->gfx.guest_fb.framebuffer);
/* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */
@@ -62,6 +75,22 @@ void gd_gl_area_draw(VirtualConsole *vc)
glBlitFramebuffer(0, y1, vc->gfx.w, y2,
0, 0, ww, wh,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
+#ifdef CONFIG_GBM
+ if (dmabuf) {
+ egl_dmabuf_create_sync(dmabuf);
+ }
+#endif
+ glFlush();
+#ifdef CONFIG_GBM
+ if (dmabuf) {
+ egl_dmabuf_create_fence(dmabuf);
+ if (dmabuf->fence_fd > 0) {
+ qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
+ return;
+ }
+ graphic_hw_gl_block(vc->gfx.dcl.con, false);
+ }
+#endif
} else {
if (!vc->gfx.ds) {
return;
@@ -72,25 +101,6 @@ void gd_gl_area_draw(VirtualConsole *vc)
surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds);
}
-#ifdef CONFIG_GBM
- if (vc->gfx.guest_fb.dmabuf) {
- egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf);
- }
-#endif
-
- glFlush();
-#ifdef CONFIG_GBM
- if (vc->gfx.guest_fb.dmabuf) {
- QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
-
- egl_dmabuf_create_fence(dmabuf);
- if (dmabuf->fence_fd > 0) {
- qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
- return;
- }
- graphic_hw_gl_block(vc->gfx.dcl.con, false);
- }
-#endif
graphic_hw_gl_flushed(vc->gfx.dcl.con);
}
@@ -112,6 +122,9 @@ void gd_gl_area_refresh(DisplayChangeListener *dcl)
{
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
+ vc->gfx.dcl.update_interval = gd_monitor_update_interval(
+ vc->window ? vc->window : vc->gfx.drawing_area);
+
if (!vc->gfx.gls) {
if (!gtk_widget_get_realized(vc->gfx.drawing_area)) {
return;
@@ -234,6 +247,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl,
if (vc->gfx.guest_fb.dmabuf) {
graphic_hw_gl_block(vc->gfx.dcl.con, true);
+ vc->gfx.guest_fb.dmabuf->draw_submitted = true;
}
gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area));
}
diff --git a/util/iova-tree.c b/util/iova-tree.c
index 7990692cbd..23ea35b7a4 100644
--- a/util/iova-tree.c
+++ b/util/iova-tree.c
@@ -42,14 +42,14 @@ IOVATree *iova_tree_new(void)
return iova_tree;
}
-DMAMap *iova_tree_find(IOVATree *tree, DMAMap *map)
+const DMAMap *iova_tree_find(const IOVATree *tree, const DMAMap *map)
{
return g_tree_lookup(tree->tree, map);
}
-DMAMap *iova_tree_find_address(IOVATree *tree, hwaddr iova)
+const DMAMap *iova_tree_find_address(const IOVATree *tree, hwaddr iova)
{
- DMAMap map = { .iova = iova, .size = 0 };
+ const DMAMap map = { .iova = iova, .size = 0 };
return iova_tree_find(tree, &map);
}
@@ -60,7 +60,7 @@ static inline void iova_tree_insert_internal(GTree *gtree, DMAMap *range)
g_tree_insert(gtree, range, range);
}
-int iova_tree_insert(IOVATree *tree, DMAMap *map)
+int iova_tree_insert(IOVATree *tree, const DMAMap *map)
{
DMAMap *new;
@@ -96,9 +96,9 @@ void iova_tree_foreach(IOVATree *tree, iova_tree_iterator iterator)
g_tree_foreach(tree->tree, iova_tree_traverse, iterator);
}
-int iova_tree_remove(IOVATree *tree, DMAMap *map)
+int iova_tree_remove(IOVATree *tree, const DMAMap *map)
{
- DMAMap *overlap;
+ const DMAMap *overlap;
while ((overlap = iova_tree_find(tree, map))) {
g_tree_remove(tree->tree, overlap);