Revision 6049f4f8
b/Makefile.target | ||
---|---|---|
51 | 51 |
libobj-y += op_helper.o helper.o |
52 | 52 |
libobj-$(CONFIG_NEED_MMU) += mmu.o |
53 | 53 |
libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o |
54 |
libobj-$(TARGET_ALPHA) += alpha_palcode.o |
|
55 | 54 |
|
56 | 55 |
# NOTE: the disassembler code is only needed for debugging |
57 | 56 |
libobj-y += disas.o |
... | ... | |
312 | 311 |
|
313 | 312 |
obj-s390x-y = s390-virtio-bus.o s390-virtio.o |
314 | 313 |
|
314 |
obj-alpha-y = alpha_palcode.o |
|
315 |
|
|
315 | 316 |
main.o vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS) |
316 | 317 |
|
317 | 318 |
vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS) |
b/hw/alpha_palcode.c | ||
---|---|---|
21 | 21 |
#include <stdlib.h> |
22 | 22 |
#include <stdio.h> |
23 | 23 |
|
24 |
#include "qemu.h" |
|
25 | 24 |
#include "cpu.h" |
26 | 25 |
#include "exec-all.h" |
27 | 26 |
|
28 |
#if !defined (CONFIG_USER_ONLY) |
|
29 | 27 |
/* Shared handlers */ |
30 | 28 |
static void pal_reset (CPUState *env); |
31 | 29 |
/* Console handlers */ |
... | ... | |
997 | 995 |
uint64_t physical, page_size, end; |
998 | 996 |
int prot, zbits, ret; |
999 | 997 |
|
1000 |
#if defined(CONFIG_USER_ONLY) |
|
1001 |
ret = 2; |
|
1002 |
#else |
|
1003 |
ret = virtual_to_physical(env, &physical, &zbits, &prot, |
|
1004 |
address, mmu_idx, rw); |
|
1005 |
#endif |
|
998 |
ret = virtual_to_physical(env, &physical, &zbits, &prot, |
|
999 |
address, mmu_idx, rw); |
|
1000 |
|
|
1006 | 1001 |
switch (ret) { |
1007 | 1002 |
case 0: |
1008 | 1003 |
/* No fault */ |
... | ... | |
1050 | 1045 |
return ret; |
1051 | 1046 |
} |
1052 | 1047 |
#endif |
1053 |
|
|
1054 |
#else /* !defined (CONFIG_USER_ONLY) */ |
|
1055 |
void pal_init (CPUState *env) |
|
1056 |
{ |
|
1057 |
} |
|
1058 |
|
|
1059 |
void call_pal (CPUState *env, int palcode) |
|
1060 |
{ |
|
1061 |
target_long ret; |
|
1062 |
|
|
1063 |
switch (palcode) { |
|
1064 |
case 0x80: |
|
1065 |
/* BPT */ |
|
1066 |
qemu_log("BPT\n"); |
|
1067 |
/* FIXME: Sends SIGTRAP, si_code=TRAP_BRKPT. */ |
|
1068 |
exit(1); |
|
1069 |
case 0x81: |
|
1070 |
/* BUGCHK */ |
|
1071 |
qemu_log("BUGCHK\n"); |
|
1072 |
/* FIXME: Sends SIGTRAP, si_code=SI_FAULT. */ |
|
1073 |
exit(1); |
|
1074 |
case 0x83: |
|
1075 |
/* CALLSYS */ |
|
1076 |
qemu_log("CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]); |
|
1077 |
ret = do_syscall(env, env->ir[IR_V0], env->ir[IR_A0], env->ir[IR_A1], |
|
1078 |
env->ir[IR_A2], env->ir[IR_A3], env->ir[IR_A4], |
|
1079 |
env->ir[IR_A5]); |
|
1080 |
if (ret >= 0) { |
|
1081 |
env->ir[IR_A3] = 0; |
|
1082 |
env->ir[IR_V0] = ret; |
|
1083 |
} else { |
|
1084 |
env->ir[IR_A3] = 1; |
|
1085 |
env->ir[IR_V0] = -ret; |
|
1086 |
} |
|
1087 |
break; |
|
1088 |
case 0x86: |
|
1089 |
/* IMB */ |
|
1090 |
qemu_log("IMB\n"); |
|
1091 |
/* ??? We can probably elide the code using page_unprotect that is |
|
1092 |
checking for self-modifying code. Instead we could simply call |
|
1093 |
tb_flush here. Until we work out the changes required to turn |
|
1094 |
off the extra write protection, this can be a no-op. */ |
|
1095 |
break; |
|
1096 |
case 0x9E: |
|
1097 |
/* RDUNIQUE */ |
|
1098 |
qemu_log("RDUNIQUE: " TARGET_FMT_lx "\n", env->unique); |
|
1099 |
/* Handled in the translator for usermode. */ |
|
1100 |
abort(); |
|
1101 |
case 0x9F: |
|
1102 |
/* WRUNIQUE */ |
|
1103 |
qemu_log("WRUNIQUE: " TARGET_FMT_lx "\n", env->ir[IR_A0]); |
|
1104 |
/* Handled in the translator for usermode. */ |
|
1105 |
abort(); |
|
1106 |
case 0xAA: |
|
1107 |
/* GENTRAP */ |
|
1108 |
qemu_log("GENTRAP: " TARGET_FMT_lx "\n", env->ir[IR_A0]); |
|
1109 |
/* FIXME: This is supposed to send a signal: |
|
1110 |
SIGFPE: |
|
1111 |
GEN_INTOVF, GEN_INTDIV, GEN_FLTOVF, GEN_FLTDIV, |
|
1112 |
GEN_FLTUND, GEN_FLTINV, GEN_FLTINE, GEN_ROPRAND |
|
1113 |
SIGTRAP: |
|
1114 |
others |
|
1115 |
with various settings of si_code. */ |
|
1116 |
exit(1); |
|
1117 |
default: |
|
1118 |
qemu_log("%s: unhandled palcode %02x\n", __func__, palcode); |
|
1119 |
exit(1); |
|
1120 |
} |
|
1121 |
} |
|
1122 |
#endif |
b/linux-user/alpha/target_signal.h | ||
---|---|---|
26 | 26 |
return state->ir[IR_SP]; |
27 | 27 |
} |
28 | 28 |
|
29 |
/* From <asm/gentrap.h>. */ |
|
30 |
#define TARGET_GEN_INTOVF -1 /* integer overflow */ |
|
31 |
#define TARGET_GEN_INTDIV -2 /* integer division by zero */ |
|
32 |
#define TARGET_GEN_FLTOVF -3 /* fp overflow */ |
|
33 |
#define TARGET_GEN_FLTDIV -4 /* fp division by zero */ |
|
34 |
#define TARGET_GEN_FLTUND -5 /* fp underflow */ |
|
35 |
#define TARGET_GEN_FLTINV -6 /* invalid fp operand */ |
|
36 |
#define TARGET_GEN_FLTINE -7 /* inexact fp operand */ |
|
37 |
#define TARGET_GEN_DECOVF -8 /* decimal overflow (for COBOL??) */ |
|
38 |
#define TARGET_GEN_DECDIV -9 /* decimal division by zero */ |
|
39 |
#define TARGET_GEN_DECINV -10 /* invalid decimal operand */ |
|
40 |
#define TARGET_GEN_ROPRAND -11 /* reserved operand */ |
|
41 |
#define TARGET_GEN_ASSERTERR -12 /* assertion error */ |
|
42 |
#define TARGET_GEN_NULPTRERR -13 /* null pointer error */ |
|
43 |
#define TARGET_GEN_STKOVF -14 /* stack overflow */ |
|
44 |
#define TARGET_GEN_STRLENERR -15 /* string length error */ |
|
45 |
#define TARGET_GEN_SUBSTRERR -16 /* substring error */ |
|
46 |
#define TARGET_GEN_RANGERR -17 /* range error */ |
|
47 |
#define TARGET_GEN_SUBRNG -18 |
|
48 |
#define TARGET_GEN_SUBRNG1 -19 |
|
49 |
#define TARGET_GEN_SUBRNG2 -20 |
|
50 |
#define TARGET_GEN_SUBRNG3 -21 |
|
51 |
#define TARGET_GEN_SUBRNG4 -22 |
|
52 |
#define TARGET_GEN_SUBRNG5 -23 |
|
53 |
#define TARGET_GEN_SUBRNG6 -24 |
|
54 |
#define TARGET_GEN_SUBRNG7 -25 |
|
55 |
|
|
29 | 56 |
#endif /* TARGET_SIGNAL_H */ |
b/linux-user/main.c | ||
---|---|---|
2351 | 2351 |
{ |
2352 | 2352 |
int trapnr; |
2353 | 2353 |
target_siginfo_t info; |
2354 |
abi_long sysret; |
|
2354 | 2355 |
|
2355 | 2356 |
while (1) { |
2356 | 2357 |
trapnr = cpu_alpha_exec (env); |
... | ... | |
2365 | 2366 |
exit(1); |
2366 | 2367 |
break; |
2367 | 2368 |
case EXCP_ARITH: |
2368 |
fprintf(stderr, "Arithmetic trap.\n"); |
|
2369 |
exit(1); |
|
2369 |
info.si_signo = TARGET_SIGFPE; |
|
2370 |
info.si_errno = 0; |
|
2371 |
info.si_code = TARGET_FPE_FLTINV; |
|
2372 |
info._sifields._sigfault._addr = env->pc; |
|
2373 |
queue_signal(env, info.si_signo, &info); |
|
2370 | 2374 |
break; |
2371 | 2375 |
case EXCP_HW_INTERRUPT: |
2372 | 2376 |
fprintf(stderr, "External interrupt. Exit\n"); |
2373 | 2377 |
exit(1); |
2374 | 2378 |
break; |
2375 | 2379 |
case EXCP_DFAULT: |
2376 |
fprintf(stderr, "MMU data fault\n"); |
|
2377 |
exit(1); |
|
2380 |
info.si_signo = TARGET_SIGSEGV; |
|
2381 |
info.si_errno = 0; |
|
2382 |
info.si_code = 0; /* ??? SEGV_MAPERR vs SEGV_ACCERR. */ |
|
2383 |
info._sifields._sigfault._addr = env->pc; |
|
2384 |
queue_signal(env, info.si_signo, &info); |
|
2378 | 2385 |
break; |
2379 | 2386 |
case EXCP_DTB_MISS_PAL: |
2380 | 2387 |
fprintf(stderr, "MMU data TLB miss in PALcode\n"); |
... | ... | |
2393 | 2400 |
exit(1); |
2394 | 2401 |
break; |
2395 | 2402 |
case EXCP_UNALIGN: |
2396 |
fprintf(stderr, "Unaligned access\n"); |
|
2397 |
exit(1); |
|
2403 |
info.si_signo = TARGET_SIGBUS; |
|
2404 |
info.si_errno = 0; |
|
2405 |
info.si_code = TARGET_BUS_ADRALN; |
|
2406 |
info._sifields._sigfault._addr = env->pc; |
|
2407 |
queue_signal(env, info.si_signo, &info); |
|
2398 | 2408 |
break; |
2399 | 2409 |
case EXCP_OPCDEC: |
2400 |
fprintf(stderr, "Invalid instruction\n"); |
|
2401 |
exit(1); |
|
2410 |
do_sigill: |
|
2411 |
info.si_signo = TARGET_SIGILL; |
|
2412 |
info.si_errno = 0; |
|
2413 |
info.si_code = TARGET_ILL_ILLOPC; |
|
2414 |
info._sifields._sigfault._addr = env->pc; |
|
2415 |
queue_signal(env, info.si_signo, &info); |
|
2402 | 2416 |
break; |
2403 | 2417 |
case EXCP_FEN: |
2404 |
fprintf(stderr, "Floating-point not allowed\n"); |
|
2405 |
exit(1); |
|
2418 |
/* No-op. Linux simply re-enables the FPU. */ |
|
2406 | 2419 |
break; |
2407 | 2420 |
case EXCP_CALL_PAL ... (EXCP_CALL_PALP - 1): |
2408 |
call_pal(env, (trapnr >> 6) | 0x80); |
|
2421 |
switch ((trapnr >> 6) | 0x80) { |
|
2422 |
case 0x80: |
|
2423 |
/* BPT */ |
|
2424 |
info.si_signo = TARGET_SIGTRAP; |
|
2425 |
info.si_errno = 0; |
|
2426 |
info.si_code = TARGET_TRAP_BRKPT; |
|
2427 |
info._sifields._sigfault._addr = env->pc; |
|
2428 |
queue_signal(env, info.si_signo, &info); |
|
2429 |
break; |
|
2430 |
case 0x81: |
|
2431 |
/* BUGCHK */ |
|
2432 |
info.si_signo = TARGET_SIGTRAP; |
|
2433 |
info.si_errno = 0; |
|
2434 |
info.si_code = 0; |
|
2435 |
info._sifields._sigfault._addr = env->pc; |
|
2436 |
queue_signal(env, info.si_signo, &info); |
|
2437 |
break; |
|
2438 |
case 0x83: |
|
2439 |
/* CALLSYS */ |
|
2440 |
trapnr = env->ir[IR_V0]; |
|
2441 |
sysret = do_syscall(env, trapnr, |
|
2442 |
env->ir[IR_A0], env->ir[IR_A1], |
|
2443 |
env->ir[IR_A2], env->ir[IR_A3], |
|
2444 |
env->ir[IR_A4], env->ir[IR_A5]); |
|
2445 |
if (trapnr != TARGET_NR_sigreturn |
|
2446 |
&& trapnr != TARGET_NR_rt_sigreturn) { |
|
2447 |
env->ir[IR_V0] = (sysret < 0 ? -sysret : sysret); |
|
2448 |
env->ir[IR_A3] = (sysret < 0); |
|
2449 |
} |
|
2450 |
break; |
|
2451 |
case 0x86: |
|
2452 |
/* IMB */ |
|
2453 |
/* ??? We can probably elide the code using page_unprotect |
|
2454 |
that is checking for self-modifying code. Instead we |
|
2455 |
could simply call tb_flush here. Until we work out the |
|
2456 |
changes required to turn off the extra write protection, |
|
2457 |
this can be a no-op. */ |
|
2458 |
break; |
|
2459 |
case 0x9E: |
|
2460 |
/* RDUNIQUE */ |
|
2461 |
/* Handled in the translator for usermode. */ |
|
2462 |
abort(); |
|
2463 |
case 0x9F: |
|
2464 |
/* WRUNIQUE */ |
|
2465 |
/* Handled in the translator for usermode. */ |
|
2466 |
abort(); |
|
2467 |
case 0xAA: |
|
2468 |
/* GENTRAP */ |
|
2469 |
info.si_signo = TARGET_SIGFPE; |
|
2470 |
switch (env->ir[IR_A0]) { |
|
2471 |
case TARGET_GEN_INTOVF: |
|
2472 |
info.si_code = TARGET_FPE_INTOVF; |
|
2473 |
break; |
|
2474 |
case TARGET_GEN_INTDIV: |
|
2475 |
info.si_code = TARGET_FPE_INTDIV; |
|
2476 |
break; |
|
2477 |
case TARGET_GEN_FLTOVF: |
|
2478 |
info.si_code = TARGET_FPE_FLTOVF; |
|
2479 |
break; |
|
2480 |
case TARGET_GEN_FLTUND: |
|
2481 |
info.si_code = TARGET_FPE_FLTUND; |
|
2482 |
break; |
|
2483 |
case TARGET_GEN_FLTINV: |
|
2484 |
info.si_code = TARGET_FPE_FLTINV; |
|
2485 |
break; |
|
2486 |
case TARGET_GEN_FLTINE: |
|
2487 |
info.si_code = TARGET_FPE_FLTRES; |
|
2488 |
break; |
|
2489 |
case TARGET_GEN_ROPRAND: |
|
2490 |
info.si_code = 0; |
|
2491 |
break; |
|
2492 |
default: |
|
2493 |
info.si_signo = TARGET_SIGTRAP; |
|
2494 |
info.si_code = 0; |
|
2495 |
break; |
|
2496 |
} |
|
2497 |
info.si_errno = 0; |
|
2498 |
info._sifields._sigfault._addr = env->pc; |
|
2499 |
queue_signal(env, info.si_signo, &info); |
|
2500 |
break; |
|
2501 |
default: |
|
2502 |
goto do_sigill; |
|
2503 |
} |
|
2409 | 2504 |
break; |
2410 | 2505 |
case EXCP_CALL_PALP ... (EXCP_CALL_PALE - 1): |
2411 |
fprintf(stderr, "Privileged call to PALcode\n"); |
|
2412 |
exit(1); |
|
2413 |
break; |
|
2506 |
goto do_sigill; |
|
2414 | 2507 |
case EXCP_DEBUG: |
2415 |
{ |
|
2416 |
int sig; |
|
2417 |
|
|
2418 |
sig = gdb_handlesig (env, TARGET_SIGTRAP); |
|
2419 |
if (sig) |
|
2420 |
{ |
|
2421 |
info.si_signo = sig; |
|
2422 |
info.si_errno = 0; |
|
2423 |
info.si_code = TARGET_TRAP_BRKPT; |
|
2424 |
queue_signal(env, info.si_signo, &info); |
|
2425 |
} |
|
2508 |
info.si_signo = gdb_handlesig (env, TARGET_SIGTRAP); |
|
2509 |
if (info.si_signo) { |
|
2510 |
info.si_errno = 0; |
|
2511 |
info.si_code = TARGET_TRAP_BRKPT; |
|
2512 |
queue_signal(env, info.si_signo, &info); |
|
2426 | 2513 |
} |
2427 | 2514 |
break; |
2428 | 2515 |
default: |
b/linux-user/signal.c | ||
---|---|---|
4410 | 4410 |
return 0; |
4411 | 4411 |
} |
4412 | 4412 |
|
4413 |
#elif defined(TARGET_ALPHA) |
|
4414 |
|
|
4415 |
struct target_sigcontext { |
|
4416 |
abi_long sc_onstack; |
|
4417 |
abi_long sc_mask; |
|
4418 |
abi_long sc_pc; |
|
4419 |
abi_long sc_ps; |
|
4420 |
abi_long sc_regs[32]; |
|
4421 |
abi_long sc_ownedfp; |
|
4422 |
abi_long sc_fpregs[32]; |
|
4423 |
abi_ulong sc_fpcr; |
|
4424 |
abi_ulong sc_fp_control; |
|
4425 |
abi_ulong sc_reserved1; |
|
4426 |
abi_ulong sc_reserved2; |
|
4427 |
abi_ulong sc_ssize; |
|
4428 |
abi_ulong sc_sbase; |
|
4429 |
abi_ulong sc_traparg_a0; |
|
4430 |
abi_ulong sc_traparg_a1; |
|
4431 |
abi_ulong sc_traparg_a2; |
|
4432 |
abi_ulong sc_fp_trap_pc; |
|
4433 |
abi_ulong sc_fp_trigger_sum; |
|
4434 |
abi_ulong sc_fp_trigger_inst; |
|
4435 |
}; |
|
4436 |
|
|
4437 |
struct target_ucontext { |
|
4438 |
abi_ulong uc_flags; |
|
4439 |
abi_ulong uc_link; |
|
4440 |
abi_ulong uc_osf_sigmask; |
|
4441 |
target_stack_t uc_stack; |
|
4442 |
struct target_sigcontext uc_mcontext; |
|
4443 |
target_sigset_t uc_sigmask; |
|
4444 |
}; |
|
4445 |
|
|
4446 |
struct target_sigframe { |
|
4447 |
struct target_sigcontext sc; |
|
4448 |
unsigned int retcode[3]; |
|
4449 |
}; |
|
4450 |
|
|
4451 |
struct target_rt_sigframe { |
|
4452 |
target_siginfo_t info; |
|
4453 |
struct target_ucontext uc; |
|
4454 |
unsigned int retcode[3]; |
|
4455 |
}; |
|
4456 |
|
|
4457 |
#define INSN_MOV_R30_R16 0x47fe0410 |
|
4458 |
#define INSN_LDI_R0 0x201f0000 |
|
4459 |
#define INSN_CALLSYS 0x00000083 |
|
4460 |
|
|
4461 |
static int setup_sigcontext(struct target_sigcontext *sc, CPUState *env, |
|
4462 |
abi_ulong frame_addr, target_sigset_t *set) |
|
4463 |
{ |
|
4464 |
int i, err = 0; |
|
4465 |
|
|
4466 |
err |= __put_user(on_sig_stack(frame_addr), &sc->sc_onstack); |
|
4467 |
err |= __put_user(set->sig[0], &sc->sc_mask); |
|
4468 |
err |= __put_user(env->pc, &sc->sc_pc); |
|
4469 |
err |= __put_user(8, &sc->sc_ps); |
|
4470 |
|
|
4471 |
for (i = 0; i < 31; ++i) { |
|
4472 |
err |= __put_user(env->ir[i], &sc->sc_regs[i]); |
|
4473 |
} |
|
4474 |
err |= __put_user(0, &sc->sc_regs[31]); |
|
4475 |
|
|
4476 |
for (i = 0; i < 31; ++i) { |
|
4477 |
err |= __put_user(env->fir[i], &sc->sc_fpregs[i]); |
|
4478 |
} |
|
4479 |
err |= __put_user(0, &sc->sc_fpregs[31]); |
|
4480 |
err |= __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr); |
|
4481 |
|
|
4482 |
err |= __put_user(0, &sc->sc_traparg_a0); /* FIXME */ |
|
4483 |
err |= __put_user(0, &sc->sc_traparg_a1); /* FIXME */ |
|
4484 |
err |= __put_user(0, &sc->sc_traparg_a2); /* FIXME */ |
|
4485 |
|
|
4486 |
return err; |
|
4487 |
} |
|
4488 |
|
|
4489 |
static int restore_sigcontext(CPUState *env, struct target_sigcontext *sc) |
|
4490 |
{ |
|
4491 |
uint64_t fpcr; |
|
4492 |
int i, err = 0; |
|
4493 |
|
|
4494 |
err |= __get_user(env->pc, &sc->sc_pc); |
|
4495 |
|
|
4496 |
for (i = 0; i < 31; ++i) { |
|
4497 |
err |= __get_user(env->ir[i], &sc->sc_regs[i]); |
|
4498 |
} |
|
4499 |
for (i = 0; i < 31; ++i) { |
|
4500 |
err |= __get_user(env->fir[i], &sc->sc_fpregs[i]); |
|
4501 |
} |
|
4502 |
|
|
4503 |
err |= __get_user(fpcr, &sc->sc_fpcr); |
|
4504 |
cpu_alpha_store_fpcr(env, fpcr); |
|
4505 |
|
|
4506 |
return err; |
|
4507 |
} |
|
4508 |
|
|
4509 |
static inline abi_ulong get_sigframe(struct target_sigaction *sa, |
|
4510 |
CPUState *env, unsigned long framesize) |
|
4511 |
{ |
|
4512 |
abi_ulong sp = env->ir[IR_SP]; |
|
4513 |
|
|
4514 |
/* This is the X/Open sanctioned signal stack switching. */ |
|
4515 |
if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) { |
|
4516 |
sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; |
|
4517 |
} |
|
4518 |
return (sp - framesize) & -32; |
|
4519 |
} |
|
4520 |
|
|
4521 |
static void setup_frame(int sig, struct target_sigaction *ka, |
|
4522 |
target_sigset_t *set, CPUState *env) |
|
4523 |
{ |
|
4524 |
abi_ulong frame_addr, r26; |
|
4525 |
struct target_sigframe *frame; |
|
4526 |
int err = 0; |
|
4527 |
|
|
4528 |
frame_addr = get_sigframe(ka, env, sizeof(*frame)); |
|
4529 |
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { |
|
4530 |
goto give_sigsegv; |
|
4531 |
} |
|
4532 |
|
|
4533 |
err |= setup_sigcontext(&frame->sc, env, frame_addr, set); |
|
4534 |
|
|
4535 |
if (ka->sa_restorer) { |
|
4536 |
r26 = ka->sa_restorer; |
|
4537 |
} else { |
|
4538 |
err |= __put_user(INSN_MOV_R30_R16, &frame->retcode[0]); |
|
4539 |
err |= __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn, |
|
4540 |
&frame->retcode[1]); |
|
4541 |
err |= __put_user(INSN_CALLSYS, &frame->retcode[2]); |
|
4542 |
/* imb() */ |
|
4543 |
r26 = frame_addr; |
|
4544 |
} |
|
4545 |
|
|
4546 |
unlock_user_struct(frame, frame_addr, 1); |
|
4547 |
|
|
4548 |
if (err) { |
|
4549 |
give_sigsegv: |
|
4550 |
if (sig == TARGET_SIGSEGV) { |
|
4551 |
ka->_sa_handler = TARGET_SIG_DFL; |
|
4552 |
} |
|
4553 |
force_sig(TARGET_SIGSEGV); |
|
4554 |
} |
|
4555 |
|
|
4556 |
env->ir[IR_RA] = r26; |
|
4557 |
env->ir[IR_PV] = env->pc = ka->_sa_handler; |
|
4558 |
env->ir[IR_A0] = sig; |
|
4559 |
env->ir[IR_A1] = 0; |
|
4560 |
env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc); |
|
4561 |
env->ir[IR_SP] = frame_addr; |
|
4562 |
} |
|
4563 |
|
|
4564 |
static void setup_rt_frame(int sig, struct target_sigaction *ka, |
|
4565 |
target_siginfo_t *info, |
|
4566 |
target_sigset_t *set, CPUState *env) |
|
4567 |
{ |
|
4568 |
abi_ulong frame_addr, r26; |
|
4569 |
struct target_rt_sigframe *frame; |
|
4570 |
int i, err = 0; |
|
4571 |
|
|
4572 |
frame_addr = get_sigframe(ka, env, sizeof(*frame)); |
|
4573 |
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { |
|
4574 |
goto give_sigsegv; |
|
4575 |
} |
|
4576 |
|
|
4577 |
err |= copy_siginfo_to_user(&frame->info, info); |
|
4578 |
|
|
4579 |
err |= __put_user(0, &frame->uc.uc_flags); |
|
4580 |
err |= __put_user(0, &frame->uc.uc_link); |
|
4581 |
err |= __put_user(set->sig[0], &frame->uc.uc_osf_sigmask); |
|
4582 |
err |= __put_user(target_sigaltstack_used.ss_sp, |
|
4583 |
&frame->uc.uc_stack.ss_sp); |
|
4584 |
err |= __put_user(sas_ss_flags(env->ir[IR_SP]), |
|
4585 |
&frame->uc.uc_stack.ss_flags); |
|
4586 |
err |= __put_user(target_sigaltstack_used.ss_size, |
|
4587 |
&frame->uc.uc_stack.ss_size); |
|
4588 |
err |= setup_sigcontext(&frame->uc.uc_mcontext, env, frame_addr, set); |
|
4589 |
for (i = 0; i < TARGET_NSIG_WORDS; ++i) { |
|
4590 |
err |= __put_user(set->sig[i], &frame->uc.uc_sigmask.sig[i]); |
|
4591 |
} |
|
4592 |
|
|
4593 |
if (ka->sa_restorer) { |
|
4594 |
r26 = ka->sa_restorer; |
|
4595 |
} else { |
|
4596 |
err |= __put_user(INSN_MOV_R30_R16, &frame->retcode[0]); |
|
4597 |
err |= __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn, |
|
4598 |
&frame->retcode[1]); |
|
4599 |
err |= __put_user(INSN_CALLSYS, &frame->retcode[2]); |
|
4600 |
/* imb(); */ |
|
4601 |
r26 = frame_addr; |
|
4602 |
} |
|
4603 |
|
|
4604 |
if (err) { |
|
4605 |
give_sigsegv: |
|
4606 |
if (sig == TARGET_SIGSEGV) { |
|
4607 |
ka->_sa_handler = TARGET_SIG_DFL; |
|
4608 |
} |
|
4609 |
force_sig(TARGET_SIGSEGV); |
|
4610 |
} |
|
4611 |
|
|
4612 |
env->ir[IR_RA] = r26; |
|
4613 |
env->ir[IR_PV] = env->pc = ka->_sa_handler; |
|
4614 |
env->ir[IR_A0] = sig; |
|
4615 |
env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info); |
|
4616 |
env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc); |
|
4617 |
env->ir[IR_SP] = frame_addr; |
|
4618 |
} |
|
4619 |
|
|
4620 |
long do_sigreturn(CPUState *env) |
|
4621 |
{ |
|
4622 |
struct target_sigcontext *sc; |
|
4623 |
abi_ulong sc_addr = env->ir[IR_A0]; |
|
4624 |
target_sigset_t target_set; |
|
4625 |
sigset_t set; |
|
4626 |
|
|
4627 |
if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) { |
|
4628 |
goto badframe; |
|
4629 |
} |
|
4630 |
|
|
4631 |
target_sigemptyset(&target_set); |
|
4632 |
if (__get_user(target_set.sig[0], &sc->sc_mask)) { |
|
4633 |
goto badframe; |
|
4634 |
} |
|
4635 |
|
|
4636 |
target_to_host_sigset_internal(&set, &target_set); |
|
4637 |
sigprocmask(SIG_SETMASK, &set, NULL); |
|
4638 |
|
|
4639 |
if (restore_sigcontext(env, sc)) { |
|
4640 |
goto badframe; |
|
4641 |
} |
|
4642 |
unlock_user_struct(sc, sc_addr, 0); |
|
4643 |
return env->ir[IR_V0]; |
|
4644 |
|
|
4645 |
badframe: |
|
4646 |
unlock_user_struct(sc, sc_addr, 0); |
|
4647 |
force_sig(TARGET_SIGSEGV); |
|
4648 |
} |
|
4649 |
|
|
4650 |
long do_rt_sigreturn(CPUState *env) |
|
4651 |
{ |
|
4652 |
abi_ulong frame_addr = env->ir[IR_A0]; |
|
4653 |
struct target_rt_sigframe *frame; |
|
4654 |
sigset_t set; |
|
4655 |
|
|
4656 |
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { |
|
4657 |
goto badframe; |
|
4658 |
} |
|
4659 |
target_to_host_sigset(&set, &frame->uc.uc_sigmask); |
|
4660 |
sigprocmask(SIG_SETMASK, &set, NULL); |
|
4661 |
|
|
4662 |
if (restore_sigcontext(env, &frame->uc.uc_mcontext)) { |
|
4663 |
goto badframe; |
|
4664 |
} |
|
4665 |
if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe, |
|
4666 |
uc.uc_stack), |
|
4667 |
0, env->ir[IR_SP]) == -EFAULT) { |
|
4668 |
goto badframe; |
|
4669 |
} |
|
4670 |
|
|
4671 |
unlock_user_struct(frame, frame_addr, 0); |
|
4672 |
return env->ir[IR_V0]; |
|
4673 |
|
|
4674 |
|
|
4675 |
badframe: |
|
4676 |
unlock_user_struct(frame, frame_addr, 0); |
|
4677 |
force_sig(TARGET_SIGSEGV); |
|
4678 |
} |
|
4679 |
|
|
4413 | 4680 |
#else |
4414 | 4681 |
|
4415 | 4682 |
static void setup_frame(int sig, struct target_sigaction *ka, |
b/linux-user/syscall.c | ||
---|---|---|
4775 | 4775 |
#ifdef TARGET_NR_sigaction |
4776 | 4776 |
case TARGET_NR_sigaction: |
4777 | 4777 |
{ |
4778 |
#if !defined(TARGET_MIPS) |
|
4778 |
#if defined(TARGET_ALPHA) |
|
4779 |
struct target_sigaction act, oact, *pact = 0; |
|
4779 | 4780 |
struct target_old_sigaction *old_act; |
4780 |
struct target_sigaction act, oact, *pact; |
|
4781 | 4781 |
if (arg2) { |
4782 | 4782 |
if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) |
4783 | 4783 |
goto efault; |
4784 | 4784 |
act._sa_handler = old_act->_sa_handler; |
4785 | 4785 |
target_siginitset(&act.sa_mask, old_act->sa_mask); |
4786 | 4786 |
act.sa_flags = old_act->sa_flags; |
4787 |
act.sa_restorer = old_act->sa_restorer;
|
|
4787 |
act.sa_restorer = 0;
|
|
4788 | 4788 |
unlock_user_struct(old_act, arg2, 0); |
4789 | 4789 |
pact = &act; |
4790 |
} else { |
|
4791 |
pact = NULL; |
|
4792 | 4790 |
} |
4793 | 4791 |
ret = get_errno(do_sigaction(arg1, pact, &oact)); |
4794 | 4792 |
if (!is_error(ret) && arg3) { |
... | ... | |
4797 | 4795 |
old_act->_sa_handler = oact._sa_handler; |
4798 | 4796 |
old_act->sa_mask = oact.sa_mask.sig[0]; |
4799 | 4797 |
old_act->sa_flags = oact.sa_flags; |
4800 |
old_act->sa_restorer = oact.sa_restorer; |
|
4801 | 4798 |
unlock_user_struct(old_act, arg3, 1); |
4802 | 4799 |
} |
4803 |
#else
|
|
4800 |
#elif defined(TARGET_MIPS)
|
|
4804 | 4801 |
struct target_sigaction act, oact, *pact, *old_act; |
4805 | 4802 |
|
4806 | 4803 |
if (arg2) { |
... | ... | |
4828 | 4825 |
old_act->sa_mask.sig[3] = 0; |
4829 | 4826 |
unlock_user_struct(old_act, arg3, 1); |
4830 | 4827 |
} |
4828 |
#else |
|
4829 |
struct target_old_sigaction *old_act; |
|
4830 |
struct target_sigaction act, oact, *pact; |
|
4831 |
if (arg2) { |
|
4832 |
if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) |
|
4833 |
goto efault; |
|
4834 |
act._sa_handler = old_act->_sa_handler; |
|
4835 |
target_siginitset(&act.sa_mask, old_act->sa_mask); |
|
4836 |
act.sa_flags = old_act->sa_flags; |
|
4837 |
act.sa_restorer = old_act->sa_restorer; |
|
4838 |
unlock_user_struct(old_act, arg2, 0); |
|
4839 |
pact = &act; |
|
4840 |
} else { |
|
4841 |
pact = NULL; |
|
4842 |
} |
|
4843 |
ret = get_errno(do_sigaction(arg1, pact, &oact)); |
|
4844 |
if (!is_error(ret) && arg3) { |
|
4845 |
if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) |
|
4846 |
goto efault; |
|
4847 |
old_act->_sa_handler = oact._sa_handler; |
|
4848 |
old_act->sa_mask = oact.sa_mask.sig[0]; |
|
4849 |
old_act->sa_flags = oact.sa_flags; |
|
4850 |
old_act->sa_restorer = oact.sa_restorer; |
|
4851 |
unlock_user_struct(old_act, arg3, 1); |
|
4852 |
} |
|
4831 | 4853 |
#endif |
4832 | 4854 |
} |
4833 | 4855 |
break; |
4834 | 4856 |
#endif |
4835 | 4857 |
case TARGET_NR_rt_sigaction: |
4836 | 4858 |
{ |
4859 |
#if defined(TARGET_ALPHA) |
|
4860 |
struct target_sigaction act, oact, *pact = 0; |
|
4861 |
struct target_rt_sigaction *rt_act; |
|
4862 |
/* ??? arg4 == sizeof(sigset_t). */ |
|
4863 |
if (arg2) { |
|
4864 |
if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1)) |
|
4865 |
goto efault; |
|
4866 |
act._sa_handler = rt_act->_sa_handler; |
|
4867 |
act.sa_mask = rt_act->sa_mask; |
|
4868 |
act.sa_flags = rt_act->sa_flags; |
|
4869 |
act.sa_restorer = arg5; |
|
4870 |
unlock_user_struct(rt_act, arg2, 0); |
|
4871 |
pact = &act; |
|
4872 |
} |
|
4873 |
ret = get_errno(do_sigaction(arg1, pact, &oact)); |
|
4874 |
if (!is_error(ret) && arg3) { |
|
4875 |
if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0)) |
|
4876 |
goto efault; |
|
4877 |
rt_act->_sa_handler = oact._sa_handler; |
|
4878 |
rt_act->sa_mask = oact.sa_mask; |
|
4879 |
rt_act->sa_flags = oact.sa_flags; |
|
4880 |
unlock_user_struct(rt_act, arg3, 1); |
|
4881 |
} |
|
4882 |
#else |
|
4837 | 4883 |
struct target_sigaction *act; |
4838 | 4884 |
struct target_sigaction *oact; |
4839 | 4885 |
|
... | ... | |
4855 | 4901 |
unlock_user_struct(act, arg2, 0); |
4856 | 4902 |
if (oact) |
4857 | 4903 |
unlock_user_struct(oact, arg3, 1); |
4904 |
#endif |
|
4858 | 4905 |
} |
4859 | 4906 |
break; |
4860 | 4907 |
#ifdef TARGET_NR_sgetmask /* not on alpha */ |
b/linux-user/syscall_defs.h | ||
---|---|---|
472 | 472 |
|
473 | 473 |
#endif |
474 | 474 |
|
475 |
#if defined(TARGET_MIPS) |
|
475 |
#if defined(TARGET_ALPHA) |
|
476 |
struct target_old_sigaction { |
|
477 |
abi_ulong _sa_handler; |
|
478 |
abi_ulong sa_mask; |
|
479 |
abi_ulong sa_flags; |
|
480 |
}; |
|
481 |
|
|
482 |
struct target_rt_sigaction { |
|
483 |
abi_ulong _sa_handler; |
|
484 |
abi_ulong sa_flags; |
|
485 |
target_sigset_t sa_mask; |
|
486 |
}; |
|
476 | 487 |
|
488 |
/* This is the struct used inside the kernel. The ka_restorer |
|
489 |
field comes from the 5th argument to sys_rt_sigaction. */ |
|
490 |
struct target_sigaction { |
|
491 |
abi_ulong _sa_handler; |
|
492 |
abi_ulong sa_flags; |
|
493 |
target_sigset_t sa_mask; |
|
494 |
abi_ulong sa_restorer; |
|
495 |
}; |
|
496 |
#elif defined(TARGET_MIPS) |
|
477 | 497 |
struct target_sigaction { |
478 | 498 |
uint32_t sa_flags; |
479 | 499 |
#if defined(TARGET_ABI_MIPSN32) |
... | ... | |
483 | 503 |
#endif |
484 | 504 |
target_sigset_t sa_mask; |
485 | 505 |
}; |
486 |
|
|
487 | 506 |
#else |
488 | 507 |
struct target_old_sigaction { |
489 | 508 |
abi_ulong _sa_handler; |
b/target-alpha/cpu.h | ||
---|---|---|
511 | 511 |
void cpu_alpha_store_fpcr (CPUState *env, uint64_t val); |
512 | 512 |
int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp); |
513 | 513 |
int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp); |
514 |
void pal_init (CPUState *env); |
|
515 | 514 |
#if !defined (CONFIG_USER_ONLY) |
515 |
void pal_init (CPUState *env); |
|
516 | 516 |
void call_pal (CPUState *env); |
517 |
#else |
|
518 |
void call_pal (CPUState *env, int palcode); |
|
519 | 517 |
#endif |
520 | 518 |
|
521 | 519 |
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb) |
b/target-alpha/translate.c | ||
---|---|---|
3094 | 3094 |
env->ps |= 1 << 3; |
3095 | 3095 |
cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD |
3096 | 3096 |
| FPCR_UNFD | FPCR_INED | FPCR_DNOD)); |
3097 |
#endif
|
|
3097 |
#else
|
|
3098 | 3098 |
pal_init(env); |
3099 |
#endif |
|
3099 | 3100 |
|
3100 | 3101 |
/* Initialize IPR */ |
3101 | 3102 |
#if defined (CONFIG_USER_ONLY) |
Also available in: Unified diff