1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef ARCH_S390_ENTRY_PERCPU_H 3 #define ARCH_S390_ENTRY_PERCPU_H 4 5 #include <linux/bitfield.h> 6 #include <linux/percpu.h> 7 #include <asm/lowcore.h> 8 #include <asm/ptrace.h> 9 10 static __always_inline void percpu_entry(struct pt_regs *regs) 11 { 12 struct lowcore *lc = get_lowcore(); 13 14 regs->cpu = lc->cpu_nr; 15 regs->percpu_register = lc->percpu_register; 16 lc->percpu_register = 0; 17 } 18 19 static __always_inline void percpu_exit(struct pt_regs *regs) 20 { 21 unsigned char regval, regpcp, regoff, regptr; 22 struct lowcore *lc = get_lowcore(); 23 24 if (!regs->percpu_register) 25 return; 26 regval = regs->percpu_register; 27 lc->percpu_register = regval; 28 /* Migrated to a different CPU? */ 29 if (regs->cpu == lc->cpu_nr) 30 return; 31 regpcp = FIELD_GET(PCPU_REG_PCP, regval); 32 regoff = FIELD_GET(PCPU_REG_OFF, regval); 33 regptr = regoff + 1; 34 /* 35 * Update register 'regoff' with the current CPU's percpu offset, 36 * and recalculate and update current CPU's percpu variable address 37 * contained in register 'regptr'. 38 */ 39 regs->gprs[regoff] = lc->percpu_offset; 40 regs->gprs[regptr] = regs->gprs[regpcp] + regs->gprs[regoff]; 41 } 42 43 #endif 44