18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <elfutils/libdwfl.h>
38c2ecf20Sopenharmony_ci#include <linux/kernel.h>
48c2ecf20Sopenharmony_ci#include "../../../util/unwind-libdw.h"
58c2ecf20Sopenharmony_ci#include "../../../util/perf_regs.h"
68c2ecf20Sopenharmony_ci#include "../../../util/event.h"
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci/* See backends/ppc_initreg.c and backends/ppc_regs.c in elfutils.  */
98c2ecf20Sopenharmony_cistatic const int special_regs[3][2] = {
108c2ecf20Sopenharmony_ci	{ 65, PERF_REG_POWERPC_LINK },
118c2ecf20Sopenharmony_ci	{ 101, PERF_REG_POWERPC_XER },
128c2ecf20Sopenharmony_ci	{ 109, PERF_REG_POWERPC_CTR },
138c2ecf20Sopenharmony_ci};
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cibool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
168c2ecf20Sopenharmony_ci{
178c2ecf20Sopenharmony_ci	struct unwind_info *ui = arg;
188c2ecf20Sopenharmony_ci	struct regs_dump *user_regs = &ui->sample->user_regs;
198c2ecf20Sopenharmony_ci	Dwarf_Word dwarf_regs[32], dwarf_nip;
208c2ecf20Sopenharmony_ci	size_t i;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define REG(r) ({						\
238c2ecf20Sopenharmony_ci	Dwarf_Word val = 0;					\
248c2ecf20Sopenharmony_ci	perf_reg_value(&val, user_regs, PERF_REG_POWERPC_##r);	\
258c2ecf20Sopenharmony_ci	val;							\
268c2ecf20Sopenharmony_ci})
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	dwarf_regs[0]  = REG(R0);
298c2ecf20Sopenharmony_ci	dwarf_regs[1]  = REG(R1);
308c2ecf20Sopenharmony_ci	dwarf_regs[2]  = REG(R2);
318c2ecf20Sopenharmony_ci	dwarf_regs[3]  = REG(R3);
328c2ecf20Sopenharmony_ci	dwarf_regs[4]  = REG(R4);
338c2ecf20Sopenharmony_ci	dwarf_regs[5]  = REG(R5);
348c2ecf20Sopenharmony_ci	dwarf_regs[6]  = REG(R6);
358c2ecf20Sopenharmony_ci	dwarf_regs[7]  = REG(R7);
368c2ecf20Sopenharmony_ci	dwarf_regs[8]  = REG(R8);
378c2ecf20Sopenharmony_ci	dwarf_regs[9]  = REG(R9);
388c2ecf20Sopenharmony_ci	dwarf_regs[10] = REG(R10);
398c2ecf20Sopenharmony_ci	dwarf_regs[11] = REG(R11);
408c2ecf20Sopenharmony_ci	dwarf_regs[12] = REG(R12);
418c2ecf20Sopenharmony_ci	dwarf_regs[13] = REG(R13);
428c2ecf20Sopenharmony_ci	dwarf_regs[14] = REG(R14);
438c2ecf20Sopenharmony_ci	dwarf_regs[15] = REG(R15);
448c2ecf20Sopenharmony_ci	dwarf_regs[16] = REG(R16);
458c2ecf20Sopenharmony_ci	dwarf_regs[17] = REG(R17);
468c2ecf20Sopenharmony_ci	dwarf_regs[18] = REG(R18);
478c2ecf20Sopenharmony_ci	dwarf_regs[19] = REG(R19);
488c2ecf20Sopenharmony_ci	dwarf_regs[20] = REG(R20);
498c2ecf20Sopenharmony_ci	dwarf_regs[21] = REG(R21);
508c2ecf20Sopenharmony_ci	dwarf_regs[22] = REG(R22);
518c2ecf20Sopenharmony_ci	dwarf_regs[23] = REG(R23);
528c2ecf20Sopenharmony_ci	dwarf_regs[24] = REG(R24);
538c2ecf20Sopenharmony_ci	dwarf_regs[25] = REG(R25);
548c2ecf20Sopenharmony_ci	dwarf_regs[26] = REG(R26);
558c2ecf20Sopenharmony_ci	dwarf_regs[27] = REG(R27);
568c2ecf20Sopenharmony_ci	dwarf_regs[28] = REG(R28);
578c2ecf20Sopenharmony_ci	dwarf_regs[29] = REG(R29);
588c2ecf20Sopenharmony_ci	dwarf_regs[30] = REG(R30);
598c2ecf20Sopenharmony_ci	dwarf_regs[31] = REG(R31);
608c2ecf20Sopenharmony_ci	if (!dwfl_thread_state_registers(thread, 0, 32, dwarf_regs))
618c2ecf20Sopenharmony_ci		return false;
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	dwarf_nip = REG(NIP);
648c2ecf20Sopenharmony_ci	dwfl_thread_state_register_pc(thread, dwarf_nip);
658c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(special_regs); i++) {
668c2ecf20Sopenharmony_ci		Dwarf_Word val = 0;
678c2ecf20Sopenharmony_ci		perf_reg_value(&val, user_regs, special_regs[i][1]);
688c2ecf20Sopenharmony_ci		if (!dwfl_thread_state_registers(thread,
698c2ecf20Sopenharmony_ci						 special_regs[i][0], 1,
708c2ecf20Sopenharmony_ci						 &val))
718c2ecf20Sopenharmony_ci			return false;
728c2ecf20Sopenharmony_ci	}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	return true;
758c2ecf20Sopenharmony_ci}
76