linux/arch/x86/um/os-Linux/registers.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2004 PathScale, Inc
   3 * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   4 * Licensed under the GPL
   5 */
   6
   7#include <errno.h>
   8#include <sys/ptrace.h>
   9#ifdef __i386__
  10#include <sys/user.h>
  11#endif
  12#include <longjmp.h>
  13#include <sysdep/ptrace_user.h>
  14#include <sys/uio.h>
  15#include <asm/sigcontext.h>
  16#include <linux/elf.h>
  17
  18int have_xstate_support;
  19
  20int save_i387_registers(int pid, unsigned long *fp_regs)
  21{
  22        if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
  23                return -errno;
  24        return 0;
  25}
  26
  27int save_fp_registers(int pid, unsigned long *fp_regs)
  28{
  29        struct iovec iov;
  30
  31        if (have_xstate_support) {
  32                iov.iov_base = fp_regs;
  33                iov.iov_len = sizeof(struct _xstate);
  34                if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
  35                        return -errno;
  36                return 0;
  37        } else {
  38                return save_i387_registers(pid, fp_regs);
  39        }
  40}
  41
  42int restore_i387_registers(int pid, unsigned long *fp_regs)
  43{
  44        if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
  45                return -errno;
  46        return 0;
  47}
  48
  49int restore_fp_registers(int pid, unsigned long *fp_regs)
  50{
  51        struct iovec iov;
  52
  53        if (have_xstate_support) {
  54                iov.iov_base = fp_regs;
  55                iov.iov_len = sizeof(struct _xstate);
  56                if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
  57                        return -errno;
  58                return 0;
  59        } else {
  60                return restore_i387_registers(pid, fp_regs);
  61        }
  62}
  63
  64#ifdef __i386__
  65int have_fpx_regs = 1;
  66int save_fpx_registers(int pid, unsigned long *fp_regs)
  67{
  68        if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
  69                return -errno;
  70        return 0;
  71}
  72
  73int restore_fpx_registers(int pid, unsigned long *fp_regs)
  74{
  75        if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
  76                return -errno;
  77        return 0;
  78}
  79
  80int get_fp_registers(int pid, unsigned long *regs)
  81{
  82        if (have_fpx_regs)
  83                return save_fpx_registers(pid, regs);
  84        else
  85                return save_fp_registers(pid, regs);
  86}
  87
  88int put_fp_registers(int pid, unsigned long *regs)
  89{
  90        if (have_fpx_regs)
  91                return restore_fpx_registers(pid, regs);
  92        else
  93                return restore_fp_registers(pid, regs);
  94}
  95
  96void arch_init_registers(int pid)
  97{
  98        struct user_fpxregs_struct fpx_regs;
  99        int err;
 100
 101        err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
 102        if (!err)
 103                return;
 104
 105        if (errno != EIO)
 106                panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
 107                      errno);
 108
 109        have_fpx_regs = 0;
 110}
 111#else
 112
 113int get_fp_registers(int pid, unsigned long *regs)
 114{
 115        return save_fp_registers(pid, regs);
 116}
 117
 118int put_fp_registers(int pid, unsigned long *regs)
 119{
 120        return restore_fp_registers(pid, regs);
 121}
 122
 123void arch_init_registers(int pid)
 124{
 125        struct _xstate fp_regs;
 126        struct iovec iov;
 127
 128        iov.iov_base = &fp_regs;
 129        iov.iov_len = sizeof(struct _xstate);
 130        if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0)
 131                have_xstate_support = 1;
 132}
 133#endif
 134
 135unsigned long get_thread_reg(int reg, jmp_buf *buf)
 136{
 137        switch (reg) {
 138#ifdef __i386__
 139        case HOST_IP:
 140                return buf[0]->__eip;
 141        case HOST_SP:
 142                return buf[0]->__esp;
 143        case HOST_BP:
 144                return buf[0]->__ebp;
 145#else
 146        case HOST_IP:
 147                return buf[0]->__rip;
 148        case HOST_SP:
 149                return buf[0]->__rsp;
 150        case HOST_BP:
 151                return buf[0]->__rbp;
 152#endif
 153        default:
 154                printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
 155                       reg);
 156                return 0;
 157        }
 158}
 159