op_model_fsl_booke.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * oprofile/op_model_e500.c
  3. *
  4. * Freescale Book-E oprofile support, based on ppc64 oprofile support
  5. * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
  6. *
  7. * Copyright (c) 2004 Freescale Semiconductor, Inc
  8. *
  9. * Author: Andy Fleming
  10. * Maintainer: Kumar Gala <galak@kernel.crashing.org>
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License
  14. * as published by the Free Software Foundation; either version
  15. * 2 of the License, or (at your option) any later version.
  16. */
  17. #include <linux/oprofile.h>
  18. #include <linux/init.h>
  19. #include <linux/smp.h>
  20. #include <asm/ptrace.h>
  21. #include <asm/system.h>
  22. #include <asm/processor.h>
  23. #include <asm/cputable.h>
  24. #include <asm/reg_booke.h>
  25. #include <asm/page.h>
  26. #include <asm/pmc.h>
  27. #include <asm/oprofile_impl.h>
  28. static unsigned long reset_value[OP_MAX_COUNTER];
  29. static int num_counters;
  30. static int oprofile_running;
  31. static inline unsigned int ctr_read(unsigned int i)
  32. {
  33. switch(i) {
  34. case 0:
  35. return mfpmr(PMRN_PMC0);
  36. case 1:
  37. return mfpmr(PMRN_PMC1);
  38. case 2:
  39. return mfpmr(PMRN_PMC2);
  40. case 3:
  41. return mfpmr(PMRN_PMC3);
  42. default:
  43. return 0;
  44. }
  45. }
  46. static inline void ctr_write(unsigned int i, unsigned int val)
  47. {
  48. switch(i) {
  49. case 0:
  50. mtpmr(PMRN_PMC0, val);
  51. break;
  52. case 1:
  53. mtpmr(PMRN_PMC1, val);
  54. break;
  55. case 2:
  56. mtpmr(PMRN_PMC2, val);
  57. break;
  58. case 3:
  59. mtpmr(PMRN_PMC3, val);
  60. break;
  61. default:
  62. break;
  63. }
  64. }
  65. static void fsl_booke_reg_setup(struct op_counter_config *ctr,
  66. struct op_system_config *sys,
  67. int num_ctrs)
  68. {
  69. int i;
  70. num_counters = num_ctrs;
  71. /* freeze all counters */
  72. pmc_stop_ctrs();
  73. /* Our counters count up, and "count" refers to
  74. * how much before the next interrupt, and we interrupt
  75. * on overflow. So we calculate the starting value
  76. * which will give us "count" until overflow.
  77. * Then we set the events on the enabled counters */
  78. for (i = 0; i < num_counters; ++i) {
  79. reset_value[i] = 0x80000000UL - ctr[i].count;
  80. init_pmc_stop(i);
  81. set_pmc_event(i, ctr[i].event);
  82. set_pmc_user_kernel(i, ctr[i].user, ctr[i].kernel);
  83. }
  84. }
  85. static void fsl_booke_start(struct op_counter_config *ctr)
  86. {
  87. int i;
  88. mtmsr(mfmsr() | MSR_PMM);
  89. for (i = 0; i < num_counters; ++i) {
  90. if (ctr[i].enabled) {
  91. ctr_write(i, reset_value[i]);
  92. /* Set Each enabled counterd to only
  93. * count when the Mark bit is not set */
  94. set_pmc_marked(i, 1, 0);
  95. pmc_start_ctr(i, 1);
  96. } else {
  97. ctr_write(i, 0);
  98. /* Set the ctr to be stopped */
  99. pmc_start_ctr(i, 0);
  100. }
  101. }
  102. /* Clear the freeze bit, and enable the interrupt.
  103. * The counters won't actually start until the rfi clears
  104. * the PMM bit */
  105. pmc_start_ctrs(1);
  106. oprofile_running = 1;
  107. pr_debug("start on cpu %d, pmgc0 %x\n", smp_processor_id(),
  108. mfpmr(PMRN_PMGC0));
  109. }
  110. static void fsl_booke_stop(void)
  111. {
  112. /* freeze counters */
  113. pmc_stop_ctrs();
  114. oprofile_running = 0;
  115. pr_debug("stop on cpu %d, pmgc0 %x\n", smp_processor_id(),
  116. mfpmr(PMRN_PMGC0));
  117. mb();
  118. }
  119. static void fsl_booke_handle_interrupt(struct pt_regs *regs,
  120. struct op_counter_config *ctr)
  121. {
  122. unsigned long pc;
  123. int is_kernel;
  124. int val;
  125. int i;
  126. /* set the PMM bit (see comment below) */
  127. mtmsr(mfmsr() | MSR_PMM);
  128. pc = regs->nip;
  129. is_kernel = is_kernel_addr(pc);
  130. for (i = 0; i < num_counters; ++i) {
  131. val = ctr_read(i);
  132. if (val < 0) {
  133. if (oprofile_running && ctr[i].enabled) {
  134. oprofile_add_ext_sample(pc, regs, i, is_kernel);
  135. ctr_write(i, reset_value[i]);
  136. } else {
  137. ctr_write(i, 0);
  138. }
  139. }
  140. }
  141. /* The freeze bit was set by the interrupt. */
  142. /* Clear the freeze bit, and reenable the interrupt.
  143. * The counters won't actually start until the rfi clears
  144. * the PMM bit */
  145. pmc_start_ctrs(1);
  146. }
  147. struct op_powerpc_model op_model_fsl_booke = {
  148. .reg_setup = fsl_booke_reg_setup,
  149. .start = fsl_booke_start,
  150. .stop = fsl_booke_stop,
  151. .handle_interrupt = fsl_booke_handle_interrupt,
  152. };