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); | ||||
| 
 | ||||
| /* 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 { | ||||
|     Elf64_Nhdr hdr; | ||||
|     char name[8]; /* align_up(sizeof("CORE"), 4) */ | ||||
|     struct aarch64_elf_prstatus prstatus; | ||||
|     union { | ||||
|         struct aarch64_elf_prstatus prstatus; | ||||
|         struct aarch64_user_vfp_state vfp; | ||||
|     }; | ||||
| } 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, | ||||
|                               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); | ||||
| } | ||||
| 
 | ||||
| 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 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)); | ||||
| 
 | ||||
|     note.prstatus.pr_pid = cpu_to_dump32(s, cpuid); | ||||
|     note.prstatus.pr_fpvalid = cpu_to_dump32(s, 1); | ||||
| 
 | ||||
|     if (!is_a64(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.pstate = cpu_to_dump64(s, pstate); | ||||
| 
 | ||||
|     ret = f(¬e, sizeof(note), s); | ||||
|     ret = f(¬e, AARCH64_PRSTATUS_NOTE_SIZE, s); | ||||
|     if (ret < 0) { | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
|     return aarch64_write_elf64_prfpreg(f, env, cpuid, s); | ||||
| } | ||||
| 
 | ||||
| /* struct pt_regs from arch/arm/include/asm/ptrace.h */ | ||||
| @ -129,7 +189,9 @@ struct arm_note { | ||||
|     struct arm_elf_prstatus prstatus; | ||||
| } 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, | ||||
|                           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)); | ||||
| 
 | ||||
|     ret = f(¬e, sizeof(note), s); | ||||
|     ret = f(¬e, ARM_PRSTATUS_NOTE_SIZE, s); | ||||
|     if (ret < 0) { | ||||
|         return -1; | ||||
|     } | ||||
| @ -221,9 +283,10 @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus) | ||||
|     size_t note_size; | ||||
| 
 | ||||
|     if (class == ELFCLASS64) { | ||||
|         note_size = sizeof(struct aarch64_note); | ||||
|         note_size = AARCH64_PRSTATUS_NOTE_SIZE; | ||||
|         note_size += AARCH64_PRFPREG_NOTE_SIZE; | ||||
|     } else { | ||||
|         note_size = sizeof(struct arm_note); | ||||
|         note_size = ARM_PRSTATUS_NOTE_SIZE; | ||||
|     } | ||||
| 
 | ||||
|     return note_size * nr_cpus; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Andrew Jones
						Andrew Jones