diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index 7704e4017d..a35aca7889 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -239,13 +239,16 @@ void page_dump(FILE *f) int page_get_flags(vaddr address) { - PageFlagsNode *p = pageflags_find(address, address); + PageFlagsNode *p; + + RCU_READ_LOCK_GUARD(); /* * See util/interval-tree.c re lockless lookups: no false positives but * there are false negatives. If we find nothing, retry with the mmap * lock acquired. */ + p = pageflags_find(address, address); if (p) { return p->flags; } @@ -301,15 +304,15 @@ static void pageflags_create_merge(vaddr start, vaddr last, int flags) if (prev) { if (next) { - prev->itree.last = next->itree.last; + pageflags_create(prev->itree.start, next->itree.last, flags); g_free_rcu(next, rcu); } else { - prev->itree.last = last; + pageflags_create(prev->itree.start, last, flags); } - interval_tree_insert(&prev->itree, &pageflags_root); + g_free_rcu(prev, rcu); } else if (next) { - next->itree.start = start; - interval_tree_insert(&next->itree, &pageflags_root); + pageflags_create(start, next->itree.last, flags); + g_free_rcu(next, rcu); } else { pageflags_create(start, last, flags); } @@ -371,8 +374,8 @@ static bool pageflags_set_clear(vaddr start, vaddr last, if (set_flags != merge_flags) { if (p_start < start) { interval_tree_remove(&p->itree, &pageflags_root); - p->itree.last = start - 1; - interval_tree_insert(&p->itree, &pageflags_root); + pageflags_create(p_start, start - 1, p_flags); + g_free_rcu(p, rcu); if (last < p_last) { if (merge_flags & PAGE_VALID) { @@ -394,11 +397,11 @@ static bool pageflags_set_clear(vaddr start, vaddr last, } if (last < p_last) { interval_tree_remove(&p->itree, &pageflags_root); - p->itree.start = last + 1; - interval_tree_insert(&p->itree, &pageflags_root); + pageflags_create(last + 1, p_last, p_flags); if (merge_flags & PAGE_VALID) { pageflags_create(start, last, merge_flags); } + g_free_rcu(p, rcu); } else { if (merge_flags & PAGE_VALID) { p->flags = merge_flags; @@ -419,8 +422,8 @@ static bool pageflags_set_clear(vaddr start, vaddr last, if (set_flags == p_flags) { if (start < p_start) { interval_tree_remove(&p->itree, &pageflags_root); - p->itree.start = start; - interval_tree_insert(&p->itree, &pageflags_root); + pageflags_create(start, p_last, p_flags); + g_free_rcu(p, rcu); } if (p_last < last) { start = p_last + 1; @@ -432,8 +435,8 @@ static bool pageflags_set_clear(vaddr start, vaddr last, /* Maybe split out head and/or tail ranges with the original flags. */ interval_tree_remove(&p->itree, &pageflags_root); if (p_start < start) { - p->itree.last = start - 1; - interval_tree_insert(&p->itree, &pageflags_root); + pageflags_create(p_start, start - 1, p_flags); + g_free_rcu(p, rcu); if (p_last < last) { goto restart; @@ -442,8 +445,8 @@ static bool pageflags_set_clear(vaddr start, vaddr last, pageflags_create(last + 1, p_last, p_flags); } } else if (last < p_last) { - p->itree.start = last + 1; - interval_tree_insert(&p->itree, &pageflags_root); + pageflags_create(last + 1, p_last, p_flags); + g_free_rcu(p, rcu); } else { g_free_rcu(p, rcu); goto restart; @@ -505,6 +508,8 @@ bool page_check_range(vaddr start, vaddr len, int flags) return false; /* wrap around */ } + RCU_READ_LOCK_GUARD(); + locked = have_mmap_lock(); while (true) { PageFlagsNode *p = pageflags_find(start, last); @@ -769,7 +774,7 @@ static int probe_access_internal(CPUArchState *env, vaddr addr, if (page_flags & acc_flag) { if (access_type != MMU_INST_FETCH && cpu_plugin_mem_cbs_enabled(env_cpu(env))) { - return TLB_MMIO; + return TLB_FORCE_SLOW; } return 0; /* success */ } @@ -804,7 +809,7 @@ void *probe_access(CPUArchState *env, vaddr addr, int size, g_assert(-(addr | TARGET_PAGE_MASK) >= size); flags = probe_access_internal(env, addr, size, access_type, false, ra); - g_assert((flags & ~TLB_MMIO) == 0); + g_assert((flags & ~TLB_FORCE_SLOW) == 0); return size ? g2h_vaddr(env_cpu(env), addr) : NULL; } diff --git a/include/exec/tlb-flags.h b/include/exec/tlb-flags.h index 357e79095c..e12cddf234 100644 --- a/include/exec/tlb-flags.h +++ b/include/exec/tlb-flags.h @@ -27,12 +27,13 @@ /* * Allow some level of source compatibility with softmmu. - * Invalid is set when the page does not have requested permissions. - * MMIO is set when we want the target helper to use the functional + * INVALID is set when the page does not have requested permissions. + * FORCE_SLOW is set when we want the target helper to use the functional * interface for load/store so that plugins see the access. */ #define TLB_INVALID_MASK (1 << 0) -#define TLB_MMIO (1 << 1) +#define TLB_FORCE_SLOW (1 << 1) +#define TLB_MMIO 0 #define TLB_WATCHPOINT 0 #else diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index c3350c90fc..182dcfd5eb 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -2371,19 +2371,36 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, default: g_assert_not_reached(); } - break; - } - - insn = cmp_vec_insn[cond][lasx][vece]; - if (insn == 0) { - TCGArg t; - t = a1, a1 = a2, a2 = t; - cond = tcg_swap_cond(cond); - insn = cmp_vec_insn[cond][lasx][vece]; - tcg_debug_assert(insn != 0); + } else { + switch (cond) { + case TCG_COND_EQ: + case TCG_COND_LE: + case TCG_COND_LEU: + case TCG_COND_LT: + case TCG_COND_LTU: + insn = cmp_vec_insn[cond][lasx][vece]; + tcg_out32(s, encode_vdvjvk_insn(insn, a0, a1, a2)); + break; + case TCG_COND_GE: + case TCG_COND_GEU: + case TCG_COND_GT: + case TCG_COND_GTU: + insn = cmp_vec_insn[tcg_swap_cond(cond)][lasx][vece]; + tcg_out32(s, encode_vdvjvk_insn(insn, a0, a2, a1)); + break; + case TCG_COND_NE: + /* ne -> not(eq) */ + insn = cmp_vec_insn[TCG_COND_EQ][lasx][vece]; + tcg_out32(s, encode_vdvjvk_insn(insn, a0, a1, a2)); + insn = lasx ? OPC_XVNOR_V : OPC_VNOR_V; + tcg_out32(s, encode_vdvjvk_insn(insn, a0, a0, a0)); + break; + default: + g_assert_not_reached(); + } } } - goto vdvjvk; + break; case INDEX_op_add_vec: tcg_out_addsub_vec(s, lasx, vece, a0, a1, a2, const_args[2], true); break; diff --git a/tcg/x86_64/tcg-target.c.inc b/tcg/x86_64/tcg-target.c.inc index 92251f8327..1fc45e4ec6 100644 --- a/tcg/x86_64/tcg-target.c.inc +++ b/tcg/x86_64/tcg-target.c.inc @@ -1783,7 +1783,7 @@ bool tcg_target_has_memory_bswap(MemOp memop) * Reject 16-byte memop with 16-byte atomicity, i.e. VMOVDQA, * but do allow a pair of 64-bit operations, i.e. MOVBEQ. */ - aa = atom_and_align_for_opc(tcg_ctx, memop, MO_ATOM_IFALIGN, true); + aa = atom_and_align_for_opc(tcg_ctx, memop, MO_ATOM_WITHIN16, true); return aa.atom < MO_128; } @@ -1934,7 +1934,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h, *h = x86_guest_base; } h->base = addr; - h->aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, s_bits == MO_128); + h->aa = atom_and_align_for_opc(s, opc, MO_ATOM_WITHIN16, s_bits == MO_128); a_mask = (1 << h->aa.align) - 1; if (tcg_use_softmmu) { diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index 508149d57b..ab4bf9c5d5 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -60,15 +60,6 @@ tb-link: LDFLAGS+=-lpthread # code to work around the compiler. sha1: CFLAGS+=-Wno-stringop-overread -Wno-unknown-warning-option -# The vma-pthread seems very sensitive on gitlab and we currently -# don't know if its exposing a real bug or the test is flaky. -ifneq ($(GITLAB_CI),) -run-vma-pthread: vma-pthread - $(call skip-test, $<, "flaky on CI?") -run-plugin-vma-pthread-with-%: vma-pthread - $(call skip-test, $<, "flaky on CI?") -endif - run-test-mmap: test-mmap $(call run-test, test-mmap, $(QEMU) $<, $< (default)) diff --git a/tests/tcg/multiarch/vma-pthread.c b/tests/tcg/multiarch/vma-pthread.c index 7045da08fc..0b8ce9751b 100644 --- a/tests/tcg/multiarch/vma-pthread.c +++ b/tests/tcg/multiarch/vma-pthread.c @@ -11,6 +11,7 @@ * pages, which are guaranteed to have the respective protection bit set. * Two mutator threads change the non-fixed protection bits randomly. */ +#define _GNU_SOURCE #include #include #include @@ -121,7 +122,7 @@ static void *thread_mutate(void *arg) unsigned int seed; int prot, ret; - seed = (unsigned int)time(NULL); + seed = (unsigned int)time(NULL) + (unsigned int)gettid(); for (i = 0; i < 10000; i++) { start_idx = rand_r(&seed) & PAGE_IDX_MASK; end_idx = rand_r(&seed) & PAGE_IDX_MASK;