page.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2004 Jakub Jermar
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00035 #include <arch/mm/page.h>
00036 #include <genarch/mm/page_pt.h>
00037 #include <arch/mm/frame.h>
00038 #include <mm/page.h>
00039 #include <mm/frame.h>
00040 #include <mm/as.h>
00041 #include <arch/interrupt.h>
00042 #include <arch/asm.h>
00043 #include <config.h>
00044 #include <memstr.h>
00045 #include <interrupt.h>
00046 #include <print.h>
00047 #include <panic.h>
00048 #include <align.h>
00049 
00050 /* Definitions for identity page mapper */
00051 pte_t helper_ptl1[512] __attribute__((aligned (PAGE_SIZE)));
00052 pte_t helper_ptl2[512] __attribute__((aligned (PAGE_SIZE)));
00053 pte_t helper_ptl3[512] __attribute__((aligned (PAGE_SIZE)));
00054 extern pte_t ptl_0; /* From boot.S */
00055 
00056 #define PTL1_PRESENT(ptl0, page) (!(GET_PTL1_FLAGS_ARCH(ptl0, PTL0_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
00057 #define PTL2_PRESENT(ptl1, page) (!(GET_PTL2_FLAGS_ARCH(ptl1, PTL1_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
00058 #define PTL3_PRESENT(ptl2, page) (!(GET_PTL3_FLAGS_ARCH(ptl2, PTL2_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
00059 
00060 #define PTL1_ADDR(ptl0, page) ((pte_t *)PA2KA(GET_PTL1_ADDRESS_ARCH(ptl0, PTL0_INDEX_ARCH(page))))
00061 #define PTL2_ADDR(ptl1, page) ((pte_t *)PA2KA(GET_PTL2_ADDRESS_ARCH(ptl1, PTL1_INDEX_ARCH(page))))
00062 #define PTL3_ADDR(ptl2, page) ((pte_t *)PA2KA(GET_PTL3_ADDRESS_ARCH(ptl2, PTL2_INDEX_ARCH(page))))
00063 
00064 #define SETUP_PTL1(ptl0, page, tgt)  {  \
00065         SET_PTL1_ADDRESS_ARCH(ptl0, PTL0_INDEX_ARCH(page), (__address)KA2PA(tgt)); \
00066         SET_PTL1_FLAGS_ARCH(ptl0, PTL0_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
00067     }
00068 #define SETUP_PTL2(ptl1, page, tgt)  {  \
00069         SET_PTL2_ADDRESS_ARCH(ptl1, PTL1_INDEX_ARCH(page), (__address)KA2PA(tgt)); \
00070         SET_PTL2_FLAGS_ARCH(ptl1, PTL1_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
00071     }
00072 #define SETUP_PTL3(ptl2, page, tgt)  {  \
00073         SET_PTL3_ADDRESS_ARCH(ptl2, PTL2_INDEX_ARCH(page), (__address)KA2PA(tgt)); \
00074         SET_PTL3_FLAGS_ARCH(ptl2, PTL2_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
00075     }
00076 #define SETUP_FRAME(ptl3, page, tgt)  { \
00077         SET_FRAME_ADDRESS_ARCH(ptl3, PTL3_INDEX_ARCH(page), (__address)KA2PA(tgt)); \
00078         SET_FRAME_FLAGS_ARCH(ptl3, PTL3_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
00079     }
00080 
00081 
00082 void page_arch_init(void)
00083 {
00084         __address cur;
00085         int i;
00086         int identity_flags = PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL;
00087 
00088         if (config.cpu_active == 1) {
00089                 page_mapping_operations = &pt_mapping_operations;
00090                 
00091                 /*
00092                  * PA2KA(identity) mapping for all frames.
00093                  */
00094                 for (cur = 0; cur < last_frame; cur += FRAME_SIZE) {
00095                         /* Standard identity mapping */
00096                         page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, identity_flags);
00097                 }
00098                 /* Upper kernel mapping
00099                  * - from zero to top of kernel (include bottom addresses
00100                  *   because some are needed for init )
00101                  */
00102                 for (cur = PA2KA_CODE(0); cur < config.base+config.kernel_size; cur += FRAME_SIZE) {
00103                         page_mapping_insert(AS_KERNEL, cur, KA2PA(cur), identity_flags);
00104                 }
00105                 for (i=0; i < init.cnt; i++) {
00106                         for (cur=init.tasks[i].addr;cur < init.tasks[i].size; cur += FRAME_SIZE) {
00107                                 page_mapping_insert(AS_KERNEL, PA2KA_CODE(KA2PA(cur)), KA2PA(cur), identity_flags);
00108                         }
00109                 }
00110 
00111                 exc_register(14, "page_fault", (iroutine)page_fault);
00112                 write_cr3((__address) AS_KERNEL->page_table);
00113         }
00114         else {
00115                 write_cr3((__address) AS_KERNEL->page_table);
00116         }
00117 }
00118 
00119 
00126 void ident_page_fault(int n, istate_t *istate)
00127 {
00128         __address page;
00129         static __address oldpage = 0;
00130         pte_t *aptl_1, *aptl_2, *aptl_3;
00131 
00132         page = read_cr2();
00133         if (oldpage) {
00134                 /* Unmap old address */
00135                 aptl_1 = PTL1_ADDR(&ptl_0, oldpage);
00136                 aptl_2 = PTL2_ADDR(aptl_1, oldpage);
00137                 aptl_3 = PTL3_ADDR(aptl_2, oldpage);
00138 
00139                 SET_FRAME_FLAGS_ARCH(aptl_3, PTL3_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
00140                 if (KA2PA(aptl_3) == KA2PA(helper_ptl3))
00141                         SET_PTL3_FLAGS_ARCH(aptl_2, PTL2_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
00142                 if (KA2PA(aptl_2) == KA2PA(helper_ptl2))
00143                         SET_PTL2_FLAGS_ARCH(aptl_1, PTL1_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
00144                 if (KA2PA(aptl_1) == KA2PA(helper_ptl1))
00145                         SET_PTL1_FLAGS_ARCH(&ptl_0, PTL0_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
00146         }
00147         if (PTL1_PRESENT(&ptl_0, page))
00148                 aptl_1 = PTL1_ADDR(&ptl_0, page);
00149         else {
00150                 SETUP_PTL1(&ptl_0, page, helper_ptl1);
00151                 aptl_1 = helper_ptl1;
00152         }
00153             
00154         if (PTL2_PRESENT(aptl_1, page)) 
00155                 aptl_2 = PTL2_ADDR(aptl_1, page);
00156         else {
00157                 SETUP_PTL2(aptl_1, page, helper_ptl2);
00158                 aptl_2 = helper_ptl2;
00159         }
00160 
00161         if (PTL3_PRESENT(aptl_2, page))
00162                 aptl_3 = PTL3_ADDR(aptl_2, page);
00163         else {
00164                 SETUP_PTL3(aptl_2, page, helper_ptl3);
00165                 aptl_3 = helper_ptl3;
00166         }
00167         
00168         SETUP_FRAME(aptl_3, page, page);
00169 
00170         oldpage = page;
00171 }
00172 
00173 
00174 void page_fault(int n, istate_t *istate)
00175 {
00176         __address page;
00177         pf_access_t access;
00178         
00179         page = read_cr2();
00180         
00181         if (istate->error_word & PFERR_CODE_RSVD)
00182                 panic("Reserved bit set in page table entry.\n");
00183         
00184         if (istate->error_word & PFERR_CODE_RW)
00185                 access = PF_ACCESS_WRITE;
00186         else if (istate->error_word & PFERR_CODE_ID)
00187                 access = PF_ACCESS_EXEC;
00188         else
00189                 access = PF_ACCESS_READ;
00190         
00191         if (as_page_fault(page, access, istate) == AS_PF_FAULT) {
00192                 fault_if_from_uspace(istate, "Page fault: %#x", page);
00193 
00194                 print_info_errcode(n, istate);
00195                 printf("Page fault address: %llx\n", page);
00196                 panic("page fault\n");
00197         }
00198 }
00199 
00200 
00201 __address hw_map(__address physaddr, size_t size)
00202 {
00203         if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
00204                 panic("Unable to map physical memory %p (%d bytes)", physaddr, size)
00205         
00206         __address virtaddr = PA2KA(last_frame);
00207         pfn_t i;
00208         for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++)
00209                 page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE);
00210         
00211         last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
00212         
00213         return virtaddr;
00214 }
00215 

Generated on Sun Jun 18 16:26:58 2006 for HelenOS Kernel (amd64) by  doxygen 1.4.6