xref: /openbmc/qemu/target/loongarch/arch_dump.c (revision 32c22cc4)
1*32c22cc4SBibo Mao /*
2*32c22cc4SBibo Mao  * Support for writing ELF notes for LoongArch architectures
3*32c22cc4SBibo Mao  *
4*32c22cc4SBibo Mao  * Copyright (c) 2023 Loongarch Technology
5*32c22cc4SBibo Mao  *
6*32c22cc4SBibo Mao  * This program is free software; you can redistribute it and/or modify it
7*32c22cc4SBibo Mao  * under the terms and conditions of the GNU General Public License,
8*32c22cc4SBibo Mao  * version 2 or later, as published by the Free Software Foundation.
9*32c22cc4SBibo Mao  *
10*32c22cc4SBibo Mao  * This program is distributed in the hope it will be useful, but WITHOUT
11*32c22cc4SBibo Mao  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12*32c22cc4SBibo Mao  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13*32c22cc4SBibo Mao  * more details.
14*32c22cc4SBibo Mao  *
15*32c22cc4SBibo Mao  * You should have received a copy of the GNU General Public License along with
16*32c22cc4SBibo Mao  * this program.  If not, see <http://www.gnu.org/licenses/>.
17*32c22cc4SBibo Mao  *
18*32c22cc4SBibo Mao  */
19*32c22cc4SBibo Mao 
20*32c22cc4SBibo Mao #include "qemu/osdep.h"
21*32c22cc4SBibo Mao #include "cpu.h"
22*32c22cc4SBibo Mao #include "elf.h"
23*32c22cc4SBibo Mao #include "sysemu/dump.h"
24*32c22cc4SBibo Mao #include "internals.h"
25*32c22cc4SBibo Mao 
26*32c22cc4SBibo Mao /* struct user_pt_regs from arch/loongarch/include/uapi/asm/ptrace.h */
27*32c22cc4SBibo Mao struct loongarch_user_regs {
28*32c22cc4SBibo Mao     uint64_t gpr[32];
29*32c22cc4SBibo Mao     uint64_t pad1[1];
30*32c22cc4SBibo Mao     /* Special CSR registers. */
31*32c22cc4SBibo Mao     uint64_t csr_era;
32*32c22cc4SBibo Mao     uint64_t csr_badv;
33*32c22cc4SBibo Mao     uint64_t pad2[10];
34*32c22cc4SBibo Mao } QEMU_PACKED;
35*32c22cc4SBibo Mao 
36*32c22cc4SBibo Mao QEMU_BUILD_BUG_ON(sizeof(struct loongarch_user_regs) != 360);
37*32c22cc4SBibo Mao 
38*32c22cc4SBibo Mao /* struct elf_prstatus from include/uapi/linux/elfcore.h */
39*32c22cc4SBibo Mao struct loongarch_elf_prstatus {
40*32c22cc4SBibo Mao     char pad1[32]; /* 32 == offsetof(struct elf_prstatus, pr_pid) */
41*32c22cc4SBibo Mao     uint32_t pr_pid;
42*32c22cc4SBibo Mao     /*
43*32c22cc4SBibo Mao      * 76 == offsetof(struct elf_prstatus, pr_reg) -
44*32c22cc4SBibo Mao      * offsetof(struct elf_prstatus, pr_ppid)
45*32c22cc4SBibo Mao      */
46*32c22cc4SBibo Mao     char pad2[76];
47*32c22cc4SBibo Mao     struct loongarch_user_regs pr_reg;
48*32c22cc4SBibo Mao     uint32_t pr_fpvalid;
49*32c22cc4SBibo Mao     char pad3[4];
50*32c22cc4SBibo Mao } QEMU_PACKED;
51*32c22cc4SBibo Mao 
52*32c22cc4SBibo Mao QEMU_BUILD_BUG_ON(sizeof(struct loongarch_elf_prstatus) != 480);
53*32c22cc4SBibo Mao 
54*32c22cc4SBibo Mao /* struct user_fp_state from arch/loongarch/include/uapi/asm/ptrace.h */
55*32c22cc4SBibo Mao struct loongarch_fpu_struct {
56*32c22cc4SBibo Mao     uint64_t fpr[32];
57*32c22cc4SBibo Mao     uint64_t fcc;
58*32c22cc4SBibo Mao     unsigned int fcsr;
59*32c22cc4SBibo Mao } QEMU_PACKED;
60*32c22cc4SBibo Mao 
61*32c22cc4SBibo Mao QEMU_BUILD_BUG_ON(sizeof(struct loongarch_fpu_struct) != 268);
62*32c22cc4SBibo Mao 
63*32c22cc4SBibo Mao struct loongarch_note {
64*32c22cc4SBibo Mao     Elf64_Nhdr hdr;
65*32c22cc4SBibo Mao     char name[8]; /* align_up(sizeof("CORE"), 4) */
66*32c22cc4SBibo Mao     union {
67*32c22cc4SBibo Mao         struct loongarch_elf_prstatus prstatus;
68*32c22cc4SBibo Mao         struct loongarch_fpu_struct fpu;
69*32c22cc4SBibo Mao     };
70*32c22cc4SBibo Mao } QEMU_PACKED;
71*32c22cc4SBibo Mao 
72*32c22cc4SBibo Mao #define LOONGARCH_NOTE_HEADER_SIZE offsetof(struct loongarch_note, prstatus)
73*32c22cc4SBibo Mao #define LOONGARCH_PRSTATUS_NOTE_SIZE                                          \
74*32c22cc4SBibo Mao     (LOONGARCH_NOTE_HEADER_SIZE + sizeof(struct loongarch_elf_prstatus))
75*32c22cc4SBibo Mao #define LOONGARCH_PRFPREG_NOTE_SIZE                                           \
76*32c22cc4SBibo Mao     (LOONGARCH_NOTE_HEADER_SIZE + sizeof(struct loongarch_fpu_struct))
77*32c22cc4SBibo Mao 
78*32c22cc4SBibo Mao static void loongarch_note_init(struct loongarch_note *note, DumpState *s,
79*32c22cc4SBibo Mao                                 const char *name, Elf64_Word namesz,
80*32c22cc4SBibo Mao                                 Elf64_Word type, Elf64_Word descsz)
81*32c22cc4SBibo Mao {
82*32c22cc4SBibo Mao     memset(note, 0, sizeof(*note));
83*32c22cc4SBibo Mao 
84*32c22cc4SBibo Mao     note->hdr.n_namesz = cpu_to_dump32(s, namesz);
85*32c22cc4SBibo Mao     note->hdr.n_descsz = cpu_to_dump32(s, descsz);
86*32c22cc4SBibo Mao     note->hdr.n_type = cpu_to_dump32(s, type);
87*32c22cc4SBibo Mao 
88*32c22cc4SBibo Mao     memcpy(note->name, name, namesz);
89*32c22cc4SBibo Mao }
90*32c22cc4SBibo Mao 
91*32c22cc4SBibo Mao static int loongarch_write_elf64_fprpreg(WriteCoreDumpFunction f,
92*32c22cc4SBibo Mao                                          CPULoongArchState *env, int cpuid,
93*32c22cc4SBibo Mao                                          DumpState *s)
94*32c22cc4SBibo Mao {
95*32c22cc4SBibo Mao     struct loongarch_note note;
96*32c22cc4SBibo Mao     int ret, i;
97*32c22cc4SBibo Mao 
98*32c22cc4SBibo Mao     loongarch_note_init(&note, s, "CORE", 5, NT_PRFPREG, sizeof(note.fpu));
99*32c22cc4SBibo Mao     note.fpu.fcsr = cpu_to_dump64(s, env->fcsr0);
100*32c22cc4SBibo Mao 
101*32c22cc4SBibo Mao     for (i = 0; i < 8; i++) {
102*32c22cc4SBibo Mao         note.fpu.fcc |= env->cf[i] << (8 * i);
103*32c22cc4SBibo Mao     }
104*32c22cc4SBibo Mao     note.fpu.fcc = cpu_to_dump64(s, note.fpu.fcc);
105*32c22cc4SBibo Mao 
106*32c22cc4SBibo Mao     for (i = 0; i < 32; ++i) {
107*32c22cc4SBibo Mao         note.fpu.fpr[i] = cpu_to_dump64(s, env->fpr[i].vreg.UD[0]);
108*32c22cc4SBibo Mao     }
109*32c22cc4SBibo Mao 
110*32c22cc4SBibo Mao     ret = f(&note, LOONGARCH_PRFPREG_NOTE_SIZE, s);
111*32c22cc4SBibo Mao     if (ret < 0) {
112*32c22cc4SBibo Mao         return -1;
113*32c22cc4SBibo Mao     }
114*32c22cc4SBibo Mao 
115*32c22cc4SBibo Mao     return 0;
116*32c22cc4SBibo Mao }
117*32c22cc4SBibo Mao 
118*32c22cc4SBibo Mao int loongarch_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
119*32c22cc4SBibo Mao                                    int cpuid, DumpState *s)
120*32c22cc4SBibo Mao {
121*32c22cc4SBibo Mao     struct loongarch_note note;
122*32c22cc4SBibo Mao     CPULoongArchState *env = &LOONGARCH_CPU(cs)->env;
123*32c22cc4SBibo Mao     int ret, i;
124*32c22cc4SBibo Mao 
125*32c22cc4SBibo Mao     loongarch_note_init(&note, s, "CORE", 5, NT_PRSTATUS,
126*32c22cc4SBibo Mao                         sizeof(note.prstatus));
127*32c22cc4SBibo Mao     note.prstatus.pr_pid = cpu_to_dump32(s, cpuid);
128*32c22cc4SBibo Mao     note.prstatus.pr_fpvalid = cpu_to_dump32(s, 1);
129*32c22cc4SBibo Mao 
130*32c22cc4SBibo Mao     for (i = 0; i < 32; ++i) {
131*32c22cc4SBibo Mao         note.prstatus.pr_reg.gpr[i] = cpu_to_dump64(s, env->gpr[i]);
132*32c22cc4SBibo Mao     }
133*32c22cc4SBibo Mao     note.prstatus.pr_reg.csr_era  = cpu_to_dump64(s, env->CSR_ERA);
134*32c22cc4SBibo Mao     note.prstatus.pr_reg.csr_badv = cpu_to_dump64(s, env->CSR_BADV);
135*32c22cc4SBibo Mao     ret = f(&note, LOONGARCH_PRSTATUS_NOTE_SIZE, s);
136*32c22cc4SBibo Mao     if (ret < 0) {
137*32c22cc4SBibo Mao         return -1;
138*32c22cc4SBibo Mao     }
139*32c22cc4SBibo Mao 
140*32c22cc4SBibo Mao     ret = loongarch_write_elf64_fprpreg(f, env, cpuid, s);
141*32c22cc4SBibo Mao     if (ret < 0) {
142*32c22cc4SBibo Mao         return -1;
143*32c22cc4SBibo Mao     }
144*32c22cc4SBibo Mao 
145*32c22cc4SBibo Mao     return ret;
146*32c22cc4SBibo Mao }
147*32c22cc4SBibo Mao 
148*32c22cc4SBibo Mao int cpu_get_dump_info(ArchDumpInfo *info,
149*32c22cc4SBibo Mao                       const GuestPhysBlockList *guest_phys_blocks)
150*32c22cc4SBibo Mao {
151*32c22cc4SBibo Mao     info->d_machine = EM_LOONGARCH;
152*32c22cc4SBibo Mao     info->d_endian = ELFDATA2LSB;
153*32c22cc4SBibo Mao     info->d_class = ELFCLASS64;
154*32c22cc4SBibo Mao 
155*32c22cc4SBibo Mao     return 0;
156*32c22cc4SBibo Mao }
157*32c22cc4SBibo Mao 
158*32c22cc4SBibo Mao ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
159*32c22cc4SBibo Mao {
160*32c22cc4SBibo Mao     size_t note_size = 0;
161*32c22cc4SBibo Mao 
162*32c22cc4SBibo Mao     if (class == ELFCLASS64) {
163*32c22cc4SBibo Mao         note_size = LOONGARCH_PRSTATUS_NOTE_SIZE + LOONGARCH_PRFPREG_NOTE_SIZE;
164*32c22cc4SBibo Mao     }
165*32c22cc4SBibo Mao 
166*32c22cc4SBibo Mao     return note_size * nr_cpus;
167*32c22cc4SBibo Mao }
168