xref: /openbmc/linux/arch/x86/um/os-Linux/registers.c (revision 0a987645)
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>
85c48b108SAl Viro #include <sys/ptrace.h>
938b64aedSRichard Weinberger #ifdef __i386__
105c48b108SAl Viro #include <sys/user.h>
1138b64aedSRichard Weinberger #endif
1237185b33SAl Viro #include <longjmp.h>
1337185b33SAl Viro #include <sysdep/ptrace_user.h>
14a78ff111SEli Cooper #include <sys/uio.h>
15a78ff111SEli Cooper #include <asm/sigcontext.h>
16a78ff111SEli Cooper #include <linux/elf.h>
175c48b108SAl Viro 
18a78ff111SEli Cooper int have_xstate_support;
19a78ff111SEli Cooper 
20a78ff111SEli Cooper int save_i387_registers(int pid, unsigned long *fp_regs)
215c48b108SAl Viro {
225c48b108SAl Viro 	if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
235c48b108SAl Viro 		return -errno;
245c48b108SAl Viro 	return 0;
255c48b108SAl Viro }
265c48b108SAl Viro 
27a78ff111SEli Cooper int save_fp_registers(int pid, unsigned long *fp_regs)
28a78ff111SEli Cooper {
290a987645SFlorian Fainelli #ifdef PTRACE_GETREGSET
30a78ff111SEli Cooper 	struct iovec iov;
31a78ff111SEli Cooper 
32a78ff111SEli Cooper 	if (have_xstate_support) {
33a78ff111SEli Cooper 		iov.iov_base = fp_regs;
34a78ff111SEli Cooper 		iov.iov_len = sizeof(struct _xstate);
35a78ff111SEli Cooper 		if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
36a78ff111SEli Cooper 			return -errno;
37a78ff111SEli Cooper 		return 0;
380a987645SFlorian Fainelli 	} else
390a987645SFlorian Fainelli #endif
40a78ff111SEli Cooper 		return save_i387_registers(pid, fp_regs);
41a78ff111SEli Cooper }
42a78ff111SEli Cooper 
43a78ff111SEli Cooper int restore_i387_registers(int pid, unsigned long *fp_regs)
445c48b108SAl Viro {
455c48b108SAl Viro 	if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
465c48b108SAl Viro 		return -errno;
475c48b108SAl Viro 	return 0;
485c48b108SAl Viro }
495c48b108SAl Viro 
50a78ff111SEli Cooper int restore_fp_registers(int pid, unsigned long *fp_regs)
51a78ff111SEli Cooper {
520a987645SFlorian Fainelli #ifdef PTRACE_SETREGSET
53a78ff111SEli Cooper 	struct iovec iov;
54a78ff111SEli Cooper 
55a78ff111SEli Cooper 	if (have_xstate_support) {
56a78ff111SEli Cooper 		iov.iov_base = fp_regs;
57a78ff111SEli Cooper 		iov.iov_len = sizeof(struct _xstate);
58a78ff111SEli Cooper 		if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
59a78ff111SEli Cooper 			return -errno;
60a78ff111SEli Cooper 		return 0;
610a987645SFlorian Fainelli 	} else
620a987645SFlorian Fainelli #endif
63a78ff111SEli Cooper 		return restore_i387_registers(pid, fp_regs);
64a78ff111SEli Cooper }
65a78ff111SEli Cooper 
665c48b108SAl Viro #ifdef __i386__
675c48b108SAl Viro int have_fpx_regs = 1;
685c48b108SAl Viro int save_fpx_registers(int pid, unsigned long *fp_regs)
695c48b108SAl Viro {
705c48b108SAl Viro 	if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
715c48b108SAl Viro 		return -errno;
725c48b108SAl Viro 	return 0;
735c48b108SAl Viro }
745c48b108SAl Viro 
755c48b108SAl Viro int restore_fpx_registers(int pid, unsigned long *fp_regs)
765c48b108SAl Viro {
775c48b108SAl Viro 	if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
785c48b108SAl Viro 		return -errno;
795c48b108SAl Viro 	return 0;
805c48b108SAl Viro }
815c48b108SAl Viro 
825c48b108SAl Viro int get_fp_registers(int pid, unsigned long *regs)
835c48b108SAl Viro {
845c48b108SAl Viro 	if (have_fpx_regs)
855c48b108SAl Viro 		return save_fpx_registers(pid, regs);
865c48b108SAl Viro 	else
875c48b108SAl Viro 		return save_fp_registers(pid, regs);
885c48b108SAl Viro }
895c48b108SAl Viro 
905c48b108SAl Viro int put_fp_registers(int pid, unsigned long *regs)
915c48b108SAl Viro {
925c48b108SAl Viro 	if (have_fpx_regs)
935c48b108SAl Viro 		return restore_fpx_registers(pid, regs);
945c48b108SAl Viro 	else
955c48b108SAl Viro 		return restore_fp_registers(pid, regs);
965c48b108SAl Viro }
975c48b108SAl Viro 
985c48b108SAl Viro void arch_init_registers(int pid)
995c48b108SAl Viro {
1005c48b108SAl Viro 	struct user_fpxregs_struct fpx_regs;
1015c48b108SAl Viro 	int err;
1025c48b108SAl Viro 
1035c48b108SAl Viro 	err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
1045c48b108SAl Viro 	if (!err)
1055c48b108SAl Viro 		return;
1065c48b108SAl Viro 
1075c48b108SAl Viro 	if (errno != EIO)
1085c48b108SAl Viro 		panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
1095c48b108SAl Viro 		      errno);
1105c48b108SAl Viro 
1115c48b108SAl Viro 	have_fpx_regs = 0;
1125c48b108SAl Viro }
1135c48b108SAl Viro #else
1145c48b108SAl Viro 
1155c48b108SAl Viro int get_fp_registers(int pid, unsigned long *regs)
1165c48b108SAl Viro {
1175c48b108SAl Viro 	return save_fp_registers(pid, regs);
1185c48b108SAl Viro }
1195c48b108SAl Viro 
1205c48b108SAl Viro int put_fp_registers(int pid, unsigned long *regs)
1215c48b108SAl Viro {
1225c48b108SAl Viro 	return restore_fp_registers(pid, regs);
1235c48b108SAl Viro }
1245c48b108SAl Viro 
125a78ff111SEli Cooper void arch_init_registers(int pid)
126a78ff111SEli Cooper {
1270a987645SFlorian Fainelli #ifdef PTRACE_GETREGSET
128a78ff111SEli Cooper 	struct _xstate fp_regs;
129a78ff111SEli Cooper 	struct iovec iov;
130a78ff111SEli Cooper 
131a78ff111SEli Cooper 	iov.iov_base = &fp_regs;
132a78ff111SEli Cooper 	iov.iov_len = sizeof(struct _xstate);
133a78ff111SEli Cooper 	if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0)
134a78ff111SEli Cooper 		have_xstate_support = 1;
1350a987645SFlorian Fainelli #endif
136a78ff111SEli Cooper }
1375c48b108SAl Viro #endif
1385c48b108SAl Viro 
1395c48b108SAl Viro unsigned long get_thread_reg(int reg, jmp_buf *buf)
1405c48b108SAl Viro {
1415c48b108SAl Viro 	switch (reg) {
1425c48b108SAl Viro #ifdef __i386__
143a10c95d8SAl Viro 	case HOST_IP:
1445c48b108SAl Viro 		return buf[0]->__eip;
145a10c95d8SAl Viro 	case HOST_SP:
1465c48b108SAl Viro 		return buf[0]->__esp;
147a10c95d8SAl Viro 	case HOST_BP:
1485c48b108SAl Viro 		return buf[0]->__ebp;
1495c48b108SAl Viro #else
150a10c95d8SAl Viro 	case HOST_IP:
1515c48b108SAl Viro 		return buf[0]->__rip;
152a10c95d8SAl Viro 	case HOST_SP:
1535c48b108SAl Viro 		return buf[0]->__rsp;
154a10c95d8SAl Viro 	case HOST_BP:
1555c48b108SAl Viro 		return buf[0]->__rbp;
1565c48b108SAl Viro #endif
1575c48b108SAl Viro 	default:
1585c48b108SAl Viro 		printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
1595c48b108SAl Viro 		       reg);
1605c48b108SAl Viro 		return 0;
1615c48b108SAl Viro 	}
1625c48b108SAl Viro }
163