xref: /openbmc/qemu/bsd-user/aarch64/signal.c (revision 2e1cacfb)
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  */
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  */
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  */
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  */
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 */
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