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

armv8_deprecated.c (15705B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  Copyright (C) 2014 ARM Limited
      4 */
      5
      6#include <linux/cpu.h>
      7#include <linux/init.h>
      8#include <linux/list.h>
      9#include <linux/perf_event.h>
     10#include <linux/sched.h>
     11#include <linux/slab.h>
     12#include <linux/sysctl.h>
     13#include <linux/uaccess.h>
     14
     15#include <asm/cpufeature.h>
     16#include <asm/insn.h>
     17#include <asm/sysreg.h>
     18#include <asm/system_misc.h>
     19#include <asm/traps.h>
     20#include <asm/kprobes.h>
     21
     22#define CREATE_TRACE_POINTS
     23#include "trace-events-emulation.h"
     24
     25/*
     26 * The runtime support for deprecated instruction support can be in one of
     27 * following three states -
     28 *
     29 * 0 = undef
     30 * 1 = emulate (software emulation)
     31 * 2 = hw (supported in hardware)
     32 */
     33enum insn_emulation_mode {
     34	INSN_UNDEF,
     35	INSN_EMULATE,
     36	INSN_HW,
     37};
     38
     39enum legacy_insn_status {
     40	INSN_DEPRECATED,
     41	INSN_OBSOLETE,
     42};
     43
     44struct insn_emulation_ops {
     45	const char		*name;
     46	enum legacy_insn_status	status;
     47	struct undef_hook	*hooks;
     48	int			(*set_hw_mode)(bool enable);
     49};
     50
     51struct insn_emulation {
     52	struct list_head node;
     53	struct insn_emulation_ops *ops;
     54	int current_mode;
     55	int min;
     56	int max;
     57};
     58
     59static LIST_HEAD(insn_emulation);
     60static int nr_insn_emulated __initdata;
     61static DEFINE_RAW_SPINLOCK(insn_emulation_lock);
     62
     63static void register_emulation_hooks(struct insn_emulation_ops *ops)
     64{
     65	struct undef_hook *hook;
     66
     67	BUG_ON(!ops->hooks);
     68
     69	for (hook = ops->hooks; hook->instr_mask; hook++)
     70		register_undef_hook(hook);
     71
     72	pr_notice("Registered %s emulation handler\n", ops->name);
     73}
     74
     75static void remove_emulation_hooks(struct insn_emulation_ops *ops)
     76{
     77	struct undef_hook *hook;
     78
     79	BUG_ON(!ops->hooks);
     80
     81	for (hook = ops->hooks; hook->instr_mask; hook++)
     82		unregister_undef_hook(hook);
     83
     84	pr_notice("Removed %s emulation handler\n", ops->name);
     85}
     86
     87static void enable_insn_hw_mode(void *data)
     88{
     89	struct insn_emulation *insn = (struct insn_emulation *)data;
     90	if (insn->ops->set_hw_mode)
     91		insn->ops->set_hw_mode(true);
     92}
     93
     94static void disable_insn_hw_mode(void *data)
     95{
     96	struct insn_emulation *insn = (struct insn_emulation *)data;
     97	if (insn->ops->set_hw_mode)
     98		insn->ops->set_hw_mode(false);
     99}
    100
    101/* Run set_hw_mode(mode) on all active CPUs */
    102static int run_all_cpu_set_hw_mode(struct insn_emulation *insn, bool enable)
    103{
    104	if (!insn->ops->set_hw_mode)
    105		return -EINVAL;
    106	if (enable)
    107		on_each_cpu(enable_insn_hw_mode, (void *)insn, true);
    108	else
    109		on_each_cpu(disable_insn_hw_mode, (void *)insn, true);
    110	return 0;
    111}
    112
    113/*
    114 * Run set_hw_mode for all insns on a starting CPU.
    115 * Returns:
    116 *  0 		- If all the hooks ran successfully.
    117 * -EINVAL	- At least one hook is not supported by the CPU.
    118 */
    119static int run_all_insn_set_hw_mode(unsigned int cpu)
    120{
    121	int rc = 0;
    122	unsigned long flags;
    123	struct insn_emulation *insn;
    124
    125	raw_spin_lock_irqsave(&insn_emulation_lock, flags);
    126	list_for_each_entry(insn, &insn_emulation, node) {
    127		bool enable = (insn->current_mode == INSN_HW);
    128		if (insn->ops->set_hw_mode && insn->ops->set_hw_mode(enable)) {
    129			pr_warn("CPU[%u] cannot support the emulation of %s",
    130				cpu, insn->ops->name);
    131			rc = -EINVAL;
    132		}
    133	}
    134	raw_spin_unlock_irqrestore(&insn_emulation_lock, flags);
    135	return rc;
    136}
    137
    138static int update_insn_emulation_mode(struct insn_emulation *insn,
    139				       enum insn_emulation_mode prev)
    140{
    141	int ret = 0;
    142
    143	switch (prev) {
    144	case INSN_UNDEF: /* Nothing to be done */
    145		break;
    146	case INSN_EMULATE:
    147		remove_emulation_hooks(insn->ops);
    148		break;
    149	case INSN_HW:
    150		if (!run_all_cpu_set_hw_mode(insn, false))
    151			pr_notice("Disabled %s support\n", insn->ops->name);
    152		break;
    153	}
    154
    155	switch (insn->current_mode) {
    156	case INSN_UNDEF:
    157		break;
    158	case INSN_EMULATE:
    159		register_emulation_hooks(insn->ops);
    160		break;
    161	case INSN_HW:
    162		ret = run_all_cpu_set_hw_mode(insn, true);
    163		if (!ret)
    164			pr_notice("Enabled %s support\n", insn->ops->name);
    165		break;
    166	}
    167
    168	return ret;
    169}
    170
    171static void __init register_insn_emulation(struct insn_emulation_ops *ops)
    172{
    173	unsigned long flags;
    174	struct insn_emulation *insn;
    175
    176	insn = kzalloc(sizeof(*insn), GFP_KERNEL);
    177	if (!insn)
    178		return;
    179
    180	insn->ops = ops;
    181	insn->min = INSN_UNDEF;
    182
    183	switch (ops->status) {
    184	case INSN_DEPRECATED:
    185		insn->current_mode = INSN_EMULATE;
    186		/* Disable the HW mode if it was turned on at early boot time */
    187		run_all_cpu_set_hw_mode(insn, false);
    188		insn->max = INSN_HW;
    189		break;
    190	case INSN_OBSOLETE:
    191		insn->current_mode = INSN_UNDEF;
    192		insn->max = INSN_EMULATE;
    193		break;
    194	}
    195
    196	raw_spin_lock_irqsave(&insn_emulation_lock, flags);
    197	list_add(&insn->node, &insn_emulation);
    198	nr_insn_emulated++;
    199	raw_spin_unlock_irqrestore(&insn_emulation_lock, flags);
    200
    201	/* Register any handlers if required */
    202	update_insn_emulation_mode(insn, INSN_UNDEF);
    203}
    204
    205static int emulation_proc_handler(struct ctl_table *table, int write,
    206				  void *buffer, size_t *lenp,
    207				  loff_t *ppos)
    208{
    209	int ret = 0;
    210	struct insn_emulation *insn = (struct insn_emulation *) table->data;
    211	enum insn_emulation_mode prev_mode = insn->current_mode;
    212
    213	table->data = &insn->current_mode;
    214	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
    215
    216	if (ret || !write || prev_mode == insn->current_mode)
    217		goto ret;
    218
    219	ret = update_insn_emulation_mode(insn, prev_mode);
    220	if (ret) {
    221		/* Mode change failed, revert to previous mode. */
    222		insn->current_mode = prev_mode;
    223		update_insn_emulation_mode(insn, INSN_UNDEF);
    224	}
    225ret:
    226	table->data = insn;
    227	return ret;
    228}
    229
    230static void __init register_insn_emulation_sysctl(void)
    231{
    232	unsigned long flags;
    233	int i = 0;
    234	struct insn_emulation *insn;
    235	struct ctl_table *insns_sysctl, *sysctl;
    236
    237	insns_sysctl = kcalloc(nr_insn_emulated + 1, sizeof(*sysctl),
    238			       GFP_KERNEL);
    239	if (!insns_sysctl)
    240		return;
    241
    242	raw_spin_lock_irqsave(&insn_emulation_lock, flags);
    243	list_for_each_entry(insn, &insn_emulation, node) {
    244		sysctl = &insns_sysctl[i];
    245
    246		sysctl->mode = 0644;
    247		sysctl->maxlen = sizeof(int);
    248
    249		sysctl->procname = insn->ops->name;
    250		sysctl->data = insn;
    251		sysctl->extra1 = &insn->min;
    252		sysctl->extra2 = &insn->max;
    253		sysctl->proc_handler = emulation_proc_handler;
    254		i++;
    255	}
    256	raw_spin_unlock_irqrestore(&insn_emulation_lock, flags);
    257
    258	register_sysctl("abi", insns_sysctl);
    259}
    260
    261/*
    262 *  Implement emulation of the SWP/SWPB instructions using load-exclusive and
    263 *  store-exclusive.
    264 *
    265 *  Syntax of SWP{B} instruction: SWP{B}<c> <Rt>, <Rt2>, [<Rn>]
    266 *  Where: Rt  = destination
    267 *	   Rt2 = source
    268 *	   Rn  = address
    269 */
    270
    271/*
    272 * Error-checking SWP macros implemented using ldxr{b}/stxr{b}
    273 */
    274
    275/* Arbitrary constant to ensure forward-progress of the LL/SC loop */
    276#define __SWP_LL_SC_LOOPS	4
    277
    278#define __user_swpX_asm(data, addr, res, temp, temp2, B)	\
    279do {								\
    280	uaccess_enable_privileged();				\
    281	__asm__ __volatile__(					\
    282	"	mov		%w3, %w6\n"			\
    283	"0:	ldxr"B"		%w2, [%4]\n"			\
    284	"1:	stxr"B"		%w0, %w1, [%4]\n"		\
    285	"	cbz		%w0, 2f\n"			\
    286	"	sub		%w3, %w3, #1\n"			\
    287	"	cbnz		%w3, 0b\n"			\
    288	"	mov		%w0, %w5\n"			\
    289	"	b		3f\n"				\
    290	"2:\n"							\
    291	"	mov		%w1, %w2\n"			\
    292	"3:\n"							\
    293	_ASM_EXTABLE_UACCESS_ERR(0b, 3b, %w0)			\
    294	_ASM_EXTABLE_UACCESS_ERR(1b, 3b, %w0)			\
    295	: "=&r" (res), "+r" (data), "=&r" (temp), "=&r" (temp2)	\
    296	: "r" ((unsigned long)addr), "i" (-EAGAIN),		\
    297	  "i" (__SWP_LL_SC_LOOPS)				\
    298	: "memory");						\
    299	uaccess_disable_privileged();				\
    300} while (0)
    301
    302#define __user_swp_asm(data, addr, res, temp, temp2) \
    303	__user_swpX_asm(data, addr, res, temp, temp2, "")
    304#define __user_swpb_asm(data, addr, res, temp, temp2) \
    305	__user_swpX_asm(data, addr, res, temp, temp2, "b")
    306
    307/*
    308 * Bit 22 of the instruction encoding distinguishes between
    309 * the SWP and SWPB variants (bit set means SWPB).
    310 */
    311#define TYPE_SWPB (1 << 22)
    312
    313static int emulate_swpX(unsigned int address, unsigned int *data,
    314			unsigned int type)
    315{
    316	unsigned int res = 0;
    317
    318	if ((type != TYPE_SWPB) && (address & 0x3)) {
    319		/* SWP to unaligned address not permitted */
    320		pr_debug("SWP instruction on unaligned pointer!\n");
    321		return -EFAULT;
    322	}
    323
    324	while (1) {
    325		unsigned long temp, temp2;
    326
    327		if (type == TYPE_SWPB)
    328			__user_swpb_asm(*data, address, res, temp, temp2);
    329		else
    330			__user_swp_asm(*data, address, res, temp, temp2);
    331
    332		if (likely(res != -EAGAIN) || signal_pending(current))
    333			break;
    334
    335		cond_resched();
    336	}
    337
    338	return res;
    339}
    340
    341#define ARM_OPCODE_CONDTEST_FAIL   0
    342#define ARM_OPCODE_CONDTEST_PASS   1
    343#define ARM_OPCODE_CONDTEST_UNCOND 2
    344
    345#define	ARM_OPCODE_CONDITION_UNCOND	0xf
    346
    347static unsigned int __kprobes aarch32_check_condition(u32 opcode, u32 psr)
    348{
    349	u32 cc_bits  = opcode >> 28;
    350
    351	if (cc_bits != ARM_OPCODE_CONDITION_UNCOND) {
    352		if ((*aarch32_opcode_cond_checks[cc_bits])(psr))
    353			return ARM_OPCODE_CONDTEST_PASS;
    354		else
    355			return ARM_OPCODE_CONDTEST_FAIL;
    356	}
    357	return ARM_OPCODE_CONDTEST_UNCOND;
    358}
    359
    360/*
    361 * swp_handler logs the id of calling process, dissects the instruction, sanity
    362 * checks the memory location, calls emulate_swpX for the actual operation and
    363 * deals with fixup/error handling before returning
    364 */
    365static int swp_handler(struct pt_regs *regs, u32 instr)
    366{
    367	u32 destreg, data, type, address = 0;
    368	const void __user *user_ptr;
    369	int rn, rt2, res = 0;
    370
    371	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc);
    372
    373	type = instr & TYPE_SWPB;
    374
    375	switch (aarch32_check_condition(instr, regs->pstate)) {
    376	case ARM_OPCODE_CONDTEST_PASS:
    377		break;
    378	case ARM_OPCODE_CONDTEST_FAIL:
    379		/* Condition failed - return to next instruction */
    380		goto ret;
    381	case ARM_OPCODE_CONDTEST_UNCOND:
    382		/* If unconditional encoding - not a SWP, undef */
    383		return -EFAULT;
    384	default:
    385		return -EINVAL;
    386	}
    387
    388	rn = aarch32_insn_extract_reg_num(instr, A32_RN_OFFSET);
    389	rt2 = aarch32_insn_extract_reg_num(instr, A32_RT2_OFFSET);
    390
    391	address = (u32)regs->user_regs.regs[rn];
    392	data	= (u32)regs->user_regs.regs[rt2];
    393	destreg = aarch32_insn_extract_reg_num(instr, A32_RT_OFFSET);
    394
    395	pr_debug("addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n",
    396		rn, address, destreg,
    397		aarch32_insn_extract_reg_num(instr, A32_RT2_OFFSET), data);
    398
    399	/* Check access in reasonable access range for both SWP and SWPB */
    400	user_ptr = (const void __user *)(unsigned long)(address & ~3);
    401	if (!access_ok(user_ptr, 4)) {
    402		pr_debug("SWP{B} emulation: access to 0x%08x not allowed!\n",
    403			address);
    404		goto fault;
    405	}
    406
    407	res = emulate_swpX(address, &data, type);
    408	if (res == -EFAULT)
    409		goto fault;
    410	else if (res == 0)
    411		regs->user_regs.regs[destreg] = data;
    412
    413ret:
    414	if (type == TYPE_SWPB)
    415		trace_instruction_emulation("swpb", regs->pc);
    416	else
    417		trace_instruction_emulation("swp", regs->pc);
    418
    419	pr_warn_ratelimited("\"%s\" (%ld) uses obsolete SWP{B} instruction at 0x%llx\n",
    420			current->comm, (unsigned long)current->pid, regs->pc);
    421
    422	arm64_skip_faulting_instruction(regs, 4);
    423	return 0;
    424
    425fault:
    426	pr_debug("SWP{B} emulation: access caused memory abort!\n");
    427	arm64_notify_segfault(address);
    428
    429	return 0;
    430}
    431
    432/*
    433 * Only emulate SWP/SWPB executed in ARM state/User mode.
    434 * The kernel must be SWP free and SWP{B} does not exist in Thumb.
    435 */
    436static struct undef_hook swp_hooks[] = {
    437	{
    438		.instr_mask	= 0x0fb00ff0,
    439		.instr_val	= 0x01000090,
    440		.pstate_mask	= PSR_AA32_MODE_MASK,
    441		.pstate_val	= PSR_AA32_MODE_USR,
    442		.fn		= swp_handler
    443	},
    444	{ }
    445};
    446
    447static struct insn_emulation_ops swp_ops = {
    448	.name = "swp",
    449	.status = INSN_OBSOLETE,
    450	.hooks = swp_hooks,
    451	.set_hw_mode = NULL,
    452};
    453
    454static int cp15barrier_handler(struct pt_regs *regs, u32 instr)
    455{
    456	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc);
    457
    458	switch (aarch32_check_condition(instr, regs->pstate)) {
    459	case ARM_OPCODE_CONDTEST_PASS:
    460		break;
    461	case ARM_OPCODE_CONDTEST_FAIL:
    462		/* Condition failed - return to next instruction */
    463		goto ret;
    464	case ARM_OPCODE_CONDTEST_UNCOND:
    465		/* If unconditional encoding - not a barrier instruction */
    466		return -EFAULT;
    467	default:
    468		return -EINVAL;
    469	}
    470
    471	switch (aarch32_insn_mcr_extract_crm(instr)) {
    472	case 10:
    473		/*
    474		 * dmb - mcr p15, 0, Rt, c7, c10, 5
    475		 * dsb - mcr p15, 0, Rt, c7, c10, 4
    476		 */
    477		if (aarch32_insn_mcr_extract_opc2(instr) == 5) {
    478			dmb(sy);
    479			trace_instruction_emulation(
    480				"mcr p15, 0, Rt, c7, c10, 5 ; dmb", regs->pc);
    481		} else {
    482			dsb(sy);
    483			trace_instruction_emulation(
    484				"mcr p15, 0, Rt, c7, c10, 4 ; dsb", regs->pc);
    485		}
    486		break;
    487	case 5:
    488		/*
    489		 * isb - mcr p15, 0, Rt, c7, c5, 4
    490		 *
    491		 * Taking an exception or returning from one acts as an
    492		 * instruction barrier. So no explicit barrier needed here.
    493		 */
    494		trace_instruction_emulation(
    495			"mcr p15, 0, Rt, c7, c5, 4 ; isb", regs->pc);
    496		break;
    497	}
    498
    499ret:
    500	pr_warn_ratelimited("\"%s\" (%ld) uses deprecated CP15 Barrier instruction at 0x%llx\n",
    501			current->comm, (unsigned long)current->pid, regs->pc);
    502
    503	arm64_skip_faulting_instruction(regs, 4);
    504	return 0;
    505}
    506
    507static int cp15_barrier_set_hw_mode(bool enable)
    508{
    509	if (enable)
    510		sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_CP15BEN);
    511	else
    512		sysreg_clear_set(sctlr_el1, SCTLR_EL1_CP15BEN, 0);
    513	return 0;
    514}
    515
    516static struct undef_hook cp15_barrier_hooks[] = {
    517	{
    518		.instr_mask	= 0x0fff0fdf,
    519		.instr_val	= 0x0e070f9a,
    520		.pstate_mask	= PSR_AA32_MODE_MASK,
    521		.pstate_val	= PSR_AA32_MODE_USR,
    522		.fn		= cp15barrier_handler,
    523	},
    524	{
    525		.instr_mask	= 0x0fff0fff,
    526		.instr_val	= 0x0e070f95,
    527		.pstate_mask	= PSR_AA32_MODE_MASK,
    528		.pstate_val	= PSR_AA32_MODE_USR,
    529		.fn		= cp15barrier_handler,
    530	},
    531	{ }
    532};
    533
    534static struct insn_emulation_ops cp15_barrier_ops = {
    535	.name = "cp15_barrier",
    536	.status = INSN_DEPRECATED,
    537	.hooks = cp15_barrier_hooks,
    538	.set_hw_mode = cp15_barrier_set_hw_mode,
    539};
    540
    541static int setend_set_hw_mode(bool enable)
    542{
    543	if (!cpu_supports_mixed_endian_el0())
    544		return -EINVAL;
    545
    546	if (enable)
    547		sysreg_clear_set(sctlr_el1, SCTLR_EL1_SED, 0);
    548	else
    549		sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_SED);
    550	return 0;
    551}
    552
    553static int compat_setend_handler(struct pt_regs *regs, u32 big_endian)
    554{
    555	char *insn;
    556
    557	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc);
    558
    559	if (big_endian) {
    560		insn = "setend be";
    561		regs->pstate |= PSR_AA32_E_BIT;
    562	} else {
    563		insn = "setend le";
    564		regs->pstate &= ~PSR_AA32_E_BIT;
    565	}
    566
    567	trace_instruction_emulation(insn, regs->pc);
    568	pr_warn_ratelimited("\"%s\" (%ld) uses deprecated setend instruction at 0x%llx\n",
    569			current->comm, (unsigned long)current->pid, regs->pc);
    570
    571	return 0;
    572}
    573
    574static int a32_setend_handler(struct pt_regs *regs, u32 instr)
    575{
    576	int rc = compat_setend_handler(regs, (instr >> 9) & 1);
    577	arm64_skip_faulting_instruction(regs, 4);
    578	return rc;
    579}
    580
    581static int t16_setend_handler(struct pt_regs *regs, u32 instr)
    582{
    583	int rc = compat_setend_handler(regs, (instr >> 3) & 1);
    584	arm64_skip_faulting_instruction(regs, 2);
    585	return rc;
    586}
    587
    588static struct undef_hook setend_hooks[] = {
    589	{
    590		.instr_mask	= 0xfffffdff,
    591		.instr_val	= 0xf1010000,
    592		.pstate_mask	= PSR_AA32_MODE_MASK,
    593		.pstate_val	= PSR_AA32_MODE_USR,
    594		.fn		= a32_setend_handler,
    595	},
    596	{
    597		/* Thumb mode */
    598		.instr_mask	= 0xfffffff7,
    599		.instr_val	= 0x0000b650,
    600		.pstate_mask	= (PSR_AA32_T_BIT | PSR_AA32_MODE_MASK),
    601		.pstate_val	= (PSR_AA32_T_BIT | PSR_AA32_MODE_USR),
    602		.fn		= t16_setend_handler,
    603	},
    604	{}
    605};
    606
    607static struct insn_emulation_ops setend_ops = {
    608	.name = "setend",
    609	.status = INSN_DEPRECATED,
    610	.hooks = setend_hooks,
    611	.set_hw_mode = setend_set_hw_mode,
    612};
    613
    614/*
    615 * Invoked as core_initcall, which guarantees that the instruction
    616 * emulation is ready for userspace.
    617 */
    618static int __init armv8_deprecated_init(void)
    619{
    620	if (IS_ENABLED(CONFIG_SWP_EMULATION))
    621		register_insn_emulation(&swp_ops);
    622
    623	if (IS_ENABLED(CONFIG_CP15_BARRIER_EMULATION))
    624		register_insn_emulation(&cp15_barrier_ops);
    625
    626	if (IS_ENABLED(CONFIG_SETEND_EMULATION)) {
    627		if (system_supports_mixed_endian_el0())
    628			register_insn_emulation(&setend_ops);
    629		else
    630			pr_info("setend instruction emulation is not supported on this system\n");
    631	}
    632
    633	cpuhp_setup_state_nocalls(CPUHP_AP_ARM64_ISNDEP_STARTING,
    634				  "arm64/isndep:starting",
    635				  run_all_insn_set_hw_mode, NULL);
    636	register_insn_emulation_sysctl();
    637
    638	return 0;
    639}
    640
    641core_initcall(armv8_deprecated_init);