From nobody Thu Nov 6 03:27:20 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1539704638098706.3896406938131; Tue, 16 Oct 2018 08:43:58 -0700 (PDT) Received: from localhost ([::1]:58771 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gCRVk-0001Kl-LN for importer@patchew.org; Tue, 16 Oct 2018 11:43:56 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48488) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gCRQj-00060M-Lq for qemu-devel@nongnu.org; Tue, 16 Oct 2018 11:38:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gCRQg-0008Ng-BQ for qemu-devel@nongnu.org; Tue, 16 Oct 2018 11:38:45 -0400 Received: from out3-smtp.messagingengine.com ([66.111.4.27]:60669) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gCRQf-0008Kp-Vx for qemu-devel@nongnu.org; Tue, 16 Oct 2018 11:38:42 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 1AE66221F5; Tue, 16 Oct 2018 11:38:41 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Tue, 16 Oct 2018 11:38:41 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 60D4FE43A6; Tue, 16 Oct 2018 11:38:40 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h= from:to:cc:subject:date:message-id; s=mesmtp; bh=Rt71yZF8UG8C+H6 Ndj/2iavOx2ZxqooUCIAfIMKzoV4=; b=tAIHjNEQ1v3vStlj4tyYWgEXnohAqgS qSXqHLF7NSbXQP9ASEOwyvwljNOSHZQDtBGr6KJbdVrCRmpbLis1bP1MajIWuM2Q mS+X88rbnrBf3JXID44mOAgHgZobocJb5RkyvzE+Ayt538BdKJVfpUAkcU80rHzS 5umfrICuiQAo= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:message-id:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm1; bh=Rt71yZF8UG8C+H6Ndj/2iavOx2ZxqooUCIAfIMKzoV4=; b=yj7F0zUv PnpjY68bkiSQUMORibv6411MFY+I+9/32J4xcvitFymVDaVkb/U/51orAKQnIu4K 97j3dRIOgAjstlOTv4Hb3zvi4SGJRns1iFv4re27gWEky/ES3k01DF3FPlPWDvl8 ar/2R29+6j76E46YWqYmJywHYPTVHL5vYf/ZHGV0bnunipAUbtctS7XXCI6Oa0rH SI3Z1OY0wxYryPOJcwotnhUA3X7VBBRD2T5N+5OkfQ5NEV4fJZBcshHSwgc8JWdU j7VsgMJ0jXTHzNSISkw5krk2PHhOW1csqfdo6jhJVxvPrN0Txppn2Seybf5C533u 6i9w7Z367J3VLA== X-ME-Sender: X-ME-Proxy: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Tue, 16 Oct 2018 11:38:40 -0400 Message-Id: <20181016153840.25877-1-cota@braap.org> X-Mailer: git-send-email 2.17.1 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 66.111.4.27 Subject: [Qemu-devel] [PATCH tcg-next] cputlb: read CPUTLBEntry.addr_write atomically X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Updates can come from other threads, so readers that do not take tlb_lock must use atomic_read to avoid undefined behaviour (UB). This completes the conversion to tlb_lock. This conversion results on average in no performance loss, as the following experiments (run on an Intel i7-6700K CPU @ 4.00GHz) show. 1. aarch64 bootup+shutdown test: - Before: Performance counter stats for 'taskset -c 0 ../img/aarch64/die.sh' (10 run= s): 7487.087786 task-clock (msec) # 0.998 CPUs utilized = ( +- 0.12% ) 31,574,905,303 cycles # 4.217 GHz = ( +- 0.12% ) 57,097,908,812 instructions # 1.81 insns per cycl= e ( +- 0.08% ) 10,255,415,367 branches # 1369.747 M/sec = ( +- 0.08% ) 173,278,962 branch-misses # 1.69% of all branche= s ( +- 0.18% ) 7.504481349 seconds time elapsed = ( +- 0.14% ) - After: Performance counter stats for 'taskset -c 0 ../img/aarch64/die.sh' (10 run= s): 7462.441328 task-clock (msec) # 0.998 CPUs utilized = ( +- 0.07% ) 31,478,476,520 cycles # 4.218 GHz = ( +- 0.07% ) 57,017,330,084 instructions # 1.81 insns per cycl= e ( +- 0.05% ) 10,251,929,667 branches # 1373.804 M/sec = ( +- 0.05% ) 173,023,787 branch-misses # 1.69% of all branche= s ( +- 0.11% ) 7.474970463 seconds time elapsed = ( +- 0.07% ) 2. SPEC06int: SPEC06int (test set) [Y axis: Speedup over master] 1.15 +-+----+------+------+------+------+------+-------+------+------+---= ---+------+------+------+----+-+ | = | 1.1 +-+.................................+++.............................= + tlb-lock-v2 (m+++x) +-+ | +++ | +++ = tlb-lock-v3 (spinl|ck) | | +++ | | +++ +++ | = | | 1.05 +-+....+++...........####.........|####.+++.|......|.....###....+++.= ..........+++....###.........+-+ | ### ++#| # |# |# ***### +++### +++#+# | = +++ | #|# ### | 1 +-+++***+#++++####+++#++#++++++++++#++#+*+*++#++++#+#+****+#++++###+= +++###++++###++++#+#++++#+#+++-+ | *+* # #++# *** # #### *** # * *++# ****+# *| * # ****|# = |# # #|# #+# # # | 0.95 +-+..*.*.#....#..#.*|*..#...#..#.*|*..#.*.*..#.*|.*.#.*++*.#.*++*+#.= ****.#....#+#....#.#..++#.#..+-+ | * * # # # *|* # # # *|* # * * # *++* # * * # * * # = * |* # ++# # # # *** # | | * * # ++# # *+* # # # *|* # * * # * * # * * # * * # = *++* # **** # ++# # * * # | 0.9 +-+..*.*.#...|#..#.*.*..#.++#..#.*|*..#.*.*..#.*..*.#.*..*.#.*..*.#.= *..*.#.*.|*.#...|#.#..*.*.#..+-+ | * * # *** # * * # |# # *+* # * * # * * # * * # * * # = * * # *++* # |# # * * # | 0.85 +-+..*.*.#..*|*..#.*.*..#.***..#.*.*..#.*.*..#.*..*.#.*..*.#.*..*.#.= *..*.#.*..*.#.****.#..*.*.#..+-+ | * * # *+* # * * # *|* # * * # * * # * * # * * # * * # = * * # * * # * |* # * * # | | * * # * * # * * # *+* # * * # * * # * * # * * # * * # = * * # * * # * |* # * * # | 0.8 +-+..*.*.#..*.*..#.*.*..#.*.*..#.*.*..#.*.*..#.*..*.#.*..*.#.*..*.#.= *..*.#.*..*.#.*++*.#..*.*.#..+-+ | * * # * * # * * # * * # * * # * * # * * # * * # * * # = * * # * * # * * # * * # | 0.75 +-+--***##--***###-***###-***###-***###-***###-****##-****##-****##-= ****##-****##-****##--***##--+-+ 400.perlben401.bzip2403.gcc429.m445.gob456.hmme45462.libqua464.h26471.omne= t473483.xalancbmkgeomean png: https://imgur.com/a/BHzpPTW Notes: - tlb-lock-v2 corresponds to an implementation with a mutex. - tlb-lock-v3 corresponds to the current implementation, i.e. a spinlock and a single lock acquisition in tlb_set_page_with_attrs. Signed-off-by: Emilio G. Cota --- accel/tcg/softmmu_template.h | 12 ++++++------ include/exec/cpu_ldst.h | 11 ++++++++++- include/exec/cpu_ldst_template.h | 2 +- accel/tcg/cputlb.c | 19 +++++++++++++------ 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/accel/tcg/softmmu_template.h b/accel/tcg/softmmu_template.h index 09538b5349..b0adea045e 100644 --- a/accel/tcg/softmmu_template.h +++ b/accel/tcg/softmmu_template.h @@ -280,7 +280,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong = addr, DATA_TYPE val, uintptr_t mmu_idx =3D get_mmuidx(oi); uintptr_t index =3D tlb_index(env, mmu_idx, addr); CPUTLBEntry *entry =3D tlb_entry(env, mmu_idx, addr); - target_ulong tlb_addr =3D entry->addr_write; + target_ulong tlb_addr =3D tlb_addr_write(entry); unsigned a_bits =3D get_alignment_bits(get_memop(oi)); uintptr_t haddr; =20 @@ -295,7 +295,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong = addr, DATA_TYPE val, tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE, mmu_idx, retaddr); } - tlb_addr =3D entry->addr_write & ~TLB_INVALID_MASK; + tlb_addr =3D tlb_addr_write(entry) & ~TLB_INVALID_MASK; } =20 /* Handle an IO access. */ @@ -325,7 +325,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong = addr, DATA_TYPE val, cannot evict the first. */ page2 =3D (addr + DATA_SIZE) & TARGET_PAGE_MASK; entry2 =3D tlb_entry(env, mmu_idx, page2); - if (!tlb_hit_page(entry2->addr_write, page2) + if (!tlb_hit_page(tlb_addr_write(entry2), page2) && !VICTIM_TLB_HIT(addr_write, page2)) { tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE, mmu_idx, retaddr); @@ -358,7 +358,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong = addr, DATA_TYPE val, uintptr_t mmu_idx =3D get_mmuidx(oi); uintptr_t index =3D tlb_index(env, mmu_idx, addr); CPUTLBEntry *entry =3D tlb_entry(env, mmu_idx, addr); - target_ulong tlb_addr =3D entry->addr_write; + target_ulong tlb_addr =3D tlb_addr_write(entry); unsigned a_bits =3D get_alignment_bits(get_memop(oi)); uintptr_t haddr; =20 @@ -373,7 +373,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong = addr, DATA_TYPE val, tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE, mmu_idx, retaddr); } - tlb_addr =3D entry->addr_write & ~TLB_INVALID_MASK; + tlb_addr =3D tlb_addr_write(entry) & ~TLB_INVALID_MASK; } =20 /* Handle an IO access. */ @@ -403,7 +403,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong = addr, DATA_TYPE val, cannot evict the first. */ page2 =3D (addr + DATA_SIZE) & TARGET_PAGE_MASK; entry2 =3D tlb_entry(env, mmu_idx, page2); - if (!tlb_hit_page(entry2->addr_write, page2) + if (!tlb_hit_page(tlb_addr_write(entry2), page2) && !VICTIM_TLB_HIT(addr_write, page2)) { tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE, mmu_idx, retaddr); diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h index f54d91ff68..959068495a 100644 --- a/include/exec/cpu_ldst.h +++ b/include/exec/cpu_ldst.h @@ -126,6 +126,15 @@ extern __thread uintptr_t helper_retaddr; /* The memory helpers for tcg-generated code need tcg_target_long etc. */ #include "tcg.h" =20 +static inline target_ulong tlb_addr_write(const CPUTLBEntry *entry) +{ +#if TCG_OVERSIZED_GUEST + return entry->addr_write; +#else + return atomic_read(&entry->addr_write); +#endif +} + /* Find the TLB index corresponding to the mmu_idx + address pair. */ static inline uintptr_t tlb_index(CPUArchState *env, uintptr_t mmu_idx, target_ulong addr) @@ -439,7 +448,7 @@ static inline void *tlb_vaddr_to_host(CPUArchState *env= , abi_ptr addr, tlb_addr =3D tlbentry->addr_read; break; case 1: - tlb_addr =3D tlbentry->addr_write; + tlb_addr =3D tlb_addr_write(tlbentry); break; case 2: tlb_addr =3D tlbentry->addr_code; diff --git a/include/exec/cpu_ldst_template.h b/include/exec/cpu_ldst_templ= ate.h index d21a0b59bf..0f061d47ef 100644 --- a/include/exec/cpu_ldst_template.h +++ b/include/exec/cpu_ldst_template.h @@ -177,7 +177,7 @@ glue(glue(glue(cpu_st, SUFFIX), MEMSUFFIX), _ra)(CPUArc= hState *env, addr =3D ptr; mmu_idx =3D CPU_MMU_INDEX; entry =3D tlb_entry(env, mmu_idx, addr); - if (unlikely(entry->addr_write !=3D + if (unlikely(tlb_addr_write(entry) !=3D (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { oi =3D make_memop_idx(SHIFT, mmu_idx); glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(env, addr, v, oi, diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 28b770a404..af57aca5e4 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -258,7 +258,7 @@ static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tl= b_entry, target_ulong page) { return tlb_hit_page(tlb_entry->addr_read, page) || - tlb_hit_page(tlb_entry->addr_write, page) || + tlb_hit_page(tlb_addr_write(tlb_entry), page) || tlb_hit_page(tlb_entry->addr_code, page); } =20 @@ -855,7 +855,7 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry = *iotlbentry, tlb_fill(cpu, addr, size, MMU_DATA_STORE, mmu_idx, retaddr); =20 entry =3D tlb_entry(env, mmu_idx, addr); - tlb_addr =3D entry->addr_write; + tlb_addr =3D tlb_addr_write(entry); if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) { /* RAM access */ uintptr_t haddr =3D addr + entry->addend; @@ -904,7 +904,14 @@ static bool victim_tlb_hit(CPUArchState *env, size_t m= mu_idx, size_t index, assert_cpu_is_self(ENV_GET_CPU(env)); for (vidx =3D 0; vidx < CPU_VTLB_SIZE; ++vidx) { CPUTLBEntry *vtlb =3D &env->tlb_v_table[mmu_idx][vidx]; - target_ulong cmp =3D *(target_ulong *)((uintptr_t)vtlb + elt_ofs); + target_ulong cmp; + + /* elt_ofs might correspond to .addr_write, so use atomic_read */ +#if TCG_OVERSIZED_GUEST + cmp =3D *(target_ulong *)((uintptr_t)vtlb + elt_ofs); +#else + cmp =3D atomic_read((target_ulong *)((uintptr_t)vtlb + elt_ofs)); +#endif =20 if (cmp =3D=3D page) { /* Found entry in victim tlb, swap tlb and iotlb. */ @@ -977,7 +984,7 @@ void probe_write(CPUArchState *env, target_ulong addr, = int size, int mmu_idx, uintptr_t index =3D tlb_index(env, mmu_idx, addr); CPUTLBEntry *entry =3D tlb_entry(env, mmu_idx, addr); =20 - if (!tlb_hit(entry->addr_write, addr)) { + if (!tlb_hit(tlb_addr_write(entry), addr)) { /* TLB entry is for a different page */ if (!VICTIM_TLB_HIT(addr_write, addr)) { tlb_fill(ENV_GET_CPU(env), addr, size, MMU_DATA_STORE, @@ -995,7 +1002,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, targ= et_ulong addr, size_t mmu_idx =3D get_mmuidx(oi); uintptr_t index =3D tlb_index(env, mmu_idx, addr); CPUTLBEntry *tlbe =3D tlb_entry(env, mmu_idx, addr); - target_ulong tlb_addr =3D tlbe->addr_write; + target_ulong tlb_addr =3D tlb_addr_write(tlbe); TCGMemOp mop =3D get_memop(oi); int a_bits =3D get_alignment_bits(mop); int s_bits =3D mop & MO_SIZE; @@ -1026,7 +1033,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, tar= get_ulong addr, tlb_fill(ENV_GET_CPU(env), addr, 1 << s_bits, MMU_DATA_STORE, mmu_idx, retaddr); } - tlb_addr =3D tlbe->addr_write & ~TLB_INVALID_MASK; + tlb_addr =3D tlb_addr_write(tlbe) & ~TLB_INVALID_MASK; } =20 /* Notice an IO access or a needs-MMU-lookup access */ --=20 2.17.1