《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
4.9 KiB

  1. #ifndef __KERN_MM_PMM_H__
  2. #define __KERN_MM_PMM_H__
  3. #include <defs.h>
  4. #include <mmu.h>
  5. #include <memlayout.h>
  6. #include <atomic.h>
  7. #include <assert.h>
  8. // pmm_manager is a physical memory management class. A special pmm manager - XXX_pmm_manager
  9. // only needs to implement the methods in pmm_manager class, then XXX_pmm_manager can be used
  10. // by ucore to manage the total physical memory space.
  11. struct pmm_manager {
  12. const char *name; // XXX_pmm_manager's name
  13. void (*init)(void); // initialize internal description&management data structure
  14. // (free block list, number of free block) of XXX_pmm_manager
  15. void (*init_memmap)(struct Page *base, size_t n); // setup description&management data structcure according to
  16. // the initial free physical memory space
  17. struct Page *(*alloc_pages)(size_t n); // allocate >=n pages, depend on the allocation algorithm
  18. void (*free_pages)(struct Page *base, size_t n); // free >=n pages with "base" addr of Page descriptor structures(memlayout.h)
  19. size_t (*nr_free_pages)(void); // return the number of free pages
  20. void (*check)(void); // check the correctness of XXX_pmm_manager
  21. };
  22. extern const struct pmm_manager *pmm_manager;
  23. extern pde_t *boot_pgdir;
  24. extern uintptr_t boot_cr3;
  25. void pmm_init(void);
  26. struct Page *alloc_pages(size_t n);
  27. void free_pages(struct Page *base, size_t n);
  28. size_t nr_free_pages(void);
  29. #define alloc_page() alloc_pages(1)
  30. #define free_page(page) free_pages(page, 1)
  31. pte_t *get_pte(pde_t *pgdir, uintptr_t la, bool create);
  32. struct Page *get_page(pde_t *pgdir, uintptr_t la, pte_t **ptep_store);
  33. void page_remove(pde_t *pgdir, uintptr_t la);
  34. int page_insert(pde_t *pgdir, struct Page *page, uintptr_t la, uint32_t perm);
  35. void load_esp0(uintptr_t esp0);
  36. void tlb_invalidate(pde_t *pgdir, uintptr_t la);
  37. struct Page *pgdir_alloc_page(pde_t *pgdir, uintptr_t la, uint32_t perm);
  38. void unmap_range(pde_t *pgdir, uintptr_t start, uintptr_t end);
  39. void exit_range(pde_t *pgdir, uintptr_t start, uintptr_t end);
  40. int copy_range(pde_t *to, pde_t *from, uintptr_t start, uintptr_t end, bool share);
  41. void print_pgdir(void);
  42. /* *
  43. * PADDR - takes a kernel virtual address (an address that points above KERNBASE),
  44. * where the machine's maximum 256MB of physical memory is mapped and returns the
  45. * corresponding physical address. It panics if you pass it a non-kernel virtual address.
  46. * */
  47. #define PADDR(kva) ({ \
  48. uintptr_t __m_kva = (uintptr_t)(kva); \
  49. if (__m_kva < KERNBASE) { \
  50. panic("PADDR called with invalid kva %08lx", __m_kva); \
  51. } \
  52. __m_kva - KERNBASE; \
  53. })
  54. /* *
  55. * KADDR - takes a physical address and returns the corresponding kernel virtual
  56. * address. It panics if you pass an invalid physical address.
  57. * */
  58. #define KADDR(pa) ({ \
  59. uintptr_t __m_pa = (pa); \
  60. size_t __m_ppn = PPN(__m_pa); \
  61. if (__m_ppn >= npage) { \
  62. panic("KADDR called with invalid pa %08lx", __m_pa); \
  63. } \
  64. (void *) (__m_pa + KERNBASE); \
  65. })
  66. extern struct Page *pages;
  67. extern size_t npage;
  68. static inline ppn_t
  69. page2ppn(struct Page *page) {
  70. return page - pages;
  71. }
  72. static inline uintptr_t
  73. page2pa(struct Page *page) {
  74. return page2ppn(page) << PGSHIFT;
  75. }
  76. static inline struct Page *
  77. pa2page(uintptr_t pa) {
  78. if (PPN(pa) >= npage) {
  79. panic("pa2page called with invalid pa");
  80. }
  81. return &pages[PPN(pa)];
  82. }
  83. static inline void *
  84. page2kva(struct Page *page) {
  85. return KADDR(page2pa(page));
  86. }
  87. static inline struct Page *
  88. kva2page(void *kva) {
  89. return pa2page(PADDR(kva));
  90. }
  91. static inline struct Page *
  92. pte2page(pte_t pte) {
  93. if (!(pte & PTE_P)) {
  94. panic("pte2page called with invalid pte");
  95. }
  96. return pa2page(PTE_ADDR(pte));
  97. }
  98. static inline struct Page *
  99. pde2page(pde_t pde) {
  100. return pa2page(PDE_ADDR(pde));
  101. }
  102. static inline int
  103. page_ref(struct Page *page) {
  104. return page->ref;
  105. }
  106. static inline void
  107. set_page_ref(struct Page *page, int val) {
  108. page->ref = val;
  109. }
  110. static inline int
  111. page_ref_inc(struct Page *page) {
  112. page->ref += 1;
  113. return page->ref;
  114. }
  115. static inline int
  116. page_ref_dec(struct Page *page) {
  117. page->ref -= 1;
  118. return page->ref;
  119. }
  120. extern char bootstack[], bootstacktop[];
  121. #endif /* !__KERN_MM_PMM_H__ */