mmu.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-07-14 JasonHu first version
  9. */
  10. #ifndef __MMU_H__
  11. #define __MMU_H__
  12. #include <stddef.h>
  13. #include <rtdef.h>
  14. #include <rtconfig.h>
  15. #undef PAGE_SIZE
  16. #define ADDRESS_WIDTH_BITS 32
  17. #define PHYSICAL_ADDRESS_WIDTH_BITS ADDRESS_WIDTH_BITS
  18. #define ARCH_ADDRESS_WIDTH_BITS ADDRESS_WIDTH_BITS
  19. #define __SIZE(bit) (1U << (bit))
  20. #define __MASK(bit) (__SIZE(bit) - 1UL)
  21. #define __UMASK(bit) (~(__MASK(bit)))
  22. #define __MASKVALUE(value,maskvalue) ((value) & (maskvalue))
  23. #define __UMASKVALUE(value,maskvalue) ((value) & (~(maskvalue)))
  24. #define __CHECKUPBOUND(value,bit_count) (!(((rt_size_t)(value)) & (~__MASK(bit_count))))
  25. #define __CHECKALIGN(value,start_bit) (!(((rt_size_t)(value)) & (__MASK(start_bit))))
  26. #define __PARTBIT(value,start_bit,length) (((value) >> (start_bit)) & __MASK(length))
  27. #define __ALIGNUP(value,bit) (((value) + __MASK(bit)) & __UMASK(bit))
  28. #define __ALIGNDOWN(value,bit) ((value) & __UMASK(bit))
  29. #define PAGE_OFFSET_SHIFT 0
  30. #define PAGE_OFFSET_BIT 12
  31. #define PAGE_SIZE __SIZE(PAGE_OFFSET_BIT)
  32. #define PAGE_OFFSET_MASK __MASK(PAGE_OFFSET_BIT)
  33. #define PAGE_ADDR_MASK __UMASK(PAGE_OFFSET_BIT)
  34. #define PTE_SHIFT (PAGE_OFFSET_SHIFT + PAGE_OFFSET_BIT)
  35. #define PTE_BIT 10
  36. #define PDE_SHIFT (PTE_SHIFT + PTE_BIT)
  37. #define PDE_BIT 10
  38. #define mmu_flush_tlb() \
  39. do \
  40. { \
  41. unsigned long tmpreg; \
  42. __asm__ __volatile__ ( \
  43. "movl %%cr3, %0 \n\t" \
  44. "movl %0, %%cr3 \n\t" \
  45. :"=r"(tmpreg) \
  46. : \
  47. :"memory" \
  48. ); \
  49. } \
  50. while(0)
  51. #define ARCH_PAGE_SIZE PAGE_SIZE
  52. #define ARCH_PAGE_MASK (ARCH_PAGE_SIZE - 1)
  53. #define ARCH_PAGE_SHIFT PAGE_OFFSET_BIT
  54. typedef struct
  55. {
  56. rt_size_t *vtable;
  57. rt_size_t vstart;
  58. rt_size_t vend;
  59. rt_size_t pv_off;
  60. }rt_mmu_info;
  61. typedef rt_size_t pde_t; /* page dir entry */
  62. typedef rt_size_t pte_t; /* page table entry */
  63. /* page offset */
  64. #define GET_PF_ID(addr) ((addr) >> PAGE_OFFSET_BIT)
  65. #define GET_PF_OFFSET(addr) __MASKVALUE(addr,PAGE_OFFSET_MASK)
  66. #define GET_L1(addr) __PARTBIT(addr,PDE_SHIFT,PDE_BIT)
  67. #define GET_L2(addr) __PARTBIT(addr,PTE_SHIFT,PTE_BIT)
  68. #define GET_PADDR(pte) ((pte) & PAGE_ADDR_MASK)
  69. #define GET_PATTR(pte) ((pte) & PAGE_OFFSET_MASK)
  70. #define PTE_PER_PAGE 1024
  71. #define PAGE_TABLE_PADDR 0X3F3000
  72. #define PAGE_TABLE_VADDR (KERNEL_VADDR_START + PAGE_TABLE_PADDR)
  73. #define MAKE_PTE(paddr, attr) (rt_size_t) (((rt_size_t)(paddr) & PAGE_ADDR_MASK) | ((attr) & PAGE_OFFSET_MASK))
  74. // page table entry (PTE) fields
  75. #define PTE_P 0x001 // Present
  76. #define PTE_R 0x000 // Read
  77. #define PTE_W 0x002 // Write
  78. #define PTE_X 0x000 // Execute
  79. #define PTE_U 0x004 // User
  80. #define PTE_PWT 0x008 // Write-through
  81. #define PTE_S 0x000 // System
  82. #define PTE_A 0x020 // Accessed
  83. #define PTE_D 0x040 // Dirty
  84. #define PAGE_ATTR_RWX (PTE_X | PTE_W | PTE_R)
  85. #define PAGE_ATTR_READONLY (PTE_R)
  86. #define PAGE_ATTR_READEXECUTE (PTE_X | PTE_R)
  87. #define PAGE_ATTR_USER (PTE_U)
  88. #define PAGE_ATTR_SYSTEM (PTE_S)
  89. #define KERNEL_PAGE_ATTR (PTE_P | PAGE_ATTR_RWX | PAGE_ATTR_SYSTEM)
  90. #define PTE_USED(pte) __MASKVALUE(pte,PTE_P)
  91. #define MMU_MAP_K_RO (PTE_S | PTE_R)
  92. #define MMU_MAP_K_RWCB (PTE_S | PTE_R | PTE_W)
  93. #define MMU_MAP_K_RW (PTE_S | PTE_R | PTE_W)
  94. #define MMU_MAP_K_DEVICE (PTE_S | PTE_R | PTE_W)
  95. #define MMU_MAP_U_RO (PTE_U | PTE_R)
  96. #define MMU_MAP_U_RWCB (PTE_U | PTE_R | PTE_W)
  97. #define MMU_MAP_U_RW (PTE_U | PTE_R | PTE_W)
  98. #define MMU_MAP_U_DEVICE (PTE_U | PTE_R | PTE_W)
  99. #define PAGE_ATTR_MASK PAGE_OFFSET_MASK
  100. void mmu_set_pagetable(rt_ubase_t addr);
  101. void mmu_enable_user_page_access();
  102. void mmu_disable_user_page_access();
  103. void mmu_enable();
  104. void *rt_hw_mmu_tbl_get();
  105. void rt_hw_mmu_switch(void *mmu_table);
  106. int rt_hw_mmu_map_init(rt_mmu_info *mmu_info,void *v_address,rt_size_t size,rt_size_t *vtable,rt_size_t pv_off);
  107. void rt_hw_mmu_kernel_map_init(rt_mmu_info *mmu_info,rt_size_t vaddr_start,rt_size_t size);
  108. #ifdef RT_USING_USERSPACE
  109. void *rt_hw_mmu_map(rt_mmu_info *mmu_info,void *v_addr,void *p_addr,rt_size_t size,rt_size_t attr);
  110. void *rt_hw_mmu_map_auto(rt_mmu_info *mmu_info,void *v_addr,rt_size_t size,rt_size_t attr);
  111. #else
  112. void *rt_hw_mmu_map(rt_mmu_info *mmu_info, void* p_addr, size_t size, size_t attr);
  113. #endif /* RT_USING_USERSPACE */
  114. void rt_hw_mmu_unmap(rt_mmu_info *mmu_info,void *v_addr,rt_size_t size);
  115. void *rt_hw_mmu_v2p(rt_mmu_info *mmu_info,void *v_addr);
  116. /* used in kernel mmaped area */
  117. #define rt_hw_phy2vir(p) ((rt_ubase_t)(p) + KERNEL_VADDR_START)
  118. #define rt_hw_vir2phy(v) ((rt_ubase_t)(v) - KERNEL_VADDR_START)
  119. #endif