1 /*
2 * ARM AArch64 specific signal definitions for bsd-user
3 *
4 * Copyright (c) 2015 Stacey D. Son <sson at FreeBSD>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "qemu/osdep.h"
20
21 #include "qemu.h"
22
23 /*
24 * Compare to sendsig() in sys/arm64/arm64/exec_machdep.c
25 * Assumes that target stack frame memory is locked.
26 */
set_sigtramp_args(CPUARMState * regs,int sig,struct target_sigframe * frame,abi_ulong frame_addr,struct target_sigaction * ka)27 abi_long set_sigtramp_args(CPUARMState *regs, int sig,
28 struct target_sigframe *frame,
29 abi_ulong frame_addr,
30 struct target_sigaction *ka)
31 {
32 /*
33 * Arguments to signal handler:
34 * x0 = signal number
35 * x1 = siginfo pointer
36 * x2 = ucontext pointer
37 * pc/elr = signal handler pointer
38 * sp = sigframe struct pointer
39 * lr = sigtramp at base of user stack
40 */
41
42 regs->xregs[0] = sig;
43 regs->xregs[1] = frame_addr +
44 offsetof(struct target_sigframe, sf_si);
45 regs->xregs[2] = frame_addr +
46 offsetof(struct target_sigframe, sf_uc);
47
48 regs->pc = ka->_sa_handler;
49 regs->xregs[TARGET_REG_SP] = frame_addr;
50 regs->xregs[TARGET_REG_LR] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
51
52 return 0;
53 }
54
55 /*
56 * Compare to get_mcontext() in arm64/arm64/machdep.c
57 * Assumes that the memory is locked if mcp points to user memory.
58 */
get_mcontext(CPUARMState * regs,target_mcontext_t * mcp,int flags)59 abi_long get_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int flags)
60 {
61 int err = 0, i;
62 uint64_t *gr = mcp->mc_gpregs.gp_x;
63
64 mcp->mc_gpregs.gp_spsr = pstate_read(regs);
65 if (flags & TARGET_MC_GET_CLEAR_RET) {
66 gr[0] = 0UL;
67 mcp->mc_gpregs.gp_spsr &= ~CPSR_C;
68 } else {
69 gr[0] = tswap64(regs->xregs[0]);
70 }
71
72 for (i = 1; i < 30; i++) {
73 gr[i] = tswap64(regs->xregs[i]);
74 }
75
76 mcp->mc_gpregs.gp_sp = tswap64(regs->xregs[TARGET_REG_SP]);
77 mcp->mc_gpregs.gp_lr = tswap64(regs->xregs[TARGET_REG_LR]);
78 mcp->mc_gpregs.gp_elr = tswap64(regs->pc);
79
80 /* XXX FP? */
81
82 return err;
83 }
84
85 /*
86 * Compare to arm64/arm64/exec_machdep.c sendsig()
87 * Assumes that the memory is locked if frame points to user memory.
88 */
setup_sigframe_arch(CPUARMState * env,abi_ulong frame_addr,struct target_sigframe * frame,int flags)89 abi_long setup_sigframe_arch(CPUARMState *env, abi_ulong frame_addr,
90 struct target_sigframe *frame, int flags)
91 {
92 target_mcontext_t *mcp = &frame->sf_uc.uc_mcontext;
93
94 get_mcontext(env, mcp, flags);
95 return 0;
96 }
97
98 /*
99 * Compare to set_mcontext() in arm64/arm64/machdep.c
100 * Assumes that the memory is locked if frame points to user memory.
101 */
set_mcontext(CPUARMState * regs,target_mcontext_t * mcp,int srflag)102 abi_long set_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int srflag)
103 {
104 int err = 0, i;
105 const uint64_t *gr = mcp->mc_gpregs.gp_x;
106
107 for (i = 0; i < 30; i++) {
108 regs->xregs[i] = tswap64(gr[i]);
109 }
110
111 regs->xregs[TARGET_REG_SP] = tswap64(mcp->mc_gpregs.gp_sp);
112 regs->xregs[TARGET_REG_LR] = tswap64(mcp->mc_gpregs.gp_lr);
113 regs->pc = mcp->mc_gpregs.gp_elr;
114 pstate_write(regs, mcp->mc_gpregs.gp_spsr);
115
116 /* XXX FP? */
117
118 return err;
119 }
120
121 /* Compare to sys_sigreturn() in arm64/arm64/machdep.c */
get_ucontext_sigreturn(CPUARMState * regs,abi_ulong target_sf,abi_ulong * target_uc)122 abi_long get_ucontext_sigreturn(CPUARMState *regs, abi_ulong target_sf,
123 abi_ulong *target_uc)
124 {
125 uint32_t pstate = pstate_read(regs);
126
127 *target_uc = 0;
128
129 if ((pstate & PSTATE_M) != PSTATE_MODE_EL0t ||
130 (pstate & (PSTATE_F | PSTATE_I | PSTATE_A | PSTATE_D)) != 0) {
131 return -TARGET_EINVAL;
132 }
133
134 *target_uc = target_sf;
135
136 return 0;
137 }
138