Author: andrew
Date: Mon Aug  3 11:05:02 2015
New Revision: 286225
URL: https://svnweb.freebsd.org/changeset/base/286225

Log:
  Pass the pcb to store the vfp state in to vfp_save_state. This fixes a bug
  in savectx where it will be used to store the current state however will
  pass in a pcb when vfp_save_state expected a thread pointer.
  
  Obtained from:        ABT Systems Ltd
  Sponsored by: The FreeBSD Foundation

Modified:
  head/sys/arm64/arm64/machdep.c
  head/sys/arm64/arm64/swtch.S
  head/sys/arm64/arm64/vfp.c
  head/sys/arm64/arm64/vm_machdep.c
  head/sys/arm64/include/vfp.h

Modified: head/sys/arm64/arm64/machdep.c
==============================================================================
--- head/sys/arm64/arm64/machdep.c      Mon Aug  3 10:10:49 2015        
(r286224)
+++ head/sys/arm64/arm64/machdep.c      Mon Aug  3 11:05:02 2015        
(r286225)
@@ -180,7 +180,7 @@ fill_fpregs(struct thread *td, struct fp
                 * If we have just been running VFP instructions we will
                 * need to save the state to memcpy it below.
                 */
-               vfp_save_state(td);
+               vfp_save_state(td, pcb);
 
                memcpy(regs->fp_q, pcb->pcb_vfp, sizeof(regs->fp_q));
                regs->fp_cr = pcb->pcb_fpcr;
@@ -314,7 +314,7 @@ get_fpcontext(struct thread *td, mcontex
                 * If we have just been running VFP instructions we will
                 * need to save the state to memcpy it below.
                 */
-               vfp_save_state(td);
+               vfp_save_state(td, curpcb);
 
                memcpy(mcp->mc_fpregs.fp_q, curpcb->pcb_vfp,
                    sizeof(mcp->mc_fpregs));

Modified: head/sys/arm64/arm64/swtch.S
==============================================================================
--- head/sys/arm64/arm64/swtch.S        Mon Aug  3 10:10:49 2015        
(r286224)
+++ head/sys/arm64/arm64/swtch.S        Mon Aug  3 11:05:02 2015        
(r286225)
@@ -131,6 +131,8 @@ ENTRY(cpu_switch)
        mov     x19, x0
        mov     x20, x1
        mov     x21, x2
+       /* Load the pcb address */
+       mov     x1, x4
        bl      vfp_save_state
        mov     x2, x21
        mov     x1, x20
@@ -268,9 +270,11 @@ ENTRY(savectx)
 
        /* Store the VFP registers */
 #ifdef VFP
-       mov     x29, lr
+       mov     x28, lr
+       mov     x1, x0                  /* move pcb to the correct register */
+       mov     x0, xzr                 /* td = NULL */
        bl      vfp_save_state
-       mov     lr, x29
+       mov     lr, x28
 #endif
 
        ret

Modified: head/sys/arm64/arm64/vfp.c
==============================================================================
--- head/sys/arm64/arm64/vfp.c  Mon Aug  3 10:10:49 2015        (r286224)
+++ head/sys/arm64/arm64/vfp.c  Mon Aug  3 11:05:02 2015        (r286225)
@@ -82,12 +82,18 @@ vfp_discard(struct thread *td)
 }
 
 void
-vfp_save_state(struct thread *td)
+vfp_save_state(struct thread *td, struct pcb *pcb)
 {
        __int128_t *vfp_state;
        uint64_t fpcr, fpsr;
        uint32_t cpacr;
 
+       KASSERT(pcb != NULL, ("NULL vfp pcb"));
+       KASSERT(td == NULL || td->td_pcb == pcb, ("Invalid vfp pcb"));
+
+       if (td == NULL)
+               td = curthread;
+
        critical_enter();
        /*
         * Only store the registers if the VFP is enabled,
@@ -98,7 +104,7 @@ vfp_save_state(struct thread *td)
                KASSERT(PCPU_GET(fpcurthread) == td,
                    ("Storing an invalid VFP state"));
 
-               vfp_state = td->td_pcb->pcb_vfp;
+               vfp_state = pcb->pcb_vfp;
                __asm __volatile(
                    "mrs        %0, fpcr                \n"
                    "mrs        %1, fpsr                \n"
@@ -120,8 +126,8 @@ vfp_save_state(struct thread *td)
                    "stp        q30, q31, [%2, #16 * 30]\n"
                    : "=&r"(fpcr), "=&r"(fpsr) : "r"(vfp_state));
 
-               td->td_pcb->pcb_fpcr = fpcr;
-               td->td_pcb->pcb_fpsr = fpsr;
+               pcb->pcb_fpcr = fpcr;
+               pcb->pcb_fpsr = fpsr;
 
                dsb(ish);
                vfp_disable();

Modified: head/sys/arm64/arm64/vm_machdep.c
==============================================================================
--- head/sys/arm64/arm64/vm_machdep.c   Mon Aug  3 10:10:49 2015        
(r286224)
+++ head/sys/arm64/arm64/vm_machdep.c   Mon Aug  3 11:05:02 2015        
(r286225)
@@ -74,7 +74,7 @@ cpu_fork(struct thread *td1, struct proc
                td1->td_pcb->pcb_tpidr_el0 = READ_SPECIALREG(tpidr_el0);
 #ifdef VFP
                if ((td1->td_pcb->pcb_fpflags & PCB_FP_STARTED) != 0)
-                       vfp_save_state(td1);
+                       vfp_save_state(td1, td1->td_pcb);
 #endif
        }
 

Modified: head/sys/arm64/include/vfp.h
==============================================================================
--- head/sys/arm64/include/vfp.h        Mon Aug  3 10:10:49 2015        
(r286224)
+++ head/sys/arm64/include/vfp.h        Mon Aug  3 11:05:02 2015        
(r286225)
@@ -38,7 +38,7 @@
 void   vfp_init(void);
 void   vfp_discard(struct thread *);
 void   vfp_restore_state(void);
-void   vfp_save_state(struct thread *);
+void   vfp_save_state(struct thread *, struct pcb *);
 #endif
 
 #endif
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to