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
, target_siginfo_t
*info
)
55 qemu_log_mask(LOG_UNIMP
, "No signal queueing, dropping signal %d\n", sig
);
58 static int fatal_signal(int sig
)
66 /* Ignored by default. */
73 /* Job control signals. */
81 * Force a synchronously taken QEMU_SI_FAULT signal. For QEMU the
82 * 'force' part is handled in process_pending_signals().
84 void force_sig_fault(int sig
, int code
, abi_ulong addr
)
86 CPUState
*cpu
= thread_cpu
;
87 CPUArchState
*env
= cpu
->env_ptr
;
88 target_siginfo_t info
= {};
94 queue_signal(env
, sig
, &info
);
97 static void host_signal_handler(int host_sig
, siginfo_t
*info
, void *puc
)
101 void signal_init(void)
103 TaskState
*ts
= (TaskState
*)thread_cpu
->opaque
;
104 struct sigaction act
;
105 struct sigaction oact
;
109 /* Set the signal mask from the host mask. */
110 sigprocmask(0, 0, &ts
->signal_mask
);
112 sigfillset(&act
.sa_mask
);
113 act
.sa_sigaction
= host_signal_handler
;
114 act
.sa_flags
= SA_SIGINFO
;
116 for (i
= 1; i
<= TARGET_NSIG
; i
++) {
118 if (i
== TARGET_SIGPROF
) {
122 host_sig
= target_to_host_signal(i
);
123 sigaction(host_sig
, NULL
, &oact
);
124 if (oact
.sa_sigaction
== (void *)SIG_IGN
) {
125 sigact_table
[i
- 1]._sa_handler
= TARGET_SIG_IGN
;
126 } else if (oact
.sa_sigaction
== (void *)SIG_DFL
) {
127 sigact_table
[i
- 1]._sa_handler
= TARGET_SIG_DFL
;
130 * If there's already a handler installed then something has
131 * gone horribly wrong, so don't even try to handle that case.
132 * Install some handlers for our own use. We need at least
133 * SIGSEGV and SIGBUS, to detect exceptions. We can not just
134 * trap all signals because it affects syscall interrupt
135 * behavior. But do trap all default-fatal signals.
137 if (fatal_signal(i
)) {
138 sigaction(host_sig
, &act
, NULL
);
143 void process_pending_signals(CPUArchState
*cpu_env
)
147 void cpu_loop_exit_sigsegv(CPUState
*cpu
, target_ulong addr
,
148 MMUAccessType access_type
, bool maperr
, uintptr_t ra
)
150 const struct TCGCPUOps
*tcg_ops
= CPU_GET_CLASS(cpu
)->tcg_ops
;
152 if (tcg_ops
->record_sigsegv
) {
153 tcg_ops
->record_sigsegv(cpu
, addr
, access_type
, maperr
, ra
);
156 force_sig_fault(TARGET_SIGSEGV
,
157 maperr
? TARGET_SEGV_MAPERR
: TARGET_SEGV_ACCERR
,
159 cpu
->exception_index
= EXCP_INTERRUPT
;
160 cpu_loop_exit_restore(cpu
, ra
);
163 void cpu_loop_exit_sigbus(CPUState
*cpu
, target_ulong addr
,
164 MMUAccessType access_type
, uintptr_t ra
)
166 const struct TCGCPUOps
*tcg_ops
= CPU_GET_CLASS(cpu
)->tcg_ops
;
168 if (tcg_ops
->record_sigbus
) {
169 tcg_ops
->record_sigbus(cpu
, addr
, access_type
, ra
);
172 force_sig_fault(TARGET_SIGBUS
, TARGET_BUS_ADRALN
, addr
);
173 cpu
->exception_index
= EXCP_INTERRUPT
;
174 cpu_loop_exit_restore(cpu
, ra
);