aboutsummaryrefslogtreecommitdiff
path: root/hw/core/machine-smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/core/machine-smp.c')
-rw-r--r--hw/core/machine-smp.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c
index 5d8d7ed..0be0ac0 100644
--- a/hw/core/machine-smp.c
+++ b/hw/core/machine-smp.c
@@ -261,6 +261,82 @@ void machine_parse_smp_config(MachineState *ms,
}
}
+static bool machine_check_topo_support(MachineState *ms,
+ CpuTopologyLevel topo,
+ Error **errp)
+{
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
+
+ if ((topo == CPU_TOPOLOGY_LEVEL_MODULE && !mc->smp_props.modules_supported) ||
+ (topo == CPU_TOPOLOGY_LEVEL_CLUSTER && !mc->smp_props.clusters_supported) ||
+ (topo == CPU_TOPOLOGY_LEVEL_DIE && !mc->smp_props.dies_supported) ||
+ (topo == CPU_TOPOLOGY_LEVEL_BOOK && !mc->smp_props.books_supported) ||
+ (topo == CPU_TOPOLOGY_LEVEL_DRAWER && !mc->smp_props.drawers_supported)) {
+ error_setg(errp,
+ "Invalid topology level: %s. "
+ "The topology level is not supported by this machine",
+ CpuTopologyLevel_str(topo));
+ return false;
+ }
+
+ return true;
+}
+
+bool machine_parse_smp_cache(MachineState *ms,
+ const SmpCachePropertiesList *caches,
+ Error **errp)
+{
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
+ const SmpCachePropertiesList *node;
+ DECLARE_BITMAP(caches_bitmap, CACHE_LEVEL_AND_TYPE__MAX);
+
+ bitmap_zero(caches_bitmap, CACHE_LEVEL_AND_TYPE__MAX);
+ for (node = caches; node; node = node->next) {
+ /* Prohibit users from repeating settings. */
+ if (test_bit(node->value->cache, caches_bitmap)) {
+ error_setg(errp,
+ "Invalid cache properties: %s. "
+ "The cache properties are duplicated",
+ CacheLevelAndType_str(node->value->cache));
+ return false;
+ }
+
+ machine_set_cache_topo_level(ms, node->value->cache,
+ node->value->topology);
+ set_bit(node->value->cache, caches_bitmap);
+ }
+
+ for (int i = 0; i < CACHE_LEVEL_AND_TYPE__MAX; i++) {
+ const SmpCacheProperties *props = &ms->smp_cache.props[i];
+
+ /*
+ * Reject non "default" topology level if the cache isn't
+ * supported by the machine.
+ */
+ if (props->topology != CPU_TOPOLOGY_LEVEL_DEFAULT &&
+ !mc->smp_props.cache_supported[props->cache]) {
+ error_setg(errp,
+ "%s cache topology not supported by this machine",
+ CacheLevelAndType_str(props->cache));
+ return false;
+ }
+
+ if (props->topology == CPU_TOPOLOGY_LEVEL_THREAD) {
+ error_setg(errp,
+ "%s level cache not supported by this machine",
+ CpuTopologyLevel_str(props->topology));
+ return false;
+ }
+
+ if (!machine_check_topo_support(ms, props->topology, errp)) {
+ return false;
+ }
+ }
+
+ mc->smp_props.has_caches = true;
+ return true;
+}
+
unsigned int machine_topo_get_cores_per_socket(const MachineState *ms)
{
return ms->smp.cores * ms->smp.modules * ms->smp.clusters * ms->smp.dies;
@@ -270,3 +346,63 @@ unsigned int machine_topo_get_threads_per_socket(const MachineState *ms)
{
return ms->smp.threads * machine_topo_get_cores_per_socket(ms);
}
+
+CpuTopologyLevel machine_get_cache_topo_level(const MachineState *ms,
+ CacheLevelAndType cache)
+{
+ return ms->smp_cache.props[cache].topology;
+}
+
+void machine_set_cache_topo_level(MachineState *ms, CacheLevelAndType cache,
+ CpuTopologyLevel level)
+{
+ 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;
+}