《操作系统》的实验代码。

146 lines
4.7 KiB

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