Commit c61264f98c1a974ee6f545f61a4ab33b141d6bda

Authored by Linus Torvalds

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 }
... ... @@ -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>