diff options
author | Warner Losh <imp@bsdimp.com> | 2021-09-23 09:16:15 -0600 |
---|---|---|
committer | Warner Losh <imp@bsdimp.com> | 2022-01-07 22:58:51 -0700 |
commit | f10521cc22aec74ad259bee03ca15ae5ee561c6c (patch) | |
tree | a6a2ac85d2f61bf42e046e3dea46223a9c316650 /bsd-user/arm/target_arch_thread.h | |
parent | eacb50b8d92452251d890f6bfb4ac8eb22acb8d2 (diff) | |
download | qemu-f10521cc22aec74ad259bee03ca15ae5ee561c6c.zip qemu-f10521cc22aec74ad259bee03ca15ae5ee561c6c.tar.gz qemu-f10521cc22aec74ad259bee03ca15ae5ee561c6c.tar.bz2 |
bsd-user/arm/target_arch_thread.h: Routines to create and switch to a thread
Implement target_thread_init (to create a thread) and target_set_upcall
(to switch to a thread) for arm.
Signed-off-by: Stacey Son <sson@FreeBSD.org>
Signed-off-by: Kyle Evans <kevans@FreeBSD.org>
Signed-off-by: Warner Losh <imp@bsdimp.com>
Reviewed-by: Kyle Evans <kevans@FreeBSD.org>
Diffstat (limited to 'bsd-user/arm/target_arch_thread.h')
-rw-r--r-- | bsd-user/arm/target_arch_thread.h | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/bsd-user/arm/target_arch_thread.h b/bsd-user/arm/target_arch_thread.h new file mode 100644 index 0000000..11c7f76 --- /dev/null +++ b/bsd-user/arm/target_arch_thread.h @@ -0,0 +1,82 @@ +/* + * arm thread support + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef _TARGET_ARCH_THREAD_H_ +#define _TARGET_ARCH_THREAD_H_ + +/* Compare to arm/arm/vm_machdep.c cpu_set_upcall_kse() */ +static inline void target_thread_set_upcall(CPUARMState *env, abi_ulong entry, + abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size) +{ + abi_ulong sp; + + /* + * Make sure the stack is properly aligned. + * arm/include/param.h (STACKLIGN() macro) + */ + sp = (u_int)(stack_base + stack_size) & ~0x7; + + /* sp = stack base */ + env->regs[13] = sp; + /* pc = start function entry */ + env->regs[15] = entry & 0xfffffffe; + /* r0 = arg */ + env->regs[0] = arg; + env->spsr = ARM_CPU_MODE_USR; + /* + * Thumb mode is encoded by the low bit in the entry point (since ARM can't + * execute at odd addresses). When it's set, set the Thumb bit (T) in the + * CPSR. + */ + cpsr_write(env, (entry & 1) * CPSR_T, CPSR_T, CPSRWriteByInstr); +} + +static inline void target_thread_init(struct target_pt_regs *regs, + struct image_info *infop) +{ + abi_long stack = infop->start_stack; + memset(regs, 0, sizeof(*regs)); + regs->ARM_cpsr = ARM_CPU_MODE_USR; + /* + * Thumb mode is encoded by the low bit in the entry point (since ARM can't + * execute at odd addresses). When it's set, set the Thumb bit (T) in the + * CPSR. + */ + if (infop->entry & 1) { + regs->ARM_cpsr |= CPSR_T; + } + regs->ARM_pc = infop->entry & 0xfffffffe; + regs->ARM_sp = stack; + if (bsd_type == target_freebsd) { + regs->ARM_lr = infop->entry & 0xfffffffe; + } + /* + * FreeBSD kernel passes the ps_strings pointer in r0. This is used by some + * programs to set status messages that we see in ps. bsd-user doesn't + * support that functionality, so it's ignored. When set to 0, FreeBSD's csu + * code ignores it. For the static case, r1 and r2 are effectively ignored + * by the csu __startup() routine. For the dynamic case, rtld saves r0 but + * generates r1 and r2 and passes them into the csu _startup. + * + * r0 ps_strings 0 passed since ps arg setting not supported + * r1 obj_main ignored by _start(), so 0 passed + * r2 cleanup generated by rtld or ignored by _start(), so 0 passed + */ +} + +#endif /* !_TARGET_ARCH_THREAD_H_ */ |