mpmm.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <stdbool.h>
  7. #include <common/debug.h>
  8. #include <lib/mpmm/mpmm.h>
  9. #include <plat/common/platform.h>
  10. #if ENABLE_MPMM_FCONF
  11. # include <lib/fconf/fconf.h>
  12. # include <lib/fconf/fconf_mpmm_getter.h>
  13. #endif
  14. static uint64_t read_cpuppmcr_el3_mpmmpinctl(void)
  15. {
  16. return (read_cpuppmcr_el3() >> CPUPPMCR_EL3_MPMMPINCTL_SHIFT) &
  17. CPUPPMCR_EL3_MPMMPINCTL_MASK;
  18. }
  19. static void write_cpumpmmcr_el3_mpmm_en(uint64_t mpmm_en)
  20. {
  21. uint64_t value = read_cpumpmmcr_el3();
  22. value &= ~(CPUMPMMCR_EL3_MPMM_EN_MASK << CPUMPMMCR_EL3_MPMM_EN_SHIFT);
  23. value |= (mpmm_en & CPUMPMMCR_EL3_MPMM_EN_MASK) <<
  24. CPUMPMMCR_EL3_MPMM_EN_SHIFT;
  25. write_cpumpmmcr_el3(value);
  26. }
  27. static bool mpmm_supported(void)
  28. {
  29. bool supported = false;
  30. const struct mpmm_topology *topology;
  31. #if ENABLE_MPMM_FCONF
  32. topology = FCONF_GET_PROPERTY(mpmm, config, topology);
  33. #else
  34. topology = plat_mpmm_topology();
  35. #endif /* ENABLE_MPMM_FCONF */
  36. /*
  37. * For the current core firstly try to find out if the platform
  38. * configuration has claimed support for MPMM, then make sure that MPMM
  39. * is controllable through the system registers.
  40. */
  41. if (topology != NULL) {
  42. unsigned int core_pos = plat_my_core_pos();
  43. supported = topology->cores[core_pos].supported &&
  44. (read_cpuppmcr_el3_mpmmpinctl() == 0U);
  45. } else {
  46. ERROR("MPMM: failed to generate MPMM topology\n");
  47. }
  48. return supported;
  49. }
  50. /* Defaults to false */
  51. static bool mpmm_disable_for_errata;
  52. void mpmm_enable(void)
  53. {
  54. if (mpmm_supported()) {
  55. if (mpmm_disable_for_errata) {
  56. WARN("MPMM: disabled by errata workaround\n");
  57. return;
  58. }
  59. write_cpumpmmcr_el3_mpmm_en(1U);
  60. }
  61. }
  62. /*
  63. * This function is called from assembly code very early in BL31 so it must be
  64. * small and simple.
  65. */
  66. void mpmm_errata_disable(void)
  67. {
  68. mpmm_disable_for_errata = true;
  69. }