* 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)
+static uint8_t cpuid2_cache_descriptor(CPUCacheInfo *cache, bool *unmacthed)
{
int i;
}
}
+ *unmacthed |= true;
return CACHE_DESCRIPTOR_UNAVAILABLE;
}
+/* Encode cache info for CPUID[2] */
+static void encode_cache_cpuid2(X86CPU *cpu,
+ uint32_t *eax, uint32_t *ebx,
+ uint32_t *ecx, uint32_t *edx)
+{
+ CPUX86State *env = &cpu->env;
+ CPUCaches *caches = &env->cache_info_cpuid2;
+ int l1d, l1i, l2, l3;
+ bool unmatched = false;
+
+ *eax = 1; /* Number of CPUID[EAX=2] calls required */
+ *ebx = *ecx = *edx = 0;
+
+ l1d = cpuid2_cache_descriptor(caches->l1d_cache, &unmatched);
+ l1i = cpuid2_cache_descriptor(caches->l1i_cache, &unmatched);
+ l2 = cpuid2_cache_descriptor(caches->l2_cache, &unmatched);
+ l3 = cpuid2_cache_descriptor(caches->l3_cache, &unmatched);
+
+ if (!cpu->consistent_cache ||
+ (env->cpuid_min_level < 0x4 && !unmatched)) {
+ /*
+ * Though SDM defines code 0x40 for cases with no L2 or L3. It's
+ * also valid to just ignore l3's code if there's no l2.
+ */
+ if (cpu->enable_l3_cache) {
+ *ecx = l3;
+ }
+ *edx = (l1d << 16) | (l1i << 8) | l2;
+ } else {
+ *ecx = 0;
+ *edx = CACHE_DESCRIPTOR_UNAVAILABLE;
+ }
+}
+
/* CPUID Leaf 4 constants: */
/* EAX: */
*eax = *ebx = *ecx = *edx = 0;
break;
}
- *eax = 1; /* Number of CPUID[EAX=2] calls required */
- *ebx = 0;
- if (!cpu->enable_l3_cache) {
- *ecx = 0;
- } else {
- *ecx = cpuid2_cache_descriptor(env->cache_info_cpuid2.l3_cache);
- }
- *edx = (cpuid2_cache_descriptor(env->cache_info_cpuid2.l1d_cache) << 16) |
- (cpuid2_cache_descriptor(env->cache_info_cpuid2.l1i_cache) << 8) |
- (cpuid2_cache_descriptor(env->cache_info_cpuid2.l2_cache));
+ encode_cache_cpuid2(cpu, eax, ebx, ecx, edx);
break;
case 4:
/* cache info: needed for Core compatibility */