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 "cpu.h"
21#include "disas/disas.h"
22#include "exec/exec-all.h"
23#include "tcg.h"
24#include "qemu/bitops.h"
25#include "exec/cpu_ldst.h"
26#include "translate-all.h"
27#include "exec/helper-proto.h"
28#include "qemu/atomic128.h"
29
30#undef EAX
31#undef ECX
32#undef EDX
33#undef EBX
34#undef ESP
35#undef EBP
36#undef ESI
37#undef EDI
38#undef EIP
39#ifdef __linux__
40#include <sys/ucontext.h>
41#endif
42
43__thread uintptr_t helper_retaddr;
44
45
46
47
48
49
50static void cpu_exit_tb_from_sighandler(CPUState *cpu, sigset_t *old_set)
51{
52
53 sigprocmask(SIG_SETMASK, old_set, NULL);
54 cpu_loop_exit_noexc(cpu);
55}
56
57
58
59
60
61static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
62 int is_write, sigset_t *old_set)
63{
64 CPUState *cpu = current_cpu;
65 CPUClass *cc;
66 unsigned long address = (unsigned long)info->si_addr;
67 MMUAccessType access_type = is_write ? MMU_DATA_STORE : MMU_DATA_LOAD;
68
69 switch (helper_retaddr) {
70 default:
71
72
73
74
75
76
77 pc = helper_retaddr;
78 break;
79
80 case 0:
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 pc += GETPC_ADJ;
98 break;
99
100 case 1:
101
102
103
104
105
106
107
108
109
110
111
112
113 pc = 0;
114 access_type = MMU_INST_FETCH;
115 mmap_unlock();
116 break;
117 }
118
119
120
121
122
123
124
125
126 if (!cpu || !cpu->running) {
127 printf("qemu:%s received signal outside vCPU context @ pc=0x%"
128 PRIxPTR "\n", __func__, pc);
129 abort();
130 }
131
132#if defined(DEBUG_SIGNAL)
133 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
134 pc, address, is_write, *(unsigned long *)old_set);
135#endif
136
137
138
139
140
141
142
143
144
145
146
147 if (is_write && info->si_signo == SIGSEGV && info->si_code == SEGV_ACCERR &&
148 h2g_valid(address)) {
149 switch (page_unprotect(h2g(address), pc)) {
150 case 0:
151
152
153
154 break;
155 case 1:
156
157
158
159
160 return 1;
161 case 2:
162
163
164
165
166 clear_helper_retaddr();
167 cpu_exit_tb_from_sighandler(cpu, old_set);
168
169
170 default:
171 g_assert_not_reached();
172 }
173 }
174
175
176
177 address = h2g_nocheck(address);
178
179
180
181
182
183 sigprocmask(SIG_SETMASK, old_set, NULL);
184 clear_helper_retaddr();
185
186 cc = CPU_GET_CLASS(cpu);
187 cc->tlb_fill(cpu, address, 0, access_type, MMU_USER_IDX, false, pc);
188 g_assert_not_reached();
189}
190
191void *probe_access(CPUArchState *env, target_ulong addr, int size,
192 MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
193{
194 int flags;
195
196 g_assert(-(addr | TARGET_PAGE_MASK) >= size);
197
198 switch (access_type) {
199 case MMU_DATA_STORE:
200 flags = PAGE_WRITE;
201 break;
202 case MMU_DATA_LOAD:
203 flags = PAGE_READ;
204 break;
205 case MMU_INST_FETCH:
206 flags = PAGE_EXEC;
207 break;
208 default:
209 g_assert_not_reached();
210 }
211
212 if (!guest_addr_valid(addr) || page_check_range(addr, size, flags) < 0) {
213 CPUState *cpu = env_cpu(env);
214 CPUClass *cc = CPU_GET_CLASS(cpu);
215 cc->tlb_fill(cpu, addr, size, access_type, MMU_USER_IDX, false,
216 retaddr);
217 g_assert_not_reached();
218 }
219
220 return size ? g2h(addr) : NULL;
221}
222
223#if defined(__i386__)
224
225#if defined(__NetBSD__)
226#include <ucontext.h>
227
228#define EIP_sig(context) ((context)->uc_mcontext.__gregs[_REG_EIP])
229#define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
230#define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
231#define MASK_sig(context) ((context)->uc_sigmask)
232#elif defined(__FreeBSD__) || defined(__DragonFly__)
233#include <ucontext.h>
234
235#define EIP_sig(context) (*((unsigned long *)&(context)->uc_mcontext.mc_eip))
236#define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
237#define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
238#define MASK_sig(context) ((context)->uc_sigmask)
239#elif defined(__OpenBSD__)
240#define EIP_sig(context) ((context)->sc_eip)
241#define TRAP_sig(context) ((context)->sc_trapno)
242#define ERROR_sig(context) ((context)->sc_err)
243#define MASK_sig(context) ((context)->sc_mask)
244#else
245#define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
246#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
247#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
248#define MASK_sig(context) ((context)->uc_sigmask)
249#endif
250
251int cpu_signal_handler(int host_signum, void *pinfo,
252 void *puc)
253{
254 siginfo_t *info = pinfo;
255#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
256 ucontext_t *uc = puc;
257#elif defined(__OpenBSD__)
258 struct sigcontext *uc = puc;
259#else
260 ucontext_t *uc = puc;
261#endif
262 unsigned long pc;
263 int trapno;
264
265#ifndef REG_EIP
266
267#define REG_EIP EIP
268#define REG_ERR ERR
269#define REG_TRAPNO TRAPNO
270#endif
271 pc = EIP_sig(uc);
272 trapno = TRAP_sig(uc);
273 return handle_cpu_signal(pc, info,
274 trapno == 0xe ? (ERROR_sig(uc) >> 1) & 1 : 0,
275 &MASK_sig(uc));
276}
277
278#elif defined(__x86_64__)
279
280#ifdef __NetBSD__
281#define PC_sig(context) _UC_MACHINE_PC(context)
282#define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
283#define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
284#define MASK_sig(context) ((context)->uc_sigmask)
285#elif defined(__OpenBSD__)
286#define PC_sig(context) ((context)->sc_rip)
287#define TRAP_sig(context) ((context)->sc_trapno)
288#define ERROR_sig(context) ((context)->sc_err)
289#define MASK_sig(context) ((context)->sc_mask)
290#elif defined(__FreeBSD__) || defined(__DragonFly__)
291#include <ucontext.h>
292
293#define PC_sig(context) (*((unsigned long *)&(context)->uc_mcontext.mc_rip))
294#define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
295#define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
296#define MASK_sig(context) ((context)->uc_sigmask)
297#else
298#define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP])
299#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
300#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
301#define MASK_sig(context) ((context)->uc_sigmask)
302#endif
303
304int cpu_signal_handler(int host_signum, void *pinfo,
305 void *puc)
306{
307 siginfo_t *info = pinfo;
308 unsigned long pc;
309#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
310 ucontext_t *uc = puc;
311#elif defined(__OpenBSD__)
312 struct sigcontext *uc = puc;
313#else
314 ucontext_t *uc = puc;
315#endif
316
317 pc = PC_sig(uc);
318 return handle_cpu_signal(pc, info,
319 TRAP_sig(uc) == 0xe ? (ERROR_sig(uc) >> 1) & 1 : 0,
320 &MASK_sig(uc));
321}
322
323#elif defined(_ARCH_PPC)
324
325
326
327
328
329#ifdef linux
330
331#define REG_sig(reg_name, context) \
332 ((context)->uc_mcontext.regs->reg_name)
333
334#define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
335
336#define IAR_sig(context) REG_sig(nip, context)
337
338#define MSR_sig(context) REG_sig(msr, context)
339
340#define CTR_sig(context) REG_sig(ctr, context)
341
342#define XER_sig(context) REG_sig(xer, context)
343
344#define LR_sig(context) REG_sig(link, context)
345
346#define CR_sig(context) REG_sig(ccr, context)
347
348
349#define FLOAT_sig(reg_num, context) \
350 (((double *)((char *)((context)->uc_mcontext.regs + 48 * 4)))[reg_num])
351#define FPSCR_sig(context) \
352 (*(int *)((char *)((context)->uc_mcontext.regs + (48 + 32 * 2) * 4)))
353
354#define DAR_sig(context) REG_sig(dar, context)
355#define DSISR_sig(context) REG_sig(dsisr, context)
356#define TRAP_sig(context) REG_sig(trap, context)
357#endif
358
359#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
360#include <ucontext.h>
361#define IAR_sig(context) ((context)->uc_mcontext.mc_srr0)
362#define MSR_sig(context) ((context)->uc_mcontext.mc_srr1)
363#define CTR_sig(context) ((context)->uc_mcontext.mc_ctr)
364#define XER_sig(context) ((context)->uc_mcontext.mc_xer)
365#define LR_sig(context) ((context)->uc_mcontext.mc_lr)
366#define CR_sig(context) ((context)->uc_mcontext.mc_cr)
367
368#define DAR_sig(context) ((context)->uc_mcontext.mc_dar)
369#define DSISR_sig(context) ((context)->uc_mcontext.mc_dsisr)
370#define TRAP_sig(context) ((context)->uc_mcontext.mc_exc)
371#endif
372
373int cpu_signal_handler(int host_signum, void *pinfo,
374 void *puc)
375{
376 siginfo_t *info = pinfo;
377#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
378 ucontext_t *uc = puc;
379#else
380 ucontext_t *uc = puc;
381#endif
382 unsigned long pc;
383 int is_write;
384
385 pc = IAR_sig(uc);
386 is_write = 0;
387#if 0
388
389 if (DSISR_sig(uc) & 0x00800000) {
390 is_write = 1;
391 }
392#else
393 if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000)) {
394 is_write = 1;
395 }
396#endif
397 return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
398}
399
400#elif defined(__alpha__)
401
402int cpu_signal_handler(int host_signum, void *pinfo,
403 void *puc)
404{
405 siginfo_t *info = pinfo;
406 ucontext_t *uc = puc;
407 uint32_t *pc = uc->uc_mcontext.sc_pc;
408 uint32_t insn = *pc;
409 int is_write = 0;
410
411
412 switch (insn >> 26) {
413 case 0x0d:
414 case 0x0e:
415 case 0x0f:
416 case 0x24:
417 case 0x25:
418 case 0x26:
419 case 0x27:
420 case 0x2c:
421 case 0x2d:
422 case 0x2e:
423 case 0x2f:
424 is_write = 1;
425 }
426
427 return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
428}
429#elif defined(__sparc__)
430
431int cpu_signal_handler(int host_signum, void *pinfo,
432 void *puc)
433{
434 siginfo_t *info = pinfo;
435 int is_write;
436 uint32_t insn;
437#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
438 uint32_t *regs = (uint32_t *)(info + 1);
439 void *sigmask = (regs + 20);
440
441 unsigned long pc = regs[1];
442#else
443#ifdef __linux__
444 struct sigcontext *sc = puc;
445 unsigned long pc = sc->sigc_regs.tpc;
446 void *sigmask = (void *)sc->sigc_mask;
447#elif defined(__OpenBSD__)
448 struct sigcontext *uc = puc;
449 unsigned long pc = uc->sc_pc;
450 void *sigmask = (void *)(long)uc->sc_mask;
451#elif defined(__NetBSD__)
452 ucontext_t *uc = puc;
453 unsigned long pc = _UC_MACHINE_PC(uc);
454 void *sigmask = (void *)&uc->uc_sigmask;
455#endif
456#endif
457
458
459 is_write = 0;
460 insn = *(uint32_t *)pc;
461 if ((insn >> 30) == 3) {
462 switch ((insn >> 19) & 0x3f) {
463 case 0x05:
464 case 0x15:
465 case 0x06:
466 case 0x16:
467 case 0x04:
468 case 0x14:
469 case 0x07:
470 case 0x17:
471 case 0x0e:
472 case 0x1e:
473 case 0x24:
474 case 0x34:
475 case 0x27:
476 case 0x37:
477 case 0x26:
478 case 0x36:
479 case 0x25:
480 case 0x3c:
481 case 0x3e:
482 is_write = 1;
483 break;
484 }
485 }
486 return handle_cpu_signal(pc, info, is_write, sigmask);
487}
488
489#elif defined(__arm__)
490
491#if defined(__NetBSD__)
492#include <ucontext.h>
493#endif
494
495int cpu_signal_handler(int host_signum, void *pinfo,
496 void *puc)
497{
498 siginfo_t *info = pinfo;
499#if defined(__NetBSD__)
500 ucontext_t *uc = puc;
501#else
502 ucontext_t *uc = puc;
503#endif
504 unsigned long pc;
505 int is_write;
506
507#if defined(__NetBSD__)
508 pc = uc->uc_mcontext.__gregs[_REG_R15];
509#elif defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
510 pc = uc->uc_mcontext.gregs[R15];
511#else
512 pc = uc->uc_mcontext.arm_pc;
513#endif
514
515
516
517
518 is_write = extract32(uc->uc_mcontext.error_code, 11, 1);
519 return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
520}
521
522#elif defined(__aarch64__)
523
524#ifndef ESR_MAGIC
525
526#define ESR_MAGIC 0x45535201
527struct esr_context {
528 struct _aarch64_ctx head;
529 uint64_t esr;
530};
531#endif
532
533static inline struct _aarch64_ctx *first_ctx(ucontext_t *uc)
534{
535 return (struct _aarch64_ctx *)&uc->uc_mcontext.__reserved;
536}
537
538static inline struct _aarch64_ctx *next_ctx(struct _aarch64_ctx *hdr)
539{
540 return (struct _aarch64_ctx *)((char *)hdr + hdr->size);
541}
542
543int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
544{
545 siginfo_t *info = pinfo;
546 ucontext_t *uc = puc;
547 uintptr_t pc = uc->uc_mcontext.pc;
548 bool is_write;
549 struct _aarch64_ctx *hdr;
550 struct esr_context const *esrctx = NULL;
551
552
553 for (hdr = first_ctx(uc); hdr->magic; hdr = next_ctx(hdr)) {
554 if (hdr->magic == ESR_MAGIC) {
555 esrctx = (struct esr_context const *)hdr;
556 break;
557 }
558 }
559
560 if (esrctx) {
561
562 uint64_t esr = esrctx->esr;
563 is_write = extract32(esr, 27, 5) == 0x12 && extract32(esr, 6, 1) == 1;
564 } else {
565
566
567
568
569 uint32_t insn = *(uint32_t *)pc;
570
571 is_write = ((insn & 0xbfff0000) == 0x0c000000
572 || (insn & 0xbfe00000) == 0x0c800000
573 || (insn & 0xbfdf0000) == 0x0d000000
574 || (insn & 0xbfc00000) == 0x0d800000
575 || (insn & 0x3f400000) == 0x08000000
576 || (insn & 0x3bc00000) == 0x39000000
577 || (insn & 0x3fc00000) == 0x3d800000
578
579 || (insn & 0x3bc00000) == 0x38000000
580 || (insn & 0x3fe00000) == 0x3c800000
581
582 || (insn & 0x3a400000) == 0x28000000);
583 }
584 return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
585}
586
587#elif defined(__s390__)
588
589int cpu_signal_handler(int host_signum, void *pinfo,
590 void *puc)
591{
592 siginfo_t *info = pinfo;
593 ucontext_t *uc = puc;
594 unsigned long pc;
595 uint16_t *pinsn;
596 int is_write = 0;
597
598 pc = uc->uc_mcontext.psw.addr;
599
600
601
602
603
604
605
606
607 pinsn = (uint16_t *)pc;
608 switch (pinsn[0] >> 8) {
609 case 0x50:
610 case 0x42:
611 case 0x40:
612 is_write = 1;
613 break;
614 case 0xc4:
615 switch (pinsn[0] & 0xf) {
616 case 0xf:
617 case 0xb:
618 case 0x7:
619 is_write = 1;
620 }
621 break;
622 case 0xe3:
623 switch (pinsn[2] & 0xff) {
624 case 0x50:
625 case 0x24:
626 case 0x72:
627 case 0x70:
628 case 0x8e:
629 case 0x3f:
630 case 0x3e:
631 case 0x2f:
632 is_write = 1;
633 }
634 break;
635 }
636 return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
637}
638
639#elif defined(__mips__)
640
641int cpu_signal_handler(int host_signum, void *pinfo,
642 void *puc)
643{
644 siginfo_t *info = pinfo;
645 ucontext_t *uc = puc;
646 greg_t pc = uc->uc_mcontext.pc;
647 int is_write;
648
649
650 is_write = 0;
651 return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
652}
653
654#elif defined(__riscv)
655
656int cpu_signal_handler(int host_signum, void *pinfo,
657 void *puc)
658{
659 siginfo_t *info = pinfo;
660 ucontext_t *uc = puc;
661 greg_t pc = uc->uc_mcontext.__gregs[REG_PC];
662 uint32_t insn = *(uint32_t *)pc;
663 int is_write = 0;
664
665
666
667
668 switch (((insn >> 0) & 0b11)) {
669 case 3:
670 switch (((insn >> 2) & 0b11111)) {
671 case 8:
672 switch (((insn >> 12) & 0b111)) {
673 case 0:
674 case 1:
675 case 2:
676 case 3:
677 case 4:
678 is_write = 1;
679 break;
680 default:
681 break;
682 }
683 break;
684 case 9:
685 switch (((insn >> 12) & 0b111)) {
686 case 2:
687 case 3:
688 case 4:
689 is_write = 1;
690 break;
691 default:
692 break;
693 }
694 break;
695 default:
696 break;
697 }
698 }
699
700
701 switch (((insn >> 13) & 0b111)) {
702 case 7:
703 switch (insn & 0b11) {
704 case 0:
705 case 2:
706 is_write = 1;
707 break;
708 default:
709 break;
710 }
711 break;
712 case 6:
713 switch (insn & 0b11) {
714 case 0:
715 case 3:
716 is_write = 1;
717 break;
718 default:
719 break;
720 }
721 break;
722 default:
723 break;
724 }
725
726 return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
727}
728
729#else
730
731#error host CPU specific signal handler needed
732
733#endif
734
735
736
737
738static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
739 int size, uintptr_t retaddr)
740{
741
742 if (unlikely(addr & (size - 1))) {
743 cpu_loop_exit_atomic(env_cpu(env), retaddr);
744 }
745 void *ret = g2h(addr);
746 set_helper_retaddr(retaddr);
747 return ret;
748}
749
750
751#define ATOMIC_MMU_DECLS do {} while (0)
752#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, DATA_SIZE, GETPC())
753#define ATOMIC_MMU_CLEANUP do { clear_helper_retaddr(); } while (0)
754#define ATOMIC_MMU_IDX MMU_USER_IDX
755
756#define ATOMIC_NAME(X) HELPER(glue(glue(atomic_ ## X, SUFFIX), END))
757#define EXTRA_ARGS
758
759#include "atomic_common.inc.c"
760
761#define DATA_SIZE 1
762#include "atomic_template.h"
763
764#define DATA_SIZE 2
765#include "atomic_template.h"
766
767#define DATA_SIZE 4
768#include "atomic_template.h"
769
770#ifdef CONFIG_ATOMIC64
771#define DATA_SIZE 8
772#include "atomic_template.h"
773#endif
774
775
776
777
778#if HAVE_ATOMIC128 || HAVE_CMPXCHG128
779
780#undef EXTRA_ARGS
781#undef ATOMIC_NAME
782#undef ATOMIC_MMU_LOOKUP
783
784#define EXTRA_ARGS , TCGMemOpIdx oi, uintptr_t retaddr
785#define ATOMIC_NAME(X) \
786 HELPER(glue(glue(glue(atomic_ ## X, SUFFIX), END), _mmu))
787#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, DATA_SIZE, retaddr)
788
789#define DATA_SIZE 16
790#include "atomic_template.h"
791#endif
792