1 /* 2 * Copyright 2008 Michael Ellerman, IBM Corporation. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/vmalloc.h> 12 #include <linux/init.h> 13 #include <linux/mm.h> 14 #include <asm/page.h> 15 #include <asm/code-patching.h> 16 #include <asm/uaccess.h> 17 18 19 int patch_instruction(unsigned int *addr, unsigned int instr) 20 { 21 int err; 22 23 __put_user_size(instr, addr, 4, err); 24 if (err) 25 return err; 26 asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr)); 27 return 0; 28 } 29 30 int patch_branch(unsigned int *addr, unsigned long target, int flags) 31 { 32 return patch_instruction(addr, create_branch(addr, target, flags)); 33 } 34 35 unsigned int create_branch(const unsigned int *addr, 36 unsigned long target, int flags) 37 { 38 unsigned int instruction; 39 long offset; 40 41 offset = target; 42 if (! (flags & BRANCH_ABSOLUTE)) 43 offset = offset - (unsigned long)addr; 44 45 /* Check we can represent the target in the instruction format */ 46 if (offset < -0x2000000 || offset > 0x1fffffc || offset & 0x3) 47 return 0; 48 49 /* Mask out the flags and target, so they don't step on each other. */ 50 instruction = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC); 51 52 return instruction; 53 } 54 55 unsigned int create_cond_branch(const unsigned int *addr, 56 unsigned long target, int flags) 57 { 58 unsigned int instruction; 59 long offset; 60 61 offset = target; 62 if (! (flags & BRANCH_ABSOLUTE)) 63 offset = offset - (unsigned long)addr; 64 65 /* Check we can represent the target in the instruction format */ 66 if (offset < -0x8000 || offset > 0x7FFF || offset & 0x3) 67 return 0; 68 69 /* Mask out the flags and target, so they don't step on each other. */ 70 instruction = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC); 71 72 return instruction; 73 } 74 75 static unsigned int branch_opcode(unsigned int instr) 76 { 77 return (instr >> 26) & 0x3F; 78 } 79 80 static int instr_is_branch_iform(unsigned int instr) 81 { 82 return branch_opcode(instr) == 18; 83 } 84 85 static int instr_is_branch_bform(unsigned int instr) 86 { 87 return branch_opcode(instr) == 16; 88 } 89 90 int instr_is_relative_branch(unsigned int instr) 91 { 92 if (instr & BRANCH_ABSOLUTE) 93 return 0; 94 95 return instr_is_branch_iform(instr) || instr_is_branch_bform(instr); 96 } 97 98 static unsigned long branch_iform_target(const unsigned int *instr) 99 { 100 signed long imm; 101 102 imm = *instr & 0x3FFFFFC; 103 104 /* If the top bit of the immediate value is set this is negative */ 105 if (imm & 0x2000000) 106 imm -= 0x4000000; 107 108 if ((*instr & BRANCH_ABSOLUTE) == 0) 109 imm += (unsigned long)instr; 110 111 return (unsigned long)imm; 112 } 113 114 static unsigned long branch_bform_target(const unsigned int *instr) 115 { 116 signed long imm; 117 118 imm = *instr & 0xFFFC; 119 120 /* If the top bit of the immediate value is set this is negative */ 121 if (imm & 0x8000) 122 imm -= 0x10000; 123 124 if ((*instr & BRANCH_ABSOLUTE) == 0) 125 imm += (unsigned long)instr; 126 127 return (unsigned long)imm; 128 } 129 130 unsigned long branch_target(const unsigned int *instr) 131 { 132 if (instr_is_branch_iform(*instr)) 133 return branch_iform_target(instr); 134 else if (instr_is_branch_bform(*instr)) 135 return branch_bform_target(instr); 136 137 return 0; 138 } 139 140 int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr) 141 { 142 if (instr_is_branch_iform(*instr) || instr_is_branch_bform(*instr)) 143 return branch_target(instr) == addr; 144 145 return 0; 146 } 147 148 unsigned int translate_branch(const unsigned int *dest, const unsigned int *src) 149 { 150 unsigned long target; 151 152 target = branch_target(src); 153 154 if (instr_is_branch_iform(*src)) 155 return create_branch(dest, target, *src); 156 else if (instr_is_branch_bform(*src)) 157 return create_cond_branch(dest, target, *src); 158 159 return 0; 160 } 161 162 #ifdef CONFIG_PPC_BOOK3E_64 163 void __patch_exception(int exc, unsigned long addr) 164 { 165 extern unsigned int interrupt_base_book3e; 166 unsigned int *ibase = &interrupt_base_book3e; 167 168 /* Our exceptions vectors start with a NOP and -then- a branch 169 * to deal with single stepping from userspace which stops on 170 * the second instruction. Thus we need to patch the second 171 * instruction of the exception, not the first one 172 */ 173 174 patch_branch(ibase + (exc / 4) + 1, addr, 0); 175 } 176 #endif 177 178 #ifdef CONFIG_CODE_PATCHING_SELFTEST 179 180 static void __init test_trampoline(void) 181 { 182 asm ("nop;\n"); 183 } 184 185 #define check(x) \ 186 if (!(x)) printk("code-patching: test failed at line %d\n", __LINE__); 187 188 static void __init test_branch_iform(void) 189 { 190 unsigned int instr; 191 unsigned long addr; 192 193 addr = (unsigned long)&instr; 194 195 /* The simplest case, branch to self, no flags */ 196 check(instr_is_branch_iform(0x48000000)); 197 /* All bits of target set, and flags */ 198 check(instr_is_branch_iform(0x4bffffff)); 199 /* High bit of opcode set, which is wrong */ 200 check(!instr_is_branch_iform(0xcbffffff)); 201 /* Middle bits of opcode set, which is wrong */ 202 check(!instr_is_branch_iform(0x7bffffff)); 203 204 /* Simplest case, branch to self with link */ 205 check(instr_is_branch_iform(0x48000001)); 206 /* All bits of targets set */ 207 check(instr_is_branch_iform(0x4bfffffd)); 208 /* Some bits of targets set */ 209 check(instr_is_branch_iform(0x4bff00fd)); 210 /* Must be a valid branch to start with */ 211 check(!instr_is_branch_iform(0x7bfffffd)); 212 213 /* Absolute branch to 0x100 */ 214 instr = 0x48000103; 215 check(instr_is_branch_to_addr(&instr, 0x100)); 216 /* Absolute branch to 0x420fc */ 217 instr = 0x480420ff; 218 check(instr_is_branch_to_addr(&instr, 0x420fc)); 219 /* Maximum positive relative branch, + 20MB - 4B */ 220 instr = 0x49fffffc; 221 check(instr_is_branch_to_addr(&instr, addr + 0x1FFFFFC)); 222 /* Smallest negative relative branch, - 4B */ 223 instr = 0x4bfffffc; 224 check(instr_is_branch_to_addr(&instr, addr - 4)); 225 /* Largest negative relative branch, - 32 MB */ 226 instr = 0x4a000000; 227 check(instr_is_branch_to_addr(&instr, addr - 0x2000000)); 228 229 /* Branch to self, with link */ 230 instr = create_branch(&instr, addr, BRANCH_SET_LINK); 231 check(instr_is_branch_to_addr(&instr, addr)); 232 233 /* Branch to self - 0x100, with link */ 234 instr = create_branch(&instr, addr - 0x100, BRANCH_SET_LINK); 235 check(instr_is_branch_to_addr(&instr, addr - 0x100)); 236 237 /* Branch to self + 0x100, no link */ 238 instr = create_branch(&instr, addr + 0x100, 0); 239 check(instr_is_branch_to_addr(&instr, addr + 0x100)); 240 241 /* Maximum relative negative offset, - 32 MB */ 242 instr = create_branch(&instr, addr - 0x2000000, BRANCH_SET_LINK); 243 check(instr_is_branch_to_addr(&instr, addr - 0x2000000)); 244 245 /* Out of range relative negative offset, - 32 MB + 4*/ 246 instr = create_branch(&instr, addr - 0x2000004, BRANCH_SET_LINK); 247 check(instr == 0); 248 249 /* Out of range relative positive offset, + 32 MB */ 250 instr = create_branch(&instr, addr + 0x2000000, BRANCH_SET_LINK); 251 check(instr == 0); 252 253 /* Unaligned target */ 254 instr = create_branch(&instr, addr + 3, BRANCH_SET_LINK); 255 check(instr == 0); 256 257 /* Check flags are masked correctly */ 258 instr = create_branch(&instr, addr, 0xFFFFFFFC); 259 check(instr_is_branch_to_addr(&instr, addr)); 260 check(instr == 0x48000000); 261 } 262 263 static void __init test_create_function_call(void) 264 { 265 unsigned int *iptr; 266 unsigned long dest; 267 268 /* Check we can create a function call */ 269 iptr = (unsigned int *)ppc_function_entry(test_trampoline); 270 dest = ppc_function_entry(test_create_function_call); 271 patch_instruction(iptr, create_branch(iptr, dest, BRANCH_SET_LINK)); 272 check(instr_is_branch_to_addr(iptr, dest)); 273 } 274 275 static void __init test_branch_bform(void) 276 { 277 unsigned long addr; 278 unsigned int *iptr, instr, flags; 279 280 iptr = &instr; 281 addr = (unsigned long)iptr; 282 283 /* The simplest case, branch to self, no flags */ 284 check(instr_is_branch_bform(0x40000000)); 285 /* All bits of target set, and flags */ 286 check(instr_is_branch_bform(0x43ffffff)); 287 /* High bit of opcode set, which is wrong */ 288 check(!instr_is_branch_bform(0xc3ffffff)); 289 /* Middle bits of opcode set, which is wrong */ 290 check(!instr_is_branch_bform(0x7bffffff)); 291 292 /* Absolute conditional branch to 0x100 */ 293 instr = 0x43ff0103; 294 check(instr_is_branch_to_addr(&instr, 0x100)); 295 /* Absolute conditional branch to 0x20fc */ 296 instr = 0x43ff20ff; 297 check(instr_is_branch_to_addr(&instr, 0x20fc)); 298 /* Maximum positive relative conditional branch, + 32 KB - 4B */ 299 instr = 0x43ff7ffc; 300 check(instr_is_branch_to_addr(&instr, addr + 0x7FFC)); 301 /* Smallest negative relative conditional branch, - 4B */ 302 instr = 0x43fffffc; 303 check(instr_is_branch_to_addr(&instr, addr - 4)); 304 /* Largest negative relative conditional branch, - 32 KB */ 305 instr = 0x43ff8000; 306 check(instr_is_branch_to_addr(&instr, addr - 0x8000)); 307 308 /* All condition code bits set & link */ 309 flags = 0x3ff000 | BRANCH_SET_LINK; 310 311 /* Branch to self */ 312 instr = create_cond_branch(iptr, addr, flags); 313 check(instr_is_branch_to_addr(&instr, addr)); 314 315 /* Branch to self - 0x100 */ 316 instr = create_cond_branch(iptr, addr - 0x100, flags); 317 check(instr_is_branch_to_addr(&instr, addr - 0x100)); 318 319 /* Branch to self + 0x100 */ 320 instr = create_cond_branch(iptr, addr + 0x100, flags); 321 check(instr_is_branch_to_addr(&instr, addr + 0x100)); 322 323 /* Maximum relative negative offset, - 32 KB */ 324 instr = create_cond_branch(iptr, addr - 0x8000, flags); 325 check(instr_is_branch_to_addr(&instr, addr - 0x8000)); 326 327 /* Out of range relative negative offset, - 32 KB + 4*/ 328 instr = create_cond_branch(iptr, addr - 0x8004, flags); 329 check(instr == 0); 330 331 /* Out of range relative positive offset, + 32 KB */ 332 instr = create_cond_branch(iptr, addr + 0x8000, flags); 333 check(instr == 0); 334 335 /* Unaligned target */ 336 instr = create_cond_branch(iptr, addr + 3, flags); 337 check(instr == 0); 338 339 /* Check flags are masked correctly */ 340 instr = create_cond_branch(iptr, addr, 0xFFFFFFFC); 341 check(instr_is_branch_to_addr(&instr, addr)); 342 check(instr == 0x43FF0000); 343 } 344 345 static void __init test_translate_branch(void) 346 { 347 unsigned long addr; 348 unsigned int *p, *q; 349 void *buf; 350 351 buf = vmalloc(PAGE_ALIGN(0x2000000 + 1)); 352 check(buf); 353 if (!buf) 354 return; 355 356 /* Simple case, branch to self moved a little */ 357 p = buf; 358 addr = (unsigned long)p; 359 patch_branch(p, addr, 0); 360 check(instr_is_branch_to_addr(p, addr)); 361 q = p + 1; 362 patch_instruction(q, translate_branch(q, p)); 363 check(instr_is_branch_to_addr(q, addr)); 364 365 /* Maximum negative case, move b . to addr + 32 MB */ 366 p = buf; 367 addr = (unsigned long)p; 368 patch_branch(p, addr, 0); 369 q = buf + 0x2000000; 370 patch_instruction(q, translate_branch(q, p)); 371 check(instr_is_branch_to_addr(p, addr)); 372 check(instr_is_branch_to_addr(q, addr)); 373 check(*q == 0x4a000000); 374 375 /* Maximum positive case, move x to x - 32 MB + 4 */ 376 p = buf + 0x2000000; 377 addr = (unsigned long)p; 378 patch_branch(p, addr, 0); 379 q = buf + 4; 380 patch_instruction(q, translate_branch(q, p)); 381 check(instr_is_branch_to_addr(p, addr)); 382 check(instr_is_branch_to_addr(q, addr)); 383 check(*q == 0x49fffffc); 384 385 /* Jump to x + 16 MB moved to x + 20 MB */ 386 p = buf; 387 addr = 0x1000000 + (unsigned long)buf; 388 patch_branch(p, addr, BRANCH_SET_LINK); 389 q = buf + 0x1400000; 390 patch_instruction(q, translate_branch(q, p)); 391 check(instr_is_branch_to_addr(p, addr)); 392 check(instr_is_branch_to_addr(q, addr)); 393 394 /* Jump to x + 16 MB moved to x - 16 MB + 4 */ 395 p = buf + 0x1000000; 396 addr = 0x2000000 + (unsigned long)buf; 397 patch_branch(p, addr, 0); 398 q = buf + 4; 399 patch_instruction(q, translate_branch(q, p)); 400 check(instr_is_branch_to_addr(p, addr)); 401 check(instr_is_branch_to_addr(q, addr)); 402 403 404 /* Conditional branch tests */ 405 406 /* Simple case, branch to self moved a little */ 407 p = buf; 408 addr = (unsigned long)p; 409 patch_instruction(p, create_cond_branch(p, addr, 0)); 410 check(instr_is_branch_to_addr(p, addr)); 411 q = p + 1; 412 patch_instruction(q, translate_branch(q, p)); 413 check(instr_is_branch_to_addr(q, addr)); 414 415 /* Maximum negative case, move b . to addr + 32 KB */ 416 p = buf; 417 addr = (unsigned long)p; 418 patch_instruction(p, create_cond_branch(p, addr, 0xFFFFFFFC)); 419 q = buf + 0x8000; 420 patch_instruction(q, translate_branch(q, p)); 421 check(instr_is_branch_to_addr(p, addr)); 422 check(instr_is_branch_to_addr(q, addr)); 423 check(*q == 0x43ff8000); 424 425 /* Maximum positive case, move x to x - 32 KB + 4 */ 426 p = buf + 0x8000; 427 addr = (unsigned long)p; 428 patch_instruction(p, create_cond_branch(p, addr, 0xFFFFFFFC)); 429 q = buf + 4; 430 patch_instruction(q, translate_branch(q, p)); 431 check(instr_is_branch_to_addr(p, addr)); 432 check(instr_is_branch_to_addr(q, addr)); 433 check(*q == 0x43ff7ffc); 434 435 /* Jump to x + 12 KB moved to x + 20 KB */ 436 p = buf; 437 addr = 0x3000 + (unsigned long)buf; 438 patch_instruction(p, create_cond_branch(p, addr, BRANCH_SET_LINK)); 439 q = buf + 0x5000; 440 patch_instruction(q, translate_branch(q, p)); 441 check(instr_is_branch_to_addr(p, addr)); 442 check(instr_is_branch_to_addr(q, addr)); 443 444 /* Jump to x + 8 KB moved to x - 8 KB + 4 */ 445 p = buf + 0x2000; 446 addr = 0x4000 + (unsigned long)buf; 447 patch_instruction(p, create_cond_branch(p, addr, 0)); 448 q = buf + 4; 449 patch_instruction(q, translate_branch(q, p)); 450 check(instr_is_branch_to_addr(p, addr)); 451 check(instr_is_branch_to_addr(q, addr)); 452 453 /* Free the buffer we were using */ 454 vfree(buf); 455 } 456 457 static int __init test_code_patching(void) 458 { 459 printk(KERN_DEBUG "Running code patching self-tests ...\n"); 460 461 test_branch_iform(); 462 test_branch_bform(); 463 test_create_function_call(); 464 test_translate_branch(); 465 466 return 0; 467 } 468 late_initcall(test_code_patching); 469 470 #endif /* CONFIG_CODE_PATCHING_SELFTEST */ 471