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

processor.h (9466B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2/*
      3 *  S390 version
      4 *    Copyright IBM Corp. 1999
      5 *    Author(s): Hartmut Penner (hp@de.ibm.com),
      6 *               Martin Schwidefsky (schwidefsky@de.ibm.com)
      7 *
      8 *  Derived from "include/asm-i386/processor.h"
      9 *    Copyright (C) 1994, Linus Torvalds
     10 */
     11
     12#ifndef __ASM_S390_PROCESSOR_H
     13#define __ASM_S390_PROCESSOR_H
     14
     15#include <linux/bits.h>
     16
     17#define CIF_NOHZ_DELAY		2	/* delay HZ disable for a tick */
     18#define CIF_FPU			3	/* restore FPU registers */
     19#define CIF_ENABLED_WAIT	5	/* in enabled wait state */
     20#define CIF_MCCK_GUEST		6	/* machine check happening in guest */
     21#define CIF_DEDICATED_CPU	7	/* this CPU is dedicated */
     22
     23#define _CIF_NOHZ_DELAY		BIT(CIF_NOHZ_DELAY)
     24#define _CIF_FPU		BIT(CIF_FPU)
     25#define _CIF_ENABLED_WAIT	BIT(CIF_ENABLED_WAIT)
     26#define _CIF_MCCK_GUEST		BIT(CIF_MCCK_GUEST)
     27#define _CIF_DEDICATED_CPU	BIT(CIF_DEDICATED_CPU)
     28
     29#define RESTART_FLAG_CTLREGS	_AC(1 << 0, U)
     30
     31#ifndef __ASSEMBLY__
     32
     33#include <linux/cpumask.h>
     34#include <linux/linkage.h>
     35#include <linux/irqflags.h>
     36#include <asm/cpu.h>
     37#include <asm/page.h>
     38#include <asm/ptrace.h>
     39#include <asm/setup.h>
     40#include <asm/runtime_instr.h>
     41#include <asm/fpu/types.h>
     42#include <asm/fpu/internal.h>
     43#include <asm/irqflags.h>
     44
     45typedef long (*sys_call_ptr_t)(struct pt_regs *regs);
     46
     47static inline void set_cpu_flag(int flag)
     48{
     49	S390_lowcore.cpu_flags |= (1UL << flag);
     50}
     51
     52static inline void clear_cpu_flag(int flag)
     53{
     54	S390_lowcore.cpu_flags &= ~(1UL << flag);
     55}
     56
     57static inline int test_cpu_flag(int flag)
     58{
     59	return !!(S390_lowcore.cpu_flags & (1UL << flag));
     60}
     61
     62/*
     63 * Test CIF flag of another CPU. The caller needs to ensure that
     64 * CPU hotplug can not happen, e.g. by disabling preemption.
     65 */
     66static inline int test_cpu_flag_of(int flag, int cpu)
     67{
     68	struct lowcore *lc = lowcore_ptr[cpu];
     69	return !!(lc->cpu_flags & (1UL << flag));
     70}
     71
     72#define arch_needs_cpu() test_cpu_flag(CIF_NOHZ_DELAY)
     73
     74static inline void get_cpu_id(struct cpuid *ptr)
     75{
     76	asm volatile("stidp %0" : "=Q" (*ptr));
     77}
     78
     79void s390_adjust_jiffies(void);
     80void s390_update_cpu_mhz(void);
     81void cpu_detect_mhz_feature(void);
     82
     83extern const struct seq_operations cpuinfo_op;
     84extern void execve_tail(void);
     85extern void __bpon(void);
     86unsigned long vdso_size(void);
     87
     88/*
     89 * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
     90 */
     91
     92#define TASK_SIZE		(test_thread_flag(TIF_31BIT) ? \
     93					_REGION3_SIZE : TASK_SIZE_MAX)
     94#define TASK_UNMAPPED_BASE	(test_thread_flag(TIF_31BIT) ? \
     95					(_REGION3_SIZE >> 1) : (_REGION2_SIZE >> 1))
     96#define TASK_SIZE_MAX		(-PAGE_SIZE)
     97
     98#define VDSO_BASE		(STACK_TOP + PAGE_SIZE)
     99#define VDSO_LIMIT		(test_thread_flag(TIF_31BIT) ? _REGION3_SIZE : _REGION2_SIZE)
    100#define STACK_TOP		(VDSO_LIMIT - vdso_size() - PAGE_SIZE)
    101#define STACK_TOP_MAX		(_REGION2_SIZE - vdso_size() - PAGE_SIZE)
    102
    103#define HAVE_ARCH_PICK_MMAP_LAYOUT
    104
    105/*
    106 * Thread structure
    107 */
    108struct thread_struct {
    109	unsigned int  acrs[NUM_ACRS];
    110	unsigned long ksp;			/* kernel stack pointer */
    111	unsigned long user_timer;		/* task cputime in user space */
    112	unsigned long guest_timer;		/* task cputime in kvm guest */
    113	unsigned long system_timer;		/* task cputime in kernel space */
    114	unsigned long hardirq_timer;		/* task cputime in hardirq context */
    115	unsigned long softirq_timer;		/* task cputime in softirq context */
    116	const sys_call_ptr_t *sys_call_table;	/* system call table address */
    117	unsigned long gmap_addr;		/* address of last gmap fault. */
    118	unsigned int gmap_write_flag;		/* gmap fault write indication */
    119	unsigned int gmap_int_code;		/* int code of last gmap fault */
    120	unsigned int gmap_pfault;		/* signal of a pending guest pfault */
    121
    122	/* Per-thread information related to debugging */
    123	struct per_regs per_user;		/* User specified PER registers */
    124	struct per_event per_event;		/* Cause of the last PER trap */
    125	unsigned long per_flags;		/* Flags to control debug behavior */
    126	unsigned int system_call;		/* system call number in signal */
    127	unsigned long last_break;		/* last breaking-event-address. */
    128	/* pfault_wait is used to block the process on a pfault event */
    129	unsigned long pfault_wait;
    130	struct list_head list;
    131	/* cpu runtime instrumentation */
    132	struct runtime_instr_cb *ri_cb;
    133	struct gs_cb *gs_cb;			/* Current guarded storage cb */
    134	struct gs_cb *gs_bc_cb;			/* Broadcast guarded storage cb */
    135	struct pgm_tdb trap_tdb;		/* Transaction abort diagnose block */
    136	/*
    137	 * Warning: 'fpu' is dynamically-sized. It *MUST* be at
    138	 * the end.
    139	 */
    140	struct fpu fpu;			/* FP and VX register save area */
    141};
    142
    143/* Flag to disable transactions. */
    144#define PER_FLAG_NO_TE			1UL
    145/* Flag to enable random transaction aborts. */
    146#define PER_FLAG_TE_ABORT_RAND		2UL
    147/* Flag to specify random transaction abort mode:
    148 * - abort each transaction at a random instruction before TEND if set.
    149 * - abort random transactions at a random instruction if cleared.
    150 */
    151#define PER_FLAG_TE_ABORT_RAND_TEND	4UL
    152
    153typedef struct thread_struct thread_struct;
    154
    155#define ARCH_MIN_TASKALIGN	8
    156
    157#define INIT_THREAD {							\
    158	.ksp = sizeof(init_stack) + (unsigned long) &init_stack,	\
    159	.fpu.regs = (void *) init_task.thread.fpu.fprs,			\
    160	.last_break = 1,						\
    161}
    162
    163/*
    164 * Do necessary setup to start up a new thread.
    165 */
    166#define start_thread(regs, new_psw, new_stackp) do {			\
    167	regs->psw.mask	= PSW_USER_BITS | PSW_MASK_EA | PSW_MASK_BA;	\
    168	regs->psw.addr	= new_psw;					\
    169	regs->gprs[15]	= new_stackp;					\
    170	execve_tail();							\
    171} while (0)
    172
    173#define start_thread31(regs, new_psw, new_stackp) do {			\
    174	regs->psw.mask	= PSW_USER_BITS | PSW_MASK_BA;			\
    175	regs->psw.addr	= new_psw;					\
    176	regs->gprs[15]	= new_stackp;					\
    177	execve_tail();							\
    178} while (0)
    179
    180/* Forward declaration, a strange C thing */
    181struct task_struct;
    182struct mm_struct;
    183struct seq_file;
    184struct pt_regs;
    185
    186void show_registers(struct pt_regs *regs);
    187void show_cacheinfo(struct seq_file *m);
    188
    189/* Free all resources held by a thread. */
    190static inline void release_thread(struct task_struct *tsk) { }
    191
    192/* Free guarded storage control block */
    193void guarded_storage_release(struct task_struct *tsk);
    194void gs_load_bc_cb(struct pt_regs *regs);
    195
    196unsigned long __get_wchan(struct task_struct *p);
    197#define task_pt_regs(tsk) ((struct pt_regs *) \
    198        (task_stack_page(tsk) + THREAD_SIZE) - 1)
    199#define KSTK_EIP(tsk)	(task_pt_regs(tsk)->psw.addr)
    200#define KSTK_ESP(tsk)	(task_pt_regs(tsk)->gprs[15])
    201
    202/* Has task runtime instrumentation enabled ? */
    203#define is_ri_task(tsk) (!!(tsk)->thread.ri_cb)
    204
    205register unsigned long current_stack_pointer asm("r15");
    206
    207static __always_inline unsigned short stap(void)
    208{
    209	unsigned short cpu_address;
    210
    211	asm volatile("stap %0" : "=Q" (cpu_address));
    212	return cpu_address;
    213}
    214
    215#define cpu_relax() barrier()
    216
    217#define ECAG_CACHE_ATTRIBUTE	0
    218#define ECAG_CPU_ATTRIBUTE	1
    219
    220static inline unsigned long __ecag(unsigned int asi, unsigned char parm)
    221{
    222	unsigned long val;
    223
    224	asm volatile("ecag %0,0,0(%1)" : "=d" (val) : "a" (asi << 8 | parm));
    225	return val;
    226}
    227
    228static inline void psw_set_key(unsigned int key)
    229{
    230	asm volatile("spka 0(%0)" : : "d" (key));
    231}
    232
    233/*
    234 * Set PSW to specified value.
    235 */
    236static inline void __load_psw(psw_t psw)
    237{
    238	asm volatile("lpswe %0" : : "Q" (psw) : "cc");
    239}
    240
    241/*
    242 * Set PSW mask to specified value, while leaving the
    243 * PSW addr pointing to the next instruction.
    244 */
    245static __always_inline void __load_psw_mask(unsigned long mask)
    246{
    247	unsigned long addr;
    248	psw_t psw;
    249
    250	psw.mask = mask;
    251
    252	asm volatile(
    253		"	larl	%0,1f\n"
    254		"	stg	%0,%1\n"
    255		"	lpswe	%2\n"
    256		"1:"
    257		: "=&d" (addr), "=Q" (psw.addr) : "Q" (psw) : "memory", "cc");
    258}
    259
    260/*
    261 * Extract current PSW mask
    262 */
    263static inline unsigned long __extract_psw(void)
    264{
    265	unsigned int reg1, reg2;
    266
    267	asm volatile("epsw %0,%1" : "=d" (reg1), "=a" (reg2));
    268	return (((unsigned long) reg1) << 32) | ((unsigned long) reg2);
    269}
    270
    271static inline void local_mcck_enable(void)
    272{
    273	__load_psw_mask(__extract_psw() | PSW_MASK_MCHECK);
    274}
    275
    276static inline void local_mcck_disable(void)
    277{
    278	__load_psw_mask(__extract_psw() & ~PSW_MASK_MCHECK);
    279}
    280
    281/*
    282 * Rewind PSW instruction address by specified number of bytes.
    283 */
    284static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)
    285{
    286	unsigned long mask;
    287
    288	mask = (psw.mask & PSW_MASK_EA) ? -1UL :
    289	       (psw.mask & PSW_MASK_BA) ? (1UL << 31) - 1 :
    290					  (1UL << 24) - 1;
    291	return (psw.addr - ilc) & mask;
    292}
    293
    294/*
    295 * Function to drop a processor into disabled wait state
    296 */
    297static __always_inline void __noreturn disabled_wait(void)
    298{
    299	psw_t psw;
    300
    301	psw.mask = PSW_MASK_BASE | PSW_MASK_WAIT | PSW_MASK_BA | PSW_MASK_EA;
    302	psw.addr = _THIS_IP_;
    303	__load_psw(psw);
    304	while (1);
    305}
    306
    307#define ARCH_LOW_ADDRESS_LIMIT	0x7fffffffUL
    308
    309extern int memcpy_real(void *, unsigned long, size_t);
    310extern void memcpy_absolute(void *, void *, size_t);
    311
    312#define put_abs_lowcore(member, x) do {					\
    313	unsigned long __abs_address = offsetof(struct lowcore, member);	\
    314	__typeof__(((struct lowcore *)0)->member) __tmp = (x);		\
    315									\
    316	memcpy_absolute(__va(__abs_address), &__tmp, sizeof(__tmp));	\
    317} while (0)
    318
    319#define get_abs_lowcore(x, member) do {					\
    320	unsigned long __abs_address = offsetof(struct lowcore, member);	\
    321	__typeof__(((struct lowcore *)0)->member) *__ptr = &(x);	\
    322									\
    323	memcpy_absolute(__ptr, __va(__abs_address), sizeof(*__ptr));	\
    324} while (0)
    325
    326extern int s390_isolate_bp(void);
    327extern int s390_isolate_bp_guest(void);
    328
    329static __always_inline bool regs_irqs_disabled(struct pt_regs *regs)
    330{
    331	return arch_irqs_disabled_flags(regs->psw.mask);
    332}
    333
    334#endif /* __ASSEMBLY__ */
    335
    336#endif /* __ASM_S390_PROCESSOR_H */