From patchwork Thu May 10 20:41:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Moger, Babu" X-Patchwork-Id: 10392463 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id ABC1860236 for ; Thu, 10 May 2018 20:47:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9936128CF8 for ; Thu, 10 May 2018 20:47:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8C93D28CFB; Thu, 10 May 2018 20:47:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAD_ENC_HEADER,BAYES_00, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 26AB528CF8 for ; Thu, 10 May 2018 20:47:20 +0000 (UTC) Received: from localhost ([::1]:35570 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fGsT9-00050A-GX for patchwork-qemu-devel@patchwork.kernel.org; Thu, 10 May 2018 16:47:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57146) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fGsOB-0005PX-7n for qemu-devel@nongnu.org; Thu, 10 May 2018 16:42:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fGsO7-0004WU-GM for qemu-devel@nongnu.org; Thu, 10 May 2018 16:42:11 -0400 Received: from mail-sn1nam01on0041.outbound.protection.outlook.com ([104.47.32.41]:36736 helo=NAM01-SN1-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fGsO7-0004Vg-70 for qemu-devel@nongnu.org; Thu, 10 May 2018 16:42:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector1-amd-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=2iULzvNMLIPrzuWbZN3SjQNVff9TIiRl2/ZYWFL3I6c=; b=LKJrmJgMaJSuHpCiN1u0eWRqeOpArWgBTTM5lOhOJaJceZ/NiU4vL7yHnPNBppVKj7ZvFDRj3kBgk2r83q153NvzJZ6VFGPVTJG3fHNlcFynH5dzoycK6VJn0eh06ZrJUo3+cJvfkNrt8dLtaE+9JMpydSGsAqfa2onZldWAlXo= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Babu.Moger@amd.com; Received: from bmoger-ubuntu.amd.com (165.204.78.1) by SN1PR12MB2478.namprd12.prod.outlook.com (2603:10b6:802:29::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.755.16; Thu, 10 May 2018 20:42:03 +0000 From: Babu Moger To: mst@redhat.com, marcel.apfelbaum@gmail.com, pbonzini@redhat.com, rth@twiddle.net, ehabkost@redhat.com, mtosatti@redhat.com Date: Thu, 10 May 2018 15:41:41 -0500 Message-Id: <20180510204148.11687-2-babu.moger@amd.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180510204148.11687-1-babu.moger@amd.com> References: <20180510204148.11687-1-babu.moger@amd.com> MIME-Version: 1.0 X-Originating-IP: [165.204.78.1] X-ClientProxiedBy: SN4PR0801CA0024.namprd08.prod.outlook.com (2603:10b6:803:29::34) To SN1PR12MB2478.namprd12.prod.outlook.com (2603:10b6:802:29::17) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(4534165)(4627221)(201703031133081)(201702281549075)(5600026)(48565401081)(2017052603328)(7153060)(7193020); SRVR:SN1PR12MB2478; X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB2478; 3:J1VN0i5zKDfwzLnv9CX0FuyYbBkSEbXpg3o1/aFZUoV9/rDztTNznhVCPdWDilsOr1i2fJmutemutlSQ/QBkA5cmSVQi8WcGQZ8mlULIM23NtUfImXO9DlFBR50K6fsf1JpZqJz9X9VZWxfRAfvr6Ghe3q/bmK1m5jnSU/EDIMzkQLAaoanipMk9rGFplhMVT1zLNjF9niKPhvrOmxI0hqoaz/ND3THOpSqXz0Zcoph1yPecxR4vYJGvaum0mYo/; 25:BuFaoAUHBu4y7b/rDCdkxzpnPcOR2VYK6pPOLZXDXEJfVhK3VS/RWqIIOhqPhlD05CnQ/2H0P0CKn+Cdn0XEdX61uHtkM7xLVpT19BXWPfc4HhXteyf6kOSACRCdQujGpzgM1o0ajMhIckTm4jILMHiEAhLdK/ctz9s85mRR8Gpxf0QfiIlwgstPf2q2J+P15hLohmlwXTkA/5RRwR+CQ0AxRbq57MF3+bdxIw7pQsB4TYtYAmhMN9kY3sj5CpYR8kimfTF0Y0rMJDN11Q2tGD0dqScj+rtw/SUI6wS88xwQZH6wS/rRzLzCLr8Q8mKiieC4mEXFkI8eAaGjw/7AlQ==; 31:wxsVP1sILOGYOsb11YcXxc4oQZTuVyzjjRyqRN+z0HCMVFAOvqyOkUrz0bCJDaRALcN6OLPGleTmUh8fo5kEuclwwcmrGCeRBiSL8FX+xOjY5pVhaiGJH+swDClW7OllRfFblO6vHFj4bDfDQMGhqO7m7E0ePkr4N4JSQwoal3D/BMbLSPwznCyqIThgH7Civ3h81i+O8Qye2vGMrVq0r/uTjHSM0o6q8+HQA194Vvs= X-MS-TrafficTypeDiagnostic: SN1PR12MB2478: X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB2478; 20:gSZDkltlgcKHdX/opGOi5KV2JNqcTa7SMlDzIQXl4D9Sn6pgejExnizIQJr9NBhU28vW7nIcmnz0N145cS9dio8M+tS07KSKTYeiYdGBf7B9Bk+IBWvCKXx73SWb6E1DioA/WTspNBExNx9DUJAR1sD0IIDIINhJSd74qhMIKUgSNRpd7+LUKm7t6a4K6w0XdWl7ANuMnR3MJtGWOKpQ7MpgNzkWSk9lATyqcTTGiLHUKnbxIAOUYdkPX5WES6FeBzYuulyQkBesGMKlyx20X38pja14GUyIrUJbyvVJnfUP4SWGnkyUrX99FME70ZnWdkJHoREovLIW0k/3D7dtA27jquWMM2/6G8r6IWxHks88An4vkf4E7gtcqWAYDUD8meepazHssjoN18vbdh5jj5Lz2U/xAJJezNQml7tfQt7zoZHslsiFhWbvbjqGjReYJq61bAphsNxQEUs0fZpSAbOMZ7lqeJYeV1Rlg0upwtj4xJZX5Thffh57uKqdT6Lh; 4:mHFQprzH/+IVfPZSpqcCc9k3/PLS6s+MO1s1NkbFschqVcFBpSta2aVwsubsggYbVufI+P+VlnNzs06vYIfaqUrm7ik4LFtAVnSXfeRAGziq+tM4/oHS8RZP7ymX5U5x3vSJoRMAAyY8RrrmT84jspHq0UFSrP764HHBELAW5INKPhsXK2NYYjYGGFQvVpmBUloAbrZOkIN3AwHAp8KabtPe4DK39J0qL+GlT/n293D7ZDgPhy9TspV5cg9NfSzoHyubBjkOQpfJINPygSRyMTjAb0UjOiUe+eK64kLYs2FRvmtetd1mrpS0PTZIlyIN X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(767451399110); X-MS-Exchange-SenderADCheck: 1 X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(5005006)(8121501046)(10201501046)(3002001)(93006095)(93001095)(3231254)(944501410)(52105095)(6055026)(149027)(150027)(6041310)(20161123558120)(20161123562045)(20161123560045)(20161123564045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(6072148)(201708071742011); SRVR:SN1PR12MB2478; BCL:0; PCL:0; RULEID:; SRVR:SN1PR12MB2478; X-Forefront-PRVS: 066898046A X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(346002)(366004)(376002)(396003)(39860400002)(39380400002)(189003)(199004)(476003)(446003)(48376002)(50466002)(50226002)(2616005)(53936002)(76176011)(97736004)(4326008)(11346002)(16526019)(8676002)(86362001)(186003)(7736002)(956004)(44832011)(305945005)(6486002)(81156014)(2906002)(575784001)(8936002)(52116002)(7696005)(59450400001)(486006)(81166006)(386003)(3846002)(26005)(25786009)(68736007)(51416003)(106356001)(5660300001)(316002)(36756003)(16586007)(105586002)(53416004)(7416002)(6666003)(6116002)(39060400002)(72206003)(66066001)(478600001)(47776003)(1076002)(19627235001); DIR:OUT; SFP:1101; SCL:1; SRVR:SN1PR12MB2478; H:bmoger-ubuntu.amd.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; MX:1; A:1; Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; SN1PR12MB2478; 23:qwkhrZAAgfvNcNOupcRUOvM8CfsyvVxa3DKuCDKtr?= =?us-ascii?Q?Ms2rvlMYnY71kuvb4CA4cJURdWgI5P+XM0/ppPyiUZzuf5jcXyLh/iyTemZ6?= =?us-ascii?Q?mPXAVbH67dJqA8yV2subNs0Yc0GvssR0mHmQWtY4YGg/UooKgG2b9b6spnLe?= =?us-ascii?Q?XMucYfkm9PEwx9sztFpLWImYatKKLZsmyUfXRefRZkK+HGvEJAbt+tG0w3/n?= =?us-ascii?Q?MHeUZTt/5Rm8ENh05op14ZmTGZZFPa8BFcT6cZ7cLQUN4PH85VLiIG+zkve7?= =?us-ascii?Q?8UOtqwgHYJUSHpaLpna+w8EbXy0Qi3fc+tmvhlDuQVQsWCAS4uzFRovsZyhx?= =?us-ascii?Q?/ugbLCJcrsc9wQnUqnDUgIuZPMuUI2iLDSDGYLK7TsBdr6eL7H5/W6cR7Qwf?= =?us-ascii?Q?RYoHN06A1xT2FVEHRjgY5d9PJZUEDRyeyZppOL8sO8pXsgtnmqnLqCxSheg5?= =?us-ascii?Q?ZVhN05oLpUCMoLc48/Qyx+gdyrcj7000YBkNYcu0M9zhwekYOz/lh+n2RHHL?= =?us-ascii?Q?YJUWhhTYMu7PVtVLfv5RpdmC/9+fBlPonL+7zetlH5M5c97JotMBhN7i3RyU?= =?us-ascii?Q?v+cIglmfxFGipX/TpPbIV9eDE2GQoqbVUgyg9d2ARiC1M2nqUOpp0iKjcIJI?= =?us-ascii?Q?3+gdOpBAStIbpX2PSJP9sPR5x88P1IjN03IAfLT/TqjX3z9vOQME7jv94onP?= =?us-ascii?Q?pMfQR6gLwBtTeomGd4HVYMJLI2BeLknudcj9aOqV5642TkV39KN0+WQGjrHY?= =?us-ascii?Q?od/o+aqBAme3mu4+Nk3kD3EUNv1L6N1lg7dQ3s3HRrVeeI89skjD5NHFsFen?= =?us-ascii?Q?mV1AvrVXvbozRq2VPTTJRsunhFqriPAvb5X/wKlqSzhGfyySfOaEJemtdh5x?= =?us-ascii?Q?Yi5MsjY+3HdAMdog6JIF/8gz7E80wziNhafaucXWGwFVxmW9o9FDmMWUiX3E?= =?us-ascii?Q?NOixLAsoX+3H6OWhVHafiBQOpl3PC990PGVs7odo0X0c5LZq5XaZ2a6FwChM?= =?us-ascii?Q?Ka3tAR4PY054Vk++APm751Z3txDzjskNtDO3o1zqQNwck6dbROANrL4AcPvW?= =?us-ascii?Q?dgt0xLUoa763oktvzVgtuxboX4Hu+8bVSGAxhMJU8HtveOROhoFADkY64MqZ?= =?us-ascii?Q?fuXkqVnIAV6w6YlkCLQVefOMa0CFp4chbdh2VRD1FXaEkqDNTx2ccEsakCZE?= =?us-ascii?Q?kMYLl7Wf4cUYlc/ktN7/7kApCnSH4x2dNV3CgHiHqTjPaKao9QXf2oQ5rpdz?= =?us-ascii?Q?DzZX+7FLxu6q1sgeHBt6XlRU+DJC/O4JzPKhq7H5WYpYseTaSBSyn1RG69F5?= =?us-ascii?Q?8Y3xdVBFRSD9rffFERGzJWNZZs6ede9J+T0At3hYKgb+Hh2RkoGGIZ6fb6tO?= =?us-ascii?Q?W6baw=3D=3D?= X-Microsoft-Antispam-Message-Info: VlD/MVsfn2h6syQO/XFCwP6waSYm/vgSmziwBQ8Z6aN4S8kn4fXYBmlG7FkrQNQK88EzRYulTXirv3cHnWxvEOpNX/TMdRgf7JnPQC8ZaCjz1JVbaFhxJaGwvHyaD2gEKstktwV0fPU83ZmofOCH7Yx+XsrsUVihZQoYwrgtCBTXYMqk2zUY0+ExPMI1YZ50 X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB2478; 6:f1pNARD3ShL9pXj9AsitgUPTid0ese1+wywXgsLSiRbR19PuhN9PwfRaHoRpQqs2gswfj54nzipUZ0BdBaH0jv6BshQ7SUrLrDA7EX6nRQ0zmeN7Dp4/8P53LEP7AXaeIePq/UAknDT/aDXC9AYWPl36rpQh3m0U01SMfIpZ7bEN4+oeuzvZkZ1M6rfqawxHVgdtw9NYl5UHHDf6DEQV1cLV1Xvr23yO/p2re+daQ9MFUlNtDAYYGtNLaHiIdIkQIblKFHm35x6WEbojgvv3oSggeYiMDpy4anrx/uc03v/FL5jr+JmHxzW+MjWXoCF8ApRilMugmZ5mpugBa4+evCvb6c6XCNOhfX8vE/WZ11Sqa9DjcvYR6vmYmvxS+rnxpOWFM8gLgs7Im8CYJy/XaxCWZ4LCE/4KU8q4+YAkWP54gBolLBktX/bps0bAKNR8AezMxfQ/dmpFri3xiNl1aQ==; 5:CQ/Nx+3W2/7SHNl2Y2TNjvIDZe5PrrBrRGqi28GXod8blMTEVGk9JScEiuNmrIMkXnT7QbrNL/95dWM5/TZcMILxy3MCjMGklg9oE0JPpwsxDg7e2CsvI0ZvmDmSTY9y2jfRgO7BQ8cbsR2li8u4Zc2A86SFBPO1lIzEwpvo3sc=; 24:gvp7Nk7ie9qRhMf5Ic6ORvH3p3Uev4PAtJMuMIFfznhMwN9+LsOq0xKlQoY0HpjQ0LOL7VY2TXNfra46CEO5fYSlm76tfr1fPlv33ubcjK0= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB2478; 7:24qqSefjMWrDMkW+yd7GyHI5YEspPBoRe9pcKm9w2hleLuXFOt66FElTuousqefikMkUDmX/sVzQ+kdBZvWar8kSfn24Hy9pN5ozrQOQR7Edttp6la90SeJ0O9h8ipNzqmfm0L51cPyLF1l3nf1GAqnvcRwfopJnHWB/XuidFjeA8MLHhTsCg3My5hkJuREKugxifWo4iOoj3gG7BhDvUj0lZVM8zkOb+kfGsETpiwNSVg6F7Fh4BnaxoRT7KkTY; 20:n/UZD7uTi0hDgTrhdeNt3PFwccEyEc35e7v+V9dLxreZowS1+HdSHVNa1ROpA3vXdFcqPqBA7mY5tq4PT7GcKGWXfNMr7O4E8054NovBqmFEW2hUGSPJqfC3tmXptVFE5WyHhmLUKr4lDLr1o98FuXlr2IGlrHLnq/EDDUxRKy22W+405d6qxYQb5qaa8a55ywrVG/MNOGSU+J/HIoUPI1iZT1slFh32gvVl7C8LgmgUOGZcIWURSnWQzHTGiLyh X-MS-Office365-Filtering-Correlation-Id: d34d01bd-8331-45c9-8f3b-08d5b6b67d02 X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 May 2018 20:42:03.4322 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: d34d01bd-8331-45c9-8f3b-08d5b6b67d02 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN1PR12MB2478 X-detected-operating-system: by eggs.gnu.org: Windows 7 or 8 [fuzzy] X-Received-From: 104.47.32.41 Subject: [Qemu-devel] [PATCH v8 1/8] i386: Helpers to encode cache information consistently 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: geoff@hostfission.com, babu.moger@amd.com, kash@tripleback.net, qemu-devel@nongnu.org, kvm@vger.kernel.org Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Eduardo Habkost Instead of having a collection of macros that need to be used in complex expressions to build CPUID data, define a CPUCacheInfo struct that can hold information about a given cache. Helper functions will take a CPUCacheInfo struct as input to encode CPUID leaves for a cache. This will help us ensure consistency between cache information CPUID leaves, and make the existing inconsistencies in CPUID info more visible. Signed-off-by: Eduardo Habkost Signed-off-by: Babu Moger Tested-by: Geoffrey McRae Reviewed-by: Eduardo Habkost --- target/i386/cpu.c | 495 ++++++++++++++++++++++++++++++++++------------ target/i386/cpu.h | 53 +++++ 2 files changed, 424 insertions(+), 124 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index a20fe26573..18835400f1 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -56,33 +56,240 @@ #include "disas/capstone.h" +/* Helpers for building CPUID[2] descriptors: */ + +struct CPUID2CacheDescriptorInfo { + enum CacheType type; + int level; + int size; + int line_size; + int associativity; +}; -/* Cache topology CPUID constants: */ +#define KiB 1024 +#define MiB (1024 * 1024) -/* CPUID Leaf 2 Descriptors */ +/* + * Known CPUID 2 cache descriptors. + * From Intel SDM Volume 2A, CPUID instruction + */ +struct CPUID2CacheDescriptorInfo cpuid2_cache_descriptors[] = { + [0x06] = { .level = 1, .type = ICACHE, .size = 8 * KiB, + .associativity = 4, .line_size = 32, }, + [0x08] = { .level = 1, .type = ICACHE, .size = 16 * KiB, + .associativity = 4, .line_size = 32, }, + [0x09] = { .level = 1, .type = ICACHE, .size = 32 * KiB, + .associativity = 4, .line_size = 64, }, + [0x0A] = { .level = 1, .type = DCACHE, .size = 8 * KiB, + .associativity = 2, .line_size = 32, }, + [0x0C] = { .level = 1, .type = DCACHE, .size = 16 * KiB, + .associativity = 4, .line_size = 32, }, + [0x0D] = { .level = 1, .type = DCACHE, .size = 16 * KiB, + .associativity = 4, .line_size = 64, }, + [0x0E] = { .level = 1, .type = DCACHE, .size = 24 * KiB, + .associativity = 6, .line_size = 64, }, + [0x1D] = { .level = 2, .type = UNIFIED_CACHE, .size = 128 * KiB, + .associativity = 2, .line_size = 64, }, + [0x21] = { .level = 2, .type = UNIFIED_CACHE, .size = 256 * KiB, + .associativity = 8, .line_size = 64, }, + /* lines per sector is not supported cpuid2_cache_descriptor(), + * so descriptors 0x22, 0x23 are not included + */ + [0x24] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB, + .associativity = 16, .line_size = 64, }, + /* lines per sector is not supported cpuid2_cache_descriptor(), + * so descriptors 0x25, 0x20 are not included + */ + [0x2C] = { .level = 1, .type = DCACHE, .size = 32 * KiB, + .associativity = 8, .line_size = 64, }, + [0x30] = { .level = 1, .type = ICACHE, .size = 32 * KiB, + .associativity = 8, .line_size = 64, }, + [0x41] = { .level = 2, .type = UNIFIED_CACHE, .size = 128 * KiB, + .associativity = 4, .line_size = 32, }, + [0x42] = { .level = 2, .type = UNIFIED_CACHE, .size = 256 * KiB, + .associativity = 4, .line_size = 32, }, + [0x43] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB, + .associativity = 4, .line_size = 32, }, + [0x44] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB, + .associativity = 4, .line_size = 32, }, + [0x45] = { .level = 2, .type = UNIFIED_CACHE, .size = 2 * MiB, + .associativity = 4, .line_size = 32, }, + [0x46] = { .level = 3, .type = UNIFIED_CACHE, .size = 4 * MiB, + .associativity = 4, .line_size = 64, }, + [0x47] = { .level = 3, .type = UNIFIED_CACHE, .size = 8 * MiB, + .associativity = 8, .line_size = 64, }, + [0x48] = { .level = 2, .type = UNIFIED_CACHE, .size = 3 * MiB, + .associativity = 12, .line_size = 64, }, + /* Descriptor 0x49 depends on CPU family/model, so it is not included */ + [0x4A] = { .level = 3, .type = UNIFIED_CACHE, .size = 6 * MiB, + .associativity = 12, .line_size = 64, }, + [0x4B] = { .level = 3, .type = UNIFIED_CACHE, .size = 8 * MiB, + .associativity = 16, .line_size = 64, }, + [0x4C] = { .level = 3, .type = UNIFIED_CACHE, .size = 12 * MiB, + .associativity = 12, .line_size = 64, }, + [0x4D] = { .level = 3, .type = UNIFIED_CACHE, .size = 16 * MiB, + .associativity = 16, .line_size = 64, }, + [0x4E] = { .level = 2, .type = UNIFIED_CACHE, .size = 6 * MiB, + .associativity = 24, .line_size = 64, }, + [0x60] = { .level = 1, .type = DCACHE, .size = 16 * KiB, + .associativity = 8, .line_size = 64, }, + [0x66] = { .level = 1, .type = DCACHE, .size = 8 * KiB, + .associativity = 4, .line_size = 64, }, + [0x67] = { .level = 1, .type = DCACHE, .size = 16 * KiB, + .associativity = 4, .line_size = 64, }, + [0x68] = { .level = 1, .type = DCACHE, .size = 32 * KiB, + .associativity = 4, .line_size = 64, }, + [0x78] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB, + .associativity = 4, .line_size = 64, }, + /* lines per sector is not supported cpuid2_cache_descriptor(), + * so descriptors 0x79, 0x7A, 0x7B, 0x7C are not included. + */ + [0x7D] = { .level = 2, .type = UNIFIED_CACHE, .size = 2 * MiB, + .associativity = 8, .line_size = 64, }, + [0x7F] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB, + .associativity = 2, .line_size = 64, }, + [0x80] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB, + .associativity = 8, .line_size = 64, }, + [0x82] = { .level = 2, .type = UNIFIED_CACHE, .size = 256 * KiB, + .associativity = 8, .line_size = 32, }, + [0x83] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB, + .associativity = 8, .line_size = 32, }, + [0x84] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB, + .associativity = 8, .line_size = 32, }, + [0x85] = { .level = 2, .type = UNIFIED_CACHE, .size = 2 * MiB, + .associativity = 8, .line_size = 32, }, + [0x86] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB, + .associativity = 4, .line_size = 64, }, + [0x87] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB, + .associativity = 8, .line_size = 64, }, + [0xD0] = { .level = 3, .type = UNIFIED_CACHE, .size = 512 * KiB, + .associativity = 4, .line_size = 64, }, + [0xD1] = { .level = 3, .type = UNIFIED_CACHE, .size = 1 * MiB, + .associativity = 4, .line_size = 64, }, + [0xD2] = { .level = 3, .type = UNIFIED_CACHE, .size = 2 * MiB, + .associativity = 4, .line_size = 64, }, + [0xD6] = { .level = 3, .type = UNIFIED_CACHE, .size = 1 * MiB, + .associativity = 8, .line_size = 64, }, + [0xD7] = { .level = 3, .type = UNIFIED_CACHE, .size = 2 * MiB, + .associativity = 8, .line_size = 64, }, + [0xD8] = { .level = 3, .type = UNIFIED_CACHE, .size = 4 * MiB, + .associativity = 8, .line_size = 64, }, + [0xDC] = { .level = 3, .type = UNIFIED_CACHE, .size = 1.5 * MiB, + .associativity = 12, .line_size = 64, }, + [0xDD] = { .level = 3, .type = UNIFIED_CACHE, .size = 3 * MiB, + .associativity = 12, .line_size = 64, }, + [0xDE] = { .level = 3, .type = UNIFIED_CACHE, .size = 6 * MiB, + .associativity = 12, .line_size = 64, }, + [0xE2] = { .level = 3, .type = UNIFIED_CACHE, .size = 2 * MiB, + .associativity = 16, .line_size = 64, }, + [0xE3] = { .level = 3, .type = UNIFIED_CACHE, .size = 4 * MiB, + .associativity = 16, .line_size = 64, }, + [0xE4] = { .level = 3, .type = UNIFIED_CACHE, .size = 8 * MiB, + .associativity = 16, .line_size = 64, }, + [0xEA] = { .level = 3, .type = UNIFIED_CACHE, .size = 12 * MiB, + .associativity = 24, .line_size = 64, }, + [0xEB] = { .level = 3, .type = UNIFIED_CACHE, .size = 18 * MiB, + .associativity = 24, .line_size = 64, }, + [0xEC] = { .level = 3, .type = UNIFIED_CACHE, .size = 24 * MiB, + .associativity = 24, .line_size = 64, }, +}; + +/* + * "CPUID leaf 2 does not report cache descriptor information, + * use CPUID leaf 4 to query cache parameters" + */ +#define CACHE_DESCRIPTOR_UNAVAILABLE 0xFF -#define CPUID_2_L1D_32KB_8WAY_64B 0x2c -#define CPUID_2_L1I_32KB_8WAY_64B 0x30 -#define CPUID_2_L2_2MB_8WAY_64B 0x7d -#define CPUID_2_L3_16MB_16WAY_64B 0x4d +/* + * Return a CPUID 2 cache descriptor for a given cache. + * If no known descriptor is found, return CACHE_DESCRIPTOR_UNAVAILABLE + */ +static uint8_t cpuid2_cache_descriptor(CPUCacheInfo *cache) +{ + int i; + + assert(cache->size > 0); + assert(cache->level > 0); + assert(cache->line_size > 0); + assert(cache->associativity > 0); + for (i = 0; i < ARRAY_SIZE(cpuid2_cache_descriptors); i++) { + struct CPUID2CacheDescriptorInfo *d = &cpuid2_cache_descriptors[i]; + if (d->level == cache->level && d->type == cache->type && + d->size == cache->size && d->line_size == cache->line_size && + d->associativity == cache->associativity) { + return i; + } + } + return CACHE_DESCRIPTOR_UNAVAILABLE; +} /* CPUID Leaf 4 constants: */ /* EAX: */ -#define CPUID_4_TYPE_DCACHE 1 -#define CPUID_4_TYPE_ICACHE 2 -#define CPUID_4_TYPE_UNIFIED 3 +#define CACHE_TYPE_D 1 +#define CACHE_TYPE_I 2 +#define CACHE_TYPE_UNIFIED 3 -#define CPUID_4_LEVEL(l) ((l) << 5) +#define CACHE_LEVEL(l) (l << 5) -#define CPUID_4_SELF_INIT_LEVEL (1 << 8) -#define CPUID_4_FULLY_ASSOC (1 << 9) +#define CACHE_SELF_INIT_LEVEL (1 << 8) /* EDX: */ -#define CPUID_4_NO_INVD_SHARING (1 << 0) -#define CPUID_4_INCLUSIVE (1 << 1) -#define CPUID_4_COMPLEX_IDX (1 << 2) +#define CACHE_NO_INVD_SHARING (1 << 0) +#define CACHE_INCLUSIVE (1 << 1) +#define CACHE_COMPLEX_IDX (1 << 2) + +/* Encode CacheType for CPUID[4].EAX */ +#define CACHE_TYPE(t) (((t) == DCACHE) ? CACHE_TYPE_D : \ + ((t) == ICACHE) ? CACHE_TYPE_I : \ + ((t) == UNIFIED_CACHE) ? CACHE_TYPE_UNIFIED : \ + 0 /* Invalid value */) + + +/* Encode cache info for CPUID[4] */ +static void encode_cache_cpuid4(CPUCacheInfo *cache, + int num_apic_ids, int num_cores, + uint32_t *eax, uint32_t *ebx, + uint32_t *ecx, uint32_t *edx) +{ + assert(cache->size == cache->line_size * cache->associativity * + cache->partitions * cache->sets); + + assert(num_apic_ids > 0); + *eax = CACHE_TYPE(cache->type) | + CACHE_LEVEL(cache->level) | + (cache->self_init ? CACHE_SELF_INIT_LEVEL : 0) | + ((num_cores - 1) << 26) | + ((num_apic_ids - 1) << 14); + + assert(cache->line_size > 0); + assert(cache->partitions > 0); + assert(cache->associativity > 0); + /* We don't implement fully-associative caches */ + assert(cache->associativity < cache->sets); + *ebx = (cache->line_size - 1) | + ((cache->partitions - 1) << 12) | + ((cache->associativity - 1) << 22); + + assert(cache->sets > 0); + *ecx = cache->sets - 1; + + *edx = (cache->no_invd_sharing ? CACHE_NO_INVD_SHARING : 0) | + (cache->inclusive ? CACHE_INCLUSIVE : 0) | + (cache->complex_indexing ? CACHE_COMPLEX_IDX : 0); +} + +/* Encode cache info for CPUID[0x80000005].ECX or CPUID[0x80000005].EDX */ +static uint32_t encode_cache_cpuid80000005(CPUCacheInfo *cache) +{ + assert(cache->size % 1024 == 0); + assert(cache->lines_per_tag > 0); + assert(cache->associativity > 0); + assert(cache->line_size > 0); + return ((cache->size / 1024) << 24) | (cache->associativity << 16) | + (cache->lines_per_tag << 8) | (cache->line_size); +} #define ASSOC_FULL 0xFF @@ -100,57 +307,140 @@ a == ASSOC_FULL ? 0xF : \ 0 /* invalid value */) +/* + * Encode cache info for CPUID[0x80000006].ECX and CPUID[0x80000006].EDX + * @l3 can be NULL. + */ +static void encode_cache_cpuid80000006(CPUCacheInfo *l2, + CPUCacheInfo *l3, + uint32_t *ecx, uint32_t *edx) +{ + assert(l2->size % 1024 == 0); + assert(l2->associativity > 0); + assert(l2->lines_per_tag > 0); + assert(l2->line_size > 0); + *ecx = ((l2->size / 1024) << 16) | + (AMD_ENC_ASSOC(l2->associativity) << 12) | + (l2->lines_per_tag << 8) | (l2->line_size); + + if (l3) { + assert(l3->size % (512 * 1024) == 0); + assert(l3->associativity > 0); + assert(l3->lines_per_tag > 0); + assert(l3->line_size > 0); + *edx = ((l3->size / (512 * 1024)) << 18) | + (AMD_ENC_ASSOC(l3->associativity) << 12) | + (l3->lines_per_tag << 8) | (l3->line_size); + } else { + *edx = 0; + } +} /* Definitions of the hardcoded cache entries we expose: */ /* L1 data cache: */ -#define L1D_LINE_SIZE 64 -#define L1D_ASSOCIATIVITY 8 -#define L1D_SETS 64 -#define L1D_PARTITIONS 1 -/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 32KiB */ -#define L1D_DESCRIPTOR CPUID_2_L1D_32KB_8WAY_64B +static CPUCacheInfo l1d_cache = { + .type = DCACHE, + .level = 1, + .size = 32 * KiB, + .self_init = 1, + .line_size = 64, + .associativity = 8, + .sets = 64, + .partitions = 1, + .no_invd_sharing = true, +}; + /*FIXME: CPUID leaf 0x80000005 is inconsistent with leaves 2 & 4 */ -#define L1D_LINES_PER_TAG 1 -#define L1D_SIZE_KB_AMD 64 -#define L1D_ASSOCIATIVITY_AMD 2 +static CPUCacheInfo l1d_cache_amd = { + .type = DCACHE, + .level = 1, + .size = 64 * KiB, + .self_init = 1, + .line_size = 64, + .associativity = 2, + .sets = 512, + .partitions = 1, + .lines_per_tag = 1, + .no_invd_sharing = true, +}; /* L1 instruction cache: */ -#define L1I_LINE_SIZE 64 -#define L1I_ASSOCIATIVITY 8 -#define L1I_SETS 64 -#define L1I_PARTITIONS 1 -/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 32KiB */ -#define L1I_DESCRIPTOR CPUID_2_L1I_32KB_8WAY_64B +static CPUCacheInfo l1i_cache = { + .type = ICACHE, + .level = 1, + .size = 32 * KiB, + .self_init = 1, + .line_size = 64, + .associativity = 8, + .sets = 64, + .partitions = 1, + .no_invd_sharing = true, +}; + /*FIXME: CPUID leaf 0x80000005 is inconsistent with leaves 2 & 4 */ -#define L1I_LINES_PER_TAG 1 -#define L1I_SIZE_KB_AMD 64 -#define L1I_ASSOCIATIVITY_AMD 2 +static CPUCacheInfo l1i_cache_amd = { + .type = ICACHE, + .level = 1, + .size = 64 * KiB, + .self_init = 1, + .line_size = 64, + .associativity = 2, + .sets = 512, + .partitions = 1, + .lines_per_tag = 1, + .no_invd_sharing = true, +}; /* Level 2 unified cache: */ -#define L2_LINE_SIZE 64 -#define L2_ASSOCIATIVITY 16 -#define L2_SETS 4096 -#define L2_PARTITIONS 1 -/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 4MiB */ +static CPUCacheInfo l2_cache = { + .type = UNIFIED_CACHE, + .level = 2, + .size = 4 * MiB, + .self_init = 1, + .line_size = 64, + .associativity = 16, + .sets = 4096, + .partitions = 1, + .no_invd_sharing = true, +}; + /*FIXME: CPUID leaf 2 descriptor is inconsistent with CPUID leaf 4 */ -#define L2_DESCRIPTOR CPUID_2_L2_2MB_8WAY_64B +static CPUCacheInfo l2_cache_cpuid2 = { + .type = UNIFIED_CACHE, + .level = 2, + .size = 2 * MiB, + .line_size = 64, + .associativity = 8, +}; + + /*FIXME: CPUID leaf 0x80000006 is inconsistent with leaves 2 & 4 */ -#define L2_LINES_PER_TAG 1 -#define L2_SIZE_KB_AMD 512 +static CPUCacheInfo l2_cache_amd = { + .type = UNIFIED_CACHE, + .level = 2, + .size = 512 * KiB, + .line_size = 64, + .lines_per_tag = 1, + .associativity = 16, + .sets = 512, + .partitions = 1, +}; /* Level 3 unified cache: */ -#define L3_SIZE_KB 0 /* disabled */ -#define L3_ASSOCIATIVITY 0 /* disabled */ -#define L3_LINES_PER_TAG 0 /* disabled */ -#define L3_LINE_SIZE 0 /* disabled */ -#define L3_N_LINE_SIZE 64 -#define L3_N_ASSOCIATIVITY 16 -#define L3_N_SETS 16384 -#define L3_N_PARTITIONS 1 -#define L3_N_DESCRIPTOR CPUID_2_L3_16MB_16WAY_64B -#define L3_N_LINES_PER_TAG 1 -#define L3_N_SIZE_KB_AMD 16384 +static CPUCacheInfo l3_cache = { + .type = UNIFIED_CACHE, + .level = 3, + .size = 16 * MiB, + .line_size = 64, + .associativity = 16, + .sets = 16384, + .partitions = 1, + .lines_per_tag = 1, + .self_init = true, + .inclusive = true, + .complex_indexing = true, +}; /* TLB definitions: */ @@ -3301,85 +3591,53 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, if (!cpu->enable_l3_cache) { *ecx = 0; } else { - *ecx = L3_N_DESCRIPTOR; + *ecx = cpuid2_cache_descriptor(&l3_cache); } - *edx = (L1D_DESCRIPTOR << 16) | \ - (L1I_DESCRIPTOR << 8) | \ - (L2_DESCRIPTOR); + *edx = (cpuid2_cache_descriptor(&l1d_cache) << 16) | + (cpuid2_cache_descriptor(&l1i_cache) << 8) | + (cpuid2_cache_descriptor(&l2_cache_cpuid2)); break; case 4: /* cache info: needed for Core compatibility */ if (cpu->cache_info_passthrough) { host_cpuid(index, count, eax, ebx, ecx, edx); + /* QEMU gives out its own APIC IDs, never pass down bits 31..26. */ *eax &= ~0xFC000000; + if ((*eax & 31) && cs->nr_cores > 1) { + *eax |= (cs->nr_cores - 1) << 26; + } } else { *eax = 0; switch (count) { case 0: /* L1 dcache info */ - *eax |= CPUID_4_TYPE_DCACHE | \ - CPUID_4_LEVEL(1) | \ - CPUID_4_SELF_INIT_LEVEL; - *ebx = (L1D_LINE_SIZE - 1) | \ - ((L1D_PARTITIONS - 1) << 12) | \ - ((L1D_ASSOCIATIVITY - 1) << 22); - *ecx = L1D_SETS - 1; - *edx = CPUID_4_NO_INVD_SHARING; + encode_cache_cpuid4(&l1d_cache, + 1, cs->nr_cores, + eax, ebx, ecx, edx); break; case 1: /* L1 icache info */ - *eax |= CPUID_4_TYPE_ICACHE | \ - CPUID_4_LEVEL(1) | \ - CPUID_4_SELF_INIT_LEVEL; - *ebx = (L1I_LINE_SIZE - 1) | \ - ((L1I_PARTITIONS - 1) << 12) | \ - ((L1I_ASSOCIATIVITY - 1) << 22); - *ecx = L1I_SETS - 1; - *edx = CPUID_4_NO_INVD_SHARING; + encode_cache_cpuid4(&l1i_cache, + 1, cs->nr_cores, + eax, ebx, ecx, edx); break; case 2: /* L2 cache info */ - *eax |= CPUID_4_TYPE_UNIFIED | \ - CPUID_4_LEVEL(2) | \ - CPUID_4_SELF_INIT_LEVEL; - if (cs->nr_threads > 1) { - *eax |= (cs->nr_threads - 1) << 14; - } - *ebx = (L2_LINE_SIZE - 1) | \ - ((L2_PARTITIONS - 1) << 12) | \ - ((L2_ASSOCIATIVITY - 1) << 22); - *ecx = L2_SETS - 1; - *edx = CPUID_4_NO_INVD_SHARING; + encode_cache_cpuid4(&l2_cache, + cs->nr_threads, cs->nr_cores, + eax, ebx, ecx, edx); break; case 3: /* L3 cache info */ - if (!cpu->enable_l3_cache) { - *eax = 0; - *ebx = 0; - *ecx = 0; - *edx = 0; + pkg_offset = apicid_pkg_offset(cs->nr_cores, cs->nr_threads); + if (cpu->enable_l3_cache) { + encode_cache_cpuid4(&l3_cache, + (1 << pkg_offset), cs->nr_cores, + eax, ebx, ecx, edx); break; } - *eax |= CPUID_4_TYPE_UNIFIED | \ - CPUID_4_LEVEL(3) | \ - CPUID_4_SELF_INIT_LEVEL; - pkg_offset = apicid_pkg_offset(cs->nr_cores, cs->nr_threads); - *eax |= ((1 << pkg_offset) - 1) << 14; - *ebx = (L3_N_LINE_SIZE - 1) | \ - ((L3_N_PARTITIONS - 1) << 12) | \ - ((L3_N_ASSOCIATIVITY - 1) << 22); - *ecx = L3_N_SETS - 1; - *edx = CPUID_4_INCLUSIVE | CPUID_4_COMPLEX_IDX; - break; + /* fall through */ default: /* end of info */ - *eax = 0; - *ebx = 0; - *ecx = 0; - *edx = 0; + *eax = *ebx = *ecx = *edx = 0; break; } } - - /* QEMU gives out its own APIC IDs, never pass down bits 31..26. */ - if ((*eax & 31) && cs->nr_cores > 1) { - *eax |= (cs->nr_cores - 1) << 26; - } break; case 5: /* mwait info: needed for Core compatibility */ @@ -3583,10 +3841,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, (L1_ITLB_2M_ASSOC << 8) | (L1_ITLB_2M_ENTRIES); *ebx = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | \ (L1_ITLB_4K_ASSOC << 8) | (L1_ITLB_4K_ENTRIES); - *ecx = (L1D_SIZE_KB_AMD << 24) | (L1D_ASSOCIATIVITY_AMD << 16) | \ - (L1D_LINES_PER_TAG << 8) | (L1D_LINE_SIZE); - *edx = (L1I_SIZE_KB_AMD << 24) | (L1I_ASSOCIATIVITY_AMD << 16) | \ - (L1I_LINES_PER_TAG << 8) | (L1I_LINE_SIZE); + *ecx = encode_cache_cpuid80000005(&l1d_cache_amd); + *edx = encode_cache_cpuid80000005(&l1i_cache_amd); break; case 0x80000006: /* cache info (L2 cache) */ @@ -3602,18 +3858,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, (L2_DTLB_4K_ENTRIES << 16) | \ (AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) | \ (L2_ITLB_4K_ENTRIES); - *ecx = (L2_SIZE_KB_AMD << 16) | \ - (AMD_ENC_ASSOC(L2_ASSOCIATIVITY) << 12) | \ - (L2_LINES_PER_TAG << 8) | (L2_LINE_SIZE); - if (!cpu->enable_l3_cache) { - *edx = ((L3_SIZE_KB / 512) << 18) | \ - (AMD_ENC_ASSOC(L3_ASSOCIATIVITY) << 12) | \ - (L3_LINES_PER_TAG << 8) | (L3_LINE_SIZE); - } else { - *edx = ((L3_N_SIZE_KB_AMD / 512) << 18) | \ - (AMD_ENC_ASSOC(L3_N_ASSOCIATIVITY) << 12) | \ - (L3_N_LINES_PER_TAG << 8) | (L3_N_LINE_SIZE); - } + encode_cache_cpuid80000006(&l2_cache_amd, + cpu->enable_l3_cache ? &l3_cache : NULL, + ecx, edx); break; case 0x80000007: *eax = 0; diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 1b219fafc4..fa03e2ced4 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1044,6 +1044,59 @@ typedef enum TPRAccess { TPR_ACCESS_WRITE, } TPRAccess; +/* Cache information data structures: */ + +enum CacheType { + DCACHE, + ICACHE, + UNIFIED_CACHE +}; + +typedef struct CPUCacheInfo { + enum CacheType type; + uint8_t level; + /* Size in bytes */ + uint32_t size; + /* Line size, in bytes */ + uint16_t line_size; + /* + * Associativity. + * Note: representation of fully-associative caches is not implemented + */ + uint8_t associativity; + /* Physical line partitions. CPUID[0x8000001D].EBX, CPUID[4].EBX */ + uint8_t partitions; + /* Number of sets. CPUID[0x8000001D].ECX, CPUID[4].ECX */ + uint32_t sets; + /* + * Lines per tag. + * AMD-specific: CPUID[0x80000005], CPUID[0x80000006]. + * (Is this synonym to @partitions?) + */ + uint8_t lines_per_tag; + + /* Self-initializing cache */ + bool self_init; + /* + * WBINVD/INVD is not guaranteed to act upon lower level caches of + * non-originating threads sharing this cache. + * CPUID[4].EDX[bit 0], CPUID[0x8000001D].EDX[bit 0] + */ + bool no_invd_sharing; + /* + * Cache is inclusive of lower cache levels. + * CPUID[4].EDX[bit 1], CPUID[0x8000001D].EDX[bit 1]. + */ + bool inclusive; + /* + * A complex function is used to index the cache, potentially using all + * address bits. CPUID[4].EDX[bit 2]. + */ + bool complex_indexing; +} CPUCacheInfo; + + + typedef struct CPUX86State { /* standard registers */ target_ulong regs[CPU_NB_REGS];