l32p.s 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #include "mem.h"
  2. /*
  3. * Some machine instructions not handled by 8[al].
  4. */
  5. #define DELAY BYTE $0xEB; BYTE $0x00 /* JMP .+2 */
  6. #define FARJUMP(s, o) BYTE $0xEA; /* far jump to ptr32:16 */\
  7. LONG $o; WORD $s
  8. /*
  9. * Macro for calculating offset within the page directory base.
  10. * Note that this is assembler-specific hence the '<<2'.
  11. */
  12. #define PDO(a) (((((a))>>22) & 0x03FF)<<2)
  13. /*
  14. * May enter here either from the 16-bit real-mode startup or
  15. * from other 32-bit protected mode code. For the latter case must
  16. * make sure the GDT is set as it would be by the 16-bit code:
  17. * disable interrupts;
  18. * load the GDT with the table in _gdt32p;
  19. * load all the data segments
  20. * load the code segment via a far jump.
  21. */
  22. TEXT _start32p(SB), $0
  23. BYTE $0xEB; BYTE $0x58; /* jmp .+ 0x58 (_start32p58) */
  24. BYTE $0x90; BYTE $0x90 /* nop */
  25. /*
  26. * Must be 4-byte aligned.
  27. */
  28. TEXT _multibootheader(SB), $0
  29. LONG $0x1BADB002 /* magic */
  30. LONG $0x00010003 /* flags */
  31. LONG $-(0x1BADB002 + 0x00010003) /* checksum */
  32. LONG $_multibootheader-KZERO(SB) /* header_addr */
  33. LONG $_start32p-KZERO(SB) /* load_addr */
  34. LONG $edata-KZERO(SB) /* load_end_addr */
  35. LONG $end-KZERO(SB) /* bss_end_addr */
  36. LONG $_start32p-KZERO(SB) /* entry_addr */
  37. LONG $0 /* mode_type */
  38. LONG $0 /* width */
  39. LONG $0 /* height */
  40. LONG $0 /* depth */
  41. LONG $0 /* +48: saved AX - magic */
  42. LONG $0 /* +52: saved BX - info* */
  43. TEXT _gdt32p(SB), $0
  44. LONG $0x0000; LONG $0
  45. LONG $0xFFFF; LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
  46. LONG $0xFFFF; LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
  47. TEXT _gdtptr32p(SB), $0
  48. WORD $(3*8)
  49. LONG $_gdt32p-KZERO(SB)
  50. _start32p58:
  51. CLI
  52. MOVL AX, _multibootheader+(48-KZERO)(SB)
  53. MOVL BX, _multibootheader+(52-KZERO)(SB)
  54. MOVL $_gdtptr32p-KZERO(SB), AX
  55. MOVL (AX), GDTR
  56. MOVL $SELECTOR(1, SELGDT, 0), AX
  57. MOVW AX, DS
  58. MOVW AX, ES
  59. MOVW AX, FS
  60. MOVW AX, GS
  61. MOVW AX, SS
  62. FARJUMP(SELECTOR(2, SELGDT, 0), _start32pg-KZERO(SB))
  63. /*
  64. * Make the basic page tables for processor 0. Five pages are needed for
  65. * the basic set:
  66. * a page directory, a page table for mapping the first 4MB of physical
  67. * memory, a separate physical and virtual page for the Mach structure
  68. * and a page to be used later for the GDT.
  69. * The remaining PTEs will be allocated later when memory is sized.
  70. * Could clear BSS here too when clearing the space for the tables,
  71. * but that would violate the separation of church and state.
  72. * The first aligned page after end[] is where the real-mode startup
  73. * puts any BIOS parameters (APM, MAP).
  74. */
  75. TEXT _start32pg(SB), $0
  76. MOVL $end-KZERO(SB), DX /* clear pages for the tables etc. */
  77. ADDL $(2*BY2PG-1), DX /* start must be page aligned */
  78. ANDL $~(BY2PG-1), DX
  79. MOVL DX, DI
  80. XORL AX, AX
  81. MOVL $(5*BY2PG), CX
  82. SHRL $2, CX
  83. CLD
  84. REP; STOSL
  85. MOVL DX, AX /* bootstrap processor PDB */
  86. MOVL DX, DI /* save it for later */
  87. ADDL $BY2PG, DX /* -> PA of first page of page table */
  88. ADDL $PDO(KZERO), AX /* page directory offset for KZERO */
  89. MOVL DX, (AX) /* PTE's for KZERO */
  90. MOVL $(PTEWRITE|PTEVALID), BX/* page permissions */
  91. ORL BX, (AX)
  92. MOVL DX, AX /* PA of first page of page table */
  93. MOVL $1024, CX /* 1024 pages in 4MB */
  94. _setpte:
  95. MOVL BX, (AX)
  96. ADDL $(1<<PGSHIFT), BX
  97. ADDL $4, AX
  98. LOOP _setpte
  99. MOVL DX, AX /* PA of first page of page table */
  100. ADDL $BY2PG, DX /* -> PA of Mach structure */
  101. MOVL DX, BX
  102. ADDL $(KZERO+BY2PG), BX /* VA of Mach structure */
  103. SHRL $10, BX /* create offset into PTEs */
  104. ANDL $(0x3FF<<2), BX
  105. ADDL BX, AX /* PTE offset for Mach structure */
  106. MOVL DX, (AX) /* create PTE for Mach */
  107. MOVL $(PTEWRITE|PTEVALID), BX/* page permissions */
  108. ORL BX, (AX)
  109. /*
  110. * Now ready to use the new map. Initialise CR0 (assume the BIOS gets
  111. * it mostly correct for this processor type w.r.t. caches and FPU).
  112. * It is necessary on some processors to follow mode switching
  113. * with a JMP instruction to clear the prefetch queues.
  114. * The instruction to switch modes and the following jump instruction
  115. * should be identity-mapped; to this end double map KZERO at
  116. * virtual 0 and undo the mapping once virtual nirvana has been attained.
  117. * If paging is already on, don't load CR3 before setting CR0, in which
  118. * case most of this is a NOP and the 2nd load of CR3 actually does
  119. * the business.
  120. */
  121. MOVL DI, CX /* load address of PDB */
  122. MOVL PDO(KZERO)(CX), DX /* double-map KZERO at 0 */
  123. MOVL DX, PDO(0)(CX)
  124. MOVL CR0, DX
  125. MOVL DX, AX
  126. ANDL $0x80000000, AX /* check paging not already on */
  127. JNE _nocr3load
  128. MOVL CX, CR3
  129. _nocr3load:
  130. ORL $0x80010000, DX /* PG|WP */
  131. ANDL $~0x6000000A, DX /* ~(CD|NW|TS|MP) */
  132. MOVL $_startpg(SB), AX
  133. TESTL $KZERO, AX /* want to run protected or virtual? */
  134. JNE _dorkness
  135. MOVL $_start32v(SB), AX
  136. JMP* AX /* into the dorkness */
  137. _dorkness:
  138. MOVL DX, CR0 /* turn on paging */
  139. JMP* AX /* headfirst into the new world */
  140. TEXT _startpg(SB), $0
  141. // MOVL $0, PDO(0)(CX) /* undo double-map of KZERO at 0 */
  142. // MOVL CX, CR3 /* load and flush the mmu */
  143. MOVL $_start32v(SB), AX
  144. JMP* AX /* into the dorkness */