stack size limit on ppc64

Anil K Prasad aprasad at in.ibm.com
Thu Nov 6 05:55:38 EST 2003


Hi,
I worked on Anton's skelton code, and accomodated 64bit instructions.. Here
is the patch.

Thanks,
Anil.

***************************************************************************************
diff -uNr linux-official/arch/ppc64/mm/fault.c
linux-stack/arch/ppc64/mm/fault.c
--- linux-official/arch/ppc64/mm/fault.c         2003-11-04
23:40:06.000000000 -0600
+++ linux-stack/arch/ppc64/mm/fault.c            2003-11-05
11:43:55.000000000 -0600
@@ -52,6 +52,7 @@
 extern void die_if_kernel(char *, struct pt_regs *, long);
 void bad_page_fault(struct pt_regs *, unsigned long);
 void do_page_fault(struct pt_regs *, unsigned long, unsigned long);
+static int store_updates_sp(struct pt_regs *);

 #ifdef CONFIG_PPCDBG
 extern unsigned long get_srr0(void);
@@ -119,6 +120,41 @@
                         goto bad_area;
             }
             vma = find_vma_prev(mm, address, &prev_vma);
+            /*
+         * N.B. The rs6000/xcoff ABI allows programs to access up to
+         * a few hundred bytes below the stack pointer.
+         * The kernel signal delivery code writes up to about 1.5kB
+         * below the stack pointer (r1) before decrementing it.
+         * The exec code can write slightly over 640kB to the stack
+         * before setting the user r1.  Thus we allow the stack to
+         * expand to 1MB without further checks.
+         */
+            if(address + 0x100000 < vma->vm_end){
+                /* get user regs even if this fault is in kernel mode */
+                struct pt_regs *uregs = current->thread.regs;
+                if (uregs == NULL)
+                        goto bad_area;
+
+                /*
+                 * A user-mode access to an address a long way below
+                 * the stack pointer is only valid if the instruction
+                 * is one which would update the stack pointer to the
+                 * address accessed if the instruction completed,
+                 * i.e. either stwu rs,n(r1) or stwux rs,r1,rb
+                 * (or the byte, halfword, float or double forms).
+                 *
+                 * If we don't check this then any write to the area
+                 * between the last mapped region and the stack will
+                 * expand the stack rather than segfaulting.
+                         * Also lowest valid address is 288 bytes less
than the
+                         * value in the stack pointer( according to ppc64
ABI)
+                 */
+
+                        if (address + 288 < uregs->gpr[1] &&
+                                    (!user_mode(regs) ||
!store_updates_sp(regs)))
+                                    PPCDBG(PPCDBG_MM, "\tdo_page_fault:
huge stack\n");
+                                    goto bad_area;
+            }
             if (expand_stack(vma, address, prev_vma)) {
                         PPCDBG(PPCDBG_MM, "\tdo_page_fault:
expand_stack\n");
                         goto bad_area;
@@ -242,3 +278,66 @@
             panic("kernel access of bad area pc %lx lr %lx address %lX tsk
%s/%d",

regs->nip,regs->link,address,current->comm,current->pid);
 }
+/*
+ * Check wether the instruction at regs->nip is a store using an
+ * update addressing form which will update sp
+ */
+
+static int
+store_updates_sp(struct pt_regs *regs)
+{
+            union {
+                        unsigned int inst;
+                        union {
+                                    struct {
+                                                unsigned int opcode:6;
+                                                unsigned int rs:5;
+                                                unsigned int ra:5;
+                                                unsigned int d:16;
+                                    }d_form;
+                                    struct {
+                                                unsigned int opcode:6;
+                                                unsigned int rs:5;
+                                                unsigned int ra:5;
+                                                unsigned int rb:5;
+                                                unsigned int xcode:10;
+                                                unsigned int resv:1;
+                                    }index_form;
+                        }inst_form;
+            }inst;
+            if(get_user(inst.inst, (unsigned int*)regs->nip))
+                        return 0;
+            /*
+             * if RA != sp
+             */
+            if(inst.inst_form.d_form.ra != 1)
+                        return 0;
+            /*
+             * check for store update instructions
+             */
+            switch(inst.inst_form.d_form.opcode) {
+                        case 37:          /* stwu */
+                        case 39:          /* stbu */
+                        case 45:          /* sthu */
+                        case 53:          /* stfsu */
+                        case 55:          /* stfdu */
+                        case 62:          /* stdu */
+                                    return 1;
+                        case 31:
+
switch(inst.inst_form.index_form.xcode) {
+                                                case 181:         /* stwux
*/
+                                                case 183:         /* stbux
*/
+                                                case 247:         /* stdux
*/
+                                                case 439:         /* sthux
*/
+                                                case 695:         /*
stfsux */
+                                                case 759:         /*
stfdux */
+                                                            return 1;
+                                                default:
+                                                            return 0;
+                                    }
+                        default:
+                                    return 0;
+
+            }
+            return 0;
+}


** Sent via the linuxppc64-dev mail list. See http://lists.linuxppc.org/





More information about the Linuxppc64-dev mailing list