1ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal/* 2ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal * Copyright (C) 2014 ARM Limited 3ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal * 4ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal * This program is free software; you can redistribute it and/or modify 5ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal * it under the terms of the GNU General Public License version 2 as 6ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal * published by the Free Software Foundation. 7ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal */ 8ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 9cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal#include <linux/cpu.h> 10ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal#include <linux/init.h> 11ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal#include <linux/list.h> 12f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal#include <linux/perf_event.h> 13f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal#include <linux/sched.h> 14ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal#include <linux/slab.h> 15ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal#include <linux/sysctl.h> 16ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 17f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal#include <asm/insn.h> 18f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal#include <asm/opcodes.h> 19f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal#include <asm/system_misc.h> 20ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal#include <asm/traps.h> 21f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal#include <asm/uaccess.h> 2268b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose#include <asm/cpufeature.h> 23ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 24203077a7db3bc692ff8177e822110400868efab4Punit Agrawal#define CREATE_TRACE_POINTS 25203077a7db3bc692ff8177e822110400868efab4Punit Agrawal#include "trace-events-emulation.h" 26203077a7db3bc692ff8177e822110400868efab4Punit Agrawal 27ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal/* 28ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal * The runtime support for deprecated instruction support can be in one of 29ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal * following three states - 30ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal * 31ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal * 0 = undef 32ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal * 1 = emulate (software emulation) 33ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal * 2 = hw (supported in hardware) 34ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal */ 35ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalenum insn_emulation_mode { 36ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal INSN_UNDEF, 37ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal INSN_EMULATE, 38ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal INSN_HW, 39ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal}; 40ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 41ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalenum legacy_insn_status { 42ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal INSN_DEPRECATED, 43ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal INSN_OBSOLETE, 44ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal}; 45ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 46ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalstruct insn_emulation_ops { 47ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal const char *name; 48ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal enum legacy_insn_status status; 49ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal struct undef_hook *hooks; 50ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal int (*set_hw_mode)(bool enable); 51ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal}; 52ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 53ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalstruct insn_emulation { 54ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal struct list_head node; 55ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal struct insn_emulation_ops *ops; 56ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal int current_mode; 57ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal int min; 58ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal int max; 59ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal}; 60ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 61ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalstatic LIST_HEAD(insn_emulation); 62ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalstatic int nr_insn_emulated; 63ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalstatic DEFINE_RAW_SPINLOCK(insn_emulation_lock); 64ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 65ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalstatic void register_emulation_hooks(struct insn_emulation_ops *ops) 66ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal{ 67ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal struct undef_hook *hook; 68ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 69ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal BUG_ON(!ops->hooks); 70ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 71ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal for (hook = ops->hooks; hook->instr_mask; hook++) 72ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal register_undef_hook(hook); 73ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 74ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal pr_notice("Registered %s emulation handler\n", ops->name); 75ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal} 76ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 77ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalstatic void remove_emulation_hooks(struct insn_emulation_ops *ops) 78ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal{ 79ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal struct undef_hook *hook; 80ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 81ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal BUG_ON(!ops->hooks); 82ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 83ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal for (hook = ops->hooks; hook->instr_mask; hook++) 84ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal unregister_undef_hook(hook); 85ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 86ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal pr_notice("Removed %s emulation handler\n", ops->name); 87ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal} 88ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 8968b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulosestatic void enable_insn_hw_mode(void *data) 9068b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose{ 9168b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose struct insn_emulation *insn = (struct insn_emulation *)data; 9268b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose if (insn->ops->set_hw_mode) 9368b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose insn->ops->set_hw_mode(true); 9468b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose} 9568b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose 9668b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulosestatic void disable_insn_hw_mode(void *data) 9768b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose{ 9868b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose struct insn_emulation *insn = (struct insn_emulation *)data; 9968b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose if (insn->ops->set_hw_mode) 10068b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose insn->ops->set_hw_mode(false); 10168b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose} 10268b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose 10368b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose/* Run set_hw_mode(mode) on all active CPUs */ 10468b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulosestatic int run_all_cpu_set_hw_mode(struct insn_emulation *insn, bool enable) 10568b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose{ 10668b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose if (!insn->ops->set_hw_mode) 10768b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose return -EINVAL; 10868b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose if (enable) 10968b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose on_each_cpu(enable_insn_hw_mode, (void *)insn, true); 11068b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose else 11168b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose on_each_cpu(disable_insn_hw_mode, (void *)insn, true); 11268b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose return 0; 11368b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose} 11468b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose 11568b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose/* 11668b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose * Run set_hw_mode for all insns on a starting CPU. 11768b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose * Returns: 11868b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose * 0 - If all the hooks ran successfully. 11968b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose * -EINVAL - At least one hook is not supported by the CPU. 12068b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose */ 12168b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulosestatic int run_all_insn_set_hw_mode(unsigned long cpu) 12268b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose{ 12368b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose int rc = 0; 12468b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose unsigned long flags; 12568b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose struct insn_emulation *insn; 12668b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose 12768b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose raw_spin_lock_irqsave(&insn_emulation_lock, flags); 12868b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose list_for_each_entry(insn, &insn_emulation, node) { 12968b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose bool enable = (insn->current_mode == INSN_HW); 13068b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose if (insn->ops->set_hw_mode && insn->ops->set_hw_mode(enable)) { 13168b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose pr_warn("CPU[%ld] cannot support the emulation of %s", 13268b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose cpu, insn->ops->name); 13368b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose rc = -EINVAL; 13468b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose } 13568b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose } 13668b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose raw_spin_unlock_irqrestore(&insn_emulation_lock, flags); 13768b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose return rc; 13868b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose} 13968b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose 140ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalstatic int update_insn_emulation_mode(struct insn_emulation *insn, 141ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal enum insn_emulation_mode prev) 142ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal{ 143ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal int ret = 0; 144ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 145ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal switch (prev) { 146ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal case INSN_UNDEF: /* Nothing to be done */ 147ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal break; 148ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal case INSN_EMULATE: 149ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal remove_emulation_hooks(insn->ops); 150ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal break; 151ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal case INSN_HW: 15268b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose if (!run_all_cpu_set_hw_mode(insn, false)) 153ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal pr_notice("Disabled %s support\n", insn->ops->name); 154ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal break; 155ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal } 156ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 157ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal switch (insn->current_mode) { 158ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal case INSN_UNDEF: 159ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal break; 160ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal case INSN_EMULATE: 161ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal register_emulation_hooks(insn->ops); 162ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal break; 163ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal case INSN_HW: 16468b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose ret = run_all_cpu_set_hw_mode(insn, true); 16568b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose if (!ret) 166ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal pr_notice("Enabled %s support\n", insn->ops->name); 167ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal break; 168ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal } 169ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 170ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal return ret; 171ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal} 172ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 173ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalstatic void register_insn_emulation(struct insn_emulation_ops *ops) 174ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal{ 175ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal unsigned long flags; 176ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal struct insn_emulation *insn; 177ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 178ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal insn = kzalloc(sizeof(*insn), GFP_KERNEL); 179ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal insn->ops = ops; 180ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal insn->min = INSN_UNDEF; 181ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 182ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal switch (ops->status) { 183ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal case INSN_DEPRECATED: 184ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal insn->current_mode = INSN_EMULATE; 18568b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose /* Disable the HW mode if it was turned on at early boot time */ 18668b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose run_all_cpu_set_hw_mode(insn, false); 187ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal insn->max = INSN_HW; 188ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal break; 189ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal case INSN_OBSOLETE: 190ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal insn->current_mode = INSN_UNDEF; 191ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal insn->max = INSN_EMULATE; 192ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal break; 193ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal } 194ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 195ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal raw_spin_lock_irqsave(&insn_emulation_lock, flags); 196ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal list_add(&insn->node, &insn_emulation); 197ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal nr_insn_emulated++; 198ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal raw_spin_unlock_irqrestore(&insn_emulation_lock, flags); 199ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 200ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal /* Register any handlers if required */ 201ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal update_insn_emulation_mode(insn, INSN_UNDEF); 202ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal} 203ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 204ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalstatic int emulation_proc_handler(struct ctl_table *table, int write, 205ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal void __user *buffer, size_t *lenp, 206ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal loff_t *ppos) 207ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal{ 208ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal int ret = 0; 209ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal struct insn_emulation *insn = (struct insn_emulation *) table->data; 210ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal enum insn_emulation_mode prev_mode = insn->current_mode; 211ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 212ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal table->data = &insn->current_mode; 213ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); 214ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 215ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal if (ret || !write || prev_mode == insn->current_mode) 216ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal goto ret; 217ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 218ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal ret = update_insn_emulation_mode(insn, prev_mode); 219c5650ea788e45467ce5aa944829f3e6f72e6a9ebWill Deacon if (ret) { 220ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal /* Mode change failed, revert to previous mode. */ 221ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal insn->current_mode = prev_mode; 222ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal update_insn_emulation_mode(insn, INSN_UNDEF); 223ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal } 224ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalret: 225ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal table->data = insn; 226ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal return ret; 227ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal} 228ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 229ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalstatic struct ctl_table ctl_abi[] = { 230ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal { 231ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal .procname = "abi", 232ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal .mode = 0555, 233ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal }, 234ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal { } 235ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal}; 236ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 237ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalstatic void register_insn_emulation_sysctl(struct ctl_table *table) 238ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal{ 239ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal unsigned long flags; 240ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal int i = 0; 241ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal struct insn_emulation *insn; 242ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal struct ctl_table *insns_sysctl, *sysctl; 243ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 244ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal insns_sysctl = kzalloc(sizeof(*sysctl) * (nr_insn_emulated + 1), 245ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal GFP_KERNEL); 246ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 247ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal raw_spin_lock_irqsave(&insn_emulation_lock, flags); 248ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal list_for_each_entry(insn, &insn_emulation, node) { 249ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal sysctl = &insns_sysctl[i]; 250ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 251ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal sysctl->mode = 0644; 252ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal sysctl->maxlen = sizeof(int); 253ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 254ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal sysctl->procname = insn->ops->name; 255ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal sysctl->data = insn; 256ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal sysctl->extra1 = &insn->min; 257ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal sysctl->extra2 = &insn->max; 258ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal sysctl->proc_handler = emulation_proc_handler; 259ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal i++; 260ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal } 261ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal raw_spin_unlock_irqrestore(&insn_emulation_lock, flags); 262ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 263ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal table->child = insns_sysctl; 264ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal register_sysctl_table(table); 265ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal} 266ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 267ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal/* 268f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * Implement emulation of the SWP/SWPB instructions using load-exclusive and 269f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * store-exclusive. 270f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * 271f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * Syntax of SWP{B} instruction: SWP{B}<c> <Rt>, <Rt2>, [<Rn>] 272f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * Where: Rt = destination 273f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * Rt2 = source 274f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * Rn = address 275f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal */ 276f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 277f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal/* 278f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * Error-checking SWP macros implemented using ldxr{b}/stxr{b} 279f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal */ 280f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal#define __user_swpX_asm(data, addr, res, temp, B) \ 281f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal __asm__ __volatile__( \ 282f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal " mov %w2, %w1\n" \ 283f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal "0: ldxr"B" %w1, [%3]\n" \ 284f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal "1: stxr"B" %w0, %w2, [%3]\n" \ 285f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal " cbz %w0, 2f\n" \ 286f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal " mov %w0, %w4\n" \ 287f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal "2:\n" \ 288f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal " .pushsection .fixup,\"ax\"\n" \ 289f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal " .align 2\n" \ 290f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal "3: mov %w0, %w5\n" \ 291f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal " b 2b\n" \ 292f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal " .popsection" \ 293f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal " .pushsection __ex_table,\"a\"\n" \ 294f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal " .align 3\n" \ 295f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal " .quad 0b, 3b\n" \ 296f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal " .quad 1b, 3b\n" \ 297f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal " .popsection" \ 298f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal : "=&r" (res), "+r" (data), "=&r" (temp) \ 299f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \ 300f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal : "memory") 301f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 302f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal#define __user_swp_asm(data, addr, res, temp) \ 303f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal __user_swpX_asm(data, addr, res, temp, "") 304f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal#define __user_swpb_asm(data, addr, res, temp) \ 305f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal __user_swpX_asm(data, addr, res, temp, "b") 306f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 307f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal/* 308f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * Bit 22 of the instruction encoding distinguishes between 309f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * the SWP and SWPB variants (bit set means SWPB). 310f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal */ 311f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal#define TYPE_SWPB (1 << 22) 312f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 313f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal/* 314f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * Set up process info to signal segmentation fault - called on access error. 315f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal */ 316f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawalstatic void set_segfault(struct pt_regs *regs, unsigned long addr) 317f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal{ 318f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal siginfo_t info; 319f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 320f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal down_read(¤t->mm->mmap_sem); 321f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal if (find_vma(current->mm, addr) == NULL) 322f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal info.si_code = SEGV_MAPERR; 323f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal else 324f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal info.si_code = SEGV_ACCERR; 325f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal up_read(¤t->mm->mmap_sem); 326f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 327f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal info.si_signo = SIGSEGV; 328f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal info.si_errno = 0; 329f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal info.si_addr = (void *) instruction_pointer(regs); 330f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 331f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal pr_debug("SWP{B} emulation: access caused memory abort!\n"); 332f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal arm64_notify_die("Illegal memory access", regs, &info, 0); 333f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal} 334f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 335f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawalstatic int emulate_swpX(unsigned int address, unsigned int *data, 336f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal unsigned int type) 337f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal{ 338f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal unsigned int res = 0; 339f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 340f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal if ((type != TYPE_SWPB) && (address & 0x3)) { 341f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal /* SWP to unaligned address not permitted */ 342f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal pr_debug("SWP instruction on unaligned pointer!\n"); 343f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal return -EFAULT; 344f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal } 345f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 346f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal while (1) { 347f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal unsigned long temp; 348f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 349f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal if (type == TYPE_SWPB) 350f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal __user_swpb_asm(*data, address, res, temp); 351f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal else 352f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal __user_swp_asm(*data, address, res, temp); 353f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 354f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal if (likely(res != -EAGAIN) || signal_pending(current)) 355f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal break; 356f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 357f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal cond_resched(); 358f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal } 359f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 360f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal return res; 361f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal} 362f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 363f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal/* 364f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * swp_handler logs the id of calling process, dissects the instruction, sanity 365f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * checks the memory location, calls emulate_swpX for the actual operation and 366f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * deals with fixup/error handling before returning 367f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal */ 368f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawalstatic int swp_handler(struct pt_regs *regs, u32 instr) 369f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal{ 370f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal u32 destreg, data, type, address = 0; 371f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal int rn, rt2, res = 0; 372f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 373f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc); 374f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 375f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal type = instr & TYPE_SWPB; 376f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 377f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal switch (arm_check_condition(instr, regs->pstate)) { 378f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal case ARM_OPCODE_CONDTEST_PASS: 379f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal break; 380f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal case ARM_OPCODE_CONDTEST_FAIL: 381f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal /* Condition failed - return to next instruction */ 382f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal goto ret; 383f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal case ARM_OPCODE_CONDTEST_UNCOND: 384f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal /* If unconditional encoding - not a SWP, undef */ 385f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal return -EFAULT; 386f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal default: 387f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal return -EINVAL; 388f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal } 389f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 390f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal rn = aarch32_insn_extract_reg_num(instr, A32_RN_OFFSET); 391f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal rt2 = aarch32_insn_extract_reg_num(instr, A32_RT2_OFFSET); 392f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 393f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal address = (u32)regs->user_regs.regs[rn]; 394f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal data = (u32)regs->user_regs.regs[rt2]; 395f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal destreg = aarch32_insn_extract_reg_num(instr, A32_RT_OFFSET); 396f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 397f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal pr_debug("addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n", 398f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal rn, address, destreg, 399f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal aarch32_insn_extract_reg_num(instr, A32_RT2_OFFSET), data); 400f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 401f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal /* Check access in reasonable access range for both SWP and SWPB */ 402f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal if (!access_ok(VERIFY_WRITE, (address & ~3), 4)) { 403f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal pr_debug("SWP{B} emulation: access to 0x%08x not allowed!\n", 404f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal address); 405f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal goto fault; 406f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal } 407f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 408f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal res = emulate_swpX(address, &data, type); 409f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal if (res == -EFAULT) 410f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal goto fault; 411f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal else if (res == 0) 412f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal regs->user_regs.regs[destreg] = data; 413f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 414f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawalret: 415203077a7db3bc692ff8177e822110400868efab4Punit Agrawal if (type == TYPE_SWPB) 416203077a7db3bc692ff8177e822110400868efab4Punit Agrawal trace_instruction_emulation("swpb", regs->pc); 417203077a7db3bc692ff8177e822110400868efab4Punit Agrawal else 418203077a7db3bc692ff8177e822110400868efab4Punit Agrawal trace_instruction_emulation("swp", regs->pc); 419203077a7db3bc692ff8177e822110400868efab4Punit Agrawal 420f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal pr_warn_ratelimited("\"%s\" (%ld) uses obsolete SWP{B} instruction at 0x%llx\n", 421f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal current->comm, (unsigned long)current->pid, regs->pc); 422f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 423f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal regs->pc += 4; 424f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal return 0; 425f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 426f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawalfault: 427f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal set_segfault(regs, address); 428f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 429f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal return 0; 430f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal} 431f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 432f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal/* 433f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * Only emulate SWP/SWPB executed in ARM state/User mode. 434f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal * The kernel must be SWP free and SWP{B} does not exist in Thumb. 435f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal */ 436f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawalstatic struct undef_hook swp_hooks[] = { 437f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal { 438f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal .instr_mask = 0x0fb00ff0, 439f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal .instr_val = 0x01000090, 440f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal .pstate_mask = COMPAT_PSR_MODE_MASK, 441f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal .pstate_val = COMPAT_PSR_MODE_USR, 442f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal .fn = swp_handler 443f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal }, 444f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal { } 445f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal}; 446f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 447f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawalstatic struct insn_emulation_ops swp_ops = { 448f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal .name = "swp", 449f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal .status = INSN_OBSOLETE, 450f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal .hooks = swp_hooks, 451f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal .set_hw_mode = NULL, 452f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal}; 453f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 454cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawalstatic int cp15barrier_handler(struct pt_regs *regs, u32 instr) 455cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal{ 456cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc); 457cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal 458cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal switch (arm_check_condition(instr, regs->pstate)) { 459cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal case ARM_OPCODE_CONDTEST_PASS: 460cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal break; 461cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal case ARM_OPCODE_CONDTEST_FAIL: 462cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal /* Condition failed - return to next instruction */ 463cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal goto ret; 464cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal case ARM_OPCODE_CONDTEST_UNCOND: 465cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal /* If unconditional encoding - not a barrier instruction */ 466cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal return -EFAULT; 467cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal default: 468cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal return -EINVAL; 469cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal } 470cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal 471cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal switch (aarch32_insn_mcr_extract_crm(instr)) { 472cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal case 10: 473cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal /* 474cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal * dmb - mcr p15, 0, Rt, c7, c10, 5 475cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal * dsb - mcr p15, 0, Rt, c7, c10, 4 476cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal */ 477203077a7db3bc692ff8177e822110400868efab4Punit Agrawal if (aarch32_insn_mcr_extract_opc2(instr) == 5) { 478cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal dmb(sy); 479203077a7db3bc692ff8177e822110400868efab4Punit Agrawal trace_instruction_emulation( 480203077a7db3bc692ff8177e822110400868efab4Punit Agrawal "mcr p15, 0, Rt, c7, c10, 5 ; dmb", regs->pc); 481203077a7db3bc692ff8177e822110400868efab4Punit Agrawal } else { 482cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal dsb(sy); 483203077a7db3bc692ff8177e822110400868efab4Punit Agrawal trace_instruction_emulation( 484203077a7db3bc692ff8177e822110400868efab4Punit Agrawal "mcr p15, 0, Rt, c7, c10, 4 ; dsb", regs->pc); 485203077a7db3bc692ff8177e822110400868efab4Punit Agrawal } 486cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal break; 487cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal case 5: 488cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal /* 489cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal * isb - mcr p15, 0, Rt, c7, c5, 4 490cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal * 491cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal * Taking an exception or returning from one acts as an 492cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal * instruction barrier. So no explicit barrier needed here. 493cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal */ 494203077a7db3bc692ff8177e822110400868efab4Punit Agrawal trace_instruction_emulation( 495203077a7db3bc692ff8177e822110400868efab4Punit Agrawal "mcr p15, 0, Rt, c7, c5, 4 ; isb", regs->pc); 496cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal break; 497cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal } 498cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal 499cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawalret: 500cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal pr_warn_ratelimited("\"%s\" (%ld) uses deprecated CP15 Barrier instruction at 0x%llx\n", 501cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal current->comm, (unsigned long)current->pid, regs->pc); 502cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal 503cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal regs->pc += 4; 504cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal return 0; 505cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal} 506cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal 507cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawalstatic inline void config_sctlr_el1(u32 clear, u32 set) 508cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal{ 509cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal u32 val; 510cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal 511cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal asm volatile("mrs %0, sctlr_el1" : "=r" (val)); 512cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal val &= ~clear; 513cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal val |= set; 514cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal asm volatile("msr sctlr_el1, %0" : : "r" (val)); 515cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal} 516cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal 517cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawalstatic int cp15_barrier_set_hw_mode(bool enable) 518cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal{ 51968b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose if (enable) 52068b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose config_sctlr_el1(0, SCTLR_EL1_CP15BEN); 52168b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose else 52268b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose config_sctlr_el1(SCTLR_EL1_CP15BEN, 0); 52368b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose return 0; 524cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal} 525cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal 526cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawalstatic struct undef_hook cp15_barrier_hooks[] = { 527cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal { 528cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal .instr_mask = 0x0fff0fdf, 529cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal .instr_val = 0x0e070f9a, 530cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal .pstate_mask = COMPAT_PSR_MODE_MASK, 531cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal .pstate_val = COMPAT_PSR_MODE_USR, 532cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal .fn = cp15barrier_handler, 533cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal }, 534cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal { 535cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal .instr_mask = 0x0fff0fff, 536cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal .instr_val = 0x0e070f95, 537cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal .pstate_mask = COMPAT_PSR_MODE_MASK, 538cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal .pstate_val = COMPAT_PSR_MODE_USR, 539cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal .fn = cp15barrier_handler, 540cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal }, 541cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal { } 542cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal}; 543cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal 544cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawalstatic struct insn_emulation_ops cp15_barrier_ops = { 545cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal .name = "cp15_barrier", 546cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal .status = INSN_DEPRECATED, 547cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal .hooks = cp15_barrier_hooks, 548cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal .set_hw_mode = cp15_barrier_set_hw_mode, 549cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal}; 550cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal 5517540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulosestatic int setend_set_hw_mode(bool enable) 5527540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose{ 5537540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose if (!cpu_supports_mixed_endian_el0()) 5547540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose return -EINVAL; 5557540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose 5567540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose if (enable) 5577540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose config_sctlr_el1(SCTLR_EL1_SED, 0); 5587540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose else 5597540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose config_sctlr_el1(0, SCTLR_EL1_SED); 5607540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose return 0; 5617540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose} 5627540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose 5637540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulosestatic int compat_setend_handler(struct pt_regs *regs, u32 big_endian) 5647540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose{ 5657540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose char *insn; 5667540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose 5677540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc); 5687540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose 5697540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose if (big_endian) { 5707540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose insn = "setend be"; 5717540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose regs->pstate |= COMPAT_PSR_E_BIT; 5727540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose } else { 5737540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose insn = "setend le"; 5747540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose regs->pstate &= ~COMPAT_PSR_E_BIT; 5757540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose } 5767540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose 5777540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose trace_instruction_emulation(insn, regs->pc); 5787540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose pr_warn_ratelimited("\"%s\" (%ld) uses deprecated setend instruction at 0x%llx\n", 5797540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose current->comm, (unsigned long)current->pid, regs->pc); 5807540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose 5817540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose return 0; 5827540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose} 5837540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose 5847540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulosestatic int a32_setend_handler(struct pt_regs *regs, u32 instr) 5857540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose{ 5867540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose int rc = compat_setend_handler(regs, (instr >> 9) & 1); 5877540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose regs->pc += 4; 5887540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose return rc; 5897540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose} 5907540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose 5917540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulosestatic int t16_setend_handler(struct pt_regs *regs, u32 instr) 5927540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose{ 5937540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose int rc = compat_setend_handler(regs, (instr >> 3) & 1); 5947540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose regs->pc += 2; 5957540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose return rc; 5967540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose} 5977540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose 5987540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulosestatic struct undef_hook setend_hooks[] = { 5997540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose { 6007540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose .instr_mask = 0xfffffdff, 6017540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose .instr_val = 0xf1010000, 6027540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose .pstate_mask = COMPAT_PSR_MODE_MASK, 6037540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose .pstate_val = COMPAT_PSR_MODE_USR, 6047540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose .fn = a32_setend_handler, 6057540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose }, 6067540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose { 6077540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose /* Thumb mode */ 6087540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose .instr_mask = 0x0000fff7, 6097540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose .instr_val = 0x0000b650, 6107540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose .pstate_mask = (COMPAT_PSR_T_BIT | COMPAT_PSR_MODE_MASK), 6117540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose .pstate_val = (COMPAT_PSR_T_BIT | COMPAT_PSR_MODE_USR), 6127540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose .fn = t16_setend_handler, 6137540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose }, 6147540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose {} 6157540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose}; 6167540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose 6177540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulosestatic struct insn_emulation_ops setend_ops = { 6187540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose .name = "setend", 6197540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose .status = INSN_DEPRECATED, 6207540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose .hooks = setend_hooks, 6217540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose .set_hw_mode = setend_set_hw_mode, 6227540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose}; 6237540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose 62468b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulosestatic int insn_cpu_hotplug_notify(struct notifier_block *b, 62568b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose unsigned long action, void *hcpu) 62668b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose{ 62768b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose int rc = 0; 62868b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose if ((action & ~CPU_TASKS_FROZEN) == CPU_STARTING) 62968b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose rc = run_all_insn_set_hw_mode((unsigned long)hcpu); 63068b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose 63168b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose return notifier_from_errno(rc); 63268b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose} 63368b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose 63468b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulosestatic struct notifier_block insn_cpu_hotplug_notifier = { 63568b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose .notifier_call = insn_cpu_hotplug_notify, 63668b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose}; 63768b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose 638f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal/* 639ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal * Invoked as late_initcall, since not needed before init spawned. 640ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal */ 641ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawalstatic int __init armv8_deprecated_init(void) 642ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal{ 643f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal if (IS_ENABLED(CONFIG_SWP_EMULATION)) 644f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal register_insn_emulation(&swp_ops); 645f2e97ae6b98e61fa4f1539a47661baef41992b04Punit Agrawal 646cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal if (IS_ENABLED(CONFIG_CP15_BARRIER_EMULATION)) 647cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal register_insn_emulation(&cp15_barrier_ops); 648cbefb97b6d7961359f2af89d77b8d5ab77f45528Punit Agrawal 6497540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose if (IS_ENABLED(CONFIG_SETEND_EMULATION)) { 6507540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose if(system_supports_mixed_endian_el0()) 6517540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose register_insn_emulation(&setend_ops); 6527540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose else 6537540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose pr_info("setend instruction emulation is not supported on the system"); 6547540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose } 6557540dadaf9a8b0f67d41f8bc216ca4d67d9128b0Suzuki K. Poulose 65668b703b63b2892538ef7b083cd43a77476688e4dSuzuki K. Poulose register_cpu_notifier(&insn_cpu_hotplug_notifier); 657ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal register_insn_emulation_sysctl(ctl_abi); 658ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 659ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal return 0; 660ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal} 661ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawal 662ab12a809254a343a42f7655e752a9d2eb65364dbPunit Agrawallate_initcall(armv8_deprecated_init); 663