Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /* ptrace.c: Sparc process tracing support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  * and David Mosberger.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  * Added Linux support -miguel (weird, eh?, the original code was meant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  * to emulate SunOS).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/sched/task_stack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/user.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <linux/security.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <linux/seccomp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <linux/audit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <linux/regset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <linux/tracehook.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <trace/syscall.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #include <linux/elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #include <linux/context_tracking.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #include <asm/asi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #include <asm/psrcompat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #include <asm/visasm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #include <asm/spitfire.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) #include <asm/cpudata.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #define CREATE_TRACE_POINTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) #include <trace/events/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) #include "entry.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) /* #define ALLOW_INIT_TRACING */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) struct pt_regs_offset {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 	const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 	int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) #define REG_OFFSET_NAME(n, r) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 	{.name = n, .offset = (PT_V9_##r)}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) #define REG_OFFSET_END {.name = NULL, .offset = 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) static const struct pt_regs_offset regoffset_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 	REG_OFFSET_NAME("g0", G0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 	REG_OFFSET_NAME("g1", G1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 	REG_OFFSET_NAME("g2", G2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 	REG_OFFSET_NAME("g3", G3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 	REG_OFFSET_NAME("g4", G4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 	REG_OFFSET_NAME("g5", G5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 	REG_OFFSET_NAME("g6", G6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 	REG_OFFSET_NAME("g7", G7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 	REG_OFFSET_NAME("i0", I0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 	REG_OFFSET_NAME("i1", I1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 	REG_OFFSET_NAME("i2", I2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 	REG_OFFSET_NAME("i3", I3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 	REG_OFFSET_NAME("i4", I4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 	REG_OFFSET_NAME("i5", I5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 	REG_OFFSET_NAME("i6", I6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 	REG_OFFSET_NAME("i7", I7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 	REG_OFFSET_NAME("tstate", TSTATE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 	REG_OFFSET_NAME("pc", TPC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 	REG_OFFSET_NAME("npc", TNPC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 	REG_OFFSET_NAME("y", Y),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 	REG_OFFSET_NAME("lr", I7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 	REG_OFFSET_END,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88)  * Called by kernel/ptrace.c when detaching..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90)  * Make sure single step bits etc are not set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) void ptrace_disable(struct task_struct *child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 	/* nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) /* To get the necessary page struct, access_process_vm() first calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98)  * get_user_pages().  This has done a flush_dcache_page() on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99)  * accessed page.  Then our caller (copy_{to,from}_user_page()) did
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100)  * to memcpy to read/write the data from that page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102)  * Now, the only thing we have to do is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103)  * 1) flush the D-cache if it's possible than an illegal alias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104)  *    has been created
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105)  * 2) flush the I-cache if this is pre-cheetah and we did a write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 			 unsigned long uaddr, void *kaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 			 unsigned long len, int write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 	BUG_ON(len > PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 	if (tlb_type == hypervisor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 	preempt_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) #ifdef DCACHE_ALIASING_POSSIBLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 	/* If bit 13 of the kernel address we used to access the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	 * user page is the same as the virtual address that page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 	 * is mapped to in the user's address space, we can skip the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 	 * D-cache flush.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 	if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 		unsigned long start = __pa(kaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 		unsigned long end = start + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 		unsigned long dcache_line_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 		dcache_line_size = local_cpu_data().dcache_line_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 		if (tlb_type == spitfire) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 			for (; start < end; start += dcache_line_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 				spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 			start &= ~(dcache_line_size - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 			for (; start < end; start += dcache_line_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 				__asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 					"stxa %%g0, [%0] %1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 					"membar #Sync"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 					: /* no outputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 					: "r" (start),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 					"i" (ASI_DCACHE_INVALIDATE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	if (write && tlb_type == spitfire) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 		unsigned long start = (unsigned long) kaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 		unsigned long end = start + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 		unsigned long icache_line_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 		icache_line_size = local_cpu_data().icache_line_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 		for (; start < end; start += icache_line_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 			flushi(start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	preempt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) EXPORT_SYMBOL_GPL(flush_ptrace_access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) static int get_from_target(struct task_struct *target, unsigned long uaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 			   void *kbuf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	if (target == current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 		if (copy_from_user(kbuf, (void __user *) uaddr, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 		int len2 = access_process_vm(target, uaddr, kbuf, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 				FOLL_FORCE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 		if (len2 != len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) static int set_to_target(struct task_struct *target, unsigned long uaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 			 void *kbuf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 	if (target == current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 		if (copy_to_user((void __user *) uaddr, kbuf, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 		int len2 = access_process_vm(target, uaddr, kbuf, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 				FOLL_FORCE | FOLL_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 		if (len2 != len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) static int regwindow64_get(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 			   const struct pt_regs *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 			   struct reg_window *wbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 	unsigned long rw_addr = regs->u_regs[UREG_I6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	if (!test_thread_64bit_stack(rw_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 		struct reg_window32 win32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 		int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 		if (get_from_target(target, rw_addr, &win32, sizeof(win32)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 		for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 			wbuf->locals[i] = win32.locals[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 		for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 			wbuf->ins[i] = win32.ins[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 		rw_addr += STACK_BIAS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 		if (get_from_target(target, rw_addr, wbuf, sizeof(*wbuf)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) static int regwindow64_set(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 			   const struct pt_regs *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 			   struct reg_window *wbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	unsigned long rw_addr = regs->u_regs[UREG_I6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	if (!test_thread_64bit_stack(rw_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 		struct reg_window32 win32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 		int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 		for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 			win32.locals[i] = wbuf->locals[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 		for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 			win32.ins[i] = wbuf->ins[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 		if (set_to_target(target, rw_addr, &win32, sizeof(win32)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 		rw_addr += STACK_BIAS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 		if (set_to_target(target, rw_addr, wbuf, sizeof(*wbuf)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) enum sparc_regset {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	REGSET_GENERAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	REGSET_FP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) static int genregs64_get(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 			 const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 			 struct membuf to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	const struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	struct reg_window window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	if (target == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 		flushw_user();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 	membuf_write(&to, regs->u_regs, 16 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	if (!to.left)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	if (regwindow64_get(target, regs, &window))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 		return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 	membuf_write(&to, &window, 16 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	/* TSTATE, TPC, TNPC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	membuf_write(&to, &regs->tstate, 3 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	return membuf_store(&to, (u64)regs->y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) static int genregs64_set(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 			 const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 			 unsigned int pos, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 			 const void *kbuf, const void __user *ubuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	if (target == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 		flushw_user();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 				 regs->u_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 				 0, 16 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	if (!ret && count && pos < (32 * sizeof(u64))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 		struct reg_window window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 		if (regwindow64_get(target, regs, &window))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 					 &window,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 					 16 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 					 32 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 		if (!ret &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 		    regwindow64_set(target, regs, &window))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	if (!ret && count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 		unsigned long tstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 		/* TSTATE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 					 &tstate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 					 32 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 					 33 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 		if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 			/* Only the condition codes and the "in syscall"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 			 * state can be modified in the %tstate register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 			tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 			regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 			regs->tstate |= tstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 		/* TPC, TNPC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 					 &regs->tpc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 					 33 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 					 35 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 		unsigned long y = regs->y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 					 &y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 					 35 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 					 36 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 		if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 			regs->y = y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 						36 * sizeof(u64), -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) static int fpregs64_get(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 			const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 			struct membuf to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 	struct thread_info *t = task_thread_info(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	unsigned long fprs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 	if (target == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 		save_and_clear_fpu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 	fprs = t->fpsaved[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	if (fprs & FPRS_DL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 		membuf_write(&to, t->fpregs, 16 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 		membuf_zero(&to, 16 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 	if (fprs & FPRS_DU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 		membuf_write(&to, t->fpregs + 16, 16 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 		membuf_zero(&to, 16 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 	if (fprs & FPRS_FEF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 		membuf_store(&to, t->xfsr[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 		membuf_store(&to, t->gsr[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 		membuf_zero(&to, 2 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 	return membuf_store(&to, fprs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) static int fpregs64_set(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 			const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 			unsigned int pos, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 			const void *kbuf, const void __user *ubuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	unsigned long *fpregs = task_thread_info(target)->fpregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 	unsigned long fprs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	if (target == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 		save_and_clear_fpu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 				 fpregs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 				 0, 32 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 					 task_thread_info(target)->xfsr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 					 32 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 					 33 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 					 task_thread_info(target)->gsr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 					 33 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 					 34 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 	fprs = task_thread_info(target)->fpsaved[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	if (!ret && count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 					 &fprs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 					 34 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 					 35 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	fprs |= (FPRS_FEF | FPRS_DL | FPRS_DU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	task_thread_info(target)->fpsaved[0] = fprs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 						35 * sizeof(u64), -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) static const struct user_regset sparc64_regsets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	/* Format is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 	 * 	G0 --> G7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	 *	O0 --> O7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 	 *	L0 --> L7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	 *	I0 --> I7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 	 *	TSTATE, TPC, TNPC, Y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	[REGSET_GENERAL] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 		.core_note_type = NT_PRSTATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 		.n = 36,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 		.size = sizeof(u64), .align = sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 		.regset_get = genregs64_get, .set = genregs64_set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 	/* Format is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	 *	F0 --> F63
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	 *	FSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	 *	GSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	 *	FPRS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	[REGSET_FP] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 		.core_note_type = NT_PRFPREG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 		.n = 35,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 		.size = sizeof(u64), .align = sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 		.regset_get = fpregs64_get, .set = fpregs64_set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) static int getregs64_get(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 			 const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 			 struct membuf to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 	const struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 	if (target == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 		flushw_user();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 	membuf_write(&to, regs->u_regs + 1, 15 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 	membuf_store(&to, (u64)0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	membuf_write(&to, &regs->tstate, 3 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 	return membuf_store(&to, (u64)regs->y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) static int setregs64_set(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 			 const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 			 unsigned int pos, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 			 const void *kbuf, const void __user *ubuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 	struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	unsigned long y = regs->y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	unsigned long tstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 	if (target == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 		flushw_user();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 				 regs->u_regs + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 				 0 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 				 15 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	ret =user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 				 15 * sizeof(u64), 16 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 	/* TSTATE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 				 &tstate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 				 16 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 				 17 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	/* Only the condition codes and the "in syscall"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	 * state can be modified in the %tstate register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 	regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 	regs->tstate |= tstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	/* TPC, TNPC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 				 &regs->tpc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 				 17 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 				 19 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 	/* Y */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 				 &y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 				 19 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 				 20 * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 		regs->y = y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) static const struct user_regset ptrace64_regsets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	/* Format is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 	 *      G1 --> G7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	 *      O0 --> O7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	 *	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	 *      TSTATE, TPC, TNPC, Y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	[REGSET_GENERAL] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 		.n = 20, .size = sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 		.regset_get = getregs64_get, .set = setregs64_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) static const struct user_regset_view ptrace64_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	.regsets = ptrace64_regsets, .n = ARRAY_SIZE(ptrace64_regsets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) static const struct user_regset_view user_sparc64_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	.name = "sparc64", .e_machine = EM_SPARCV9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	.regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) static int genregs32_get(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 			 const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 			 struct membuf to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	const struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	u32 uregs[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	if (target == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 		flushw_user();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 	for (i = 0; i < 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 		membuf_store(&to, (u32)regs->u_regs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 	if (!to.left)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	if (get_from_target(target, regs->u_regs[UREG_I6],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 			    uregs, sizeof(uregs)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 		return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	membuf_write(&to, uregs, 16 * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	membuf_store(&to, (u32)tstate_to_psr(regs->tstate));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 	membuf_store(&to, (u32)(regs->tpc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 	membuf_store(&to, (u32)(regs->tnpc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	membuf_store(&to, (u32)(regs->y));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 	return membuf_zero(&to, 2 * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) static int genregs32_set(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 			 const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 			 unsigned int pos, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 			 const void *kbuf, const void __user *ubuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	compat_ulong_t __user *reg_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 	const compat_ulong_t *k = kbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 	const compat_ulong_t __user *u = ubuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	compat_ulong_t reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	if (target == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 		flushw_user();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	pos /= sizeof(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	count /= sizeof(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	if (kbuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 		for (; count > 0 && pos < 16; count--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 			regs->u_regs[pos++] = *k++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 		reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 		reg_window -= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 		if (target == current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 			for (; count > 0 && pos < 32; count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 				if (put_user(*k++, &reg_window[pos++]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 					return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 			for (; count > 0 && pos < 32; count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 				if (access_process_vm(target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 						      (unsigned long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 						      &reg_window[pos],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 						      (void *) k,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 						      sizeof(*k),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 						      FOLL_FORCE | FOLL_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 				    != sizeof(*k))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 					return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 				k++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 				pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 		for (; count > 0 && pos < 16; count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 			if (get_user(reg, u++))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 				return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 			regs->u_regs[pos++] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 		reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 		reg_window -= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 		if (target == current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 			for (; count > 0 && pos < 32; count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 				if (get_user(reg, u++) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 				    put_user(reg, &reg_window[pos++]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 					return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 			for (; count > 0 && pos < 32; count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 				if (get_user(reg, u++))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 					return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 				if (access_process_vm(target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 						      (unsigned long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 						      &reg_window[pos],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 						      &reg, sizeof(reg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 						      FOLL_FORCE | FOLL_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 				    != sizeof(reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 					return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 				pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 				u++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	while (count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 		unsigned long tstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 		if (kbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 			reg = *k++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 		else if (get_user(reg, u++))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 		switch (pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 		case 32: /* PSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 			tstate = regs->tstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 			tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 			tstate |= psr_to_tstate_icc(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 			if (reg & PSR_SYSCALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 				tstate |= TSTATE_SYSCALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 			regs->tstate = tstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 		case 33: /* PC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 			regs->tpc = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 		case 34: /* NPC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 			regs->tnpc = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 		case 35: /* Y */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 			regs->y = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 		case 36: /* WIM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 		case 37: /* TBR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 			goto finish;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 		pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 		count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) finish:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	pos *= sizeof(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 	count *= sizeof(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 					 38 * sizeof(reg), -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) static int fpregs32_get(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 			const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 			struct membuf to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	struct thread_info *t = task_thread_info(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	bool enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	if (target == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 		save_and_clear_fpu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	enabled = t->fpsaved[0] & FPRS_FEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	membuf_write(&to, t->fpregs, 32 * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	membuf_zero(&to, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	if (enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 		membuf_store(&to, (u32)t->xfsr[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 		membuf_zero(&to, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	membuf_store(&to, (u32)((enabled << 8) | (8 << 16)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	return membuf_zero(&to, 64 * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) static int fpregs32_set(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 			const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 			unsigned int pos, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 			const void *kbuf, const void __user *ubuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	unsigned long *fpregs = task_thread_info(target)->fpregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	unsigned long fprs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 	if (target == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 		save_and_clear_fpu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	fprs = task_thread_info(target)->fpsaved[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 				 fpregs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 				 0, 32 * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 		user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 					  32 * sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 					  33 * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	if (!ret && count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 		compat_ulong_t fsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 		unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 					 &fsr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 					 33 * sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 					 34 * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 		if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 			val = task_thread_info(target)->xfsr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 			val &= 0xffffffff00000000UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 			val |= fsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 			task_thread_info(target)->xfsr[0] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 	fprs |= (FPRS_FEF | FPRS_DL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 	task_thread_info(target)->fpsaved[0] = fprs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 						34 * sizeof(u32), -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) static const struct user_regset sparc32_regsets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	/* Format is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	 * 	G0 --> G7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 	 *	O0 --> O7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	 *	L0 --> L7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 	 *	I0 --> I7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	 *	PSR, PC, nPC, Y, WIM, TBR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	[REGSET_GENERAL] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 		.core_note_type = NT_PRSTATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 		.n = 38,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 		.size = sizeof(u32), .align = sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 		.regset_get = genregs32_get, .set = genregs32_set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	/* Format is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	 *	F0 --> F31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	 *	empty 32-bit word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	 *	FSR (32--bit word)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	 *	FPU QUEUE COUNT (8-bit char)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	 *	FPU QUEUE ENTRYSIZE (8-bit char)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	 *	FPU ENABLED (8-bit char)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	 *	empty 8-bit char
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	 *	FPU QUEUE (64 32-bit ints)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	[REGSET_FP] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 		.core_note_type = NT_PRFPREG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 		.n = 99,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 		.size = sizeof(u32), .align = sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 		.regset_get = fpregs32_get, .set = fpregs32_set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) static int getregs_get(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 			 const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 			 struct membuf to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 	const struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	if (target == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 		flushw_user();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	membuf_store(&to, (u32)tstate_to_psr(regs->tstate));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	membuf_store(&to, (u32)(regs->tpc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	membuf_store(&to, (u32)(regs->tnpc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	membuf_store(&to, (u32)(regs->y));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	for (i = 1; i < 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 		membuf_store(&to, (u32)regs->u_regs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	return to.left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) static int setregs_set(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 			 const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 			 unsigned int pos, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 			 const void *kbuf, const void __user *ubuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	unsigned long tstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	u32 uregs[19];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 	int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	if (target == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 		flushw_user();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 				 uregs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 				 0, 19 * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	tstate = regs->tstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	tstate |= psr_to_tstate_icc(uregs[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	if (uregs[0] & PSR_SYSCALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 		tstate |= TSTATE_SYSCALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 	regs->tstate = tstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 	regs->tpc = uregs[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 	regs->tnpc = uregs[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 	regs->y = uregs[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 	for (i = 1; i < 15; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 		regs->u_regs[i] = uregs[3 + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) static int getfpregs_get(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 			const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 			struct membuf to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	struct thread_info *t = task_thread_info(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	if (target == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 		save_and_clear_fpu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	membuf_write(&to, t->fpregs, 32 * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 	if (t->fpsaved[0] & FPRS_FEF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 		membuf_store(&to, (u32)t->xfsr[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		membuf_zero(&to, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 	return membuf_zero(&to, 35 * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) static int setfpregs_set(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 			const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 			unsigned int pos, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 			const void *kbuf, const void __user *ubuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	unsigned long *fpregs = task_thread_info(target)->fpregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	unsigned long fprs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	if (target == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 		save_and_clear_fpu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 	fprs = task_thread_info(target)->fpsaved[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 				 fpregs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 				 0, 32 * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 	if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 		compat_ulong_t fsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 		unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 					 &fsr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 					 32 * sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 					 33 * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 		if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 			val = task_thread_info(target)->xfsr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 			val &= 0xffffffff00000000UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 			val |= fsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 			task_thread_info(target)->xfsr[0] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 	fprs |= (FPRS_FEF | FPRS_DL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	task_thread_info(target)->fpsaved[0] = fprs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) static const struct user_regset ptrace32_regsets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 	[REGSET_GENERAL] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 		.n = 19, .size = sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 		.regset_get = getregs_get, .set = setregs_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	[REGSET_FP] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 		.n = 68, .size = sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 		.regset_get = getfpregs_get, .set = setfpregs_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) static const struct user_regset_view ptrace32_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	.regsets = ptrace32_regsets, .n = ARRAY_SIZE(ptrace32_regsets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) static const struct user_regset_view user_sparc32_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 	.name = "sparc", .e_machine = EM_SPARC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	.regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) #endif /* CONFIG_COMPAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) const struct user_regset_view *task_user_regset_view(struct task_struct *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	if (test_tsk_thread_flag(task, TIF_32BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 		return &user_sparc32_view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	return &user_sparc64_view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) struct compat_fps {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	unsigned int regs[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 	unsigned int fsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	unsigned int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	unsigned int extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 	unsigned int fpqd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 	struct compat_fq {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 		unsigned int insnaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 		unsigned int insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	} fpq[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 			compat_ulong_t caddr, compat_ulong_t cdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	struct pt_regs32 __user *pregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	struct compat_fps __user *fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	unsigned long addr2 = caddr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	unsigned long addr = caddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	unsigned long data = cdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	pregs = (struct pt_regs32 __user *) addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 	fps = (struct compat_fps __user *) addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	switch (request) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	case PTRACE_PEEKUSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 		ret = (addr != 0) ? -EIO : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	case PTRACE_GETREGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 		ret = copy_regset_to_user(child, &ptrace32_view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 					  REGSET_GENERAL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 					  19 * sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 					  pregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	case PTRACE_SETREGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 		ret = copy_regset_from_user(child, &ptrace32_view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 					  REGSET_GENERAL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 					  19 * sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 					  pregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	case PTRACE_GETFPREGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 		ret = copy_regset_to_user(child, &ptrace32_view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 					  REGSET_FP, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 					  68 * sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 					  fps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	case PTRACE_SETFPREGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 		ret = copy_regset_from_user(child, &ptrace32_view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 					  REGSET_FP, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 					  33 * sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 					  fps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 	case PTRACE_READTEXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 	case PTRACE_READDATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 		ret = ptrace_readdata(child, addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 				      (char __user *)addr2, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 		if (ret == data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 			ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 		else if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 			ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 	case PTRACE_WRITETEXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 	case PTRACE_WRITEDATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 		ret = ptrace_writedata(child, (char __user *) addr2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 				       addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 		if (ret == data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 			ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 		else if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 			ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 		if (request == PTRACE_SPARC_DETACH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 			request = PTRACE_DETACH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		ret = compat_ptrace_request(child, request, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) #endif /* CONFIG_COMPAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) struct fps {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 	unsigned int regs[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	unsigned long fsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) long arch_ptrace(struct task_struct *child, long request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 		 unsigned long addr, unsigned long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 	const struct user_regset_view *view = task_user_regset_view(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	struct pt_regs __user *pregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	struct fps __user *fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	void __user *addr2p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	pregs = (struct pt_regs __user *) addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 	fps = (struct fps __user *) addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	addr2p = (void __user *) addr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 	switch (request) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	case PTRACE_PEEKUSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 		ret = (addr != 0) ? -EIO : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	case PTRACE_GETREGS64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 		ret = copy_regset_to_user(child, &ptrace64_view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 					  REGSET_GENERAL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 					  19 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 					  pregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	case PTRACE_SETREGS64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 		ret = copy_regset_from_user(child, &ptrace64_view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 					  REGSET_GENERAL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 					  19 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 					  pregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 	case PTRACE_GETFPREGS64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 		ret = copy_regset_to_user(child, view, REGSET_FP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 					  0 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 					  33 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 					  fps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 	case PTRACE_SETFPREGS64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 		ret = copy_regset_from_user(child, view, REGSET_FP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 					  0 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 					  33 * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 					  fps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 	case PTRACE_READTEXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 	case PTRACE_READDATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 		ret = ptrace_readdata(child, addr, addr2p, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 		if (ret == data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 			ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 		else if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 			ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 	case PTRACE_WRITETEXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 	case PTRACE_WRITEDATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 		ret = ptrace_writedata(child, addr2p, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 		if (ret == data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 			ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 		else if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 			ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 		if (request == PTRACE_SPARC_DETACH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 			request = PTRACE_DETACH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 		ret = ptrace_request(child, request, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) asmlinkage int syscall_trace_enter(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 	/* do the secure computing check first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 	secure_computing_strict(regs->u_regs[UREG_G1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 	if (test_thread_flag(TIF_NOHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 		user_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 	if (test_thread_flag(TIF_SYSCALL_TRACE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 		ret = tracehook_report_syscall_entry(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 		trace_sys_enter(regs, regs->u_regs[UREG_G1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 	audit_syscall_entry(regs->u_regs[UREG_G1], regs->u_regs[UREG_I0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 			    regs->u_regs[UREG_I1], regs->u_regs[UREG_I2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 			    regs->u_regs[UREG_I3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) asmlinkage void syscall_trace_leave(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 	if (test_thread_flag(TIF_NOHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 		user_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 	audit_syscall_exit(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 		trace_sys_exit(regs, regs->u_regs[UREG_I0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	if (test_thread_flag(TIF_SYSCALL_TRACE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 		tracehook_report_syscall_exit(regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 	if (test_thread_flag(TIF_NOHZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 		user_enter();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)  * regs_query_register_offset() - query register offset from its name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)  * @name:	the name of a register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)  * regs_query_register_offset() returns the offset of a register in struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)  * pt_regs from its name. If the name is invalid, this returns -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) int regs_query_register_offset(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 	const struct pt_regs_offset *roff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 	for (roff = regoffset_table; roff->name != NULL; roff++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 		if (!strcmp(roff->name, name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 			return roff->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)  * regs_within_kernel_stack() - check the address in the stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)  * @regs:	pt_regs which contains kernel stack pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)  * @addr:	address which is checked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)  * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)  * If @addr is within the kernel stack, it returns true. If not, returns false.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) static inline int regs_within_kernel_stack(struct pt_regs *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 					   unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 	unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	return ((addr & ~(THREAD_SIZE - 1))  ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 		(ksp & ~(THREAD_SIZE - 1)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)  * regs_get_kernel_stack_nth() - get Nth entry of the stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)  * @regs:	pt_regs which contains kernel stack pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)  * @n:		stack entry number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)  * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)  * is specified by @regs. If the @n th entry is NOT in the kernel stack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)  * this returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 	unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 	unsigned long *addr = (unsigned long *)ksp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 	addr += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 	if (regs_within_kernel_stack(regs, (unsigned long)addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 		return *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) }