xref: /openbmc/qemu/accel/tcg/tb-maint.c (revision 1dcea719)
1 /*
2  * Translation Block Maintaince
3  *
4  *  Copyright (c) 2003 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 
20 #include "qemu/osdep.h"
21 #include "exec/cputlb.h"
22 #include "exec/log.h"
23 #include "exec/exec-all.h"
24 #include "exec/translate-all.h"
25 #include "sysemu/tcg.h"
26 #include "tcg/tcg.h"
27 #include "tb-hash.h"
28 #include "tb-context.h"
29 #include "internal.h"
30 
31 
32 static bool tb_cmp(const void *ap, const void *bp)
33 {
34     const TranslationBlock *a = ap;
35     const TranslationBlock *b = bp;
36 
37     return ((TARGET_TB_PCREL || tb_pc(a) == tb_pc(b)) &&
38             a->cs_base == b->cs_base &&
39             a->flags == b->flags &&
40             (tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
41             a->trace_vcpu_dstate == b->trace_vcpu_dstate &&
42             tb_page_addr0(a) == tb_page_addr0(b) &&
43             tb_page_addr1(a) == tb_page_addr1(b));
44 }
45 
46 void tb_htable_init(void)
47 {
48     unsigned int mode = QHT_MODE_AUTO_RESIZE;
49 
50     qht_init(&tb_ctx.htable, tb_cmp, CODE_GEN_HTABLE_SIZE, mode);
51 }
52 
53 /* Set to NULL all the 'first_tb' fields in all PageDescs. */
54 static void page_flush_tb_1(int level, void **lp)
55 {
56     int i;
57 
58     if (*lp == NULL) {
59         return;
60     }
61     if (level == 0) {
62         PageDesc *pd = *lp;
63 
64         for (i = 0; i < V_L2_SIZE; ++i) {
65             page_lock(&pd[i]);
66             pd[i].first_tb = (uintptr_t)NULL;
67             page_unlock(&pd[i]);
68         }
69     } else {
70         void **pp = *lp;
71 
72         for (i = 0; i < V_L2_SIZE; ++i) {
73             page_flush_tb_1(level - 1, pp + i);
74         }
75     }
76 }
77 
78 static void page_flush_tb(void)
79 {
80     int i, l1_sz = v_l1_size;
81 
82     for (i = 0; i < l1_sz; i++) {
83         page_flush_tb_1(v_l2_levels, l1_map + i);
84     }
85 }
86 
87 /* flush all the translation blocks */
88 static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count)
89 {
90     bool did_flush = false;
91 
92     mmap_lock();
93     /* If it is already been done on request of another CPU, just retry. */
94     if (tb_ctx.tb_flush_count != tb_flush_count.host_int) {
95         goto done;
96     }
97     did_flush = true;
98 
99     CPU_FOREACH(cpu) {
100         tcg_flush_jmp_cache(cpu);
101     }
102 
103     qht_reset_size(&tb_ctx.htable, CODE_GEN_HTABLE_SIZE);
104     page_flush_tb();
105 
106     tcg_region_reset_all();
107     /* XXX: flush processor icache at this point if cache flush is expensive */
108     qatomic_mb_set(&tb_ctx.tb_flush_count, tb_ctx.tb_flush_count + 1);
109 
110 done:
111     mmap_unlock();
112     if (did_flush) {
113         qemu_plugin_flush_cb();
114     }
115 }
116 
117 void tb_flush(CPUState *cpu)
118 {
119     if (tcg_enabled()) {
120         unsigned tb_flush_count = qatomic_mb_read(&tb_ctx.tb_flush_count);
121 
122         if (cpu_in_exclusive_context(cpu)) {
123             do_tb_flush(cpu, RUN_ON_CPU_HOST_INT(tb_flush_count));
124         } else {
125             async_safe_run_on_cpu(cpu, do_tb_flush,
126                                   RUN_ON_CPU_HOST_INT(tb_flush_count));
127         }
128     }
129 }
130 
131 /*
132  * user-mode: call with mmap_lock held
133  * !user-mode: call with @pd->lock held
134  */
135 static inline void tb_page_remove(PageDesc *pd, TranslationBlock *tb)
136 {
137     TranslationBlock *tb1;
138     uintptr_t *pprev;
139     unsigned int n1;
140 
141     assert_page_locked(pd);
142     pprev = &pd->first_tb;
143     PAGE_FOR_EACH_TB(pd, tb1, n1) {
144         if (tb1 == tb) {
145             *pprev = tb1->page_next[n1];
146             return;
147         }
148         pprev = &tb1->page_next[n1];
149     }
150     g_assert_not_reached();
151 }
152 
153 /* remove @orig from its @n_orig-th jump list */
154 static inline void tb_remove_from_jmp_list(TranslationBlock *orig, int n_orig)
155 {
156     uintptr_t ptr, ptr_locked;
157     TranslationBlock *dest;
158     TranslationBlock *tb;
159     uintptr_t *pprev;
160     int n;
161 
162     /* mark the LSB of jmp_dest[] so that no further jumps can be inserted */
163     ptr = qatomic_or_fetch(&orig->jmp_dest[n_orig], 1);
164     dest = (TranslationBlock *)(ptr & ~1);
165     if (dest == NULL) {
166         return;
167     }
168 
169     qemu_spin_lock(&dest->jmp_lock);
170     /*
171      * While acquiring the lock, the jump might have been removed if the
172      * destination TB was invalidated; check again.
173      */
174     ptr_locked = qatomic_read(&orig->jmp_dest[n_orig]);
175     if (ptr_locked != ptr) {
176         qemu_spin_unlock(&dest->jmp_lock);
177         /*
178          * The only possibility is that the jump was unlinked via
179          * tb_jump_unlink(dest). Seeing here another destination would be a bug,
180          * because we set the LSB above.
181          */
182         g_assert(ptr_locked == 1 && dest->cflags & CF_INVALID);
183         return;
184     }
185     /*
186      * We first acquired the lock, and since the destination pointer matches,
187      * we know for sure that @orig is in the jmp list.
188      */
189     pprev = &dest->jmp_list_head;
190     TB_FOR_EACH_JMP(dest, tb, n) {
191         if (tb == orig && n == n_orig) {
192             *pprev = tb->jmp_list_next[n];
193             /* no need to set orig->jmp_dest[n]; setting the LSB was enough */
194             qemu_spin_unlock(&dest->jmp_lock);
195             return;
196         }
197         pprev = &tb->jmp_list_next[n];
198     }
199     g_assert_not_reached();
200 }
201 
202 /*
203  * Reset the jump entry 'n' of a TB so that it is not chained to another TB.
204  */
205 void tb_reset_jump(TranslationBlock *tb, int n)
206 {
207     uintptr_t addr = (uintptr_t)(tb->tc.ptr + tb->jmp_reset_offset[n]);
208     tb_set_jmp_target(tb, n, addr);
209 }
210 
211 /* remove any jumps to the TB */
212 static inline void tb_jmp_unlink(TranslationBlock *dest)
213 {
214     TranslationBlock *tb;
215     int n;
216 
217     qemu_spin_lock(&dest->jmp_lock);
218 
219     TB_FOR_EACH_JMP(dest, tb, n) {
220         tb_reset_jump(tb, n);
221         qatomic_and(&tb->jmp_dest[n], (uintptr_t)NULL | 1);
222         /* No need to clear the list entry; setting the dest ptr is enough */
223     }
224     dest->jmp_list_head = (uintptr_t)NULL;
225 
226     qemu_spin_unlock(&dest->jmp_lock);
227 }
228 
229 static void tb_jmp_cache_inval_tb(TranslationBlock *tb)
230 {
231     CPUState *cpu;
232 
233     if (TARGET_TB_PCREL) {
234         /* A TB may be at any virtual address */
235         CPU_FOREACH(cpu) {
236             tcg_flush_jmp_cache(cpu);
237         }
238     } else {
239         uint32_t h = tb_jmp_cache_hash_func(tb_pc(tb));
240 
241         CPU_FOREACH(cpu) {
242             CPUJumpCache *jc = cpu->tb_jmp_cache;
243 
244             if (qatomic_read(&jc->array[h].tb) == tb) {
245                 qatomic_set(&jc->array[h].tb, NULL);
246             }
247         }
248     }
249 }
250 
251 /*
252  * In user-mode, call with mmap_lock held.
253  * In !user-mode, if @rm_from_page_list is set, call with the TB's pages'
254  * locks held.
255  */
256 static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
257 {
258     PageDesc *p;
259     uint32_t h;
260     tb_page_addr_t phys_pc;
261     uint32_t orig_cflags = tb_cflags(tb);
262 
263     assert_memory_lock();
264 
265     /* make sure no further incoming jumps will be chained to this TB */
266     qemu_spin_lock(&tb->jmp_lock);
267     qatomic_set(&tb->cflags, tb->cflags | CF_INVALID);
268     qemu_spin_unlock(&tb->jmp_lock);
269 
270     /* remove the TB from the hash list */
271     phys_pc = tb_page_addr0(tb);
272     h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
273                      tb->flags, orig_cflags, tb->trace_vcpu_dstate);
274     if (!qht_remove(&tb_ctx.htable, tb, h)) {
275         return;
276     }
277 
278     /* remove the TB from the page list */
279     if (rm_from_page_list) {
280         p = page_find(phys_pc >> TARGET_PAGE_BITS);
281         tb_page_remove(p, tb);
282         phys_pc = tb_page_addr1(tb);
283         if (phys_pc != -1) {
284             p = page_find(phys_pc >> TARGET_PAGE_BITS);
285             tb_page_remove(p, tb);
286         }
287     }
288 
289     /* remove the TB from the hash list */
290     tb_jmp_cache_inval_tb(tb);
291 
292     /* suppress this TB from the two jump lists */
293     tb_remove_from_jmp_list(tb, 0);
294     tb_remove_from_jmp_list(tb, 1);
295 
296     /* suppress any remaining jumps to this TB */
297     tb_jmp_unlink(tb);
298 
299     qatomic_set(&tb_ctx.tb_phys_invalidate_count,
300                 tb_ctx.tb_phys_invalidate_count + 1);
301 }
302 
303 static void tb_phys_invalidate__locked(TranslationBlock *tb)
304 {
305     qemu_thread_jit_write();
306     do_tb_phys_invalidate(tb, true);
307     qemu_thread_jit_execute();
308 }
309 
310 static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1,
311                            PageDesc **ret_p2, tb_page_addr_t phys2, bool alloc)
312 {
313     PageDesc *p1, *p2;
314     tb_page_addr_t page1;
315     tb_page_addr_t page2;
316 
317     assert_memory_lock();
318     g_assert(phys1 != -1);
319 
320     page1 = phys1 >> TARGET_PAGE_BITS;
321     page2 = phys2 >> TARGET_PAGE_BITS;
322 
323     p1 = page_find_alloc(page1, alloc);
324     if (ret_p1) {
325         *ret_p1 = p1;
326     }
327     if (likely(phys2 == -1)) {
328         page_lock(p1);
329         return;
330     } else if (page1 == page2) {
331         page_lock(p1);
332         if (ret_p2) {
333             *ret_p2 = p1;
334         }
335         return;
336     }
337     p2 = page_find_alloc(page2, alloc);
338     if (ret_p2) {
339         *ret_p2 = p2;
340     }
341     if (page1 < page2) {
342         page_lock(p1);
343         page_lock(p2);
344     } else {
345         page_lock(p2);
346         page_lock(p1);
347     }
348 }
349 
350 #ifdef CONFIG_USER_ONLY
351 static inline void page_lock_tb(const TranslationBlock *tb) { }
352 static inline void page_unlock_tb(const TranslationBlock *tb) { }
353 #else
354 /* lock the page(s) of a TB in the correct acquisition order */
355 static void page_lock_tb(const TranslationBlock *tb)
356 {
357     page_lock_pair(NULL, tb_page_addr0(tb), NULL, tb_page_addr1(tb), false);
358 }
359 
360 static void page_unlock_tb(const TranslationBlock *tb)
361 {
362     PageDesc *p1 = page_find(tb_page_addr0(tb) >> TARGET_PAGE_BITS);
363 
364     page_unlock(p1);
365     if (unlikely(tb_page_addr1(tb) != -1)) {
366         PageDesc *p2 = page_find(tb_page_addr1(tb) >> TARGET_PAGE_BITS);
367 
368         if (p2 != p1) {
369             page_unlock(p2);
370         }
371     }
372 }
373 #endif
374 
375 /*
376  * Invalidate one TB.
377  * Called with mmap_lock held in user-mode.
378  */
379 void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
380 {
381     if (page_addr == -1 && tb_page_addr0(tb) != -1) {
382         page_lock_tb(tb);
383         do_tb_phys_invalidate(tb, true);
384         page_unlock_tb(tb);
385     } else {
386         do_tb_phys_invalidate(tb, false);
387     }
388 }
389 
390 /*
391  * Add the tb in the target page and protect it if necessary.
392  * Called with mmap_lock held for user-mode emulation.
393  * Called with @p->lock held in !user-mode.
394  */
395 static inline void tb_page_add(PageDesc *p, TranslationBlock *tb,
396                                unsigned int n, tb_page_addr_t page_addr)
397 {
398 #ifndef CONFIG_USER_ONLY
399     bool page_already_protected;
400 #endif
401 
402     assert_page_locked(p);
403 
404     tb->page_next[n] = p->first_tb;
405 #ifndef CONFIG_USER_ONLY
406     page_already_protected = p->first_tb != (uintptr_t)NULL;
407 #endif
408     p->first_tb = (uintptr_t)tb | n;
409 
410 #if defined(CONFIG_USER_ONLY)
411     /* translator_loop() must have made all TB pages non-writable */
412     assert(!(p->flags & PAGE_WRITE));
413 #else
414     /*
415      * If some code is already present, then the pages are already
416      * protected. So we handle the case where only the first TB is
417      * allocated in a physical page.
418      */
419     if (!page_already_protected) {
420         tlb_protect_code(page_addr);
421     }
422 #endif
423 }
424 
425 /*
426  * Add a new TB and link it to the physical page tables. phys_page2 is
427  * (-1) to indicate that only one page contains the TB.
428  *
429  * Called with mmap_lock held for user-mode emulation.
430  *
431  * Returns a pointer @tb, or a pointer to an existing TB that matches @tb.
432  * Note that in !user-mode, another thread might have already added a TB
433  * for the same block of guest code that @tb corresponds to. In that case,
434  * the caller should discard the original @tb, and use instead the returned TB.
435  */
436 TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
437                                tb_page_addr_t phys_page2)
438 {
439     PageDesc *p;
440     PageDesc *p2 = NULL;
441     void *existing_tb = NULL;
442     uint32_t h;
443 
444     assert_memory_lock();
445     tcg_debug_assert(!(tb->cflags & CF_INVALID));
446 
447     /*
448      * Add the TB to the page list, acquiring first the pages's locks.
449      * We keep the locks held until after inserting the TB in the hash table,
450      * so that if the insertion fails we know for sure that the TBs are still
451      * in the page descriptors.
452      * Note that inserting into the hash table first isn't an option, since
453      * we can only insert TBs that are fully initialized.
454      */
455     page_lock_pair(&p, phys_pc, &p2, phys_page2, true);
456     tb_page_add(p, tb, 0, phys_pc);
457     if (p2) {
458         tb_page_add(p2, tb, 1, phys_page2);
459     }
460 
461     /* add in the hash table */
462     h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
463                      tb->flags, tb->cflags, tb->trace_vcpu_dstate);
464     qht_insert(&tb_ctx.htable, tb, h, &existing_tb);
465 
466     /* remove TB from the page(s) if we couldn't insert it */
467     if (unlikely(existing_tb)) {
468         tb_page_remove(p, tb);
469         if (p2) {
470             tb_page_remove(p2, tb);
471         }
472         tb = existing_tb;
473     }
474 
475     if (p2 && p2 != p) {
476         page_unlock(p2);
477     }
478     page_unlock(p);
479     return tb;
480 }
481 
482 /*
483  * @p must be non-NULL.
484  * user-mode: call with mmap_lock held.
485  * !user-mode: call with all @pages locked.
486  */
487 static void
488 tb_invalidate_phys_page_range__locked(struct page_collection *pages,
489                                       PageDesc *p, tb_page_addr_t start,
490                                       tb_page_addr_t end,
491                                       uintptr_t retaddr)
492 {
493     TranslationBlock *tb;
494     tb_page_addr_t tb_start, tb_end;
495     int n;
496 #ifdef TARGET_HAS_PRECISE_SMC
497     CPUState *cpu = current_cpu;
498     bool current_tb_not_found = retaddr != 0;
499     bool current_tb_modified = false;
500     TranslationBlock *current_tb = NULL;
501 #endif /* TARGET_HAS_PRECISE_SMC */
502 
503     assert_page_locked(p);
504 
505     /*
506      * We remove all the TBs in the range [start, end[.
507      * XXX: see if in some cases it could be faster to invalidate all the code
508      */
509     PAGE_FOR_EACH_TB(p, tb, n) {
510         assert_page_locked(p);
511         /* NOTE: this is subtle as a TB may span two physical pages */
512         if (n == 0) {
513             /* NOTE: tb_end may be after the end of the page, but
514                it is not a problem */
515             tb_start = tb_page_addr0(tb);
516             tb_end = tb_start + tb->size;
517         } else {
518             tb_start = tb_page_addr1(tb);
519             tb_end = tb_start + ((tb_page_addr0(tb) + tb->size)
520                                  & ~TARGET_PAGE_MASK);
521         }
522         if (!(tb_end <= start || tb_start >= end)) {
523 #ifdef TARGET_HAS_PRECISE_SMC
524             if (current_tb_not_found) {
525                 current_tb_not_found = false;
526                 /* now we have a real cpu fault */
527                 current_tb = tcg_tb_lookup(retaddr);
528             }
529             if (current_tb == tb &&
530                 (tb_cflags(current_tb) & CF_COUNT_MASK) != 1) {
531                 /*
532                  * If we are modifying the current TB, we must stop
533                  * its execution. We could be more precise by checking
534                  * that the modification is after the current PC, but it
535                  * would require a specialized function to partially
536                  * restore the CPU state.
537                  */
538                 current_tb_modified = true;
539                 cpu_restore_state_from_tb(cpu, current_tb, retaddr, true);
540             }
541 #endif /* TARGET_HAS_PRECISE_SMC */
542             tb_phys_invalidate__locked(tb);
543         }
544     }
545 #if !defined(CONFIG_USER_ONLY)
546     /* if no code remaining, no need to continue to use slow writes */
547     if (!p->first_tb) {
548         tlb_unprotect_code(start);
549     }
550 #endif
551 #ifdef TARGET_HAS_PRECISE_SMC
552     if (current_tb_modified) {
553         page_collection_unlock(pages);
554         /* Force execution of one insn next time.  */
555         cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu);
556         mmap_unlock();
557         cpu_loop_exit_noexc(cpu);
558     }
559 #endif
560 }
561 
562 /*
563  * Invalidate all TBs which intersect with the target physical
564  * address page @addr.
565  *
566  * Called with mmap_lock held for user-mode emulation
567  */
568 void tb_invalidate_phys_page(tb_page_addr_t addr)
569 {
570     struct page_collection *pages;
571     tb_page_addr_t start, end;
572     PageDesc *p;
573 
574     assert_memory_lock();
575 
576     p = page_find(addr >> TARGET_PAGE_BITS);
577     if (p == NULL) {
578         return;
579     }
580 
581     start = addr & TARGET_PAGE_MASK;
582     end = start + TARGET_PAGE_SIZE;
583     pages = page_collection_lock(start, end);
584     tb_invalidate_phys_page_range__locked(pages, p, start, end, 0);
585     page_collection_unlock(pages);
586 }
587 
588 /*
589  * Invalidate all TBs which intersect with the target physical address range
590  * [start;end[. NOTE: start and end may refer to *different* physical pages.
591  * 'is_cpu_write_access' should be true if called from a real cpu write
592  * access: the virtual CPU will exit the current TB if code is modified inside
593  * this TB.
594  *
595  * Called with mmap_lock held for user-mode emulation.
596  */
597 void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end)
598 {
599     struct page_collection *pages;
600     tb_page_addr_t next;
601 
602     assert_memory_lock();
603 
604     pages = page_collection_lock(start, end);
605     for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
606          start < end;
607          start = next, next += TARGET_PAGE_SIZE) {
608         PageDesc *pd = page_find(start >> TARGET_PAGE_BITS);
609         tb_page_addr_t bound = MIN(next, end);
610 
611         if (pd == NULL) {
612             continue;
613         }
614         tb_invalidate_phys_page_range__locked(pages, pd, start, bound, 0);
615     }
616     page_collection_unlock(pages);
617 }
618 
619 #ifdef CONFIG_SOFTMMU
620 /*
621  * len must be <= 8 and start must be a multiple of len.
622  * Called via softmmu_template.h when code areas are written to with
623  * iothread mutex not held.
624  *
625  * Call with all @pages in the range [@start, @start + len[ locked.
626  */
627 void tb_invalidate_phys_page_fast(struct page_collection *pages,
628                                   tb_page_addr_t start, int len,
629                                   uintptr_t retaddr)
630 {
631     PageDesc *p;
632 
633     assert_memory_lock();
634 
635     p = page_find(start >> TARGET_PAGE_BITS);
636     if (!p) {
637         return;
638     }
639 
640     assert_page_locked(p);
641     tb_invalidate_phys_page_range__locked(pages, p, start, start + len,
642                                           retaddr);
643 }
644 #else
645 /*
646  * Called with mmap_lock held. If pc is not 0 then it indicates the
647  * host PC of the faulting store instruction that caused this invalidate.
648  * Returns true if the caller needs to abort execution of the current
649  * TB (because it was modified by this store and the guest CPU has
650  * precise-SMC semantics).
651  */
652 bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc)
653 {
654     TranslationBlock *tb;
655     PageDesc *p;
656     int n;
657 #ifdef TARGET_HAS_PRECISE_SMC
658     TranslationBlock *current_tb = NULL;
659     CPUState *cpu = current_cpu;
660     bool current_tb_modified = false;
661 #endif
662 
663     assert_memory_lock();
664 
665     addr &= TARGET_PAGE_MASK;
666     p = page_find(addr >> TARGET_PAGE_BITS);
667     if (!p) {
668         return false;
669     }
670 
671 #ifdef TARGET_HAS_PRECISE_SMC
672     if (p->first_tb && pc != 0) {
673         current_tb = tcg_tb_lookup(pc);
674     }
675 #endif
676     assert_page_locked(p);
677     PAGE_FOR_EACH_TB(p, tb, n) {
678 #ifdef TARGET_HAS_PRECISE_SMC
679         if (current_tb == tb &&
680             (tb_cflags(current_tb) & CF_COUNT_MASK) != 1) {
681             /*
682              * If we are modifying the current TB, we must stop its execution.
683              * We could be more precise by checking that the modification is
684              * after the current PC, but it would require a specialized
685              * function to partially restore the CPU state.
686              */
687             current_tb_modified = true;
688             cpu_restore_state_from_tb(cpu, current_tb, pc, true);
689         }
690 #endif /* TARGET_HAS_PRECISE_SMC */
691         tb_phys_invalidate(tb, addr);
692     }
693     p->first_tb = (uintptr_t)NULL;
694 #ifdef TARGET_HAS_PRECISE_SMC
695     if (current_tb_modified) {
696         /* Force execution of one insn next time.  */
697         cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu);
698         return true;
699     }
700 #endif
701 
702     return false;
703 }
704 #endif
705