1/* 2 * Copyright (C) 2004 PathScale, Inc 3 * Licensed under the GPL 4 */ 5 6#include <errno.h> 7#include <string.h> 8#include "sysdep/ptrace_user.h" 9#include "sysdep/ptrace.h" 10#include "uml-config.h" 11#include "skas_ptregs.h" 12#include "registers.h" 13#include "longjmp.h" 14#include "user.h" 15 16/* These are set once at boot time and not changed thereafter */ 17 18static unsigned long exec_regs[MAX_REG_NR]; 19static unsigned long exec_fp_regs[HOST_FP_SIZE]; 20static unsigned long exec_fpx_regs[HOST_XFP_SIZE]; 21static int have_fpx_regs = 1; 22 23void init_thread_registers(union uml_pt_regs *to) 24{ 25 memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); 26 memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); 27 if(have_fpx_regs) 28 memcpy(to->skas.xfp, exec_fpx_regs, sizeof(to->skas.xfp)); 29} 30 31int save_fp_registers(int pid, unsigned long *fp_regs) 32{ 33 if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) 34 return -errno; 35 return 0; 36} 37 38int restore_fp_registers(int pid, unsigned long *fp_regs) 39{ 40 if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) 41 return -errno; 42 return 0; 43} 44 45static int move_registers(int pid, int int_op, union uml_pt_regs *regs, 46 int fp_op, unsigned long *fp_regs) 47{ 48 if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) 49 return -errno; 50 51 if(ptrace(fp_op, pid, 0, fp_regs) < 0) 52 return -errno; 53 54 return 0; 55} 56 57void save_registers(int pid, union uml_pt_regs *regs) 58{ 59 unsigned long *fp_regs; 60 int err, fp_op; 61 62 if(have_fpx_regs){ 63 fp_op = PTRACE_GETFPXREGS; 64 fp_regs = regs->skas.xfp; 65 } 66 else { 67 fp_op = PTRACE_GETFPREGS; 68 fp_regs = regs->skas.fp; 69 } 70 71 err = move_registers(pid, PTRACE_GETREGS, regs, fp_op, fp_regs); 72 if(err) 73 panic("save_registers - saving registers failed, errno = %d\n", 74 -err); 75} 76 77void restore_registers(int pid, union uml_pt_regs *regs) 78{ 79 unsigned long *fp_regs; 80 int err, fp_op; 81 82 if(have_fpx_regs){ 83 fp_op = PTRACE_SETFPXREGS; 84 fp_regs = regs->skas.xfp; 85 } 86 else { 87 fp_op = PTRACE_SETFPREGS; 88 fp_regs = regs->skas.fp; 89 } 90 91 err = move_registers(pid, PTRACE_SETREGS, regs, fp_op, fp_regs); 92 if(err) 93 panic("restore_registers - saving registers failed, " 94 "errno = %d\n", -err); 95} 96 97void init_registers(int pid) 98{ 99 int err; 100 101 memset(exec_regs, 0, sizeof(exec_regs)); 102 err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); 103 if(err) 104 panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", 105 errno); 106 107 errno = 0; 108 err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs); 109 if(!err) 110 return; 111 if(errno != EIO) 112 panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", 113 errno); 114 115 have_fpx_regs = 0; 116 117 err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); 118 if(err) 119 panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", 120 errno); 121} 122 123void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) 124{ 125 memcpy(regs, exec_regs, sizeof(exec_regs)); 126 if(fp_regs != NULL) 127 memcpy(fp_regs, exec_fp_regs, 128 HOST_FP_SIZE * sizeof(unsigned long)); 129} 130 131unsigned long get_thread_reg(int reg, jmp_buf *buf) 132{ 133 switch(reg){ 134 case EIP: return buf[0]->__eip; 135 case UESP: return buf[0]->__esp; 136 case EBP: return buf[0]->__ebp; 137 default: 138 printk("get_thread_regs - unknown register %d\n", reg); 139 return 0; 140 } 141} 142