From patchwork Wed Apr 18 12:55:57 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wen Congyang X-Patchwork-Id: 153500 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id CECA3B6EF3 for ; Wed, 18 Apr 2012 22:53:08 +1000 (EST) Received: from localhost ([::1]:37710 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SKUNc-0008Fa-0x for incoming@patchwork.ozlabs.org; Wed, 18 Apr 2012 08:53:04 -0400 Received: from eggs.gnu.org ([208.118.235.92]:47246) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SKUNS-0008EP-4G for qemu-devel@nongnu.org; Wed, 18 Apr 2012 08:52:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SKUNN-0006Gd-L4 for qemu-devel@nongnu.org; Wed, 18 Apr 2012 08:52:53 -0400 Received: from [222.73.24.84] (port=16323 helo=song.cn.fujitsu.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SKUNM-0006DV-7i for qemu-devel@nongnu.org; Wed, 18 Apr 2012 08:52:49 -0400 X-IronPort-AV: E=Sophos;i="4.75,441,1330876800"; d="scan'208";a="4783519" Received: from unknown (HELO tang.cn.fujitsu.com) ([10.167.250.3]) by song.cn.fujitsu.com with ESMTP; 18 Apr 2012 20:52:25 +0800 Received: from mailserver.fnst.cn.fujitsu.com (tang.cn.fujitsu.com [127.0.0.1]) by tang.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id q3ICqiwa020662; Wed, 18 Apr 2012 20:52:44 +0800 Received: from [10.167.225.226] ([10.167.225.226]) by mailserver.fnst.cn.fujitsu.com (Lotus Domino Release 8.5.3) with ESMTP id 2012041820515072-62321 ; Wed, 18 Apr 2012 20:51:50 +0800 Message-ID: <4F8EB9DD.2050406@cn.fujitsu.com> Date: Wed, 18 Apr 2012 20:55:57 +0800 From: Wen Congyang User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100413 Fedora/3.0.4-2.fc13 Thunderbird/3.0.4 MIME-Version: 1.0 To: qemu-devel , HATAYAMA Daisuke , Luiz Capitulino , "Daniel P. Berrange" References: <4F8EB840.90108@cn.fujitsu.com> In-Reply-To: <4F8EB840.90108@cn.fujitsu.com> X-MIMETrack: Itemize by SMTP Server on mailserver/fnst(Release 8.5.3|September 15, 2011) at 2012/04/18 20:51:50, Serialize by Router on mailserver/fnst(Release 8.5.3|September 15, 2011) at 2012/04/18 20:51:50, Serialize complete at 2012/04/18 20:51:50 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 222.73.24.84 Subject: [Qemu-devel] [PATCH 08/12 v13] target-i386: Add API to write cpu status to core file X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The core file has register's value. But it does not include all registers value. Store the cpu status into QEMU note, and the user can get more information from vmcore. If you change QEMUCPUState, please count up QEMUCPUSTATE_VERSION. Signed-off-by: Wen Congyang --- cpu-all.h | 18 ++++++ target-i386/arch_dump.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 0 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index f23b578..0ea1f7f 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -549,6 +549,10 @@ int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env, int cpuid, void *opaque); int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env, int cpuid, void *opaque); +int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env, + void *opaque); +int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env, + void *opaque); #else static inline int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env, int cpuid, @@ -563,6 +567,20 @@ static inline int cpu_write_elf32_note(write_core_dump_function f, { return -1; } + +static inline int cpu_write_elf64_qemunote(write_core_dump_function f, + CPUArchState *env, + void *opaque); +{ + return -1; +} + +static inline int cpu_write_elf32_qemunote(write_core_dump_function f, + CPUArchState *env, + void *opaque) +{ + return -1; +} #endif #endif /* CPU_ALL_H */ diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c index d55c2ce..ddbe20c 100644 --- a/target-i386/arch_dump.c +++ b/target-i386/arch_dump.c @@ -231,3 +231,152 @@ int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env, return 0; } + +/* + * please count up QEMUCPUSTATE_VERSION if you have changed definition of + * QEMUCPUState, and modify the tools using this information accordingly. + */ +#define QEMUCPUSTATE_VERSION (1) + +struct QEMUCPUSegment { + uint32_t selector; + uint32_t limit; + uint32_t flags; + uint32_t pad; + uint64_t base; +}; + +typedef struct QEMUCPUSegment QEMUCPUSegment; + +struct QEMUCPUState { + uint32_t version; + uint32_t size; + uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp; + uint64_t r8, r9, r10, r11, r12, r13, r14, r15; + uint64_t rip, rflags; + QEMUCPUSegment cs, ds, es, fs, gs, ss; + QEMUCPUSegment ldt, tr, gdt, idt; + uint64_t cr[5]; +}; + +typedef struct QEMUCPUState QEMUCPUState; + +static void copy_segment(QEMUCPUSegment *d, SegmentCache *s) +{ + d->pad = 0; + d->selector = s->selector; + d->limit = s->limit; + d->flags = s->flags; + d->base = s->base; +} + +static void qemu_get_cpustate(QEMUCPUState *s, CPUArchState *env) +{ + memset(s, 0, sizeof(QEMUCPUState)); + + s->version = QEMUCPUSTATE_VERSION; + s->size = sizeof(QEMUCPUState); + + s->rax = env->regs[R_EAX]; + s->rbx = env->regs[R_EBX]; + s->rcx = env->regs[R_ECX]; + s->rdx = env->regs[R_EDX]; + s->rsi = env->regs[R_ESI]; + s->rdi = env->regs[R_EDI]; + s->rsp = env->regs[R_ESP]; + s->rbp = env->regs[R_EBP]; +#ifdef TARGET_X86_64 + s->r8 = env->regs[8]; + s->r9 = env->regs[9]; + s->r10 = env->regs[10]; + s->r11 = env->regs[11]; + s->r12 = env->regs[12]; + s->r13 = env->regs[13]; + s->r14 = env->regs[14]; + s->r15 = env->regs[15]; +#endif + s->rip = env->eip; + s->rflags = env->eflags; + + copy_segment(&s->cs, &env->segs[R_CS]); + copy_segment(&s->ds, &env->segs[R_DS]); + copy_segment(&s->es, &env->segs[R_ES]); + copy_segment(&s->fs, &env->segs[R_FS]); + copy_segment(&s->gs, &env->segs[R_GS]); + copy_segment(&s->ss, &env->segs[R_SS]); + copy_segment(&s->ldt, &env->ldt); + copy_segment(&s->tr, &env->tr); + copy_segment(&s->gdt, &env->gdt); + copy_segment(&s->idt, &env->idt); + + s->cr[0] = env->cr[0]; + s->cr[1] = env->cr[1]; + s->cr[2] = env->cr[2]; + s->cr[3] = env->cr[3]; + s->cr[4] = env->cr[4]; +} + +static inline int cpu_write_qemu_note(write_core_dump_function f, + CPUArchState *env, + void *opaque, + int type) +{ + QEMUCPUState state; + Elf64_Nhdr *note64; + Elf32_Nhdr *note32; + void *note; + char *buf; + int descsz, note_size, name_size = 5, note_head_size; + const char *name = "QEMU"; + int ret; + + qemu_get_cpustate(&state, env); + + descsz = sizeof(state); + if (type == 0) { + note_head_size = sizeof(Elf32_Nhdr); + } else { + note_head_size = sizeof(Elf64_Nhdr); + } + note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 + + (descsz + 3) / 4) * 4; + note = g_malloc(note_size); + + memset(note, 0, note_size); + if (type == 0) { + note32 = note; + note32->n_namesz = cpu_to_le32(name_size); + note32->n_descsz = cpu_to_le32(descsz); + note32->n_type = 0; + } else { + note64 = note; + note64->n_namesz = cpu_to_le32(name_size); + note64->n_descsz = cpu_to_le32(descsz); + note64->n_type = 0; + } + buf = note; + buf += ((note_head_size + 3) / 4) * 4; + memcpy(buf, name, name_size); + buf += ((name_size + 3) / 4) * 4; + memcpy(buf, &state, sizeof(state)); + + ret = f(note, note_size, opaque); + g_free(note); + if (ret < 0) { + return -1; + } + + return 0; +} + +int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env, + void *opaque) +{ + return cpu_write_qemu_note(f, env, opaque, 1); +} + +int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env, + void *opaque) +{ + return cpu_write_qemu_note(f, env, opaque, 0); +}