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

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



target-arm queue:
 * aspeed: code cleanup to use unimplemented_device
 * preparatory work for 'raspi3' RaspberryPi 3 machine model
 * more SVE prep work
 * v8M: add minor missing registers
 * v7M: fix bug where we weren't migrating v7m.other_sp
 * v7M: fix bugs in handling of interrupt registers for
   external interrupts beyond 32

# gpg: Signature made Thu 15 Feb 2018 18:34:40 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-20180215-1:
  raspi: Raspberry Pi 3 support
  bcm2836: Make CPU type configurable
  target/arm: Implement v8M MSPLIM and PSPLIM registers
  target/arm: Migrate v7m.other_sp
  target/arm: Add AIRCR to vmstate struct
  hw/intc/armv7m_nvic: Fix byte-to-interrupt number conversions
  target/arm: Implement writing to CONTROL_NS for v8M
  hw/intc/armv7m_nvic: Implement SCR
  hw/intc/armv7m_nvic: Implement cache ID registers
  hw/intc/armv7m_nvic: Implement v8M CPPWR register
  hw/intc/armv7m_nvic: Implement M profile cache maintenance ops
  hw/intc/armv7m_nvic: Fix ICSR PENDNMISET/CLR handling
  hw/intc/armv7m_nvic: Don't hardcode M profile ID registers in NVIC
  target/arm: Handle SVE registers when using clear_vec_high
  target/arm: Enforce access to ZCR_EL at translation
  target/arm: Suppress TB end for FPCR/FPSR
  target/arm: Enforce FP access to FPCR/FPSR
  target/arm: Remove ARM_CP_64BIT from ZCR_EL registers
  hw/arm/aspeed: simplify using the 'unimplemented device' for aspeed_soc.io
  hw/arm/aspeed: directly map the serial device to the system address space

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents f003d073 bade5816
Loading
Loading
Loading
Loading
+5 −30
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include "qemu-common.h"
#include "cpu.h"
#include "exec/address-spaces.h"
#include "hw/misc/unimp.h"
#include "hw/arm/aspeed_soc.h"
#include "hw/char/serial.h"
#include "qemu/log.h"
@@ -99,31 +100,6 @@ static const AspeedSoCInfo aspeed_socs[] = {
    },
};

/*
 * IO handlers: simply catch any reads/writes to IO addresses that aren't
 * handled by a device mapping.
 */

static uint64_t aspeed_soc_io_read(void *p, hwaddr offset, unsigned size)
{
    qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n",
                  __func__, offset, size);
    return 0;
}

static void aspeed_soc_io_write(void *opaque, hwaddr offset, uint64_t value,
                unsigned size)
{
    qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]\n",
                  __func__, offset, value, size);
}

static const MemoryRegionOps aspeed_soc_io_ops = {
    .read = aspeed_soc_io_read,
    .write = aspeed_soc_io_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static void aspeed_soc_init(Object *obj)
{
    AspeedSoCState *s = ASPEED_SOC(obj);
@@ -199,10 +175,8 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
    Error *err = NULL, *local_err = NULL;

    /* IO space */
    memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL,
            "aspeed_soc.io", ASPEED_SOC_IOMEM_SIZE);
    memory_region_add_subregion_overlap(get_system_memory(),
                                        ASPEED_SOC_IOMEM_BASE, &s->iomem, -1);
    create_unimplemented_device("aspeed_soc.io",
                                ASPEED_SOC_IOMEM_BASE, ASPEED_SOC_IOMEM_SIZE);

    /* CPU */
    object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
@@ -257,7 +231,8 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
    /* UART - attach an 8250 to the IO space as our UART5 */
    if (serial_hds[0]) {
        qemu_irq uart5 = qdev_get_gpio_in(DEVICE(&s->vic), uart_irqs[4]);
        serial_mm_init(&s->iomem, ASPEED_SOC_UART_5_BASE, 2,
        serial_mm_init(get_system_memory(),
                       ASPEED_SOC_IOMEM_BASE + ASPEED_SOC_UART_5_BASE, 2,
                       uart5, 38400, serial_hds[0], DEVICE_LITTLE_ENDIAN);
    }

+9 −8
Original line number Diff line number Diff line
@@ -26,14 +26,6 @@
static void bcm2836_init(Object *obj)
{
    BCM2836State *s = BCM2836(obj);
    int n;

    for (n = 0; n < BCM2836_NCPUS; n++) {
        object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
                          "cortex-a15-" TYPE_ARM_CPU);
        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);
@@ -59,6 +51,14 @@ static void bcm2836_realize(DeviceState *dev, Error **errp)

    /* 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",
@@ -150,6 +150,7 @@ 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_END_OF_LIST()
};
+24 −10
Original line number Diff line number Diff line
@@ -5,6 +5,9 @@
 * Rasperry Pi 2 emulation Copyright (c) 2015, Microsoft
 * Written by Andrew Baumann
 *
 * Raspberry Pi 3 emulation Copyright (c) 2018 Zoltán Baldaszti
 * Upstream code cleanup (c) 2018 Pekka Enberg
 *
 * This code is licensed under the GNU GPLv2 and later.
 */

@@ -22,10 +25,11 @@
#define SMPBOOT_ADDR    0x300 /* this should leave enough space for ATAGS */
#define MVBAR_ADDR      0x400 /* secure vectors */
#define BOARDSETUP_ADDR (MVBAR_ADDR + 0x20) /* board setup code */
#define FIRMWARE_ADDR   0x8000 /* Pi loads kernel.img here by default */
#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 */

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

typedef struct RasPiState {
    BCM2836State soc;
@@ -83,8 +87,8 @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
    binfo.secure_board_setup = true;
    binfo.secure_boot = true;

    /* Pi2 requires SMP setup */
    if (version == 2) {
    /* Pi2 and Pi3 requires SMP setup */
    if (version >= 2) {
        binfo.smp_loader_start = SMPBOOT_ADDR;
        binfo.write_secondary_boot = write_smpboot;
        binfo.secondary_cpu_reset_hook = reset_secondary;
@@ -94,15 +98,16 @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
     * the normal Linux boot process
     */
    if (machine->firmware) {
        hwaddr firmware_addr = version == 3 ? FIRMWARE_ADDR_3 : FIRMWARE_ADDR_2;
        /* load the firmware image (typically kernel.img) */
        r = load_image_targphys(machine->firmware, FIRMWARE_ADDR,
                                ram_size - FIRMWARE_ADDR);
        r = load_image_targphys(machine->firmware, firmware_addr,
                                ram_size - firmware_addr);
        if (r < 0) {
            error_report("Failed to load firmware from %s", machine->firmware);
            exit(1);
        }

        binfo.entry = FIRMWARE_ADDR;
        binfo.entry = firmware_addr;
        binfo.firmware_loaded = true;
    } else {
        binfo.kernel_filename = machine->kernel_filename;
@@ -113,7 +118,7 @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
    arm_load_kernel(ARM_CPU(first_cpu), &binfo);
}

static void raspi2_init(MachineState *machine)
static void raspi_init(MachineState *machine, int version)
{
    RasPiState *s = g_new0(RasPiState, 1);
    uint32_t vcram_size;
@@ -135,9 +140,12 @@ static void raspi2_init(MachineState *machine)
    /* 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);
    object_property_set_int(OBJECT(&s->soc), 0xa21041, "board-rev",
    int board_rev = version == 3 ? 0xa02082 : 0xa21041;
    object_property_set_int(OBJECT(&s->soc), board_rev, "board-rev",
                            &error_abort);
    object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort);

@@ -155,7 +163,12 @@ static void raspi2_init(MachineState *machine)

    vcram_size = object_property_get_uint(OBJECT(&s->soc), "vcram-size",
                                          &error_abort);
    setup_boot(machine, 2, machine->ram_size - vcram_size);
    setup_boot(machine, version, machine->ram_size - vcram_size);
}

static void raspi2_init(MachineState *machine)
{
    raspi_init(machine, 2);
}

static void raspi2_machine_init(MachineClass *mc)
@@ -166,6 +179,7 @@ static void raspi2_machine_init(MachineClass *mc)
    mc->no_parallel = 1;
    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;
+73 −25
Original line number Diff line number Diff line
@@ -776,6 +776,14 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
    switch (offset) {
    case 4: /* Interrupt Control Type.  */
        return ((s->num_irq - NVIC_FIRST_IRQ) / 32) - 1;
    case 0xc: /* CPPWR */
        if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
            goto bad_offset;
        }
        /* We make the IMPDEF choice that nothing can ever go into a
         * non-retentive power state, which allows us to RAZ/WI this.
         */
        return 0;
    case 0x380 ... 0x3bf: /* NVIC_ITNS<n> */
    {
        int startvec = 8 * (offset - 0x380) + NVIC_FIRST_IRQ;
@@ -830,8 +838,8 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
            }
        }
        /* NMIPENDSET */
        if ((cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK) &&
            s->vectors[ARMV7M_EXCP_NMI].pending) {
        if ((attrs.secure || (cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK))
            && s->vectors[ARMV7M_EXCP_NMI].pending) {
            val |= (1 << 31);
        }
        /* ISRPREEMPT: RES0 when halting debug not implemented */
@@ -855,8 +863,7 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
        }
        return val;
    case 0xd10: /* System Control.  */
        /* TODO: Implement SLEEPONEXIT.  */
        return 0;
        return cpu->env.v7m.scr[attrs.secure];
    case 0xd14: /* Configuration Control.  */
        /* The BFHFNMIGN bit is the only non-banked bit; we
         * keep it in the non-secure copy of the register.
@@ -990,31 +997,44 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
                      "Aux Fault status registers unimplemented\n");
        return 0;
    case 0xd40: /* PFR0.  */
        return 0x00000030;
    case 0xd44: /* PRF1.  */
        return 0x00000200;
        return cpu->id_pfr0;
    case 0xd44: /* PFR1.  */
        return cpu->id_pfr1;
    case 0xd48: /* DFR0.  */
        return 0x00100000;
        return cpu->id_dfr0;
    case 0xd4c: /* AFR0.  */
        return 0x00000000;
        return cpu->id_afr0;
    case 0xd50: /* MMFR0.  */
        return 0x00000030;
        return cpu->id_mmfr0;
    case 0xd54: /* MMFR1.  */
        return 0x00000000;
        return cpu->id_mmfr1;
    case 0xd58: /* MMFR2.  */
        return 0x00000000;
        return cpu->id_mmfr2;
    case 0xd5c: /* MMFR3.  */
        return 0x00000000;
        return cpu->id_mmfr3;
    case 0xd60: /* ISAR0.  */
        return 0x01141110;
        return cpu->id_isar0;
    case 0xd64: /* ISAR1.  */
        return 0x02111000;
        return cpu->id_isar1;
    case 0xd68: /* ISAR2.  */
        return 0x21112231;
        return cpu->id_isar2;
    case 0xd6c: /* ISAR3.  */
        return 0x01111110;
        return cpu->id_isar3;
    case 0xd70: /* ISAR4.  */
        return 0x01310102;
        return cpu->id_isar4;
    case 0xd74: /* ISAR5.  */
        return cpu->id_isar5;
    case 0xd78: /* CLIDR */
        return cpu->clidr;
    case 0xd7c: /* CTR */
        return cpu->ctr;
    case 0xd80: /* CSSIDR */
    {
        int idx = cpu->env.v7m.csselr[attrs.secure] & R_V7M_CSSELR_INDEX_MASK;
        return cpu->ccsidr[idx];
    }
    case 0xd84: /* CSSELR */
        return cpu->env.v7m.csselr[attrs.secure];
    /* TODO: Implement debug registers.  */
    case 0xd90: /* MPU_TYPE */
        /* Unified MPU; if the MPU is not present this value is zero */
@@ -1173,6 +1193,12 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
    ARMCPU *cpu = s->cpu;

    switch (offset) {
    case 0xc: /* CPPWR */
        if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
            goto bad_offset;
        }
        /* Make the IMPDEF choice to RAZ/WI this. */
        break;
    case 0x380 ... 0x3bf: /* NVIC_ITNS<n> */
    {
        int startvec = 8 * (offset - 0x380) + NVIC_FIRST_IRQ;
@@ -1191,7 +1217,7 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
        break;
    }
    case 0xd04: /* Interrupt Control State (ICSR) */
        if (cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK) {
        if (attrs.secure || cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK) {
            if (value & (1 << 31)) {
                armv7m_nvic_set_pending(s, ARMV7M_EXCP_NMI, false);
            } else if (value & (1 << 30) &&
@@ -1258,8 +1284,13 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
        }
        break;
    case 0xd10: /* System Control.  */
        /* TODO: Implement control registers.  */
        qemu_log_mask(LOG_UNIMP, "NVIC: SCR unimplemented\n");
        /* We don't implement deep-sleep so these bits are RAZ/WI.
         * The other bits in the register are banked.
         * QEMU's implementation ignores SEVONPEND and SLEEPONEXIT, which
         * is architecturally permitted.
         */
        value &= ~(R_V7M_SCR_SLEEPDEEP_MASK | R_V7M_SCR_SLEEPDEEPS_MASK);
        cpu->env.v7m.scr[attrs.secure] = value;
        break;
    case 0xd14: /* Configuration Control.  */
        /* Enforce RAZ/WI on reserved and must-RAZ/WI bits */
@@ -1369,6 +1400,11 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
        qemu_log_mask(LOG_UNIMP,
                      "NVIC: Aux fault status registers unimplemented\n");
        break;
    case 0xd84: /* CSSELR */
        if (!arm_v7m_csselr_razwi(cpu)) {
            cpu->env.v7m.csselr[attrs.secure] = value & R_V7M_CSSELR_INDEX_MASK;
        }
        break;
    case 0xd90: /* MPU_TYPE */
        return; /* RO */
    case 0xd94: /* MPU_CTRL */
@@ -1592,6 +1628,18 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
        }
        break;
    }
    case 0xf50: /* ICIALLU */
    case 0xf58: /* ICIMVAU */
    case 0xf5c: /* DCIMVAC */
    case 0xf60: /* DCISW */
    case 0xf64: /* DCCMVAU */
    case 0xf68: /* DCCMVAC */
    case 0xf6c: /* DCCSW */
    case 0xf70: /* DCCIMVAC */
    case 0xf74: /* DCCISW */
    case 0xf78: /* BPIALL */
        /* Cache and branch predictor maintenance: for QEMU these always NOP */
        break;
    default:
    bad_offset:
        qemu_log_mask(LOG_GUEST_ERROR,
@@ -1676,7 +1724,7 @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
        /* fall through */
    case 0x180 ... 0x1bf: /* NVIC Clear enable */
        val = 0;
        startvec = offset - 0x180 + NVIC_FIRST_IRQ; /* vector # */
        startvec = 8 * (offset - 0x180) + NVIC_FIRST_IRQ; /* vector # */

        for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
            if (s->vectors[startvec + i].enabled &&
@@ -1690,7 +1738,7 @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
        /* fall through */
    case 0x280 ... 0x2bf: /* NVIC Clear pend */
        val = 0;
        startvec = offset - 0x280 + NVIC_FIRST_IRQ; /* vector # */
        startvec = 8 * (offset - 0x280) + NVIC_FIRST_IRQ; /* vector # */
        for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
            if (s->vectors[startvec + i].pending &&
                (attrs.secure || s->itns[startvec + i])) {
@@ -1700,7 +1748,7 @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
        break;
    case 0x300 ... 0x33f: /* NVIC Active */
        val = 0;
        startvec = offset - 0x300 + NVIC_FIRST_IRQ; /* vector # */
        startvec = 8 * (offset - 0x300) + NVIC_FIRST_IRQ; /* vector # */

        for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
            if (s->vectors[startvec + i].active &&
@@ -1815,7 +1863,7 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
    case 0x300 ... 0x33f: /* NVIC Active */
        return MEMTX_OK; /* R/O */
    case 0x400 ... 0x5ef: /* NVIC Priority */
        startvec = 8 * (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */
        startvec = (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */

        for (i = 0; i < size && startvec + i < s->num_irq; i++) {
            if (attrs.secure || s->itns[startvec + i]) {
+0 −1
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ typedef struct AspeedSoCState {

    /*< public >*/
    ARMCPU cpu;
    MemoryRegion iomem;
    MemoryRegion sram;
    AspeedVICState vic;
    AspeedTimerCtrlState timerctrl;
Loading