0001
0002
0003
0004
0005
0006 #include <linux/vmalloc.h>
0007 #include <linux/init.h>
0008
0009 #include <asm/code-patching.h>
0010
0011 static int __init instr_is_branch_to_addr(const u32 *instr, unsigned long addr)
0012 {
0013 if (instr_is_branch_iform(ppc_inst_read(instr)) ||
0014 instr_is_branch_bform(ppc_inst_read(instr)))
0015 return branch_target(instr) == addr;
0016
0017 return 0;
0018 }
0019
0020 static void __init test_trampoline(void)
0021 {
0022 asm ("nop;nop;\n");
0023 }
0024
0025 #define check(x) do { \
0026 if (!(x)) \
0027 pr_err("code-patching: test failed at line %d\n", __LINE__); \
0028 } while (0)
0029
0030 static void __init test_branch_iform(void)
0031 {
0032 int err;
0033 ppc_inst_t instr;
0034 u32 tmp[2];
0035 u32 *iptr = tmp;
0036 unsigned long addr = (unsigned long)tmp;
0037
0038
0039 check(instr_is_branch_iform(ppc_inst(0x48000000)));
0040
0041 check(instr_is_branch_iform(ppc_inst(0x4bffffff)));
0042
0043 check(!instr_is_branch_iform(ppc_inst(0xcbffffff)));
0044
0045 check(!instr_is_branch_iform(ppc_inst(0x7bffffff)));
0046
0047
0048 check(instr_is_branch_iform(ppc_inst(0x48000001)));
0049
0050 check(instr_is_branch_iform(ppc_inst(0x4bfffffd)));
0051
0052 check(instr_is_branch_iform(ppc_inst(0x4bff00fd)));
0053
0054 check(!instr_is_branch_iform(ppc_inst(0x7bfffffd)));
0055
0056
0057 ppc_inst_write(iptr, ppc_inst(0x48000103));
0058 check(instr_is_branch_to_addr(iptr, 0x100));
0059
0060 ppc_inst_write(iptr, ppc_inst(0x480420ff));
0061 check(instr_is_branch_to_addr(iptr, 0x420fc));
0062
0063 ppc_inst_write(iptr, ppc_inst(0x49fffffc));
0064 check(instr_is_branch_to_addr(iptr, addr + 0x1FFFFFC));
0065
0066 ppc_inst_write(iptr, ppc_inst(0x4bfffffc));
0067 check(instr_is_branch_to_addr(iptr, addr - 4));
0068
0069 ppc_inst_write(iptr, ppc_inst(0x4a000000));
0070 check(instr_is_branch_to_addr(iptr, addr - 0x2000000));
0071
0072
0073 err = create_branch(&instr, iptr, addr, BRANCH_SET_LINK);
0074 ppc_inst_write(iptr, instr);
0075 check(instr_is_branch_to_addr(iptr, addr));
0076
0077
0078 err = create_branch(&instr, iptr, addr - 0x100, BRANCH_SET_LINK);
0079 ppc_inst_write(iptr, instr);
0080 check(instr_is_branch_to_addr(iptr, addr - 0x100));
0081
0082
0083 err = create_branch(&instr, iptr, addr + 0x100, 0);
0084 ppc_inst_write(iptr, instr);
0085 check(instr_is_branch_to_addr(iptr, addr + 0x100));
0086
0087
0088 err = create_branch(&instr, iptr, addr - 0x2000000, BRANCH_SET_LINK);
0089 ppc_inst_write(iptr, instr);
0090 check(instr_is_branch_to_addr(iptr, addr - 0x2000000));
0091
0092
0093 err = create_branch(&instr, iptr, addr - 0x2000004, BRANCH_SET_LINK);
0094 check(err);
0095
0096
0097 err = create_branch(&instr, iptr, addr + 0x2000000, BRANCH_SET_LINK);
0098 check(err);
0099
0100
0101 err = create_branch(&instr, iptr, addr + 3, BRANCH_SET_LINK);
0102 check(err);
0103
0104
0105 err = create_branch(&instr, iptr, addr, 0xFFFFFFFC);
0106 ppc_inst_write(iptr, instr);
0107 check(instr_is_branch_to_addr(iptr, addr));
0108 check(ppc_inst_equal(instr, ppc_inst(0x48000000)));
0109 }
0110
0111 static void __init test_create_function_call(void)
0112 {
0113 u32 *iptr;
0114 unsigned long dest;
0115 ppc_inst_t instr;
0116
0117
0118 iptr = (u32 *)ppc_function_entry(test_trampoline);
0119 dest = ppc_function_entry(test_create_function_call);
0120 create_branch(&instr, iptr, dest, BRANCH_SET_LINK);
0121 patch_instruction(iptr, instr);
0122 check(instr_is_branch_to_addr(iptr, dest));
0123 }
0124
0125 static void __init test_branch_bform(void)
0126 {
0127 int err;
0128 unsigned long addr;
0129 ppc_inst_t instr;
0130 u32 tmp[2];
0131 u32 *iptr = tmp;
0132 unsigned int flags;
0133
0134 addr = (unsigned long)iptr;
0135
0136
0137 check(instr_is_branch_bform(ppc_inst(0x40000000)));
0138
0139 check(instr_is_branch_bform(ppc_inst(0x43ffffff)));
0140
0141 check(!instr_is_branch_bform(ppc_inst(0xc3ffffff)));
0142
0143 check(!instr_is_branch_bform(ppc_inst(0x7bffffff)));
0144
0145
0146 ppc_inst_write(iptr, ppc_inst(0x43ff0103));
0147 check(instr_is_branch_to_addr(iptr, 0x100));
0148
0149 ppc_inst_write(iptr, ppc_inst(0x43ff20ff));
0150 check(instr_is_branch_to_addr(iptr, 0x20fc));
0151
0152 ppc_inst_write(iptr, ppc_inst(0x43ff7ffc));
0153 check(instr_is_branch_to_addr(iptr, addr + 0x7FFC));
0154
0155 ppc_inst_write(iptr, ppc_inst(0x43fffffc));
0156 check(instr_is_branch_to_addr(iptr, addr - 4));
0157
0158 ppc_inst_write(iptr, ppc_inst(0x43ff8000));
0159 check(instr_is_branch_to_addr(iptr, addr - 0x8000));
0160
0161
0162 flags = 0x3ff000 | BRANCH_SET_LINK;
0163
0164
0165 err = create_cond_branch(&instr, iptr, addr, flags);
0166 ppc_inst_write(iptr, instr);
0167 check(instr_is_branch_to_addr(iptr, addr));
0168
0169
0170 err = create_cond_branch(&instr, iptr, addr - 0x100, flags);
0171 ppc_inst_write(iptr, instr);
0172 check(instr_is_branch_to_addr(iptr, addr - 0x100));
0173
0174
0175 err = create_cond_branch(&instr, iptr, addr + 0x100, flags);
0176 ppc_inst_write(iptr, instr);
0177 check(instr_is_branch_to_addr(iptr, addr + 0x100));
0178
0179
0180 err = create_cond_branch(&instr, iptr, addr - 0x8000, flags);
0181 ppc_inst_write(iptr, instr);
0182 check(instr_is_branch_to_addr(iptr, addr - 0x8000));
0183
0184
0185 err = create_cond_branch(&instr, iptr, addr - 0x8004, flags);
0186 check(err);
0187
0188
0189 err = create_cond_branch(&instr, iptr, addr + 0x8000, flags);
0190 check(err);
0191
0192
0193 err = create_cond_branch(&instr, iptr, addr + 3, flags);
0194 check(err);
0195
0196
0197 err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
0198 ppc_inst_write(iptr, instr);
0199 check(instr_is_branch_to_addr(iptr, addr));
0200 check(ppc_inst_equal(instr, ppc_inst(0x43FF0000)));
0201 }
0202
0203 static void __init test_translate_branch(void)
0204 {
0205 unsigned long addr;
0206 void *p, *q;
0207 ppc_inst_t instr;
0208 void *buf;
0209
0210 buf = vmalloc(PAGE_ALIGN(0x2000000 + 1));
0211 check(buf);
0212 if (!buf)
0213 return;
0214
0215
0216 p = buf;
0217 addr = (unsigned long)p;
0218 create_branch(&instr, p, addr, 0);
0219 ppc_inst_write(p, instr);
0220 check(instr_is_branch_to_addr(p, addr));
0221 q = p + 4;
0222 translate_branch(&instr, q, p);
0223 ppc_inst_write(q, instr);
0224 check(instr_is_branch_to_addr(q, addr));
0225
0226
0227 p = buf;
0228 addr = (unsigned long)p;
0229 create_branch(&instr, p, addr, 0);
0230 ppc_inst_write(p, instr);
0231 q = buf + 0x2000000;
0232 translate_branch(&instr, q, p);
0233 ppc_inst_write(q, instr);
0234 check(instr_is_branch_to_addr(p, addr));
0235 check(instr_is_branch_to_addr(q, addr));
0236 check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x4a000000)));
0237
0238
0239 p = buf + 0x2000000;
0240 addr = (unsigned long)p;
0241 create_branch(&instr, p, addr, 0);
0242 ppc_inst_write(p, instr);
0243 q = buf + 4;
0244 translate_branch(&instr, q, p);
0245 ppc_inst_write(q, instr);
0246 check(instr_is_branch_to_addr(p, addr));
0247 check(instr_is_branch_to_addr(q, addr));
0248 check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x49fffffc)));
0249
0250
0251 p = buf;
0252 addr = 0x1000000 + (unsigned long)buf;
0253 create_branch(&instr, p, addr, BRANCH_SET_LINK);
0254 ppc_inst_write(p, instr);
0255 q = buf + 0x1400000;
0256 translate_branch(&instr, q, p);
0257 ppc_inst_write(q, instr);
0258 check(instr_is_branch_to_addr(p, addr));
0259 check(instr_is_branch_to_addr(q, addr));
0260
0261
0262 p = buf + 0x1000000;
0263 addr = 0x2000000 + (unsigned long)buf;
0264 create_branch(&instr, p, addr, 0);
0265 ppc_inst_write(p, instr);
0266 q = buf + 4;
0267 translate_branch(&instr, q, p);
0268 ppc_inst_write(q, instr);
0269 check(instr_is_branch_to_addr(p, addr));
0270 check(instr_is_branch_to_addr(q, addr));
0271
0272
0273
0274
0275
0276 p = buf;
0277 addr = (unsigned long)p;
0278 create_cond_branch(&instr, p, addr, 0);
0279 ppc_inst_write(p, instr);
0280 check(instr_is_branch_to_addr(p, addr));
0281 q = buf + 4;
0282 translate_branch(&instr, q, p);
0283 ppc_inst_write(q, instr);
0284 check(instr_is_branch_to_addr(q, addr));
0285
0286
0287 p = buf;
0288 addr = (unsigned long)p;
0289 create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
0290 ppc_inst_write(p, instr);
0291 q = buf + 0x8000;
0292 translate_branch(&instr, q, p);
0293 ppc_inst_write(q, instr);
0294 check(instr_is_branch_to_addr(p, addr));
0295 check(instr_is_branch_to_addr(q, addr));
0296 check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff8000)));
0297
0298
0299 p = buf + 0x8000;
0300 addr = (unsigned long)p;
0301 create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
0302 ppc_inst_write(p, instr);
0303 q = buf + 4;
0304 translate_branch(&instr, q, p);
0305 ppc_inst_write(q, instr);
0306 check(instr_is_branch_to_addr(p, addr));
0307 check(instr_is_branch_to_addr(q, addr));
0308 check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff7ffc)));
0309
0310
0311 p = buf;
0312 addr = 0x3000 + (unsigned long)buf;
0313 create_cond_branch(&instr, p, addr, BRANCH_SET_LINK);
0314 ppc_inst_write(p, instr);
0315 q = buf + 0x5000;
0316 translate_branch(&instr, q, p);
0317 ppc_inst_write(q, instr);
0318 check(instr_is_branch_to_addr(p, addr));
0319 check(instr_is_branch_to_addr(q, addr));
0320
0321
0322 p = buf + 0x2000;
0323 addr = 0x4000 + (unsigned long)buf;
0324 create_cond_branch(&instr, p, addr, 0);
0325 ppc_inst_write(p, instr);
0326 q = buf + 4;
0327 translate_branch(&instr, q, p);
0328 ppc_inst_write(q, instr);
0329 check(instr_is_branch_to_addr(p, addr));
0330 check(instr_is_branch_to_addr(q, addr));
0331
0332
0333 vfree(buf);
0334 }
0335
0336 static void __init test_prefixed_patching(void)
0337 {
0338 u32 *iptr = (u32 *)ppc_function_entry(test_trampoline);
0339 u32 expected[2] = {OP_PREFIX << 26, 0};
0340 ppc_inst_t inst = ppc_inst_prefix(OP_PREFIX << 26, 0);
0341
0342 if (!IS_ENABLED(CONFIG_PPC64))
0343 return;
0344
0345 patch_instruction(iptr, inst);
0346
0347 check(!memcmp(iptr, expected, sizeof(expected)));
0348 }
0349
0350 static int __init test_code_patching(void)
0351 {
0352 pr_info("Running code patching self-tests ...\n");
0353
0354 test_branch_iform();
0355 test_branch_bform();
0356 test_create_function_call();
0357 test_translate_branch();
0358 test_prefixed_patching();
0359
0360 return 0;
0361 }
0362 late_initcall(test_code_patching);