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

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



pc, pci, misc bugfixes

A bunch of bugfixes for 2.2.

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

# gpg: Signature made Mon 24 Nov 2014 18:59:47 GMT 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:
  pc: acpi: mark all possible CPUs as enabled in SRAT
  pcie: fix improper use of negative value
  pcie: fix typo in pcie_cap_deverr_init()
  target-i386: move generic memory hotplug methods to DSDTs
  acpi-build: mark RAM dirty on table update
  hw/pci: fix crash on shpc error flow
  pc: count in 1Gb hugepage alignment when sizing hotplug-memory container
  pc: explicitly check maxmem limit when adding DIMM
  pc: pc-dimm: use backend alignment during address auto allocation
  pc: align DIMM's address/size by backend's alignment value
  memory: expose alignment used for allocating RAM as MemoryRegion API
  pc: limit DIMM address and size to page aligned values
  pc: make pc_dimm_plug() more readble
  pc: kvm: check if KVM has free memory slots to avoid abort()
  qemu-char: fix tcp_get_fds

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 3d4a70f8 dd0247e0
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -909,14 +909,15 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
                             uint16_t section);
static subpage_t *subpage_init(AddressSpace *as, hwaddr base);

static void *(*phys_mem_alloc)(size_t size) = qemu_anon_ram_alloc;
static void *(*phys_mem_alloc)(size_t size, uint64_t *align) =
                               qemu_anon_ram_alloc;

/*
 * Set a custom physical guest memory alloator.
 * Accelerators with unusual needs may need this.  Hopefully, we can
 * get rid of it eventually.
 */
void phys_mem_set_alloc(void *(*alloc)(size_t))
void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align))
{
    phys_mem_alloc = alloc;
}
@@ -1098,6 +1099,7 @@ static void *file_ram_alloc(RAMBlock *block,
        error_propagate(errp, local_err);
        goto error;
    }
    block->mr->align = hpagesize;

    if (memory < hpagesize) {
        error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to "
@@ -1309,7 +1311,8 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp)
        if (xen_enabled()) {
            xen_ram_alloc(new_block->offset, new_block->length, new_block->mr);
        } else {
            new_block->host = phys_mem_alloc(new_block->length);
            new_block->host = phys_mem_alloc(new_block->length,
                                             &new_block->mr->align);
            if (!new_block->host) {
                error_setg_errno(errp, errno,
                                 "cannot set up guest memory '%s'",
+5 −3
Original line number Diff line number Diff line
@@ -811,12 +811,12 @@ err:
    return -1;
}

void *rom_add_blob(const char *name, const void *blob, size_t len,
ram_addr_t rom_add_blob(const char *name, const void *blob, size_t len,
                   hwaddr addr, const char *fw_file_name,
                   FWCfgReadCallback fw_callback, void *callback_opaque)
{
    Rom *rom;
    void *data = NULL;
    ram_addr_t ret = RAM_ADDR_MAX;

    rom           = g_malloc0(sizeof(*rom));
    rom->name     = g_strdup(name);
@@ -828,11 +828,13 @@ void *rom_add_blob(const char *name, const void *blob, size_t len,
    rom_insert(rom);
    if (fw_file_name && fw_cfg) {
        char devpath[100];
        void *data;

        snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);

        if (rom_file_has_mr) {
            data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
            ret = memory_region_get_ram_addr(rom->mr);
        } else {
            data = rom->data;
        }
@@ -841,7 +843,7 @@ void *rom_add_blob(const char *name, const void *blob, size_t len,
                                 fw_callback, callback_opaque,
                                 data, rom->romsize);
    }
    return data;
    return ret;
}

/* This function is specific for elf program because we don't need to allocate
+11 −11
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@

#include "qapi/qmp/qint.h"
#include "qom/qom-qobject.h"
#include "exec/ram_addr.h"

/* These are used to size the ACPI tables for -M pc-i440fx-1.7 and
 * -M pc-i440fx-2.0.  Even if the actual amount of AML generated grows
@@ -1269,8 +1270,7 @@ acpi_build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
}

static void
build_srat(GArray *table_data, GArray *linker,
           AcpiCpuInfo *cpu, PcGuestInfo *guest_info)
build_srat(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
{
    AcpiSystemResourceAffinityTable *srat;
    AcpiSratProcessorAffinity *core;
@@ -1300,11 +1300,7 @@ build_srat(GArray *table_data, GArray *linker,
        core->proximity_lo = curnode;
        memset(core->proximity_hi, 0, 3);
        core->local_sapic_eid = 0;
        if (test_bit(i, cpu->found_cpus)) {
        core->flags = cpu_to_le32(1);
        } else {
            core->flags = cpu_to_le32(0);
        }
    }


@@ -1511,7 +1507,7 @@ static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
typedef
struct AcpiBuildState {
    /* Copy of table in RAM (for patching). */
    uint8_t *table_ram;
    ram_addr_t table_ram;
    uint32_t table_size;
    /* Is table patched? */
    uint8_t patched;
@@ -1622,7 +1618,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
    }
    if (guest_info->numa_nodes) {
        acpi_add_table(table_offsets, tables->table_data);
        build_srat(tables->table_data, tables->linker, &cpu, guest_info);
        build_srat(tables->table_data, tables->linker, guest_info);
    }
    if (acpi_get_mcfg(&mcfg)) {
        acpi_add_table(table_offsets, tables->table_data);
@@ -1716,7 +1712,10 @@ static void acpi_build_update(void *build_opaque, uint32_t offset)
    acpi_build(build_state->guest_info, &tables);

    assert(acpi_data_len(tables.table_data) == build_state->table_size);
    memcpy(build_state->table_ram, tables.table_data->data,
    memcpy(qemu_get_ram_ptr(build_state->table_ram), tables.table_data->data,
           build_state->table_size);

    cpu_physical_memory_set_dirty_range_nocode(build_state->table_ram,
                                               build_state->table_size);

    acpi_build_tables_cleanup(&tables, true);
@@ -1728,7 +1727,7 @@ static void acpi_build_reset(void *build_opaque)
    build_state->patched = 0;
}

static void *acpi_add_rom_blob(AcpiBuildState *build_state, GArray *blob,
static ram_addr_t acpi_add_rom_blob(AcpiBuildState *build_state, GArray *blob,
                               const char *name)
{
    return rom_add_blob(name, blob->data, acpi_data_len(blob), -1, name,
@@ -1777,6 +1776,7 @@ void acpi_setup(PcGuestInfo *guest_info)
    /* Now expose it all to Guest */
    build_state->table_ram = acpi_add_rom_blob(build_state, tables.table_data,
                                               ACPI_BUILD_TABLE_FILE);
    assert(build_state->table_ram != RAM_ADDR_MAX);
    build_state->table_size = acpi_data_len(tables.table_data);

    acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader");
+176 −0
Original line number Diff line number Diff line
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License along
 * with this program; if not, see <http://www.gnu.org/licenses/>.
 */

    External(MEMORY_SLOT_NOTIFY_METHOD, MethodObj)

    Scope(\_SB.PCI0) {
        Device(MEMORY_HOTPLUG_DEVICE) {
            Name(_HID, "PNP0A06")
            Name(_UID, "Memory hotplug resources")
            External(MEMORY_SLOTS_NUMBER, IntObj)

            /* Memory hotplug IO registers */
            OperationRegion(MEMORY_HOTPLUG_IO_REGION, SystemIO,
                            ACPI_MEMORY_HOTPLUG_BASE,
                            ACPI_MEMORY_HOTPLUG_IO_LEN)

            Name(_CRS, ResourceTemplate() {
                IO(Decode16, ACPI_MEMORY_HOTPLUG_BASE, ACPI_MEMORY_HOTPLUG_BASE,
                   0, ACPI_MEMORY_HOTPLUG_IO_LEN, IO)
            })

            Method(_STA, 0) {
                If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
                    Return(0x0)
                }
                /* present, functioning, decoding, not shown in UI */
                Return(0xB)
            }

            Field(MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) {
                MEMORY_SLOT_ADDR_LOW, 32,  // read only
                MEMORY_SLOT_ADDR_HIGH, 32, // read only
                MEMORY_SLOT_SIZE_LOW, 32,  // read only
                MEMORY_SLOT_SIZE_HIGH, 32, // read only
                MEMORY_SLOT_PROXIMITY, 32, // read only
            }
            Field(MEMORY_HOTPLUG_IO_REGION, ByteAcc, NoLock, Preserve) {
                Offset(20),
                MEMORY_SLOT_ENABLED,  1, // 1 if enabled, read only
                MEMORY_SLOT_INSERT_EVENT, 1, // (read) 1 if has a insert event. (write) 1 to clear event
            }

            Mutex (MEMORY_SLOT_LOCK, 0)
            Field (MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) {
                MEMORY_SLOT_SLECTOR, 32,  // DIMM selector, write only
                MEMORY_SLOT_OST_EVENT, 32,  // _OST event code, write only
                MEMORY_SLOT_OST_STATUS, 32,  // _OST status code, write only
            }

            Method(MEMORY_SLOT_SCAN_METHOD, 0) {
                If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
                     Return(Zero)
                }

                Store(Zero, Local0) // Mem devs iterrator
                Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
                while (LLess(Local0, MEMORY_SLOTS_NUMBER)) {
                    Store(Local0, MEMORY_SLOT_SLECTOR) // select Local0 DIMM
                    If (LEqual(MEMORY_SLOT_INSERT_EVENT, One)) { // Memory device needs check
                        MEMORY_SLOT_NOTIFY_METHOD(Local0, 1)
                        Store(1, MEMORY_SLOT_INSERT_EVENT)
                    }
                    // TODO: handle memory eject request
                    Add(Local0, One, Local0) // goto next DIMM
                }
                Release(MEMORY_SLOT_LOCK)
                Return(One)
            }

            Method(MEMORY_SLOT_STATUS_METHOD, 1) {
                Store(Zero, Local0)

                Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
                Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM

                If (LEqual(MEMORY_SLOT_ENABLED, One)) {
                    Store(0xF, Local0)
                }

                Release(MEMORY_SLOT_LOCK)
                Return(Local0)
            }

            Method(MEMORY_SLOT_CRS_METHOD, 1, Serialized) {
                Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
                Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM

                Name(MR64, ResourceTemplate() {
                    QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
                    Cacheable, ReadWrite,
                    0x0000000000000000,        // Address Space Granularity
                    0x0000000000000000,        // Address Range Minimum
                    0xFFFFFFFFFFFFFFFE,        // Address Range Maximum
                    0x0000000000000000,        // Address Translation Offset
                    0xFFFFFFFFFFFFFFFF,        // Address Length
                    ,, MW64, AddressRangeMemory, TypeStatic)
                })

                CreateDWordField(MR64, 14, MINL)
                CreateDWordField(MR64, 18, MINH)
                CreateDWordField(MR64, 38, LENL)
                CreateDWordField(MR64, 42, LENH)
                CreateDWordField(MR64, 22, MAXL)
                CreateDWordField(MR64, 26, MAXH)

                Store(MEMORY_SLOT_ADDR_HIGH, MINH)
                Store(MEMORY_SLOT_ADDR_LOW, MINL)
                Store(MEMORY_SLOT_SIZE_HIGH, LENH)
                Store(MEMORY_SLOT_SIZE_LOW, LENL)

                // 64-bit math: MAX = MIN + LEN - 1
                Add(MINL, LENL, MAXL)
                Add(MINH, LENH, MAXH)
                If (LLess(MAXL, MINL)) {
                    Add(MAXH, One, MAXH)
                }
                If (LLess(MAXL, One)) {
                    Subtract(MAXH, One, MAXH)
                }
                Subtract(MAXL, One, MAXL)

                If (LEqual(MAXH, Zero)){
                    Name(MR32, ResourceTemplate() {
                        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
                        Cacheable, ReadWrite,
                        0x00000000,        // Address Space Granularity
                        0x00000000,        // Address Range Minimum
                        0xFFFFFFFE,        // Address Range Maximum
                        0x00000000,        // Address Translation Offset
                        0xFFFFFFFF,        // Address Length
                        ,, MW32, AddressRangeMemory, TypeStatic)
                    })
                    CreateDWordField(MR32, MW32._MIN, MIN)
                    CreateDWordField(MR32, MW32._MAX, MAX)
                    CreateDWordField(MR32, MW32._LEN, LEN)
                    Store(MINL, MIN)
                    Store(MAXL, MAX)
                    Store(LENL, LEN)

                    Release(MEMORY_SLOT_LOCK)
                    Return(MR32)
                }

                Release(MEMORY_SLOT_LOCK)
                Return(MR64)
            }

            Method(MEMORY_SLOT_PROXIMITY_METHOD, 1) {
                Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
                Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
                Store(MEMORY_SLOT_PROXIMITY, Local0)
                Release(MEMORY_SLOT_LOCK)
                Return(Local0)
            }

            Method(MEMORY_SLOT_OST_METHOD, 4) {
                Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
                Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
                Store(Arg1, MEMORY_SLOT_OST_EVENT)
                Store(Arg2, MEMORY_SLOT_OST_STATUS)
                Release(MEMORY_SLOT_LOCK)
            }
        } // Device()
    } // Scope()
+1 −2
Original line number Diff line number Diff line
@@ -297,13 +297,12 @@ DefinitionBlock (
#include "hw/acpi/pc-hotplug.h"
#define CPU_STATUS_BASE PIIX4_CPU_HOTPLUG_IO_BASE
#include "acpi-dsdt-cpu-hotplug.dsl"
#include "acpi-dsdt-mem-hotplug.dsl"


/****************************************************************
 * General purpose events
 ****************************************************************/
    External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_SCAN_METHOD, MethodObj)

    Scope(\_GPE) {
        Name(_HID, "ACPI0006")

Loading