xref: /freebsd/sys/arm64/linux/linux_machdep.c (revision 2b8b37c8f516a5955f81a6fc35c7aac01ddf4a3a)
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