pgtable.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. /*
  2. * Copyright (C) 2009 Wind River Systems Inc
  3. * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
  4. *
  5. * This file is subject to the terms and conditions of the GNU General Public
  6. * License. See the file "COPYING" in the main directory of this archive
  7. * for more details.
  8. */
  9. #include <linux/mm.h>
  10. #include <linux/sched.h>
  11. #include <asm/pgtable.h>
  12. #include <asm/cpuinfo.h>
  13. /* pteaddr:
  14. * ptbase | vpn* | zero
  15. * 31-22 | 21-2 | 1-0
  16. *
  17. * *vpn is preserved on double fault
  18. *
  19. * tlbacc:
  20. * IG |*flags| pfn
  21. * 31-25|24-20 | 19-0
  22. *
  23. * *crwxg
  24. *
  25. * tlbmisc:
  26. * resv |way |rd | we|pid |dbl|bad|perm|d
  27. * 31-24 |23-20 |19 | 20|17-4|3 |2 |1 |0
  28. *
  29. */
  30. /*
  31. * Initialize a new pgd / pmd table with invalid pointers.
  32. */
  33. static void pgd_init(pgd_t *pgd)
  34. {
  35. unsigned long *p = (unsigned long *) pgd;
  36. int i;
  37. for (i = 0; i < USER_PTRS_PER_PGD; i += 8) {
  38. p[i + 0] = (unsigned long) invalid_pte_table;
  39. p[i + 1] = (unsigned long) invalid_pte_table;
  40. p[i + 2] = (unsigned long) invalid_pte_table;
  41. p[i + 3] = (unsigned long) invalid_pte_table;
  42. p[i + 4] = (unsigned long) invalid_pte_table;
  43. p[i + 5] = (unsigned long) invalid_pte_table;
  44. p[i + 6] = (unsigned long) invalid_pte_table;
  45. p[i + 7] = (unsigned long) invalid_pte_table;
  46. }
  47. }
  48. pgd_t *pgd_alloc(struct mm_struct *mm)
  49. {
  50. pgd_t *ret, *init;
  51. ret = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ORDER);
  52. if (ret) {
  53. init = pgd_offset(&init_mm, 0UL);
  54. pgd_init(ret);
  55. memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
  56. (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
  57. }
  58. return ret;
  59. }
  60. void __init pagetable_init(void)
  61. {
  62. /* Initialize the entire pgd. */
  63. pgd_init(swapper_pg_dir);
  64. pgd_init(swapper_pg_dir + USER_PTRS_PER_PGD);
  65. }