《操作系统》的实验代码。
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.

143 lines
4.6 KiB

10 years ago
  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. void print_pgdir(void);
  38. /* *
  39. * PADDR - takes a kernel virtual address (an address that points above KERNBASE),
  40. * where the machine's maximum 256MB of physical memory is mapped and returns the
  41. * corresponding physical address. It panics if you pass it a non-kernel virtual address.
  42. * */
  43. #define PADDR(kva) ({ \
  44. uintptr_t __m_kva = (uintptr_t)(kva); \
  45. if (__m_kva < KERNBASE) { \
  46. panic("PADDR called with invalid kva %08lx", __m_kva); \
  47. } \
  48. __m_kva - KERNBASE; \
  49. })
  50. /* *
  51. * KADDR - takes a physical address and returns the corresponding kernel virtual
  52. * address. It panics if you pass an invalid physical address.
  53. * */
  54. #define KADDR(pa) ({ \
  55. uintptr_t __m_pa = (pa); \
  56. size_t __m_ppn = PPN(__m_pa); \
  57. if (__m_ppn >= npage) { \
  58. panic("KADDR called with invalid pa %08lx", __m_pa); \
  59. } \
  60. (void *) (__m_pa + KERNBASE); \
  61. })
  62. extern struct Page *pages;
  63. extern size_t npage;
  64. static inline ppn_t
  65. page2ppn(struct Page *page) {
  66. return page - pages;
  67. }
  68. static inline uintptr_t
  69. page2pa(struct Page *page) {
  70. return page2ppn(page) << PGSHIFT;
  71. }
  72. static inline struct Page *
  73. pa2page(uintptr_t pa) {
  74. if (PPN(pa) >= npage) {
  75. panic("pa2page called with invalid pa");
  76. }
  77. return &pages[PPN(pa)];
  78. }
  79. static inline void *
  80. page2kva(struct Page *page) {
  81. return KADDR(page2pa(page));
  82. }
  83. static inline struct Page *
  84. kva2page(void *kva) {
  85. return pa2page(PADDR(kva));
  86. }
  87. static inline struct Page *
  88. pte2page(pte_t pte) {
  89. if (!(pte & PTE_P)) {
  90. panic("pte2page called with invalid pte");
  91. }
  92. return pa2page(PTE_ADDR(pte));
  93. }
  94. static inline struct Page *
  95. pde2page(pde_t pde) {
  96. return pa2page(PDE_ADDR(pde));
  97. }
  98. static inline int
  99. page_ref(struct Page *page) {
  100. return page->ref;
  101. }
  102. static inline void
  103. set_page_ref(struct Page *page, int val) {
  104. page->ref = val;
  105. }
  106. static inline int
  107. page_ref_inc(struct Page *page) {
  108. page->ref += 1;
  109. return page->ref;
  110. }
  111. static inline int
  112. page_ref_dec(struct Page *page) {
  113. page->ref -= 1;
  114. return page->ref;
  115. }
  116. extern char bootstack[], bootstacktop[];
  117. #endif /* !__KERN_MM_PMM_H__ */