From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6110E15EFDB for ; Wed, 24 Apr 2024 15:37:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713973033; cv=none; b=bbkvJWrXpdiwvl8Wz8UHrhQLLFLqk73OCM5NwmyHsjU8e9aZ2PTwGeWQbn2vYyuoOtJsxsmdoC7nmEHAnzp1HJPsczMc++zpXOjZhJ+cYkaPV8u2a4S3gECuTYD1PTVY4cEP2SeNQq0TECD7I9aUoXmLegCGb3ldKvfUgvfJEfQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713973033; c=relaxed/simple; bh=GnZ9XZjg7vIRGre5yHTqTO1k6lozqLPvqbfHSGyDS7M=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Q1HcHpsPiOH5fMvlCsYheh1zrf+sBDhbOjRVyefV8V66h2uOIt8MRLTJhuF17Qo7hDH31NcDMDuoiBCnwoH0134FD/b9du49LWPXolFbYKuHqv3GGjtO2jNK/gSu+jWWW+/6ibwSYOUBjp/NJasp28LNgxqGxp6xCjmX9EXznGk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=W0MzxgAJ; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="W0MzxgAJ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1713973031; x=1745509031; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=GnZ9XZjg7vIRGre5yHTqTO1k6lozqLPvqbfHSGyDS7M=; b=W0MzxgAJVWKO4hFIH4xaE8R2N14iYBOCLlclYPmWuy8WCsOTxoxnLXFp MhlVpETQeBj7yTBjPmB9RkrK2bUff4DfHiX9xSMvNS6Je/Ro45B+1KKZ4 cRHDRNb5pzm4/Ci2c1tVjAzbpsFg7Yq5I/PmM1C6AK60pQUcQwrphpJ35 FwnJGzlfU8afyQbC5Q3ScPC1pJ2cDH5DUad85cQZ11AuMZvZTAdXBVRw3 3C+bDC0ooXe28DCttawxJq6ItyNcT2Cg/wLL8MWFXfUD2jGr5fMaQMEHn q6B+By6igvcbB16ubo+LFs/LTgGCOez8DhzGFPM3vUFQ1AlrV5aGXjc6T w==; X-CSE-ConnectionGUID: qyMM7JxAQc2Dxlh3zA27bA== X-CSE-MsgGUID: FFTlKKPPQWGgI9c752RAZg== X-IronPort-AV: E=McAfee;i="6600,9927,11054"; a="12545738" X-IronPort-AV: E=Sophos;i="6.07,226,1708416000"; d="scan'208";a="12545738" Received: from orviesa008.jf.intel.com ([10.64.159.148]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Apr 2024 08:36:52 -0700 X-CSE-ConnectionGUID: EqlMxMwfR0So2IC58bXQRw== X-CSE-MsgGUID: Fj+hfyk8SMW84bBFBFFm3g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,226,1708416000"; d="scan'208";a="25363219" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.36]) by orviesa008.jf.intel.com with ESMTP; 24 Apr 2024 08:36:47 -0700 From: Zhao Liu To: Eduardo Habkost , Marcel Apfelbaum , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Yanan Wang , "Michael S . Tsirkin" , Richard Henderson , Paolo Bonzini , Eric Blake , Markus Armbruster , Marcelo Tosatti , =?UTF-8?q?Daniel=20P=20=2E=20Berrang=C3=A9?= Cc: qemu-devel@nongnu.org, kvm@vger.kernel.org, Zhenyu Wang , Zhuocheng Ding , Babu Moger , Xiaoyao Li , Dapeng Mi , Yongwei Ma , Zhao Liu Subject: [PATCH v11 11/21] i386/cpu: Decouple CPUID[0x1F] subleaf with specific topology level Date: Wed, 24 Apr 2024 23:49:19 +0800 Message-Id: <20240424154929.1487382-12-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240424154929.1487382-1-zhao1.liu@intel.com> References: <20240424154929.1487382-1-zhao1.liu@intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit At present, the subleaf 0x02 of CPUID[0x1F] is bound to the "die" level. In fact, the specific topology level exposed in 0x1F depends on the platform's support for extension levels (module, tile and die). To help expose "module" level in 0x1F, decouple CPUID[0x1F] subleaf with specific topology level. Tested-by: Yongwei Ma Signed-off-by: Zhao Liu Tested-by: Babu Moger Reviewed-by: Xiaoyao Li --- Changes since v10: * Combined ecx and edx encoding into the single line. (Xiaoyao) * Fixed the comment in encode_topo_cpuid1f(). (Xiaoyao) Changes since v7: * Refactored the encode_topo_cpuid1f() to use traversal to search the encoded level and avoid using static variables. (Xiaoyao) - Since the total number of levels in the bitmap is not too large, the overhead of traversing is supposed to be acceptable. * Renamed the variable num_cpus_next_level to num_threads_next_level. (Xiaoyao) * Renamed the helper num_cpus_by_topo_level() to num_threads_by_topo_level(). (Xiaoyao) * Dropped Michael/Babu's Acked/Tested tags since the code change. * Re-added Yongwei's Tested tag For his re-testing. Changes since v3: * New patch to prepare to expose module level in 0x1F. * Moved the CPUTopoLevel enumeration definition from "i386: Add cache topology info in CPUCacheInfo" to this patch. Note, to align with topology types in SDM, revert the name of CPU_TOPO_LEVEL_UNKNOW to CPU_TOPO_LEVEL_INVALID. --- target/i386/cpu.c | 135 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 110 insertions(+), 25 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index a39c45585be0..504ec569e0b2 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -269,6 +269,115 @@ static void encode_cache_cpuid4(CPUCacheInfo *cache, (cache->complex_indexing ? CACHE_COMPLEX_IDX : 0); } +static uint32_t num_threads_by_topo_level(X86CPUTopoInfo *topo_info, + enum CPUTopoLevel topo_level) +{ + switch (topo_level) { + case CPU_TOPO_LEVEL_SMT: + return 1; + case CPU_TOPO_LEVEL_CORE: + return topo_info->threads_per_core; + case CPU_TOPO_LEVEL_DIE: + return topo_info->threads_per_core * topo_info->cores_per_die; + case CPU_TOPO_LEVEL_PACKAGE: + return topo_info->threads_per_core * topo_info->cores_per_die * + topo_info->dies_per_pkg; + default: + g_assert_not_reached(); + } + return 0; +} + +static uint32_t apicid_offset_by_topo_level(X86CPUTopoInfo *topo_info, + enum CPUTopoLevel topo_level) +{ + switch (topo_level) { + case CPU_TOPO_LEVEL_SMT: + return 0; + case CPU_TOPO_LEVEL_CORE: + return apicid_core_offset(topo_info); + case CPU_TOPO_LEVEL_DIE: + return apicid_die_offset(topo_info); + case CPU_TOPO_LEVEL_PACKAGE: + return apicid_pkg_offset(topo_info); + default: + g_assert_not_reached(); + } + return 0; +} + +static uint32_t cpuid1f_topo_type(enum CPUTopoLevel topo_level) +{ + switch (topo_level) { + case CPU_TOPO_LEVEL_INVALID: + return CPUID_1F_ECX_TOPO_LEVEL_INVALID; + case CPU_TOPO_LEVEL_SMT: + return CPUID_1F_ECX_TOPO_LEVEL_SMT; + case CPU_TOPO_LEVEL_CORE: + return CPUID_1F_ECX_TOPO_LEVEL_CORE; + case CPU_TOPO_LEVEL_DIE: + return CPUID_1F_ECX_TOPO_LEVEL_DIE; + default: + /* Other types are not supported in QEMU. */ + g_assert_not_reached(); + } + return 0; +} + +static void encode_topo_cpuid1f(CPUX86State *env, uint32_t count, + X86CPUTopoInfo *topo_info, + uint32_t *eax, uint32_t *ebx, + uint32_t *ecx, uint32_t *edx) +{ + X86CPU *cpu = env_archcpu(env); + unsigned long level, next_level; + uint32_t num_threads_next_level, offset_next_level; + + assert(count + 1 < CPU_TOPO_LEVEL_MAX); + + /* + * Find the No.(count + 1) topology level in avail_cpu_topo bitmap. + * The search starts from bit 1 (CPU_TOPO_LEVEL_INVALID + 1). + */ + level = CPU_TOPO_LEVEL_INVALID; + for (int i = 0; i <= count; i++) { + level = find_next_bit(env->avail_cpu_topo, + CPU_TOPO_LEVEL_PACKAGE, + level + 1); + + /* + * CPUID[0x1f] doesn't explicitly encode the package level, + * and it just encodes the invalid level (all fields are 0) + * into the last subleaf of 0x1f. + */ + if (level == CPU_TOPO_LEVEL_PACKAGE) { + level = CPU_TOPO_LEVEL_INVALID; + break; + } + } + + if (level == CPU_TOPO_LEVEL_INVALID) { + num_threads_next_level = 0; + offset_next_level = 0; + } else { + next_level = find_next_bit(env->avail_cpu_topo, + CPU_TOPO_LEVEL_PACKAGE, + level + 1); + num_threads_next_level = num_threads_by_topo_level(topo_info, + next_level); + offset_next_level = apicid_offset_by_topo_level(topo_info, + next_level); + } + + *eax = offset_next_level; + /* The count (bits 15-00) doesn't need to be reliable. */ + *ebx = num_threads_next_level & 0xffff; + *ecx = (count & 0xff) | (cpuid1f_topo_type(level) << 8); + *edx = cpu->apic_id; + + assert(!(*eax & ~0x1f)); +} + /* Encode cache info for CPUID[0x80000005].ECX or CPUID[0x80000005].EDX */ static uint32_t encode_cache_cpuid80000005(CPUCacheInfo *cache) { @@ -6431,31 +6540,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; } - *ecx = count & 0xff; - *edx = cpu->apic_id; - switch (count) { - case 0: - *eax = apicid_core_offset(&topo_info); - *ebx = topo_info.threads_per_core; - *ecx |= CPUID_1F_ECX_TOPO_LEVEL_SMT << 8; - break; - case 1: - *eax = apicid_die_offset(&topo_info); - *ebx = topo_info.cores_per_die * topo_info.threads_per_core; - *ecx |= CPUID_1F_ECX_TOPO_LEVEL_CORE << 8; - break; - case 2: - *eax = apicid_pkg_offset(&topo_info); - *ebx = threads_per_pkg; - *ecx |= CPUID_1F_ECX_TOPO_LEVEL_DIE << 8; - break; - default: - *eax = 0; - *ebx = 0; - *ecx |= CPUID_1F_ECX_TOPO_LEVEL_INVALID << 8; - } - assert(!(*eax & ~0x1f)); - *ebx &= 0xffff; /* The count doesn't need to be reliable. */ + encode_topo_cpuid1f(env, count, &topo_info, eax, ebx, ecx, edx); break; case 0xD: { /* Processor Extended State */ -- 2.34.1