xref: /openbmc/linux/arch/x86/um/os-Linux/registers.c (revision dbba7f70)
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 
save_i387_registers(int pid,unsigned long * fp_regs)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 
save_fp_registers(int pid,unsigned long * fp_regs)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 
restore_i387_registers(int pid,unsigned long * fp_regs)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 
restore_fp_registers(int pid,unsigned long * fp_regs)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;
save_fpx_registers(int pid,unsigned long * fp_regs)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 
restore_fpx_registers(int pid,unsigned long * fp_regs)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 
get_fp_registers(int pid,unsigned long * regs)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 
put_fp_registers(int pid,unsigned long * regs)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 
arch_init_registers(int pid)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 
get_fp_registers(int pid,unsigned long * regs)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 
put_fp_registers(int pid,unsigned long * regs)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 
arch_init_registers(int pid)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 
get_thread_reg(int reg,jmp_buf * buf)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