1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include "qemu/osdep.h"
20#include "qemu.h"
21#include "user-internals.h"
22#include "signal-common.h"
23#include "linux-user/trace.h"
24
25
26
27
28
29
30
31
32
33struct target_sigcontext {
34 abi_long pc;
35 abi_long gpr[31];
36 uint64_t fpr[32];
37 uint32_t fcsr;
38};
39
40struct target_ucontext {
41 unsigned long uc_flags;
42 struct target_ucontext *uc_link;
43 target_stack_t uc_stack;
44 target_sigset_t uc_sigmask;
45 uint8_t __unused[1024 / 8 - sizeof(target_sigset_t)];
46 struct target_sigcontext uc_mcontext QEMU_ALIGNED(16);
47};
48
49struct target_rt_sigframe {
50 struct target_siginfo info;
51 struct target_ucontext uc;
52};
53
54static abi_ulong get_sigframe(struct target_sigaction *ka,
55 CPURISCVState *regs, size_t framesize)
56{
57 abi_ulong sp = get_sp_from_cpustate(regs);
58
59
60
61 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) {
62 return -1L;
63 }
64
65
66 sp = target_sigsp(sp, ka) - framesize;
67 sp &= ~0xf;
68
69 return sp;
70}
71
72static void setup_sigcontext(struct target_sigcontext *sc, CPURISCVState *env)
73{
74 int i;
75
76 __put_user(env->pc, &sc->pc);
77
78 for (i = 1; i < 32; i++) {
79 __put_user(env->gpr[i], &sc->gpr[i - 1]);
80 }
81 for (i = 0; i < 32; i++) {
82 __put_user(env->fpr[i], &sc->fpr[i]);
83 }
84
85 uint32_t fcsr = riscv_csr_read(env, CSR_FCSR);
86 __put_user(fcsr, &sc->fcsr);
87}
88
89static void setup_ucontext(struct target_ucontext *uc,
90 CPURISCVState *env, target_sigset_t *set)
91{
92 __put_user(0, &(uc->uc_flags));
93 __put_user(0, &(uc->uc_link));
94
95 target_save_altstack(&uc->uc_stack, env);
96
97 int i;
98 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
99 __put_user(set->sig[i], &(uc->uc_sigmask.sig[i]));
100 }
101
102 setup_sigcontext(&uc->uc_mcontext, env);
103}
104
105void setup_rt_frame(int sig, struct target_sigaction *ka,
106 target_siginfo_t *info,
107 target_sigset_t *set, CPURISCVState *env)
108{
109 abi_ulong frame_addr;
110 struct target_rt_sigframe *frame;
111
112 frame_addr = get_sigframe(ka, env, sizeof(*frame));
113 trace_user_setup_rt_frame(env, frame_addr);
114
115 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
116 goto badframe;
117 }
118
119 setup_ucontext(&frame->uc, env, set);
120 tswap_siginfo(&frame->info, info);
121
122 env->pc = ka->_sa_handler;
123 env->gpr[xSP] = frame_addr;
124 env->gpr[xA0] = sig;
125 env->gpr[xA1] = frame_addr + offsetof(struct target_rt_sigframe, info);
126 env->gpr[xA2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
127 env->gpr[xRA] = default_rt_sigreturn;
128
129 return;
130
131badframe:
132 unlock_user_struct(frame, frame_addr, 1);
133 if (sig == TARGET_SIGSEGV) {
134 ka->_sa_handler = TARGET_SIG_DFL;
135 }
136 force_sig(TARGET_SIGSEGV);
137}
138
139static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
140{
141 int i;
142
143 __get_user(env->pc, &sc->pc);
144
145 for (i = 1; i < 32; ++i) {
146 __get_user(env->gpr[i], &sc->gpr[i - 1]);
147 }
148 for (i = 0; i < 32; ++i) {
149 __get_user(env->fpr[i], &sc->fpr[i]);
150 }
151
152 uint32_t fcsr;
153 __get_user(fcsr, &sc->fcsr);
154 riscv_csr_write(env, CSR_FCSR, fcsr);
155}
156
157static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
158{
159 sigset_t blocked;
160 target_sigset_t target_set;
161 int i;
162
163 target_sigemptyset(&target_set);
164 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
165 __get_user(target_set.sig[i], &(uc->uc_sigmask.sig[i]));
166 }
167
168 target_to_host_sigset_internal(&blocked, &target_set);
169 set_sigmask(&blocked);
170
171 restore_sigcontext(env, &uc->uc_mcontext);
172}
173
174long do_rt_sigreturn(CPURISCVState *env)
175{
176 struct target_rt_sigframe *frame;
177 abi_ulong frame_addr;
178
179 frame_addr = env->gpr[xSP];
180 trace_user_do_sigreturn(env, frame_addr);
181 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
182 goto badframe;
183 }
184
185 restore_ucontext(env, &frame->uc);
186 target_restore_altstack(&frame->uc.uc_stack, env);
187
188 unlock_user_struct(frame, frame_addr, 0);
189 return -QEMU_ESIGRETURN;
190
191badframe:
192 unlock_user_struct(frame, frame_addr, 0);
193 force_sig(TARGET_SIGSEGV);
194 return 0;
195}
196
197void setup_sigtramp(abi_ulong sigtramp_page)
198{
199 uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
200 assert(tramp != NULL);
201
202 __put_user(0x08b00893, tramp + 0);
203 __put_user(0x00000073, tramp + 1);
204
205 default_rt_sigreturn = sigtramp_page;
206 unlock_user(tramp, sigtramp_page, 8);
207}
208