]> Git Repo - qemu.git/blob - dump.c
dump: add APIs to operate DataCache
[qemu.git] / dump.c
1 /*
2  * QEMU dump
3  *
4  * Copyright Fujitsu, Corp. 2011, 2012
5  *
6  * Authors:
7  *     Wen Congyang <[email protected]>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  *
12  */
13
14 #include "qemu-common.h"
15 #include "elf.h"
16 #include "cpu.h"
17 #include "exec/cpu-all.h"
18 #include "exec/hwaddr.h"
19 #include "monitor/monitor.h"
20 #include "sysemu/kvm.h"
21 #include "sysemu/dump.h"
22 #include "sysemu/sysemu.h"
23 #include "sysemu/memory_mapping.h"
24 #include "sysemu/cpus.h"
25 #include "qapi/error.h"
26 #include "qmp-commands.h"
27
28 static uint16_t cpu_convert_to_target16(uint16_t val, int endian)
29 {
30     if (endian == ELFDATA2LSB) {
31         val = cpu_to_le16(val);
32     } else {
33         val = cpu_to_be16(val);
34     }
35
36     return val;
37 }
38
39 static uint32_t cpu_convert_to_target32(uint32_t val, int endian)
40 {
41     if (endian == ELFDATA2LSB) {
42         val = cpu_to_le32(val);
43     } else {
44         val = cpu_to_be32(val);
45     }
46
47     return val;
48 }
49
50 static uint64_t cpu_convert_to_target64(uint64_t val, int endian)
51 {
52     if (endian == ELFDATA2LSB) {
53         val = cpu_to_le64(val);
54     } else {
55         val = cpu_to_be64(val);
56     }
57
58     return val;
59 }
60
61 typedef struct DumpState {
62     GuestPhysBlockList guest_phys_blocks;
63     ArchDumpInfo dump_info;
64     MemoryMappingList list;
65     uint16_t phdr_num;
66     uint32_t sh_info;
67     bool have_section;
68     bool resume;
69     ssize_t note_size;
70     hwaddr memory_offset;
71     int fd;
72
73     GuestPhysBlock *next_block;
74     ram_addr_t start;
75     bool has_filter;
76     int64_t begin;
77     int64_t length;
78     Error **errp;
79
80     uint8_t *note_buf;          /* buffer for notes */
81     size_t note_buf_offset;     /* the writing place in note_buf */
82     uint32_t nr_cpus;           /* number of guest's cpu */
83     size_t page_size;           /* guest's page size */
84     uint32_t page_shift;        /* guest's page shift */
85     uint64_t max_mapnr;         /* the biggest guest's phys-mem's number */
86     size_t len_dump_bitmap;     /* the size of the place used to store
87                                    dump_bitmap in vmcore */
88     off_t offset_dump_bitmap;   /* offset of dump_bitmap part in vmcore */
89     off_t offset_page;          /* offset of page part in vmcore */
90     size_t num_dumpable;        /* number of page that can be dumped */
91     uint32_t flag_compress;     /* indicate the compression format */
92 } DumpState;
93
94 static int dump_cleanup(DumpState *s)
95 {
96     int ret = 0;
97
98     guest_phys_blocks_free(&s->guest_phys_blocks);
99     memory_mapping_list_free(&s->list);
100     if (s->fd != -1) {
101         close(s->fd);
102     }
103     if (s->resume) {
104         vm_start();
105     }
106
107     return ret;
108 }
109
110 static void dump_error(DumpState *s, const char *reason)
111 {
112     dump_cleanup(s);
113 }
114
115 static int fd_write_vmcore(const void *buf, size_t size, void *opaque)
116 {
117     DumpState *s = opaque;
118     size_t written_size;
119
120     written_size = qemu_write_full(s->fd, buf, size);
121     if (written_size != size) {
122         return -1;
123     }
124
125     return 0;
126 }
127
128 static int write_elf64_header(DumpState *s)
129 {
130     Elf64_Ehdr elf_header;
131     int ret;
132     int endian = s->dump_info.d_endian;
133
134     memset(&elf_header, 0, sizeof(Elf64_Ehdr));
135     memcpy(&elf_header, ELFMAG, SELFMAG);
136     elf_header.e_ident[EI_CLASS] = ELFCLASS64;
137     elf_header.e_ident[EI_DATA] = s->dump_info.d_endian;
138     elf_header.e_ident[EI_VERSION] = EV_CURRENT;
139     elf_header.e_type = cpu_convert_to_target16(ET_CORE, endian);
140     elf_header.e_machine = cpu_convert_to_target16(s->dump_info.d_machine,
141                                                    endian);
142     elf_header.e_version = cpu_convert_to_target32(EV_CURRENT, endian);
143     elf_header.e_ehsize = cpu_convert_to_target16(sizeof(elf_header), endian);
144     elf_header.e_phoff = cpu_convert_to_target64(sizeof(Elf64_Ehdr), endian);
145     elf_header.e_phentsize = cpu_convert_to_target16(sizeof(Elf64_Phdr),
146                                                      endian);
147     elf_header.e_phnum = cpu_convert_to_target16(s->phdr_num, endian);
148     if (s->have_section) {
149         uint64_t shoff = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * s->sh_info;
150
151         elf_header.e_shoff = cpu_convert_to_target64(shoff, endian);
152         elf_header.e_shentsize = cpu_convert_to_target16(sizeof(Elf64_Shdr),
153                                                          endian);
154         elf_header.e_shnum = cpu_convert_to_target16(1, endian);
155     }
156
157     ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
158     if (ret < 0) {
159         dump_error(s, "dump: failed to write elf header.\n");
160         return -1;
161     }
162
163     return 0;
164 }
165
166 static int write_elf32_header(DumpState *s)
167 {
168     Elf32_Ehdr elf_header;
169     int ret;
170     int endian = s->dump_info.d_endian;
171
172     memset(&elf_header, 0, sizeof(Elf32_Ehdr));
173     memcpy(&elf_header, ELFMAG, SELFMAG);
174     elf_header.e_ident[EI_CLASS] = ELFCLASS32;
175     elf_header.e_ident[EI_DATA] = endian;
176     elf_header.e_ident[EI_VERSION] = EV_CURRENT;
177     elf_header.e_type = cpu_convert_to_target16(ET_CORE, endian);
178     elf_header.e_machine = cpu_convert_to_target16(s->dump_info.d_machine,
179                                                    endian);
180     elf_header.e_version = cpu_convert_to_target32(EV_CURRENT, endian);
181     elf_header.e_ehsize = cpu_convert_to_target16(sizeof(elf_header), endian);
182     elf_header.e_phoff = cpu_convert_to_target32(sizeof(Elf32_Ehdr), endian);
183     elf_header.e_phentsize = cpu_convert_to_target16(sizeof(Elf32_Phdr),
184                                                      endian);
185     elf_header.e_phnum = cpu_convert_to_target16(s->phdr_num, endian);
186     if (s->have_section) {
187         uint32_t shoff = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * s->sh_info;
188
189         elf_header.e_shoff = cpu_convert_to_target32(shoff, endian);
190         elf_header.e_shentsize = cpu_convert_to_target16(sizeof(Elf32_Shdr),
191                                                          endian);
192         elf_header.e_shnum = cpu_convert_to_target16(1, endian);
193     }
194
195     ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
196     if (ret < 0) {
197         dump_error(s, "dump: failed to write elf header.\n");
198         return -1;
199     }
200
201     return 0;
202 }
203
204 static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping,
205                             int phdr_index, hwaddr offset,
206                             hwaddr filesz)
207 {
208     Elf64_Phdr phdr;
209     int ret;
210     int endian = s->dump_info.d_endian;
211
212     memset(&phdr, 0, sizeof(Elf64_Phdr));
213     phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian);
214     phdr.p_offset = cpu_convert_to_target64(offset, endian);
215     phdr.p_paddr = cpu_convert_to_target64(memory_mapping->phys_addr, endian);
216     phdr.p_filesz = cpu_convert_to_target64(filesz, endian);
217     phdr.p_memsz = cpu_convert_to_target64(memory_mapping->length, endian);
218     phdr.p_vaddr = cpu_convert_to_target64(memory_mapping->virt_addr, endian);
219
220     assert(memory_mapping->length >= filesz);
221
222     ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s);
223     if (ret < 0) {
224         dump_error(s, "dump: failed to write program header table.\n");
225         return -1;
226     }
227
228     return 0;
229 }
230
231 static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping,
232                             int phdr_index, hwaddr offset,
233                             hwaddr filesz)
234 {
235     Elf32_Phdr phdr;
236     int ret;
237     int endian = s->dump_info.d_endian;
238
239     memset(&phdr, 0, sizeof(Elf32_Phdr));
240     phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian);
241     phdr.p_offset = cpu_convert_to_target32(offset, endian);
242     phdr.p_paddr = cpu_convert_to_target32(memory_mapping->phys_addr, endian);
243     phdr.p_filesz = cpu_convert_to_target32(filesz, endian);
244     phdr.p_memsz = cpu_convert_to_target32(memory_mapping->length, endian);
245     phdr.p_vaddr = cpu_convert_to_target32(memory_mapping->virt_addr, endian);
246
247     assert(memory_mapping->length >= filesz);
248
249     ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s);
250     if (ret < 0) {
251         dump_error(s, "dump: failed to write program header table.\n");
252         return -1;
253     }
254
255     return 0;
256 }
257
258 static int write_elf64_note(DumpState *s)
259 {
260     Elf64_Phdr phdr;
261     int endian = s->dump_info.d_endian;
262     hwaddr begin = s->memory_offset - s->note_size;
263     int ret;
264
265     memset(&phdr, 0, sizeof(Elf64_Phdr));
266     phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian);
267     phdr.p_offset = cpu_convert_to_target64(begin, endian);
268     phdr.p_paddr = 0;
269     phdr.p_filesz = cpu_convert_to_target64(s->note_size, endian);
270     phdr.p_memsz = cpu_convert_to_target64(s->note_size, endian);
271     phdr.p_vaddr = 0;
272
273     ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s);
274     if (ret < 0) {
275         dump_error(s, "dump: failed to write program header table.\n");
276         return -1;
277     }
278
279     return 0;
280 }
281
282 static inline int cpu_index(CPUState *cpu)
283 {
284     return cpu->cpu_index + 1;
285 }
286
287 static int write_elf64_notes(WriteCoreDumpFunction f, DumpState *s)
288 {
289     CPUState *cpu;
290     int ret;
291     int id;
292
293     CPU_FOREACH(cpu) {
294         id = cpu_index(cpu);
295         ret = cpu_write_elf64_note(f, cpu, id, s);
296         if (ret < 0) {
297             dump_error(s, "dump: failed to write elf notes.\n");
298             return -1;
299         }
300     }
301
302     CPU_FOREACH(cpu) {
303         ret = cpu_write_elf64_qemunote(f, cpu, s);
304         if (ret < 0) {
305             dump_error(s, "dump: failed to write CPU status.\n");
306             return -1;
307         }
308     }
309
310     return 0;
311 }
312
313 static int write_elf32_note(DumpState *s)
314 {
315     hwaddr begin = s->memory_offset - s->note_size;
316     Elf32_Phdr phdr;
317     int endian = s->dump_info.d_endian;
318     int ret;
319
320     memset(&phdr, 0, sizeof(Elf32_Phdr));
321     phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian);
322     phdr.p_offset = cpu_convert_to_target32(begin, endian);
323     phdr.p_paddr = 0;
324     phdr.p_filesz = cpu_convert_to_target32(s->note_size, endian);
325     phdr.p_memsz = cpu_convert_to_target32(s->note_size, endian);
326     phdr.p_vaddr = 0;
327
328     ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s);
329     if (ret < 0) {
330         dump_error(s, "dump: failed to write program header table.\n");
331         return -1;
332     }
333
334     return 0;
335 }
336
337 static int write_elf32_notes(WriteCoreDumpFunction f, DumpState *s)
338 {
339     CPUState *cpu;
340     int ret;
341     int id;
342
343     CPU_FOREACH(cpu) {
344         id = cpu_index(cpu);
345         ret = cpu_write_elf32_note(f, cpu, id, s);
346         if (ret < 0) {
347             dump_error(s, "dump: failed to write elf notes.\n");
348             return -1;
349         }
350     }
351
352     CPU_FOREACH(cpu) {
353         ret = cpu_write_elf32_qemunote(f, cpu, s);
354         if (ret < 0) {
355             dump_error(s, "dump: failed to write CPU status.\n");
356             return -1;
357         }
358     }
359
360     return 0;
361 }
362
363 static int write_elf_section(DumpState *s, int type)
364 {
365     Elf32_Shdr shdr32;
366     Elf64_Shdr shdr64;
367     int endian = s->dump_info.d_endian;
368     int shdr_size;
369     void *shdr;
370     int ret;
371
372     if (type == 0) {
373         shdr_size = sizeof(Elf32_Shdr);
374         memset(&shdr32, 0, shdr_size);
375         shdr32.sh_info = cpu_convert_to_target32(s->sh_info, endian);
376         shdr = &shdr32;
377     } else {
378         shdr_size = sizeof(Elf64_Shdr);
379         memset(&shdr64, 0, shdr_size);
380         shdr64.sh_info = cpu_convert_to_target32(s->sh_info, endian);
381         shdr = &shdr64;
382     }
383
384     ret = fd_write_vmcore(&shdr, shdr_size, s);
385     if (ret < 0) {
386         dump_error(s, "dump: failed to write section header table.\n");
387         return -1;
388     }
389
390     return 0;
391 }
392
393 static int write_data(DumpState *s, void *buf, int length)
394 {
395     int ret;
396
397     ret = fd_write_vmcore(buf, length, s);
398     if (ret < 0) {
399         dump_error(s, "dump: failed to save memory.\n");
400         return -1;
401     }
402
403     return 0;
404 }
405
406 /* write the memroy to vmcore. 1 page per I/O. */
407 static int write_memory(DumpState *s, GuestPhysBlock *block, ram_addr_t start,
408                         int64_t size)
409 {
410     int64_t i;
411     int ret;
412
413     for (i = 0; i < size / TARGET_PAGE_SIZE; i++) {
414         ret = write_data(s, block->host_addr + start + i * TARGET_PAGE_SIZE,
415                          TARGET_PAGE_SIZE);
416         if (ret < 0) {
417             return ret;
418         }
419     }
420
421     if ((size % TARGET_PAGE_SIZE) != 0) {
422         ret = write_data(s, block->host_addr + start + i * TARGET_PAGE_SIZE,
423                          size % TARGET_PAGE_SIZE);
424         if (ret < 0) {
425             return ret;
426         }
427     }
428
429     return 0;
430 }
431
432 /* get the memory's offset and size in the vmcore */
433 static void get_offset_range(hwaddr phys_addr,
434                              ram_addr_t mapping_length,
435                              DumpState *s,
436                              hwaddr *p_offset,
437                              hwaddr *p_filesz)
438 {
439     GuestPhysBlock *block;
440     hwaddr offset = s->memory_offset;
441     int64_t size_in_block, start;
442
443     /* When the memory is not stored into vmcore, offset will be -1 */
444     *p_offset = -1;
445     *p_filesz = 0;
446
447     if (s->has_filter) {
448         if (phys_addr < s->begin || phys_addr >= s->begin + s->length) {
449             return;
450         }
451     }
452
453     QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
454         if (s->has_filter) {
455             if (block->target_start >= s->begin + s->length ||
456                 block->target_end <= s->begin) {
457                 /* This block is out of the range */
458                 continue;
459             }
460
461             if (s->begin <= block->target_start) {
462                 start = block->target_start;
463             } else {
464                 start = s->begin;
465             }
466
467             size_in_block = block->target_end - start;
468             if (s->begin + s->length < block->target_end) {
469                 size_in_block -= block->target_end - (s->begin + s->length);
470             }
471         } else {
472             start = block->target_start;
473             size_in_block = block->target_end - block->target_start;
474         }
475
476         if (phys_addr >= start && phys_addr < start + size_in_block) {
477             *p_offset = phys_addr - start + offset;
478
479             /* The offset range mapped from the vmcore file must not spill over
480              * the GuestPhysBlock, clamp it. The rest of the mapping will be
481              * zero-filled in memory at load time; see
482              * <http://refspecs.linuxbase.org/elf/gabi4+/ch5.pheader.html>.
483              */
484             *p_filesz = phys_addr + mapping_length <= start + size_in_block ?
485                         mapping_length :
486                         size_in_block - (phys_addr - start);
487             return;
488         }
489
490         offset += size_in_block;
491     }
492 }
493
494 static int write_elf_loads(DumpState *s)
495 {
496     hwaddr offset, filesz;
497     MemoryMapping *memory_mapping;
498     uint32_t phdr_index = 1;
499     int ret;
500     uint32_t max_index;
501
502     if (s->have_section) {
503         max_index = s->sh_info;
504     } else {
505         max_index = s->phdr_num;
506     }
507
508     QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
509         get_offset_range(memory_mapping->phys_addr,
510                          memory_mapping->length,
511                          s, &offset, &filesz);
512         if (s->dump_info.d_class == ELFCLASS64) {
513             ret = write_elf64_load(s, memory_mapping, phdr_index++, offset,
514                                    filesz);
515         } else {
516             ret = write_elf32_load(s, memory_mapping, phdr_index++, offset,
517                                    filesz);
518         }
519
520         if (ret < 0) {
521             return -1;
522         }
523
524         if (phdr_index >= max_index) {
525             break;
526         }
527     }
528
529     return 0;
530 }
531
532 /* write elf header, PT_NOTE and elf note to vmcore. */
533 static int dump_begin(DumpState *s)
534 {
535     int ret;
536
537     /*
538      * the vmcore's format is:
539      *   --------------
540      *   |  elf header |
541      *   --------------
542      *   |  PT_NOTE    |
543      *   --------------
544      *   |  PT_LOAD    |
545      *   --------------
546      *   |  ......     |
547      *   --------------
548      *   |  PT_LOAD    |
549      *   --------------
550      *   |  sec_hdr    |
551      *   --------------
552      *   |  elf note   |
553      *   --------------
554      *   |  memory     |
555      *   --------------
556      *
557      * we only know where the memory is saved after we write elf note into
558      * vmcore.
559      */
560
561     /* write elf header to vmcore */
562     if (s->dump_info.d_class == ELFCLASS64) {
563         ret = write_elf64_header(s);
564     } else {
565         ret = write_elf32_header(s);
566     }
567     if (ret < 0) {
568         return -1;
569     }
570
571     if (s->dump_info.d_class == ELFCLASS64) {
572         /* write PT_NOTE to vmcore */
573         if (write_elf64_note(s) < 0) {
574             return -1;
575         }
576
577         /* write all PT_LOAD to vmcore */
578         if (write_elf_loads(s) < 0) {
579             return -1;
580         }
581
582         /* write section to vmcore */
583         if (s->have_section) {
584             if (write_elf_section(s, 1) < 0) {
585                 return -1;
586             }
587         }
588
589         /* write notes to vmcore */
590         if (write_elf64_notes(fd_write_vmcore, s) < 0) {
591             return -1;
592         }
593
594     } else {
595         /* write PT_NOTE to vmcore */
596         if (write_elf32_note(s) < 0) {
597             return -1;
598         }
599
600         /* write all PT_LOAD to vmcore */
601         if (write_elf_loads(s) < 0) {
602             return -1;
603         }
604
605         /* write section to vmcore */
606         if (s->have_section) {
607             if (write_elf_section(s, 0) < 0) {
608                 return -1;
609             }
610         }
611
612         /* write notes to vmcore */
613         if (write_elf32_notes(fd_write_vmcore, s) < 0) {
614             return -1;
615         }
616     }
617
618     return 0;
619 }
620
621 /* write PT_LOAD to vmcore */
622 static int dump_completed(DumpState *s)
623 {
624     dump_cleanup(s);
625     return 0;
626 }
627
628 static int get_next_block(DumpState *s, GuestPhysBlock *block)
629 {
630     while (1) {
631         block = QTAILQ_NEXT(block, next);
632         if (!block) {
633             /* no more block */
634             return 1;
635         }
636
637         s->start = 0;
638         s->next_block = block;
639         if (s->has_filter) {
640             if (block->target_start >= s->begin + s->length ||
641                 block->target_end <= s->begin) {
642                 /* This block is out of the range */
643                 continue;
644             }
645
646             if (s->begin > block->target_start) {
647                 s->start = s->begin - block->target_start;
648             }
649         }
650
651         return 0;
652     }
653 }
654
655 /* write all memory to vmcore */
656 static int dump_iterate(DumpState *s)
657 {
658     GuestPhysBlock *block;
659     int64_t size;
660     int ret;
661
662     while (1) {
663         block = s->next_block;
664
665         size = block->target_end - block->target_start;
666         if (s->has_filter) {
667             size -= s->start;
668             if (s->begin + s->length < block->target_end) {
669                 size -= block->target_end - (s->begin + s->length);
670             }
671         }
672         ret = write_memory(s, block, s->start, size);
673         if (ret == -1) {
674             return ret;
675         }
676
677         ret = get_next_block(s, block);
678         if (ret == 1) {
679             dump_completed(s);
680             return 0;
681         }
682     }
683 }
684
685 static int create_vmcore(DumpState *s)
686 {
687     int ret;
688
689     ret = dump_begin(s);
690     if (ret < 0) {
691         return -1;
692     }
693
694     ret = dump_iterate(s);
695     if (ret < 0) {
696         return -1;
697     }
698
699     return 0;
700 }
701
702 static int write_start_flat_header(int fd)
703 {
704     uint8_t *buf;
705     MakedumpfileHeader mh;
706     int ret = 0;
707
708     memset(&mh, 0, sizeof(mh));
709     strncpy(mh.signature, MAKEDUMPFILE_SIGNATURE,
710             strlen(MAKEDUMPFILE_SIGNATURE));
711
712     mh.type = cpu_to_be64(TYPE_FLAT_HEADER);
713     mh.version = cpu_to_be64(VERSION_FLAT_HEADER);
714
715     buf = g_malloc0(MAX_SIZE_MDF_HEADER);
716     memcpy(buf, &mh, sizeof(mh));
717
718     size_t written_size;
719     written_size = qemu_write_full(fd, buf, MAX_SIZE_MDF_HEADER);
720     if (written_size != MAX_SIZE_MDF_HEADER) {
721         ret = -1;
722     }
723
724     g_free(buf);
725     return ret;
726 }
727
728 static int write_end_flat_header(int fd)
729 {
730     MakedumpfileDataHeader mdh;
731
732     mdh.offset = END_FLAG_FLAT_HEADER;
733     mdh.buf_size = END_FLAG_FLAT_HEADER;
734
735     size_t written_size;
736     written_size = qemu_write_full(fd, &mdh, sizeof(mdh));
737     if (written_size != sizeof(mdh)) {
738         return -1;
739     }
740
741     return 0;
742 }
743
744 static int write_buffer(int fd, off_t offset, const void *buf, size_t size)
745 {
746     size_t written_size;
747     MakedumpfileDataHeader mdh;
748
749     mdh.offset = cpu_to_be64(offset);
750     mdh.buf_size = cpu_to_be64(size);
751
752     written_size = qemu_write_full(fd, &mdh, sizeof(mdh));
753     if (written_size != sizeof(mdh)) {
754         return -1;
755     }
756
757     written_size = qemu_write_full(fd, buf, size);
758     if (written_size != size) {
759         return -1;
760     }
761
762     return 0;
763 }
764
765 static int buf_write_note(const void *buf, size_t size, void *opaque)
766 {
767     DumpState *s = opaque;
768
769     /* note_buf is not enough */
770     if (s->note_buf_offset + size > s->note_size) {
771         return -1;
772     }
773
774     memcpy(s->note_buf + s->note_buf_offset, buf, size);
775
776     s->note_buf_offset += size;
777
778     return 0;
779 }
780
781 /* write common header, sub header and elf note to vmcore */
782 static int create_header32(DumpState *s)
783 {
784     int ret = 0;
785     DiskDumpHeader32 *dh = NULL;
786     KdumpSubHeader32 *kh = NULL;
787     size_t size;
788     int endian = s->dump_info.d_endian;
789     uint32_t block_size;
790     uint32_t sub_hdr_size;
791     uint32_t bitmap_blocks;
792     uint32_t status = 0;
793     uint64_t offset_note;
794
795     /* write common header, the version of kdump-compressed format is 6th */
796     size = sizeof(DiskDumpHeader32);
797     dh = g_malloc0(size);
798
799     strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));
800     dh->header_version = cpu_convert_to_target32(6, endian);
801     block_size = s->page_size;
802     dh->block_size = cpu_convert_to_target32(block_size, endian);
803     sub_hdr_size = sizeof(struct KdumpSubHeader32) + s->note_size;
804     sub_hdr_size = DIV_ROUND_UP(sub_hdr_size, block_size);
805     dh->sub_hdr_size = cpu_convert_to_target32(sub_hdr_size, endian);
806     /* dh->max_mapnr may be truncated, full 64bit is in kh.max_mapnr_64 */
807     dh->max_mapnr = cpu_convert_to_target32(MIN(s->max_mapnr, UINT_MAX),
808                                             endian);
809     dh->nr_cpus = cpu_convert_to_target32(s->nr_cpus, endian);
810     bitmap_blocks = DIV_ROUND_UP(s->len_dump_bitmap, block_size) * 2;
811     dh->bitmap_blocks = cpu_convert_to_target32(bitmap_blocks, endian);
812     memcpy(&(dh->utsname.machine), "i686", 4);
813
814     if (s->flag_compress & DUMP_DH_COMPRESSED_ZLIB) {
815         status |= DUMP_DH_COMPRESSED_ZLIB;
816     }
817 #ifdef CONFIG_LZO
818     if (s->flag_compress & DUMP_DH_COMPRESSED_LZO) {
819         status |= DUMP_DH_COMPRESSED_LZO;
820     }
821 #endif
822 #ifdef CONFIG_SNAPPY
823     if (s->flag_compress & DUMP_DH_COMPRESSED_SNAPPY) {
824         status |= DUMP_DH_COMPRESSED_SNAPPY;
825     }
826 #endif
827     dh->status = cpu_convert_to_target32(status, endian);
828
829     if (write_buffer(s->fd, 0, dh, size) < 0) {
830         dump_error(s, "dump: failed to write disk dump header.\n");
831         ret = -1;
832         goto out;
833     }
834
835     /* write sub header */
836     size = sizeof(KdumpSubHeader32);
837     kh = g_malloc0(size);
838
839     /* 64bit max_mapnr_64 */
840     kh->max_mapnr_64 = cpu_convert_to_target64(s->max_mapnr, endian);
841     kh->phys_base = cpu_convert_to_target32(PHYS_BASE, endian);
842     kh->dump_level = cpu_convert_to_target32(DUMP_LEVEL, endian);
843
844     offset_note = DISKDUMP_HEADER_BLOCKS * block_size + size;
845     kh->offset_note = cpu_convert_to_target64(offset_note, endian);
846     kh->note_size = cpu_convert_to_target32(s->note_size, endian);
847
848     if (write_buffer(s->fd, DISKDUMP_HEADER_BLOCKS *
849                      block_size, kh, size) < 0) {
850         dump_error(s, "dump: failed to write kdump sub header.\n");
851         ret = -1;
852         goto out;
853     }
854
855     /* write note */
856     s->note_buf = g_malloc0(s->note_size);
857     s->note_buf_offset = 0;
858
859     /* use s->note_buf to store notes temporarily */
860     if (write_elf32_notes(buf_write_note, s) < 0) {
861         ret = -1;
862         goto out;
863     }
864
865     if (write_buffer(s->fd, offset_note, s->note_buf,
866                      s->note_size) < 0) {
867         dump_error(s, "dump: failed to write notes");
868         ret = -1;
869         goto out;
870     }
871
872     /* get offset of dump_bitmap */
873     s->offset_dump_bitmap = (DISKDUMP_HEADER_BLOCKS + sub_hdr_size) *
874                              block_size;
875
876     /* get offset of page */
877     s->offset_page = (DISKDUMP_HEADER_BLOCKS + sub_hdr_size + bitmap_blocks) *
878                      block_size;
879
880 out:
881     g_free(dh);
882     g_free(kh);
883     g_free(s->note_buf);
884
885     return ret;
886 }
887
888 /* write common header, sub header and elf note to vmcore */
889 static int create_header64(DumpState *s)
890 {
891     int ret = 0;
892     DiskDumpHeader64 *dh = NULL;
893     KdumpSubHeader64 *kh = NULL;
894     size_t size;
895     int endian = s->dump_info.d_endian;
896     uint32_t block_size;
897     uint32_t sub_hdr_size;
898     uint32_t bitmap_blocks;
899     uint32_t status = 0;
900     uint64_t offset_note;
901
902     /* write common header, the version of kdump-compressed format is 6th */
903     size = sizeof(DiskDumpHeader64);
904     dh = g_malloc0(size);
905
906     strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));
907     dh->header_version = cpu_convert_to_target32(6, endian);
908     block_size = s->page_size;
909     dh->block_size = cpu_convert_to_target32(block_size, endian);
910     sub_hdr_size = sizeof(struct KdumpSubHeader64) + s->note_size;
911     sub_hdr_size = DIV_ROUND_UP(sub_hdr_size, block_size);
912     dh->sub_hdr_size = cpu_convert_to_target32(sub_hdr_size, endian);
913     /* dh->max_mapnr may be truncated, full 64bit is in kh.max_mapnr_64 */
914     dh->max_mapnr = cpu_convert_to_target32(MIN(s->max_mapnr, UINT_MAX),
915                                             endian);
916     dh->nr_cpus = cpu_convert_to_target32(s->nr_cpus, endian);
917     bitmap_blocks = DIV_ROUND_UP(s->len_dump_bitmap, block_size) * 2;
918     dh->bitmap_blocks = cpu_convert_to_target32(bitmap_blocks, endian);
919     memcpy(&(dh->utsname.machine), "x86_64", 6);
920
921     if (s->flag_compress & DUMP_DH_COMPRESSED_ZLIB) {
922         status |= DUMP_DH_COMPRESSED_ZLIB;
923     }
924 #ifdef CONFIG_LZO
925     if (s->flag_compress & DUMP_DH_COMPRESSED_LZO) {
926         status |= DUMP_DH_COMPRESSED_LZO;
927     }
928 #endif
929 #ifdef CONFIG_SNAPPY
930     if (s->flag_compress & DUMP_DH_COMPRESSED_SNAPPY) {
931         status |= DUMP_DH_COMPRESSED_SNAPPY;
932     }
933 #endif
934     dh->status = cpu_convert_to_target32(status, endian);
935
936     if (write_buffer(s->fd, 0, dh, size) < 0) {
937         dump_error(s, "dump: failed to write disk dump header.\n");
938         ret = -1;
939         goto out;
940     }
941
942     /* write sub header */
943     size = sizeof(KdumpSubHeader64);
944     kh = g_malloc0(size);
945
946     /* 64bit max_mapnr_64 */
947     kh->max_mapnr_64 = cpu_convert_to_target64(s->max_mapnr, endian);
948     kh->phys_base = cpu_convert_to_target64(PHYS_BASE, endian);
949     kh->dump_level = cpu_convert_to_target32(DUMP_LEVEL, endian);
950
951     offset_note = DISKDUMP_HEADER_BLOCKS * block_size + size;
952     kh->offset_note = cpu_convert_to_target64(offset_note, endian);
953     kh->note_size = cpu_convert_to_target64(s->note_size, endian);
954
955     if (write_buffer(s->fd, DISKDUMP_HEADER_BLOCKS *
956                      block_size, kh, size) < 0) {
957         dump_error(s, "dump: failed to write kdump sub header.\n");
958         ret = -1;
959         goto out;
960     }
961
962     /* write note */
963     s->note_buf = g_malloc0(s->note_size);
964     s->note_buf_offset = 0;
965
966     /* use s->note_buf to store notes temporarily */
967     if (write_elf64_notes(buf_write_note, s) < 0) {
968         ret = -1;
969         goto out;
970     }
971
972     if (write_buffer(s->fd, offset_note, s->note_buf,
973                      s->note_size) < 0) {
974         dump_error(s, "dump: failed to write notes");
975         ret = -1;
976         goto out;
977     }
978
979     /* get offset of dump_bitmap */
980     s->offset_dump_bitmap = (DISKDUMP_HEADER_BLOCKS + sub_hdr_size) *
981                              block_size;
982
983     /* get offset of page */
984     s->offset_page = (DISKDUMP_HEADER_BLOCKS + sub_hdr_size + bitmap_blocks) *
985                      block_size;
986
987 out:
988     g_free(dh);
989     g_free(kh);
990     g_free(s->note_buf);
991
992     return ret;
993 }
994
995 static int write_dump_header(DumpState *s)
996 {
997     if (s->dump_info.d_machine == EM_386) {
998         return create_header32(s);
999     } else {
1000         return create_header64(s);
1001     }
1002 }
1003
1004 /*
1005  * set dump_bitmap sequencely. the bit before last_pfn is not allowed to be
1006  * rewritten, so if need to set the first bit, set last_pfn and pfn to 0.
1007  * set_dump_bitmap will always leave the recently set bit un-sync. And setting
1008  * (last bit + sizeof(buf) * 8) to 0 will do flushing the content in buf into
1009  * vmcore, ie. synchronizing un-sync bit into vmcore.
1010  */
1011 static int set_dump_bitmap(uint64_t last_pfn, uint64_t pfn, bool value,
1012                            uint8_t *buf, DumpState *s)
1013 {
1014     off_t old_offset, new_offset;
1015     off_t offset_bitmap1, offset_bitmap2;
1016     uint32_t byte, bit;
1017
1018     /* should not set the previous place */
1019     assert(last_pfn <= pfn);
1020
1021     /*
1022      * if the bit needed to be set is not cached in buf, flush the data in buf
1023      * to vmcore firstly.
1024      * making new_offset be bigger than old_offset can also sync remained data
1025      * into vmcore.
1026      */
1027     old_offset = BUFSIZE_BITMAP * (last_pfn / PFN_BUFBITMAP);
1028     new_offset = BUFSIZE_BITMAP * (pfn / PFN_BUFBITMAP);
1029
1030     while (old_offset < new_offset) {
1031         /* calculate the offset and write dump_bitmap */
1032         offset_bitmap1 = s->offset_dump_bitmap + old_offset;
1033         if (write_buffer(s->fd, offset_bitmap1, buf,
1034                          BUFSIZE_BITMAP) < 0) {
1035             return -1;
1036         }
1037
1038         /* dump level 1 is chosen, so 1st and 2nd bitmap are same */
1039         offset_bitmap2 = s->offset_dump_bitmap + s->len_dump_bitmap +
1040                          old_offset;
1041         if (write_buffer(s->fd, offset_bitmap2, buf,
1042                          BUFSIZE_BITMAP) < 0) {
1043             return -1;
1044         }
1045
1046         memset(buf, 0, BUFSIZE_BITMAP);
1047         old_offset += BUFSIZE_BITMAP;
1048     }
1049
1050     /* get the exact place of the bit in the buf, and set it */
1051     byte = (pfn % PFN_BUFBITMAP) / CHAR_BIT;
1052     bit = (pfn % PFN_BUFBITMAP) % CHAR_BIT;
1053     if (value) {
1054         buf[byte] |= 1u << bit;
1055     } else {
1056         buf[byte] &= ~(1u << bit);
1057     }
1058
1059     return 0;
1060 }
1061
1062 /*
1063  * exam every page and return the page frame number and the address of the page.
1064  * bufptr can be NULL. note: the blocks here is supposed to reflect guest-phys
1065  * blocks, so block->target_start and block->target_end should be interal
1066  * multiples of the target page size.
1067  */
1068 static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr,
1069                           uint8_t **bufptr, DumpState *s)
1070 {
1071     GuestPhysBlock *block = *blockptr;
1072     hwaddr addr;
1073     uint8_t *buf;
1074
1075     /* block == NULL means the start of the iteration */
1076     if (!block) {
1077         block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
1078         *blockptr = block;
1079         assert(block->target_start % s->page_size == 0);
1080         assert(block->target_end % s->page_size == 0);
1081         *pfnptr = paddr_to_pfn(block->target_start, s->page_shift);
1082         if (bufptr) {
1083             *bufptr = block->host_addr;
1084         }
1085         return true;
1086     }
1087
1088     *pfnptr = *pfnptr + 1;
1089     addr = pfn_to_paddr(*pfnptr, s->page_shift);
1090
1091     if ((addr >= block->target_start) &&
1092         (addr + s->page_size <= block->target_end)) {
1093         buf = block->host_addr + (addr - block->target_start);
1094     } else {
1095         /* the next page is in the next block */
1096         block = QTAILQ_NEXT(block, next);
1097         *blockptr = block;
1098         if (!block) {
1099             return false;
1100         }
1101         assert(block->target_start % s->page_size == 0);
1102         assert(block->target_end % s->page_size == 0);
1103         *pfnptr = paddr_to_pfn(block->target_start, s->page_shift);
1104         buf = block->host_addr;
1105     }
1106
1107     if (bufptr) {
1108         *bufptr = buf;
1109     }
1110
1111     return true;
1112 }
1113
1114 static int write_dump_bitmap(DumpState *s)
1115 {
1116     int ret = 0;
1117     uint64_t last_pfn, pfn;
1118     void *dump_bitmap_buf;
1119     size_t num_dumpable;
1120     GuestPhysBlock *block_iter = NULL;
1121
1122     /* dump_bitmap_buf is used to store dump_bitmap temporarily */
1123     dump_bitmap_buf = g_malloc0(BUFSIZE_BITMAP);
1124
1125     num_dumpable = 0;
1126     last_pfn = 0;
1127
1128     /*
1129      * exam memory page by page, and set the bit in dump_bitmap corresponded
1130      * to the existing page.
1131      */
1132     while (get_next_page(&block_iter, &pfn, NULL, s)) {
1133         ret = set_dump_bitmap(last_pfn, pfn, true, dump_bitmap_buf, s);
1134         if (ret < 0) {
1135             dump_error(s, "dump: failed to set dump_bitmap.\n");
1136             ret = -1;
1137             goto out;
1138         }
1139
1140         last_pfn = pfn;
1141         num_dumpable++;
1142     }
1143
1144     /*
1145      * set_dump_bitmap will always leave the recently set bit un-sync. Here we
1146      * set last_pfn + PFN_BUFBITMAP to 0 and those set but un-sync bit will be
1147      * synchronized into vmcore.
1148      */
1149     if (num_dumpable > 0) {
1150         ret = set_dump_bitmap(last_pfn, last_pfn + PFN_BUFBITMAP, false,
1151                               dump_bitmap_buf, s);
1152         if (ret < 0) {
1153             dump_error(s, "dump: failed to sync dump_bitmap.\n");
1154             ret = -1;
1155             goto out;
1156         }
1157     }
1158
1159     /* number of dumpable pages that will be dumped later */
1160     s->num_dumpable = num_dumpable;
1161
1162 out:
1163     g_free(dump_bitmap_buf);
1164
1165     return ret;
1166 }
1167
1168 static void prepare_data_cache(DataCache *data_cache, DumpState *s,
1169                                off_t offset)
1170 {
1171     data_cache->fd = s->fd;
1172     data_cache->data_size = 0;
1173     data_cache->buf_size = BUFSIZE_DATA_CACHE;
1174     data_cache->buf = g_malloc0(BUFSIZE_DATA_CACHE);
1175     data_cache->offset = offset;
1176 }
1177
1178 static int write_cache(DataCache *dc, const void *buf, size_t size,
1179                        bool flag_sync)
1180 {
1181     /*
1182      * dc->buf_size should not be less than size, otherwise dc will never be
1183      * enough
1184      */
1185     assert(size <= dc->buf_size);
1186
1187     /*
1188      * if flag_sync is set, synchronize data in dc->buf into vmcore.
1189      * otherwise check if the space is enough for caching data in buf, if not,
1190      * write the data in dc->buf to dc->fd and reset dc->buf
1191      */
1192     if ((!flag_sync && dc->data_size + size > dc->buf_size) ||
1193         (flag_sync && dc->data_size > 0)) {
1194         if (write_buffer(dc->fd, dc->offset, dc->buf, dc->data_size) < 0) {
1195             return -1;
1196         }
1197
1198         dc->offset += dc->data_size;
1199         dc->data_size = 0;
1200     }
1201
1202     if (!flag_sync) {
1203         memcpy(dc->buf + dc->data_size, buf, size);
1204         dc->data_size += size;
1205     }
1206
1207     return 0;
1208 }
1209
1210 static void free_data_cache(DataCache *data_cache)
1211 {
1212     g_free(data_cache->buf);
1213 }
1214
1215 static ram_addr_t get_start_block(DumpState *s)
1216 {
1217     GuestPhysBlock *block;
1218
1219     if (!s->has_filter) {
1220         s->next_block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
1221         return 0;
1222     }
1223
1224     QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
1225         if (block->target_start >= s->begin + s->length ||
1226             block->target_end <= s->begin) {
1227             /* This block is out of the range */
1228             continue;
1229         }
1230
1231         s->next_block = block;
1232         if (s->begin > block->target_start) {
1233             s->start = s->begin - block->target_start;
1234         } else {
1235             s->start = 0;
1236         }
1237         return s->start;
1238     }
1239
1240     return -1;
1241 }
1242
1243 static void get_max_mapnr(DumpState *s)
1244 {
1245     GuestPhysBlock *last_block;
1246
1247     last_block = QTAILQ_LAST(&s->guest_phys_blocks.head, GuestPhysBlockHead);
1248     s->max_mapnr = paddr_to_pfn(last_block->target_end, s->page_shift);
1249 }
1250
1251 static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
1252                      int64_t begin, int64_t length, Error **errp)
1253 {
1254     CPUState *cpu;
1255     int nr_cpus;
1256     Error *err = NULL;
1257     int ret;
1258
1259     if (runstate_is_running()) {
1260         vm_stop(RUN_STATE_SAVE_VM);
1261         s->resume = true;
1262     } else {
1263         s->resume = false;
1264     }
1265
1266     /* If we use KVM, we should synchronize the registers before we get dump
1267      * info or physmap info.
1268      */
1269     cpu_synchronize_all_states();
1270     nr_cpus = 0;
1271     CPU_FOREACH(cpu) {
1272         nr_cpus++;
1273     }
1274
1275     s->errp = errp;
1276     s->fd = fd;
1277     s->has_filter = has_filter;
1278     s->begin = begin;
1279     s->length = length;
1280
1281     guest_phys_blocks_init(&s->guest_phys_blocks);
1282     guest_phys_blocks_append(&s->guest_phys_blocks);
1283
1284     s->start = get_start_block(s);
1285     if (s->start == -1) {
1286         error_set(errp, QERR_INVALID_PARAMETER, "begin");
1287         goto cleanup;
1288     }
1289
1290     /* get dump info: endian, class and architecture.
1291      * If the target architecture is not supported, cpu_get_dump_info() will
1292      * return -1.
1293      */
1294     ret = cpu_get_dump_info(&s->dump_info, &s->guest_phys_blocks);
1295     if (ret < 0) {
1296         error_set(errp, QERR_UNSUPPORTED);
1297         goto cleanup;
1298     }
1299
1300     s->note_size = cpu_get_note_size(s->dump_info.d_class,
1301                                      s->dump_info.d_machine, nr_cpus);
1302     if (s->note_size < 0) {
1303         error_set(errp, QERR_UNSUPPORTED);
1304         goto cleanup;
1305     }
1306
1307     /* get memory mapping */
1308     memory_mapping_list_init(&s->list);
1309     if (paging) {
1310         qemu_get_guest_memory_mapping(&s->list, &s->guest_phys_blocks, &err);
1311         if (err != NULL) {
1312             error_propagate(errp, err);
1313             goto cleanup;
1314         }
1315     } else {
1316         qemu_get_guest_simple_memory_mapping(&s->list, &s->guest_phys_blocks);
1317     }
1318
1319     s->nr_cpus = nr_cpus;
1320     s->page_size = TARGET_PAGE_SIZE;
1321     s->page_shift = ffs(s->page_size) - 1;
1322
1323     get_max_mapnr(s);
1324
1325     uint64_t tmp;
1326     tmp = DIV_ROUND_UP(DIV_ROUND_UP(s->max_mapnr, CHAR_BIT), s->page_size);
1327     s->len_dump_bitmap = tmp * s->page_size;
1328
1329     if (s->has_filter) {
1330         memory_mapping_filter(&s->list, s->begin, s->length);
1331     }
1332
1333     /*
1334      * calculate phdr_num
1335      *
1336      * the type of ehdr->e_phnum is uint16_t, so we should avoid overflow
1337      */
1338     s->phdr_num = 1; /* PT_NOTE */
1339     if (s->list.num < UINT16_MAX - 2) {
1340         s->phdr_num += s->list.num;
1341         s->have_section = false;
1342     } else {
1343         s->have_section = true;
1344         s->phdr_num = PN_XNUM;
1345         s->sh_info = 1; /* PT_NOTE */
1346
1347         /* the type of shdr->sh_info is uint32_t, so we should avoid overflow */
1348         if (s->list.num <= UINT32_MAX - 1) {
1349             s->sh_info += s->list.num;
1350         } else {
1351             s->sh_info = UINT32_MAX;
1352         }
1353     }
1354
1355     if (s->dump_info.d_class == ELFCLASS64) {
1356         if (s->have_section) {
1357             s->memory_offset = sizeof(Elf64_Ehdr) +
1358                                sizeof(Elf64_Phdr) * s->sh_info +
1359                                sizeof(Elf64_Shdr) + s->note_size;
1360         } else {
1361             s->memory_offset = sizeof(Elf64_Ehdr) +
1362                                sizeof(Elf64_Phdr) * s->phdr_num + s->note_size;
1363         }
1364     } else {
1365         if (s->have_section) {
1366             s->memory_offset = sizeof(Elf32_Ehdr) +
1367                                sizeof(Elf32_Phdr) * s->sh_info +
1368                                sizeof(Elf32_Shdr) + s->note_size;
1369         } else {
1370             s->memory_offset = sizeof(Elf32_Ehdr) +
1371                                sizeof(Elf32_Phdr) * s->phdr_num + s->note_size;
1372         }
1373     }
1374
1375     return 0;
1376
1377 cleanup:
1378     guest_phys_blocks_free(&s->guest_phys_blocks);
1379
1380     if (s->resume) {
1381         vm_start();
1382     }
1383
1384     return -1;
1385 }
1386
1387 void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
1388                            int64_t begin, bool has_length, int64_t length,
1389                            Error **errp)
1390 {
1391     const char *p;
1392     int fd = -1;
1393     DumpState *s;
1394     int ret;
1395
1396     if (has_begin && !has_length) {
1397         error_set(errp, QERR_MISSING_PARAMETER, "length");
1398         return;
1399     }
1400     if (!has_begin && has_length) {
1401         error_set(errp, QERR_MISSING_PARAMETER, "begin");
1402         return;
1403     }
1404
1405 #if !defined(WIN32)
1406     if (strstart(file, "fd:", &p)) {
1407         fd = monitor_get_fd(cur_mon, p, errp);
1408         if (fd == -1) {
1409             return;
1410         }
1411     }
1412 #endif
1413
1414     if  (strstart(file, "file:", &p)) {
1415         fd = qemu_open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR);
1416         if (fd < 0) {
1417             error_setg_file_open(errp, errno, p);
1418             return;
1419         }
1420     }
1421
1422     if (fd == -1) {
1423         error_set(errp, QERR_INVALID_PARAMETER, "protocol");
1424         return;
1425     }
1426
1427     s = g_malloc0(sizeof(DumpState));
1428
1429     ret = dump_init(s, fd, paging, has_begin, begin, length, errp);
1430     if (ret < 0) {
1431         g_free(s);
1432         return;
1433     }
1434
1435     if (create_vmcore(s) < 0 && !error_is_set(s->errp)) {
1436         error_set(errp, QERR_IO_ERROR);
1437     }
1438
1439     g_free(s);
1440 }
This page took 0.101513 seconds and 4 git commands to generate.