diff options
Diffstat (limited to 'hw/core')
| -rw-r--r-- | hw/core/machine-smp.c | 126 | ||||
| -rw-r--r-- | hw/core/machine.c | 77 |
2 files changed, 175 insertions, 28 deletions
diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c index 5d8d7edcbd..640b2114b4 100644 --- a/hw/core/machine-smp.c +++ b/hw/core/machine-smp.c @@ -261,6 +261,72 @@ 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); + + 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(node->value->cache)); + return false; + } + + if (!machine_check_topo_support(ms, props->topology, errp)) { + return false; + } + } + 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 +336,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; +} diff --git a/hw/core/machine.c b/hw/core/machine.c index 222799bc46..a35c4a8fae 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -11,10 +11,12 @@ */ #include "qemu/osdep.h" +#include "qemu/units.h" #include "qemu/accel.h" #include "sysemu/replay.h" #include "hw/boards.h" #include "hw/loader.h" +#include "qemu/error-report.h" #include "qapi/error.h" #include "qapi/qapi-visit-machine.h" #include "qemu/madvise.h" @@ -34,7 +36,9 @@ #include "hw/virtio/virtio-iommu.h" #include "audio/audio.h" -GlobalProperty hw_compat_9_1[] = {}; +GlobalProperty hw_compat_9_1[] = { + { TYPE_PCI_DEVICE, "x-pcie-ext-tag", "false" }, +}; const size_t hw_compat_9_1_len = G_N_ELEMENTS(hw_compat_9_1); GlobalProperty hw_compat_9_0[] = { @@ -281,33 +285,6 @@ GlobalProperty hw_compat_2_4[] = { }; const size_t hw_compat_2_4_len = G_N_ELEMENTS(hw_compat_2_4); -GlobalProperty hw_compat_2_3[] = { - { "virtio-blk-pci", "any_layout", "off" }, - { "virtio-balloon-pci", "any_layout", "off" }, - { "virtio-serial-pci", "any_layout", "off" }, - { "virtio-9p-pci", "any_layout", "off" }, - { "virtio-rng-pci", "any_layout", "off" }, - { TYPE_PCI_DEVICE, "x-pcie-lnksta-dllla", "off" }, - { "migration", "send-configuration", "off" }, - { "migration", "send-section-footer", "off" }, - { "migration", "store-global-state", "off" }, -}; -const size_t hw_compat_2_3_len = G_N_ELEMENTS(hw_compat_2_3); - -GlobalProperty hw_compat_2_2[] = {}; -const size_t hw_compat_2_2_len = G_N_ELEMENTS(hw_compat_2_2); - -GlobalProperty hw_compat_2_1[] = { - { "intel-hda", "old_msi_addr", "on" }, - { "VGA", "qemu-extended-regs", "off" }, - { "secondary-vga", "qemu-extended-regs", "off" }, - { "virtio-scsi-pci", "any_layout", "off" }, - { "usb-mouse", "usb_version", "1" }, - { "usb-kbd", "usb_version", "1" }, - { "virtio-pci", "virtio-pci-bus-master-bug-migration", "on" }, -}; -const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1); - MachineState *current_machine; static char *machine_get_kernel(Object *obj, Error **errp) @@ -932,6 +909,40 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name, machine_parse_smp_config(ms, config, errp); } +static void machine_get_smp_cache(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + MachineState *ms = MACHINE(obj); + SmpCache *cache = &ms->smp_cache; + SmpCachePropertiesList *head = NULL; + SmpCachePropertiesList **tail = &head; + + for (int i = 0; i < CACHE_LEVEL_AND_TYPE__MAX; i++) { + SmpCacheProperties *node = g_new(SmpCacheProperties, 1); + + node->cache = cache->props[i].cache; + node->topology = cache->props[i].topology; + QAPI_LIST_APPEND(tail, node); + } + + visit_type_SmpCachePropertiesList(v, name, &head, errp); + qapi_free_SmpCachePropertiesList(head); +} + +static void machine_set_smp_cache(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + MachineState *ms = MACHINE(obj); + SmpCachePropertiesList *caches; + + if (!visit_type_SmpCachePropertiesList(v, name, &caches, errp)) { + return; + } + + machine_parse_smp_cache(ms, caches, errp); + qapi_free_SmpCachePropertiesList(caches); +} + static void machine_get_boot(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { @@ -1092,6 +1103,11 @@ static void machine_class_init(ObjectClass *oc, void *data) object_class_property_set_description(oc, "smp", "CPU topology"); + object_class_property_add(oc, "smp-cache", "SmpCachePropertiesWrapper", + machine_get_smp_cache, machine_set_smp_cache, NULL, NULL); + object_class_property_set_description(oc, "smp-cache", + "Cache properties list for SMP machine"); + object_class_property_add(oc, "phandle-start", "int", machine_get_phandle_start, machine_set_phandle_start, NULL, NULL); @@ -1230,6 +1246,11 @@ static void machine_initfn(Object *obj) ms->smp.cores = 1; ms->smp.threads = 1; + for (int i = 0; i < CACHE_LEVEL_AND_TYPE__MAX; i++) { + ms->smp_cache.props[i].cache = (CacheLevelAndType)i; + ms->smp_cache.props[i].topology = CPU_TOPOLOGY_LEVEL_DEFAULT; + } + machine_copy_boot_config(ms, &(BootConfiguration){ 0 }); } |