22 #include <linux/kernel.h>
24 #include <linux/sched.h>
26 #include <linux/perf_event.h>
29 #include <asm/traps.h>
30 #include <asm/uaccess.h>
35 #define __user_swpX_asm(data, addr, res, temp, B) \
36 __asm__ __volatile__( \
38 "0: ldrex"B" %1, [%3]\n" \
39 "1: strex"B" %0, %2, [%3]\n" \
43 " .section .fixup,\"ax\"\n" \
48 " .section __ex_table,\"a\"\n" \
53 : "=&r" (res), "+r" (data), "=&r" (temp) \
54 : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \
57 #define __user_swp_asm(data, addr, res, temp) \
58 __user_swpX_asm(data, addr, res, temp, "")
59 #define __user_swpb_asm(data, addr, res, temp) \
60 __user_swpX_asm(data, addr, res, temp, "b")
65 #define EXTRACT_REG_NUM(instruction, offset) \
66 (((instruction) & (0xf << (offset))) >> (offset))
74 #define TYPE_SWPB (1 << 22)
76 static unsigned long swpcounter;
77 static unsigned long swpbcounter;
78 static unsigned long abtcounter;
79 static pid_t previous_pid;
88 p +=
sprintf(p,
"Emulated SWP:\t\t%lu\n", swpcounter);
89 p +=
sprintf(p,
"Emulated SWPB:\t\t%lu\n", swpbcounter);
90 p +=
sprintf(p,
"Aborted SWP{B}:\t\t%lu\n", abtcounter);
91 if (previous_pid != 0)
92 p +=
sprintf(p,
"Last process:\t\t%d\n", previous_pid);
94 len = (p -
page) - off;
98 *eof = (len <=
count) ? 1 : 0;
121 pr_debug(
"SWP{B} emulation: access caused memory abort!\n");
127 static int emulate_swpX(
unsigned int address,
unsigned int *
data,
130 unsigned int res = 0;
132 if ((type !=
TYPE_SWPB) && (address & 0x3)) {
134 pr_debug(
"SWP instruction on unaligned pointer!\n");
182 static int swp_handler(
struct pt_regs *regs,
unsigned int instr)
185 unsigned int res = 0;
204 if (
current->pid != previous_pid) {
205 pr_debug(
"\"%s\" (%ld) uses deprecated SWP{B} instruction\n",
216 pr_debug(
"addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n",
222 pr_debug(
"SWP{B} emulation: access to %p not allowed!\n",
226 res = emulate_swpX(address, &data, type);
237 }
else if (res == -
EFAULT) {
242 set_segfault(regs, address);
253 .instr_mask = 0x0fb00ff0,
254 .instr_val = 0x01000090,
264 static int __init swp_emulation_init(
void)
266 #ifdef CONFIG_PROC_FS