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

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



target-arm queue:
 * fsl-imx6: Fix incorrect Ethernet interrupt defines
 * dump: Update correct kdump phys_base field for AArch64
 * char: i.MX: Add support for "TX complete" interrupt
 * bcm2836/raspi: Fix various bugs resulting in panics trying
   to boot a Debian Linux kernel on raspi3

# gpg: Signature made Mon 19 Mar 2018 18:30:33 GMT
# gpg:                using RSA key 3C2525ED14360CDE
# 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-20180319:
  hw/arm/raspi: Provide spin-loop code for AArch64 CPUs
  hw/arm/bcm2836: Hardcode correct CPU type
  hw/arm/bcm2836: Use correct affinity values for BCM2837
  hw/arm/bcm2836: Create proper bcm2837 device
  hw/arm/bcm2836: Rename bcm2836 type/struct to bcm283x
  hw/arm/bcm2386: Fix parent type of bcm2386
  hw/arm/boot: If booting a kernel in EL2, set SCR_EL3.HCE
  hw/arm/boot: assert that secure_boot and secure_board_setup are false for AArch64
  hw/arm/raspi: Don't do board-setup or secure-boot for raspi3
  char: i.MX: Add support for "TX complete" interrupt
  char: i.MX: Simplify imx_update()
  dump: Update correct kdump phys_base field for AArch64
  fsl-imx6: Swap Ethernet interrupt defines

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 2c8cfc0b ff72cb6b
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -1609,10 +1609,18 @@ static void vmcoreinfo_update_phys_base(DumpState *s)

    lines = g_strsplit((char *)vmci, "\n", -1);
    for (i = 0; lines[i]; i++) {
        if (g_str_has_prefix(lines[i], "NUMBER(phys_base)=")) {
            if (qemu_strtou64(lines[i] + 18, NULL, 16,
        const char *prefix = NULL;

        if (s->dump_info.d_machine == EM_X86_64) {
            prefix = "NUMBER(phys_base)=";
        } else if (s->dump_info.d_machine == EM_AARCH64) {
            prefix = "NUMBER(PHYS_OFFSET)=";
        }

        if (prefix && g_str_has_prefix(lines[i], prefix)) {
            if (qemu_strtou64(lines[i] + strlen(prefix), NULL, 16,
                              &phys_base) < 0) {
                warn_report("Failed to read NUMBER(phys_base)=");
                warn_report("Failed to read %s", prefix);
            } else {
                s->dump_info.phys_base = phys_base;
            }
+62 −25
Original line number Diff line number Diff line
@@ -23,9 +23,40 @@
/* "QA7" (Pi2) interrupt controller and mailboxes etc. */
#define BCM2836_CONTROL_BASE    0x40000000

struct BCM283XInfo {
    const char *name;
    const char *cpu_type;
    int clusterid;
};

static const BCM283XInfo bcm283x_socs[] = {
    {
        .name = TYPE_BCM2836,
        .cpu_type = ARM_CPU_TYPE_NAME("cortex-a15"),
        .clusterid = 0xf,
    },
#ifdef TARGET_AARCH64
    {
        .name = TYPE_BCM2837,
        .cpu_type = ARM_CPU_TYPE_NAME("cortex-a53"),
        .clusterid = 0x0,
    },
#endif
};

static void bcm2836_init(Object *obj)
{
    BCM2836State *s = BCM2836(obj);
    BCM283XState *s = BCM283X(obj);
    BCM283XClass *bc = BCM283X_GET_CLASS(obj);
    const BCM283XInfo *info = bc->info;
    int n;

    for (n = 0; n < BCM283X_NCPUS; n++) {
        object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
                          info->cpu_type);
        object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]),
                                  &error_abort);
    }

    object_initialize(&s->control, sizeof(s->control), TYPE_BCM2836_CONTROL);
    object_property_add_child(obj, "control", OBJECT(&s->control), NULL);
@@ -44,21 +75,15 @@ static void bcm2836_init(Object *obj)

static void bcm2836_realize(DeviceState *dev, Error **errp)
{
    BCM2836State *s = BCM2836(dev);
    BCM283XState *s = BCM283X(dev);
    BCM283XClass *bc = BCM283X_GET_CLASS(dev);
    const BCM283XInfo *info = bc->info;
    Object *obj;
    Error *err = NULL;
    int n;

    /* common peripherals from bcm2835 */

    obj = OBJECT(dev);
    for (n = 0; n < BCM2836_NCPUS; n++) {
        object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
                          s->cpu_type);
        object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]),
                                  &error_abort);
    }

    obj = object_property_get_link(OBJECT(dev), "ram", &err);
    if (obj == NULL) {
        error_setg(errp, "%s: required ram link not found: %s",
@@ -102,11 +127,9 @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
    sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1,
        qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-fiq", 0));

    for (n = 0; n < BCM2836_NCPUS; n++) {
        /* Mirror bcm2836, which has clusterid set to 0xf
         * TODO: this should be converted to a property of ARM_CPU
         */
        s->cpus[n].mp_affinity = 0xF00 | n;
    for (n = 0; n < BCM283X_NCPUS; n++) {
        /* TODO: this should be converted to a property of ARM_CPU */
        s->cpus[n].mp_affinity = (info->clusterid << 8) | n;

        /* set periphbase/CBAR value for CPU-local registers */
        object_property_set_int(OBJECT(&s->cpus[n]),
@@ -150,30 +173,44 @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
}

static Property bcm2836_props[] = {
    DEFINE_PROP_STRING("cpu-type", BCM2836State, cpu_type),
    DEFINE_PROP_UINT32("enabled-cpus", BCM2836State, enabled_cpus, BCM2836_NCPUS),
    DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus,
                       BCM283X_NCPUS),
    DEFINE_PROP_END_OF_LIST()
};

static void bcm2836_class_init(ObjectClass *oc, void *data)
static void bcm283x_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);
    BCM283XClass *bc = BCM283X_CLASS(oc);

    dc->props = bcm2836_props;
    bc->info = data;
    dc->realize = bcm2836_realize;
    dc->props = bcm2836_props;
}

static const TypeInfo bcm2836_type_info = {
    .name = TYPE_BCM2836,
    .parent = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(BCM2836State),
static const TypeInfo bcm283x_type_info = {
    .name = TYPE_BCM283X,
    .parent = TYPE_DEVICE,
    .instance_size = sizeof(BCM283XState),
    .instance_init = bcm2836_init,
    .class_init = bcm2836_class_init,
    .class_size = sizeof(BCM283XClass),
    .abstract = true,
};

static void bcm2836_register_types(void)
{
    type_register_static(&bcm2836_type_info);
    int i;

    type_register_static(&bcm283x_type_info);
    for (i = 0; i < ARRAY_SIZE(bcm283x_socs); i++) {
        TypeInfo ti = {
            .name = bcm283x_socs[i].name,
            .parent = TYPE_BCM283X,
            .class_init = bcm283x_class_init,
            .class_data = (void *) &bcm283x_socs[i],
        };
        type_register(&ti);
    }
}

type_init(bcm2836_register_types)
+12 −0
Original line number Diff line number Diff line
@@ -720,6 +720,18 @@ static void do_cpu_reset(void *opaque)
                    } else {
                        env->pstate = PSTATE_MODE_EL1h;
                    }
                    /* AArch64 kernels never boot in secure mode */
                    assert(!info->secure_boot);
                    /* This hook is only supported for AArch32 currently:
                     * bootloader_aarch64[] will not call the hook, and
                     * the code above has already dropped us into EL2 or EL1.
                     */
                    assert(!info->secure_board_setup);
                }

                if (arm_feature(env, ARM_FEATURE_EL2)) {
                    /* If we have EL2 then Linux expects the HVC insn to work */
                    env->cp15.scr_el3 |= SCR_HCE;
                }

                /* Set to non-secure if not a secure boot */
+62 −15
Original line number Diff line number Diff line
@@ -27,12 +27,13 @@
#define BOARDSETUP_ADDR (MVBAR_ADDR + 0x20) /* board setup code */
#define FIRMWARE_ADDR_2 0x8000 /* Pi 2 loads kernel.img here by default */
#define FIRMWARE_ADDR_3 0x80000 /* Pi 3 loads kernel.img here by default */
#define SPINTABLE_ADDR  0xd8 /* Pi 3 bootloader spintable */

/* Table of Linux board IDs for different Pi versions */
static const int raspi_boardid[] = {[1] = 0xc42, [2] = 0xc43, [3] = 0xc44};

typedef struct RasPiState {
    BCM2836State soc;
    BCM283XState soc;
    MemoryRegion ram;
} RasPiState;

@@ -63,6 +64,40 @@ static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info)
                       info->smp_loader_start);
}

static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
{
    /* Unlike the AArch32 version we don't need to call the board setup hook.
     * The mechanism for doing the spin-table is also entirely different.
     * We must have four 64-bit fields at absolute addresses
     * 0xd8, 0xe0, 0xe8, 0xf0 in RAM, which are the flag variables for
     * our CPUs, and which we must ensure are zero initialized before
     * the primary CPU goes into the kernel. We put these variables inside
     * a rom blob, so that the reset for ROM contents zeroes them for us.
     */
    static const uint32_t smpboot[] = {
        0xd2801b05, /*        mov     x5, 0xd8 */
        0xd53800a6, /*        mrs     x6, mpidr_el1 */
        0x924004c6, /*        and     x6, x6, #0x3 */
        0xd503205f, /* spin:  wfe */
        0xf86678a4, /*        ldr     x4, [x5,x6,lsl #3] */
        0xb4ffffc4, /*        cbz     x4, spin */
        0xd2800000, /*        mov     x0, #0x0 */
        0xd2800001, /*        mov     x1, #0x0 */
        0xd2800002, /*        mov     x2, #0x0 */
        0xd2800003, /*        mov     x3, #0x0 */
        0xd61f0080, /*        br      x4 */
    };

    static const uint64_t spintables[] = {
        0, 0, 0, 0
    };

    rom_add_blob_fixed("raspi_smpboot", smpboot, sizeof(smpboot),
                       info->smp_loader_start);
    rom_add_blob_fixed("raspi_spintables", spintables, sizeof(spintables),
                       SPINTABLE_ADDR);
}

static void write_board_setup(ARMCPU *cpu, const struct arm_boot_info *info)
{
    arm_write_secure_board_setup_dummy_smc(cpu, info, MVBAR_ADDR);
@@ -82,15 +117,28 @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
    binfo.board_id = raspi_boardid[version];
    binfo.ram_size = ram_size;
    binfo.nb_cpus = smp_cpus;

    if (version <= 2) {
        /* The rpi1 and 2 require some custom setup code to run in Secure
         * mode before booting a kernel (to set up the SMC vectors so
         * that we get a no-op SMC; this is used by Linux to call the
         * firmware for some cache maintenance operations.
         * The rpi3 doesn't need this.
         */
        binfo.board_setup_addr = BOARDSETUP_ADDR;
        binfo.write_board_setup = write_board_setup;
        binfo.secure_board_setup = true;
        binfo.secure_boot = true;
    }

    /* Pi2 and Pi3 requires SMP setup */
    if (version >= 2) {
        binfo.smp_loader_start = SMPBOOT_ADDR;
        if (version == 2) {
            binfo.write_secondary_boot = write_smpboot;
        } else {
            binfo.write_secondary_boot = write_smpboot64;
        }
        binfo.secondary_cpu_reset_hook = reset_secondary;
    }

@@ -127,7 +175,8 @@ static void raspi_init(MachineState *machine, int version)
    BusState *bus;
    DeviceState *carddev;

    object_initialize(&s->soc, sizeof(s->soc), TYPE_BCM2836);
    object_initialize(&s->soc, sizeof(s->soc),
                      version == 3 ? TYPE_BCM2837 : TYPE_BCM2836);
    object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
                              &error_abort);

@@ -140,8 +189,6 @@ static void raspi_init(MachineState *machine, int version)
    /* Setup the SOC */
    object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(&s->ram),
                                   &error_abort);
    object_property_set_str(OBJECT(&s->soc), machine->cpu_type, "cpu-type",
                            &error_abort);
    object_property_set_int(OBJECT(&s->soc), smp_cpus, "enabled-cpus",
                            &error_abort);
    int board_rev = version == 3 ? 0xa02082 : 0xa21041;
@@ -180,9 +227,9 @@ static void raspi2_machine_init(MachineClass *mc)
    mc->no_floppy = 1;
    mc->no_cdrom = 1;
    mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
    mc->max_cpus = BCM2836_NCPUS;
    mc->min_cpus = BCM2836_NCPUS;
    mc->default_cpus = BCM2836_NCPUS;
    mc->max_cpus = BCM283X_NCPUS;
    mc->min_cpus = BCM283X_NCPUS;
    mc->default_cpus = BCM283X_NCPUS;
    mc->default_ram_size = 1024 * 1024 * 1024;
    mc->ignore_memory_transaction_failures = true;
};
@@ -203,9 +250,9 @@ static void raspi3_machine_init(MachineClass *mc)
    mc->no_floppy = 1;
    mc->no_cdrom = 1;
    mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a53");
    mc->max_cpus = BCM2836_NCPUS;
    mc->min_cpus = BCM2836_NCPUS;
    mc->default_cpus = BCM2836_NCPUS;
    mc->max_cpus = BCM283X_NCPUS;
    mc->min_cpus = BCM283X_NCPUS;
    mc->default_cpus = BCM283X_NCPUS;
    mc->default_ram_size = 1024 * 1024 * 1024;
}
DEFINE_MACHINE("raspi3", raspi3_machine_init)
+33 −11
Original line number Diff line number Diff line
@@ -37,8 +37,8 @@

static const VMStateDescription vmstate_imx_serial = {
    .name = TYPE_IMX_SERIAL,
    .version_id = 1,
    .minimum_version_id = 1,
    .version_id = 2,
    .minimum_version_id = 2,
    .fields = (VMStateField[]) {
        VMSTATE_INT32(readbuff, IMXSerialState),
        VMSTATE_UINT32(usr1, IMXSerialState),
@@ -50,22 +50,36 @@ static const VMStateDescription vmstate_imx_serial = {
        VMSTATE_UINT32(ubmr, IMXSerialState),
        VMSTATE_UINT32(ubrc, IMXSerialState),
        VMSTATE_UINT32(ucr3, IMXSerialState),
        VMSTATE_UINT32(ucr4, IMXSerialState),
        VMSTATE_END_OF_LIST()
    },
};

static void imx_update(IMXSerialState *s)
{
    uint32_t flags;
    uint32_t usr1;
    uint32_t usr2;
    uint32_t mask;

    flags = (s->usr1 & s->ucr1) & (USR1_TRDY|USR1_RRDY);
    if (s->ucr1 & UCR1_TXMPTYEN) {
        flags |= (s->uts1 & UTS1_TXEMPTY);
    } else {
        flags &= ~USR1_TRDY;
    }
    /*
     * Lucky for us TRDY and RRDY has the same offset in both USR1 and
     * UCR1, so we can get away with something as simple as the
     * following:
     */
    usr1 = s->usr1 & s->ucr1 & (USR1_TRDY | USR1_RRDY);
    /*
     * Bits that we want in USR2 are not as conveniently laid out,
     * unfortunately.
     */
    mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0;
    /*
     * TCEN and TXDC are both bit 3
     */
    mask |= s->ucr4 & UCR4_TCEN;

    qemu_set_irq(s->irq, !!flags);
    usr2 = s->usr2 & mask;

    qemu_set_irq(s->irq, usr1 || usr2);
}

static void imx_serial_reset(IMXSerialState *s)
@@ -155,6 +169,8 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
        return s->ucr3;

    case 0x23: /* UCR4 */
        return s->ucr4;

    case 0x29: /* BRM Incremental */
        return 0x0; /* TODO */

@@ -183,8 +199,10 @@ static void imx_serial_write(void *opaque, hwaddr offset,
             * qemu_chr_fe_write and background I/O callbacks */
            qemu_chr_fe_write_all(&s->chr, &ch, 1);
            s->usr1 &= ~USR1_TRDY;
            s->usr2 &= ~USR2_TXDC;
            imx_update(s);
            s->usr1 |= USR1_TRDY;
            s->usr2 |= USR2_TXDC;
            imx_update(s);
        }
        break;
@@ -257,8 +275,12 @@ static void imx_serial_write(void *opaque, hwaddr offset,
        s->ucr3 = value & 0xffff;
        break;

    case 0x2d: /* UTS1 */
    case 0x23: /* UCR4 */
        s->ucr4 = value & 0xffff;
        imx_update(s);
        break;

    case 0x2d: /* UTS1 */
        qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented reg 0x%"
                      HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
        /* TODO */
Loading