00001 /*********************************************************** 00002 *PANALIX 0.06, (c) Adrian Panasiuk 2002,3 * 00003 *adek336[at]o2.pl, panalix.prv.pl * 00004 *under GPLv3 license * 00005 * * 00006 *panalix - small osdev project * 00007 ************************************************************ 00008 * paging.s, version 1.2 * 00009 * * 00010 ************************************************************ 00011 * * 00012 *Responsible for initialising paging * 00013 * * 00014 *17'04'04- forked from panalix 0.05 branch paging.s(1.2) * 00015 * * 00016 ***********************************************************/ 00017 00018 /*----------------------------------------------------------*/ 00019 00020 /*a copy of these is in crt.s and other files*/ 00021 .set virt_addr, 0xC0000000 /*Virtual adress for the kernel*/ /*3Gb*/ 00022 .set lma_addr, 0x100000 /*Physical address where the kernel was loaded*/ /*1Mb*/ 00023 00024 00025 .text 00026 00027 .globl __init_paging 00028 __init_paging: 00029 00030 /*we are linked to 0xc000_0000, and running at 0x0010_0000. accessing PGD accesses the 0xc000_0000 00031 address, but if we substract 0xc000_0000 and add 0x0010_0000 we will have the object's address in 00032 the moment before paging.*/ 00033 xor %ebx, %ebx 00034 subl $virt_addr, %ebx /*count the phys adress of the PGD which is the virt addr*/ 00035 addl $lma_addr, %ebx /*- the virt addr of kernel + load adress of kernel*/ 00036 00037 /*put the address of the 0xc000_0000 page table into %eax*/ 00038 movl %ebx, %eax 00039 addl $KERNEL_PAGE_TABLES, %eax 00040 /*as we map all the pages, we hold the current phys addr in %edx.*/ 00041 movl $lma_addr, %edx /*the page we're mapping*/ 00042 /*we map only 1024 times, so we need a counter*/ 00043 xor %ecx, %ecx /*counter*/ 00044 sk_l1: /*loop for setting kpgt entries*/ 00045 movl %edx, (%eax) 00046 addl $3, (%eax) /*3 == PTE_PRESENT|PTE_WRITEABLE*/ 00047 addl $4096, %edx /*next page*/ 00048 addl $4, %eax /*next kpgte*/ 00049 incl %ecx 00050 cmpl $0x400, %ecx 00051 jne sk_l1 00052 00053 /*we will be running approximately 10 instructions between enabling paging and filling %eip 00054 with the 0xc000_0000 values, so we need to identity-map the region which will be executed later.*/ 00055 /*get the proper address of the pgt #0 into %eax*/ 00056 movl %ebx, %eax 00057 addl $IDENTITY_PGT, %eax 00058 /*keep the current's page physical address in %edx*/ 00059 xor %edx, %edx /*start from page 0*/ 00060 xor %ecx, %ecx /*clear counter*/ 00061 /*leave page 0 unmapped to catch null pointer dereferences*/ 00062 movl $0, (%eax) 00063 addl $4096, %edx/*next page*/ 00064 addl $4, %eax /*next pgte*/ 00065 /*all rest mapped, 0xffff_f000 also for wrong ptrs*/ 00066 sk_l2: /*loop for identity mapping first 4Mb. this is done temporarily*/ 00067 movl %edx, (%eax) /*so I can execute code after setting the paging bit in %cr0*/ 00068 addl $3, (%eax) /*3 == PTE_WRITEABLE|PTE_PRESENT*/ 00069 addl $4096, %edx/*next page*/ 00070 addl $4, %eax /*next pgte*/ 00071 incl %ecx 00072 cmpl $0x400, %ecx 00073 jne sk_l2 00074 00075 /*install ident_pgt into pgd*/ 00076 movl %ebx, %eax 00077 movl %ebx, %ecx /*save the value*/ 00078 addl $PGD, %eax /*+the pgd offset*/ 00079 addl $IDENTITY_PGT, %ecx /*+the ident_pgt offset*/ 00080 movl %ecx, (%eax) /*install pgt 0*/ 00081 addl $7, (%eax) /*with attr = 7*/ 00082 /*install all kernel level page tables now*/ 00083 movl %ebx, %edx 00084 addl $KERNEL_PAGE_TABLES, %edx 00085 movl %ebx, %eax 00086 addl $PGD, %eax 00087 addl $0xc00, %eax 00088 xor %ecx, %ecx 00089 sk_l3: 00090 movl %edx, (%eax) 00091 addl $7, (%eax) /*7==PTE_WRITEABLE|PTE_PRESENT|PTE_USER*/ 00092 addl $4, %eax 00093 addl $0x1000, %edx 00094 incl %ecx 00095 /*where does the 0xfe come? we are mapping the area 0xc000_0000-0xf7ff_ffff, of which the page 00096 tables are as big as 1Mib-2kib*/ 00097 cmpl $0xfe, %ecx 00098 jne sk_l3 00099 00100 /*install pgd as pgde 0x3fe*/ 00101 movl %ebx, %eax 00102 addl $PGD, %eax 00103 movl %eax, 0xFF8(%eax) /*FF80_0000 - FFBF_FFFF is filled with the PGD*/ 00104 addl $3, 0xFF8(%eax) /*3==PTE_WRITEABLE|PTE_PRESENT*/ 00105 00106 enable_paging: /*enable paging*/ 00107 mov %eax, %cr3 /*set %cr3 to the phys addr of the PGD saved earlier in %eax*/ 00108 00109 movl %cr0, %eax 00110 orl $0x80000000, %eax /*init paging bit of %cr0*/ 00111 movl %eax, %cr0 00112 00113 ljmp $0x8,$reload_cs 00114 reload_cs: 00115 ret /*return. now paging is up and running with kernel at 3Gb*/ 00116 00117 /*---------------------------------------------------------*/ 00118 .bss 00119 .align 0x1000 00120 /*the page directory*/ 00121 .lcomm PGD, 0x1000 00122 /*these are of 0xc000_0000-0xff7f_ffff, so this makes 1Mib-8Kib*/ 00123 .lcomm KERNEL_PAGE_TABLES, 0xfe000 00124 /*first 4Mib, identity-mapped*/ 00125 .lcomm IDENTITY_PGT, 0x1000 00126 00127 /*********************************************************** 00128 * * 00129 *panalix 0.06 (c) Adrian Panasiuk 2002,3 * 00130 *adek336[at]o2.pl, panalix.prv.pl * 00131 * * 00132 ***********************************************************/