/* CPUClass::reset() */ static void openrisc_cpu_reset(CPUState *s) { OpenRISCCPU *cpu = OPENRISC_CPU(s); OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu); occ->parent_reset(s); memset(&cpu->env, 0, offsetof(CPUOpenRISCState, breakpoints)); tlb_flush(&cpu->env, 1); /*tb_flush(&cpu->env); FIXME: Do we need it? */ cpu->env.pc = 0x100; cpu->env.sr = SR_FO | SR_SM; cpu->env.exception_index = -1; cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP; cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S; cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2)); cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2)); #ifndef CONFIG_USER_ONLY cpu->env.picmr = 0x00000000; cpu->env.picsr = 0x00000000; cpu->env.ttmr = 0x00000000; cpu->env.ttcr = 0x00000000; #endif }
int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { OpenRISCCPU *cpu = OPENRISC_CPU(cs); CPUClass *cc = CPU_GET_CLASS(cs); CPUOpenRISCState *env = &cpu->env; uint32_t tmp; if (n > cc->gdb_num_core_regs) { return 0; } tmp = ldl_p(mem_buf); if (n < 32) { env->gpr[n] = tmp; } else { switch (n) { case 32: /* PPC */ env->ppc = tmp; break; case 33: /* NPC */ env->npc = tmp; break; case 34: /* SR */ env->sr = tmp; break; default: break; } } return 4; }
static void or1200_initfn(Object *obj) { OpenRISCCPU *cpu = OPENRISC_CPU(obj); set_feature(cpu, OPENRISC_FEATURE_OB32S); set_feature(cpu, OPENRISC_FEATURE_OF32S); }
bool openrisc_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { OpenRISCCPU *cpu = OPENRISC_CPU(cs); CPUOpenRISCState *env = &cpu->env; int idx = -1; if ((interrupt_request & CPU_INTERRUPT_HARD) && (env->sr & SR_IEE)) { idx = EXCP_INT; } if ((interrupt_request & CPU_INTERRUPT_TIMER) && (env->sr & SR_TEE)) { idx = EXCP_TICK; } // Here's where we set our custom interrupt; I can trace execution to here in GDB, // but FreeRTOS doesn't know what to do with this interrupt so it freaks out - DRM if ((interrupt_request & CPU_INTERRUPT_CUSTOM) && (env->sr & SR_IEE)) { idx = EXCP_CUSTOM; } if (idx >= 0) { cs->exception_index = idx; openrisc_cpu_do_interrupt(cs); return true; } return false; }
bool openrisc_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { OpenRISCCPU *cpu = OPENRISC_CPU(cs); CPUOpenRISCState *env = &cpu->env; int idx = -1; if ((interrupt_request & CPU_INTERRUPT_HARD) && (env->sr & SR_IEE)) { idx = EXCP_INT; } if ((interrupt_request & CPU_INTERRUPT_TIMER) && (env->sr & SR_TEE)) { idx = EXCP_TICK; } // Set up custom interrupts -- make sure to disable the interrupt here, // or it will get thrown multiple times if ((interrupt_request & CPU_INTERRUPT_FFS_WRITE) && (env->sr & SR_IEE)) { idx = EXCP_FFS_WRITE; cs->interrupt_request &= ~(CPU_INTERRUPT_FFS_WRITE); } if ((interrupt_request & CPU_INTERRUPT_FFS_ACK) && (env->sr & SR_IEE)) { idx = EXCP_FFS_ACK; cs->interrupt_request &= ~(CPU_INTERRUPT_FFS_ACK); } if (idx >= 0) { cs->exception_index = idx; openrisc_cpu_do_interrupt(cs); return true; } return false; }
void openrisc_cpu_do_interrupt(CPUState *cs) { OpenRISCCPU *cpu = OPENRISC_CPU(cs); CPUOpenRISCState *env = &cpu->env; #ifndef CONFIG_USER_ONLY if (env->flags & D_FLAG) { /* Delay Slot insn */ env->flags &= ~D_FLAG; env->sr |= SR_DSX; if (env->exception_index == EXCP_TICK || env->exception_index == EXCP_INT || env->exception_index == EXCP_SYSCALL || env->exception_index == EXCP_FPE) { env->epcr = env->jmp_pc; } else { env->epcr = env->pc - 4; } } else { if (env->exception_index == EXCP_TICK || env->exception_index == EXCP_INT || env->exception_index == EXCP_SYSCALL || env->exception_index == EXCP_FPE) { env->epcr = env->npc; } else { env->epcr = env->pc; } } /* For machine-state changed between user-mode and supervisor mode, we need flush TLB when we enter&exit EXCP. */ tlb_flush(env, 1); env->esr = env->sr; env->sr &= ~SR_DME; env->sr &= ~SR_IME; env->sr |= SR_SM; env->sr &= ~SR_IEE; env->sr &= ~SR_TEE; env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; if (env->exception_index > 0 && env->exception_index < EXCP_NR) { env->pc = (env->exception_index << 8); } else { cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index); } #endif env->exception_index = -1; }
static void openrisc_sim_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; const char *kernel_filename = machine->kernel_filename; OpenRISCCPU *cpu = NULL; MemoryRegion *ram; qemu_irq *cpu_irqs[2]; qemu_irq serial_irq; int n; for (n = 0; n < smp_cpus; n++) { cpu = OPENRISC_CPU(cpu_create(machine->cpu_type)); if (cpu == NULL) { fprintf(stderr, "Unable to find CPU definition!\n"); exit(1); } cpu_openrisc_pic_init(cpu); cpu_irqs[n] = (qemu_irq *) cpu->env.irq; cpu_openrisc_clock_init(cpu); qemu_register_reset(main_cpu_reset, cpu); } ram = g_malloc(sizeof(*ram)); memory_region_init_ram(ram, NULL, "openrisc.ram", ram_size, &error_fatal); memory_region_add_subregion(get_system_memory(), 0, ram); if (nd_table[0].used) { openrisc_sim_net_init(0x92000000, 0x92000400, smp_cpus, cpu_irqs, 4, nd_table); } if (smp_cpus > 1) { openrisc_sim_ompic_init(0x98000000, smp_cpus, cpu_irqs, 1); serial_irq = qemu_irq_split(cpu_irqs[0][2], cpu_irqs[1][2]); } else { serial_irq = cpu_irqs[0][2]; } serial_mm_init(get_system_memory(), 0x90000000, 0, serial_irq, 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN); openrisc_load_kernel(ram_size, kernel_filename); }
static void openrisc_cpu_initfn(Object *obj) { CPUState *cs = CPU(obj); OpenRISCCPU *cpu = OPENRISC_CPU(obj); static int inited; cs->env_ptr = &cpu->env; cpu_exec_init(&cpu->env); #ifndef CONFIG_USER_ONLY cpu_openrisc_mmu_init(cpu); #endif if (tcg_enabled() && !inited) { inited = 1; openrisc_translate_init(); } }
bool openrisc_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { OpenRISCCPU *cpu = OPENRISC_CPU(cs); CPUOpenRISCState *env = &cpu->env; int idx = -1; if ((interrupt_request & CPU_INTERRUPT_HARD) && (env->sr & SR_IEE)) { idx = EXCP_INT; } if ((interrupt_request & CPU_INTERRUPT_TIMER) && (env->sr & SR_TEE)) { idx = EXCP_TICK; } if (idx >= 0) { cs->exception_index = idx; openrisc_cpu_do_interrupt(cs); return true; } return false; }
void openrisc_cpu_do_interrupt(CPUState *cs) { #ifndef CONFIG_USER_ONLY OpenRISCCPU *cpu = OPENRISC_CPU(cs); CPUOpenRISCState *env = &cpu->env; env->epcr = env->pc; if (env->flags & D_FLAG) { env->flags &= ~D_FLAG; env->sr |= SR_DSX; env->epcr -= 4; } if (cs->exception_index == EXCP_SYSCALL) { env->epcr += 4; } /* For machine-state changed between user-mode and supervisor mode, we need flush TLB when we enter&exit EXCP. */ tlb_flush(cs, 1); env->esr = env->sr; env->sr &= ~SR_DME; env->sr &= ~SR_IME; env->sr |= SR_SM; env->sr &= ~SR_IEE; env->sr &= ~SR_TEE; env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) { #ifdef OR32_ARCH_DEFAULT env->pc = (cs->exception_index << 8); #else env->pc = 0x100000 + (cs->exception_index << 8); #endif //printf("pc = 0x%x\n", env->pc); } else { cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index); } #endif cs->exception_index = -1; }
int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { OpenRISCCPU *cpu = OPENRISC_CPU(cs); CPUClass *cc = CPU_GET_CLASS(cs); CPUOpenRISCState *env = &cpu->env; uint32_t tmp; if (n > cc->gdb_num_core_regs) { return 0; } tmp = ldl_p(mem_buf); if (n < 32) { env->gpr[n] = tmp; } else { switch (n) { case 32: /* PPC */ env->ppc = tmp; break; case 33: /* NPC (equals PC) */ /* If setting PC to something different, also clear delayed branch status. */ if (env->pc != tmp) { env->pc = tmp; env->dflag = 0; } break; case 34: /* SR */ cpu_set_sr(env, tmp); break; default: break; } } return 4; }
int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) { OpenRISCCPU *cpu = OPENRISC_CPU(cs); CPUOpenRISCState *env = &cpu->env; if (n < 32) { return gdb_get_reg32(mem_buf, env->gpr[n]); } else { switch (n) { case 32: /* PPC */ return gdb_get_reg32(mem_buf, env->ppc); case 33: /* NPC */ return gdb_get_reg32(mem_buf, env->npc); case 34: /* SR */ return gdb_get_reg32(mem_buf, env->sr); default: break; } } return 0; }
static void openrisc_cpu_set_pc(CPUState *cs, vaddr value) { OpenRISCCPU *cpu = OPENRISC_CPU(cs); cpu->env.pc = value; }