Commit 144ecc7f authored by Peter Maydell's avatar Peter Maydell
Browse files

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



target-arm queue:
 * support large kernel images in bootloader (by avoiding
   putting the initrd over the top of them)
 * correctly disable FPU/DSP in the CPU for the mps2-an521, musca-a boards
 * arm_gicv3: Fix decoding of ID register range
 * arm_gicv3: GICD_TYPER.SecurityExtn is RAZ if GICD_CTLR.DS == 1
 * some code cleanups following on from the VFP decodetree conversion
 * Only implement doubles if the FPU supports them
   (so we now correctly model Cortex-M4, -M33 as single precision only)

# gpg: Signature made Mon 17 Jun 2019 15:33:01 BST
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20190617: (24 commits)
  target/arm: Only implement doubles if the FPU supports them
  target/arm: Fix typos in trans function prototypes
  target/arm: Remove unused cpu_F0s, cpu_F0d, cpu_F1s, cpu_F1d
  target/arm: Stop using deprecated functions in NEON_2RM_VCVT_F32_F16
  target/arm: stop using deprecated functions in NEON_2RM_VCVT_F16_F32
  target/arm: Stop using cpu_F0s in Neon VCVT fixed-point ops
  target/arm: Stop using cpu_F0s for Neon f32/s32 VCVT
  target/arm: Stop using cpu_F0s for NEON_2RM_VRECPE_F and NEON_2RM_VRSQRTE_F
  target/arm: Stop using cpu_F0s for NEON_2RM_VCVT[ANPM][US]
  target/arm: Stop using cpu_F0s for NEON_2RM_VRINT*
  target/arm: Stop using cpu_F0s for NEON_2RM_VNEG_F
  target/arm: Stop using cpu_F0s for NEON_2RM_VABS_F
  target/arm: Use vfp_expand_imm() for AArch32 VFP VMOV_imm
  target/arm: Move vfp_expand_imm() to translate.[ch]
  hw/intc/arm_gicv3: GICD_TYPER.SecurityExtn is RAZ if GICD_CTLR.DS == 1
  hw/intc/arm_gicv3: Fix decoding of ID register range
  hw/arm: Correctly disable FPU/DSP for some ARMSSE-based boards
  hw/arm/armv7m: Forward "vfp" and "dsp" properties to CPU
  target/arm: Allow M-profile CPUs to disable the DSP extension via CPU property
  target/arm: Allow VFP and Neon to be disabled via a CPU property
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 5d0e5694 1120827f
Loading
Loading
Loading
Loading
+46 −12
Original line number Diff line number Diff line
@@ -38,6 +38,33 @@ struct ARMSSEInfo {
    bool has_cachectrl;
    bool has_cpusecctrl;
    bool has_cpuid;
    Property *props;
};

static Property iotkit_properties[] = {
    DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
                     MemoryRegion *),
    DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
    DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
    DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
    DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
    DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
    DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], true),
    DEFINE_PROP_END_OF_LIST()
};

static Property armsse_properties[] = {
    DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
                     MemoryRegion *),
    DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
    DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
    DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
    DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
    DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], false),
    DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], false),
    DEFINE_PROP_BOOL("CPU1_FPU", ARMSSE, cpu_fpu[1], true),
    DEFINE_PROP_BOOL("CPU1_DSP", ARMSSE, cpu_dsp[1], true),
    DEFINE_PROP_END_OF_LIST()
};

static const ARMSSEInfo armsse_variants[] = {
@@ -53,6 +80,7 @@ static const ARMSSEInfo armsse_variants[] = {
        .has_cachectrl = false,
        .has_cpusecctrl = false,
        .has_cpuid = false,
        .props = iotkit_properties,
    },
    {
        .name = TYPE_SSE200,
@@ -66,6 +94,7 @@ static const ARMSSEInfo armsse_variants[] = {
        .has_cachectrl = true,
        .has_cpusecctrl = true,
        .has_cpuid = true,
        .props = armsse_properties,
    },
};

@@ -533,6 +562,20 @@ static void armsse_realize(DeviceState *dev, Error **errp)
                return;
            }
        }
        if (!s->cpu_fpu[i]) {
            object_property_set_bool(cpuobj, false, "vfp", &err);
            if (err) {
                error_propagate(errp, err);
                return;
            }
        }
        if (!s->cpu_dsp[i]) {
            object_property_set_bool(cpuobj, false, "dsp", &err);
            if (err) {
                error_propagate(errp, err);
                return;
            }
        }

        if (i > 0) {
            memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
@@ -1222,16 +1265,6 @@ static const VMStateDescription armsse_vmstate = {
    }
};

static Property armsse_properties[] = {
    DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
                     MemoryRegion *),
    DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
    DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
    DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
    DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
    DEFINE_PROP_END_OF_LIST()
};

static void armsse_reset(DeviceState *dev)
{
    ARMSSE *s = ARMSSE(dev);
@@ -1244,13 +1277,14 @@ static void armsse_class_init(ObjectClass *klass, void *data)
    DeviceClass *dc = DEVICE_CLASS(klass);
    IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
    ARMSSEClass *asc = ARMSSE_CLASS(klass);
    const ARMSSEInfo *info = data;

    dc->realize = armsse_realize;
    dc->vmsd = &armsse_vmstate;
    dc->props = armsse_properties;
    dc->props = info->props;
    dc->reset = armsse_reset;
    iic->check = armsse_idau_check;
    asc->info = data;
    asc->info = info;
}

static const TypeInfo armsse_info = {
+18 −0
Original line number Diff line number Diff line
@@ -190,6 +190,22 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
            return;
        }
    }
    if (object_property_find(OBJECT(s->cpu), "vfp", NULL)) {
        object_property_set_bool(OBJECT(s->cpu), s->vfp,
                                 "vfp", &err);
        if (err != NULL) {
            error_propagate(errp, err);
            return;
        }
    }
    if (object_property_find(OBJECT(s->cpu), "dsp", NULL)) {
        object_property_set_bool(OBJECT(s->cpu), s->dsp,
                                 "dsp", &err);
        if (err != NULL) {
            error_propagate(errp, err);
            return;
        }
    }

    /*
     * Tell the CPU where the NVIC is; it will fail realize if it doesn't
@@ -260,6 +276,8 @@ static Property armv7m_properties[] = {
    DEFINE_PROP_BOOL("enable-bitband", ARMv7MState, enable_bitband, false),
    DEFINE_PROP_BOOL("start-powered-off", ARMv7MState, start_powered_off,
                     false),
    DEFINE_PROP_BOOL("vfp", ARMv7MState, vfp, true),
    DEFINE_PROP_BOOL("dsp", ARMv7MState, dsp, true),
    DEFINE_PROP_END_OF_LIST(),
};

+62 −21
Original line number Diff line number Diff line
@@ -911,6 +911,7 @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
                                   hwaddr *entry, AddressSpace *as)
{
    hwaddr kernel_load_offset = KERNEL64_LOAD_ADDR;
    uint64_t kernel_size = 0;
    uint8_t *buffer;
    int size;

@@ -938,7 +939,10 @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
         * is only valid if the image_size is non-zero.
         */
        memcpy(&hdrvals, buffer + ARM64_TEXT_OFFSET_OFFSET, sizeof(hdrvals));
        if (hdrvals[1] != 0) {

        kernel_size = le64_to_cpu(hdrvals[1]);

        if (kernel_size != 0) {
            kernel_load_offset = le64_to_cpu(hdrvals[0]);

            /*
@@ -956,12 +960,21 @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
        }
    }

    /*
     * Kernels before v3.17 don't populate the image_size field, and
     * raw images have no header. For those our best guess at the size
     * is the size of the Image file itself.
     */
    if (kernel_size == 0) {
        kernel_size = size;
    }

    *entry = mem_base + kernel_load_offset;
    rom_add_blob_fixed_as(filename, buffer, size, *entry, as);

    g_free(buffer);

    return size;
    return kernel_size;
}

static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
@@ -977,6 +990,7 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
    int elf_machine;
    hwaddr entry;
    static const ARMInsnFixup *primary_loader;
    uint64_t ram_end = info->loader_start + info->ram_size;

    if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
        primary_loader = bootloader_aarch64;
@@ -999,20 +1013,6 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
    if (info->nb_cpus == 0)
        info->nb_cpus = 1;

    /*
     * We want to put the initrd far enough into RAM that when the
     * kernel is uncompressed it will not clobber the initrd. However
     * on boards without much RAM we must ensure that we still leave
     * enough room for a decent sized initrd, and on boards with large
     * amounts of RAM we must avoid the initrd being so far up in RAM
     * that it is outside lowmem and inaccessible to the kernel.
     * So for boards with less  than 256MB of RAM we put the initrd
     * halfway into RAM, and for boards with 256MB of RAM or more we put
     * the initrd at 128MB.
     */
    info->initrd_start = info->loader_start +
        MIN(info->ram_size / 2, 128 * 1024 * 1024);

    /* Assume that raw images are linux kernels, and ELF images are not.  */
    kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
                               &elf_high_addr, elf_machine, as);
@@ -1048,27 +1048,59 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
        /* 32-bit ARM */
        entry = info->loader_start + KERNEL_LOAD_ADDR;
        kernel_size = load_image_targphys_as(info->kernel_filename, entry,
                                             info->ram_size - KERNEL_LOAD_ADDR,
                                             as);
                                             ram_end - KERNEL_LOAD_ADDR, as);
        is_linux = 1;
    }
    if (kernel_size < 0) {
        error_report("could not load kernel '%s'", info->kernel_filename);
        exit(1);
    }

    if (kernel_size > info->ram_size) {
        error_report("kernel '%s' is too large to fit in RAM "
                     "(kernel size %d, RAM size %" PRId64 ")",
                     info->kernel_filename, kernel_size, info->ram_size);
        exit(1);
    }

    info->entry = entry;

    /*
     * We want to put the initrd far enough into RAM that when the
     * kernel is uncompressed it will not clobber the initrd. However
     * on boards without much RAM we must ensure that we still leave
     * enough room for a decent sized initrd, and on boards with large
     * amounts of RAM we must avoid the initrd being so far up in RAM
     * that it is outside lowmem and inaccessible to the kernel.
     * So for boards with less  than 256MB of RAM we put the initrd
     * halfway into RAM, and for boards with 256MB of RAM or more we put
     * the initrd at 128MB.
     * We also refuse to put the initrd somewhere that will definitely
     * overlay the kernel we just loaded, though for kernel formats which
     * don't tell us their exact size (eg self-decompressing 32-bit kernels)
     * we might still make a bad choice here.
     */
    info->initrd_start = info->loader_start +
        MAX(MIN(info->ram_size / 2, 128 * 1024 * 1024), kernel_size);
    info->initrd_start = TARGET_PAGE_ALIGN(info->initrd_start);

    if (is_linux) {
        uint32_t fixupcontext[FIXUP_MAX];

        if (info->initrd_filename) {

            if (info->initrd_start >= ram_end) {
                error_report("not enough space after kernel to load initrd");
                exit(1);
            }

            initrd_size = load_ramdisk_as(info->initrd_filename,
                                          info->initrd_start,
                                          info->ram_size - info->initrd_start,
                                          as);
                                          ram_end - info->initrd_start, as);
            if (initrd_size < 0) {
                initrd_size = load_image_targphys_as(info->initrd_filename,
                                                     info->initrd_start,
                                                     info->ram_size -
                                                     ram_end -
                                                     info->initrd_start,
                                                     as);
            }
@@ -1077,6 +1109,11 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
                             info->initrd_filename);
                exit(1);
            }
            if (info->initrd_start + initrd_size > info->ram_size) {
                error_report("could not load initrd '%s': "
                             "too big to fit into RAM after the kernel",
                             info->initrd_filename);
            }
        } else {
            initrd_size = 0;
        }
@@ -1112,6 +1149,10 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
            /* Place the DTB after the initrd in memory with alignment. */
            info->dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size,
                                           align);
            if (info->dtb_start >= ram_end) {
                error_report("Not enough space for DTB after kernel/initrd");
                exit(1);
            }
            fixupcontext[FIXUP_ARGPTR_LO] = info->dtb_start;
            fixupcontext[FIXUP_ARGPTR_HI] = info->dtb_start >> 32;
        } else {
+8 −0
Original line number Diff line number Diff line
@@ -385,6 +385,14 @@ static void musca_init(MachineState *machine)
    qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
    qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
    qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ);
    /*
     * Musca-A takes the default SSE-200 FPU/DSP settings (ie no for
     * CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0.
     */
    if (mmc->type == MUSCA_B1) {
        qdev_prop_set_bit(ssedev, "CPU0_FPU", true);
        qdev_prop_set_bit(ssedev, "CPU0_DSP", true);
    }
    object_property_set_bool(OBJECT(&mms->sse), true, "realized",
                             &error_fatal);

+9 −3
Original line number Diff line number Diff line
@@ -378,8 +378,14 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
         * ITLinesNumber == (num external irqs / 32) - 1
         */
        int itlinesnumber = ((s->num_irq - GIC_INTERNAL) / 32) - 1;
        /*
         * SecurityExtn must be RAZ if GICD_CTLR.DS == 1, and
         * "security extensions not supported" always implies DS == 1,
         * so we only need to check the DS bit.
         */
        bool sec_extn = !(s->gicd_ctlr & GICD_CTLR_DS);

        *data = (1 << 25) | (1 << 24) | (s->security_extn << 10) |
        *data = (1 << 25) | (1 << 24) | (sec_extn << 10) |
            (0xf << 19) | itlinesnumber;
        return MEMTX_OK;
    }
@@ -533,7 +539,7 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
        }
        return MEMTX_OK;
    }
    case GICD_IDREGS ... GICD_IDREGS + 0x1f:
    case GICD_IDREGS ... GICD_IDREGS + 0x2f:
        /* ID registers */
        *data = gicv3_idreg(offset - GICD_IDREGS);
        return MEMTX_OK;
@@ -744,7 +750,7 @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset,
        gicd_write_irouter(s, attrs, irq, r);
        return MEMTX_OK;
    }
    case GICD_IDREGS ... GICD_IDREGS + 0x1f:
    case GICD_IDREGS ... GICD_IDREGS + 0x2f:
    case GICD_TYPER:
    case GICD_IIDR:
        /* RO registers, ignore the write */
Loading