cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

memory-device.c (10929B)


      1/*
      2 * Memory Device Interface
      3 *
      4 * Copyright ProfitBricks GmbH 2012
      5 * Copyright (C) 2014 Red Hat Inc
      6 * Copyright (c) 2018 Red Hat Inc
      7 *
      8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
      9 * See the COPYING file in the top-level directory.
     10 */
     11
     12#include "qemu/osdep.h"
     13#include "hw/mem/memory-device.h"
     14#include "qapi/error.h"
     15#include "hw/boards.h"
     16#include "qemu/range.h"
     17#include "hw/virtio/vhost.h"
     18#include "sysemu/kvm.h"
     19#include "trace.h"
     20
     21static gint memory_device_addr_sort(gconstpointer a, gconstpointer b)
     22{
     23    const MemoryDeviceState *md_a = MEMORY_DEVICE(a);
     24    const MemoryDeviceState *md_b = MEMORY_DEVICE(b);
     25    const MemoryDeviceClass *mdc_a = MEMORY_DEVICE_GET_CLASS(a);
     26    const MemoryDeviceClass *mdc_b = MEMORY_DEVICE_GET_CLASS(b);
     27    const uint64_t addr_a = mdc_a->get_addr(md_a);
     28    const uint64_t addr_b = mdc_b->get_addr(md_b);
     29
     30    if (addr_a > addr_b) {
     31        return 1;
     32    } else if (addr_a < addr_b) {
     33        return -1;
     34    }
     35    return 0;
     36}
     37
     38static int memory_device_build_list(Object *obj, void *opaque)
     39{
     40    GSList **list = opaque;
     41
     42    if (object_dynamic_cast(obj, TYPE_MEMORY_DEVICE)) {
     43        DeviceState *dev = DEVICE(obj);
     44        if (dev->realized) { /* only realized memory devices matter */
     45            *list = g_slist_insert_sorted(*list, dev, memory_device_addr_sort);
     46        }
     47    }
     48
     49    object_child_foreach(obj, memory_device_build_list, opaque);
     50    return 0;
     51}
     52
     53static int memory_device_used_region_size(Object *obj, void *opaque)
     54{
     55    uint64_t *size = opaque;
     56
     57    if (object_dynamic_cast(obj, TYPE_MEMORY_DEVICE)) {
     58        const DeviceState *dev = DEVICE(obj);
     59        const MemoryDeviceState *md = MEMORY_DEVICE(obj);
     60
     61        if (dev->realized) {
     62            *size += memory_device_get_region_size(md, &error_abort);
     63        }
     64    }
     65
     66    object_child_foreach(obj, memory_device_used_region_size, opaque);
     67    return 0;
     68}
     69
     70static void memory_device_check_addable(MachineState *ms, uint64_t size,
     71                                        Error **errp)
     72{
     73    uint64_t used_region_size = 0;
     74
     75    /* we will need a new memory slot for kvm and vhost */
     76    if (kvm_enabled() && !kvm_has_free_slot(ms)) {
     77        error_setg(errp, "hypervisor has no free memory slots left");
     78        return;
     79    }
     80    if (!vhost_has_free_slot()) {
     81        error_setg(errp, "a used vhost backend has no free memory slots left");
     82        return;
     83    }
     84
     85    /* will we exceed the total amount of memory specified */
     86    memory_device_used_region_size(OBJECT(ms), &used_region_size);
     87    if (used_region_size + size < used_region_size ||
     88        used_region_size + size > ms->maxram_size - ms->ram_size) {
     89        error_setg(errp, "not enough space, currently 0x%" PRIx64
     90                   " in use of total space for memory devices 0x" RAM_ADDR_FMT,
     91                   used_region_size, ms->maxram_size - ms->ram_size);
     92        return;
     93    }
     94
     95}
     96
     97static uint64_t memory_device_get_free_addr(MachineState *ms,
     98                                            const uint64_t *hint,
     99                                            uint64_t align, uint64_t size,
    100                                            Error **errp)
    101{
    102    Error *err = NULL;
    103    GSList *list = NULL, *item;
    104    Range as, new = range_empty;
    105
    106    if (!ms->device_memory) {
    107        error_setg(errp, "memory devices (e.g. for memory hotplug) are not "
    108                         "supported by the machine");
    109        return 0;
    110    }
    111
    112    if (!memory_region_size(&ms->device_memory->mr)) {
    113        error_setg(errp, "memory devices (e.g. for memory hotplug) are not "
    114                         "enabled, please specify the maxmem option");
    115        return 0;
    116    }
    117    range_init_nofail(&as, ms->device_memory->base,
    118                      memory_region_size(&ms->device_memory->mr));
    119
    120    /* start of address space indicates the maximum alignment we expect */
    121    if (!QEMU_IS_ALIGNED(range_lob(&as), align)) {
    122        warn_report("the alignment (0x%" PRIx64 ") exceeds the expected"
    123                    " maximum alignment, memory will get fragmented and not"
    124                    " all 'maxmem' might be usable for memory devices.",
    125                    align);
    126    }
    127
    128    memory_device_check_addable(ms, size, &err);
    129    if (err) {
    130        error_propagate(errp, err);
    131        return 0;
    132    }
    133
    134    if (hint && !QEMU_IS_ALIGNED(*hint, align)) {
    135        error_setg(errp, "address must be aligned to 0x%" PRIx64 " bytes",
    136                   align);
    137        return 0;
    138    }
    139
    140    if (!QEMU_IS_ALIGNED(size, align)) {
    141        error_setg(errp, "backend memory size must be multiple of 0x%"
    142                   PRIx64, align);
    143        return 0;
    144    }
    145
    146    if (hint) {
    147        if (range_init(&new, *hint, size) || !range_contains_range(&as, &new)) {
    148            error_setg(errp, "can't add memory device [0x%" PRIx64 ":0x%" PRIx64
    149                       "], usable range for memory devices [0x%" PRIx64 ":0x%"
    150                       PRIx64 "]", *hint, size, range_lob(&as),
    151                       range_size(&as));
    152            return 0;
    153        }
    154    } else {
    155        if (range_init(&new, QEMU_ALIGN_UP(range_lob(&as), align), size)) {
    156            error_setg(errp, "can't add memory device, device too big");
    157            return 0;
    158        }
    159    }
    160
    161    /* find address range that will fit new memory device */
    162    object_child_foreach(OBJECT(ms), memory_device_build_list, &list);
    163    for (item = list; item; item = g_slist_next(item)) {
    164        const MemoryDeviceState *md = item->data;
    165        const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(OBJECT(md));
    166        uint64_t next_addr;
    167        Range tmp;
    168
    169        range_init_nofail(&tmp, mdc->get_addr(md),
    170                          memory_device_get_region_size(md, &error_abort));
    171
    172        if (range_overlaps_range(&tmp, &new)) {
    173            if (hint) {
    174                const DeviceState *d = DEVICE(md);
    175                error_setg(errp, "address range conflicts with memory device"
    176                           " id='%s'", d->id ? d->id : "(unnamed)");
    177                goto out;
    178            }
    179
    180            next_addr = QEMU_ALIGN_UP(range_upb(&tmp) + 1, align);
    181            if (!next_addr || range_init(&new, next_addr, range_size(&new))) {
    182                range_make_empty(&new);
    183                break;
    184            }
    185        } else if (range_lob(&tmp) > range_upb(&new)) {
    186            break;
    187        }
    188    }
    189
    190    if (!range_contains_range(&as, &new)) {
    191        error_setg(errp, "could not find position in guest address space for "
    192                   "memory device - memory fragmented due to alignments");
    193    }
    194out:
    195    g_slist_free(list);
    196    return range_lob(&new);
    197}
    198
    199MemoryDeviceInfoList *qmp_memory_device_list(void)
    200{
    201    GSList *devices = NULL, *item;
    202    MemoryDeviceInfoList *list = NULL, **tail = &list;
    203
    204    object_child_foreach(qdev_get_machine(), memory_device_build_list,
    205                         &devices);
    206
    207    for (item = devices; item; item = g_slist_next(item)) {
    208        const MemoryDeviceState *md = MEMORY_DEVICE(item->data);
    209        const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(item->data);
    210        MemoryDeviceInfo *info = g_new0(MemoryDeviceInfo, 1);
    211
    212        mdc->fill_device_info(md, info);
    213
    214        QAPI_LIST_APPEND(tail, info);
    215    }
    216
    217    g_slist_free(devices);
    218
    219    return list;
    220}
    221
    222static int memory_device_plugged_size(Object *obj, void *opaque)
    223{
    224    uint64_t *size = opaque;
    225
    226    if (object_dynamic_cast(obj, TYPE_MEMORY_DEVICE)) {
    227        const DeviceState *dev = DEVICE(obj);
    228        const MemoryDeviceState *md = MEMORY_DEVICE(obj);
    229        const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(obj);
    230
    231        if (dev->realized) {
    232            *size += mdc->get_plugged_size(md, &error_abort);
    233        }
    234    }
    235
    236    object_child_foreach(obj, memory_device_plugged_size, opaque);
    237    return 0;
    238}
    239
    240uint64_t get_plugged_memory_size(void)
    241{
    242    uint64_t size = 0;
    243
    244    memory_device_plugged_size(qdev_get_machine(), &size);
    245
    246    return size;
    247}
    248
    249void memory_device_pre_plug(MemoryDeviceState *md, MachineState *ms,
    250                            const uint64_t *legacy_align, Error **errp)
    251{
    252    const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(md);
    253    Error *local_err = NULL;
    254    uint64_t addr, align = 0;
    255    MemoryRegion *mr;
    256
    257    mr = mdc->get_memory_region(md, &local_err);
    258    if (local_err) {
    259        goto out;
    260    }
    261
    262    if (legacy_align) {
    263        align = *legacy_align;
    264    } else {
    265        if (mdc->get_min_alignment) {
    266            align = mdc->get_min_alignment(md);
    267        }
    268        align = MAX(align, memory_region_get_alignment(mr));
    269    }
    270    addr = mdc->get_addr(md);
    271    addr = memory_device_get_free_addr(ms, !addr ? NULL : &addr, align,
    272                                       memory_region_size(mr), &local_err);
    273    if (local_err) {
    274        goto out;
    275    }
    276    mdc->set_addr(md, addr, &local_err);
    277    if (!local_err) {
    278        trace_memory_device_pre_plug(DEVICE(md)->id ? DEVICE(md)->id : "",
    279                                     addr);
    280    }
    281out:
    282    error_propagate(errp, local_err);
    283}
    284
    285void memory_device_plug(MemoryDeviceState *md, MachineState *ms)
    286{
    287    const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(md);
    288    const uint64_t addr = mdc->get_addr(md);
    289    MemoryRegion *mr;
    290
    291    /*
    292     * We expect that a previous call to memory_device_pre_plug() succeeded, so
    293     * it can't fail at this point.
    294     */
    295    mr = mdc->get_memory_region(md, &error_abort);
    296    g_assert(ms->device_memory);
    297
    298    memory_region_add_subregion(&ms->device_memory->mr,
    299                                addr - ms->device_memory->base, mr);
    300    trace_memory_device_plug(DEVICE(md)->id ? DEVICE(md)->id : "", addr);
    301}
    302
    303void memory_device_unplug(MemoryDeviceState *md, MachineState *ms)
    304{
    305    const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(md);
    306    MemoryRegion *mr;
    307
    308    /*
    309     * We expect that a previous call to memory_device_pre_plug() succeeded, so
    310     * it can't fail at this point.
    311     */
    312    mr = mdc->get_memory_region(md, &error_abort);
    313    g_assert(ms->device_memory);
    314
    315    memory_region_del_subregion(&ms->device_memory->mr, mr);
    316    trace_memory_device_unplug(DEVICE(md)->id ? DEVICE(md)->id : "",
    317                               mdc->get_addr(md));
    318}
    319
    320uint64_t memory_device_get_region_size(const MemoryDeviceState *md,
    321                                       Error **errp)
    322{
    323    const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(md);
    324    MemoryRegion *mr;
    325
    326    /* dropping const here is fine as we don't touch the memory region */
    327    mr = mdc->get_memory_region((MemoryDeviceState *)md, errp);
    328    if (!mr) {
    329        return 0;
    330    }
    331
    332    return memory_region_size(mr);
    333}
    334
    335static const TypeInfo memory_device_info = {
    336    .name          = TYPE_MEMORY_DEVICE,
    337    .parent        = TYPE_INTERFACE,
    338    .class_size = sizeof(MemoryDeviceClass),
    339};
    340
    341static void memory_device_register_types(void)
    342{
    343    type_register_static(&memory_device_info);
    344}
    345
    346type_init(memory_device_register_types)