11fbaf06eSEd Maste /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31fbaf06eSEd Maste *
41fbaf06eSEd Maste * Copyright (c) 2018 Turing Robotic Industries Inc.
51fbaf06eSEd Maste * Copyright (c) 2000 Marcel Moolenaar
61fbaf06eSEd Maste *
71fbaf06eSEd Maste * Redistribution and use in source and binary forms, with or without
81fbaf06eSEd Maste * modification, are permitted provided that the following conditions
91fbaf06eSEd Maste * are met:
101fbaf06eSEd Maste * 1. Redistributions of source code must retain the above copyright
111fbaf06eSEd Maste * notice, this list of conditions and the following disclaimer.
121fbaf06eSEd Maste * 2. Redistributions in binary form must reproduce the above copyright
131fbaf06eSEd Maste * notice, this list of conditions and the following disclaimer in the
141fbaf06eSEd Maste * documentation and/or other materials provided with the distribution.
151fbaf06eSEd Maste *
161fbaf06eSEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
171fbaf06eSEd Maste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
181fbaf06eSEd Maste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
191fbaf06eSEd Maste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
201fbaf06eSEd Maste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
211fbaf06eSEd Maste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
221fbaf06eSEd Maste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
231fbaf06eSEd Maste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
241fbaf06eSEd Maste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
251fbaf06eSEd Maste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
261fbaf06eSEd Maste * SUCH DAMAGE.
271fbaf06eSEd Maste */
281fbaf06eSEd Maste
291fbaf06eSEd Maste #include <sys/param.h>
301fbaf06eSEd Maste #include <sys/proc.h>
310bf8d5d5SEdward Tomasz Napierala #include <sys/ptrace.h>
32b7924341SAndrew Turner #include <sys/reg.h>
331fbaf06eSEd Maste
3431e938c5SDmitry Chagin #include <vm/vm_param.h>
3531e938c5SDmitry Chagin
361fbaf06eSEd Maste #include <arm64/linux/linux.h>
371fbaf06eSEd Maste #include <arm64/linux/linux_proto.h>
380a4b664aSDmitry Chagin #include <compat/linux/linux_fork.h>
391fbaf06eSEd Maste #include <compat/linux/linux_misc.h>
401fbaf06eSEd Maste #include <compat/linux/linux_util.h>
411fbaf06eSEd Maste
420bf8d5d5SEdward Tomasz Napierala #define LINUX_ARCH_AARCH64 0xc00000b7
430bf8d5d5SEdward Tomasz Napierala
441fbaf06eSEd Maste
451fbaf06eSEd Maste int
linux_set_upcall(struct thread * td,register_t stack)463b57ddb0SJohn Baldwin linux_set_upcall(struct thread *td, register_t stack)
471fbaf06eSEd Maste {
481fbaf06eSEd Maste
49e505c306SEdward Tomasz Napierala if (stack)
50e505c306SEdward Tomasz Napierala td->td_frame->tf_sp = stack;
51e505c306SEdward Tomasz Napierala
52e505c306SEdward Tomasz Napierala /*
53e505c306SEdward Tomasz Napierala * The newly created Linux thread returns
54e505c306SEdward Tomasz Napierala * to the user space by the same path that a parent does.
55e505c306SEdward Tomasz Napierala */
56e505c306SEdward Tomasz Napierala td->td_frame->tf_x[0] = 0;
57e505c306SEdward Tomasz Napierala return (0);
581fbaf06eSEd Maste }
591fbaf06eSEd Maste
601fbaf06eSEd Maste int
linux_set_cloned_tls(struct thread * td,void * desc)611fbaf06eSEd Maste linux_set_cloned_tls(struct thread *td, void *desc)
621fbaf06eSEd Maste {
631fbaf06eSEd Maste
64a397b550SEdward Tomasz Napierala if ((uint64_t)desc >= VM_MAXUSER_ADDRESS)
65a397b550SEdward Tomasz Napierala return (EPERM);
66a397b550SEdward Tomasz Napierala
67*2b8b37c8SKonstantin Belousov return (cpu_set_user_tls(td, desc, 0));
681fbaf06eSEd Maste }
6945d99014SEdward Tomasz Napierala
7045d99014SEdward Tomasz Napierala void
bsd_to_linux_regset(const struct reg * b_reg,struct linux_pt_regset * l_regset)713417c298SEdward Tomasz Napierala bsd_to_linux_regset(const struct reg *b_reg, struct linux_pt_regset *l_regset)
7245d99014SEdward Tomasz Napierala {
7345d99014SEdward Tomasz Napierala
7445d99014SEdward Tomasz Napierala KASSERT(sizeof(l_regset->x) == sizeof(b_reg->x) + sizeof(l_ulong),
7545d99014SEdward Tomasz Napierala ("%s: size mismatch\n", __func__));
7645d99014SEdward Tomasz Napierala memcpy(l_regset->x, b_reg->x, sizeof(b_reg->x));
7745d99014SEdward Tomasz Napierala
7845d99014SEdward Tomasz Napierala l_regset->x[30] = b_reg->lr;
7945d99014SEdward Tomasz Napierala l_regset->sp = b_reg->sp;
8045d99014SEdward Tomasz Napierala l_regset->pc = b_reg->elr;
8145d99014SEdward Tomasz Napierala l_regset->cpsr = b_reg->spsr;
8245d99014SEdward Tomasz Napierala }
836f397bc0SEdward Tomasz Napierala
846f397bc0SEdward Tomasz Napierala void
linux_to_bsd_regset(struct reg * b_reg,const struct linux_pt_regset * l_regset)856f397bc0SEdward Tomasz Napierala linux_to_bsd_regset(struct reg *b_reg, const struct linux_pt_regset *l_regset)
866f397bc0SEdward Tomasz Napierala {
876f397bc0SEdward Tomasz Napierala
886f397bc0SEdward Tomasz Napierala KASSERT(sizeof(l_regset->x) == sizeof(b_reg->x) + sizeof(l_ulong),
896f397bc0SEdward Tomasz Napierala ("%s: size mismatch\n", __func__));
906f397bc0SEdward Tomasz Napierala
916f397bc0SEdward Tomasz Napierala memcpy(b_reg->x, l_regset->x, sizeof(b_reg->x));
926f397bc0SEdward Tomasz Napierala b_reg->sp = l_regset->sp;
936f397bc0SEdward Tomasz Napierala b_reg->elr = l_regset->pc;
946f397bc0SEdward Tomasz Napierala b_reg->spsr = l_regset->cpsr;
956f397bc0SEdward Tomasz Napierala }
960bf8d5d5SEdward Tomasz Napierala
970bf8d5d5SEdward Tomasz Napierala void
linux_ptrace_get_syscall_info_machdep(const struct reg * reg,struct syscall_info * si)980bf8d5d5SEdward Tomasz Napierala linux_ptrace_get_syscall_info_machdep(const struct reg *reg,
990bf8d5d5SEdward Tomasz Napierala struct syscall_info *si)
1000bf8d5d5SEdward Tomasz Napierala {
1010bf8d5d5SEdward Tomasz Napierala
1020bf8d5d5SEdward Tomasz Napierala si->arch = LINUX_ARCH_AARCH64;
1030bf8d5d5SEdward Tomasz Napierala si->instruction_pointer = reg->lr;
1040bf8d5d5SEdward Tomasz Napierala si->stack_pointer = reg->sp;
1050bf8d5d5SEdward Tomasz Napierala }
1060bf8d5d5SEdward Tomasz Napierala
1070bf8d5d5SEdward Tomasz Napierala int
linux_ptrace_getregs_machdep(struct thread * td __unused,pid_t pid __unused,struct linux_pt_regset * l_regset __unused)1080bf8d5d5SEdward Tomasz Napierala linux_ptrace_getregs_machdep(struct thread *td __unused, pid_t pid __unused,
1090bf8d5d5SEdward Tomasz Napierala struct linux_pt_regset *l_regset __unused)
1100bf8d5d5SEdward Tomasz Napierala {
1110bf8d5d5SEdward Tomasz Napierala
1120bf8d5d5SEdward Tomasz Napierala return (0);
1130bf8d5d5SEdward Tomasz Napierala }
1140bf8d5d5SEdward Tomasz Napierala
115dd2a6cd7SDmitry Chagin int
linux_ptrace_peekuser(struct thread * td,pid_t pid,void * addr,void * data)116dd2a6cd7SDmitry Chagin linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data)
117dd2a6cd7SDmitry Chagin {
118dd2a6cd7SDmitry Chagin
119dd2a6cd7SDmitry Chagin LINUX_RATELIMIT_MSG_OPT1("PTRACE_PEEKUSER offset %ld not implemented; "
120dd2a6cd7SDmitry Chagin "returning EINVAL", (uintptr_t)addr);
121dd2a6cd7SDmitry Chagin return (EINVAL);
122dd2a6cd7SDmitry Chagin }
1233d0addcdSDmitry Chagin
1243d0addcdSDmitry Chagin int
linux_ptrace_pokeuser(struct thread * td,pid_t pid,void * addr,void * data)1253d0addcdSDmitry Chagin linux_ptrace_pokeuser(struct thread *td, pid_t pid, void *addr, void *data)
1263d0addcdSDmitry Chagin {
1273d0addcdSDmitry Chagin
1283d0addcdSDmitry Chagin LINUX_RATELIMIT_MSG_OPT1("PTRACE_POKEUSER offset %ld "
1293d0addcdSDmitry Chagin "not implemented; returning EINVAL", (uintptr_t)addr);
1303d0addcdSDmitry Chagin return (EINVAL);
1313d0addcdSDmitry Chagin }
132