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