Annotation of qemu/target-xtensa/cpu.h, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions are met:
                      7:  *     * Redistributions of source code must retain the above copyright
                      8:  *       notice, this list of conditions and the following disclaimer.
                      9:  *     * Redistributions in binary form must reproduce the above copyright
                     10:  *       notice, this list of conditions and the following disclaimer in the
                     11:  *       documentation and/or other materials provided with the distribution.
                     12:  *     * Neither the name of the Open Source and Linux Lab nor the
                     13:  *       names of its contributors may be used to endorse or promote products
                     14:  *       derived from this software without specific prior written permission.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
                     17:  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     18:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     19:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
                     20:  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     21:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     22:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
                     23:  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                     25:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27: 
                     28: #ifndef CPU_XTENSA_H
                     29: #define CPU_XTENSA_H
                     30: 
                     31: #define TARGET_LONG_BITS 32
                     32: #define ELF_MACHINE EM_XTENSA
                     33: 
                     34: #define CPUState struct CPUXtensaState
                     35: 
                     36: #include "config.h"
                     37: #include "qemu-common.h"
                     38: #include "cpu-defs.h"
                     39: 
                     40: #define TARGET_HAS_ICE 1
                     41: 
                     42: #define NB_MMU_MODES 4
                     43: 
                     44: #define TARGET_PHYS_ADDR_SPACE_BITS 32
                     45: #define TARGET_VIRT_ADDR_SPACE_BITS 32
                     46: #define TARGET_PAGE_BITS 12
                     47: 
                     48: enum {
                     49:     /* Additional instructions */
                     50:     XTENSA_OPTION_CODE_DENSITY,
                     51:     XTENSA_OPTION_LOOP,
                     52:     XTENSA_OPTION_EXTENDED_L32R,
                     53:     XTENSA_OPTION_16_BIT_IMUL,
                     54:     XTENSA_OPTION_32_BIT_IMUL,
                     55:     XTENSA_OPTION_32_BIT_IMUL_HIGH,
                     56:     XTENSA_OPTION_32_BIT_IDIV,
                     57:     XTENSA_OPTION_MAC16,
                     58:     XTENSA_OPTION_MISC_OP_NSA,
                     59:     XTENSA_OPTION_MISC_OP_MINMAX,
                     60:     XTENSA_OPTION_MISC_OP_SEXT,
                     61:     XTENSA_OPTION_MISC_OP_CLAMPS,
                     62:     XTENSA_OPTION_COPROCESSOR,
                     63:     XTENSA_OPTION_BOOLEAN,
                     64:     XTENSA_OPTION_FP_COPROCESSOR,
                     65:     XTENSA_OPTION_MP_SYNCHRO,
                     66:     XTENSA_OPTION_CONDITIONAL_STORE,
                     67: 
                     68:     /* Interrupts and exceptions */
                     69:     XTENSA_OPTION_EXCEPTION,
                     70:     XTENSA_OPTION_RELOCATABLE_VECTOR,
                     71:     XTENSA_OPTION_UNALIGNED_EXCEPTION,
                     72:     XTENSA_OPTION_INTERRUPT,
                     73:     XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
                     74:     XTENSA_OPTION_TIMER_INTERRUPT,
                     75: 
                     76:     /* Local memory */
                     77:     XTENSA_OPTION_ICACHE,
                     78:     XTENSA_OPTION_ICACHE_TEST,
                     79:     XTENSA_OPTION_ICACHE_INDEX_LOCK,
                     80:     XTENSA_OPTION_DCACHE,
                     81:     XTENSA_OPTION_DCACHE_TEST,
                     82:     XTENSA_OPTION_DCACHE_INDEX_LOCK,
                     83:     XTENSA_OPTION_IRAM,
                     84:     XTENSA_OPTION_IROM,
                     85:     XTENSA_OPTION_DRAM,
                     86:     XTENSA_OPTION_DROM,
                     87:     XTENSA_OPTION_XLMI,
                     88:     XTENSA_OPTION_HW_ALIGNMENT,
                     89:     XTENSA_OPTION_MEMORY_ECC_PARITY,
                     90: 
                     91:     /* Memory protection and translation */
                     92:     XTENSA_OPTION_REGION_PROTECTION,
                     93:     XTENSA_OPTION_REGION_TRANSLATION,
                     94:     XTENSA_OPTION_MMU,
                     95: 
                     96:     /* Other */
                     97:     XTENSA_OPTION_WINDOWED_REGISTER,
                     98:     XTENSA_OPTION_PROCESSOR_INTERFACE,
                     99:     XTENSA_OPTION_MISC_SR,
                    100:     XTENSA_OPTION_THREAD_POINTER,
                    101:     XTENSA_OPTION_PROCESSOR_ID,
                    102:     XTENSA_OPTION_DEBUG,
                    103:     XTENSA_OPTION_TRACE_PORT,
                    104: };
                    105: 
                    106: enum {
                    107:     THREADPTR = 231,
                    108:     FCR = 232,
                    109:     FSR = 233,
                    110: };
                    111: 
                    112: enum {
                    113:     LBEG = 0,
                    114:     LEND = 1,
                    115:     LCOUNT = 2,
                    116:     SAR = 3,
                    117:     BR = 4,
                    118:     LITBASE = 5,
                    119:     SCOMPARE1 = 12,
                    120:     ACCLO = 16,
                    121:     ACCHI = 17,
                    122:     MR = 32,
                    123:     WINDOW_BASE = 72,
                    124:     WINDOW_START = 73,
                    125:     PTEVADDR = 83,
                    126:     RASID = 90,
                    127:     ITLBCFG = 91,
                    128:     DTLBCFG = 92,
                    129:     EPC1 = 177,
                    130:     DEPC = 192,
                    131:     EPS2 = 194,
                    132:     EXCSAVE1 = 209,
                    133:     CPENABLE = 224,
                    134:     INTSET = 226,
                    135:     INTCLEAR = 227,
                    136:     INTENABLE = 228,
                    137:     PS = 230,
                    138:     VECBASE = 231,
                    139:     EXCCAUSE = 232,
                    140:     CCOUNT = 234,
                    141:     PRID = 235,
                    142:     EXCVADDR = 238,
                    143:     CCOMPARE = 240,
                    144: };
                    145: 
                    146: #define PS_INTLEVEL 0xf
                    147: #define PS_INTLEVEL_SHIFT 0
                    148: 
                    149: #define PS_EXCM 0x10
                    150: #define PS_UM 0x20
                    151: 
                    152: #define PS_RING 0xc0
                    153: #define PS_RING_SHIFT 6
                    154: 
                    155: #define PS_OWB 0xf00
                    156: #define PS_OWB_SHIFT 8
                    157: 
                    158: #define PS_CALLINC 0x30000
                    159: #define PS_CALLINC_SHIFT 16
                    160: #define PS_CALLINC_LEN 2
                    161: 
                    162: #define PS_WOE 0x40000
                    163: 
                    164: #define MAX_NAREG 64
                    165: #define MAX_NINTERRUPT 32
                    166: #define MAX_NLEVEL 6
                    167: #define MAX_NNMI 1
                    168: #define MAX_NCCOMPARE 3
                    169: #define MAX_TLB_WAY_SIZE 8
                    170: 
                    171: #define REGION_PAGE_MASK 0xe0000000
                    172: 
                    173: enum {
                    174:     /* Static vectors */
                    175:     EXC_RESET,
                    176:     EXC_MEMORY_ERROR,
                    177: 
                    178:     /* Dynamic vectors */
                    179:     EXC_WINDOW_OVERFLOW4,
                    180:     EXC_WINDOW_UNDERFLOW4,
                    181:     EXC_WINDOW_OVERFLOW8,
                    182:     EXC_WINDOW_UNDERFLOW8,
                    183:     EXC_WINDOW_OVERFLOW12,
                    184:     EXC_WINDOW_UNDERFLOW12,
                    185:     EXC_IRQ,
                    186:     EXC_KERNEL,
                    187:     EXC_USER,
                    188:     EXC_DOUBLE,
                    189:     EXC_MAX
                    190: };
                    191: 
                    192: enum {
                    193:     ILLEGAL_INSTRUCTION_CAUSE = 0,
                    194:     SYSCALL_CAUSE,
                    195:     INSTRUCTION_FETCH_ERROR_CAUSE,
                    196:     LOAD_STORE_ERROR_CAUSE,
                    197:     LEVEL1_INTERRUPT_CAUSE,
                    198:     ALLOCA_CAUSE,
                    199:     INTEGER_DIVIDE_BY_ZERO_CAUSE,
                    200:     PRIVILEGED_CAUSE = 8,
                    201:     LOAD_STORE_ALIGNMENT_CAUSE,
                    202: 
                    203:     INSTR_PIF_DATA_ERROR_CAUSE = 12,
                    204:     LOAD_STORE_PIF_DATA_ERROR_CAUSE,
                    205:     INSTR_PIF_ADDR_ERROR_CAUSE,
                    206:     LOAD_STORE_PIF_ADDR_ERROR_CAUSE,
                    207: 
                    208:     INST_TLB_MISS_CAUSE,
                    209:     INST_TLB_MULTI_HIT_CAUSE,
                    210:     INST_FETCH_PRIVILEGE_CAUSE,
                    211:     INST_FETCH_PROHIBITED_CAUSE = 20,
                    212:     LOAD_STORE_TLB_MISS_CAUSE = 24,
                    213:     LOAD_STORE_TLB_MULTI_HIT_CAUSE,
                    214:     LOAD_STORE_PRIVILEGE_CAUSE,
                    215:     LOAD_PROHIBITED_CAUSE = 28,
                    216:     STORE_PROHIBITED_CAUSE,
                    217: 
                    218:     COPROCESSOR0_DISABLED = 32,
                    219: };
                    220: 
                    221: typedef enum {
                    222:     INTTYPE_LEVEL,
                    223:     INTTYPE_EDGE,
                    224:     INTTYPE_NMI,
                    225:     INTTYPE_SOFTWARE,
                    226:     INTTYPE_TIMER,
                    227:     INTTYPE_DEBUG,
                    228:     INTTYPE_WRITE_ERR,
                    229:     INTTYPE_MAX
                    230: } interrupt_type;
                    231: 
                    232: typedef struct xtensa_tlb_entry {
                    233:     uint32_t vaddr;
                    234:     uint32_t paddr;
                    235:     uint8_t asid;
                    236:     uint8_t attr;
                    237:     bool variable;
                    238: } xtensa_tlb_entry;
                    239: 
                    240: typedef struct xtensa_tlb {
                    241:     unsigned nways;
                    242:     const unsigned way_size[10];
                    243:     bool varway56;
                    244:     unsigned nrefillentries;
                    245: } xtensa_tlb;
                    246: 
                    247: typedef struct XtensaGdbReg {
                    248:     int targno;
                    249:     int type;
                    250:     int group;
                    251: } XtensaGdbReg;
                    252: 
                    253: typedef struct XtensaGdbRegmap {
                    254:     int num_regs;
                    255:     int num_core_regs;
                    256:     /* PC + a + ar + sr + ur */
                    257:     XtensaGdbReg reg[1 + 16 + 64 + 256 + 256];
                    258: } XtensaGdbRegmap;
                    259: 
                    260: typedef struct XtensaConfig {
                    261:     const char *name;
                    262:     uint64_t options;
                    263:     XtensaGdbRegmap gdb_regmap;
                    264:     unsigned nareg;
                    265:     int excm_level;
                    266:     int ndepc;
                    267:     uint32_t vecbase;
                    268:     uint32_t exception_vector[EXC_MAX];
                    269:     unsigned ninterrupt;
                    270:     unsigned nlevel;
                    271:     uint32_t interrupt_vector[MAX_NLEVEL + MAX_NNMI + 1];
                    272:     uint32_t level_mask[MAX_NLEVEL + MAX_NNMI + 1];
                    273:     uint32_t inttype_mask[INTTYPE_MAX];
                    274:     struct {
                    275:         uint32_t level;
                    276:         interrupt_type inttype;
                    277:     } interrupt[MAX_NINTERRUPT];
                    278:     unsigned nccompare;
                    279:     uint32_t timerint[MAX_NCCOMPARE];
                    280:     unsigned nextint;
                    281:     unsigned extint[MAX_NINTERRUPT];
                    282:     uint32_t clock_freq_khz;
                    283: 
                    284:     xtensa_tlb itlb;
                    285:     xtensa_tlb dtlb;
                    286: } XtensaConfig;
                    287: 
                    288: typedef struct XtensaConfigList {
                    289:     const XtensaConfig *config;
                    290:     struct XtensaConfigList *next;
                    291: } XtensaConfigList;
                    292: 
                    293: typedef struct CPUXtensaState {
                    294:     const XtensaConfig *config;
                    295:     uint32_t regs[16];
                    296:     uint32_t pc;
                    297:     uint32_t sregs[256];
                    298:     uint32_t uregs[256];
                    299:     uint32_t phys_regs[MAX_NAREG];
                    300: 
                    301:     xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
                    302:     xtensa_tlb_entry dtlb[10][MAX_TLB_WAY_SIZE];
                    303:     unsigned autorefill_idx;
                    304: 
                    305:     int pending_irq_level; /* level of last raised IRQ */
                    306:     void **irq_inputs;
                    307:     QEMUTimer *ccompare_timer;
                    308:     uint32_t wake_ccount;
                    309:     int64_t halt_clock;
                    310: 
                    311:     int exception_taken;
                    312: 
                    313:     CPU_COMMON
                    314: } CPUXtensaState;
                    315: 
                    316: #define cpu_init cpu_xtensa_init
                    317: #define cpu_exec cpu_xtensa_exec
                    318: #define cpu_gen_code cpu_xtensa_gen_code
                    319: #define cpu_signal_handler cpu_xtensa_signal_handler
                    320: #define cpu_list xtensa_cpu_list
                    321: 
                    322: CPUXtensaState *cpu_xtensa_init(const char *cpu_model);
                    323: void xtensa_translate_init(void);
                    324: int cpu_xtensa_exec(CPUXtensaState *s);
                    325: void xtensa_register_core(XtensaConfigList *node);
                    326: void do_interrupt(CPUXtensaState *s);
                    327: void check_interrupts(CPUXtensaState *s);
                    328: void xtensa_irq_init(CPUState *env);
                    329: void *xtensa_get_extint(CPUState *env, unsigned extint);
                    330: void xtensa_advance_ccount(CPUState *env, uint32_t d);
                    331: void xtensa_timer_irq(CPUState *env, uint32_t id, uint32_t active);
                    332: void xtensa_rearm_ccompare_timer(CPUState *env);
                    333: int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
                    334: void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
                    335: void xtensa_sync_window_from_phys(CPUState *env);
                    336: void xtensa_sync_phys_from_window(CPUState *env);
                    337: uint32_t xtensa_tlb_get_addr_mask(const CPUState *env, bool dtlb, uint32_t way);
                    338: void split_tlb_entry_spec_way(const CPUState *env, uint32_t v, bool dtlb,
                    339:         uint32_t *vpn, uint32_t wi, uint32_t *ei);
                    340: int xtensa_tlb_lookup(const CPUState *env, uint32_t addr, bool dtlb,
                    341:         uint32_t *pwi, uint32_t *pei, uint8_t *pring);
                    342: void xtensa_tlb_set_entry(CPUState *env, bool dtlb,
                    343:         unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
                    344: int xtensa_get_physical_addr(CPUState *env,
                    345:         uint32_t vaddr, int is_write, int mmu_idx,
                    346:         uint32_t *paddr, uint32_t *page_size, unsigned *access);
                    347: 
                    348: 
                    349: #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
                    350: 
                    351: static inline bool xtensa_option_bits_enabled(const XtensaConfig *config,
                    352:         uint64_t opt)
                    353: {
                    354:     return (config->options & opt) != 0;
                    355: }
                    356: 
                    357: static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt)
                    358: {
                    359:     return xtensa_option_bits_enabled(config, XTENSA_OPTION_BIT(opt));
                    360: }
                    361: 
                    362: static inline int xtensa_get_cintlevel(const CPUState *env)
                    363: {
                    364:     int level = (env->sregs[PS] & PS_INTLEVEL) >> PS_INTLEVEL_SHIFT;
                    365:     if ((env->sregs[PS] & PS_EXCM) && env->config->excm_level > level) {
                    366:         level = env->config->excm_level;
                    367:     }
                    368:     return level;
                    369: }
                    370: 
                    371: static inline int xtensa_get_ring(const CPUState *env)
                    372: {
                    373:     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
                    374:         return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
                    375:     } else {
                    376:         return 0;
                    377:     }
                    378: }
                    379: 
                    380: static inline int xtensa_get_cring(const CPUState *env)
                    381: {
                    382:     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) &&
                    383:             (env->sregs[PS] & PS_EXCM) == 0) {
                    384:         return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
                    385:     } else {
                    386:         return 0;
                    387:     }
                    388: }
                    389: 
                    390: static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUState *env,
                    391:         bool dtlb, unsigned wi, unsigned ei)
                    392: {
                    393:     return dtlb ?
                    394:         env->dtlb[wi] + ei :
                    395:         env->itlb[wi] + ei;
                    396: }
                    397: 
                    398: /* MMU modes definitions */
                    399: #define MMU_MODE0_SUFFIX _ring0
                    400: #define MMU_MODE1_SUFFIX _ring1
                    401: #define MMU_MODE2_SUFFIX _ring2
                    402: #define MMU_MODE3_SUFFIX _ring3
                    403: 
                    404: static inline int cpu_mmu_index(CPUState *env)
                    405: {
                    406:     return xtensa_get_cring(env);
                    407: }
                    408: 
                    409: #define XTENSA_TBFLAG_RING_MASK 0x3
                    410: #define XTENSA_TBFLAG_EXCM 0x4
                    411: #define XTENSA_TBFLAG_LITBASE 0x8
                    412: 
                    413: static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
                    414:         target_ulong *cs_base, int *flags)
                    415: {
                    416:     *pc = env->pc;
                    417:     *cs_base = 0;
                    418:     *flags = 0;
                    419:     *flags |= xtensa_get_ring(env);
                    420:     if (env->sregs[PS] & PS_EXCM) {
                    421:         *flags |= XTENSA_TBFLAG_EXCM;
                    422:     }
                    423:     if (xtensa_option_enabled(env->config, XTENSA_OPTION_EXTENDED_L32R) &&
                    424:             (env->sregs[LITBASE] & 1)) {
                    425:         *flags |= XTENSA_TBFLAG_LITBASE;
                    426:     }
                    427: }
                    428: 
                    429: #include "cpu-all.h"
                    430: #include "exec-all.h"
                    431: 
                    432: static inline int cpu_has_work(CPUState *env)
                    433: {
                    434:     return env->pending_irq_level;
                    435: }
                    436: 
                    437: static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
                    438: {
                    439:     env->pc = tb->pc;
                    440: }
                    441: 
                    442: #endif

unix.superglobalmegacorp.com