Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/amd64/src/mm/page.c

    r64f6ef04 ra043e39  
    3939#include <mm/frame.h>
    4040#include <mm/as.h>
     41#include <arch/interrupt.h>
    4142#include <arch/asm.h>
    4243#include <config.h>
     
    4748#include <align.h>
    4849
     50/* Definitions for identity page mapper */
     51pte_t helper_ptl1[512] __attribute__((aligned (PAGE_SIZE)));
     52pte_t helper_ptl2[512] __attribute__((aligned (PAGE_SIZE)));
     53pte_t helper_ptl3[512] __attribute__((aligned (PAGE_SIZE)));
     54extern pte_t ptl_0; /* From boot.S */
     55
     56#define PTL1_PRESENT(ptl0, page) (!(GET_PTL1_FLAGS_ARCH(ptl0, PTL0_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
     57#define PTL2_PRESENT(ptl1, page) (!(GET_PTL2_FLAGS_ARCH(ptl1, PTL1_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
     58#define PTL3_PRESENT(ptl2, page) (!(GET_PTL3_FLAGS_ARCH(ptl2, PTL2_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
     59
     60#define PTL1_ADDR(ptl0, page) ((pte_t *)PA2KA(GET_PTL1_ADDRESS_ARCH(ptl0, PTL0_INDEX_ARCH(page))))
     61#define PTL2_ADDR(ptl1, page) ((pte_t *)PA2KA(GET_PTL2_ADDRESS_ARCH(ptl1, PTL1_INDEX_ARCH(page))))
     62#define PTL3_ADDR(ptl2, page) ((pte_t *)PA2KA(GET_PTL3_ADDRESS_ARCH(ptl2, PTL2_INDEX_ARCH(page))))
     63
     64#define SETUP_PTL1(ptl0, page, tgt)  {  \
     65        SET_PTL1_ADDRESS_ARCH(ptl0, PTL0_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \
     66        SET_PTL1_FLAGS_ARCH(ptl0, PTL0_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
     67    }
     68#define SETUP_PTL2(ptl1, page, tgt)  {  \
     69        SET_PTL2_ADDRESS_ARCH(ptl1, PTL1_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \
     70        SET_PTL2_FLAGS_ARCH(ptl1, PTL1_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
     71    }
     72#define SETUP_PTL3(ptl2, page, tgt)  {  \
     73        SET_PTL3_ADDRESS_ARCH(ptl2, PTL2_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \
     74        SET_PTL3_FLAGS_ARCH(ptl2, PTL2_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
     75    }
     76#define SETUP_FRAME(ptl3, page, tgt)  { \
     77        SET_FRAME_ADDRESS_ARCH(ptl3, PTL3_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \
     78        SET_FRAME_FLAGS_ARCH(ptl3, PTL3_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
     79    }
     80
     81
    4982void page_arch_init(void)
    5083{
     84        uintptr_t cur;
     85        unsigned int i;
     86        int identity_flags = PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL | PAGE_WRITE;
     87
    5188        if (config.cpu_active == 1) {
    52                 uintptr_t cur;
    53                 unsigned int identity_flags =
    54                     PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL | PAGE_WRITE;
    55                
    5689                page_mapping_operations = &pt_mapping_operations;
    57                
     90
    5891                page_table_lock(AS_KERNEL, true);
    59                
     92
    6093                /*
    6194                 * PA2KA(identity) mapping for all frames.
    6295                 */
    63                 for (cur = 0; cur < last_frame; cur += FRAME_SIZE)
     96                for (cur = 0; cur < last_frame; cur += FRAME_SIZE) {
     97                        /* Standard identity mapping */
    6498                        page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, identity_flags);
     99                }
    65100               
     101                /* Upper kernel mapping
     102                 * - from zero to top of kernel (include bottom addresses
     103                 *   because some are needed for init)
     104                 */
     105                for (cur = PA2KA_CODE(0); cur < config.base + config.kernel_size; cur += FRAME_SIZE)
     106                        page_mapping_insert(AS_KERNEL, cur, KA2PA(cur), identity_flags);
     107               
     108                for (cur = config.stack_base; cur < config.stack_base + config.stack_size; cur += FRAME_SIZE)
     109                        page_mapping_insert(AS_KERNEL, cur, KA2PA(cur), identity_flags);
     110               
     111                for (i = 0; i < init.cnt; i++) {
     112                        for (cur = init.tasks[i].addr; cur < init.tasks[i].addr + init.tasks[i].size; cur += FRAME_SIZE)
     113                                page_mapping_insert(AS_KERNEL, PA2KA_CODE(KA2PA(cur)), KA2PA(cur), identity_flags);
     114                }
     115
    66116                page_table_unlock(AS_KERNEL, true);
    67                
     117
    68118                exc_register(14, "page_fault", true, (iroutine_t) page_fault);
    69119                write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
     
    72122}
    73123
     124
     125/** Identity page mapper
     126 *
     127 * We need to map whole physical memory identically before the page subsystem
     128 * is initializaed. This thing clears page table and fills in the specific
     129 * items.
     130 */
     131void ident_page_fault(unsigned int n, istate_t *istate)
     132{
     133        uintptr_t page;
     134        static uintptr_t oldpage = 0;
     135        pte_t *aptl_1, *aptl_2, *aptl_3;
     136
     137        page = read_cr2();
     138        if (oldpage) {
     139                /* Unmap old address */
     140                aptl_1 = PTL1_ADDR(&ptl_0, oldpage);
     141                aptl_2 = PTL2_ADDR(aptl_1, oldpage);
     142                aptl_3 = PTL3_ADDR(aptl_2, oldpage);
     143
     144                SET_FRAME_FLAGS_ARCH(aptl_3, PTL3_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
     145                if (KA2PA(aptl_3) == KA2PA(helper_ptl3))
     146                        SET_PTL3_FLAGS_ARCH(aptl_2, PTL2_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
     147                if (KA2PA(aptl_2) == KA2PA(helper_ptl2))
     148                        SET_PTL2_FLAGS_ARCH(aptl_1, PTL1_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
     149                if (KA2PA(aptl_1) == KA2PA(helper_ptl1))
     150                        SET_PTL1_FLAGS_ARCH(&ptl_0, PTL0_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
     151        }
     152        if (PTL1_PRESENT(&ptl_0, page))
     153                aptl_1 = PTL1_ADDR(&ptl_0, page);
     154        else {
     155                SETUP_PTL1(&ptl_0, page, helper_ptl1);
     156                aptl_1 = helper_ptl1;
     157        }
     158           
     159        if (PTL2_PRESENT(aptl_1, page))
     160                aptl_2 = PTL2_ADDR(aptl_1, page);
     161        else {
     162                SETUP_PTL2(aptl_1, page, helper_ptl2);
     163                aptl_2 = helper_ptl2;
     164        }
     165
     166        if (PTL3_PRESENT(aptl_2, page))
     167                aptl_3 = PTL3_ADDR(aptl_2, page);
     168        else {
     169                SETUP_PTL3(aptl_2, page, helper_ptl3);
     170                aptl_3 = helper_ptl3;
     171        }
     172       
     173        SETUP_FRAME(aptl_3, page, page);
     174
     175        oldpage = page;
     176}
     177
     178
    74179void page_fault(unsigned int n, istate_t *istate)
    75180{
    76         uintptr_t page = read_cr2();
     181        uintptr_t page;
     182        pf_access_t access;
     183       
     184        page = read_cr2();
    77185       
    78186        if (istate->error_word & PFERR_CODE_RSVD)
    79187                panic("Reserved bit set in page table entry.");
    80        
    81         pf_access_t access;
    82188       
    83189        if (istate->error_word & PFERR_CODE_RW)
     
    89195       
    90196        if (as_page_fault(page, access, istate) == AS_PF_FAULT) {
    91                 fault_if_from_uspace(istate, "Page fault: %p.", page);
    92                 decode_istate(n, istate);
    93                 panic("Page fault: %p", page);
    94         }
    95 }
     197                fault_if_from_uspace(istate, "Page fault: %#x.", page);
     198                panic_memtrap(istate, access, page, "Page fault.");
     199        }
     200}
     201
    96202
    97203uintptr_t hw_map(uintptr_t physaddr, size_t size)
    98204{
    99205        if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
    100                 panic("Unable to map physical memory %p (%" PRIs " bytes).", physaddr,
     206                panic("Unable to map physical memory %p (%d bytes).", physaddr,
    101207                    size);
    102208       
    103209        uintptr_t virtaddr = PA2KA(last_frame);
    104210        pfn_t i;
    105        
     211
    106212        page_table_lock(AS_KERNEL, true);
    107        
    108213        for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++)
    109214                page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE);
    110        
    111215        page_table_unlock(AS_KERNEL, true);
    112216       
Note: See TracChangeset for help on using the changeset viewer.