Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset a218709 in mainline


Ignore:
Timestamp:
2013-12-02T23:45:45Z (9 years ago)
Author:
Jakub Klama <jakub.klama@…>
Branches:
lfn, master, serial
Children:
2955bb9
Parents:
3bc42bd
Message:

Implement new userspace window trap mechanism, which utilizes MMU probe
to choose between slow (preemptive, involving inserting stack page mapping)
and fast (direct) handlers.

Location:
kernel/arch/sparc32
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/sparc32/include/arch/arch.h

    r3bc42bd ra218709  
    4040
    4141#include <typedefs.h>
     42#include <arch/istate.h>
    4243
    4344#define NWINDOWS        8
     
    7677extern void arch_pre_main(void *unused, bootinfo_t *bootinfo);
    7778extern void write_to_invalid(uint32_t l0, uint32_t l1, uint32_t l2);
     79extern void read_from_invalid(uint32_t *l0, uint32_t *l1, uint32_t *l2);
     80extern void preemptible_save_uspace(uintptr_t sp, istate_t *istate);
     81extern void preemptible_restore_uspace(uintptr_t sp, istate_t *istate);
     82extern void flush_windows(void);
    7883
    7984#endif
  • kernel/arch/sparc32/include/arch/asm.h

    r3bc42bd ra218709  
    145145}
    146146
     147NO_TRACE static inline uint32_t wim_read()
     148{
     149        uint32_t v;
     150
     151        asm volatile (
     152                "mov %%wim, %[v]\n"
     153                : [v] "=r" (v)
     154        );
     155
     156        return v;
     157}
     158
    147159NO_TRACE static inline uint32_t asi_u32_read(int asi, uintptr_t va)
    148160{
     
    178190}
    179191
     192NO_TRACE static inline void wim_write(uint32_t wim)
     193{
     194        asm volatile (
     195                "mov %[v], %%wim\n"
     196                :: [v] "r" (wim)
     197        );
     198}
     199
    180200NO_TRACE static inline ipl_t interrupts_enable(void)
    181201{
  • kernel/arch/sparc32/include/arch/context.h

    r3bc42bd ra218709  
    4545#define context_set(c, _pc, stack, size) \
    4646        do { \
    47                 (c)->pc = ((uintptr_t) _pc) - 4; \
     47                (c)->pc = ((uintptr_t) _pc) - 8; \
    4848                (c)->sp = ((uintptr_t) stack) + ALIGN_UP((size), \
    4949                    STACK_ALIGNMENT) - (SP_DELTA); \
  • kernel/arch/sparc32/include/arch/faddr.h

    r3bc42bd ra218709  
    3333 */
    3434
    35 #ifndef KERN_abs32le_FADDR_H_
    36 #define KERN_abs32le_FADDR_H_
     35#ifndef KERN_sparc32_FADDR_H_
     36#define KERN_sparc32_FADDR_H_
    3737
    3838#include <typedefs.h>
  • kernel/arch/sparc32/include/arch/regwin.h

    r3bc42bd ra218709  
    4242#include <align.h>
    4343
    44 #define CLEAN_WINDOW_HANDLER_SIZE       REGWIN_HANDLER_SIZE
    45 #define SPILL_HANDLER_SIZE              REGWIN_HANDLER_SIZE
    46 #define FILL_HANDLER_SIZE               REGWIN_HANDLER_SIZE
     44#define UWB_ALIGNMENT   1024
    4745
    4846/* Window Save Area offsets. */
  • kernel/arch/sparc32/src/exception.c

    r3bc42bd ra218709  
    3939#include <arch/istate.h>
    4040#include <arch/exception.h>
     41#include <arch/regwin.h>
    4142#include <syscall/syscall.h>
    4243#include <interrupt.h>
    4344#include <arch/asm.h>
     45#include <mm/frame.h>
     46#include <mm/page.h>
     47#include <mm/as.h>
     48#include <memstr.h>
    4449#include <debug.h>
    4550#include <print.h>
     
    142147sysarg_t syscall(sysarg_t a1, sysarg_t a2, sysarg_t a3, sysarg_t a4, sysarg_t a5, sysarg_t a6, sysarg_t id)
    143148{
    144         printf("syscall %d\n", id);
    145         printf("args: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", a1, a2, a3, a4, a5, a6);
     149//      printf("syscall %d\n", id);
     150//      printf("args: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", a1, a2, a3, a4, a5, a6);
     151        if (id == 0x4f) {
     152            flush_windows();
     153            return 0;
     154        }
     155   
    146156        return syscall_handler(a1, a2, a3, a4, a5, a6, id);
     157}
     158
     159void preemptible_save_uspace(uintptr_t sp, istate_t *istate)
     160{
     161        as_page_fault(sp, PF_ACCESS_WRITE, istate);
     162}
     163
     164void preemptible_restore_uspace(uintptr_t sp, istate_t *istate)
     165{
     166        as_page_fault(sp, PF_ACCESS_WRITE, istate);
    147167}
    148168
  • kernel/arch/sparc32/src/trap_table.S

    r3bc42bd ra218709  
    2828
    2929#include <arch/trap.h>
     30#include <arch/regwin.h>
    3031
    3132.text
     
    3940.global window_underflow_trap
    4041.global write_to_invalid
     42.global read_from_invalid
     43.global flush_windows
    4144
    4245.macro get_wim_number reg
     
    231234        nop
    232235
     236read_from_invalid:
     237        ! Read value 1
     238        mov %o0, %g7
     239        switch_to_invalid %g3, %g4
     240        st %l5, [%g7]
     241        switch_back %g3, %g4
     242        ! Write value 2
     243        mov %o1, %g7
     244        switch_to_invalid %g3, %g4
     245        st %l6, [%g7]
     246        switch_back %g3, %g4
     247        ! Write value 3
     248        mov %o2, %g7
     249        switch_to_invalid %g3, %g4
     250        st %l7, [%g7]
     251        switch_back %g3, %g4
     252        retl
     253        nop
     254
    233255reset_trap:
    234256        set 0x80000100, %l0
     
    240262        mov %g7, %l0
    241263
    242         /* rotate WIM on bit right, we have 8 windows */
     264        /* Check whether previous mode was usermode */
     265        mov %psr, %l4
     266        and %l4, (1 << 6), %l4
     267        cmp %l4, 0
     268        bne 1f
     269        nop
     270
     271        /* userspace: */
     272        /* time to check whether desired stack page is mapped
     273         * on the MMU. if so, process with saving window directly.
     274         * if not, go to preemptible trap handler */
     275        mov %wim, %g5
     276        mov %g0, %wim
     277        save
     278        mov %sp, %g4
     279        restore
     280        mov %g5, %wim
     281        and %g4, 0xfffff000, %l4
     282        lda [%l4] 0x18, %l4
     283        cmp %l4, 0
     284        bne 1f
     285        nop
     286
     287        /* prepare args for preemptible handler */
     288        mov %g4, %o0
     289        set preemptible_save_uspace, %o2
     290        b preemptible_trap
     291        nop
     292
     293        /* kernel: */
     2941:      /* rotate WIM on bit right, we have 8 windows */
    243295        mov %wim, %l3
    244296        sll %l3, 7, %l4
     
    256308        mov %l7, %g7
    257309
    258         /* Check whether previous mode was usermode */
    259         mov %psr, %l4
    260         and %l4, (1 << 6), %l4
    261         cmp %l4, 0
    262         beq 1f
    263         nop
    264 
    265         /* kernel: */
     310
    266311        /* we should check whether window needs to be saved
    267312         * to kernel stack or uwb
     
    284329        nop
    285330
    286 1:      /* uspace: */
    287         /* set uspace window mark */
    288         mov %psr, %g7
    289         and %g7, 0x7, %g7
    290         or %g7, 0x10, %g7
    291 
     331        /* dump registers to uwb */
    2923322:      save
    293333        std %l0, [%g6 +  0]
     
    330370        mov %g7, %l0
    331371
     372        /* Check whether previous mode was usermode */
     373        mov %psr, %l4
     374        and %l4, (1 << 6), %l4
     375        cmp %l4, 0
     376        bne 1f
     377        nop
     378
     379        /* userspace: */
     380        /* time to check whether desired stack page is mapped
     381         * on the MMU. if so, process with saving window directly.
     382         * if not, go to preemptible trap handler */
     383        mov %wim, %g5
     384        mov %g0, %wim
     385        restore
     386        restore
     387        mov %sp, %g4
     388        save
     389        save
     390        mov %g5, %wim
     391        and %sp, 0xfffff000, %l4
     392        lda [%l4] 0x18, %l4
     393        cmp %l4, 0
     394        bne 1f
     395        nop
     396
     397        /* prepare args for preemptible handler */
     398        mov %g4, %o0
     399        set preemptible_restore_uspace, %o2
     400        b preemptible_trap
     401        nop
     402
    332403        /* rotate WIM on bit LEFT, we have 8 windows */
    333         mov %wim,%l3
     4041:      mov %wim,%l3
    334405        srl %l3,7,%l4
    335406        sll %l3,1,%l3
     
    341412        nop; nop; nop
    342413
    343         /* Check whether previous mode was usermode */
    344         mov %psr, %l4
    345         and %l4, (1 << 6), %l4
    346         cmp %l4, 0
    347         beq 1f
    348         nop
    349 
     414        /* kernel: */
    350415        restore
    351416        restore
     
    365430        nop
    366431
    367 1:      restore
    368         restore
    369         mov %l5, %g5            ! kernel stack pointer
    370         mov %l6, %g6            ! kernel wbuf
    371         mov %l7, %g7
    372         sub %g6, 64, %g6
    373         ldd [%g6 +  0], %l0
    374         ldd [%g6 +  8], %l2
    375         ldd [%g6 + 16], %l4
    376         ldd [%g6 + 24], %l6
    377         ldd [%g6 + 32], %i0
    378         ldd [%g6 + 40], %i2
    379         ldd [%g6 + 48], %i4
    380         ldd [%g6 + 56], %i6
    381 
    3824322:      /* Restore invalid window data */
    383433        restore
     
    397447        jmp %l1
    398448        rett %l2
     449
     450flush_windows:
     451        mov 7, %g1
     4521:      subcc %g1, 1, %g1
     453        bg 1b
     454        save %sp, -64, %sp
     455
     456        mov 7, %g1
     4571:      subcc %g1, 1, %g1
     458        bg 1b
     459        restore
     460
     461        retl
     462        nop
    399463
    400464preemptible_trap:
     
    470534        /* Jump to actual subroutine */
    471535        call %o2
    472         sub %fp, 12, %o1
     536        add %sp, 128, %o1
    473537
    474538        /* Return from handler */
     
    487551        switch_to_invalid %g5, %g6
    488552        clr %l7
     553        mov %l5, %g2
    489554        mov %l6, %g7
    490555        switch_back %g5, %g6
    491556        mov %g7, %g1
     557
     558        /* If trap originated from uspace, restore all windows from UWB */
     559        /* UWB pointer is at %g1 */
     5600:      mov %g0, %wim
     561        clr %g5
     562        andcc %g1, UWB_ALIGNMENT - 1, %g0
     563        bz 0f
     564        nop
     565
     566        restore
     567        sub %g1, 64, %g1
     568        ldd [%g1 +  0], %l0
     569        ldd [%g1 +  8], %l2
     570        ldd [%g1 + 16], %l4
     571        ldd [%g1 + 24], %l6
     572        ldd [%g1 + 32], %i0
     573        ldd [%g1 + 40], %i2
     574        ldd [%g1 + 48], %i4
     575        ldd [%g1 + 56], %i6
     576        inc %g5
     577        and %g5, 0x7, %g5
     578        ba 0b
     579        nop
     580
     581        /* We've restored all uspace windows. Now time to
     582         * fix CWP and WIM
     583         */
     5840:      restore
     585        get_cwp %g7
     586        clr %g5
     587        inc %g5
     588        sll %g5, %g7, %g5
     589
     590        /* Write values to invalid window and switch back */
     591        mov %g2, %l5
     592        mov %g1, %l6
     593        clr %l7
     594        switch_back %g5, %g6
    492595
    493596        /* If next window is invalid, do inline restore */
     
    679782        ld [%sp + 100], %l0
    680783        mov %o0, %i0
     784        mov %psr, %l1
     785        and %l1, 0xf, %l1
     786        and %l0, 0xfffffff0, %l0
     787        or %l0, %l1, %l0
    681788        mov %l0, %psr
    682789        nop
     
    690797        switch_to_invalid %g5, %g6
    691798        clr %l7
     799        mov %l5, %g2
    692800        mov %l6, %g7
    693801        switch_back %g5, %g6
    694802        mov %g7, %g1
     803
     804        /* If trap originated from uspace, restore all windows from UWB */
     805        /* UWB pointer is at %g1 */
     8060:      mov %g0, %wim
     807        clr %g5
     808        andcc %g1, UWB_ALIGNMENT - 1, %g0
     809        bz 0f
     810        nop
     811
     812        restore
     813        sub %g1, 64, %g1
     814        ldd [%g1 +  0], %l0
     815        ldd [%g1 +  8], %l2
     816        ldd [%g1 + 16], %l4
     817        ldd [%g1 + 24], %l6
     818        ldd [%g1 + 32], %i0
     819        ldd [%g1 + 40], %i2
     820        ldd [%g1 + 48], %i4
     821        ldd [%g1 + 56], %i6
     822        inc %g5
     823        and %g5, 0x7, %g5
     824        ba 0b
     825        nop
     826
     827        /* We've restored all uspace windows. Now time to
     828         * fix CWP and WIM
     829         */
     8300:      restore
     831        get_cwp %g7
     832        clr %g5
     833        inc %g5
     834        sll %g5, %g7, %g5
     835
     836        /* Write values to invalid window and switch back */
     837        mov %g2, %l5
     838        mov %g1, %l6
     839        clr %l7
     840        switch_back %g5, %g6
    695841
    696842        /* If next window is invalid, do inline restore */
     
    9291075        SYSCALL(0xae)
    9301076        SYSCALL(0xaf)
     1077        SYSCALL(0xb0)
     1078        SYSCALL(0xb1)
     1079        SYSCALL(0xb2)
     1080        SYSCALL(0xb3)
     1081        SYSCALL(0xb4)
     1082        SYSCALL(0xb5)
     1083        SYSCALL(0xb6)
     1084        SYSCALL(0xb7)
     1085        SYSCALL(0xb8)
     1086        SYSCALL(0xb9)
     1087        SYSCALL(0xba)
     1088        SYSCALL(0xbb)
     1089        SYSCALL(0xbc)
     1090        SYSCALL(0xbd)
     1091        SYSCALL(0xbe)
     1092        SYSCALL(0xbf)
     1093        SYSCALL(0xc0)
     1094        SYSCALL(0xc1)
     1095        SYSCALL(0xc2)
     1096        SYSCALL(0xc3)
     1097        SYSCALL(0xc4)
     1098        SYSCALL(0xc5)
     1099        SYSCALL(0xc6)
     1100        SYSCALL(0xc7)
     1101        SYSCALL(0xc8)
     1102        SYSCALL(0xc9)
     1103        SYSCALL(0xca)
     1104        SYSCALL(0xcb)
     1105        SYSCALL(0xcc)
     1106        SYSCALL(0xcd)
     1107        SYSCALL(0xce)
     1108        SYSCALL(0xcf)
  • kernel/arch/sparc32/src/userspace.c

    r3bc42bd ra218709  
    4242void userspace(uspace_arg_t *kernel_uarg)
    4343{
    44         printf("userspace(): entry=%p, stack=%p, stacksize=%d\n", kernel_uarg->uspace_entry, kernel_uarg->uspace_stack, kernel_uarg->uspace_stack_size);
     44//      printf("userspace(): entry=%p, stack=%p, stacksize=%d\n", kernel_uarg->uspace_entry, kernel_uarg->uspace_stack, kernel_uarg->uspace_stack_size);
    4545        /* On real hardware this switches the CPU to user
    4646           space mode and jumps to kernel_uarg->uspace_entry. */
    4747
     48        uint32_t l0, l1, l2;
    4849        uint32_t psr = psr_read();
     50        uint8_t wim;
    4951
    5052        psr &= ~(1 << 7);
    5153        psr &= ~(1 << 6);
    5254
     55        /* Read invalid window variables */
     56        read_from_invalid(&l0, &l1, &l2);
     57
     58        /* Make current window invalid */
     59        wim = (psr & 0x7) + 1;
     60        wim = (1 << wim) | (1 >> (8 - wim));
     61
    5362        asm volatile (
    5463                "flush\n"
    5564                "mov %[stack], %%sp\n"
    56                 "mov %[arg], %%o1\n"
     65                "mov %[wim], %%wim\n"
     66                "ld %[v0], %%o0\n"
     67                "ld %[v1], %%o1\n"
     68                "ld %[v2], %%o2\n"
     69                "call write_to_invalid\n"
     70                "nop\n"
     71                "ld %[arg], %%o1\n"
    5772                "jmp %[entry]\n"
    5873                "mov %[psr], %%psr\n" :: [entry] "r" (kernel_uarg->uspace_entry),
    59                            [arg] "r" (kernel_uarg->uspace_uarg),
     74                           [arg] "m" (kernel_uarg->uspace_uarg),
    6075                           [psr] "r" (psr),
    61                            [stack] "r" (kernel_uarg->uspace_stack + kernel_uarg->uspace_stack_size));
     76                           [wim] "r" ((uint32_t)wim),   
     77                           [v0] "m" (l0),
     78                           [v1] "m" (l1),
     79                           [v2] "m" (l2),
     80                           [stack] "r" (kernel_uarg->uspace_stack + kernel_uarg->uspace_stack_size - 64) : "%g3", "%g4");
    6281
    6382        while (true);
Note: See TracChangeset for help on using the changeset viewer.