Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ia64/pv_op/binarypatch: add helper functions to support binary patching for paravirt_ops.

add helper functions to support binary patching for paravirt_ops.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: Tony Luck <tony.luck@intel.com>

authored by

Isaku Yamahata and committed by
Tony Luck
bf7ab02f f8de2ec6

+737
+143
arch/ia64/include/asm/paravirt_patch.h
··· 1 + /****************************************************************************** 2 + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> 3 + * VA Linux Systems Japan K.K. 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License as published by 7 + * the Free Software Foundation; either version 2 of the License, or 8 + * (at your option) any later version. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + * You should have received a copy of the GNU General Public License 16 + * along with this program; if not, write to the Free Software 17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 + * 19 + */ 20 + 21 + #ifndef __ASM_PARAVIRT_PATCH_H 22 + #define __ASM_PARAVIRT_PATCH_H 23 + 24 + #ifdef __ASSEMBLY__ 25 + 26 + .section .paravirt_branches, "a" 27 + .previous 28 + #define PARAVIRT_PATCH_SITE_BR(type) \ 29 + { \ 30 + [1:] ; \ 31 + br.cond.sptk.many 2f ; \ 32 + nop.b 0 ; \ 33 + nop.b 0;; ; \ 34 + } ; \ 35 + 2: \ 36 + .xdata8 ".paravirt_branches", 1b, type 37 + 38 + #else 39 + 40 + #include <linux/stringify.h> 41 + #include <asm/intrinsics.h> 42 + 43 + /* for binary patch */ 44 + struct paravirt_patch_site_bundle { 45 + void *sbundle; 46 + void *ebundle; 47 + unsigned long type; 48 + }; 49 + 50 + /* label means the beginning of new bundle */ 51 + #define paravirt_alt_bundle(instr, privop) \ 52 + "\t998:\n" \ 53 + "\t" instr "\n" \ 54 + "\t999:\n" \ 55 + "\t.pushsection .paravirt_bundles, \"a\"\n" \ 56 + "\t.popsection\n" \ 57 + "\t.xdata8 \".paravirt_bundles\", 998b, 999b, " \ 58 + __stringify(privop) "\n" 59 + 60 + 61 + struct paravirt_patch_bundle_elem { 62 + const void *sbundle; 63 + const void *ebundle; 64 + unsigned long type; 65 + }; 66 + 67 + 68 + struct paravirt_patch_site_inst { 69 + unsigned long stag; 70 + unsigned long etag; 71 + unsigned long type; 72 + }; 73 + 74 + #define paravirt_alt_inst(instr, privop) \ 75 + "\t[998:]\n" \ 76 + "\t" instr "\n" \ 77 + "\t[999:]\n" \ 78 + "\t.pushsection .paravirt_insts, \"a\"\n" \ 79 + "\t.popsection\n" \ 80 + "\t.xdata8 \".paravirt_insts\", 998b, 999b, " \ 81 + __stringify(privop) "\n" 82 + 83 + struct paravirt_patch_site_branch { 84 + unsigned long tag; 85 + unsigned long type; 86 + }; 87 + 88 + struct paravirt_patch_branch_target { 89 + const void *entry; 90 + unsigned long type; 91 + }; 92 + 93 + void 94 + __paravirt_patch_apply_branch( 95 + unsigned long tag, unsigned long type, 96 + const struct paravirt_patch_branch_target *entries, 97 + unsigned int nr_entries); 98 + 99 + void 100 + paravirt_patch_reloc_br(unsigned long tag, const void *target); 101 + 102 + void 103 + paravirt_patch_reloc_brl(unsigned long tag, const void *target); 104 + 105 + 106 + #if defined(ASM_SUPPORTED) && defined(CONFIG_PARAVIRT) 107 + unsigned long 108 + ia64_native_patch_bundle(void *sbundle, void *ebundle, unsigned long type); 109 + 110 + unsigned long 111 + __paravirt_patch_apply_bundle(void *sbundle, void *ebundle, unsigned long type, 112 + const struct paravirt_patch_bundle_elem *elems, 113 + unsigned long nelems, 114 + const struct paravirt_patch_bundle_elem **found); 115 + 116 + void 117 + paravirt_patch_apply_bundle(const struct paravirt_patch_site_bundle *start, 118 + const struct paravirt_patch_site_bundle *end); 119 + 120 + void 121 + paravirt_patch_apply_inst(const struct paravirt_patch_site_inst *start, 122 + const struct paravirt_patch_site_inst *end); 123 + 124 + void paravirt_patch_apply(void); 125 + #else 126 + #define paravirt_patch_apply_bundle(start, end) do { } while (0) 127 + #define paravirt_patch_apply_inst(start, end) do { } while (0) 128 + #define paravirt_patch_apply() do { } while (0) 129 + #endif 130 + 131 + #endif /* !__ASSEMBLEY__ */ 132 + 133 + #endif /* __ASM_PARAVIRT_PATCH_H */ 134 + 135 + /* 136 + * Local variables: 137 + * mode: C 138 + * c-set-style: "linux" 139 + * c-basic-offset: 8 140 + * tab-width: 8 141 + * indent-tabs-mode: t 142 + * End: 143 + */
+514
arch/ia64/kernel/paravirt_patch.c
··· 1 + /****************************************************************************** 2 + * linux/arch/ia64/xen/paravirt_patch.c 3 + * 4 + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> 5 + * VA Linux Systems Japan K.K. 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License as published by 9 + * the Free Software Foundation; either version 2 of the License, or 10 + * (at your option) any later version. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + * 17 + * You should have received a copy of the GNU General Public License 18 + * along with this program; if not, write to the Free Software 19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 + * 21 + */ 22 + 23 + #include <linux/init.h> 24 + #include <asm/intrinsics.h> 25 + #include <asm/kprobes.h> 26 + #include <asm/paravirt.h> 27 + #include <asm/paravirt_patch.h> 28 + 29 + typedef union ia64_inst { 30 + struct { 31 + unsigned long long qp : 6; 32 + unsigned long long : 31; 33 + unsigned long long opcode : 4; 34 + unsigned long long reserved : 23; 35 + } generic; 36 + unsigned long long l; 37 + } ia64_inst_t; 38 + 39 + /* 40 + * flush_icache_range() can't be used here. 41 + * we are here before cpu_init() which initializes 42 + * ia64_i_cache_stride_shift. flush_icache_range() uses it. 43 + */ 44 + void __init_or_module 45 + paravirt_flush_i_cache_range(const void *instr, unsigned long size) 46 + { 47 + extern void paravirt_fc_i(const void *addr); 48 + unsigned long i; 49 + 50 + for (i = 0; i < size; i += sizeof(bundle_t)) 51 + paravirt_fc_i(instr + i); 52 + } 53 + 54 + bundle_t* __init_or_module 55 + paravirt_get_bundle(unsigned long tag) 56 + { 57 + return (bundle_t *)(tag & ~3UL); 58 + } 59 + 60 + unsigned long __init_or_module 61 + paravirt_get_slot(unsigned long tag) 62 + { 63 + return tag & 3UL; 64 + } 65 + 66 + unsigned long __init_or_module 67 + paravirt_get_num_inst(unsigned long stag, unsigned long etag) 68 + { 69 + bundle_t *sbundle = paravirt_get_bundle(stag); 70 + unsigned long sslot = paravirt_get_slot(stag); 71 + bundle_t *ebundle = paravirt_get_bundle(etag); 72 + unsigned long eslot = paravirt_get_slot(etag); 73 + 74 + return (ebundle - sbundle) * 3 + eslot - sslot + 1; 75 + } 76 + 77 + unsigned long __init_or_module 78 + paravirt_get_next_tag(unsigned long tag) 79 + { 80 + unsigned long slot = paravirt_get_slot(tag); 81 + 82 + switch (slot) { 83 + case 0: 84 + case 1: 85 + return tag + 1; 86 + case 2: { 87 + bundle_t *bundle = paravirt_get_bundle(tag); 88 + return (unsigned long)(bundle + 1); 89 + } 90 + default: 91 + BUG(); 92 + } 93 + /* NOTREACHED */ 94 + } 95 + 96 + ia64_inst_t __init_or_module 97 + paravirt_read_slot0(const bundle_t *bundle) 98 + { 99 + ia64_inst_t inst; 100 + inst.l = bundle->quad0.slot0; 101 + return inst; 102 + } 103 + 104 + ia64_inst_t __init_or_module 105 + paravirt_read_slot1(const bundle_t *bundle) 106 + { 107 + ia64_inst_t inst; 108 + inst.l = bundle->quad0.slot1_p0 | 109 + ((unsigned long long)bundle->quad1.slot1_p1 << 18UL); 110 + return inst; 111 + } 112 + 113 + ia64_inst_t __init_or_module 114 + paravirt_read_slot2(const bundle_t *bundle) 115 + { 116 + ia64_inst_t inst; 117 + inst.l = bundle->quad1.slot2; 118 + return inst; 119 + } 120 + 121 + ia64_inst_t __init_or_module 122 + paravirt_read_inst(unsigned long tag) 123 + { 124 + bundle_t *bundle = paravirt_get_bundle(tag); 125 + unsigned long slot = paravirt_get_slot(tag); 126 + 127 + switch (slot) { 128 + case 0: 129 + return paravirt_read_slot0(bundle); 130 + case 1: 131 + return paravirt_read_slot1(bundle); 132 + case 2: 133 + return paravirt_read_slot2(bundle); 134 + default: 135 + BUG(); 136 + } 137 + /* NOTREACHED */ 138 + } 139 + 140 + void __init_or_module 141 + paravirt_write_slot0(bundle_t *bundle, ia64_inst_t inst) 142 + { 143 + bundle->quad0.slot0 = inst.l; 144 + } 145 + 146 + void __init_or_module 147 + paravirt_write_slot1(bundle_t *bundle, ia64_inst_t inst) 148 + { 149 + bundle->quad0.slot1_p0 = inst.l; 150 + bundle->quad1.slot1_p1 = inst.l >> 18UL; 151 + } 152 + 153 + void __init_or_module 154 + paravirt_write_slot2(bundle_t *bundle, ia64_inst_t inst) 155 + { 156 + bundle->quad1.slot2 = inst.l; 157 + } 158 + 159 + void __init_or_module 160 + paravirt_write_inst(unsigned long tag, ia64_inst_t inst) 161 + { 162 + bundle_t *bundle = paravirt_get_bundle(tag); 163 + unsigned long slot = paravirt_get_slot(tag); 164 + 165 + switch (slot) { 166 + case 0: 167 + paravirt_write_slot0(bundle, inst); 168 + break; 169 + case 1: 170 + paravirt_write_slot1(bundle, inst); 171 + break; 172 + case 2: 173 + paravirt_write_slot2(bundle, inst); 174 + break; 175 + default: 176 + BUG(); 177 + break; 178 + } 179 + paravirt_flush_i_cache_range(bundle, sizeof(*bundle)); 180 + } 181 + 182 + /* for debug */ 183 + void 184 + paravirt_print_bundle(const bundle_t *bundle) 185 + { 186 + const unsigned long *quad = (const unsigned long *)bundle; 187 + ia64_inst_t slot0 = paravirt_read_slot0(bundle); 188 + ia64_inst_t slot1 = paravirt_read_slot1(bundle); 189 + ia64_inst_t slot2 = paravirt_read_slot2(bundle); 190 + 191 + printk(KERN_DEBUG 192 + "bundle 0x%p 0x%016lx 0x%016lx\n", bundle, quad[0], quad[1]); 193 + printk(KERN_DEBUG 194 + "bundle template 0x%x\n", 195 + bundle->quad0.template); 196 + printk(KERN_DEBUG 197 + "slot0 0x%lx slot1_p0 0x%lx slot1_p1 0x%lx slot2 0x%lx\n", 198 + (unsigned long)bundle->quad0.slot0, 199 + (unsigned long)bundle->quad0.slot1_p0, 200 + (unsigned long)bundle->quad1.slot1_p1, 201 + (unsigned long)bundle->quad1.slot2); 202 + printk(KERN_DEBUG 203 + "slot0 0x%016llx slot1 0x%016llx slot2 0x%016llx\n", 204 + slot0.l, slot1.l, slot2.l); 205 + } 206 + 207 + static int noreplace_paravirt __init_or_module = 0; 208 + 209 + static int __init setup_noreplace_paravirt(char *str) 210 + { 211 + noreplace_paravirt = 1; 212 + return 1; 213 + } 214 + __setup("noreplace-paravirt", setup_noreplace_paravirt); 215 + 216 + #ifdef ASM_SUPPORTED 217 + static void __init_or_module 218 + fill_nop_bundle(void *sbundle, void *ebundle) 219 + { 220 + extern const char paravirt_nop_bundle[]; 221 + extern const unsigned long paravirt_nop_bundle_size; 222 + 223 + void *bundle = sbundle; 224 + 225 + BUG_ON((((unsigned long)sbundle) % sizeof(bundle_t)) != 0); 226 + BUG_ON((((unsigned long)ebundle) % sizeof(bundle_t)) != 0); 227 + 228 + while (bundle < ebundle) { 229 + memcpy(bundle, paravirt_nop_bundle, paravirt_nop_bundle_size); 230 + 231 + bundle += paravirt_nop_bundle_size; 232 + } 233 + } 234 + 235 + /* helper function */ 236 + unsigned long __init_or_module 237 + __paravirt_patch_apply_bundle(void *sbundle, void *ebundle, unsigned long type, 238 + const struct paravirt_patch_bundle_elem *elems, 239 + unsigned long nelems, 240 + const struct paravirt_patch_bundle_elem **found) 241 + { 242 + unsigned long used = 0; 243 + unsigned long i; 244 + 245 + BUG_ON((((unsigned long)sbundle) % sizeof(bundle_t)) != 0); 246 + BUG_ON((((unsigned long)ebundle) % sizeof(bundle_t)) != 0); 247 + 248 + found = NULL; 249 + for (i = 0; i < nelems; i++) { 250 + const struct paravirt_patch_bundle_elem *p = &elems[i]; 251 + if (p->type == type) { 252 + unsigned long need = p->ebundle - p->sbundle; 253 + unsigned long room = ebundle - sbundle; 254 + 255 + if (found != NULL) 256 + *found = p; 257 + 258 + if (room < need) { 259 + /* no room to replace. skip it */ 260 + printk(KERN_DEBUG 261 + "the space is too small to put " 262 + "bundles. type %ld need %ld room %ld\n", 263 + type, need, room); 264 + break; 265 + } 266 + 267 + used = need; 268 + memcpy(sbundle, p->sbundle, used); 269 + break; 270 + } 271 + } 272 + 273 + return used; 274 + } 275 + 276 + void __init_or_module 277 + paravirt_patch_apply_bundle(const struct paravirt_patch_site_bundle *start, 278 + const struct paravirt_patch_site_bundle *end) 279 + { 280 + const struct paravirt_patch_site_bundle *p; 281 + 282 + if (noreplace_paravirt) 283 + return; 284 + if (pv_init_ops.patch_bundle == NULL) 285 + return; 286 + 287 + for (p = start; p < end; p++) { 288 + unsigned long used; 289 + 290 + used = (*pv_init_ops.patch_bundle)(p->sbundle, p->ebundle, 291 + p->type); 292 + if (used == 0) 293 + continue; 294 + 295 + fill_nop_bundle(p->sbundle + used, p->ebundle); 296 + paravirt_flush_i_cache_range(p->sbundle, 297 + p->ebundle - p->sbundle); 298 + } 299 + ia64_sync_i(); 300 + ia64_srlz_i(); 301 + } 302 + 303 + /* 304 + * nop.i, nop.m, nop.f instruction are same format. 305 + * but nop.b has differennt format. 306 + * This doesn't support nop.b for now. 307 + */ 308 + static void __init_or_module 309 + fill_nop_inst(unsigned long stag, unsigned long etag) 310 + { 311 + extern const bundle_t paravirt_nop_mfi_inst_bundle[]; 312 + unsigned long tag; 313 + const ia64_inst_t nop_inst = 314 + paravirt_read_slot0(paravirt_nop_mfi_inst_bundle); 315 + 316 + for (tag = stag; tag < etag; tag = paravirt_get_next_tag(tag)) 317 + paravirt_write_inst(tag, nop_inst); 318 + } 319 + 320 + void __init_or_module 321 + paravirt_patch_apply_inst(const struct paravirt_patch_site_inst *start, 322 + const struct paravirt_patch_site_inst *end) 323 + { 324 + const struct paravirt_patch_site_inst *p; 325 + 326 + if (noreplace_paravirt) 327 + return; 328 + if (pv_init_ops.patch_inst == NULL) 329 + return; 330 + 331 + for (p = start; p < end; p++) { 332 + unsigned long tag; 333 + bundle_t *sbundle; 334 + bundle_t *ebundle; 335 + 336 + tag = (*pv_init_ops.patch_inst)(p->stag, p->etag, p->type); 337 + if (tag == p->stag) 338 + continue; 339 + 340 + fill_nop_inst(tag, p->etag); 341 + sbundle = paravirt_get_bundle(p->stag); 342 + ebundle = paravirt_get_bundle(p->etag) + 1; 343 + paravirt_flush_i_cache_range(sbundle, (ebundle - sbundle) * 344 + sizeof(bundle_t)); 345 + } 346 + ia64_sync_i(); 347 + ia64_srlz_i(); 348 + } 349 + #endif /* ASM_SUPPOTED */ 350 + 351 + /* brl.cond.sptk.many <target64> X3 */ 352 + typedef union inst_x3_op { 353 + ia64_inst_t inst; 354 + struct { 355 + unsigned long qp: 6; 356 + unsigned long btyp: 3; 357 + unsigned long unused: 3; 358 + unsigned long p: 1; 359 + unsigned long imm20b: 20; 360 + unsigned long wh: 2; 361 + unsigned long d: 1; 362 + unsigned long i: 1; 363 + unsigned long opcode: 4; 364 + }; 365 + unsigned long l; 366 + } inst_x3_op_t; 367 + 368 + typedef union inst_x3_imm { 369 + ia64_inst_t inst; 370 + struct { 371 + unsigned long unused: 2; 372 + unsigned long imm39: 39; 373 + }; 374 + unsigned long l; 375 + } inst_x3_imm_t; 376 + 377 + void __init_or_module 378 + paravirt_patch_reloc_brl(unsigned long tag, const void *target) 379 + { 380 + unsigned long tag_op = paravirt_get_next_tag(tag); 381 + unsigned long tag_imm = tag; 382 + bundle_t *bundle = paravirt_get_bundle(tag); 383 + 384 + ia64_inst_t inst_op = paravirt_read_inst(tag_op); 385 + ia64_inst_t inst_imm = paravirt_read_inst(tag_imm); 386 + 387 + inst_x3_op_t inst_x3_op = { .l = inst_op.l }; 388 + inst_x3_imm_t inst_x3_imm = { .l = inst_imm.l }; 389 + 390 + unsigned long imm60 = 391 + ((unsigned long)target - (unsigned long)bundle) >> 4; 392 + 393 + BUG_ON(paravirt_get_slot(tag) != 1); /* MLX */ 394 + BUG_ON(((unsigned long)target & (sizeof(bundle_t) - 1)) != 0); 395 + 396 + /* imm60[59] 1bit */ 397 + inst_x3_op.i = (imm60 >> 59) & 1; 398 + /* imm60[19:0] 20bit */ 399 + inst_x3_op.imm20b = imm60 & ((1UL << 20) - 1); 400 + /* imm60[58:20] 39bit */ 401 + inst_x3_imm.imm39 = (imm60 >> 20) & ((1UL << 39) - 1); 402 + 403 + inst_op.l = inst_x3_op.l; 404 + inst_imm.l = inst_x3_imm.l; 405 + 406 + paravirt_write_inst(tag_op, inst_op); 407 + paravirt_write_inst(tag_imm, inst_imm); 408 + } 409 + 410 + /* br.cond.sptk.many <target25> B1 */ 411 + typedef union inst_b1 { 412 + ia64_inst_t inst; 413 + struct { 414 + unsigned long qp: 6; 415 + unsigned long btype: 3; 416 + unsigned long unused: 3; 417 + unsigned long p: 1; 418 + unsigned long imm20b: 20; 419 + unsigned long wh: 2; 420 + unsigned long d: 1; 421 + unsigned long s: 1; 422 + unsigned long opcode: 4; 423 + }; 424 + unsigned long l; 425 + } inst_b1_t; 426 + 427 + void __init 428 + paravirt_patch_reloc_br(unsigned long tag, const void *target) 429 + { 430 + bundle_t *bundle = paravirt_get_bundle(tag); 431 + ia64_inst_t inst = paravirt_read_inst(tag); 432 + unsigned long target25 = (unsigned long)target - (unsigned long)bundle; 433 + inst_b1_t inst_b1; 434 + 435 + BUG_ON(((unsigned long)target & (sizeof(bundle_t) - 1)) != 0); 436 + 437 + inst_b1.l = inst.l; 438 + if (target25 & (1UL << 63)) 439 + inst_b1.s = 1; 440 + else 441 + inst_b1.s = 0; 442 + 443 + inst_b1.imm20b = target25 >> 4; 444 + inst.l = inst_b1.l; 445 + 446 + paravirt_write_inst(tag, inst); 447 + } 448 + 449 + void __init 450 + __paravirt_patch_apply_branch( 451 + unsigned long tag, unsigned long type, 452 + const struct paravirt_patch_branch_target *entries, 453 + unsigned int nr_entries) 454 + { 455 + unsigned int i; 456 + for (i = 0; i < nr_entries; i++) { 457 + if (entries[i].type == type) { 458 + paravirt_patch_reloc_br(tag, entries[i].entry); 459 + break; 460 + } 461 + } 462 + } 463 + 464 + static void __init 465 + paravirt_patch_apply_branch(const struct paravirt_patch_site_branch *start, 466 + const struct paravirt_patch_site_branch *end) 467 + { 468 + const struct paravirt_patch_site_branch *p; 469 + 470 + if (noreplace_paravirt) 471 + return; 472 + if (pv_init_ops.patch_branch == NULL) 473 + return; 474 + 475 + for (p = start; p < end; p++) 476 + (*pv_init_ops.patch_branch)(p->tag, p->type); 477 + 478 + ia64_sync_i(); 479 + ia64_srlz_i(); 480 + } 481 + 482 + void __init 483 + paravirt_patch_apply(void) 484 + { 485 + extern const char __start_paravirt_bundles[]; 486 + extern const char __stop_paravirt_bundles[]; 487 + extern const char __start_paravirt_insts[]; 488 + extern const char __stop_paravirt_insts[]; 489 + extern const char __start_paravirt_branches[]; 490 + extern const char __stop_paravirt_branches[]; 491 + 492 + paravirt_patch_apply_bundle((const struct paravirt_patch_site_bundle *) 493 + __start_paravirt_bundles, 494 + (const struct paravirt_patch_site_bundle *) 495 + __stop_paravirt_bundles); 496 + paravirt_patch_apply_inst((const struct paravirt_patch_site_inst *) 497 + __start_paravirt_insts, 498 + (const struct paravirt_patch_site_inst *) 499 + __stop_paravirt_insts); 500 + paravirt_patch_apply_branch((const struct paravirt_patch_site_branch *) 501 + __start_paravirt_branches, 502 + (const struct paravirt_patch_site_branch *) 503 + __stop_paravirt_branches); 504 + } 505 + 506 + /* 507 + * Local variables: 508 + * mode: C 509 + * c-set-style: "linux" 510 + * c-basic-offset: 8 511 + * tab-width: 8 512 + * indent-tabs-mode: t 513 + * End: 514 + */
+56
arch/ia64/kernel/paravirtentry.S
··· 58 58 BRANCH_PROC_UNWINFO(leave_syscall, r22, b7) 59 59 BRANCH_PROC(work_processed_syscall, r2, b7) 60 60 BRANCH_PROC_UNWINFO(leave_kernel, r22, b7) 61 + 62 + 63 + #ifdef CONFIG_MODULES 64 + #define __INIT_OR_MODULE .text 65 + #define __INITDATA_OR_MODULE .data 66 + #else 67 + #define __INIT_OR_MODULE __INIT 68 + #define __INITDATA_OR_MODULE __INITDATA 69 + #endif /* CONFIG_MODULES */ 70 + 71 + __INIT_OR_MODULE 72 + GLOBAL_ENTRY(paravirt_fc_i) 73 + fc.i r32 74 + br.ret.sptk.many rp 75 + END(paravirt_fc_i) 76 + __FINIT 77 + 78 + __INIT_OR_MODULE 79 + .align 32 80 + GLOBAL_ENTRY(paravirt_nop_b_inst_bundle) 81 + { 82 + nop.b 0 83 + nop.b 0 84 + nop.b 0 85 + } 86 + END(paravirt_nop_b_inst_bundle) 87 + __FINIT 88 + 89 + /* NOTE: nop.[mfi] has same format */ 90 + __INIT_OR_MODULE 91 + GLOBAL_ENTRY(paravirt_nop_mfi_inst_bundle) 92 + { 93 + nop.m 0 94 + nop.f 0 95 + nop.i 0 96 + } 97 + END(paravirt_nop_mfi_inst_bundle) 98 + __FINIT 99 + 100 + __INIT_OR_MODULE 101 + GLOBAL_ENTRY(paravirt_nop_bundle) 102 + paravirt_nop_bundle_start: 103 + { 104 + nop 0 105 + nop 0 106 + nop 0 107 + } 108 + paravirt_nop_bundle_end: 109 + END(paravirt_nop_bundle) 110 + __FINIT 111 + 112 + __INITDATA_OR_MODULE 113 + .align 8 114 + .global paravirt_nop_bundle_size 115 + paravirt_nop_bundle_size: 116 + data8 paravirt_nop_bundle_end - paravirt_nop_bundle_start
+24
arch/ia64/kernel/vmlinux.lds.S
··· 169 169 __end___mckinley_e9_bundles = .; 170 170 } 171 171 172 + #if defined(CONFIG_PARAVIRT) 173 + . = ALIGN(16); 174 + .paravirt_bundles : AT(ADDR(.paravirt_bundles) - LOAD_OFFSET) 175 + { 176 + __start_paravirt_bundles = .; 177 + *(.paravirt_bundles) 178 + __stop_paravirt_bundles = .; 179 + } 180 + . = ALIGN(16); 181 + .paravirt_insts : AT(ADDR(.paravirt_insts) - LOAD_OFFSET) 182 + { 183 + __start_paravirt_insts = .; 184 + *(.paravirt_insts) 185 + __stop_paravirt_insts = .; 186 + } 187 + . = ALIGN(16); 188 + .paravirt_branches : AT(ADDR(.paravirt_branches) - LOAD_OFFSET) 189 + { 190 + __start_paravirt_branches = .; 191 + *(.paravirt_branches) 192 + __stop_paravirt_branches = .; 193 + } 194 + #endif 195 + 172 196 #if defined(CONFIG_IA64_GENERIC) 173 197 /* Machine Vector */ 174 198 . = ALIGN(16);