Commit c0b520df authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging



virtio,pc features, fixes

New features:
    guest RAM buffer overrun mitigation
    RAM physical address gaps for memory hotplug
    (except refactoring which got some review comments)

Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Fri 02 Oct 2015 15:04:56 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream:
  vhost-user-test: fix predictable filename on tmpfs
  vhost-user-test: use tmpfs by default
  pc: memhp: force gaps between DIMM's GPA
  memhp: extend address auto assignment to support gaps
  vhost-user: unit test for new messages
  vhost-user-test: do not reinvent glib-compat.h
  virtio: Notice when the system doesn't support MSIx at all
  pc: Add a comment explaining why pc_compat_2_4() doesn't exist
  exec: allocate PROT_NONE pages on top of RAM
  oslib: allocate PROT_NONE pages on top of RAM
  oslib: rework anonimous RAM allocation
  virtio-net: correctly drop truncated packets
  virtio: introduce virtqueue_discard()
  virtio: introduce virtqueue_unmap_sg()

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 945507d6 6fdac093
Loading
Loading
Loading
Loading
+39 −3
Original line number Diff line number Diff line
@@ -84,6 +84,9 @@ static MemoryRegion io_mem_unassigned;
 */
#define RAM_RESIZEABLE (1 << 2)

/* An extra page is mapped on top of this RAM.
 */
#define RAM_EXTRA (1 << 3)
#endif

struct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus);
@@ -1185,10 +1188,13 @@ static void *file_ram_alloc(RAMBlock *block,
    char *filename;
    char *sanitized_name;
    char *c;
    void *ptr;
    void *area = NULL;
    int fd;
    uint64_t hpagesize;
    uint64_t total;
    Error *local_err = NULL;
    size_t offset;

    hpagesize = gethugepagesize(path, &local_err);
    if (local_err) {
@@ -1232,6 +1238,7 @@ static void *file_ram_alloc(RAMBlock *block,
    g_free(filename);

    memory = ROUND_UP(memory, hpagesize);
    total = memory + hpagesize;

    /*
     * ftruncate is not supported by hugetlbfs in older
@@ -1243,16 +1250,40 @@ static void *file_ram_alloc(RAMBlock *block,
        perror("ftruncate");
    }

    area = mmap(0, memory, PROT_READ | PROT_WRITE,
                (block->flags & RAM_SHARED ? MAP_SHARED : MAP_PRIVATE),
    ptr = mmap(0, total, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
                -1, 0);
    if (ptr == MAP_FAILED) {
        error_setg_errno(errp, errno,
                         "unable to allocate memory range for hugepages");
        close(fd);
        goto error;
    }

    offset = QEMU_ALIGN_UP((uintptr_t)ptr, hpagesize) - (uintptr_t)ptr;

    area = mmap(ptr + offset, memory, PROT_READ | PROT_WRITE,
                (block->flags & RAM_SHARED ? MAP_SHARED : MAP_PRIVATE) |
                MAP_FIXED,
                fd, 0);
    if (area == MAP_FAILED) {
        error_setg_errno(errp, errno,
                         "unable to map backing store for hugepages");
        munmap(ptr, total);
        close(fd);
        goto error;
    }

    if (offset > 0) {
        munmap(ptr, offset);
    }
    ptr += offset;
    total -= offset;

    if (total > memory + getpagesize()) {
        munmap(ptr + memory + getpagesize(),
               total - memory - getpagesize());
    }

    if (mem_prealloc) {
        os_mem_prealloc(fd, area, memory);
    }
@@ -1570,6 +1601,7 @@ ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
    new_block->used_length = size;
    new_block->max_length = size;
    new_block->flags = share ? RAM_SHARED : 0;
    new_block->flags |= RAM_EXTRA;
    new_block->host = file_ram_alloc(new_block, size,
                                     mem_path, errp);
    if (!new_block->host) {
@@ -1671,7 +1703,11 @@ static void reclaim_ramblock(RAMBlock *block)
        xen_invalidate_map_cache_entry(block->host);
#ifndef _WIN32
    } else if (block->fd >= 0) {
        if (block->flags & RAM_EXTRA) {
            munmap(block->host, block->max_length + getpagesize());
        } else {
            munmap(block->host, block->max_length);
        }
        close(block->fd);
#endif
    } else {
+4 −1
Original line number Diff line number Diff line
@@ -1629,6 +1629,7 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
    HotplugHandlerClass *hhc;
    Error *local_err = NULL;
    PCMachineState *pcms = PC_MACHINE(hotplug_dev);
    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
    PCDIMMDevice *dimm = PC_DIMM(dev);
    PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
    MemoryRegion *mr = ddc->get_memory_region(dimm);
@@ -1644,7 +1645,8 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
        goto out;
    }

    pc_dimm_memory_plug(dev, &pcms->hotplug_memory, mr, align, &local_err);
    pc_dimm_memory_plug(dev, &pcms->hotplug_memory, mr, align,
                        pcmc->inter_dimm_gap, &local_err);
    if (local_err) {
        goto out;
    }
@@ -1945,6 +1947,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
    PCMachineClass *pcmc = PC_MACHINE_CLASS(oc);
    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);

    pcmc->inter_dimm_gap = true;
    pcmc->get_hotplug_handler = mc->get_hotplug_handler;
    mc->get_hotplug_handler = pc_get_hotpug_handler;
    mc->cpu_index_to_socket_id = pc_cpu_index_to_socket_id;
+8 −0
Original line number Diff line number Diff line
@@ -301,6 +301,13 @@ static void pc_init1(MachineState *machine,
    }
}

/* Looking for a pc_compat_2_4() function? It doesn't exist.
 * pc_compat_*() functions that run on machine-init time and
 * change global QEMU state are deprecated. Please don't create
 * one, and implement any pc-*-2.4 (and newer) compat code in
 * HW_COMPAT_*, PC_COMPAT_*, or * pc_*_machine_options().
 */

static void pc_compat_2_3(MachineState *machine)
{
    PCMachineState *pcms = PC_MACHINE(machine);
@@ -482,6 +489,7 @@ static void pc_i440fx_2_4_machine_options(MachineClass *m)
    m->alias = NULL;
    m->is_default = 0;
    pcmc->broken_reserved_end = true;
    pcmc->inter_dimm_gap = false;
    SET_MACHINE_COMPAT(m, PC_COMPAT_2_4);
}

+8 −0
Original line number Diff line number Diff line
@@ -284,6 +284,13 @@ static void pc_q35_init(MachineState *machine)
    }
}

/* Looking for a pc_compat_2_4() function? It doesn't exist.
 * pc_compat_*() functions that run on machine-init time and
 * change global QEMU state are deprecated. Please don't create
 * one, and implement any pc-*-2.4 (and newer) compat code in
 * HW_COMPAT_*, PC_COMPAT_*, or * pc_*_machine_options().
 */

static void pc_compat_2_3(MachineState *machine)
{
    PCMachineState *pcms = PC_MACHINE(machine);
@@ -385,6 +392,7 @@ static void pc_q35_2_4_machine_options(MachineClass *m)
    pc_q35_2_5_machine_options(m);
    m->alias = NULL;
    pcmc->broken_reserved_end = true;
    pcmc->inter_dimm_gap = false;
    SET_MACHINE_COMPAT(m, PC_COMPAT_2_4);
}

+9 −6
Original line number Diff line number Diff line
@@ -32,7 +32,8 @@ typedef struct pc_dimms_capacity {
} pc_dimms_capacity;

void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
                         MemoryRegion *mr, uint64_t align, Error **errp)
                         MemoryRegion *mr, uint64_t align, bool gap,
                         Error **errp)
{
    int slot;
    MachineState *machine = MACHINE(qdev_get_machine());
@@ -48,7 +49,7 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,

    addr = pc_dimm_get_free_addr(hpms->base,
                                 memory_region_size(&hpms->mr),
                                 !addr ? NULL : &addr, align,
                                 !addr ? NULL : &addr, align, gap,
                                 memory_region_size(mr), &local_err);
    if (local_err) {
        goto out;
@@ -287,8 +288,8 @@ static int pc_dimm_built_list(Object *obj, void *opaque)

uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
                               uint64_t address_space_size,
                               uint64_t *hint, uint64_t align, uint64_t size,
                               Error **errp)
                               uint64_t *hint, uint64_t align, bool gap,
                               uint64_t size, Error **errp)
{
    GSList *list = NULL, *item;
    uint64_t new_addr, ret = 0;
@@ -333,13 +334,15 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
            goto out;
        }

        if (ranges_overlap(dimm->addr, dimm_size, new_addr, size)) {
        if (ranges_overlap(dimm->addr, dimm_size, new_addr,
                           size + (gap ? 1 : 0))) {
            if (hint) {
                DeviceState *d = DEVICE(dimm);
                error_setg(errp, "address range conflicts with '%s'", d->id);
                goto out;
            }
            new_addr = QEMU_ALIGN_UP(dimm->addr + dimm_size, align);
            new_addr = QEMU_ALIGN_UP(dimm->addr + dimm_size + (gap ? 1 : 0),
                                     align);
        }
    }
    ret = new_addr;
Loading