@samitouri / QOSamiQemu / commits / 49854252fc

tests/qtest/dump: cover win-dmp availability via vmcoreinfo

win-dmp becomes available only once the guest exposes a Windows dump header through vmcoreinfo. Forge exactly such a note (an ELF note header followed by a WinDumpHeader64 carrying the PAGE/DU64 signatures, the layout a Windows guest with the QEMU vmcoreinfo writer produces), place it in guest RAM, point the vmcoreinfo device at it via fw_cfg, and check that win-dmp flips from unavailable to available. This exercises win_dump_available()'s positive path without a real Windows guest. It only covers availability reporting; the actual win-dmp generation (create_win_dump()) needs real Windows kernel structures and is not exercised here. The test is registered only on x86_64 with a vmcoreinfo device present. Signed-off-by: Denis V. Lunev <den@openvz.org> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20260619101834.228432-8-den@openvz.org>

Denis V. Lunev committed Jun 19, 2026 at 12:18 UTC 49854252fc9f22f21f6c6a307e141309bcd54fc6
1 file changed +94
tests/qtest/dump-test.c
+94
@@ -12,10 +12,15 @@
12
13 #include "qemu/osdep.h"
14 #include "libqtest.h"
15 +#include "libqos/libqos-pc.h"
16 +#include "libqos/fw_cfg.h"
17 #include "qobject/qdict.h"
18 #include "qobject/qlist.h"
19 #include "qobject/qstring.h"
20 #include "qemu/bswap.h"
21 +#include "qemu/win_dump_defs.h"
22 +#include "standard-headers/linux/qemu_fw_cfg.h"
23 +#include "hw/misc/vmcoreinfo.h"
24 #include "elf.h"
25
26 #define KDUMP_RAW_MAGIC "KDUMP "
@@ -215,6 +220,90 @@ static void test_dump_win_dmp_unavailable(void)
220 qtest_quit(qts);
221 }
222
223 +static bool capability_has_format(QTestState *qts, const char *want)
224 +{
225 + QDict *resp, *ret;
226 + QList *formats;
227 + QListEntry *e;
228 + bool found = false;
229 +
230 + resp = qtest_qmp(qts,
231 + "{ 'execute': 'query-dump-guest-memory-capability' }");
232 + g_assert(qdict_haskey(resp, "return"));
233 + ret = qdict_get_qdict(resp, "return");
234 + formats = qdict_get_qlist(ret, "formats");
235 + g_assert_nonnull(formats);
236 +
237 + QLIST_FOREACH_ENTRY(formats, e) {
238 + QString *qs = qobject_to(QString, qlist_entry_obj(e));
239 +
240 + if (g_str_equal(qstring_get_str(qs), want)) {
241 + found = true;
242 + }
243 + }
244 + qobject_unref(resp);
245 + return found;
246 +}
247 +
248 +/*
249 + * win-dmp becomes available only once the guest exposes a Windows dump
250 + * header through vmcoreinfo. Forge exactly such a note -- the layout a
251 + * Windows guest with the QEMU vmcoreinfo writer produces: a fixed-size ELF
252 + * note header followed by a WinDumpHeader64 carrying the PAGE/DU64
253 + * signatures -- place it in guest RAM, point the vmcoreinfo device at it
254 + * via fw_cfg, and check that win-dmp flips from unavailable to available.
255 + *
256 + * This only covers availability *reporting*; the actual win-dmp generation
257 + * (create_win_dump()) needs real Windows kernel structures and is not
258 + * exercised here.
259 + */
260 +static void test_dump_win_dmp_available(void)
261 +{
262 + const uint64_t paddr = 0x800000; /* 8 MiB, inside guest RAM */
263 + size_t notesz = VMCOREINFO_WIN_DUMP_NOTE_SIZE64;
264 + g_autofree uint8_t *note = g_malloc0(notesz);
265 + Elf64_Nhdr *nhdr = (Elf64_Nhdr *)note;
266 + WinDumpHeader64 *hdr;
267 + FWCfgVMCoreInfo info;
268 + QFWCFG *fw_cfg;
269 + QOSState *qs;
270 +
271 + /* the WinDumpHeader64 must sit right after the fixed ELF note header */
272 + g_assert_cmpint(sizeof(WinDumpHeader64) % 4, ==, 0);
273 +
274 + nhdr->n_namesz = cpu_to_le32(sizeof("VMCOREINFO")); /* 11 -> padded 12 */
275 + nhdr->n_descsz = cpu_to_le32(sizeof(WinDumpHeader64));
276 + nhdr->n_type = 0;
277 + memcpy(note + sizeof(Elf64_Nhdr), "VMCOREINFO", sizeof("VMCOREINFO") - 1);
278 +
279 + hdr = (WinDumpHeader64 *)(note + VMCOREINFO_ELF_NOTE_HDR_SIZE);
280 + memcpy(hdr->Signature, "PAGE", sizeof(hdr->Signature));
281 + memcpy(hdr->ValidDump, "DU64", sizeof(hdr->ValidDump));
282 +
283 + qs = qtest_pc_boot("-device vmcoreinfo -m 16");
284 + fw_cfg = pc_fw_cfg_init(qs->qts);
285 +
286 + /* with no guest note yet, win-dmp must not be advertised */
287 + g_assert_false(capability_has_format(qs->qts, "win-dmp"));
288 +
289 + /* place the forged note in guest RAM and point vmcoreinfo at it */
290 + qtest_memwrite(qs->qts, paddr, note, notesz);
291 +
292 + memset(&info, 0, sizeof(info));
293 + info.host_format = cpu_to_le16(FW_CFG_VMCOREINFO_FORMAT_ELF);
294 + info.guest_format = cpu_to_le16(FW_CFG_VMCOREINFO_FORMAT_ELF);
295 + info.size = cpu_to_le32(notesz);
296 + info.paddr = cpu_to_le64(paddr);
297 + qfw_cfg_write_file(fw_cfg, qs, FW_CFG_VMCOREINFO_FILENAME,
298 + &info, sizeof(info));
299 +
300 + /* now win-dmp must be reported as available */
301 + g_assert_true(capability_has_format(qs->qts, "win-dmp"));
302 +
303 + pc_fw_cfg_uninit(fw_cfg);
304 + qtest_shutdown(qs);
305 +}
306 +
307 int main(int argc, char **argv)
308 {
309 const char *arch = qtest_get_arch();
@@ -231,6 +320,11 @@ int main(int argc, char **argv)
320 if (g_str_equal(arch, "x86_64")) {
321 qtest_add_func("/dump/win-dmp-unavailable",
322 test_dump_win_dmp_unavailable);
323 +
324 + if (qtest_has_device("vmcoreinfo")) {
325 + qtest_add_func("/dump/win-dmp-available",
326 + test_dump_win_dmp_available);
327 + }
328 }
329
330 return g_test_run();