Commit c61264f98c1a974ee6f545f61a4ab33b141d6bda
Exists in
master
and in
6 other branches
Merge branch 'upstream/xen-tracing2' of git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen
* 'upstream/xen-tracing2' of git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen: xen/trace: use class for multicall trace xen/trace: convert mmu events to use DECLARE_EVENT_CLASS()/DEFINE_EVENT() xen/multicall: move *idx fields to start of mc_buffer xen/multicall: special-case singleton hypercalls xen/multicalls: add unlikely around slowpath in __xen_mc_entry() xen/multicalls: disable MC_DEBUG xen/mmu: tune pgtable alloc/release xen/mmu: use extend_args for more mmuext updates xen/trace: add tlb flush tracepoints xen/trace: add segment desc tracing xen/trace: add xen_pgd_(un)pin tracepoints xen/trace: add ptpage alloc/release tracepoints xen/trace: add mmu tracepoints xen/trace: add multicall tracing xen/trace: set up tracepoint skeleton xen/multicalls: remove debugfs stats trace/xen: add skeleton for Xen trace events
Showing 9 changed files Side-by-side Diff
arch/x86/include/asm/xen/hypercall.h
... | ... | @@ -39,6 +39,8 @@ |
39 | 39 | #include <linux/string.h> |
40 | 40 | #include <linux/types.h> |
41 | 41 | |
42 | +#include <trace/events/xen.h> | |
43 | + | |
42 | 44 | #include <asm/page.h> |
43 | 45 | #include <asm/pgtable.h> |
44 | 46 | |
... | ... | @@ -459,6 +461,8 @@ |
459 | 461 | { |
460 | 462 | mcl->op = __HYPERVISOR_fpu_taskswitch; |
461 | 463 | mcl->args[0] = set; |
464 | + | |
465 | + trace_xen_mc_entry(mcl, 1); | |
462 | 466 | } |
463 | 467 | |
464 | 468 | static inline void |
... | ... | @@ -475,6 +479,8 @@ |
475 | 479 | mcl->args[2] = new_val.pte >> 32; |
476 | 480 | mcl->args[3] = flags; |
477 | 481 | } |
482 | + | |
483 | + trace_xen_mc_entry(mcl, sizeof(new_val) == sizeof(long) ? 3 : 4); | |
478 | 484 | } |
479 | 485 | |
480 | 486 | static inline void |
... | ... | @@ -485,6 +491,8 @@ |
485 | 491 | mcl->args[0] = cmd; |
486 | 492 | mcl->args[1] = (unsigned long)uop; |
487 | 493 | mcl->args[2] = count; |
494 | + | |
495 | + trace_xen_mc_entry(mcl, 3); | |
488 | 496 | } |
489 | 497 | |
490 | 498 | static inline void |
... | ... | @@ -504,6 +512,8 @@ |
504 | 512 | mcl->args[3] = flags; |
505 | 513 | mcl->args[4] = domid; |
506 | 514 | } |
515 | + | |
516 | + trace_xen_mc_entry(mcl, sizeof(new_val) == sizeof(long) ? 4 : 5); | |
507 | 517 | } |
508 | 518 | |
509 | 519 | static inline void |
... | ... | @@ -520,6 +530,8 @@ |
520 | 530 | mcl->args[2] = desc.a; |
521 | 531 | mcl->args[3] = desc.b; |
522 | 532 | } |
533 | + | |
534 | + trace_xen_mc_entry(mcl, sizeof(maddr) == sizeof(long) ? 2 : 4); | |
523 | 535 | } |
524 | 536 | |
525 | 537 | static inline void |
... | ... | @@ -528,6 +540,8 @@ |
528 | 540 | mcl->op = __HYPERVISOR_memory_op; |
529 | 541 | mcl->args[0] = cmd; |
530 | 542 | mcl->args[1] = (unsigned long)arg; |
543 | + | |
544 | + trace_xen_mc_entry(mcl, 2); | |
531 | 545 | } |
532 | 546 | |
533 | 547 | static inline void |
... | ... | @@ -539,6 +553,8 @@ |
539 | 553 | mcl->args[1] = count; |
540 | 554 | mcl->args[2] = (unsigned long)success_count; |
541 | 555 | mcl->args[3] = domid; |
556 | + | |
557 | + trace_xen_mc_entry(mcl, 4); | |
542 | 558 | } |
543 | 559 | |
544 | 560 | static inline void |
... | ... | @@ -550,6 +566,8 @@ |
550 | 566 | mcl->args[1] = count; |
551 | 567 | mcl->args[2] = (unsigned long)success_count; |
552 | 568 | mcl->args[3] = domid; |
569 | + | |
570 | + trace_xen_mc_entry(mcl, 4); | |
553 | 571 | } |
554 | 572 | |
555 | 573 | static inline void |
... | ... | @@ -558,6 +576,8 @@ |
558 | 576 | mcl->op = __HYPERVISOR_set_gdt; |
559 | 577 | mcl->args[0] = (unsigned long)frames; |
560 | 578 | mcl->args[1] = entries; |
579 | + | |
580 | + trace_xen_mc_entry(mcl, 2); | |
561 | 581 | } |
562 | 582 | |
563 | 583 | static inline void |
... | ... | @@ -567,6 +587,8 @@ |
567 | 587 | mcl->op = __HYPERVISOR_stack_switch; |
568 | 588 | mcl->args[0] = ss; |
569 | 589 | mcl->args[1] = esp; |
590 | + | |
591 | + trace_xen_mc_entry(mcl, 2); | |
570 | 592 | } |
571 | 593 | |
572 | 594 | #endif /* _ASM_X86_XEN_HYPERCALL_H */ |
arch/x86/include/asm/xen/trace_types.h
1 | +#ifndef _ASM_XEN_TRACE_TYPES_H | |
2 | +#define _ASM_XEN_TRACE_TYPES_H | |
3 | + | |
4 | +enum xen_mc_flush_reason { | |
5 | + XEN_MC_FL_NONE, /* explicit flush */ | |
6 | + XEN_MC_FL_BATCH, /* out of hypercall space */ | |
7 | + XEN_MC_FL_ARGS, /* out of argument space */ | |
8 | + XEN_MC_FL_CALLBACK, /* out of callback space */ | |
9 | +}; | |
10 | + | |
11 | +enum xen_mc_extend_args { | |
12 | + XEN_MC_XE_OK, | |
13 | + XEN_MC_XE_BAD_OP, | |
14 | + XEN_MC_XE_NO_SPACE | |
15 | +}; | |
16 | +typedef void (*xen_mc_callback_fn_t)(void *); | |
17 | + | |
18 | +#endif /* _ASM_XEN_TRACE_TYPES_H */ |
arch/x86/xen/Makefile
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \ |
14 | 14 | time.o xen-asm.o xen-asm_$(BITS).o \ |
15 | 15 | grant-table.o suspend.o platform-pci-unplug.o \ |
16 | - p2m.o | |
16 | + p2m.o trace.o | |
17 | 17 | |
18 | 18 | obj-$(CONFIG_SMP) += smp.o |
19 | 19 | obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o |
arch/x86/xen/enlighten.c
... | ... | @@ -341,6 +341,8 @@ |
341 | 341 | struct mmuext_op *op; |
342 | 342 | struct multicall_space mcs = xen_mc_entry(sizeof(*op)); |
343 | 343 | |
344 | + trace_xen_cpu_set_ldt(addr, entries); | |
345 | + | |
344 | 346 | op = mcs.args; |
345 | 347 | op->cmd = MMUEXT_SET_LDT; |
346 | 348 | op->arg1.linear_addr = (unsigned long)addr; |
... | ... | @@ -496,6 +498,8 @@ |
496 | 498 | xmaddr_t mach_lp = arbitrary_virt_to_machine(&dt[entrynum]); |
497 | 499 | u64 entry = *(u64 *)ptr; |
498 | 500 | |
501 | + trace_xen_cpu_write_ldt_entry(dt, entrynum, entry); | |
502 | + | |
499 | 503 | preempt_disable(); |
500 | 504 | |
501 | 505 | xen_mc_flush(); |
... | ... | @@ -565,6 +569,8 @@ |
565 | 569 | unsigned long p = (unsigned long)&dt[entrynum]; |
566 | 570 | unsigned long start, end; |
567 | 571 | |
572 | + trace_xen_cpu_write_idt_entry(dt, entrynum, g); | |
573 | + | |
568 | 574 | preempt_disable(); |
569 | 575 | |
570 | 576 | start = __this_cpu_read(idt_desc.address); |
... | ... | @@ -619,6 +625,8 @@ |
619 | 625 | static DEFINE_SPINLOCK(lock); |
620 | 626 | static struct trap_info traps[257]; |
621 | 627 | |
628 | + trace_xen_cpu_load_idt(desc); | |
629 | + | |
622 | 630 | spin_lock(&lock); |
623 | 631 | |
624 | 632 | __get_cpu_var(idt_desc) = *desc; |
... | ... | @@ -637,6 +645,8 @@ |
637 | 645 | static void xen_write_gdt_entry(struct desc_struct *dt, int entry, |
638 | 646 | const void *desc, int type) |
639 | 647 | { |
648 | + trace_xen_cpu_write_gdt_entry(dt, entry, desc, type); | |
649 | + | |
640 | 650 | preempt_disable(); |
641 | 651 | |
642 | 652 | switch (type) { |
... | ... | @@ -665,6 +675,8 @@ |
665 | 675 | static void __init xen_write_gdt_entry_boot(struct desc_struct *dt, int entry, |
666 | 676 | const void *desc, int type) |
667 | 677 | { |
678 | + trace_xen_cpu_write_gdt_entry(dt, entry, desc, type); | |
679 | + | |
668 | 680 | switch (type) { |
669 | 681 | case DESC_LDT: |
670 | 682 | case DESC_TSS: |
... | ... | @@ -684,7 +696,9 @@ |
684 | 696 | static void xen_load_sp0(struct tss_struct *tss, |
685 | 697 | struct thread_struct *thread) |
686 | 698 | { |
687 | - struct multicall_space mcs = xen_mc_entry(0); | |
699 | + struct multicall_space mcs; | |
700 | + | |
701 | + mcs = xen_mc_entry(0); | |
688 | 702 | MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0); |
689 | 703 | xen_mc_issue(PARAVIRT_LAZY_CPU); |
690 | 704 | } |
arch/x86/xen/mmu.c
... | ... | @@ -48,6 +48,8 @@ |
48 | 48 | #include <linux/memblock.h> |
49 | 49 | #include <linux/seq_file.h> |
50 | 50 | |
51 | +#include <trace/events/xen.h> | |
52 | + | |
51 | 53 | #include <asm/pgtable.h> |
52 | 54 | #include <asm/tlbflush.h> |
53 | 55 | #include <asm/fixmap.h> |
... | ... | @@ -194,6 +196,8 @@ |
194 | 196 | struct multicall_space mcs; |
195 | 197 | struct mmu_update *u; |
196 | 198 | |
199 | + trace_xen_mmu_set_domain_pte(ptep, pteval, domid); | |
200 | + | |
197 | 201 | mcs = xen_mc_entry(sizeof(*u)); |
198 | 202 | u = mcs.args; |
199 | 203 | |
... | ... | @@ -225,6 +229,24 @@ |
225 | 229 | *u = *update; |
226 | 230 | } |
227 | 231 | |
232 | +static void xen_extend_mmuext_op(const struct mmuext_op *op) | |
233 | +{ | |
234 | + struct multicall_space mcs; | |
235 | + struct mmuext_op *u; | |
236 | + | |
237 | + mcs = xen_mc_extend_args(__HYPERVISOR_mmuext_op, sizeof(*u)); | |
238 | + | |
239 | + if (mcs.mc != NULL) { | |
240 | + mcs.mc->args[1]++; | |
241 | + } else { | |
242 | + mcs = __xen_mc_entry(sizeof(*u)); | |
243 | + MULTI_mmuext_op(mcs.mc, mcs.args, 1, NULL, DOMID_SELF); | |
244 | + } | |
245 | + | |
246 | + u = mcs.args; | |
247 | + *u = *op; | |
248 | +} | |
249 | + | |
228 | 250 | static void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val) |
229 | 251 | { |
230 | 252 | struct mmu_update u; |
... | ... | @@ -245,6 +267,8 @@ |
245 | 267 | |
246 | 268 | static void xen_set_pmd(pmd_t *ptr, pmd_t val) |
247 | 269 | { |
270 | + trace_xen_mmu_set_pmd(ptr, val); | |
271 | + | |
248 | 272 | /* If page is not pinned, we can just update the entry |
249 | 273 | directly */ |
250 | 274 | if (!xen_page_pinned(ptr)) { |
251 | 275 | |
252 | 276 | |
253 | 277 | |
... | ... | @@ -282,22 +306,30 @@ |
282 | 306 | return true; |
283 | 307 | } |
284 | 308 | |
285 | -static void xen_set_pte(pte_t *ptep, pte_t pteval) | |
309 | +static inline void __xen_set_pte(pte_t *ptep, pte_t pteval) | |
286 | 310 | { |
287 | 311 | if (!xen_batched_set_pte(ptep, pteval)) |
288 | 312 | native_set_pte(ptep, pteval); |
289 | 313 | } |
290 | 314 | |
315 | +static void xen_set_pte(pte_t *ptep, pte_t pteval) | |
316 | +{ | |
317 | + trace_xen_mmu_set_pte(ptep, pteval); | |
318 | + __xen_set_pte(ptep, pteval); | |
319 | +} | |
320 | + | |
291 | 321 | static void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, |
292 | 322 | pte_t *ptep, pte_t pteval) |
293 | 323 | { |
294 | - xen_set_pte(ptep, pteval); | |
324 | + trace_xen_mmu_set_pte_at(mm, addr, ptep, pteval); | |
325 | + __xen_set_pte(ptep, pteval); | |
295 | 326 | } |
296 | 327 | |
297 | 328 | pte_t xen_ptep_modify_prot_start(struct mm_struct *mm, |
298 | 329 | unsigned long addr, pte_t *ptep) |
299 | 330 | { |
300 | 331 | /* Just return the pte as-is. We preserve the bits on commit */ |
332 | + trace_xen_mmu_ptep_modify_prot_start(mm, addr, ptep, *ptep); | |
301 | 333 | return *ptep; |
302 | 334 | } |
303 | 335 | |
... | ... | @@ -306,6 +338,7 @@ |
306 | 338 | { |
307 | 339 | struct mmu_update u; |
308 | 340 | |
341 | + trace_xen_mmu_ptep_modify_prot_commit(mm, addr, ptep, pte); | |
309 | 342 | xen_mc_batch(); |
310 | 343 | |
311 | 344 | u.ptr = virt_to_machine(ptep).maddr | MMU_PT_UPDATE_PRESERVE_AD; |
... | ... | @@ -530,6 +563,8 @@ |
530 | 563 | |
531 | 564 | static void xen_set_pud(pud_t *ptr, pud_t val) |
532 | 565 | { |
566 | + trace_xen_mmu_set_pud(ptr, val); | |
567 | + | |
533 | 568 | /* If page is not pinned, we can just update the entry |
534 | 569 | directly */ |
535 | 570 | if (!xen_page_pinned(ptr)) { |
536 | 571 | |
537 | 572 | |
... | ... | @@ -543,17 +578,20 @@ |
543 | 578 | #ifdef CONFIG_X86_PAE |
544 | 579 | static void xen_set_pte_atomic(pte_t *ptep, pte_t pte) |
545 | 580 | { |
581 | + trace_xen_mmu_set_pte_atomic(ptep, pte); | |
546 | 582 | set_64bit((u64 *)ptep, native_pte_val(pte)); |
547 | 583 | } |
548 | 584 | |
549 | 585 | static void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) |
550 | 586 | { |
587 | + trace_xen_mmu_pte_clear(mm, addr, ptep); | |
551 | 588 | if (!xen_batched_set_pte(ptep, native_make_pte(0))) |
552 | 589 | native_pte_clear(mm, addr, ptep); |
553 | 590 | } |
554 | 591 | |
555 | 592 | static void xen_pmd_clear(pmd_t *pmdp) |
556 | 593 | { |
594 | + trace_xen_mmu_pmd_clear(pmdp); | |
557 | 595 | set_pmd(pmdp, __pmd(0)); |
558 | 596 | } |
559 | 597 | #endif /* CONFIG_X86_PAE */ |
... | ... | @@ -629,6 +667,8 @@ |
629 | 667 | { |
630 | 668 | pgd_t *user_ptr = xen_get_user_pgd(ptr); |
631 | 669 | |
670 | + trace_xen_mmu_set_pgd(ptr, user_ptr, val); | |
671 | + | |
632 | 672 | /* If page is not pinned, we can just update the entry |
633 | 673 | directly */ |
634 | 674 | if (!xen_page_pinned(ptr)) { |
635 | 675 | |
... | ... | @@ -788,14 +828,12 @@ |
788 | 828 | |
789 | 829 | static void xen_do_pin(unsigned level, unsigned long pfn) |
790 | 830 | { |
791 | - struct mmuext_op *op; | |
792 | - struct multicall_space mcs; | |
831 | + struct mmuext_op op; | |
793 | 832 | |
794 | - mcs = __xen_mc_entry(sizeof(*op)); | |
795 | - op = mcs.args; | |
796 | - op->cmd = level; | |
797 | - op->arg1.mfn = pfn_to_mfn(pfn); | |
798 | - MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); | |
833 | + op.cmd = level; | |
834 | + op.arg1.mfn = pfn_to_mfn(pfn); | |
835 | + | |
836 | + xen_extend_mmuext_op(&op); | |
799 | 837 | } |
800 | 838 | |
801 | 839 | static int xen_pin_page(struct mm_struct *mm, struct page *page, |
... | ... | @@ -863,6 +901,8 @@ |
863 | 901 | read-only, and can be pinned. */ |
864 | 902 | static void __xen_pgd_pin(struct mm_struct *mm, pgd_t *pgd) |
865 | 903 | { |
904 | + trace_xen_mmu_pgd_pin(mm, pgd); | |
905 | + | |
866 | 906 | xen_mc_batch(); |
867 | 907 | |
868 | 908 | if (__xen_pgd_walk(mm, pgd, xen_pin_page, USER_LIMIT)) { |
... | ... | @@ -988,6 +1028,8 @@ |
988 | 1028 | /* Release a pagetables pages back as normal RW */ |
989 | 1029 | static void __xen_pgd_unpin(struct mm_struct *mm, pgd_t *pgd) |
990 | 1030 | { |
1031 | + trace_xen_mmu_pgd_unpin(mm, pgd); | |
1032 | + | |
991 | 1033 | xen_mc_batch(); |
992 | 1034 | |
993 | 1035 | xen_do_pin(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); |
... | ... | @@ -1196,6 +1238,8 @@ |
1196 | 1238 | struct mmuext_op *op; |
1197 | 1239 | struct multicall_space mcs; |
1198 | 1240 | |
1241 | + trace_xen_mmu_flush_tlb(0); | |
1242 | + | |
1199 | 1243 | preempt_disable(); |
1200 | 1244 | |
1201 | 1245 | mcs = xen_mc_entry(sizeof(*op)); |
... | ... | @@ -1214,6 +1258,8 @@ |
1214 | 1258 | struct mmuext_op *op; |
1215 | 1259 | struct multicall_space mcs; |
1216 | 1260 | |
1261 | + trace_xen_mmu_flush_tlb_single(addr); | |
1262 | + | |
1217 | 1263 | preempt_disable(); |
1218 | 1264 | |
1219 | 1265 | mcs = xen_mc_entry(sizeof(*op)); |
... | ... | @@ -1240,6 +1286,8 @@ |
1240 | 1286 | } *args; |
1241 | 1287 | struct multicall_space mcs; |
1242 | 1288 | |
1289 | + trace_xen_mmu_flush_tlb_others(cpus, mm, va); | |
1290 | + | |
1243 | 1291 | if (cpumask_empty(cpus)) |
1244 | 1292 | return; /* nothing to do */ |
1245 | 1293 | |
1246 | 1294 | |
... | ... | @@ -1275,10 +1323,11 @@ |
1275 | 1323 | |
1276 | 1324 | static void __xen_write_cr3(bool kernel, unsigned long cr3) |
1277 | 1325 | { |
1278 | - struct mmuext_op *op; | |
1279 | - struct multicall_space mcs; | |
1326 | + struct mmuext_op op; | |
1280 | 1327 | unsigned long mfn; |
1281 | 1328 | |
1329 | + trace_xen_mmu_write_cr3(kernel, cr3); | |
1330 | + | |
1282 | 1331 | if (cr3) |
1283 | 1332 | mfn = pfn_to_mfn(PFN_DOWN(cr3)); |
1284 | 1333 | else |
1285 | 1334 | |
1286 | 1335 | |
... | ... | @@ -1286,14 +1335,11 @@ |
1286 | 1335 | |
1287 | 1336 | WARN_ON(mfn == 0 && kernel); |
1288 | 1337 | |
1289 | - mcs = __xen_mc_entry(sizeof(*op)); | |
1338 | + op.cmd = kernel ? MMUEXT_NEW_BASEPTR : MMUEXT_NEW_USER_BASEPTR; | |
1339 | + op.arg1.mfn = mfn; | |
1290 | 1340 | |
1291 | - op = mcs.args; | |
1292 | - op->cmd = kernel ? MMUEXT_NEW_BASEPTR : MMUEXT_NEW_USER_BASEPTR; | |
1293 | - op->arg1.mfn = mfn; | |
1341 | + xen_extend_mmuext_op(&op); | |
1294 | 1342 | |
1295 | - MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); | |
1296 | - | |
1297 | 1343 | if (kernel) { |
1298 | 1344 | percpu_write(xen_cr3, cr3); |
1299 | 1345 | |
1300 | 1346 | |
1301 | 1347 | |
1302 | 1348 | |
1303 | 1349 | |
1304 | 1350 | |
... | ... | @@ -1451,19 +1497,52 @@ |
1451 | 1497 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); |
1452 | 1498 | } |
1453 | 1499 | |
1500 | +static inline void __pin_pagetable_pfn(unsigned cmd, unsigned long pfn) | |
1501 | +{ | |
1502 | + struct multicall_space mcs; | |
1503 | + struct mmuext_op *op; | |
1504 | + | |
1505 | + mcs = __xen_mc_entry(sizeof(*op)); | |
1506 | + op = mcs.args; | |
1507 | + op->cmd = cmd; | |
1508 | + op->arg1.mfn = pfn_to_mfn(pfn); | |
1509 | + | |
1510 | + MULTI_mmuext_op(mcs.mc, mcs.args, 1, NULL, DOMID_SELF); | |
1511 | +} | |
1512 | + | |
1513 | +static inline void __set_pfn_prot(unsigned long pfn, pgprot_t prot) | |
1514 | +{ | |
1515 | + struct multicall_space mcs; | |
1516 | + unsigned long addr = (unsigned long)__va(pfn << PAGE_SHIFT); | |
1517 | + | |
1518 | + mcs = __xen_mc_entry(0); | |
1519 | + MULTI_update_va_mapping(mcs.mc, (unsigned long)addr, | |
1520 | + pfn_pte(pfn, prot), 0); | |
1521 | +} | |
1522 | + | |
1454 | 1523 | /* This needs to make sure the new pte page is pinned iff its being |
1455 | 1524 | attached to a pinned pagetable. */ |
1456 | -static void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, unsigned level) | |
1525 | +static inline void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, | |
1526 | + unsigned level) | |
1457 | 1527 | { |
1458 | - struct page *page = pfn_to_page(pfn); | |
1528 | + bool pinned = PagePinned(virt_to_page(mm->pgd)); | |
1459 | 1529 | |
1460 | - if (PagePinned(virt_to_page(mm->pgd))) { | |
1530 | + trace_xen_mmu_alloc_ptpage(mm, pfn, level, pinned); | |
1531 | + | |
1532 | + if (pinned) { | |
1533 | + struct page *page = pfn_to_page(pfn); | |
1534 | + | |
1461 | 1535 | SetPagePinned(page); |
1462 | 1536 | |
1463 | 1537 | if (!PageHighMem(page)) { |
1464 | - make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn))); | |
1538 | + xen_mc_batch(); | |
1539 | + | |
1540 | + __set_pfn_prot(pfn, PAGE_KERNEL_RO); | |
1541 | + | |
1465 | 1542 | if (level == PT_PTE && USE_SPLIT_PTLOCKS) |
1466 | - pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); | |
1543 | + __pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); | |
1544 | + | |
1545 | + xen_mc_issue(PARAVIRT_LAZY_MMU); | |
1467 | 1546 | } else { |
1468 | 1547 | /* make sure there are no stray mappings of |
1469 | 1548 | this page */ |
1470 | 1549 | |
1471 | 1550 | |
1472 | 1551 | |
1473 | 1552 | |
... | ... | @@ -1483,15 +1562,23 @@ |
1483 | 1562 | } |
1484 | 1563 | |
1485 | 1564 | /* This should never happen until we're OK to use struct page */ |
1486 | -static void xen_release_ptpage(unsigned long pfn, unsigned level) | |
1565 | +static inline void xen_release_ptpage(unsigned long pfn, unsigned level) | |
1487 | 1566 | { |
1488 | 1567 | struct page *page = pfn_to_page(pfn); |
1568 | + bool pinned = PagePinned(page); | |
1489 | 1569 | |
1490 | - if (PagePinned(page)) { | |
1570 | + trace_xen_mmu_release_ptpage(pfn, level, pinned); | |
1571 | + | |
1572 | + if (pinned) { | |
1491 | 1573 | if (!PageHighMem(page)) { |
1574 | + xen_mc_batch(); | |
1575 | + | |
1492 | 1576 | if (level == PT_PTE && USE_SPLIT_PTLOCKS) |
1493 | - pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); | |
1494 | - make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); | |
1577 | + __pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); | |
1578 | + | |
1579 | + __set_pfn_prot(pfn, PAGE_KERNEL); | |
1580 | + | |
1581 | + xen_mc_issue(PARAVIRT_LAZY_MMU); | |
1495 | 1582 | } |
1496 | 1583 | ClearPagePinned(page); |
1497 | 1584 | } |
arch/x86/xen/multicalls.c
... | ... | @@ -30,12 +30,13 @@ |
30 | 30 | |
31 | 31 | #define MC_BATCH 32 |
32 | 32 | |
33 | -#define MC_DEBUG 1 | |
33 | +#define MC_DEBUG 0 | |
34 | 34 | |
35 | 35 | #define MC_ARGS (MC_BATCH * 16) |
36 | 36 | |
37 | 37 | |
38 | 38 | struct mc_buffer { |
39 | + unsigned mcidx, argidx, cbidx; | |
39 | 40 | struct multicall_entry entries[MC_BATCH]; |
40 | 41 | #if MC_DEBUG |
41 | 42 | struct multicall_entry debug[MC_BATCH]; |
42 | 43 | |
43 | 44 | |
... | ... | @@ -46,85 +47,15 @@ |
46 | 47 | void (*fn)(void *); |
47 | 48 | void *data; |
48 | 49 | } callbacks[MC_BATCH]; |
49 | - unsigned mcidx, argidx, cbidx; | |
50 | 50 | }; |
51 | 51 | |
52 | 52 | static DEFINE_PER_CPU(struct mc_buffer, mc_buffer); |
53 | 53 | DEFINE_PER_CPU(unsigned long, xen_mc_irq_flags); |
54 | 54 | |
55 | -/* flush reasons 0- slots, 1- args, 2- callbacks */ | |
56 | -enum flush_reasons | |
57 | -{ | |
58 | - FL_SLOTS, | |
59 | - FL_ARGS, | |
60 | - FL_CALLBACKS, | |
61 | - | |
62 | - FL_N_REASONS | |
63 | -}; | |
64 | - | |
65 | -#ifdef CONFIG_XEN_DEBUG_FS | |
66 | -#define NHYPERCALLS 40 /* not really */ | |
67 | - | |
68 | -static struct { | |
69 | - unsigned histo[MC_BATCH+1]; | |
70 | - | |
71 | - unsigned issued; | |
72 | - unsigned arg_total; | |
73 | - unsigned hypercalls; | |
74 | - unsigned histo_hypercalls[NHYPERCALLS]; | |
75 | - | |
76 | - unsigned flush[FL_N_REASONS]; | |
77 | -} mc_stats; | |
78 | - | |
79 | -static u8 zero_stats; | |
80 | - | |
81 | -static inline void check_zero(void) | |
82 | -{ | |
83 | - if (unlikely(zero_stats)) { | |
84 | - memset(&mc_stats, 0, sizeof(mc_stats)); | |
85 | - zero_stats = 0; | |
86 | - } | |
87 | -} | |
88 | - | |
89 | -static void mc_add_stats(const struct mc_buffer *mc) | |
90 | -{ | |
91 | - int i; | |
92 | - | |
93 | - check_zero(); | |
94 | - | |
95 | - mc_stats.issued++; | |
96 | - mc_stats.hypercalls += mc->mcidx; | |
97 | - mc_stats.arg_total += mc->argidx; | |
98 | - | |
99 | - mc_stats.histo[mc->mcidx]++; | |
100 | - for(i = 0; i < mc->mcidx; i++) { | |
101 | - unsigned op = mc->entries[i].op; | |
102 | - if (op < NHYPERCALLS) | |
103 | - mc_stats.histo_hypercalls[op]++; | |
104 | - } | |
105 | -} | |
106 | - | |
107 | -static void mc_stats_flush(enum flush_reasons idx) | |
108 | -{ | |
109 | - check_zero(); | |
110 | - | |
111 | - mc_stats.flush[idx]++; | |
112 | -} | |
113 | - | |
114 | -#else /* !CONFIG_XEN_DEBUG_FS */ | |
115 | - | |
116 | -static inline void mc_add_stats(const struct mc_buffer *mc) | |
117 | -{ | |
118 | -} | |
119 | - | |
120 | -static inline void mc_stats_flush(enum flush_reasons idx) | |
121 | -{ | |
122 | -} | |
123 | -#endif /* CONFIG_XEN_DEBUG_FS */ | |
124 | - | |
125 | 55 | void xen_mc_flush(void) |
126 | 56 | { |
127 | 57 | struct mc_buffer *b = &__get_cpu_var(mc_buffer); |
58 | + struct multicall_entry *mc; | |
128 | 59 | int ret = 0; |
129 | 60 | unsigned long flags; |
130 | 61 | int i; |
131 | 62 | |
... | ... | @@ -135,9 +66,26 @@ |
135 | 66 | something in the middle */ |
136 | 67 | local_irq_save(flags); |
137 | 68 | |
138 | - mc_add_stats(b); | |
69 | + trace_xen_mc_flush(b->mcidx, b->argidx, b->cbidx); | |
139 | 70 | |
140 | - if (b->mcidx) { | |
71 | + switch (b->mcidx) { | |
72 | + case 0: | |
73 | + /* no-op */ | |
74 | + BUG_ON(b->argidx != 0); | |
75 | + break; | |
76 | + | |
77 | + case 1: | |
78 | + /* Singleton multicall - bypass multicall machinery | |
79 | + and just do the call directly. */ | |
80 | + mc = &b->entries[0]; | |
81 | + | |
82 | + mc->result = privcmd_call(mc->op, | |
83 | + mc->args[0], mc->args[1], mc->args[2], | |
84 | + mc->args[3], mc->args[4]); | |
85 | + ret = mc->result < 0; | |
86 | + break; | |
87 | + | |
88 | + default: | |
141 | 89 | #if MC_DEBUG |
142 | 90 | memcpy(b->debug, b->entries, |
143 | 91 | b->mcidx * sizeof(struct multicall_entry)); |
144 | 92 | |
... | ... | @@ -164,11 +112,10 @@ |
164 | 112 | } |
165 | 113 | } |
166 | 114 | #endif |
115 | + } | |
167 | 116 | |
168 | - b->mcidx = 0; | |
169 | - b->argidx = 0; | |
170 | - } else | |
171 | - BUG_ON(b->argidx != 0); | |
117 | + b->mcidx = 0; | |
118 | + b->argidx = 0; | |
172 | 119 | |
173 | 120 | for (i = 0; i < b->cbidx; i++) { |
174 | 121 | struct callback *cb = &b->callbacks[i]; |
175 | 122 | |
176 | 123 | |
... | ... | @@ -188,18 +135,21 @@ |
188 | 135 | struct multicall_space ret; |
189 | 136 | unsigned argidx = roundup(b->argidx, sizeof(u64)); |
190 | 137 | |
138 | + trace_xen_mc_entry_alloc(args); | |
139 | + | |
191 | 140 | BUG_ON(preemptible()); |
192 | 141 | BUG_ON(b->argidx >= MC_ARGS); |
193 | 142 | |
194 | - if (b->mcidx == MC_BATCH || | |
195 | - (argidx + args) >= MC_ARGS) { | |
196 | - mc_stats_flush(b->mcidx == MC_BATCH ? FL_SLOTS : FL_ARGS); | |
143 | + if (unlikely(b->mcidx == MC_BATCH || | |
144 | + (argidx + args) >= MC_ARGS)) { | |
145 | + trace_xen_mc_flush_reason((b->mcidx == MC_BATCH) ? | |
146 | + XEN_MC_FL_BATCH : XEN_MC_FL_ARGS); | |
197 | 147 | xen_mc_flush(); |
198 | 148 | argidx = roundup(b->argidx, sizeof(u64)); |
199 | 149 | } |
200 | 150 | |
201 | 151 | ret.mc = &b->entries[b->mcidx]; |
202 | -#ifdef MC_DEBUG | |
152 | +#if MC_DEBUG | |
203 | 153 | b->caller[b->mcidx] = __builtin_return_address(0); |
204 | 154 | #endif |
205 | 155 | b->mcidx++; |
206 | 156 | |
207 | 157 | |
208 | 158 | |
... | ... | @@ -218,20 +168,25 @@ |
218 | 168 | BUG_ON(preemptible()); |
219 | 169 | BUG_ON(b->argidx >= MC_ARGS); |
220 | 170 | |
221 | - if (b->mcidx == 0) | |
222 | - return ret; | |
171 | + if (unlikely(b->mcidx == 0 || | |
172 | + b->entries[b->mcidx - 1].op != op)) { | |
173 | + trace_xen_mc_extend_args(op, size, XEN_MC_XE_BAD_OP); | |
174 | + goto out; | |
175 | + } | |
223 | 176 | |
224 | - if (b->entries[b->mcidx - 1].op != op) | |
225 | - return ret; | |
177 | + if (unlikely((b->argidx + size) >= MC_ARGS)) { | |
178 | + trace_xen_mc_extend_args(op, size, XEN_MC_XE_NO_SPACE); | |
179 | + goto out; | |
180 | + } | |
226 | 181 | |
227 | - if ((b->argidx + size) >= MC_ARGS) | |
228 | - return ret; | |
229 | - | |
230 | 182 | ret.mc = &b->entries[b->mcidx - 1]; |
231 | 183 | ret.args = &b->args[b->argidx]; |
232 | 184 | b->argidx += size; |
233 | 185 | |
234 | 186 | BUG_ON(b->argidx >= MC_ARGS); |
187 | + | |
188 | + trace_xen_mc_extend_args(op, size, XEN_MC_XE_OK); | |
189 | +out: | |
235 | 190 | return ret; |
236 | 191 | } |
237 | 192 | |
238 | 193 | |
239 | 194 | |
... | ... | @@ -241,44 +196,14 @@ |
241 | 196 | struct callback *cb; |
242 | 197 | |
243 | 198 | if (b->cbidx == MC_BATCH) { |
244 | - mc_stats_flush(FL_CALLBACKS); | |
199 | + trace_xen_mc_flush_reason(XEN_MC_FL_CALLBACK); | |
245 | 200 | xen_mc_flush(); |
246 | 201 | } |
247 | 202 | |
203 | + trace_xen_mc_callback(fn, data); | |
204 | + | |
248 | 205 | cb = &b->callbacks[b->cbidx++]; |
249 | 206 | cb->fn = fn; |
250 | 207 | cb->data = data; |
251 | 208 | } |
252 | - | |
253 | -#ifdef CONFIG_XEN_DEBUG_FS | |
254 | - | |
255 | -static struct dentry *d_mc_debug; | |
256 | - | |
257 | -static int __init xen_mc_debugfs(void) | |
258 | -{ | |
259 | - struct dentry *d_xen = xen_init_debugfs(); | |
260 | - | |
261 | - if (d_xen == NULL) | |
262 | - return -ENOMEM; | |
263 | - | |
264 | - d_mc_debug = debugfs_create_dir("multicalls", d_xen); | |
265 | - | |
266 | - debugfs_create_u8("zero_stats", 0644, d_mc_debug, &zero_stats); | |
267 | - | |
268 | - debugfs_create_u32("batches", 0444, d_mc_debug, &mc_stats.issued); | |
269 | - debugfs_create_u32("hypercalls", 0444, d_mc_debug, &mc_stats.hypercalls); | |
270 | - debugfs_create_u32("arg_total", 0444, d_mc_debug, &mc_stats.arg_total); | |
271 | - | |
272 | - xen_debugfs_create_u32_array("batch_histo", 0444, d_mc_debug, | |
273 | - mc_stats.histo, MC_BATCH); | |
274 | - xen_debugfs_create_u32_array("hypercall_histo", 0444, d_mc_debug, | |
275 | - mc_stats.histo_hypercalls, NHYPERCALLS); | |
276 | - xen_debugfs_create_u32_array("flush_reasons", 0444, d_mc_debug, | |
277 | - mc_stats.flush, FL_N_REASONS); | |
278 | - | |
279 | - return 0; | |
280 | -} | |
281 | -fs_initcall(xen_mc_debugfs); | |
282 | - | |
283 | -#endif /* CONFIG_XEN_DEBUG_FS */ |
arch/x86/xen/multicalls.h
1 | 1 | #ifndef _XEN_MULTICALLS_H |
2 | 2 | #define _XEN_MULTICALLS_H |
3 | 3 | |
4 | +#include <trace/events/xen.h> | |
5 | + | |
4 | 6 | #include "xen-ops.h" |
5 | 7 | |
6 | 8 | /* Multicalls */ |
7 | 9 | |
... | ... | @@ -20,8 +22,10 @@ |
20 | 22 | static inline void xen_mc_batch(void) |
21 | 23 | { |
22 | 24 | unsigned long flags; |
25 | + | |
23 | 26 | /* need to disable interrupts until this entry is complete */ |
24 | 27 | local_irq_save(flags); |
28 | + trace_xen_mc_batch(paravirt_get_lazy_mode()); | |
25 | 29 | __this_cpu_write(xen_mc_irq_flags, flags); |
26 | 30 | } |
27 | 31 | |
... | ... | @@ -37,6 +41,8 @@ |
37 | 41 | /* Issue a multicall if we're not in a lazy mode */ |
38 | 42 | static inline void xen_mc_issue(unsigned mode) |
39 | 43 | { |
44 | + trace_xen_mc_issue(mode); | |
45 | + | |
40 | 46 | if ((paravirt_get_lazy_mode() & mode) == 0) |
41 | 47 | xen_mc_flush(); |
42 | 48 |
arch/x86/xen/trace.c
1 | +#include <linux/ftrace.h> | |
2 | + | |
3 | +#define N(x) [__HYPERVISOR_##x] = "("#x")" | |
4 | +static const char *xen_hypercall_names[] = { | |
5 | + N(set_trap_table), | |
6 | + N(mmu_update), | |
7 | + N(set_gdt), | |
8 | + N(stack_switch), | |
9 | + N(set_callbacks), | |
10 | + N(fpu_taskswitch), | |
11 | + N(sched_op_compat), | |
12 | + N(dom0_op), | |
13 | + N(set_debugreg), | |
14 | + N(get_debugreg), | |
15 | + N(update_descriptor), | |
16 | + N(memory_op), | |
17 | + N(multicall), | |
18 | + N(update_va_mapping), | |
19 | + N(set_timer_op), | |
20 | + N(event_channel_op_compat), | |
21 | + N(xen_version), | |
22 | + N(console_io), | |
23 | + N(physdev_op_compat), | |
24 | + N(grant_table_op), | |
25 | + N(vm_assist), | |
26 | + N(update_va_mapping_otherdomain), | |
27 | + N(iret), | |
28 | + N(vcpu_op), | |
29 | + N(set_segment_base), | |
30 | + N(mmuext_op), | |
31 | + N(acm_op), | |
32 | + N(nmi_op), | |
33 | + N(sched_op), | |
34 | + N(callback_op), | |
35 | + N(xenoprof_op), | |
36 | + N(event_channel_op), | |
37 | + N(physdev_op), | |
38 | + N(hvm_op), | |
39 | + | |
40 | +/* Architecture-specific hypercall definitions. */ | |
41 | + N(arch_0), | |
42 | + N(arch_1), | |
43 | + N(arch_2), | |
44 | + N(arch_3), | |
45 | + N(arch_4), | |
46 | + N(arch_5), | |
47 | + N(arch_6), | |
48 | + N(arch_7), | |
49 | +}; | |
50 | +#undef N | |
51 | + | |
52 | +static const char *xen_hypercall_name(unsigned op) | |
53 | +{ | |
54 | + if (op < ARRAY_SIZE(xen_hypercall_names) && xen_hypercall_names[op] != NULL) | |
55 | + return xen_hypercall_names[op]; | |
56 | + | |
57 | + return ""; | |
58 | +} | |
59 | + | |
60 | +#define CREATE_TRACE_POINTS | |
61 | +#include <trace/events/xen.h> |
include/trace/events/xen.h
1 | +#undef TRACE_SYSTEM | |
2 | +#define TRACE_SYSTEM xen | |
3 | + | |
4 | +#if !defined(_TRACE_XEN_H) || defined(TRACE_HEADER_MULTI_READ) | |
5 | +#define _TRACE_XEN_H | |
6 | + | |
7 | +#include <linux/tracepoint.h> | |
8 | +#include <asm/paravirt_types.h> | |
9 | +#include <asm/xen/trace_types.h> | |
10 | + | |
11 | +/* Multicalls */ | |
12 | +DECLARE_EVENT_CLASS(xen_mc__batch, | |
13 | + TP_PROTO(enum paravirt_lazy_mode mode), | |
14 | + TP_ARGS(mode), | |
15 | + TP_STRUCT__entry( | |
16 | + __field(enum paravirt_lazy_mode, mode) | |
17 | + ), | |
18 | + TP_fast_assign(__entry->mode = mode), | |
19 | + TP_printk("start batch LAZY_%s", | |
20 | + (__entry->mode == PARAVIRT_LAZY_MMU) ? "MMU" : | |
21 | + (__entry->mode == PARAVIRT_LAZY_CPU) ? "CPU" : "NONE") | |
22 | + ); | |
23 | +#define DEFINE_XEN_MC_BATCH(name) \ | |
24 | + DEFINE_EVENT(xen_mc__batch, name, \ | |
25 | + TP_PROTO(enum paravirt_lazy_mode mode), \ | |
26 | + TP_ARGS(mode)) | |
27 | + | |
28 | +DEFINE_XEN_MC_BATCH(xen_mc_batch); | |
29 | +DEFINE_XEN_MC_BATCH(xen_mc_issue); | |
30 | + | |
31 | +TRACE_EVENT(xen_mc_entry, | |
32 | + TP_PROTO(struct multicall_entry *mc, unsigned nargs), | |
33 | + TP_ARGS(mc, nargs), | |
34 | + TP_STRUCT__entry( | |
35 | + __field(unsigned int, op) | |
36 | + __field(unsigned int, nargs) | |
37 | + __array(unsigned long, args, 6) | |
38 | + ), | |
39 | + TP_fast_assign(__entry->op = mc->op; | |
40 | + __entry->nargs = nargs; | |
41 | + memcpy(__entry->args, mc->args, sizeof(unsigned long) * nargs); | |
42 | + memset(__entry->args + nargs, 0, sizeof(unsigned long) * (6 - nargs)); | |
43 | + ), | |
44 | + TP_printk("op %u%s args [%lx, %lx, %lx, %lx, %lx, %lx]", | |
45 | + __entry->op, xen_hypercall_name(__entry->op), | |
46 | + __entry->args[0], __entry->args[1], __entry->args[2], | |
47 | + __entry->args[3], __entry->args[4], __entry->args[5]) | |
48 | + ); | |
49 | + | |
50 | +TRACE_EVENT(xen_mc_entry_alloc, | |
51 | + TP_PROTO(size_t args), | |
52 | + TP_ARGS(args), | |
53 | + TP_STRUCT__entry( | |
54 | + __field(size_t, args) | |
55 | + ), | |
56 | + TP_fast_assign(__entry->args = args), | |
57 | + TP_printk("alloc entry %zu arg bytes", __entry->args) | |
58 | + ); | |
59 | + | |
60 | +TRACE_EVENT(xen_mc_callback, | |
61 | + TP_PROTO(xen_mc_callback_fn_t fn, void *data), | |
62 | + TP_ARGS(fn, data), | |
63 | + TP_STRUCT__entry( | |
64 | + __field(xen_mc_callback_fn_t, fn) | |
65 | + __field(void *, data) | |
66 | + ), | |
67 | + TP_fast_assign( | |
68 | + __entry->fn = fn; | |
69 | + __entry->data = data; | |
70 | + ), | |
71 | + TP_printk("callback %pf, data %p", | |
72 | + __entry->fn, __entry->data) | |
73 | + ); | |
74 | + | |
75 | +TRACE_EVENT(xen_mc_flush_reason, | |
76 | + TP_PROTO(enum xen_mc_flush_reason reason), | |
77 | + TP_ARGS(reason), | |
78 | + TP_STRUCT__entry( | |
79 | + __field(enum xen_mc_flush_reason, reason) | |
80 | + ), | |
81 | + TP_fast_assign(__entry->reason = reason), | |
82 | + TP_printk("flush reason %s", | |
83 | + (__entry->reason == XEN_MC_FL_NONE) ? "NONE" : | |
84 | + (__entry->reason == XEN_MC_FL_BATCH) ? "BATCH" : | |
85 | + (__entry->reason == XEN_MC_FL_ARGS) ? "ARGS" : | |
86 | + (__entry->reason == XEN_MC_FL_CALLBACK) ? "CALLBACK" : "??") | |
87 | + ); | |
88 | + | |
89 | +TRACE_EVENT(xen_mc_flush, | |
90 | + TP_PROTO(unsigned mcidx, unsigned argidx, unsigned cbidx), | |
91 | + TP_ARGS(mcidx, argidx, cbidx), | |
92 | + TP_STRUCT__entry( | |
93 | + __field(unsigned, mcidx) | |
94 | + __field(unsigned, argidx) | |
95 | + __field(unsigned, cbidx) | |
96 | + ), | |
97 | + TP_fast_assign(__entry->mcidx = mcidx; | |
98 | + __entry->argidx = argidx; | |
99 | + __entry->cbidx = cbidx), | |
100 | + TP_printk("flushing %u hypercalls, %u arg bytes, %u callbacks", | |
101 | + __entry->mcidx, __entry->argidx, __entry->cbidx) | |
102 | + ); | |
103 | + | |
104 | +TRACE_EVENT(xen_mc_extend_args, | |
105 | + TP_PROTO(unsigned long op, size_t args, enum xen_mc_extend_args res), | |
106 | + TP_ARGS(op, args, res), | |
107 | + TP_STRUCT__entry( | |
108 | + __field(unsigned int, op) | |
109 | + __field(size_t, args) | |
110 | + __field(enum xen_mc_extend_args, res) | |
111 | + ), | |
112 | + TP_fast_assign(__entry->op = op; | |
113 | + __entry->args = args; | |
114 | + __entry->res = res), | |
115 | + TP_printk("extending op %u%s by %zu bytes res %s", | |
116 | + __entry->op, xen_hypercall_name(__entry->op), | |
117 | + __entry->args, | |
118 | + __entry->res == XEN_MC_XE_OK ? "OK" : | |
119 | + __entry->res == XEN_MC_XE_BAD_OP ? "BAD_OP" : | |
120 | + __entry->res == XEN_MC_XE_NO_SPACE ? "NO_SPACE" : "???") | |
121 | + ); | |
122 | + | |
123 | +/* mmu */ | |
124 | +DECLARE_EVENT_CLASS(xen_mmu__set_pte, | |
125 | + TP_PROTO(pte_t *ptep, pte_t pteval), | |
126 | + TP_ARGS(ptep, pteval), | |
127 | + TP_STRUCT__entry( | |
128 | + __field(pte_t *, ptep) | |
129 | + __field(pteval_t, pteval) | |
130 | + ), | |
131 | + TP_fast_assign(__entry->ptep = ptep; | |
132 | + __entry->pteval = pteval.pte), | |
133 | + TP_printk("ptep %p pteval %0*llx (raw %0*llx)", | |
134 | + __entry->ptep, | |
135 | + (int)sizeof(pteval_t) * 2, (unsigned long long)pte_val(native_make_pte(__entry->pteval)), | |
136 | + (int)sizeof(pteval_t) * 2, (unsigned long long)__entry->pteval) | |
137 | + ); | |
138 | + | |
139 | +#define DEFINE_XEN_MMU_SET_PTE(name) \ | |
140 | + DEFINE_EVENT(xen_mmu__set_pte, name, \ | |
141 | + TP_PROTO(pte_t *ptep, pte_t pteval), \ | |
142 | + TP_ARGS(ptep, pteval)) | |
143 | + | |
144 | +DEFINE_XEN_MMU_SET_PTE(xen_mmu_set_pte); | |
145 | +DEFINE_XEN_MMU_SET_PTE(xen_mmu_set_pte_atomic); | |
146 | + | |
147 | +TRACE_EVENT(xen_mmu_set_domain_pte, | |
148 | + TP_PROTO(pte_t *ptep, pte_t pteval, unsigned domid), | |
149 | + TP_ARGS(ptep, pteval, domid), | |
150 | + TP_STRUCT__entry( | |
151 | + __field(pte_t *, ptep) | |
152 | + __field(pteval_t, pteval) | |
153 | + __field(unsigned, domid) | |
154 | + ), | |
155 | + TP_fast_assign(__entry->ptep = ptep; | |
156 | + __entry->pteval = pteval.pte; | |
157 | + __entry->domid = domid), | |
158 | + TP_printk("ptep %p pteval %0*llx (raw %0*llx) domid %u", | |
159 | + __entry->ptep, | |
160 | + (int)sizeof(pteval_t) * 2, (unsigned long long)pte_val(native_make_pte(__entry->pteval)), | |
161 | + (int)sizeof(pteval_t) * 2, (unsigned long long)__entry->pteval, | |
162 | + __entry->domid) | |
163 | + ); | |
164 | + | |
165 | +TRACE_EVENT(xen_mmu_set_pte_at, | |
166 | + TP_PROTO(struct mm_struct *mm, unsigned long addr, | |
167 | + pte_t *ptep, pte_t pteval), | |
168 | + TP_ARGS(mm, addr, ptep, pteval), | |
169 | + TP_STRUCT__entry( | |
170 | + __field(struct mm_struct *, mm) | |
171 | + __field(unsigned long, addr) | |
172 | + __field(pte_t *, ptep) | |
173 | + __field(pteval_t, pteval) | |
174 | + ), | |
175 | + TP_fast_assign(__entry->mm = mm; | |
176 | + __entry->addr = addr; | |
177 | + __entry->ptep = ptep; | |
178 | + __entry->pteval = pteval.pte), | |
179 | + TP_printk("mm %p addr %lx ptep %p pteval %0*llx (raw %0*llx)", | |
180 | + __entry->mm, __entry->addr, __entry->ptep, | |
181 | + (int)sizeof(pteval_t) * 2, (unsigned long long)pte_val(native_make_pte(__entry->pteval)), | |
182 | + (int)sizeof(pteval_t) * 2, (unsigned long long)__entry->pteval) | |
183 | + ); | |
184 | + | |
185 | +TRACE_EVENT(xen_mmu_pte_clear, | |
186 | + TP_PROTO(struct mm_struct *mm, unsigned long addr, pte_t *ptep), | |
187 | + TP_ARGS(mm, addr, ptep), | |
188 | + TP_STRUCT__entry( | |
189 | + __field(struct mm_struct *, mm) | |
190 | + __field(unsigned long, addr) | |
191 | + __field(pte_t *, ptep) | |
192 | + ), | |
193 | + TP_fast_assign(__entry->mm = mm; | |
194 | + __entry->addr = addr; | |
195 | + __entry->ptep = ptep), | |
196 | + TP_printk("mm %p addr %lx ptep %p", | |
197 | + __entry->mm, __entry->addr, __entry->ptep) | |
198 | + ); | |
199 | + | |
200 | +TRACE_EVENT(xen_mmu_set_pmd, | |
201 | + TP_PROTO(pmd_t *pmdp, pmd_t pmdval), | |
202 | + TP_ARGS(pmdp, pmdval), | |
203 | + TP_STRUCT__entry( | |
204 | + __field(pmd_t *, pmdp) | |
205 | + __field(pmdval_t, pmdval) | |
206 | + ), | |
207 | + TP_fast_assign(__entry->pmdp = pmdp; | |
208 | + __entry->pmdval = pmdval.pmd), | |
209 | + TP_printk("pmdp %p pmdval %0*llx (raw %0*llx)", | |
210 | + __entry->pmdp, | |
211 | + (int)sizeof(pmdval_t) * 2, (unsigned long long)pmd_val(native_make_pmd(__entry->pmdval)), | |
212 | + (int)sizeof(pmdval_t) * 2, (unsigned long long)__entry->pmdval) | |
213 | + ); | |
214 | + | |
215 | +TRACE_EVENT(xen_mmu_pmd_clear, | |
216 | + TP_PROTO(pmd_t *pmdp), | |
217 | + TP_ARGS(pmdp), | |
218 | + TP_STRUCT__entry( | |
219 | + __field(pmd_t *, pmdp) | |
220 | + ), | |
221 | + TP_fast_assign(__entry->pmdp = pmdp), | |
222 | + TP_printk("pmdp %p", __entry->pmdp) | |
223 | + ); | |
224 | + | |
225 | +#if PAGETABLE_LEVELS >= 4 | |
226 | + | |
227 | +TRACE_EVENT(xen_mmu_set_pud, | |
228 | + TP_PROTO(pud_t *pudp, pud_t pudval), | |
229 | + TP_ARGS(pudp, pudval), | |
230 | + TP_STRUCT__entry( | |
231 | + __field(pud_t *, pudp) | |
232 | + __field(pudval_t, pudval) | |
233 | + ), | |
234 | + TP_fast_assign(__entry->pudp = pudp; | |
235 | + __entry->pudval = native_pud_val(pudval)), | |
236 | + TP_printk("pudp %p pudval %0*llx (raw %0*llx)", | |
237 | + __entry->pudp, | |
238 | + (int)sizeof(pudval_t) * 2, (unsigned long long)pud_val(native_make_pud(__entry->pudval)), | |
239 | + (int)sizeof(pudval_t) * 2, (unsigned long long)__entry->pudval) | |
240 | + ); | |
241 | + | |
242 | +TRACE_EVENT(xen_mmu_set_pgd, | |
243 | + TP_PROTO(pgd_t *pgdp, pgd_t *user_pgdp, pgd_t pgdval), | |
244 | + TP_ARGS(pgdp, user_pgdp, pgdval), | |
245 | + TP_STRUCT__entry( | |
246 | + __field(pgd_t *, pgdp) | |
247 | + __field(pgd_t *, user_pgdp) | |
248 | + __field(pgdval_t, pgdval) | |
249 | + ), | |
250 | + TP_fast_assign(__entry->pgdp = pgdp; | |
251 | + __entry->user_pgdp = user_pgdp; | |
252 | + __entry->pgdval = pgdval.pgd), | |
253 | + TP_printk("pgdp %p user_pgdp %p pgdval %0*llx (raw %0*llx)", | |
254 | + __entry->pgdp, __entry->user_pgdp, | |
255 | + (int)sizeof(pgdval_t) * 2, (unsigned long long)pgd_val(native_make_pgd(__entry->pgdval)), | |
256 | + (int)sizeof(pgdval_t) * 2, (unsigned long long)__entry->pgdval) | |
257 | + ); | |
258 | + | |
259 | +TRACE_EVENT(xen_mmu_pud_clear, | |
260 | + TP_PROTO(pud_t *pudp), | |
261 | + TP_ARGS(pudp), | |
262 | + TP_STRUCT__entry( | |
263 | + __field(pud_t *, pudp) | |
264 | + ), | |
265 | + TP_fast_assign(__entry->pudp = pudp), | |
266 | + TP_printk("pudp %p", __entry->pudp) | |
267 | + ); | |
268 | +#else | |
269 | + | |
270 | +TRACE_EVENT(xen_mmu_set_pud, | |
271 | + TP_PROTO(pud_t *pudp, pud_t pudval), | |
272 | + TP_ARGS(pudp, pudval), | |
273 | + TP_STRUCT__entry( | |
274 | + __field(pud_t *, pudp) | |
275 | + __field(pudval_t, pudval) | |
276 | + ), | |
277 | + TP_fast_assign(__entry->pudp = pudp; | |
278 | + __entry->pudval = native_pud_val(pudval)), | |
279 | + TP_printk("pudp %p pudval %0*llx (raw %0*llx)", | |
280 | + __entry->pudp, | |
281 | + (int)sizeof(pudval_t) * 2, (unsigned long long)pgd_val(native_make_pgd(__entry->pudval)), | |
282 | + (int)sizeof(pudval_t) * 2, (unsigned long long)__entry->pudval) | |
283 | + ); | |
284 | + | |
285 | +#endif | |
286 | + | |
287 | +TRACE_EVENT(xen_mmu_pgd_clear, | |
288 | + TP_PROTO(pgd_t *pgdp), | |
289 | + TP_ARGS(pgdp), | |
290 | + TP_STRUCT__entry( | |
291 | + __field(pgd_t *, pgdp) | |
292 | + ), | |
293 | + TP_fast_assign(__entry->pgdp = pgdp), | |
294 | + TP_printk("pgdp %p", __entry->pgdp) | |
295 | + ); | |
296 | + | |
297 | +DECLARE_EVENT_CLASS(xen_mmu_ptep_modify_prot, | |
298 | + TP_PROTO(struct mm_struct *mm, unsigned long addr, | |
299 | + pte_t *ptep, pte_t pteval), | |
300 | + TP_ARGS(mm, addr, ptep, pteval), | |
301 | + TP_STRUCT__entry( | |
302 | + __field(struct mm_struct *, mm) | |
303 | + __field(unsigned long, addr) | |
304 | + __field(pte_t *, ptep) | |
305 | + __field(pteval_t, pteval) | |
306 | + ), | |
307 | + TP_fast_assign(__entry->mm = mm; | |
308 | + __entry->addr = addr; | |
309 | + __entry->ptep = ptep; | |
310 | + __entry->pteval = pteval.pte), | |
311 | + TP_printk("mm %p addr %lx ptep %p pteval %0*llx (raw %0*llx)", | |
312 | + __entry->mm, __entry->addr, __entry->ptep, | |
313 | + (int)sizeof(pteval_t) * 2, (unsigned long long)pte_val(native_make_pte(__entry->pteval)), | |
314 | + (int)sizeof(pteval_t) * 2, (unsigned long long)__entry->pteval) | |
315 | + ); | |
316 | +#define DEFINE_XEN_MMU_PTEP_MODIFY_PROT(name) \ | |
317 | + DEFINE_EVENT(xen_mmu_ptep_modify_prot, name, \ | |
318 | + TP_PROTO(struct mm_struct *mm, unsigned long addr, \ | |
319 | + pte_t *ptep, pte_t pteval), \ | |
320 | + TP_ARGS(mm, addr, ptep, pteval)) | |
321 | + | |
322 | +DEFINE_XEN_MMU_PTEP_MODIFY_PROT(xen_mmu_ptep_modify_prot_start); | |
323 | +DEFINE_XEN_MMU_PTEP_MODIFY_PROT(xen_mmu_ptep_modify_prot_commit); | |
324 | + | |
325 | +TRACE_EVENT(xen_mmu_alloc_ptpage, | |
326 | + TP_PROTO(struct mm_struct *mm, unsigned long pfn, unsigned level, bool pinned), | |
327 | + TP_ARGS(mm, pfn, level, pinned), | |
328 | + TP_STRUCT__entry( | |
329 | + __field(struct mm_struct *, mm) | |
330 | + __field(unsigned long, pfn) | |
331 | + __field(unsigned, level) | |
332 | + __field(bool, pinned) | |
333 | + ), | |
334 | + TP_fast_assign(__entry->mm = mm; | |
335 | + __entry->pfn = pfn; | |
336 | + __entry->level = level; | |
337 | + __entry->pinned = pinned), | |
338 | + TP_printk("mm %p pfn %lx level %d %spinned", | |
339 | + __entry->mm, __entry->pfn, __entry->level, | |
340 | + __entry->pinned ? "" : "un") | |
341 | + ); | |
342 | + | |
343 | +TRACE_EVENT(xen_mmu_release_ptpage, | |
344 | + TP_PROTO(unsigned long pfn, unsigned level, bool pinned), | |
345 | + TP_ARGS(pfn, level, pinned), | |
346 | + TP_STRUCT__entry( | |
347 | + __field(unsigned long, pfn) | |
348 | + __field(unsigned, level) | |
349 | + __field(bool, pinned) | |
350 | + ), | |
351 | + TP_fast_assign(__entry->pfn = pfn; | |
352 | + __entry->level = level; | |
353 | + __entry->pinned = pinned), | |
354 | + TP_printk("pfn %lx level %d %spinned", | |
355 | + __entry->pfn, __entry->level, | |
356 | + __entry->pinned ? "" : "un") | |
357 | + ); | |
358 | + | |
359 | +DECLARE_EVENT_CLASS(xen_mmu_pgd, | |
360 | + TP_PROTO(struct mm_struct *mm, pgd_t *pgd), | |
361 | + TP_ARGS(mm, pgd), | |
362 | + TP_STRUCT__entry( | |
363 | + __field(struct mm_struct *, mm) | |
364 | + __field(pgd_t *, pgd) | |
365 | + ), | |
366 | + TP_fast_assign(__entry->mm = mm; | |
367 | + __entry->pgd = pgd), | |
368 | + TP_printk("mm %p pgd %p", __entry->mm, __entry->pgd) | |
369 | + ); | |
370 | +#define DEFINE_XEN_MMU_PGD_EVENT(name) \ | |
371 | + DEFINE_EVENT(xen_mmu_pgd, name, \ | |
372 | + TP_PROTO(struct mm_struct *mm, pgd_t *pgd), \ | |
373 | + TP_ARGS(mm, pgd)) | |
374 | + | |
375 | +DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin); | |
376 | +DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin); | |
377 | + | |
378 | +TRACE_EVENT(xen_mmu_flush_tlb, | |
379 | + TP_PROTO(int x), | |
380 | + TP_ARGS(x), | |
381 | + TP_STRUCT__entry(__array(char, x, 0)), | |
382 | + TP_fast_assign((void)x), | |
383 | + TP_printk("%s", "") | |
384 | + ); | |
385 | + | |
386 | +TRACE_EVENT(xen_mmu_flush_tlb_single, | |
387 | + TP_PROTO(unsigned long addr), | |
388 | + TP_ARGS(addr), | |
389 | + TP_STRUCT__entry( | |
390 | + __field(unsigned long, addr) | |
391 | + ), | |
392 | + TP_fast_assign(__entry->addr = addr), | |
393 | + TP_printk("addr %lx", __entry->addr) | |
394 | + ); | |
395 | + | |
396 | +TRACE_EVENT(xen_mmu_flush_tlb_others, | |
397 | + TP_PROTO(const struct cpumask *cpus, struct mm_struct *mm, | |
398 | + unsigned long addr), | |
399 | + TP_ARGS(cpus, mm, addr), | |
400 | + TP_STRUCT__entry( | |
401 | + __field(unsigned, ncpus) | |
402 | + __field(struct mm_struct *, mm) | |
403 | + __field(unsigned long, addr) | |
404 | + ), | |
405 | + TP_fast_assign(__entry->ncpus = cpumask_weight(cpus); | |
406 | + __entry->mm = mm; | |
407 | + __entry->addr = addr), | |
408 | + TP_printk("ncpus %d mm %p addr %lx", | |
409 | + __entry->ncpus, __entry->mm, __entry->addr) | |
410 | + ); | |
411 | + | |
412 | +TRACE_EVENT(xen_mmu_write_cr3, | |
413 | + TP_PROTO(bool kernel, unsigned long cr3), | |
414 | + TP_ARGS(kernel, cr3), | |
415 | + TP_STRUCT__entry( | |
416 | + __field(bool, kernel) | |
417 | + __field(unsigned long, cr3) | |
418 | + ), | |
419 | + TP_fast_assign(__entry->kernel = kernel; | |
420 | + __entry->cr3 = cr3), | |
421 | + TP_printk("%s cr3 %lx", | |
422 | + __entry->kernel ? "kernel" : "user", __entry->cr3) | |
423 | + ); | |
424 | + | |
425 | + | |
426 | +/* CPU */ | |
427 | +TRACE_EVENT(xen_cpu_write_ldt_entry, | |
428 | + TP_PROTO(struct desc_struct *dt, int entrynum, u64 desc), | |
429 | + TP_ARGS(dt, entrynum, desc), | |
430 | + TP_STRUCT__entry( | |
431 | + __field(struct desc_struct *, dt) | |
432 | + __field(int, entrynum) | |
433 | + __field(u64, desc) | |
434 | + ), | |
435 | + TP_fast_assign(__entry->dt = dt; | |
436 | + __entry->entrynum = entrynum; | |
437 | + __entry->desc = desc; | |
438 | + ), | |
439 | + TP_printk("dt %p entrynum %d entry %016llx", | |
440 | + __entry->dt, __entry->entrynum, | |
441 | + (unsigned long long)__entry->desc) | |
442 | + ); | |
443 | + | |
444 | +TRACE_EVENT(xen_cpu_write_idt_entry, | |
445 | + TP_PROTO(gate_desc *dt, int entrynum, const gate_desc *ent), | |
446 | + TP_ARGS(dt, entrynum, ent), | |
447 | + TP_STRUCT__entry( | |
448 | + __field(gate_desc *, dt) | |
449 | + __field(int, entrynum) | |
450 | + ), | |
451 | + TP_fast_assign(__entry->dt = dt; | |
452 | + __entry->entrynum = entrynum; | |
453 | + ), | |
454 | + TP_printk("dt %p entrynum %d", | |
455 | + __entry->dt, __entry->entrynum) | |
456 | + ); | |
457 | + | |
458 | +TRACE_EVENT(xen_cpu_load_idt, | |
459 | + TP_PROTO(const struct desc_ptr *desc), | |
460 | + TP_ARGS(desc), | |
461 | + TP_STRUCT__entry( | |
462 | + __field(unsigned long, addr) | |
463 | + ), | |
464 | + TP_fast_assign(__entry->addr = desc->address), | |
465 | + TP_printk("addr %lx", __entry->addr) | |
466 | + ); | |
467 | + | |
468 | +TRACE_EVENT(xen_cpu_write_gdt_entry, | |
469 | + TP_PROTO(struct desc_struct *dt, int entrynum, const void *desc, int type), | |
470 | + TP_ARGS(dt, entrynum, desc, type), | |
471 | + TP_STRUCT__entry( | |
472 | + __field(u64, desc) | |
473 | + __field(struct desc_struct *, dt) | |
474 | + __field(int, entrynum) | |
475 | + __field(int, type) | |
476 | + ), | |
477 | + TP_fast_assign(__entry->dt = dt; | |
478 | + __entry->entrynum = entrynum; | |
479 | + __entry->desc = *(u64 *)desc; | |
480 | + __entry->type = type; | |
481 | + ), | |
482 | + TP_printk("dt %p entrynum %d type %d desc %016llx", | |
483 | + __entry->dt, __entry->entrynum, __entry->type, | |
484 | + (unsigned long long)__entry->desc) | |
485 | + ); | |
486 | + | |
487 | +TRACE_EVENT(xen_cpu_set_ldt, | |
488 | + TP_PROTO(const void *addr, unsigned entries), | |
489 | + TP_ARGS(addr, entries), | |
490 | + TP_STRUCT__entry( | |
491 | + __field(const void *, addr) | |
492 | + __field(unsigned, entries) | |
493 | + ), | |
494 | + TP_fast_assign(__entry->addr = addr; | |
495 | + __entry->entries = entries), | |
496 | + TP_printk("addr %p entries %u", | |
497 | + __entry->addr, __entry->entries) | |
498 | + ); | |
499 | + | |
500 | + | |
501 | +#endif /* _TRACE_XEN_H */ | |
502 | + | |
503 | +/* This part must be outside protection */ | |
504 | +#include <trace/define_trace.h> |