qemu/target/nios2/cpu.c
<<
>>
Prefs
   1/*
   2 * QEMU Nios II CPU
   3 *
   4 * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2.1 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see
  18 * <http://www.gnu.org/licenses/lgpl-2.1.html>
  19 */
  20
  21#include "qemu/osdep.h"
  22#include "qemu/module.h"
  23#include "qapi/error.h"
  24#include "cpu.h"
  25#include "exec/log.h"
  26#include "exec/gdbstub.h"
  27#include "hw/qdev-properties.h"
  28
  29static void nios2_cpu_set_pc(CPUState *cs, vaddr value)
  30{
  31    Nios2CPU *cpu = NIOS2_CPU(cs);
  32    CPUNios2State *env = &cpu->env;
  33
  34    env->pc = value;
  35}
  36
  37static bool nios2_cpu_has_work(CPUState *cs)
  38{
  39    return cs->interrupt_request & CPU_INTERRUPT_HARD;
  40}
  41
  42static void nios2_cpu_reset(DeviceState *dev)
  43{
  44    CPUState *cs = CPU(dev);
  45    Nios2CPU *cpu = NIOS2_CPU(cs);
  46    Nios2CPUClass *ncc = NIOS2_CPU_GET_CLASS(cpu);
  47    CPUNios2State *env = &cpu->env;
  48
  49    ncc->parent_reset(dev);
  50
  51    memset(env->ctrl, 0, sizeof(env->ctrl));
  52    env->pc = cpu->reset_addr;
  53
  54#if defined(CONFIG_USER_ONLY)
  55    /* Start in user mode with interrupts enabled. */
  56    env->ctrl[CR_STATUS] = CR_STATUS_RSIE | CR_STATUS_U | CR_STATUS_PIE;
  57    memset(env->regs, 0, sizeof(env->regs));
  58#else
  59    env->ctrl[CR_STATUS] = CR_STATUS_RSIE;
  60    nios2_update_crs(env);
  61    memset(env->shadow_regs, 0, sizeof(env->shadow_regs));
  62#endif
  63}
  64
  65#ifndef CONFIG_USER_ONLY
  66static void eic_set_irq(void *opaque, int irq, int level)
  67{
  68    Nios2CPU *cpu = opaque;
  69    CPUState *cs = CPU(cpu);
  70
  71    if (level) {
  72        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
  73    } else {
  74        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
  75    }
  76}
  77
  78static void iic_set_irq(void *opaque, int irq, int level)
  79{
  80    Nios2CPU *cpu = opaque;
  81    CPUNios2State *env = &cpu->env;
  82    CPUState *cs = CPU(cpu);
  83
  84    env->ctrl[CR_IPENDING] = deposit32(env->ctrl[CR_IPENDING], irq, 1, !!level);
  85
  86    if (env->ctrl[CR_IPENDING]) {
  87        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
  88    } else {
  89        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
  90    }
  91}
  92#endif
  93
  94static void nios2_cpu_initfn(Object *obj)
  95{
  96    Nios2CPU *cpu = NIOS2_CPU(obj);
  97
  98    cpu_set_cpustate_pointers(cpu);
  99
 100#if !defined(CONFIG_USER_ONLY)
 101    mmu_init(&cpu->env);
 102#endif
 103}
 104
 105static ObjectClass *nios2_cpu_class_by_name(const char *cpu_model)
 106{
 107    return object_class_by_name(TYPE_NIOS2_CPU);
 108}
 109
 110static void realize_cr_status(CPUState *cs)
 111{
 112    Nios2CPU *cpu = NIOS2_CPU(cs);
 113
 114    /* Begin with all fields of all registers are reserved. */
 115    memset(cpu->cr_state, 0, sizeof(cpu->cr_state));
 116
 117    /*
 118     * The combination of writable and readonly is the set of all
 119     * non-reserved fields.  We apply writable as a mask to bits,
 120     * and merge in existing readonly bits, before storing.
 121     */
 122#define WR_REG(C)       cpu->cr_state[C].writable = -1
 123#define RO_REG(C)       cpu->cr_state[C].readonly = -1
 124#define WR_FIELD(C, F)  cpu->cr_state[C].writable |= R_##C##_##F##_MASK
 125#define RO_FIELD(C, F)  cpu->cr_state[C].readonly |= R_##C##_##F##_MASK
 126
 127    WR_FIELD(CR_STATUS, PIE);
 128    WR_REG(CR_ESTATUS);
 129    WR_REG(CR_BSTATUS);
 130    RO_REG(CR_CPUID);
 131    RO_REG(CR_EXCEPTION);
 132    WR_REG(CR_BADADDR);
 133
 134    if (cpu->eic_present) {
 135        WR_FIELD(CR_STATUS, RSIE);
 136        RO_FIELD(CR_STATUS, NMI);
 137        WR_FIELD(CR_STATUS, PRS);
 138        RO_FIELD(CR_STATUS, CRS);
 139        WR_FIELD(CR_STATUS, IL);
 140        WR_FIELD(CR_STATUS, IH);
 141    } else {
 142        RO_FIELD(CR_STATUS, RSIE);
 143        WR_REG(CR_IENABLE);
 144        RO_REG(CR_IPENDING);
 145    }
 146
 147    if (cpu->mmu_present) {
 148        WR_FIELD(CR_STATUS, U);
 149        WR_FIELD(CR_STATUS, EH);
 150
 151        WR_FIELD(CR_PTEADDR, VPN);
 152        WR_FIELD(CR_PTEADDR, PTBASE);
 153
 154        RO_FIELD(CR_TLBMISC, D);
 155        RO_FIELD(CR_TLBMISC, PERM);
 156        RO_FIELD(CR_TLBMISC, BAD);
 157        RO_FIELD(CR_TLBMISC, DBL);
 158        WR_FIELD(CR_TLBMISC, PID);
 159        WR_FIELD(CR_TLBMISC, WE);
 160        WR_FIELD(CR_TLBMISC, RD);
 161        WR_FIELD(CR_TLBMISC, WAY);
 162
 163        WR_REG(CR_TLBACC);
 164    }
 165
 166    /*
 167     * TODO: ECC (config, eccinj) and MPU (config, mpubase, mpuacc) are
 168     * unimplemented, so their corresponding control regs remain reserved.
 169     */
 170
 171#undef WR_REG
 172#undef RO_REG
 173#undef WR_FIELD
 174#undef RO_FIELD
 175}
 176
 177static void nios2_cpu_realizefn(DeviceState *dev, Error **errp)
 178{
 179    CPUState *cs = CPU(dev);
 180    Nios2CPU *cpu = NIOS2_CPU(cs);
 181    Nios2CPUClass *ncc = NIOS2_CPU_GET_CLASS(dev);
 182    Error *local_err = NULL;
 183
 184#ifndef CONFIG_USER_ONLY
 185    if (cpu->eic_present) {
 186        qdev_init_gpio_in_named(DEVICE(cpu), eic_set_irq, "EIC", 1);
 187    } else {
 188        qdev_init_gpio_in_named(DEVICE(cpu), iic_set_irq, "IRQ", 32);
 189    }
 190#endif
 191
 192    cpu_exec_realizefn(cs, &local_err);
 193    if (local_err != NULL) {
 194        error_propagate(errp, local_err);
 195        return;
 196    }
 197
 198    realize_cr_status(cs);
 199    qemu_init_vcpu(cs);
 200    cpu_reset(cs);
 201
 202    /* We have reserved storage for cpuid; might as well use it. */
 203    cpu->env.ctrl[CR_CPUID] = cs->cpu_index;
 204
 205    ncc->parent_realize(dev, errp);
 206}
 207
 208#ifndef CONFIG_USER_ONLY
 209static bool eic_take_interrupt(Nios2CPU *cpu)
 210{
 211    CPUNios2State *env = &cpu->env;
 212    const uint32_t status = env->ctrl[CR_STATUS];
 213
 214    if (cpu->rnmi) {
 215        return !(status & CR_STATUS_NMI);
 216    }
 217    if (!(status & CR_STATUS_PIE)) {
 218        return false;
 219    }
 220    if (cpu->ril <= FIELD_EX32(status, CR_STATUS, IL)) {
 221        return false;
 222    }
 223    if (cpu->rrs != FIELD_EX32(status, CR_STATUS, CRS)) {
 224        return true;
 225    }
 226    return status & CR_STATUS_RSIE;
 227}
 228
 229static bool iic_take_interrupt(Nios2CPU *cpu)
 230{
 231    CPUNios2State *env = &cpu->env;
 232
 233    if (!(env->ctrl[CR_STATUS] & CR_STATUS_PIE)) {
 234        return false;
 235    }
 236    return env->ctrl[CR_IPENDING] & env->ctrl[CR_IENABLE];
 237}
 238
 239static bool nios2_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 240{
 241    Nios2CPU *cpu = NIOS2_CPU(cs);
 242
 243    if (interrupt_request & CPU_INTERRUPT_HARD) {
 244        if (cpu->eic_present
 245            ? eic_take_interrupt(cpu)
 246            : iic_take_interrupt(cpu)) {
 247            cs->exception_index = EXCP_IRQ;
 248            nios2_cpu_do_interrupt(cs);
 249            return true;
 250        }
 251    }
 252    return false;
 253}
 254#endif /* !CONFIG_USER_ONLY */
 255
 256static void nios2_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
 257{
 258    /* NOTE: NiosII R2 is not supported yet. */
 259    info->mach = bfd_arch_nios2;
 260    info->print_insn = print_insn_nios2;
 261}
 262
 263static int nios2_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
 264{
 265    Nios2CPU *cpu = NIOS2_CPU(cs);
 266    CPUNios2State *env = &cpu->env;
 267    uint32_t val;
 268
 269    if (n < 32) {          /* GP regs */
 270        val = env->regs[n];
 271    } else if (n == 32) {    /* PC */
 272        val = env->pc;
 273    } else if (n < 49) {     /* Status regs */
 274        unsigned cr = n - 33;
 275        if (nios2_cr_reserved(&cpu->cr_state[cr])) {
 276            val = 0;
 277        } else {
 278            val = env->ctrl[n - 33];
 279        }
 280    } else {
 281        /* Invalid regs */
 282        return 0;
 283    }
 284
 285    return gdb_get_reg32(mem_buf, val);
 286}
 287
 288static int nios2_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 289{
 290    Nios2CPU *cpu = NIOS2_CPU(cs);
 291    CPUClass *cc = CPU_GET_CLASS(cs);
 292    CPUNios2State *env = &cpu->env;
 293    uint32_t val;
 294
 295    if (n > cc->gdb_num_core_regs) {
 296        return 0;
 297    }
 298    val = ldl_p(mem_buf);
 299
 300    if (n < 32) {            /* GP regs */
 301        env->regs[n] = val;
 302    } else if (n == 32) {    /* PC */
 303        env->pc = val;
 304    } else if (n < 49) {     /* Status regs */
 305        unsigned cr = n - 33;
 306        /* ??? Maybe allow the debugger to write to readonly fields. */
 307        val &= cpu->cr_state[cr].writable;
 308        val |= cpu->cr_state[cr].readonly & env->ctrl[cr];
 309        env->ctrl[cr] = val;
 310    } else {
 311        g_assert_not_reached();
 312    }
 313
 314    return 4;
 315}
 316
 317static Property nios2_properties[] = {
 318    DEFINE_PROP_BOOL("diverr_present", Nios2CPU, diverr_present, true),
 319    DEFINE_PROP_BOOL("mmu_present", Nios2CPU, mmu_present, true),
 320    /* ALTR,pid-num-bits */
 321    DEFINE_PROP_UINT32("mmu_pid_num_bits", Nios2CPU, pid_num_bits, 8),
 322    /* ALTR,tlb-num-ways */
 323    DEFINE_PROP_UINT32("mmu_tlb_num_ways", Nios2CPU, tlb_num_ways, 16),
 324    /* ALTR,tlb-num-entries */
 325    DEFINE_PROP_UINT32("mmu_pid_num_entries", Nios2CPU, tlb_num_entries, 256),
 326    DEFINE_PROP_END_OF_LIST(),
 327};
 328
 329#ifndef CONFIG_USER_ONLY
 330#include "hw/core/sysemu-cpu-ops.h"
 331
 332static const struct SysemuCPUOps nios2_sysemu_ops = {
 333    .get_phys_page_debug = nios2_cpu_get_phys_page_debug,
 334};
 335#endif
 336
 337#include "hw/core/tcg-cpu-ops.h"
 338
 339static const struct TCGCPUOps nios2_tcg_ops = {
 340    .initialize = nios2_tcg_init,
 341
 342#ifndef CONFIG_USER_ONLY
 343    .tlb_fill = nios2_cpu_tlb_fill,
 344    .cpu_exec_interrupt = nios2_cpu_exec_interrupt,
 345    .do_interrupt = nios2_cpu_do_interrupt,
 346    .do_unaligned_access = nios2_cpu_do_unaligned_access,
 347#endif /* !CONFIG_USER_ONLY */
 348};
 349
 350static void nios2_cpu_class_init(ObjectClass *oc, void *data)
 351{
 352    DeviceClass *dc = DEVICE_CLASS(oc);
 353    CPUClass *cc = CPU_CLASS(oc);
 354    Nios2CPUClass *ncc = NIOS2_CPU_CLASS(oc);
 355
 356    device_class_set_parent_realize(dc, nios2_cpu_realizefn,
 357                                    &ncc->parent_realize);
 358    device_class_set_props(dc, nios2_properties);
 359    device_class_set_parent_reset(dc, nios2_cpu_reset, &ncc->parent_reset);
 360
 361    cc->class_by_name = nios2_cpu_class_by_name;
 362    cc->has_work = nios2_cpu_has_work;
 363    cc->dump_state = nios2_cpu_dump_state;
 364    cc->set_pc = nios2_cpu_set_pc;
 365    cc->disas_set_info = nios2_cpu_disas_set_info;
 366#ifndef CONFIG_USER_ONLY
 367    cc->sysemu_ops = &nios2_sysemu_ops;
 368#endif
 369    cc->gdb_read_register = nios2_cpu_gdb_read_register;
 370    cc->gdb_write_register = nios2_cpu_gdb_write_register;
 371    cc->gdb_num_core_regs = 49;
 372    cc->tcg_ops = &nios2_tcg_ops;
 373}
 374
 375static const TypeInfo nios2_cpu_type_info = {
 376    .name = TYPE_NIOS2_CPU,
 377    .parent = TYPE_CPU,
 378    .instance_size = sizeof(Nios2CPU),
 379    .instance_init = nios2_cpu_initfn,
 380    .class_size = sizeof(Nios2CPUClass),
 381    .class_init = nios2_cpu_class_init,
 382};
 383
 384static void nios2_cpu_register_types(void)
 385{
 386    type_register_static(&nios2_cpu_type_info);
 387}
 388
 389type_init(nios2_cpu_register_types)
 390