cpu.c 31.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * QEMU ARM CPU
 *
 * Copyright (c) 2012 SUSE LINUX Products GmbH
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see
 * <http://www.gnu.org/licenses/gpl-2.0.html>
 */

21
#include "cpu.h"
22
#include "qemu-common.h"
23
#include "hw/qdev-properties.h"
24 25 26
#if !defined(CONFIG_USER_ONLY)
#include "hw/loader.h"
#endif
27
#include "hw/arm/arm.h"
28
#include "sysemu/sysemu.h"
29
#include "sysemu/kvm.h"
30

31 32 33 34 35 36 37
static void arm_cpu_set_pc(CPUState *cs, vaddr value)
{
    ARMCPU *cpu = ARM_CPU(cs);

    cpu->env.regs[15] = value;
}

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
{
    /* Reset a single ARMCPRegInfo register */
    ARMCPRegInfo *ri = value;
    ARMCPU *cpu = opaque;

    if (ri->type & ARM_CP_SPECIAL) {
        return;
    }

    if (ri->resetfn) {
        ri->resetfn(&cpu->env, ri);
        return;
    }

    /* A zero offset is never possible as it would be regs[0]
     * so we use it to indicate that reset is being handled elsewhere.
     * This is basically only used for fields in non-core coprocessors
     * (like the pxa2xx ones).
     */
    if (!ri->fieldoffset) {
        return;
    }

    if (ri->type & ARM_CP_64BIT) {
        CPREG_FIELD64(&cpu->env, ri) = ri->resetvalue;
    } else {
        CPREG_FIELD32(&cpu->env, ri) = ri->resetvalue;
    }
}

69 70 71 72 73
/* CPUClass::reset() */
static void arm_cpu_reset(CPUState *s)
{
    ARMCPU *cpu = ARM_CPU(s);
    ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu);
74 75
    CPUARMState *env = &cpu->env;

76 77
    acc->parent_reset(s);

78
    memset(env, 0, offsetof(CPUARMState, breakpoints));
79
    g_hash_table_foreach(cpu->cp_regs, cp_reg_reset, cpu);
80 81 82 83 84 85 86 87
    env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid;
    env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0;
    env->vfp.xregs[ARM_VFP_MVFR1] = cpu->mvfr1;

    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
        env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
    }

88 89 90 91 92
    if (arm_feature(env, ARM_FEATURE_AARCH64)) {
        /* 64 bit CPUs always start in 64 bit mode */
        env->aarch64 = 1;
    }

93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
#if defined(CONFIG_USER_ONLY)
    env->uncached_cpsr = ARM_CPU_MODE_USR;
    /* For user mode we must enable access to coprocessors */
    env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
        env->cp15.c15_cpar = 3;
    } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
        env->cp15.c15_cpar = 1;
    }
#else
    /* SVC mode with interrupts disabled.  */
    env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
    /* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is
       clear at reset.  Initial SP and PC are loaded from ROM.  */
    if (IS_M(env)) {
        uint32_t pc;
        uint8_t *rom;
        env->uncached_cpsr &= ~CPSR_I;
        rom = rom_ptr(0);
        if (rom) {
            /* We should really use ldl_phys here, in case the guest
               modified flash and reset itself.  However images
               loaded via -kernel have not been copied yet, so load the
               values directly from there.  */
117
            env->regs[13] = ldl_p(rom) & 0xFFFFFFFC;
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
            pc = ldl_p(rom + 4);
            env->thumb = pc & 1;
            env->regs[15] = pc & ~1;
        }
    }
    env->vfp.xregs[ARM_VFP_FPEXC] = 0;
#endif
    set_flush_to_zero(1, &env->vfp.standard_fp_status);
    set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
    set_default_nan_mode(1, &env->vfp.standard_fp_status);
    set_float_detect_tininess(float_tininess_before_rounding,
                              &env->vfp.fp_status);
    set_float_detect_tininess(float_tininess_before_rounding,
                              &env->vfp.standard_fp_status);
    tlb_flush(env, 1);
    /* Reset is a state change for some CPUARMState fields which we
     * bake assumptions about into translated code, so we need to
     * tb_flush().
     */
    tb_flush(env);
138 139
}

140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
#ifndef CONFIG_USER_ONLY
static void arm_cpu_set_irq(void *opaque, int irq, int level)
{
    ARMCPU *cpu = opaque;
    CPUState *cs = CPU(cpu);

    switch (irq) {
    case ARM_CPU_IRQ:
        if (level) {
            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
        } else {
            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
        }
        break;
    case ARM_CPU_FIQ:
        if (level) {
            cpu_interrupt(cs, CPU_INTERRUPT_FIQ);
        } else {
            cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
        }
        break;
    default:
        hw_error("arm_cpu_set_irq: Bad interrupt line %d\n", irq);
    }
}

static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
{
#ifdef CONFIG_KVM
    ARMCPU *cpu = opaque;
    CPUState *cs = CPU(cpu);
    int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT;

    switch (irq) {
    case ARM_CPU_IRQ:
        kvm_irq |= KVM_ARM_IRQ_CPU_IRQ;
        break;
    case ARM_CPU_FIQ:
        kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
        break;
    default:
        hw_error("arm_cpu_kvm_set_irq: Bad interrupt line %d\n", irq);
    }
    kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT;
    kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0);
#endif
}
#endif

189 190
static inline void set_feature(CPUARMState *env, int feature)
{
191
    env->features |= 1ULL << feature;
192 193
}

194 195
static void arm_cpu_initfn(Object *obj)
{
196
    CPUState *cs = CPU(obj);
197
    ARMCPU *cpu = ARM_CPU(obj);
198
    static bool inited;
199

200
    cs->env_ptr = &cpu->env;
201
    cpu_exec_init(&cpu->env);
202 203
    cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal,
                                         g_free, g_free);
204

205 206 207 208 209 210 211
#ifndef CONFIG_USER_ONLY
    /* Our inbound IRQ and FIQ lines */
    if (kvm_enabled()) {
        qdev_init_gpio_in(DEVICE(cpu), arm_cpu_kvm_set_irq, 2);
    } else {
        qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 2);
    }
212

213
    cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
214
                                                arm_gt_ptimer_cb, cpu);
215
    cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
216 217 218
                                                arm_gt_vtimer_cb, cpu);
    qdev_init_gpio_out(DEVICE(cpu), cpu->gt_timer_outputs,
                       ARRAY_SIZE(cpu->gt_timer_outputs));
219 220
#endif

221 222 223 224 225 226
    /* DTB consumers generally don't in fact care what the 'compatible'
     * string is, so always provide some string and trust that a hypothetical
     * picky DTB consumer will also provide a helpful error message.
     */
    cpu->dtb_compatible = "qemu,unknown";

227 228 229 230
    if (tcg_enabled() && !inited) {
        inited = true;
        arm_translate_init();
    }
231 232 233 234 235 236
}

static void arm_cpu_finalizefn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
    g_hash_table_destroy(cpu->cp_regs);
237 238
}

239
static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
240
{
241
    CPUState *cs = CPU(dev);
242 243
    ARMCPU *cpu = ARM_CPU(dev);
    ARMCPUClass *acc = ARM_CPU_GET_CLASS(dev);
244
    CPUARMState *env = &cpu->env;
245

246
    /* Some features automatically imply others: */
247 248 249 250 251
    if (arm_feature(env, ARM_FEATURE_V8)) {
        set_feature(env, ARM_FEATURE_V7);
        set_feature(env, ARM_FEATURE_ARM_DIV);
        set_feature(env, ARM_FEATURE_LPAE);
    }
252 253 254
    if (arm_feature(env, ARM_FEATURE_V7)) {
        set_feature(env, ARM_FEATURE_VAPA);
        set_feature(env, ARM_FEATURE_THUMB2);
P
Peter Maydell 已提交
255
        set_feature(env, ARM_FEATURE_MPIDR);
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
        if (!arm_feature(env, ARM_FEATURE_M)) {
            set_feature(env, ARM_FEATURE_V6K);
        } else {
            set_feature(env, ARM_FEATURE_V6);
        }
    }
    if (arm_feature(env, ARM_FEATURE_V6K)) {
        set_feature(env, ARM_FEATURE_V6);
        set_feature(env, ARM_FEATURE_MVFR);
    }
    if (arm_feature(env, ARM_FEATURE_V6)) {
        set_feature(env, ARM_FEATURE_V5);
        if (!arm_feature(env, ARM_FEATURE_M)) {
            set_feature(env, ARM_FEATURE_AUXCR);
        }
    }
    if (arm_feature(env, ARM_FEATURE_V5)) {
        set_feature(env, ARM_FEATURE_V4T);
    }
    if (arm_feature(env, ARM_FEATURE_M)) {
        set_feature(env, ARM_FEATURE_THUMB_DIV);
    }
    if (arm_feature(env, ARM_FEATURE_ARM_DIV)) {
        set_feature(env, ARM_FEATURE_THUMB_DIV);
    }
    if (arm_feature(env, ARM_FEATURE_VFP4)) {
        set_feature(env, ARM_FEATURE_VFP3);
    }
    if (arm_feature(env, ARM_FEATURE_VFP3)) {
        set_feature(env, ARM_FEATURE_VFP);
    }
287
    if (arm_feature(env, ARM_FEATURE_LPAE)) {
288
        set_feature(env, ARM_FEATURE_V7MP);
289 290
        set_feature(env, ARM_FEATURE_PXN);
    }
291 292

    register_cp_regs_for_features(cpu);
293 294
    arm_cpu_register_gdb_regs_for_features(cpu);

295 296
    init_cpreg_list(cpu);

297 298
    cpu_reset(cs);
    qemu_init_vcpu(cs);
299 300

    acc->parent_realize(dev, errp);
301 302
}

303 304 305
static ObjectClass *arm_cpu_class_by_name(const char *cpu_model)
{
    ObjectClass *oc;
A
Andreas Färber 已提交
306
    char *typename;
307 308 309 310 311

    if (!cpu_model) {
        return NULL;
    }

A
Andreas Färber 已提交
312 313 314
    typename = g_strdup_printf("%s-" TYPE_ARM_CPU, cpu_model);
    oc = object_class_by_name(typename);
    g_free(typename);
315 316
    if (!oc || !object_class_dynamic_cast(oc, TYPE_ARM_CPU) ||
        object_class_is_abstract(oc)) {
317 318 319 320 321
        return NULL;
    }
    return oc;
}

322 323 324
/* CPU models. These are not needed for the AArch64 linux-user build. */
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)

325 326 327
static void arm926_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
328 329

    cpu->dtb_compatible = "arm,arm926";
330 331
    set_feature(&cpu->env, ARM_FEATURE_V5);
    set_feature(&cpu->env, ARM_FEATURE_VFP);
332 333
    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
    set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN);
334
    cpu->midr = 0x41069265;
335
    cpu->reset_fpsid = 0x41011090;
336
    cpu->ctr = 0x1dd20d2;
337
    cpu->reset_sctlr = 0x00090078;
338 339 340 341 342
}

static void arm946_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
343 344

    cpu->dtb_compatible = "arm,arm946";
345 346
    set_feature(&cpu->env, ARM_FEATURE_V5);
    set_feature(&cpu->env, ARM_FEATURE_MPU);
347
    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
348
    cpu->midr = 0x41059461;
349
    cpu->ctr = 0x0f004006;
350
    cpu->reset_sctlr = 0x00000078;
351 352 353 354 355
}

static void arm1026_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
356 357

    cpu->dtb_compatible = "arm,arm1026";
358 359 360
    set_feature(&cpu->env, ARM_FEATURE_V5);
    set_feature(&cpu->env, ARM_FEATURE_VFP);
    set_feature(&cpu->env, ARM_FEATURE_AUXCR);
361 362
    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
    set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN);
363
    cpu->midr = 0x4106a262;
364
    cpu->reset_fpsid = 0x410110a0;
365
    cpu->ctr = 0x1dd20d2;
366
    cpu->reset_sctlr = 0x00090078;
367
    cpu->reset_auxcr = 1;
368 369 370 371 372 373 374 375 376 377
    {
        /* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */
        ARMCPRegInfo ifar = {
            .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1,
            .access = PL1_RW,
            .fieldoffset = offsetof(CPUARMState, cp15.c6_insn),
            .resetvalue = 0
        };
        define_one_arm_cp_reg(cpu, &ifar);
    }
378 379 380 381 382
}

static void arm1136_r2_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
383 384 385 386 387 388 389
    /* What qemu calls "arm1136_r2" is actually the 1136 r0p2, ie an
     * older core than plain "arm1136". In particular this does not
     * have the v6K features.
     * These ID register values are correct for 1136 but may be wrong
     * for 1136_r2 (in particular r0p2 does not actually implement most
     * of the ID registers).
     */
390 391

    cpu->dtb_compatible = "arm,arm1136";
392 393
    set_feature(&cpu->env, ARM_FEATURE_V6);
    set_feature(&cpu->env, ARM_FEATURE_VFP);
394 395 396
    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
    set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG);
    set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS);
397
    cpu->midr = 0x4107b362;
398
    cpu->reset_fpsid = 0x410120b4;
399 400
    cpu->mvfr0 = 0x11111111;
    cpu->mvfr1 = 0x00000000;
401
    cpu->ctr = 0x1dd20d2;
402
    cpu->reset_sctlr = 0x00050078;
403 404 405 406 407 408 409 410 411 412 413 414
    cpu->id_pfr0 = 0x111;
    cpu->id_pfr1 = 0x1;
    cpu->id_dfr0 = 0x2;
    cpu->id_afr0 = 0x3;
    cpu->id_mmfr0 = 0x01130003;
    cpu->id_mmfr1 = 0x10030302;
    cpu->id_mmfr2 = 0x01222110;
    cpu->id_isar0 = 0x00140011;
    cpu->id_isar1 = 0x12002111;
    cpu->id_isar2 = 0x11231111;
    cpu->id_isar3 = 0x01102131;
    cpu->id_isar4 = 0x141;
415
    cpu->reset_auxcr = 7;
416 417 418 419 420
}

static void arm1136_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
421 422

    cpu->dtb_compatible = "arm,arm1136";
423 424 425
    set_feature(&cpu->env, ARM_FEATURE_V6K);
    set_feature(&cpu->env, ARM_FEATURE_V6);
    set_feature(&cpu->env, ARM_FEATURE_VFP);
426 427 428
    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
    set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG);
    set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS);
429
    cpu->midr = 0x4117b363;
430
    cpu->reset_fpsid = 0x410120b4;
431 432
    cpu->mvfr0 = 0x11111111;
    cpu->mvfr1 = 0x00000000;
433
    cpu->ctr = 0x1dd20d2;
434
    cpu->reset_sctlr = 0x00050078;
435 436 437 438 439 440 441 442 443 444 445 446
    cpu->id_pfr0 = 0x111;
    cpu->id_pfr1 = 0x1;
    cpu->id_dfr0 = 0x2;
    cpu->id_afr0 = 0x3;
    cpu->id_mmfr0 = 0x01130003;
    cpu->id_mmfr1 = 0x10030302;
    cpu->id_mmfr2 = 0x01222110;
    cpu->id_isar0 = 0x00140011;
    cpu->id_isar1 = 0x12002111;
    cpu->id_isar2 = 0x11231111;
    cpu->id_isar3 = 0x01102131;
    cpu->id_isar4 = 0x141;
447
    cpu->reset_auxcr = 7;
448 449 450 451 452
}

static void arm1176_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
453 454

    cpu->dtb_compatible = "arm,arm1176";
455 456 457
    set_feature(&cpu->env, ARM_FEATURE_V6K);
    set_feature(&cpu->env, ARM_FEATURE_VFP);
    set_feature(&cpu->env, ARM_FEATURE_VAPA);
458 459 460
    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
    set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG);
    set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS);
461
    cpu->midr = 0x410fb767;
462
    cpu->reset_fpsid = 0x410120b5;
463 464
    cpu->mvfr0 = 0x11111111;
    cpu->mvfr1 = 0x00000000;
465
    cpu->ctr = 0x1dd20d2;
466
    cpu->reset_sctlr = 0x00050078;
467 468 469 470 471 472 473 474 475 476 477 478
    cpu->id_pfr0 = 0x111;
    cpu->id_pfr1 = 0x11;
    cpu->id_dfr0 = 0x33;
    cpu->id_afr0 = 0;
    cpu->id_mmfr0 = 0x01130003;
    cpu->id_mmfr1 = 0x10030302;
    cpu->id_mmfr2 = 0x01222100;
    cpu->id_isar0 = 0x0140011;
    cpu->id_isar1 = 0x12002111;
    cpu->id_isar2 = 0x11231121;
    cpu->id_isar3 = 0x01102131;
    cpu->id_isar4 = 0x01141;
479
    cpu->reset_auxcr = 7;
480 481 482 483 484
}

static void arm11mpcore_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
485 486

    cpu->dtb_compatible = "arm,arm11mpcore";
487 488 489
    set_feature(&cpu->env, ARM_FEATURE_V6K);
    set_feature(&cpu->env, ARM_FEATURE_VFP);
    set_feature(&cpu->env, ARM_FEATURE_VAPA);
P
Peter Maydell 已提交
490
    set_feature(&cpu->env, ARM_FEATURE_MPIDR);
491
    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
492
    cpu->midr = 0x410fb022;
493
    cpu->reset_fpsid = 0x410120b4;
494 495
    cpu->mvfr0 = 0x11111111;
    cpu->mvfr1 = 0x00000000;
496
    cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */
497 498 499 500 501 502 503 504 505 506 507 508
    cpu->id_pfr0 = 0x111;
    cpu->id_pfr1 = 0x1;
    cpu->id_dfr0 = 0;
    cpu->id_afr0 = 0x2;
    cpu->id_mmfr0 = 0x01100103;
    cpu->id_mmfr1 = 0x10020302;
    cpu->id_mmfr2 = 0x01222000;
    cpu->id_isar0 = 0x00100011;
    cpu->id_isar1 = 0x12002111;
    cpu->id_isar2 = 0x11221011;
    cpu->id_isar3 = 0x01102131;
    cpu->id_isar4 = 0x141;
509
    cpu->reset_auxcr = 1;
510 511 512 513 514
}

static void cortex_m3_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
515 516
    set_feature(&cpu->env, ARM_FEATURE_V7);
    set_feature(&cpu->env, ARM_FEATURE_M);
517
    cpu->midr = 0x410fc231;
518 519
}

520 521 522 523 524 525 526 527 528
static void arm_v7m_class_init(ObjectClass *oc, void *data)
{
#ifndef CONFIG_USER_ONLY
    CPUClass *cc = CPU_CLASS(oc);

    cc->do_interrupt = arm_v7m_cpu_do_interrupt;
#endif
}

529 530 531 532 533 534 535 536
static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
    { .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
    { .name = "L2AUXCR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
    REGINFO_SENTINEL
};

537 538 539
static void cortex_a8_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
540 541

    cpu->dtb_compatible = "arm,cortex-a8";
542 543 544 545
    set_feature(&cpu->env, ARM_FEATURE_V7);
    set_feature(&cpu->env, ARM_FEATURE_VFP3);
    set_feature(&cpu->env, ARM_FEATURE_NEON);
    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
546
    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
547
    cpu->midr = 0x410fc080;
548
    cpu->reset_fpsid = 0x410330c0;
549 550
    cpu->mvfr0 = 0x11110222;
    cpu->mvfr1 = 0x00011100;
551
    cpu->ctr = 0x82048004;
552
    cpu->reset_sctlr = 0x00c50078;
553 554 555 556 557 558 559 560 561 562 563 564 565
    cpu->id_pfr0 = 0x1031;
    cpu->id_pfr1 = 0x11;
    cpu->id_dfr0 = 0x400;
    cpu->id_afr0 = 0;
    cpu->id_mmfr0 = 0x31100003;
    cpu->id_mmfr1 = 0x20000000;
    cpu->id_mmfr2 = 0x01202000;
    cpu->id_mmfr3 = 0x11;
    cpu->id_isar0 = 0x00101111;
    cpu->id_isar1 = 0x12112111;
    cpu->id_isar2 = 0x21232031;
    cpu->id_isar3 = 0x11112131;
    cpu->id_isar4 = 0x00111142;
566 567 568 569
    cpu->clidr = (1 << 27) | (2 << 24) | 3;
    cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
    cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
    cpu->ccsidr[2] = 0xf0000000; /* No L2 icache. */
570
    cpu->reset_auxcr = 2;
571
    define_arm_cp_regs(cpu, cortexa8_cp_reginfo);
572 573
}

574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
    /* power_control should be set to maximum latency. Again,
     * default to 0 and set by private hook
     */
    { .name = "A9_PWRCTL", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
      .access = PL1_RW, .resetvalue = 0,
      .fieldoffset = offsetof(CPUARMState, cp15.c15_power_control) },
    { .name = "A9_DIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 1,
      .access = PL1_RW, .resetvalue = 0,
      .fieldoffset = offsetof(CPUARMState, cp15.c15_diagnostic) },
    { .name = "A9_PWRDIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 2,
      .access = PL1_RW, .resetvalue = 0,
      .fieldoffset = offsetof(CPUARMState, cp15.c15_power_diagnostic) },
    { .name = "NEONBUSY", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
    /* TLB lockdown control */
    { .name = "TLB_LOCKR", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 2,
      .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
    { .name = "TLB_LOCKW", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 4,
      .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
    { .name = "TLB_VA", .cp = 15, .crn = 15, .crm = 5, .opc1 = 5, .opc2 = 2,
      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
    { .name = "TLB_PA", .cp = 15, .crn = 15, .crm = 6, .opc1 = 5, .opc2 = 2,
      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
    { .name = "TLB_ATTR", .cp = 15, .crn = 15, .crm = 7, .opc1 = 5, .opc2 = 2,
      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
    REGINFO_SENTINEL
};

603 604 605
static void cortex_a9_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
606 607

    cpu->dtb_compatible = "arm,cortex-a9";
608 609 610 611 612 613 614 615 616 617
    set_feature(&cpu->env, ARM_FEATURE_V7);
    set_feature(&cpu->env, ARM_FEATURE_VFP3);
    set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
    set_feature(&cpu->env, ARM_FEATURE_NEON);
    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
    /* Note that A9 supports the MP extensions even for
     * A9UP and single-core A9MP (which are both different
     * and valid configurations; we don't model A9UP).
     */
    set_feature(&cpu->env, ARM_FEATURE_V7MP);
618
    cpu->midr = 0x410fc090;
619
    cpu->reset_fpsid = 0x41033090;
620 621
    cpu->mvfr0 = 0x11110222;
    cpu->mvfr1 = 0x01111111;
622
    cpu->ctr = 0x80038003;
623
    cpu->reset_sctlr = 0x00c50078;
624 625 626 627 628 629 630 631 632 633 634 635 636
    cpu->id_pfr0 = 0x1031;
    cpu->id_pfr1 = 0x11;
    cpu->id_dfr0 = 0x000;
    cpu->id_afr0 = 0;
    cpu->id_mmfr0 = 0x00100103;
    cpu->id_mmfr1 = 0x20000000;
    cpu->id_mmfr2 = 0x01230000;
    cpu->id_mmfr3 = 0x00002111;
    cpu->id_isar0 = 0x00101111;
    cpu->id_isar1 = 0x13112111;
    cpu->id_isar2 = 0x21232041;
    cpu->id_isar3 = 0x11112131;
    cpu->id_isar4 = 0x00111142;
637 638 639
    cpu->clidr = (1 << 27) | (1 << 24) | 3;
    cpu->ccsidr[0] = 0xe00fe015; /* 16k L1 dcache. */
    cpu->ccsidr[1] = 0x200fe015; /* 16k L1 icache. */
640 641 642 643 644 645 646 647 648
    {
        ARMCPRegInfo cbar = {
            .name = "CBAR", .cp = 15, .crn = 15,  .crm = 0, .opc1 = 4,
            .opc2 = 0, .access = PL1_R|PL3_W, .resetvalue = cpu->reset_cbar,
            .fieldoffset = offsetof(CPUARMState, cp15.c15_config_base_address)
        };
        define_one_arm_cp_reg(cpu, &cbar);
        define_arm_cp_regs(cpu, cortexa9_cp_reginfo);
    }
649 650
}

651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
#ifndef CONFIG_USER_ONLY
static int a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri,
                           uint64_t *value)
{
    /* Linux wants the number of processors from here.
     * Might as well set the interrupt-controller bit too.
     */
    *value = ((smp_cpus - 1) << 24) | (1 << 23);
    return 0;
}
#endif

static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
#ifndef CONFIG_USER_ONLY
    { .name = "L2CTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
      .access = PL1_RW, .resetvalue = 0, .readfn = a15_l2ctlr_read,
      .writefn = arm_cp_write_ignore, },
#endif
    { .name = "L2ECTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 3,
      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
    REGINFO_SENTINEL
};

674 675 676
static void cortex_a15_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
677 678

    cpu->dtb_compatible = "arm,cortex-a15";
679 680 681 682 683 684 685
    set_feature(&cpu->env, ARM_FEATURE_V7);
    set_feature(&cpu->env, ARM_FEATURE_VFP4);
    set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
    set_feature(&cpu->env, ARM_FEATURE_NEON);
    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
    set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
    set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
686
    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
687
    set_feature(&cpu->env, ARM_FEATURE_LPAE);
688
    cpu->midr = 0x412fc0f1;
689
    cpu->reset_fpsid = 0x410430f0;
690 691
    cpu->mvfr0 = 0x10110222;
    cpu->mvfr1 = 0x11111111;
692
    cpu->ctr = 0x8444c004;
693
    cpu->reset_sctlr = 0x00c50078;
694 695 696 697 698 699 700 701 702 703 704 705 706
    cpu->id_pfr0 = 0x00001131;
    cpu->id_pfr1 = 0x00011011;
    cpu->id_dfr0 = 0x02010555;
    cpu->id_afr0 = 0x00000000;
    cpu->id_mmfr0 = 0x10201105;
    cpu->id_mmfr1 = 0x20000000;
    cpu->id_mmfr2 = 0x01240000;
    cpu->id_mmfr3 = 0x02102211;
    cpu->id_isar0 = 0x02101110;
    cpu->id_isar1 = 0x13112111;
    cpu->id_isar2 = 0x21232041;
    cpu->id_isar3 = 0x11112131;
    cpu->id_isar4 = 0x10011142;
707 708 709 710
    cpu->clidr = 0x0a200023;
    cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
    cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
    cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
711
    define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
712 713 714 715 716
}

static void ti925t_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
717 718
    set_feature(&cpu->env, ARM_FEATURE_V4T);
    set_feature(&cpu->env, ARM_FEATURE_OMAPCP);
719
    cpu->midr = ARM_CPUID_TI925T;
720
    cpu->ctr = 0x5109149;
721
    cpu->reset_sctlr = 0x00000070;
722 723 724 725 726
}

static void sa1100_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
727 728

    cpu->dtb_compatible = "intel,sa1100";
729
    set_feature(&cpu->env, ARM_FEATURE_STRONGARM);
730
    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
731
    cpu->midr = 0x4401A11B;
732
    cpu->reset_sctlr = 0x00000070;
733 734 735 736 737
}

static void sa1110_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
738
    set_feature(&cpu->env, ARM_FEATURE_STRONGARM);
739
    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
740
    cpu->midr = 0x6901B119;
741
    cpu->reset_sctlr = 0x00000070;
742 743 744 745 746
}

static void pxa250_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
747 748

    cpu->dtb_compatible = "marvell,xscale";
749 750
    set_feature(&cpu->env, ARM_FEATURE_V5);
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
751
    cpu->midr = 0x69052100;
752
    cpu->ctr = 0xd172172;
753
    cpu->reset_sctlr = 0x00000078;
754 755 756 757 758
}

static void pxa255_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
759 760

    cpu->dtb_compatible = "marvell,xscale";
761 762
    set_feature(&cpu->env, ARM_FEATURE_V5);
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
763
    cpu->midr = 0x69052d00;
764
    cpu->ctr = 0xd172172;
765
    cpu->reset_sctlr = 0x00000078;
766 767 768 769 770
}

static void pxa260_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
771 772

    cpu->dtb_compatible = "marvell,xscale";
773 774
    set_feature(&cpu->env, ARM_FEATURE_V5);
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
775
    cpu->midr = 0x69052903;
776
    cpu->ctr = 0xd172172;
777
    cpu->reset_sctlr = 0x00000078;
778 779 780 781 782
}

static void pxa261_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
783 784

    cpu->dtb_compatible = "marvell,xscale";
785 786
    set_feature(&cpu->env, ARM_FEATURE_V5);
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
787
    cpu->midr = 0x69052d05;
788
    cpu->ctr = 0xd172172;
789
    cpu->reset_sctlr = 0x00000078;
790 791 792 793 794
}

static void pxa262_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
795 796

    cpu->dtb_compatible = "marvell,xscale";
797 798
    set_feature(&cpu->env, ARM_FEATURE_V5);
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
799
    cpu->midr = 0x69052d06;
800
    cpu->ctr = 0xd172172;
801
    cpu->reset_sctlr = 0x00000078;
802 803 804 805 806
}

static void pxa270a0_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
807 808

    cpu->dtb_compatible = "marvell,xscale";
809 810 811
    set_feature(&cpu->env, ARM_FEATURE_V5);
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
812
    cpu->midr = 0x69054110;
813
    cpu->ctr = 0xd172172;
814
    cpu->reset_sctlr = 0x00000078;
815 816 817 818 819
}

static void pxa270a1_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
820 821

    cpu->dtb_compatible = "marvell,xscale";
822 823 824
    set_feature(&cpu->env, ARM_FEATURE_V5);
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
825
    cpu->midr = 0x69054111;
826
    cpu->ctr = 0xd172172;
827
    cpu->reset_sctlr = 0x00000078;
828 829 830 831 832
}

static void pxa270b0_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
833 834

    cpu->dtb_compatible = "marvell,xscale";
835 836 837
    set_feature(&cpu->env, ARM_FEATURE_V5);
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
838
    cpu->midr = 0x69054112;
839
    cpu->ctr = 0xd172172;
840
    cpu->reset_sctlr = 0x00000078;
841 842 843 844 845
}

static void pxa270b1_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
846 847

    cpu->dtb_compatible = "marvell,xscale";
848 849 850
    set_feature(&cpu->env, ARM_FEATURE_V5);
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
851
    cpu->midr = 0x69054113;
852
    cpu->ctr = 0xd172172;
853
    cpu->reset_sctlr = 0x00000078;
854 855 856 857 858
}

static void pxa270c0_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
859 860

    cpu->dtb_compatible = "marvell,xscale";
861 862 863
    set_feature(&cpu->env, ARM_FEATURE_V5);
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
864
    cpu->midr = 0x69054114;
865
    cpu->ctr = 0xd172172;
866
    cpu->reset_sctlr = 0x00000078;
867 868 869 870 871
}

static void pxa270c5_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
872 873

    cpu->dtb_compatible = "marvell,xscale";
874 875 876
    set_feature(&cpu->env, ARM_FEATURE_V5);
    set_feature(&cpu->env, ARM_FEATURE_XSCALE);
    set_feature(&cpu->env, ARM_FEATURE_IWMMXT);
877
    cpu->midr = 0x69054117;
878
    cpu->ctr = 0xd172172;
879
    cpu->reset_sctlr = 0x00000078;
880 881
}

882
#ifdef CONFIG_USER_ONLY
883 884 885
static void arm_any_initfn(Object *obj)
{
    ARMCPU *cpu = ARM_CPU(obj);
886
    set_feature(&cpu->env, ARM_FEATURE_V8);
887 888 889 890 891 892
    set_feature(&cpu->env, ARM_FEATURE_VFP4);
    set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
    set_feature(&cpu->env, ARM_FEATURE_NEON);
    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
    set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
    set_feature(&cpu->env, ARM_FEATURE_V7MP);
893 894 895
#ifdef TARGET_AARCH64
    set_feature(&cpu->env, ARM_FEATURE_AARCH64);
#endif
896
    cpu->midr = 0xffffffff;
897
}
898
#endif
899

900 901
#endif /* !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) */

902 903 904
typedef struct ARMCPUInfo {
    const char *name;
    void (*initfn)(Object *obj);
905
    void (*class_init)(ObjectClass *oc, void *data);
906 907 908
} ARMCPUInfo;

static const ARMCPUInfo arm_cpus[] = {
909
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
910 911 912 913 914 915 916 917 918 919 920
    { .name = "arm926",      .initfn = arm926_initfn },
    { .name = "arm946",      .initfn = arm946_initfn },
    { .name = "arm1026",     .initfn = arm1026_initfn },
    /* What QEMU calls "arm1136-r2" is actually the 1136 r0p2, i.e. an
     * older core than plain "arm1136". In particular this does not
     * have the v6K features.
     */
    { .name = "arm1136-r2",  .initfn = arm1136_r2_initfn },
    { .name = "arm1136",     .initfn = arm1136_initfn },
    { .name = "arm1176",     .initfn = arm1176_initfn },
    { .name = "arm11mpcore", .initfn = arm11mpcore_initfn },
921 922
    { .name = "cortex-m3",   .initfn = cortex_m3_initfn,
                             .class_init = arm_v7m_class_init },
923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941
    { .name = "cortex-a8",   .initfn = cortex_a8_initfn },
    { .name = "cortex-a9",   .initfn = cortex_a9_initfn },
    { .name = "cortex-a15",  .initfn = cortex_a15_initfn },
    { .name = "ti925t",      .initfn = ti925t_initfn },
    { .name = "sa1100",      .initfn = sa1100_initfn },
    { .name = "sa1110",      .initfn = sa1110_initfn },
    { .name = "pxa250",      .initfn = pxa250_initfn },
    { .name = "pxa255",      .initfn = pxa255_initfn },
    { .name = "pxa260",      .initfn = pxa260_initfn },
    { .name = "pxa261",      .initfn = pxa261_initfn },
    { .name = "pxa262",      .initfn = pxa262_initfn },
    /* "pxa270" is an alias for "pxa270-a0" */
    { .name = "pxa270",      .initfn = pxa270a0_initfn },
    { .name = "pxa270-a0",   .initfn = pxa270a0_initfn },
    { .name = "pxa270-a1",   .initfn = pxa270a1_initfn },
    { .name = "pxa270-b0",   .initfn = pxa270b0_initfn },
    { .name = "pxa270-b1",   .initfn = pxa270b1_initfn },
    { .name = "pxa270-c0",   .initfn = pxa270c0_initfn },
    { .name = "pxa270-c5",   .initfn = pxa270c5_initfn },
942
#ifdef CONFIG_USER_ONLY
943
    { .name = "any",         .initfn = arm_any_initfn },
944
#endif
945
#endif
946 947
};

948 949 950 951 952
static Property arm_cpu_properties[] = {
    DEFINE_PROP_BOOL("start-powered-off", ARMCPU, start_powered_off, false),
    DEFINE_PROP_END_OF_LIST()
};

953 954 955 956
static void arm_cpu_class_init(ObjectClass *oc, void *data)
{
    ARMCPUClass *acc = ARM_CPU_CLASS(oc);
    CPUClass *cc = CPU_CLASS(acc);
957 958 959 960
    DeviceClass *dc = DEVICE_CLASS(oc);

    acc->parent_realize = dc->realize;
    dc->realize = arm_cpu_realizefn;
961
    dc->props = arm_cpu_properties;
962 963 964

    acc->parent_reset = cc->reset;
    cc->reset = arm_cpu_reset;
965 966

    cc->class_by_name = arm_cpu_class_by_name;
967
    cc->do_interrupt = arm_cpu_do_interrupt;
968
    cc->dump_state = arm_cpu_dump_state;
969
    cc->set_pc = arm_cpu_set_pc;
970 971
    cc->gdb_read_register = arm_cpu_gdb_read_register;
    cc->gdb_write_register = arm_cpu_gdb_write_register;
972 973 974 975
#ifndef CONFIG_USER_ONLY
    cc->get_phys_page_debug = arm_cpu_get_phys_page_debug;
    cc->vmsd = &vmstate_arm_cpu;
#endif
976
    cc->gdb_num_core_regs = 26;
977
    cc->gdb_core_xml_file = "arm-core.xml";
978 979
}

980 981 982 983 984 985 986
static void cpu_register(const ARMCPUInfo *info)
{
    TypeInfo type_info = {
        .parent = TYPE_ARM_CPU,
        .instance_size = sizeof(ARMCPU),
        .instance_init = info->initfn,
        .class_size = sizeof(ARMCPUClass),
987
        .class_init = info->class_init,
988 989
    };

A
Andreas Färber 已提交
990
    type_info.name = g_strdup_printf("%s-" TYPE_ARM_CPU, info->name);
991
    type_register(&type_info);
A
Andreas Färber 已提交
992
    g_free((void *)type_info.name);
993 994
}

995 996 997 998
static const TypeInfo arm_cpu_type_info = {
    .name = TYPE_ARM_CPU,
    .parent = TYPE_CPU,
    .instance_size = sizeof(ARMCPU),
999
    .instance_init = arm_cpu_initfn,
1000
    .instance_finalize = arm_cpu_finalizefn,
1001
    .abstract = true,
1002 1003 1004 1005 1006 1007
    .class_size = sizeof(ARMCPUClass),
    .class_init = arm_cpu_class_init,
};

static void arm_cpu_register_types(void)
{
1008 1009
    int i;

1010
    type_register_static(&arm_cpu_type_info);
1011 1012 1013
    for (i = 0; i < ARRAY_SIZE(arm_cpus); i++) {
        cpu_register(&arm_cpus[i]);
    }
1014 1015 1016
}

type_init(arm_cpu_register_types)