| 1 |
|
| 2 | #ifndef __ASM_MEMORY_MODEL_H
|
| 3 | #define __ASM_MEMORY_MODEL_H
|
| 4 |
|
| 5 | #include <linux/pfn.h>
|
| 6 |
|
| 7 | #ifndef __ASSEMBLER__
|
| 8 |
|
| 9 | |
| 10 | * supports 3 memory models.
|
| 11 |
|
| 12 | #if defined(CONFIG_FLATMEM)
|
| 13 |
|
| 14 | #ifndef ARCH_PFN_OFFSET
|
| 15 | #define ARCH_PFN_OFFSET (0UL)
|
| 16 | #endif
|
| 17 |
|
| 18 | #define __pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET))
|
| 19 | #define __page_to_pfn(page) ((unsigned long)((page) - mem_map) + \
|
| 20 | ARCH_PFN_OFFSET)
|
| 21 |
|
| 22 |
|
| 23 | extern unsigned long max_mapnr;
|
| 24 |
|
| 25 | #ifndef pfn_valid
|
| 26 | static inline int pfn_valid(unsigned long pfn)
|
| 27 | {
|
| 28 | unsigned long pfn_offset = ARCH_PFN_OFFSET;
|
| 29 |
|
| 30 | return pfn >= pfn_offset && (pfn - pfn_offset) < max_mapnr;
|
| 31 | }
|
| 32 | #define pfn_valid pfn_valid
|
| 33 |
|
| 34 | #ifndef for_each_valid_pfn
|
| 35 | #define for_each_valid_pfn(pfn, start_pfn, end_pfn) \
|
| 36 | for ((pfn) = max_t(unsigned long, (start_pfn), ARCH_PFN_OFFSET); \
|
| 37 | (pfn) < min_t(unsigned long, (end_pfn), \
|
| 38 | ARCH_PFN_OFFSET + max_mapnr); \
|
| 39 | (pfn)++)
|
| 40 | #endif
|
| 41 | #endif
|
| 42 |
|
| 43 | #elif defined(CONFIG_SPARSEMEM_VMEMMAP)
|
| 44 |
|
| 45 |
|
| 46 | #define __pfn_to_page(pfn) (vmemmap + (pfn))
|
| 47 | #define __page_to_pfn(page) (unsigned long)((page) - vmemmap)
|
| 48 |
|
| 49 | #elif defined(CONFIG_SPARSEMEM)
|
| 50 | |
| 51 | * Note: section's mem_map is encoded to reflect its start_pfn.
|
| 52 | * section[i].section_mem_map == mem_map's address - start_pfn;
|
| 53 |
|
| 54 | #define __page_to_pfn(pg) \
|
| 55 | ({ const struct page *__pg = (pg); \
|
| 56 | int __sec = memdesc_section(&__pg->flags); \
|
| 57 | (unsigned long)(__pg - __section_mem_map_addr(__nr_to_section(__sec))); \
|
| 58 | })
|
| 59 |
|
| 60 | #define __pfn_to_page(pfn) \
|
| 61 | ({ unsigned long __pfn = (pfn); \
|
| 62 | struct mem_section *__sec = __pfn_to_section(__pfn); \
|
| 63 | __section_mem_map_addr(__sec) + __pfn; \
|
| 64 | })
|
| 65 | #endif
|
| 66 |
|
| 67 | |
| 68 | * Convert a physical address to a Page Frame Number and back
|
| 69 |
|
| 70 | #define __phys_to_pfn(paddr) PHYS_PFN(paddr)
|
| 71 | #define __pfn_to_phys(pfn) PFN_PHYS(pfn)
|
| 72 |
|
| 73 | #define page_to_pfn __page_to_pfn
|
| 74 | #define pfn_to_page __pfn_to_page
|
| 75 |
|
| 76 | #ifdef CONFIG_DEBUG_VIRTUAL
|
| 77 | #define page_to_phys(page) \
|
| 78 | ({ \
|
| 79 | unsigned long __pfn = page_to_pfn(page); \
|
| 80 | \
|
| 81 | WARN_ON_ONCE(!pfn_valid(__pfn)); \
|
| 82 | PFN_PHYS(__pfn); \
|
| 83 | })
|
| 84 | #else
|
| 85 | #define page_to_phys(page) PFN_PHYS(page_to_pfn(page))
|
| 86 | #endif
|
| 87 | #define phys_to_page(phys) pfn_to_page(PHYS_PFN(phys))
|
| 88 |
|
| 89 | #endif
|
| 90 |
|
| 91 | #endif
|