Skip to content

Commit

Permalink
Merge tag 'patchew/20200219160953.13771-1-imammedo@redhat.com' of htt…
Browse files Browse the repository at this point in the history
…ps://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.
  • Loading branch information
bonzini committed Feb 25, 2020
2 parents c220cde + 9584b56 commit ca6155c
Show file tree
Hide file tree
Showing 78 changed files with 829 additions and 775 deletions.
8 changes: 0 additions & 8 deletions backends/hostmem-file.c
Expand Up @@ -18,13 +18,6 @@
#include "sysemu/sysemu.h"
#include "qom/object_interfaces.h"

/* hostmem-file.c */
/**
* @TYPE_MEMORY_BACKEND_FILE:
* name of backend that uses mmap on a file descriptor
*/
#define TYPE_MEMORY_BACKEND_FILE "memory-backend-file"

#define MEMORY_BACKEND_FILE(obj) \
OBJECT_CHECK(HostMemoryBackendFile, (obj), TYPE_MEMORY_BACKEND_FILE)

Expand Down Expand Up @@ -58,7 +51,6 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
return;
}

backend->force_prealloc = mem_prealloc;
name = host_memory_backend_get_name(backend);
memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
name,
Expand Down
1 change: 0 additions & 1 deletion backends/hostmem-memfd.c
Expand Up @@ -45,7 +45,6 @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
return;
}

backend->force_prealloc = mem_prealloc;
fd = qemu_memfd_create(TYPE_MEMORY_BACKEND_MEMFD, backend->size,
m->hugetlb, m->hugetlbsize, m->seal ?
F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL : 0,
Expand Down
2 changes: 0 additions & 2 deletions backends/hostmem-ram.c
Expand Up @@ -16,8 +16,6 @@
#include "qemu/module.h"
#include "qom/object_interfaces.h"

#define TYPE_MEMORY_BACKEND_RAM "memory-backend-ram"

static void
ram_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
{
Expand Down
53 changes: 39 additions & 14 deletions backends/hostmem.c
Expand Up @@ -215,23 +215,14 @@ static bool host_memory_backend_get_prealloc(Object *obj, Error **errp)
{
HostMemoryBackend *backend = MEMORY_BACKEND(obj);

return backend->prealloc || backend->force_prealloc;
return backend->prealloc;
}

static void host_memory_backend_set_prealloc(Object *obj, bool value,
Error **errp)
{
Error *local_err = NULL;
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
MachineState *ms = MACHINE(qdev_get_machine());

if (backend->force_prealloc) {
if (value) {
error_setg(errp,
"remove -mem-prealloc to use the prealloc property");
return;
}
}

if (!host_memory_backend_mr_inited(backend)) {
backend->prealloc = value;
Expand All @@ -243,7 +234,7 @@ static void host_memory_backend_set_prealloc(Object *obj, bool value,
void *ptr = memory_region_get_ram_ptr(&backend->mr);
uint64_t sz = memory_region_size(&backend->mr);

os_mem_prealloc(fd, ptr, sz, ms->smp.cpus, &local_err);
os_mem_prealloc(fd, ptr, sz, backend->prealloc_threads, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
Expand All @@ -252,14 +243,43 @@ static void host_memory_backend_set_prealloc(Object *obj, bool value,
}
}

static void host_memory_backend_get_prealloc_threads(Object *obj, Visitor *v,
const char *name, void *opaque, Error **errp)
{
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
visit_type_uint32(v, name, &backend->prealloc_threads, errp);
}

static void host_memory_backend_set_prealloc_threads(Object *obj, Visitor *v,
const char *name, void *opaque, Error **errp)
{
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
Error *local_err = NULL;
uint32_t value;

visit_type_uint32(v, name, &value, &local_err);
if (local_err) {
goto out;
}
if (value <= 0) {
error_setg(&local_err,
"property '%s' of %s doesn't take value '%d'",
name, object_get_typename(obj), value);
goto out;
}
backend->prealloc_threads = value;
out:
error_propagate(errp, local_err);
}

static void host_memory_backend_init(Object *obj)
{
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
MachineState *machine = MACHINE(qdev_get_machine());

/* TODO: convert access to globals to compat properties */
backend->merge = machine_mem_merge(machine);
backend->dump = machine_dump_guest_core(machine);
backend->prealloc = mem_prealloc;
}

static void host_memory_backend_post_init(Object *obj)
Expand Down Expand Up @@ -313,7 +333,6 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
{
HostMemoryBackend *backend = MEMORY_BACKEND(uc);
HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc);
MachineState *ms = MACHINE(qdev_get_machine());
Error *local_err = NULL;
void *ptr;
uint64_t sz;
Expand Down Expand Up @@ -378,7 +397,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
*/
if (backend->prealloc) {
os_mem_prealloc(memory_region_get_fd(&backend->mr), ptr, sz,
ms->smp.cpus, &local_err);
backend->prealloc_threads, &local_err);
if (local_err) {
goto out;
}
Expand Down Expand Up @@ -456,6 +475,12 @@ host_memory_backend_class_init(ObjectClass *oc, void *data)
host_memory_backend_set_prealloc, &error_abort);
object_class_property_set_description(oc, "prealloc",
"Preallocate memory", &error_abort);
object_class_property_add(oc, "prealloc-threads", "int",
host_memory_backend_get_prealloc_threads,
host_memory_backend_set_prealloc_threads,
NULL, NULL, &error_abort);
object_class_property_set_description(oc, "prealloc-threads",
"Number of CPU threads to use for prealloc", &error_abort);
object_class_property_add(oc, "size", "int",
host_memory_backend_get_size,
host_memory_backend_set_size,
Expand Down
64 changes: 6 additions & 58 deletions exec.c
Expand Up @@ -1668,59 +1668,18 @@ static int find_max_backend_pagesize(Object *obj, void *opaque)
long qemu_minrampagesize(void)
{
long hpsize = LONG_MAX;
long mainrampagesize;
Object *memdev_root;
MachineState *ms = MACHINE(qdev_get_machine());

mainrampagesize = qemu_mempath_getpagesize(mem_path);

/* it's possible we have memory-backend objects with
* hugepage-backed RAM. these may get mapped into system
* address space via -numa parameters or memory hotplug
* hooks. we want to take these into account, but we
* also want to make sure these supported hugepage
* sizes are applicable across the entire range of memory
* we may boot from, so we take the min across all
* backends, and assume normal pages in cases where a
* backend isn't backed by hugepages.
*/
memdev_root = object_resolve_path("/objects", NULL);
if (memdev_root) {
object_child_foreach(memdev_root, find_min_backend_pagesize, &hpsize);
}
if (hpsize == LONG_MAX) {
/* No additional memory regions found ==> Report main RAM page size */
return mainrampagesize;
}

/* If NUMA is disabled or the NUMA nodes are not backed with a
* memory-backend, then there is at least one node using "normal" RAM,
* so if its page size is smaller we have got to report that size instead.
*/
if (hpsize > mainrampagesize &&
(ms->numa_state == NULL ||
ms->numa_state->num_nodes == 0 ||
ms->numa_state->nodes[0].node_memdev == NULL)) {
static bool warned;
if (!warned) {
error_report("Huge page support disabled (n/a for main memory).");
warned = true;
}
return mainrampagesize;
}
Object *memdev_root = object_resolve_path("/objects", NULL);

object_child_foreach(memdev_root, find_min_backend_pagesize, &hpsize);
return hpsize;
}

long qemu_maxrampagesize(void)
{
long pagesize = qemu_mempath_getpagesize(mem_path);
long pagesize = 0;
Object *memdev_root = object_resolve_path("/objects", NULL);

if (memdev_root) {
object_child_foreach(memdev_root, find_max_backend_pagesize,
&pagesize);
}
object_child_foreach(memdev_root, find_max_backend_pagesize, &pagesize);
return pagesize;
}
#else
Expand Down Expand Up @@ -1843,8 +1802,6 @@ static void *file_ram_alloc(RAMBlock *block,
bool truncate,
Error **errp)
{
Error *err = NULL;
MachineState *ms = MACHINE(qdev_get_machine());
void *area;

block->page_size = qemu_fd_getpagesize(fd);
Expand Down Expand Up @@ -1900,15 +1857,6 @@ static void *file_ram_alloc(RAMBlock *block,
return NULL;
}

if (mem_prealloc) {
os_mem_prealloc(fd, area, memory, ms->smp.cpus, &err);
if (err) {
error_propagate(errp, err);
qemu_ram_munmap(fd, area, memory);
return NULL;
}
}

block->fd = fd;
return area;
}
Expand Down Expand Up @@ -2356,9 +2304,9 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
size = HOST_PAGE_ALIGN(size);
file_size = get_file_size(fd);
if (file_size > 0 && file_size < size) {
error_setg(errp, "backing store %s size 0x%" PRIx64
error_setg(errp, "backing store size 0x%" PRIx64
" does not match 'size' option 0x" RAM_ADDR_FMT,
mem_path, file_size, size);
file_size, size);
return NULL;
}

Expand Down
2 changes: 1 addition & 1 deletion hw/alpha/alpha_sys.h
Expand Up @@ -11,7 +11,7 @@
#include "hw/intc/i8259.h"


PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, AlphaCPU *[4],
PCIBus *typhoon_init(MemoryRegion *, ISABus **, qemu_irq *, AlphaCPU *[4],
pci_map_irq_fn);

/* alpha_pci.c. */
Expand Down
3 changes: 2 additions & 1 deletion hw/alpha/dp264.c
Expand Up @@ -75,7 +75,7 @@ static void clipper_init(MachineState *machine)
cpus[0]->env.trap_arg2 = smp_cpus;

/* Init the chipset. */
pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus,
pci_bus = typhoon_init(machine->ram, &isa_bus, &rtc_irq, cpus,
clipper_pci_map_irq);

/* Since we have an SRM-compatible PALcode, use the SRM epoch. */
Expand Down Expand Up @@ -183,6 +183,7 @@ static void clipper_machine_init(MachineClass *mc)
mc->max_cpus = 4;
mc->is_default = 1;
mc->default_cpu_type = ALPHA_CPU_TYPE_NAME("ev67");
mc->default_ram_id = "ram";
}

DEFINE_MACHINE("clipper", clipper_machine_init)
8 changes: 2 additions & 6 deletions hw/alpha/typhoon.c
Expand Up @@ -58,7 +58,6 @@ typedef struct TyphoonState {
TyphoonCchip cchip;
TyphoonPchip pchip;
MemoryRegion dchip_region;
MemoryRegion ram_region;
} TyphoonState;

/* Called when one of DRIR or DIM changes. */
Expand Down Expand Up @@ -817,8 +816,7 @@ static void typhoon_alarm_timer(void *opaque)
cpu_interrupt(CPU(s->cchip.cpu[cpu]), CPU_INTERRUPT_TIMER);
}

PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
qemu_irq *p_rtc_irq,
PCIBus *typhoon_init(MemoryRegion *ram, ISABus **isa_bus, qemu_irq *p_rtc_irq,
AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq)
{
MemoryRegion *addr_space = get_system_memory();
Expand Down Expand Up @@ -851,9 +849,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,

/* Main memory region, 0x00.0000.0000. Real hardware supports 32GB,
but the address space hole reserved at this point is 8TB. */
memory_region_allocate_system_memory(&s->ram_region, OBJECT(s), "ram",
ram_size);
memory_region_add_subregion(addr_space, 0, &s->ram_region);
memory_region_add_subregion(addr_space, 0, ram);

/* TIGbus, 0x801.0000.0000, 1GB. */
/* ??? The TIGbus is used for delivering interrupts, and access to
Expand Down
18 changes: 7 additions & 11 deletions hw/arm/aspeed.c
Expand Up @@ -35,7 +35,6 @@ static struct arm_boot_info aspeed_board_binfo = {
struct AspeedBoardState {
AspeedSoCState soc;
MemoryRegion ram_container;
MemoryRegion ram;
MemoryRegion max_ram;
};

Expand Down Expand Up @@ -197,15 +196,20 @@ static void aspeed_machine_init(MachineState *machine)

memory_region_init(&bmc->ram_container, NULL, "aspeed-ram-container",
UINT32_MAX);
memory_region_add_subregion(&bmc->ram_container, 0, machine->ram);

object_initialize_child(OBJECT(machine), "soc", &bmc->soc,
(sizeof(bmc->soc)), amc->soc_name, &error_abort,
NULL);

sc = ASPEED_SOC_GET_CLASS(&bmc->soc);

/*
* This will error out if isize is not supported by memory controller.
*/
object_property_set_uint(OBJECT(&bmc->soc), ram_size, "ram-size",
&error_abort);
&error_fatal);

object_property_set_int(OBJECT(&bmc->soc), amc->hw_strap1, "hw-strap1",
&error_abort);
object_property_set_int(OBJECT(&bmc->soc), amc->hw_strap2, "hw-strap2",
Expand All @@ -228,15 +232,6 @@ static void aspeed_machine_init(MachineState *machine)
object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
&error_abort);

/*
* Allocate RAM after the memory controller has checked the size
* was valid. If not, a default value is used.
*/
ram_size = object_property_get_uint(OBJECT(&bmc->soc), "ram-size",
&error_abort);

memory_region_allocate_system_memory(&bmc->ram, NULL, "ram", ram_size);
memory_region_add_subregion(&bmc->ram_container, 0, &bmc->ram);
memory_region_add_subregion(get_system_memory(),
sc->memmap[ASPEED_SDRAM],
&bmc->ram_container);
Expand Down Expand Up @@ -439,6 +434,7 @@ static void aspeed_machine_class_init(ObjectClass *oc, void *data)
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->no_parallel = 1;
mc->default_ram_id = "ram";

aspeed_machine_class_props_init(oc);
}
Expand Down
16 changes: 12 additions & 4 deletions hw/arm/collie.c
Expand Up @@ -10,6 +10,7 @@
*/
#include "qemu/osdep.h"
#include "qemu/units.h"
#include "qemu/cutils.h"
#include "hw/sysbus.h"
#include "hw/boards.h"
#include "strongarm.h"
Expand All @@ -27,13 +28,18 @@ static void collie_init(MachineState *machine)
{
StrongARMState *s;
DriveInfo *dinfo;
MemoryRegion *sdram = g_new(MemoryRegion, 1);
MachineClass *mc = MACHINE_GET_CLASS(machine);

if (machine->ram_size != mc->default_ram_size) {
char *sz = size_to_str(mc->default_ram_size);
error_report("Invalid RAM size, should be %s", sz);
g_free(sz);
exit(EXIT_FAILURE);
}

s = sa1110_init(machine->cpu_type);

memory_region_allocate_system_memory(sdram, NULL, "strongarm.sdram",
collie_binfo.ram_size);
memory_region_add_subregion(get_system_memory(), SA_SDCS0, sdram);
memory_region_add_subregion(get_system_memory(), SA_SDCS0, machine->ram);

dinfo = drive_get(IF_PFLASH, 0, 0);
pflash_cfi01_register(SA_CS0, "collie.fl1", 0x02000000,
Expand All @@ -57,6 +63,8 @@ static void collie_machine_init(MachineClass *mc)
mc->init = collie_init;
mc->ignore_memory_transaction_failures = true;
mc->default_cpu_type = ARM_CPU_TYPE_NAME("sa1110");
mc->default_ram_size = 0x20000000;
mc->default_ram_id = "strongarm.sdram";
}

DEFINE_MACHINE("collie", collie_machine_init)

0 comments on commit ca6155c

Please sign in to comment.