cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ptrace.h (4212B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2/*
      3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
      4 */
      5#ifndef _ASM_PTRACE_H
      6#define _ASM_PTRACE_H
      7
      8#include <asm/page.h>
      9#include <asm/thread_info.h>
     10#include <uapi/asm/ptrace.h>
     11
     12/*
     13 * This struct defines the way the registers are stored on the stack during
     14 * a system call/exception. If you add a register here, please also add it to
     15 * regoffset_table[] in arch/loongarch/kernel/ptrace.c.
     16 */
     17struct pt_regs {
     18	/* Main processor registers. */
     19	unsigned long regs[32];
     20
     21	/* Original syscall arg0. */
     22	unsigned long orig_a0;
     23
     24	/* Special CSR registers. */
     25	unsigned long csr_era;
     26	unsigned long csr_badvaddr;
     27	unsigned long csr_crmd;
     28	unsigned long csr_prmd;
     29	unsigned long csr_euen;
     30	unsigned long csr_ecfg;
     31	unsigned long csr_estat;
     32	unsigned long __last[0];
     33} __aligned(8);
     34
     35static inline int regs_irqs_disabled(struct pt_regs *regs)
     36{
     37	return arch_irqs_disabled_flags(regs->csr_prmd);
     38}
     39
     40static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
     41{
     42	return regs->regs[3];
     43}
     44
     45/*
     46 * Don't use asm-generic/ptrace.h it defines FP accessors that don't make
     47 * sense on LoongArch.  We rather want an error if they get invoked.
     48 */
     49
     50static inline void instruction_pointer_set(struct pt_regs *regs, unsigned long val)
     51{
     52	regs->csr_era = val;
     53}
     54
     55/* Query offset/name of register from its name/offset */
     56extern int regs_query_register_offset(const char *name);
     57#define MAX_REG_OFFSET (offsetof(struct pt_regs, __last))
     58
     59/**
     60 * regs_get_register() - get register value from its offset
     61 * @regs:       pt_regs from which register value is gotten.
     62 * @offset:     offset number of the register.
     63 *
     64 * regs_get_register returns the value of a register. The @offset is the
     65 * offset of the register in struct pt_regs address which specified by @regs.
     66 * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
     67 */
     68static inline unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset)
     69{
     70	if (unlikely(offset > MAX_REG_OFFSET))
     71		return 0;
     72
     73	return *(unsigned long *)((unsigned long)regs + offset);
     74}
     75
     76/**
     77 * regs_within_kernel_stack() - check the address in the stack
     78 * @regs:       pt_regs which contains kernel stack pointer.
     79 * @addr:       address which is checked.
     80 *
     81 * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
     82 * If @addr is within the kernel stack, it returns true. If not, returns false.
     83 */
     84static inline int regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
     85{
     86	return ((addr & ~(THREAD_SIZE - 1))  ==
     87		(kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
     88}
     89
     90/**
     91 * regs_get_kernel_stack_nth() - get Nth entry of the stack
     92 * @regs:       pt_regs which contains kernel stack pointer.
     93 * @n:          stack entry number.
     94 *
     95 * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
     96 * is specified by @regs. If the @n th entry is NOT in the kernel stack,
     97 * this returns 0.
     98 */
     99static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
    100{
    101	unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
    102
    103	addr += n;
    104	if (regs_within_kernel_stack(regs, (unsigned long)addr))
    105		return *addr;
    106	else
    107		return 0;
    108}
    109
    110struct task_struct;
    111
    112/*
    113 * Does the process account for user or for system time?
    114 */
    115#define user_mode(regs) (((regs)->csr_prmd & PLV_MASK) == PLV_USER)
    116
    117static inline long regs_return_value(struct pt_regs *regs)
    118{
    119	return regs->regs[4];
    120}
    121
    122#define instruction_pointer(regs) ((regs)->csr_era)
    123#define profile_pc(regs) instruction_pointer(regs)
    124
    125extern void die(const char *, struct pt_regs *) __noreturn;
    126
    127static inline void die_if_kernel(const char *str, struct pt_regs *regs)
    128{
    129	if (unlikely(!user_mode(regs)))
    130		die(str, regs);
    131}
    132
    133#define current_pt_regs()						\
    134({									\
    135	unsigned long sp = (unsigned long)__builtin_frame_address(0);	\
    136	(struct pt_regs *)((sp | (THREAD_SIZE - 1)) + 1 - 32) - 1;	\
    137})
    138
    139/* Helpers for working with the user stack pointer */
    140
    141static inline unsigned long user_stack_pointer(struct pt_regs *regs)
    142{
    143	return regs->regs[3];
    144}
    145
    146static inline void user_stack_pointer_set(struct pt_regs *regs,
    147	unsigned long val)
    148{
    149	regs->regs[3] = val;
    150}
    151
    152#endif /* _ASM_PTRACE_H */