Made stuff work on SPARC HW
authorAndrew Waterman <waterman@s143.Millennium.Berkeley.EDU>
Sun, 2 May 2010 03:31:22 +0000 (20:31 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:46 +0000 (17:35 -0700)
Three issues:

1) Not HW related, but need 96 bytes on stack before TF.  This
   is because bytes 64-96 are reserved for spilling the args of
   a variadic function.  So if your ISR called printk immediately,
   it would trash the user's trap frame.

2) An MMU bug spuriously set the FSR, causing the spill/fill handlers
   to have false-positive stack-fucks.  Fixed by clearing FSR before
   doing spill/fill.

3) GLIBC doesn't use FLUSHes in all necessary places in the RTLD.
   Added them in.

kern/arch/sparc/spillfill.S
kern/arch/sparc/trap_entry.S
kern/include/elf.h
kern/src/elf.c
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/sparc/sparc32/dl-machine.h

index 3196975..0608bce 100644 (file)
 ! %l0, %l1, %l2, %l5, %l6, %l7 have not changed 
 .global handle_window_overflow
 handle_window_overflow:
+       ! clear out MMU faults (workaround for HW bug :()
+       mov     0x300,%l3
+       lda     [%l3] 4,%g0
+
        mov     %g1,%l4
        mov     %wim,%l3
        mov     %g0,%wim
@@ -76,6 +80,10 @@ spill_patchme:
 
 .global handle_window_underflow
 handle_window_underflow:
+       ! clear out MMU faults (workaround for HW bug :()
+       mov     0x300,%l3
+       lda     [%l3] 4,%g0
+
        mov     %wim,%l3
        mov     %g1,%l4
        mov     %psr,%l5
index 0167040..3c62c15 100644 (file)
@@ -69,7 +69,7 @@ handle_trap:
        save
 
        // Set up stack, save state, call handler
-       sub     %fp,64+SIZEOF_TRAPFRAME_T,%sp
+       sub     %fp,96+SIZEOF_TRAPFRAME_T,%sp
 
        // Save full trap frame if this was a synchronous exception (=> bug!!)
        and     %g1,0xF00,%g1
@@ -78,19 +78,19 @@ handle_trap:
         nop
 
        call    save_rest_of_tf
-        add    %sp,64,%o0
+        add    %sp,96,%o0
 
 2:     call    %l0
-        add    %sp,64,%o0
+        add    %sp,96,%o0
 
        // Fill a window if necessary.
        restore
        save
 
        // Restore PSR, then GTFO
-       ld      [%sp+64+128],%l7
+       ld      [%sp+96+128],%l7
        mov     %l7,%psr
-       RESTORE_MINIMAL_TF(%sp+64)
+       RESTORE_MINIMAL_TF(%sp+96)
 
        // Trap came from user.  Spill a window if necessary.
 1:     mov     CORE_ID_REG,%l1
@@ -98,7 +98,7 @@ handle_trap:
        set     bootstacktop-SIZEOF_TRAPFRAME_T,%l2
        sub     %l2,%l1,%l1
        SAVE_MINIMAL_TF(%l1)
-       sub     %l1,64,%g1
+       sub     %l1,96,%g1
        restore
 tflush1:
        save
@@ -107,7 +107,7 @@ tflush1:
        // Save a full trap frame, since we might not return through this path
        mov     %g1,%sp
        call    save_rest_of_tf
-        add    %sp,64,%o0
+        add    %sp,96,%o0
 
        // spill all trapper's windows out to the stack.
        // the 'save' may trap (triggering the spill),
@@ -127,10 +127,10 @@ tflush2:
 
        // Call the handler
        call    %l0
-        add    %sp,64,%o0
+        add    %sp,96,%o0
 
        // fallthrough to env_pop_tf, which is right below this function
-       add     %sp,64,%o0
+       add     %sp,96,%o0
 
        // this routine only works for returning to userspace.
        // right now, there's no mechanism to resume kernel operation after
index 8fb320a..522de69 100644 (file)
@@ -80,6 +80,10 @@ typedef long elf_aux_t[2];
 #define ELF_AUX_PHENT          4
 #define ELF_AUX_PHNUM          5
 #define ELF_AUX_ENTRY          9
+#define ELF_AUX_HWCAP          16
+
+// Hardware capabilities (for use with ELF_AUX_HWCAP)
+#define ELF_HWCAP_SPARC_FLUSH  1
 
 struct file;
 int load_elf(struct proc* p, struct file* f);
index 38a3190..5e241e4 100644 (file)
@@ -115,6 +115,9 @@ int load_elf(struct proc* p, struct file* f)
                                    {ELF_AUX_PHENT,sizeof(proghdr_t)},
                                    {ELF_AUX_PHNUM,ei.phnum},
                                    {ELF_AUX_ENTRY,ei.entry},
+                                   #ifdef __sparc_v8__
+                                   {ELF_AUX_HWCAP,ELF_HWCAP_SPARC_FLUSH},
+                                   #endif
                                    {0,0}};
 
                // put auxp after argv, envp in procinfo
index f6d9957..b32c7f1 100644 (file)
@@ -152,6 +152,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
       plt[1] = 0x85c0a000 | (rfunc & 0x3ff);
       plt[2] = OPCODE_NOP;     /* Fill call delay slot.  */
       plt[3] = (Elf32_Addr) l;
+
+      if(GLRO(dl_hwcap) & HWCAP_SPARC_FLUSH)
+        for(int i = 0; i < 4; i++)
+          asm volatile("flush %0" : : "r"(&plt[i]));
+
       if (__builtin_expect (l->l_info[VALIDX(DT_GNU_PRELINKED)] != NULL, 0)
          || __builtin_expect (l->l_info [VALIDX (DT_GNU_LIBLISTSZ)] != NULL, 0))
        {