/* * SPDX-License-Identifier: GPL-2.0-or-later * * This C++ plugin ensures we don't have regression when compiling C++. */ #include /* * We include all C++ standard headers (without deprecated ones), * taken from: https://en.cppreference.com/w/cpp/headers.html * * To update, copy page text, and then: * grep '^<' | * sort -u | * grep -v strstream | * grep -v codecvt | * sed -e 's/\(.*\)/#if __has_include(\1)\n#include \1\n#endif/' */ #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif #if __has_include() #include #endif QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; class Plugin { public: void tb_exec(std::atomic &count) { count++; } void tb_trans(struct qemu_plugin_tb *tb) { auto vaddr = qemu_plugin_tb_vaddr(tb); TbData *data = [&]() { std::lock_guard l(tb_trans_lock); auto [it, is_new] = tb_data.try_emplace(vaddr); TbData &in = it->second; if (is_new) { in.first = 0; in.second = this; } return ∈ } (); qemu_plugin_register_vcpu_tb_exec_cb( tb, [](unsigned int cpu_index, void *udata) { auto &[counter, p] = *static_cast(udata); p->tb_exec(counter); }, QEMU_PLUGIN_CB_NO_REGS, data); } void at_exit() { std::vector> v; for (auto &[vaddr, data] : tb_data) { uint64_t count = data.first; v.push_back({vaddr, count}); } std::sort(v.begin(), v.end(), [](const auto &a, const auto &b) { return a.second > b.second; }); std::stringstream ss; ss << "Top 10 executed TB are:\n"; size_t idx = 0; for (auto &tb : v) { if (idx >= 10) { break; } ss << std::hex << "0x" << tb.first << std::dec << ": " << tb.second << '\n'; ++idx; } qemu_plugin_outs(ss.str().c_str()); } private: using Vaddr = uint64_t; using Counter = std::atomic; using TbData = std::pair; std::unordered_map tb_data; std::mutex tb_trans_lock; }; QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, int argc, char **argv) { Plugin *plugin = new Plugin; /* * We can register a cb with any function, which may be a free * function, a static class function, or a captureless lambda. */ qemu_plugin_register_vcpu_tb_trans_cb( id, [](struct qemu_plugin_tb *tb, void *userdata) { Plugin *p = static_cast(userdata); p->tb_trans(tb); }, plugin); qemu_plugin_register_atexit_cb( id, [](void *userdata) { Plugin *p = static_cast(userdata); p->at_exit(); delete p; }, plugin); return 0; }