X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=numa.c;h=955ec0c830db4981b929d6c9a72fb8f8a8888c59;hb=6b7ac49d570c66754fad1b80cc200c7596d1facd;hp=7b9c33ad1208047fc73e7f52faf2eea7beeb5f5a;hpb=eaefea537b476cb853e2edbdc68e969ec777e4bb;p=mirror_qemu.git diff --git a/numa.c b/numa.c index 7b9c33ad12..955ec0c830 100644 --- a/numa.c +++ b/numa.c @@ -29,12 +29,14 @@ #include "qemu/bitmap.h" #include "qom/cpu.h" #include "qemu/error-report.h" -#include "qapi-visit.h" +#include "qapi/error.h" #include "qapi/opts-visitor.h" +#include "qapi/qapi-commands-misc.h" +#include "qapi/qapi-visit-misc.h" #include "hw/boards.h" #include "sysemu/hostmem.h" -#include "qmp-commands.h" #include "hw/mem/pc-dimm.h" +#include "hw/mem/memory-device.h" #include "qemu/option.h" #include "qemu/config-file.h" #include "qemu/cutils.h" @@ -58,6 +60,7 @@ NodeInfo numa_info[MAX_NODES]; static void parse_numa_node(MachineState *ms, NumaNodeOptions *node, Error **errp) { + Error *err = NULL; uint16_t nodenr; uint16List *cpus = NULL; MachineClass *mc = MACHINE_GET_CLASS(ms); @@ -79,9 +82,9 @@ static void parse_numa_node(MachineState *ms, NumaNodeOptions *node, return; } - if (!mc->cpu_index_to_instance_props) { - error_report("NUMA is not supported by this machine-type"); - exit(1); + if (!mc->cpu_index_to_instance_props || !mc->get_default_cpu_node_id) { + error_setg(errp, "NUMA is not supported by this machine-type"); + return; } for (cpus = node->cpus; cpus; cpus = cpus->next) { CpuInstanceProperties props; @@ -95,7 +98,11 @@ static void parse_numa_node(MachineState *ms, NumaNodeOptions *node, props = mc->cpu_index_to_instance_props(ms, cpus->value); props.node_id = nodenr; props.has_node_id = true; - machine_set_cpu_numa_node(ms, &props, &error_fatal); + machine_set_cpu_numa_node(ms, &props, &err); + if (err) { + error_propagate(errp, err); + return; + } } if (node->has_mem && node->has_memdev) { @@ -139,9 +146,8 @@ static void parse_numa_distance(NumaDistOptions *dist, Error **errp) uint8_t val = dist->val; if (src >= MAX_NODES || dst >= MAX_NODES) { - error_setg(errp, - "Invalid node %d, max possible could be %d", - MAX(src, dst), MAX_NODES); + error_setg(errp, "Parameter '%s' expects an integer between 0 and %d", + src >= MAX_NODES ? "src" : "dst", MAX_NODES - 1); return; } @@ -168,28 +174,11 @@ static void parse_numa_distance(NumaDistOptions *dist, Error **errp) have_numa_distance = true; } -static int parse_numa(void *opaque, QemuOpts *opts, Error **errp) +static +void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp) { - NumaOptions *object = NULL; - MachineState *ms = opaque; Error *err = NULL; - { - Visitor *v = opts_visitor_new(opts); - visit_type_NumaOptions(v, NULL, &object, &err); - visit_free(v); - } - - if (err) { - goto end; - } - - /* Fix up legacy suffix-less format */ - if ((object->type == NUMA_OPTIONS_TYPE_NODE) && object->u.node.has_mem) { - const char *mem_str = qemu_opt_get(opts, "mem"); - qemu_strtosz_MiB(mem_str, NULL, &object->u.node.mem); - } - switch (object->type) { case NUMA_OPTIONS_TYPE_NODE: parse_numa_node(ms, &object->u.node, &err); @@ -222,10 +211,35 @@ static int parse_numa(void *opaque, QemuOpts *opts, Error **errp) abort(); } +end: + error_propagate(errp, err); +} + +static int parse_numa(void *opaque, QemuOpts *opts, Error **errp) +{ + NumaOptions *object = NULL; + MachineState *ms = MACHINE(opaque); + Error *err = NULL; + Visitor *v = opts_visitor_new(opts); + + visit_type_NumaOptions(v, NULL, &object, &err); + visit_free(v); + if (err) { + goto end; + } + + /* Fix up legacy suffix-less format */ + if ((object->type == NUMA_OPTIONS_TYPE_NODE) && object->u.node.has_mem) { + const char *mem_str = qemu_opt_get(opts, "mem"); + qemu_strtosz_MiB(mem_str, NULL, &object->u.node.mem); + } + + set_numa_options(ms, object, &err); + end: qapi_free_NumaOptions(object); if (err) { - error_report_err(err); + error_propagate(errp, err); return -1; } @@ -337,15 +351,11 @@ void numa_default_auto_assign_ram(MachineClass *mc, NodeInfo *nodes, nodes[i].node_mem = size - usedmem; } -void parse_numa_opts(MachineState *ms) +void numa_complete_configuration(MachineState *ms) { int i; MachineClass *mc = MACHINE_GET_CLASS(ms); - if (qemu_opts_foreach(qemu_find_opts("numa"), parse_numa, ms, NULL)) { - exit(1); - } - /* * If memory hotplug is enabled (slots > 0) but without '-numa' * options explicitly on CLI, guestes will break. @@ -362,7 +372,7 @@ void parse_numa_opts(MachineState *ms) if (ms->ram_slots > 0 && nb_numa_nodes == 0 && mc->auto_enable_numa_with_memhp) { NumaNodeOptions node = { }; - parse_numa_node(ms, &node, NULL); + parse_numa_node(ms, &node, &error_abort); } assert(max_numa_nodeid <= MAX_NODES); @@ -432,6 +442,22 @@ void parse_numa_opts(MachineState *ms) } } +void parse_numa_opts(MachineState *ms) +{ + qemu_opts_foreach(qemu_find_opts("numa"), parse_numa, ms, &error_fatal); +} + +void qmp_set_numa_node(NumaOptions *cmd, Error **errp) +{ + if (!runstate_check(RUN_STATE_PRECONFIG)) { + error_setg(errp, "The command is permitted only in '%s' state", + RunState_str(RUN_STATE_PRECONFIG)); + return; + } + + set_numa_options(MACHINE(qdev_get_machine()), cmd, errp); +} + void numa_cpu_pre_plug(const CPUArchId *slot, DeviceState *dev, Error **errp) { int node_id = object_property_get_int(OBJECT(dev), "node-id", &error_abort); @@ -444,8 +470,8 @@ void numa_cpu_pre_plug(const CPUArchId *slot, DeviceState *dev, Error **errp) "node-id", errp); } } else if (node_id != slot->props.node_id) { - error_setg(errp, "node-id=%d must match numa node specified " - "with -numa option", node_id); + error_setg(errp, "invalid node-id, must be %"PRId64, + slot->props.node_id); } } @@ -456,17 +482,19 @@ static void allocate_system_memory_nonnuma(MemoryRegion *mr, Object *owner, if (mem_path) { #ifdef __linux__ Error *err = NULL; - memory_region_init_ram_from_file(mr, owner, name, ram_size, false, + memory_region_init_ram_from_file(mr, owner, name, ram_size, 0, 0, mem_path, &err); if (err) { error_report_err(err); if (mem_prealloc) { exit(1); } + error_report("falling back to regular RAM allocation."); /* Legacy behavior: if allocation failed, fall back to * regular RAM allocation. */ + mem_path = NULL; memory_region_init_ram_nomigrate(mr, owner, name, ram_size, &error_fatal); } #else @@ -498,14 +526,14 @@ void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner, if (!backend) { continue; } - MemoryRegion *seg = host_memory_backend_get_memory(backend, - &error_fatal); + MemoryRegion *seg = host_memory_backend_get_memory(backend); if (memory_region_is_mapped(seg)) { char *path = object_get_canonical_path_component(OBJECT(backend)); error_report("memory backend %s is used multiple times. Each " "-numa option must use a different memdev value.", path); + g_free(path); exit(1); } @@ -518,30 +546,33 @@ void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner, static void numa_stat_memory_devices(NumaNodeMem node_mem[]) { - MemoryDeviceInfoList *info_list = NULL; - MemoryDeviceInfoList **prev = &info_list; + MemoryDeviceInfoList *info_list = qmp_memory_device_list(); MemoryDeviceInfoList *info; PCDIMMDeviceInfo *pcdimm_info; - qmp_pc_dimm_device_list(qdev_get_machine(), &prev); for (info = info_list; info; info = info->next) { MemoryDeviceInfo *value = info->value; if (value) { switch (value->type) { - case MEMORY_DEVICE_INFO_KIND_DIMM: { + case MEMORY_DEVICE_INFO_KIND_DIMM: pcdimm_info = value->u.dimm.data; - node_mem[pcdimm_info->node].node_mem += pcdimm_info->size; - if (pcdimm_info->hotpluggable && pcdimm_info->hotplugged) { - node_mem[pcdimm_info->node].node_plugged_mem += - pcdimm_info->size; - } break; - } + + case MEMORY_DEVICE_INFO_KIND_NVDIMM: + pcdimm_info = value->u.nvdimm.data; + break; default: + pcdimm_info = NULL; break; } + + if (pcdimm_info) { + node_mem[pcdimm_info->node].node_mem += pcdimm_info->size; + node_mem[pcdimm_info->node].node_plugged_mem += + pcdimm_info->size; + } } } qapi_free_MemoryDeviceInfoList(info_list); @@ -571,7 +602,7 @@ static int query_memdev(Object *obj, void *opaque) m->value = g_malloc0(sizeof(*m->value)); - m->value->id = object_property_get_str(obj, "id", NULL); + m->value->id = object_get_canonical_path_component(obj); m->value->has_id = !!m->value->id; m->value->size = object_property_get_uint(obj, "size",