xref: /openbmc/qemu/target/loongarch/arch_dump.c (revision 4521167f)
132c22cc4SBibo Mao /*
232c22cc4SBibo Mao  * Support for writing ELF notes for LoongArch architectures
332c22cc4SBibo Mao  *
432c22cc4SBibo Mao  * Copyright (c) 2023 Loongarch Technology
532c22cc4SBibo Mao  *
632c22cc4SBibo Mao  * This program is free software; you can redistribute it and/or modify it
732c22cc4SBibo Mao  * under the terms and conditions of the GNU General Public License,
832c22cc4SBibo Mao  * version 2 or later, as published by the Free Software Foundation.
932c22cc4SBibo Mao  *
1032c22cc4SBibo Mao  * This program is distributed in the hope it will be useful, but WITHOUT
1132c22cc4SBibo Mao  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1232c22cc4SBibo Mao  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
1332c22cc4SBibo Mao  * more details.
1432c22cc4SBibo Mao  *
1532c22cc4SBibo Mao  * You should have received a copy of the GNU General Public License along with
1632c22cc4SBibo Mao  * this program.  If not, see <http://www.gnu.org/licenses/>.
1732c22cc4SBibo Mao  *
1832c22cc4SBibo Mao  */
1932c22cc4SBibo Mao 
2032c22cc4SBibo Mao #include "qemu/osdep.h"
2132c22cc4SBibo Mao #include "cpu.h"
2232c22cc4SBibo Mao #include "elf.h"
2332c22cc4SBibo Mao #include "sysemu/dump.h"
2432c22cc4SBibo Mao #include "internals.h"
2532c22cc4SBibo Mao 
2632c22cc4SBibo Mao /* struct user_pt_regs from arch/loongarch/include/uapi/asm/ptrace.h */
2732c22cc4SBibo Mao struct loongarch_user_regs {
2832c22cc4SBibo Mao     uint64_t gpr[32];
2932c22cc4SBibo Mao     uint64_t pad1[1];
3032c22cc4SBibo Mao     /* Special CSR registers. */
3132c22cc4SBibo Mao     uint64_t csr_era;
3232c22cc4SBibo Mao     uint64_t csr_badv;
3332c22cc4SBibo Mao     uint64_t pad2[10];
3432c22cc4SBibo Mao } QEMU_PACKED;
3532c22cc4SBibo Mao 
3632c22cc4SBibo Mao QEMU_BUILD_BUG_ON(sizeof(struct loongarch_user_regs) != 360);
3732c22cc4SBibo Mao 
3832c22cc4SBibo Mao /* struct elf_prstatus from include/uapi/linux/elfcore.h */
3932c22cc4SBibo Mao struct loongarch_elf_prstatus {
4032c22cc4SBibo Mao     char pad1[32]; /* 32 == offsetof(struct elf_prstatus, pr_pid) */
4132c22cc4SBibo Mao     uint32_t pr_pid;
4232c22cc4SBibo Mao     /*
4332c22cc4SBibo Mao      * 76 == offsetof(struct elf_prstatus, pr_reg) -
4432c22cc4SBibo Mao      * offsetof(struct elf_prstatus, pr_ppid)
4532c22cc4SBibo Mao      */
4632c22cc4SBibo Mao     char pad2[76];
4732c22cc4SBibo Mao     struct loongarch_user_regs pr_reg;
4832c22cc4SBibo Mao     uint32_t pr_fpvalid;
4932c22cc4SBibo Mao     char pad3[4];
5032c22cc4SBibo Mao } QEMU_PACKED;
5132c22cc4SBibo Mao 
5232c22cc4SBibo Mao QEMU_BUILD_BUG_ON(sizeof(struct loongarch_elf_prstatus) != 480);
5332c22cc4SBibo Mao 
5432c22cc4SBibo Mao /* struct user_fp_state from arch/loongarch/include/uapi/asm/ptrace.h */
5532c22cc4SBibo Mao struct loongarch_fpu_struct {
5632c22cc4SBibo Mao     uint64_t fpr[32];
5732c22cc4SBibo Mao     uint64_t fcc;
5832c22cc4SBibo Mao     unsigned int fcsr;
5932c22cc4SBibo Mao } QEMU_PACKED;
6032c22cc4SBibo Mao 
6132c22cc4SBibo Mao QEMU_BUILD_BUG_ON(sizeof(struct loongarch_fpu_struct) != 268);
6232c22cc4SBibo Mao 
6332c22cc4SBibo Mao struct loongarch_note {
6432c22cc4SBibo Mao     Elf64_Nhdr hdr;
6532c22cc4SBibo Mao     char name[8]; /* align_up(sizeof("CORE"), 4) */
6632c22cc4SBibo Mao     union {
6732c22cc4SBibo Mao         struct loongarch_elf_prstatus prstatus;
6832c22cc4SBibo Mao         struct loongarch_fpu_struct fpu;
6932c22cc4SBibo Mao     };
7032c22cc4SBibo Mao } QEMU_PACKED;
7132c22cc4SBibo Mao 
7232c22cc4SBibo Mao #define LOONGARCH_NOTE_HEADER_SIZE offsetof(struct loongarch_note, prstatus)
7332c22cc4SBibo Mao #define LOONGARCH_PRSTATUS_NOTE_SIZE                                          \
7432c22cc4SBibo Mao     (LOONGARCH_NOTE_HEADER_SIZE + sizeof(struct loongarch_elf_prstatus))
7532c22cc4SBibo Mao #define LOONGARCH_PRFPREG_NOTE_SIZE                                           \
7632c22cc4SBibo Mao     (LOONGARCH_NOTE_HEADER_SIZE + sizeof(struct loongarch_fpu_struct))
7732c22cc4SBibo Mao 
loongarch_note_init(struct loongarch_note * note,DumpState * s,const char * name,Elf64_Word namesz,Elf64_Word type,Elf64_Word descsz)7832c22cc4SBibo Mao static void loongarch_note_init(struct loongarch_note *note, DumpState *s,
7932c22cc4SBibo Mao                                 const char *name, Elf64_Word namesz,
8032c22cc4SBibo Mao                                 Elf64_Word type, Elf64_Word descsz)
8132c22cc4SBibo Mao {
8232c22cc4SBibo Mao     memset(note, 0, sizeof(*note));
8332c22cc4SBibo Mao 
8432c22cc4SBibo Mao     note->hdr.n_namesz = cpu_to_dump32(s, namesz);
8532c22cc4SBibo Mao     note->hdr.n_descsz = cpu_to_dump32(s, descsz);
8632c22cc4SBibo Mao     note->hdr.n_type = cpu_to_dump32(s, type);
8732c22cc4SBibo Mao 
8832c22cc4SBibo Mao     memcpy(note->name, name, namesz);
8932c22cc4SBibo Mao }
9032c22cc4SBibo Mao 
loongarch_write_elf64_fprpreg(WriteCoreDumpFunction f,CPULoongArchState * env,int cpuid,DumpState * s)9132c22cc4SBibo Mao static int loongarch_write_elf64_fprpreg(WriteCoreDumpFunction f,
9232c22cc4SBibo Mao                                          CPULoongArchState *env, int cpuid,
9332c22cc4SBibo Mao                                          DumpState *s)
9432c22cc4SBibo Mao {
9532c22cc4SBibo Mao     struct loongarch_note note;
9632c22cc4SBibo Mao     int ret, i;
9732c22cc4SBibo Mao 
9832c22cc4SBibo Mao     loongarch_note_init(&note, s, "CORE", 5, NT_PRFPREG, sizeof(note.fpu));
9932c22cc4SBibo Mao     note.fpu.fcsr = cpu_to_dump64(s, env->fcsr0);
100*4521167fSBibo Mao     note.fpu.fcc = cpu_to_dump64(s, read_fcc(env));
10132c22cc4SBibo Mao 
10232c22cc4SBibo Mao     for (i = 0; i < 32; ++i) {
10332c22cc4SBibo Mao         note.fpu.fpr[i] = cpu_to_dump64(s, env->fpr[i].vreg.UD[0]);
10432c22cc4SBibo Mao     }
10532c22cc4SBibo Mao 
10632c22cc4SBibo Mao     ret = f(&note, LOONGARCH_PRFPREG_NOTE_SIZE, s);
10732c22cc4SBibo Mao     if (ret < 0) {
10832c22cc4SBibo Mao         return -1;
10932c22cc4SBibo Mao     }
11032c22cc4SBibo Mao 
11132c22cc4SBibo Mao     return 0;
11232c22cc4SBibo Mao }
11332c22cc4SBibo Mao 
loongarch_cpu_write_elf64_note(WriteCoreDumpFunction f,CPUState * cs,int cpuid,DumpState * s)11432c22cc4SBibo Mao int loongarch_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
11532c22cc4SBibo Mao                                    int cpuid, DumpState *s)
11632c22cc4SBibo Mao {
11732c22cc4SBibo Mao     struct loongarch_note note;
11832c22cc4SBibo Mao     CPULoongArchState *env = &LOONGARCH_CPU(cs)->env;
11932c22cc4SBibo Mao     int ret, i;
12032c22cc4SBibo Mao 
12132c22cc4SBibo Mao     loongarch_note_init(&note, s, "CORE", 5, NT_PRSTATUS,
12232c22cc4SBibo Mao                         sizeof(note.prstatus));
12332c22cc4SBibo Mao     note.prstatus.pr_pid = cpu_to_dump32(s, cpuid);
12432c22cc4SBibo Mao     note.prstatus.pr_fpvalid = cpu_to_dump32(s, 1);
12532c22cc4SBibo Mao 
12632c22cc4SBibo Mao     for (i = 0; i < 32; ++i) {
12732c22cc4SBibo Mao         note.prstatus.pr_reg.gpr[i] = cpu_to_dump64(s, env->gpr[i]);
12832c22cc4SBibo Mao     }
12932c22cc4SBibo Mao     note.prstatus.pr_reg.csr_era  = cpu_to_dump64(s, env->CSR_ERA);
13032c22cc4SBibo Mao     note.prstatus.pr_reg.csr_badv = cpu_to_dump64(s, env->CSR_BADV);
13132c22cc4SBibo Mao     ret = f(&note, LOONGARCH_PRSTATUS_NOTE_SIZE, s);
13232c22cc4SBibo Mao     if (ret < 0) {
13332c22cc4SBibo Mao         return -1;
13432c22cc4SBibo Mao     }
13532c22cc4SBibo Mao 
13632c22cc4SBibo Mao     ret = loongarch_write_elf64_fprpreg(f, env, cpuid, s);
13732c22cc4SBibo Mao     if (ret < 0) {
13832c22cc4SBibo Mao         return -1;
13932c22cc4SBibo Mao     }
14032c22cc4SBibo Mao 
14132c22cc4SBibo Mao     return ret;
14232c22cc4SBibo Mao }
14332c22cc4SBibo Mao 
cpu_get_dump_info(ArchDumpInfo * info,const GuestPhysBlockList * guest_phys_blocks)14432c22cc4SBibo Mao int cpu_get_dump_info(ArchDumpInfo *info,
14532c22cc4SBibo Mao                       const GuestPhysBlockList *guest_phys_blocks)
14632c22cc4SBibo Mao {
14732c22cc4SBibo Mao     info->d_machine = EM_LOONGARCH;
14832c22cc4SBibo Mao     info->d_endian = ELFDATA2LSB;
14932c22cc4SBibo Mao     info->d_class = ELFCLASS64;
15032c22cc4SBibo Mao 
15132c22cc4SBibo Mao     return 0;
15232c22cc4SBibo Mao }
15332c22cc4SBibo Mao 
cpu_get_note_size(int class,int machine,int nr_cpus)15432c22cc4SBibo Mao ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
15532c22cc4SBibo Mao {
15632c22cc4SBibo Mao     size_t note_size = 0;
15732c22cc4SBibo Mao 
15832c22cc4SBibo Mao     if (class == ELFCLASS64) {
15932c22cc4SBibo Mao         note_size = LOONGARCH_PRSTATUS_NOTE_SIZE + LOONGARCH_PRFPREG_NOTE_SIZE;
16032c22cc4SBibo Mao     }
16132c22cc4SBibo Mao 
16232c22cc4SBibo Mao     return note_size * nr_cpus;
16332c22cc4SBibo Mao }
164