qemu/target-unicore32/cpu.c
<<
>>
Prefs
   1/*
   2 * QEMU UniCore32 CPU
   3 *
   4 * Copyright (c) 2010-2012 Guan Xuetao
   5 * Copyright (c) 2012 SUSE LINUX Products GmbH
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 * Contributions from 2012-04-01 on are considered under GPL version 2,
  12 * or (at your option) any later version.
  13 */
  14
  15#include "qemu/osdep.h"
  16#include "qapi/error.h"
  17#include "cpu.h"
  18#include "qemu-common.h"
  19#include "migration/vmstate.h"
  20
  21static void uc32_cpu_set_pc(CPUState *cs, vaddr value)
  22{
  23    UniCore32CPU *cpu = UNICORE32_CPU(cs);
  24
  25    cpu->env.regs[31] = value;
  26}
  27
  28static bool uc32_cpu_has_work(CPUState *cs)
  29{
  30    return cs->interrupt_request &
  31        (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
  32}
  33
  34static inline void set_feature(CPUUniCore32State *env, int feature)
  35{
  36    env->features |= feature;
  37}
  38
  39/* CPU models */
  40
  41static ObjectClass *uc32_cpu_class_by_name(const char *cpu_model)
  42{
  43    ObjectClass *oc;
  44    char *typename;
  45
  46    if (cpu_model == NULL) {
  47        return NULL;
  48    }
  49
  50    typename = g_strdup_printf("%s-" TYPE_UNICORE32_CPU, cpu_model);
  51    oc = object_class_by_name(typename);
  52    g_free(typename);
  53    if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_UNICORE32_CPU) ||
  54                       object_class_is_abstract(oc))) {
  55        oc = NULL;
  56    }
  57    return oc;
  58}
  59
  60typedef struct UniCore32CPUInfo {
  61    const char *name;
  62    void (*instance_init)(Object *obj);
  63} UniCore32CPUInfo;
  64
  65static void unicore_ii_cpu_initfn(Object *obj)
  66{
  67    UniCore32CPU *cpu = UNICORE32_CPU(obj);
  68    CPUUniCore32State *env = &cpu->env;
  69
  70    env->cp0.c0_cpuid = 0x4d000863;
  71    env->cp0.c0_cachetype = 0x0d152152;
  72    env->cp0.c1_sys = 0x2000;
  73    env->cp0.c2_base = 0x0;
  74    env->cp0.c3_faultstatus = 0x0;
  75    env->cp0.c4_faultaddr = 0x0;
  76    env->ucf64.xregs[UC32_UCF64_FPSCR] = 0;
  77
  78    set_feature(env, UC32_HWCAP_CMOV);
  79    set_feature(env, UC32_HWCAP_UCF64);
  80}
  81
  82static void uc32_any_cpu_initfn(Object *obj)
  83{
  84    UniCore32CPU *cpu = UNICORE32_CPU(obj);
  85    CPUUniCore32State *env = &cpu->env;
  86
  87    env->cp0.c0_cpuid = 0xffffffff;
  88    env->ucf64.xregs[UC32_UCF64_FPSCR] = 0;
  89
  90    set_feature(env, UC32_HWCAP_CMOV);
  91    set_feature(env, UC32_HWCAP_UCF64);
  92}
  93
  94static const UniCore32CPUInfo uc32_cpus[] = {
  95    { .name = "UniCore-II", .instance_init = unicore_ii_cpu_initfn },
  96    { .name = "any",        .instance_init = uc32_any_cpu_initfn },
  97};
  98
  99static void uc32_cpu_realizefn(DeviceState *dev, Error **errp)
 100{
 101    UniCore32CPUClass *ucc = UNICORE32_CPU_GET_CLASS(dev);
 102
 103    qemu_init_vcpu(CPU(dev));
 104
 105    ucc->parent_realize(dev, errp);
 106}
 107
 108static void uc32_cpu_initfn(Object *obj)
 109{
 110    CPUState *cs = CPU(obj);
 111    UniCore32CPU *cpu = UNICORE32_CPU(obj);
 112    CPUUniCore32State *env = &cpu->env;
 113    static bool inited;
 114
 115    cs->env_ptr = env;
 116    cpu_exec_init(cs, &error_abort);
 117
 118#ifdef CONFIG_USER_ONLY
 119    env->uncached_asr = ASR_MODE_USER;
 120    env->regs[31] = 0;
 121#else
 122    env->uncached_asr = ASR_MODE_PRIV;
 123    env->regs[31] = 0x03000000;
 124#endif
 125
 126    tlb_flush(cs, 1);
 127
 128    if (tcg_enabled() && !inited) {
 129        inited = true;
 130        uc32_translate_init();
 131    }
 132}
 133
 134static const VMStateDescription vmstate_uc32_cpu = {
 135    .name = "cpu",
 136    .unmigratable = 1,
 137};
 138
 139static void uc32_cpu_class_init(ObjectClass *oc, void *data)
 140{
 141    DeviceClass *dc = DEVICE_CLASS(oc);
 142    CPUClass *cc = CPU_CLASS(oc);
 143    UniCore32CPUClass *ucc = UNICORE32_CPU_CLASS(oc);
 144
 145    ucc->parent_realize = dc->realize;
 146    dc->realize = uc32_cpu_realizefn;
 147
 148    cc->class_by_name = uc32_cpu_class_by_name;
 149    cc->has_work = uc32_cpu_has_work;
 150    cc->do_interrupt = uc32_cpu_do_interrupt;
 151    cc->cpu_exec_interrupt = uc32_cpu_exec_interrupt;
 152    cc->dump_state = uc32_cpu_dump_state;
 153    cc->set_pc = uc32_cpu_set_pc;
 154#ifdef CONFIG_USER_ONLY
 155    cc->handle_mmu_fault = uc32_cpu_handle_mmu_fault;
 156#else
 157    cc->get_phys_page_debug = uc32_cpu_get_phys_page_debug;
 158#endif
 159    dc->vmsd = &vmstate_uc32_cpu;
 160
 161    /*
 162     * Reason: uc32_cpu_initfn() calls cpu_exec_init(), which saves
 163     * the object in cpus -> dangling pointer after final
 164     * object_unref().
 165     */
 166    dc->cannot_destroy_with_object_finalize_yet = true;
 167}
 168
 169static void uc32_register_cpu_type(const UniCore32CPUInfo *info)
 170{
 171    TypeInfo type_info = {
 172        .parent = TYPE_UNICORE32_CPU,
 173        .instance_init = info->instance_init,
 174    };
 175
 176    type_info.name = g_strdup_printf("%s-" TYPE_UNICORE32_CPU, info->name);
 177    type_register(&type_info);
 178    g_free((void *)type_info.name);
 179}
 180
 181static const TypeInfo uc32_cpu_type_info = {
 182    .name = TYPE_UNICORE32_CPU,
 183    .parent = TYPE_CPU,
 184    .instance_size = sizeof(UniCore32CPU),
 185    .instance_init = uc32_cpu_initfn,
 186    .abstract = true,
 187    .class_size = sizeof(UniCore32CPUClass),
 188    .class_init = uc32_cpu_class_init,
 189};
 190
 191static void uc32_cpu_register_types(void)
 192{
 193    int i;
 194
 195    type_register_static(&uc32_cpu_type_info);
 196    for (i = 0; i < ARRAY_SIZE(uc32_cpus); i++) {
 197        uc32_register_cpu_type(&uc32_cpus[i]);
 198    }
 199}
 200
 201type_init(uc32_cpu_register_types)
 202