2 * Emulation of BSD signals
4 * Copyright (c) 2003 - 2008 Fabrice Bellard
5 * Copyright (c) 2013 Stacey Son
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
23 #include "signal-common.h"
24 #include "hw/core/tcg-cpu-ops.h"
27 * Stubbed out routines until we merge signal support from bsd-user
31 static struct target_sigaction sigact_table
[TARGET_NSIG
];
32 static void host_signal_handler(int host_sig
, siginfo_t
*info
, void *puc
);
35 * The BSD ABIs use the same singal numbers across all the CPU architectures, so
36 * (unlike Linux) these functions are just the identity mapping. This might not
37 * be true for XyzBSD running on AbcBSD, which doesn't currently work.
39 int host_to_target_signal(int sig
)
44 int target_to_host_signal(int sig
)
50 * Queue a signal so that it will be send to the virtual CPU as soon as
53 void queue_signal(CPUArchState
*env
, int sig
, int si_type
,
54 target_siginfo_t
*info
)
56 qemu_log_mask(LOG_UNIMP
, "No signal queueing, dropping signal %d\n", sig
);
59 static int fatal_signal(int sig
)
67 /* Ignored by default. */
74 /* Job control signals. */
82 * Force a synchronously taken QEMU_SI_FAULT signal. For QEMU the
83 * 'force' part is handled in process_pending_signals().
85 void force_sig_fault(int sig
, int code
, abi_ulong addr
)
87 CPUState
*cpu
= thread_cpu
;
88 CPUArchState
*env
= cpu
->env_ptr
;
89 target_siginfo_t info
= {};
95 queue_signal(env
, sig
, QEMU_SI_FAULT
, &info
);
98 static void host_signal_handler(int host_sig
, siginfo_t
*info
, void *puc
)
102 void signal_init(void)
104 TaskState
*ts
= (TaskState
*)thread_cpu
->opaque
;
105 struct sigaction act
;
106 struct sigaction oact
;
110 /* Set the signal mask from the host mask. */
111 sigprocmask(0, 0, &ts
->signal_mask
);
113 sigfillset(&act
.sa_mask
);
114 act
.sa_sigaction
= host_signal_handler
;
115 act
.sa_flags
= SA_SIGINFO
;
117 for (i
= 1; i
<= TARGET_NSIG
; i
++) {
119 if (i
== TARGET_SIGPROF
) {
123 host_sig
= target_to_host_signal(i
);
124 sigaction(host_sig
, NULL
, &oact
);
125 if (oact
.sa_sigaction
== (void *)SIG_IGN
) {
126 sigact_table
[i
- 1]._sa_handler
= TARGET_SIG_IGN
;
127 } else if (oact
.sa_sigaction
== (void *)SIG_DFL
) {
128 sigact_table
[i
- 1]._sa_handler
= TARGET_SIG_DFL
;
131 * If there's already a handler installed then something has
132 * gone horribly wrong, so don't even try to handle that case.
133 * Install some handlers for our own use. We need at least
134 * SIGSEGV and SIGBUS, to detect exceptions. We can not just
135 * trap all signals because it affects syscall interrupt
136 * behavior. But do trap all default-fatal signals.
138 if (fatal_signal(i
)) {
139 sigaction(host_sig
, &act
, NULL
);
144 void process_pending_signals(CPUArchState
*cpu_env
)
148 void cpu_loop_exit_sigsegv(CPUState
*cpu
, target_ulong addr
,
149 MMUAccessType access_type
, bool maperr
, uintptr_t ra
)
151 const struct TCGCPUOps
*tcg_ops
= CPU_GET_CLASS(cpu
)->tcg_ops
;
153 if (tcg_ops
->record_sigsegv
) {
154 tcg_ops
->record_sigsegv(cpu
, addr
, access_type
, maperr
, ra
);
157 force_sig_fault(TARGET_SIGSEGV
,
158 maperr
? TARGET_SEGV_MAPERR
: TARGET_SEGV_ACCERR
,
160 cpu
->exception_index
= EXCP_INTERRUPT
;
161 cpu_loop_exit_restore(cpu
, ra
);
164 void cpu_loop_exit_sigbus(CPUState
*cpu
, target_ulong addr
,
165 MMUAccessType access_type
, uintptr_t ra
)
167 const struct TCGCPUOps
*tcg_ops
= CPU_GET_CLASS(cpu
)->tcg_ops
;
169 if (tcg_ops
->record_sigbus
) {
170 tcg_ops
->record_sigbus(cpu
, addr
, access_type
, ra
);
173 force_sig_fault(TARGET_SIGBUS
, TARGET_BUS_ADRALN
, addr
);
174 cpu
->exception_index
= EXCP_INTERRUPT
;
175 cpu_loop_exit_restore(cpu
, ra
);