init.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
  4. */
  5. #include <linux/init.h>
  6. #include <linux/export.h>
  7. #include <linux/signal.h>
  8. #include <linux/sched.h>
  9. #include <linux/smp.h>
  10. #include <linux/kernel.h>
  11. #include <linux/errno.h>
  12. #include <linux/string.h>
  13. #include <linux/types.h>
  14. #include <linux/pagemap.h>
  15. #include <linux/memblock.h>
  16. #include <linux/memremap.h>
  17. #include <linux/mm.h>
  18. #include <linux/mman.h>
  19. #include <linux/highmem.h>
  20. #include <linux/swap.h>
  21. #include <linux/proc_fs.h>
  22. #include <linux/pfn.h>
  23. #include <linux/hardirq.h>
  24. #include <linux/gfp.h>
  25. #include <linux/hugetlb.h>
  26. #include <linux/mmzone.h>
  27. #include <linux/execmem.h>
  28. #include <asm/asm-offsets.h>
  29. #include <asm/bootinfo.h>
  30. #include <asm/cpu.h>
  31. #include <asm/dma.h>
  32. #include <asm/mmu_context.h>
  33. #include <asm/sections.h>
  34. #include <asm/pgtable.h>
  35. #include <asm/pgalloc.h>
  36. #include <asm/tlb.h>
  37. unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] __page_aligned_bss;
  38. EXPORT_SYMBOL(empty_zero_page);
  39. void copy_user_highpage(struct page *to, struct page *from,
  40. unsigned long vaddr, struct vm_area_struct *vma)
  41. {
  42. void *vfrom, *vto;
  43. vfrom = kmap_local_page(from);
  44. vto = kmap_local_page(to);
  45. copy_page(vto, vfrom);
  46. kunmap_local(vfrom);
  47. kunmap_local(vto);
  48. /* Make sure this page is cleared on other CPU's too before using it */
  49. smp_wmb();
  50. }
  51. int __ref page_is_ram(unsigned long pfn)
  52. {
  53. unsigned long addr = PFN_PHYS(pfn);
  54. return memblock_is_memory(addr) && !memblock_is_reserved(addr);
  55. }
  56. void __init arch_zone_limits_init(unsigned long *max_zone_pfns)
  57. {
  58. #ifdef CONFIG_ZONE_DMA32
  59. max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
  60. #endif
  61. max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
  62. }
  63. void __ref free_initmem(void)
  64. {
  65. free_initmem_default(POISON_FREE_INITMEM);
  66. }
  67. #ifdef CONFIG_MEMORY_HOTPLUG
  68. int arch_add_memory(int nid, u64 start, u64 size, struct mhp_params *params)
  69. {
  70. unsigned long start_pfn = start >> PAGE_SHIFT;
  71. unsigned long nr_pages = size >> PAGE_SHIFT;
  72. int ret;
  73. ret = __add_pages(nid, start_pfn, nr_pages, params);
  74. if (ret)
  75. pr_warn("%s: Problem encountered in __add_pages() as ret=%d\n",
  76. __func__, ret);
  77. return ret;
  78. }
  79. void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
  80. {
  81. unsigned long start_pfn = start >> PAGE_SHIFT;
  82. unsigned long nr_pages = size >> PAGE_SHIFT;
  83. struct page *page = pfn_to_page(start_pfn);
  84. /* With altmap the first mapped page is offset from @start */
  85. if (altmap)
  86. page += vmem_altmap_offset(altmap);
  87. __remove_pages(start_pfn, nr_pages, altmap);
  88. }
  89. #endif
  90. #ifdef CONFIG_SPARSEMEM_VMEMMAP
  91. void __meminit vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
  92. unsigned long addr, unsigned long next)
  93. {
  94. pmd_t entry;
  95. entry = pfn_pmd(virt_to_pfn(p), PAGE_KERNEL);
  96. pmd_val(entry) |= _PAGE_HUGE | _PAGE_HGLOBAL;
  97. set_pmd_at(&init_mm, addr, pmd, entry);
  98. }
  99. int __meminit vmemmap_check_pmd(pmd_t *pmd, int node,
  100. unsigned long addr, unsigned long next)
  101. {
  102. int huge = pmd_val(pmdp_get(pmd)) & _PAGE_HUGE;
  103. if (huge)
  104. vmemmap_verify((pte_t *)pmd, node, addr, next);
  105. return huge;
  106. }
  107. int __meminit vmemmap_populate(unsigned long start, unsigned long end,
  108. int node, struct vmem_altmap *altmap)
  109. {
  110. #if CONFIG_PGTABLE_LEVELS == 2
  111. return vmemmap_populate_basepages(start, end, node, NULL);
  112. #else
  113. return vmemmap_populate_hugepages(start, end, node, NULL);
  114. #endif
  115. }
  116. #ifdef CONFIG_MEMORY_HOTPLUG
  117. void vmemmap_free(unsigned long start, unsigned long end, struct vmem_altmap *altmap)
  118. {
  119. }
  120. #endif
  121. #endif
  122. pte_t * __init populate_kernel_pte(unsigned long addr)
  123. {
  124. pgd_t *pgd = pgd_offset_k(addr);
  125. p4d_t *p4d = p4d_offset(pgd, addr);
  126. pud_t *pud;
  127. pmd_t *pmd;
  128. if (p4d_none(p4dp_get(p4d))) {
  129. pud = memblock_alloc_or_panic(PAGE_SIZE, PAGE_SIZE);
  130. p4d_populate(&init_mm, p4d, pud);
  131. #ifndef __PAGETABLE_PUD_FOLDED
  132. pud_init(pud);
  133. #endif
  134. }
  135. pud = pud_offset(p4d, addr);
  136. if (pud_none(pudp_get(pud))) {
  137. pmd = memblock_alloc_or_panic(PAGE_SIZE, PAGE_SIZE);
  138. pud_populate(&init_mm, pud, pmd);
  139. #ifndef __PAGETABLE_PMD_FOLDED
  140. pmd_init(pmd);
  141. #endif
  142. }
  143. pmd = pmd_offset(pud, addr);
  144. if (!pmd_present(pmdp_get(pmd))) {
  145. pte_t *pte;
  146. pte = memblock_alloc_or_panic(PAGE_SIZE, PAGE_SIZE);
  147. pmd_populate_kernel(&init_mm, pmd, pte);
  148. kernel_pte_init(pte);
  149. }
  150. return pte_offset_kernel(pmd, addr);
  151. }
  152. void __init __set_fixmap(enum fixed_addresses idx,
  153. phys_addr_t phys, pgprot_t flags)
  154. {
  155. unsigned long addr = __fix_to_virt(idx);
  156. pte_t *ptep;
  157. BUG_ON(idx <= FIX_HOLE || idx >= __end_of_fixed_addresses);
  158. ptep = populate_kernel_pte(addr);
  159. if (!pte_none(ptep_get(ptep))) {
  160. pte_ERROR(*ptep);
  161. return;
  162. }
  163. if (pgprot_val(flags))
  164. set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, flags));
  165. else {
  166. pte_clear(&init_mm, addr, ptep);
  167. flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
  168. }
  169. }
  170. /*
  171. * Align swapper_pg_dir in to 64K, allows its address to be loaded
  172. * with a single LUI instruction in the TLB handlers. If we used
  173. * __aligned(64K), its size would get rounded up to the alignment
  174. * size, and waste space. So we place it in its own section and align
  175. * it in the linker script.
  176. */
  177. pgd_t swapper_pg_dir[_PTRS_PER_PGD] __section(".bss..swapper_pg_dir");
  178. pgd_t invalid_pg_dir[_PTRS_PER_PGD] __page_aligned_bss;
  179. #ifndef __PAGETABLE_PUD_FOLDED
  180. pud_t invalid_pud_table[PTRS_PER_PUD] __page_aligned_bss;
  181. EXPORT_SYMBOL(invalid_pud_table);
  182. #endif
  183. #ifndef __PAGETABLE_PMD_FOLDED
  184. pmd_t invalid_pmd_table[PTRS_PER_PMD] __page_aligned_bss;
  185. EXPORT_SYMBOL(invalid_pmd_table);
  186. #endif
  187. pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned_bss;
  188. EXPORT_SYMBOL(invalid_pte_table);
  189. #if defined(CONFIG_EXECMEM) && defined(MODULES_VADDR)
  190. static struct execmem_info execmem_info __ro_after_init;
  191. struct execmem_info __init *execmem_arch_setup(void)
  192. {
  193. execmem_info = (struct execmem_info){
  194. .ranges = {
  195. [EXECMEM_DEFAULT] = {
  196. .start = MODULES_VADDR,
  197. .end = MODULES_END,
  198. .pgprot = PAGE_KERNEL,
  199. .alignment = 1,
  200. },
  201. },
  202. };
  203. return &execmem_info;
  204. }
  205. #endif /* CONFIG_EXECMEM && MODULES_VADDR */