pgtable-32.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2003 by Ralf Baechle
  7. */
  8. #include <linux/config.h>
  9. #include <linux/init.h>
  10. #include <linux/mm.h>
  11. #include <linux/bootmem.h>
  12. #include <linux/highmem.h>
  13. #include <asm/pgtable.h>
  14. void pgd_init(unsigned long page)
  15. {
  16. unsigned long *p = (unsigned long *) page;
  17. int i;
  18. for (i = 0; i < USER_PTRS_PER_PGD; i+=8) {
  19. p[i + 0] = (unsigned long) invalid_pte_table;
  20. p[i + 1] = (unsigned long) invalid_pte_table;
  21. p[i + 2] = (unsigned long) invalid_pte_table;
  22. p[i + 3] = (unsigned long) invalid_pte_table;
  23. p[i + 4] = (unsigned long) invalid_pte_table;
  24. p[i + 5] = (unsigned long) invalid_pte_table;
  25. p[i + 6] = (unsigned long) invalid_pte_table;
  26. p[i + 7] = (unsigned long) invalid_pte_table;
  27. }
  28. }
  29. #ifdef CONFIG_HIGHMEM
  30. static void __init fixrange_init (unsigned long start, unsigned long end,
  31. pgd_t *pgd_base)
  32. {
  33. pgd_t *pgd;
  34. pmd_t *pmd;
  35. pte_t *pte;
  36. int i, j;
  37. unsigned long vaddr;
  38. vaddr = start;
  39. i = __pgd_offset(vaddr);
  40. j = __pmd_offset(vaddr);
  41. pgd = pgd_base + i;
  42. for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
  43. pmd = (pmd_t *)pgd;
  44. for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
  45. if (pmd_none(*pmd)) {
  46. pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
  47. set_pmd(pmd, __pmd((unsigned long)pte));
  48. if (pte != pte_offset_kernel(pmd, 0))
  49. BUG();
  50. }
  51. vaddr += PMD_SIZE;
  52. }
  53. j = 0;
  54. }
  55. }
  56. #endif
  57. void __init pagetable_init(void)
  58. {
  59. #ifdef CONFIG_HIGHMEM
  60. unsigned long vaddr;
  61. pgd_t *pgd, *pgd_base;
  62. pmd_t *pmd;
  63. pte_t *pte;
  64. #endif
  65. /* Initialize the entire pgd. */
  66. pgd_init((unsigned long)swapper_pg_dir);
  67. pgd_init((unsigned long)swapper_pg_dir
  68. + sizeof(pgd_t) * USER_PTRS_PER_PGD);
  69. #ifdef CONFIG_HIGHMEM
  70. pgd_base = swapper_pg_dir;
  71. /*
  72. * Fixed mappings:
  73. */
  74. vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
  75. fixrange_init(vaddr, 0, pgd_base);
  76. /*
  77. * Permanent kmaps:
  78. */
  79. vaddr = PKMAP_BASE;
  80. fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
  81. pgd = swapper_pg_dir + __pgd_offset(vaddr);
  82. pmd = pmd_offset(pgd, vaddr);
  83. pte = pte_offset_kernel(pmd, vaddr);
  84. pkmap_page_table = pte;
  85. #endif
  86. }