Print this page
XXX AVX procfs

@@ -131,17 +131,19 @@
         label_t ljb;
         volatile caddr_t sp;
         caddr_t fp;
         volatile struct regs *rp;
         volatile greg_t upc;
-        volatile proc_t *p = ttoproc(curthread);
+        proc_t *volatile p = ttoproc(curthread);
         struct as *as = p->p_as;
         klwp_t *lwp = ttolwp(curthread);
         ucontext_t *volatile tuc = NULL;
         ucontext_t *uc;
         siginfo_t *sip_addr;
         volatile int watched;
+        char *volatile xregs = NULL;
+        volatile size_t xregs_size = 0;
 
         /*
          * This routine is utterly dependent upon STACK_ALIGN being
          * 16 and STACK_ENTRY_ALIGN being 8. Let's just acknowledge
          * that and require it.

@@ -173,10 +175,18 @@
         ASSERT((sizeof (struct sigframe) % 16) == 8);
 
         minstacksz = sizeof (struct sigframe) + SA(sizeof (*uc));
         if (sip != NULL)
                 minstacksz += SA(sizeof (siginfo_t));
+
+        /*
+         * Extra registers, if supported by this platform, may be of arbitrary
+         * length. Size them now so we know how big the signal frame has to be.
+         */
+        xregs_size = xregs_getsize(p);
+        minstacksz += SA(xregs_size);
+
         ASSERT((minstacksz & (STACK_ENTRY_ALIGN - 1ul)) == 0);
 
         /*
          * Figure out whether we will be handling this signal on
          * an alternate stack specified by the user.  Then allocate

@@ -287,10 +297,24 @@
          * 16-byte alignment for ucontext_t and its %xmm registers.
          */
         uc = (ucontext_t *)(sp + sizeof (struct sigframe));
         tuc = kmem_alloc(sizeof (*tuc), KM_SLEEP);
         savecontext(tuc, &lwp->lwp_sigoldmask);
+
+        /*
+         * Save extra register state if it exists.
+         */
+        if (xregs_size != 0) {
+                xregs_setptr(lwp, tuc, sp);
+                xregs = kmem_alloc(xregs_size, KM_SLEEP);
+                xregs_get(lwp, xregs);
+                copyout_noerr(xregs, sp, xregs_size);
+                kmem_free(xregs, xregs_size);
+                xregs = NULL;
+                sp += SA(xregs_size);
+        }
+
         copyout_noerr(tuc, uc, sizeof (*tuc));
         kmem_free(tuc, sizeof (*tuc));
         tuc = NULL;
 
         lwp->lwp_oldcontext = (uintptr_t)uc;

@@ -352,10 +376,12 @@
         no_fault();
         if (watched)
                 watch_enable_addr((caddr_t)sp, minstacksz, S_WRITE);
         if (tuc)
                 kmem_free(tuc, sizeof (*tuc));
+        if (xregs)
+                kmem_free(xregs, xregs_size);
 #ifdef DEBUG
         printf("sendsig: bad signal stack cmd=%s, pid=%d, sig=%d\n",
             PTOU(p)->u_comm, p->p_pid, sig);
         printf("on fault, sigsp = 0x%p, action = 0x%p, upc = 0x%lx\n",
             (void *)sp, (void *)hdlr, (uintptr_t)upc);

@@ -391,23 +417,33 @@
         label_t ljb;
         volatile caddr_t sp;
         caddr_t fp;
         volatile struct regs *rp;
         volatile greg_t upc;
-        volatile proc_t *p = ttoproc(curthread);
+        proc_t *volatile p = ttoproc(curthread);
         klwp_t *lwp = ttolwp(curthread);
         ucontext32_t *volatile tuc = NULL;
         ucontext32_t *uc;
         siginfo32_t *sip_addr;
         volatile int watched;
+        char *volatile xregs = NULL;
+        volatile size_t xregs_size = 0;
 
         rp = lwptoregs(lwp);
         upc = rp->r_pc;
 
         minstacksz = SA32(sizeof (struct sigframe32)) + SA32(sizeof (*uc));
         if (sip != NULL)
                 minstacksz += SA32(sizeof (siginfo32_t));
+
+        /*
+         * Extra registers, if supported by this platform, may be of arbitrary
+         * length. Size them now so we know how big the signal frame has to be.
+         */
+        xregs_size = xregs_getsize(p);
+        minstacksz += SA32(xregs_size);
+
         ASSERT((minstacksz & (STACK_ALIGN32 - 1)) == 0);
 
         /*
          * Figure out whether we will be handling this signal on
          * an alternate stack specified by the user.  Then allocate

@@ -505,10 +541,24 @@
         /* save the current context on the user stack */
         fp -= SA32(sizeof (*tuc));
         uc = (ucontext32_t *)fp;
         tuc = kmem_alloc(sizeof (*tuc), KM_SLEEP);
         savecontext32(tuc, &lwp->lwp_sigoldmask);
+
+        /*
+         * Save extra register state if it exists.
+         */
+        if (xregs_size != 0) {
+                xregs_setptr32(lwp, tuc, (caddr32_t)(uintptr_t)sp);
+                xregs = kmem_alloc(xregs_size, KM_SLEEP);
+                xregs_get(lwp, xregs);
+                copyout_noerr(xregs, sp, xregs_size);
+                kmem_free(xregs, xregs_size);
+                xregs = NULL;
+                sp += SA32(xregs_size);
+        }
+
         copyout_noerr(tuc, uc, sizeof (*tuc));
         kmem_free(tuc, sizeof (*tuc));
         tuc = NULL;
 
         lwp->lwp_oldcontext = (uintptr_t)uc;

@@ -570,10 +620,12 @@
         no_fault();
         if (watched)
                 watch_enable_addr((caddr_t)sp, minstacksz, S_WRITE);
         if (tuc)
                 kmem_free(tuc, sizeof (*tuc));
+        if (xregs_size)
+                kmem_free(xregs, xregs_size);
 #ifdef DEBUG
         printf("sendsig32: bad signal stack cmd=%s pid=%d, sig=%d\n",
             PTOU(p)->u_comm, p->p_pid, sig);
         printf("on fault, sigsp = 0x%p, action = 0x%p, upc = 0x%lx\n",
             (void *)sp, (void *)hdlr, (uintptr_t)upc);