From nobody Fri Oct 24 20:17:19 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 1519710536112413.73164025072947; Mon, 26 Feb 2018 21:48:56 -0800 (PST) Received: from localhost ([::1]:34964 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqY8E-0003C9-NG for importer@patchew.org; Tue, 27 Feb 2018 00:48:54 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50936) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqXzG-0004aZ-9j for qemu-devel@nongnu.org; Tue, 27 Feb 2018 00:39:45 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eqXzC-0000Q6-Kw for qemu-devel@nongnu.org; Tue, 27 Feb 2018 00:39:38 -0500 Received: from out2-smtp.messagingengine.com ([66.111.4.26]:47437) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eqXzC-0000PS-Fk for qemu-devel@nongnu.org; Tue, 27 Feb 2018 00:39:34 -0500 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 676BD20C05; Tue, 27 Feb 2018 00:39:33 -0500 (EST) Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Tue, 27 Feb 2018 00:39:33 -0500 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 1F1E97E26F; Tue, 27 Feb 2018 00:39:33 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=SSpBvxw0ts09+D HyhcRFOvw4AaFEyfIxMd95+fElITI=; b=00+ntdo3tjOSqxySZja9GM2V4KEnps CYp6fP9JazBR0HxdnXaqASDLn3mubfgHOJkfC/JV1xqfeatDZQ4m0fYG2usdoXDV hbcioJmNExoqkIRNMAnrxvnws5T1cziTdx2MzUKLAKSG72sTWeDVsmUy6ICzSELN eeJzVbkm22jSA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=SSpBvxw0ts09+DHyhcRFOvw4AaFEyfIxMd95+fElITI=; b=mcpLq3Ls My4ZOcEvR6rgQ5TeS9GfhUmH2uFpjpmfBsZ3EoEt1KRAw4UeG1Iz7ij/dYUnfMvr icaelxfwhBTsq9hniAPpCt88a2bTsJcfxXWnVkI7gMZlMFnFXDCEcJ76xyVEfAT3 rndU1CsPn9b6y4ERLITJYb93Xf80kK7GucyupjX5hO/EtQHXi1z3vI2MUeU9HuZM GtV95lxPRVJ5Gx6nrCwQHnOhjPLaeHEwUOMFm7gDOvkFZ5Zh2qV0BMbbodHBPl0N gAlLikYAVKsZ2seyzx37gTjFEZueT6Bv3KM+/7GkHN3hSmT5CkES8JOQUAPI2m7r lNOULmskKbbIFw== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Tue, 27 Feb 2018 00:39:14 -0500 Message-Id: <1519709965-29833-6-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1519709965-29833-1-git-send-email-cota@braap.org> References: <1519709965-29833-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.26 Subject: [Qemu-devel] [PATCH 05/16] translate-all: iterate over TBs in a page with PAGE_FOR_EACH_TB 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: Paolo Bonzini , 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" This commit does several things, but to avoid churn I merged them all into the same commit. To wit: - Use uintptr_t instead of TranslationBlock * for the list of TBs in a page. Just like we did in (c37e6d7e "tcg: Use uintptr_t type for jmp_list_{next|first} fields of TB"), the rationale is the same: these are tagged pointers, not pointers. So use a more appropriate type. - Only check the least significant bit of the tagged pointers. Masking with 3/~3 is unnecessary and confusing. - Introduce the TB_FOR_EACH_TAGGED macro, and use it to define PAGE_FOR_EACH_TB, which improves readability. - Update tb_page_remove to use PAGE_FOR_EACH_TB. In case there is a bug and we attempt to remove a TB that is not in the list, instead of segfaulting (since the list is NULL-terminated) we will reach g_assert_not_reached(). Signed-off-by: Emilio G. Cota Reviewed-by: Richard Henderson --- accel/tcg/translate-all.c | 65 +++++++++++++++++++++++--------------------= ---- include/exec/exec-all.h | 2 +- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 20ad3fc..06aa905 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -103,7 +103,7 @@ =20 typedef struct PageDesc { /* list of TBs intersecting this ram page */ - TranslationBlock *first_tb; + uintptr_t first_tb; #ifdef CONFIG_SOFTMMU /* in order to optimize self modifying code, we count the number of lookups we do to a given page to use a bitmap */ @@ -114,6 +114,18 @@ typedef struct PageDesc { #endif } PageDesc; =20 +/* list iterators for lists of tagged pointers in TranslationBlock */ +#define TB_FOR_EACH_TAGGED(head, tb, n, field) \ + for (n =3D (head) & 1, \ + tb =3D (TranslationBlock *)((head) & ~1); \ + tb; \ + tb =3D (TranslationBlock *)tb->field[n], \ + n =3D (uintptr_t)tb & 1, \ + tb =3D (TranslationBlock *)((uintptr_t)tb & ~1)) + +#define PAGE_FOR_EACH_TB(pagedesc, tb, n) \ + TB_FOR_EACH_TAGGED((pagedesc)->first_tb, tb, n, page_next) + /* In system mode we want L1_MAP to be based on ram offsets, while in user mode we want it to be based on virtual addresses. */ #if !defined(CONFIG_USER_ONLY) @@ -818,7 +830,7 @@ static void page_flush_tb_1(int level, void **lp) PageDesc *pd =3D *lp; =20 for (i =3D 0; i < V_L2_SIZE; ++i) { - pd[i].first_tb =3D NULL; + pd[i].first_tb =3D (uintptr_t)NULL; invalidate_page_bitmap(pd + i); } } else { @@ -946,21 +958,21 @@ static void tb_page_check(void) =20 #endif /* CONFIG_USER_ONLY */ =20 -static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock= *tb) +static inline void tb_page_remove(PageDesc *pd, TranslationBlock *tb) { TranslationBlock *tb1; + uintptr_t *pprev; unsigned int n1; =20 - for (;;) { - tb1 =3D *ptb; - n1 =3D (uintptr_t)tb1 & 3; - tb1 =3D (TranslationBlock *)((uintptr_t)tb1 & ~3); + pprev =3D &pd->first_tb; + PAGE_FOR_EACH_TB(pd, tb1, n1) { if (tb1 =3D=3D tb) { - *ptb =3D tb1->page_next[n1]; - break; + *pprev =3D tb1->page_next[n1]; + return; } - ptb =3D &tb1->page_next[n1]; + pprev =3D &tb1->page_next[n1]; } + g_assert_not_reached(); } =20 /* remove the TB from a list of TBs jumping to the n-th jump target of the= TB */ @@ -1048,12 +1060,12 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_pa= ge_addr_t page_addr) /* remove the TB from the page list */ if (tb->page_addr[0] !=3D page_addr) { p =3D page_find(tb->page_addr[0] >> TARGET_PAGE_BITS); - tb_page_remove(&p->first_tb, tb); + tb_page_remove(p, tb); invalidate_page_bitmap(p); } if (tb->page_addr[1] !=3D -1 && tb->page_addr[1] !=3D page_addr) { p =3D page_find(tb->page_addr[1] >> TARGET_PAGE_BITS); - tb_page_remove(&p->first_tb, tb); + tb_page_remove(p, tb); invalidate_page_bitmap(p); } =20 @@ -1084,10 +1096,7 @@ static void build_page_bitmap(PageDesc *p) =20 p->code_bitmap =3D bitmap_new(TARGET_PAGE_SIZE); =20 - tb =3D p->first_tb; - while (tb !=3D NULL) { - n =3D (uintptr_t)tb & 3; - tb =3D (TranslationBlock *)((uintptr_t)tb & ~3); + PAGE_FOR_EACH_TB(p, tb, n) { /* NOTE: this is subtle as a TB may span two physical pages */ if (n =3D=3D 0) { /* NOTE: tb_end may be after the end of the page, but @@ -1102,7 +1111,6 @@ static void build_page_bitmap(PageDesc *p) tb_end =3D ((tb->pc + tb->size) & ~TARGET_PAGE_MASK); } bitmap_set(p->code_bitmap, tb_start, tb_end - tb_start); - tb =3D tb->page_next[n]; } } #endif @@ -1125,9 +1133,9 @@ static inline void tb_alloc_page(TranslationBlock *tb, p =3D page_find_alloc(page_addr >> TARGET_PAGE_BITS, 1); tb->page_next[n] =3D p->first_tb; #ifndef CONFIG_USER_ONLY - page_already_protected =3D p->first_tb !=3D NULL; + page_already_protected =3D p->first_tb !=3D (uintptr_t)NULL; #endif - p->first_tb =3D (TranslationBlock *)((uintptr_t)tb | n); + p->first_tb =3D (uintptr_t)tb | n; invalidate_page_bitmap(p); =20 #if defined(CONFIG_USER_ONLY) @@ -1404,7 +1412,7 @@ void tb_invalidate_phys_range(tb_page_addr_t start, t= b_page_addr_t end) void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t en= d, int is_cpu_write_access) { - TranslationBlock *tb, *tb_next; + TranslationBlock *tb; tb_page_addr_t tb_start, tb_end; PageDesc *p; int n; @@ -1435,11 +1443,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t st= art, tb_page_addr_t end, /* we remove all the TBs in the range [start, end[ */ /* XXX: see if in some cases it could be faster to invalidate all the code */ - tb =3D p->first_tb; - while (tb !=3D NULL) { - n =3D (uintptr_t)tb & 3; - tb =3D (TranslationBlock *)((uintptr_t)tb & ~3); - tb_next =3D tb->page_next[n]; + PAGE_FOR_EACH_TB(p, tb, n) { /* NOTE: this is subtle as a TB may span two physical pages */ if (n =3D=3D 0) { /* NOTE: tb_end may be after the end of the page, but @@ -1476,7 +1480,6 @@ void tb_invalidate_phys_page_range(tb_page_addr_t sta= rt, tb_page_addr_t end, #endif /* TARGET_HAS_PRECISE_SMC */ tb_phys_invalidate(tb, -1); } - tb =3D tb_next; } #if !defined(CONFIG_USER_ONLY) /* if no code remaining, no need to continue to use slow writes */ @@ -1570,18 +1573,15 @@ static bool tb_invalidate_phys_page(tb_page_addr_t = addr, uintptr_t pc) } =20 tb_lock(); - tb =3D p->first_tb; #ifdef TARGET_HAS_PRECISE_SMC - if (tb && pc !=3D 0) { + if (p->first_tb && pc !=3D 0) { current_tb =3D tcg_tb_lookup(pc); } if (cpu !=3D NULL) { env =3D cpu->env_ptr; } #endif - while (tb !=3D NULL) { - n =3D (uintptr_t)tb & 3; - tb =3D (TranslationBlock *)((uintptr_t)tb & ~3); + PAGE_FOR_EACH_TB(p, tb, n) { #ifdef TARGET_HAS_PRECISE_SMC if (current_tb =3D=3D tb && (current_tb->cflags & CF_COUNT_MASK) !=3D 1) { @@ -1598,9 +1598,8 @@ static bool tb_invalidate_phys_page(tb_page_addr_t ad= dr, uintptr_t pc) } #endif /* TARGET_HAS_PRECISE_SMC */ tb_phys_invalidate(tb, addr); - tb =3D tb->page_next[n]; } - p->first_tb =3D NULL; + p->first_tb =3D (uintptr_t)NULL; #ifdef TARGET_HAS_PRECISE_SMC if (current_tb_modified) { /* Force execution of one insn next time. */ diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 17e08b3..5f7e65a 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -356,7 +356,7 @@ struct TranslationBlock { struct TranslationBlock *orig_tb; /* first and second physical page containing code. The lower bit of the pointer tells the index in page_next[] */ - struct TranslationBlock *page_next[2]; + uintptr_t page_next[2]; tb_page_addr_t page_addr[2]; =20 /* The following data are used to directly call another TB from --=20 2.7.4