]> git.proxmox.com Git - mirror_qemu.git/blob - accel/tcg/user-exec.c
Merge tag 'pull-tcg-20221220' of https://gitlab.com/rth7680/qemu into staging
[mirror_qemu.git] / accel / tcg / user-exec.c
1 /*
2 * User emulator execution
3 *
4 * Copyright (c) 2003-2005 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "qemu/osdep.h"
20 #include "hw/core/tcg-cpu-ops.h"
21 #include "disas/disas.h"
22 #include "exec/exec-all.h"
23 #include "tcg/tcg.h"
24 #include "qemu/bitops.h"
25 #include "exec/cpu_ldst.h"
26 #include "exec/translate-all.h"
27 #include "exec/helper-proto.h"
28 #include "qemu/atomic128.h"
29 #include "trace/trace-root.h"
30 #include "tcg/tcg-ldst.h"
31 #include "internal.h"
32
33 __thread uintptr_t helper_retaddr;
34
35 //#define DEBUG_SIGNAL
36
37 /*
38 * Adjust the pc to pass to cpu_restore_state; return the memop type.
39 */
40 MMUAccessType adjust_signal_pc(uintptr_t *pc, bool is_write)
41 {
42 switch (helper_retaddr) {
43 default:
44 /*
45 * Fault during host memory operation within a helper function.
46 * The helper's host return address, saved here, gives us a
47 * pointer into the generated code that will unwind to the
48 * correct guest pc.
49 */
50 *pc = helper_retaddr;
51 break;
52
53 case 0:
54 /*
55 * Fault during host memory operation within generated code.
56 * (Or, a unrelated bug within qemu, but we can't tell from here).
57 *
58 * We take the host pc from the signal frame. However, we cannot
59 * use that value directly. Within cpu_restore_state_from_tb, we
60 * assume PC comes from GETPC(), as used by the helper functions,
61 * so we adjust the address by -GETPC_ADJ to form an address that
62 * is within the call insn, so that the address does not accidentally
63 * match the beginning of the next guest insn. However, when the
64 * pc comes from the signal frame it points to the actual faulting
65 * host memory insn and not the return from a call insn.
66 *
67 * Therefore, adjust to compensate for what will be done later
68 * by cpu_restore_state_from_tb.
69 */
70 *pc += GETPC_ADJ;
71 break;
72
73 case 1:
74 /*
75 * Fault during host read for translation, or loosely, "execution".
76 *
77 * The guest pc is already pointing to the start of the TB for which
78 * code is being generated. If the guest translator manages the
79 * page crossings correctly, this is exactly the correct address
80 * (and if the translator doesn't handle page boundaries correctly
81 * there's little we can do about that here). Therefore, do not
82 * trigger the unwinder.
83 */
84 *pc = 0;
85 return MMU_INST_FETCH;
86 }
87
88 return is_write ? MMU_DATA_STORE : MMU_DATA_LOAD;
89 }
90
91 /**
92 * handle_sigsegv_accerr_write:
93 * @cpu: the cpu context
94 * @old_set: the sigset_t from the signal ucontext_t
95 * @host_pc: the host pc, adjusted for the signal
96 * @guest_addr: the guest address of the fault
97 *
98 * Return true if the write fault has been handled, and should be re-tried.
99 *
100 * Note that it is important that we don't call page_unprotect() unless
101 * this is really a "write to nonwritable page" fault, because
102 * page_unprotect() assumes that if it is called for an access to
103 * a page that's writable this means we had two threads racing and
104 * another thread got there first and already made the page writable;
105 * so we will retry the access. If we were to call page_unprotect()
106 * for some other kind of fault that should really be passed to the
107 * guest, we'd end up in an infinite loop of retrying the faulting access.
108 */
109 bool handle_sigsegv_accerr_write(CPUState *cpu, sigset_t *old_set,
110 uintptr_t host_pc, abi_ptr guest_addr)
111 {
112 switch (page_unprotect(guest_addr, host_pc)) {
113 case 0:
114 /*
115 * Fault not caused by a page marked unwritable to protect
116 * cached translations, must be the guest binary's problem.
117 */
118 return false;
119 case 1:
120 /*
121 * Fault caused by protection of cached translation; TBs
122 * invalidated, so resume execution.
123 */
124 return true;
125 case 2:
126 /*
127 * Fault caused by protection of cached translation, and the
128 * currently executing TB was modified and must be exited immediately.
129 */
130 sigprocmask(SIG_SETMASK, old_set, NULL);
131 cpu_loop_exit_noexc(cpu);
132 /* NORETURN */
133 default:
134 g_assert_not_reached();
135 }
136 }
137
138 typedef struct PageFlagsNode {
139 IntervalTreeNode itree;
140 int flags;
141 } PageFlagsNode;
142
143 static IntervalTreeRoot pageflags_root;
144
145 static PageFlagsNode *pageflags_find(target_ulong start, target_long last)
146 {
147 IntervalTreeNode *n;
148
149 n = interval_tree_iter_first(&pageflags_root, start, last);
150 return n ? container_of(n, PageFlagsNode, itree) : NULL;
151 }
152
153 static PageFlagsNode *pageflags_next(PageFlagsNode *p, target_ulong start,
154 target_long last)
155 {
156 IntervalTreeNode *n;
157
158 n = interval_tree_iter_next(&p->itree, start, last);
159 return n ? container_of(n, PageFlagsNode, itree) : NULL;
160 }
161
162 int walk_memory_regions(void *priv, walk_memory_regions_fn fn)
163 {
164 IntervalTreeNode *n;
165 int rc = 0;
166
167 mmap_lock();
168 for (n = interval_tree_iter_first(&pageflags_root, 0, -1);
169 n != NULL;
170 n = interval_tree_iter_next(n, 0, -1)) {
171 PageFlagsNode *p = container_of(n, PageFlagsNode, itree);
172
173 rc = fn(priv, n->start, n->last + 1, p->flags);
174 if (rc != 0) {
175 break;
176 }
177 }
178 mmap_unlock();
179
180 return rc;
181 }
182
183 static int dump_region(void *priv, target_ulong start,
184 target_ulong end, unsigned long prot)
185 {
186 FILE *f = (FILE *)priv;
187
188 fprintf(f, TARGET_FMT_lx"-"TARGET_FMT_lx" "TARGET_FMT_lx" %c%c%c\n",
189 start, end, end - start,
190 ((prot & PAGE_READ) ? 'r' : '-'),
191 ((prot & PAGE_WRITE) ? 'w' : '-'),
192 ((prot & PAGE_EXEC) ? 'x' : '-'));
193 return 0;
194 }
195
196 /* dump memory mappings */
197 void page_dump(FILE *f)
198 {
199 const int length = sizeof(target_ulong) * 2;
200
201 fprintf(f, "%-*s %-*s %-*s %s\n",
202 length, "start", length, "end", length, "size", "prot");
203 walk_memory_regions(f, dump_region);
204 }
205
206 int page_get_flags(target_ulong address)
207 {
208 PageFlagsNode *p = pageflags_find(address, address);
209
210 /*
211 * See util/interval-tree.c re lockless lookups: no false positives but
212 * there are false negatives. If we find nothing, retry with the mmap
213 * lock acquired.
214 */
215 if (p) {
216 return p->flags;
217 }
218 if (have_mmap_lock()) {
219 return 0;
220 }
221
222 mmap_lock();
223 p = pageflags_find(address, address);
224 mmap_unlock();
225 return p ? p->flags : 0;
226 }
227
228 /* A subroutine of page_set_flags: insert a new node for [start,last]. */
229 static void pageflags_create(target_ulong start, target_ulong last, int flags)
230 {
231 PageFlagsNode *p = g_new(PageFlagsNode, 1);
232
233 p->itree.start = start;
234 p->itree.last = last;
235 p->flags = flags;
236 interval_tree_insert(&p->itree, &pageflags_root);
237 }
238
239 /* A subroutine of page_set_flags: remove everything in [start,last]. */
240 static bool pageflags_unset(target_ulong start, target_ulong last)
241 {
242 bool inval_tb = false;
243
244 while (true) {
245 PageFlagsNode *p = pageflags_find(start, last);
246 target_ulong p_last;
247
248 if (!p) {
249 break;
250 }
251
252 if (p->flags & PAGE_EXEC) {
253 inval_tb = true;
254 }
255
256 interval_tree_remove(&p->itree, &pageflags_root);
257 p_last = p->itree.last;
258
259 if (p->itree.start < start) {
260 /* Truncate the node from the end, or split out the middle. */
261 p->itree.last = start - 1;
262 interval_tree_insert(&p->itree, &pageflags_root);
263 if (last < p_last) {
264 pageflags_create(last + 1, p_last, p->flags);
265 break;
266 }
267 } else if (p_last <= last) {
268 /* Range completely covers node -- remove it. */
269 g_free(p);
270 } else {
271 /* Truncate the node from the start. */
272 p->itree.start = last + 1;
273 interval_tree_insert(&p->itree, &pageflags_root);
274 break;
275 }
276 }
277
278 return inval_tb;
279 }
280
281 /*
282 * A subroutine of page_set_flags: nothing overlaps [start,last],
283 * but check adjacent mappings and maybe merge into a single range.
284 */
285 static void pageflags_create_merge(target_ulong start, target_ulong last,
286 int flags)
287 {
288 PageFlagsNode *next = NULL, *prev = NULL;
289
290 if (start > 0) {
291 prev = pageflags_find(start - 1, start - 1);
292 if (prev) {
293 if (prev->flags == flags) {
294 interval_tree_remove(&prev->itree, &pageflags_root);
295 } else {
296 prev = NULL;
297 }
298 }
299 }
300 if (last + 1 != 0) {
301 next = pageflags_find(last + 1, last + 1);
302 if (next) {
303 if (next->flags == flags) {
304 interval_tree_remove(&next->itree, &pageflags_root);
305 } else {
306 next = NULL;
307 }
308 }
309 }
310
311 if (prev) {
312 if (next) {
313 prev->itree.last = next->itree.last;
314 g_free(next);
315 } else {
316 prev->itree.last = last;
317 }
318 interval_tree_insert(&prev->itree, &pageflags_root);
319 } else if (next) {
320 next->itree.start = start;
321 interval_tree_insert(&next->itree, &pageflags_root);
322 } else {
323 pageflags_create(start, last, flags);
324 }
325 }
326
327 /*
328 * Allow the target to decide if PAGE_TARGET_[12] may be reset.
329 * By default, they are not kept.
330 */
331 #ifndef PAGE_TARGET_STICKY
332 #define PAGE_TARGET_STICKY 0
333 #endif
334 #define PAGE_STICKY (PAGE_ANON | PAGE_PASSTHROUGH | PAGE_TARGET_STICKY)
335
336 /* A subroutine of page_set_flags: add flags to [start,last]. */
337 static bool pageflags_set_clear(target_ulong start, target_ulong last,
338 int set_flags, int clear_flags)
339 {
340 PageFlagsNode *p;
341 target_ulong p_start, p_last;
342 int p_flags, merge_flags;
343 bool inval_tb = false;
344
345 restart:
346 p = pageflags_find(start, last);
347 if (!p) {
348 if (set_flags) {
349 pageflags_create_merge(start, last, set_flags);
350 }
351 goto done;
352 }
353
354 p_start = p->itree.start;
355 p_last = p->itree.last;
356 p_flags = p->flags;
357 /* Using mprotect on a page does not change sticky bits. */
358 merge_flags = (p_flags & ~clear_flags) | set_flags;
359
360 /*
361 * Need to flush if an overlapping executable region
362 * removes exec, or adds write.
363 */
364 if ((p_flags & PAGE_EXEC)
365 && (!(merge_flags & PAGE_EXEC)
366 || (merge_flags & ~p_flags & PAGE_WRITE))) {
367 inval_tb = true;
368 }
369
370 /*
371 * If there is an exact range match, update and return without
372 * attempting to merge with adjacent regions.
373 */
374 if (start == p_start && last == p_last) {
375 if (merge_flags) {
376 p->flags = merge_flags;
377 } else {
378 interval_tree_remove(&p->itree, &pageflags_root);
379 g_free(p);
380 }
381 goto done;
382 }
383
384 /*
385 * If sticky bits affect the original mapping, then we must be more
386 * careful about the existing intervals and the separate flags.
387 */
388 if (set_flags != merge_flags) {
389 if (p_start < start) {
390 interval_tree_remove(&p->itree, &pageflags_root);
391 p->itree.last = start - 1;
392 interval_tree_insert(&p->itree, &pageflags_root);
393
394 if (last < p_last) {
395 if (merge_flags) {
396 pageflags_create(start, last, merge_flags);
397 }
398 pageflags_create(last + 1, p_last, p_flags);
399 } else {
400 if (merge_flags) {
401 pageflags_create(start, p_last, merge_flags);
402 }
403 if (p_last < last) {
404 start = p_last + 1;
405 goto restart;
406 }
407 }
408 } else {
409 if (start < p_start && set_flags) {
410 pageflags_create(start, p_start - 1, set_flags);
411 }
412 if (last < p_last) {
413 interval_tree_remove(&p->itree, &pageflags_root);
414 p->itree.start = last + 1;
415 interval_tree_insert(&p->itree, &pageflags_root);
416 if (merge_flags) {
417 pageflags_create(start, last, merge_flags);
418 }
419 } else {
420 if (merge_flags) {
421 p->flags = merge_flags;
422 } else {
423 interval_tree_remove(&p->itree, &pageflags_root);
424 g_free(p);
425 }
426 if (p_last < last) {
427 start = p_last + 1;
428 goto restart;
429 }
430 }
431 }
432 goto done;
433 }
434
435 /* If flags are not changing for this range, incorporate it. */
436 if (set_flags == p_flags) {
437 if (start < p_start) {
438 interval_tree_remove(&p->itree, &pageflags_root);
439 p->itree.start = start;
440 interval_tree_insert(&p->itree, &pageflags_root);
441 }
442 if (p_last < last) {
443 start = p_last + 1;
444 goto restart;
445 }
446 goto done;
447 }
448
449 /* Maybe split out head and/or tail ranges with the original flags. */
450 interval_tree_remove(&p->itree, &pageflags_root);
451 if (p_start < start) {
452 p->itree.last = start - 1;
453 interval_tree_insert(&p->itree, &pageflags_root);
454
455 if (p_last < last) {
456 goto restart;
457 }
458 if (last < p_last) {
459 pageflags_create(last + 1, p_last, p_flags);
460 }
461 } else if (last < p_last) {
462 p->itree.start = last + 1;
463 interval_tree_insert(&p->itree, &pageflags_root);
464 } else {
465 g_free(p);
466 goto restart;
467 }
468 if (set_flags) {
469 pageflags_create(start, last, set_flags);
470 }
471
472 done:
473 return inval_tb;
474 }
475
476 /*
477 * Modify the flags of a page and invalidate the code if necessary.
478 * The flag PAGE_WRITE_ORG is positioned automatically depending
479 * on PAGE_WRITE. The mmap_lock should already be held.
480 */
481 void page_set_flags(target_ulong start, target_ulong end, int flags)
482 {
483 target_ulong last;
484 bool reset = false;
485 bool inval_tb = false;
486
487 /* This function should never be called with addresses outside the
488 guest address space. If this assert fires, it probably indicates
489 a missing call to h2g_valid. */
490 assert(start < end);
491 assert(end - 1 <= GUEST_ADDR_MAX);
492 /* Only set PAGE_ANON with new mappings. */
493 assert(!(flags & PAGE_ANON) || (flags & PAGE_RESET));
494 assert_memory_lock();
495
496 start = start & TARGET_PAGE_MASK;
497 end = TARGET_PAGE_ALIGN(end);
498 last = end - 1;
499
500 if (!(flags & PAGE_VALID)) {
501 flags = 0;
502 } else {
503 reset = flags & PAGE_RESET;
504 flags &= ~PAGE_RESET;
505 if (flags & PAGE_WRITE) {
506 flags |= PAGE_WRITE_ORG;
507 }
508 }
509
510 if (!flags || reset) {
511 page_reset_target_data(start, end);
512 inval_tb |= pageflags_unset(start, last);
513 }
514 if (flags) {
515 inval_tb |= pageflags_set_clear(start, last, flags,
516 ~(reset ? 0 : PAGE_STICKY));
517 }
518 if (inval_tb) {
519 tb_invalidate_phys_range(start, end);
520 }
521 }
522
523 int page_check_range(target_ulong start, target_ulong len, int flags)
524 {
525 target_ulong last;
526
527 if (len == 0) {
528 return 0; /* trivial length */
529 }
530
531 last = start + len - 1;
532 if (last < start) {
533 return -1; /* wrap around */
534 }
535
536 while (true) {
537 PageFlagsNode *p = pageflags_find(start, last);
538 int missing;
539
540 if (!p) {
541 return -1; /* entire region invalid */
542 }
543 if (start < p->itree.start) {
544 return -1; /* initial bytes invalid */
545 }
546
547 missing = flags & ~p->flags;
548 if (missing & PAGE_READ) {
549 return -1; /* page not readable */
550 }
551 if (missing & PAGE_WRITE) {
552 if (!(p->flags & PAGE_WRITE_ORG)) {
553 return -1; /* page not writable */
554 }
555 /* Asking about writable, but has been protected: undo. */
556 if (!page_unprotect(start, 0)) {
557 return -1;
558 }
559 /* TODO: page_unprotect should take a range, not a single page. */
560 if (last - start < TARGET_PAGE_SIZE) {
561 return 0; /* ok */
562 }
563 start += TARGET_PAGE_SIZE;
564 continue;
565 }
566
567 if (last <= p->itree.last) {
568 return 0; /* ok */
569 }
570 start = p->itree.last + 1;
571 }
572 }
573
574 void page_protect(tb_page_addr_t address)
575 {
576 PageFlagsNode *p;
577 target_ulong start, last;
578 int prot;
579
580 assert_memory_lock();
581
582 if (qemu_host_page_size <= TARGET_PAGE_SIZE) {
583 start = address & TARGET_PAGE_MASK;
584 last = start + TARGET_PAGE_SIZE - 1;
585 } else {
586 start = address & qemu_host_page_mask;
587 last = start + qemu_host_page_size - 1;
588 }
589
590 p = pageflags_find(start, last);
591 if (!p) {
592 return;
593 }
594 prot = p->flags;
595
596 if (unlikely(p->itree.last < last)) {
597 /* More than one protection region covers the one host page. */
598 assert(TARGET_PAGE_SIZE < qemu_host_page_size);
599 while ((p = pageflags_next(p, start, last)) != NULL) {
600 prot |= p->flags;
601 }
602 }
603
604 if (prot & PAGE_WRITE) {
605 pageflags_set_clear(start, last, 0, PAGE_WRITE);
606 mprotect(g2h_untagged(start), qemu_host_page_size,
607 prot & (PAGE_READ | PAGE_EXEC) ? PROT_READ : PROT_NONE);
608 }
609 }
610
611 /*
612 * Called from signal handler: invalidate the code and unprotect the
613 * page. Return 0 if the fault was not handled, 1 if it was handled,
614 * and 2 if it was handled but the caller must cause the TB to be
615 * immediately exited. (We can only return 2 if the 'pc' argument is
616 * non-zero.)
617 */
618 int page_unprotect(target_ulong address, uintptr_t pc)
619 {
620 PageFlagsNode *p;
621 bool current_tb_invalidated;
622
623 /*
624 * Technically this isn't safe inside a signal handler. However we
625 * know this only ever happens in a synchronous SEGV handler, so in
626 * practice it seems to be ok.
627 */
628 mmap_lock();
629
630 p = pageflags_find(address, address);
631
632 /* If this address was not really writable, nothing to do. */
633 if (!p || !(p->flags & PAGE_WRITE_ORG)) {
634 mmap_unlock();
635 return 0;
636 }
637
638 current_tb_invalidated = false;
639 if (p->flags & PAGE_WRITE) {
640 /*
641 * If the page is actually marked WRITE then assume this is because
642 * this thread raced with another one which got here first and
643 * set the page to PAGE_WRITE and did the TB invalidate for us.
644 */
645 #ifdef TARGET_HAS_PRECISE_SMC
646 TranslationBlock *current_tb = tcg_tb_lookup(pc);
647 if (current_tb) {
648 current_tb_invalidated = tb_cflags(current_tb) & CF_INVALID;
649 }
650 #endif
651 } else {
652 target_ulong start, len, i;
653 int prot;
654
655 if (qemu_host_page_size <= TARGET_PAGE_SIZE) {
656 start = address & TARGET_PAGE_MASK;
657 len = TARGET_PAGE_SIZE;
658 prot = p->flags | PAGE_WRITE;
659 pageflags_set_clear(start, start + len - 1, PAGE_WRITE, 0);
660 current_tb_invalidated = tb_invalidate_phys_page_unwind(start, pc);
661 } else {
662 start = address & qemu_host_page_mask;
663 len = qemu_host_page_size;
664 prot = 0;
665
666 for (i = 0; i < len; i += TARGET_PAGE_SIZE) {
667 target_ulong addr = start + i;
668
669 p = pageflags_find(addr, addr);
670 if (p) {
671 prot |= p->flags;
672 if (p->flags & PAGE_WRITE_ORG) {
673 prot |= PAGE_WRITE;
674 pageflags_set_clear(addr, addr + TARGET_PAGE_SIZE - 1,
675 PAGE_WRITE, 0);
676 }
677 }
678 /*
679 * Since the content will be modified, we must invalidate
680 * the corresponding translated code.
681 */
682 current_tb_invalidated |=
683 tb_invalidate_phys_page_unwind(addr, pc);
684 }
685 }
686 if (prot & PAGE_EXEC) {
687 prot = (prot & ~PAGE_EXEC) | PAGE_READ;
688 }
689 mprotect((void *)g2h_untagged(start), len, prot & PAGE_BITS);
690 }
691 mmap_unlock();
692
693 /* If current TB was invalidated return to main loop */
694 return current_tb_invalidated ? 2 : 1;
695 }
696
697 static int probe_access_internal(CPUArchState *env, target_ulong addr,
698 int fault_size, MMUAccessType access_type,
699 bool nonfault, uintptr_t ra)
700 {
701 int acc_flag;
702 bool maperr;
703
704 switch (access_type) {
705 case MMU_DATA_STORE:
706 acc_flag = PAGE_WRITE_ORG;
707 break;
708 case MMU_DATA_LOAD:
709 acc_flag = PAGE_READ;
710 break;
711 case MMU_INST_FETCH:
712 acc_flag = PAGE_EXEC;
713 break;
714 default:
715 g_assert_not_reached();
716 }
717
718 if (guest_addr_valid_untagged(addr)) {
719 int page_flags = page_get_flags(addr);
720 if (page_flags & acc_flag) {
721 return 0; /* success */
722 }
723 maperr = !(page_flags & PAGE_VALID);
724 } else {
725 maperr = true;
726 }
727
728 if (nonfault) {
729 return TLB_INVALID_MASK;
730 }
731
732 cpu_loop_exit_sigsegv(env_cpu(env), addr, access_type, maperr, ra);
733 }
734
735 int probe_access_flags(CPUArchState *env, target_ulong addr,
736 MMUAccessType access_type, int mmu_idx,
737 bool nonfault, void **phost, uintptr_t ra)
738 {
739 int flags;
740
741 flags = probe_access_internal(env, addr, 0, access_type, nonfault, ra);
742 *phost = flags ? NULL : g2h(env_cpu(env), addr);
743 return flags;
744 }
745
746 void *probe_access(CPUArchState *env, target_ulong addr, int size,
747 MMUAccessType access_type, int mmu_idx, uintptr_t ra)
748 {
749 int flags;
750
751 g_assert(-(addr | TARGET_PAGE_MASK) >= size);
752 flags = probe_access_internal(env, addr, size, access_type, false, ra);
753 g_assert(flags == 0);
754
755 return size ? g2h(env_cpu(env), addr) : NULL;
756 }
757
758 tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
759 void **hostp)
760 {
761 int flags;
762
763 flags = probe_access_internal(env, addr, 1, MMU_INST_FETCH, false, 0);
764 g_assert(flags == 0);
765
766 if (hostp) {
767 *hostp = g2h_untagged(addr);
768 }
769 return addr;
770 }
771
772 #ifdef TARGET_PAGE_DATA_SIZE
773 /*
774 * Allocate chunks of target data together. For the only current user,
775 * if we allocate one hunk per page, we have overhead of 40/128 or 40%.
776 * Therefore, allocate memory for 64 pages at a time for overhead < 1%.
777 */
778 #define TPD_PAGES 64
779 #define TBD_MASK (TARGET_PAGE_MASK * TPD_PAGES)
780
781 typedef struct TargetPageDataNode {
782 IntervalTreeNode itree;
783 char data[TPD_PAGES][TARGET_PAGE_DATA_SIZE] __attribute__((aligned));
784 } TargetPageDataNode;
785
786 static IntervalTreeRoot targetdata_root;
787
788 void page_reset_target_data(target_ulong start, target_ulong end)
789 {
790 IntervalTreeNode *n, *next;
791 target_ulong last;
792
793 assert_memory_lock();
794
795 start = start & TARGET_PAGE_MASK;
796 last = TARGET_PAGE_ALIGN(end) - 1;
797
798 for (n = interval_tree_iter_first(&targetdata_root, start, last),
799 next = n ? interval_tree_iter_next(n, start, last) : NULL;
800 n != NULL;
801 n = next,
802 next = next ? interval_tree_iter_next(n, start, last) : NULL) {
803 target_ulong n_start, n_last, p_ofs, p_len;
804 TargetPageDataNode *t;
805
806 if (n->start >= start && n->last <= last) {
807 interval_tree_remove(n, &targetdata_root);
808 g_free(n);
809 continue;
810 }
811
812 if (n->start < start) {
813 n_start = start;
814 p_ofs = (start - n->start) >> TARGET_PAGE_BITS;
815 } else {
816 n_start = n->start;
817 p_ofs = 0;
818 }
819 n_last = MIN(last, n->last);
820 p_len = (n_last + 1 - n_start) >> TARGET_PAGE_BITS;
821
822 t = container_of(n, TargetPageDataNode, itree);
823 memset(t->data[p_ofs], 0, p_len * TARGET_PAGE_DATA_SIZE);
824 }
825 }
826
827 void *page_get_target_data(target_ulong address)
828 {
829 IntervalTreeNode *n;
830 TargetPageDataNode *t;
831 target_ulong page, region;
832
833 page = address & TARGET_PAGE_MASK;
834 region = address & TBD_MASK;
835
836 n = interval_tree_iter_first(&targetdata_root, page, page);
837 if (!n) {
838 /*
839 * See util/interval-tree.c re lockless lookups: no false positives
840 * but there are false negatives. If we find nothing, retry with
841 * the mmap lock acquired. We also need the lock for the
842 * allocation + insert.
843 */
844 mmap_lock();
845 n = interval_tree_iter_first(&targetdata_root, page, page);
846 if (!n) {
847 t = g_new0(TargetPageDataNode, 1);
848 n = &t->itree;
849 n->start = region;
850 n->last = region | ~TBD_MASK;
851 interval_tree_insert(n, &targetdata_root);
852 }
853 mmap_unlock();
854 }
855
856 t = container_of(n, TargetPageDataNode, itree);
857 return t->data[(page - region) >> TARGET_PAGE_BITS];
858 }
859 #else
860 void page_reset_target_data(target_ulong start, target_ulong end) { }
861 #endif /* TARGET_PAGE_DATA_SIZE */
862
863 /* The softmmu versions of these helpers are in cputlb.c. */
864
865 /*
866 * Verify that we have passed the correct MemOp to the correct function.
867 *
868 * We could present one function to target code, and dispatch based on
869 * the MemOp, but so far we have worked hard to avoid an indirect function
870 * call along the memory path.
871 */
872 static void validate_memop(MemOpIdx oi, MemOp expected)
873 {
874 #ifdef CONFIG_DEBUG_TCG
875 MemOp have = get_memop(oi) & (MO_SIZE | MO_BSWAP);
876 assert(have == expected);
877 #endif
878 }
879
880 void helper_unaligned_ld(CPUArchState *env, target_ulong addr)
881 {
882 cpu_loop_exit_sigbus(env_cpu(env), addr, MMU_DATA_LOAD, GETPC());
883 }
884
885 void helper_unaligned_st(CPUArchState *env, target_ulong addr)
886 {
887 cpu_loop_exit_sigbus(env_cpu(env), addr, MMU_DATA_STORE, GETPC());
888 }
889
890 static void *cpu_mmu_lookup(CPUArchState *env, target_ulong addr,
891 MemOpIdx oi, uintptr_t ra, MMUAccessType type)
892 {
893 MemOp mop = get_memop(oi);
894 int a_bits = get_alignment_bits(mop);
895 void *ret;
896
897 /* Enforce guest required alignment. */
898 if (unlikely(addr & ((1 << a_bits) - 1))) {
899 cpu_loop_exit_sigbus(env_cpu(env), addr, type, ra);
900 }
901
902 ret = g2h(env_cpu(env), addr);
903 set_helper_retaddr(ra);
904 return ret;
905 }
906
907 uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr addr,
908 MemOpIdx oi, uintptr_t ra)
909 {
910 void *haddr;
911 uint8_t ret;
912
913 validate_memop(oi, MO_UB);
914 haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
915 ret = ldub_p(haddr);
916 clear_helper_retaddr();
917 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
918 return ret;
919 }
920
921 uint16_t cpu_ldw_be_mmu(CPUArchState *env, abi_ptr addr,
922 MemOpIdx oi, uintptr_t ra)
923 {
924 void *haddr;
925 uint16_t ret;
926
927 validate_memop(oi, MO_BEUW);
928 haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
929 ret = lduw_be_p(haddr);
930 clear_helper_retaddr();
931 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
932 return ret;
933 }
934
935 uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr addr,
936 MemOpIdx oi, uintptr_t ra)
937 {
938 void *haddr;
939 uint32_t ret;
940
941 validate_memop(oi, MO_BEUL);
942 haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
943 ret = ldl_be_p(haddr);
944 clear_helper_retaddr();
945 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
946 return ret;
947 }
948
949 uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr,
950 MemOpIdx oi, uintptr_t ra)
951 {
952 void *haddr;
953 uint64_t ret;
954
955 validate_memop(oi, MO_BEUQ);
956 haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
957 ret = ldq_be_p(haddr);
958 clear_helper_retaddr();
959 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
960 return ret;
961 }
962
963 uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr addr,
964 MemOpIdx oi, uintptr_t ra)
965 {
966 void *haddr;
967 uint16_t ret;
968
969 validate_memop(oi, MO_LEUW);
970 haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
971 ret = lduw_le_p(haddr);
972 clear_helper_retaddr();
973 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
974 return ret;
975 }
976
977 uint32_t cpu_ldl_le_mmu(CPUArchState *env, abi_ptr addr,
978 MemOpIdx oi, uintptr_t ra)
979 {
980 void *haddr;
981 uint32_t ret;
982
983 validate_memop(oi, MO_LEUL);
984 haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
985 ret = ldl_le_p(haddr);
986 clear_helper_retaddr();
987 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
988 return ret;
989 }
990
991 uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr addr,
992 MemOpIdx oi, uintptr_t ra)
993 {
994 void *haddr;
995 uint64_t ret;
996
997 validate_memop(oi, MO_LEUQ);
998 haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
999 ret = ldq_le_p(haddr);
1000 clear_helper_retaddr();
1001 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
1002 return ret;
1003 }
1004
1005 void cpu_stb_mmu(CPUArchState *env, abi_ptr addr, uint8_t val,
1006 MemOpIdx oi, uintptr_t ra)
1007 {
1008 void *haddr;
1009
1010 validate_memop(oi, MO_UB);
1011 haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
1012 stb_p(haddr, val);
1013 clear_helper_retaddr();
1014 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
1015 }
1016
1017 void cpu_stw_be_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
1018 MemOpIdx oi, uintptr_t ra)
1019 {
1020 void *haddr;
1021
1022 validate_memop(oi, MO_BEUW);
1023 haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
1024 stw_be_p(haddr, val);
1025 clear_helper_retaddr();
1026 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
1027 }
1028
1029 void cpu_stl_be_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
1030 MemOpIdx oi, uintptr_t ra)
1031 {
1032 void *haddr;
1033
1034 validate_memop(oi, MO_BEUL);
1035 haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
1036 stl_be_p(haddr, val);
1037 clear_helper_retaddr();
1038 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
1039 }
1040
1041 void cpu_stq_be_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
1042 MemOpIdx oi, uintptr_t ra)
1043 {
1044 void *haddr;
1045
1046 validate_memop(oi, MO_BEUQ);
1047 haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
1048 stq_be_p(haddr, val);
1049 clear_helper_retaddr();
1050 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
1051 }
1052
1053 void cpu_stw_le_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
1054 MemOpIdx oi, uintptr_t ra)
1055 {
1056 void *haddr;
1057
1058 validate_memop(oi, MO_LEUW);
1059 haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
1060 stw_le_p(haddr, val);
1061 clear_helper_retaddr();
1062 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
1063 }
1064
1065 void cpu_stl_le_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
1066 MemOpIdx oi, uintptr_t ra)
1067 {
1068 void *haddr;
1069
1070 validate_memop(oi, MO_LEUL);
1071 haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
1072 stl_le_p(haddr, val);
1073 clear_helper_retaddr();
1074 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
1075 }
1076
1077 void cpu_stq_le_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
1078 MemOpIdx oi, uintptr_t ra)
1079 {
1080 void *haddr;
1081
1082 validate_memop(oi, MO_LEUQ);
1083 haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
1084 stq_le_p(haddr, val);
1085 clear_helper_retaddr();
1086 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
1087 }
1088
1089 uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr ptr)
1090 {
1091 uint32_t ret;
1092
1093 set_helper_retaddr(1);
1094 ret = ldub_p(g2h_untagged(ptr));
1095 clear_helper_retaddr();
1096 return ret;
1097 }
1098
1099 uint32_t cpu_lduw_code(CPUArchState *env, abi_ptr ptr)
1100 {
1101 uint32_t ret;
1102
1103 set_helper_retaddr(1);
1104 ret = lduw_p(g2h_untagged(ptr));
1105 clear_helper_retaddr();
1106 return ret;
1107 }
1108
1109 uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr ptr)
1110 {
1111 uint32_t ret;
1112
1113 set_helper_retaddr(1);
1114 ret = ldl_p(g2h_untagged(ptr));
1115 clear_helper_retaddr();
1116 return ret;
1117 }
1118
1119 uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr ptr)
1120 {
1121 uint64_t ret;
1122
1123 set_helper_retaddr(1);
1124 ret = ldq_p(g2h_untagged(ptr));
1125 clear_helper_retaddr();
1126 return ret;
1127 }
1128
1129 #include "ldst_common.c.inc"
1130
1131 /*
1132 * Do not allow unaligned operations to proceed. Return the host address.
1133 *
1134 * @prot may be PAGE_READ, PAGE_WRITE, or PAGE_READ|PAGE_WRITE.
1135 */
1136 static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
1137 MemOpIdx oi, int size, int prot,
1138 uintptr_t retaddr)
1139 {
1140 MemOp mop = get_memop(oi);
1141 int a_bits = get_alignment_bits(mop);
1142 void *ret;
1143
1144 /* Enforce guest required alignment. */
1145 if (unlikely(addr & ((1 << a_bits) - 1))) {
1146 MMUAccessType t = prot == PAGE_READ ? MMU_DATA_LOAD : MMU_DATA_STORE;
1147 cpu_loop_exit_sigbus(env_cpu(env), addr, t, retaddr);
1148 }
1149
1150 /* Enforce qemu required alignment. */
1151 if (unlikely(addr & (size - 1))) {
1152 cpu_loop_exit_atomic(env_cpu(env), retaddr);
1153 }
1154
1155 ret = g2h(env_cpu(env), addr);
1156 set_helper_retaddr(retaddr);
1157 return ret;
1158 }
1159
1160 #include "atomic_common.c.inc"
1161
1162 /*
1163 * First set of functions passes in OI and RETADDR.
1164 * This makes them callable from other helpers.
1165 */
1166
1167 #define ATOMIC_NAME(X) \
1168 glue(glue(glue(cpu_atomic_ ## X, SUFFIX), END), _mmu)
1169 #define ATOMIC_MMU_CLEANUP do { clear_helper_retaddr(); } while (0)
1170
1171 #define DATA_SIZE 1
1172 #include "atomic_template.h"
1173
1174 #define DATA_SIZE 2
1175 #include "atomic_template.h"
1176
1177 #define DATA_SIZE 4
1178 #include "atomic_template.h"
1179
1180 #ifdef CONFIG_ATOMIC64
1181 #define DATA_SIZE 8
1182 #include "atomic_template.h"
1183 #endif
1184
1185 #if HAVE_ATOMIC128 || HAVE_CMPXCHG128
1186 #define DATA_SIZE 16
1187 #include "atomic_template.h"
1188 #endif