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

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



target-arm queue:
 * implement M profile exception return properly
 * cadence GEM: fix multiqueue handling bugs
 * pxa2xx.c: QOMify a device
 * arm/kvm: Remove trailing newlines from error_report()
 * stellaris: Don't hw_error() on bad register accesses
 * Add assertion about FSC format for syndrome registers
 * Move excnames[] array into arm_log_exceptions()
 * exynos: minor code cleanups
 * hw/arm/boot: take Linux/arm64 TEXT_OFFSET header field into account
 * Fix APSR writes via M profile MSR

# gpg: Signature made Thu 20 Apr 2017 17:39:35 BST
# 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-20170420: (24 commits)
  arm: Remove workarounds for old M-profile exception return implementation
  arm: Implement M profile exception return properly
  arm: Track M profile handler mode state in TB flags
  arm: Abstract out "are we singlestepping" test to utility function
  arm: Move condition-failed codepath generation out of if()
  arm: Move gen_set_condexec() and gen_set_pc_im() up in the file
  arm: Factor out "generate right kind of step exception"
  arm: Thumb shift operations should not permit interworking branches
  arm: Don't implement BXJ on M-profile CPUs
  xlnx-zynqmp: Set the Cadence GEM revision
  cadence_gem: Make the revision a property
  cadence_gem: Correct the interupt logic
  cadence_gem: Correct the multi-queue can rx logic
  cadence_gem: Read the correct queue descriptor
  hw/arm: Qomify pxa2xx.c
  arm/kvm: Remove trailing newlines from error_report()
  stellaris: Don't hw_error() on bad register accesses
  target/arm: Add assertion about FSC format for syndrome registers
  arm: Move excnames[] array into arm_log_exceptions()
  target/arm: Add missing entries to excnames[] for log strings
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 64c8ed97 f4e8e4ed
Loading
Loading
Loading
Loading
+53 −11
Original line number Diff line number Diff line
@@ -31,6 +31,9 @@
#define KERNEL_LOAD_ADDR 0x00010000
#define KERNEL64_LOAD_ADDR 0x00080000

#define ARM64_TEXT_OFFSET_OFFSET    8
#define ARM64_MAGIC_OFFSET          56

typedef enum {
    FIXUP_NONE = 0,     /* do nothing */
    FIXUP_TERMINATOR,   /* end of insns */
@@ -768,6 +771,49 @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
    return ret;
}

static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
                                   hwaddr *entry)
{
    hwaddr kernel_load_offset = KERNEL64_LOAD_ADDR;
    uint8_t *buffer;
    int size;

    /* On aarch64, it's the bootloader's job to uncompress the kernel. */
    size = load_image_gzipped_buffer(filename, LOAD_IMAGE_MAX_GUNZIP_BYTES,
                                     &buffer);

    if (size < 0) {
        gsize len;

        /* Load as raw file otherwise */
        if (!g_file_get_contents(filename, (char **)&buffer, &len, NULL)) {
            return -1;
        }
        size = len;
    }

    /* check the arm64 magic header value -- very old kernels may not have it */
    if (memcmp(buffer + ARM64_MAGIC_OFFSET, "ARM\x64", 4) == 0) {
        uint64_t hdrvals[2];

        /* The arm64 Image header has text_offset and image_size fields at 8 and
         * 16 bytes into the Image header, respectively. The text_offset field
         * is only valid if the image_size is non-zero.
         */
        memcpy(&hdrvals, buffer + ARM64_TEXT_OFFSET_OFFSET, sizeof(hdrvals));
        if (hdrvals[1] != 0) {
            kernel_load_offset = le64_to_cpu(hdrvals[0]);
        }
    }

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

    g_free(buffer);

    return size;
}

static void arm_load_kernel_notify(Notifier *notifier, void *data)
{
    CPUState *cs;
@@ -776,7 +822,7 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
    int is_linux = 0;
    uint64_t elf_entry, elf_low_addr, elf_high_addr;
    int elf_machine;
    hwaddr entry, kernel_load_offset;
    hwaddr entry;
    static const ARMInsnFixup *primary_loader;
    ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier,
                                         notifier, notifier);
@@ -841,14 +887,12 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)

    if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
        primary_loader = bootloader_aarch64;
        kernel_load_offset = KERNEL64_LOAD_ADDR;
        elf_machine = EM_AARCH64;
    } else {
        primary_loader = bootloader;
        if (!info->write_board_setup) {
            primary_loader += BOOTLOADER_NO_BOARD_SETUP_OFFSET;
        }
        kernel_load_offset = KERNEL_LOAD_ADDR;
        elf_machine = EM_ARM;
    }

@@ -900,17 +944,15 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
        kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
                                  &is_linux, NULL, NULL);
    }
    /* On aarch64, it's the bootloader's job to uncompress the kernel. */
    if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && kernel_size < 0) {
        entry = info->loader_start + kernel_load_offset;
        kernel_size = load_image_gzipped(info->kernel_filename, entry,
                                         info->ram_size - kernel_load_offset);
        kernel_size = load_aarch64_image(info->kernel_filename,
                                         info->loader_start, &entry);
        is_linux = 1;
    }
    if (kernel_size < 0) {
        entry = info->loader_start + kernel_load_offset;
    } else if (kernel_size < 0) {
        /* 32-bit ARM */
        entry = info->loader_start + KERNEL_LOAD_ADDR;
        kernel_size = load_image_targphys(info->kernel_filename, entry,
                                          info->ram_size - kernel_load_offset);
                                          info->ram_size - KERNEL_LOAD_ADDR);
        is_linux = 1;
    }
    if (kernel_size < 0) {
+4 −3
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
 */

#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qemu-common.h"
#include "cpu.h"
#include "sysemu/sysemu.h"
@@ -101,8 +102,8 @@ static Exynos4210State *exynos4_boards_init_common(MachineState *machine,
    MachineClass *mc = MACHINE_GET_CLASS(machine);

    if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) {
        fprintf(stderr, "%s board supports only %d CPU cores. Ignoring smp_cpus"
                " value.\n",
        error_report("%s board supports only %d CPU cores, ignoring smp_cpus"
                     " value",
                     mc->name, EXYNOS4210_NCPUS);
    }

+6 −8
Original line number Diff line number Diff line
@@ -755,19 +755,18 @@ static void pxa2xx_ssp_reset(DeviceState *d)
    s->rx_start = s->rx_level = 0;
}

static int pxa2xx_ssp_init(SysBusDevice *sbd)
static void pxa2xx_ssp_init(Object *obj)
{
    DeviceState *dev = DEVICE(sbd);
    PXA2xxSSPState *s = PXA2XX_SSP(dev);

    DeviceState *dev = DEVICE(obj);
    PXA2xxSSPState *s = PXA2XX_SSP(obj);
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    sysbus_init_irq(sbd, &s->irq);

    memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_ssp_ops, s,
    memory_region_init_io(&s->iomem, obj, &pxa2xx_ssp_ops, s,
                          "pxa2xx-ssp", 0x1000);
    sysbus_init_mmio(sbd, &s->iomem);

    s->bus = ssi_create_bus(dev, "ssi");
    return 0;
}

/* Real-Time Clock */
@@ -2321,10 +2320,8 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)

static void pxa2xx_ssp_class_init(ObjectClass *klass, void *data)
{
    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
    DeviceClass *dc = DEVICE_CLASS(klass);

    sdc->init = pxa2xx_ssp_init;
    dc->reset = pxa2xx_ssp_reset;
    dc->vmsd = &vmstate_pxa2xx_ssp;
}
@@ -2333,6 +2330,7 @@ static const TypeInfo pxa2xx_ssp_info = {
    .name          = TYPE_PXA2XX_SSP,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(PXA2xxSSPState),
    .instance_init = pxa2xx_ssp_init,
    .class_init    = pxa2xx_ssp_class_init,
};

+37 −23
Original line number Diff line number Diff line
@@ -108,7 +108,10 @@ static void gptm_reload(gptm_state *s, int n, int reset)
    } else if (s->mode[n] == 0xa) {
        /* PWM mode.  Not implemented.  */
    } else {
        hw_error("TODO: 16-bit timer mode 0x%x\n", s->mode[n]);
        qemu_log_mask(LOG_UNIMP,
                      "GPTM: 16-bit timer mode unimplemented: 0x%x\n",
                      s->mode[n]);
        return;
    }
    s->tick[n] = tick;
    timer_mod(s->timer[n], tick);
@@ -149,7 +152,9 @@ static void gptm_tick(void *opaque)
    } else if (s->mode[n] == 0xa) {
        /* PWM mode.  Not implemented.  */
    } else {
        hw_error("TODO: 16-bit timer mode 0x%x\n", s->mode[n]);
        qemu_log_mask(LOG_UNIMP,
                      "GPTM: 16-bit timer mode unimplemented: 0x%x\n",
                      s->mode[n]);
    }
    gptm_update_irq(s);
}
@@ -286,7 +291,8 @@ static void gptm_write(void *opaque, hwaddr offset,
        s->match_prescale[0] = value;
        break;
    default:
        hw_error("gptm_write: Bad offset 0x%x\n", (int)offset);
        qemu_log_mask(LOG_GUEST_ERROR,
                      "GPTM: read at bad offset 0x%x\n", (int)offset);
    }
    gptm_update_irq(s);
}
@@ -425,7 +431,10 @@ static int ssys_board_class(const ssys_state *s)
        }
        /* for unknown classes, fall through */
    default:
        hw_error("ssys_board_class: Unknown class 0x%08x\n", did0);
        /* This can only happen if the hardwired constant did0 value
         * in this board's stellaris_board_info struct is wrong.
         */
        g_assert_not_reached();
    }
}

@@ -479,8 +488,7 @@ static uint64_t ssys_read(void *opaque, hwaddr offset,
            case DID0_CLASS_SANDSTORM:
                return pllcfg_sandstorm[xtal];
            default:
                hw_error("ssys_read: Unhandled class for PLLCFG read.\n");
                return 0;
                g_assert_not_reached();
            }
        }
    case 0x070: /* RCC2 */
@@ -512,7 +520,8 @@ static uint64_t ssys_read(void *opaque, hwaddr offset,
    case 0x1e4: /* USER1 */
        return s->user1;
    default:
        hw_error("ssys_read: Bad offset 0x%x\n", (int)offset);
        qemu_log_mask(LOG_GUEST_ERROR,
                      "SSYS: read at bad offset 0x%x\n", (int)offset);
        return 0;
    }
}
@@ -614,7 +623,8 @@ static void ssys_write(void *opaque, hwaddr offset,
        s->ldoarst = value;
        break;
    default:
        hw_error("ssys_write: Bad offset 0x%x\n", (int)offset);
        qemu_log_mask(LOG_GUEST_ERROR,
                      "SSYS: write at bad offset 0x%x\n", (int)offset);
    }
    ssys_update(s);
}
@@ -748,7 +758,8 @@ static uint64_t stellaris_i2c_read(void *opaque, hwaddr offset,
    case 0x20: /* MCR */
        return s->mcr;
    default:
        hw_error("strllaris_i2c_read: Bad offset 0x%x\n", (int)offset);
        qemu_log_mask(LOG_GUEST_ERROR,
                      "stellaris_i2c: read at bad offset 0x%x\n", (int)offset);
        return 0;
    }
}
@@ -823,17 +834,18 @@ static void stellaris_i2c_write(void *opaque, hwaddr offset,
        s->mris &= ~value;
        break;
    case 0x20: /* MCR */
        if (value & 1)
            hw_error(
                      "stellaris_i2c_write: Loopback not implemented\n");
        if (value & 0x20)
            hw_error(
                      "stellaris_i2c_write: Slave mode not implemented\n");
        if (value & 1) {
            qemu_log_mask(LOG_UNIMP, "stellaris_i2c: Loopback not implemented");
        }
        if (value & 0x20) {
            qemu_log_mask(LOG_UNIMP,
                          "stellaris_i2c: Slave mode not implemented");
        }
        s->mcr = value & 0x31;
        break;
    default:
        hw_error("stellaris_i2c_write: Bad offset 0x%x\n",
                  (int)offset);
        qemu_log_mask(LOG_GUEST_ERROR,
                      "stellaris_i2c: write at bad offset 0x%x\n", (int)offset);
    }
    stellaris_i2c_update(s);
}
@@ -1057,8 +1069,8 @@ static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
    case 0x30: /* SAC */
        return s->sac;
    default:
        hw_error("strllaris_adc_read: Bad offset 0x%x\n",
                  (int)offset);
        qemu_log_mask(LOG_GUEST_ERROR,
                      "stellaris_adc: read at bad offset 0x%x\n", (int)offset);
        return 0;
    }
}
@@ -1078,7 +1090,8 @@ static void stellaris_adc_write(void *opaque, hwaddr offset,
            return;
        case 0x04: /* SSCTL */
            if (value != 6) {
                hw_error("ADC: Unimplemented sequence %" PRIx64 "\n",
                qemu_log_mask(LOG_UNIMP,
                              "ADC: Unimplemented sequence %" PRIx64 "\n",
                              value);
            }
            s->ssctl[n] = value;
@@ -1110,13 +1123,14 @@ static void stellaris_adc_write(void *opaque, hwaddr offset,
        s->sspri = value;
        break;
    case 0x28: /* PSSI */
        hw_error("Not implemented:  ADC sample initiate\n");
        qemu_log_mask(LOG_UNIMP, "ADC: sample initiate unimplemented");
        break;
    case 0x30: /* SAC */
        s->sac = value;
        break;
    default:
        hw_error("stellaris_adc_write: Bad offset 0x%x\n", (int)offset);
        qemu_log_mask(LOG_GUEST_ERROR,
                      "stellaris_adc: write at bad offset 0x%x\n", (int)offset);
    }
    stellaris_adc_update(s);
}
+5 −1
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@
#define ARM_PHYS_TIMER_PPI  30
#define ARM_VIRT_TIMER_PPI  27

#define GEM_REVISION        0x40070106

#define GIC_BASE_ADDR       0xf9000000
#define GIC_DIST_ADDR       0xf9010000
#define GIC_CPU_ADDR        0xf9020000
@@ -334,6 +336,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
            qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
            qdev_set_nic_properties(DEVICE(&s->gem[i]), nd);
        }
        object_property_set_int(OBJECT(&s->gem[i]), GEM_REVISION, "revision",
                                &error_abort);
        object_property_set_int(OBJECT(&s->gem[i]), 2, "num-priority-queues",
                                &error_abort);
        object_property_set_bool(OBJECT(&s->gem[i]), true, "realized", &err);
Loading