Browse Source

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kyle/parisc-2.6

* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kyle/parisc-2.6:
  [PARISC] unwinder improvements
  [PARISC] Fix unwinder on 64-bit kernels
  [PARISC] Handle wrapping in expand_upwards()
  [PARISC] stop lcd driver from stripping initial whitespace
Linus Torvalds 18 years ago
parent
commit
9738cbe321
4 changed files with 43 additions and 16 deletions
  1. 36 7
      arch/parisc/kernel/unwind.c
  2. 0 6
      drivers/parisc/led.c
  3. 0 1
      include/asm-parisc/system.h
  4. 7 2
      mm/mmap.c

+ 36 - 7
arch/parisc/kernel/unwind.c

@@ -16,6 +16,8 @@
 
 #include <asm/uaccess.h>
 #include <asm/assembly.h>
+#include <asm/asm-offsets.h>
+#include <asm/ptrace.h>
 
 #include <asm/unwind.h>
 
@@ -26,6 +28,8 @@
 #define dbg(x...)
 #endif
 
+#define KERNEL_START (KERNEL_BINARY_TEXT_START - 0x1000)
+
 extern struct unwind_table_entry __start___unwind[];
 extern struct unwind_table_entry __stop___unwind[];
 
@@ -197,6 +201,29 @@ static int unwind_init(void)
 	return 0;
 }
 
+#ifdef CONFIG_64BIT
+#define get_func_addr(fptr) fptr[2]
+#else
+#define get_func_addr(fptr) fptr[0]
+#endif
+
+static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size)
+{
+	void handle_interruption(int, struct pt_regs *);
+	static unsigned long *hi = (unsigned long)&handle_interruption;
+
+	if (pc == get_func_addr(hi)) {
+		struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN);
+		dbg("Unwinding through handle_interruption()\n");
+		info->prev_sp = regs->gr[30];
+		info->prev_ip = regs->iaoq[0];
+
+		return 1;
+	}
+
+	return 0;
+}
+
 static void unwind_frame_regs(struct unwind_frame_info *info)
 {
 	const struct unwind_table_entry *e;
@@ -310,13 +337,15 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
 			}
 		}
 
-		info->prev_sp = info->sp - frame_size;
-		if (e->Millicode)
-			info->rp = info->r31;
-		else if (rpoffset)
-			info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
-		info->prev_ip = info->rp;
-		info->rp = 0;
+		if (!unwind_special(info, e->region_start, frame_size)) {
+			info->prev_sp = info->sp - frame_size;
+			if (e->Millicode)
+				info->rp = info->r31;
+			else if (rpoffset)
+				info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
+			info->prev_ip = info->rp;
+			info->rp = 0;
+		}
 
 		dbg("analyzing func @ %lx, setting prev_sp=%lx "
 		    "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp, 

+ 0 - 6
drivers/parisc/led.c

@@ -195,12 +195,6 @@ static int led_proc_write(struct file *file, const char *buf,
 
 	cur = lbuf;
 
-	/* skip initial spaces */
-	while (*cur && isspace(*cur))
-	{
-		cur++;
-	}
-
 	switch ((long)data)
 	{
 	case LED_NOLCD:

+ 0 - 1
include/asm-parisc/system.h

@@ -188,7 +188,6 @@ static inline void set_eiem(unsigned long val)
 # define __lock_aligned __attribute__((__section__(".data.lock_aligned")))
 #endif
 
-#define KERNEL_START (0x10100000 - 0x1000)
 #define arch_align_stack(x) (x)
 
 #endif

+ 7 - 2
mm/mmap.c

@@ -1536,9 +1536,14 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
 	 * vma->vm_start/vm_end cannot change under us because the caller
 	 * is required to hold the mmap_sem in read mode.  We need the
 	 * anon_vma lock to serialize against concurrent expand_stacks.
+	 * Also guard against wrapping around to address 0.
 	 */
-	address += 4 + PAGE_SIZE - 1;
-	address &= PAGE_MASK;
+	if (address < PAGE_ALIGN(address+4))
+		address = PAGE_ALIGN(address+4);
+	else {
+		anon_vma_unlock(vma);
+		return -ENOMEM;
+	}
 	error = 0;
 
 	/* Somebody else might have raced and expanded it already */