From patchwork Thu Jul 11 18:52:12 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Widawsky X-Patchwork-Id: 2826572 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 43E2DC0AB2 for ; Thu, 11 Jul 2013 18:49:15 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D308F2021C for ; Thu, 11 Jul 2013 18:49:13 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id B10DA20214 for ; Thu, 11 Jul 2013 18:49:12 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 99864E5DC7 for ; Thu, 11 Jul 2013 11:49:12 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from shiva.localdomain (unknown [209.20.75.48]) by gabe.freedesktop.org (Postfix) with ESMTP id 89D69E5DC7 for ; Thu, 11 Jul 2013 11:48:58 -0700 (PDT) Received: by shiva.localdomain (Postfix, from userid 99) id DC8418862F; Thu, 11 Jul 2013 18:48:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-4.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from lundgren.jf.intel.com (unknown [134.134.139.76]) by shiva.localdomain (Postfix) with ESMTPSA id 8674588167; Thu, 11 Jul 2013 18:48:56 +0000 (UTC) From: Ben Widawsky To: Intel GFX Date: Thu, 11 Jul 2013 11:52:12 -0700 Message-Id: <1373568732-3061-1-git-send-email-ben@bwidawsk.net> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1373425083-1276-1-git-send-email-ben@bwidawsk.net> References: <1373425083-1276-1-git-send-email-ben@bwidawsk.net> Cc: Ben Widawsky , Bryan Bell Subject: [Intel-gfx] [PATCH] [v2] drm/i915: Expose LLC size to user space X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Virus-Scanned: ClamAV using ClamSMTP The algorithm/information was originally written by Chad, though I changed the control flow, and I think his original code had a couple of bugs, though I didn't look very hard before rewriting. That could have also been different interpretations of the spec. I've tested this on two platforms, and it seems to perform how I want. With this patch is a small tool for igt to query the size. This can be used as a reference for DRI clients wishing to query the information. v2: Update name of the SDM location (Bryan) Dissent: Use a new param instead of reusing HAS_LLC param (Chris, Chad) Fix unicode multiply symbol (Ben) CC: Chad Versace CC: Bryan Bell Signed-off-by: Ben Widawsky Reviewed-by: Chad Versace --- drivers/gpu/drm/i915/i915_dma.c | 3 +++ drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_gem.c | 55 +++++++++++++++++++++++++++++++++++++++++ include/uapi/drm/i915_drm.h | 1 + 4 files changed, 61 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 0e22142..1224586 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1000,6 +1000,9 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_EXEC_HANDLE_LUT: value = 1; break; + case I915_PARAM_LLC_SIZE: + value = dev_priv->llc_size; + break; default: DRM_DEBUG("Unknown parameter %d\n", param->param); return -EINVAL; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c8d6104..43a549d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1187,6 +1187,8 @@ typedef struct drm_i915_private { /* Old dri1 support infrastructure, beware the dragons ya fools entering * here! */ struct i915_dri1_state dri1; + + size_t llc_size; } drm_i915_private_t; /* Iterate over initialised rings */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index af61be8..629837d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4282,6 +4282,59 @@ i915_gem_lastclose(struct drm_device *dev) DRM_ERROR("failed to idle hardware: %d\n", ret); } +/** + * Return the size, in bytes, of the CPU L3 cache size. If the CPU has no L3 + * cache, or if an error occurs in obtaining the cache size, then return 0. + * From Intel 64 and IA32 Architectures Developer's Manual: Vol. 2A -> section + * 3.2 -> CPUID + * + * Deterministic Cache Parmaeters (Function 04h)": + * When EAX is initialized to a value of 4, the CPUID instruction returns + * deterministic cache information in the EAX, EBX, ECX and EDX registers. + * This function requires ECX be initialized with an index which indicates + * which cache to return information about. The OS is expected to call this + * function (CPUID.4) with ECX = 0, 1, 2, until EAX[4:0] == 0, indicating no + * more caches. The order in which the caches are returned is not specified + * and may change at Intel's discretion. + * + * Calculating the Cache Size in bytes: + * = (Ways +1) * (Partitions +1) * (Line Size +1) * (Sets +1) + * = (EBX[31:22] +1) * (EBX[21:12] +1) * (EBX[11:0] +1 * (ECX + 1) + */ +static size_t get_llc_size(struct drm_device *dev) +{ + u8 cnt = 0; + unsigned int eax, ebx, ecx, edx; + + if (!HAS_LLC(dev)) + return 0; + + do { + uint32_t cache_level; + uint32_t associativity, line_partitions, line_size, sets; + + eax = 4; + ecx = cnt; + __cpuid(&eax, &ebx, &ecx, &edx); + + cache_level = (eax >> 5) & 0x7; + if (cache_level != 3) + continue; + + associativity = ((ebx >> 22) & 0x3ff) + 1; + line_partitions = ((ebx >> 12) & 0x3ff) + 1; + line_size = (ebx & 0xfff) + 1; + sets = ecx + 1; + + return associativity * line_partitions * line_size * sets; + } while (eax & 0x1f && ++cnt); + + /* Let user space know we have non-zero LLC, we can't figure it out */ + DRM_DEBUG_DRIVER("Couldn't find LLC size. Bug?\n"); + return 1; +} + + static void init_ring_lists(struct intel_ring_buffer *ring) { @@ -4333,6 +4386,8 @@ i915_gem_load(struct drm_device *dev) else dev_priv->num_fence_regs = 8; + dev_priv->llc_size = get_llc_size(dev); + /* Initialize fence registers to zero */ INIT_LIST_HEAD(&dev_priv->mm.fence_list); i915_gem_restore_fences(dev); diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 923ed7f..c54559e 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -310,6 +310,7 @@ typedef struct drm_i915_irq_wait { #define I915_PARAM_HAS_PINNED_BATCHES 24 #define I915_PARAM_HAS_EXEC_NO_RELOC 25 #define I915_PARAM_HAS_EXEC_HANDLE_LUT 26 +#define I915_PARAM_LLC_SIZE 27 typedef struct drm_i915_getparam { int param;