mmu.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include "u.h"
  2. #include "mem.h"
  3. #include "dat.h"
  4. #include "fns.h"
  5. #include "lib.h"
  6. static int debug;
  7. static uvlong by2pg; /* hwrpb->by2pg */
  8. static uvlong pte2pg; /* by2pg/8 */
  9. static uvlong pgmask; /* by2pg-1 */
  10. static uvlong ptemask; /* pte2pg-1 */
  11. static uvlong pgshift; /* log2(by2pg) */
  12. static uvlong pteshift; /* log2(pte2pg) = pgshift - 3 */
  13. #define L1(va) (((uvlong)(va)>>3*pteshift+3) & (pte2pg-1))
  14. #define L2(va) (((uvlong)(va)>>2*pteshift+3) & (pte2pg-1))
  15. #define L3(va) (((uvlong)(va)>>pgshift) & (pte2pg-1))
  16. #define OFF(va) (((uvlong)(va)) & (by2pg-1))
  17. #define V1(l1) (((vlong)l1<<(64-pteshift)) >> 64-(3*pteshift+3))
  18. #define V2(l2) (((uvlong)l2<<(64-pteshift)) >> 64-(2*pteshift+3))
  19. #define V3(l3) (((uvlong)l3<<(64-pteshift)) >> 64-pgshift)
  20. #define VA(l1, l2, l3, off) (V1(l1) | V2(l2) | V3(l3) | (off))
  21. static int
  22. log2(uvlong x)
  23. {
  24. int i;
  25. if ((x & (x-1)) == 0)
  26. for (i = 0; i < 64; i++)
  27. if (x & (1<<i))
  28. return i;
  29. panic("log2: %llux", x);
  30. return -1;
  31. }
  32. void
  33. mmuinit(void)
  34. {
  35. int i;
  36. uvlong npage, nlvl2, nlvl3;
  37. uvlong l1p, l2p, lvl2, lvl3;
  38. extern ulong _main[], edata[];
  39. /* map entire physical memory at KZERO */
  40. by2pg = hwrpb->by2pg;
  41. pte2pg = (by2pg >> 3);
  42. pgmask = by2pg-1;
  43. ptemask = pte2pg-1;
  44. pgshift = log2(by2pg);
  45. pteshift = pgshift-3;
  46. l1p = (1LL<<3*pteshift+3)|(1LL<<2*pteshift+3)|(1LL<<pgshift);
  47. if (rdv(l1p+8*(pte2pg-1)) != 0 || rdv(l1p+8*(pte2pg-2)) != 0)
  48. panic("KZERO lvl1 already mapped");
  49. npage = (conf.maxphys+pgmask)>>pgshift;
  50. nlvl3 = (npage+ptemask)>>pteshift;
  51. nlvl2 = (nlvl3+ptemask)>>pteshift;
  52. if (nlvl2 > 1)
  53. panic("meminit: nlvl2"); /* cannot happen, due to virtual space limitation */
  54. if (debug)
  55. print("nlvl1 %llud nlvl2 %llud nlvl3 %llud npage %llud\n", 1LL, nlvl2, nlvl3, npage);
  56. lvl2 = allocate(nlvl2+nlvl3);
  57. lvl3 = lvl2 + nlvl2*by2pg;
  58. wrv(l1p+8*(pte2pg-2), rdv(l1p+8)|PTEASM);
  59. wrv(l1p+8*(pte2pg-1), (lvl2<<(32-pgshift)) | PTEKVALID | PTEASM);
  60. l2p = (1LL<<3*pteshift+3)|(1LL<<2*pteshift+3)|((vlong)KZERO >> 2*pteshift)&((1LL<<2*pteshift+3)-1);
  61. for (i = 0; i < nlvl3; i++)
  62. stqp(lvl2+(l2p&(by2pg-1))+8*i, ((lvl3+i*by2pg)<<(32-pgshift)) | PTEKVALID | PTEASM);
  63. for (i = 0; i < npage; i++)
  64. stqp(lvl3+8*i, ((uvlong)i<<32) | PTEKVALID | PTEASM);
  65. tlbflush();
  66. if (debug)
  67. print("\n");
  68. }
  69. uvlong
  70. paddr(uvlong va)
  71. {
  72. uvlong ptbr, x, pte;
  73. ptbr = getptbr();
  74. pte = ldqp((ptbr<<pgshift)+8*L1(va));
  75. if ((pte&PTEKVALID) != PTEKVALID)
  76. return 0;
  77. x = ((pte>>32)<<pgshift);
  78. pte = ldqp(x+8*L2(va));
  79. if ((pte&PTEKVALID) != PTEKVALID)
  80. return 0;
  81. x = ((pte>>32)<<pgshift);
  82. pte = ldqp(x+8*L3(va));
  83. if ((pte&PTEKVALID) != PTEKVALID)
  84. return 0;
  85. x = ((pte>>32)<<pgshift);
  86. return x;
  87. }
  88. uvlong
  89. pground(uvlong x)
  90. {
  91. return (x+pgmask) & ~pgmask;
  92. }