7975feece9
We want to support memory devices that have a memory region container as device memory region that maps multiple RAM memory regions. Let's start by supporting memory devices that statically map multiple RAM memory regions and, thereby, consume multiple memslots. We already have one device that uses a container as device memory region: NVDIMMs. However, a NVDIMM always ends up consuming exactly one memslot. Let's add support for that by asking the memory device via a new callback how many memslots it requires. Message-ID: <20230926185738.277351-7-david@redhat.com> Reviewed-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: David Hildenbrand <david@redhat.com>
136 lines
4.9 KiB
C
136 lines
4.9 KiB
C
/*
|
|
* Memory Device Interface
|
|
*
|
|
* Copyright (c) 2018 Red Hat, Inc.
|
|
*
|
|
* Authors:
|
|
* David Hildenbrand <david@redhat.com>
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
* See the COPYING file in the top-level directory.
|
|
*/
|
|
|
|
#ifndef MEMORY_DEVICE_H
|
|
#define MEMORY_DEVICE_H
|
|
|
|
#include "hw/qdev-core.h"
|
|
#include "qapi/qapi-types-machine.h"
|
|
#include "qom/object.h"
|
|
|
|
#define TYPE_MEMORY_DEVICE "memory-device"
|
|
|
|
typedef struct MemoryDeviceClass MemoryDeviceClass;
|
|
DECLARE_CLASS_CHECKERS(MemoryDeviceClass, MEMORY_DEVICE,
|
|
TYPE_MEMORY_DEVICE)
|
|
#define MEMORY_DEVICE(obj) \
|
|
INTERFACE_CHECK(MemoryDeviceState, (obj), TYPE_MEMORY_DEVICE)
|
|
|
|
typedef struct MemoryDeviceState MemoryDeviceState;
|
|
|
|
/**
|
|
* MemoryDeviceClass:
|
|
*
|
|
* All memory devices need to implement TYPE_MEMORY_DEVICE as an interface.
|
|
*
|
|
* A memory device is a device that owns a memory region which is
|
|
* mapped into guest physical address space at a certain address. The
|
|
* address in guest physical memory can either be specified explicitly
|
|
* or get assigned automatically.
|
|
*
|
|
* Conceptually, memory devices only span one memory region. If multiple
|
|
* successive memory regions are used, a covering memory region has to
|
|
* be provided. Scattered memory regions are not supported for single
|
|
* devices.
|
|
*
|
|
* The device memory region returned via @get_memory_region may either be a
|
|
* single RAM memory region or a memory region container with subregions
|
|
* that are RAM memory regions or aliases to RAM memory regions. Other
|
|
* memory regions or subregions are not supported.
|
|
*/
|
|
struct MemoryDeviceClass {
|
|
/* private */
|
|
InterfaceClass parent_class;
|
|
|
|
/*
|
|
* Return the address of the memory device in guest physical memory.
|
|
*
|
|
* Called when (un)plugging a memory device or when iterating over
|
|
* all memory devices mapped into guest physical address space.
|
|
*
|
|
* If "0" is returned, no address has been specified by the user and
|
|
* no address has been assigned to this memory device yet.
|
|
*/
|
|
uint64_t (*get_addr)(const MemoryDeviceState *md);
|
|
|
|
/*
|
|
* Set the address of the memory device in guest physical memory.
|
|
*
|
|
* Called when plugging the memory device to configure the determined
|
|
* address in guest physical memory.
|
|
*/
|
|
void (*set_addr)(MemoryDeviceState *md, uint64_t addr, Error **errp);
|
|
|
|
/*
|
|
* Return the amount of memory provided by the memory device currently
|
|
* usable ("plugged") by the VM.
|
|
*
|
|
* Called when calculating the total amount of ram available to the
|
|
* VM (e.g. to report memory stats to the user).
|
|
*
|
|
* This is helpful for devices that dynamically manage the amount of
|
|
* memory accessible by the guest via the reserved memory region. For
|
|
* most devices, this corresponds to the size of the memory region.
|
|
*/
|
|
uint64_t (*get_plugged_size)(const MemoryDeviceState *md, Error **errp);
|
|
|
|
/*
|
|
* Return the memory region of the memory device.
|
|
*
|
|
* Called when (un)plugging the memory device, to (un)map the
|
|
* memory region in guest physical memory, but also to detect the
|
|
* required alignment during address assignment or when the size of the
|
|
* memory region is required.
|
|
*/
|
|
MemoryRegion *(*get_memory_region)(MemoryDeviceState *md, Error **errp);
|
|
|
|
/*
|
|
* Optional for memory devices that require only a single memslot,
|
|
* required for all other memory devices: Return the number of memslots
|
|
* (distinct RAM memory regions in the device memory region) that are
|
|
* required by the device.
|
|
*
|
|
* If this function is not implemented, the assumption is "1".
|
|
*
|
|
* Called when (un)plugging the memory device, to check if the requirements
|
|
* can be satisfied, and to do proper accounting.
|
|
*/
|
|
unsigned int (*get_memslots)(MemoryDeviceState *md);
|
|
|
|
/*
|
|
* Optional: Return the desired minimum alignment of the device in guest
|
|
* physical address space. The final alignment is computed based on this
|
|
* alignment and the alignment requirements of the memory region.
|
|
*
|
|
* Called when plugging the memory device to detect the required alignment
|
|
* during address assignment.
|
|
*/
|
|
uint64_t (*get_min_alignment)(const MemoryDeviceState *md);
|
|
|
|
/*
|
|
* Translate the memory device into #MemoryDeviceInfo.
|
|
*/
|
|
void (*fill_device_info)(const MemoryDeviceState *md,
|
|
MemoryDeviceInfo *info);
|
|
};
|
|
|
|
MemoryDeviceInfoList *qmp_memory_device_list(void);
|
|
uint64_t get_plugged_memory_size(void);
|
|
void memory_device_pre_plug(MemoryDeviceState *md, MachineState *ms,
|
|
const uint64_t *legacy_align, Error **errp);
|
|
void memory_device_plug(MemoryDeviceState *md, MachineState *ms);
|
|
void memory_device_unplug(MemoryDeviceState *md, MachineState *ms);
|
|
uint64_t memory_device_get_region_size(const MemoryDeviceState *md,
|
|
Error **errp);
|
|
|
|
#endif
|