From patchwork Thu Mar 1 02:48:17 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wen Congyang X-Patchwork-Id: 143879 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 01F13B6EF3 for ; Thu, 1 Mar 2012 13:47:22 +1100 (EST) Received: from localhost ([::1]:47125 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S2w35-00036z-Vn for incoming@patchwork.ozlabs.org; Wed, 29 Feb 2012 21:47:19 -0500 Received: from eggs.gnu.org ([208.118.235.92]:41223) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S2w2y-00036V-9q for qemu-devel@nongnu.org; Wed, 29 Feb 2012 21:47:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S2w2v-0005UJ-GM for qemu-devel@nongnu.org; Wed, 29 Feb 2012 21:47:11 -0500 Received: from [222.73.24.84] (port=57075 helo=song.cn.fujitsu.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S2w2t-0005Sn-VJ for qemu-devel@nongnu.org; Wed, 29 Feb 2012 21:47:09 -0500 Received: from tang.cn.fujitsu.com (tang.cn.fujitsu.com [10.167.250.3]) by song.cn.fujitsu.com (Postfix) with ESMTP id 7FC7217008E; Thu, 1 Mar 2012 10:47:02 +0800 (CST) 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 q212l0B3007822; Thu, 1 Mar 2012 10:47:00 +0800 Received: from [10.167.225.226] ([10.167.225.226]) by mailserver.fnst.cn.fujitsu.com (Lotus Domino Release 8.5.1FP4) with ESMTP id 2012030110451272-829587 ; Thu, 1 Mar 2012 10:45:12 +0800 Message-ID: <4F4EE371.6000601@cn.fujitsu.com> Date: Thu, 01 Mar 2012 10:48:17 +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 , Jan Kiszka , Dave Anderson , HATAYAMA Daisuke , Luiz Capitulino , Eric Blake References: <4F4EE080.9060307@cn.fujitsu.com> In-Reply-To: <4F4EE080.9060307@cn.fujitsu.com> X-MIMETrack: Itemize by SMTP Server on mailserver/fnst(Release 8.5.1FP4|July 25, 2010) at 2012-03-01 10:45:12, Serialize by Router on mailserver/fnst(Release 8.5.1FP4|July 25, 2010) at 2012-03-01 10:45:13, Serialize complete at 2012-03-01 10:45:13 X-detected-operating-system: by eggs.gnu.org: FreeBSD 6.x (1) X-Received-From: 222.73.24.84 Subject: [Qemu-devel] [RFC][PATCH 06/14 v7] 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 register. Store the cpu status into QEMU note, and the user can get more information from vmcore. Signed-off-by: Wen Congyang --- cpu-all.h | 20 ++++++ target-i386/arch_dump.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 0 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index f7c6321..ad69269 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -540,6 +540,10 @@ int cpu_write_elf64_note(write_core_dump_function f, CPUState *env, int cpuid, target_phys_addr_t *offset, void *opaque); int cpu_write_elf32_note(write_core_dump_function f, CPUState *env, int cpuid, target_phys_addr_t *offset, void *opaque); +int cpu_write_elf64_qemunote(write_core_dump_function f, CPUState *env, + target_phys_addr_t *offset, void *opaque); +int cpu_write_elf32_qemunote(write_core_dump_function f, CPUState *env, + target_phys_addr_t *offset, void *opaque); #else static inline int cpu_write_elf64_note(write_core_dump_function f, CPUState *env, int cpuid, @@ -554,6 +558,22 @@ 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, + CPUState *env, + target_phys_addr_t *offset, + void *opaque); +{ + return -1; +} + +static inline int cpu_write_elf32_qemunote(write_core_dump_function f, + CPUState *env, + target_phys_addr_t *offset, + void *opaque) +{ + return -1; +} #endif #endif /* CPU_ALL_H */ diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c index 3239c40..560c8a3 100644 --- a/target-i386/arch_dump.c +++ b/target-i386/arch_dump.c @@ -247,3 +247,157 @@ int cpu_write_elf32_note(write_core_dump_function f, CPUState *env, int cpuid, return 0; } + +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, CPUState *env) +{ + memset(s, 0, sizeof(QEMUCPUState)); + + s->version = 1; + 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]; +} + +int cpu_write_elf64_qemunote(write_core_dump_function f, CPUState *env, + target_phys_addr_t *offset, void *opaque) +{ + QEMUCPUState state; + Elf64_Nhdr *note; + char *buf; + int descsz, note_size, name_size = 5; + const char *name = "QEMU"; + int ret; + + qemu_get_cpustate(&state, env); + + descsz = sizeof(state); + note_size = ((sizeof(Elf32_Nhdr) + 3) / 4 + (name_size + 3) / 4 + + (descsz + 3) / 4) * 4; + note = g_malloc(note_size); + + memset(note, 0, note_size); + note->n_namesz = cpu_to_le32(name_size); + note->n_descsz = cpu_to_le32(descsz); + note->n_type = 0; + buf = (char *)note; + buf += ((sizeof(Elf32_Nhdr) + 3) / 4) * 4; + memcpy(buf, name, name_size); + buf += ((name_size + 3) / 4) * 4; + memcpy(buf, &state, sizeof(state)); + + ret = f(*offset, note, note_size, opaque); + g_free(note); + if (ret < 0) { + return -1; + } + + *offset += note_size; + + return 0; +} + +int cpu_write_elf32_qemunote(write_core_dump_function f, CPUState *env, + target_phys_addr_t *offset, void *opaque) +{ + QEMUCPUState state; + Elf32_Nhdr *note; + char *buf; + int descsz, note_size, name_size = 5; + const char *name = "QEMU"; + int ret; + + qemu_get_cpustate(&state, env); + + descsz = sizeof(state); + note_size = ((sizeof(Elf32_Nhdr) + 3) / 4 + (name_size + 3) / 4 + + (descsz + 3) / 4) * 4; + note = g_malloc(note_size); + + memset(note, 0, note_size); + note->n_namesz = cpu_to_le32(name_size); + note->n_descsz = cpu_to_le32(descsz); + note->n_type = 0; + buf = (char *)note; + buf += ((sizeof(Elf32_Nhdr) + 3) / 4) * 4; + memcpy(buf, name, name_size); + buf += ((name_size + 3) / 4) * 4; + memcpy(buf, &state, sizeof(state)); + + ret = f(*offset, note, note_size, opaque); + g_free(note); + if (ret < 0) { + return -1; + } + + *offset += note_size; + + return 0; +}