Ignore:
File:
1 edited

Legend:

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

    rc15b374 rfabc883  
    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                
    58                 page_table_lock(AS_KERNEL, true);
    59                
     90
    6091                /*
    6192                 * PA2KA(identity) mapping for all frames.
    6293                 */
    63                 for (cur = 0; cur < last_frame; cur += FRAME_SIZE)
     94                for (cur = 0; cur < last_frame; cur += FRAME_SIZE) {
     95                        /* Standard identity mapping */
    6496                        page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, identity_flags);
     97                }
    6598               
    66                 page_table_unlock(AS_KERNEL, true);
     99                /* Upper kernel mapping
     100                 * - from zero to top of kernel (include bottom addresses
     101                 *   because some are needed for init)
     102                 */
     103                for (cur = PA2KA_CODE(0); cur < config.base + config.kernel_size; cur += FRAME_SIZE)
     104                        page_mapping_insert(AS_KERNEL, cur, KA2PA(cur), identity_flags);
    67105               
    68                 exc_register(14, "page_fault", true, (iroutine_t) page_fault);
     106                for (cur = config.stack_base; cur < config.stack_base + config.stack_size; cur += FRAME_SIZE)
     107                        page_mapping_insert(AS_KERNEL, cur, KA2PA(cur), identity_flags);
     108               
     109                for (i = 0; i < init.cnt; i++) {
     110                        for (cur = init.tasks[i].addr; cur < init.tasks[i].addr + init.tasks[i].size; cur += FRAME_SIZE)
     111                                page_mapping_insert(AS_KERNEL, PA2KA_CODE(KA2PA(cur)), KA2PA(cur), identity_flags);
     112                }
     113
     114                exc_register(14, "page_fault", (iroutine) page_fault);
    69115                write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
    70         } else
     116        } else 
    71117                write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
    72118}
    73119
    74 void page_fault(unsigned int n, istate_t *istate)
    75 {
    76         uintptr_t page = read_cr2();
     120
     121/** Identity page mapper
     122 *
     123 * We need to map whole physical memory identically before the page subsystem
     124 * is initializaed. This thing clears page table and fills in the specific
     125 * items.
     126 */
     127void ident_page_fault(int n, istate_t *istate)
     128{
     129        uintptr_t page;
     130        static uintptr_t oldpage = 0;
     131        pte_t *aptl_1, *aptl_2, *aptl_3;
     132
     133        page = read_cr2();
     134        if (oldpage) {
     135                /* Unmap old address */
     136                aptl_1 = PTL1_ADDR(&ptl_0, oldpage);
     137                aptl_2 = PTL2_ADDR(aptl_1, oldpage);
     138                aptl_3 = PTL3_ADDR(aptl_2, oldpage);
     139
     140                SET_FRAME_FLAGS_ARCH(aptl_3, PTL3_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
     141                if (KA2PA(aptl_3) == KA2PA(helper_ptl3))
     142                        SET_PTL3_FLAGS_ARCH(aptl_2, PTL2_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
     143                if (KA2PA(aptl_2) == KA2PA(helper_ptl2))
     144                        SET_PTL2_FLAGS_ARCH(aptl_1, PTL1_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
     145                if (KA2PA(aptl_1) == KA2PA(helper_ptl1))
     146                        SET_PTL1_FLAGS_ARCH(&ptl_0, PTL0_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
     147        }
     148        if (PTL1_PRESENT(&ptl_0, page))
     149                aptl_1 = PTL1_ADDR(&ptl_0, page);
     150        else {
     151                SETUP_PTL1(&ptl_0, page, helper_ptl1);
     152                aptl_1 = helper_ptl1;
     153        }
     154           
     155        if (PTL2_PRESENT(aptl_1, page))
     156                aptl_2 = PTL2_ADDR(aptl_1, page);
     157        else {
     158                SETUP_PTL2(aptl_1, page, helper_ptl2);
     159                aptl_2 = helper_ptl2;
     160        }
     161
     162        if (PTL3_PRESENT(aptl_2, page))
     163                aptl_3 = PTL3_ADDR(aptl_2, page);
     164        else {
     165                SETUP_PTL3(aptl_2, page, helper_ptl3);
     166                aptl_3 = helper_ptl3;
     167        }
     168       
     169        SETUP_FRAME(aptl_3, page, page);
     170
     171        oldpage = page;
     172}
     173
     174
     175void page_fault(int n, istate_t *istate)
     176{
     177        uintptr_t page;
     178        pf_access_t access;
     179       
     180        page = read_cr2();
    77181       
    78182        if (istate->error_word & PFERR_CODE_RSVD)
    79183                panic("Reserved bit set in page table entry.");
    80        
    81         pf_access_t access;
    82184       
    83185        if (istate->error_word & PFERR_CODE_RW)
     
    90192        if (as_page_fault(page, access, istate) == AS_PF_FAULT) {
    91193                fault_if_from_uspace(istate, "Page fault: %#x.", page);
    92                 panic_memtrap(istate, access, page, NULL);
    93         }
    94 }
     194
     195                decode_istate(n, istate);
     196                printf("Page fault address: %llx.\n", page);
     197                panic("Page fault.");
     198        }
     199}
     200
    95201
    96202uintptr_t hw_map(uintptr_t physaddr, size_t size)
    97203{
    98204        if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
    99                 panic("Unable to map physical memory %p (%" PRIs " bytes).", physaddr,
     205                panic("Unable to map physical memory %p (%d bytes).", physaddr,
    100206                    size);
    101207       
    102208        uintptr_t virtaddr = PA2KA(last_frame);
    103209        pfn_t i;
    104        
    105         page_table_lock(AS_KERNEL, true);
    106        
    107210        for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++)
    108211                page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE);
    109212       
    110         page_table_unlock(AS_KERNEL, true);
    111        
    112213        last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
    113214       
Note: See TracChangeset for help on using the changeset viewer.