15c48b108SAl Viro /* 25c48b108SAl Viro * Copyright (C) 2004 PathScale, Inc 35c48b108SAl Viro * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 45c48b108SAl Viro * Licensed under the GPL 55c48b108SAl Viro */ 65c48b108SAl Viro 75c48b108SAl Viro #include <errno.h> 86f602afdSThomas Meyer #include <stdlib.h> 95c48b108SAl Viro #include <sys/ptrace.h> 1038b64aedSRichard Weinberger #ifdef __i386__ 115c48b108SAl Viro #include <sys/user.h> 1238b64aedSRichard Weinberger #endif 1337185b33SAl Viro #include <longjmp.h> 1437185b33SAl Viro #include <sysdep/ptrace_user.h> 15a78ff111SEli Cooper #include <sys/uio.h> 16a78ff111SEli Cooper #include <asm/sigcontext.h> 17a78ff111SEli Cooper #include <linux/elf.h> 18*dbba7f70SAl Viro #include <registers.h> 195c48b108SAl Viro 20a78ff111SEli Cooper int have_xstate_support; 21a78ff111SEli Cooper 22a78ff111SEli Cooper int save_i387_registers(int pid, unsigned long *fp_regs) 235c48b108SAl Viro { 245c48b108SAl Viro if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) 255c48b108SAl Viro return -errno; 265c48b108SAl Viro return 0; 275c48b108SAl Viro } 285c48b108SAl Viro 29a78ff111SEli Cooper int save_fp_registers(int pid, unsigned long *fp_regs) 30a78ff111SEli Cooper { 310a987645SFlorian Fainelli #ifdef PTRACE_GETREGSET 32a78ff111SEli Cooper struct iovec iov; 33a78ff111SEli Cooper 34a78ff111SEli Cooper if (have_xstate_support) { 35a78ff111SEli Cooper iov.iov_base = fp_regs; 366f602afdSThomas Meyer iov.iov_len = FP_SIZE * sizeof(unsigned long); 37a78ff111SEli Cooper if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) 38a78ff111SEli Cooper return -errno; 39a78ff111SEli Cooper return 0; 400a987645SFlorian Fainelli } else 410a987645SFlorian Fainelli #endif 42a78ff111SEli Cooper return save_i387_registers(pid, fp_regs); 43a78ff111SEli Cooper } 44a78ff111SEli Cooper 45a78ff111SEli Cooper int restore_i387_registers(int pid, unsigned long *fp_regs) 465c48b108SAl Viro { 475c48b108SAl Viro if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) 485c48b108SAl Viro return -errno; 495c48b108SAl Viro return 0; 505c48b108SAl Viro } 515c48b108SAl Viro 52a78ff111SEli Cooper int restore_fp_registers(int pid, unsigned long *fp_regs) 53a78ff111SEli Cooper { 540a987645SFlorian Fainelli #ifdef PTRACE_SETREGSET 55a78ff111SEli Cooper struct iovec iov; 56a78ff111SEli Cooper if (have_xstate_support) { 57a78ff111SEli Cooper iov.iov_base = fp_regs; 586f602afdSThomas Meyer iov.iov_len = FP_SIZE * sizeof(unsigned long); 59a78ff111SEli Cooper if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) 60a78ff111SEli Cooper return -errno; 61a78ff111SEli Cooper return 0; 620a987645SFlorian Fainelli } else 630a987645SFlorian Fainelli #endif 64a78ff111SEli Cooper return restore_i387_registers(pid, fp_regs); 65a78ff111SEli Cooper } 66a78ff111SEli Cooper 675c48b108SAl Viro #ifdef __i386__ 685c48b108SAl Viro int have_fpx_regs = 1; 695c48b108SAl Viro int save_fpx_registers(int pid, unsigned long *fp_regs) 705c48b108SAl Viro { 715c48b108SAl Viro if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0) 725c48b108SAl Viro return -errno; 735c48b108SAl Viro return 0; 745c48b108SAl Viro } 755c48b108SAl Viro 765c48b108SAl Viro int restore_fpx_registers(int pid, unsigned long *fp_regs) 775c48b108SAl Viro { 785c48b108SAl Viro if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0) 795c48b108SAl Viro return -errno; 805c48b108SAl Viro return 0; 815c48b108SAl Viro } 825c48b108SAl Viro 835c48b108SAl Viro int get_fp_registers(int pid, unsigned long *regs) 845c48b108SAl Viro { 855c48b108SAl Viro if (have_fpx_regs) 865c48b108SAl Viro return save_fpx_registers(pid, regs); 875c48b108SAl Viro else 885c48b108SAl Viro return save_fp_registers(pid, regs); 895c48b108SAl Viro } 905c48b108SAl Viro 915c48b108SAl Viro int put_fp_registers(int pid, unsigned long *regs) 925c48b108SAl Viro { 935c48b108SAl Viro if (have_fpx_regs) 945c48b108SAl Viro return restore_fpx_registers(pid, regs); 955c48b108SAl Viro else 965c48b108SAl Viro return restore_fp_registers(pid, regs); 975c48b108SAl Viro } 985c48b108SAl Viro 995c48b108SAl Viro void arch_init_registers(int pid) 1005c48b108SAl Viro { 1015c48b108SAl Viro struct user_fpxregs_struct fpx_regs; 1025c48b108SAl Viro int err; 1035c48b108SAl Viro 1045c48b108SAl Viro err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs); 1055c48b108SAl Viro if (!err) 1065c48b108SAl Viro return; 1075c48b108SAl Viro 1085c48b108SAl Viro if (errno != EIO) 1095c48b108SAl Viro panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", 1105c48b108SAl Viro errno); 1115c48b108SAl Viro 1125c48b108SAl Viro have_fpx_regs = 0; 1135c48b108SAl Viro } 1145c48b108SAl Viro #else 1155c48b108SAl Viro 1165c48b108SAl Viro int get_fp_registers(int pid, unsigned long *regs) 1175c48b108SAl Viro { 1185c48b108SAl Viro return save_fp_registers(pid, regs); 1195c48b108SAl Viro } 1205c48b108SAl Viro 1215c48b108SAl Viro int put_fp_registers(int pid, unsigned long *regs) 1225c48b108SAl Viro { 1235c48b108SAl Viro return restore_fp_registers(pid, regs); 1245c48b108SAl Viro } 1255c48b108SAl Viro 126a78ff111SEli Cooper void arch_init_registers(int pid) 127a78ff111SEli Cooper { 1280a987645SFlorian Fainelli #ifdef PTRACE_GETREGSET 1296f602afdSThomas Meyer void * fp_regs; 130a78ff111SEli Cooper struct iovec iov; 131a78ff111SEli Cooper 1326f602afdSThomas Meyer fp_regs = malloc(FP_SIZE * sizeof(unsigned long)); 1336f602afdSThomas Meyer if(fp_regs == NULL) 1346f602afdSThomas Meyer return; 1356f602afdSThomas Meyer 1366f602afdSThomas Meyer iov.iov_base = fp_regs; 1376f602afdSThomas Meyer iov.iov_len = FP_SIZE * sizeof(unsigned long); 138a78ff111SEli Cooper if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0) 139a78ff111SEli Cooper have_xstate_support = 1; 1406f602afdSThomas Meyer 1416f602afdSThomas Meyer free(fp_regs); 1420a987645SFlorian Fainelli #endif 143a78ff111SEli Cooper } 1445c48b108SAl Viro #endif 1455c48b108SAl Viro 1465c48b108SAl Viro unsigned long get_thread_reg(int reg, jmp_buf *buf) 1475c48b108SAl Viro { 1485c48b108SAl Viro switch (reg) { 1495c48b108SAl Viro #ifdef __i386__ 150a10c95d8SAl Viro case HOST_IP: 1515c48b108SAl Viro return buf[0]->__eip; 152a10c95d8SAl Viro case HOST_SP: 1535c48b108SAl Viro return buf[0]->__esp; 154a10c95d8SAl Viro case HOST_BP: 1555c48b108SAl Viro return buf[0]->__ebp; 1565c48b108SAl Viro #else 157a10c95d8SAl Viro case HOST_IP: 1585c48b108SAl Viro return buf[0]->__rip; 159a10c95d8SAl Viro case HOST_SP: 1605c48b108SAl Viro return buf[0]->__rsp; 161a10c95d8SAl Viro case HOST_BP: 1625c48b108SAl Viro return buf[0]->__rbp; 1635c48b108SAl Viro #endif 1645c48b108SAl Viro default: 1655c48b108SAl Viro printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n", 1665c48b108SAl Viro reg); 1675c48b108SAl Viro return 0; 1685c48b108SAl Viro } 1695c48b108SAl Viro } 170