Merge tag 'pull-10.0-gdb-plugins-doc-updates-170125-1' of https://gitlab.com/stsquad/qemu into staging

semihosting, plugin and doc updates:

  - log a guest_error for failed semihosting open()
  - clean up semihosting includes to reduce build duplication
  - re-factor misc device initialisation to fail with &error_exit
  - propagate Error * to gdbserver_start sub-functions
  - fix 32-bit build of plugins and re-enable by default
  - ensure IRQs don't preempt io recompiled instructions
  - remove usage of gcc_struct to enable clang builds
  - enable clang/lld to build plugins on windows
  - various small kdoc typo fixes
  - add perl scripts to editorconfig
  - remove unused field from MemoryRegion
  - make kdoc script a dependency so doc rebuilds get triggered
  - expand developer documentation:
    - notes on git-publish
    - describe usage of b4
    - setting up build dependencies
    - codebase layout
    - add a glossary of common terms
  -  optimise the windows ndis script

# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmeKO8sACgkQ+9DbCVqe
# KkTbBQf9HRlspCl2r5a8K9O1ymylKiZ653OBWMStGTQ8xPXeLDFhT+ION34VBgBh
# LXHEcjIHn24cN2s1BO5+xJs0nzqYe7UEAK6JQmdX3/HEuf8VmaVslvhm+nCWKoIL
# JQbsHno92wh6vvTWQu53zijEuG5HdBseWiwQKHbE1oSRc2CikG70o902AL9zXAsp
# mpUYWxUmWwg5uQATztp4XfylJBcSX3SiVgv22jXLqBj9drXPftl/E33fcWXxTj5f
# AM3kz9fxaCfo5+znmYw3R1tT/Hv52Q6hW+oNAm34XeWp1/+ho27QMRrpIi/dpdwX
# mCbvJwI75sCnD91p9NW7vZIYZJKsLg==
# =SLCY
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 17 Jan 2025 06:15:23 EST
# gpg:                using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 6685 AE99 E751 67BC AFC8  DF35 FBD0 DB09 5A9E 2A44

* tag 'pull-10.0-gdb-plugins-doc-updates-170125-1' of https://gitlab.com/stsquad/qemu: (37 commits)
  scripts/nsis.py: Run dependency check for each DLL file only once
  docs: add a glossary
  docs/devel: add a codebase section
  docs/devel: add information on how to setup build environments
  docs/devel: add b4 for patch retrieval
  docs/devel: add git-publish for patch submitting
  docs/sphinx: include kernel-doc script as a dependency
  include/exec: remove warning_printed from MemoryRegion
  include/exec: fix some copy and paste errors in kdoc
  tests/qtest: fix some copy and paste errors in kdoc
  editorconfig: update for perl scripts
  plugins: fix kdoc annotation
  plugins: enable linking with clang/lld
  docs/devel/style: add a section about bitfield, and disallow them for packed structures
  win32: remove usage of attribute gcc_struct
  accel/tcg: also suppress asynchronous IRQs for cpu_io_recompile
  configure: reenable plugins by default for 32-bit hosts
  contrib/plugins/hotpages: fix 32-bit build
  contrib/plugins/hwprofile: fix 32-bit build
  contrib/plugins/cflow: fix 32-bit build
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi
2025-01-17 10:13:07 -05:00
68 changed files with 1035 additions and 226 deletions
+13
View File
@@ -47,3 +47,16 @@ emacs_mode = glsl
[*.json]
indent_style = space
emacs_mode = python
# by default follow QEMU's style
[*.pl]
indent_style = space
indent_size = 4
emacs_mode = perl
# but user kernel "style" for imported scripts
[scripts/{kernel-doc,get_maintainer.pl,checkpatch.pl}]
indent_style = tab
indent_size = 8
emacs_mode = perl
+4 -1
View File
@@ -72,11 +72,14 @@ R: Markus Armbruster <armbru@redhat.com>
R: Philippe Mathieu-Daudé <philmd@linaro.org>
W: https://www.qemu.org/docs/master/devel/index.html
S: Odd Fixes
F: docs/devel/style.rst
F: docs/devel/build-environment.rst
F: docs/devel/code-of-conduct.rst
F: docs/devel/codebase.rst
F: docs/devel/conflict-resolution.rst
F: docs/devel/style.rst
F: docs/devel/submitting-a-patch.rst
F: docs/devel/submitting-a-pull-request.rst
F: docs/glossary.rst
Responsible Disclosure, Reporting Security Issues
-------------------------------------------------
+3 -2
View File
@@ -633,9 +633,10 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
* Exit the loop and potentially generate a new TB executing the
* just the I/O insns. We also limit instrumentation to memory
* operations only (which execute after completion) so we don't
* double instrument the instruction.
* double instrument the instruction. Also don't let an IRQ sneak
* in before we execute it.
*/
cpu->cflags_next_tb = curr_cflags(cpu) | CF_MEMI_ONLY | n;
cpu->cflags_next_tb = curr_cflags(cpu) | CF_MEMI_ONLY | CF_NOIRQ | n;
if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
vaddr pc = cpu->cc->get_pc(cpu);
+1 -1
View File
@@ -628,7 +628,7 @@ int main(int argc, char **argv)
target_cpu_init(env, regs);
if (gdbstub) {
gdbserver_start(gdbstub);
gdbserver_start(gdbstub, &error_fatal);
gdb_handlesig(cpu, 0, NULL, NULL, 0);
}
cpu_loop(env);
Vendored
+1 -20
View File
@@ -528,25 +528,6 @@ case "$cpu" in
;;
esac
# Now we have our CPU_CFLAGS we can check if we are targeting a 32 or
# 64 bit host.
check_64bit_host() {
cat > $TMPC <<EOF
#if __SIZEOF_POINTER__ != 8
#error not 64 bit system
#endif
int main(void) { return 0; }
EOF
compile_object "$1"
}
if check_64bit_host "$CPU_CFLAGS"; then
host_bits=64
else
host_bits=32
fi
if test -n "$host_arch" && {
! test -d "$source_path/linux-user/include/host/$host_arch" ||
! test -d "$source_path/common-user/host/$host_arch"; }; then
@@ -1072,7 +1053,7 @@ if test "$static" = "yes" ; then
fi
plugins="no"
fi
if test "$plugins" != "no" && test $host_bits -eq 64; then
if test "$plugins" != "no"; then
if has_meson_option "-Dtcg_interpreter=true"; then
plugins="no"
else
+6 -12
View File
@@ -208,7 +208,7 @@ static int fifo_get_first_block(Cache *cache, int set)
static void fifo_update_on_miss(Cache *cache, int set, int blk_idx)
{
GQueue *q = cache->sets[set].fifo_queue;
g_queue_push_head(q, GINT_TO_POINTER(blk_idx));
g_queue_push_head(q, (gpointer)(intptr_t) blk_idx);
}
static void fifo_destroy(Cache *cache)
@@ -471,13 +471,8 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
n_insns = qemu_plugin_tb_n_insns(tb);
for (i = 0; i < n_insns; i++) {
struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i);
uint64_t effective_addr;
if (sys) {
effective_addr = (uint64_t) qemu_plugin_insn_haddr(insn);
} else {
effective_addr = (uint64_t) qemu_plugin_insn_vaddr(insn);
}
uint64_t effective_addr = sys ? (uintptr_t) qemu_plugin_insn_haddr(insn) :
qemu_plugin_insn_vaddr(insn);
/*
* Instructions might get translated multiple times, we do not create
@@ -485,14 +480,13 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
* entry from the hash table and register it for the callback again.
*/
g_mutex_lock(&hashtable_lock);
data = g_hash_table_lookup(miss_ht, GUINT_TO_POINTER(effective_addr));
data = g_hash_table_lookup(miss_ht, &effective_addr);
if (data == NULL) {
data = g_new0(InsnData, 1);
data->disas_str = qemu_plugin_insn_disas(insn);
data->symbol = qemu_plugin_insn_symbol(insn);
data->addr = effective_addr;
g_hash_table_insert(miss_ht, GUINT_TO_POINTER(effective_addr),
(gpointer) data);
g_hash_table_insert(miss_ht, &data->addr, data);
}
g_mutex_unlock(&hashtable_lock);
@@ -853,7 +847,7 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info,
qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
qemu_plugin_register_atexit_cb(id, plugin_exit, NULL);
miss_ht = g_hash_table_new_full(NULL, g_direct_equal, NULL, insn_free);
miss_ht = g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, insn_free);
return 0;
}
+11 -6
View File
@@ -76,6 +76,8 @@ typedef struct {
/* We use this to track the current execution state */
typedef struct {
/* address of current translated block */
uint64_t tb_pc;
/* address of end of block */
uint64_t end_block;
/* next pc after end of block */
@@ -85,6 +87,7 @@ typedef struct {
} VCPUScoreBoard;
/* descriptors for accessing the above scoreboard */
static qemu_plugin_u64 tb_pc;
static qemu_plugin_u64 end_block;
static qemu_plugin_u64 pc_after_block;
static qemu_plugin_u64 last_pc;
@@ -189,10 +192,11 @@ static void plugin_exit(qemu_plugin_id_t id, void *p)
static void plugin_init(void)
{
g_mutex_init(&node_lock);
nodes = g_hash_table_new(NULL, g_direct_equal);
nodes = g_hash_table_new(g_int64_hash, g_int64_equal);
state = qemu_plugin_scoreboard_new(sizeof(VCPUScoreBoard));
/* score board declarations */
tb_pc = qemu_plugin_scoreboard_u64_in_struct(state, VCPUScoreBoard, tb_pc);
end_block = qemu_plugin_scoreboard_u64_in_struct(state, VCPUScoreBoard,
end_block);
pc_after_block = qemu_plugin_scoreboard_u64_in_struct(state, VCPUScoreBoard,
@@ -215,10 +219,10 @@ static NodeData *fetch_node(uint64_t addr, bool create_if_not_found)
NodeData *node = NULL;
g_mutex_lock(&node_lock);
node = (NodeData *) g_hash_table_lookup(nodes, (gconstpointer) addr);
node = (NodeData *) g_hash_table_lookup(nodes, &addr);
if (!node && create_if_not_found) {
node = create_node(addr);
g_hash_table_insert(nodes, (gpointer) addr, (gpointer) node);
g_hash_table_insert(nodes, &node->addr, node);
}
g_mutex_unlock(&node_lock);
return node;
@@ -234,7 +238,7 @@ static void vcpu_tb_branched_exec(unsigned int cpu_index, void *udata)
uint64_t lpc = qemu_plugin_u64_get(last_pc, cpu_index);
uint64_t ebpc = qemu_plugin_u64_get(end_block, cpu_index);
uint64_t npc = qemu_plugin_u64_get(pc_after_block, cpu_index);
uint64_t pc = GPOINTER_TO_UINT(udata);
uint64_t pc = qemu_plugin_u64_get(tb_pc, cpu_index);
/* return early for address 0 */
if (!lpc) {
@@ -305,10 +309,11 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
* handle both early block exits and normal branches in the
* callback if we hit it.
*/
gpointer udata = GUINT_TO_POINTER(pc);
qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu(
tb, QEMU_PLUGIN_INLINE_STORE_U64, tb_pc, pc);
qemu_plugin_register_vcpu_tb_exec_cond_cb(
tb, vcpu_tb_branched_exec, QEMU_PLUGIN_CB_NO_REGS,
QEMU_PLUGIN_COND_NE, pc_after_block, pc, udata);
QEMU_PLUGIN_COND_NE, pc_after_block, pc, NULL);
/*
* Now we can set start/end for this block so the next block can
+24 -5
View File
@@ -29,7 +29,7 @@ static guint64 limit = 20;
*
* The internals of the TCG are not exposed to plugins so we can only
* get the starting PC for each block. We cheat this slightly by
* xor'ing the number of instructions to the hash to help
* checking the number of instructions as well to help
* differentiate.
*/
typedef struct {
@@ -50,6 +50,20 @@ static gint cmp_exec_count(gconstpointer a, gconstpointer b)
return count_a > count_b ? -1 : 1;
}
static guint exec_count_hash(gconstpointer v)
{
const ExecCount *e = v;
return e->start_addr ^ e->insns;
}
static gboolean exec_count_equal(gconstpointer v1, gconstpointer v2)
{
const ExecCount *ea = v1;
const ExecCount *eb = v2;
return (ea->start_addr == eb->start_addr) &&
(ea->insns == eb->insns);
}
static void exec_count_free(gpointer key, gpointer value, gpointer user_data)
{
ExecCount *cnt = value;
@@ -91,7 +105,7 @@ static void plugin_exit(qemu_plugin_id_t id, void *p)
static void plugin_init(void)
{
hotblocks = g_hash_table_new(NULL, g_direct_equal);
hotblocks = g_hash_table_new(exec_count_hash, exec_count_equal);
}
static void vcpu_tb_exec(unsigned int cpu_index, void *udata)
@@ -111,10 +125,15 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
ExecCount *cnt;
uint64_t pc = qemu_plugin_tb_vaddr(tb);
size_t insns = qemu_plugin_tb_n_insns(tb);
uint64_t hash = pc ^ insns;
g_mutex_lock(&lock);
cnt = (ExecCount *) g_hash_table_lookup(hotblocks, (gconstpointer) hash);
{
ExecCount e;
e.start_addr = pc;
e.insns = insns;
cnt = (ExecCount *) g_hash_table_lookup(hotblocks, &e);
}
if (cnt) {
cnt->trans_count++;
} else {
@@ -123,7 +142,7 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
cnt->trans_count = 1;
cnt->insns = insns;
cnt->exec_count = qemu_plugin_scoreboard_new(sizeof(uint64_t));
g_hash_table_insert(hotblocks, (gpointer) hash, (gpointer) cnt);
g_hash_table_insert(hotblocks, cnt, cnt);
}
g_mutex_unlock(&lock);
+3 -3
View File
@@ -103,7 +103,7 @@ static void plugin_exit(qemu_plugin_id_t id, void *p)
static void plugin_init(void)
{
page_mask = (page_size - 1);
pages = g_hash_table_new(NULL, g_direct_equal);
pages = g_hash_table_new(g_int64_hash, g_int64_equal);
}
static void vcpu_haddr(unsigned int cpu_index, qemu_plugin_meminfo_t meminfo,
@@ -130,12 +130,12 @@ static void vcpu_haddr(unsigned int cpu_index, qemu_plugin_meminfo_t meminfo,
page &= ~page_mask;
g_mutex_lock(&lock);
count = (PageCounters *) g_hash_table_lookup(pages, GUINT_TO_POINTER(page));
count = (PageCounters *) g_hash_table_lookup(pages, &page);
if (!count) {
count = g_new0(PageCounters, 1);
count->page_address = page;
g_hash_table_insert(pages, GUINT_TO_POINTER(page), (gpointer) count);
g_hash_table_insert(pages, &count->page_address, count);
}
if (qemu_plugin_mem_is_store(meminfo)) {
count->writes++;
+4 -3
View File
@@ -253,6 +253,8 @@ static struct qemu_plugin_scoreboard *find_counter(
int i;
uint64_t *cnt = NULL;
uint32_t opcode = 0;
/* if opcode is greater than 32 bits, we should refactor insn hash table. */
G_STATIC_ASSERT(sizeof(opcode) == sizeof(uint32_t));
InsnClassExecCount *class = NULL;
/*
@@ -284,7 +286,7 @@ static struct qemu_plugin_scoreboard *find_counter(
g_mutex_lock(&lock);
icount = (InsnExecCount *) g_hash_table_lookup(insns,
GUINT_TO_POINTER(opcode));
(gpointer)(intptr_t) opcode);
if (!icount) {
icount = g_new0(InsnExecCount, 1);
@@ -295,8 +297,7 @@ static struct qemu_plugin_scoreboard *find_counter(
qemu_plugin_scoreboard_new(sizeof(uint64_t));
icount->count = qemu_plugin_scoreboard_u64(score);
g_hash_table_insert(insns, GUINT_TO_POINTER(opcode),
(gpointer) icount);
g_hash_table_insert(insns, (gpointer)(intptr_t) opcode, icount);
}
g_mutex_unlock(&lock);
+16 -11
View File
@@ -43,6 +43,8 @@ typedef struct {
static GMutex lock;
static GHashTable *devices;
static struct qemu_plugin_scoreboard *source_pc_scoreboard;
static qemu_plugin_u64 source_pc;
/* track the access pattern to a piece of HW */
static bool pattern;
@@ -159,7 +161,7 @@ static DeviceCounts *new_count(const char *name, uint64_t base)
count->name = name;
count->base = base;
if (pattern || source) {
count->detail = g_hash_table_new(NULL, NULL);
count->detail = g_hash_table_new(g_int64_hash, g_int64_equal);
}
g_hash_table_insert(devices, (gpointer) name, count);
return count;
@@ -169,7 +171,7 @@ static IOLocationCounts *new_location(GHashTable *table, uint64_t off_or_pc)
{
IOLocationCounts *loc = g_new0(IOLocationCounts, 1);
loc->off_or_pc = off_or_pc;
g_hash_table_insert(table, (gpointer) off_or_pc, loc);
g_hash_table_insert(table, &loc->off_or_pc, loc);
return loc;
}
@@ -224,12 +226,12 @@ static void vcpu_haddr(unsigned int cpu_index, qemu_plugin_meminfo_t meminfo,
/* either track offsets or source of access */
if (source) {
off = (uint64_t) udata;
off = qemu_plugin_u64_get(source_pc, cpu_index);
}
if (pattern || source) {
IOLocationCounts *io_count = g_hash_table_lookup(counts->detail,
(gpointer) off);
&off);
if (!io_count) {
io_count = new_location(counts->detail, off);
}
@@ -247,10 +249,14 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
for (i = 0; i < n; i++) {
struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i);
gpointer udata = (gpointer) (source ? qemu_plugin_insn_vaddr(insn) : 0);
if (source) {
uint64_t pc = qemu_plugin_insn_vaddr(insn);
qemu_plugin_register_vcpu_mem_inline_per_vcpu(
insn, rw, QEMU_PLUGIN_INLINE_STORE_U64,
source_pc, pc);
}
qemu_plugin_register_vcpu_mem_cb(insn, vcpu_haddr,
QEMU_PLUGIN_CB_NO_REGS,
rw, udata);
QEMU_PLUGIN_CB_NO_REGS, rw, NULL);
}
}
@@ -306,10 +312,9 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info,
return -1;
}
/* Just warn about overflow */
if (info->system.smp_vcpus > 64 ||
info->system.max_vcpus > 64) {
fprintf(stderr, "hwprofile: can only track up to 64 CPUs\n");
if (source) {
source_pc_scoreboard = qemu_plugin_scoreboard_new(sizeof(uint64_t));
source_pc = qemu_plugin_scoreboard_u64(source_pc_scoreboard);
}
plugin_init();
+1 -1
View File
@@ -12,7 +12,7 @@ if get_option('plugins')
t += shared_module(i, files(i + '.c') + 'win32_linker.c',
include_directories: '../../include/qemu',
link_depends: [win32_qemu_plugin_api_lib],
link_args: ['-Lplugins', '-lqemu_plugin_api'],
link_args: win32_qemu_plugin_api_link_flags,
dependencies: glib)
else
t += shared_module(i, files(i + '.c'),
+27 -21
View File
@@ -21,9 +21,11 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
/* Scoreboard to track executed instructions count */
typedef struct {
uint64_t insn_count;
uint64_t current_pc;
} InstructionsCount;
static struct qemu_plugin_scoreboard *insn_count_sb;
static qemu_plugin_u64 insn_count;
static qemu_plugin_u64 current_pc;
static uint64_t icount;
static int icount_exit_code;
@@ -34,6 +36,11 @@ static bool exit_on_address;
/* Map trigger addresses to exit code */
static GHashTable *addrs_ht;
typedef struct {
uint64_t exit_addr;
int exit_code;
} ExitInfo;
static void exit_emulation(int return_code, char *message)
{
qemu_plugin_outs(message);
@@ -43,23 +50,18 @@ static void exit_emulation(int return_code, char *message)
static void exit_icount_reached(unsigned int cpu_index, void *udata)
{
uint64_t insn_vaddr = GPOINTER_TO_UINT(udata);
uint64_t insn_vaddr = qemu_plugin_u64_get(current_pc, cpu_index);
char *msg = g_strdup_printf("icount reached at 0x%" PRIx64 ", exiting\n",
insn_vaddr);
exit_emulation(icount_exit_code, msg);
}
static void exit_address_reached(unsigned int cpu_index, void *udata)
{
uint64_t insn_vaddr = GPOINTER_TO_UINT(udata);
char *msg = g_strdup_printf("0x%" PRIx64 " reached, exiting\n", insn_vaddr);
int exit_code;
exit_code = GPOINTER_TO_INT(
g_hash_table_lookup(addrs_ht, GUINT_TO_POINTER(insn_vaddr)));
exit_emulation(exit_code, msg);
ExitInfo *ei = udata;
g_assert(ei);
char *msg = g_strdup_printf("0x%" PRIx64 " reached, exiting\n", ei->exit_addr);
exit_emulation(ei->exit_code, msg);
}
static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
@@ -67,23 +69,25 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
size_t tb_n = qemu_plugin_tb_n_insns(tb);
for (size_t i = 0; i < tb_n; i++) {
struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i);
gpointer insn_vaddr = GUINT_TO_POINTER(qemu_plugin_insn_vaddr(insn));
uint64_t insn_vaddr = qemu_plugin_insn_vaddr(insn);
if (exit_on_icount) {
/* Increment and check scoreboard for each instruction */
qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(
insn, QEMU_PLUGIN_INLINE_ADD_U64, insn_count, 1);
qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(
insn, QEMU_PLUGIN_INLINE_STORE_U64, current_pc, insn_vaddr);
qemu_plugin_register_vcpu_insn_exec_cond_cb(
insn, exit_icount_reached, QEMU_PLUGIN_CB_NO_REGS,
QEMU_PLUGIN_COND_EQ, insn_count, icount + 1, insn_vaddr);
QEMU_PLUGIN_COND_EQ, insn_count, icount + 1, NULL);
}
if (exit_on_address) {
if (g_hash_table_contains(addrs_ht, insn_vaddr)) {
ExitInfo *ei = g_hash_table_lookup(addrs_ht, &insn_vaddr);
if (ei) {
/* Exit triggered by address */
qemu_plugin_register_vcpu_insn_exec_cb(
insn, exit_address_reached, QEMU_PLUGIN_CB_NO_REGS,
insn_vaddr);
insn, exit_address_reached, QEMU_PLUGIN_CB_NO_REGS, ei);
}
}
}
@@ -99,11 +103,13 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
const qemu_info_t *info, int argc,
char **argv)
{
addrs_ht = g_hash_table_new(NULL, g_direct_equal);
addrs_ht = g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, g_free);
insn_count_sb = qemu_plugin_scoreboard_new(sizeof(InstructionsCount));
insn_count = qemu_plugin_scoreboard_u64_in_struct(
insn_count_sb, InstructionsCount, insn_count);
current_pc = qemu_plugin_scoreboard_u64_in_struct(
insn_count_sb, InstructionsCount, current_pc);
for (int i = 0; i < argc; i++) {
char *opt = argv[i];
@@ -124,13 +130,13 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
exit_on_icount = true;
} else if (g_strcmp0(tokens[0], "addr") == 0) {
g_auto(GStrv) addr_tokens = g_strsplit(tokens[1], ":", 2);
uint64_t exit_addr = g_ascii_strtoull(addr_tokens[0], NULL, 0);
int exit_code = 0;
ExitInfo *ei = g_malloc(sizeof(ExitInfo));
ei->exit_addr = g_ascii_strtoull(addr_tokens[0], NULL, 0);
ei->exit_code = 0;
if (addr_tokens[1]) {
exit_code = g_ascii_strtoull(addr_tokens[1], NULL, 0);
ei->exit_code = g_ascii_strtoull(addr_tokens[1], NULL, 0);
}
g_hash_table_insert(addrs_ht, GUINT_TO_POINTER(exit_addr),
GINT_TO_POINTER(exit_code));
g_hash_table_insert(addrs_ht, &ei->exit_addr, ei);
exit_on_address = true;
} else {
fprintf(stderr, "option parsing failed: %s\n", opt);
+3 -1
View File
@@ -29,6 +29,9 @@ The `Repology`_ site is a useful resource to identify
currently shipped versions of software in various operating systems,
though it does not cover all distros listed below.
You can find how to install build dependencies for different systems on the
:ref:`setup-build-env` page.
Supported host architectures
----------------------------
@@ -130,7 +133,6 @@ Optional build dependencies
cross compilation using ``docker`` or ``podman``, or to use pre-built
binaries distributed with QEMU.
Windows
-------
+2
View File
@@ -176,6 +176,8 @@ for that architecture.
- System
- Tensilica ISS SIMCALL
.. _tcg-plugins:
TCG Plugins
-----------
+118
View File
@@ -0,0 +1,118 @@
.. _setup-build-env:
Setup build environment
=======================
QEMU uses a lot of dependencies on the host system. glib2 is used everywhere in
the code base, and most of the other dependencies are optional.
We present here simple instructions to enable native builds on most popular
systems.
You can find additional instructions on `QEMU wiki <https://wiki.qemu.org/>`_:
- `Linux <https://wiki.qemu.org/Hosts/Linux>`_
- `MacOS <https://wiki.qemu.org/Hosts/Mac>`_
- `Windows <https://wiki.qemu.org/Hosts/W32>`_
- `BSD <https://wiki.qemu.org/Hosts/BSD>`_
Note: Installing dependencies using your package manager build dependencies may
miss out on deps that have been newly introduced in qemu.git. In more, it misses
deps the distribution has decided to exclude.
Linux
-----
Fedora
++++++
::
sudo dnf update && sudo dnf builddep qemu
Debian/Ubuntu
+++++++++++++
You first need to enable `Sources List <https://wiki.debian.org/SourcesList>`_.
Then, use apt to install dependencies:
::
sudo apt update && sudo apt build-dep qemu
MacOS
-----
You first need to install `Homebrew <https://brew.sh/>`_. Then, use it to
install dependencies:
::
brew update && brew install $(brew deps --include-build qemu)
Windows
-------
You first need to install `MSYS2 <https://www.msys2.org/>`_.
MSYS2 offers `different environments <https://www.msys2.org/docs/environments/>`_.
x86_64 environments are based on GCC, while aarch64 is based on Clang.
We recommend to use MINGW64 for windows-x86_64 and CLANGARM64 for windows-aarch64
(only available on windows-aarch64 hosts).
Then, you can open a windows shell, and enter msys2 env using:
::
c:/msys64/msys2_shell.cmd -defterm -here -no-start -mingw64
# Replace -ucrt64 by -clangarm64 or -ucrt64 for other environments.
MSYS2 package manager does not offer a built-in way to install build
dependencies. You can start with this list of packages using pacman:
Note: Dependencies need to be installed again if you use a different MSYS2
environment.
::
# update MSYS2 itself, you need to reopen your shell at the end.
pacman -Syu
pacman -S \
base-devel binutils bison diffutils flex git grep make sed \
${MINGW_PACKAGE_PREFIX}-toolchain \
${MINGW_PACKAGE_PREFIX}-glib2 \
${MINGW_PACKAGE_PREFIX}-gtk3 \
${MINGW_PACKAGE_PREFIX}-libnfs \
${MINGW_PACKAGE_PREFIX}-libssh \
${MINGW_PACKAGE_PREFIX}-ninja \
${MINGW_PACKAGE_PREFIX}-pixman \
${MINGW_PACKAGE_PREFIX}-pkgconf \
${MINGW_PACKAGE_PREFIX}-python \
${MINGW_PACKAGE_PREFIX}-SDL2 \
${MINGW_PACKAGE_PREFIX}-zstd
If you want to install all dependencies, it's possible to use recipe used to
build QEMU in MSYS2 itself.
::
pacman -S wget
wget https://raw.githubusercontent.com/msys2/MINGW-packages/refs/heads/master/mingw-w64-qemu/PKGBUILD
# Some packages may be missing for your environment, installation will still
# be done though.
makepkg -s PKGBUILD || true
Build on windows-aarch64
++++++++++++++++++++++++
When trying to cross compile meson for x86_64 using UCRT64 or MINGW64 env,
configure will run into an error because the cpu detected is not correct.
Meson detects x86_64 processes emulated, so you need to manually set the cpu,
and force a cross compilation (with empty prefix).
::
./configure --cpu=x86_64 --cross-prefix=
+220
View File
@@ -0,0 +1,220 @@
========
Codebase
========
This section presents the various parts of QEMU and how the codebase is
organized.
Beyond giving succint descriptions, the goal is to offer links to various
parts of the documentation/codebase.
Subsystems
----------
An exhaustive list of subsystems and associated files can be found in the
`MAINTAINERS <https://gitlab.com/qemu-project/qemu/-/blob/master/MAINTAINERS>`_
file.
Some of the main QEMU subsystems are:
- `Accelerators<Accelerators>`
- Block devices and `disk images<disk images>` support
- `CI<ci>` and `Tests<testing>`
- `Devices<device-emulation>` & Board models
- `Documentation <documentation-root>`
- `GDB support<GDB usage>`
- `Migration<migration>`
- `Monitor<QEMU monitor>`
- :ref:`QOM (QEMU Object Model)<qom>`
- `System mode<System emulation>`
- :ref:`TCG (Tiny Code Generator)<tcg>`
- `User mode<user-mode>` (`Linux<linux-user-mode>` & `BSD<bsd-user-mode>`)
- User Interfaces
More documentation on QEMU subsystems can be found on :ref:`internal-subsystem`
page.
The Grand tour
--------------
We present briefly here what every folder in the top directory of the codebase
contains. Hop on!
The folder name links here will take you to that folder in our gitlab
repository. Other links will take you to more detailed documentation for that
subsystem, where we have it. Unfortunately not every subsystem has documentation
yet, so sometimes the source code is all you have.
* `accel <https://gitlab.com/qemu-project/qemu/-/tree/master/accel>`_:
Infrastructure and architecture agnostic code related to the various
`accelerators <Accelerators>` supported by QEMU
(TCG, KVM, hvf, whpx, xen, nvmm).
Contains interfaces for operations that will be implemented per
`target <https://gitlab.com/qemu-project/qemu/-/tree/master/target>`_.
* `audio <https://gitlab.com/qemu-project/qemu/-/tree/master/audio>`_:
Audio (host) support.
* `authz <https://gitlab.com/qemu-project/qemu/-/tree/master/authz>`_:
`QEMU Authorization framework<client authorization>`.
* `backends <https://gitlab.com/qemu-project/qemu/-/tree/master/backends>`_:
Various backends that are used to access resources on the host (e.g. for
random number generation, memory backing or cryptographic functions).
* `block <https://gitlab.com/qemu-project/qemu/-/tree/master/block>`_:
Block devices and `image formats<disk images>` implementation.
* `bsd-user <https://gitlab.com/qemu-project/qemu/-/tree/master/bsd-user>`_:
`BSD User mode<bsd-user-mode>`.
* build: Where the code built goes by default. You can tell the QEMU build
system to put the built code anywhere else you like.
* `chardev <https://gitlab.com/qemu-project/qemu/-/tree/master/chardev>`_:
Various backends used by char devices.
* `common-user <https://gitlab.com/qemu-project/qemu/-/tree/master/common-user>`_:
User-mode assembly code for dealing with signals occuring during syscalls.
* `configs <https://gitlab.com/qemu-project/qemu/-/tree/master/configs>`_:
Makefiles defining configurations to build QEMU.
* `contrib <https://gitlab.com/qemu-project/qemu/-/tree/master/contrib>`_:
Community contributed devices/plugins/tools.
* `crypto <https://gitlab.com/qemu-project/qemu/-/tree/master/crypto>`_:
Cryptographic algorithms used in QEMU.
* `disas <https://gitlab.com/qemu-project/qemu/-/tree/master/disas>`_:
Disassembly functions used by QEMU target code.
* `docs <https://gitlab.com/qemu-project/qemu/-/tree/master/docs>`_:
QEMU Documentation.
* `dump <https://gitlab.com/qemu-project/qemu/-/tree/master/dump>`_:
Code to dump memory of a running VM.
* `ebpf <https://gitlab.com/qemu-project/qemu/-/tree/master/ebpf>`_:
eBPF program support in QEMU. `virtio-net RSS<ebpf-rss>` uses it.
* `fpu <https://gitlab.com/qemu-project/qemu/-/tree/master/fpu>`_:
Floating-point software emulation.
* `fsdev <https://gitlab.com/qemu-project/qemu/-/tree/master/fsdev>`_:
`VirtFS <https://www.linux-kvm.org/page/VirtFS>`_ support.
* `gdbstub <https://gitlab.com/qemu-project/qemu/-/tree/master/gdbstub>`_:
`GDB <GDB usage>` support.
* `gdb-xml <https://gitlab.com/qemu-project/qemu/-/tree/master/gdb-xml>`_:
Set of XML files describing architectures and used by `gdbstub <GDB usage>`.
* `host <https://gitlab.com/qemu-project/qemu/-/tree/master/host>`_:
Various architecture specific header files (crypto, atomic, memory
operations).
* `linux-headers <https://gitlab.com/qemu-project/qemu/-/tree/master/linux-headers>`_:
A subset of headers imported from Linux kernel and used for implementing
KVM support and user-mode.
* `linux-user <https://gitlab.com/qemu-project/qemu/-/tree/master/linux-user>`_:
`User mode <user-mode>` implementation. Contains one folder per target
architecture.
* `.gitlab-ci.d <https://gitlab.com/qemu-project/qemu/-/tree/master/.gitlab-ci.d>`_:
`CI <ci>` yaml and scripts.
* `include <https://gitlab.com/qemu-project/qemu/-/tree/master/include>`_:
All headers associated to different subsystems in QEMU. The hierachy used
mirrors source code organization and naming.
* `hw <https://gitlab.com/qemu-project/qemu/-/tree/master/hw>`_:
`Devices <device-emulation>` and boards emulation. Devices are categorized by
type/protocol/architecture and located in associated subfolder.
* `io <https://gitlab.com/qemu-project/qemu/-/tree/master/io>`_:
QEMU `I/O channels <https://lists.gnu.org/archive/html/qemu-devel/2015-11/msg04208.html>`_.
* `libdecnumber <https://gitlab.com/qemu-project/qemu/-/tree/master/libdecnumber>`_:
Import of gcc library, used to implement decimal number arithmetic.
* `migration <https://gitlab.com/qemu-project/qemu/-/tree/master/migration>`__:
`Migration framework <migration>`.
* `monitor <https://gitlab.com/qemu-project/qemu/-/tree/master/monitor>`_:
`Monitor <QEMU monitor>` implementation (HMP & QMP).
* `nbd <https://gitlab.com/qemu-project/qemu/-/tree/master/nbd>`_:
QEMU `NBD (Network Block Device) <nbd>` server.
* `net <https://gitlab.com/qemu-project/qemu/-/tree/master/net>`_:
Network (host) support.
* `pc-bios <https://gitlab.com/qemu-project/qemu/-/tree/master/pc-bios>`_:
Contains pre-built firmware binaries and boot images, ready to use in
QEMU without compilation.
* `plugins <https://gitlab.com/qemu-project/qemu/-/tree/master/plugins>`_:
:ref:`TCG plugins <tcg-plugins>` core implementation. Plugins can be found in
`tests <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/tcg/plugins>`__
and `contrib <https://gitlab.com/qemu-project/qemu/-/tree/master/contrib/plugins>`__
folders.
* `po <https://gitlab.com/qemu-project/qemu/-/tree/master/po>`_:
Translation files.
* `python <https://gitlab.com/qemu-project/qemu/-/tree/master/python>`_:
Python part of our build/test system.
* `qapi <https://gitlab.com/qemu-project/qemu/-/tree/master/qapi>`_:
`QAPI <qapi>` implementation.
* `qobject <https://gitlab.com/qemu-project/qemu/-/tree/master/qobject>`_:
QEMU Object implementation.
* `qga <https://gitlab.com/qemu-project/qemu/-/tree/master/qga>`_:
QEMU `Guest agent <qemu-ga>` implementation.
* `qom <https://gitlab.com/qemu-project/qemu/-/tree/master/qom>`_:
QEMU :ref:`Object model <qom>` implementation, with monitor associated commands.
* `replay <https://gitlab.com/qemu-project/qemu/-/tree/master/replay>`_:
QEMU :ref:`Record/replay <replay>` implementation.
* `roms <https://gitlab.com/qemu-project/qemu/-/tree/master/roms>`_:
Contains source code for various firmware and ROMs, which can be compiled if
custom or updated versions are needed.
* `rust <https://gitlab.com/qemu-project/qemu/-/tree/master/rust>`_:
Rust integration in QEMU. It contains the new interfaces defined and
associated devices using it.
* `scripts <https://gitlab.com/qemu-project/qemu/-/tree/master/scripts>`_:
Collection of scripts used in build and test systems, and various
tools for QEMU codebase and execution traces.
* `scsi <https://gitlab.com/qemu-project/qemu/-/tree/master/scsi>`_:
Code related to SCSI support, used by SCSI devices.
* `semihosting <https://gitlab.com/qemu-project/qemu/-/tree/master/semihosting>`_:
QEMU `Semihosting <Semihosting>` implementation.
* `stats <https://gitlab.com/qemu-project/qemu/-/tree/master/stats>`_:
`Monitor <QEMU monitor>` stats commands implementation.
* `storage-daemon <https://gitlab.com/qemu-project/qemu/-/tree/master/storage-daemon>`_:
QEMU `Storage daemon <storage-daemon>` implementation.
* `stubs <https://gitlab.com/qemu-project/qemu/-/tree/master/stubs>`_:
Various stubs (empty functions) used to compile QEMU with specific
configurations.
* `subprojects <https://gitlab.com/qemu-project/qemu/-/tree/master/subprojects>`_:
QEMU submodules used by QEMU build system.
* `system <https://gitlab.com/qemu-project/qemu/-/tree/master/system>`_:
QEMU `system mode <System emulation>` implementation (cpu, mmu, boot support).
* `target <https://gitlab.com/qemu-project/qemu/-/tree/master/target>`_:
Contains code for all target architectures supported (one subfolder
per arch). For every architecture, you can find accelerator specific
implementations.
* `tcg <https://gitlab.com/qemu-project/qemu/-/tree/master/tcg>`_:
:ref:`TCG <tcg>` related code.
Contains one subfolder per host supported architecture.
* `tests <https://gitlab.com/qemu-project/qemu/-/tree/master/tests>`_:
QEMU `test <testing>` suite
- `avocado <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/avocado>`_:
Functional tests booting full VM using `Avocado framework <checkavocado-ref>`.
Those tests will be transformed and moved into
`tests/functional <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/functional>`_
in the future.
- `data <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/data>`_:
Data for various tests.
- `decode <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/decode>`_:
Testsuite for :ref:`decodetree <decodetree>` implementation.
- `docker <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/docker>`_:
Code and scripts to create `containers <container-ref>` used in `CI <ci>`.
- `fp <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/fp>`_:
QEMU testsuite for soft float implementation.
- `functional <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/functional>`_:
`Functional tests <checkfunctional-ref>` (full VM boot).
- `lcitool <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/lcitool>`_:
Generate dockerfiles for CI containers.
- `migration <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/migration>`_:
Test scripts and data for `Migration framework <migration>`.
- `multiboot <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/multiboot>`_:
Test multiboot functionality for x86_64/i386.
- `qapi-schema <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/qapi-schema>`_:
Test scripts and data for `QAPI <qapi-tests>`.
- `qemu-iotests <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/qemu-iotests>`_:
`Disk image and block tests <qemu-iotests>`.
- `qtest <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/qtest>`_:
`Device emulation testing <qtest>`.
- `tcg <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/tcg>`__:
`TCG related tests <checktcg-ref>`. Contains code per architecture
(subfolder) and multiarch tests as well.
- `tsan <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/tsan>`_:
`Suppressions <tsan-suppressions>` for thread sanitizer.
- `uefi-test-tools <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/uefi-test-tools>`_:
Test tool for UEFI support.
- `unit <https://gitlab.com/qemu-project/qemu/-/tree/master/tests/unit>`_:
QEMU `Unit tests <unit-tests>`.
* `trace <https://gitlab.com/qemu-project/qemu/-/tree/master/trace>`_:
:ref:`Tracing framework <tracing>`. Used to print information associated to various
events during execution.
* `ui <https://gitlab.com/qemu-project/qemu/-/tree/master/ui>`_:
QEMU User interfaces.
* `util <https://gitlab.com/qemu-project/qemu/-/tree/master/util>`_:
Utility code used by other parts of QEMU.
+2
View File
@@ -1,3 +1,5 @@
.. _cfi:
============================
Control-Flow Integrity (CFI)
============================
+2
View File
@@ -1,3 +1,5 @@
.. _decodetree:
========================
Decodetree Specification
========================
+2
View File
@@ -1,3 +1,5 @@
.. _ebpf-rss:
===========================
eBPF RSS virtio-net support
===========================

Some files were not shown because too many files have changed in this diff Show More