| File: | target-unicore32/softmmu.c |
| Location: | line 219, column 5 |
| Description: | Value stored to 'ret' is never read |
| 1 | /* |
| 2 | * Softmmu related functions |
| 3 | * |
| 4 | * Copyright (C) 2010-2012 Guan Xuetao |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License version 2 as |
| 8 | * published by the Free Software Foundation, or any later version. |
| 9 | * See the COPYING file in the top-level directory. |
| 10 | */ |
| 11 | #ifdef CONFIG_USER_ONLY |
| 12 | #error This file only exist under softmmu circumstance |
| 13 | #endif |
| 14 | |
| 15 | #include <cpu.h> |
| 16 | |
| 17 | #undef DEBUG_UC32 |
| 18 | |
| 19 | #ifdef DEBUG_UC32 |
| 20 | #define DPRINTF(fmt, ...)do {} while (0) printf("%s: " fmt , __func__, ## __VA_ARGS__) |
| 21 | #else |
| 22 | #define DPRINTF(fmt, ...)do {} while (0) do {} while (0) |
| 23 | #endif |
| 24 | |
| 25 | #define SUPERPAGE_SIZE(1 << 22) (1 << 22) |
| 26 | #define UC32_PAGETABLE_READ(1 << 8) (1 << 8) |
| 27 | #define UC32_PAGETABLE_WRITE(1 << 7) (1 << 7) |
| 28 | #define UC32_PAGETABLE_EXEC(1 << 6) (1 << 6) |
| 29 | #define UC32_PAGETABLE_EXIST(1 << 2) (1 << 2) |
| 30 | #define PAGETABLE_TYPE(x)((x) & 3) ((x) & 3) |
| 31 | |
| 32 | |
| 33 | /* Map CPU modes onto saved register banks. */ |
| 34 | static inline int bank_number(CPUUniCore32State *env, int mode) |
| 35 | { |
| 36 | switch (mode) { |
| 37 | case ASR_MODE_USER(0x10): |
| 38 | case ASR_MODE_SUSR(0x1f): |
| 39 | return 0; |
| 40 | case ASR_MODE_PRIV(0x13): |
| 41 | return 1; |
| 42 | case ASR_MODE_TRAP(0x17): |
| 43 | return 2; |
| 44 | case ASR_MODE_EXTN(0x1b): |
| 45 | return 3; |
| 46 | case ASR_MODE_INTR(0x12): |
| 47 | return 4; |
| 48 | } |
| 49 | cpu_abort(env, "Bad mode %x\n", mode); |
| 50 | return -1; |
| 51 | } |
| 52 | |
| 53 | void switch_mode(CPUUniCore32State *env, int mode) |
| 54 | { |
| 55 | int old_mode; |
| 56 | int i; |
| 57 | |
| 58 | old_mode = env->uncached_asr & ASR_M(0x1f); |
| 59 | if (mode == old_mode) { |
| 60 | return; |
| 61 | } |
| 62 | |
| 63 | i = bank_number(env, old_mode); |
| 64 | env->banked_r29[i] = env->regs[29]; |
| 65 | env->banked_r30[i] = env->regs[30]; |
| 66 | env->banked_bsr[i] = env->bsr; |
| 67 | |
| 68 | i = bank_number(env, mode); |
| 69 | env->regs[29] = env->banked_r29[i]; |
| 70 | env->regs[30] = env->banked_r30[i]; |
| 71 | env->bsr = env->banked_bsr[i]; |
| 72 | } |
| 73 | |
| 74 | /* Handle a CPU exception. */ |
| 75 | void uc32_cpu_do_interrupt(CPUState *cs) |
| 76 | { |
| 77 | UniCore32CPU *cpu = UNICORE32_CPU(cs)((UniCore32CPU *)object_dynamic_cast_assert(((Object *)((cs)) ), ("unicore32-cpu"), "/home/stefan/src/qemu/qemu.org/qemu/target-unicore32/softmmu.c" , 77, __func__)); |
| 78 | CPUUniCore32State *env = &cpu->env; |
| 79 | uint32_t addr; |
| 80 | int new_mode; |
| 81 | |
| 82 | switch (env->exception_index) { |
| 83 | case UC32_EXCP_PRIV(1): |
| 84 | new_mode = ASR_MODE_PRIV(0x13); |
| 85 | addr = 0x08; |
| 86 | break; |
| 87 | case UC32_EXCP_ITRAP(2): |
| 88 | DPRINTF("itrap happened at %x\n", env->regs[31])do {} while (0); |
| 89 | new_mode = ASR_MODE_TRAP(0x17); |
| 90 | addr = 0x0c; |
| 91 | break; |
| 92 | case UC32_EXCP_DTRAP(3): |
| 93 | DPRINTF("dtrap happened at %x\n", env->regs[31])do {} while (0); |
| 94 | new_mode = ASR_MODE_TRAP(0x17); |
| 95 | addr = 0x10; |
| 96 | break; |
| 97 | case UC32_EXCP_INTR(4): |
| 98 | new_mode = ASR_MODE_INTR(0x12); |
| 99 | addr = 0x18; |
| 100 | break; |
| 101 | default: |
| 102 | cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index); |
| 103 | return; |
| 104 | } |
| 105 | /* High vectors. */ |
| 106 | if (env->cp0.c1_sys & (1 << 13)) { |
| 107 | addr += 0xffff0000; |
| 108 | } |
| 109 | |
| 110 | switch_mode(env, new_mode); |
| 111 | env->bsr = cpu_asr_read(env); |
| 112 | env->uncached_asr = (env->uncached_asr & ~ASR_M(0x1f)) | new_mode; |
| 113 | env->uncached_asr |= ASR_I(1 << 7); |
| 114 | /* The PC already points to the proper instruction. */ |
| 115 | env->regs[30] = env->regs[31]; |
| 116 | env->regs[31] = addr; |
| 117 | cs->interrupt_request |= CPU_INTERRUPT_EXITTB0x0004; |
| 118 | } |
| 119 | |
| 120 | static int get_phys_addr_ucv2(CPUUniCore32State *env, uint32_t address, |
| 121 | int access_type, int is_user, uint32_t *phys_ptr, int *prot, |
| 122 | target_ulong *page_size) |
| 123 | { |
| 124 | int code; |
| 125 | uint32_t table; |
| 126 | uint32_t desc; |
| 127 | uint32_t phys_addr; |
| 128 | |
| 129 | /* Pagetable walk. */ |
| 130 | /* Lookup l1 descriptor. */ |
| 131 | table = env->cp0.c2_base & 0xfffff000; |
| 132 | table |= (address >> 20) & 0xffc; |
| 133 | desc = ldl_phys(table); |
| 134 | code = 0; |
| 135 | switch (PAGETABLE_TYPE(desc)((desc) & 3)) { |
| 136 | case 3: |
| 137 | /* Superpage */ |
| 138 | if (!(desc & UC32_PAGETABLE_EXIST(1 << 2))) { |
| 139 | code = 0x0b; /* superpage miss */ |
| 140 | goto do_fault; |
| 141 | } |
| 142 | phys_addr = (desc & 0xffc00000) | (address & 0x003fffff); |
| 143 | *page_size = SUPERPAGE_SIZE(1 << 22); |
| 144 | break; |
| 145 | case 0: |
| 146 | /* Lookup l2 entry. */ |
| 147 | if (is_user) { |
| 148 | DPRINTF("PGD address %x, desc %x\n", table, desc)do {} while (0); |
| 149 | } |
| 150 | if (!(desc & UC32_PAGETABLE_EXIST(1 << 2))) { |
| 151 | code = 0x05; /* second pagetable miss */ |
| 152 | goto do_fault; |
| 153 | } |
| 154 | table = (desc & 0xfffff000) | ((address >> 10) & 0xffc); |
| 155 | desc = ldl_phys(table); |
| 156 | /* 4k page. */ |
| 157 | if (is_user) { |
| 158 | DPRINTF("PTE address %x, desc %x\n", table, desc)do {} while (0); |
| 159 | } |
| 160 | if (!(desc & UC32_PAGETABLE_EXIST(1 << 2))) { |
| 161 | code = 0x08; /* page miss */ |
| 162 | goto do_fault; |
| 163 | } |
| 164 | switch (PAGETABLE_TYPE(desc)((desc) & 3)) { |
| 165 | case 0: |
| 166 | phys_addr = (desc & 0xfffff000) | (address & 0xfff); |
| 167 | *page_size = TARGET_PAGE_SIZE(1 << 12); |
| 168 | break; |
| 169 | default: |
| 170 | cpu_abort(env, "wrong page type!"); |
| 171 | } |
| 172 | break; |
| 173 | default: |
| 174 | cpu_abort(env, "wrong page type!"); |
| 175 | } |
| 176 | |
| 177 | *phys_ptr = phys_addr; |
| 178 | *prot = 0; |
| 179 | /* Check access permissions. */ |
| 180 | if (desc & UC32_PAGETABLE_READ(1 << 8)) { |
| 181 | *prot |= PAGE_READ0x0001; |
| 182 | } else { |
| 183 | if (is_user && (access_type == 0)) { |
| 184 | code = 0x11; /* access unreadable area */ |
| 185 | goto do_fault; |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | if (desc & UC32_PAGETABLE_WRITE(1 << 7)) { |
| 190 | *prot |= PAGE_WRITE0x0002; |
| 191 | } else { |
| 192 | if (is_user && (access_type == 1)) { |
| 193 | code = 0x12; /* access unwritable area */ |
| 194 | goto do_fault; |
| 195 | } |
| 196 | } |
| 197 | |
| 198 | if (desc & UC32_PAGETABLE_EXEC(1 << 6)) { |
| 199 | *prot |= PAGE_EXEC0x0004; |
| 200 | } else { |
| 201 | if (is_user && (access_type == 2)) { |
| 202 | code = 0x13; /* access unexecutable area */ |
| 203 | goto do_fault; |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | do_fault: |
| 208 | return code; |
| 209 | } |
| 210 | |
| 211 | int uc32_cpu_handle_mmu_fault(CPUUniCore32State *env, target_ulong address, |
| 212 | int access_type, int mmu_idx) |
| 213 | { |
| 214 | uint32_t phys_addr; |
| 215 | target_ulong page_size; |
| 216 | int prot; |
| 217 | int ret, is_user; |
| 218 | |
| 219 | ret = 1; |
Value stored to 'ret' is never read | |
| 220 | is_user = mmu_idx == MMU_USER_IDX1; |
| 221 | |
| 222 | if ((env->cp0.c1_sys & 1) == 0) { |
| 223 | /* MMU disabled. */ |
| 224 | phys_addr = address; |
| 225 | prot = PAGE_READ0x0001 | PAGE_WRITE0x0002 | PAGE_EXEC0x0004; |
| 226 | page_size = TARGET_PAGE_SIZE(1 << 12); |
| 227 | ret = 0; |
| 228 | } else { |
| 229 | if ((address & (1 << 31)) || (is_user)) { |
| 230 | ret = get_phys_addr_ucv2(env, address, access_type, is_user, |
| 231 | &phys_addr, &prot, &page_size); |
| 232 | if (is_user) { |
| 233 | DPRINTF("user space access: ret %x, address %x, "do {} while (0) |
| 234 | "access_type %x, phys_addr %x, prot %x\n",do {} while (0) |
| 235 | ret, address, access_type, phys_addr, prot)do {} while (0); |
| 236 | } |
| 237 | } else { |
| 238 | /*IO memory */ |
| 239 | phys_addr = address | (1 << 31); |
| 240 | prot = PAGE_READ0x0001 | PAGE_WRITE0x0002 | PAGE_EXEC0x0004; |
| 241 | page_size = TARGET_PAGE_SIZE(1 << 12); |
| 242 | ret = 0; |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | if (ret == 0) { |
| 247 | /* Map a single page. */ |
| 248 | phys_addr &= TARGET_PAGE_MASK~((1 << 12) - 1); |
| 249 | address &= TARGET_PAGE_MASK~((1 << 12) - 1); |
| 250 | tlb_set_page(env, address, phys_addr, prot, mmu_idx, page_size); |
| 251 | return 0; |
| 252 | } |
| 253 | |
| 254 | env->cp0.c3_faultstatus = ret; |
| 255 | env->cp0.c4_faultaddr = address; |
| 256 | if (access_type == 2) { |
| 257 | env->exception_index = UC32_EXCP_ITRAP(2); |
| 258 | } else { |
| 259 | env->exception_index = UC32_EXCP_DTRAP(3); |
| 260 | } |
| 261 | return ret; |
| 262 | } |
| 263 | |
| 264 | hwaddr uc32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) |
| 265 | { |
| 266 | UniCore32CPU *cpu = UNICORE32_CPU(cs)((UniCore32CPU *)object_dynamic_cast_assert(((Object *)((cs)) ), ("unicore32-cpu"), "/home/stefan/src/qemu/qemu.org/qemu/target-unicore32/softmmu.c" , 266, __func__)); |
| 267 | |
| 268 | cpu_abort(&cpu->env, "%s not supported yet\n", __func__); |
| 269 | return addr; |
| 270 | } |