Commit 28f5e970 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20170120' into staging



target-arm queue:
 * support virtualization in GICv3
 * enable EL2 in AArch64 CPU models
 * allow EL2 to be enabled on 'virt' board via -machine virtualization=on
 * aspeed: SMC improvements
 * m25p80: support die erase command
 * m25p80: Add Quad Page Program 4byte
 * m25p80: Improve 1GiB Micron flash definition
 * arm: Uniquely name imx25 I2C buses

# gpg: Signature made Fri 20 Jan 2017 11:31:53 GMT
# gpg:                using RSA key 0x3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20170120: (36 commits)
  hw/arm/virt: Add board property to enable EL2
  target-arm: Enable EL2 feature bit on A53 and A57
  target/arm/psci.c: If EL2 implemented, start CPUs in EL2
  hw/arm/virt-acpi-build: use SMC if booting in EL2
  hw/arm/virt: Support using SMC for PSCI
  hw/intc/arm_gicv3: Implement EL2 traps for CPU i/f regs
  hw/intc/arm_gicv3: Implement gicv3_cpuif_virt_update()
  hw/intc/arm_gicv3: Implement ICV_ registers EOIR and IAR
  hw/intc/arm_gicv3: Implement ICV_ HPPIR, DIR and RPR registers
  hw/intc/arm_gicv3: Implement ICV_ registers which are just accessors
  hw/intc/arm_gicv3: Add accessors for ICH_ system registers
  hw/intc/gicv3: Add data fields for virtualization support
  hw/intc/gicv3: Add defines for ICH system register fields
  target-arm: Add ARMCPU fields for GIC CPU i/f config
  hw/arm/virt: Wire VIRQ, VFIQ, maintenance irq lines from GIC to CPU
  target-arm: Expose output GPIO line for VCPU maintenance interrupt
  hw/intc/arm_gic: Add external IRQ lines for VIRQ and VFIQ
  hw/intc/arm_gicv3: Add external IRQ lines for VIRQ and VFIQ
  hw/arm/virt-acpi - reserve ECAM space as PNP0C02 device
  arm: virt: Fix segmentation fault when specifying an unsupported CPU
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 0f6bcf68 f29cacfb
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@
#include "qemu/log.h"
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
#include "hw/loader.h"
#include "qemu/error-report.h"

static struct arm_boot_info aspeed_board_binfo = {
    .board_id = -1, /* device-tree-only board */
@@ -104,6 +106,28 @@ static const AspeedBoardConfig aspeed_boards[] = {
    },
};

#define FIRMWARE_ADDR 0x0

static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
                           Error **errp)
{
    BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
    uint8_t *storage;

    if (rom_size > blk_getlength(blk)) {
        rom_size = blk_getlength(blk);
    }

    storage = g_new0(uint8_t, rom_size);
    if (blk_pread(blk, 0, storage, rom_size) < 0) {
        error_setg(errp, "failed to read the initial flash content");
        return;
    }

    rom_add_blob_fixed("aspeed.boot_rom", storage, rom_size, addr);
    g_free(storage);
}

static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
                                      Error **errp)
{
@@ -135,6 +159,7 @@ static void aspeed_board_init(MachineState *machine,
{
    AspeedBoardState *bmc;
    AspeedSoCClass *sc;
    DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);

    bmc = g_new0(AspeedBoardState, 1);
    object_initialize(&bmc->soc, (sizeof(bmc->soc)), cfg->soc_name);
@@ -168,6 +193,22 @@ static void aspeed_board_init(MachineState *machine,
    aspeed_board_init_flashes(&bmc->soc.fmc, cfg->fmc_model, &error_abort);
    aspeed_board_init_flashes(&bmc->soc.spi[0], cfg->spi_model, &error_abort);

    /* Install first FMC flash content as a boot rom. */
    if (drive0) {
        AspeedSMCFlash *fl = &bmc->soc.fmc.flashes[0];
        MemoryRegion *boot_rom = g_new(MemoryRegion, 1);

        /*
         * create a ROM region using the default mapping window size of
         * the flash module.
         */
        memory_region_init_rom(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
                               fl->size, &error_abort);
        memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
                                    boot_rom);
        write_boot_rom(drive0, FIRMWARE_ADDR, fl->size, &error_abort);
    }

    aspeed_board_binfo.kernel_filename = machine->kernel_filename;
    aspeed_board_binfo.initrd_filename = machine->initrd_filename;
    aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline;
+1 −1
Original line number Diff line number Diff line
@@ -139,7 +139,7 @@ static void imx25_pdk_init(MachineState *machine)
         * of simple qtest. See "make check" for details.
         */
        i2c_create_slave((I2CBus *)qdev_get_child_bus(DEVICE(&s->soc.i2c[0]),
                                                      "i2c"),
                                                      "i2c-bus.0"),
                         "ds1338", 0x68);
    }
}
+30 −6
Original line number Diff line number Diff line
@@ -310,6 +310,13 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
    Aml *dev_rp0 = aml_device("%s", "RP0");
    aml_append(dev_rp0, aml_name_decl("_ADR", aml_int(0)));
    aml_append(dev, dev_rp0);

    Aml *dev_res0 = aml_device("%s", "RES0");
    aml_append(dev_res0, aml_name_decl("_HID", aml_string("PNP0C02")));
    crs = aml_resource_template();
    aml_append(crs, aml_memory32_fixed(base_ecam, size_ecam, AML_READ_WRITE));
    aml_append(dev_res0, aml_name_decl("_CRS", crs));
    aml_append(dev, dev_res0);
    aml_append(scope, dev);
}

@@ -607,6 +614,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
        if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
            gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ));
        }
        if (vms->virt && vms->gic_version == 3) {
            gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GICV3_MAINT_IRQ));
        }
    }

    if (vms->gic_version == 3) {
@@ -643,16 +653,30 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
}

/* FADT */
static void
build_fadt(GArray *table_data, BIOSLinker *linker, unsigned dsdt_tbl_offset)
static void build_fadt(GArray *table_data, BIOSLinker *linker,
                       VirtMachineState *vms, unsigned dsdt_tbl_offset)
{
    AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
    unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data;

    /* Hardware Reduced = 1 and use PSCI 0.2+ and with HVC */
    uint16_t bootflags;

    switch (vms->psci_conduit) {
    case QEMU_PSCI_CONDUIT_DISABLED:
        bootflags = 0;
        break;
    case QEMU_PSCI_CONDUIT_HVC:
        bootflags = ACPI_FADT_ARM_PSCI_COMPLIANT | ACPI_FADT_ARM_PSCI_USE_HVC;
        break;
    case QEMU_PSCI_CONDUIT_SMC:
        bootflags = ACPI_FADT_ARM_PSCI_COMPLIANT;
        break;
    default:
        g_assert_not_reached();
    }

    /* Hardware Reduced = 1 and use PSCI 0.2+ */
    fadt->flags = cpu_to_le32(1 << ACPI_FADT_F_HW_REDUCED_ACPI);
    fadt->arm_boot_flags = cpu_to_le16(ACPI_FADT_ARM_PSCI_COMPLIANT |
                                       ACPI_FADT_ARM_PSCI_USE_HVC);
    fadt->arm_boot_flags = cpu_to_le16(bootflags);

    /* ACPI v5.1 (fadt->revision.fadt->minor_revision) */
    fadt->minor_revision = 0x1;
@@ -738,7 +762,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)

    /* FADT MADT GTDT MCFG SPCR pointed to by RSDT */
    acpi_add_table(table_offsets, tables_blob);
    build_fadt(tables_blob, tables->linker, dsdt);
    build_fadt(tables_blob, tables->linker, vms, dsdt);

    acpi_add_table(table_offsets, tables_blob);
    build_madt(tables_blob, tables->linker, vms);
+77 −11
Original line number Diff line number Diff line
@@ -167,7 +167,6 @@ static const char *valid_cpus[] = {
    "cortex-a53",
    "cortex-a57",
    "host",
    NULL
};

static bool cpuname_valid(const char *cpu)
@@ -230,9 +229,19 @@ static void fdt_add_psci_node(const VirtMachineState *vms)
    uint32_t migrate_fn;
    void *fdt = vms->fdt;
    ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
    const char *psci_method;

    if (!vms->using_psci) {
    switch (vms->psci_conduit) {
    case QEMU_PSCI_CONDUIT_DISABLED:
        return;
    case QEMU_PSCI_CONDUIT_HVC:
        psci_method = "hvc";
        break;
    case QEMU_PSCI_CONDUIT_SMC:
        psci_method = "smc";
        break;
    default:
        g_assert_not_reached();
    }

    qemu_fdt_add_subnode(fdt, "/psci");
@@ -264,7 +273,7 @@ static void fdt_add_psci_node(const VirtMachineState *vms)
     * However, the device tree binding uses 'method' instead, so that is
     * what we should use here.
     */
    qemu_fdt_setprop_string(fdt, "/psci", "method", "hvc");
    qemu_fdt_setprop_string(fdt, "/psci", "method", psci_method);

    qemu_fdt_setprop_cell(fdt, "/psci", "cpu_suspend", cpu_suspend_fn);
    qemu_fdt_setprop_cell(fdt, "/psci", "cpu_off", cpu_off_fn);
@@ -366,7 +375,8 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
        qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
                                    armcpu->dtb_compatible);

        if (vms->using_psci && vms->smp_cpus > 1) {
        if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED
            && vms->smp_cpus > 1) {
            qemu_fdt_setprop_string(vms->fdt, nodename,
                                        "enable-method", "psci");
        }
@@ -433,6 +443,11 @@ static void fdt_add_gic_node(VirtMachineState *vms)
                                     2, vms->memmap[VIRT_GIC_DIST].size,
                                     2, vms->memmap[VIRT_GIC_REDIST].base,
                                     2, vms->memmap[VIRT_GIC_REDIST].size);
        if (vms->virt) {
            qemu_fdt_setprop_cells(vms->fdt, "/intc", "interrupts",
                                   GIC_FDT_IRQ_TYPE_PPI, ARCH_GICV3_MAINT_IRQ,
                                   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
        }
    } else {
        /* 'cortex-a15-gic' means 'GIC v2' */
        qemu_fdt_setprop_string(vms->fdt, "/intc", "compatible",
@@ -547,9 +562,9 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
        sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
    }

    /* Wire the outputs from each CPU's generic timer to the
     * appropriate GIC PPI inputs, and the GIC's IRQ output to
     * the CPU's IRQ input.
    /* Wire the outputs from each CPU's generic timer and the GICv3
     * maintenance interrupt signal to the appropriate GIC PPI inputs,
     * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
     */
    for (i = 0; i < smp_cpus; i++) {
        DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
@@ -571,9 +586,17 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
                                                   ppibase + timer_irq[irq]));
        }

        qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0,
                                    qdev_get_gpio_in(gicdev, ppibase
                                                     + ARCH_GICV3_MAINT_IRQ));

        sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
        sysbus_connect_irq(gicbusdev, i + smp_cpus,
                           qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
        sysbus_connect_irq(gicbusdev, i + 2 * smp_cpus,
                           qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
        sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
                           qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
    }

    for (i = 0; i < NUM_IRQS; i++) {
@@ -1221,9 +1244,18 @@ static void machvirt_init(MachineState *machine)
     * so it doesn't get in the way. Instead of starting secondary
     * CPUs in PSCI powerdown state we will start them all running and
     * let the boot ROM sort them out.
     * The usual case is that we do use QEMU's PSCI implementation.
     * The usual case is that we do use QEMU's PSCI implementation;
     * if the guest has EL2 then we will use SMC as the conduit,
     * and otherwise we will use HVC (for backwards compatibility and
     * because if we're using KVM then we must use HVC).
     */
    vms->using_psci = !(vms->secure && firmware_loaded);
    if (vms->secure && firmware_loaded) {
        vms->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
    } else if (vms->virt) {
        vms->psci_conduit = QEMU_PSCI_CONDUIT_SMC;
    } else {
        vms->psci_conduit = QEMU_PSCI_CONDUIT_HVC;
    }

    /* The maximum number of CPUs depends on the GIC version, or on how
     * many redistributors we can fit into the memory map.
@@ -1250,6 +1282,12 @@ static void machvirt_init(MachineState *machine)
        exit(1);
    }

    if (vms->virt && kvm_enabled()) {
        error_report("mach-virt: KVM does not support providing "
                     "Virtualization extensions to the guest CPU");
        exit(1);
    }

    if (vms->secure) {
        if (kvm_enabled()) {
            error_report("mach-virt: KVM does not support Security extensions");
@@ -1306,8 +1344,12 @@ static void machvirt_init(MachineState *machine)
            object_property_set_bool(cpuobj, false, "has_el3", NULL);
        }

        if (vms->using_psci) {
            object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_HVC,
        if (!vms->virt && object_property_find(cpuobj, "has_el2", NULL)) {
            object_property_set_bool(cpuobj, false, "has_el2", NULL);
        }

        if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
            object_property_set_int(cpuobj, vms->psci_conduit,
                                    "psci-conduit", NULL);

            /* Secondary CPUs start in PSCI powered-down state */
@@ -1408,6 +1450,20 @@ static void virt_set_secure(Object *obj, bool value, Error **errp)
    vms->secure = value;
}

static bool virt_get_virt(Object *obj, Error **errp)
{
    VirtMachineState *vms = VIRT_MACHINE(obj);

    return vms->virt;
}

static void virt_set_virt(Object *obj, bool value, Error **errp)
{
    VirtMachineState *vms = VIRT_MACHINE(obj);

    vms->virt = value;
}

static bool virt_get_highmem(Object *obj, Error **errp)
{
    VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -1495,6 +1551,16 @@ static void virt_2_9_instance_init(Object *obj)
                                    "Security Extensions (TrustZone)",
                                    NULL);

    /* EL2 is also disabled by default, for similar reasons */
    vms->virt = false;
    object_property_add_bool(obj, "virtualization", virt_get_virt,
                             virt_set_virt, NULL);
    object_property_set_description(obj, "virtualization",
                                    "Set on/off to enable/disable emulating a "
                                    "guest CPU which implements the ARM "
                                    "Virtualization Extensions",
                                    NULL);

    /* High memory is enabled by default */
    vms->highmem = true;
    object_property_add_bool(obj, "highmem", virt_get_highmem,
+2 −0
Original line number Diff line number Diff line
@@ -258,6 +258,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)

        object_property_set_bool(OBJECT(&s->apu_cpu[i]),
                                 s->secure, "has_el3", NULL);
        object_property_set_bool(OBJECT(&s->apu_cpu[i]),
                                 false, "has_el2", NULL);
        object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR,
                                "reset-cbar", &error_abort);
        object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "realized",
Loading