Changeset 36f19c0 in mainline


Ignore:
Timestamp:
2007-04-09T16:21:47Z (18 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ec5b3204
Parents:
183788f1
Message:

Fix a nasty bug in the TLB miss handlers on sparc64.
After we no longer lock the kernel stack in the DTLB,
there is a real danger of nested DTLB misses. The nested
miss can very easily clobber the DTLB Tag Access register.
Therefore, the original miss may not read this register, but
it has to receive its value as an argument. The argument
value is saved in the trap table when it is guaranteed that
the nested TLB miss will not occur.

Location:
kernel/arch/sparc64
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/sparc64/include/mm/tlb.h

    r183788f1 r36f19c0  
    429429}
    430430
    431 extern void fast_instruction_access_mmu_miss(int n, istate_t *istate);
    432 extern void fast_data_access_mmu_miss(int n, istate_t *istate);
    433 extern void fast_data_access_protection(int n, istate_t *istate);
     431extern void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate);
     432extern void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate);
     433extern void fast_data_access_protection(tlb_tag_access_reg_t tag , istate_t *istate);
    434434
    435435extern void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize, bool locked, bool cacheable);
  • kernel/arch/sparc64/include/trap/mmu.h

    r183788f1 r36f19c0  
    130130.endif
    131131
     132        /*
     133         * Switch from the MM globals.
     134         */
    132135        wrpr %g0, PSTATE_PRIV_BIT | PSTATE_AG_BIT, %pstate
     136
     137        /*
     138         * Read the Tag Access register for the higher-level handler.
     139         * This is necessary to survive nested DTLB misses.
     140         */     
     141        mov VA_DMMU_TAG_ACCESS, %g2
     142        ldxa [%g2] ASI_DMMU, %g2
     143
     144        /*
     145         * g2 will be passed as an argument to fast_data_access_mmu_miss().
     146         */
    133147        PREEMPTIBLE_HANDLER fast_data_access_mmu_miss
    134148.endm
     
    143157.endif
    144158
     159        /*
     160         * Switch from the MM globals.
     161         */
    145162        wrpr %g0, PSTATE_PRIV_BIT | PSTATE_AG_BIT, %pstate
     163
     164        /*
     165         * Read the Tag Access register for the higher-level handler.
     166         * This is necessary to survive nested DTLB misses.
     167         */     
     168        mov VA_DMMU_TAG_ACCESS, %g2
     169        ldxa [%g2] ASI_DMMU, %g2
     170
     171        /*
     172         * g2 will be passed as an argument to fast_data_access_mmu_miss().
     173         */
    146174        PREEMPTIBLE_HANDLER fast_data_access_protection
    147175.endm
  • kernel/arch/sparc64/src/mm/tlb.c

    r183788f1 r36f19c0  
    199199
    200200/** ITLB miss handler. */
    201 void fast_instruction_access_mmu_miss(int n, istate_t *istate)
     201void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate)
    202202{
    203203        uintptr_t va = ALIGN_DOWN(istate->tpc, PAGE_SIZE);
     
    235235 * Note that some faults (e.g. kernel faults) were already resolved by the
    236236 * low-level, assembly language part of the fast_data_access_mmu_miss handler.
    237  */
    238 void fast_data_access_mmu_miss(int n, istate_t *istate)
    239 {
    240         tlb_tag_access_reg_t tag;
     237 *
     238 * @param tag Content of the TLB Tag Access register as it existed when the
     239 *    trap happened. This is to prevent confusion created by clobbered
     240 *    Tag Access register during a nested DTLB miss.
     241 * @param istate Interrupted state saved on the stack.
     242 */
     243void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate)
     244{
    241245        uintptr_t va;
    242246        index_t index;
    243247        pte_t *t;
    244248
    245         tag.value = dtlb_tag_access_read();
    246249        va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE);
    247250        index = tag.vpn % MMU_PAGES_PER_PAGE;
     
    283286}
    284287
    285 /** DTLB protection fault handler. */
    286 void fast_data_access_protection(int n, istate_t *istate)
    287 {
    288         tlb_tag_access_reg_t tag;
     288/** DTLB protection fault handler.
     289 *
     290 * @param tag Content of the TLB Tag Access register as it existed when the
     291 *    trap happened. This is to prevent confusion created by clobbered
     292 *    Tag Access register during a nested DTLB miss.
     293 * @param istate Interrupted state saved on the stack.
     294 */
     295void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate)
     296{
    289297        uintptr_t va;
    290298        index_t index;
    291299        pte_t *t;
    292300
    293         tag.value = dtlb_tag_access_read();
    294301        va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE);
    295302        index = tag.vpn % MMU_PAGES_PER_PAGE;   /* 16K-page emulation */
     
    372379
    373380        va = tag.vpn << MMU_PAGE_WIDTH;
    374 
    375         fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va,
    376             tag.context);
     381        if (tag.context) {
     382                fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va,
     383                    tag.context);
     384        }
    377385        dump_istate(istate);
    378386        printf("Faulting page: %p, ASID=%d\n", va, tag.context);
     
    387395        va = tag.vpn << MMU_PAGE_WIDTH;
    388396
    389         fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va,
    390             tag.context);
     397        if (tag.context) {
     398                fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va,
     399                    tag.context);
     400        }
    391401        printf("Faulting page: %p, ASID=%d\n", va, tag.context);
    392402        dump_istate(istate);
Note: See TracChangeset for help on using the changeset viewer.