[parisc-linux] Re: [parisc-linux-cvs] linux-2.6 jejb

James Bottomley James.Bottomley@steeleye.com
18 Sep 2003 20:06:32 -0500


On Thu, 2003-09-18 at 20:03, James Bottomley wrote:
> CVSROOT:	/var/cvs
> Module name:	linux-2.6
> Changes by:	jejb	03/09/18 19:03:56
> 
> Modified files:
> 	.              : Makefile 
> 	arch/parisc/kernel: module.c signal.c 
> 	include/asm-parisc: elf.h 
> 
> Log message:
> Clean up signal handling code:
> 
> - remove the less than helpful comments (and replace them with
> meaningful ones
> - get rid of the HACK macros
> - Unify the PLABEL function descriptor handling with modules.c

===== arch/parisc/kernel/module.c 1.8 vs edited =====
--- 1.8/arch/parisc/kernel/module.c	Wed Sep 10 00:44:18 2003
+++ edited/arch/parisc/kernel/module.c	Thu Sep 18 16:01:11 2003
@@ -73,10 +73,7 @@
 	Elf32_Addr addr;
 };
 
-struct fdesc_entry {
-	Elf32_Addr addr;
-	Elf32_Addr gp;
-};
+#define Elf_Fdesc	Elf32_Fdesc
 
 struct stub_entry {
 	Elf32_Word insns[2]; /* each stub entry has two insns */
@@ -86,11 +83,7 @@
 	Elf64_Addr addr;
 };
 
-struct fdesc_entry {
-	Elf64_Addr dummy[2];
-	Elf64_Addr addr;
-	Elf64_Addr gp;
-};
+#define Elf_Fdesc	Elf64_Fdesc
 
 struct stub_entry {
 	Elf64_Word insns[4]; /* each stub entry has four insns */
@@ -276,7 +269,7 @@
 
 	me->core_size = ALIGN(me->core_size, 16);
 	me->arch.fdesc_offset = me->core_size;
-	me->core_size += fdescs * sizeof(struct fdesc_entry);
+	me->core_size += fdescs * sizeof(Elf_Fdesc);
 
 	me->core_size = ALIGN(me->core_size, 16);
 	me->arch.stub_offset = me->core_size;
@@ -322,7 +315,7 @@
 #ifdef __LP64__
 static Elf_Addr get_fdesc(struct module *me, unsigned long value)
 {
-	struct fdesc_entry *fdesc = me->module_core + me->arch.fdesc_offset;
+	Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset;
 
 	if (!value) {
 		printk(KERN_ERR "%s: zero OPD requested!\n", me->name);
@@ -664,7 +657,7 @@
 				*loc64 = get_fdesc(me, val+addend);
 				DEBUGP("FDESC for %s at %p points to %lx\n",
 				       strtab + sym->st_name, *loc64,
-				       ((struct fdesc_entry *)*loc64)->addr);
+				       ((Elf_Fdesc *)*loc64)->addr);
 			} else {
 				/* if the symbol is not local to this
 				 * module then val+addend is a pointer
@@ -696,10 +689,10 @@
 	Elf_Sym *newptr, *oldptr;
 	Elf_Shdr *symhdr = NULL;
 #ifdef DEBUG
-	struct fdesc_entry *entry;
+	Elf_Fdesc *entry;
 	u32 *addr;
 
-	entry = (struct fdesc_entry *)me->init;
+	entry = (Elf_Fdesc *)me->init;
 	printk("FINALIZE, ->init FPTR is %p, GP %lx ADDR %lx\n", entry,
 	       entry->gp, entry->addr);
 	addr = (u32 *)entry->addr;
===== arch/parisc/kernel/signal.c 1.13 vs edited =====
--- 1.13/arch/parisc/kernel/signal.c	Wed Sep 10 00:44:19 2003
+++ edited/arch/parisc/kernel/signal.c	Thu Sep 18 17:49:36 2003
@@ -25,6 +25,7 @@
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/compat.h>
+#include <linux/elf.h>
 #include <asm/ucontext.h>
 #include <asm/rt_sigframe.h>
 #include <asm/uaccess.h>
@@ -41,8 +42,11 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-/* Use this to get at 32-bit user passed pointers. 
- *    See sys_sparc32.c for description about these. */
+/* gcc will complain if a pointer is cast to an integer of different
+ * size.  If you really need to do this (and we do for an ELF32 user
+ * application in an ELF64 kernel) then you have to do a cast to an
+ * integer of the same size first.  The A() macro accomplishes
+ * this. */
 #define A(__x)	((unsigned long)(__x))
 
 int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
@@ -271,7 +275,8 @@
 	       sigset_t *set, struct pt_regs *regs, int in_syscall)
 {
 	struct rt_sigframe *frame;
-	unsigned long rp, usp, haddr;
+	unsigned long rp, usp;
+	Elf32_Addr haddr;
 	struct siginfo si;
 	int err = 0;
 
@@ -308,64 +313,50 @@
 	}
 #endif
 
-#undef CACHE_FLUSHING_IS_NOT_BROKEN
-#ifdef CACHE_FLUSHING_IS_NOT_BROKEN
+	flush_user_dcache_range((unsigned long) &frame->tramp[0],
+			   (unsigned long) &frame->tramp[4]);
 	flush_user_icache_range((unsigned long) &frame->tramp[0],
 			   (unsigned long) &frame->tramp[4]);
-#else
-	/* It should *always* be cache line-aligned, but the compiler
-	sometimes screws up. */
-	asm volatile("fdc 0(%%sr3,%0)\n\t"
-		     "fdc %1(%%sr3,%0)\n\t"
-		     "sync\n\t"
-		     "fic 0(%%sr3,%0)\n\t"
-		     "fic %1(%%sr3,%0)\n\t"
-		     "sync\n\t"
-		      : : "r" (frame->tramp), "r" (L1_CACHE_BYTES));
-#endif
 
 	rp = (unsigned long) frame->tramp;
 
 	if (err)
 		goto give_sigsegv;
 
-/* Much more has to happen with signals than this -- but it'll at least */
-/* provide a pointer to some places which definitely need a look. */
-#define HACK u32
-
-	haddr = (HACK)A(ka->sa.sa_handler);
-	/* ARGH!  Fucking brain damage.  You don't want to know. */
-	if (haddr & 2) {
-		HACK *plabel;
-		HACK ltp;
-
-		plabel = (HACK *) (haddr & ~3);
-		err |= __get_user(haddr, plabel);
-		err |= __get_user(ltp, plabel + 1);
+	haddr = A(ka->sa.sa_handler);
+	/* The sa_handler may be a pointer to a function descriptor */
+	if (haddr & PA_PLABEL_FDESC) {
+		Elf32_Fdesc fdesc;
+		Elf32_Fdesc *ufdesc = (Elf32_Fdesc *)A(haddr & ~3);
+
+		err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
+
 		if (err)
 			goto give_sigsegv;
-		regs->gr[19] = ltp;
+
+		haddr = fdesc.addr;
+		regs->gr[19] = fdesc.gp;
 	}
 
 	/* The syscall return path will create IAOQ values from r31.
 	 */
 	if (in_syscall)
-		regs->gr[31] = (HACK) haddr;
+		regs->gr[31] = haddr;
 	else {
 		regs->gr[0] = USER_PSW;
-		regs->iaoq[0] = (HACK) haddr | 3;
+		regs->iaoq[0] = haddr | 3;
 		regs->iaoq[1] = regs->iaoq[0] + 4;
 	}
 
 	regs->gr[2]  = rp;                /* userland return pointer */
 	regs->gr[26] = sig;               /* signal number */
-	regs->gr[25] = (HACK)A(&frame->info); /* siginfo pointer */
-	regs->gr[24] = (HACK)A(&frame->uc);   /* ucontext pointer */
+	regs->gr[25] = A(&frame->info); /* siginfo pointer */
+	regs->gr[24] = A(&frame->uc);   /* ucontext pointer */
 	DBG(("making sigreturn frame: %#lx + %#x = %#lx\n",
 	       regs->gr[30], PARISC_RT_SIGFRAME_SIZE,
 	       regs->gr[30] + PARISC_RT_SIGFRAME_SIZE));
 	/* Raise the user stack pointer to make a proper call frame. */
-	regs->gr[30] = ((HACK)A(frame) + PARISC_RT_SIGFRAME_SIZE);
+	regs->gr[30] = (A(frame) + PARISC_RT_SIGFRAME_SIZE);
 
 	DBG(("SIG deliver (%s:%d): frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
 	       current->comm, current->pid, frame, regs->gr[30],
===== include/asm-parisc/elf.h 1.8 vs edited =====
--- 1.8/include/asm-parisc/elf.h	Wed Sep 10 00:44:23 2003
+++ edited/include/asm-parisc/elf.h	Thu Sep 18 16:07:25 2003
@@ -144,6 +144,30 @@
 #define R_PARISC_LTOFF_TP16DF	231	/* 16 bits LT-TP-rel. address.  */
 #define R_PARISC_HIRESERVE	255
 
+#define PA_PLABEL_FDESC		0x02	/* bit set if PLABEL points to
+					 * a function descriptor, not
+					 * an address */
+
+/* The following are PA function descriptors 
+ *
+ * addr:	the absolute address of the function
+ * gp:		either the data pointer (r27) for non-PIC code or the
+ *		the PLT pointer (r19) for PIC code */
+
+/* Format for the Elf32 Function descriptor */
+typedef struct elf32_fdesc {
+	__u32	addr;
+	__u32	gp;
+} Elf32_Fdesc;
+
+/* Format for the Elf64 Function descriptor */
+typedef struct elf64_fdesc {
+	__u64	dummy[2]; /* FIXME: nothing uses these, why waste
+			   * the space */
+	__u64	addr;
+	__u64	gp;
+} Elf64_Fdesc;
+
 /* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr.  */
 
 #define PT_HP_TLS		(PT_LOOS + 0x0)