From patchwork Thu Jun 14 19:31:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138614 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2525562lji; Thu, 14 Jun 2018 12:37:35 -0700 (PDT) X-Google-Smtp-Source: ADUXVKI/Q8RxI0frS7gucz+80aqMjzEuRkWV70ZY1Gyrdth88ClV5aLPywo2OwnReOXu/Bx2dhyq X-Received: by 2002:a37:444c:: with SMTP id r73-v6mr3352671qka.351.1529005055150; Thu, 14 Jun 2018 12:37:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005055; cv=none; d=google.com; s=arc-20160816; b=P1BiZd/icuhBXAQkoNFiS1S4HgVgToo2X3CLCBivdE/c9I2DXaLCi1kjYpOA/+2PmU AdaPR8ONgqFVj/+PvKqwmEUO4y/qtYK9WC/fO5axq73QowtR5sAzC88dBOsNWP83Nz4v caZJhiNj2+PoW2XF5SUtX58eAoU88qhQcWFwYcBHcn+SzrjGLwWN0FDDlwNkL9Qh34X1 wodS+reJM8BQz0dq8i2c0ucR1/5sztrib3IjeaE8TEi5CzKTJpeKLagVLHp2X/A5yPn0 ZSwbgigKAJklZbVOWl6bg+Uy2uhd0kLizFflPABduT7wx2EZWiTBMG3sA5voJdCaAeDG jO2w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=8yfaMikkCfKbwAVcUNBZHbpP9x83/6cBIZm5WMmsiqk=; b=VOQ80Vl+lukfCSER6y8FW284/IOgtncPrBFi7pZPL4n0O61eFj13b8uQLu8vvs5FBZ 9hc75UGW8uNl8dCFS7h8jUOdrtlvwXIdet3S6ZFlI/r28GzfS40tHrkQkvat9En/2K0C VsYk1LHk+1kNzd4IyNs1YwkK5yCtOvVlEIRD667K2fBLtvM40foyyEMc4X/1WGdBMYhp pYIdSjhi6JJfdZJB9dfZOCZDIicLzwRfzrvRGzi73TZ9pzfLk5Z8kiYigRTjmkUft9MY pDgZw1D06/dnlE2wRzZT5aqPR5lWSGvdzKwDNVPslla32YRdw28Uz/QVTXcNF81X4Q9E 221w== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=hGwOTovT; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id d10-v6si5832765qvd.227.2018.06.14.12.37.34 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:37:35 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=hGwOTovT; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42356 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTY3q-0002Qg-IE for patch@linaro.org; Thu, 14 Jun 2018 15:37:34 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36786) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyP-0006pu-OJ for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyN-0005fI-3u for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:31:57 -0400 Received: from mail-pg0-x241.google.com ([2607:f8b0:400e:c05::241]:39031) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyM-0005ex-Tw for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:31:55 -0400 Received: by mail-pg0-x241.google.com with SMTP id w12-v6so3362539pgc.6 for ; Thu, 14 Jun 2018 12:31:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8yfaMikkCfKbwAVcUNBZHbpP9x83/6cBIZm5WMmsiqk=; b=hGwOTovT4Eb1DSoEb7j/efiKsucQ9bEghPC6qxH0FRRrp6qwy248GGhv/svvXDUqEL OBWG0H+kPzmOHWUNf7FJ1kg7GYhRdxuKI2J1xJZLu8miMhrJI5ocvsbuGu/K28vrOGef 3Z3b5so5qhI3JEgkVcE/DyOy6y1SFbR12A21Q= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=8yfaMikkCfKbwAVcUNBZHbpP9x83/6cBIZm5WMmsiqk=; b=nqLaeIEBR2C02HbDW5C1A0unX6RdIDHf358wlK322MfId3yF+rPndBpCjUDJ/Al/zo 1twVyJgNj31B4WpiKWtE6J9NCbekdneq3En/lBzOI5oG5RPhlUu+X2+ANt5+N2Hs2NT3 hWb7hotG4Cq34pkDuyluE9R7BtANk8/w8766YDG8iwXKXU3diZl5MRAgjpHSmabKNcTm ULRipgVCbn1Qspx27xYLY4rDinJQ60NoDGDxtman7X0iRyKsI+m11LMdIRXh93Blgt1+ +O2bexWv4SAnC6f+Qp/qGP8SHqIwV85H5J9NkaT0XIlbvgggOGN/jn6cxS4MZd3Iv11K Ydlg== X-Gm-Message-State: APt69E3FHD300Ay5FOzM1LXBqk3vMkj2esiig3+xJqfCSYMHxfKZpEq6 ZeNeneK+6wgz84Y4AtArdBirhmO/Wbg= X-Received: by 2002:a62:1747:: with SMTP id 68-v6mr10672774pfx.69.1529004713687; Thu, 14 Jun 2018 12:31:53 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.31.52 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:31:52 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:30 -1000 Message-Id: <20180614193147.29680-2-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::241 Subject: [Qemu-devel] [PULL 01/18] tcg/i386: Use byte form of xgetbv instruction 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: peter.maydell@linaro.org, John Arbuckle Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: John Arbuckle The assembler in most versions of Mac OS X is pretty old and does not support the xgetbv instruction. To go around this problem, the raw encoding of the instruction is used instead. Signed-off-by: John Arbuckle Message-Id: <20180604215102.11002-1-programmingkidx@gmail.com> Signed-off-by: Richard Henderson --- tcg/i386/tcg-target.inc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) -- 2.17.1 diff --git a/tcg/i386/tcg-target.inc.c b/tcg/i386/tcg-target.inc.c index 5357909fff..0d0ff524b7 100644 --- a/tcg/i386/tcg-target.inc.c +++ b/tcg/i386/tcg-target.inc.c @@ -3501,7 +3501,10 @@ static void tcg_target_init(TCGContext *s) sure of not hitting invalid opcode. */ if (c & bit_OSXSAVE) { unsigned xcrl, xcrh; - asm ("xgetbv" : "=a" (xcrl), "=d" (xcrh) : "c" (0)); + /* The xgetbv instruction is not available to older versions of + * the assembler, so we encode the instruction manually. + */ + asm(".byte 0x0f, 0x01, 0xd0" : "=a" (xcrl), "=d" (xcrh) : "c" (0)); if ((xcrl & 6) == 6) { have_avx1 = (c & bit_AVX) != 0; have_avx2 = (b7 & bit_AVX2) != 0; From patchwork Thu Jun 14 19:31:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138613 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2525460lji; Thu, 14 Jun 2018 12:37:30 -0700 (PDT) X-Google-Smtp-Source: ADUXVKKLrWXeBK15yjlZ9s57qdcj/TGRub6CSnBn+RQV8w2x/v+ZZs4CPaJm3kKWMvhkoTgNoUK2 X-Received: by 2002:ac8:1492:: with SMTP id l18-v6mr3715201qtj.129.1529005050014; Thu, 14 Jun 2018 12:37:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005050; cv=none; d=google.com; s=arc-20160816; b=0buqBlhhAKsMzNkO4Ch0D94FcL/1EDGE/R96hp13tleSOYHiSpHdX8OYBLWTHVX4G0 2mfevvnRy8DjgAsNIFRtch6a7md9vMOZ558sRYW2NATVzsrfLvzbPzctA2BrKVfOy2NF pSw0G2OvFZF1MMQ6MHguRtFDdzvmitvdFP2sZmZ+lCHVhN9XbuTtotIBFlprAqiSEoRa 8Ek9RjWHRzWItc4r3FOJ6Sqq72+1JMn6qvdHlIq25sg1FVqwQgxCIzO1MaSZsu7r8WQa JKI0IwOtz4JXgdaScuZ5LLZVWUsU/aJdL7opbcP7loAQqQy5XOsBr+DiNdl7lIjuNmyv MC7A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=M1WJimfiOpdfhSsAH0MrmldFGe5RTCBwDNlrKZr6LjE=; b=cd6Tzg7k2i6Jky8OTUe5006OQ61IdpxsqQCDYGecJmeAdbyxxaE1cptuZ/IJ0hHZ1X mVWslHiflvfluH6+yo6sT1ALzGIoQbYJ+LVHvVqERUruTk5BY55XEl//tC0zSyB+k0m9 xuKaqMbTRbgcRzNfKnmxv/Hbxlrwy/lI3zvpOAw72u4HwNwZv85kC+iA4JiK/+REjB6n VIKaf01XrXqDvVEZ/+LAcBulMIfLJfncPeTYKzN+k1amfSJIAVulQGQUR2dR8dAwOjcu +TGz6gUBTeSaV6Nah469jbvJmpGTifeC2+swtEMdwamYRC9rk6vFGCLPyJPK/b72FbVm eAiA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=SE81m6wH; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id h23-v6si1937643qtm.273.2018.06.14.12.37.29 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:37:30 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=SE81m6wH; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42354 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTY3l-0002Jc-C2 for patch@linaro.org; Thu, 14 Jun 2018 15:37:29 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36808) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyQ-0006qP-NB for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyP-0005gJ-3s for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:31:58 -0400 Received: from mail-pg0-x22a.google.com ([2607:f8b0:400e:c05::22a]:37423) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyO-0005ff-Rf for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:31:57 -0400 Received: by mail-pg0-x22a.google.com with SMTP id r21-v6so3364224pgv.4 for ; Thu, 14 Jun 2018 12:31:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=M1WJimfiOpdfhSsAH0MrmldFGe5RTCBwDNlrKZr6LjE=; b=SE81m6wHJhcxDLxjMzUy0a8b7982cT1F8jgD6vEpoL0rocLpdCdNJJZO8prr3aaq2t iaEeCVM4mstvEPJGWNixRI8oy1hhc3Xuu8BLO9TtMVoBn4t/5JhktZMK4QzLdSXzJaR0 qXOE0iLnfu9Oz0weB5r5XhnPjsWEbVFLOrm/M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=M1WJimfiOpdfhSsAH0MrmldFGe5RTCBwDNlrKZr6LjE=; b=E4Q01DMADOEFFKBSal2fSCgGKARQ+lacmKqIbjMF2XFYRSVsTcdR+T4xj9+dnSR4eA IMe2SqUjpT8IenXYvSN83wYWH9CycPozmDXeorx7aVBAMduC/gsPJ6Ef0JxV2tjRkloq FqG8jthpayJKHm5wkie+4gGjI/H/qxd2gBZyunE6oE3yxaZ7XMRp6cw4M6HsK5diI/BC A7vU1j8W3RSneHOuAJwgbSjHpBOap59dJXC6QDZZQNYQWTlZ1eTk8cflTs4aFSCGgBdg svCcVaz+ORQ0lw61wxtAJ6lFs/w03NVqg02pPNT1y41L/doP72bDdZwnyI3L5MrEJa0K /vSg== X-Gm-Message-State: APt69E1jODTHbgKekCeveer7lBxZO44TRB55lvOsBJMDzW2X4UIK240a Q8GSvd6F2DChA0EU+deE3TJT56oYes8= X-Received: by 2002:a62:50d6:: with SMTP id g83-v6mr10728511pfj.31.1529004715523; Thu, 14 Jun 2018 12:31:55 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.31.53 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:31:54 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:31 -1000 Message-Id: <20180614193147.29680-3-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::22a Subject: [Qemu-devel] [PULL 02/18] qht: require a default comparison function 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" qht_lookup now uses the default cmp function. qht_lookup_custom is defined to retain the old behaviour, that is a cmp function is explicitly provided. qht_insert will gain use of the default cmp in the next patch. Note that we move qht_lookup_custom's @func to be the last argument, which makes the new qht_lookup as simple as possible. Instead of this (i.e. keeping @func 2nd): 0000000000010750 : 10750: 89 d1 mov %edx,%ecx 10752: 48 89 f2 mov %rsi,%rdx 10755: 48 8b 77 08 mov 0x8(%rdi),%rsi 10759: e9 22 ff ff ff jmpq 10680 1075e: 66 90 xchg %ax,%ax We get: 0000000000010740 : 10740: 48 8b 4f 08 mov 0x8(%rdi),%rcx 10744: e9 37 ff ff ff jmpq 10680 10749: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- include/qemu/qht.h | 25 ++++++++++++++++++++----- accel/tcg/cpu-exec.c | 4 ++-- accel/tcg/translate-all.c | 16 +++++++++++++++- tests/qht-bench.c | 14 +++++++------- tests/test-qht.c | 15 ++++++++++----- util/qht.c | 14 +++++++++++--- 6 files changed, 65 insertions(+), 23 deletions(-) -- 2.17.1 diff --git a/include/qemu/qht.h b/include/qemu/qht.h index 531aa95325..5f03a0f4cb 100644 --- a/include/qemu/qht.h +++ b/include/qemu/qht.h @@ -11,8 +11,11 @@ #include "qemu/thread.h" #include "qemu/qdist.h" +typedef bool (*qht_cmp_func_t)(const void *a, const void *b); + struct qht { struct qht_map *map; + qht_cmp_func_t cmp; QemuMutex lock; /* serializes setters of ht->map */ unsigned int mode; }; @@ -47,10 +50,12 @@ typedef void (*qht_iter_func_t)(struct qht *ht, void *p, uint32_t h, void *up); /** * qht_init - Initialize a QHT * @ht: QHT to be initialized + * @cmp: default comparison function. Cannot be NULL. * @n_elems: number of entries the hash table should be optimized for. * @mode: bitmask with OR'ed QHT_MODE_* */ -void qht_init(struct qht *ht, size_t n_elems, unsigned int mode); +void qht_init(struct qht *ht, qht_cmp_func_t cmp, size_t n_elems, + unsigned int mode); /** * qht_destroy - destroy a previously initialized QHT @@ -78,11 +83,11 @@ void qht_destroy(struct qht *ht); bool qht_insert(struct qht *ht, void *p, uint32_t hash); /** - * qht_lookup - Look up a pointer in a QHT + * qht_lookup_custom - Look up a pointer using a custom comparison function. * @ht: QHT to be looked up - * @func: function to compare existing pointers against @userp * @userp: pointer to pass to @func * @hash: hash of the pointer to be looked up + * @func: function to compare existing pointers against @userp * * Needs to be called under an RCU read-critical section. * @@ -94,8 +99,18 @@ bool qht_insert(struct qht *ht, void *p, uint32_t hash); * Returns the corresponding pointer when a match is found. * Returns NULL otherwise. */ -void *qht_lookup(struct qht *ht, qht_lookup_func_t func, const void *userp, - uint32_t hash); +void *qht_lookup_custom(struct qht *ht, const void *userp, uint32_t hash, + qht_lookup_func_t func); + +/** + * qht_lookup - Look up a pointer in a QHT + * @ht: QHT to be looked up + * @userp: pointer to pass to the comparison function + * @hash: hash of the pointer to be looked up + * + * Calls qht_lookup_custom() using @ht's default comparison function. + */ +void *qht_lookup(struct qht *ht, const void *userp, uint32_t hash); /** * qht_remove - remove a pointer from the hash table diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 4ef95d8dd3..6d6c51b686 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -295,7 +295,7 @@ struct tb_desc { uint32_t trace_vcpu_dstate; }; -static bool tb_cmp(const void *p, const void *d) +static bool tb_lookup_cmp(const void *p, const void *d) { const TranslationBlock *tb = p; const struct tb_desc *desc = d; @@ -340,7 +340,7 @@ TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc, phys_pc = get_page_addr_code(desc.env, pc); desc.phys_page1 = phys_pc & TARGET_PAGE_MASK; h = tb_hash_func(phys_pc, pc, flags, cf_mask, *cpu->trace_dstate); - return qht_lookup(&tb_ctx.htable, tb_cmp, &desc, h); + return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp); } void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index d48b56ca38..f39123bd5a 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -782,11 +782,25 @@ static inline void code_gen_alloc(size_t tb_size) qemu_mutex_init(&tb_ctx.tb_lock); } +static bool tb_cmp(const void *ap, const void *bp) +{ + const TranslationBlock *a = ap; + const TranslationBlock *b = bp; + + return a->pc == b->pc && + a->cs_base == b->cs_base && + a->flags == b->flags && + (tb_cflags(a) & CF_HASH_MASK) == (tb_cflags(b) & CF_HASH_MASK) && + a->trace_vcpu_dstate == b->trace_vcpu_dstate && + a->page_addr[0] == b->page_addr[0] && + a->page_addr[1] == b->page_addr[1]; +} + static void tb_htable_init(void) { unsigned int mode = QHT_MODE_AUTO_RESIZE; - qht_init(&tb_ctx.htable, CODE_GEN_HTABLE_SIZE, mode); + qht_init(&tb_ctx.htable, tb_cmp, CODE_GEN_HTABLE_SIZE, mode); } /* Must be called before using the QEMU cpus. 'tb_size' is the size diff --git a/tests/qht-bench.c b/tests/qht-bench.c index 4cabdfd62a..c94ac25158 100644 --- a/tests/qht-bench.c +++ b/tests/qht-bench.c @@ -93,10 +93,10 @@ static void usage_complete(int argc, char *argv[]) exit(-1); } -static bool is_equal(const void *obj, const void *userp) +static bool is_equal(const void *ap, const void *bp) { - const long *a = obj; - const long *b = userp; + const long *a = ap; + const long *b = bp; return *a == *b; } @@ -150,7 +150,7 @@ static void do_rw(struct thread_info *info) p = &keys[info->r & (lookup_range - 1)]; hash = h(*p); - read = qht_lookup(&ht, is_equal, p, hash); + read = qht_lookup(&ht, p, hash); if (read) { stats->rd++; } else { @@ -162,7 +162,7 @@ static void do_rw(struct thread_info *info) if (info->write_op) { bool written = false; - if (qht_lookup(&ht, is_equal, p, hash) == NULL) { + if (qht_lookup(&ht, p, hash) == NULL) { written = qht_insert(&ht, p, hash); } if (written) { @@ -173,7 +173,7 @@ static void do_rw(struct thread_info *info) } else { bool removed = false; - if (qht_lookup(&ht, is_equal, p, hash)) { + if (qht_lookup(&ht, p, hash)) { removed = qht_remove(&ht, p, hash); } if (removed) { @@ -308,7 +308,7 @@ static void htable_init(void) } /* initialize the hash table */ - qht_init(&ht, qht_n_elems, qht_mode); + qht_init(&ht, is_equal, qht_n_elems, qht_mode); assert(init_size <= init_range); pr_params(); diff --git a/tests/test-qht.c b/tests/test-qht.c index 9b7423abb6..b069881342 100644 --- a/tests/test-qht.c +++ b/tests/test-qht.c @@ -13,10 +13,10 @@ static struct qht ht; static int32_t arr[N * 2]; -static bool is_equal(const void *obj, const void *userp) +static bool is_equal(const void *ap, const void *bp) { - const int32_t *a = obj; - const int32_t *b = userp; + const int32_t *a = ap; + const int32_t *b = bp; return *a == *b; } @@ -60,7 +60,12 @@ static void check(int a, int b, bool expected) val = i; hash = i; - p = qht_lookup(&ht, is_equal, &val, hash); + /* test both lookup variants; results should be the same */ + if (i % 2) { + p = qht_lookup(&ht, &val, hash); + } else { + p = qht_lookup_custom(&ht, &val, hash, is_equal); + } g_assert_true(!!p == expected); } rcu_read_unlock(); @@ -102,7 +107,7 @@ static void qht_do_test(unsigned int mode, size_t init_entries) /* under KVM we might fetch stats from an uninitialized qht */ check_n(0); - qht_init(&ht, 0, mode); + qht_init(&ht, is_equal, 0, mode); check_n(0); insert(0, N); diff --git a/util/qht.c b/util/qht.c index ff4d2e6974..8610ce3644 100644 --- a/util/qht.c +++ b/util/qht.c @@ -351,11 +351,14 @@ static struct qht_map *qht_map_create(size_t n_buckets) return map; } -void qht_init(struct qht *ht, size_t n_elems, unsigned int mode) +void qht_init(struct qht *ht, qht_cmp_func_t cmp, size_t n_elems, + unsigned int mode) { struct qht_map *map; size_t n_buckets = qht_elems_to_buckets(n_elems); + g_assert(cmp); + ht->cmp = cmp; ht->mode = mode; qemu_mutex_init(&ht->lock); map = qht_map_create(n_buckets); @@ -479,8 +482,8 @@ void *qht_lookup__slowpath(struct qht_bucket *b, qht_lookup_func_t func, return ret; } -void *qht_lookup(struct qht *ht, qht_lookup_func_t func, const void *userp, - uint32_t hash) +void *qht_lookup_custom(struct qht *ht, const void *userp, uint32_t hash, + qht_lookup_func_t func) { struct qht_bucket *b; struct qht_map *map; @@ -502,6 +505,11 @@ void *qht_lookup(struct qht *ht, qht_lookup_func_t func, const void *userp, return qht_lookup__slowpath(b, func, userp, hash); } +void *qht_lookup(struct qht *ht, const void *userp, uint32_t hash) +{ + return qht_lookup_custom(ht, userp, hash, ht->cmp); +} + /* call with head->lock held */ static bool qht_insert__locked(struct qht *ht, struct qht_map *map, struct qht_bucket *head, void *p, uint32_t hash, From patchwork Thu Jun 14 19:31:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138620 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2528920lji; Thu, 14 Jun 2018 12:41:10 -0700 (PDT) X-Google-Smtp-Source: ADUXVKI+kdUIC5G1JKFeBRDPEu6H4ATsBPEP6a4iUsgxSv8QWAdLYNfL4IISPVWnwt9nJfKyFRLT X-Received: by 2002:ac8:2238:: with SMTP id o53-v6mr3727584qto.355.1529005270486; Thu, 14 Jun 2018 12:41:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005270; cv=none; d=google.com; s=arc-20160816; b=usLy0Mlfy57OUZtHSLgk9IuhLffRakhhYWUzyOXYv1iJzU1jbjZ/tMD4g69Mm7uHkS sX56t0ucLALqR0Vg787pW+L3Rj3MVBPk6zBG2xMG6mBw2iybC7WTR2yw1Mf8/porG4AT 0gxXKduRwKtbtyfLeS3v5xQSnb/S73mqAPCvm/kuue86kWNWFV/JKeJRluy7tXE0Zk4w 4IW6Cj6LwQLljTWYZJaPYb7xp6OYXgjAAfjtn9ruJ7LyIU9kdNmDyihuyqvV46XZFi1y g5uaQPVYKZ/yX0UnzdgSPXv8eEw0ZOKc1d3tTLYFUIQ1AgDSnid/HI5Q4rW8qIoOxGcY 9/Aw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=0ifFvg47P31SiqVLHK249PSF/Xw/scsIziiDtRJNjko=; b=iXpHhx8XVDsI62+LjQ9i2kLV8mY/uhHV8K9jB840m+odunrd4PfoNA/nU6jTGzhvuI 3ExsWmJ11NKUIyhe4aczKJYYzXR9EmJY1qFJrNgHmQPiNWfGBBfqcu7py29sqFO7lod0 zbwsKrietoGad8oLh1s0qAEAjLlmlcYX1UkyLkI//n3CNvw+NDGfdE5bMF4PfsEaXAgh 4KSayxB8GjC0xVkFOX7wgnXkD3KjBSziCfaIT4seJiGxjzGkDQdSjQsCV4tjcFxmqmzS zpsSOdQ5ll05VTybqUU0AStqoiVyEQu/8OZ+oKO0fQyf2AQFoxBtTv2Gk2jIjg80EkRb XIXA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b="GLHx49/z"; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id p17-v6si5040594qvf.115.2018.06.14.12.41.10 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:41:10 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b="GLHx49/z"; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42375 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTY7J-0005wh-LG for patch@linaro.org; Thu, 14 Jun 2018 15:41:09 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36832) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyS-0006qQ-0K for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyQ-0005hO-Ml for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:00 -0400 Received: from mail-pg0-x22a.google.com ([2607:f8b0:400e:c05::22a]:40832) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyQ-0005h6-FK for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:31:58 -0400 Received: by mail-pg0-x22a.google.com with SMTP id w8-v6so330697pgp.7 for ; Thu, 14 Jun 2018 12:31:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0ifFvg47P31SiqVLHK249PSF/Xw/scsIziiDtRJNjko=; b=GLHx49/zPCGzimPZgIpOxzvV/uh8LnXRBoYVC/r86kQoC0OxGksZEb8aZfHnRytzPi fm9IFybwumTTWznaM4z1wXT6GPotxKWMzCnddXUydc2LnrheKTSCf3EcS0KMrCCnHfIa YVHfU5lz7MdgatvAZIqI5CdQ4LLMpk41rFBgU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0ifFvg47P31SiqVLHK249PSF/Xw/scsIziiDtRJNjko=; b=dJhNWOhgFB/lPR/a98kZiy98T/aZ/GYwM2F8xagyGVC/u7CJzsm92pbRe8H4lzVKiJ b337gvqomiV66EoTT61tN8GRhIRjiTb9uqynBh8wI72cAQ1vD0xVEQHLj3P64WGzrKTG sPKLJcQuoO2cX4zjU1H5ES4jtgmsSUuFUUhSsZSfuFEiHTD6y2BvYkJe8qNDZV5ZAiIF m5zSAuz/YIcEQMeILgUlG35R90EevZaM5VJ2gj0V20DK7ThSM/ODJjpeXdmqr5ABRzJ7 zqAyZtRhZFiIZvOvD3yZGHJaeCcAuUbBXfSuDzALtM1b/ng/NY9gmRqoqIurZET55N4T QxWA== X-Gm-Message-State: APt69E0sRMdMBnZmfvyn9DnQhw0wRuDxrEuopf/2YfvTpUbPWZKLjKFy Bwju3EI4uQzY2PCiWg+kC4Azf1ompXA= X-Received: by 2002:a62:e401:: with SMTP id r1-v6mr10817705pfh.172.1529004717298; Thu, 14 Jun 2018 12:31:57 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.31.55 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:31:56 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:32 -1000 Message-Id: <20180614193147.29680-4-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::22a Subject: [Qemu-devel] [PULL 03/18] qht: return existing entry when qht_insert fails 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" The meaning of "existing" is now changed to "matches in hash and ht->cmp result". This is saner than just checking the pointer value. Suggested-by: Richard Henderson Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- include/qemu/qht.h | 7 +++++-- accel/tcg/translate-all.c | 2 +- tests/qht-bench.c | 4 ++-- tests/test-qht.c | 8 +++++++- util/qht.c | 27 +++++++++++++++++---------- 5 files changed, 32 insertions(+), 16 deletions(-) -- 2.17.1 diff --git a/include/qemu/qht.h b/include/qemu/qht.h index 5f03a0f4cb..1fb9116fa0 100644 --- a/include/qemu/qht.h +++ b/include/qemu/qht.h @@ -70,6 +70,7 @@ void qht_destroy(struct qht *ht); * @ht: QHT to insert to * @p: pointer to be inserted * @hash: hash corresponding to @p + * @existing: address where the pointer to an existing entry can be copied to * * Attempting to insert a NULL @p is a bug. * Inserting the same pointer @p with different @hash values is a bug. @@ -78,9 +79,11 @@ void qht_destroy(struct qht *ht); * inserted into the hash table. * * Returns true on success. - * Returns false if the @p-@hash pair already exists in the hash table. + * Returns false if there is an existing entry in the table that is equivalent + * (i.e. ht->cmp matches and the hash is the same) to @p-@h. If @existing + * is !NULL, a pointer to this existing entry is copied to it. */ -bool qht_insert(struct qht *ht, void *p, uint32_t hash); +bool qht_insert(struct qht *ht, void *p, uint32_t hash, void **existing); /** * qht_lookup_custom - Look up a pointer using a custom comparison function. diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index f39123bd5a..1695f8c352 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -1242,7 +1242,7 @@ static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, /* add in the hash table */ h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags & CF_HASH_MASK, tb->trace_vcpu_dstate); - qht_insert(&tb_ctx.htable, tb, h); + qht_insert(&tb_ctx.htable, tb, h, NULL); #ifdef CONFIG_USER_ONLY if (DEBUG_TB_CHECK_GATE) { diff --git a/tests/qht-bench.c b/tests/qht-bench.c index c94ac25158..f492b3a20a 100644 --- a/tests/qht-bench.c +++ b/tests/qht-bench.c @@ -163,7 +163,7 @@ static void do_rw(struct thread_info *info) bool written = false; if (qht_lookup(&ht, p, hash) == NULL) { - written = qht_insert(&ht, p, hash); + written = qht_insert(&ht, p, hash, NULL); } if (written) { stats->in++; @@ -322,7 +322,7 @@ static void htable_init(void) r = xorshift64star(r); p = &keys[r & (init_range - 1)]; hash = h(*p); - if (qht_insert(&ht, p, hash)) { + if (qht_insert(&ht, p, hash, NULL)) { break; } retries++; diff --git a/tests/test-qht.c b/tests/test-qht.c index b069881342..dda6a067be 100644 --- a/tests/test-qht.c +++ b/tests/test-qht.c @@ -27,11 +27,17 @@ static void insert(int a, int b) for (i = a; i < b; i++) { uint32_t hash; + void *existing; + bool inserted; arr[i] = i; hash = i; - qht_insert(&ht, &arr[i], hash); + inserted = qht_insert(&ht, &arr[i], hash, NULL); + g_assert_true(inserted); + inserted = qht_insert(&ht, &arr[i], hash, &existing); + g_assert_false(inserted); + g_assert_true(existing == &arr[i]); } } diff --git a/util/qht.c b/util/qht.c index 8610ce3644..9d030e7b76 100644 --- a/util/qht.c +++ b/util/qht.c @@ -511,9 +511,9 @@ void *qht_lookup(struct qht *ht, const void *userp, uint32_t hash) } /* call with head->lock held */ -static bool qht_insert__locked(struct qht *ht, struct qht_map *map, - struct qht_bucket *head, void *p, uint32_t hash, - bool *needs_resize) +static void *qht_insert__locked(struct qht *ht, struct qht_map *map, + struct qht_bucket *head, void *p, uint32_t hash, + bool *needs_resize) { struct qht_bucket *b = head; struct qht_bucket *prev = NULL; @@ -523,8 +523,9 @@ static bool qht_insert__locked(struct qht *ht, struct qht_map *map, do { for (i = 0; i < QHT_BUCKET_ENTRIES; i++) { if (b->pointers[i]) { - if (unlikely(b->pointers[i] == p)) { - return false; + if (unlikely(b->hashes[i] == hash && + ht->cmp(b->pointers[i], p))) { + return b->pointers[i]; } } else { goto found; @@ -553,7 +554,7 @@ static bool qht_insert__locked(struct qht *ht, struct qht_map *map, atomic_set(&b->hashes[i], hash); atomic_set(&b->pointers[i], p); seqlock_write_end(&head->sequence); - return true; + return NULL; } static __attribute__((noinline)) void qht_grow_maybe(struct qht *ht) @@ -577,25 +578,31 @@ static __attribute__((noinline)) void qht_grow_maybe(struct qht *ht) qemu_mutex_unlock(&ht->lock); } -bool qht_insert(struct qht *ht, void *p, uint32_t hash) +bool qht_insert(struct qht *ht, void *p, uint32_t hash, void **existing) { struct qht_bucket *b; struct qht_map *map; bool needs_resize = false; - bool ret; + void *prev; /* NULL pointers are not supported */ qht_debug_assert(p); b = qht_bucket_lock__no_stale(ht, hash, &map); - ret = qht_insert__locked(ht, map, b, p, hash, &needs_resize); + prev = qht_insert__locked(ht, map, b, p, hash, &needs_resize); qht_bucket_debug__locked(b); qemu_spin_unlock(&b->lock); if (unlikely(needs_resize) && ht->mode & QHT_MODE_AUTO_RESIZE) { qht_grow_maybe(ht); } - return ret; + if (likely(prev == NULL)) { + return true; + } + if (existing) { + *existing = prev; + } + return false; } static inline bool qht_entry_is_last(struct qht_bucket *b, int pos) From patchwork Thu Jun 14 19:31:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138618 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2528430lji; Thu, 14 Jun 2018 12:40:40 -0700 (PDT) X-Google-Smtp-Source: ADUXVKL8KApO8t/b2X7/ho5xJsxMpRGkjpAOaZe/85O/V5DatBQIGan0KCehmJJhsnTtuwzvh6v7 X-Received: by 2002:a37:b281:: with SMTP id b123-v6mr3272087qkf.377.1529005240046; Thu, 14 Jun 2018 12:40:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005240; cv=none; d=google.com; s=arc-20160816; b=lQE8iyxiajIQVreTEYgI46O5OcIdqrmrWfjztuE+CTkj2oycgGhVgItA6ZsdvuYm8n VBgYTyecoSBXD+5aCncK6Gki9iC45HOgEpA3omPnDdwcwmoA7oajnUYJVUYH0FnvHGRV GJmaxWGI/rN63qpEyI8EC+XB8Xkdd0nYgx46virFXN2sMiH7QC6lZYzId1OsxzAhHb5o bhPE8lSFTtNEy5CW7APzUIaCiI4r94vcpWcxuRv/KF9sv+15J+whznDNY5UPP4vhePmR uR/4eC7EZWeOgkGigBv58dVgCObCSmyrSjUzEFIUvy9kFUdMOA0PMXwrmBUuQnHNfeej Jsvw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=p3L83IwxkkS1bcBe6OYSTJn34sARlD7rJnlui1ECL2U=; b=SB0tK9Ak7HnCYZljmK/WKA/wC9wv3Rf61emDHeOy2va7OvaOSRGVlKYU7Oi0uc5hva 5SIMAr5osTbmmhU8Jk90xhWKUfmbxhO7MnpTp+RUCwtw/g/EBOGMLa2aYg62smHpqAtZ S5hLR/W/tY+wQDCC3WyT7FRDl/GOPSlO0jIqsvyfHX59xFeooMSGUJCzZt3hMr2XiAbR GLISp+9QWH3TkJk2Ln2sjZNVYH2WiXE0/19ypcfwsYwDB+XWs5O1FtvuDCXNPUZ2Nb/g whJuvBnTFYQgktEPwUEtXzGTElpL8CVxrUU3X4E8nUshetJo2joT0Io8Bo7cjA8zAGlt pWig== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=bK2uiZ3o; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id k26-v6si855418qta.218.2018.06.14.12.40.39 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:40:40 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=bK2uiZ3o; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42372 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTY6p-00059Q-BG for patch@linaro.org; Thu, 14 Jun 2018 15:40:39 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36870) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyV-0006ti-HB for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyS-0005ip-WE for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:03 -0400 Received: from mail-pg0-x22f.google.com ([2607:f8b0:400e:c05::22f]:44096) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyS-0005ig-NA for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:00 -0400 Received: by mail-pg0-x22f.google.com with SMTP id p21-v6so3354562pgd.11 for ; Thu, 14 Jun 2018 12:32:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=p3L83IwxkkS1bcBe6OYSTJn34sARlD7rJnlui1ECL2U=; b=bK2uiZ3oYnjGlYsMAIN2mtASMJCLRpWNjF2WThcpSmmittaEq6ZWGlleRkTzd66f0c QE2tdP5Yz5fgl900HUy3GP+zOveWae2a8nZE8EOinxbus6MQTiIAi2rIrh9phgE0v6+O C8x3uGDdLLgdLP0ly2WvZjmsEzqDbd9iZH45g= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=p3L83IwxkkS1bcBe6OYSTJn34sARlD7rJnlui1ECL2U=; b=ZdRijaK0nz8M0vEhtMOqAX/ykxQJIZdANZyhWheQCDEI+rx9BYaaPasTaYOT8jA4Zw bG3/2pbvHJ7fyal+Hgrh6patA/jGfIWgv6SYTEAbo1pniNGox0MxoxQWmPOjNcBng9We UODRW7pbkjsbWucJWXTOo0UqFJz3x4TOYh+UboLlNAOn1RccRGSr+CRQ3nT/GmyUDudg 1jXXG2klKellrpl01gu3ZVbEDPdy+xXchgNpegbLYiWZsbHtqbEx6oMazo1TRAP/jMx4 CBuchj5LwtX+9SiH0oRcnNViOMa5You6iLcJetWSk7p0IfM398fCt/lM+c55FiZ79F2Y JfzQ== X-Gm-Message-State: APt69E3EkvUDCAQBJGVeQin18tG3WAj0ofEi1Mcn5s3m0psjETrwNHJC rfFdRIapRN/NGTqzw/lGckO1vso2sVU= X-Received: by 2002:a62:dc1c:: with SMTP id t28-v6mr10781333pfg.137.1529004719342; Thu, 14 Jun 2018 12:31:59 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.31.57 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:31:58 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:33 -1000 Message-Id: <20180614193147.29680-5-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::22f Subject: [Qemu-devel] [PULL 04/18] tcg: track TBs with per-region BST's 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" This paves the way for enabling scalable parallel generation of TCG code. Instead of tracking TBs with a single binary search tree (BST), use a BST for each TCG region, protecting it with a lock. This is as scalable as it gets, since each TCG thread operates on a separate region. The core of this change is the introduction of struct tcg_region_tree, which contains a pointer to a GTree and an associated lock to serialize accesses to it. We then allocate an array of tcg_region_tree's, adding the appropriate padding to avoid false sharing based on qemu_dcache_linesize. Given a tc_ptr, we first find the corresponding region_tree. This is done by special-casing the first and last regions first, since they might be of size != region.size; otherwise we just divide the offset by region.stride. I was worried about this division (several dozen cycles of latency), but profiling shows that this is not a fast path. Note that region.stride is not required to be a power of two; it is only required to be a multiple of the host's page size. Note that with this design we can also provide consistent snapshots about all region trees at once; for instance, tcg_tb_foreach acquires/releases all region_tree locks before/after iterating over them. For this reason we now drop tb_lock in dump_exec_info(). As an alternative I considered implementing a concurrent BST, but this can be tricky to get right, offers no consistent snapshots of the BST, and performance and scalability-wise I don't think it could ever beat having separate GTrees, given that our workload is insert-mostly (all concurrent BST designs I've seen focus, understandably, on making lookups fast, which comes at the expense of convoluted, non-wait-free insertions/removals). Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- include/exec/exec-all.h | 1 - include/exec/tb-context.h | 1 - tcg/tcg.h | 6 ++ accel/tcg/cpu-exec.c | 2 +- accel/tcg/translate-all.c | 101 +++----------------- tcg/tcg.c | 191 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 213 insertions(+), 89 deletions(-) -- 2.17.1 diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 4d09eaba72..7684f4cb69 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -405,7 +405,6 @@ static inline uint32_t curr_cflags(void) | (use_icount ? CF_USE_ICOUNT : 0); } -void tb_remove(TranslationBlock *tb); void tb_flush(CPUState *cpu); void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr); TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc, diff --git a/include/exec/tb-context.h b/include/exec/tb-context.h index 1d41202485..d8472c88fb 100644 --- a/include/exec/tb-context.h +++ b/include/exec/tb-context.h @@ -31,7 +31,6 @@ typedef struct TBContext TBContext; struct TBContext { - GTree *tb_tree; struct qht htable; /* any access to the tbs or the page table must use this lock */ QemuMutex tb_lock; diff --git a/tcg/tcg.h b/tcg/tcg.h index 509f4d65d2..1e6df1906f 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -866,6 +866,12 @@ void tcg_region_reset_all(void); size_t tcg_code_size(void); size_t tcg_code_capacity(void); +void tcg_tb_insert(TranslationBlock *tb); +void tcg_tb_remove(TranslationBlock *tb); +TranslationBlock *tcg_tb_lookup(uintptr_t tc_ptr); +void tcg_tb_foreach(GTraverseFunc func, gpointer user_data); +size_t tcg_nb_tbs(void); + /* user-mode: Called with tb_lock held. */ static inline void *tcg_malloc(int size) { diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 6d6c51b686..7570c59f09 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -224,7 +224,7 @@ static void cpu_exec_nocache(CPUState *cpu, int max_cycles, tb_lock(); tb_phys_invalidate(tb, -1); - tb_remove(tb); + tcg_tb_remove(tb); tb_unlock(); } #endif diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 1695f8c352..ef841c82cc 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -205,8 +205,6 @@ void tb_lock_reset(void) } } -static TranslationBlock *tb_find_pc(uintptr_t tc_ptr); - void cpu_gen_init(void) { tcg_context_init(&tcg_init_ctx); @@ -375,13 +373,13 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit) if (check_offset < tcg_init_ctx.code_gen_buffer_size) { tb_lock(); - tb = tb_find_pc(host_pc); + tb = tcg_tb_lookup(host_pc); if (tb) { cpu_restore_state_from_tb(cpu, tb, host_pc, will_exit); if (tb->cflags & CF_NOCACHE) { /* one-shot translation, invalidate it immediately */ tb_phys_invalidate(tb, -1); - tb_remove(tb); + tcg_tb_remove(tb); } r = true; } @@ -728,48 +726,6 @@ static inline void *alloc_code_gen_buffer(void) } #endif /* USE_STATIC_CODE_GEN_BUFFER, WIN32, POSIX */ -/* compare a pointer @ptr and a tb_tc @s */ -static int ptr_cmp_tb_tc(const void *ptr, const struct tb_tc *s) -{ - if (ptr >= s->ptr + s->size) { - return 1; - } else if (ptr < s->ptr) { - return -1; - } - return 0; -} - -static gint tb_tc_cmp(gconstpointer ap, gconstpointer bp) -{ - const struct tb_tc *a = ap; - const struct tb_tc *b = bp; - - /* - * When both sizes are set, we know this isn't a lookup. - * This is the most likely case: every TB must be inserted; lookups - * are a lot less frequent. - */ - if (likely(a->size && b->size)) { - if (a->ptr > b->ptr) { - return 1; - } else if (a->ptr < b->ptr) { - return -1; - } - /* a->ptr == b->ptr should happen only on deletions */ - g_assert(a->size == b->size); - return 0; - } - /* - * All lookups have either .size field set to 0. - * From the glib sources we see that @ap is always the lookup key. However - * the docs provide no guarantee, so we just mark this case as likely. - */ - if (likely(a->size == 0)) { - return ptr_cmp_tb_tc(a->ptr, b); - } - return ptr_cmp_tb_tc(b->ptr, a); -} - static inline void code_gen_alloc(size_t tb_size) { tcg_ctx->code_gen_buffer_size = size_code_gen_buffer(tb_size); @@ -778,7 +734,6 @@ static inline void code_gen_alloc(size_t tb_size) fprintf(stderr, "Could not allocate dynamic translator buffer\n"); exit(1); } - tb_ctx.tb_tree = g_tree_new(tb_tc_cmp); qemu_mutex_init(&tb_ctx.tb_lock); } @@ -839,14 +794,6 @@ static TranslationBlock *tb_alloc(target_ulong pc) return tb; } -/* Called with tb_lock held. */ -void tb_remove(TranslationBlock *tb) -{ - assert_tb_locked(); - - g_tree_remove(tb_ctx.tb_tree, &tb->tc); -} - static inline void invalidate_page_bitmap(PageDesc *p) { #ifdef CONFIG_SOFTMMU @@ -911,10 +858,10 @@ static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count) } if (DEBUG_TB_FLUSH_GATE) { - size_t nb_tbs = g_tree_nnodes(tb_ctx.tb_tree); + size_t nb_tbs = tcg_nb_tbs(); size_t host_size = 0; - g_tree_foreach(tb_ctx.tb_tree, tb_host_size_iter, &host_size); + tcg_tb_foreach(tb_host_size_iter, &host_size); printf("qemu: flush code_size=%zu nb_tbs=%zu avg_tb_size=%zu\n", tcg_code_size(), nb_tbs, nb_tbs > 0 ? host_size / nb_tbs : 0); } @@ -923,10 +870,6 @@ static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count) cpu_tb_jmp_cache_clear(cpu); } - /* Increment the refcount first so that destroy acts as a reset */ - g_tree_ref(tb_ctx.tb_tree); - g_tree_destroy(tb_ctx.tb_tree); - qht_reset_size(&tb_ctx.htable, CODE_GEN_HTABLE_SIZE); page_flush_tb(); @@ -1406,7 +1349,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, * through the physical hash table and physical page list. */ tb_link_page(tb, phys_pc, phys_page2); - g_tree_insert(tb_ctx.tb_tree, &tb->tc, tb); + tcg_tb_insert(tb); return tb; } @@ -1510,7 +1453,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, current_tb = NULL; if (cpu->mem_io_pc) { /* now we have a real cpu fault */ - current_tb = tb_find_pc(cpu->mem_io_pc); + current_tb = tcg_tb_lookup(cpu->mem_io_pc); } } if (current_tb == tb && @@ -1627,7 +1570,7 @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc) tb = p->first_tb; #ifdef TARGET_HAS_PRECISE_SMC if (tb && pc != 0) { - current_tb = tb_find_pc(pc); + current_tb = tcg_tb_lookup(pc); } if (cpu != NULL) { env = cpu->env_ptr; @@ -1670,18 +1613,6 @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc) } #endif -/* - * Find the TB 'tb' such that - * tb->tc.ptr <= tc_ptr < tb->tc.ptr + tb->tc.size - * Return NULL if not found. - */ -static TranslationBlock *tb_find_pc(uintptr_t tc_ptr) -{ - struct tb_tc s = { .ptr = (void *)tc_ptr }; - - return g_tree_lookup(tb_ctx.tb_tree, &s); -} - #if !defined(CONFIG_USER_ONLY) void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs) { @@ -1709,7 +1640,7 @@ void tb_check_watchpoint(CPUState *cpu) { TranslationBlock *tb; - tb = tb_find_pc(cpu->mem_io_pc); + tb = tcg_tb_lookup(cpu->mem_io_pc); if (tb) { /* We can use retranslation to find the PC. */ cpu_restore_state_from_tb(cpu, tb, cpu->mem_io_pc, true); @@ -1743,7 +1674,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) uint32_t n; tb_lock(); - tb = tb_find_pc(retaddr); + tb = tcg_tb_lookup(retaddr); if (!tb) { cpu_abort(cpu, "cpu_io_recompile: could not find TB for pc=%p", (void *)retaddr); @@ -1782,7 +1713,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) * cpu_exec_nocache() */ tb_phys_invalidate(tb->orig_tb, -1); } - tb_remove(tb); + tcg_tb_remove(tb); } /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not @@ -1853,6 +1784,7 @@ static void print_qht_statistics(FILE *f, fprintf_function cpu_fprintf, } struct tb_tree_stats { + size_t nb_tbs; size_t host_size; size_t target_size; size_t max_target_size; @@ -1866,6 +1798,7 @@ static gboolean tb_tree_stats_iter(gpointer key, gpointer value, gpointer data) const TranslationBlock *tb = value; struct tb_tree_stats *tst = data; + tst->nb_tbs++; tst->host_size += tb->tc.size; tst->target_size += tb->size; if (tb->size > tst->max_target_size) { @@ -1889,10 +1822,8 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) struct qht_stats hst; size_t nb_tbs; - tb_lock(); - - nb_tbs = g_tree_nnodes(tb_ctx.tb_tree); - g_tree_foreach(tb_ctx.tb_tree, tb_tree_stats_iter, &tst); + tcg_tb_foreach(tb_tree_stats_iter, &tst); + nb_tbs = tst.nb_tbs; /* XXX: avoid using doubles ? */ cpu_fprintf(f, "Translation buffer state:\n"); /* @@ -1927,8 +1858,6 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) cpu_fprintf(f, "TB invalidate count %d\n", tb_ctx.tb_phys_invalidate_count); cpu_fprintf(f, "TLB flush count %zu\n", tlb_flush_count()); tcg_dump_info(f, cpu_fprintf); - - tb_unlock(); } void dump_opcount_info(FILE *f, fprintf_function cpu_fprintf) @@ -2196,7 +2125,7 @@ int page_unprotect(target_ulong address, uintptr_t pc) * set the page to PAGE_WRITE and did the TB invalidate for us. */ #ifdef TARGET_HAS_PRECISE_SMC - TranslationBlock *current_tb = tb_find_pc(pc); + TranslationBlock *current_tb = tcg_tb_lookup(pc); if (current_tb) { current_tb_invalidated = tb_cflags(current_tb) & CF_INVALID; } diff --git a/tcg/tcg.c b/tcg/tcg.c index 6eeebe0624..62e3391020 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -135,6 +135,12 @@ static TCGContext **tcg_ctxs; static unsigned int n_tcg_ctxs; TCGv_env cpu_env = 0; +struct tcg_region_tree { + QemuMutex lock; + GTree *tree; + /* padding to avoid false sharing is computed at run-time */ +}; + /* * We divide code_gen_buffer into equally-sized "regions" that TCG threads * dynamically allocate from as demand dictates. Given appropriate region @@ -158,6 +164,13 @@ struct tcg_region_state { }; static struct tcg_region_state region; +/* + * This is an array of struct tcg_region_tree's, with padding. + * We use void * to simplify the computation of region_trees[i]; each + * struct is found every tree_size bytes. + */ +static void *region_trees; +static size_t tree_size; static TCGRegSet tcg_target_available_regs[TCG_TYPE_COUNT]; static TCGRegSet tcg_target_call_clobber_regs; @@ -295,6 +308,180 @@ TCGLabel *gen_new_label(void) #include "tcg-target.inc.c" +/* compare a pointer @ptr and a tb_tc @s */ +static int ptr_cmp_tb_tc(const void *ptr, const struct tb_tc *s) +{ + if (ptr >= s->ptr + s->size) { + return 1; + } else if (ptr < s->ptr) { + return -1; + } + return 0; +} + +static gint tb_tc_cmp(gconstpointer ap, gconstpointer bp) +{ + const struct tb_tc *a = ap; + const struct tb_tc *b = bp; + + /* + * When both sizes are set, we know this isn't a lookup. + * This is the most likely case: every TB must be inserted; lookups + * are a lot less frequent. + */ + if (likely(a->size && b->size)) { + if (a->ptr > b->ptr) { + return 1; + } else if (a->ptr < b->ptr) { + return -1; + } + /* a->ptr == b->ptr should happen only on deletions */ + g_assert(a->size == b->size); + return 0; + } + /* + * All lookups have either .size field set to 0. + * From the glib sources we see that @ap is always the lookup key. However + * the docs provide no guarantee, so we just mark this case as likely. + */ + if (likely(a->size == 0)) { + return ptr_cmp_tb_tc(a->ptr, b); + } + return ptr_cmp_tb_tc(b->ptr, a); +} + +static void tcg_region_trees_init(void) +{ + size_t i; + + tree_size = ROUND_UP(sizeof(struct tcg_region_tree), qemu_dcache_linesize); + region_trees = qemu_memalign(qemu_dcache_linesize, region.n * tree_size); + for (i = 0; i < region.n; i++) { + struct tcg_region_tree *rt = region_trees + i * tree_size; + + qemu_mutex_init(&rt->lock); + rt->tree = g_tree_new(tb_tc_cmp); + } +} + +static struct tcg_region_tree *tc_ptr_to_region_tree(void *p) +{ + size_t region_idx; + + if (p < region.start_aligned) { + region_idx = 0; + } else { + ptrdiff_t offset = p - region.start_aligned; + + if (offset > region.stride * (region.n - 1)) { + region_idx = region.n - 1; + } else { + region_idx = offset / region.stride; + } + } + return region_trees + region_idx * tree_size; +} + +void tcg_tb_insert(TranslationBlock *tb) +{ + struct tcg_region_tree *rt = tc_ptr_to_region_tree(tb->tc.ptr); + + qemu_mutex_lock(&rt->lock); + g_tree_insert(rt->tree, &tb->tc, tb); + qemu_mutex_unlock(&rt->lock); +} + +void tcg_tb_remove(TranslationBlock *tb) +{ + struct tcg_region_tree *rt = tc_ptr_to_region_tree(tb->tc.ptr); + + qemu_mutex_lock(&rt->lock); + g_tree_remove(rt->tree, &tb->tc); + qemu_mutex_unlock(&rt->lock); +} + +/* + * Find the TB 'tb' such that + * tb->tc.ptr <= tc_ptr < tb->tc.ptr + tb->tc.size + * Return NULL if not found. + */ +TranslationBlock *tcg_tb_lookup(uintptr_t tc_ptr) +{ + struct tcg_region_tree *rt = tc_ptr_to_region_tree((void *)tc_ptr); + TranslationBlock *tb; + struct tb_tc s = { .ptr = (void *)tc_ptr }; + + qemu_mutex_lock(&rt->lock); + tb = g_tree_lookup(rt->tree, &s); + qemu_mutex_unlock(&rt->lock); + return tb; +} + +static void tcg_region_tree_lock_all(void) +{ + size_t i; + + for (i = 0; i < region.n; i++) { + struct tcg_region_tree *rt = region_trees + i * tree_size; + + qemu_mutex_lock(&rt->lock); + } +} + +static void tcg_region_tree_unlock_all(void) +{ + size_t i; + + for (i = 0; i < region.n; i++) { + struct tcg_region_tree *rt = region_trees + i * tree_size; + + qemu_mutex_unlock(&rt->lock); + } +} + +void tcg_tb_foreach(GTraverseFunc func, gpointer user_data) +{ + size_t i; + + tcg_region_tree_lock_all(); + for (i = 0; i < region.n; i++) { + struct tcg_region_tree *rt = region_trees + i * tree_size; + + g_tree_foreach(rt->tree, func, user_data); + } + tcg_region_tree_unlock_all(); +} + +size_t tcg_nb_tbs(void) +{ + size_t nb_tbs = 0; + size_t i; + + tcg_region_tree_lock_all(); + for (i = 0; i < region.n; i++) { + struct tcg_region_tree *rt = region_trees + i * tree_size; + + nb_tbs += g_tree_nnodes(rt->tree); + } + tcg_region_tree_unlock_all(); + return nb_tbs; +} + +static void tcg_region_tree_reset_all(void) +{ + size_t i; + + tcg_region_tree_lock_all(); + for (i = 0; i < region.n; i++) { + struct tcg_region_tree *rt = region_trees + i * tree_size; + + /* Increment the refcount first so that destroy acts as a reset */ + g_tree_ref(rt->tree); + g_tree_destroy(rt->tree); + } + tcg_region_tree_unlock_all(); +} + static void tcg_region_bounds(size_t curr_region, void **pstart, void **pend) { void *start, *end; @@ -380,6 +567,8 @@ void tcg_region_reset_all(void) g_assert(!err); } qemu_mutex_unlock(®ion.lock); + + tcg_region_tree_reset_all(); } #ifdef CONFIG_USER_ONLY @@ -496,6 +685,8 @@ void tcg_region_init(void) g_assert(!rc); } + tcg_region_trees_init(); + /* In user-mode we support only one ctx, so do the initial allocation now */ #ifdef CONFIG_USER_ONLY { From patchwork Thu Jun 14 19:31:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138623 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2532855lji; Thu, 14 Jun 2018 12:45:25 -0700 (PDT) X-Google-Smtp-Source: ADUXVKLqVsQuE2bTsIcSDwLcicwhaML+F5yxYAxZ58tJdPWReZi/3yC7JJ/RvecZtbZVqDh/hon+ X-Received: by 2002:aed:35dc:: with SMTP id d28-v6mr3774702qte.294.1529005525418; Thu, 14 Jun 2018 12:45:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005525; cv=none; d=google.com; s=arc-20160816; b=kme9tgcJ/+CRPHi5wPRClGOyNsb5iVTZIXeuXQvIi7fFASJbbxP/w/bWwAd+1LtVKq dMf+X4Xr3bwRLTnV3e4dNkdPkrl4HPolZX8Bozo2u2WIH+GGBrw04vpSWWtSUJPMvcax jnWRh/W4+gpgQ7/YukiD5uNatomaVfI6OKFzc0W0Ljet8KrAmhCpkjygekc5R+qXXl0K pNDxULhFZyrqKQ5FAV9k/1jbhgteAw05K1Gd4ebDGeTiXgVt9SYi7nncxmUZbV+UkfQE Ho/9Q/TrMlagXEsZnAaeOTlaG7wdziBVvqWvuEvJVWU0QiSSjFd+5+QLTryP+Sao5rS7 TwSA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=jwAP7X29dbyxdynmu1epQ4EzxJvbPBd/BBvpAfZSEjM=; b=WupQOqagLe4jR8J8MNHd7giG42DB1uLYo+YcdlIPeYI5KP/N6zPc6jq9/uC2d1Wkx3 1Fs8k1fzZdOfpWA3wXXXS9rTvH4ra0aKxWfUIz2bBdb2EjAB6hWXAqecmggpyLGfbj07 kjY49pmwSgitZsR5izTb3T17cQmOx0rlJTLQPtk2FTNP9TWmlCWhxtRFgbEKAzsmiwth taN2HduZ9Weo+LZXHU5TrHMN0ZAENlG24LoOTnSdBfWAYz5JSmbyd1lO8gPLzfcIIFYW 48QsMFConq/+DHCj4ExoMJgBvk6BB4v2vFpcZtxJNaFXKfeJ56j6pDPXd1kkNqN4aLkA HBjg== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=SDp1c72h; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id r86-v6si316161qkr.36.2018.06.14.12.45.25 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:45:25 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=SDp1c72h; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42425 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTYBQ-0001DK-Ls for patch@linaro.org; Thu, 14 Jun 2018 15:45:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36868) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyV-0006tf-F2 for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyU-0005jX-FC for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:03 -0400 Received: from mail-pl0-x22f.google.com ([2607:f8b0:400e:c01::22f]:39337) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyU-0005jH-AR for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:02 -0400 Received: by mail-pl0-x22f.google.com with SMTP id f1-v6so4069236plt.6 for ; Thu, 14 Jun 2018 12:32:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=jwAP7X29dbyxdynmu1epQ4EzxJvbPBd/BBvpAfZSEjM=; b=SDp1c72hi8mXwbSgKT6vLNZTvUU4uB++ZaVQzS9+sgWTKmZQfzc398ySxt2w33u4U+ JlEq71o3vShRhUz4vqI+kcSM/gViq2ffD76IGuIPh7nLHEbyPVoChQqzsLXlDXMg/pR1 4dDsacg+EuIbIiH5tjdp1moUJwipt6IZBN3kw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=jwAP7X29dbyxdynmu1epQ4EzxJvbPBd/BBvpAfZSEjM=; b=eeDghj6iIh8+frCVnGWdNMYHcysvks6DDG1ch+4zi2QojQjeCirYxMwc5hBsL2yx12 Z/ze3E67pA8obKLZo/VxlyHTy1cHVp7SZifocjMKWugGUxC+qOds6siug2IOpC1XLGQB a9xO6mLKT1Uzqf9ZtK3HgBpt4ErgovyZxRGDj7/faSOxFThFieRR3LJeSopJSpWV/ZOy Pqaoy2ZQKuKP1M4/zQ3G7Yh4kO83P9H+/qWJjuCIwV/BK4HRZZ3LPEV67vSNZbDdNtVF x5U3UnbufxA5vUyF9Rv+1R3Bdu+Upuh1nhyYeytKZ+5tKEVeHTNwejVe/8/keRdxk4RH oynQ== X-Gm-Message-State: APt69E0Yln380B0hnsJk+2C/i+trtHictTkasEJKUBAyuW/eG2Y1owsm jPTJnfeY+OLemKGdtWY1MbbRtPp29Qs= X-Received: by 2002:a17:902:7e07:: with SMTP id b7-v6mr4459462plm.230.1529004721148; Thu, 14 Jun 2018 12:32:01 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.31.59 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:32:00 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:34 -1000 Message-Id: <20180614193147.29680-6-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::22f Subject: [Qemu-devel] [PULL 05/18] tcg: move tb_ctx.tb_phys_invalidate_count to tcg_ctx 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" Thereby making it per-TCGContext. Once we remove tb_lock, this will avoid an atomic increment every time a TB is invalidated. Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- include/exec/tb-context.h | 1 - tcg/tcg.h | 3 +++ accel/tcg/translate-all.c | 5 +++-- tcg/tcg.c | 14 ++++++++++++++ 4 files changed, 20 insertions(+), 3 deletions(-) -- 2.17.1 diff --git a/include/exec/tb-context.h b/include/exec/tb-context.h index d8472c88fb..8c9b49c98e 100644 --- a/include/exec/tb-context.h +++ b/include/exec/tb-context.h @@ -37,7 +37,6 @@ struct TBContext { /* statistics */ unsigned tb_flush_count; - int tb_phys_invalidate_count; }; extern TBContext tb_ctx; diff --git a/tcg/tcg.h b/tcg/tcg.h index 1e6df1906f..e49b289ba1 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -695,6 +695,8 @@ struct TCGContext { /* Threshold to flush the translated code buffer. */ void *code_gen_highwater; + size_t tb_phys_invalidate_count; + /* Track which vCPU triggers events */ CPUState *cpu; /* *_trans */ @@ -868,6 +870,7 @@ size_t tcg_code_capacity(void); void tcg_tb_insert(TranslationBlock *tb); void tcg_tb_remove(TranslationBlock *tb); +size_t tcg_tb_phys_invalidate_count(void); TranslationBlock *tcg_tb_lookup(uintptr_t tc_ptr); void tcg_tb_foreach(GTraverseFunc func, gpointer user_data); size_t tcg_nb_tbs(void); diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index ef841c82cc..a9f2bfb468 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -1069,7 +1069,8 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) /* suppress any remaining jumps to this TB */ tb_jmp_unlink(tb); - tb_ctx.tb_phys_invalidate_count++; + atomic_set(&tcg_ctx->tb_phys_invalidate_count, + tcg_ctx->tb_phys_invalidate_count + 1); } #ifdef CONFIG_SOFTMMU @@ -1855,7 +1856,7 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) cpu_fprintf(f, "\nStatistics:\n"); cpu_fprintf(f, "TB flush count %u\n", atomic_read(&tb_ctx.tb_flush_count)); - cpu_fprintf(f, "TB invalidate count %d\n", tb_ctx.tb_phys_invalidate_count); + cpu_fprintf(f, "TB invalidate count %zu\n", tcg_tb_phys_invalidate_count()); cpu_fprintf(f, "TLB flush count %zu\n", tlb_flush_count()); tcg_dump_info(f, cpu_fprintf); } diff --git a/tcg/tcg.c b/tcg/tcg.c index 62e3391020..1d1dfd7f7c 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -791,6 +791,20 @@ size_t tcg_code_capacity(void) return capacity; } +size_t tcg_tb_phys_invalidate_count(void) +{ + unsigned int n_ctxs = atomic_read(&n_tcg_ctxs); + unsigned int i; + size_t total = 0; + + for (i = 0; i < n_ctxs; i++) { + const TCGContext *s = atomic_read(&tcg_ctxs[i]); + + total += atomic_read(&s->tb_phys_invalidate_count); + } + return total; +} + /* pool based memory allocation */ void *tcg_malloc_internal(TCGContext *s, int size) { From patchwork Thu Jun 14 19:31:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138617 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2527454lji; Thu, 14 Jun 2018 12:39:36 -0700 (PDT) X-Google-Smtp-Source: ADUXVKLdoQFbPEGPI9xuxrSi9PWb82PZ8PWop3m39w/XyIaO1FGohmCZcXUrxTODyHlc7ijBNirV X-Received: by 2002:a37:34ca:: with SMTP id b193-v6mr3277688qka.435.1529005176328; Thu, 14 Jun 2018 12:39:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005176; cv=none; d=google.com; s=arc-20160816; b=RB2jZTKjxVbT//f4LSSNj2XHHuREGCoN3TQZ9cQqwGbtdnCNBWGl2rPSTMSG9b/oMo AP4U1tsFDSz5TuCWCwXbtoRa2kZzITeRe1Ox3W0OHzHqUFJd9MI4UmSuHRGqwT/+KLAG xfsOC5ApzAW3oVAk/ATy2xBlrFBevahLnbB/5rvAqBWY43oe8+OzfLLPa1HrjSE4VGSN DlSCH2OvdTb2WcJhKw68z85aA/PX1yIno+vq8qfwjYPGXUEZciGhA+swuDs2klXAs2Qs YV141m201iCdsjqZNG4SNgE7BsbSSMMmDG2QvQb6bRMqP026kbJSywhS0NWjRP2RbJai TNcQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=8gYiYUL8lXxTailPJ53NLxVw5b580afFuqReCeuTUJw=; b=aSRRAc/7cv6c9CvZDDRkffehsuKIv+LjP5qtRe1L1/h+O7MAzbYUVEsQH4SagT+gAM ZMMv5rwBjLeQ1Y/qnGbOn025FAkt7Kjfs4C4QUg5gdfEtAg8GCFnpYGQsYRN79FhdKad 7ZNoP6ncM0XSXtlzWYxWeNoHqyzHlUmvbrmis0LUMwK6VcAjjMyiDKqlnUPRJdw3kXxw 7fqpUUPlwgguiWFDZFk0a/0g42X/uX4OSILj/ayY+6KyDyaiP+QALex3akUpf6ZcbpR4 7eYA8LsATFAv9kpduvqjn+OjAgXLqF0yl31V3gkLFOL+T8INVIbFNojWH6stByk9zxuy G3Rw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=Wx3UATVz; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id l5-v6si5879646qvc.98.2018.06.14.12.39.36 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:39:36 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=Wx3UATVz; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42363 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTY5n-00040H-Ly for patch@linaro.org; Thu, 14 Jun 2018 15:39:35 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36935) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyZ-0006wm-Og for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyW-0005kT-FD for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:07 -0400 Received: from mail-pg0-x243.google.com ([2607:f8b0:400e:c05::243]:40792) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyW-0005jz-73 for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:04 -0400 Received: by mail-pg0-x243.google.com with SMTP id w8-v6so330794pgp.7 for ; Thu, 14 Jun 2018 12:32:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8gYiYUL8lXxTailPJ53NLxVw5b580afFuqReCeuTUJw=; b=Wx3UATVzU8m6Ax4jTXq4WbpV6ShCGXiafhoUvyTfSRTMIlWhLQbEeN138zrdjPM49L Cknmhjps+vyFJTVw9Cq21fRh3aWhE3Lqz2iixfzAYYh1nkEIBZeayEmEe5MTJrXi1rkI ocMEUG4MOPnd+mQrBFO+KbSLswvXPBpUqfRCc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=8gYiYUL8lXxTailPJ53NLxVw5b580afFuqReCeuTUJw=; b=R/DdTKHI2e5cLm8NkORej7NPMaW7RahyHsvYcqIBLoxVsH2esyN0uJuC07eecVxiYf kZa9Kalty88BH1w5qTiElrB0jolqE14BhX9ye+tC9A2OqNZoDSUrDuf8vzLnW7La7AVN dQX1lL15uANU9fptSTEYQeVWBADGVLg04KZ+Vd1kJWnMmnZtLoWqrO3UfXch6ec0mIK2 pOgb9jxW9PVCaXz110o4tI5P8F0DWjuo5CioPw+kHcZsbAZOo8mIl8ConVvceZOPQWFY ctk2i+sXFyyZLECUAW5on5b+hcrC7n4Cg3zUIxcckktJcVV45uJ+3QTSLS+DkopSZT47 WrkQ== X-Gm-Message-State: APt69E2LYDXk8i/AfWwQUTEdtYQ3LUGwLZ69+1X3fsYgsN1uf6jWAAhm XfOfmjcfFru+CS2K43BJfF5p0ZT/Ovk= X-Received: by 2002:a62:968f:: with SMTP id s15-v6mr10792598pfk.191.1529004722926; Thu, 14 Jun 2018 12:32:02 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.32.01 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:32:02 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:35 -1000 Message-Id: <20180614193147.29680-7-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::243 Subject: [Qemu-devel] [PULL 06/18] 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" 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. Note that TB_FOR_EACH_TAGGED will gain another user in a subsequent patch. - 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(). Reviewed-by: Richard Henderson Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- include/exec/exec-all.h | 2 +- accel/tcg/translate-all.c | 62 ++++++++++++++++++--------------------- 2 files changed, 30 insertions(+), 34 deletions(-) -- 2.17.1 diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 7684f4cb69..54a3398374 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -360,7 +360,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]; /* The following data are used to directly call another TB from diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index a9f2bfb468..52e62125ed 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -103,7 +103,7 @@ 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,15 @@ typedef struct PageDesc { #endif } PageDesc; +/* list iterators for lists of tagged pointers in TranslationBlock */ +#define TB_FOR_EACH_TAGGED(head, tb, n, field) \ + for (n = (head) & 1, tb = (TranslationBlock *)((head) & ~1); \ + tb; tb = (TranslationBlock *)tb->field[n], n = (uintptr_t)tb & 1, \ + tb = (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) @@ -815,7 +824,7 @@ static void page_flush_tb_1(int level, void **lp) PageDesc *pd = *lp; for (i = 0; i < V_L2_SIZE; ++i) { - pd[i].first_tb = NULL; + pd[i].first_tb = (uintptr_t)NULL; invalidate_page_bitmap(pd + i); } } else { @@ -943,21 +952,21 @@ static void tb_page_check(void) #endif /* CONFIG_USER_ONLY */ -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; - for (;;) { - tb1 = *ptb; - n1 = (uintptr_t)tb1 & 3; - tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); + pprev = &pd->first_tb; + PAGE_FOR_EACH_TB(pd, tb1, n1) { if (tb1 == tb) { - *ptb = tb1->page_next[n1]; - break; + *pprev = tb1->page_next[n1]; + return; } - ptb = &tb1->page_next[n1]; + pprev = &tb1->page_next[n1]; } + g_assert_not_reached(); } /* remove the TB from a list of TBs jumping to the n-th jump target of the TB */ @@ -1045,12 +1054,12 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) /* remove the TB from the page list */ if (tb->page_addr[0] != page_addr) { p = 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] != -1 && tb->page_addr[1] != page_addr) { p = 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); } @@ -1081,10 +1090,7 @@ static void build_page_bitmap(PageDesc *p) p->code_bitmap = bitmap_new(TARGET_PAGE_SIZE); - tb = p->first_tb; - while (tb != NULL) { - n = (uintptr_t)tb & 3; - tb = (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 == 0) { /* NOTE: tb_end may be after the end of the page, but @@ -1099,7 +1105,6 @@ static void build_page_bitmap(PageDesc *p) tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK); } bitmap_set(p->code_bitmap, tb_start, tb_end - tb_start); - tb = tb->page_next[n]; } } #endif @@ -1122,9 +1127,9 @@ static inline void tb_alloc_page(TranslationBlock *tb, p = page_find_alloc(page_addr >> TARGET_PAGE_BITS, 1); tb->page_next[n] = p->first_tb; #ifndef CONFIG_USER_ONLY - page_already_protected = p->first_tb != NULL; + page_already_protected = p->first_tb != (uintptr_t)NULL; #endif - p->first_tb = (TranslationBlock *)((uintptr_t)tb | n); + p->first_tb = (uintptr_t)tb | n; invalidate_page_bitmap(p); #if defined(CONFIG_USER_ONLY) @@ -1401,7 +1406,7 @@ void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end) void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, int is_cpu_write_access) { - TranslationBlock *tb, *tb_next; + TranslationBlock *tb; tb_page_addr_t tb_start, tb_end; PageDesc *p; int n; @@ -1432,11 +1437,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, 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 = p->first_tb; - while (tb != NULL) { - n = (uintptr_t)tb & 3; - tb = (TranslationBlock *)((uintptr_t)tb & ~3); - tb_next = 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 == 0) { /* NOTE: tb_end may be after the end of the page, but @@ -1474,7 +1475,6 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, #endif /* TARGET_HAS_PRECISE_SMC */ tb_phys_invalidate(tb, -1); } - tb = tb_next; } #if !defined(CONFIG_USER_ONLY) /* if no code remaining, no need to continue to use slow writes */ @@ -1568,18 +1568,15 @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc) } tb_lock(); - tb = p->first_tb; #ifdef TARGET_HAS_PRECISE_SMC - if (tb && pc != 0) { + if (p->first_tb && pc != 0) { current_tb = tcg_tb_lookup(pc); } if (cpu != NULL) { env = cpu->env_ptr; } #endif - while (tb != NULL) { - n = (uintptr_t)tb & 3; - tb = (TranslationBlock *)((uintptr_t)tb & ~3); + PAGE_FOR_EACH_TB(p, tb, n) { #ifdef TARGET_HAS_PRECISE_SMC if (current_tb == tb && (current_tb->cflags & CF_COUNT_MASK) != 1) { @@ -1596,9 +1593,8 @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc) } #endif /* TARGET_HAS_PRECISE_SMC */ tb_phys_invalidate(tb, addr); - tb = tb->page_next[n]; } - p->first_tb = NULL; + p->first_tb = (uintptr_t)NULL; #ifdef TARGET_HAS_PRECISE_SMC if (current_tb_modified) { /* Force execution of one insn next time. */ From patchwork Thu Jun 14 19:31:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138619 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2528480lji; Thu, 14 Jun 2018 12:40:43 -0700 (PDT) X-Google-Smtp-Source: ADUXVKLmtUfrbd0ZBivEZVOeVCQg8D6EatXhADUTEEuUP8s5Xl9cmadqMUhub43cIdBUm09N6y2f X-Received: by 2002:a0c:b297:: with SMTP id r23-v6mr3708775qve.74.1529005243655; Thu, 14 Jun 2018 12:40:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005243; cv=none; d=google.com; s=arc-20160816; b=nrC5CYPLTJD3Zn+r2gt+khnzEuXpnHdLNP3h0UWqDW3diNXvv6Fg9jlcCjxIMNvJ9g EsBr9vZFV9tCEAnit19hpsORQGJB6/+p3W+bPuqhw0VOdl0Xm0sWb8iNXT6PEBR9SXOx ytknDhGjxpcq/vL9kPBJchIq+tLOYuKnw+c8VniOdNkl+DiDeRZlHeTqiqU7wjAhHqri IUQkWG36ayOnAUHU0v0pvYpEvEo5lMPP1lgksOxFw2ye9v3ihd6KsBK6EYLEQUHrEv0W /CpF8m3TB4vfnGM5FNsJw5Qg6g8DReZ+AwqT0JuVYQ8N4gsK2C4ws78uTKAZ/0wDM3tz 2H7A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=+wmxg/OG714qNbfIRNlSF9jWomNEICTIUlUkDChX+hI=; b=ysyFJl0D3R0Ia8FUeXmF+dWhVqMK5ODQjJpUGWYpfZORnkssbqSuTb85n6MbflveWw 0c5EXxGUE8kpQxP575Ch/Jptv9pjGevxf6WEOFzBgd0gY0gDdbEjO8Q3Qureoja8WrRY ce5Nqdsom0MoO3Yj5LTG3mwMmn2ZQoTClbc5coS4BawhkF4ekOJWB9dmxoT97TYn2hnX hyhNhafq9hy+gCAdDuWasELxE0KVTdLcsqmHcSgh1zzg0YYUp3yddFF1Esp0sL+yLkDe 223ePtYA23yLZAXstGJRXYrdj6DdRmFMhzHaMnlrxlER33Z6mQS8mQjglNq/UzSZ+LWz aafg== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=buHVfDEC; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id t67-v6si1202936qkd.147.2018.06.14.12.40.43 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:40:43 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=buHVfDEC; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42373 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTY6s-0005FC-Uc for patch@linaro.org; Thu, 14 Jun 2018 15:40:43 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36934) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyZ-0006wl-OO for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyY-0005n5-4U for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:07 -0400 Received: from mail-pf0-x242.google.com ([2607:f8b0:400e:c00::242]:41796) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyX-0005lj-VA for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:06 -0400 Received: by mail-pf0-x242.google.com with SMTP id a11-v6so3706183pff.8 for ; Thu, 14 Jun 2018 12:32:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+wmxg/OG714qNbfIRNlSF9jWomNEICTIUlUkDChX+hI=; b=buHVfDECFOZOri8UOzBkKinkOOgjycG79VfIiaQQezinfx69+t7nLKpj4MmBJUcrzl rngYq16uVzhK3ykJ1171SGp+T3R8htTIrvC1ILXPLI+vgTwu0ke0vVM37mciM1H9BbYs BRVtuxObQVwmY80MTEXq+/AQIQrH/YzC4HcMM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+wmxg/OG714qNbfIRNlSF9jWomNEICTIUlUkDChX+hI=; b=LZH0ijmOhHQdbeQ/BP2UVwjC5oX3M/EbUNeD6RPaTIz9w9MwGzYzKqyfYNGt/EgJQb a9aQggYkHu1oNqgtZ4t3W9nYnirbuF4FxhMCqf9YcK3CTy3X3jG1y5VM8/QgjnKkINls Ebwt6H50sWJWBCuZzG3z4f794msRaF1iEM1/0PT6qr9GuyEnltsahuRuOYBsa7OR+hTK 2QS/renRd4OQ5M0E00HKK9ZDdDLbLT15ryPhZ9eQ65Ni2olViigGHAOuNs7MAJV0CHHc dV+KZKOtngGVGWbxjiGphFyVn0TuH/I40dUvGqMrsO1uaQR7IW9y1QZA+wdq+2A5HLTc ouug== X-Gm-Message-State: APt69E0unp1M5Y/W95fIXcMMpXpFMHPq0CK96a0AO3mYBR1Xxy9uf8JA oxvOwwJ8/hcjro3uAK7ToZEQ0f95M6A= X-Received: by 2002:a63:a44a:: with SMTP id c10-v6mr3378721pgp.198.1529004724721; Thu, 14 Jun 2018 12:32:04 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.32.03 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:32:03 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:36 -1000 Message-Id: <20180614193147.29680-8-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::242 Subject: [Qemu-devel] [PULL 07/18] translate-all: make l1_map lockless 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" Groundwork for supporting parallel TCG generation. We never remove entries from the radix tree, so we can use cmpxchg to implement lockless insertions. Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- accel/tcg/translate-all.c | 24 ++++++++++++++---------- docs/devel/multi-thread-tcg.txt | 4 ++-- 2 files changed, 16 insertions(+), 12 deletions(-) -- 2.17.1 diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 52e62125ed..52273e5846 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -469,20 +469,12 @@ static void page_init(void) #endif } -/* If alloc=1: - * Called with tb_lock held for system emulation. - * Called with mmap_lock held for user-mode emulation. - */ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc) { PageDesc *pd; void **lp; int i; - if (alloc) { - assert_memory_lock(); - } - /* Level 1. Always allocated. */ lp = l1_map + ((index >> v_l1_shift) & (v_l1_size - 1)); @@ -491,11 +483,17 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc) void **p = atomic_rcu_read(lp); if (p == NULL) { + void *existing; + if (!alloc) { return NULL; } p = g_new0(void *, V_L2_SIZE); - atomic_rcu_set(lp, p); + existing = atomic_cmpxchg(lp, NULL, p); + if (unlikely(existing)) { + g_free(p); + p = existing; + } } lp = p + ((index >> (i * V_L2_BITS)) & (V_L2_SIZE - 1)); @@ -503,11 +501,17 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc) pd = atomic_rcu_read(lp); if (pd == NULL) { + void *existing; + if (!alloc) { return NULL; } pd = g_new0(PageDesc, V_L2_SIZE); - atomic_rcu_set(lp, pd); + existing = atomic_cmpxchg(lp, NULL, pd); + if (unlikely(existing)) { + g_free(pd); + pd = existing; + } } return pd + (index & (V_L2_SIZE - 1)); diff --git a/docs/devel/multi-thread-tcg.txt b/docs/devel/multi-thread-tcg.txt index a99b4564c6..faf8918b23 100644 --- a/docs/devel/multi-thread-tcg.txt +++ b/docs/devel/multi-thread-tcg.txt @@ -134,8 +134,8 @@ tb_set_jmp_target() code. Modification to the linked lists that allow searching for linked pages are done under the protect of the tb_lock(). -The global page table is protected by the tb_lock() in system-mode and -mmap_lock() in linux-user mode. +The global page table is a lockless radix tree; cmpxchg is used +to atomically insert new elements. The lookup caches are updated atomically and the lookup hash uses QHT which is designed for concurrent safe lookup. From patchwork Thu Jun 14 19:31:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138622 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2531117lji; Thu, 14 Jun 2018 12:43:31 -0700 (PDT) X-Google-Smtp-Source: ADUXVKLVbn4eaqn9Oh2v/khJn5IdJY/HYOXz5imBrjZ3UuWVVHrfi/zsD1uUYKfTcY6c17fAnXlU X-Received: by 2002:a37:70c1:: with SMTP id l184-v6mr3603566qkc.86.1529005411416; Thu, 14 Jun 2018 12:43:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005411; cv=none; d=google.com; s=arc-20160816; b=mNo8VQ6GFQPtYDPco+7LF5LuRZjGswajTbeFRTl/vLAClOOmHZ8ZrAQ9jhjtKl1pHO U5Tj3ilctxqWCgZWEmN1MhXJz/xXf3IU9v6ZvmISckqbppukuT12IRKsTGt8Tq7IRIWK kVKgYAW11StrRXaAvhcHqpdv0JYtEmNUVkMzlIdF4mZrtz/wt+VGJJ1FzwqpGF1tNrqD 86PXeuKOC3AIEZ/Zz2xrh5OjVojX/GwdA7ls95RuEb4nmr/HgA9XZVWhgBBjSG4WbWNF kK+aT6yR0Pdsw/WwIC/VXJEjtjwCUqLQcVAuRBZH7zA3uFu7IYp6sEzj777ya9P4qYE6 D3jQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=PUl84RGj2OqEjV3sjRt0a3dQMiShyLF4sGf17shcl8g=; b=vhhCNFUqrJDXKlnB2/tWEh+9IvcZVtU+KoT4maOtE/VUDp4mctfZKO/eDQXrJlTmss dQ8KxKi1cXA3H5qLY3cd3HFXfQjTEunRlw9UmZGLI3pjuZ1ApiEjOAndBjLKOeAmFluS kcHyJAFzfPZBtwi/inuGKdphI40GxodDQtHw/2s4YK0Dx2uCrGRCdp4/U/caEiBL9fqy wYBhIOnx0EPTUljNOYTdETbfTNxkA6MGX+S1QmLwYEeBquDq7mMnjgiVnO3U6IqE2QOk hehltiTeukTLYjM0Pm0uDlLTz8DZt6yGowj5EXY0FEvw/nqwcglQjB9juAL/9gtQ8eqT H/3Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b="FpYk/q4p"; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id v81-v6si6038438qkv.189.2018.06.14.12.43.31 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:43:31 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b="FpYk/q4p"; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42387 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTY9a-0007dw-RE for patch@linaro.org; Thu, 14 Jun 2018 15:43:30 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37006) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXye-00073A-IK for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyZ-0005nr-Sz for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:12 -0400 Received: from mail-pf0-x242.google.com ([2607:f8b0:400e:c00::242]:46353) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyZ-0005nW-Lq for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:07 -0400 Received: by mail-pf0-x242.google.com with SMTP id q1-v6so3709732pff.13 for ; Thu, 14 Jun 2018 12:32:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=PUl84RGj2OqEjV3sjRt0a3dQMiShyLF4sGf17shcl8g=; b=FpYk/q4pUXIjZ3I4q6+wgyEqt49MjHvh+jJL6kcJIUBKuTaXoJnB7rBdM28iOkqyZZ DzHPyagl57zebOSjVBb6Vyh/aefUUWUZgsA1tUFuu/E65sC/JGcutflz4Lj5Il26pbGQ Bodq5AeYSF2C0uBSsrx3WrBUYJLofr+LXxYsM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=PUl84RGj2OqEjV3sjRt0a3dQMiShyLF4sGf17shcl8g=; b=iFKLvFa+boeGYL1JaNSnju6FqeiWea1EvebAzEV2sBgB8lVFPGD+DZ3Ocd3TzWjsIK 3ZqZBRsNkdPkadHHAm0Qe7ZnHbY4LTUyaYymEU+mTjt0QLZvOHyqn2FcBQCqg0JTPqGI zI3t/j7TDF1Tr8Nt4ImNYWClvOP5NJxSK3hUQ6dcEYnwz6h9DtUBv+zSznTWwGIAPZcW nmex7jwlcQrwQNtl0LEKbg8+g5FfW/2RKfsniUzLtr6fOUmvAvJPdfGipLTZHuZaBH8y f9G5nBnpRrsOuEhHccKdZpH3JNRL2PAN6drct/0jNxb6EivbfnPEoWvtP5f5u9O9pJCy ZlgA== X-Gm-Message-State: APt69E3sJNVIklw9z3+4phHtcySQnyBOC9tVSqWmSyk0voQPvW9/1Qzn oO9A1/Eo3h+2oS6fNiXGqhLTr1e11Wk= X-Received: by 2002:a62:3d05:: with SMTP id k5-v6mr10792186pfa.122.1529004726530; Thu, 14 Jun 2018 12:32:06 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.32.04 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:32:05 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:37 -1000 Message-Id: <20180614193147.29680-9-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::242 Subject: [Qemu-devel] [PULL 08/18] translate-all: remove hole in PageDesc 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" Groundwork for supporting parallel TCG generation. Move the hole to the end of the struct, so that a u32 field can be added there without bloating the struct. Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- accel/tcg/translate-all.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -- 2.17.1 diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 52273e5846..b9c36a3e45 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -107,8 +107,8 @@ typedef struct PageDesc { #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 */ - unsigned int code_write_count; unsigned long *code_bitmap; + unsigned int code_write_count; #else unsigned long flags; #endif From patchwork Thu Jun 14 19:31:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138621 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2529428lji; Thu, 14 Jun 2018 12:41:42 -0700 (PDT) X-Google-Smtp-Source: ADUXVKLv99MarU3e6nSLprqh05IVRUgiUaeBGr1g5NHB9iwh+8/ADcP05h1Hnmk5NVcTIXopxdWR X-Received: by 2002:a37:ba47:: with SMTP id k68-v6mr3431512qkf.105.1529005302833; Thu, 14 Jun 2018 12:41:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005302; cv=none; d=google.com; s=arc-20160816; b=DxD2xGwL/rCprddBqugviEffsflDSFxyGbsM2+RDF2KrHVcEvHYd+uLkR3tR5/hRra lraCnoRNpA2mZ7ZnimYzb0M66Ijtu23yX2h2xE0qWOM9TYBuqNCifmRnB5FMCZR5wuOC 82/FiKarUlK/wHioLt8H6AVs1Hm4tssrSjPIWAQUX1u0t6TSteQF+KNXmBSgILhdm1ei Aj88tFpSCU/YJ4W16LO1k55HHVpOVA4edIhMdcP4hGCEqTl5TGgyHaqhJpBH7c2agsX3 XwG4wuZabodm/bYYQHLgsfpuqdS8j2fwwXCJB12+dMWsVNfFqvhuWUQdlr7jEIUeygjh CErA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=Wexsdf6RCRL9p3KT+WfakrG7waRhQx2Db6LZYDP544g=; b=K5M457Fpk0ASJWYJ9esshut0Qeo+01CqW1AFKzaugV67TRv/Vecil9qG1RPSvRjaJi 8sjMnDTtDG9FOwpPh+Pt7ha0KYR7VSrPXGmXKxkadF7oyKXf7bhw3Pj7MGN+Mrj6fwPp fjaSBxhHhQdZV1ne32iU+U6f6pMMQT18ZIR1cdyljDRa8PZ2EbK2DI064QdXSxlyUzJH nhp3PjMaK1C41uZdghFoKxZNnGZuZfBxfPmd7v5dthL1YQLDqH7sPY9Ft6Nf6bcyHN1E R4NPkJzZ5fzeqzOjoBR1Uz1BpPM86bardr4NFwfYucFJJwSK15k0VOvZUEASZUeCI4cM OhnQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b="a9np+/ix"; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id k1-v6si2369356qtk.400.2018.06.14.12.41.42 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:41:42 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b="a9np+/ix"; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42376 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTY7q-00062v-6J for patch@linaro.org; Thu, 14 Jun 2018 15:41:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36975) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyd-00071B-1o for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyb-0005pU-Tc for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:10 -0400 Received: from mail-pg0-x232.google.com ([2607:f8b0:400e:c05::232]:44099) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyb-0005ol-NG for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:09 -0400 Received: by mail-pg0-x232.google.com with SMTP id p21-v6so3354716pgd.11 for ; Thu, 14 Jun 2018 12:32:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Wexsdf6RCRL9p3KT+WfakrG7waRhQx2Db6LZYDP544g=; b=a9np+/ixxS+/jL4/AphXpNTu7XSPCqNuE+JT0rbqg9vJvpIzPcmkMwg8ANaWTksXyt 3/6t5L1d4u4QaU+FRXwb9uKh88UqVgmGV9EABKXk+FCbp57HwrClsRhUdaAmjVcFkK4X /NVZw68ivbZsKeyJgZRbXCpc1S7zmwKEk3MGU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Wexsdf6RCRL9p3KT+WfakrG7waRhQx2Db6LZYDP544g=; b=U82Bke+fU6S5bKrc3QMk1vv2HsDa/NT48OzQS+t+RcNU2p8HKIJn7F6az0+9e4npKt 6xZDZDL9/Q0R6N6ixzob6eODIDUpCzyXoL9Hpb8bbHFVeYvLWEALgKaJNtqq7PhOwRgQ dEtO6FBKkHsclkEW97OwhYtEkXVci2fho5rnsTLKs26iDLLvDxXmlsXBfZqCv5y9B3fp R+PoNXq0l+icoewTDkQH25BIbOsEdRfe9hIW40cK6YWvhzw8Uebu4wb0gIhMJ1V9d4AP 7X72RAysONTzRwBDwmm1PaAkIHjRbLZ87pIHiNj5gsk9Bo61qfs828GN99MSh8y4lH6P cbAA== X-Gm-Message-State: APt69E0AEgMarMfnhBuhijFg+g5Ylx1e7xKKd6jjaHAViWgp/XFfKekI CuUOq0OoEZhshvH5Wq2lsSRAhvL1hpE= X-Received: by 2002:a62:c8a:: with SMTP id 10-v6mr10749076pfm.27.1529004728406; Thu, 14 Jun 2018 12:32:08 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.32.06 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:32:07 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:38 -1000 Message-Id: <20180614193147.29680-10-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::232 Subject: [Qemu-devel] [PULL 09/18] translate-all: work page-by-page in tb_invalidate_phys_range_1 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" So that we pass a same-page range to tb_invalidate_phys_page_range, instead of always passing an end address that could be on a different page. As discussed with Peter Maydell on the list [1], tb_invalidate_phys_page_range doesn't actually do much with 'end', which explains why we have never hit a bug despite going against what the comment on top of tb_invalidate_phys_page_range requires: > * Invalidate all TBs which intersect with the target physical address range > * [start;end[. NOTE: start and end must refer to the *same* physical page. The appended honours the comment, which avoids confusion. While at it, rework the loop into a for loop, which is less error prone (e.g. "continue" won't result in an infinite loop). [1] https://lists.gnu.org/archive/html/qemu-devel/2017-07/msg09165.html Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- accel/tcg/translate-all.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) -- 2.17.1 diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index b9c36a3e45..f32904d4a3 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -1375,10 +1375,14 @@ TranslationBlock *tb_gen_code(CPUState *cpu, */ static void tb_invalidate_phys_range_1(tb_page_addr_t start, tb_page_addr_t end) { - while (start < end) { - tb_invalidate_phys_page_range(start, end, 0); - start &= TARGET_PAGE_MASK; - start += TARGET_PAGE_SIZE; + tb_page_addr_t next; + + for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + start < end; + start = next, next += TARGET_PAGE_SIZE) { + tb_page_addr_t bound = MIN(next, end); + + tb_invalidate_phys_page_range(start, bound, 0); } } From patchwork Thu Jun 14 19:31:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138624 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2533168lji; Thu, 14 Jun 2018 12:45:46 -0700 (PDT) X-Google-Smtp-Source: ADUXVKI/azd6RCIbFOVFMXkHLFYzDrNMnruGWcj+H5lHQJ3vcEOhk3qDqO9rHS6PdKFwaEev/PAE X-Received: by 2002:ac8:5053:: with SMTP id h19-v6mr3778279qtm.71.1529005546266; Thu, 14 Jun 2018 12:45:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005546; cv=none; d=google.com; s=arc-20160816; b=t7LC2ljke0D1FRkRocnjjyiDoeF3LZLrO4nSfjiRB4h651tnioU5OeOSKUcMTbMUSz rzJ/V+tnL4RbXnujArrTqagyIoyRhE0msKP26q0uvTgmXi5a2ZPu4P8UKxLsYxtsD8ON pc5YTBFN+E848JLgbRR41LyrSEMzRp4z0Ztaw1Gcc9KKnFf2LyIPnlcbUFz171bV1UaF Dr9nJjBO+LmziEcani+QeO40n+xYBtECM0QFHCBeDKRehumyf6aGPnfLjOyf6s90SCjL WdZDxRAmmHtrcQ0mEtzlTDRMPmY6fXzDqIf0AKVjjq3a6ng7a0djK7ljmRaYd1cw7q+/ /ixg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=ShUlIMM0KTqpBxnqZKpmUtzBtiivBcjvXZG919nAn2g=; b=QI89SuPHH21pQcrGH+AfHlhpj7DoGFtMPQ2gFexiXuTIApBC4Z/MAYUeS3K+E73yvs UcF2h8mf58vqGzfRAO//VYPGzF+WFpxXnvBsoOdN8tO8BeYYlb1STL49+Hz4YwrXO4P1 XTDdXSNPotFE5ynXMa4BQCWqMVpqG+405QavETVKE84o/eT09HmDVFX7pU+PkdhP/a/4 kmK6QFEjKd95IhmcazKW4QSrY5NPmbHECnkXddBtuEbOV6Tw/LecJDaQwE0bKB1Pt41Y iU2ETHzZQfkRFQqOdqcISw49Fb8lRAX22yz7kLAuoMcj4q1phVonVAd/Xxb85WT3R7Ri z87A== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=Vmm1aTns; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id w10-v6si5934075qtk.365.2018.06.14.12.45.46 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:45:46 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=Vmm1aTns; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42427 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTYBl-0001F9-Ic for patch@linaro.org; Thu, 14 Jun 2018 15:45:45 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37012) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXye-00073a-S0 for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyd-0005r6-MF for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:12 -0400 Received: from mail-pg0-x242.google.com ([2607:f8b0:400e:c05::242]:41585) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyd-0005qH-GC for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:11 -0400 Received: by mail-pg0-x242.google.com with SMTP id l65-v6so3358462pgl.8 for ; Thu, 14 Jun 2018 12:32:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ShUlIMM0KTqpBxnqZKpmUtzBtiivBcjvXZG919nAn2g=; b=Vmm1aTnset9s3Wl/YXS4ex7cbli8V/lh+RHlFnRoMl2QE0mejugK2HndAnwNZaxghb E1L4Ooo49+0uZ4eg70TaChkOsA15HiCTP3khzbdtDgekYfm1HVOKR4UCauCAxZIGXERj II3vXSYJuVqEUrA/bE0Oetk/6P/SJTv/1yDgI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ShUlIMM0KTqpBxnqZKpmUtzBtiivBcjvXZG919nAn2g=; b=hsaPG0lzsmKv4NoV/PUA+u3dUJ2eSWU87HzcVJFTZwBMbYXYVWvHlvUQDRTq3Lebcl BtvyfPmjcSynNTkWcWofc2LMz5fsPfNbIBfc931igAkccN5jaXtqprqLl76uDbUW1VwE nqBDWIZqAPbXeNlSc1sg4D8bqTSl+E5r+xzrKR4L+mHvZqGFGBbjY6k3F5pP/h3D82EL IUKDABAINLxsiavLgw+wBGoMswqV7RlRAz9wP3lT/4WDzloWcvNlcc6x7LJ+yT0dNMeD zXtDPrFGmqWUnKqII6lZQUONYtZtGsv+IP0sdAgyfI51ICR6VqJZgydr84alrMDaiHvB O74g== X-Gm-Message-State: APt69E1y7ZBQgQIwhJ96fs/Peov5CnqNHSNXfw6RXARDknhvoLBUG9Hv HE+gO0sRPhwCa/DiWdd6KEbn9TwM6fM= X-Received: by 2002:a62:2044:: with SMTP id g65-v6mr10832022pfg.40.1529004730256; Thu, 14 Jun 2018 12:32:10 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.32.08 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:32:09 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:39 -1000 Message-Id: <20180614193147.29680-11-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::242 Subject: [Qemu-devel] [PULL 10/18] translate-all: move tb_invalidate_phys_page_range up in the file 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" This greatly simplifies next commit's diff. Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- accel/tcg/translate-all.c | 77 ++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 38 deletions(-) -- 2.17.1 diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index f32904d4a3..83bb40fb20 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -1363,44 +1363,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu, return tb; } -/* - * Invalidate all TBs which intersect with the target physical address range - * [start;end[. NOTE: start and end may refer to *different* physical pages. - * 'is_cpu_write_access' should be true if called from a real cpu write - * access: the virtual CPU will exit the current TB if code is modified inside - * this TB. - * - * Called with mmap_lock held for user-mode emulation, grabs tb_lock - * Called with tb_lock held for system-mode emulation - */ -static void tb_invalidate_phys_range_1(tb_page_addr_t start, tb_page_addr_t end) -{ - tb_page_addr_t next; - - for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - start < end; - start = next, next += TARGET_PAGE_SIZE) { - tb_page_addr_t bound = MIN(next, end); - - tb_invalidate_phys_page_range(start, bound, 0); - } -} - -#ifdef CONFIG_SOFTMMU -void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end) -{ - assert_tb_locked(); - tb_invalidate_phys_range_1(start, end); -} -#else -void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end) -{ - assert_memory_lock(); - tb_lock(); - tb_invalidate_phys_range_1(start, end); - tb_unlock(); -} -#endif /* * Invalidate all TBs which intersect with the target physical address range * [start;end[. NOTE: start and end must refer to the *same* physical page. @@ -1500,6 +1462,45 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, #endif } +/* + * Invalidate all TBs which intersect with the target physical address range + * [start;end[. NOTE: start and end may refer to *different* physical pages. + * 'is_cpu_write_access' should be true if called from a real cpu write + * access: the virtual CPU will exit the current TB if code is modified inside + * this TB. + * + * Called with mmap_lock held for user-mode emulation, grabs tb_lock + * Called with tb_lock held for system-mode emulation + */ +static void tb_invalidate_phys_range_1(tb_page_addr_t start, tb_page_addr_t end) +{ + tb_page_addr_t next; + + for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + start < end; + start = next, next += TARGET_PAGE_SIZE) { + tb_page_addr_t bound = MIN(next, end); + + tb_invalidate_phys_page_range(start, bound, 0); + } +} + +#ifdef CONFIG_SOFTMMU +void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end) +{ + assert_tb_locked(); + tb_invalidate_phys_range_1(start, end); +} +#else +void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end) +{ + assert_memory_lock(); + tb_lock(); + tb_invalidate_phys_range_1(start, end); + tb_unlock(); +} +#endif + #ifdef CONFIG_SOFTMMU /* len must be <= 8 and start must be a multiple of len. * Called via softmmu_template.h when code areas are written to with From patchwork Thu Jun 14 19:31:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138626 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2533632lji; Thu, 14 Jun 2018 12:46:12 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJkMigH6y1QQau6gUvbqKYI0IvEn+eJ/1ULzrlDidECDB9Mh1s5yspyHr6mEIrGx5lHZ9Fp X-Received: by 2002:a37:2b66:: with SMTP id r99-v6mr3538895qkh.286.1529005572649; Thu, 14 Jun 2018 12:46:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005572; cv=none; d=google.com; s=arc-20160816; b=aiNJqV8WputbWZ1devGoEnvdYHebYtGl4Fpm4Iw6upHU2isAh6SgtbsRMm5ZzjdNRz YSeEC/Ex/DML2BZzO9DXpdWdWu18fF7qxgtYB+l0fmsZO8EeypLBzCqzV0d8/AAtyOHF 52dcKBtcNgAPVAxpRTvGWeyuBiNq+Ogcia0oxZB05GodlvDpKzAiIbOBqCdApiWLnZ2l EcmkAgbnEWYa31kT6EdhAsM3qyQq9FKlXoJMJfumzhZQca8JqlwtMKzyLJHiLXUnb4Fz 2tFJyt/m97oHeCFbMRI78p1UzNHBamUd807vuthPdXPn3timYMGb+y0dqhrn1Z7LneFy 3EzQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=zfBpY5j+HH+rVlSYURyRdU4D9rVc0jOxfeEQurgSOig=; b=MIEW/Wk7+SfXGx00BFlA7v6+UMlZEpMWx207HjjOmTcoj7PwU2bZPIaYWRgeCeznGo PVPaVfKLtoLtf7WZYw9fgmraHH2IAnFQZOWUhEj8Kw9JD3WD8yyv0gUNxbn3rozXOmfI xIei6Ut9bfhSK1f/02muHGI9aTlLHtKGAbmnykI94EbcFqZ8Zdhtr/OCvbbeX2ubtRlG +cEV/j9HfMReK3pJlTBqD0f4S/uyNi3r609QhHHVncWaQOoRbCXeGkuC6NFBxJmtGO91 6o6UjUKfXXxcChZl1jKrURpSuGhXjKZjIkVGBLGzhBVLOkBl7rNoTPPeRnzplO4FgiSE Rr5A== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b="Dx38IFT/"; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id z197-v6si1397500qkz.375.2018.06.14.12.46.12 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:46:12 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b="Dx38IFT/"; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42430 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTYCC-0001t9-0f for patch@linaro.org; Thu, 14 Jun 2018 15:46:12 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37082) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyj-000772-12 for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyg-0005ta-1g for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:17 -0400 Received: from mail-pg0-x236.google.com ([2607:f8b0:400e:c05::236]:35911) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyf-0005sj-Nr for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:13 -0400 Received: by mail-pg0-x236.google.com with SMTP id m5-v6so3366718pgd.3 for ; Thu, 14 Jun 2018 12:32:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zfBpY5j+HH+rVlSYURyRdU4D9rVc0jOxfeEQurgSOig=; b=Dx38IFT/U+m5NYubYDBJpx9HxtHwG94bbZQ9gq9f4/flIrTMEZ92YB6tHwcM6KP34X NIydkVuZNQ1tAlPtT1UAuBE2FRV4maykwoCJark1LBTbXGHFeKmhbv7SD97xAow6LCk4 fx6ibmw2uwFSCWjgEfEJkG8vCzgj4iInYkEU4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zfBpY5j+HH+rVlSYURyRdU4D9rVc0jOxfeEQurgSOig=; b=XpLrKWYutnxMvyrwD4kzFK5/YKkvjPfPpRFNXeQzMD9UCzPeZk+VMbN4YaNMG7X6TI 3Y32GcYkU3jfB9aecjdLtwgE9F/Zs2+ZSe5Q1gJK5Xs9FYIzKqHx0w00yTMJhnsGVhH3 DJKiSvKgJMCrirT65VYaQydXkvqEj41as3ntygQtRI2WFIBFRzX392UD+TEGKZACeFdA /F6fUNjDUUwSlhtvjm5JKAgOsTK0+fQJraVoSG9Rf3Bwqlb0sw3bFnzhEbKcFajxA4Or /YzLblWdJejMuqcvMVkNFHQv13i6PpannSIINtEYXPTDYDEiNLCR3+wNASqLU15xQMFQ j/PA== X-Gm-Message-State: APt69E1jqiLQG55DMvDbyO8Fr8tzh4lbNzWXNOumWBIbbH3Oa2Idl2+V PvZWDoCqVQ+EhQBmKYfs56Qh3nUa6BE= X-Received: by 2002:a62:1747:: with SMTP id 68-v6mr10673718pfx.69.1529004732344; Thu, 14 Jun 2018 12:32:12 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.32.10 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:32:11 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:40 -1000 Message-Id: <20180614193147.29680-12-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::236 Subject: [Qemu-devel] [PULL 11/18] translate-all: use per-page locking in !user-mode 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" Groundwork for supporting parallel TCG generation. Instead of using a global lock (tb_lock) to protect changes to pages, use fine-grained, per-page locks in !user-mode. User-mode stays with mmap_lock. Sometimes changes need to happen atomically on more than one page (e.g. when a TB that spans across two pages is added/invalidated, or when a range of pages is invalidated). We therefore introduce struct page_collection, which helps us keep track of a set of pages that have been locked in the appropriate locking order (i.e. by ascending page index). This commit first introduces the structs and the function helpers, to then convert the calling code to use per-page locking. Note that tb_lock is not removed yet. While at it, rename tb_alloc_page to tb_page_add, which pairs with tb_page_remove. Reviewed-by: Richard Henderson Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- accel/tcg/translate-all.h | 3 + include/exec/exec-all.h | 3 +- accel/tcg/translate-all.c | 444 ++++++++++++++++++++++++++++++++++---- 3 files changed, 409 insertions(+), 41 deletions(-) -- 2.17.1 diff --git a/accel/tcg/translate-all.h b/accel/tcg/translate-all.h index ba8e4d63c4..6d1d2588b5 100644 --- a/accel/tcg/translate-all.h +++ b/accel/tcg/translate-all.h @@ -23,6 +23,9 @@ /* translate-all.c */ +struct page_collection *page_collection_lock(tb_page_addr_t start, + tb_page_addr_t end); +void page_collection_unlock(struct page_collection *set); void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len); void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, int is_cpu_write_access); diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 54a3398374..a647cf8841 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -359,7 +359,8 @@ struct TranslationBlock { /* original tb when cflags has CF_NOCACHE */ struct TranslationBlock *orig_tb; /* first and second physical page containing code. The lower bit - of the pointer tells the index in page_next[] */ + of the pointer tells the index in page_next[]. + The list is protected by the TB's page('s) lock(s) */ uintptr_t page_next[2]; tb_page_addr_t page_addr[2]; diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 83bb40fb20..1cc7aab82c 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -112,8 +112,55 @@ typedef struct PageDesc { #else unsigned long flags; #endif +#ifndef CONFIG_USER_ONLY + QemuSpin lock; +#endif } PageDesc; +/** + * struct page_entry - page descriptor entry + * @pd: pointer to the &struct PageDesc of the page this entry represents + * @index: page index of the page + * @locked: whether the page is locked + * + * This struct helps us keep track of the locked state of a page, without + * bloating &struct PageDesc. + * + * A page lock protects accesses to all fields of &struct PageDesc. + * + * See also: &struct page_collection. + */ +struct page_entry { + PageDesc *pd; + tb_page_addr_t index; + bool locked; +}; + +/** + * struct page_collection - tracks a set of pages (i.e. &struct page_entry's) + * @tree: Binary search tree (BST) of the pages, with key == page index + * @max: Pointer to the page in @tree with the highest page index + * + * To avoid deadlock we lock pages in ascending order of page index. + * When operating on a set of pages, we need to keep track of them so that + * we can lock them in order and also unlock them later. For this we collect + * pages (i.e. &struct page_entry's) in a binary search @tree. Given that the + * @tree implementation we use does not provide an O(1) operation to obtain the + * highest-ranked element, we use @max to keep track of the inserted page + * with the highest index. This is valuable because if a page is not in + * the tree and its index is higher than @max's, then we can lock it + * without breaking the locking order rule. + * + * Note on naming: 'struct page_set' would be shorter, but we already have a few + * page_set_*() helpers, so page_collection is used instead to avoid confusion. + * + * See also: page_collection_lock(). + */ +struct page_collection { + GTree *tree; + struct page_entry *max; +}; + /* list iterators for lists of tagged pointers in TranslationBlock */ #define TB_FOR_EACH_TAGGED(head, tb, n, field) \ for (n = (head) & 1, tb = (TranslationBlock *)((head) & ~1); \ @@ -507,6 +554,15 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc) return NULL; } pd = g_new0(PageDesc, V_L2_SIZE); +#ifndef CONFIG_USER_ONLY + { + int i; + + for (i = 0; i < V_L2_SIZE; i++) { + qemu_spin_init(&pd[i].lock); + } + } +#endif existing = atomic_cmpxchg(lp, NULL, pd); if (unlikely(existing)) { g_free(pd); @@ -522,6 +578,253 @@ static inline PageDesc *page_find(tb_page_addr_t index) return page_find_alloc(index, 0); } +static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1, + PageDesc **ret_p2, tb_page_addr_t phys2, int alloc); + +/* In user-mode page locks aren't used; mmap_lock is enough */ +#ifdef CONFIG_USER_ONLY +static inline void page_lock(PageDesc *pd) +{ } + +static inline void page_unlock(PageDesc *pd) +{ } + +static inline void page_lock_tb(const TranslationBlock *tb) +{ } + +static inline void page_unlock_tb(const TranslationBlock *tb) +{ } + +struct page_collection * +page_collection_lock(tb_page_addr_t start, tb_page_addr_t end) +{ + return NULL; +} + +void page_collection_unlock(struct page_collection *set) +{ } +#else /* !CONFIG_USER_ONLY */ + +static inline void page_lock(PageDesc *pd) +{ + qemu_spin_lock(&pd->lock); +} + +static inline void page_unlock(PageDesc *pd) +{ + qemu_spin_unlock(&pd->lock); +} + +/* lock the page(s) of a TB in the correct acquisition order */ +static inline void page_lock_tb(const TranslationBlock *tb) +{ + page_lock_pair(NULL, tb->page_addr[0], NULL, tb->page_addr[1], 0); +} + +static inline void page_unlock_tb(const TranslationBlock *tb) +{ + page_unlock(page_find(tb->page_addr[0] >> TARGET_PAGE_BITS)); + if (unlikely(tb->page_addr[1] != -1)) { + page_unlock(page_find(tb->page_addr[1] >> TARGET_PAGE_BITS)); + } +} + +static inline struct page_entry * +page_entry_new(PageDesc *pd, tb_page_addr_t index) +{ + struct page_entry *pe = g_malloc(sizeof(*pe)); + + pe->index = index; + pe->pd = pd; + pe->locked = false; + return pe; +} + +static void page_entry_destroy(gpointer p) +{ + struct page_entry *pe = p; + + g_assert(pe->locked); + page_unlock(pe->pd); + g_free(pe); +} + +/* returns false on success */ +static bool page_entry_trylock(struct page_entry *pe) +{ + bool busy; + + busy = qemu_spin_trylock(&pe->pd->lock); + if (!busy) { + g_assert(!pe->locked); + pe->locked = true; + } + return busy; +} + +static void do_page_entry_lock(struct page_entry *pe) +{ + page_lock(pe->pd); + g_assert(!pe->locked); + pe->locked = true; +} + +static gboolean page_entry_lock(gpointer key, gpointer value, gpointer data) +{ + struct page_entry *pe = value; + + do_page_entry_lock(pe); + return FALSE; +} + +static gboolean page_entry_unlock(gpointer key, gpointer value, gpointer data) +{ + struct page_entry *pe = value; + + if (pe->locked) { + pe->locked = false; + page_unlock(pe->pd); + } + return FALSE; +} + +/* + * Trylock a page, and if successful, add the page to a collection. + * Returns true ("busy") if the page could not be locked; false otherwise. + */ +static bool page_trylock_add(struct page_collection *set, tb_page_addr_t addr) +{ + tb_page_addr_t index = addr >> TARGET_PAGE_BITS; + struct page_entry *pe; + PageDesc *pd; + + pe = g_tree_lookup(set->tree, &index); + if (pe) { + return false; + } + + pd = page_find(index); + if (pd == NULL) { + return false; + } + + pe = page_entry_new(pd, index); + g_tree_insert(set->tree, &pe->index, pe); + + /* + * If this is either (1) the first insertion or (2) a page whose index + * is higher than any other so far, just lock the page and move on. + */ + if (set->max == NULL || pe->index > set->max->index) { + set->max = pe; + do_page_entry_lock(pe); + return false; + } + /* + * Try to acquire out-of-order lock; if busy, return busy so that we acquire + * locks in order. + */ + return page_entry_trylock(pe); +} + +static gint tb_page_addr_cmp(gconstpointer ap, gconstpointer bp, gpointer udata) +{ + tb_page_addr_t a = *(const tb_page_addr_t *)ap; + tb_page_addr_t b = *(const tb_page_addr_t *)bp; + + if (a == b) { + return 0; + } else if (a < b) { + return -1; + } + return 1; +} + +/* + * Lock a range of pages ([@start,@end[) as well as the pages of all + * intersecting TBs. + * Locking order: acquire locks in ascending order of page index. + */ +struct page_collection * +page_collection_lock(tb_page_addr_t start, tb_page_addr_t end) +{ + struct page_collection *set = g_malloc(sizeof(*set)); + tb_page_addr_t index; + PageDesc *pd; + + start >>= TARGET_PAGE_BITS; + end >>= TARGET_PAGE_BITS; + g_assert(start <= end); + + set->tree = g_tree_new_full(tb_page_addr_cmp, NULL, NULL, + page_entry_destroy); + set->max = NULL; + + retry: + g_tree_foreach(set->tree, page_entry_lock, NULL); + + for (index = start; index <= end; index++) { + TranslationBlock *tb; + int n; + + pd = page_find(index); + if (pd == NULL) { + continue; + } + if (page_trylock_add(set, index << TARGET_PAGE_BITS)) { + g_tree_foreach(set->tree, page_entry_unlock, NULL); + goto retry; + } + PAGE_FOR_EACH_TB(pd, tb, n) { + if (page_trylock_add(set, tb->page_addr[0]) || + (tb->page_addr[1] != -1 && + page_trylock_add(set, tb->page_addr[1]))) { + /* drop all locks, and reacquire in order */ + g_tree_foreach(set->tree, page_entry_unlock, NULL); + goto retry; + } + } + } + return set; +} + +void page_collection_unlock(struct page_collection *set) +{ + /* entries are unlocked and freed via page_entry_destroy */ + g_tree_destroy(set->tree); + g_free(set); +} + +#endif /* !CONFIG_USER_ONLY */ + +static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1, + PageDesc **ret_p2, tb_page_addr_t phys2, int alloc) +{ + PageDesc *p1, *p2; + + assert_memory_lock(); + g_assert(phys1 != -1 && phys1 != phys2); + p1 = page_find_alloc(phys1 >> TARGET_PAGE_BITS, alloc); + if (ret_p1) { + *ret_p1 = p1; + } + if (likely(phys2 == -1)) { + page_lock(p1); + return; + } + p2 = page_find_alloc(phys2 >> TARGET_PAGE_BITS, alloc); + if (ret_p2) { + *ret_p2 = p2; + } + if (phys1 < phys2) { + page_lock(p1); + page_lock(p2); + } else { + page_lock(p2); + page_lock(p1); + } +} + #if defined(CONFIG_USER_ONLY) /* Currently it is not recommended to allocate big chunks of data in user mode. It will change when a dedicated libc will be used. */ @@ -807,6 +1110,7 @@ static TranslationBlock *tb_alloc(target_ulong pc) return tb; } +/* call with @p->lock held */ static inline void invalidate_page_bitmap(PageDesc *p) { #ifdef CONFIG_SOFTMMU @@ -828,8 +1132,10 @@ static void page_flush_tb_1(int level, void **lp) PageDesc *pd = *lp; for (i = 0; i < V_L2_SIZE; ++i) { + page_lock(&pd[i]); pd[i].first_tb = (uintptr_t)NULL; invalidate_page_bitmap(pd + i); + page_unlock(&pd[i]); } } else { void **pp = *lp; @@ -956,6 +1262,7 @@ static void tb_page_check(void) #endif /* CONFIG_USER_ONLY */ +/* call with @pd->lock held */ static inline void tb_page_remove(PageDesc *pd, TranslationBlock *tb) { TranslationBlock *tb1; @@ -1032,11 +1339,8 @@ static inline void tb_jmp_unlink(TranslationBlock *tb) } } -/* invalidate one TB - * - * Called with tb_lock held. - */ -void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) +/* If @rm_from_page_list is set, call with the TB's pages' locks held */ +static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) { CPUState *cpu; PageDesc *p; @@ -1056,15 +1360,15 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) } /* remove the TB from the page list */ - if (tb->page_addr[0] != page_addr) { + if (rm_from_page_list) { p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS); tb_page_remove(p, tb); invalidate_page_bitmap(p); - } - if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) { - p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS); - tb_page_remove(p, tb); - invalidate_page_bitmap(p); + if (tb->page_addr[1] != -1) { + p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS); + tb_page_remove(p, tb); + invalidate_page_bitmap(p); + } } /* remove the TB from the hash list */ @@ -1086,7 +1390,28 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) tcg_ctx->tb_phys_invalidate_count + 1); } +static void tb_phys_invalidate__locked(TranslationBlock *tb) +{ + do_tb_phys_invalidate(tb, true); +} + +/* invalidate one TB + * + * Called with tb_lock held. + */ +void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) +{ + if (page_addr == -1) { + page_lock_tb(tb); + do_tb_phys_invalidate(tb, true); + page_unlock_tb(tb); + } else { + do_tb_phys_invalidate(tb, false); + } +} + #ifdef CONFIG_SOFTMMU +/* call with @p->lock held */ static void build_page_bitmap(PageDesc *p) { int n, tb_start, tb_end; @@ -1116,11 +1441,11 @@ static void build_page_bitmap(PageDesc *p) /* add the tb in the target page and protect it if necessary * * Called with mmap_lock held for user-mode emulation. + * Called with @p->lock held. */ -static inline void tb_alloc_page(TranslationBlock *tb, - unsigned int n, tb_page_addr_t page_addr) +static inline void tb_page_add(PageDesc *p, TranslationBlock *tb, + unsigned int n, tb_page_addr_t page_addr) { - PageDesc *p; #ifndef CONFIG_USER_ONLY bool page_already_protected; #endif @@ -1128,7 +1453,6 @@ static inline void tb_alloc_page(TranslationBlock *tb, assert_memory_lock(); tb->page_addr[n] = page_addr; - p = page_find_alloc(page_addr >> TARGET_PAGE_BITS, 1); tb->page_next[n] = p->first_tb; #ifndef CONFIG_USER_ONLY page_already_protected = p->first_tb != (uintptr_t)NULL; @@ -1180,18 +1504,28 @@ static inline void tb_alloc_page(TranslationBlock *tb, static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, tb_page_addr_t phys_page2) { + PageDesc *p; + PageDesc *p2 = NULL; uint32_t h; assert_memory_lock(); - /* add in the page list */ - tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK); - if (phys_page2 != -1) { - tb_alloc_page(tb, 1, phys_page2); + /* + * Add the TB to the page list, acquiring first the pages's locks. + */ + page_lock_pair(&p, phys_pc, &p2, phys_page2, 1); + tb_page_add(p, tb, 0, phys_pc & TARGET_PAGE_MASK); + if (p2) { + tb_page_add(p2, tb, 1, phys_page2); } else { tb->page_addr[1] = -1; } + if (p2) { + page_unlock(p2); + } + page_unlock(p); + /* add in the hash table */ h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags & CF_HASH_MASK, tb->trace_vcpu_dstate); @@ -1364,21 +1698,17 @@ TranslationBlock *tb_gen_code(CPUState *cpu, } /* - * Invalidate all TBs which intersect with the target physical address range - * [start;end[. NOTE: start and end must refer to the *same* physical page. - * 'is_cpu_write_access' should be true if called from a real cpu write - * access: the virtual CPU will exit the current TB if code is modified inside - * this TB. - * - * Called with tb_lock/mmap_lock held for user-mode emulation - * Called with tb_lock held for system-mode emulation + * Call with all @pages locked. + * @p must be non-NULL. */ -void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, - int is_cpu_write_access) +static void +tb_invalidate_phys_page_range__locked(struct page_collection *pages, + PageDesc *p, tb_page_addr_t start, + tb_page_addr_t end, + int is_cpu_write_access) { TranslationBlock *tb; tb_page_addr_t tb_start, tb_end; - PageDesc *p; int n; #ifdef TARGET_HAS_PRECISE_SMC CPUState *cpu = current_cpu; @@ -1394,10 +1724,6 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, assert_memory_lock(); assert_tb_locked(); - p = page_find(start >> TARGET_PAGE_BITS); - if (!p) { - return; - } #if defined(TARGET_HAS_PRECISE_SMC) if (cpu != NULL) { env = cpu->env_ptr; @@ -1443,7 +1769,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, ¤t_flags); } #endif /* TARGET_HAS_PRECISE_SMC */ - tb_phys_invalidate(tb, -1); + tb_phys_invalidate__locked(tb); } } #if !defined(CONFIG_USER_ONLY) @@ -1455,6 +1781,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, #endif #ifdef TARGET_HAS_PRECISE_SMC if (current_tb_modified) { + page_collection_unlock(pages); /* Force execution of one insn next time. */ cpu->cflags_next_tb = 1 | curr_cflags(); cpu_loop_exit_noexc(cpu); @@ -1462,6 +1789,35 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, #endif } +/* + * Invalidate all TBs which intersect with the target physical address range + * [start;end[. NOTE: start and end must refer to the *same* physical page. + * 'is_cpu_write_access' should be true if called from a real cpu write + * access: the virtual CPU will exit the current TB if code is modified inside + * this TB. + * + * Called with tb_lock/mmap_lock held for user-mode emulation + * Called with tb_lock held for system-mode emulation + */ +void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, + int is_cpu_write_access) +{ + struct page_collection *pages; + PageDesc *p; + + assert_memory_lock(); + assert_tb_locked(); + + p = page_find(start >> TARGET_PAGE_BITS); + if (p == NULL) { + return; + } + pages = page_collection_lock(start, end); + tb_invalidate_phys_page_range__locked(pages, p, start, end, + is_cpu_write_access); + page_collection_unlock(pages); +} + /* * Invalidate all TBs which intersect with the target physical address range * [start;end[. NOTE: start and end may refer to *different* physical pages. @@ -1474,15 +1830,22 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, */ static void tb_invalidate_phys_range_1(tb_page_addr_t start, tb_page_addr_t end) { + struct page_collection *pages; tb_page_addr_t next; + pages = page_collection_lock(start, end); for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; start < end; start = next, next += TARGET_PAGE_SIZE) { + PageDesc *pd = page_find(start >> TARGET_PAGE_BITS); tb_page_addr_t bound = MIN(next, end); - tb_invalidate_phys_page_range(start, bound, 0); + if (pd == NULL) { + continue; + } + tb_invalidate_phys_page_range__locked(pages, pd, start, bound, 0); } + page_collection_unlock(pages); } #ifdef CONFIG_SOFTMMU @@ -1508,6 +1871,7 @@ void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end) */ void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len) { + struct page_collection *pages; PageDesc *p; #if 0 @@ -1525,11 +1889,10 @@ void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len) if (!p) { return; } + + pages = page_collection_lock(start, start + len); if (!p->code_bitmap && ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD) { - /* build code bitmap. FIXME: writes should be protected by - * tb_lock, reads by tb_lock or RCU. - */ build_page_bitmap(p); } if (p->code_bitmap) { @@ -1543,8 +1906,9 @@ void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len) } } else { do_invalidate: - tb_invalidate_phys_page_range(start, start + len, 1); + tb_invalidate_phys_page_range__locked(pages, p, start, start + len, 1); } + page_collection_unlock(pages); } #else /* Called with mmap_lock held. If pc is not 0 then it indicates the From patchwork Thu Jun 14 19:31:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138628 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2536065lji; Thu, 14 Jun 2018 12:48:52 -0700 (PDT) X-Google-Smtp-Source: ADUXVKKvl9pJuxBrqKrV/yWGvfSNU3BHxCNU2S9aKv2rcEdGYIouR3/nEc3ZpPv/6SHF/qXkgxya X-Received: by 2002:ac8:33f3:: with SMTP id d48-v6mr3670409qtb.317.1529005732786; Thu, 14 Jun 2018 12:48:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005732; cv=none; d=google.com; s=arc-20160816; b=RmdOPHdEcZbBbQApEYHtQLj4pNAchjLFYvw+aHTstndhpvC3+j8wpE8MaIyDoIwSTL XUj7pI1xuX5i4dewOJCp9vYz5Fv03H2xH0AjnvRC8XuQV78W7D+eLHJpX2ow6smY0WkQ BsKNiG8S5XKkm+/iNVLi9g+N7Ris26R/cLmljVBLIOyhEcbzWsT9p5modPj4WElVSrSs 0xs+40xpivllKgy35bHqBy4xqF1gDgm+9XB+QEgwmaSM/K2LLdIEEahugnLthGhDeppP fR6TZ3HhwrUn1uL2vd7lx9nQDNUocP0SIw/Dx6Ud+9UTX5eLycw9gSCICdvy/2i0oaUe Zp+g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=B2SA4mmIv/f/uj1OaCwYNsFOq5P2Uw7DvOSNDc7St/o=; b=qwsRtDjoaEl4I7izcPpH2UElEQkFsnDpWWlA+rNCu+W6oH8o/TPhsiFo9hpBFrpwPn dO5o5Jf0B5hncMTGoPwHhK0WHPdKQ05WsiQx5b4tLmTvtgkxVkHM8lTWrcNhE8i8VYXF AW4cSmHdn/A90VCvRlutGP/2cokQ+OhCTnSAoAaERMkcjNkl+q55XApeg1Xy+uSLVWTS KvPCesvDSBxjHNaRqf4vg22rsPf975HCHHQJq2wtRPO72I5dz7CAfu7+uFXsjCwR7eyd 8zw901p5epr2yybKpeeqNeAHHVfhLrKOP9BrlmeQ4A1NFJHMVfL+d5YjkMj0aYT70Wkp ZXIw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=QJ93jh5T; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id d123-v6si6027187qka.111.2018.06.14.12.48.52 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:48:52 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=QJ93jh5T; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42450 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTYEm-0003mv-5A for patch@linaro.org; Thu, 14 Jun 2018 15:48:52 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37083) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyj-000773-1o for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyh-0005vb-LO for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:17 -0400 Received: from mail-pg0-x241.google.com ([2607:f8b0:400e:c05::241]:38217) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyh-0005uj-Dh for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:15 -0400 Received: by mail-pg0-x241.google.com with SMTP id c9-v6so3364332pgf.5 for ; Thu, 14 Jun 2018 12:32:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=B2SA4mmIv/f/uj1OaCwYNsFOq5P2Uw7DvOSNDc7St/o=; b=QJ93jh5TwHuq8LirQA0LPgj7QOgTXdezMuCg1Ui4DZmXPqtLoIeYabjhYMiwn0i3v9 NluDuwa1KidVUtRfS2NrW8hB32IMWc66ZM3lc5DrmT5Ny+XLph23lZZffoVSXIFeoQvx B4+UNgZqHniWLpmiiMUFyc6k0PnjE7m+O6K7Q= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=B2SA4mmIv/f/uj1OaCwYNsFOq5P2Uw7DvOSNDc7St/o=; b=bmfHyyg88zHCpPaJlQtWl/HnL0KllN30OwpZvgBODvzw8PfJ4M1Sik9Z6dw/vrKXVb InT9IwLtCyBkExvzavcqwbwGAg4EqEeOgV3SMt4d92ZFHWsX5y+2XFQk+bOttdcAV8tz N4UFFpUMv2GN/UiqsfYQFsi6NyX+evy9C8Qh2Ow+OsCBoh+t4hZHPUmzX5635/KkyXD6 s6YubMk1DHJw2CbKS5JVoCQtyvFXPc/31QtNSJsTbmKaVtRJ50zFPgi5AnfAv1DMOSo7 2g7bM066fmAJkImzYABm2tJKMfUfQ23Es065frvnGQgCE1E0OT4jTN6jj2ZGg5wgzhl3 +q+w== X-Gm-Message-State: APt69E0mofCdEPc9BjHajU4d6pi8A2/H5oaL37Ba8/hupajpo/1MrIi3 b5yo6/UQLS0ZYbxoFxyXEWFFuuhz8cg= X-Received: by 2002:a65:4d08:: with SMTP id i8-v6mr3409499pgt.427.1529004734210; Thu, 14 Jun 2018 12:32:14 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.32.12 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:32:13 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:41 -1000 Message-Id: <20180614193147.29680-13-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::241 Subject: [Qemu-devel] [PULL 12/18] translate-all: add page_locked assertions 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" This is only compiled under CONFIG_DEBUG_TCG to avoid bloating the binary. In user-mode, assert_page_locked is equivalent to assert_mmap_lock. Note: There are some tb_lock assertions left that will be removed by later patches. Reviewed-by: Richard Henderson Suggested-by: Alex Bennée Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- accel/tcg/translate-all.c | 82 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 3 deletions(-) -- 2.17.1 diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 1cc7aab82c..8b378586f4 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -583,6 +583,9 @@ static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1, /* In user-mode page locks aren't used; mmap_lock is enough */ #ifdef CONFIG_USER_ONLY + +#define assert_page_locked(pd) tcg_debug_assert(have_mmap_lock()) + static inline void page_lock(PageDesc *pd) { } @@ -605,14 +608,80 @@ void page_collection_unlock(struct page_collection *set) { } #else /* !CONFIG_USER_ONLY */ +#ifdef CONFIG_DEBUG_TCG + +static __thread GHashTable *ht_pages_locked_debug; + +static void ht_pages_locked_debug_init(void) +{ + if (ht_pages_locked_debug) { + return; + } + ht_pages_locked_debug = g_hash_table_new(NULL, NULL); +} + +static bool page_is_locked(const PageDesc *pd) +{ + PageDesc *found; + + ht_pages_locked_debug_init(); + found = g_hash_table_lookup(ht_pages_locked_debug, pd); + return !!found; +} + +static void page_lock__debug(PageDesc *pd) +{ + ht_pages_locked_debug_init(); + g_assert(!page_is_locked(pd)); + g_hash_table_insert(ht_pages_locked_debug, pd, pd); +} + +static void page_unlock__debug(const PageDesc *pd) +{ + bool removed; + + ht_pages_locked_debug_init(); + g_assert(page_is_locked(pd)); + removed = g_hash_table_remove(ht_pages_locked_debug, pd); + g_assert(removed); +} + +static void +do_assert_page_locked(const PageDesc *pd, const char *file, int line) +{ + if (unlikely(!page_is_locked(pd))) { + error_report("assert_page_lock: PageDesc %p not locked @ %s:%d", + pd, file, line); + abort(); + } +} + +#define assert_page_locked(pd) do_assert_page_locked(pd, __FILE__, __LINE__) + +#else /* !CONFIG_DEBUG_TCG */ + +#define assert_page_locked(pd) + +static inline void page_lock__debug(const PageDesc *pd) +{ +} + +static inline void page_unlock__debug(const PageDesc *pd) +{ +} + +#endif /* CONFIG_DEBUG_TCG */ + static inline void page_lock(PageDesc *pd) { + page_lock__debug(pd); qemu_spin_lock(&pd->lock); } static inline void page_unlock(PageDesc *pd) { qemu_spin_unlock(&pd->lock); + page_unlock__debug(pd); } /* lock the page(s) of a TB in the correct acquisition order */ @@ -658,6 +727,7 @@ static bool page_entry_trylock(struct page_entry *pe) if (!busy) { g_assert(!pe->locked); pe->locked = true; + page_lock__debug(pe->pd); } return busy; } @@ -775,6 +845,7 @@ page_collection_lock(tb_page_addr_t start, tb_page_addr_t end) g_tree_foreach(set->tree, page_entry_unlock, NULL); goto retry; } + assert_page_locked(pd); PAGE_FOR_EACH_TB(pd, tb, n) { if (page_trylock_add(set, tb->page_addr[0]) || (tb->page_addr[1] != -1 && @@ -1113,6 +1184,7 @@ static TranslationBlock *tb_alloc(target_ulong pc) /* call with @p->lock held */ static inline void invalidate_page_bitmap(PageDesc *p) { + assert_page_locked(p); #ifdef CONFIG_SOFTMMU g_free(p->code_bitmap); p->code_bitmap = NULL; @@ -1269,6 +1341,7 @@ static inline void tb_page_remove(PageDesc *pd, TranslationBlock *tb) uintptr_t *pprev; unsigned int n1; + assert_page_locked(pd); pprev = &pd->first_tb; PAGE_FOR_EACH_TB(pd, tb1, n1) { if (tb1 == tb) { @@ -1417,6 +1490,7 @@ static void build_page_bitmap(PageDesc *p) int n, tb_start, tb_end; TranslationBlock *tb; + assert_page_locked(p); p->code_bitmap = bitmap_new(TARGET_PAGE_SIZE); PAGE_FOR_EACH_TB(p, tb, n) { @@ -1450,7 +1524,7 @@ static inline void tb_page_add(PageDesc *p, TranslationBlock *tb, bool page_already_protected; #endif - assert_memory_lock(); + assert_page_locked(p); tb->page_addr[n] = page_addr; tb->page_next[n] = p->first_tb; @@ -1721,8 +1795,7 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages, uint32_t current_flags = 0; #endif /* TARGET_HAS_PRECISE_SMC */ - assert_memory_lock(); - assert_tb_locked(); + assert_page_locked(p); #if defined(TARGET_HAS_PRECISE_SMC) if (cpu != NULL) { @@ -1734,6 +1807,7 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages, /* XXX: see if in some cases it could be faster to invalidate all the code */ PAGE_FOR_EACH_TB(p, tb, n) { + assert_page_locked(p); /* NOTE: this is subtle as a TB may span two physical pages */ if (n == 0) { /* NOTE: tb_end may be after the end of the page, but @@ -1891,6 +1965,7 @@ void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len) } pages = page_collection_lock(start, start + len); + assert_page_locked(p); if (!p->code_bitmap && ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD) { build_page_bitmap(p); @@ -1949,6 +2024,7 @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc) env = cpu->env_ptr; } #endif + assert_page_locked(p); PAGE_FOR_EACH_TB(p, tb, n) { #ifdef TARGET_HAS_PRECISE_SMC if (current_tb == tb && From patchwork Thu Jun 14 19:31:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138627 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2535632lji; Thu, 14 Jun 2018 12:48:25 -0700 (PDT) X-Google-Smtp-Source: ADUXVKIBTju+PbR+nPGccv6f7wdZkUSomC66pV9EEL1a6HINddYTbkYSIByn6iQmKhunLL2IoKoa X-Received: by 2002:a0c:a995:: with SMTP id a21-v6mr3674984qvb.173.1529005705470; Thu, 14 Jun 2018 12:48:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005705; cv=none; d=google.com; s=arc-20160816; b=Pv77wN8Ah1a7T1MAcY1i2HxLYkiCZerzrvU9j3EBESCwkXbC0CbTmArsQQyh/RBKDW +S2duqSohgdpaCtYYRNT1GB6hXXkahtGjNCa69a075CYOoFmS0T9cTHtMKLheYvVda9G eYtx+u1LpV0Qmvf7agYlJbdie0K3RK4Z+3lStKOjKWLeuCBH2yiIdZhx6dRswUNZBNhq knVlfq+wcSmHkVujDnrpX/2+gYF7QFzxXogD5pSvxkKikBye8iiq3vPEfW0yKXnHDXIS McQ9dgg2c5ROhOlJD/Tdax+4uxSfm6LLfW5jjlDYMyh8QqLO+lTFyDQm3lyrUUU96k1i xTkQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=zLcISsWRZ421wCIGWhD88VN2O5w5GA8j9/OMTA3FiXQ=; b=MjoNrqsktM0G/9rZEX38rQMvpTeDYb22RB+px1Fn/lyeTsWocP3BUuEXP60j6A1dZO qkfne0sKoy9dzqACbAww2GP98haQEkpV+e8rTGYH2UTupX9CVVyqQ31RvrKo+EE1XaTv 8rwt5dgiSV8mTUWLhM5TKb+nvf1z2fvH4KIF/wRgV7P/poL0W3FdSondlGXTyT4RrtoJ K7JZUB1IRguek362JZv7OszTOTfa+C0ppK/wAb9dyeGB6VMs8ELMNhs7dPZsvsIW2ATQ G3FI9cDTeUe4LUkg89XZjtGQXJHsK3Co7rfmrA886CEbmKw0/Ru4W9JBa5g1l4qcZr+F TzAQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=EP2IURmY; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id o34-v6si5142173qve.171.2018.06.14.12.48.25 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:48:25 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=EP2IURmY; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42439 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTYEK-00038T-RA for patch@linaro.org; Thu, 14 Jun 2018 15:48:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37103) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyk-00077y-E1 for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyj-0005x9-AQ for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:18 -0400 Received: from mail-pg0-x241.google.com ([2607:f8b0:400e:c05::241]:35626) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyj-0005wL-4M for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:17 -0400 Received: by mail-pg0-x241.google.com with SMTP id 15-v6so3366657pge.2 for ; Thu, 14 Jun 2018 12:32:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zLcISsWRZ421wCIGWhD88VN2O5w5GA8j9/OMTA3FiXQ=; b=EP2IURmYz8p1ccyC3YKxK46WtEN7jyJG8/M0x650Pb9OeY6UE5ztWuIXApHkFGH7Ff 9Nl7JUgTCD0zrKC3Yz/yEATTcjv4YIkwwDlqKZ2+gc5l1ukD0PRanLHQqvRUaNDeNszp I8RxLYUzGm6eWGn84recCGqq5FoRg56dETuRw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zLcISsWRZ421wCIGWhD88VN2O5w5GA8j9/OMTA3FiXQ=; b=Xl7ls4iUHUQZxDJcO04F/n86IHoWjrps/WJ33H3WV493TaZYJ+9Q8iwSQuslidLUCf 1aEPaOGMZ0J5HnR55VUE4qLNzFvfOuaVuxLMZhPbCf5nVhzfSmjLNCKgsHvTPDFfRUXK /SFddgLgaeobFCJ1YrxBIYHp9streD5Oubo/TWbe6ENKlaKsrX2bVMLGDrYFkBNAiyGe uY6d0PLkONR5uDgDHZaWzjW09CppyQZzch0CaPu/j/puBuiSrRwNvDEkXJOVI1x8yy+k 0MdFUdYUCOqP1pHnhWqOmdeAySy67k1gHGvk9Tg7Qrvkvc1TcEpaJCuiJSPB/SmGh7mv cOyA== X-Gm-Message-State: APt69E0UEyaYrSd7unjI6EA2XRyZw4XYDN6MKQVybEv+XhUnWhHeTSBJ 6vk9d/ZCkoNDohU2QmG9fl3zQoNLlZw= X-Received: by 2002:a63:6d41:: with SMTP id i62-v6mr3379574pgc.286.1529004735966; Thu, 14 Jun 2018 12:32:15 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.32.14 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:32:15 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:42 -1000 Message-Id: <20180614193147.29680-14-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::241 Subject: [Qemu-devel] [PULL 13/18] translate-all: introduce assert_no_pages_locked 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" The appended adds assertions to make sure we do not longjmp with page locks held. Note that user-mode has nothing to check, since page_locks are !user-mode only. Reviewed-by: Richard Henderson Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- include/exec/exec-all.h | 8 ++++++++ accel/tcg/cpu-exec.c | 1 + accel/tcg/translate-all.c | 7 +++++++ 3 files changed, 16 insertions(+) -- 2.17.1 diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index a647cf8841..b9e3018aee 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -435,6 +435,14 @@ void tb_lock(void); void tb_unlock(void); void tb_lock_reset(void); +#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_DEBUG_TCG) +void assert_no_pages_locked(void); +#else +static inline void assert_no_pages_locked(void) +{ +} +#endif + #if !defined(CONFIG_USER_ONLY) struct MemoryRegion *iotlb_to_region(CPUState *cpu, diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 7570c59f09..d75c35380a 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -273,6 +273,7 @@ void cpu_exec_step_atomic(CPUState *cpu) tcg_debug_assert(!have_mmap_lock()); #endif tb_lock_reset(); + assert_no_pages_locked(); } if (in_exclusive_region) { diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 8b378586f4..c75298d08a 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -658,6 +658,12 @@ do_assert_page_locked(const PageDesc *pd, const char *file, int line) #define assert_page_locked(pd) do_assert_page_locked(pd, __FILE__, __LINE__) +void assert_no_pages_locked(void) +{ + ht_pages_locked_debug_init(); + g_assert(g_hash_table_size(ht_pages_locked_debug) == 0); +} + #else /* !CONFIG_DEBUG_TCG */ #define assert_page_locked(pd) @@ -829,6 +835,7 @@ page_collection_lock(tb_page_addr_t start, tb_page_addr_t end) set->tree = g_tree_new_full(tb_page_addr_cmp, NULL, NULL, page_entry_destroy); set->max = NULL; + assert_no_pages_locked(); retry: g_tree_foreach(set->tree, page_entry_lock, NULL); From patchwork Thu Jun 14 19:31:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138629 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2536593lji; Thu, 14 Jun 2018 12:49:23 -0700 (PDT) X-Google-Smtp-Source: ADUXVKIX6Hy7jTya8B3w9cULPUfIzXAqXtp/LEs01Oe1ctDsEhKDrGZn5g5I4IKGNN7oeKdpc6qh X-Received: by 2002:a0c:e2cd:: with SMTP id t13-v6mr3684327qvl.47.1529005763120; Thu, 14 Jun 2018 12:49:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005763; cv=none; d=google.com; s=arc-20160816; b=RafnVt7mE4ow+nTyei7pRYxIASuTJftqCQ5JqmmRASg2XVKedRJxGXfx2NZz6d6DzZ AZ1pzKl4mjM1rf/Wpik3A3CUcJmAqxF2yxWZk/R/LLSkqIGBv4Fw0Ui1+1QzA3KDuA06 2eas5oCXcfFR9kOrrSgy1CBPJ6o/DbPssmje5UM+RVj4UlnyaMn5NHMLdELiLjvpBgmB BITgXvAZyCLtnFbSWp8fjr7aC4NVJqthCexxopsDT1Z7jH0CN8XfA7qdm6MRghY1hcSQ 8UUuC1kcfbc8LB6n/2u3eGSQPL09nsu2we344WteCDmOciZ2Cn+P9C+yKBM4EtEqnTCD U/6w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=t7rbHIfP7bGjD+FWmMNzziJrtUs9iEaHFBrJCstC904=; b=EyTs5aNRpAQQfcVx4AM6lJgH1TEssPSgC0sboW8HLxDCuzHoM9TwMLKrIhL+zwKU8E qCst9lEIGmWnnteliSDeBpbn4dKmLgNQcCUNctRHa6FZDyqrzMr6MXvYCpJFS7m49U0D 1yhZc94UT0Lxl8ZjHuM5gqlXH2aES+vd5OSAbAGr7UYLc010y0TxqV7lStTsCzmmStqy uqGdHTEHaNQIxWY1UOX/LMfHGcjOwYAEnEbVVrZrl38R5hQ7h6o9pvgIXVvkALsksle8 uucPN0oVr0FMEFkvBXLQrmZCEJhCSGBdzXfD7MGrhvClVch2ksvXvM5eHzXh1m4rH8f+ A9tw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b="b/kWOCtC"; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id w13-v6si2514751qto.294.2018.06.14.12.49.22 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:49:23 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b="b/kWOCtC"; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42451 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTYFG-0003rs-EH for patch@linaro.org; Thu, 14 Jun 2018 15:49:22 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37138) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXym-000781-Sz for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyl-0005yd-Gp for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:20 -0400 Received: from mail-pg0-x242.google.com ([2607:f8b0:400e:c05::242]:46141) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyl-0005xy-8K for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:19 -0400 Received: by mail-pg0-x242.google.com with SMTP id d2-v6so3353563pga.13 for ; Thu, 14 Jun 2018 12:32:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=t7rbHIfP7bGjD+FWmMNzziJrtUs9iEaHFBrJCstC904=; b=b/kWOCtCeg/JosFKJt2RrFrjieqAcelcioU0X/mCdwn75tPOg6alipy8kPxKb8KED+ g1ggfZLMiytbq8jBnjwV54Gn1b9SID8Fc/IPtevFoKfCGpqCaBCc3VDWY9EfBqoc0H1E pLhq4uw//rP+n9dUBL8/QD491Kt2k4rkkVV6M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=t7rbHIfP7bGjD+FWmMNzziJrtUs9iEaHFBrJCstC904=; b=bODsCmsvpp4N0MjGKpSlkJFqJCj8o4O+FGOAyMFHgJzk4kbnvFgKYOgiZqQ4IdYjUZ qXVdjhyzDnUXaRxJuLP2owaoxGLZFXu4HpvOAOXDxXC33oXPavChjBwroi22Jbup7c0w AzP1yYy9Z5X/Wagvequqw4qJJcIa9b7HgJU3D2YJ0LvSkKlX/gI9+K4NoxN64XjJOX99 ndJQ1366AY7rSjIudv2PF8ODetbH0m+fWRxEJd8FnbU71krffgtfSAyv7L35TEaWIdqQ JbfGyvI7V8KBWBmrVwkJOvlo19RdRC6D4smrJAUAwyz8TzDY0Op8bKoXzcXTi2CJ+5NG kzVA== X-Gm-Message-State: APt69E2jcHUG0v8hE/V10MwsQjJaWPyVl1AwrUnBUrM+S0s8/iwpiDtQ ymaWH+GmLMcab7n4Xf5HyIoBkESd/v4= X-Received: by 2002:aa7:818b:: with SMTP id g11-v6mr10843367pfi.50.1529004738069; Thu, 14 Jun 2018 12:32:18 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.32.16 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:32:17 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:43 -1000 Message-Id: <20180614193147.29680-15-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::242 Subject: [Qemu-devel] [PULL 14/18] translate-all: discard TB when tb_link_page returns an existing matching 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" Use the recently-gained QHT feature of returning the matching TB if it already exists. This allows us to get rid of the lookup we perform right after acquiring tb_lock. Suggested-by: Richard Henderson Reviewed-by: Richard Henderson Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- accel/tcg/cpu-exec.c | 14 ++------- accel/tcg/translate-all.c | 50 +++++++++++++++++++++++++++------ docs/devel/multi-thread-tcg.txt | 3 ++ 3 files changed, 46 insertions(+), 21 deletions(-) -- 2.17.1 Tested-by: Pavel Dovgalyuk diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index d75c35380a..45f6ebc65e 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -245,10 +245,7 @@ void cpu_exec_step_atomic(CPUState *cpu) if (tb == NULL) { mmap_lock(); tb_lock(); - tb = tb_htable_lookup(cpu, pc, cs_base, flags, cf_mask); - if (likely(tb == NULL)) { - tb = tb_gen_code(cpu, pc, cs_base, flags, cflags); - } + tb = tb_gen_code(cpu, pc, cs_base, flags, cflags); tb_unlock(); mmap_unlock(); } @@ -398,14 +395,7 @@ static inline TranslationBlock *tb_find(CPUState *cpu, tb_lock(); acquired_tb_lock = true; - /* There's a chance that our desired tb has been translated while - * taking the locks so we check again inside the lock. - */ - tb = tb_htable_lookup(cpu, pc, cs_base, flags, cf_mask); - if (likely(tb == NULL)) { - /* if no translated code available, then translate it now */ - tb = tb_gen_code(cpu, pc, cs_base, flags, cf_mask); - } + tb = tb_gen_code(cpu, pc, cs_base, flags, cf_mask); mmap_unlock(); /* We add the TB in the virtual pc hash table for the fast lookup */ diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index c75298d08a..2585e6fd3e 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -1581,18 +1581,30 @@ static inline void tb_page_add(PageDesc *p, TranslationBlock *tb, * (-1) to indicate that only one page contains the TB. * * Called with mmap_lock held for user-mode emulation. + * + * Returns a pointer @tb, or a pointer to an existing TB that matches @tb. + * Note that in !user-mode, another thread might have already added a TB + * for the same block of guest code that @tb corresponds to. In that case, + * the caller should discard the original @tb, and use instead the returned TB. */ -static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, - tb_page_addr_t phys_page2) +static TranslationBlock * +tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, + tb_page_addr_t phys_page2) { PageDesc *p; PageDesc *p2 = NULL; + void *existing_tb = NULL; uint32_t h; assert_memory_lock(); /* * Add the TB to the page list, acquiring first the pages's locks. + * We keep the locks held until after inserting the TB in the hash table, + * so that if the insertion fails we know for sure that the TBs are still + * in the page descriptors. + * Note that inserting into the hash table first isn't an option, since + * we can only insert TBs that are fully initialized. */ page_lock_pair(&p, phys_pc, &p2, phys_page2, 1); tb_page_add(p, tb, 0, phys_pc & TARGET_PAGE_MASK); @@ -1602,21 +1614,33 @@ static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, tb->page_addr[1] = -1; } + /* add in the hash table */ + h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags & CF_HASH_MASK, + tb->trace_vcpu_dstate); + qht_insert(&tb_ctx.htable, tb, h, &existing_tb); + + /* remove TB from the page(s) if we couldn't insert it */ + if (unlikely(existing_tb)) { + tb_page_remove(p, tb); + invalidate_page_bitmap(p); + if (p2) { + tb_page_remove(p2, tb); + invalidate_page_bitmap(p2); + } + tb = existing_tb; + } + if (p2) { page_unlock(p2); } page_unlock(p); - /* add in the hash table */ - h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags & CF_HASH_MASK, - tb->trace_vcpu_dstate); - qht_insert(&tb_ctx.htable, tb, h, NULL); - #ifdef CONFIG_USER_ONLY if (DEBUG_TB_CHECK_GATE) { tb_page_check(); } #endif + return tb; } /* Called with mmap_lock held for user mode emulation. */ @@ -1625,7 +1649,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, uint32_t flags, int cflags) { CPUArchState *env = cpu->env_ptr; - TranslationBlock *tb; + TranslationBlock *tb, *existing_tb; tb_page_addr_t phys_pc, phys_page2; target_ulong virt_page2; tcg_insn_unit *gen_code_buf; @@ -1773,7 +1797,15 @@ TranslationBlock *tb_gen_code(CPUState *cpu, * memory barrier is required before tb_link_page() makes the TB visible * through the physical hash table and physical page list. */ - tb_link_page(tb, phys_pc, phys_page2); + existing_tb = tb_link_page(tb, phys_pc, phys_page2); + /* if the TB already exists, discard what we just translated */ + if (unlikely(existing_tb != tb)) { + uintptr_t orig_aligned = (uintptr_t)gen_code_buf; + + orig_aligned -= ROUND_UP(sizeof(*tb), qemu_icache_linesize); + atomic_set(&tcg_ctx->code_gen_ptr, orig_aligned); + return existing_tb; + } tcg_tb_insert(tb); return tb; } diff --git a/docs/devel/multi-thread-tcg.txt b/docs/devel/multi-thread-tcg.txt index faf8918b23..faf09c6069 100644 --- a/docs/devel/multi-thread-tcg.txt +++ b/docs/devel/multi-thread-tcg.txt @@ -140,6 +140,9 @@ to atomically insert new elements. The lookup caches are updated atomically and the lookup hash uses QHT which is designed for concurrent safe lookup. +Parallel code generation is supported. QHT is used at insertion time +as the synchronization point across threads, thereby ensuring that we only +keep track of a single TranslationBlock for each guest code block. Memory maps and TLBs -------------------- From patchwork Thu Jun 14 19:31:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138630 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2538423lji; Thu, 14 Jun 2018 12:51:07 -0700 (PDT) X-Google-Smtp-Source: ADUXVKIjnReDr86F91YZ4xNhPnepsZUA1NWV0snMchcEhgPQuPicrG86nwm/staZOZUipLen5ecm X-Received: by 2002:aed:3fec:: with SMTP id w41-v6mr3688342qth.15.1529005866973; Thu, 14 Jun 2018 12:51:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005866; cv=none; d=google.com; s=arc-20160816; b=JU4Asoa8Vl2Qtr/8XJOu5jynQvIGtdX8kfMmsZfJK+a4Pc4hYTbUzIGci6estzWXEv 6b/djML4mHm0iRPwh4XAVK1T9z0/GGfLxPk4Ifdc78l87SJxQkL7LsmZPtJ2ZCrDDZcJ bM5d49Wfwh1n6NRnfX8IL8CXUHpapqn8Hea72NXIqg1e8/uJ6mM84nAQ/6nPRFiwGnGX Au5iBVKktZWSfaRgA/GcJLJwk2yTjXvbjUFGIJCsKQrxDS3IVXcWWRvIT6vvTHZ0ue/t kvRXmmfLtMHmQrMpbO8AycdJ9lZYsMHfjsXocKWmLB7Z7eHjtisX9upe5ENB65MhdDTL xC0g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=GaATOk5F/toNUw3pjhP/20LK1HXbcpqGrltUGJ7DRpQ=; b=mFfdnXkVOubb6WPgBn1lc3/9A26HDFAxvEBdsRdzOoXSsS2w1yvvSm9tFW+0LhlvPb URNrFQlVTb0TD8MLroqcec2cxWir1U8X7MO1/xJd4gp/PiyUN+IvbDa6l/PkjBCn0nyh ukIjcudYdP34AYOFE4gqyCqv6DCoiC33YQD+RtEfgG/y/Azw0UOIQdWHbdQAX74+/y4y FUPGja3ckG6CFwntu4ViGVA1EUzG676+C+9wfhzN94bN0WIAlihwo/E8AH3J1hBkKVUY dPr7Nsd41rjIrFidrkccU3QKpzYYtZiqb4PRX78pK7qPMSJT+mXQfJV62kodELaUIuG7 ZEbw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=N0FDXKDO; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id j6-v6si3962183qvl.174.2018.06.14.12.51.06 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:51:06 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=N0FDXKDO; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42463 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTYGw-0005M3-Da for patch@linaro.org; Thu, 14 Jun 2018 15:51:06 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37190) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyp-0007Ax-QT for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyn-00060h-N0 for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:23 -0400 Received: from mail-pg0-x242.google.com ([2607:f8b0:400e:c05::242]:44348) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyn-0005zh-Ct for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:21 -0400 Received: by mail-pg0-x242.google.com with SMTP id p21-v6so3354947pgd.11 for ; Thu, 14 Jun 2018 12:32:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=GaATOk5F/toNUw3pjhP/20LK1HXbcpqGrltUGJ7DRpQ=; b=N0FDXKDOPfkRZLR9XiuP97JA0ZYONvkuepmdOFGg+ekL5cQ2K1JO3teMsOzQ1Wx6Cx i8OBZ7EGAO3m3MYX2J9uiXIgFGnBzrmlNs/PNkUBboY/ieqjpNOod7uD3RBAjfJnGX0a NpBqzAIWKZsHjxWvu/p139EiVAgT1uFOVFgGM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=GaATOk5F/toNUw3pjhP/20LK1HXbcpqGrltUGJ7DRpQ=; b=e/TnkKfuR5tFghwfn1Uvyn6iMZ+3ZuMpbL4ZvO5JhEjzFim6tfwhUqFvLeXRALyk4w WJFOW2HP9P77tMaJWr/+3HIboVw6RHSpgxbaAOUMyj7vX2OIhoV3O6QUYOLYMOLfp8RA bz5ySKB9lBXnQQtohcFgtTCSRrJdMi/FX6mW+TuhQRNKklt1SnNFa3WGebsAvyFBXOYA g7jDZtamArHn/tGnOyIGQJf7HyHncRq6/+gr9OGtoWBNKGkv8fFunKipAUSlwOsfX9Tq FHzj0qKjYXYmv+mIZkXGKWJS3OrkDy/X0D5yBOghbJ0doTRWANxKG6PyrPtj3Y+EOqcF kVnA== X-Gm-Message-State: APt69E38frtKtL0451sQLEO7b2Pr8CZkX7XMEPz5ApioqYEBsXUsTiX+ g9tSaUoh13fO//Q2MF0KJGINb0wD9y8= X-Received: by 2002:a63:b505:: with SMTP id y5-v6mr3483848pge.213.1529004740057; Thu, 14 Jun 2018 12:32:20 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.32.18 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:32:19 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:44 -1000 Message-Id: <20180614193147.29680-16-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::242 Subject: [Qemu-devel] [PULL 15/18] translate-all: protect TB jumps with a per-destination-TB lock 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" This applies to both user-mode and !user-mode emulation. Instead of relying on a global lock, protect the list of incoming jumps with tb->jmp_lock. This lock also protects tb->cflags, so update all tb->cflags readers outside tb->jmp_lock to use atomic reads via tb_cflags(). In order to find the destination TB (and therefore its jmp_lock) from the origin TB, we introduce tb->jmp_dest[]. I considered not using a linked list of jumps, which simplifies code and makes the struct smaller. However, it unnecessarily increases memory usage, which results in a performance decrease. See for instance these numbers booting+shutting down debian-arm: Time (s) Rel. err (%) Abs. err (s) Rel. slowdown (%) ------------------------------------------------------------------------------ before 20.88 0.74 0.154512 0. after 20.81 0.38 0.079078 -0.33524904 GTree 21.02 0.28 0.058856 0.67049808 GHashTable + xxhash 21.63 1.08 0.233604 3.5919540 Using a hash table or a binary tree to keep track of the jumps doesn't really pay off, not only due to the increased memory usage, but also because most TBs have only 0 or 1 jumps to them. The maximum number of jumps when booting debian-arm that I measured is 35, but as we can see in the histogram below a TB with that many incoming jumps is extremely rare; the average TB has 0.80 incoming jumps. n_jumps: 379208; avg jumps/tb: 0.801099 dist: [0.0,1.0)|▄█▁▁▁▁▁▁▁▁▁▁▁ ▁▁▁▁▁▁ ▁▁▁ ▁▁▁ ▁|[34.0,35.0] Reviewed-by: Richard Henderson Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- include/exec/exec-all.h | 35 ++++++---- accel/tcg/cpu-exec.c | 41 +++++++---- accel/tcg/translate-all.c | 120 +++++++++++++++++++------------- docs/devel/multi-thread-tcg.txt | 6 +- 4 files changed, 125 insertions(+), 77 deletions(-) -- 2.17.1 diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index b9e3018aee..57e5a6e358 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -345,7 +345,7 @@ struct TranslationBlock { #define CF_LAST_IO 0x00008000 /* Last insn may be an IO access. */ #define CF_NOCACHE 0x00010000 /* To be freed after execution */ #define CF_USE_ICOUNT 0x00020000 -#define CF_INVALID 0x00040000 /* TB is stale. Setters need tb_lock */ +#define CF_INVALID 0x00040000 /* TB is stale. Set with @jmp_lock held */ #define CF_PARALLEL 0x00080000 /* Generate code for a parallel context */ /* cflags' mask for hashing/comparison */ #define CF_HASH_MASK \ @@ -364,6 +364,9 @@ struct TranslationBlock { uintptr_t page_next[2]; tb_page_addr_t page_addr[2]; + /* jmp_lock placed here to fill a 4-byte hole. Its documentation is below */ + QemuSpin jmp_lock; + /* The following data are used to directly call another TB from * the code of this one. This can be done either by emitting direct or * indirect native jump instructions. These jumps are reset so that the TB @@ -375,20 +378,26 @@ struct TranslationBlock { #define TB_JMP_RESET_OFFSET_INVALID 0xffff /* indicates no jump generated */ uintptr_t jmp_target_arg[2]; /* target address or offset */ - /* Each TB has an associated circular list of TBs jumping to this one. - * jmp_list_first points to the first TB jumping to this one. - * jmp_list_next is used to point to the next TB in a list. - * Since each TB can have two jumps, it can participate in two lists. - * jmp_list_first and jmp_list_next are 4-byte aligned pointers to a - * TranslationBlock structure, but the two least significant bits of - * them are used to encode which data field of the pointed TB should - * be used to traverse the list further from that TB: - * 0 => jmp_list_next[0], 1 => jmp_list_next[1], 2 => jmp_list_first. - * In other words, 0/1 tells which jump is used in the pointed TB, - * and 2 means that this is a pointer back to the target TB of this list. + /* + * Each TB has a NULL-terminated list (jmp_list_head) of incoming jumps. + * Each TB can have two outgoing jumps, and therefore can participate + * in two lists. The list entries are kept in jmp_list_next[2]. The least + * significant bit (LSB) of the pointers in these lists is used to encode + * which of the two list entries is to be used in the pointed TB. + * + * List traversals are protected by jmp_lock. The destination TB of each + * outgoing jump is kept in jmp_dest[] so that the appropriate jmp_lock + * can be acquired from any origin TB. + * + * jmp_dest[] are tagged pointers as well. The LSB is set when the TB is + * being invalidated, so that no further outgoing jumps from it can be set. + * + * jmp_lock also protects the CF_INVALID cflag; a jump must not be chained + * to a destination TB that has CF_INVALID set. */ + uintptr_t jmp_list_head; uintptr_t jmp_list_next[2]; - uintptr_t jmp_list_first; + uintptr_t jmp_dest[2]; }; extern bool parallel_cpus; diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 45f6ebc65e..c482008bc7 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -352,28 +352,43 @@ void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr) } } -/* Called with tb_lock held. */ static inline void tb_add_jump(TranslationBlock *tb, int n, TranslationBlock *tb_next) { + uintptr_t old; + assert(n < ARRAY_SIZE(tb->jmp_list_next)); - if (tb->jmp_list_next[n]) { - /* Another thread has already done this while we were - * outside of the lock; nothing to do in this case */ - return; + qemu_spin_lock(&tb_next->jmp_lock); + + /* make sure the destination TB is valid */ + if (tb_next->cflags & CF_INVALID) { + goto out_unlock_next; } + /* Atomically claim the jump destination slot only if it was NULL */ + old = atomic_cmpxchg(&tb->jmp_dest[n], (uintptr_t)NULL, (uintptr_t)tb_next); + if (old) { + goto out_unlock_next; + } + + /* patch the native jump address */ + tb_set_jmp_target(tb, n, (uintptr_t)tb_next->tc.ptr); + + /* add in TB jmp list */ + tb->jmp_list_next[n] = tb_next->jmp_list_head; + tb_next->jmp_list_head = (uintptr_t)tb | n; + + qemu_spin_unlock(&tb_next->jmp_lock); + qemu_log_mask_and_addr(CPU_LOG_EXEC, tb->pc, "Linking TBs %p [" TARGET_FMT_lx "] index %d -> %p [" TARGET_FMT_lx "]\n", tb->tc.ptr, tb->pc, n, tb_next->tc.ptr, tb_next->pc); + return; - /* patch the native jump address */ - tb_set_jmp_target(tb, n, (uintptr_t)tb_next->tc.ptr); - - /* add in TB jmp circular list */ - tb->jmp_list_next[n] = tb_next->jmp_list_first; - tb_next->jmp_list_first = (uintptr_t)tb | n; + out_unlock_next: + qemu_spin_unlock(&tb_next->jmp_lock); + return; } static inline TranslationBlock *tb_find(CPUState *cpu, @@ -416,9 +431,7 @@ static inline TranslationBlock *tb_find(CPUState *cpu, tb_lock(); acquired_tb_lock = true; } - if (!(tb->cflags & CF_INVALID)) { - tb_add_jump(last_tb, tb_exit, tb); - } + tb_add_jump(last_tb, tb_exit, tb); } if (acquired_tb_lock) { tb_unlock(); diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 2585e6fd3e..41fbf1055a 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -170,6 +170,9 @@ struct page_collection { #define PAGE_FOR_EACH_TB(pagedesc, tb, n) \ TB_FOR_EACH_TAGGED((pagedesc)->first_tb, tb, n, page_next) +#define TB_FOR_EACH_JMP(head_tb, tb, n) \ + TB_FOR_EACH_TAGGED((head_tb)->jmp_list_head, tb, n, jmp_list_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) @@ -389,7 +392,7 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, return -1; found: - if (reset_icount && (tb->cflags & CF_USE_ICOUNT)) { + if (reset_icount && (tb_cflags(tb) & CF_USE_ICOUNT)) { assert(use_icount); /* Reset the cycle counter to the start of the block and shift if to the number of actually executed instructions */ @@ -432,7 +435,7 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit) tb = tcg_tb_lookup(host_pc); if (tb) { cpu_restore_state_from_tb(cpu, tb, host_pc, will_exit); - if (tb->cflags & CF_NOCACHE) { + if (tb_cflags(tb) & CF_NOCACHE) { /* one-shot translation, invalidate it immediately */ tb_phys_invalidate(tb, -1); tcg_tb_remove(tb); @@ -1360,34 +1363,53 @@ static inline void tb_page_remove(PageDesc *pd, TranslationBlock *tb) g_assert_not_reached(); } -/* remove the TB from a list of TBs jumping to the n-th jump target of the TB */ -static inline void tb_remove_from_jmp_list(TranslationBlock *tb, int n) +/* remove @orig from its @n_orig-th jump list */ +static inline void tb_remove_from_jmp_list(TranslationBlock *orig, int n_orig) { - TranslationBlock *tb1; - uintptr_t *ptb, ntb; - unsigned int n1; + uintptr_t ptr, ptr_locked; + TranslationBlock *dest; + TranslationBlock *tb; + uintptr_t *pprev; + int n; - ptb = &tb->jmp_list_next[n]; - if (*ptb) { - /* find tb(n) in circular list */ - for (;;) { - ntb = *ptb; - n1 = ntb & 3; - tb1 = (TranslationBlock *)(ntb & ~3); - if (n1 == n && tb1 == tb) { - break; - } - if (n1 == 2) { - ptb = &tb1->jmp_list_first; - } else { - ptb = &tb1->jmp_list_next[n1]; - } - } - /* now we can suppress tb(n) from the list */ - *ptb = tb->jmp_list_next[n]; - - tb->jmp_list_next[n] = (uintptr_t)NULL; + /* mark the LSB of jmp_dest[] so that no further jumps can be inserted */ + ptr = atomic_or_fetch(&orig->jmp_dest[n_orig], 1); + dest = (TranslationBlock *)(ptr & ~1); + if (dest == NULL) { + return; } + + qemu_spin_lock(&dest->jmp_lock); + /* + * While acquiring the lock, the jump might have been removed if the + * destination TB was invalidated; check again. + */ + ptr_locked = atomic_read(&orig->jmp_dest[n_orig]); + if (ptr_locked != ptr) { + qemu_spin_unlock(&dest->jmp_lock); + /* + * The only possibility is that the jump was unlinked via + * tb_jump_unlink(dest). Seeing here another destination would be a bug, + * because we set the LSB above. + */ + g_assert(ptr_locked == 1 && dest->cflags & CF_INVALID); + return; + } + /* + * We first acquired the lock, and since the destination pointer matches, + * we know for sure that @orig is in the jmp list. + */ + pprev = &dest->jmp_list_head; + TB_FOR_EACH_JMP(dest, tb, n) { + if (tb == orig && n == n_orig) { + *pprev = tb->jmp_list_next[n]; + /* no need to set orig->jmp_dest[n]; setting the LSB was enough */ + qemu_spin_unlock(&dest->jmp_lock); + return; + } + pprev = &tb->jmp_list_next[n]; + } + g_assert_not_reached(); } /* reset the jump entry 'n' of a TB so that it is not chained to @@ -1399,24 +1421,21 @@ static inline void tb_reset_jump(TranslationBlock *tb, int n) } /* remove any jumps to the TB */ -static inline void tb_jmp_unlink(TranslationBlock *tb) +static inline void tb_jmp_unlink(TranslationBlock *dest) { - TranslationBlock *tb1; - uintptr_t *ptb, ntb; - unsigned int n1; + TranslationBlock *tb; + int n; - ptb = &tb->jmp_list_first; - for (;;) { - ntb = *ptb; - n1 = ntb & 3; - tb1 = (TranslationBlock *)(ntb & ~3); - if (n1 == 2) { - break; - } - tb_reset_jump(tb1, n1); - *ptb = tb1->jmp_list_next[n1]; - tb1->jmp_list_next[n1] = (uintptr_t)NULL; + qemu_spin_lock(&dest->jmp_lock); + + TB_FOR_EACH_JMP(dest, tb, n) { + tb_reset_jump(tb, n); + atomic_and(&tb->jmp_dest[n], (uintptr_t)NULL | 1); + /* No need to clear the list entry; setting the dest ptr is enough */ } + dest->jmp_list_head = (uintptr_t)NULL; + + qemu_spin_unlock(&dest->jmp_lock); } /* If @rm_from_page_list is set, call with the TB's pages' locks held */ @@ -1429,11 +1448,14 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) assert_tb_locked(); + /* make sure no further incoming jumps will be chained to this TB */ + qemu_spin_lock(&tb->jmp_lock); atomic_set(&tb->cflags, tb->cflags | CF_INVALID); + qemu_spin_unlock(&tb->jmp_lock); /* remove the TB from the hash list */ phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK); - h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags & CF_HASH_MASK, + h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb_cflags(tb) & CF_HASH_MASK, tb->trace_vcpu_dstate); if (!qht_remove(&tb_ctx.htable, tb, h)) { return; @@ -1773,10 +1795,12 @@ TranslationBlock *tb_gen_code(CPUState *cpu, CODE_GEN_ALIGN)); /* init jump list */ - assert(((uintptr_t)tb & 3) == 0); - tb->jmp_list_first = (uintptr_t)tb | 2; + qemu_spin_init(&tb->jmp_lock); + tb->jmp_list_head = (uintptr_t)NULL; tb->jmp_list_next[0] = (uintptr_t)NULL; tb->jmp_list_next[1] = (uintptr_t)NULL; + tb->jmp_dest[0] = (uintptr_t)NULL; + tb->jmp_dest[1] = (uintptr_t)NULL; /* init original jump addresses wich has been set during tcg_gen_code() */ if (tb->jmp_reset_offset[0] != TB_JMP_RESET_OFFSET_INVALID) { @@ -1868,7 +1892,7 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages, } } if (current_tb == tb && - (current_tb->cflags & CF_COUNT_MASK) != 1) { + (tb_cflags(current_tb) & CF_COUNT_MASK) != 1) { /* If we are modifying the current TB, we must stop its execution. We could be more precise by checking that the modification is after the current PC, but it @@ -2067,7 +2091,7 @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc) PAGE_FOR_EACH_TB(p, tb, n) { #ifdef TARGET_HAS_PRECISE_SMC if (current_tb == tb && - (current_tb->cflags & CF_COUNT_MASK) != 1) { + (tb_cflags(current_tb) & CF_COUNT_MASK) != 1) { /* If we are modifying the current TB, we must stop its execution. We could be more precise by checking that the modification is after the current PC, but it @@ -2192,7 +2216,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) /* Generate a new TB executing the I/O insn. */ cpu->cflags_next_tb = curr_cflags() | CF_LAST_IO | n; - if (tb->cflags & CF_NOCACHE) { + if (tb_cflags(tb) & CF_NOCACHE) { if (tb->orig_tb) { /* Invalidate original TB if this TB was generated in * cpu_exec_nocache() */ diff --git a/docs/devel/multi-thread-tcg.txt b/docs/devel/multi-thread-tcg.txt index faf09c6069..df83445ccf 100644 --- a/docs/devel/multi-thread-tcg.txt +++ b/docs/devel/multi-thread-tcg.txt @@ -131,8 +131,10 @@ DESIGN REQUIREMENT: Safely handle invalidation of TBs The direct jump themselves are updated atomically by the TCG tb_set_jmp_target() code. Modification to the linked lists that allow -searching for linked pages are done under the protect of the -tb_lock(). +searching for linked pages are done under the protection of tb->jmp_lock, +where tb is the destination block of a jump. Each origin block keeps a +pointer to its destinations so that the appropriate lock can be acquired before +iterating over a jump list. The global page table is a lockless radix tree; cmpxchg is used to atomically insert new elements. From patchwork Thu Jun 14 19:31:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138632 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2540702lji; Thu, 14 Jun 2018 12:53:40 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJ7eN82/YlkWhjj7ARukQE3cDpW1QeTITWELLH+xvKO5PrmTxoCCGLdegh7yRJ4yht7nUAc X-Received: by 2002:a37:1a0e:: with SMTP id a14-v6mr3624880qka.146.1529006020162; Thu, 14 Jun 2018 12:53:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529006020; cv=none; d=google.com; s=arc-20160816; b=JFNu9XH9dXvzlPSlyJKXwFS4jScD/JXReoryC4m4fPteUnn30t1XkaeZym+VfNqZWX t5sazeD3f0nl3aRADg9iqBWuCHO+UT+wpaUTcGApGB7+HGh3ZL/D493Pmox1/IAaAbyV 5hVL1+WDU0sao4qqeaHv8pDZZRKo37Hd7T3iOTTZuy6jSFtspZsGGcQX7lLamddTY2Fa /Ucee0wDkNjbc37CnTAal3akCXbp8dRNlP8zC7t6H4FyJdo0uKw7UMhgpA7KtM4yEgZM nwejmkQWBzi1OQIhb5TH2q7w16aGodo0W9WSgPGETjTRP7sv+m/OGlPojZUZOTfl22Va cx4g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=1bRKDGWKZCLgSDuPUlRc6n0F/WmiP6u9YX3vZUkLxH0=; b=ROw5rmRdzA2+y2Ybn1Hvk2sTZ2F48t+el271Ky2q2oUuXAapZQr/MeGnG1/W0uddaN 1Eb7s0IGkiao+tf79lEbTHvvVxHgEAfKWoURCYVDFmqob0CshL/JxRiU1JOGs0VdvCKF +ZJ/elafBccTLDhbAXVaG9IxPPZvrAOncIc0mLjbfp9Bvy3lcBcXOswFvCSbTgVPt7s/ 1q3gRLc/ICOSjYDfKzibXs0p9V4CdWvxKhm80TCPq7APyFHJaLWYjpLRXFyZ4nO4ErGC 4eEckWB9XBhR/jlmzd3ZAz7n06OEI7X8S0VrBl4ARyFsBiooZAIkktQ638H5OfL4M+sS 1TIw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=ElLISmQz; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id n10-v6si6173827qtn.198.2018.06.14.12.53.39 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:53:40 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=ElLISmQz; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42505 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTYJP-0007WJ-Ic for patch@linaro.org; Thu, 14 Jun 2018 15:53:39 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37241) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyt-0007EO-Ck for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyp-000622-Cb for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:27 -0400 Received: from mail-pg0-x244.google.com ([2607:f8b0:400e:c05::244]:38220) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyp-00061a-6j for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:23 -0400 Received: by mail-pg0-x244.google.com with SMTP id c9-v6so3364501pgf.5 for ; Thu, 14 Jun 2018 12:32:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1bRKDGWKZCLgSDuPUlRc6n0F/WmiP6u9YX3vZUkLxH0=; b=ElLISmQzkryUD4oY4fgl+nGO80wUIRgNLoRGyKwcC86u/cYOR2ZIRjxuu6jk1FQbmi kV6gDF+yPiS/2ZRqrK/MjM6jnFFKURZCslLjIRUZgVTIGVI2cIZuaqI5mhjV40YzookY muW1K2zeOS34LGKwl1Jq1bOvfFrj5ysahMVuw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1bRKDGWKZCLgSDuPUlRc6n0F/WmiP6u9YX3vZUkLxH0=; b=J62QpQZo4lm9XTW0tRGblkTWk2HqZ7+zXuD+DoHfNzjJIivnaRNt0K66gbHFtex+qZ skW5qAvNapp/5RXho68OL/7LNSvSmLsnhjXK00w/FXMSLL+g2AJ3KZXvSTNog0Rwh6Co 52RVG0eTND6Uu9B0YKCYPCUKCsZTDt3KSy5G1f08wjvT1fXz2HSZeGbj0cIjlAZUwTct 9QgdRE9/X1y+0OScAj1wRrlctHuIMIQPowc/Of5+S0iSKF21Y6OWzx1eU5Wr66fhERW/ APnbuOvrwjYEA4oXGE/4qRQoW1QErEV/9zxnT5e7tI8HLaoNV4AJOr/ePGwnXvd/j/hH UAqg== X-Gm-Message-State: APt69E2VnpfLx3DcDsNoxIP5aEDZtcFXEuCjLTf4iqckE4yjuP799X3v 9Qir6CepiPpC/He+gIcw43/sIm3pdFs= X-Received: by 2002:a63:370f:: with SMTP id e15-v6mr3392213pga.192.1529004741945; Thu, 14 Jun 2018 12:32:21 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.32.20 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:32:21 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:45 -1000 Message-Id: <20180614193147.29680-17-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::244 Subject: [Qemu-devel] [PULL 16/18] cputlb: remove tb_lock from tlb_flush functions 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" The acquisition of tb_lock was added when the async tlb_flush was introduced in e3b9ca810 ("cputlb: introduce tlb_flush_* async work.") tb_lock was there to allow us to do memset() on the tb_jmp_cache's. However, since f3ced3c5928 ("tcg: consistently access cpu->tb_jmp_cache atomically") all accesses to tb_jmp_cache are atomic, so tb_lock is not needed here. Get rid of it. Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 8 -------- 1 file changed, 8 deletions(-) -- 2.17.1 diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 05439039e9..f5c3a0926f 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -125,8 +125,6 @@ static void tlb_flush_nocheck(CPUState *cpu) atomic_set(&env->tlb_flush_count, env->tlb_flush_count + 1); tlb_debug("(count: %zu)\n", tlb_flush_count()); - tb_lock(); - memset(env->tlb_table, -1, sizeof(env->tlb_table)); memset(env->tlb_v_table, -1, sizeof(env->tlb_v_table)); cpu_tb_jmp_cache_clear(cpu); @@ -135,8 +133,6 @@ static void tlb_flush_nocheck(CPUState *cpu) env->tlb_flush_addr = -1; env->tlb_flush_mask = 0; - tb_unlock(); - atomic_mb_set(&cpu->pending_tlb_flush, 0); } @@ -180,8 +176,6 @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data) assert_cpu_is_self(cpu); - tb_lock(); - tlb_debug("start: mmu_idx:0x%04lx\n", mmu_idx_bitmask); for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) { @@ -197,8 +191,6 @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data) cpu_tb_jmp_cache_clear(cpu); tlb_debug("done\n"); - - tb_unlock(); } void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap) From patchwork Thu Jun 14 19:31:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138625 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2533252lji; Thu, 14 Jun 2018 12:45:52 -0700 (PDT) X-Google-Smtp-Source: ADUXVKLBMP6+9OcxNNsjItdg6d5sqyEaK3xZXeDrGD5xGKRD83vkpkNKxYu0T6qeHXgUR7Q4b5P4 X-Received: by 2002:a37:6e83:: with SMTP id j125-v6mr3394096qkc.237.1529005552164; Thu, 14 Jun 2018 12:45:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005552; cv=none; d=google.com; s=arc-20160816; b=is3kgGMSdECf+gfDtMGKPILPwg1gjQBwXyED0iwTRtmLkDLMnN7TVwMvKom+VaBHUq YZBgERPx1vp0bfVQob7Dhd97put6yX1v6zcygFv1AfKUrhiKbhAqFDpWYdWCbt39DxlJ +XkLgwBidl2/e04TKWVjKyOWwaBOKca7k2dFEBIbi0zzFH6X+dxEKwJUm7h9OhkNZB4Q qTKQscPn3PtnMT196ai9+SgVgxf0RB+tVUerPPOY/dcOXEU8oxYqBV4Z6RTzCa8D3vYc EhVHvzDq7zU6o6meuLMHJmU5Ptd3a9Naueo7iMWUEOfrc5akKOeCk9J0EBv7RgT+LNIV yh/Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=JoshgcfdaBoqxlZIOPmVeCLy50LoSRMC+doKT4JGKHw=; b=yUG4QEEx1JyhhiPr0yG/uLsM2eK2DY+pn/m2zoFlc4J67kaoLxe1LL4dJ1kIqFpNd8 N1y9/ZlRGMXKCPaasTfIBbUzbvAP4BzNEuX0gGpY4y9i8vg9Aj7Z8vTOpzs+uQHGGidX 7tOZIzlfJTSUjJ6w3RsHJGEwfgHtl3a9/jL9HTOGiXNyxQNd8CemEQMDeyDrVqYN79Vw oM1lecUhNVvvhQEQsbZmEHqcmbGgjddmquiLcaq3+GYq4w55t+kvg1bm3O1DDLNTJjF1 HQRPN2o7U+BWxteib5fTCrDStP+2fqrHgLcK3kHPLqvQJJSdwVwEQx993xxGEViAGuRs V7qQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=iAp7QIBE; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id l20-v6si2649646qta.87.2018.06.14.12.45.51 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:45:52 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=iAp7QIBE; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42429 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTYBr-0001Ih-IF for patch@linaro.org; Thu, 14 Jun 2018 15:45:51 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37239) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyt-0007EL-CI for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyr-00063P-4u for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:27 -0400 Received: from mail-pl0-x243.google.com ([2607:f8b0:400e:c01::243]:35331) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyq-000632-V4 for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:25 -0400 Received: by mail-pl0-x243.google.com with SMTP id k1-v6so4083772plt.2 for ; Thu, 14 Jun 2018 12:32:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=JoshgcfdaBoqxlZIOPmVeCLy50LoSRMC+doKT4JGKHw=; b=iAp7QIBE+m89xfSn3ObHBb3af3p6IeSknm8PyWzITN8V8PaN7bui/XtOWWEG9abQiR 1c8gjVOVKXqiArS5Mqe1yIEwpPGYZgGabHhRmZ+S/rTM83pF0CdnPBbj8OmGalpG4YeG 6Eh8FN1C7q13WqIx32HA37NGZtyjrW0UJDreg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=JoshgcfdaBoqxlZIOPmVeCLy50LoSRMC+doKT4JGKHw=; b=t1JeEap+E2oIVbqbP98iRCTb9raSUWd2UhG04sXhghErFP1ZRG+r7ccuqYf+JyU1Fl ggoYj+wh2qUBDpDWspT4VnYjyX00UzF9tefmZSzgxerJGcWO6hKwGNfRMbXAa5VvntUh MB2HjkTGf8S9cWz1ONZ7Qra38z/wqVeH0RG1QrCm/1uevmGXcOBmCRcWkrBOt9b7n5ar FaVvaihY25YJNNkp2ZYLBR28dK06pM23d8ESp7ezojqd3ppM0oBa26Wt8qTAyuqYbXMP MI2fuzz8ExgrLGKcxW4zbACvaq6N7Ijs47hWwbzN1IAW5XFhpKClwdHKBnwPF4LvdFod kXWA== X-Gm-Message-State: APt69E0tV639E1Jvg2Q9PaJ06A6v2dJgaD4OLFuo94SoX9wXtPRwmI9x 2cJ9emzamw6UmCQUMt+CbX9VtBN+EpU= X-Received: by 2002:a17:902:b488:: with SMTP id y8-v6mr4373354plr.157.1529004743808; Thu, 14 Jun 2018 12:32:23 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.32.22 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:32:22 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:46 -1000 Message-Id: <20180614193147.29680-18-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::243 Subject: [Qemu-devel] [PULL 17/18] translate-all: remove tb_lock mention from cpu_restore_state_from_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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" tb_lock was needed when the function did retranslation. However, since fca8a500d519 ("tcg: Save insn data and use it in cpu_restore_state_from_tb") we don't do retranslation. Get rid of the comment. Reviewed-by: Richard Henderson Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- accel/tcg/translate-all.c | 1 - 1 file changed, 1 deletion(-) -- 2.17.1 diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 41fbf1055a..dc36349fc7 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -355,7 +355,6 @@ static int encode_search(TranslationBlock *tb, uint8_t *block) } /* The cpu state corresponding to 'searched_pc' is restored. - * Called with tb_lock held. * When reset_icount is true, current TB will be interrupted and * icount should be recalculated. */ From patchwork Thu Jun 14 19:31:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 138631 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp2540423lji; Thu, 14 Jun 2018 12:53:19 -0700 (PDT) X-Google-Smtp-Source: ADUXVKL6S/x6Bz6hftGdjyLPi4lAVzFdRZ5JK8Ezf0q8mykSDdoEargwrudMZXC4Ef8EyBuWn9AX X-Received: by 2002:a37:f59:: with SMTP id z86-v6mr3423399qkg.234.1529005999329; Thu, 14 Jun 2018 12:53:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529005999; cv=none; d=google.com; s=arc-20160816; b=KZOF/AKIMAO9iCZ9IRFClAcTHT2i3kqJzScmQ+HD25rdyE/U8seMNcNI3T89bhLZqG Agl9272HqYeoseUlWTIQAUXVVAyd72a5MURsQRtRs3EqXp0yAFd6MpD3oxFQD30JUK2H E0qrHJh49oDbMT/OpqLonMk+h3CxwTzexg45rWbW4WT9E4FlAn3v6LKWjoOVrEhEg8K1 SHmra/TbfueB17hV7EN6edA6JH46/EoJyimuRAdW4VXjhQDU4orv+IzAbtBCu8dkTQ20 eeFB5DkOQ9HLQ1i3LhFogaCW0K9Giu6FUC51aTXRzuF0wl00vmI5mldZyPEHzIGTfoX+ uG/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=eEHLeAOl3SB+IpTsBoo8I6HARdeZeXuG/ghQgnHK5k0=; b=EgqMli1YjpE6q8+KMYg+pKKBmeA9obrT8itsAlgtWL8tqfYFdw4RcWPaOJuoFB6pk7 vg+mSBaVRcC3udkrewA5FlUi3epyukCiL+iWJG3UCp7Agl/mx8dRHN76/SlpQJm4aq7d KiEELDpe5HYb0/AJnl3agBusIC+IUfKfLE4GeV10q6+vi19c5Jq40kA2rcQe+DEqZ9jn RV1YqVyawAK3mpl8oT9NvmxPw4J9y0QqaqcH00PCdvNet40RtDHFEONV2K2qyzUe1eDM ZNZEfgcsM9E1ypuVDMrJicVKL6rcsruSVv99xhqEOrwRkQEYG0K9OOADLmEzrPfQI74Y Kb3A== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=gV2NgYkD; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id 21-v6si5615392qvr.240.2018.06.14.12.53.19 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 14 Jun 2018 12:53:19 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=gV2NgYkD; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:42501 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTYJ4-00072I-N8 for patch@linaro.org; Thu, 14 Jun 2018 15:53:18 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37312) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTXyx-0007IY-Ld for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTXyt-00066L-Tg for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:31 -0400 Received: from mail-pl0-x22c.google.com ([2607:f8b0:400e:c01::22c]:40971) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fTXyt-00064y-I2 for qemu-devel@nongnu.org; Thu, 14 Jun 2018 15:32:27 -0400 Received: by mail-pl0-x22c.google.com with SMTP id w8-v6so2562645ply.8 for ; Thu, 14 Jun 2018 12:32:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=eEHLeAOl3SB+IpTsBoo8I6HARdeZeXuG/ghQgnHK5k0=; b=gV2NgYkDNzNgeo19l8DiyRKq9Rv+Ef+Ed0V9Y0vVs7TvsYDmVadz2e7SJ/WolI7YFU 3TEXZOD4G06SjbwU6eGOdU73ahV3Y/kncXyilcBuRXNTWTxJXOZCV84Ba31imkPT5MsD RCdEPmSfHGtWIR0jU/+IgNOWMwW1hzH5nayGs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=eEHLeAOl3SB+IpTsBoo8I6HARdeZeXuG/ghQgnHK5k0=; b=Wg6u+GLRBj+sxJcthq7LVJGKlfWCddZk0BBYpn7FSQLhc7Xsq/V/rLi8cvlkKv7Ui7 sfi2IiIrkpij1EKCFuoWjoHjXLb/qGjO9mNHW3C4gF59DVZeGKoRdtzu8Y41c0FkvB01 j9EacSV3Q0jQMjvdFNPSPLYTUvnKaVfkGPmx/qDOAdC+mRaoSLIVyK9afonbxZqUxUTD k263vmMoLtHtonW7TKdd7c7ClNS9eGlq0loKKHFJV8GOXGKRbhuOX3h6VSbgepq5cew7 xusovltiC4db63LyxAd1eacCOFV8LxP3+NdpWN7HOiAZuxPxXZb1fVgSR700N35ySkkd XcYg== X-Gm-Message-State: APt69E3BrFQYhLvTigfuQtJ8IjDxGoBwzfqR4hFmh7oh06ZH5bnogad2 MWftt4qIetpUJ9Mn1ckRzbcAt5CyM/A= X-Received: by 2002:a17:902:6b45:: with SMTP id g5-v6mr4445577plt.67.1529004746106; Thu, 14 Jun 2018 12:32:26 -0700 (PDT) Received: from cloudburst.twiddle.net (rrcs-173-198-77-219.west.biz.rr.com. [173.198.77.219]) by smtp.gmail.com with ESMTPSA id x24-v6sm11532184pfj.104.2018.06.14.12.32.23 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Jun 2018 12:32:25 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 14 Jun 2018 09:31:47 -1000 Message-Id: <20180614193147.29680-19-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180614193147.29680-1-richard.henderson@linaro.org> References: <20180614193147.29680-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::22c Subject: [Qemu-devel] [PULL 18/18] tcg: remove tb_lock 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: peter.maydell@linaro.org, "Emilio G. Cota" Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: "Emilio G. Cota" Use mmap_lock in user-mode to protect TCG state and the page descriptors. In !user-mode, each vCPU has its own TCG state, so no locks needed. Per-page locks are used to protect the page descriptors. Per-TB locks are used in both modes to protect TB jumps. Some notes: - tb_lock is removed from notdirty_mem_write by passing a locked page_collection to tb_invalidate_phys_page_fast. - tcg_tb_lookup/remove/insert/etc have their own internal lock(s), so there is no need to further serialize access to them. - do_tb_flush is run in a safe async context, meaning no other vCPU threads are running. Therefore acquiring mmap_lock there is just to please tools such as thread sanitizer. - Not visible in the diff, but tb_invalidate_phys_page already has an assert_memory_lock. - cpu_io_recompile is !user-only, so no mmap_lock there. - Added mmap_unlock()'s before all siglongjmp's that could be called in user-mode while mmap_lock is held. + Added an assert for !have_mmap_lock() after returning from the longjmp in cpu_exec, just like we do in cpu_exec_step_atomic. Performance numbers before/after: Host: AMD Opteron(tm) Processor 6376 ubuntu 17.04 ppc64 bootup+shutdown time 700 +-+--+----+------+------------+-----------+------------*--+-+ | + + + + + *B | | before ***B*** ** * | |tb lock removal ###D### *** | 600 +-+ *** +-+ | ** # | | *B* #D | | *** * ## | 500 +-+ *** ### +-+ | * *** ### | | *B* # ## | | ** * #D# | 400 +-+ ** ## +-+ | ** ### | | ** ## | | ** # ## | 300 +-+ * B* #D# +-+ | B *** ### | | * ** #### | | * *** ### | 200 +-+ B *B #D# +-+ | #B* * ## # | | #* ## | | + D##D# + + + + | 100 +-+--+----+------+------------+-----------+------------+--+-+ 1 8 16 Guest CPUs 48 64 png: https://imgur.com/HwmBHXe debian jessie aarch64 bootup+shutdown time 90 +-+--+-----+-----+------------+------------+------------+--+-+ | + + + + + + | | before ***B*** B | 80 +tb lock removal ###D### **D +-+ | **### | | **## | 70 +-+ ** # +-+ | ** ## | | ** # | 60 +-+ *B ## +-+ | ** ## | | *** #D | 50 +-+ *** ## +-+ | * ** ### | | **B* ### | 40 +-+ **** # ## +-+ | **** #D# | | ***B** ### | 30 +-+ B***B** #### +-+ | B * * # ### | | B ###D# | 20 +-+ D ##D## +-+ | D# | | + + + + + + | 10 +-+--+-----+-----+------------+------------+------------+--+-+ 1 8 16 Guest CPUs 48 64 png: https://imgur.com/iGpGFtv The gains are high for 4-8 CPUs. Beyond that point, however, unrelated lock contention significantly hurts scalability. Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Signed-off-by: Emilio G. Cota Signed-off-by: Richard Henderson --- accel/tcg/translate-all.h | 3 +- include/exec/cpu-common.h | 2 +- include/exec/exec-all.h | 4 - include/exec/memory-internal.h | 6 +- include/exec/tb-context.h | 2 - tcg/tcg.h | 4 +- accel/tcg/cpu-exec.c | 34 ++------ accel/tcg/translate-all.c | 132 ++++++++++---------------------- exec.c | 26 +++---- linux-user/main.c | 3 - docs/devel/multi-thread-tcg.txt | 11 ++- 11 files changed, 75 insertions(+), 152 deletions(-) -- 2.17.1 diff --git a/accel/tcg/translate-all.h b/accel/tcg/translate-all.h index 6d1d2588b5..e6cb963d7e 100644 --- a/accel/tcg/translate-all.h +++ b/accel/tcg/translate-all.h @@ -26,7 +26,8 @@ struct page_collection *page_collection_lock(tb_page_addr_t start, tb_page_addr_t end); void page_collection_unlock(struct page_collection *set); -void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len); +void tb_invalidate_phys_page_fast(struct page_collection *pages, + tb_page_addr_t start, int len); void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, int is_cpu_write_access); void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end); diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 0b58e262f3..18b40d6145 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -23,7 +23,7 @@ typedef struct CPUListState { FILE *file; } CPUListState; -/* The CPU list lock nests outside tb_lock/tb_unlock. */ +/* The CPU list lock nests outside page_(un)lock or mmap_(un)lock */ void qemu_init_cpu_list(void); void cpu_list_lock(void); void cpu_list_unlock(void); diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 57e5a6e358..3126c0917c 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -440,10 +440,6 @@ extern uintptr_t tci_tb_ptr; smaller than 4 bytes, so we don't worry about special-casing this. */ #define GETPC_ADJ 2 -void tb_lock(void); -void tb_unlock(void); -void tb_lock_reset(void); - #if !defined(CONFIG_USER_ONLY) && defined(CONFIG_DEBUG_TCG) void assert_no_pages_locked(void); #else diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 56c25c0ef7..bb08fa4d2f 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -49,6 +49,8 @@ void mtree_print_dispatch(fprintf_function mon, void *f, struct AddressSpaceDispatch *d, MemoryRegion *root); +struct page_collection; + /* Opaque struct for passing info from memory_notdirty_write_prepare() * to memory_notdirty_write_complete(). Callers should treat all fields * as private, with the exception of @active. @@ -60,10 +62,10 @@ void mtree_print_dispatch(fprintf_function mon, void *f, */ typedef struct { CPUState *cpu; + struct page_collection *pages; ram_addr_t ram_addr; vaddr mem_vaddr; unsigned size; - bool locked; bool active; } NotDirtyInfo; @@ -91,7 +93,7 @@ typedef struct { * * This must only be called if we are using TCG; it will assert otherwise. * - * We may take a lock in the prepare call, so callers must ensure that + * We may take locks in the prepare call, so callers must ensure that * they don't exit (via longjump or otherwise) without calling complete. * * This call must only be made inside an RCU critical section. diff --git a/include/exec/tb-context.h b/include/exec/tb-context.h index 8c9b49c98e..feb585e0a7 100644 --- a/include/exec/tb-context.h +++ b/include/exec/tb-context.h @@ -32,8 +32,6 @@ typedef struct TBContext TBContext; struct TBContext { struct qht htable; - /* any access to the tbs or the page table must use this lock */ - QemuMutex tb_lock; /* statistics */ unsigned tb_flush_count; diff --git a/tcg/tcg.h b/tcg/tcg.h index e49b289ba1..532d2a0710 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -857,7 +857,7 @@ static inline bool tcg_op_buf_full(void) /* pool based memory allocation */ -/* user-mode: tb_lock must be held for tcg_malloc_internal. */ +/* user-mode: mmap_lock must be held for tcg_malloc_internal. */ void *tcg_malloc_internal(TCGContext *s, int size); void tcg_pool_reset(TCGContext *s); TranslationBlock *tcg_tb_alloc(TCGContext *s); @@ -875,7 +875,7 @@ TranslationBlock *tcg_tb_lookup(uintptr_t tc_ptr); void tcg_tb_foreach(GTraverseFunc func, gpointer user_data); size_t tcg_nb_tbs(void); -/* user-mode: Called with tb_lock held. */ +/* user-mode: Called with mmap_lock held. */ static inline void *tcg_malloc(int size) { TCGContext *s = tcg_ctx; diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index c482008bc7..c738b7f7d6 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -212,20 +212,20 @@ static void cpu_exec_nocache(CPUState *cpu, int max_cycles, We only end up here when an existing TB is too long. */ cflags |= MIN(max_cycles, CF_COUNT_MASK); - tb_lock(); + mmap_lock(); tb = tb_gen_code(cpu, orig_tb->pc, orig_tb->cs_base, orig_tb->flags, cflags); tb->orig_tb = orig_tb; - tb_unlock(); + mmap_unlock(); /* execute the generated code */ trace_exec_tb_nocache(tb, tb->pc); cpu_tb_exec(cpu, tb); - tb_lock(); + mmap_lock(); tb_phys_invalidate(tb, -1); + mmap_unlock(); tcg_tb_remove(tb); - tb_unlock(); } #endif @@ -244,9 +244,7 @@ void cpu_exec_step_atomic(CPUState *cpu) tb = tb_lookup__cpu_state(cpu, &pc, &cs_base, &flags, cf_mask); if (tb == NULL) { mmap_lock(); - tb_lock(); tb = tb_gen_code(cpu, pc, cs_base, flags, cflags); - tb_unlock(); mmap_unlock(); } @@ -261,15 +259,13 @@ void cpu_exec_step_atomic(CPUState *cpu) cpu_tb_exec(cpu, tb); cc->cpu_exec_exit(cpu); } else { - /* We may have exited due to another problem here, so we need - * to reset any tb_locks we may have taken but didn't release. + /* * The mmap_lock is dropped by tb_gen_code if it runs out of * memory. */ #ifndef CONFIG_SOFTMMU tcg_debug_assert(!have_mmap_lock()); #endif - tb_lock_reset(); assert_no_pages_locked(); } @@ -398,20 +394,11 @@ static inline TranslationBlock *tb_find(CPUState *cpu, TranslationBlock *tb; target_ulong cs_base, pc; uint32_t flags; - bool acquired_tb_lock = false; tb = tb_lookup__cpu_state(cpu, &pc, &cs_base, &flags, cf_mask); if (tb == NULL) { - /* mmap_lock is needed by tb_gen_code, and mmap_lock must be - * taken outside tb_lock. As system emulation is currently - * single threaded the locks are NOPs. - */ mmap_lock(); - tb_lock(); - acquired_tb_lock = true; - tb = tb_gen_code(cpu, pc, cs_base, flags, cf_mask); - mmap_unlock(); /* We add the TB in the virtual pc hash table for the fast lookup */ atomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb); @@ -427,15 +414,8 @@ static inline TranslationBlock *tb_find(CPUState *cpu, #endif /* See if we can patch the calling TB. */ if (last_tb && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) { - if (!acquired_tb_lock) { - tb_lock(); - acquired_tb_lock = true; - } tb_add_jump(last_tb, tb_exit, tb); } - if (acquired_tb_lock) { - tb_unlock(); - } return tb; } @@ -710,7 +690,9 @@ int cpu_exec(CPUState *cpu) g_assert(cpu == current_cpu); g_assert(cc == CPU_GET_CLASS(cpu)); #endif /* buggy compiler */ - tb_lock_reset(); +#ifndef CONFIG_SOFTMMU + tcg_debug_assert(!have_mmap_lock()); +#endif if (qemu_mutex_iothread_locked()) { qemu_mutex_unlock_iothread(); } diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index dc36349fc7..147e47dc64 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -88,13 +88,13 @@ #endif /* Access to the various translations structures need to be serialised via locks - * for consistency. This is automatic for SoftMMU based system - * emulation due to its single threaded nature. In user-mode emulation - * access to the memory related structures are protected with the - * mmap_lock. + * for consistency. + * In user-mode emulation access to the memory related structures are protected + * with mmap_lock. + * In !user-mode we use per-page locks. */ #ifdef CONFIG_SOFTMMU -#define assert_memory_lock() tcg_debug_assert(have_tb_lock) +#define assert_memory_lock() #else #define assert_memory_lock() tcg_debug_assert(have_mmap_lock()) #endif @@ -216,9 +216,6 @@ __thread TCGContext *tcg_ctx; TBContext tb_ctx; bool parallel_cpus; -/* translation block context */ -static __thread int have_tb_lock; - static void page_table_config_init(void) { uint32_t v_l1_bits; @@ -239,31 +236,6 @@ static void page_table_config_init(void) assert(v_l2_levels >= 0); } -#define assert_tb_locked() tcg_debug_assert(have_tb_lock) -#define assert_tb_unlocked() tcg_debug_assert(!have_tb_lock) - -void tb_lock(void) -{ - assert_tb_unlocked(); - qemu_mutex_lock(&tb_ctx.tb_lock); - have_tb_lock++; -} - -void tb_unlock(void) -{ - assert_tb_locked(); - have_tb_lock--; - qemu_mutex_unlock(&tb_ctx.tb_lock); -} - -void tb_lock_reset(void) -{ - if (have_tb_lock) { - qemu_mutex_unlock(&tb_ctx.tb_lock); - have_tb_lock = 0; - } -} - void cpu_gen_init(void) { tcg_context_init(&tcg_init_ctx); @@ -420,8 +392,7 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit) * - fault during translation (instruction fetch) * - fault from helper (not using GETPC() macro) * - * Either way we need return early to avoid blowing up on a - * recursive tb_lock() as we can't resolve it here. + * Either way we need return early as we can't resolve it here. * * We are using unsigned arithmetic so if host_pc < * tcg_init_ctx.code_gen_buffer check_offset will wrap to way @@ -430,7 +401,6 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit) check_offset = host_pc - (uintptr_t) tcg_init_ctx.code_gen_buffer; if (check_offset < tcg_init_ctx.code_gen_buffer_size) { - tb_lock(); tb = tcg_tb_lookup(host_pc); if (tb) { cpu_restore_state_from_tb(cpu, tb, host_pc, will_exit); @@ -441,7 +411,6 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit) } r = true; } - tb_unlock(); } return r; @@ -1130,7 +1099,6 @@ static inline void code_gen_alloc(size_t tb_size) fprintf(stderr, "Could not allocate dynamic translator buffer\n"); exit(1); } - qemu_mutex_init(&tb_ctx.tb_lock); } static bool tb_cmp(const void *ap, const void *bp) @@ -1174,14 +1142,12 @@ void tcg_exec_init(unsigned long tb_size) /* * Allocate a new translation block. Flush the translation buffer if * too many translation blocks or too much generated code. - * - * Called with tb_lock held. */ static TranslationBlock *tb_alloc(target_ulong pc) { TranslationBlock *tb; - assert_tb_locked(); + assert_memory_lock(); tb = tcg_tb_alloc(tcg_ctx); if (unlikely(tb == NULL)) { @@ -1248,8 +1214,7 @@ static gboolean tb_host_size_iter(gpointer key, gpointer value, gpointer data) /* flush all the translation blocks */ static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count) { - tb_lock(); - + mmap_lock(); /* If it is already been done on request of another CPU, * just retry. */ @@ -1279,7 +1244,7 @@ static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count) atomic_mb_set(&tb_ctx.tb_flush_count, tb_ctx.tb_flush_count + 1); done: - tb_unlock(); + mmap_unlock(); } void tb_flush(CPUState *cpu) @@ -1313,7 +1278,7 @@ do_tb_invalidate_check(struct qht *ht, void *p, uint32_t hash, void *userp) /* verify that all the pages have correct rights for code * - * Called with tb_lock held. + * Called with mmap_lock held. */ static void tb_invalidate_check(target_ulong address) { @@ -1343,7 +1308,10 @@ static void tb_page_check(void) #endif /* CONFIG_USER_ONLY */ -/* call with @pd->lock held */ +/* + * user-mode: call with mmap_lock held + * !user-mode: call with @pd->lock held + */ static inline void tb_page_remove(PageDesc *pd, TranslationBlock *tb) { TranslationBlock *tb1; @@ -1437,7 +1405,11 @@ static inline void tb_jmp_unlink(TranslationBlock *dest) qemu_spin_unlock(&dest->jmp_lock); } -/* If @rm_from_page_list is set, call with the TB's pages' locks held */ +/* + * In user-mode, call with mmap_lock held. + * In !user-mode, if @rm_from_page_list is set, call with the TB's pages' + * locks held. + */ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) { CPUState *cpu; @@ -1445,7 +1417,7 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) uint32_t h; tb_page_addr_t phys_pc; - assert_tb_locked(); + assert_memory_lock(); /* make sure no further incoming jumps will be chained to this TB */ qemu_spin_lock(&tb->jmp_lock); @@ -1498,7 +1470,7 @@ static void tb_phys_invalidate__locked(TranslationBlock *tb) /* invalidate one TB * - * Called with tb_lock held. + * Called with mmap_lock held in user-mode. */ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) { @@ -1543,7 +1515,7 @@ static void build_page_bitmap(PageDesc *p) /* add the tb in the target page and protect it if necessary * * Called with mmap_lock held for user-mode emulation. - * Called with @p->lock held. + * Called with @p->lock held in !user-mode. */ static inline void tb_page_add(PageDesc *p, TranslationBlock *tb, unsigned int n, tb_page_addr_t page_addr) @@ -1815,10 +1787,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu, if ((pc & TARGET_PAGE_MASK) != virt_page2) { phys_page2 = get_page_addr_code(env, virt_page2); } - /* As long as consistency of the TB stuff is provided by tb_lock in user - * mode and is implicit in single-threaded softmmu emulation, no explicit - * memory barrier is required before tb_link_page() makes the TB visible - * through the physical hash table and physical page list. + /* + * No explicit memory barrier is required -- tb_link_page() makes the + * TB visible in a consistent state. */ existing_tb = tb_link_page(tb, phys_pc, phys_page2); /* if the TB already exists, discard what we just translated */ @@ -1834,8 +1805,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu, } /* - * Call with all @pages locked. * @p must be non-NULL. + * user-mode: call with mmap_lock held. + * !user-mode: call with all @pages locked. */ static void tb_invalidate_phys_page_range__locked(struct page_collection *pages, @@ -1920,6 +1892,7 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages, page_collection_unlock(pages); /* Force execution of one insn next time. */ cpu->cflags_next_tb = 1 | curr_cflags(); + mmap_unlock(); cpu_loop_exit_noexc(cpu); } #endif @@ -1932,8 +1905,7 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages, * access: the virtual CPU will exit the current TB if code is modified inside * this TB. * - * Called with tb_lock/mmap_lock held for user-mode emulation - * Called with tb_lock held for system-mode emulation + * Called with mmap_lock held for user-mode emulation */ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, int is_cpu_write_access) @@ -1942,7 +1914,6 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, PageDesc *p; assert_memory_lock(); - assert_tb_locked(); p = page_find(start >> TARGET_PAGE_BITS); if (p == NULL) { @@ -1961,14 +1932,15 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, * access: the virtual CPU will exit the current TB if code is modified inside * this TB. * - * Called with mmap_lock held for user-mode emulation, grabs tb_lock - * Called with tb_lock held for system-mode emulation + * Called with mmap_lock held for user-mode emulation. */ -static void tb_invalidate_phys_range_1(tb_page_addr_t start, tb_page_addr_t end) +void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end) { struct page_collection *pages; tb_page_addr_t next; + assert_memory_lock(); + pages = page_collection_lock(start, end); for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; start < end; @@ -1984,30 +1956,16 @@ static void tb_invalidate_phys_range_1(tb_page_addr_t start, tb_page_addr_t end) page_collection_unlock(pages); } -#ifdef CONFIG_SOFTMMU -void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end) -{ - assert_tb_locked(); - tb_invalidate_phys_range_1(start, end); -} -#else -void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end) -{ - assert_memory_lock(); - tb_lock(); - tb_invalidate_phys_range_1(start, end); - tb_unlock(); -} -#endif - #ifdef CONFIG_SOFTMMU /* len must be <= 8 and start must be a multiple of len. * Called via softmmu_template.h when code areas are written to with * iothread mutex not held. + * + * Call with all @pages in the range [@start, @start + len[ locked. */ -void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len) +void tb_invalidate_phys_page_fast(struct page_collection *pages, + tb_page_addr_t start, int len) { - struct page_collection *pages; PageDesc *p; #if 0 @@ -2026,7 +1984,6 @@ void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len) return; } - pages = page_collection_lock(start, start + len); assert_page_locked(p); if (!p->code_bitmap && ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD) { @@ -2045,7 +2002,6 @@ void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len) do_invalidate: tb_invalidate_phys_page_range__locked(pages, p, start, start + len, 1); } - page_collection_unlock(pages); } #else /* Called with mmap_lock held. If pc is not 0 then it indicates the @@ -2077,7 +2033,6 @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc) return false; } - tb_lock(); #ifdef TARGET_HAS_PRECISE_SMC if (p->first_tb && pc != 0) { current_tb = tcg_tb_lookup(pc); @@ -2110,12 +2065,9 @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc) if (current_tb_modified) { /* Force execution of one insn next time. */ cpu->cflags_next_tb = 1 | curr_cflags(); - /* tb_lock will be reset after cpu_loop_exit_noexc longjmps - * back into the cpu_exec loop. */ return true; } #endif - tb_unlock(); return false; } @@ -2136,18 +2088,18 @@ void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs) return; } ram_addr = memory_region_get_ram_addr(mr) + addr; - tb_lock(); tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0); - tb_unlock(); rcu_read_unlock(); } #endif /* !defined(CONFIG_USER_ONLY) */ -/* Called with tb_lock held. */ +/* user-mode: call with mmap_lock held */ void tb_check_watchpoint(CPUState *cpu) { TranslationBlock *tb; + assert_memory_lock(); + tb = tcg_tb_lookup(cpu->mem_io_pc); if (tb) { /* We can use retranslation to find the PC. */ @@ -2181,7 +2133,6 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) TranslationBlock *tb; uint32_t n; - tb_lock(); tb = tcg_tb_lookup(retaddr); if (!tb) { cpu_abort(cpu, "cpu_io_recompile: could not find TB for pc=%p", @@ -2229,9 +2180,6 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) * repeating the fault, which is horribly inefficient. * Better would be to execute just this insn uncached, or generate a * second new TB. - * - * cpu_loop_exit_noexc will longjmp back to cpu_exec where the - * tb_lock gets reset. */ cpu_loop_exit_noexc(cpu); } diff --git a/exec.c b/exec.c index f6645ede0c..9157912b56 100644 --- a/exec.c +++ b/exec.c @@ -893,9 +893,7 @@ const char *parse_cpu_model(const char *cpu_model) static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) { mmap_lock(); - tb_lock(); tb_invalidate_phys_page_range(pc, pc + 1, 0); - tb_unlock(); mmap_unlock(); } #else @@ -2506,21 +2504,21 @@ void memory_notdirty_write_prepare(NotDirtyInfo *ndi, ndi->ram_addr = ram_addr; ndi->mem_vaddr = mem_vaddr; ndi->size = size; - ndi->locked = false; + ndi->pages = NULL; assert(tcg_enabled()); if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) { - ndi->locked = true; - tb_lock(); - tb_invalidate_phys_page_fast(ram_addr, size); + ndi->pages = page_collection_lock(ram_addr, ram_addr + size); + tb_invalidate_phys_page_fast(ndi->pages, ram_addr, size); } } /* Called within RCU critical section. */ void memory_notdirty_write_complete(NotDirtyInfo *ndi) { - if (ndi->locked) { - tb_unlock(); + if (ndi->pages) { + page_collection_unlock(ndi->pages); + ndi->pages = NULL; } /* Set both VGA and migration bits for simplicity and to remove @@ -2622,18 +2620,16 @@ static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags) } cpu->watchpoint_hit = wp; - /* Both tb_lock and iothread_mutex will be reset when - * cpu_loop_exit or cpu_loop_exit_noexc longjmp - * back into the cpu_exec main loop. - */ - tb_lock(); + mmap_lock(); tb_check_watchpoint(cpu); if (wp->flags & BP_STOP_BEFORE_ACCESS) { cpu->exception_index = EXCP_DEBUG; + mmap_unlock(); cpu_loop_exit(cpu); } else { /* Force execution of one insn next time. */ cpu->cflags_next_tb = 1 | curr_cflags(); + mmap_unlock(); cpu_loop_exit_noexc(cpu); } } @@ -3052,9 +3048,9 @@ static void invalidate_and_set_dirty(MemoryRegion *mr, hwaddr addr, } if (dirty_log_mask & (1 << DIRTY_MEMORY_CODE)) { assert(tcg_enabled()); - tb_lock(); + mmap_lock(); tb_invalidate_phys_range(addr, addr + length); - tb_unlock(); + mmap_unlock(); dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE); } cpu_physical_memory_set_dirty_range(addr, length, dirty_log_mask); diff --git a/linux-user/main.c b/linux-user/main.c index 78d6d3e7eb..84e9ec9335 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -120,7 +120,6 @@ void fork_start(void) { start_exclusive(); mmap_fork_start(); - qemu_mutex_lock(&tb_ctx.tb_lock); cpu_list_lock(); } @@ -136,14 +135,12 @@ void fork_end(int child) QTAILQ_REMOVE(&cpus, cpu, node); } } - qemu_mutex_init(&tb_ctx.tb_lock); qemu_init_cpu_list(); gdbserver_fork(thread_cpu); /* qemu_init_cpu_list() takes care of reinitializing the * exclusive state, so we don't need to end_exclusive() here. */ } else { - qemu_mutex_unlock(&tb_ctx.tb_lock); cpu_list_unlock(); end_exclusive(); } diff --git a/docs/devel/multi-thread-tcg.txt b/docs/devel/multi-thread-tcg.txt index df83445ccf..06530be1e9 100644 --- a/docs/devel/multi-thread-tcg.txt +++ b/docs/devel/multi-thread-tcg.txt @@ -61,6 +61,7 @@ have their block-to-block jumps patched. Global TCG State ---------------- +### User-mode emulation We need to protect the entire code generation cycle including any post generation patching of the translated code. This also implies a shared translation buffer which contains code running on all cores. Any @@ -75,9 +76,11 @@ patching. (Current solution) -Mainly as part of the linux-user work all code generation is -serialised with a tb_lock(). For the SoftMMU tb_lock() also takes the -place of mmap_lock() in linux-user. +Code generation is serialised with mmap_lock(). + +### !User-mode emulation +Each vCPU has its own TCG context and associated TCG region, thereby +requiring no locking. Translation Blocks ------------------ @@ -195,7 +198,7 @@ work as "safe work" and exiting the cpu run loop. This ensure by the time execution restarts all flush operations have completed. TLB flag updates are all done atomically and are also protected by the -tb_lock() which is used by the functions that update the TLB in bulk. +corresponding page lock. (Known limitation)