|
Packit Service |
501009 |
/*
|
|
Packit Service |
501009 |
* kvmdump.c
|
|
Packit Service |
501009 |
*
|
|
Packit Service |
501009 |
* Copyright (C) 2009, 2010, 2011 David Anderson
|
|
Packit Service |
501009 |
* Copyright (C) 2009, 2010, 2011 Red Hat, Inc. All rights reserved.
|
|
Packit Service |
501009 |
*
|
|
Packit Service |
501009 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
501009 |
* it under the terms of the GNU General Public License as published by
|
|
Packit Service |
501009 |
* the Free Software Foundation; either version 2 of the License, or
|
|
Packit Service |
501009 |
* (at your option) any later version.
|
|
Packit Service |
501009 |
*
|
|
Packit Service |
501009 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
501009 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
501009 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
501009 |
* GNU General Public License for more details.
|
|
Packit Service |
501009 |
*/
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
#include "defs.h"
|
|
Packit Service |
501009 |
#include "kvmdump.h"
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
static struct kvmdump_data kvmdump_data = { 0 };
|
|
Packit Service |
501009 |
struct kvmdump_data *kvm = &kvmdump_data;
|
|
Packit Service |
501009 |
static int cache_page(physaddr_t);
|
|
Packit Service |
501009 |
static int kvmdump_mapfile_exists(void);
|
|
Packit Service |
501009 |
static off_t mapfile_offset(uint64_t);
|
|
Packit Service |
501009 |
static void kvmdump_mapfile_create(char *);
|
|
Packit Service |
501009 |
static void kvmdump_mapfile_append(void);
|
|
Packit Service |
501009 |
static char *mapfile_in_use(void);
|
|
Packit Service |
501009 |
static void write_mapfile_registers(void);
|
|
Packit Service |
501009 |
static void write_mapfile_trailer(void);
|
|
Packit Service |
501009 |
static void read_mapfile_trailer(void);
|
|
Packit Service |
501009 |
static void read_mapfile_registers(void);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
#define RAM_OFFSET_COMPRESSED (~(off_t)255)
|
|
Packit Service |
501009 |
#define QEMU_COMPRESSED ((WRITE_ERROR)-1)
|
|
Packit Service |
501009 |
#define CACHE_UNUSED (1ULL)
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
int
|
|
Packit Service |
501009 |
is_kvmdump(char *filename)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
int i;
|
|
Packit Service |
501009 |
ulong *ptr;
|
|
Packit Service |
501009 |
off_t eof;
|
|
Packit Service |
501009 |
ulonglong csum;
|
|
Packit Service |
501009 |
struct mapinfo_trailer trailer;
|
|
Packit Service |
501009 |
char buf[CHKSUM_SIZE];
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (!is_qemu_vm_file(filename))
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (lseek(kvm->vmfd, 0, SEEK_SET) < 0) {
|
|
Packit Service |
501009 |
error(INFO, "%s: read: %s\n", filename, strerror(errno));
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
if (read(kvm->vmfd, buf, CHKSUM_SIZE) != CHKSUM_SIZE) {
|
|
Packit Service |
501009 |
error(INFO, "%s: read: %s\n", filename, strerror(errno));
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
ptr = (ulong *)&buf[0];
|
|
Packit Service |
501009 |
for (i = csum = 0; i < (CHKSUM_SIZE/sizeof(ulong)); i++, ptr++)
|
|
Packit Service |
501009 |
csum += *ptr;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
eof = lseek(kvm->vmfd, 0, SEEK_END);
|
|
Packit Service |
501009 |
if (lseek(kvm->vmfd, eof - sizeof(trailer), SEEK_SET) < 0) {
|
|
Packit Service |
501009 |
error(INFO, "%s: lseek: %s\n", filename, strerror(errno));
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
if (read(kvm->vmfd, &trailer, sizeof(trailer)) != sizeof(trailer)) {
|
|
Packit Service |
501009 |
error(INFO, "%s: read: %s\n", filename, strerror(errno));
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
if (trailer.magic == MAPFILE_MAGIC) {
|
|
Packit Service |
501009 |
kvm->mapinfo.map_start_offset = trailer.map_start_offset;
|
|
Packit Service |
501009 |
kvm->flags |= MAPFILE_APPENDED;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
kvm->mapinfo.checksum = csum;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return TRUE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
int
|
|
Packit Service |
501009 |
kvmdump_init(char *filename, FILE *fptr)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
int i, page_size;
|
|
Packit Service |
501009 |
struct command_table_entry *cp;
|
|
Packit Service |
501009 |
char *cachebuf;
|
|
Packit Service |
501009 |
FILE *tmpfp;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (!machine_type("X86") && !machine_type("X86_64")) {
|
|
Packit Service |
501009 |
error(FATAL,
|
|
Packit Service |
501009 |
"invalid or unsupported host architecture for KVM: %s\n",
|
|
Packit Service |
501009 |
MACHINE_TYPE);
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
kvm->ofp = fptr;
|
|
Packit Service |
501009 |
kvm->debug = &pc->debug;
|
|
Packit Service |
501009 |
page_size = memory_page_size();
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
#ifdef X86_64
|
|
Packit Service |
501009 |
kvm->kvbase = __START_KERNEL_map;
|
|
Packit Service |
501009 |
#endif
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
switch (kvm->flags & (TMPFILE|MAPFILE|MAPFILE_APPENDED))
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
case MAPFILE_APPENDED:
|
|
Packit Service |
501009 |
kvm->mapfd = kvm->vmfd;
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
case MAPFILE|MAPFILE_APPENDED:
|
|
Packit Service |
501009 |
case MAPFILE:
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
default:
|
|
Packit Service |
501009 |
if (kvmdump_mapfile_exists())
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if ((tmpfp = tmpfile()) == NULL)
|
|
Packit Service |
501009 |
error(FATAL,
|
|
Packit Service |
501009 |
"cannot create tmpfile for KVM file offsets: %s\n",
|
|
Packit Service |
501009 |
strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
kvm->mapfd = fileno(tmpfp);
|
|
Packit Service |
501009 |
kvm->flags |= TMPFILE;
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if ((cachebuf = calloc(1, KVMDUMP_CACHED_PAGES * page_size)) == NULL)
|
|
Packit Service |
501009 |
error(FATAL, "%s: cannot malloc KVM page_cache_buf\n");
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
for (i = 0; i < KVMDUMP_CACHED_PAGES; i++) {
|
|
Packit Service |
501009 |
kvm->page_cache[i].paddr = CACHE_UNUSED;
|
|
Packit Service |
501009 |
kvm->page_cache[i].bufptr = cachebuf + (i * page_size);
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
kvmdump_regs_store(KVMDUMP_REGS_START, NULL);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (qemu_init(filename)) {
|
|
Packit Service |
501009 |
switch (kvm->flags & (TMPFILE|MAPFILE|MAPFILE_APPENDED))
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
case TMPFILE:
|
|
Packit Service |
501009 |
kvmdump_regs_store(KVMDUMP_REGS_END, NULL);
|
|
Packit Service |
501009 |
write_mapfile_trailer();
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
case MAPFILE:
|
|
Packit Service |
501009 |
case MAPFILE_APPENDED:
|
|
Packit Service |
501009 |
case MAPFILE|MAPFILE_APPENDED:
|
|
Packit Service |
501009 |
read_mapfile_trailer();
|
|
Packit Service |
501009 |
kvmdump_regs_store(KVMDUMP_REGS_END, NULL);
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
for (cp = pc->cmd_table; cp->name; cp++) {
|
|
Packit Service |
501009 |
if (STREQ(cp->name, "map")) {
|
|
Packit Service |
501009 |
cp->flags &= ~HIDDEN_COMMAND;
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
kvm->flags |= KVMDUMP_LOCAL;
|
|
Packit Service |
501009 |
return TRUE;
|
|
Packit Service |
501009 |
} else
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
int
|
|
Packit Service |
501009 |
read_kvmdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
switch (cache_page(PHYSPAGEBASE(paddr)))
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
case READ_ERROR:
|
|
Packit Service |
501009 |
return READ_ERROR;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
case SEEK_ERROR:
|
|
Packit Service |
501009 |
return SEEK_ERROR;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
case QEMU_COMPRESSED:
|
|
Packit Service |
501009 |
memset(bufptr, kvm->un.compressed, cnt);
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
default:
|
|
Packit Service |
501009 |
memcpy(bufptr, kvm->un.curbufptr + PAGEOFFSET(paddr), cnt);
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return cnt;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
int
|
|
Packit Service |
501009 |
write_kvmdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
return SEEK_ERROR;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
/*
|
|
Packit Service |
501009 |
* kvmdump_free_memory(), and kvmdump_memory_used()
|
|
Packit Service |
501009 |
* are debug only, and typically unnecessary to implement.
|
|
Packit Service |
501009 |
*/
|
|
Packit Service |
501009 |
int
|
|
Packit Service |
501009 |
kvmdump_free_memory(void)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
return 0;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
int
|
|
Packit Service |
501009 |
kvmdump_memory_used(void)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
return 0;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
/*
|
|
Packit Service |
501009 |
* This function is dump-type independent, used here to
|
|
Packit Service |
501009 |
* to dump the kvmdump_data structure contents.
|
|
Packit Service |
501009 |
*/
|
|
Packit Service |
501009 |
int
|
|
Packit Service |
501009 |
kvmdump_memory_dump(FILE *ofp)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
int i, others;
|
|
Packit Service |
501009 |
struct mapinfo_trailer trailer;
|
|
Packit Service |
501009 |
off_t eof;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
fprintf(ofp, " flags: %lx (", kvm->flags);
|
|
Packit Service |
501009 |
others = 0;
|
|
Packit Service |
501009 |
if (kvm->flags & KVMDUMP_LOCAL)
|
|
Packit Service |
501009 |
fprintf(ofp, "%sKVMDUMP_LOCAL", others++ ? "|" : "");
|
|
Packit Service |
501009 |
if (kvm->flags & TMPFILE)
|
|
Packit Service |
501009 |
fprintf(ofp, "%sTMPFILE", others++ ? "|" : "");
|
|
Packit Service |
501009 |
if (kvm->flags & MAPFILE)
|
|
Packit Service |
501009 |
fprintf(ofp, "%sMAPFILE", others++ ? "|" : "");
|
|
Packit Service |
501009 |
if (kvm->flags & MAPFILE_FOUND)
|
|
Packit Service |
501009 |
fprintf(ofp, "%sMAPFILE_FOUND", others++ ? "|" : "");
|
|
Packit Service |
501009 |
if (kvm->flags & MAPFILE_APPENDED)
|
|
Packit Service |
501009 |
fprintf(ofp, "%sMAPFILE_APPENDED", others++ ? "|" : "");
|
|
Packit Service |
501009 |
if (kvm->flags & NO_PHYS_BASE)
|
|
Packit Service |
501009 |
fprintf(ofp, "%sNO_PHYS_BASE", others++ ? "|" : "");
|
|
Packit Service |
501009 |
if (kvm->flags & KVMHOST_32)
|
|
Packit Service |
501009 |
fprintf(ofp, "%sKVMHOST_32", others++ ? "|" : "");
|
|
Packit Service |
501009 |
if (kvm->flags & KVMHOST_64)
|
|
Packit Service |
501009 |
fprintf(ofp, "%sKVMHOST_64", others++ ? "|" : "");
|
|
Packit Service |
501009 |
if (kvm->flags & REGS_FROM_MAPFILE)
|
|
Packit Service |
501009 |
fprintf(ofp, "%sREGS_FROM_MAPFILE", others++ ? "|" : "");
|
|
Packit Service |
501009 |
if (kvm->flags & REGS_FROM_DUMPFILE)
|
|
Packit Service |
501009 |
fprintf(ofp, "%sREGS_FROM_DUMPFILE", others++ ? "|" : "");
|
|
Packit Service |
501009 |
if (kvm->flags & REGS_NOT_AVAIL)
|
|
Packit Service |
501009 |
fprintf(ofp, "%sREGS_NOT_AVAIL", others++ ? "|" : "");
|
|
Packit Service |
501009 |
fprintf(ofp, ")\n");
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
fprintf(ofp, " mapfd: %d\n", kvm->mapfd);
|
|
Packit Service |
501009 |
fprintf(ofp, " vmfd: %d\n", kvm->vmfd);
|
|
Packit Service |
501009 |
fprintf(ofp, " vmp: %lx (fd: %d)\n", (ulong)kvm->vmp,
|
|
Packit Service |
501009 |
fileno(kvm->vmp));
|
|
Packit Service |
501009 |
fprintf(ofp, " ofp: %lx\n", (ulong)kvm->ofp);
|
|
Packit Service |
501009 |
fprintf(ofp, " debug: %lx\n", (ulong)kvm->debug);
|
|
Packit Service |
501009 |
if (machine_type("X86_64"))
|
|
Packit Service |
501009 |
fprintf(ofp, " kvbase: %llx\n", (ulonglong)kvm->kvbase);
|
|
Packit Service |
501009 |
else
|
|
Packit Service |
501009 |
fprintf(ofp, " kvbase: (unused)\n");
|
|
Packit Service |
501009 |
fprintf(ofp, " mapinfo:\n");
|
|
Packit Service |
501009 |
fprintf(ofp, " magic: %llx %s\n", (ulonglong)kvm->mapinfo.magic,
|
|
Packit Service |
501009 |
kvm->mapinfo.magic == MAPFILE_MAGIC ? "(MAPFILE_MAGIC)" : "");
|
|
Packit Service |
501009 |
fprintf(ofp, " phys_base: %llx %s\n", (ulonglong)kvm->mapinfo.phys_base,
|
|
Packit Service |
501009 |
machine_type("X86") ? "(unused)" : "");
|
|
Packit Service |
501009 |
fprintf(ofp, " cpu_version_id: %ld\n", (ulong)kvm->mapinfo.cpu_version_id);
|
|
Packit Service |
501009 |
fprintf(ofp, " ram_version_id: %ld\n", (ulong)kvm->mapinfo.ram_version_id);
|
|
Packit Service |
501009 |
fprintf(ofp, " map_start_offset: %llx\n", (ulonglong)kvm->mapinfo.map_start_offset);
|
|
Packit Service |
501009 |
fprintf(ofp, " checksum: %llx\n", (ulonglong)kvm->mapinfo.checksum);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
fprintf(ofp, " curbufptr: %lx\n", (ulong)kvm->un.curbufptr);
|
|
Packit Service |
501009 |
fprintf(ofp, " evict_index: %d\n", kvm->evict_index);
|
|
Packit Service |
501009 |
fprintf(ofp, " accesses: %ld\n", kvm->accesses);
|
|
Packit Service |
501009 |
fprintf(ofp, " hit_count: %ld ", kvm->hit_count);
|
|
Packit Service |
501009 |
if (kvm->accesses)
|
|
Packit Service |
501009 |
fprintf(ofp, "(%ld%%)\n",
|
|
Packit Service |
501009 |
kvm->hit_count * 100 / kvm->accesses);
|
|
Packit Service |
501009 |
else
|
|
Packit Service |
501009 |
fprintf(ofp, "\n");
|
|
Packit Service |
501009 |
fprintf(ofp, " compresses: %ld ", kvm->compresses);
|
|
Packit Service |
501009 |
if (kvm->accesses)
|
|
Packit Service |
501009 |
fprintf(ofp, "(%ld%%)\n",
|
|
Packit Service |
501009 |
kvm->compresses * 100 / kvm->accesses);
|
|
Packit Service |
501009 |
else
|
|
Packit Service |
501009 |
fprintf(ofp, "\n");
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
for (i = 0; i < KVMDUMP_CACHED_PAGES; i++) {
|
|
Packit Service |
501009 |
if (kvm->page_cache[i].paddr == CACHE_UNUSED)
|
|
Packit Service |
501009 |
fprintf(ofp, " %spage_cache[%d]: CACHE_UNUSED\n",
|
|
Packit Service |
501009 |
i < 10 ? " " : "", i);
|
|
Packit Service |
501009 |
else
|
|
Packit Service |
501009 |
fprintf(ofp,
|
|
Packit Service |
501009 |
" %spage_cache[%d]: bufptr: %lx addr: %llx\n",
|
|
Packit Service |
501009 |
i < 10 ? " " : "", i,
|
|
Packit Service |
501009 |
(ulong)kvm->page_cache[i].bufptr,
|
|
Packit Service |
501009 |
(ulonglong)kvm->page_cache[i].paddr);
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
fprintf(ofp, " cpu_devices: %d\n", kvm->cpu_devices);
|
|
Packit Service |
501009 |
fprintf(ofp, " iohole: %llx (%llx - %llx)\n",
|
|
Packit Service |
501009 |
(ulonglong)kvm->iohole, 0x100000000ULL - kvm->iohole,
|
|
Packit Service |
501009 |
0x100000000ULL);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
fprintf(ofp, " registers: %s\n",
|
|
Packit Service |
501009 |
kvm->registers ? "" : "(not used)");
|
|
Packit Service |
501009 |
for (i = 0; i < kvm->cpu_devices; i++) {
|
|
Packit Service |
501009 |
fprintf(ofp, " CPU %d:\n", i);
|
|
Packit Service |
501009 |
kvmdump_display_regs(i, ofp);
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
fprintf(ofp, "\n");
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
dump_qemu_header(ofp);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
fprintf(ofp, "\n%s: mapinfo trailer:\n\n", mapfile_in_use());
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
eof = lseek(kvm->mapfd, 0, SEEK_END);
|
|
Packit Service |
501009 |
if (lseek(kvm->mapfd, eof - sizeof(trailer), SEEK_SET) < 0)
|
|
Packit Service |
501009 |
error(FATAL, "%s: lseek: %s\n", mapfile_in_use(),
|
|
Packit Service |
501009 |
strerror(errno));
|
|
Packit Service |
501009 |
if (read(kvm->mapfd, &trailer, sizeof(trailer)) != sizeof(trailer))
|
|
Packit Service |
501009 |
error(FATAL, "%s: read: %s\n", mapfile_in_use(),
|
|
Packit Service |
501009 |
strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
fprintf(ofp, " magic: %llx %s\n", (ulonglong)trailer.magic,
|
|
Packit Service |
501009 |
trailer.magic == MAPFILE_MAGIC ? "(MAPFILE_MAGIC)" : "");
|
|
Packit Service |
501009 |
fprintf(ofp, " phys_base: %llx %s\n", (ulonglong)trailer.phys_base,
|
|
Packit Service |
501009 |
machine_type("X86") ? "(unused)" : "");
|
|
Packit Service |
501009 |
fprintf(ofp, " cpu_version_id: %ld\n", (ulong)trailer.cpu_version_id);
|
|
Packit Service |
501009 |
fprintf(ofp, " ram_version_id: %ld\n", (ulong)trailer.ram_version_id);
|
|
Packit Service |
501009 |
fprintf(ofp, " map_start_offset: %llx\n", (ulonglong)trailer.map_start_offset);
|
|
Packit Service |
501009 |
fprintf(ofp, " checksum: %llx\n\n", (ulonglong)trailer.checksum);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return TRUE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
void
|
|
Packit Service |
501009 |
kvmdump_display_regs(int cpu, FILE *ofp)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
struct register_set *rp;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (cpu >= kvm->cpu_devices) {
|
|
Packit Service |
501009 |
error(INFO, "registers not collected for cpu %d\n", cpu);
|
|
Packit Service |
501009 |
return;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
rp = &kvm->registers[cpu];
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (machine_type("X86_64")) {
|
|
Packit Service |
501009 |
fprintf(ofp,
|
|
Packit Service |
501009 |
" RIP: %016llx RSP: %016llx RFLAGS: %08llx\n"
|
|
Packit Service |
501009 |
" RAX: %016llx RBX: %016llx RCX: %016llx\n"
|
|
Packit Service |
501009 |
" RDX: %016llx RSI: %016llx RDI: %016llx\n"
|
|
Packit Service |
501009 |
" RBP: %016llx R8: %016llx R9: %016llx\n"
|
|
Packit Service |
501009 |
" R10: %016llx R11: %016llx R12: %016llx\n"
|
|
Packit Service |
501009 |
" R13: %016llx R14: %016llx R15: %016llx\n"
|
|
Packit Service |
501009 |
" CS: %04x SS: %04x\n",
|
|
Packit Service |
501009 |
(ulonglong)rp->ip,
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_ESP],
|
|
Packit Service |
501009 |
(ulonglong)rp->flags,
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_EAX],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_EBX],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_ECX],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_EDX],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_ESI],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_EDI],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_EBP],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[8],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[9],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[10],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[11],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[12],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[13],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[14],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[15],
|
|
Packit Service |
501009 |
rp->cs,
|
|
Packit Service |
501009 |
rp->ss);
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (machine_type("X86")) {
|
|
Packit Service |
501009 |
fprintf(ofp,
|
|
Packit Service |
501009 |
" EAX: %08llx EBX: %08llx ECX: %08llx EDX: %08llx\n"
|
|
Packit Service |
501009 |
" DS: %04x ESI: %08llx ES: %04x EDI: %08llx\n"
|
|
Packit Service |
501009 |
" SS: %04x ESP: %08llx EBP: %08llx GS: %04x\n"
|
|
Packit Service |
501009 |
" CS: %04x EIP: %08llx EFLAGS: %08llx\n",
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_EAX],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_EBX],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_ECX],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_EDX],
|
|
Packit Service |
501009 |
rp->ds,
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_ESI],
|
|
Packit Service |
501009 |
rp->ds,
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_EDI],
|
|
Packit Service |
501009 |
rp->ss,
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_ESP],
|
|
Packit Service |
501009 |
(ulonglong)rp->regs[R_EBP],
|
|
Packit Service |
501009 |
rp->gs,
|
|
Packit Service |
501009 |
rp->cs,
|
|
Packit Service |
501009 |
(ulonglong)rp->ip,
|
|
Packit Service |
501009 |
(ulonglong)rp->flags);
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
void
|
|
Packit Service |
501009 |
get_kvmdump_regs(struct bt_info *bt, ulong *ipp, ulong *spp)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
ulong ip, sp;
|
|
Packit Service |
501009 |
struct register_set *rp;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
ip = sp = 0;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (!is_task_active(bt->task)) {
|
|
Packit Service |
501009 |
machdep->get_stack_frame(bt, ipp, spp);
|
|
Packit Service |
501009 |
return;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
bt->flags |= BT_DUMPFILE_SEARCH;
|
|
Packit Service |
501009 |
if (machine_type("X86_64"))
|
|
Packit Service |
501009 |
machdep->get_stack_frame(bt, ipp, spp);
|
|
Packit Service |
501009 |
else if (machine_type("X86"))
|
|
Packit Service |
501009 |
get_netdump_regs_x86(bt, ipp, spp);
|
|
Packit Service |
501009 |
if (bt->flags & BT_DUMPFILE_SEARCH)
|
|
Packit Service |
501009 |
return;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if ((kvm->registers == NULL) ||
|
|
Packit Service |
501009 |
(bt->tc->processor >= kvm->cpu_devices))
|
|
Packit Service |
501009 |
return;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
rp = &kvm->registers[bt->tc->processor];
|
|
Packit Service |
501009 |
ip = (ulong)rp->ip;
|
|
Packit Service |
501009 |
sp = (ulong)rp->regs[R_ESP];
|
|
Packit Service |
501009 |
if (is_kernel_text(ip) &&
|
|
Packit Service |
501009 |
(((sp >= GET_STACKBASE(bt->task)) &&
|
|
Packit Service |
501009 |
(sp < GET_STACKTOP(bt->task))) ||
|
|
Packit Service |
501009 |
in_alternate_stack(bt->tc->processor, sp))) {
|
|
Packit Service |
501009 |
*ipp = ip;
|
|
Packit Service |
501009 |
*spp = sp;
|
|
Packit Service |
501009 |
bt->flags |= BT_KERNEL_SPACE;
|
|
Packit Service |
501009 |
return;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (!is_kernel_text(ip) &&
|
|
Packit Service |
501009 |
in_user_stack(bt->tc->task, sp))
|
|
Packit Service |
501009 |
bt->flags |= BT_USER_SPACE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
ulong
|
|
Packit Service |
501009 |
get_kvmdump_panic_task(void)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
int i;
|
|
Packit Service |
501009 |
struct bt_info *bt;
|
|
Packit Service |
501009 |
ulong panic_task, task, rip, rsp;
|
|
Packit Service |
501009 |
char *sym;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (machine_type("X86") || !get_active_set())
|
|
Packit Service |
501009 |
return NO_TASK;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
bt = (struct bt_info *)GETBUF(sizeof(struct bt_info));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
for (i = 0, panic_task = NO_TASK; i < NR_CPUS; i++) {
|
|
Packit Service |
501009 |
if (!(task = tt->active_set[i]) ||
|
|
Packit Service |
501009 |
!(bt->tc = task_to_context(task)))
|
|
Packit Service |
501009 |
continue;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
bt->task = task;
|
|
Packit Service |
501009 |
bt->stackbase = GET_STACKBASE(task);
|
|
Packit Service |
501009 |
bt->stacktop = GET_STACKTOP(task);
|
|
Packit Service |
501009 |
if (!bt->stackbuf)
|
|
Packit Service |
501009 |
bt->stackbuf = GETBUF(bt->stacktop - bt->stackbase);
|
|
Packit Service |
501009 |
alter_stackbuf(bt);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
bt->flags |= BT_DUMPFILE_SEARCH;
|
|
Packit Service |
501009 |
machdep->get_stack_frame(bt, &rip, &rsp;;
|
|
Packit Service |
501009 |
if (!(bt->flags & BT_DUMPFILE_SEARCH))
|
|
Packit Service |
501009 |
continue;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
sym = closest_symbol(rip);
|
|
Packit Service |
501009 |
if (STREQ(sym, "panic") ||
|
|
Packit Service |
501009 |
STREQ(sym, "die") ||
|
|
Packit Service |
501009 |
STREQ(sym, "die_nmi") ||
|
|
Packit Service |
501009 |
STREQ(sym, "sysrq_handle_crash")) {
|
|
Packit Service |
501009 |
if (CRASHDEBUG(1))
|
|
Packit Service |
501009 |
fprintf(fp, "get_kvmdump_panic_task: %lx\n",
|
|
Packit Service |
501009 |
task);
|
|
Packit Service |
501009 |
panic_task = task;
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (bt->stackbuf)
|
|
Packit Service |
501009 |
FREEBUF(bt->stackbuf);
|
|
Packit Service |
501009 |
FREEBUF(bt);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return panic_task;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
int
|
|
Packit Service |
501009 |
kvmdump_phys_base(unsigned long *phys_base)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
if (KVMDUMP_VALID()) {
|
|
Packit Service |
501009 |
if (CRASHDEBUG(1) && (kvm->mapinfo.cpu_version_id > 9))
|
|
Packit Service |
501009 |
error(NOTE,
|
|
Packit Service |
501009 |
"KVM/QEMU CPU_SAVE_VERSION %d is greater than"
|
|
Packit Service |
501009 |
" supported version 9\n\n",
|
|
Packit Service |
501009 |
kvm->mapinfo.cpu_version_id);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
*phys_base = kvm->mapinfo.phys_base;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return (kvm->flags & NO_PHYS_BASE ? FALSE : TRUE);
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
static int
|
|
Packit Service |
501009 |
cache_page(physaddr_t paddr)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
int idx, err;
|
|
Packit Service |
501009 |
struct kvm_page_cache_hdr *pgc;
|
|
Packit Service |
501009 |
size_t page_size;
|
|
Packit Service |
501009 |
off_t offset;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
kvm->accesses++;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
for (idx = 0; idx < KVMDUMP_CACHED_PAGES; idx++) {
|
|
Packit Service |
501009 |
pgc = &kvm->page_cache[idx];
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (pgc->paddr == CACHE_UNUSED)
|
|
Packit Service |
501009 |
continue;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (pgc->paddr == paddr) {
|
|
Packit Service |
501009 |
kvm->hit_count++;
|
|
Packit Service |
501009 |
kvm->un.curbufptr = pgc->bufptr;
|
|
Packit Service |
501009 |
return idx;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if ((err = load_mapfile_offset(paddr, &offset)) < 0)
|
|
Packit Service |
501009 |
return err;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if ((offset & RAM_OFFSET_COMPRESSED) == RAM_OFFSET_COMPRESSED) {
|
|
Packit Service |
501009 |
kvm->un.compressed = (unsigned char)(offset & 255);
|
|
Packit Service |
501009 |
kvm->compresses++;
|
|
Packit Service |
501009 |
return QEMU_COMPRESSED;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
idx = kvm->evict_index;
|
|
Packit Service |
501009 |
pgc = &kvm->page_cache[idx];
|
|
Packit Service |
501009 |
page_size = memory_page_size();
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (lseek(kvm->vmfd, offset, SEEK_SET) < 0) {
|
|
Packit Service |
501009 |
pgc->paddr = CACHE_UNUSED;
|
|
Packit Service |
501009 |
return SEEK_ERROR;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
if (read(kvm->vmfd, pgc->bufptr, page_size) != page_size) {
|
|
Packit Service |
501009 |
pgc->paddr = CACHE_UNUSED;
|
|
Packit Service |
501009 |
return READ_ERROR;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
kvm->evict_index = (idx+1) % KVMDUMP_CACHED_PAGES;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
pgc->paddr = paddr;
|
|
Packit Service |
501009 |
kvm->un.curbufptr = pgc->bufptr;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return idx;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
static off_t
|
|
Packit Service |
501009 |
mapfile_offset(uint64_t physaddr)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
off_t offset = 0;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
switch (kvm->flags & (TMPFILE|MAPFILE|MAPFILE_APPENDED))
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
case TMPFILE:
|
|
Packit Service |
501009 |
case TMPFILE|MAPFILE_APPENDED:
|
|
Packit Service |
501009 |
case MAPFILE:
|
|
Packit Service |
501009 |
case MAPFILE|MAPFILE_APPENDED:
|
|
Packit Service |
501009 |
offset = (off_t)(((((uint64_t)physaddr/(uint64_t)4096))
|
|
Packit Service |
501009 |
* sizeof(off_t)));
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
case MAPFILE_APPENDED:
|
|
Packit Service |
501009 |
offset = (off_t)(((((uint64_t)physaddr/(uint64_t)4096))
|
|
Packit Service |
501009 |
* sizeof(off_t)) + kvm->mapinfo.map_start_offset);
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return offset;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
int
|
|
Packit Service |
501009 |
store_mapfile_offset(uint64_t physaddr, off_t *entry_ptr)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
if (lseek(kvm->mapfd, mapfile_offset(physaddr), SEEK_SET) < 0) {
|
|
Packit Service |
501009 |
error(INFO, "store_mapfile_offset: "
|
|
Packit Service |
501009 |
"lseek error: physaddr: %llx %s offset: %llx\n",
|
|
Packit Service |
501009 |
(unsigned long long)physaddr, mapfile_in_use(),
|
|
Packit Service |
501009 |
(unsigned long long)mapfile_offset(physaddr));
|
|
Packit Service |
501009 |
return SEEK_ERROR;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (write(kvm->mapfd, entry_ptr, sizeof(off_t)) != sizeof(off_t)) {
|
|
Packit Service |
501009 |
error(INFO, "store_mapfile_offset: "
|
|
Packit Service |
501009 |
"write error: physaddr: %llx %s offset: %llx\n",
|
|
Packit Service |
501009 |
(unsigned long long)physaddr, mapfile_in_use(),
|
|
Packit Service |
501009 |
(unsigned long long)mapfile_offset(physaddr));
|
|
Packit Service |
501009 |
return WRITE_ERROR;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return 0;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
int
|
|
Packit Service |
501009 |
load_mapfile_offset(uint64_t physaddr, off_t *entry_ptr)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
uint64_t kvm_addr = physaddr;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
switch (kvm->iohole)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
case 0x20000000ULL:
|
|
Packit Service |
501009 |
if (physaddr >= 0xe0000000ULL) {
|
|
Packit Service |
501009 |
if (physaddr < 0x100000000ULL)
|
|
Packit Service |
501009 |
return SEEK_ERROR; /* In 512MB I/O hole */
|
|
Packit Service |
501009 |
kvm_addr -= kvm->iohole;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
case 0x40000000ULL:
|
|
Packit Service |
501009 |
if (physaddr >= 0xc0000000ULL) {
|
|
Packit Service |
501009 |
if (physaddr < 0x100000000ULL)
|
|
Packit Service |
501009 |
return SEEK_ERROR; /* In 1GB I/O hole */
|
|
Packit Service |
501009 |
kvm_addr -= kvm->iohole;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (lseek(kvm->mapfd, mapfile_offset(kvm_addr), SEEK_SET) < 0) {
|
|
Packit Service |
501009 |
if (CRASHDEBUG(1))
|
|
Packit Service |
501009 |
error(INFO, "load_mapfile_offset: "
|
|
Packit Service |
501009 |
"lseek error: physical: %llx %s offset: %llx\n",
|
|
Packit Service |
501009 |
(unsigned long long)physaddr, mapfile_in_use(),
|
|
Packit Service |
501009 |
(unsigned long long)mapfile_offset(kvm_addr));
|
|
Packit Service |
501009 |
return SEEK_ERROR;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (read(kvm->mapfd, entry_ptr, sizeof(off_t)) != sizeof(off_t)) {
|
|
Packit Service |
501009 |
if (CRASHDEBUG(1))
|
|
Packit Service |
501009 |
error(INFO, "load_mapfile_offset: "
|
|
Packit Service |
501009 |
"read error: physical: %llx %s offset: %llx\n",
|
|
Packit Service |
501009 |
(unsigned long long)physaddr, mapfile_in_use(),
|
|
Packit Service |
501009 |
(unsigned long long)mapfile_offset(kvm_addr));
|
|
Packit Service |
501009 |
return READ_ERROR;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return 0;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
static void
|
|
Packit Service |
501009 |
kvmdump_mapfile_create(char *filename)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
int fdmem, n;
|
|
Packit Service |
501009 |
off_t offset;
|
|
Packit Service |
501009 |
char buf[4096];
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (kvm->flags & MAPFILE) {
|
|
Packit Service |
501009 |
error(INFO, "%s: mapfile in use\n", pc->kvmdump_mapfile);
|
|
Packit Service |
501009 |
return;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (file_exists(filename, NULL)) {
|
|
Packit Service |
501009 |
error(INFO,
|
|
Packit Service |
501009 |
"%s: file already exists!\n", filename);
|
|
Packit Service |
501009 |
return;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if ((fdmem = open(filename, O_CREAT|O_RDWR, 0644)) < 0) {
|
|
Packit Service |
501009 |
error(INFO, "%s: open: %s\n", filename, strerror(errno));
|
|
Packit Service |
501009 |
return;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
offset = kvm->mapinfo.map_start_offset;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (lseek(kvm->mapfd, offset, SEEK_SET) < 0) {
|
|
Packit Service |
501009 |
error(INFO, "%s: leek: %s\n",
|
|
Packit Service |
501009 |
mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
return;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
while ((n = read(kvm->mapfd, buf, 4096)) > 0) {
|
|
Packit Service |
501009 |
if (write(fdmem, buf, n) != n) {
|
|
Packit Service |
501009 |
error(INFO, "%s: write: %s\n", filename,
|
|
Packit Service |
501009 |
strerror(errno));
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
close(fdmem);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
fprintf(fp, "MAP FILE CREATED: %s\n", filename);
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
static void
|
|
Packit Service |
501009 |
kvmdump_mapfile_append(void)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
int n, fdcore;
|
|
Packit Service |
501009 |
ulong round_bytes;
|
|
Packit Service |
501009 |
struct stat statbuf;
|
|
Packit Service |
501009 |
uint64_t map_start_offset;
|
|
Packit Service |
501009 |
off_t eof, orig_dumpfile_size;
|
|
Packit Service |
501009 |
char buf[4096];
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (kvm->flags & MAPFILE_APPENDED)
|
|
Packit Service |
501009 |
error(FATAL, "mapfile already appended to %s\n",
|
|
Packit Service |
501009 |
pc->dumpfile);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (access(pc->dumpfile, W_OK) != 0)
|
|
Packit Service |
501009 |
error(FATAL,
|
|
Packit Service |
501009 |
"%s: cannot append map information to this file\n",
|
|
Packit Service |
501009 |
pc->dumpfile);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (stat(pc->dumpfile, &statbuf) < 0)
|
|
Packit Service |
501009 |
error(FATAL, "%s: stat: %s\n",
|
|
Packit Service |
501009 |
pc->dumpfile, strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
round_bytes = (sizeof(uint64_t) - (statbuf.st_size % sizeof(uint64_t)))
|
|
Packit Service |
501009 |
% sizeof(uint64_t);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if ((fdcore = open(pc->dumpfile, O_WRONLY)) < 0)
|
|
Packit Service |
501009 |
error(FATAL, "%s: open: %s\n",
|
|
Packit Service |
501009 |
pc->dumpfile, strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if ((orig_dumpfile_size = lseek(fdcore, 0, SEEK_END)) < 0) {
|
|
Packit Service |
501009 |
error(INFO, "%s: lseek: %s\n", pc->dumpfile, strerror(errno));
|
|
Packit Service |
501009 |
goto bailout1;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (round_bytes) {
|
|
Packit Service |
501009 |
BZERO(buf, round_bytes);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (write(fdcore, buf, round_bytes) != round_bytes) {
|
|
Packit Service |
501009 |
error(INFO, "%s: write: %s\n",
|
|
Packit Service |
501009 |
pc->dumpfile, strerror(errno));
|
|
Packit Service |
501009 |
goto bailout2;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
map_start_offset = orig_dumpfile_size + round_bytes;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (lseek(kvm->mapfd, 0, SEEK_SET) != 0) {
|
|
Packit Service |
501009 |
error(INFO, "%s: lseek: %s\n",
|
|
Packit Service |
501009 |
mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
goto bailout2;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
while ((n = read(kvm->mapfd, buf, 4096)) > 0) {
|
|
Packit Service |
501009 |
if (write(fdcore, buf, n) != n) {
|
|
Packit Service |
501009 |
error(INFO, "%s: write: %s\n", pc->dumpfile,
|
|
Packit Service |
501009 |
strerror(errno));
|
|
Packit Service |
501009 |
goto bailout2;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
/*
|
|
Packit Service |
501009 |
* Overwrite the map_start_offset value in the trailer to reflect
|
|
Packit Service |
501009 |
* its location in the appended-to dumpfile.
|
|
Packit Service |
501009 |
*/
|
|
Packit Service |
501009 |
eof = lseek(fdcore, 0, SEEK_END);
|
|
Packit Service |
501009 |
if (lseek(fdcore, eof - sizeof(struct mapinfo_trailer), SEEK_SET) < 0) {
|
|
Packit Service |
501009 |
error(INFO, "%s: write: %s\n", pc->dumpfile, strerror(errno));
|
|
Packit Service |
501009 |
goto bailout2;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
if (write(fdcore, &map_start_offset, sizeof(uint64_t)) != sizeof(uint64_t)) {
|
|
Packit Service |
501009 |
error(INFO, "%s: write: %s\n", pc->dumpfile, strerror(errno));
|
|
Packit Service |
501009 |
goto bailout2;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
close(fdcore);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
kvm->flags |= MAPFILE_APPENDED;
|
|
Packit Service |
501009 |
fprintf(fp, "MAP FILE APPENDED TO: %s\n", pc->dumpfile);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
bailout2:
|
|
Packit Service |
501009 |
if (ftruncate(fdcore, (off_t)orig_dumpfile_size) < 0)
|
|
Packit Service |
501009 |
error(INFO, "%s: ftruncate: %s\n",
|
|
Packit Service |
501009 |
pc->dumpfile, strerror(errno));
|
|
Packit Service |
501009 |
bailout1:
|
|
Packit Service |
501009 |
close(fdcore);
|
|
Packit Service |
501009 |
error(INFO, "failed to append map to %s\n", pc->dumpfile);
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
int
|
|
Packit Service |
501009 |
is_kvmdump_mapfile(char *filename)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
int fd;
|
|
Packit Service |
501009 |
struct mapinfo_trailer trailer;
|
|
Packit Service |
501009 |
off_t eof;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if ((fd = open(filename, O_RDONLY)) < 0) {
|
|
Packit Service |
501009 |
error(INFO, "%s: open: %s\n", filename, strerror(errno));
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if ((eof = lseek(fd, 0, SEEK_END)) == -1)
|
|
Packit Service |
501009 |
goto bailout;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (lseek(fd, eof - sizeof(trailer), SEEK_SET) < 0) {
|
|
Packit Service |
501009 |
error(INFO, "%s: lseek: %s\n", filename, strerror(errno));
|
|
Packit Service |
501009 |
goto bailout;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (read(fd, &trailer, sizeof(trailer)) != sizeof(trailer)) {
|
|
Packit Service |
501009 |
error(INFO, "%s: read: %s\n", filename, strerror(errno));
|
|
Packit Service |
501009 |
goto bailout;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (trailer.magic == MAPFILE_MAGIC) {
|
|
Packit Service |
501009 |
if (pc->dumpfile && (trailer.checksum != kvm->mapinfo.checksum)) {
|
|
Packit Service |
501009 |
error(kvm->flags & MAPFILE_FOUND ? INFO : FATAL,
|
|
Packit Service |
501009 |
"checksum mismatch between %s and %s\n\n",
|
|
Packit Service |
501009 |
pc->dumpfile, filename);
|
|
Packit Service |
501009 |
goto bailout;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
kvm->mapfd = fd;
|
|
Packit Service |
501009 |
kvm->flags |= MAPFILE;
|
|
Packit Service |
501009 |
return TRUE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
bailout:
|
|
Packit Service |
501009 |
close(fd);
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
static int
|
|
Packit Service |
501009 |
kvmdump_mapfile_exists(void)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
char *filename;
|
|
Packit Service |
501009 |
struct stat stat;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (!(filename = malloc(strlen(pc->dumpfile) + strlen(".map") + 10)))
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
sprintf(filename, "%s.map", pc->dumpfile);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (!file_exists(filename, &stat) || !S_ISREG(stat.st_mode)) {
|
|
Packit Service |
501009 |
free(filename);
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (is_kvmdump_mapfile(filename)) {
|
|
Packit Service |
501009 |
pc->kvmdump_mapfile = filename;
|
|
Packit Service |
501009 |
kvm->flags |= MAPFILE_FOUND;
|
|
Packit Service |
501009 |
return TRUE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
free(filename);
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
void
|
|
Packit Service |
501009 |
cmd_map(void)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
int c;
|
|
Packit Service |
501009 |
int append, file, specified;
|
|
Packit Service |
501009 |
char *mapfile;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
append = file = specified = 0;
|
|
Packit Service |
501009 |
mapfile = NULL;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
while ((c = getopt(argcnt, args, "af")) != EOF) {
|
|
Packit Service |
501009 |
switch(c)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
case 'a':
|
|
Packit Service |
501009 |
append++;
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
case 'f':
|
|
Packit Service |
501009 |
file++;
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
default:
|
|
Packit Service |
501009 |
argerrs++;
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (argerrs)
|
|
Packit Service |
501009 |
cmd_usage(pc->curcmd, SYNOPSIS);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
while (args[optind]) {
|
|
Packit Service |
501009 |
if (!mapfile) {
|
|
Packit Service |
501009 |
mapfile = args[optind];
|
|
Packit Service |
501009 |
specified++;
|
|
Packit Service |
501009 |
} else
|
|
Packit Service |
501009 |
cmd_usage(pc->curcmd, SYNOPSIS);
|
|
Packit Service |
501009 |
optind++;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (file && !specified) {
|
|
Packit Service |
501009 |
mapfile = GETBUF(strlen(pc->dumpfile)+10);
|
|
Packit Service |
501009 |
sprintf(mapfile, "%s.map", pc->dumpfile);
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (append)
|
|
Packit Service |
501009 |
kvmdump_mapfile_append();
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (file) {
|
|
Packit Service |
501009 |
kvmdump_mapfile_create(mapfile);
|
|
Packit Service |
501009 |
if (!specified)
|
|
Packit Service |
501009 |
FREEBUF(mapfile);
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (!file && !append)
|
|
Packit Service |
501009 |
fprintf(fp, "MAP FILE IN USE: %s\n", mapfile_in_use());
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
static char *
|
|
Packit Service |
501009 |
mapfile_in_use(void)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
char *name;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
switch (kvm->flags & (TMPFILE|MAPFILE|MAPFILE_APPENDED))
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
default:
|
|
Packit Service |
501009 |
case TMPFILE:
|
|
Packit Service |
501009 |
case TMPFILE|MAPFILE_APPENDED:
|
|
Packit Service |
501009 |
name = "(tmpfile)";
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
case MAPFILE:
|
|
Packit Service |
501009 |
case MAPFILE|MAPFILE_APPENDED:
|
|
Packit Service |
501009 |
name = pc->kvmdump_mapfile;
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
case MAPFILE_APPENDED:
|
|
Packit Service |
501009 |
name = pc->dumpfile;
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return name;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
static void
|
|
Packit Service |
501009 |
write_mapfile_trailer(void)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
if (kvm->cpu_devices)
|
|
Packit Service |
501009 |
write_mapfile_registers();
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
kvm->mapinfo.magic = MAPFILE_MAGIC;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (lseek(kvm->mapfd, 0, SEEK_END) < 0)
|
|
Packit Service |
501009 |
error(FATAL, "%s: lseek: %s\n", mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (write(kvm->mapfd, &kvm->mapinfo, sizeof(struct mapinfo_trailer))
|
|
Packit Service |
501009 |
!= sizeof(struct mapinfo_trailer))
|
|
Packit Service |
501009 |
error(FATAL, "%s: write: %s\n", mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
static void
|
|
Packit Service |
501009 |
write_mapfile_registers(void)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
size_t regs_size;
|
|
Packit Service |
501009 |
uint64_t magic;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (lseek(kvm->mapfd, 0, SEEK_END) < 0)
|
|
Packit Service |
501009 |
error(FATAL, "%s: lseek: %s\n", mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
regs_size = sizeof(struct register_set) * kvm->cpu_devices;
|
|
Packit Service |
501009 |
if (write(kvm->mapfd, &kvm->registers[0], regs_size) != regs_size)
|
|
Packit Service |
501009 |
error(FATAL, "%s: write: %s\n", mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (write(kvm->mapfd, &kvm->cpu_devices, sizeof(uint64_t)) != sizeof(uint64_t))
|
|
Packit Service |
501009 |
error(FATAL, "%s: write: %s\n", mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
magic = REGS_MAGIC;
|
|
Packit Service |
501009 |
if (write(kvm->mapfd, &magic, sizeof(uint64_t)) != sizeof(uint64_t))
|
|
Packit Service |
501009 |
error(FATAL, "%s: write: %s\n", mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
static void
|
|
Packit Service |
501009 |
read_mapfile_trailer(void)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
off_t eof;
|
|
Packit Service |
501009 |
struct mapinfo_trailer trailer;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if ((eof = lseek(kvm->mapfd, 0, SEEK_END)) < 0)
|
|
Packit Service |
501009 |
error(FATAL, "%s: lseek: %s\n",
|
|
Packit Service |
501009 |
mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (lseek(kvm->mapfd, eof - sizeof(trailer), SEEK_SET) < 0)
|
|
Packit Service |
501009 |
error(FATAL, "%s: lseek: %s\n",
|
|
Packit Service |
501009 |
mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (read(kvm->mapfd, &trailer, sizeof(trailer)) != sizeof(trailer))
|
|
Packit Service |
501009 |
error(FATAL, "%s: read: %s\n",
|
|
Packit Service |
501009 |
mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (kvm->mapinfo.checksum != trailer.checksum)
|
|
Packit Service |
501009 |
error(FATAL, "checksum mismatch between %s and %s\n",
|
|
Packit Service |
501009 |
pc->dumpfile, mapfile_in_use());
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
kvm->mapinfo = trailer;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
read_mapfile_registers();
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
static void
|
|
Packit Service |
501009 |
read_mapfile_registers(void)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
size_t regs_size;
|
|
Packit Service |
501009 |
uint64_t ncpus, magic;
|
|
Packit Service |
501009 |
off_t offset;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if ((offset = lseek(kvm->mapfd, 0, SEEK_END)) < 0)
|
|
Packit Service |
501009 |
error(FATAL, "%s: lseek: %s\n",
|
|
Packit Service |
501009 |
mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
offset -= sizeof(struct mapinfo_trailer) +
|
|
Packit Service |
501009 |
sizeof(magic) + sizeof(ncpus);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (lseek(kvm->mapfd, offset, SEEK_SET) < 0)
|
|
Packit Service |
501009 |
error(FATAL, "%s: lseek: %s\n",
|
|
Packit Service |
501009 |
mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (read(kvm->mapfd, &ncpus, sizeof(uint64_t)) != sizeof(uint64_t))
|
|
Packit Service |
501009 |
error(FATAL, "%s: read: %s\n",
|
|
Packit Service |
501009 |
mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (read(kvm->mapfd, &magic, sizeof(uint64_t)) != sizeof(uint64_t))
|
|
Packit Service |
501009 |
error(FATAL, "%s: read: %s\n",
|
|
Packit Service |
501009 |
mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if ((magic != REGS_MAGIC) || (ncpus >= NR_CPUS)) {
|
|
Packit Service |
501009 |
kvm->flags |= REGS_NOT_AVAIL;
|
|
Packit Service |
501009 |
return;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
regs_size = sizeof(struct register_set) * ncpus;
|
|
Packit Service |
501009 |
offset -= regs_size;
|
|
Packit Service |
501009 |
if (lseek(kvm->mapfd, offset, SEEK_SET) < 0)
|
|
Packit Service |
501009 |
error(FATAL, "%s: lseek: %s\n",
|
|
Packit Service |
501009 |
mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (read(kvm->mapfd, &kvm->registers[0], regs_size) != regs_size)
|
|
Packit Service |
501009 |
error(FATAL, "%s: read: %s\n",
|
|
Packit Service |
501009 |
mapfile_in_use(), strerror(errno));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
kvm->cpu_devices = ncpus;
|
|
Packit Service |
501009 |
kvm->flags |= REGS_FROM_MAPFILE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
void
|
|
Packit Service |
501009 |
set_kvmhost_type(char *host)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
if (!machine_type("X86")) {
|
|
Packit Service |
501009 |
error(INFO,
|
|
Packit Service |
501009 |
"--kvmhost is only applicable to the X86 architecture\n");
|
|
Packit Service |
501009 |
return;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (STREQ(host, "32")) {
|
|
Packit Service |
501009 |
kvm->flags &= ~KVMHOST_64;
|
|
Packit Service |
501009 |
kvm->flags |= KVMHOST_32;
|
|
Packit Service |
501009 |
} else if (STREQ(host, "64")) {
|
|
Packit Service |
501009 |
kvm->flags &= ~KVMHOST_32;
|
|
Packit Service |
501009 |
kvm->flags |= KVMHOST_64;
|
|
Packit Service |
501009 |
} else
|
|
Packit Service |
501009 |
error(INFO, "invalid --kvmhost argument: %s\n", host);
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
/*
|
|
Packit Service |
501009 |
* set_kvm_iohole() is called from main() with a command line argument,
|
|
Packit Service |
501009 |
* or from the x86/x86_64_init functions for assistance in determining
|
|
Packit Service |
501009 |
* the I/O hole size.
|
|
Packit Service |
501009 |
*/
|
|
Packit Service |
501009 |
void
|
|
Packit Service |
501009 |
set_kvm_iohole(char *optarg)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
#define DEFAULT_IOHOLE() \
|
|
Packit Service |
501009 |
((kvm->mapinfo.cpu_version_id <= 9) ? 0x40000000 : 0x20000000)
|
|
Packit Service |
501009 |
#define E820_RAM 1
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (optarg) {
|
|
Packit Service |
501009 |
ulong flags;
|
|
Packit Service |
501009 |
ulonglong iohole;
|
|
Packit Service |
501009 |
char *arg;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
flags = LONG_LONG;
|
|
Packit Service |
501009 |
if (IS_A_NUMBER(&LASTCHAR(optarg)))
|
|
Packit Service |
501009 |
flags |= HEX_BIAS;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
arg = strdup(optarg);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (!calculate(arg, NULL, &iohole, flags))
|
|
Packit Service |
501009 |
error(FATAL,
|
|
Packit Service |
501009 |
"invalid --kvm_iohole argument: %s\n", optarg);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
free(arg);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
/*
|
|
Packit Service |
501009 |
* Only 512MB or 1GB have been used to date.
|
|
Packit Service |
501009 |
*/
|
|
Packit Service |
501009 |
if ((iohole != 0x20000000ULL) && (iohole != 0x40000000ULL))
|
|
Packit Service |
501009 |
error(WARNING, "questionable --kvmio argument: %s\n",
|
|
Packit Service |
501009 |
optarg);
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
kvm->iohole = iohole;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
} else {
|
|
Packit Service |
501009 |
int nr_map, i;
|
|
Packit Service |
501009 |
char *buf, *e820entry;
|
|
Packit Service |
501009 |
ulonglong addr, size, ending_addr;
|
|
Packit Service |
501009 |
uint type;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (kvm->iohole)
|
|
Packit Service |
501009 |
return; /* set by command line option below */
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
kvm->iohole = DEFAULT_IOHOLE();
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (!symbol_exists("e820"))
|
|
Packit Service |
501009 |
return;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
buf = (char *)GETBUF(SIZE(e820map));
|
|
Packit Service |
501009 |
if (!readmem(symbol_value("e820"), KVADDR, &buf[0],
|
|
Packit Service |
501009 |
SIZE(e820map), "e820map", RETURN_ON_ERROR|QUIET)) {
|
|
Packit Service |
501009 |
FREEBUF(buf);
|
|
Packit Service |
501009 |
return;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
nr_map = INT(buf + OFFSET(e820map_nr_map));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
for (i = 0; i < nr_map; i++) {
|
|
Packit Service |
501009 |
e820entry = buf + sizeof(int) + (SIZE(e820entry) * i);
|
|
Packit Service |
501009 |
addr = ULONGLONG(e820entry + OFFSET(e820entry_addr));
|
|
Packit Service |
501009 |
size = ULONGLONG(e820entry + OFFSET(e820entry_size));
|
|
Packit Service |
501009 |
type = UINT(e820entry + OFFSET(e820entry_type));
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (type != E820_RAM)
|
|
Packit Service |
501009 |
continue;
|
|
Packit Service |
501009 |
if (addr >= 0x100000000ULL)
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
ending_addr = addr + size;
|
|
Packit Service |
501009 |
if ((ending_addr > 0xc0000000ULL) &&
|
|
Packit Service |
501009 |
(ending_addr <= 0xe0000000ULL)) {
|
|
Packit Service |
501009 |
kvm->iohole = 0x20000000ULL;
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
FREEBUF(buf);
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
#include "qemu-load.h"
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
int
|
|
Packit Service |
501009 |
kvmdump_regs_store(uint32_t cpu, struct qemu_device_x86 *dx86)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
struct register_set *rp;
|
|
Packit Service |
501009 |
int retval;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
retval = TRUE;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
switch (cpu)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
case KVMDUMP_REGS_START:
|
|
Packit Service |
501009 |
if ((kvm->registers =
|
|
Packit Service |
501009 |
calloc(NR_CPUS, sizeof(struct register_set))) == NULL)
|
|
Packit Service |
501009 |
error(FATAL, "kvmdump_regs_store: "
|
|
Packit Service |
501009 |
"cannot malloc KVM register_set array\n");
|
|
Packit Service |
501009 |
kvm->cpu_devices = 0;
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
case KVMDUMP_REGS_END:
|
|
Packit Service |
501009 |
if (kvm->cpu_devices == 0) {
|
|
Packit Service |
501009 |
free(kvm->registers);
|
|
Packit Service |
501009 |
kvm->registers = NULL;
|
|
Packit Service |
501009 |
} else if ((kvm->registers = realloc(kvm->registers,
|
|
Packit Service |
501009 |
sizeof(struct register_set) * kvm->cpu_devices)) == NULL)
|
|
Packit Service |
501009 |
error(FATAL, "kvmdump_regs_store: "
|
|
Packit Service |
501009 |
"cannot realloc KVM registers array\n");
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
default:
|
|
Packit Service |
501009 |
if (cpu >= NR_CPUS) {
|
|
Packit Service |
501009 |
if (machine_type("X86") &&
|
|
Packit Service |
501009 |
!(kvm->flags & (KVMHOST_32|KVMHOST_64)))
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
rp = &kvm->registers[cpu];
|
|
Packit Service |
501009 |
rp->ip = dx86->eip;
|
|
Packit Service |
501009 |
rp->flags = dx86->eflags;
|
|
Packit Service |
501009 |
rp->cs = dx86->cs.selector;
|
|
Packit Service |
501009 |
rp->ss = dx86->ss.selector;
|
|
Packit Service |
501009 |
rp->ds = dx86->ds.selector;
|
|
Packit Service |
501009 |
rp->es = dx86->es.selector;
|
|
Packit Service |
501009 |
rp->fs = dx86->fs.selector;
|
|
Packit Service |
501009 |
rp->gs = dx86->gs.selector;
|
|
Packit Service |
501009 |
BCOPY(dx86->regs, rp->regs, 16*sizeof(uint64_t));
|
|
Packit Service |
501009 |
kvm->cpu_devices = cpu+1;
|
|
Packit Service |
501009 |
kvm->flags |= REGS_FROM_DUMPFILE;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (machine_type("X86_64") ||
|
|
Packit Service |
501009 |
(kvm->flags & (KVMHOST_32|KVMHOST_64)))
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if ((rp->regs[R_EAX] & UPPER_32_BITS) ||
|
|
Packit Service |
501009 |
(rp->regs[R_EBX] & UPPER_32_BITS) ||
|
|
Packit Service |
501009 |
(rp->regs[R_ECX] & UPPER_32_BITS) ||
|
|
Packit Service |
501009 |
(rp->regs[R_EDX] & UPPER_32_BITS) ||
|
|
Packit Service |
501009 |
(rp->regs[R_ESI] & UPPER_32_BITS) ||
|
|
Packit Service |
501009 |
(rp->regs[R_EDI] & UPPER_32_BITS) ||
|
|
Packit Service |
501009 |
(rp->regs[R_ESP] & UPPER_32_BITS) ||
|
|
Packit Service |
501009 |
(rp->regs[R_EBP] & UPPER_32_BITS) ||
|
|
Packit Service |
501009 |
(rp->ip & UPPER_32_BITS))
|
|
Packit Service |
501009 |
retval = FALSE;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
break;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return retval;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
int
|
|
Packit Service |
501009 |
get_kvm_register_set(int cpu, struct kvm_register_set *krs)
|
|
Packit Service |
501009 |
{
|
|
Packit Service |
501009 |
struct register_set *rs = &kvm->registers[cpu];
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (!krs)
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
if (machine_type("X86") || machine_type("X86_64")) {
|
|
Packit Service |
501009 |
krs->x86.cs = rs->cs;
|
|
Packit Service |
501009 |
krs->x86.ss = rs->ss;
|
|
Packit Service |
501009 |
krs->x86.ds = rs->ds;
|
|
Packit Service |
501009 |
krs->x86.es = rs->es;
|
|
Packit Service |
501009 |
krs->x86.fs = rs->fs;
|
|
Packit Service |
501009 |
krs->x86.gs = rs->gs;
|
|
Packit Service |
501009 |
krs->x86.ip = rs->ip;
|
|
Packit Service |
501009 |
krs->x86.flags = rs->flags;
|
|
Packit Service |
501009 |
krs->x86.regs[0] = rs->regs[0];
|
|
Packit Service |
501009 |
krs->x86.regs[1] = rs->regs[1];
|
|
Packit Service |
501009 |
krs->x86.regs[2] = rs->regs[2];
|
|
Packit Service |
501009 |
krs->x86.regs[3] = rs->regs[3];
|
|
Packit Service |
501009 |
krs->x86.regs[4] = rs->regs[4];
|
|
Packit Service |
501009 |
krs->x86.regs[5] = rs->regs[5];
|
|
Packit Service |
501009 |
krs->x86.regs[6] = rs->regs[6];
|
|
Packit Service |
501009 |
krs->x86.regs[7] = rs->regs[7];
|
|
Packit Service |
501009 |
krs->x86.regs[8] = rs->regs[8];
|
|
Packit Service |
501009 |
krs->x86.regs[9] = rs->regs[9];
|
|
Packit Service |
501009 |
krs->x86.regs[10] = rs->regs[10];
|
|
Packit Service |
501009 |
krs->x86.regs[11] = rs->regs[11];
|
|
Packit Service |
501009 |
krs->x86.regs[12] = rs->regs[12];
|
|
Packit Service |
501009 |
krs->x86.regs[13] = rs->regs[13];
|
|
Packit Service |
501009 |
krs->x86.regs[14] = rs->regs[14];
|
|
Packit Service |
501009 |
krs->x86.regs[15] = rs->regs[15];
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return TRUE;
|
|
Packit Service |
501009 |
}
|
|
Packit Service |
501009 |
|
|
Packit Service |
501009 |
return FALSE;
|
|
Packit Service |
501009 |
}
|