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

12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 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__ */