^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, ®s->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) ®s->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, ®s->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) ®s->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++, ®_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) ®_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, ®_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) ®_window[pos],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) ®, 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) }