cleand up and sped up SPAARC kernel entry
authorAndrew Waterman <waterman@parcad.millennium.berkeley.edu>
Wed, 3 Mar 2010 09:32:08 +0000 (01:32 -0800)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:36 +0000 (17:35 -0700)
kern/arch/sparc/arch.h
kern/arch/sparc/trap.c
kern/arch/sparc/trap_entry.S
kern/src/monitor.c
kern/src/testing.c

index 7d7ac16..575d644 100644 (file)
@@ -41,7 +41,7 @@ extern uintptr_t mmu_context_tables[MAX_NUM_CPUS][NCONTEXTS+CONTEXT_TABLE_PAD];
 static __inline void
 breakpoint(void)
 {
-       __asm __volatile("ta 0x7f");
+       asm volatile ("ta 0x7f");
 }
 
 static __inline void 
@@ -161,7 +161,7 @@ static __inline uint32_t
 core_id(void)
 {
        uint32_t reg;
-       __asm__ __volatile__("mov %" XSTR(CORE_ID_REG) ",%0" : "=r"(reg));
+       asm ("mov %" XSTR(CORE_ID_REG) ",%0" : "=r"(reg));
        return reg;
 }
 
index 905b3b4..390750f 100644 (file)
@@ -43,6 +43,13 @@ uint32_t send_active_message(uint32_t dst, amr_t pc,
 }
 
 void
+advance_pc(trapframe_t* state)
+{
+       state->pc = state->npc;
+       state->npc += 4;
+}
+
+void
 idt_init(void)
 {
 }
@@ -123,20 +130,6 @@ get_trapname(uint8_t tt, char buf[TRAPNAME_MAX])
 }
 
 void
-trap(trapframe_t* state, void (*handler)(trapframe_t*))
-{
-       // TODO: must save other cores' trap frames
-       // if we want them to migrate, block, etc.
-       if(current && current->vcoremap[0] == core_id())
-       {
-               current->env_tf = *state;
-               handler(&current->env_tf);
-       }
-       else
-               handler(state);
-}
-
-void
 handle_ipi(trapframe_t* state)
 {
        active_message_t m;
@@ -269,9 +262,7 @@ handle_syscall(trapframe_t* state)
        uint32_t a4 = state->gpr[11];
        uint32_t a5 = state->gpr[12];
 
-       // advance pc (else we reexecute the syscall)
-       state->pc = state->npc;
-       state->npc += 4;
+       advance_pc(state);
 
        /* Note we are not preemptively saving the TF in the env_tf.  We do maintain
         * a reference to it in current_tf (a per-cpu pointer).
@@ -279,9 +270,6 @@ handle_syscall(trapframe_t* state)
         * is necessary (blocking).  And only save it in env_tf when you know you
         * are single core (PROC_RUNNING_S) */
        set_current_tf(state);
-       // TODO: must save other cores' ancillary state
-       //if(current->vcoremap[0] == core_id())
-       //      env_push_ancillary_state(current); // remove this if you don't need it
 
        // some syscalls don't return this way if they succed,
        // e.g. run_binary.  so by default set the return value to success
@@ -293,7 +281,7 @@ handle_syscall(trapframe_t* state)
        state->gpr[8] = syscall(current,num,a1,a2,a3,a4,a5);
        proc_decref(current, 1);
 
-       proc_startcore(current,state);
+       env_pop_tf(state);
 }
 
 void
@@ -317,28 +305,18 @@ flush_windows()
 void
 handle_flushw(trapframe_t* state)
 {
-       flush_windows();
-       state->pc = state->npc;
-       state->npc += 4;
+       // don't actually need to do anything here.
+       // trap_entry flushes user windows to the stack.
+       advance_pc(state);
        env_pop_tf(state);
 }
 
 void
 handle_breakpoint(trapframe_t* state)
 {
-       // advance the pc
-       state->pc = state->npc;
-       state->npc += 4;
-
-       // TODO: must save other cores' ancillary state
-       // if we want them to migrate, block, etc.
-       //if(current->vcoremap[0] == core_id())
-       //      env_push_ancillary_state(current);
-
-       // run the monitor
+       advance_pc(state);
        monitor(state);
-
-       assert(0);
+       env_pop_tf(state);
 }
 
 struct kmem_cache *active_msg_cache;
index 9284f2d..e02c4be 100644 (file)
@@ -15,26 +15,25 @@ handle_trap:
        // At this point, %l1 = pc, %l2 = npc, and %l0/3/4/5
        // might contain an active message.  so we only get %l6/%l7
 
-        // calculate stack pointer (-64 is space for window spill).
-        // sp = bootstacktop - core_id*KSTKSIZE - 64 - sizeof(trapframe_t).
+       // calculate stack pointer (-64 is space for window spill).
+       // sp = bootstacktop - core_id*KSTKSIZE - 64 - sizeof(trapframe_t).
        // should you change this, make sure to change stack_fucked()
-        set     bootstacktop-64-SIZEOF_TRAPFRAME_T,%l6
-        mov     CORE_ID_REG,%l7
+       set     bootstacktop-64-SIZEOF_TRAPFRAME_T,%l6
+       mov     CORE_ID_REG,%l7
        sll     %l7,KSTKSHIFT,%l7
-        sub     %l6,%l7,%l6
+       sub     %l6,%l7,%l6
 
        // see if trap came from kernel; if so, use that stack
        // also preserve the psr, since we'll screw with the condition codes
-       mov     %psr,%l7
-       btst    PSR_PS,%l7
+       mov     %psr,%l0
+       btst    PSR_PS,%l0
        bne,a   1f
         sub    %fp,64+SIZEOF_TRAPFRAME_T,%l6
 
        // here is where we might do something with an active message
 
-1:     mov     %l7,%l0
        // At this point we may use %l3/4/5/7 as temporary regs
-
+1:
        // is CWP valid?
        and     %l0,PSR_CWP,%l4 ! %l4 = cwp
        mov     1,%l7
@@ -46,11 +45,10 @@ handle_trap:
        jmpl    %lo(spill)+%l7,%l7      !no, spill a window
         nop
 
-
        // At this point we may use %o0-7, %l3/4/5/7 as temporary regs
        // save the whole user context to a trapframe_t
 
-2:     mov     %l0,%psr
+2:
        mov     %l6,%sp
        mov     %l1,%o1
        mov     %l2,%o2
@@ -65,6 +63,9 @@ handle_trap:
        // spill all trapper's windows out to the stack.
        // the 'save' may trap (triggering the spill),
        // and if the stack is corrupted, the process may die
+       mov     %l0,%g3
+       mov     %sp,%g4
+
        set     NWINDOWS,%g1
        ld      [%g1],%g1
        sub     %g1,1,%g2
@@ -72,19 +73,13 @@ handle_trap:
        bne,a   5b
 tflush:         save   %sp,0,%sp
 
-       // get our old cwp back (restore should NOT trap)
-       sub     %g1,1,%g2
-6:     deccc   %g2
-       bne,a   6b
-        restore
-
        // restore interrupt level
-       wr      %l0,PSR_ET,%psr
+       mov     %g4,%sp 
+       wr      %g3,PSR_ET,%psr
 
-       // call the handler and pass in the tf, message, and handler addr
-       add     %sp,64,%o0
-       call    trap
-        mov    %l5,%o1
+       // call the handler and pass in the tf and handler address
+       call    %l5
+        add    %sp,64,%o0
 
        // should never get here
        unimp
@@ -140,60 +135,23 @@ env_save_tf:
        retl
         nop
 
+       // this routine only works for returning to userspace.
+       // right now, there's no mechanism to resume kernel operation after
+       // a fault
        .global env_pop_tf
 env_pop_tf:
 
        mov     %psr,%o1
-       btst    PSR_PS,%o1      ! return to kernel or user?
-       bne     1f
-
-       // we're returning to userspace.
        wr      %o1,PSR_ET,%psr
 
        // CWP = 0 (therefore 1 after rett), so set window 2 invalid
-       mov     0,%wim
-       mov     %o0,%g2
-       mov     %psr,%g1
-       andn    %g1,PSR_CWP,%g1
-       mov     %g1,%psr
-       mov     1<<2,%wim; nop
-       // time to restore user context and rett
-       ba      4f
-        mov    %g2,%o0
-
-1:
-       // this general version of the code works for kernel and user,
-       // but it is slow because it spills the windows.
-
-       // first disable interrupts.
-       // since wrpsr/rdpsr is interruptible, all interrupt handlers
-       // must restore the psr to its interrupt-time value
-       or      %o1,PSR_PIL,%o2
-       wr      %o2,%psr
-
-       // spill all kernel windows to the stack
-       set     NWINDOWS,%g1
-       ld      [%g1],%g1
-       sub     %g1,1,%g2
-5:     deccc   %g2
-       bne,a   5b
-        save   %sp,0,%sp
-
-       // get our old cwp back (restore should NOT trap)
-       sub     %g1,1,%g2
-6:     deccc   %g2
-       bne,a   6b
-        restore
-       
-       // disable traps, and restore interrupt level
-       wr      %o2,PSR_ET,%psr
-       wr      %o1,PSR_ET,%psr
-
-       // if we did this right (and didn't get an NMI!),
-       // then (CWP+1) % NWINDOWS should be invalid.  fix that.
-       save
-       mov     %i0,%o0
+       mov     1<<2,%wim
+       ld      [%o0+128],%o1
        mov     %o0,%g2
+       andn    %o1,PSR_CWP,%o1
+       mov     %o1,%psr
+       nop; nop; nop
+       mov     %g2,%o0
 
 4:     // restore user context
        restore
@@ -216,17 +174,12 @@ env_pop_tf:
        ldd     [%o0+16],%g4
        ldd     [%o0+24],%g6
 
-       ldd     [%o0+128],%l0
-       mov     %psr,%l2
-       and     %l2,PSR_CWP,%l2
-       andn    %l0,PSR_CWP,%l0
-       wr      %l2,%l0,%psr
-
+       ld      [%o0+132],%l1
        ld      [%o0+136],%l2
        ld      [%o0+148],%l5
        mov     %l5,%y
        ld      [%o0+152],%l5
-       mov %l5,%asr13
+       mov     %l5,%asr13
 
        jmp     %l1
        rett    %l2
index fced38a..267abb0 100644 (file)
@@ -194,13 +194,11 @@ int mon_cpuinfo(int argc, char **argv, trapframe_t *tf)
        cprintf("Number of CPUs detected: %d\n", num_cpus);
        cprintf("Calling CPU's ID: 0x%08x\n", core_id());
 
-#ifdef __i386__
        if (argc < 2)
                smp_call_function_self(test_print_info_handler, NULL, 0);
        else
                smp_call_function_single(strtol(argv[1], 0, 10),
                                         test_print_info_handler, NULL, 0);
-#endif
        return 0;
 }
 
index 4fe2b0c..f5a9c81 100644 (file)
@@ -718,9 +718,12 @@ spinlock_t print_info_lock = SPINLOCK_INITIALIZER;
 
 void test_print_info_handler(trapframe_t *tf, void* data)
 {
+       uint64_t tsc = read_tsc();
+
        spin_lock_irqsave(&print_info_lock);
        cprintf("----------------------------\n");
        cprintf("This is Core %d\n", core_id());
+       cprintf("Timestamp = %lld\n", tsc);
 #ifdef __i386__
        cprintf("Hardware core %d\n", hw_core_id());
        cprintf("MTRR_DEF_TYPE = 0x%08x\n", read_msr(IA32_MTRR_DEF_TYPE));