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


Ignore:
Timestamp:
2008-12-31T15:33:29Z (16 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9805cde
Parents:
d8c0dc5
Message:

Humanitarian facelift for ia64.

File:
1 edited

Legend:

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

    rd8c0dc5 r666773c  
    9393/** Invalidate entries belonging to an address space.
    9494 *
    95  * @param asid Address space identifier.
     95 * @param asid          Address space identifier.
    9696 */
    9797void tlb_invalidate_asid(asid_t asid)
     
    132132       
    133133        switch (b) {
    134         case 0: /*cnt 1-3*/
     134        case 0: /* cnt 1 - 3 */
    135135                ps = PAGE_WIDTH;
    136136                break;
    137         case 1: /*cnt 4-15*/
    138                 ps = PAGE_WIDTH+2;
    139                 va &= ~((1<<ps)-1);
    140                 break;
    141         case 2: /*cnt 16-63*/
    142                 ps = PAGE_WIDTH+4;
    143                 va &= ~((1<<ps)-1);
    144                 break;
    145         case 3: /*cnt 64-255*/
    146                 ps = PAGE_WIDTH+6;
    147                 va &= ~((1<<ps)-1);
    148                 break;
    149         case 4: /*cnt 256-1023*/
    150                 ps = PAGE_WIDTH+8;
    151                 va &= ~((1<<ps)-1);
    152                 break;
    153         case 5: /*cnt 1024-4095*/
    154                 ps = PAGE_WIDTH+10;
    155                 va &= ~((1<<ps)-1);
    156                 break;
    157         case 6: /*cnt 4096-16383*/
    158                 ps = PAGE_WIDTH+12;
    159                 va &= ~((1<<ps)-1);
    160                 break;
    161         case 7: /*cnt 16384-65535*/
    162         case 8: /*cnt 65536-(256K-1)*/
    163                 ps = PAGE_WIDTH+14;
    164                 va &= ~((1<<ps)-1);
     137        case 1: /* cnt 4 - 15 */
     138                ps = PAGE_WIDTH + 2;
     139                va &= ~((1 << ps) - 1);
     140                break;
     141        case 2: /* cnt 16 - 63 */
     142                ps = PAGE_WIDTH + 4;
     143                va &= ~((1 << ps) - 1);
     144                break;
     145        case 3: /* cnt 64 - 255 */
     146                ps = PAGE_WIDTH + 6;
     147                va &= ~((1 << ps) - 1);
     148                break;
     149        case 4: /* cnt 256 - 1023 */
     150                ps = PAGE_WIDTH + 8;
     151                va &= ~((1 << ps) - 1);
     152                break;
     153        case 5: /* cnt 1024 - 4095 */
     154                ps = PAGE_WIDTH + 10;
     155                va &= ~((1 << ps) - 1);
     156                break;
     157        case 6: /* cnt 4096 - 16383 */
     158                ps = PAGE_WIDTH + 12;
     159                va &= ~((1 << ps) - 1);
     160                break;
     161        case 7: /* cnt 16384 - 65535 */
     162        case 8: /* cnt 65536 - (256K - 1) */
     163                ps = PAGE_WIDTH + 14;
     164                va &= ~((1 << ps) - 1);
    165165                break;
    166166        default:
    167                 ps=PAGE_WIDTH+18;
    168                 va&=~((1<<ps)-1);
    169                 break;
    170         }
    171         for(; va<(page+cnt*(PAGE_SIZE)); va += (1<<ps)) {
    172                 asm volatile (
    173                         "ptc.l %0,%1;;"
    174                         :
    175                         : "r" (va), "r" (ps<<2)
    176                 );
    177         }
     167                ps = PAGE_WIDTH + 18;
     168                va &= ~((1 << ps) - 1);
     169                break;
     170        }
     171        for(; va < (page + cnt * PAGE_SIZE); va += (1 << ps))
     172                asm volatile ("ptc.l %0, %1;;" :: "r" (va), "r" (ps << 2));
    178173        srlz_d();
    179174        srlz_i();
     
    188183/** Insert data into data translation cache.
    189184 *
    190  * @param va Virtual page address.
    191  * @param asid Address space identifier.
    192  * @param entry The rest of TLB entry as required by TLB insertion format.
     185 * @param va            Virtual page address.
     186 * @param asid          Address space identifier.
     187 * @param entry         The rest of TLB entry as required by TLB insertion
     188 *                      format.
    193189 */
    194190void dtc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry)
     
    199195/** Insert data into instruction translation cache.
    200196 *
    201  * @param va Virtual page address.
    202  * @param asid Address space identifier.
    203  * @param entry The rest of TLB entry as required by TLB insertion format.
     197 * @param va            Virtual page address.
     198 * @param asid          Address space identifier.
     199 * @param entry         The rest of TLB entry as required by TLB insertion
     200 *                      format.
    204201 */
    205202void itc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry)
     
    210207/** Insert data into instruction or data translation cache.
    211208 *
    212  * @param va Virtual page address.
    213  * @param asid Address space identifier.
    214  * @param entry The rest of TLB entry as required by TLB insertion format.
    215  * @param dtc If true, insert into data translation cache, use instruction translation cache otherwise.
     209 * @param va            Virtual page address.
     210 * @param asid          Address space identifier.
     211 * @param entry         The rest of TLB entry as required by TLB insertion
     212 *                      format.
     213 * @param dtc           If true, insert into data translation cache, use
     214 *                      instruction translation cache otherwise.
    216215 */
    217216void tc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtc)
     
    236235       
    237236        asm volatile (
    238                 "mov r8=psr;;\n"
     237                "mov r8 = psr;;\n"
    239238                "rsm %0;;\n"                    /* PSR_IC_MASK */
    240239                "srlz.d;;\n"
    241240                "srlz.i;;\n"
    242                 "mov cr.ifa=%1\n"               /* va */
    243                 "mov cr.itir=%2;;\n"            /* entry.word[1] */
    244                 "cmp.eq p6,p7 = %4,r0;;\n"      /* decide between itc and dtc */ 
     241                "mov cr.ifa = %1\n"             /* va */
     242                "mov cr.itir = %2;;\n"          /* entry.word[1] */
     243                "cmp.eq p6,p7 = %4,r0;;\n"      /* decide between itc and dtc */
    245244                "(p6) itc.i %3;;\n"
    246245                "(p7) itc.d %3;;\n"
    247                 "mov psr.l=r8;;\n"
     246                "mov psr.l = r8;;\n"
    248247                "srlz.d;;\n"
    249248                :
    250                 : "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (dtc)
     249                : "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]),
     250                    "r" (entry.word[0]), "r" (dtc)
    251251                : "p6", "p7", "r8"
    252252        );
     
    261261/** Insert data into instruction translation register.
    262262 *
    263  * @param va Virtual page address.
    264  * @param asid Address space identifier.
    265  * @param entry The rest of TLB entry as required by TLB insertion format.
    266  * @param tr Translation register.
    267  */
    268 void itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
     263 * @param va            Virtual page address.
     264 * @param asid          Address space identifier.
     265 * @param entry         The rest of TLB entry as required by TLB insertion
     266 *                      format.
     267 * @param tr            Translation register.
     268 */
     269void
     270itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
    269271{
    270272        tr_mapping_insert(va, asid, entry, false, tr);
     
    273275/** Insert data into data translation register.
    274276 *
    275  * @param va Virtual page address.
    276  * @param asid Address space identifier.
    277  * @param entry The rest of TLB entry as required by TLB insertion format.
    278  * @param tr Translation register.
    279  */
    280 void dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
     277 * @param va            Virtual page address.
     278 * @param asid          Address space identifier.
     279 * @param entry         The rest of TLB entry as required by TLB insertion
     280 *                      format.
     281 * @param tr            Translation register.
     282 */
     283void
     284dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
    281285{
    282286        tr_mapping_insert(va, asid, entry, true, tr);
     
    285289/** Insert data into instruction or data translation register.
    286290 *
    287  * @param va Virtual page address.
    288  * @param asid Address space identifier.
    289  * @param entry The rest of TLB entry as required by TLB insertion format.
    290  * @param dtr If true, insert into data translation register, use instruction translation register otherwise.
    291  * @param tr Translation register.
    292  */
    293 void tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr, index_t tr)
     291 * @param va            Virtual page address.
     292 * @param asid          Address space identifier.
     293 * @param entry         The rest of TLB entry as required by TLB insertion
     294 *                      format.
     295 * @param dtr           If true, insert into data translation register, use
     296 *                      instruction translation register otherwise.
     297 * @param tr            Translation register.
     298 */
     299void
     300tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr,
     301    index_t tr)
    294302{
    295303        region_register rr;
     
    312320
    313321        asm volatile (
    314                 "mov r8=psr;;\n"
     322                "mov r8 = psr;;\n"
    315323                "rsm %0;;\n"                    /* PSR_IC_MASK */
    316324                "srlz.d;;\n"
    317325                "srlz.i;;\n"
    318                 "mov cr.ifa=%1\n"               /* va */                 
    319                 "mov cr.itir=%2;;\n"            /* entry.word[1] */
    320                 "cmp.eq p6,p7=%5,r0;;\n"        /* decide between itr and dtr */
    321                 "(p6) itr.i itr[%4]=%3;;\n"
    322                 "(p7) itr.d dtr[%4]=%3;;\n"
    323                 "mov psr.l=r8;;\n"
     326                "mov cr.ifa = %1\n"             /* va */                 
     327                "mov cr.itir = %2;;\n"          /* entry.word[1] */
     328                "cmp.eq p6,p7 = %5,r0;;\n"      /* decide between itr and dtr */
     329                "(p6) itr.i itr[%4] = %3;;\n"
     330                "(p7) itr.d dtr[%4] = %3;;\n"
     331                "mov psr.l = r8;;\n"
    324332                "srlz.d;;\n"
    325333                :
    326                 : "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (tr), "r" (dtr)
     334                : "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]),
     335                    "r" (entry.word[0]), "r" (tr), "r" (dtr)
    327336                : "p6", "p7", "r8"
    328337        );
     
    337346/** Insert data into DTLB.
    338347 *
    339  * @param page Virtual page address including VRN bits.
    340  * @param frame Physical frame address.
    341  * @param dtr If true, insert into data translation register, use data translation cache otherwise.
    342  * @param tr Translation register if dtr is true, ignored otherwise.
    343  */
    344 void dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr, index_t tr)
     348 * @param page          Virtual page address including VRN bits.
     349 * @param frame         Physical frame address.
     350 * @param dtr           If true, insert into data translation register, use data
     351 *                      translation cache otherwise.
     352 * @param tr            Translation register if dtr is true, ignored otherwise.
     353 */
     354void
     355dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr,
     356    index_t tr)
    345357{
    346358        tlb_entry_t entry;
     
    368380 * Purge DTR entries used by the kernel.
    369381 *
    370  * @param page Virtual page address including VRN bits.
    371  * @param width Width of the purge in bits.
     382 * @param page          Virtual page address including VRN bits.
     383 * @param width         Width of the purge in bits.
    372384 */
    373385void dtr_purge(uintptr_t page, count_t width)
    374386{
    375         asm volatile ("ptr.d %0, %1\n" : : "r" (page), "r" (width<<2));
     387        asm volatile ("ptr.d %0, %1\n" : : "r" (page), "r" (width << 2));
    376388}
    377389
     
    379391/** Copy content of PTE into data translation cache.
    380392 *
    381  * @param t PTE.
     393 * @param t             PTE.
    382394 */
    383395void dtc_pte_copy(pte_t *t)
     
    405417/** Copy content of PTE into instruction translation cache.
    406418 *
    407  * @param t PTE.
     419 * @param t             PTE.
    408420 */
    409421void itc_pte_copy(pte_t *t)
     
    432444/** Instruction TLB fault handler for faults with VHPT turned off.
    433445 *
    434  * @param vector Interruption vector.
    435  * @param istate Structure with saved interruption state.
     446 * @param vector                Interruption vector.
     447 * @param istate                Structure with saved interruption state.
    436448 */
    437449void alternate_instruction_tlb_fault(uint64_t vector, istate_t *istate)
     
    462474                if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
    463475                        fault_if_from_uspace(istate,"Page fault at %p",va);
    464                         panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
    465                 }
    466         }
    467 }
    468 
    469 
     476                        panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid,
     477                            istate->cr_iip);
     478                }
     479        }
     480}
    470481
    471482static int is_io_page_accessible(int page)
    472483{
    473         if(TASK->arch.iomap) return bitmap_get(TASK->arch.iomap,page);
    474         else return 0;
     484        if (TASK->arch.iomap)
     485                return bitmap_get(TASK->arch.iomap,page);
     486        else
     487                return 0;
    475488}
    476489
    477490#define IO_FRAME_BASE 0xFFFFC000000
    478491
    479 /** There is special handling of memmaped lagacy io, because
    480  * of 4KB sized access
    481  * only for userspace
    482  *
    483  * @param va virtual address of page fault
    484  * @param istate Structure with saved interruption state.
    485  *
    486  *
    487  * @return 1 on success, 0 on fail
     492/**
     493 * There is special handling of memory mapped legacy io, because of 4KB sized
     494 * access for userspace.
     495 *
     496 * @param va            Virtual address of page fault.
     497 * @param istate        Structure with saved interruption state.
     498 *
     499 * @return              One on success, zero on failure.
    488500 */
    489501static int try_memmap_io_insertion(uintptr_t va, istate_t *istate)
    490502{
    491         if((va >= IO_OFFSET ) && (va < IO_OFFSET + (1<<IO_PAGE_WIDTH)))
    492                 if(TASK){
    493                        
    494                         uint64_t io_page=(va &  ((1<<IO_PAGE_WIDTH)-1)) >> (USPACE_IO_PAGE_WIDTH);
    495                         if(is_io_page_accessible(io_page)){
    496                                 uint64_t page,frame;
    497 
    498                                 page = IO_OFFSET + (1 << USPACE_IO_PAGE_WIDTH) * io_page;
    499                                 frame = IO_FRAME_BASE + (1 << USPACE_IO_PAGE_WIDTH) * io_page;
    500 
     503        if ((va >= IO_OFFSET ) && (va < IO_OFFSET + (1 << IO_PAGE_WIDTH))) {
     504                if (TASK) {
     505                        uint64_t io_page = (va & ((1 << IO_PAGE_WIDTH) - 1)) >>
     506                            USPACE_IO_PAGE_WIDTH;
     507
     508                        if (is_io_page_accessible(io_page)) {
     509                                uint64_t page, frame;
     510
     511                                page = IO_OFFSET +
     512                                    (1 << USPACE_IO_PAGE_WIDTH) * io_page;
     513                                frame = IO_FRAME_BASE +
     514                                    (1 << USPACE_IO_PAGE_WIDTH) * io_page;
    501515
    502516                                tlb_entry_t entry;
     
    505519                                entry.word[1] = 0;
    506520       
    507                                 entry.p = true;                 /* present */
     521                                entry.p = true;         /* present */
    508522                                entry.ma = MA_UNCACHEABLE;             
    509                                 entry.a = true;                 /* already accessed */
    510                                 entry.d = true;                 /* already dirty */
     523                                entry.a = true;         /* already accessed */
     524                                entry.d = true;         /* already dirty */
    511525                                entry.pl = PL_USER;
    512526                                entry.ar = AR_READ | AR_WRITE;
     
    516530                                dtc_mapping_insert(page, TASK->as->asid, entry);
    517531                                return 1;
    518                         }else {
    519                                 fault_if_from_uspace(istate,"IO access fault at %p",va);
    520                                 return 0;
    521                         }               
    522                 } else
    523                         return 0;
    524         else
    525                 return 0;
     532                        } else {
     533                                fault_if_from_uspace(istate,
     534                                    "IO access fault at %p", va);
     535                        }
     536                }
     537        }
    526538               
    527539        return 0;
    528 
    529 }
    530 
    531 
    532 
     540}
    533541
    534542/** Data TLB fault handler for faults with VHPT turned off.
    535543 *
    536  * @param vector Interruption vector.
    537  * @param istate Structure with saved interruption state.
     544 * @param vector        Interruption vector.
     545 * @param istate        Structure with saved interruption state.
    538546 */
    539547void alternate_data_tlb_fault(uint64_t vector, istate_t *istate)
     
    569577        } else {
    570578                page_table_unlock(AS, true);
    571                 if (try_memmap_io_insertion(va,istate)) return;
    572                 /*
    573                  * Forward the page fault to the address space page fault handler.
     579                if (try_memmap_io_insertion(va, istate))
     580                        return;
     581                /*
     582                 * Forward the page fault to the address space page fault
     583                 * handler.
    574584                 */
    575585                if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
    576586                        fault_if_from_uspace(istate,"Page fault at %p",va);
    577                         panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
     587                        panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid,
     588                            istate->cr_iip);
    578589                }
    579590        }
     
    584595 * This fault should not occur.
    585596 *
    586  * @param vector Interruption vector.
    587  * @param istate Structure with saved interruption state.
     597 * @param vector        Interruption vector.
     598 * @param istate        Structure with saved interruption state.
    588599 */
    589600void data_nested_tlb_fault(uint64_t vector, istate_t *istate)
     
    594605/** Data Dirty bit fault handler.
    595606 *
    596  * @param vector Interruption vector.
    597  * @param istate Structure with saved interruption state.
     607 * @param vector        Interruption vector.
     608 * @param istate        Structure with saved interruption state.
    598609 */
    599610void data_dirty_bit_fault(uint64_t vector, istate_t *istate)
     
    621632                if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) {
    622633                        fault_if_from_uspace(istate,"Page fault at %p",va);
    623                         panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
    624                         t->d = true;
    625                         dtc_pte_copy(t);
     634                        panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid,
     635                            istate->cr_iip);
    626636                }
    627637        }
     
    631641/** Instruction access bit fault handler.
    632642 *
    633  * @param vector Interruption vector.
    634  * @param istate Structure with saved interruption state.
     643 * @param vector        Interruption vector.
     644 * @param istate        Structure with saved interruption state.
    635645 */
    636646void instruction_access_bit_fault(uint64_t vector, istate_t *istate)
     
    657667        } else {
    658668                if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
    659                         fault_if_from_uspace(istate,"Page fault at %p",va);
    660                         panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
    661                         t->a = true;
    662                         itc_pte_copy(t);
     669                        fault_if_from_uspace(istate, "Page fault at %p", va);
     670                        panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid,
     671                            istate->cr_iip);
    663672                }
    664673        }
     
    694703        } else {
    695704                if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
    696                         fault_if_from_uspace(istate,"Page fault at %p",va);
    697                         panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
    698                         t->a = true;
    699                         itc_pte_copy(t);
     705                        fault_if_from_uspace(istate, "Page fault at %p", va);
     706                        panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid,
     707                            istate->cr_iip);
    700708                }
    701709        }
     
    736744                page_table_unlock(AS, true);
    737745                if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
    738                         fault_if_from_uspace(istate,"Page fault at %p",va);
     746                        fault_if_from_uspace(istate, "Page fault at %p", va);
    739747                        panic("%s: va=%p, rid=%d\n", __func__, va, rid);
    740748                }
Note: See TracChangeset for help on using the changeset viewer.