]> git.neil.brown.name Git - history.git/commitdiff
ia64: Make signal deliver work when the current register frame is
authorDavid Mosberger <davidm@tiger.hpl.hp.com>
Mon, 10 Feb 2003 10:28:07 +0000 (02:28 -0800)
committerDavid Mosberger <davidm@tiger.hpl.hp.com>
Mon, 10 Feb 2003 10:28:07 +0000 (02:28 -0800)
incomplete (as a result of a faulting mandatory RSE load).

arch/ia64/kernel/entry.S
arch/ia64/kernel/gate.S
arch/ia64/kernel/sigframe.h
arch/ia64/kernel/signal.c

index 20c417d57bb91b58fa4eff08562a17f23c0740ac..f6d9d4c147ff9c6b5514f55567fc5c1e398166be 100644 (file)
@@ -904,13 +904,14 @@ ENTRY(notify_resume_user)
        mov r9=ar.unat
        mov loc0=rp                             // save return address
        mov out0=0                              // there is no "oldset"
-       adds out1=0,sp                          // out1=&sigscratch
+       adds out1=8,sp                          // out1=&sigscratch->ar_pfs
 (pSys) mov out2=1                              // out2==1 => we're in a syscall
        ;;
 (pNonSys) mov out2=0                           // out2==0 => not a syscall
        .fframe 16
        .spillpsp ar.unat, 16                   // (note that offset is relative to psp+0x10!)
        st8 [sp]=r9,-16                         // allocate space for ar.unat and save it
+       st8 [out1]=loc1,-8                      // save ar.pfs, out1=&sigscratch
        .body
        br.call.sptk.many rp=do_notify_resume_user
 .ret15:        .restore sp
@@ -931,11 +932,12 @@ GLOBAL_ENTRY(sys_rt_sigsuspend)
        mov loc0=rp                             // save return address
        mov out0=in0                            // mask
        mov out1=in1                            // sigsetsize
-       adds out2=0,sp                          // out2=&sigscratch
+       adds out2=8,sp                          // out2=&sigscratch->ar_pfs
        ;;
        .fframe 16
        .spillpsp ar.unat, 16                   // (note that offset is relative to psp+0x10!)
        st8 [sp]=r9,-16                         // allocate space for ar.unat and save it
+       st8 [out2]=loc1,-8                      // save ar.pfs, out2=&sigscratch
        .body
        br.call.sptk.many rp=ia64_rt_sigsuspend
 .ret17:        .restore sp
index 302fc06fb04b7c0e47da26cb60d68b6e4dfe6aa7..38b6a44e25c096896a6510a2ddcd05f77c9ce08f 100644 (file)
@@ -145,11 +145,12 @@ END(fsys_fallback_syscall)
         */
 
 #define SIGTRAMP_SAVES                                                                         \
-       .unwabi @svr4, 's'              // mark this as a sigtramp handler (saves scratch regs) \
-       .savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF                                                \
-       .savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF                                                \
-       .savesp pr, PR_OFF+SIGCONTEXT_OFF                                                       \
-       .savesp rp, RP_OFF+SIGCONTEXT_OFF                                                       \
+       .unwabi @svr4, 's';     /* mark this as a sigtramp handler (saves scratch regs) */      \
+       .savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF;                                               \
+       .savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF;                                               \
+       .savesp pr, PR_OFF+SIGCONTEXT_OFF;                                                      \
+       .savesp rp, RP_OFF+SIGCONTEXT_OFF;                                                      \
+       .savesp ar.pfs, CFM_OFF+SIGCONTEXT_OFF;                                                 \
        .vframesp SP_OFF+SIGCONTEXT_OFF
 
 GLOBAL_ENTRY(ia64_sigtramp)
@@ -173,9 +174,7 @@ GLOBAL_ENTRY(ia64_sigtramp)
        .spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
 (p8)   br.cond.spnt setup_rbs          // yup -> (clobbers r14, r15, and r16)
 back_from_setup_rbs:
-
-       .spillreg ar.pfs, r8
-       alloc r8=ar.pfs,0,0,3,0         // get CFM0, EC0, and CPL0 into r8
+       alloc r8=ar.pfs,0,0,3,0
        ld8 out0=[base0],16             // load arg0 (signum)
        adds base1=(ARG1_OFF-(RBS_BASE_OFF+SIGCONTEXT_OFF)),base1
        ;;
@@ -184,17 +183,12 @@ back_from_setup_rbs:
        ;;
        ld8 out2=[base0]                // load arg2 (sigcontextp)
        ld8 gp=[r17]                    // get signal handler's global pointer
-
        adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
        ;;
        .spillsp ar.bsp, BSP_OFF+SIGCONTEXT_OFF
-       st8 [base0]=r9,(CFM_OFF-BSP_OFF)        // save sc_ar_bsp
-       dep r8=0,r8,38,26                       // clear EC0, CPL0 and reserved bits
-       adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
-       ;;
-       .spillsp ar.pfs, CFM_OFF+SIGCONTEXT_OFF
-       st8 [base0]=r8                          // save CFM0
+       st8 [base0]=r9                  // save sc_ar_bsp
        adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
+       adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
        ;;
        stf.spill [base0]=f6,32
        stf.spill [base1]=f7,32
@@ -217,7 +211,6 @@ back_from_setup_rbs:
        ld8 r15=[base0],(CFM_OFF-BSP_OFF)       // fetch sc_ar_bsp and advance to CFM_OFF
        mov r14=ar.bsp
        ;;
-       ld8 r8=[base0]                          // restore (perhaps modified) CFM0, EC0, and CPL0
        cmp.ne p8,p0=r14,r15                    // do we need to restore the rbs?
 (p8)   br.cond.spnt restore_rbs                // yup -> (clobbers r14-r18, f6 & f7)
        ;;
index 414c121b6f69a2d912bbd3e88064d8d204a1defc..55e527527132173cb028487e0497e4f0ea7d0e1a 100644 (file)
@@ -1,6 +1,6 @@
 struct sigscratch {
        unsigned long scratch_unat;     /* ar.unat for the general registers saved in pt */
-       unsigned long pad;
+       unsigned long ar_pfs;           /* for syscalls, the user-level function-state  */
        struct pt_regs pt;
 };
 
index 8ff4fe33902a7806d0583df055dc05a1013a0138..de76608b78517e1685e4fdce6442c8533aa2031a 100644 (file)
@@ -315,7 +315,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)
 static long
 setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr)
 {
-       unsigned long flags = 0, ifs, nat;
+       unsigned long flags = 0, ifs, cfm, nat;
        long err;
 
        ifs = scr->pt.cr_ifs;
@@ -325,7 +325,9 @@ setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr)
        if ((ifs & (1UL << 63)) == 0) {
                /* if cr_ifs isn't valid, we got here through a syscall */
                flags |= IA64_SC_FLAG_IN_SYSCALL;
-       }
+               cfm = scr->ar_pfs & ((1UL << 38) - 1);
+       } else
+               cfm = ifs & ((1UL << 38) - 1);
        ia64_flush_fph(current);
        if ((current->thread.flags & IA64_THREAD_FPH_VALID)) {
                flags |= IA64_SC_FLAG_FPH_VALID;
@@ -344,6 +346,7 @@ setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr)
 
        err |= __put_user(nat, &sc->sc_nat);
        err |= PUT_SIGSET(mask, &sc->sc_mask);
+       err |= __put_user(cfm, &sc->sc_cfm);
        err |= __put_user(scr->pt.cr_ipsr & IA64_PSR_UM, &sc->sc_um);
        err |= __put_user(scr->pt.ar_rsc, &sc->sc_ar_rsc);
        err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv);
@@ -422,6 +425,15 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
        scr->pt.ar_fpsr = FPSR_DEFAULT;                 /* reset fpsr for signal handler */
        scr->pt.cr_iip = tramp_addr;
        ia64_psr(&scr->pt)->ri = 0;                     /* start executing in first slot */
+       /*
+        * Force the interruption function mask to zero.  This has no effect when a
+        * system-call got interrupted by a signal (since, in that case, scr->pt_cr_ifs is
+        * ignored), but it has the desirable effect of making it possible to deliver a
+        * signal with an incomplete register frame (which happens when a mandatory RSE
+        * load faults).  Furthermore, it has no negative effect on the getting the user's
+        * dirty partition preserved, because that's governed by scr->pt.loadrs.
+        */
+       scr->pt.cr_ifs = (1UL << 63);
 
        /*
         * Note: this affects only the NaT bits of the scratch regs (the ones saved in