|
@@ -348,3 +348,51 @@ void machine_set_cache_topo_level(MachineState *ms, CacheLevelAndType cache,
|
|
|
{
|
|
|
ms->smp_cache.props[cache].topology = level;
|
|
|
}
|
|
|
+
|
|
|
+/*
|
|
|
+ * When both cache1 and cache2 are configured with specific topology levels
|
|
|
+ * (not default level), is cache1's topology level higher than cache2?
|
|
|
+ */
|
|
|
+static bool smp_cache_topo_cmp(const SmpCache *smp_cache,
|
|
|
+ CacheLevelAndType cache1,
|
|
|
+ CacheLevelAndType cache2)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * Before comparing, the "default" topology level should be replaced
|
|
|
+ * with the specific level.
|
|
|
+ */
|
|
|
+ assert(smp_cache->props[cache1].topology != CPU_TOPOLOGY_LEVEL_DEFAULT);
|
|
|
+
|
|
|
+ return smp_cache->props[cache1].topology > smp_cache->props[cache2].topology;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Currently, we have no way to expose the arch-specific default cache model
|
|
|
+ * because the cache model is sometimes related to the CPU model (e.g., i386).
|
|
|
+ *
|
|
|
+ * We can only check the correctness of the cache topology after the arch loads
|
|
|
+ * the user-configured cache model from MachineState and consumes the special
|
|
|
+ * "default" level by replacing it with the specific level.
|
|
|
+ */
|
|
|
+bool machine_check_smp_cache(const MachineState *ms, Error **errp)
|
|
|
+{
|
|
|
+ if (smp_cache_topo_cmp(&ms->smp_cache, CACHE_LEVEL_AND_TYPE_L1D,
|
|
|
+ CACHE_LEVEL_AND_TYPE_L2) ||
|
|
|
+ smp_cache_topo_cmp(&ms->smp_cache, CACHE_LEVEL_AND_TYPE_L1I,
|
|
|
+ CACHE_LEVEL_AND_TYPE_L2)) {
|
|
|
+ error_setg(errp,
|
|
|
+ "Invalid smp cache topology. "
|
|
|
+ "L2 cache topology level shouldn't be lower than L1 cache");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (smp_cache_topo_cmp(&ms->smp_cache, CACHE_LEVEL_AND_TYPE_L2,
|
|
|
+ CACHE_LEVEL_AND_TYPE_L3)) {
|
|
|
+ error_setg(errp,
|
|
|
+ "Invalid smp cache topology. "
|
|
|
+ "L3 cache topology level shouldn't be lower than L2 cache");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|