aboutsummaryrefslogtreecommitdiff
path: root/linux-user/syscall.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2009-12-09 15:56:29 -0800
committerAurelien Jarno <aurelien@aurel32.net>2009-12-13 20:32:36 +0100
commitba0e276db4b51bd2255a5d5ff8902c70d32ade40 (patch)
tree7366b9dcf6b064f59e4879bc517906c3af5fbdb2 /linux-user/syscall.c
parent990b3e19013ebd36b3fb9af97aaa67f7bc490c15 (diff)
target-alpha: Fixes for alpha-linux syscalls.
1. Add correct definitions of error numbers. 2. Implement SYS_osf_sigprocmask 3. Implement SYS_osf_get/setsysinfo for IEEE_FP_CONTROL. This last requires exposing the FPCR value to do_syscall. Since this value is actually split up into the float_status, expose routines from helper.c to access it. Finally, also add a float_exception_mask field to float_status. We don't actually use it to control delivery of exceptions to the emulator yet, but simply hold the value that we placed there when loading/storing the FPCR. Signed-off-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r--linux-user/syscall.c137
1 files changed, 127 insertions, 10 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e38552ca1c..1acf1f5b64 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6390,25 +6390,142 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
/* Alpha specific */
case TARGET_NR_getxuid:
- {
- uid_t euid;
- euid=geteuid();
- ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
- }
+ {
+ uid_t euid;
+ euid=geteuid();
+ ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
+ }
ret = get_errno(getuid());
break;
#endif
#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
/* Alpha specific */
case TARGET_NR_getxgid:
- {
- uid_t egid;
- egid=getegid();
- ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
- }
+ {
+ uid_t egid;
+ egid=getegid();
+ ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
+ }
ret = get_errno(getgid());
break;
#endif
+#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
+ /* Alpha specific */
+ case TARGET_NR_osf_getsysinfo:
+ ret = -TARGET_EOPNOTSUPP;
+ switch (arg1) {
+ case TARGET_GSI_IEEE_FP_CONTROL:
+ {
+ uint64_t swcr, fpcr = cpu_alpha_load_fpcr (cpu_env);
+
+ /* Copied from linux ieee_fpcr_to_swcr. */
+ swcr = (fpcr >> 35) & SWCR_STATUS_MASK;
+ swcr |= (fpcr >> 36) & SWCR_MAP_DMZ;
+ swcr |= (~fpcr >> 48) & (SWCR_TRAP_ENABLE_INV
+ | SWCR_TRAP_ENABLE_DZE
+ | SWCR_TRAP_ENABLE_OVF);
+ swcr |= (~fpcr >> 57) & (SWCR_TRAP_ENABLE_UNF
+ | SWCR_TRAP_ENABLE_INE);
+ swcr |= (fpcr >> 47) & SWCR_MAP_UMZ;
+ swcr |= (~fpcr >> 41) & SWCR_TRAP_ENABLE_DNO;
+
+ if (put_user_u64 (swcr, arg2))
+ goto efault;
+ ret = 0;
+ }
+ break;
+
+ /* case GSI_IEEE_STATE_AT_SIGNAL:
+ -- Not implemented in linux kernel.
+ case GSI_UACPROC:
+ -- Retrieves current unaligned access state; not much used.
+ case GSI_PROC_TYPE:
+ -- Retrieves implver information; surely not used.
+ case GSI_GET_HWRPB:
+ -- Grabs a copy of the HWRPB; surely not used.
+ */
+ }
+ break;
+#endif
+#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
+ /* Alpha specific */
+ case TARGET_NR_osf_setsysinfo:
+ ret = -TARGET_EOPNOTSUPP;
+ switch (arg1) {
+ case TARGET_SSI_IEEE_FP_CONTROL:
+ case TARGET_SSI_IEEE_RAISE_EXCEPTION:
+ {
+ uint64_t swcr, fpcr, orig_fpcr;
+
+ if (get_user_u64 (swcr, arg2))
+ goto efault;
+ orig_fpcr = cpu_alpha_load_fpcr (cpu_env);
+ fpcr = orig_fpcr & FPCR_DYN_MASK;
+
+ /* Copied from linux ieee_swcr_to_fpcr. */
+ fpcr |= (swcr & SWCR_STATUS_MASK) << 35;
+ fpcr |= (swcr & SWCR_MAP_DMZ) << 36;
+ fpcr |= (~swcr & (SWCR_TRAP_ENABLE_INV
+ | SWCR_TRAP_ENABLE_DZE
+ | SWCR_TRAP_ENABLE_OVF)) << 48;
+ fpcr |= (~swcr & (SWCR_TRAP_ENABLE_UNF
+ | SWCR_TRAP_ENABLE_INE)) << 57;
+ fpcr |= (swcr & SWCR_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0);
+ fpcr |= (~swcr & SWCR_TRAP_ENABLE_DNO) << 41;
+
+ cpu_alpha_store_fpcr (cpu_env, fpcr);
+ ret = 0;
+
+ if (arg1 == TARGET_SSI_IEEE_RAISE_EXCEPTION) {
+ /* Old exceptions are not signaled. */
+ fpcr &= ~(orig_fpcr & FPCR_STATUS_MASK);
+
+ /* If any exceptions set by this call, and are unmasked,
+ send a signal. */
+ /* ??? FIXME */
+ }
+ }
+ break;
+
+ /* case SSI_NVPAIRS:
+ -- Used with SSIN_UACPROC to enable unaligned accesses.
+ case SSI_IEEE_STATE_AT_SIGNAL:
+ case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
+ -- Not implemented in linux kernel
+ */
+ }
+ break;
+#endif
+#ifdef TARGET_NR_osf_sigprocmask
+ /* Alpha specific. */
+ case TARGET_NR_osf_sigprocmask:
+ {
+ abi_ulong mask;
+ int how = arg1;
+ sigset_t set, oldset;
+
+ switch(arg1) {
+ case TARGET_SIG_BLOCK:
+ how = SIG_BLOCK;
+ break;
+ case TARGET_SIG_UNBLOCK:
+ how = SIG_UNBLOCK;
+ break;
+ case TARGET_SIG_SETMASK:
+ how = SIG_SETMASK;
+ break;
+ default:
+ ret = -TARGET_EINVAL;
+ goto fail;
+ }
+ mask = arg2;
+ target_to_host_old_sigset(&set, &mask);
+ sigprocmask(arg1, &set, &oldset);
+ host_to_target_old_sigset(&mask, &oldset);
+ ret = mask;
+ }
+ break;
+#endif
#ifdef TARGET_NR_getgid32
case TARGET_NR_getgid32: