sbi_scratch.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2019 Western Digital Corporation or its affiliates.
  5. *
  6. * Authors:
  7. * Anup Patel <anup.patel@wdc.com>
  8. */
  9. #include <sbi/riscv_locks.h>
  10. #include <sbi/sbi_hart.h>
  11. #include <sbi/sbi_hartmask.h>
  12. #include <sbi/sbi_platform.h>
  13. #include <sbi/sbi_scratch.h>
  14. #include <sbi/sbi_string.h>
  15. u32 last_hartid_having_scratch = SBI_HARTMASK_MAX_BITS - 1;
  16. struct sbi_scratch *hartid_to_scratch_table[SBI_HARTMASK_MAX_BITS] = { 0 };
  17. static spinlock_t extra_lock = SPIN_LOCK_INITIALIZER;
  18. static unsigned long extra_offset = SBI_SCRATCH_EXTRA_SPACE_OFFSET;
  19. typedef struct sbi_scratch *(*hartid2scratch)(ulong hartid, ulong hartindex);
  20. int sbi_scratch_init(struct sbi_scratch *scratch)
  21. {
  22. u32 i;
  23. const struct sbi_platform *plat = sbi_platform_ptr(scratch);
  24. for (i = 0; i < SBI_HARTMASK_MAX_BITS; i++) {
  25. if (sbi_platform_hart_invalid(plat, i))
  26. continue;
  27. hartid_to_scratch_table[i] =
  28. ((hartid2scratch)scratch->hartid_to_scratch)(i,
  29. sbi_platform_hart_index(plat, i));
  30. if (hartid_to_scratch_table[i])
  31. last_hartid_having_scratch = i;
  32. }
  33. return 0;
  34. }
  35. unsigned long sbi_scratch_alloc_offset(unsigned long size, const char *owner)
  36. {
  37. u32 i;
  38. void *ptr;
  39. unsigned long ret = 0;
  40. struct sbi_scratch *rscratch;
  41. /*
  42. * We have a simple brain-dead allocator which never expects
  43. * anything to be free-ed hence it keeps incrementing the
  44. * next allocation offset until it runs-out of space.
  45. *
  46. * In future, we will have more sophisticated allocator which
  47. * will allow us to re-claim free-ed space.
  48. */
  49. if (!size)
  50. return 0;
  51. if (size & (__SIZEOF_POINTER__ - 1))
  52. size = (size & ~(__SIZEOF_POINTER__ - 1)) + __SIZEOF_POINTER__;
  53. spin_lock(&extra_lock);
  54. if (SBI_SCRATCH_SIZE < (extra_offset + size))
  55. goto done;
  56. ret = extra_offset;
  57. extra_offset += size;
  58. done:
  59. spin_unlock(&extra_lock);
  60. if (ret) {
  61. for (i = 0; i <= sbi_scratch_last_hartid(); i++) {
  62. rscratch = sbi_hartid_to_scratch(i);
  63. if (!rscratch)
  64. continue;
  65. ptr = sbi_scratch_offset_ptr(rscratch, ret);
  66. sbi_memset(ptr, 0, size);
  67. }
  68. }
  69. return ret;
  70. }
  71. void sbi_scratch_free_offset(unsigned long offset)
  72. {
  73. if ((offset < SBI_SCRATCH_EXTRA_SPACE_OFFSET) ||
  74. (SBI_SCRATCH_SIZE <= offset))
  75. return;
  76. /*
  77. * We don't actually free-up because it's a simple
  78. * brain-dead allocator.
  79. */
  80. }