Changeset c520034 in mainline for kernel/arch/ia64/src/mm/tlb.c


Ignore:
Timestamp:
2011-12-31T18:19:35Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
295f658, 77c2b02, 96cd5b4
Parents:
852052d (diff), 22f0561 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Support for kernel non-identity mappings, phase I.

  • identity/non-identity kernel memory split on all architectures
  • low/high physical memory split on all architectures
  • frame allocator understands low/high memory
  • high physical memory currently unused (Phase II)
  • more compact frame_t
  • zone conf frames, pte_t, kernel stacks allocated from low memory
  • lockless TLB-miss handlers everywhere (newly sparc64, ia64)
  • preallocate PTL1 page tables for non-identity and prevent their deallocation
  • hw_map() unification
  • new resource allocator used for allocating kernel virtual addresses

Breakage:

  • sparc64/sun4v creates too large kernel identity; not fixed because of lack of testing hw
  • ppc32's tlb_refill() seems wrong as it creates too large kernel identity, but appears unused and the architecture works normally

Not implemented yet (phase II):

  • allow high memory to be used for common kernel allocations
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/ia64/src/mm/tlb.c

    r852052d rc520034  
    5252#include <arch.h>
    5353#include <interrupt.h>
    54 
    55 #define IO_FRAME_BASE 0xFFFFC000000
     54#include <arch/legacyio.h>
    5655
    5756/** Invalidate all TLB entries. */
     
    467466}
    468467
     468static bool is_kernel_fault(uintptr_t va)
     469{
     470        region_register_t rr;
     471
     472        rr.word = rr_read(VA2VRN(va));
     473        rid_t rid = rr.map.rid;
     474        return (RID2ASID(rid) == ASID_KERNEL) && (VA2VRN(va) == VRN_KERNEL);
     475}
     476
    469477/** Instruction TLB fault handler for faults with VHPT turned off.
    470478 *
     
    480488        va = istate->cr_ifa; /* faulting address */
    481489       
    482         page_table_lock(AS, true);
     490        ASSERT(!is_kernel_fault(va));
     491
    483492        t = page_mapping_find(AS, va, true);
    484493        if (t) {
     
    488497                 */
    489498                itc_pte_copy(t);
    490                 page_table_unlock(AS, true);
    491499        } else {
    492500                /*
    493501                 * Forward the page fault to address space page fault handler.
    494502                 */
    495                 page_table_unlock(AS, true);
    496503                if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
    497504                        fault_if_from_uspace(istate, "Page fault at %p.",
     
    522529static int try_memmap_io_insertion(uintptr_t va, istate_t *istate)
    523530{
    524         if ((va >= IO_OFFSET ) && (va < IO_OFFSET + (1 << IO_PAGE_WIDTH))) {
     531        if ((va >= LEGACYIO_USER_BASE) && (va < LEGACYIO_USER_BASE + (1 << LEGACYIO_PAGE_WIDTH))) {
    525532                if (TASK) {
    526                         uint64_t io_page = (va & ((1 << IO_PAGE_WIDTH) - 1)) >>
    527                             USPACE_IO_PAGE_WIDTH;
     533                        uint64_t io_page = (va & ((1 << LEGACYIO_PAGE_WIDTH) - 1)) >>
     534                            LEGACYIO_SINGLE_PAGE_WIDTH;
    528535                       
    529536                        if (is_io_page_accessible(io_page)) {
    530537                                uint64_t page, frame;
    531538                               
    532                                 page = IO_OFFSET +
    533                                     (1 << USPACE_IO_PAGE_WIDTH) * io_page;
    534                                 frame = IO_FRAME_BASE +
    535                                     (1 << USPACE_IO_PAGE_WIDTH) * io_page;
     539                                page = LEGACYIO_USER_BASE +
     540                                    (1 << LEGACYIO_SINGLE_PAGE_WIDTH) * io_page;
     541                                frame = LEGACYIO_PHYS_BASE +
     542                                    (1 << LEGACYIO_SINGLE_PAGE_WIDTH) * io_page;
    536543                               
    537544                                tlb_entry_t entry;
     
    547554                                entry.ar = AR_READ | AR_WRITE;
    548555                                entry.ppn = frame >> PPN_SHIFT;
    549                                 entry.ps = USPACE_IO_PAGE_WIDTH;
     556                                entry.ps = LEGACYIO_SINGLE_PAGE_WIDTH;
    550557                               
    551558                                dtc_mapping_insert(page, TASK->as->asid, entry);
     
    570577{
    571578        if (istate->cr_isr.sp) {
    572                 /* Speculative load. Deffer the exception
    573                    until a more clever approach can be used.
    574                   
    575                    Currently if we try to find the mapping
    576                    for the speculative load while in the kernel,
    577                    we might introduce a livelock because of
    578                    the possibly invalid values of the address. */
     579                /*
     580                 * Speculative load. Deffer the exception until a more clever
     581                 * approach can be used. Currently if we try to find the
     582                 * mapping for the speculative load while in the kernel, we
     583                 * might introduce a livelock because of the possibly invalid
     584                 * values of the address.
     585                 */
    579586                istate->cr_ipsr.ed = true;
    580587                return;
     
    582589       
    583590        uintptr_t va = istate->cr_ifa;  /* faulting address */
    584        
    585         region_register_t rr;
    586         rr.word = rr_read(VA2VRN(va));
    587         rid_t rid = rr.map.rid;
    588         if (RID2ASID(rid) == ASID_KERNEL) {
    589                 if (VA2VRN(va) == VRN_KERNEL) {
     591        as_t *as = AS;
     592       
     593        if (is_kernel_fault(va)) {
     594                if (va < end_of_identity) {
    590595                        /*
    591                          * Provide KA2PA(identity) mapping for faulting piece of
    592                          * kernel address space.
     596                         * Create kernel identity mapping for low memory.
    593597                         */
    594598                        dtlb_kernel_mapping_insert(va, KA2PA(va), false, 0);
    595599                        return;
     600                } else {
     601                        as = AS_KERNEL;
    596602                }
    597603        }
    598604       
    599605       
    600         page_table_lock(AS, true);
    601         pte_t *entry = page_mapping_find(AS, va, true);
     606        pte_t *entry = page_mapping_find(as, va, true);
    602607        if (entry) {
    603608                /*
     
    606611                 */
    607612                dtc_pte_copy(entry);
    608                 page_table_unlock(AS, true);
    609613        } else {
    610                 page_table_unlock(AS, true);
    611614                if (try_memmap_io_insertion(va, istate))
    612615                        return;
     
    647650        uintptr_t va;
    648651        pte_t *t;
     652        as_t *as = AS;
    649653       
    650654        va = istate->cr_ifa;  /* faulting address */
    651655       
    652         page_table_lock(AS, true);
    653         t = page_mapping_find(AS, va, true);
     656        if (is_kernel_fault(va))
     657                as = AS_KERNEL;
     658
     659        t = page_mapping_find(as, va, true);
    654660        ASSERT((t) && (t->p));
    655661        if ((t) && (t->p) && (t->w)) {
     
    667673                }
    668674        }
    669         page_table_unlock(AS, true);
    670675}
    671676
     
    682687       
    683688        va = istate->cr_ifa;  /* faulting address */
    684        
    685         page_table_lock(AS, true);
     689
     690        ASSERT(!is_kernel_fault(va));
     691       
    686692        t = page_mapping_find(AS, va, true);
    687693        ASSERT((t) && (t->p));
     
    700706                }
    701707        }
    702         page_table_unlock(AS, true);
    703708}
    704709
     
    713718        uintptr_t va;
    714719        pte_t *t;
     720        as_t *as = AS;
    715721       
    716722        va = istate->cr_ifa;  /* faulting address */
    717723       
    718         page_table_lock(AS, true);
    719         t = page_mapping_find(AS, va, true);
     724        if (is_kernel_fault(va))
     725                as = AS_KERNEL;
     726
     727        t = page_mapping_find(as, va, true);
    720728        ASSERT((t) && (t->p));
    721729        if ((t) && (t->p)) {
     
    733741                }
    734742        }
    735         page_table_unlock(AS, true);
    736743}
    737744
     
    748755       
    749756        va = istate->cr_ifa;  /* faulting address */
     757
     758        ASSERT(!is_kernel_fault(va));
    750759       
    751760        /*
    752761         * Assume a write to a read-only page.
    753762         */
    754         page_table_lock(AS, true);
    755763        t = page_mapping_find(AS, va, true);
    756764        ASSERT((t) && (t->p));
     
    761769                panic_memtrap(istate, PF_ACCESS_WRITE, va, NULL);
    762770        }
    763         page_table_unlock(AS, true);
    764771}
    765772
     
    777784        va = istate->cr_ifa;  /* faulting address */
    778785       
    779         page_table_lock(AS, true);
     786        ASSERT(!is_kernel_fault(va));
     787
    780788        t = page_mapping_find(AS, va, true);
    781789        ASSERT(t);
     
    790798                else
    791799                        dtc_pte_copy(t);
    792                 page_table_unlock(AS, true);
    793800        } else {
    794                 page_table_unlock(AS, true);
    795801                if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
    796802                        fault_if_from_uspace(istate, "Page fault at %p.",
Note: See TracChangeset for help on using the changeset viewer.