diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2020-02-25 09:19:00 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2020-02-25 09:19:00 +0100 |
commit | ca6155c0f2bd39b4b4162533be401c98bd960820 (patch) | |
tree | 7e5212409c90fa40b6a50923557f2083c23637ba /hw/core/numa.c | |
parent | c220cdec4845f305034330f80ce297f1f997f2d3 (diff) | |
parent | 9584b564198193bd54f00a01ed7e039d4f03fa31 (diff) |
Merge tag 'patchew/20200219160953.13771-1-imammedo@redhat.com' of https://github.com/patchew-project/qemu into HEAD
This series removes ad hoc RAM allocation API (memory_region_allocate_system_memory)
and consolidates it around hostmem backend. It allows to
* resolve conflicts between global -mem-prealloc and hostmem's "policy" option,
fixing premature allocation before binding policy is applied
* simplify complicated memory allocation routines which had to deal with 2 ways
to allocate RAM.
* reuse hostmem backends of a choice for main RAM without adding extra CLI
options to duplicate hostmem features. A recent case was -mem-shared, to
enable vhost-user on targets that don't support hostmem backends [1] (ex: s390)
* move RAM allocation from individual boards into generic machine code and
provide them with prepared MemoryRegion.
* clean up deprecated NUMA features which were tied to the old API (see patches)
- "numa: remove deprecated -mem-path fallback to anonymous RAM"
- (POSTPONED, waiting on libvirt side) "forbid '-numa node,mem' for 5.0 and newer machine types"
- (POSTPONED) "numa: remove deprecated implicit RAM distribution between nodes"
Introduce a new machine.memory-backend property and wrapper code that aliases
global -mem-path and -mem-alloc into automatically created hostmem backend
properties (provided memory-backend was not set explicitly given by user).
A bulk of trivial patches then follow to incrementally convert individual
boards to using machine.memory-backend provided MemoryRegion.
Board conversion typically involves:
* providing MachineClass::default_ram_size and MachineClass::default_ram_id
so generic code could create default backend if user didn't explicitly provide
memory-backend or -m options
* dropping memory_region_allocate_system_memory() call
* using convenience MachineState::ram MemoryRegion, which points to MemoryRegion
allocated by ram-memdev
On top of that for some boards:
* missing ram_size checks are added (typically it were boards with fixed ram size)
* ram_size fixups are replaced by checks and hard errors, forcing user to
provide correct "-m" values instead of ignoring it and continuing running.
After all boards are converted, the old API is removed and memory allocation
routines are cleaned up.
Diffstat (limited to 'hw/core/numa.c')
-rw-r--r-- | hw/core/numa.c | 101 |
1 files changed, 28 insertions, 73 deletions
diff --git a/hw/core/numa.c b/hw/core/numa.c index 0d1b4be76a..316bc50d75 100644 --- a/hw/core/numa.c +++ b/hw/core/numa.c @@ -52,6 +52,11 @@ QemuOptsList qemu_numa_opts = { }; static int have_memdevs; +bool numa_uses_legacy_mem(void) +{ + return !have_memdevs; +} + static int have_mem; static int max_numa_nodeid; /* Highest specified NUMA node ID, plus one. * For all nodes, nodeid < max_numa_nodeid @@ -652,6 +657,23 @@ void numa_default_auto_assign_ram(MachineClass *mc, NodeInfo *nodes, nodes[i].node_mem = size - usedmem; } +static void numa_init_memdev_container(MachineState *ms, MemoryRegion *ram) +{ + int i; + uint64_t addr = 0; + + for (i = 0; i < ms->numa_state->num_nodes; i++) { + uint64_t size = ms->numa_state->nodes[i].node_mem; + HostMemoryBackend *backend = ms->numa_state->nodes[i].node_memdev; + if (!backend) { + continue; + } + MemoryRegion *seg = machine_consume_memdev(ms, backend); + memory_region_add_subregion(ram, addr, seg); + addr += size; + } +} + void numa_complete_configuration(MachineState *ms) { int i; @@ -734,6 +756,12 @@ void numa_complete_configuration(MachineState *ms) exit(1); } + if (!numa_uses_legacy_mem() && mc->default_ram_id) { + ms->ram = g_new(MemoryRegion, 1); + memory_region_init(ms->ram, OBJECT(ms), mc->default_ram_id, + ram_size); + numa_init_memdev_container(ms, ms->ram); + } /* QEMU needs at least all unique node pair distances to build * the whole NUMA distance table. QEMU treats the distance table * as symmetric by default, i.e. distance A->B == distance B->A. @@ -778,79 +806,6 @@ void numa_cpu_pre_plug(const CPUArchId *slot, DeviceState *dev, Error **errp) } } -static void allocate_system_memory_nonnuma(MemoryRegion *mr, Object *owner, - const char *name, - uint64_t ram_size) -{ - if (mem_path) { -#ifdef __linux__ - Error *err = NULL; - 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); - } - warn_report("falling back to regular RAM allocation"); - error_printf("This is deprecated. Make sure that -mem-path " - " specified path has sufficient resources to allocate" - " -m specified RAM amount\n"); - /* 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 - fprintf(stderr, "-mem-path not supported on this host\n"); - exit(1); -#endif - } else { - memory_region_init_ram_nomigrate(mr, owner, name, ram_size, &error_fatal); - } - vmstate_register_ram_global(mr); -} - -void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner, - const char *name, - uint64_t ram_size) -{ - uint64_t addr = 0; - int i; - MachineState *ms = MACHINE(qdev_get_machine()); - - if (ms->numa_state == NULL || - ms->numa_state->num_nodes == 0 || !have_memdevs) { - allocate_system_memory_nonnuma(mr, owner, name, ram_size); - return; - } - - memory_region_init(mr, owner, name, ram_size); - for (i = 0; i < ms->numa_state->num_nodes; i++) { - uint64_t size = ms->numa_state->nodes[i].node_mem; - HostMemoryBackend *backend = ms->numa_state->nodes[i].node_memdev; - if (!backend) { - continue; - } - 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); - } - - host_memory_backend_set_mapped(backend, true); - memory_region_add_subregion(mr, addr, seg); - vmstate_register_ram_global(seg); - addr += size; - } -} - static void numa_stat_memory_devices(NumaNodeMem node_mem[]) { MemoryDeviceInfoList *info_list = qmp_memory_device_list(); |