diff mbox

[08/12,v13] target-i386: Add API to write cpu status to core file

Message ID 4F8EB9DD.2050406@cn.fujitsu.com
State New
Headers show

Commit Message

Wen Congyang April 18, 2012, 12:55 p.m. UTC
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 <wency@cn.fujitsu.com>
---
 cpu-all.h               |   18 ++++++
 target-i386/arch_dump.c |  149 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 167 insertions(+), 0 deletions(-)

Comments

Anthony Liguori April 23, 2012, 10:43 p.m. UTC | #1
On 04/18/2012 07:55 AM, Wen Congyang wrote:
> 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<wency@cn.fujitsu.com>

This breaks the build in the "it's fairly obvious you are only testing with
--target-list=x86_64-softmmu" sort of way.  Please don't do that.  It only takes
a 30 minutes to do a full build (less with -jN) and saves me hours of bisecting
to figure out which patch in my queue caused the breakage.

  CC    alpha-softmmu/arch_init.o
In file included from /home/anthony/git/qemu/target-alpha/cpu.h:294:0,
                 from /home/anthony/git/qemu/qemu-common.h:123,
                 from /home/anthony/git/qemu/monitor.h:4,
                 from /home/anthony/git/qemu/arch_init.c:32:
/home/anthony/git/qemu/cpu-all.h:577:1: error: expected identifier or ‘(’ before
‘{’ token
/home/anthony/git/qemu/cpu-all.h:574:19: error: ‘cpu_write_elf64_qemunote’
declared ‘static’ but never defined [-Werror=unused-function]
cc1: all warnings being treated as errors

make[1]: *** [arch_init.o] Error 1
make: *** [subdir-alpha-softmmu] Error 2

Regards,

Anthony Liguori

> ---
>   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);
> +}
Wen Congyang April 24, 2012, 2:24 a.m. UTC | #2
At 04/24/2012 06:43 AM, Anthony Liguori Wrote:
> On 04/18/2012 07:55 AM, Wen Congyang wrote:
>> 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<wency@cn.fujitsu.com>
> 
> This breaks the build in the "it's fairly obvious you are only testing with
> --target-list=x86_64-softmmu" sort of way.  Please don't do that.  It only takes
> a 30 minutes to do a full build (less with -jN) and saves me hours of bisecting
> to figure out which patch in my queue caused the breakage.
> 
>   CC    alpha-softmmu/arch_init.o
> In file included from /home/anthony/git/qemu/target-alpha/cpu.h:294:0,
>                  from /home/anthony/git/qemu/qemu-common.h:123,
>                  from /home/anthony/git/qemu/monitor.h:4,
>                  from /home/anthony/git/qemu/arch_init.c:32:
> /home/anthony/git/qemu/cpu-all.h:577:1: error: expected identifier or ‘(’ before
> ‘{’ token
> /home/anthony/git/qemu/cpu-all.h:574:19: error: ‘cpu_write_elf64_qemunote’
> declared ‘static’ but never defined [-Werror=unused-function]
> cc1: all warnings being treated as errors
> 
> make[1]: *** [arch_init.o] Error 1
> make: *** [subdir-alpha-softmmu] Error 2

Sorry, I donot do a full build. I will fix it.

Thanks
Wen Congyang

> 
> Regards,
> 
> Anthony Liguori
>
diff mbox

Patch

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);
+}