Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-2…
Browse files Browse the repository at this point in the history
…0170120' 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: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Jan 20, 2017
2 parents 0f6bcf6 + f29cacf commit 28f5e97
Show file tree
Hide file tree
Showing 23 changed files with 2,149 additions and 141 deletions.
41 changes: 41 additions & 0 deletions hw/arm/aspeed.c
Expand Up @@ -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 */
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion hw/arm/imx25_pdk.c
Expand Up @@ -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);
}
}
Expand Down
36 changes: 30 additions & 6 deletions hw/arm/virt-acpi-build.c
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
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+ and with HVC */
/* 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;
Expand Down Expand Up @@ -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);
Expand Down
88 changes: 77 additions & 11 deletions hw/arm/virt.c
Expand Up @@ -167,7 +167,6 @@ static const char *valid_cpus[] = {
"cortex-a53",
"cortex-a57",
"host",
NULL
};

static bool cpuname_valid(const char *cpu)
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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));
Expand All @@ -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++) {
Expand Down Expand Up @@ -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.
Expand All @@ -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");
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions hw/arm/xlnx-zynqmp.c
Expand Up @@ -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",
Expand Down

0 comments on commit 28f5e97

Please sign in to comment.