pgtable.c 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. /*
  2. * Copyright (C) 2009 Wind River Systems Inc
  3. * Implemented by [email protected] and [email protected]
  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/cpuinfo.h>
  12. /* pteaddr:
  13. * ptbase | vpn* | zero
  14. * 31-22 | 21-2 | 1-0
  15. *
  16. * *vpn is preserved on double fault
  17. *
  18. * tlbacc:
  19. * IG |*flags| pfn
  20. * 31-25|24-20 | 19-0
  21. *
  22. * *crwxg
  23. *
  24. * tlbmisc:
  25. * resv |way |rd | we|pid |dbl|bad|perm|d
  26. * 31-24 |23-20 |19 | 20|17-4|3 |2 |1 |0
  27. *
  28. */
  29. /*
  30. * Initialize a new pgd / pmd table with invalid pointers.
  31. */
  32. static void pgd_init(pgd_t *pgd)
  33. {
  34. unsigned long *p = (unsigned long *) pgd;
  35. int i;
  36. for (i = 0; i < USER_PTRS_PER_PGD; i += 8) {
  37. p[i + 0] = (unsigned long) invalid_pte_table;
  38. p[i + 1] = (unsigned long) invalid_pte_table;
  39. p[i + 2] = (unsigned long) invalid_pte_table;
  40. p[i + 3] = (unsigned long) invalid_pte_table;
  41. p[i + 4] = (unsigned long) invalid_pte_table;
  42. p[i + 5] = (unsigned long) invalid_pte_table;
  43. p[i + 6] = (unsigned long) invalid_pte_table;
  44. p[i + 7] = (unsigned long) invalid_pte_table;
  45. }
  46. }
  47. pgd_t *pgd_alloc(struct mm_struct *mm)
  48. {
  49. pgd_t *ret, *init;
  50. ret = (pgd_t *) __get_free_page(GFP_KERNEL);
  51. if (ret) {
  52. init = pgd_offset(&init_mm, 0UL);
  53. pgd_init(ret);
  54. memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
  55. (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
  56. }
  57. return ret;
  58. }
  59. void __init pagetable_init(void)
  60. {
  61. /* Initialize the entire pgd. */
  62. pgd_init(swapper_pg_dir);
  63. pgd_init(swapper_pg_dir + USER_PTRS_PER_PGD);
  64. }