xref: /openbmc/qemu/bsd-user/aarch64/signal.c (revision 029e13a8a56a2931e7c24c0db52ae7256b932cb0)
17dba5e10SStacey Son /*
27dba5e10SStacey Son  * ARM AArch64 specific signal definitions for bsd-user
37dba5e10SStacey Son  *
47dba5e10SStacey Son  * Copyright (c) 2015 Stacey D. Son <sson at FreeBSD>
57dba5e10SStacey Son  *
67dba5e10SStacey Son  * This library is free software; you can redistribute it and/or
77dba5e10SStacey Son  * modify it under the terms of the GNU Lesser General Public
87dba5e10SStacey Son  * License as published by the Free Software Foundation; either
97dba5e10SStacey Son  * version 2 of the License, or (at your option) any later version.
107dba5e10SStacey Son  *
117dba5e10SStacey Son  * This library is distributed in the hope that it will be useful,
127dba5e10SStacey Son  * but WITHOUT ANY WARRANTY; without even the implied warranty of
137dba5e10SStacey Son  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
147dba5e10SStacey Son  * Lesser General Public License for more details.
157dba5e10SStacey Son  *
167dba5e10SStacey Son  * You should have received a copy of the GNU Lesser General Public
177dba5e10SStacey Son  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
187dba5e10SStacey Son  */
197dba5e10SStacey Son #include "qemu/osdep.h"
207dba5e10SStacey Son 
217dba5e10SStacey Son #include "qemu.h"
227dba5e10SStacey Son 
237dba5e10SStacey Son /*
24*ce6c541dSStacey Son  * Compare to sendsig() in sys/arm64/arm64/exec_machdep.c
257dba5e10SStacey Son  * Assumes that target stack frame memory is locked.
267dba5e10SStacey Son  */
set_sigtramp_args(CPUARMState * regs,int sig,struct target_sigframe * frame,abi_ulong frame_addr,struct target_sigaction * ka)277dba5e10SStacey Son abi_long set_sigtramp_args(CPUARMState *regs, int sig,
287dba5e10SStacey Son                            struct target_sigframe *frame,
297dba5e10SStacey Son                            abi_ulong frame_addr,
307dba5e10SStacey Son                            struct target_sigaction *ka)
317dba5e10SStacey Son {
327dba5e10SStacey Son     /*
337dba5e10SStacey Son      * Arguments to signal handler:
347dba5e10SStacey Son      *  x0 = signal number
357dba5e10SStacey Son      *  x1 = siginfo pointer
367dba5e10SStacey Son      *  x2 = ucontext pointer
377dba5e10SStacey Son      *  pc/elr = signal handler pointer
387dba5e10SStacey Son      *  sp = sigframe struct pointer
397dba5e10SStacey Son      *  lr = sigtramp at base of user stack
407dba5e10SStacey Son      */
417dba5e10SStacey Son 
427dba5e10SStacey Son     regs->xregs[0] = sig;
437dba5e10SStacey Son     regs->xregs[1] = frame_addr +
447dba5e10SStacey Son         offsetof(struct target_sigframe, sf_si);
457dba5e10SStacey Son     regs->xregs[2] = frame_addr +
467dba5e10SStacey Son         offsetof(struct target_sigframe, sf_uc);
477dba5e10SStacey Son 
487dba5e10SStacey Son     regs->pc = ka->_sa_handler;
497dba5e10SStacey Son     regs->xregs[TARGET_REG_SP] = frame_addr;
507dba5e10SStacey Son     regs->xregs[TARGET_REG_LR] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
517dba5e10SStacey Son 
527dba5e10SStacey Son     return 0;
537dba5e10SStacey Son }
549959fae5SStacey Son 
559959fae5SStacey Son /*
569959fae5SStacey Son  * Compare to get_mcontext() in arm64/arm64/machdep.c
579959fae5SStacey Son  * Assumes that the memory is locked if mcp points to user memory.
589959fae5SStacey Son  */
get_mcontext(CPUARMState * regs,target_mcontext_t * mcp,int flags)599959fae5SStacey Son abi_long get_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int flags)
609959fae5SStacey Son {
619959fae5SStacey Son     int err = 0, i;
629959fae5SStacey Son     uint64_t *gr = mcp->mc_gpregs.gp_x;
639959fae5SStacey Son 
649959fae5SStacey Son     mcp->mc_gpregs.gp_spsr = pstate_read(regs);
659959fae5SStacey Son     if (flags & TARGET_MC_GET_CLEAR_RET) {
669959fae5SStacey Son         gr[0] = 0UL;
679959fae5SStacey Son         mcp->mc_gpregs.gp_spsr &= ~CPSR_C;
689959fae5SStacey Son     } else {
699959fae5SStacey Son         gr[0] = tswap64(regs->xregs[0]);
709959fae5SStacey Son     }
719959fae5SStacey Son 
729959fae5SStacey Son     for (i = 1; i < 30; i++) {
739959fae5SStacey Son         gr[i] = tswap64(regs->xregs[i]);
749959fae5SStacey Son     }
759959fae5SStacey Son 
769959fae5SStacey Son     mcp->mc_gpregs.gp_sp = tswap64(regs->xregs[TARGET_REG_SP]);
779959fae5SStacey Son     mcp->mc_gpregs.gp_lr = tswap64(regs->xregs[TARGET_REG_LR]);
789959fae5SStacey Son     mcp->mc_gpregs.gp_elr = tswap64(regs->pc);
799959fae5SStacey Son 
809959fae5SStacey Son     /* XXX FP? */
819959fae5SStacey Son 
829959fae5SStacey Son     return err;
839959fae5SStacey Son }
84c88f44d8SWarner Losh 
85c88f44d8SWarner Losh /*
86c88f44d8SWarner Losh  * Compare to arm64/arm64/exec_machdep.c sendsig()
87c88f44d8SWarner Losh  * Assumes that the memory is locked if frame points to user memory.
88c88f44d8SWarner Losh  */
setup_sigframe_arch(CPUARMState * env,abi_ulong frame_addr,struct target_sigframe * frame,int flags)89c88f44d8SWarner Losh abi_long setup_sigframe_arch(CPUARMState *env, abi_ulong frame_addr,
90c88f44d8SWarner Losh                              struct target_sigframe *frame, int flags)
91c88f44d8SWarner Losh {
92c88f44d8SWarner Losh     target_mcontext_t *mcp = &frame->sf_uc.uc_mcontext;
93c88f44d8SWarner Losh 
94c88f44d8SWarner Losh     get_mcontext(env, mcp, flags);
95c88f44d8SWarner Losh     return 0;
96c88f44d8SWarner Losh }
97c88f44d8SWarner Losh 
98dadfc6d5SStacey Son /*
99dadfc6d5SStacey Son  * Compare to set_mcontext() in arm64/arm64/machdep.c
100dadfc6d5SStacey Son  * Assumes that the memory is locked if frame points to user memory.
101dadfc6d5SStacey Son  */
set_mcontext(CPUARMState * regs,target_mcontext_t * mcp,int srflag)102dadfc6d5SStacey Son abi_long set_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int srflag)
103dadfc6d5SStacey Son {
104dadfc6d5SStacey Son     int err = 0, i;
105dadfc6d5SStacey Son     const uint64_t *gr = mcp->mc_gpregs.gp_x;
106dadfc6d5SStacey Son 
107dadfc6d5SStacey Son     for (i = 0; i < 30; i++) {
108dadfc6d5SStacey Son         regs->xregs[i] = tswap64(gr[i]);
109dadfc6d5SStacey Son     }
110dadfc6d5SStacey Son 
111dadfc6d5SStacey Son     regs->xregs[TARGET_REG_SP] = tswap64(mcp->mc_gpregs.gp_sp);
112dadfc6d5SStacey Son     regs->xregs[TARGET_REG_LR] = tswap64(mcp->mc_gpregs.gp_lr);
113dadfc6d5SStacey Son     regs->pc = mcp->mc_gpregs.gp_elr;
114dadfc6d5SStacey Son     pstate_write(regs, mcp->mc_gpregs.gp_spsr);
115dadfc6d5SStacey Son 
116dadfc6d5SStacey Son     /* XXX FP? */
117dadfc6d5SStacey Son 
118dadfc6d5SStacey Son     return err;
119dadfc6d5SStacey Son }
120*ce6c541dSStacey Son 
121*ce6c541dSStacey Son /* Compare to sys_sigreturn() in  arm64/arm64/machdep.c */
get_ucontext_sigreturn(CPUARMState * regs,abi_ulong target_sf,abi_ulong * target_uc)122*ce6c541dSStacey Son abi_long get_ucontext_sigreturn(CPUARMState *regs, abi_ulong target_sf,
123*ce6c541dSStacey Son                                 abi_ulong *target_uc)
124*ce6c541dSStacey Son {
125*ce6c541dSStacey Son     uint32_t pstate = pstate_read(regs);
126*ce6c541dSStacey Son 
127*ce6c541dSStacey Son     *target_uc = 0;
128*ce6c541dSStacey Son 
129*ce6c541dSStacey Son     if ((pstate & PSTATE_M) != PSTATE_MODE_EL0t  ||
130*ce6c541dSStacey Son         (pstate & (PSTATE_F | PSTATE_I | PSTATE_A | PSTATE_D)) != 0) {
131*ce6c541dSStacey Son         return -TARGET_EINVAL;
132*ce6c541dSStacey Son     }
133*ce6c541dSStacey Son 
134*ce6c541dSStacey Son     *target_uc = target_sf;
135*ce6c541dSStacey Son 
136*ce6c541dSStacey Son     return 0;
137*ce6c541dSStacey Son }
138