sbi_ecall_pmu.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2021 Western Digital Corporation or its affiliates.
  5. *
  6. * Authors:
  7. * Atish Patra <atish.patra@wdc.com>
  8. */
  9. #include <sbi/sbi_ecall.h>
  10. #include <sbi/sbi_ecall_interface.h>
  11. #include <sbi/sbi_error.h>
  12. #include <sbi/sbi_hart.h>
  13. #include <sbi/sbi_trap.h>
  14. #include <sbi/sbi_version.h>
  15. #include <sbi/sbi_pmu.h>
  16. #include <sbi/sbi_scratch.h>
  17. #include <sbi/riscv_asm.h>
  18. static int sbi_ecall_pmu_handler(unsigned long extid, unsigned long funcid,
  19. const struct sbi_trap_regs *regs,
  20. unsigned long *out_val,
  21. struct sbi_trap_info *out_trap)
  22. {
  23. int ret = 0;
  24. uint64_t temp;
  25. switch (funcid) {
  26. case SBI_EXT_PMU_NUM_COUNTERS:
  27. ret = sbi_pmu_num_ctr();
  28. if (ret >= 0) {
  29. *out_val = ret;
  30. ret = 0;
  31. }
  32. break;
  33. case SBI_EXT_PMU_COUNTER_GET_INFO:
  34. ret = sbi_pmu_ctr_get_info(regs->a0, out_val);
  35. break;
  36. case SBI_EXT_PMU_COUNTER_CFG_MATCH:
  37. #if __riscv_xlen == 32
  38. temp = ((uint64_t)regs->a5 << 32) | regs->a4;
  39. #else
  40. temp = regs->a4;
  41. #endif
  42. ret = sbi_pmu_ctr_cfg_match(regs->a0, regs->a1, regs->a2,
  43. regs->a3, temp);
  44. if (ret >= 0) {
  45. *out_val = ret;
  46. ret = 0;
  47. }
  48. break;
  49. case SBI_EXT_PMU_COUNTER_FW_READ:
  50. ret = sbi_pmu_ctr_fw_read(regs->a0, &temp);
  51. *out_val = temp;
  52. break;
  53. case SBI_EXT_PMU_COUNTER_START:
  54. #if __riscv_xlen == 32
  55. temp = ((uint64_t)regs->a4 << 32) | regs->a3;
  56. #else
  57. temp = regs->a3;
  58. #endif
  59. ret = sbi_pmu_ctr_start(regs->a0, regs->a1, regs->a2, temp);
  60. break;
  61. case SBI_EXT_PMU_COUNTER_STOP:
  62. ret = sbi_pmu_ctr_stop(regs->a0, regs->a1, regs->a2);
  63. break;
  64. default:
  65. ret = SBI_ENOTSUPP;
  66. };
  67. return ret;
  68. }
  69. static int sbi_ecall_pmu_probe(unsigned long extid, unsigned long *out_val)
  70. {
  71. /* PMU extension is always enabled */
  72. *out_val = 1;
  73. return 0;
  74. }
  75. struct sbi_ecall_extension ecall_pmu = {
  76. .extid_start = SBI_EXT_PMU,
  77. .extid_end = SBI_EXT_PMU,
  78. .handle = sbi_ecall_pmu_handler,
  79. .probe = sbi_ecall_pmu_probe,
  80. };