registers.c 3.2 KB

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