asid.c 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024-07-12 RT-Thread first version.
  9. */
  10. #define DBG_TAG "hw.asid"
  11. #define DBG_LVL DBG_INFO
  12. #include <rtdbg.h>
  13. #include <rtthread.h>
  14. #include <board.h>
  15. #include <cache.h>
  16. #include <mm_aspace.h>
  17. #include <mm_page.h>
  18. #include <mmu.h>
  19. #include <riscv_mmu.h>
  20. #include <tlb.h>
  21. static rt_uint8_t ASID_BITS = 0;
  22. static rt_uint32_t next_asid;
  23. static rt_uint64_t global_asid_generation;
  24. #define ASID_MASK ((1 << ASID_BITS) - 1)
  25. #define ASID_FIRST_GENERATION (1 << ASID_BITS)
  26. #define MAX_ASID ASID_FIRST_GENERATION
  27. void rt_hw_asid_init(void)
  28. {
  29. rt_uint64_t satp_reg = read_csr(satp);
  30. satp_reg |= (((rt_uint64_t)0xffff) << PPN_BITS);
  31. write_csr(satp, satp_reg);
  32. __asm__ volatile("sfence.vma x0, x0");
  33. unsigned short valid_asid_bit = ((read_csr(satp) >> PPN_BITS) & 0xffff);
  34. // The maximal value of ASIDLEN, is 9 for Sv32 or 16 for Sv39, Sv48, and Sv57
  35. for (unsigned i = 0; i < 16; i++)
  36. {
  37. if (!(valid_asid_bit & 0x1))
  38. {
  39. break;
  40. }
  41. valid_asid_bit >>= 1;
  42. ASID_BITS++;
  43. }
  44. global_asid_generation = ASID_FIRST_GENERATION;
  45. next_asid = 1;
  46. }
  47. static rt_uint64_t _asid_acquire(rt_aspace_t aspace)
  48. {
  49. if ((aspace->asid ^ global_asid_generation) >> ASID_BITS) // not same generation
  50. {
  51. if (next_asid != MAX_ASID)
  52. {
  53. aspace->asid = global_asid_generation | next_asid;
  54. next_asid++;
  55. }
  56. else
  57. {
  58. // scroll to next generation
  59. global_asid_generation += ASID_FIRST_GENERATION;
  60. next_asid = 1;
  61. rt_hw_tlb_invalidate_all_local();
  62. aspace->asid = global_asid_generation | next_asid;
  63. next_asid++;
  64. }
  65. }
  66. return aspace->asid & ASID_MASK;
  67. }
  68. void rt_hw_asid_switch_pgtbl(struct rt_aspace *aspace, rt_ubase_t pgtbl)
  69. {
  70. rt_uint64_t asid = _asid_acquire(aspace);
  71. write_csr(satp, (((size_t)SATP_MODE) << SATP_MODE_OFFSET) |
  72. (asid << PPN_BITS) |
  73. ((rt_ubase_t)pgtbl >> PAGE_OFFSET_BIT));
  74. asm volatile("sfence.vma x0,%0"::"r"(asid):"memory");
  75. }