|
@@ -10,8 +10,38 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
|
10
|
10
|
/* Drag in local definitions */
|
11
|
11
|
#include "librm.h"
|
12
|
12
|
|
13
|
|
-/* For switches to/from protected mode */
|
14
|
|
-#define CR0_PE 1
|
|
13
|
+/* CR0: protection enabled */
|
|
14
|
+#define CR0_PE ( 1 << 0 )
|
|
15
|
+
|
|
16
|
+/* CR0: paging */
|
|
17
|
+#define CR0_PG ( 1 << 31 )
|
|
18
|
+
|
|
19
|
+/* CR4: physical address extensions */
|
|
20
|
+#define CR4_PAE ( 1 << 5 )
|
|
21
|
+
|
|
22
|
+/* Page: present */
|
|
23
|
+#define PG_P 0x01
|
|
24
|
+
|
|
25
|
+/* Page: read/write */
|
|
26
|
+#define PG_RW 0x02
|
|
27
|
+
|
|
28
|
+/* Page: user/supervisor */
|
|
29
|
+#define PG_US 0x04
|
|
30
|
+
|
|
31
|
+/* Page: page size */
|
|
32
|
+#define PG_PS 0x80
|
|
33
|
+
|
|
34
|
+/* Size of various paging-related data structures */
|
|
35
|
+#define SIZEOF_PTE_LOG2 3
|
|
36
|
+#define SIZEOF_PTE ( 1 << SIZEOF_PTE_LOG2 )
|
|
37
|
+#define SIZEOF_PT_LOG2 12
|
|
38
|
+#define SIZEOF_PT ( 1 << SIZEOF_PT_LOG2 )
|
|
39
|
+#define SIZEOF_4KB_PAGE_LOG2 12
|
|
40
|
+#define SIZEOF_4KB_PAGE ( 1 << SIZEOF_4KB_PAGE_LOG2 )
|
|
41
|
+#define SIZEOF_2MB_PAGE_LOG2 21
|
|
42
|
+#define SIZEOF_2MB_PAGE ( 1 << SIZEOF_2MB_PAGE_LOG2 )
|
|
43
|
+#define SIZEOF_LOW_4GB_LOG2 32
|
|
44
|
+#define SIZEOF_LOW_4GB ( 1 << SIZEOF_LOW_4GB_LOG2 )
|
15
|
45
|
|
16
|
46
|
/* Size of various C data structures */
|
17
|
47
|
#define SIZEOF_I386_SEG_REGS 12
|
|
@@ -226,6 +256,10 @@ init_librm:
|
226
|
256
|
.if32 ; subl %edi, %eax ; .endif
|
227
|
257
|
movl %eax, rm_data16
|
228
|
258
|
|
|
259
|
+.if64 ; /* Reset page tables, if applicable */
|
|
260
|
+ xorl %eax, %eax
|
|
261
|
+ movl %eax, pml4
|
|
262
|
+.endif
|
229
|
263
|
/* Switch to protected mode */
|
230
|
264
|
virtcall init_librm_pmode
|
231
|
265
|
.section ".text.init_librm", "ax", @progbits
|
|
@@ -242,6 +276,10 @@ init_librm_pmode:
|
242
|
276
|
rep movsl
|
243
|
277
|
popw %ds
|
244
|
278
|
|
|
279
|
+.if64 ; /* Initialise page tables, if applicable */
|
|
280
|
+ movl VIRTUAL(virt_offset), %edi
|
|
281
|
+ call init_pages
|
|
282
|
+.endif
|
245
|
283
|
/* Return to real mode */
|
246
|
284
|
ret
|
247
|
285
|
.section ".text16.init_librm", "ax", @progbits
|
|
@@ -714,3 +752,144 @@ interrupt_wrapper:
|
714
|
752
|
/* Restore registers and return */
|
715
|
753
|
popal
|
716
|
754
|
iret
|
|
755
|
+
|
|
756
|
+/****************************************************************************
|
|
757
|
+ * Page tables
|
|
758
|
+ *
|
|
759
|
+ ****************************************************************************
|
|
760
|
+ */
|
|
761
|
+ .section ".pages", "aw", @nobits
|
|
762
|
+ .align SIZEOF_PT
|
|
763
|
+
|
|
764
|
+ /* Page map level 4 entries (PML4Es)
|
|
765
|
+ *
|
|
766
|
+ * This comprises
|
|
767
|
+ *
|
|
768
|
+ * - PML4E[0x000] covering [0x0000000000000000-0x0000007fffffffff]
|
|
769
|
+ * - PML4E[0x1ff] covering [0xffffff8000000000-0xffffffffffffffff]
|
|
770
|
+ *
|
|
771
|
+ * These point to the PDPT. This creates some aliased
|
|
772
|
+ * addresses within unused portions of the 64-bit address
|
|
773
|
+ * space, but allows us to use just a single PDPT.
|
|
774
|
+ */
|
|
775
|
+pml4e:
|
|
776
|
+ .space SIZEOF_PT
|
|
777
|
+ .size pml4e, . - pml4e
|
|
778
|
+
|
|
779
|
+ /* Page directory pointer table entries (PDPTEs)
|
|
780
|
+ *
|
|
781
|
+ * This comprises:
|
|
782
|
+ *
|
|
783
|
+ * - PDPTE[0x000] covering [0x0000000000000000-0x000000003fffffff]
|
|
784
|
+ * - PDPTE[0x001] covering [0x0000000040000000-0x000000007fffffff]
|
|
785
|
+ * - PDPTE[0x002] covering [0x0000000080000000-0x00000000bfffffff]
|
|
786
|
+ * - PDPTE[0x003] covering [0x00000000c0000000-0x00000000ffffffff]
|
|
787
|
+ *
|
|
788
|
+ * These point to the appropriate page directories (in pde_low)
|
|
789
|
+ * used to identity-map the whole of the 32-bit address space.
|
|
790
|
+ *
|
|
791
|
+ * - PDPTE[0x1ff] covering [0xffffffffc0000000-0xffffffffffffffff]
|
|
792
|
+ *
|
|
793
|
+ * This points back to the PDPT itself, allowing the PDPT to be
|
|
794
|
+ * (ab)used to hold PDEs covering .textdata.
|
|
795
|
+ *
|
|
796
|
+ * - PDE[N-M] covering [_textdata,_end)
|
|
797
|
+ *
|
|
798
|
+ * These are used to point to the page tables (in pte_textdata)
|
|
799
|
+ * used to map our .textdata section. Note that each PDE
|
|
800
|
+ * covers 2MB, so we are likely to use only a single PDE in
|
|
801
|
+ * practice.
|
|
802
|
+ */
|
|
803
|
+pdpte:
|
|
804
|
+ .space SIZEOF_PT
|
|
805
|
+ .size pdpte, . - pdpte
|
|
806
|
+ .equ pde_textdata, pdpte /* (ab)use */
|
|
807
|
+
|
|
808
|
+ /* Page directory entries (PDEs) for the low 4GB
|
|
809
|
+ *
|
|
810
|
+ * This comprises 2048 2MB pages to identity-map the whole of
|
|
811
|
+ * the 32-bit address space.
|
|
812
|
+ */
|
|
813
|
+pde_low:
|
|
814
|
+ .equ PDE_LOW_PTES, ( SIZEOF_LOW_4GB / SIZEOF_2MB_PAGE )
|
|
815
|
+ .equ PDE_LOW_PTS, ( ( PDE_LOW_PTES * SIZEOF_PTE ) / SIZEOF_PT )
|
|
816
|
+ .space ( PDE_LOW_PTS * SIZEOF_PT )
|
|
817
|
+ .size pde_low, . - pde_low
|
|
818
|
+
|
|
819
|
+ /* Page table entries (PTEs) for .textdata
|
|
820
|
+ *
|
|
821
|
+ * This comprises enough 4kB pages to map the whole of
|
|
822
|
+ * .textdata. The required number of PTEs is calculated by
|
|
823
|
+ * the linker script.
|
|
824
|
+ *
|
|
825
|
+ * Note that these mappings do not cover the PTEs themselves.
|
|
826
|
+ * This does not matter, since code running with paging
|
|
827
|
+ * enabled never needs to access these PTEs.
|
|
828
|
+ */
|
|
829
|
+pte_textdata:
|
|
830
|
+ /* Allocated by linker script; must be at the end of .textdata */
|
|
831
|
+
|
|
832
|
+ .section ".bss16.pml4", "aw", @nobits
|
|
833
|
+pml4: .long 0
|
|
834
|
+
|
|
835
|
+/****************************************************************************
|
|
836
|
+ * init_pages (protected-mode near call)
|
|
837
|
+ *
|
|
838
|
+ * Initialise the page tables ready for long mode.
|
|
839
|
+ *
|
|
840
|
+ * Parameters:
|
|
841
|
+ * %edi : virt_offset
|
|
842
|
+ ****************************************************************************
|
|
843
|
+ */
|
|
844
|
+ .section ".text.init_pages", "ax", @progbits
|
|
845
|
+ .code32
|
|
846
|
+init_pages:
|
|
847
|
+ /* Initialise PML4Es for low 4GB and negative 2GB */
|
|
848
|
+ leal ( VIRTUAL(pdpte) + ( PG_P | PG_RW | PG_US ) )(%edi), %eax
|
|
849
|
+ movl %eax, VIRTUAL(pml4e)
|
|
850
|
+ movl %eax, ( VIRTUAL(pml4e) + SIZEOF_PT - SIZEOF_PTE )
|
|
851
|
+
|
|
852
|
+ /* Initialise PDPTE for negative 1GB */
|
|
853
|
+ movl %eax, ( VIRTUAL(pdpte) + SIZEOF_PT - SIZEOF_PTE )
|
|
854
|
+
|
|
855
|
+ /* Initialise PDPTEs for low 4GB */
|
|
856
|
+ movl $PDE_LOW_PTS, %ecx
|
|
857
|
+ leal ( VIRTUAL(pde_low) + ( PDE_LOW_PTS * SIZEOF_PT ) + \
|
|
858
|
+ ( PG_P | PG_RW | PG_US ) )(%edi), %eax
|
|
859
|
+1: subl $SIZEOF_PT, %eax
|
|
860
|
+ movl %eax, ( VIRTUAL(pdpte) - SIZEOF_PTE )(,%ecx,SIZEOF_PTE)
|
|
861
|
+ loop 1b
|
|
862
|
+
|
|
863
|
+ /* Initialise PDEs for low 4GB */
|
|
864
|
+ movl $PDE_LOW_PTES, %ecx
|
|
865
|
+ leal ( 0 + ( PG_P | PG_RW | PG_US | PG_PS ) ), %eax
|
|
866
|
+1: subl $SIZEOF_2MB_PAGE, %eax
|
|
867
|
+ movl %eax, ( VIRTUAL(pde_low) - SIZEOF_PTE )(,%ecx,SIZEOF_PTE)
|
|
868
|
+ loop 1b
|
|
869
|
+
|
|
870
|
+ /* Initialise PDEs for .textdata */
|
|
871
|
+ movl $_textdata_pdes, %ecx
|
|
872
|
+ leal ( VIRTUAL(_etextdata) + ( PG_P | PG_RW | PG_US ) )(%edi), %eax
|
|
873
|
+ movl $VIRTUAL(_textdata), %ebx
|
|
874
|
+ shrl $( SIZEOF_2MB_PAGE_LOG2 - SIZEOF_PTE_LOG2 ), %ebx
|
|
875
|
+ andl $( SIZEOF_PT - 1 ), %ebx
|
|
876
|
+1: subl $SIZEOF_PT, %eax
|
|
877
|
+ movl %eax, (VIRTUAL(pde_textdata) - SIZEOF_PTE)(%ebx,%ecx,SIZEOF_PTE)
|
|
878
|
+ loop 1b
|
|
879
|
+
|
|
880
|
+ /* Initialise PTEs for .textdata */
|
|
881
|
+ movl $_textdata_ptes, %ecx
|
|
882
|
+ leal ( VIRTUAL(_textdata) + ( PG_P | PG_RW | PG_US ) )(%edi), %eax
|
|
883
|
+ addl $_textdata_paged_len, %eax
|
|
884
|
+1: subl $SIZEOF_4KB_PAGE, %eax
|
|
885
|
+ movl %eax, ( VIRTUAL(pte_textdata) - SIZEOF_PTE )(,%ecx,SIZEOF_PTE)
|
|
886
|
+ loop 1b
|
|
887
|
+
|
|
888
|
+ /* Record PML4 physical address */
|
|
889
|
+ leal VIRTUAL(pml4e)(%edi), %eax
|
|
890
|
+ movl VIRTUAL(data16), %ebx
|
|
891
|
+ subl %edi, %ebx
|
|
892
|
+ movl %eax, pml4(%ebx)
|
|
893
|
+
|
|
894
|
+ /* Return */
|
|
895
|
+ ret
|