Changeset a7961271 in mainline for kernel/arch/sparc64/src


Ignore:
Timestamp:
2006-08-26T18:42:11Z (19 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c8ea4a8b
Parents:
f47fd19
Message:

sparc64 work.
Bunch of changes in preparation for sparc64 mm and userspace support.
Fix alignment of hardcoded_* variables in linker script.

Location:
kernel/arch/sparc64/src
Files:
3 edited

Legend:

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

    rf47fd19 ra7961271  
    5151#include <symtab.h>
    5252
    53 static void dtlb_pte_copy(pte_t *t);
     53static void dtlb_pte_copy(pte_t *t, bool ro);
     54static void itlb_pte_copy(pte_t *t);
    5455static void do_fast_data_access_mmu_miss_fault(istate_t *istate, const char *str);
     56static void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, const char *str);
    5557
    5658char *context_encoding[] = {
     
    106108}
    107109
    108 void dtlb_pte_copy(pte_t *t)
    109 {
     110/** Copy PTE to TLB.
     111 *
     112 * @param t Page Table Entry to be copied.
     113 * @param ro If true, the entry will be created read-only, regardless of its w field.
     114 */
     115void dtlb_pte_copy(pte_t *t, bool ro)
     116{
     117        tlb_tag_access_reg_t tag;
     118        tlb_data_t data;
     119        page_address_t pg;
     120        frame_address_t fr;
     121
     122        pg.address = t->page;
     123        fr.address = t->frame;
     124
     125        tag.value = 0;
     126        tag.context = t->as->asid;
     127        tag.vpn = pg.vpn;
     128       
     129        dtlb_tag_access_write(tag.value);
     130       
     131        data.value = 0;
     132        data.v = true;
     133        data.size = PAGESIZE_8K;
     134        data.pfn = fr.pfn;
     135        data.l = false;
     136        data.cp = t->c;
     137        data.cv = t->c;
     138        data.p = t->p;
     139        data.w = ro ? false : t->w;
     140        data.g = t->g;
     141       
     142        dtlb_data_in_write(data.value);
     143}
     144
     145void itlb_pte_copy(pte_t *t)
     146{
     147        tlb_tag_access_reg_t tag;
     148        tlb_data_t data;
     149        page_address_t pg;
     150        frame_address_t fr;
     151
     152        pg.address = t->page;
     153        fr.address = t->frame;
     154
     155        tag.value = 0;
     156        tag.context = t->as->asid;
     157        tag.vpn = pg.vpn;
     158       
     159        itlb_tag_access_write(tag.value);
     160       
     161        data.value = 0;
     162        data.v = true;
     163        data.size = PAGESIZE_8K;
     164        data.pfn = fr.pfn;
     165        data.l = false;
     166        data.cp = t->c;
     167        data.cv = t->c;
     168        data.p = t->p;
     169        data.w = false;
     170        data.g = t->g;
     171       
     172        itlb_data_in_write(data.value);
    110173}
    111174
     
    113176void fast_instruction_access_mmu_miss(int n, istate_t *istate)
    114177{
    115         panic("%s\n", __FUNCTION__);
     178        uintptr_t va = ALIGN_DOWN(istate->tpc, PAGE_SIZE);
     179        pte_t *t;
     180
     181        page_table_lock(AS, true);
     182        t = page_mapping_find(AS, va);
     183        if (t && PTE_EXECUTABLE(t)) {
     184                /*
     185                 * The mapping was found in the software page hash table.
     186                 * Insert it into ITLB.
     187                 */
     188                t->a = true;
     189                itlb_pte_copy(t);
     190                page_table_unlock(AS, true);
     191        } else {
     192                /*
     193                 * Forward the page fault to the address space page fault handler.
     194                 */             
     195                page_table_unlock(AS, true);
     196                if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
     197                        do_fast_instruction_access_mmu_miss_fault(istate, __FUNCTION__);
     198                }
     199        }
    116200}
    117201
     
    145229                 * Insert it into DTLB.
    146230                 */
    147                 dtlb_pte_copy(t);
     231                t->a = true;
     232                dtlb_pte_copy(t, true);
    148233                page_table_unlock(AS, true);
    149234        } else {
     
    191276}
    192277
     278void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, const char *str)
     279{
     280        char *tpc_str = get_symtab_entry(istate->tpc);
     281
     282        printf("TPC=%p, (%s)\n", istate->tpc, tpc_str);
     283        panic("%s\n", str);
     284}
     285
    193286void do_fast_data_access_mmu_miss_fault(istate_t *istate, const char *str)
    194287{
  • kernel/arch/sparc64/src/start.S

    rf47fd19 ra7961271  
    3636.register %g2, #scratch
    3737.register %g3, #scratch
    38 .register %g6, #scratch
    39 .register %g7, #scratch
    4038
    4139.section K_TEXT_START, "ax"
     
    154152         */
    155153       
    156         set kernel_image_start, %g7
     154        set kernel_image_start, %g5
    157155       
    158156        ! write ITLB tag of context 1
     
    160158        set VA_DMMU_TAG_ACCESS, %g2
    161159        stxa %g1, [%g2] ASI_IMMU
    162         flush %g7
     160        flush %g5
    163161
    164162        ! write ITLB data and install the temporary mapping in context 1
    165163        SET_TLB_DATA(g1, g2, 0)                 ! use non-global mapping
    166164        stxa %g1, [%g0] ASI_ITLB_DATA_IN_REG           
    167         flush %g7
     165        flush %g5
    168166       
    169167        ! switch to context 1
    170168        set MEM_CONTEXT_TEMP, %g1
    171169        stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi ! ASI_DMMU is correct here !!!
    172         flush %g7
     170        flush %g5
    173171       
    174172        ! demap context 0
    175173        SET_TLB_DEMAP_CMD(g1, TLB_DEMAP_NUCLEUS)
    176174        stxa %g0, [%g1] ASI_IMMU_DEMAP                 
    177         flush %g7
     175        flush %g5
    178176       
    179177        ! write ITLB tag of context 0
     
    181179        set VA_DMMU_TAG_ACCESS, %g2
    182180        stxa %g1, [%g2] ASI_IMMU
    183         flush %g7
     181        flush %g5
    184182
    185183        ! write ITLB data and install the permanent kernel mapping in context 0
    186184        SET_TLB_DATA(g1, g2, 0)                 ! use non-global mapping
    187185        stxa %g1, [%g0] ASI_ITLB_DATA_IN_REG           
    188         flush %g7
     186        flush %g5
    189187
    190188        ! switch to context 0
    191189        stxa %g0, [VA_PRIMARY_CONTEXT_REG] %asi ! ASI_DMMU is correct here !!!
    192         flush %g7
     190        flush %g5
    193191
    194192        ! ensure nucleus mapping
     
    198196        set MEM_CONTEXT_TEMP, %g1
    199197        stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi ! ASI_DMMU is correct here !!!
    200         flush %g7
     198        flush %g5
    201199
    202200        ! demap context 1
    203201        SET_TLB_DEMAP_CMD(g1, TLB_DEMAP_PRIMARY)
    204202        stxa %g0, [%g1] ASI_IMMU_DEMAP                 
    205         flush %g7
     203        flush %g5
    206204       
    207205        ! set context 0 in the primary context register
    208206        stxa %g0, [VA_PRIMARY_CONTEXT_REG] %asi ! ASI_DMMU is correct here !!!
    209         flush %g7
     207        flush %g5
    210208       
    211209        ! set TL back to 0
  • kernel/arch/sparc64/src/trap/trap_table.S

    rf47fd19 ra7961271  
    3333.register %g2, #scratch
    3434.register %g3, #scratch
    35 .register %g6, #scratch
    36 .register %g7, #scratch
    3735
    3836.text
     
    204202.global spill_0_normal
    205203spill_0_normal:
    206         SPILL_NORMAL_HANDLER
     204        SPILL_NORMAL_HANDLER_KERNEL
    207205
    208206/* TT = 0xc0, TL = 0, fill_0_normal handler */
     
    210208.global fill_0_normal
    211209fill_0_normal:
    212         FILL_NORMAL_HANDLER
     210        FILL_NORMAL_HANDLER_KERNEL
    213211
    214212/*
     
    268266.global spill_0_normal_high
    269267spill_0_normal_high:
    270         SPILL_NORMAL_HANDLER
     268        SPILL_NORMAL_HANDLER_KERNEL
    271269
    272270/* TT = 0xc0, TL > 0, fill_0_normal handler */
     
    274272.global fill_0_normal_high
    275273fill_0_normal_high:
    276         FILL_NORMAL_HANDLER
     274        FILL_NORMAL_HANDLER_KERNEL
    277275
    278276
     
    280278 *
    281279 * This trap handler makes arrangements to make calling of scheduler() from
    282  * within a trap context possible. It is guaranteed to function only when traps
    283  * are not nested (i.e. for TL=1).
     280 * within a trap context possible. It is called from several other trap
     281 * handlers.
    284282 *
    285  * Every trap handler on TL=1 that makes a call to the scheduler needs to
    286  * be based on this function. The reason behind it is that the nested
    287  * trap levels and the automatic saving of the interrupted context by hardware
    288  * does not work well together with scheduling (i.e. a thread cannot be rescheduled
    289  * with TL>0). Therefore it is necessary to eliminate the effect of trap levels
    290  * by software and save the necessary state on the kernel stack.
    291  *
    292  * Note that for traps with TL>1, more state needs to be saved. This function
    293  * is therefore not going to work when TL>1.
    294  *
    295  * The caller is responsible for doing SAVE and allocating
    296  * PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE bytes on the stack.
     283 * This function can be entered either with interrupt globals or alternate globals.
     284 * Memory management trap handlers are obliged to switch to one of those global sets
     285 * prior to calling this function. Register window management functions are not
     286 * allowed to modify the alternate global registers.
    297287 *
    298288 * Input registers:
    299  *      %l0             Address of function to call.
    300  * Output registers:
    301  *       %l1 - %l7      Copy of %g1 - %g7
     289 *      %g1             Address of function to call.
     290 *      %g2             Argument for the function.
     291 *      %g6             Pre-set as kernel stack base if trap from userspace.
     292 *      %g7             Reserved.
    302293 */
    303294.global preemptible_handler
    304295preemptible_handler:
    305         /*
    306          * Save TSTATE, TPC, TNPC and PSTATE aside.
     296        rdpr %tstate, %g3
     297        andcc %g3, TSTATE_PRIV_BIT, %g0         ! if this trap came from the privileged mode...
     298        bnz 0f                                  ! ...skip setting of kernel stack and primary context
     299        nop
     300
     301        /*
     302         * Switch to kernel stack. The old stack is
     303         * automatically saved in the old window's %sp
     304         * and the new window's %fp.
     305         */
     306        save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
     307
     308        /*
     309         * Mark the CANSAVE windows as OTHER windows.
     310         * Set CLEANWIN to NWINDOW-1 so that clean_window traps do not occur.
     311         */
     312        rdpr %cansave, %l0
     313        wrpr %l0, %otherwin
     314        wrpr %g0, %cansave
     315        wrpr %g0, NWINDOW-1, %cleanwin
     316
     317        /*
     318         * Switch to primary context 0.
     319         */
     320        mov VA_PRIMARY_CONTEXT_REG, %l0
     321        stxa %g0, [%l0] ASI_DMMU
     322        set kernel_image_start, %l0
     323        flush %l0
     324
     325        ba 1f
     326        nop
     327
     3280:
     329        save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
     330
     331        /*
     332         * At this moment, we are using the kernel stack
     333         * and have successfully allocated a register window.
     334         */
     3351:
     336
     337        /*
     338         * Copy arguments.
     339         */
     340        mov %g1, %l0
     341        mov %g2, %o0
     342
     343        /*
     344         * Save TSTATE, TPC and TNPC aside.
    307345         */
    308346        rdpr %tstate, %g1
    309347        rdpr %tpc, %g2
    310348        rdpr %tnpc, %g3
    311         rdpr %pstate, %g4
    312349
    313350        /*
     
    316353         * the kernel stack of THREAD locked in DTLB.
    317354         */
    318         stx %g1, [%fp + STACK_BIAS + SAVED_TSTATE]
    319         stx %g2, [%fp + STACK_BIAS + SAVED_TPC]
    320         stx %g3, [%fp + STACK_BIAS + SAVED_TNPC]
    321         stx %g4, [%fp + STACK_BIAS + SAVED_PSTATE]
     355        stx %g1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE]
     356        stx %g2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC]
     357        stx %g3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC]
    322358       
    323         /*
    324          * Write 0 to TL.
    325          */
    326359        wrpr %g0, 0, %tl
    327        
    328         /*
    329          * Alter PSTATE.
    330          * - switch to normal globals.
    331          */
    332         and %g4, ~(PSTATE_AG_BIT|PSTATE_IG_BIT|PSTATE_MG_BIT), %g4
    333         wrpr %g4, 0, %pstate
    334          
    335         /*
    336          * Save the normal globals.
    337          */
     360        wrpr %g0, PSTATE_PRIV_BIT, %pstate
    338361        SAVE_GLOBALS
    339362       
    340363        /*
    341          * Call the higher-level handler.
    342          */
    343         mov %fp, %o1                            ! calculate istate address
     364         * Call the higher-level handler and pass istate as second parameter.
     365         */
    344366        call %l0
    345         add %o1, STACK_BIAS + SAVED_PSTATE, %o1 ! calculate istate address
    346        
    347         /*
    348          * Restore       the normal global register set.
    349          */
     367        add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
     368
    350369        RESTORE_GLOBALS
    351        
    352         /*
    353          * Restore PSTATE from saved copy.
    354          * Alternate/Interrupt/MM globals become active.
    355          */
    356         ldx [%fp + STACK_BIAS + SAVED_PSTATE], %l4
    357         wrpr %l4, 0, %pstate
    358        
    359         /*
    360          * Write 1 to TL.
    361          */
     370        wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
    362371        wrpr %g0, 1, %tl
    363372       
     
    365374         * Read TSTATE, TPC and TNPC from saved copy.
    366375         */
    367         ldx [%fp + STACK_BIAS + SAVED_TSTATE], %g1
    368         ldx [%fp + STACK_BIAS + SAVED_TPC], %g2
    369         ldx [%fp + STACK_BIAS + SAVED_TNPC], %g3
    370 
    371         /*
    372          * Do restore to match the save instruction from the top-level handler.
    373          */
    374         restore
    375 
    376         /*
    377          * On execution of the RETRY instruction, CWP will be restored from the TSTATE
    378          * register. However, because of scheduling, it is possible that CWP in the saved
    379          * TSTATE is different from the current CWP. The following chunk of code fixes
    380          * CWP in the saved copy of TSTATE.
    381          */
    382         rdpr %cwp, %g4          ! read current CWP
    383         and %g1, ~0x1f, %g1     ! clear CWP field in saved TSTATE
    384         or %g1, %g4, %g1        ! write current CWP to TSTATE
    385        
     376        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE], %g1
     377        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC], %g2
     378        ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC], %g3
     379
    386380        /*
    387381         * Restore TSTATE, TPC and TNPC from saved copies.
     
    390384        wrpr %g2, 0, %tpc
    391385        wrpr %g3, 0, %tnpc
    392          
    393         /*
    394          * Return from interrupt.
    395          */
     386
     387        /*
     388         * If OTHERWIN is zero, then all the userspace windows have been
     389         * spilled to kernel memory (i.e. register window buffer). If
     390         * OTHERWIN is non-zero, then some userspace windows are still
     391         * valid. Others might have been spilled. However, the CWP pointer
     392         * needs no fixing because the scheduler had not been called.
     393         */
     394        rdpr %otherwin, %l0
     395        brnz %l0, 0f
     396        nop
     397
     398        /*
     399         * OTHERWIN == 0
     400         */
     401
     402        /*
     403         * If TSTATE.CWP + 1 == CWP, then we still do not have to fix CWP.
     404         */
     405        and %g1, TSTATE_CWP_MASK, %l0
     406        inc %l0
     407        and %l0, TSTATE_CWP_MASK, %l0   ! %l0 mod NWINDOW
     408        rdpr %cwp, %l1
     409        cmp %l0, %l1
     410        bz 0f                           ! CWP is ok
     411        nop
     412
     413        /*
     414         * Fix CWP.
     415         */
     416        mov %fp, %g1
     417        flushw
     418        wrpr %l0, 0, %cwp
     419        mov %g1, %fp
     420       
     421        /*
     422         * OTHERWIN != 0 or fall-through from the OTHERWIN == 0 case.
     423         */
     4240:
     425        ! TODO: restore register windows from register window memory buffer
     426
     427        restore
    396428        retry
Note: See TracChangeset for help on using the changeset viewer.