qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

linux-user: move sparc/sparc64 cpu loop to sparc directory

No code change, only move code from main.c to
sparc/cpu_loop.c.

Include sparc/cpu_loop.c in sparc64/cpu_loop.c
to avoid to duplicate code.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20180411185651.21351-6-laurent@vivier.eu>

+282 -294
+1 -287
linux-user/main.c
··· 149 149 } 150 150 } 151 151 152 - #ifdef TARGET_SPARC 153 - #define SPARC64_STACK_BIAS 2047 154 - 155 - //#define DEBUG_WIN 156 - 157 - /* WARNING: dealing with register windows _is_ complicated. More info 158 - can be found at http://www.sics.se/~psm/sparcstack.html */ 159 - static inline int get_reg_index(CPUSPARCState *env, int cwp, int index) 160 - { 161 - index = (index + cwp * 16) % (16 * env->nwindows); 162 - /* wrap handling : if cwp is on the last window, then we use the 163 - registers 'after' the end */ 164 - if (index < 8 && env->cwp == env->nwindows - 1) 165 - index += 16 * env->nwindows; 166 - return index; 167 - } 168 - 169 - /* save the register window 'cwp1' */ 170 - static inline void save_window_offset(CPUSPARCState *env, int cwp1) 171 - { 172 - unsigned int i; 173 - abi_ulong sp_ptr; 174 - 175 - sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 176 - #ifdef TARGET_SPARC64 177 - if (sp_ptr & 3) 178 - sp_ptr += SPARC64_STACK_BIAS; 179 - #endif 180 - #if defined(DEBUG_WIN) 181 - printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n", 182 - sp_ptr, cwp1); 183 - #endif 184 - for(i = 0; i < 16; i++) { 185 - /* FIXME - what to do if put_user() fails? */ 186 - put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); 187 - sp_ptr += sizeof(abi_ulong); 188 - } 189 - } 190 - 191 - static void save_window(CPUSPARCState *env) 192 - { 193 - #ifndef TARGET_SPARC64 194 - unsigned int new_wim; 195 - new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) & 196 - ((1LL << env->nwindows) - 1); 197 - save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); 198 - env->wim = new_wim; 199 - #else 200 - save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); 201 - env->cansave++; 202 - env->canrestore--; 203 - #endif 204 - } 205 - 206 - static void restore_window(CPUSPARCState *env) 207 - { 208 - #ifndef TARGET_SPARC64 209 - unsigned int new_wim; 210 - #endif 211 - unsigned int i, cwp1; 212 - abi_ulong sp_ptr; 213 - 214 - #ifndef TARGET_SPARC64 215 - new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) & 216 - ((1LL << env->nwindows) - 1); 217 - #endif 218 - 219 - /* restore the invalid window */ 220 - cwp1 = cpu_cwp_inc(env, env->cwp + 1); 221 - sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 222 - #ifdef TARGET_SPARC64 223 - if (sp_ptr & 3) 224 - sp_ptr += SPARC64_STACK_BIAS; 225 - #endif 226 - #if defined(DEBUG_WIN) 227 - printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n", 228 - sp_ptr, cwp1); 229 - #endif 230 - for(i = 0; i < 16; i++) { 231 - /* FIXME - what to do if get_user() fails? */ 232 - get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); 233 - sp_ptr += sizeof(abi_ulong); 234 - } 235 - #ifdef TARGET_SPARC64 236 - env->canrestore++; 237 - if (env->cleanwin < env->nwindows - 1) 238 - env->cleanwin++; 239 - env->cansave--; 240 - #else 241 - env->wim = new_wim; 242 - #endif 243 - } 244 - 245 - static void flush_windows(CPUSPARCState *env) 246 - { 247 - int offset, cwp1; 248 - 249 - offset = 1; 250 - for(;;) { 251 - /* if restore would invoke restore_window(), then we can stop */ 252 - cwp1 = cpu_cwp_inc(env, env->cwp + offset); 253 - #ifndef TARGET_SPARC64 254 - if (env->wim & (1 << cwp1)) 255 - break; 256 - #else 257 - if (env->canrestore == 0) 258 - break; 259 - env->cansave++; 260 - env->canrestore--; 261 - #endif 262 - save_window_offset(env, cwp1); 263 - offset++; 264 - } 265 - cwp1 = cpu_cwp_inc(env, env->cwp + 1); 266 - #ifndef TARGET_SPARC64 267 - /* set wim so that restore will reload the registers */ 268 - env->wim = 1 << cwp1; 269 - #endif 270 - #if defined(DEBUG_WIN) 271 - printf("flush_windows: nb=%d\n", offset - 1); 272 - #endif 273 - } 274 - 275 - void cpu_loop (CPUSPARCState *env) 276 - { 277 - CPUState *cs = CPU(sparc_env_get_cpu(env)); 278 - int trapnr; 279 - abi_long ret; 280 - target_siginfo_t info; 281 - 282 - while (1) { 283 - cpu_exec_start(cs); 284 - trapnr = cpu_exec(cs); 285 - cpu_exec_end(cs); 286 - process_queued_cpu_work(cs); 287 - 288 - /* Compute PSR before exposing state. */ 289 - if (env->cc_op != CC_OP_FLAGS) { 290 - cpu_get_psr(env); 291 - } 292 - 293 - switch (trapnr) { 294 - #ifndef TARGET_SPARC64 295 - case 0x88: 296 - case 0x90: 297 - #else 298 - case 0x110: 299 - case 0x16d: 300 - #endif 301 - ret = do_syscall (env, env->gregs[1], 302 - env->regwptr[0], env->regwptr[1], 303 - env->regwptr[2], env->regwptr[3], 304 - env->regwptr[4], env->regwptr[5], 305 - 0, 0); 306 - if (ret == -TARGET_ERESTARTSYS || ret == -TARGET_QEMU_ESIGRETURN) { 307 - break; 308 - } 309 - if ((abi_ulong)ret >= (abi_ulong)(-515)) { 310 - #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 311 - env->xcc |= PSR_CARRY; 312 - #else 313 - env->psr |= PSR_CARRY; 314 - #endif 315 - ret = -ret; 316 - } else { 317 - #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 318 - env->xcc &= ~PSR_CARRY; 319 - #else 320 - env->psr &= ~PSR_CARRY; 321 - #endif 322 - } 323 - env->regwptr[0] = ret; 324 - /* next instruction */ 325 - env->pc = env->npc; 326 - env->npc = env->npc + 4; 327 - break; 328 - case 0x83: /* flush windows */ 329 - #ifdef TARGET_ABI32 330 - case 0x103: 331 - #endif 332 - flush_windows(env); 333 - /* next instruction */ 334 - env->pc = env->npc; 335 - env->npc = env->npc + 4; 336 - break; 337 - #ifndef TARGET_SPARC64 338 - case TT_WIN_OVF: /* window overflow */ 339 - save_window(env); 340 - break; 341 - case TT_WIN_UNF: /* window underflow */ 342 - restore_window(env); 343 - break; 344 - case TT_TFAULT: 345 - case TT_DFAULT: 346 - { 347 - info.si_signo = TARGET_SIGSEGV; 348 - info.si_errno = 0; 349 - /* XXX: check env->error_code */ 350 - info.si_code = TARGET_SEGV_MAPERR; 351 - info._sifields._sigfault._addr = env->mmuregs[4]; 352 - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 353 - } 354 - break; 355 - #else 356 - case TT_SPILL: /* window overflow */ 357 - save_window(env); 358 - break; 359 - case TT_FILL: /* window underflow */ 360 - restore_window(env); 361 - break; 362 - case TT_TFAULT: 363 - case TT_DFAULT: 364 - { 365 - info.si_signo = TARGET_SIGSEGV; 366 - info.si_errno = 0; 367 - /* XXX: check env->error_code */ 368 - info.si_code = TARGET_SEGV_MAPERR; 369 - if (trapnr == TT_DFAULT) 370 - info._sifields._sigfault._addr = env->dmmu.mmuregs[4]; 371 - else 372 - info._sifields._sigfault._addr = cpu_tsptr(env)->tpc; 373 - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 374 - } 375 - break; 376 - #ifndef TARGET_ABI32 377 - case 0x16e: 378 - flush_windows(env); 379 - sparc64_get_context(env); 380 - break; 381 - case 0x16f: 382 - flush_windows(env); 383 - sparc64_set_context(env); 384 - break; 385 - #endif 386 - #endif 387 - case EXCP_INTERRUPT: 388 - /* just indicate that signals should be handled asap */ 389 - break; 390 - case TT_ILL_INSN: 391 - { 392 - info.si_signo = TARGET_SIGILL; 393 - info.si_errno = 0; 394 - info.si_code = TARGET_ILL_ILLOPC; 395 - info._sifields._sigfault._addr = env->pc; 396 - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 397 - } 398 - break; 399 - case EXCP_DEBUG: 400 - { 401 - int sig; 402 - 403 - sig = gdb_handlesig(cs, TARGET_SIGTRAP); 404 - if (sig) 405 - { 406 - info.si_signo = sig; 407 - info.si_errno = 0; 408 - info.si_code = TARGET_TRAP_BRKPT; 409 - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 410 - } 411 - } 412 - break; 413 - case EXCP_ATOMIC: 414 - cpu_exec_step_atomic(cs); 415 - break; 416 - default: 417 - printf ("Unhandled trap: 0x%x\n", trapnr); 418 - cpu_dump_state(cs, stderr, fprintf, 0); 419 - exit(EXIT_FAILURE); 420 - } 421 - process_pending_signals (env); 422 - } 423 - } 424 - 425 - #endif 426 - 427 152 #ifdef TARGET_PPC 428 153 static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env) 429 154 { ··· 4002 3727 4003 3728 target_cpu_copy_regs(env, regs); 4004 3729 4005 - #if defined(TARGET_SPARC) 4006 - { 4007 - int i; 4008 - env->pc = regs->pc; 4009 - env->npc = regs->npc; 4010 - env->y = regs->y; 4011 - for(i = 0; i < 8; i++) 4012 - env->gregs[i] = regs->u_regs[i]; 4013 - for(i = 0; i < 8; i++) 4014 - env->regwptr[i] = regs->u_regs[i + 8]; 4015 - } 4016 - #elif defined(TARGET_PPC) 3730 + #if defined(TARGET_PPC) 4017 3731 { 4018 3732 int i; 4019 3733
+280
linux-user/sparc/cpu_loop.c
··· 21 21 #include "qemu.h" 22 22 #include "cpu_loop-common.h" 23 23 24 + #define SPARC64_STACK_BIAS 2047 25 + 26 + //#define DEBUG_WIN 27 + 28 + /* WARNING: dealing with register windows _is_ complicated. More info 29 + can be found at http://www.sics.se/~psm/sparcstack.html */ 30 + static inline int get_reg_index(CPUSPARCState *env, int cwp, int index) 31 + { 32 + index = (index + cwp * 16) % (16 * env->nwindows); 33 + /* wrap handling : if cwp is on the last window, then we use the 34 + registers 'after' the end */ 35 + if (index < 8 && env->cwp == env->nwindows - 1) 36 + index += 16 * env->nwindows; 37 + return index; 38 + } 39 + 40 + /* save the register window 'cwp1' */ 41 + static inline void save_window_offset(CPUSPARCState *env, int cwp1) 42 + { 43 + unsigned int i; 44 + abi_ulong sp_ptr; 45 + 46 + sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 47 + #ifdef TARGET_SPARC64 48 + if (sp_ptr & 3) 49 + sp_ptr += SPARC64_STACK_BIAS; 50 + #endif 51 + #if defined(DEBUG_WIN) 52 + printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n", 53 + sp_ptr, cwp1); 54 + #endif 55 + for(i = 0; i < 16; i++) { 56 + /* FIXME - what to do if put_user() fails? */ 57 + put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); 58 + sp_ptr += sizeof(abi_ulong); 59 + } 60 + } 61 + 62 + static void save_window(CPUSPARCState *env) 63 + { 64 + #ifndef TARGET_SPARC64 65 + unsigned int new_wim; 66 + new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) & 67 + ((1LL << env->nwindows) - 1); 68 + save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); 69 + env->wim = new_wim; 70 + #else 71 + save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); 72 + env->cansave++; 73 + env->canrestore--; 74 + #endif 75 + } 76 + 77 + static void restore_window(CPUSPARCState *env) 78 + { 79 + #ifndef TARGET_SPARC64 80 + unsigned int new_wim; 81 + #endif 82 + unsigned int i, cwp1; 83 + abi_ulong sp_ptr; 84 + 85 + #ifndef TARGET_SPARC64 86 + new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) & 87 + ((1LL << env->nwindows) - 1); 88 + #endif 89 + 90 + /* restore the invalid window */ 91 + cwp1 = cpu_cwp_inc(env, env->cwp + 1); 92 + sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 93 + #ifdef TARGET_SPARC64 94 + if (sp_ptr & 3) 95 + sp_ptr += SPARC64_STACK_BIAS; 96 + #endif 97 + #if defined(DEBUG_WIN) 98 + printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n", 99 + sp_ptr, cwp1); 100 + #endif 101 + for(i = 0; i < 16; i++) { 102 + /* FIXME - what to do if get_user() fails? */ 103 + get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); 104 + sp_ptr += sizeof(abi_ulong); 105 + } 106 + #ifdef TARGET_SPARC64 107 + env->canrestore++; 108 + if (env->cleanwin < env->nwindows - 1) 109 + env->cleanwin++; 110 + env->cansave--; 111 + #else 112 + env->wim = new_wim; 113 + #endif 114 + } 115 + 116 + static void flush_windows(CPUSPARCState *env) 117 + { 118 + int offset, cwp1; 119 + 120 + offset = 1; 121 + for(;;) { 122 + /* if restore would invoke restore_window(), then we can stop */ 123 + cwp1 = cpu_cwp_inc(env, env->cwp + offset); 124 + #ifndef TARGET_SPARC64 125 + if (env->wim & (1 << cwp1)) 126 + break; 127 + #else 128 + if (env->canrestore == 0) 129 + break; 130 + env->cansave++; 131 + env->canrestore--; 132 + #endif 133 + save_window_offset(env, cwp1); 134 + offset++; 135 + } 136 + cwp1 = cpu_cwp_inc(env, env->cwp + 1); 137 + #ifndef TARGET_SPARC64 138 + /* set wim so that restore will reload the registers */ 139 + env->wim = 1 << cwp1; 140 + #endif 141 + #if defined(DEBUG_WIN) 142 + printf("flush_windows: nb=%d\n", offset - 1); 143 + #endif 144 + } 145 + 146 + void cpu_loop (CPUSPARCState *env) 147 + { 148 + CPUState *cs = CPU(sparc_env_get_cpu(env)); 149 + int trapnr; 150 + abi_long ret; 151 + target_siginfo_t info; 152 + 153 + while (1) { 154 + cpu_exec_start(cs); 155 + trapnr = cpu_exec(cs); 156 + cpu_exec_end(cs); 157 + process_queued_cpu_work(cs); 158 + 159 + /* Compute PSR before exposing state. */ 160 + if (env->cc_op != CC_OP_FLAGS) { 161 + cpu_get_psr(env); 162 + } 163 + 164 + switch (trapnr) { 165 + #ifndef TARGET_SPARC64 166 + case 0x88: 167 + case 0x90: 168 + #else 169 + case 0x110: 170 + case 0x16d: 171 + #endif 172 + ret = do_syscall (env, env->gregs[1], 173 + env->regwptr[0], env->regwptr[1], 174 + env->regwptr[2], env->regwptr[3], 175 + env->regwptr[4], env->regwptr[5], 176 + 0, 0); 177 + if (ret == -TARGET_ERESTARTSYS || ret == -TARGET_QEMU_ESIGRETURN) { 178 + break; 179 + } 180 + if ((abi_ulong)ret >= (abi_ulong)(-515)) { 181 + #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 182 + env->xcc |= PSR_CARRY; 183 + #else 184 + env->psr |= PSR_CARRY; 185 + #endif 186 + ret = -ret; 187 + } else { 188 + #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 189 + env->xcc &= ~PSR_CARRY; 190 + #else 191 + env->psr &= ~PSR_CARRY; 192 + #endif 193 + } 194 + env->regwptr[0] = ret; 195 + /* next instruction */ 196 + env->pc = env->npc; 197 + env->npc = env->npc + 4; 198 + break; 199 + case 0x83: /* flush windows */ 200 + #ifdef TARGET_ABI32 201 + case 0x103: 202 + #endif 203 + flush_windows(env); 204 + /* next instruction */ 205 + env->pc = env->npc; 206 + env->npc = env->npc + 4; 207 + break; 208 + #ifndef TARGET_SPARC64 209 + case TT_WIN_OVF: /* window overflow */ 210 + save_window(env); 211 + break; 212 + case TT_WIN_UNF: /* window underflow */ 213 + restore_window(env); 214 + break; 215 + case TT_TFAULT: 216 + case TT_DFAULT: 217 + { 218 + info.si_signo = TARGET_SIGSEGV; 219 + info.si_errno = 0; 220 + /* XXX: check env->error_code */ 221 + info.si_code = TARGET_SEGV_MAPERR; 222 + info._sifields._sigfault._addr = env->mmuregs[4]; 223 + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 224 + } 225 + break; 226 + #else 227 + case TT_SPILL: /* window overflow */ 228 + save_window(env); 229 + break; 230 + case TT_FILL: /* window underflow */ 231 + restore_window(env); 232 + break; 233 + case TT_TFAULT: 234 + case TT_DFAULT: 235 + { 236 + info.si_signo = TARGET_SIGSEGV; 237 + info.si_errno = 0; 238 + /* XXX: check env->error_code */ 239 + info.si_code = TARGET_SEGV_MAPERR; 240 + if (trapnr == TT_DFAULT) 241 + info._sifields._sigfault._addr = env->dmmu.mmuregs[4]; 242 + else 243 + info._sifields._sigfault._addr = cpu_tsptr(env)->tpc; 244 + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 245 + } 246 + break; 247 + #ifndef TARGET_ABI32 248 + case 0x16e: 249 + flush_windows(env); 250 + sparc64_get_context(env); 251 + break; 252 + case 0x16f: 253 + flush_windows(env); 254 + sparc64_set_context(env); 255 + break; 256 + #endif 257 + #endif 258 + case EXCP_INTERRUPT: 259 + /* just indicate that signals should be handled asap */ 260 + break; 261 + case TT_ILL_INSN: 262 + { 263 + info.si_signo = TARGET_SIGILL; 264 + info.si_errno = 0; 265 + info.si_code = TARGET_ILL_ILLOPC; 266 + info._sifields._sigfault._addr = env->pc; 267 + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 268 + } 269 + break; 270 + case EXCP_DEBUG: 271 + { 272 + int sig; 273 + 274 + sig = gdb_handlesig(cs, TARGET_SIGTRAP); 275 + if (sig) 276 + { 277 + info.si_signo = sig; 278 + info.si_errno = 0; 279 + info.si_code = TARGET_TRAP_BRKPT; 280 + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 281 + } 282 + } 283 + break; 284 + case EXCP_ATOMIC: 285 + cpu_exec_step_atomic(cs); 286 + break; 287 + default: 288 + printf ("Unhandled trap: 0x%x\n", trapnr); 289 + cpu_dump_state(cs, stderr, fprintf, 0); 290 + exit(EXIT_FAILURE); 291 + } 292 + process_pending_signals (env); 293 + } 294 + } 295 + 24 296 void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) 25 297 { 298 + int i; 299 + env->pc = regs->pc; 300 + env->npc = regs->npc; 301 + env->y = regs->y; 302 + for(i = 0; i < 8; i++) 303 + env->gregs[i] = regs->u_regs[i]; 304 + for(i = 0; i < 8; i++) 305 + env->regwptr[i] = regs->u_regs[i + 8]; 26 306 }
+1 -7
linux-user/sparc64/cpu_loop.c
··· 17 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 18 */ 19 19 20 - #include "qemu/osdep.h" 21 - #include "qemu.h" 22 - #include "cpu_loop-common.h" 23 - 24 - void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) 25 - { 26 - } 20 + #include "../sparc/cpu_loop.c"