target-arm: dump-guest-memory: add prfpreg notes for aarch64
Signed-off-by: Andrew Jones <drjones@redhat.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1452542185-10914-7-git-send-email-drjones@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
							parent
							
								
									da2b91409f
								
							
						
					
					
						commit
						bada8e4470
					
				@ -45,13 +45,36 @@ struct aarch64_elf_prstatus {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
QEMU_BUILD_BUG_ON(sizeof(struct aarch64_elf_prstatus) != 392);
 | 
					QEMU_BUILD_BUG_ON(sizeof(struct aarch64_elf_prstatus) != 392);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* struct user_fpsimd_state from arch/arm64/include/uapi/asm/ptrace.h
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * While the vregs member of user_fpsimd_state is of type __uint128_t,
 | 
				
			||||||
 | 
					 * QEMU uses an array of uint64_t, where the high half of the 128-bit
 | 
				
			||||||
 | 
					 * value is always in the 2n+1'th index. Thus we also break the 128-
 | 
				
			||||||
 | 
					 * bit values into two halves in this reproduction of user_fpsimd_state.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct aarch64_user_vfp_state {
 | 
				
			||||||
 | 
					    uint64_t vregs[64];
 | 
				
			||||||
 | 
					    uint32_t fpsr;
 | 
				
			||||||
 | 
					    uint32_t fpcr;
 | 
				
			||||||
 | 
					    char pad[8];
 | 
				
			||||||
 | 
					} QEMU_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QEMU_BUILD_BUG_ON(sizeof(struct aarch64_user_vfp_state) != 528);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct aarch64_note {
 | 
					struct aarch64_note {
 | 
				
			||||||
    Elf64_Nhdr hdr;
 | 
					    Elf64_Nhdr hdr;
 | 
				
			||||||
    char name[8]; /* align_up(sizeof("CORE"), 4) */
 | 
					    char name[8]; /* align_up(sizeof("CORE"), 4) */
 | 
				
			||||||
 | 
					    union {
 | 
				
			||||||
        struct aarch64_elf_prstatus prstatus;
 | 
					        struct aarch64_elf_prstatus prstatus;
 | 
				
			||||||
 | 
					        struct aarch64_user_vfp_state vfp;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
} QEMU_PACKED;
 | 
					} QEMU_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QEMU_BUILD_BUG_ON(sizeof(struct aarch64_note) != 412);
 | 
					#define AARCH64_NOTE_HEADER_SIZE offsetof(struct aarch64_note, prstatus)
 | 
				
			||||||
 | 
					#define AARCH64_PRSTATUS_NOTE_SIZE \
 | 
				
			||||||
 | 
					            (AARCH64_NOTE_HEADER_SIZE + sizeof(struct aarch64_elf_prstatus))
 | 
				
			||||||
 | 
					#define AARCH64_PRFPREG_NOTE_SIZE \
 | 
				
			||||||
 | 
					            (AARCH64_NOTE_HEADER_SIZE + sizeof(struct aarch64_user_vfp_state))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void aarch64_note_init(struct aarch64_note *note, DumpState *s,
 | 
					static void aarch64_note_init(struct aarch64_note *note, DumpState *s,
 | 
				
			||||||
                              const char *name, Elf64_Word namesz,
 | 
					                              const char *name, Elf64_Word namesz,
 | 
				
			||||||
@ -66,6 +89,42 @@ static void aarch64_note_init(struct aarch64_note *note, DumpState *s,
 | 
				
			|||||||
    memcpy(note->name, name, namesz);
 | 
					    memcpy(note->name, name, namesz);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int aarch64_write_elf64_prfpreg(WriteCoreDumpFunction f,
 | 
				
			||||||
 | 
					                                       CPUARMState *env, int cpuid,
 | 
				
			||||||
 | 
					                                       DumpState *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct aarch64_note note;
 | 
				
			||||||
 | 
					    int ret, i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    aarch64_note_init(¬e, s, "CORE", 5, NT_PRFPREG, sizeof(note.vfp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < 64; ++i) {
 | 
				
			||||||
 | 
					        note.vfp.vregs[i] = cpu_to_dump64(s, float64_val(env->vfp.regs[i]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (s->dump_info.d_endian == ELFDATA2MSB) {
 | 
				
			||||||
 | 
					        /* For AArch64 we must always swap the vfp.regs's 2n and 2n+1
 | 
				
			||||||
 | 
					         * entries when generating BE notes, because even big endian
 | 
				
			||||||
 | 
					         * hosts use 2n+1 for the high half.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        for (i = 0; i < 32; ++i) {
 | 
				
			||||||
 | 
					            uint64_t tmp = note.vfp.vregs[2*i];
 | 
				
			||||||
 | 
					            note.vfp.vregs[2*i] = note.vfp.vregs[2*i+1];
 | 
				
			||||||
 | 
					            note.vfp.vregs[2*i+1] = tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    note.vfp.fpsr = cpu_to_dump32(s, vfp_get_fpsr(env));
 | 
				
			||||||
 | 
					    note.vfp.fpcr = cpu_to_dump32(s, vfp_get_fpcr(env));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = f(¬e, AARCH64_PRFPREG_NOTE_SIZE, s);
 | 
				
			||||||
 | 
					    if (ret < 0) {
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
 | 
					int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
 | 
				
			||||||
                             int cpuid, void *opaque)
 | 
					                             int cpuid, void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -78,6 +137,7 @@ int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
 | 
				
			|||||||
    aarch64_note_init(¬e, s, "CORE", 5, NT_PRSTATUS, sizeof(note.prstatus));
 | 
					    aarch64_note_init(¬e, s, "CORE", 5, NT_PRSTATUS, sizeof(note.prstatus));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    note.prstatus.pr_pid = cpu_to_dump32(s, cpuid);
 | 
					    note.prstatus.pr_pid = cpu_to_dump32(s, cpuid);
 | 
				
			||||||
 | 
					    note.prstatus.pr_fpvalid = cpu_to_dump32(s, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!is_a64(env)) {
 | 
					    if (!is_a64(env)) {
 | 
				
			||||||
        aarch64_sync_32_to_64(env);
 | 
					        aarch64_sync_32_to_64(env);
 | 
				
			||||||
@ -95,12 +155,12 @@ int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
 | 
				
			|||||||
    note.prstatus.pr_reg.pc = cpu_to_dump64(s, env->pc);
 | 
					    note.prstatus.pr_reg.pc = cpu_to_dump64(s, env->pc);
 | 
				
			||||||
    note.prstatus.pr_reg.pstate = cpu_to_dump64(s, pstate);
 | 
					    note.prstatus.pr_reg.pstate = cpu_to_dump64(s, pstate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = f(¬e, sizeof(note), s);
 | 
					    ret = f(¬e, AARCH64_PRSTATUS_NOTE_SIZE, s);
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return aarch64_write_elf64_prfpreg(f, env, cpuid, s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* struct pt_regs from arch/arm/include/asm/ptrace.h */
 | 
					/* struct pt_regs from arch/arm/include/asm/ptrace.h */
 | 
				
			||||||
@ -129,7 +189,9 @@ struct arm_note {
 | 
				
			|||||||
    struct arm_elf_prstatus prstatus;
 | 
					    struct arm_elf_prstatus prstatus;
 | 
				
			||||||
} QEMU_PACKED;
 | 
					} QEMU_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QEMU_BUILD_BUG_ON(sizeof(struct arm_note) != 168);
 | 
					#define ARM_NOTE_HEADER_SIZE offsetof(struct arm_note, prstatus)
 | 
				
			||||||
 | 
					#define ARM_PRSTATUS_NOTE_SIZE \
 | 
				
			||||||
 | 
					            (ARM_NOTE_HEADER_SIZE + sizeof(struct arm_elf_prstatus))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void arm_note_init(struct arm_note *note, DumpState *s,
 | 
					static void arm_note_init(struct arm_note *note, DumpState *s,
 | 
				
			||||||
                          const char *name, Elf32_Word namesz,
 | 
					                          const char *name, Elf32_Word namesz,
 | 
				
			||||||
@ -161,7 +223,7 @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    note.prstatus.pr_reg.regs[16] = cpu_to_dump32(s, cpsr_read(env));
 | 
					    note.prstatus.pr_reg.regs[16] = cpu_to_dump32(s, cpsr_read(env));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = f(¬e, sizeof(note), s);
 | 
					    ret = f(¬e, ARM_PRSTATUS_NOTE_SIZE, s);
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -221,9 +283,10 @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
 | 
				
			|||||||
    size_t note_size;
 | 
					    size_t note_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (class == ELFCLASS64) {
 | 
					    if (class == ELFCLASS64) {
 | 
				
			||||||
        note_size = sizeof(struct aarch64_note);
 | 
					        note_size = AARCH64_PRSTATUS_NOTE_SIZE;
 | 
				
			||||||
 | 
					        note_size += AARCH64_PRFPREG_NOTE_SIZE;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        note_size = sizeof(struct arm_note);
 | 
					        note_size = ARM_PRSTATUS_NOTE_SIZE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return note_size * nr_cpus;
 | 
					    return note_size * nr_cpus;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user