Skip to contentSkip to conversation

Fix FRV, ELF-FDPIC and NOMMU stuff [try #3]

PATCH In review David Howells 3 participants 25 messages Jul 6, 2006 – Jul 7, 2006

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Fix FRV, ELF-FDPIC and NOMMU stuff [try #3]

The attached patches:

(1) Fix compilation errors and other problems in the FRV arch and the ELF-FDPIC binfmt driver.

(2) Fix a problem with the NOMMU ramfs filesystem when executing binaries stored therein.

(3) Fix up the ELF-FDPIC coding style and implement a minor change to reduce the number of times ksize() is called.

(4) Add ELF-FDPIC coredump support.

(5) Make the FRV arch make use of the asm-offsets stuff.

In [try #2] the following change has been made:

(*) Inclusions of <linux/config.h> added by the patches have been dropped as
they're not necessary.

In [try #3]:

(*) ELF-FDPIC Coding style fixups.

(*) Minor ELF-FDPIC change to reduce the number of times ksize() is called.

#1 lore raw

PATCH 1/6 FDPIC: Fix FDPIC compile errors [try #3]

From: David Howells <[email protected]>

The attached patch fixes FDPIC compile errors

---

 fs/binfmt_elf_fdpic.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
fs/binfmt_elf_fdpic.c +1 -0
index eba4e23..07624b9 100644
@@ -459,6 +459,7 @@ #endif
 	 */
 	hwcap = ELF_HWCAP;
 	k_platform = ELF_PLATFORM;
+	u_platform = NULL;
 
 	if (k_platform) {
 		platform_len = strlen(k_platform) + 1;
#2 lore raw

Re: [PATCH 1/6] FDPIC: Fix FDPIC compile errors [try #3]

Quoted 15 lines · David Howells

From: David Howells <[email protected]>

The attached patch fixes FDPIC compile errors

---

 fs/binfmt_elf_fdpic.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
fs/binfmt_elf_fdpic.c +0 -0
index eba4e23..07624b9 100644

fs/binfmt_elf_fdpic.c #endif · line 465

Quoted 7 lines
fs/binfmt_elf_fdpic.c +1 -0
@@ -459,6 +459,7 @@ #endif
 	 */
 	hwcap = ELF_HWCAP;
 	k_platform = ELF_PLATFORM;
+	u_platform = NULL;
 
 	if (k_platform) {
 		platform_len = strlen(k_platform) + 1;

Isn't this just working around a compiler problem -- a spurious warning? It certainly shouldn't be a 'compile error',

Signature · 1 line
dwmw2
#3 lore raw

Re: [PATCH 1/6] FDPIC: Fix FDPIC compile errors [try #3]

Quoted 2 lines · David Woodhouse

Isn't this just working around a compiler problem -- a spurious warning? It certainly shouldn't be a 'compile error',

It's fixed as for binfmt_elf.c. You can unfix binfmt_elf.c if you wish.

David

#4 lore raw

PATCH 2/6 FRV: Fix FRV arch compile errors [try #3]

In reply to David Howells

From: David Howells <[email protected]>

The attached patch fixes some FRV arch compile errors, including:

(*) Marking nr_kernel_pages as __initdata so that references to it end up
being properly calculated rather than being assumed to be in the small data section (and thus calculated wrt the GP register). Not doing this causes the linker to emit errors as the offset is too big to fit into the load instruction.

(*) Move pm_power_off into an unconditionally compiled .c file as it's now
unconditionally accessed.

(*) Declare frv_change_cmode() in a header file rather than in a .c file, and
declare it asmlinkage.

---

 arch/frv/kernel/local.h   |    3 +++
 arch/frv/kernel/pm.c      |    5 -----
 arch/frv/kernel/process.c |    4 ++++
 include/linux/bootmem.h   |    2 +-
 4 files changed, 8 insertions(+), 6 deletions(-)
arch/frv/kernel/local.h +3 -0
index e947176..76606d1 100644
@@ -51,6 +51,9 @@ #endif
 /* time.c */
 extern void time_divisor_init(void);
 
+/* cmode.S */
+extern asmlinkage void frv_change_cmode(int);
+
 
 #endif /* __ASSEMBLY__ */
 #endif /* _FRV_LOCAL_H */
arch/frv/kernel/pm.c +0 -5
index e65a9f1..c1d9fc8 100644
@@ -26,11 +26,6 @@ #include <asm/mb86943a.h>
 
 #include "local.h"
 
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
-extern void frv_change_cmode(int);
-
 /*
  * Debug macros
  */
arch/frv/kernel/process.c +4 -0
index eeeb1e2..ecdeafb 100644
@@ -10,6 +10,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -38,6 +39,9 @@ asmlinkage void ret_from_fork(void);
 
 #include <asm/pgalloc.h>
 
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
 struct task_struct *alloc_task_struct(void)
 {
 	struct task_struct *p = kmalloc(THREAD_SIZE, GFP_KERNEL);
include/linux/bootmem.h +1 -1
index 22866fa..8735d53 100644
@@ -91,7 +91,7 @@ static inline void *alloc_remap(int nid,
 }
 #endif
 
-extern unsigned long nr_kernel_pages;
+extern unsigned long __initdata nr_kernel_pages;
 extern unsigned long nr_all_pages;
 
 extern void *__init alloc_large_system_hash(const char *tablename,
#5 lore raw

Re: [PATCH 2/6] FRV: Fix FRV arch compile errors [try #3]

include/linux/bootmem.h static inline void *alloc_remap(int nid, · line 94

Quoted 8 lines · On Thu, 06 Jul 2006 13:47:21 +0100 David Howells <[email protected]> wrote:
include/linux/bootmem.h +1 -1
@@ -91,7 +91,7 @@ static inline void *alloc_remap(int nid,
 }
 #endif
 
-extern unsigned long nr_kernel_pages;
+extern unsigned long __initdata nr_kernel_pages;

- The __init-style tags on declarations don't actually do anything and the compiler doesn't check for consistency with the definition - it's best to just omit it from the declaration.

- Setting nr_kernel_pages to be unloaded at free_initmem() seems risky.

- nr_kernel_pages is actually __meminitdata.

So I'll drop this hunk.

#6 lore raw

Re: [PATCH 2/6] FRV: Fix FRV arch compile errors [try #3]

Quoted 3 lines · Andrew Morton

- The __init-style tags on declarations don't actually do anything and the compiler doesn't check for consistency with the definition - it's best to just omit it from the declaration.

Well, you're wrong. They *do* do something. They stop the compiler using the register-relative addressing reserved for small data. If this isn't in there, then the linker will spit out a relocation error.

On fixed-size instruction architectures, it takes several instructions to dereference an absolute address, so you try and squeeze all your small data into a section of its own, plonk a register in the middle of it, and use indirect-addressing relative to that register. This saves you two or more instructions and a register on each normal global variable access.

For instance, on FRV, it may change:

	sethi.p		%hi(nr_kernel_pages),gr4
	setlo		%lo(nr_kernel_pages),gr4
	ld		@(gr4,gr0),gr5

Into:

	ld		@(gr16,%gprel(nr_kernel_pages)),gr5

Small data is 1-byte, 2-byte, 4-byte or 8-byte values that aren't arrays or const.

Setting a section marker on the variable *declaration* disables the gp-relative addressing and forces the longer absolute addressing.

Quoted 1 line

- Setting nr_kernel_pages to be unloaded at free_initmem() seems risky.

That's nothing to do with my patch.

Quoted 1 line

- nr_kernel_pages is actually __meminitdata.

Okay, I'll fix my patch to be that instead.

David

#7 lore raw

Re: [PATCH 2/6] FRV: Fix FRV arch compile errors [try #3]

Quoted 9 lines · On Thu, 06 Jul 2006 19:25:03 +0100 David Howells <[email protected]> wrote:
Quoted 3 lines · Andrew Morton

- The __init-style tags on declarations don't actually do anything and the compiler doesn't check for consistency with the definition - it's best to just omit it from the declaration.

Well, you're wrong. They *do* do something. They stop the compiler using the register-relative addressing reserved for small data. If this isn't in there, then the linker will spit out a relocation error.

Sigh. So if we get this wrong (and we have, and we shall) then the error gets silently accepted by the toolchain until someone comes along and tries to link it on FVR.

Is there anything we can do about that? Mangling the names with some macro isn't attractive. Teach sparse about it? Dunno.

Right now we're showing a grand total of two identifiers tagged with __initdata in all of include/. Why isn't FRV blowing up all over the place? Is there something about nr_kernel_pages which made us get unlucky?

#8 lore raw

Re: [PATCH 2/6] FRV: Fix FRV arch compile errors [try #3]

Quoted 3 lines · Andrew Morton

Right now we're showing a grand total of two identifiers tagged with __initdata in all of include/. Why isn't FRV blowing up all over the place? Is there something about nr_kernel_pages which made us get unlucky?

There used to be more than that, IIRC. It's possible that they've mostly been localised to single .c files. I'll have to find the patch in which I dealt with this originally and look.

It may also be that there aren't that many anymore that aren't static and/or aren't confined to arch code.

Davod

#9 lore raw

Re: [PATCH 2/6] FRV: Fix FRV arch compile errors [try #3]

In reply to David Howells
Quoted 9 lines · On Thu, 06 Jul 2006 13:47:21 +0100 David Howells <[email protected]> wrote:

From: David Howells <[email protected]>

The attached patch fixes some FRV arch compile errors, including:

(*) Marking nr_kernel_pages as __initdata so that references to it end up
being properly calculated rather than being assumed to be in the small data section (and thus calculated wrt the GP register). Not doing this causes the linker to emit errors as the offset is too big to fit into the load instruction.

ocrap, I didn't read this bit. Really? We skip the section tag on the declaration all over the place and keeping them in sync is going to be quite unreliable due to lack of compiler checking.

include/linux/bootmem.h static inline void *alloc_remap(int nid, · line 97

Quoted 11 lines
include/linux/bootmem.h +1 -1
@@ -91,7 +91,7 @@ static inline void *alloc_remap(int nid,
 }
 #endif
 
-extern unsigned long nr_kernel_pages;
+extern unsigned long __initdata nr_kernel_pages;
 extern unsigned long nr_all_pages;
 
 extern void *__init alloc_large_system_hash(const char *tablename,

So this wants to be __meminitdata. Problem. How does it manifest on FRV? A linker error or a mysterious crash?

#10 lore raw

Re: [PATCH 2/6] FRV: Fix FRV arch compile errors [try #3]

Quoted 1 line · Andrew Morton

ocrap, I didn't read this bit. Really?

Really. See the reply I sent a short while ago for more details.

Quoted 3 lines

We skip the section tag on the declaration all over the place and keeping them in sync is going to be quite unreliable due to lack of compiler checking.

Yeah. I've added quite a few previously to get FRV to link.

Quoted 2 lines

So this wants to be __meminitdata. Problem. How does it manifest on FRV? A linker error or a mysterious crash?

A linker error: the offset from the GP-register position to the variable exceeds what'll fit in an address offset field.

David

#11 lore raw

PATCH 3/6 NOMMU: Fix execution off of ramfs with mmap() [try #3]

In reply to David Howells

From: David Howells <[email protected]>

Fix execution through the FDPIC binfmt of programs stored on ramfs by preventing the ramfs mmap() returning successfully on a private mapping of a ramfs file. This causes NOMMU mmap to make a copy of the mapped portion of the file and map that instead.

This could be improved by granting direct mapping access to read-only private mappings for which the data is stored on a contiguous run of pages. However, this is only likely to be the case if the file was extended with truncate before being written.

ramfs is left to map the file directly for shared mappings so that SYSV IPC and POSIX shared memory both still work.

---

 fs/ramfs/file-nommu.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
fs/ramfs/file-nommu.c +2 -2
index 99fffc9..677139b 100644
@@ -283,9 +283,9 @@ unsigned long ramfs_nommu_get_unmapped_a
 
 /*****************************************************************************/
 /*
- * set up a mapping
+ * set up a mapping for shared memory segments
  */
 int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	return 0;
+	return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS;
 }
#12 lore raw

PATCH 4/6 FDPIC: Adjust the ELF-FDPIC driver to conform more to the CodingStyle [try #3]

In reply to David Howells

From: David Howells <[email protected]>

Adjust the ELF-FDPIC binfmt driver to conform much more to the CodingStyle, silly though it may be.

Further changes:

(*) Drop the casts to long for addresses in kdebug() statements (they're
unsigned long already).

(*) Use extra variables to avoid expressions longer than 80 chars by splitting
the statement into multiple statements and letting the compiler optimise them back together.

(*) Eliminate duplicate call of ksize() when working out how much space was
actually allocated for the stack.

(*) Discard the commented-out load_shlib prototype and op pointer as this will
not be supported in ELF-FDPIC for the foreseeable future.

---

 fs/binfmt_elf_fdpic.c |  305 +++++++++++++++++++++++++++----------------------
 1 files changed, 168 insertions(+), 137 deletions(-)
fs/binfmt_elf_fdpic.c +168 -137
index 07624b9..a4ff873 100644
@@ -1,6 +1,6 @@
 /* binfmt_elf_fdpic.c: FDPIC ELF binary format
  *
- * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2003, 2004, 2006 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells ([email protected])
  * Derived from binfmt_elf.c
  *
@@ -50,43 +50,45 @@ #endif
 
 MODULE_LICENSE("GPL");
 
-static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs);
-//static int load_elf_fdpic_library(struct file *);
-static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *file);
-static int elf_fdpic_map_file(struct elf_fdpic_params *params,
-			      struct file *file,
-			      struct mm_struct *mm,
-			      const char *what);
+static int load_elf_fdpic_binary(struct linux_binprm *, struct pt_regs *);
+static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *, struct file *);
+static int elf_fdpic_map_file(struct elf_fdpic_params *, struct file *,
+			      struct mm_struct *, const char *);
 
-static int create_elf_fdpic_tables(struct linux_binprm *bprm,
-				   struct mm_struct *mm,
-				   struct elf_fdpic_params *exec_params,
-				   struct elf_fdpic_params *interp_params);
+static int create_elf_fdpic_tables(struct linux_binprm *, struct mm_struct *,
+				   struct elf_fdpic_params *,
+				   struct elf_fdpic_params *);
 
 #ifndef CONFIG_MMU
-static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm, unsigned long *_sp);
-static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *params,
-						   struct file *file,
-						   struct mm_struct *mm);
+static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *,
+					    unsigned long *);
+static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *,
+						   struct file *,
+						   struct mm_struct *);
 #endif
 
-static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
-					     struct file *file,
-					     struct mm_struct *mm);
+static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *,
+					     struct file *, struct mm_struct *);
 
 static struct linux_binfmt elf_fdpic_format = {
 	.module		= THIS_MODULE,
 	.load_binary	= load_elf_fdpic_binary,
-//	.load_shlib	= load_elf_fdpic_library,
 //	.core_dump	= elf_fdpic_core_dump,
 	.min_coredump	= ELF_EXEC_PAGESIZE,
 };
 
-static int __init init_elf_fdpic_binfmt(void)  { return register_binfmt(&elf_fdpic_format); }
-static void __exit exit_elf_fdpic_binfmt(void) { unregister_binfmt(&elf_fdpic_format); }
+static int __init init_elf_fdpic_binfmt(void)
+{
+	return register_binfmt(&elf_fdpic_format);
+}
 
-module_init(init_elf_fdpic_binfmt)
-module_exit(exit_elf_fdpic_binfmt)
+static void __exit exit_elf_fdpic_binfmt(void)
+{
+	unregister_binfmt(&elf_fdpic_format);
+}
+
+module_init(init_elf_fdpic_binfmt);
+module_exit(exit_elf_fdpic_binfmt);
 
 static int is_elf_fdpic(struct elfhdr *hdr, struct file *file)
 {
@@ -105,7 +107,8 @@ static int is_elf_fdpic(struct elfhdr *h
 /*
  * read the program headers table into memory
  */
-static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *file)
+static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params,
+				 struct file *file)
 {
 	struct elf32_phdr *phdr;
 	unsigned long size;
@@ -121,7 +124,8 @@ static int elf_fdpic_fetch_phdrs(struct 
 	if (!params->phdrs)
 		return -ENOMEM;
 
-	retval = kernel_read(file, params->hdr.e_phoff, (char *) params->phdrs, size);
+	retval = kernel_read(file, params->hdr.e_phoff,
+			     (char *) params->phdrs, size);
 	if (retval < 0)
 		return retval;
 
@@ -141,17 +145,24 @@ static int elf_fdpic_fetch_phdrs(struct 
 	}
 
 	return 0;
-} /* end elf_fdpic_fetch_phdrs() */
+}
 
 /*****************************************************************************/
 /*
  * load an fdpic binary into various bits of memory
  */
-static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+static int load_elf_fdpic_binary(struct linux_binprm *bprm,
+				 struct pt_regs *regs)
 {
 	struct elf_fdpic_params exec_params, interp_params;
 	struct elf_phdr *phdr;
-	unsigned long stack_size;
+	unsigned long stack_size, entryaddr;
+#ifndef CONFIG_MMU
+	unsigned long fullsize;
+#endif
+#ifdef ELF_FDPIC_PLAT_INIT
+	unsigned long dynaddr;
+#endif
 	struct file *interpreter = NULL; /* to shut gcc up */
 	char *interpreter_name = NULL;
 	int executable_stack;
@@ -212,7 +223,8 @@ static int load_elf_fdpic_binary(struct 
 				goto error;
 			}
 
-			retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE);
+			retval = kernel_read(interpreter, 0, bprm->buf,
+					     BINPRM_BUF_SIZE);
 			if (retval < 0)
 				goto error;
 
@@ -295,7 +307,8 @@ #ifdef CONFIG_MMU
 				  &current->mm->start_stack,
 				  &current->mm->start_brk);
 
-	retval = setup_arg_pages(bprm, current->mm->start_stack, executable_stack);
+	retval = setup_arg_pages(bprm, current->mm->start_stack,
+				 executable_stack);
 	if (retval < 0) {
 		send_sig(SIGKILL, current, 0);
 		goto error_kill;
@@ -303,7 +316,8 @@ #ifdef CONFIG_MMU
 #endif
 
 	/* load the executable and interpreter into memory */
-	retval = elf_fdpic_map_file(&exec_params, bprm->file, current->mm, "executable");
+	retval = elf_fdpic_map_file(&exec_params, bprm->file, current->mm,
+				    "executable");
 	if (retval < 0)
 		goto error_kill;
 
@@ -324,7 +338,8 @@ #ifdef CONFIG_MMU
 	if (!current->mm->start_brk)
 		current->mm->start_brk = current->mm->end_data;
 
-	current->mm->brk = current->mm->start_brk = PAGE_ALIGN(current->mm->start_brk);
+	current->mm->brk = current->mm->start_brk =
+		PAGE_ALIGN(current->mm->start_brk);
 
 #else
 	/* create a stack and brk area big enough for everyone
@@ -336,47 +351,45 @@ #else
 		stack_size = PAGE_SIZE * 2;
 
 	down_write(&current->mm->mmap_sem);
-	current->mm->start_brk = do_mmap(NULL,
-					 0,
-					 stack_size,
+	current->mm->start_brk = do_mmap(NULL, 0, stack_size,
 					 PROT_READ | PROT_WRITE | PROT_EXEC,
 					 MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN,
 					 0);
 
-	if (IS_ERR((void *) current->mm->start_brk)) {
+	if (IS_ERR_VALUE(current->mm->start_brk)) {
 		up_write(&current->mm->mmap_sem);
 		retval = current->mm->start_brk;
 		current->mm->start_brk = 0;
 		goto error_kill;
 	}
 
-	if (do_mremap(current->mm->start_brk,
-		      stack_size,
-		      ksize((char *) current->mm->start_brk),
-		      0, 0
-		      ) == current->mm->start_brk
-	    )
-		stack_size = ksize((char *) current->mm->start_brk);
+	/* expand the stack mapping to use up the entire allocation granule */
+	fullsize = ksize((char *) current->mm->start_brk);
+	if (!IS_ERR_VALUE(do_mremap(current->mm->start_brk, stack_size,
+				    fullsize, 0, 0)))
+		stack_size = fullsize;
 	up_write(&current->mm->mmap_sem);
 
 	current->mm->brk = current->mm->start_brk;
 	current->mm->context.end_brk = current->mm->start_brk;
-	current->mm->context.end_brk += (stack_size > PAGE_SIZE) ? (stack_size - PAGE_SIZE) : 0;
+	current->mm->context.end_brk +=
+		(stack_size > PAGE_SIZE) ? (stack_size - PAGE_SIZE) : 0;
 	current->mm->start_stack = current->mm->start_brk + stack_size;
 #endif
 
 	compute_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
-	if (create_elf_fdpic_tables(bprm, current->mm, &exec_params, &interp_params) < 0)
+	if (create_elf_fdpic_tables(bprm, current->mm,
+				    &exec_params, &interp_params) < 0)
 		goto error_kill;
 
-	kdebug("- start_code  %lx",	(long) current->mm->start_code);
-	kdebug("- end_code    %lx",	(long) current->mm->end_code);
-	kdebug("- start_data  %lx",	(long) current->mm->start_data);
-	kdebug("- end_data    %lx",	(long) current->mm->end_data);
-	kdebug("- start_brk   %lx",	(long) current->mm->start_brk);
-	kdebug("- brk         %lx",	(long) current->mm->brk);
-	kdebug("- start_stack %lx",	(long) current->mm->start_stack);
+	kdebug("- start_code  %lx", current->mm->start_code);
+	kdebug("- end_code    %lx", current->mm->end_code);
+	kdebug("- start_data  %lx", current->mm->start_data);
+	kdebug("- end_data    %lx", current->mm->end_data);
+	kdebug("- start_brk   %lx", current->mm->start_brk);
+	kdebug("- brk         %lx", current->mm->brk);
+	kdebug("- start_stack %lx", current->mm->start_stack);
 
 #ifdef ELF_FDPIC_PLAT_INIT
 	/*
@@ -385,21 +398,18 @@ #ifdef ELF_FDPIC_PLAT_INIT
 	 * example.  This macro performs whatever initialization to
 	 * the regs structure is required.
 	 */
-	ELF_FDPIC_PLAT_INIT(regs,
-			    exec_params.map_addr,
-			    interp_params.map_addr,
-			    interp_params.dynamic_addr ?: exec_params.dynamic_addr
-			    );
+	dynaddr = interp_params.dynamic_addr ?: exec_params.dynamic_addr;
+	ELF_FDPIC_PLAT_INIT(regs, exec_params.map_addr, interp_params.map_addr,
+			    dynaddr);
 #endif
 
 	/* everything is now ready... get the userspace context ready to roll */
-	start_thread(regs,
-		     interp_params.entry_addr ?: exec_params.entry_addr,
-		     current->mm->start_stack);
+	entryaddr = interp_params.entry_addr ?: exec_params.entry_addr;
+	start_thread(regs, entryaddr, current->mm->start_stack);
 
 	if (unlikely(current->ptrace & PT_PTRACED)) {
 		if (current->ptrace & PT_TRACE_EXEC)
-			ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
+			ptrace_notify((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
 		else
 			send_sig(SIGTRAP, current, 0);
 	}
@@ -419,11 +429,11 @@ error:
 	return retval;
 
 	/* unrecoverable error - kill the process */
- error_kill:
+error_kill:
 	send_sig(SIGSEGV, current, 0);
 	goto error;
 
-} /* end load_elf_fdpic_binary() */
+}
 
 /*****************************************************************************/
 /*
@@ -471,11 +481,11 @@ #endif
 
 #if defined(__i386__) && defined(CONFIG_SMP)
 	/* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
-	 * by the processes running on the same package. One thing we can do
-	 * is to shuffle the initial stack for them.
+	 * by the processes running on the same package. One thing we can do is
+	 * to shuffle the initial stack for them.
 	 *
-	 * the conditionals here are unneeded, but kept in to make the
-	 * code behaviour the same as pre change unless we have hyperthreaded
+	 * the conditionals here are unneeded, but kept in to make the code
+	 * behaviour the same as pre change unless we have hyperthreaded
 	 * processors. This keeps Mr Marcelo Person happier but should be
 	 * removed for 2.5
 	 */
@@ -498,11 +508,13 @@ #endif
 
 	if (interp_params->loadmap) {
 		len = sizeof(struct elf32_fdpic_loadmap);
-		len += sizeof(struct elf32_fdpic_loadseg) * interp_params->loadmap->nsegs;
+		len += sizeof(struct elf32_fdpic_loadseg) *
+			interp_params->loadmap->nsegs;
 		sp = (sp - len) & ~7UL;
 		interp_params->map_addr = sp;
 
-		if (copy_to_user((void __user *) sp, interp_params->loadmap, len) != 0)
+		if (copy_to_user((void __user *) sp, interp_params->loadmap,
+				 len) != 0)
 			return -EFAULT;
 
 		current->mm->context.interp_fdpic_loadmap = (unsigned long) sp;
@@ -526,34 +538,37 @@ #endif
 	sp -= sp & 15UL;
 
 	/* put the ELF interpreter info on the stack */
-#define NEW_AUX_ENT(nr, id, val)						\
-	do {									\
-		struct { unsigned long _id, _val; } __user *ent = (void __user *) csp;	\
-		__put_user((id), &ent[nr]._id);					\
-		__put_user((val), &ent[nr]._val);				\
+#define NEW_AUX_ENT(nr, id, val)					\
+	do {								\
+		struct { unsigned long _id, _val; } __user *ent;	\
+									\
+		ent = (void __user *) csp;				\
+		__put_user((id), &ent[nr]._id);				\
+		__put_user((val), &ent[nr]._val);			\
 	} while (0)
 
 	csp -= 2 * sizeof(unsigned long);
 	NEW_AUX_ENT(0, AT_NULL, 0);
 	if (k_platform) {
 		csp -= 2 * sizeof(unsigned long);
-		NEW_AUX_ENT(0, AT_PLATFORM, (elf_addr_t)(unsigned long) u_platform);
+		NEW_AUX_ENT(0, AT_PLATFORM,
+			    (elf_addr_t) (unsigned long) u_platform);
 	}
 
 	csp -= DLINFO_ITEMS * 2 * sizeof(unsigned long);
-	NEW_AUX_ENT( 0, AT_HWCAP,		hwcap);
-	NEW_AUX_ENT( 1, AT_PAGESZ,		PAGE_SIZE);
-	NEW_AUX_ENT( 2, AT_CLKTCK,		CLOCKS_PER_SEC);
-	NEW_AUX_ENT( 3, AT_PHDR,		exec_params->ph_addr);
-	NEW_AUX_ENT( 4, AT_PHENT,		sizeof(struct elf_phdr));
-	NEW_AUX_ENT( 5, AT_PHNUM,		exec_params->hdr.e_phnum);
-	NEW_AUX_ENT( 6,	AT_BASE,		interp_params->elfhdr_addr);
-	NEW_AUX_ENT( 7, AT_FLAGS,		0);
-	NEW_AUX_ENT( 8, AT_ENTRY,		exec_params->entry_addr);
-	NEW_AUX_ENT( 9, AT_UID,			(elf_addr_t) current->uid);
-	NEW_AUX_ENT(10, AT_EUID,		(elf_addr_t) current->euid);
-	NEW_AUX_ENT(11, AT_GID,			(elf_addr_t) current->gid);
-	NEW_AUX_ENT(12, AT_EGID,		(elf_addr_t) current->egid);
+	NEW_AUX_ENT( 0, AT_HWCAP,	hwcap);
+	NEW_AUX_ENT( 1, AT_PAGESZ,	PAGE_SIZE);
+	NEW_AUX_ENT( 2, AT_CLKTCK,	CLOCKS_PER_SEC);
+	NEW_AUX_ENT( 3, AT_PHDR,	exec_params->ph_addr);
+	NEW_AUX_ENT( 4, AT_PHENT,	sizeof(struct elf_phdr));
+	NEW_AUX_ENT( 5, AT_PHNUM,	exec_params->hdr.e_phnum);
+	NEW_AUX_ENT( 6,	AT_BASE,	interp_params->elfhdr_addr);
+	NEW_AUX_ENT( 7, AT_FLAGS,	0);
+	NEW_AUX_ENT( 8, AT_ENTRY,	exec_params->entry_addr);
+	NEW_AUX_ENT( 9, AT_UID,		(elf_addr_t) current->uid);
+	NEW_AUX_ENT(10, AT_EUID,	(elf_addr_t) current->euid);
+	NEW_AUX_ENT(11, AT_GID,		(elf_addr_t) current->gid);
+	NEW_AUX_ENT(12, AT_EGID,	(elf_addr_t) current->egid);
 
 #ifdef ARCH_DLINFO
 	/* ARCH_DLINFO must come last so platform specific code can enforce
@@ -579,7 +594,8 @@ #undef NEW_AUX_ENT
 #ifdef CONFIG_MMU
 	current->mm->arg_start = bprm->p;
 #else
-	current->mm->arg_start = current->mm->start_stack - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p);
+	current->mm->arg_start = current->mm->start_stack -
+		(MAX_ARG_PAGES * PAGE_SIZE - bprm->p);
 #endif
 
 	p = (char __user *) current->mm->arg_start;
@@ -607,7 +623,7 @@ #endif
 
 	mm->start_stack = (unsigned long) sp;
 	return 0;
-} /* end create_elf_fdpic_tables() */
+}
 
 /*****************************************************************************/
 /*
@@ -615,7 +631,8 @@ #endif
  * the stack
  */
 #ifndef CONFIG_MMU
-static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm, unsigned long *_sp)
+static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm,
+					    unsigned long *_sp)
 {
 	unsigned long index, stop, sp;
 	char *src;
@@ -636,9 +653,9 @@ static int elf_fdpic_transfer_args_to_st
 
 	*_sp = (*_sp - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p)) & ~15;
 
- out:
+out:
 	return ret;
-} /* end elf_fdpic_transfer_args_to_stack() */
+}
 #endif
 
 /*****************************************************************************/
@@ -713,17 +730,18 @@ #endif
 		seg = loadmap->segs;
 		for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
 			if (params->hdr.e_entry >= seg->p_vaddr &&
-			    params->hdr.e_entry < seg->p_vaddr + seg->p_memsz
-			    ) {
+			    params->hdr.e_entry < seg->p_vaddr + seg->p_memsz) {
 				params->entry_addr =
-					(params->hdr.e_entry - seg->p_vaddr) + seg->addr;
+					(params->hdr.e_entry - seg->p_vaddr) +
+					seg->addr;
 				break;
 			}
 		}
 	}
 
 	/* determine where the program header table has wound up if mapped */
-	stop = params->hdr.e_phoff + params->hdr.e_phnum * sizeof (struct elf_phdr);
+	stop = params->hdr.e_phoff;
+	stop += params->hdr.e_phnum * sizeof (struct elf_phdr);
 	phdr = params->phdrs;
 
 	for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
@@ -737,9 +755,11 @@ #endif
 		seg = loadmap->segs;
 		for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
 			if (phdr->p_vaddr >= seg->p_vaddr &&
-			    phdr->p_vaddr + phdr->p_filesz <= seg->p_vaddr + seg->p_memsz
-			    ) {
-				params->ph_addr = (phdr->p_vaddr - seg->p_vaddr) + seg->addr +
+			    phdr->p_vaddr + phdr->p_filesz <=
+			    seg->p_vaddr + seg->p_memsz) {
+				params->ph_addr =
+					(phdr->p_vaddr - seg->p_vaddr) +
+					seg->addr +
 					params->hdr.e_phoff - phdr->p_offset;
 				break;
 			}
@@ -756,18 +776,22 @@ #endif
 		seg = loadmap->segs;
 		for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
 			if (phdr->p_vaddr >= seg->p_vaddr &&
-			    phdr->p_vaddr + phdr->p_memsz <= seg->p_vaddr + seg->p_memsz
-			    ) {
-				params->dynamic_addr = (phdr->p_vaddr - seg->p_vaddr) + seg->addr;
-
-				/* check the dynamic section contains at least one item, and that
-				 * the last item is a NULL entry */
+			    phdr->p_vaddr + phdr->p_memsz <=
+			    seg->p_vaddr + seg->p_memsz) {
+				params->dynamic_addr =
+					(phdr->p_vaddr - seg->p_vaddr) +
+					seg->addr;
+
+				/* check the dynamic section contains at least
+				 * one item, and that the last item is a NULL
+				 * entry */
 				if (phdr->p_memsz == 0 ||
 				    phdr->p_memsz % sizeof(Elf32_Dyn) != 0)
 					goto dynamic_error;
 
 				tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
-				if (((Elf32_Dyn *) params->dynamic_addr)[tmp - 1].d_tag != 0)
+				if (((Elf32_Dyn *)
+				     params->dynamic_addr)[tmp - 1].d_tag != 0)
 					goto dynamic_error;
 				break;
 			}
@@ -776,8 +800,8 @@ #endif
 	}
 
 	/* now elide adjacent segments in the load map on MMU linux
-	 * - on uClinux the holes between may actually be filled with system stuff or stuff from
-	 *   other processes
+	 * - on uClinux the holes between may actually be filled with system
+	 *   stuff or stuff from other processes
 	 */
 #ifdef CONFIG_MMU
 	nloads = loadmap->nsegs;
@@ -788,7 +812,9 @@ #ifdef CONFIG_MMU
 		if (seg->p_vaddr - mseg->p_vaddr == seg->addr - mseg->addr) {
 			load_addr = PAGE_ALIGN(mseg->addr + mseg->p_memsz);
 			if (load_addr == (seg->addr & PAGE_MASK)) {
-				mseg->p_memsz += load_addr - (mseg->addr + mseg->p_memsz);
+				mseg->p_memsz +=
+					load_addr -
+					(mseg->addr + mseg->p_memsz);
 				mseg->p_memsz += seg->addr & ~PAGE_MASK;
 				mseg->p_memsz += seg->p_memsz;
 				loadmap->nsegs--;
@@ -816,20 +842,21 @@ #endif
 
 	return 0;
 
- dynamic_error:
+dynamic_error:
 	printk("ELF FDPIC %s with invalid DYNAMIC section (inode=%lu)\n",
 	       what, file->f_dentry->d_inode->i_ino);
 	return -ELIBBAD;
-} /* end elf_fdpic_map_file() */
+}
 
 /*****************************************************************************/
 /*
  * map a file with constant displacement under uClinux
  */
 #ifndef CONFIG_MMU
-static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *params,
-						   struct file *file,
-						   struct mm_struct *mm)
+static int elf_fdpic_map_file_constdisp_on_uclinux(
+	struct elf_fdpic_params *params,
+	struct file *file,
+	struct mm_struct *mm)
 {
 	struct elf32_fdpic_loadseg *seg;
 	struct elf32_phdr *phdr;
@@ -840,7 +867,8 @@ static int elf_fdpic_map_file_constdisp_
 	load_addr = params->load_addr;
 	seg = params->loadmap->segs;
 
-	/* determine the bounds of the contiguous overall allocation we must make */
+	/* determine the bounds of the contiguous overall allocation we must
+	 * make */
 	phdr = params->phdrs;
 	for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
 		if (params->phdrs[loop].p_type != PT_LOAD)
@@ -861,7 +889,7 @@ static int elf_fdpic_map_file_constdisp_
 	maddr = do_mmap(NULL, load_addr, top - base,
 			PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0);
 	up_write(&mm->mmap_sem);
-	if (IS_ERR((void *) maddr))
+	if (IS_ERR_VALUE(maddr))
 		return (int) maddr;
 
 	if (load_addr != 0)
@@ -879,7 +907,8 @@ static int elf_fdpic_map_file_constdisp_
 		seg->p_vaddr = phdr->p_vaddr;
 		seg->p_memsz = phdr->p_memsz;
 
-		ret = file->f_op->read(file, (void *) seg->addr, phdr->p_filesz, &fpos);
+		ret = file->f_op->read(file, (void *) seg->addr,
+				       phdr->p_filesz, &fpos);
 		if (ret < 0)
 			return ret;
 
@@ -896,8 +925,7 @@ static int elf_fdpic_map_file_constdisp_
 			if (phdr->p_flags & PF_X) {
 				mm->start_code = seg->addr;
 				mm->end_code = seg->addr + phdr->p_memsz;
-			}
-			else if (!mm->start_data) {
+			} else if (!mm->start_data) {
 				mm->start_data = seg->addr;
 #ifndef CONFIG_MMU
 				mm->end_data = seg->addr + phdr->p_memsz;
@@ -914,7 +942,7 @@ #endif
 	}
 
 	return 0;
-} /* end elf_fdpic_map_file_constdisp_on_uclinux() */
+}
 #endif
 
 /*****************************************************************************/
@@ -975,14 +1003,14 @@ static int elf_fdpic_map_file_by_direct_
 
 		case ELF_FDPIC_FLAG_CONSTDISP:
 			/* constant displacement
-			 * - can be mapped anywhere, but must be mapped as a unit
+			 * - can be mapped anywhere, but must be mapped as a
+			 *   unit
 			 */
 			if (!dvset) {
 				maddr = load_addr;
 				delta_vaddr = phdr->p_vaddr;
 				dvset = 1;
-			}
-			else {
+			} else {
 				maddr = load_addr + phdr->p_vaddr - delta_vaddr;
 				flags |= MAP_FIXED;
 			}
@@ -1006,13 +1034,14 @@ static int elf_fdpic_map_file_by_direct_
 		up_write(&mm->mmap_sem);
 
 		kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx",
-		       loop, phdr->p_memsz + disp, prot, flags, phdr->p_offset - disp,
-		       maddr);
+		       loop, phdr->p_memsz + disp, prot, flags,
+		       phdr->p_offset - disp, maddr);
 
-		if (IS_ERR((void *) maddr))
+		if (IS_ERR_VALUE(maddr))
 			return (int) maddr;
 
-		if ((params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) == ELF_FDPIC_FLAG_CONTIGUOUS)
+		if ((params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) ==
+		    ELF_FDPIC_FLAG_CONTIGUOUS)
 			load_addr += PAGE_ALIGN(phdr->p_memsz + disp);
 
 		seg->addr = maddr + disp;
@@ -1023,7 +1052,8 @@ static int elf_fdpic_map_file_by_direct_
 		if (phdr->p_offset == 0)
 			params->elfhdr_addr = seg->addr;
 
-		/* clear the bit between beginning of mapping and beginning of PT_LOAD */
+		/* clear the bit between beginning of mapping and beginning of
+		 * PT_LOAD */
 		if (prot & PROT_WRITE && disp > 0) {
 			kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp);
 			clear_user((void __user *) maddr, disp);
@@ -1039,19 +1069,20 @@ static int elf_fdpic_map_file_by_direct_
 		excess1 = PAGE_SIZE - ((maddr + phdr->p_filesz) & ~PAGE_MASK);
 
 #ifdef CONFIG_MMU
-
 		if (excess > excess1) {
 			unsigned long xaddr = maddr + phdr->p_filesz + excess1;
 			unsigned long xmaddr;
 
 			flags |= MAP_FIXED | MAP_ANONYMOUS;
 			down_write(&mm->mmap_sem);
-			xmaddr = do_mmap(NULL, xaddr, excess - excess1, prot, flags, 0);
+			xmaddr = do_mmap(NULL, xaddr, excess - excess1,
+					 prot, flags, 0);
 			up_write(&mm->mmap_sem);
 
 			kdebug("mmap[%d] <anon>"
 			       " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx",
-			       loop, xaddr, excess - excess1, prot, flags, xmaddr);
+			       loop, xaddr, excess - excess1, prot, flags,
+			       xmaddr);
 
 			if (xmaddr != xaddr)
 				return -ENOMEM;
@@ -1060,7 +1091,8 @@ #ifdef CONFIG_MMU
 		if (prot & PROT_WRITE && excess1 > 0) {
 			kdebug("clear[%d] ad=%lx sz=%lx",
 			       loop, maddr + phdr->p_filesz, excess1);
-			clear_user((void __user *) maddr + phdr->p_filesz, excess1);
+			clear_user((void __user *) maddr + phdr->p_filesz,
+				   excess1);
 		}
 
 #else
@@ -1075,8 +1107,7 @@ #endif
 			if (phdr->p_flags & PF_X) {
 				mm->start_code = maddr;
 				mm->end_code = maddr + phdr->p_memsz;
-			}
-			else if (!mm->start_data) {
+			} else if (!mm->start_data) {
 				mm->start_data = maddr;
 				mm->end_data = maddr + phdr->p_memsz;
 			}
@@ -1086,4 +1117,4 @@ #endif
 	}
 
 	return 0;
-} /* end elf_fdpic_map_file_by_direct_mmap() */
+}
#13 lore raw

PATCH 5/6 FDPIC: Add coredump capability for the ELF-FDPIC binfmt [try #3]

In reply to David Howells

From: David Howells <[email protected]>

Add coredump capability for the ELF-FDPIC binfmt.

---

 arch/frv/kernel/process.c |    8 +
 fs/binfmt_elf_fdpic.c     |  678 +++++++++++++++++++++++++++++++++++++++++++++
 include/asm-frv/elf.h     |    6 
 include/linux/elfcore.h   |   10 +
 4 files changed, 696 insertions(+), 6 deletions(-)
arch/frv/kernel/process.c +8 -0
index ecdeafb..f0c767a 100644
@@ -371,3 +371,11 @@ int elf_check_arch(const struct elf32_hd
 
 	return 1;
 }
+
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
+{
+	memcpy(fpregs,
+	       &current->thread.user->f,
+	       sizeof(current->thread.user->f));
+	return 1;
+}
fs/binfmt_elf_fdpic.c +676 -2

709 lines not on this page · raw message

include/asm-frv/elf.h +2 -4
index 38656da..7df58a3 100644
@@ -64,7 +64,7 @@ typedef unsigned long elf_greg_t;
 #define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
-typedef struct fpmedia_struct elf_fpregset_t;
+typedef struct user_fpmedia_regs elf_fpregset_t;
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
@@ -116,6 +116,7 @@ do {											\
 } while(0)
 
 #define USE_ELF_CORE_DUMP
+#define ELF_FDPIC_CORE_EFLAGS	EF_FRV_FDPIC
 #define ELF_EXEC_PAGESIZE	16384
 
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
@@ -125,9 +126,6 @@ #define ELF_EXEC_PAGESIZE	16384
 
 #define ELF_ET_DYN_BASE         0x08000000UL
 
-#define ELF_CORE_COPY_REGS(pr_reg, regs)				\
-	memcpy(&pr_reg[0], &regs->sp, 31 * sizeof(uint32_t));
-
 /* This yields a mask that user programs can use to figure out what
    instruction set this cpu supports.  */
 
include/linux/elfcore.h +10 -0
index 0cf0bea..9631ddd 100644
@@ -60,6 +60,16 @@ #if 0
 	long	pr_instr;		/* Current instruction */
 #endif
 	elf_gregset_t pr_reg;	/* GP registers */
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+	/* When using FDPIC, the loadmap addresses need to be communicated
+	 * to GDB in order for GDB to do the necessary relocations.  The
+	 * fields (below) used to communicate this information are placed
+	 * immediately after ``pr_reg'', so that the loadmap addresses may
+	 * be viewed as part of the register set if so desired.
+	 */
+	unsigned long pr_exec_fdpic_loadmap;
+	unsigned long pr_interp_fdpic_loadmap;
+#endif
 	int pr_fpvalid;		/* True if math co-processor being used.  */
 };
 
#14 lore raw

Re: [PATCH 5/6] FDPIC: Add coredump capability for the ELF-FDPIC binfmt [try #3]

Quoted 6 lines · On Thu, 06 Jul 2006 13:47:27 +0100 David Howells <[email protected]> wrote:

From: David Howells <[email protected]>

Add coredump capability for the ELF-FDPIC binfmt.

..

Review

Quoted 10 lines
(quoted diff) +10 -0
+static int dump_seek(struct file *file, off_t off)
+{
+	if (file->f_op->llseek) {
+		if (file->f_op->llseek(file, off, 0) != off)
+			return 0;
+	} else {
+		file->f_pos = off;
+	}
+	return 1;
+}

llseek takes a loff_t and file->f_pos is loff_t. I guess it's a bit moot on such a CPU. Was it deliberate?

(how come the kernel doesn't have a SEEK_SET #define?)

Quoted 35 lines
(quoted diff) +35 -0
+/*
+ * Decide whether a segment is worth dumping; default is yes to be
+ * sure (missing info is worse than too much; etc).
+ * Personally I'd include everything, and use the coredump limit...
+ *
+ * I think we should skip something. But I am not sure how. H.J.
+ */
+static inline int maydump(struct vm_area_struct *vma)
+{
+	/* Do not dump I/O mapped devices or special mappings */
+	if (vma->vm_flags & (VM_IO | VM_RESERVED)) {
+		kdcore("%08lx: %08lx: no (IO)", vma->vm_start, vma->vm_flags);
+		return 0;
+	}
+
+	/* If we may not read the contents, don't allow us to dump
+	 * them either. "dump_write()" can't handle it anyway.
+	 */
+	if (!(vma->vm_flags & VM_READ)) {
+		kdcore("%08lx: %08lx: no (!read)", vma->vm_start, vma->vm_flags);
+		return 0;
+	}
+
+	/* Dump shared memory only if mapped from an anonymous file. */
+	if (vma->vm_flags & VM_SHARED) {
+		if (vma->vm_file->f_dentry->d_inode->i_nlink == 0) {
+			kdcore("%08lx: %08lx: no (share)", vma->vm_start, vma->vm_flags);
+			return 1;
+		}
+
+		kdcore("%08lx: %08lx: no (share)", vma->vm_start, vma->vm_flags);
+		return 0;
+	}
+
+#ifdef CONFIG_MMU

Review

Quoted 10 lines
(quoted diff) +10 -0
+	/* If it hasn't been written to, don't write it out */
+	if (!vma->anon_vma) {
+		kdcore("%08lx: %08lx: no (!anon)", vma->vm_start, vma->vm_flags);
+		return 0;
+	}
+#endif
+
+	kdcore("%08lx: %08lx: yes", vma->vm_start, vma->vm_flags);
+	return 1;
+}

Three callsites - seems too large to inline.

Quoted 1 line

+#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))

The GFS2 tree has

include/linux/kernel.h +1 -0
@@ -32,6 +32,7 @@ #define STACK_MAGIC	0xdeadbeef
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 #define ALIGN(x,a) (((x)+(a)-1)&~((a)-1))
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
 
 #define	KERN_EMERG	"<0>"	/* system is unusable			*/

Which seems reasonable to me. I'll steal it from them.

Quoted 8 lines
(quoted diff) +6 -0
+/* #define DEBUG */
+
+#define DUMP_WRITE(addr, nr)	\
+	do { if (!dump_write(file, (addr), (nr))) return 0; } while(0)
+#define DUMP_SEEK(off)	\
+	do { if (!dump_seek(file, (off))) return 0; } while(0)
 
...

Review

Quoted 10 lines
(quoted diff) +9 -0
 
+#undef DUMP_WRITE
+#undef DUMP_SEEK
+
+#define DUMP_WRITE(addr, nr)	\
+	if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
+		goto end_coredump;
+#define DUMP_SEEK(off)	\
+	if (!dump_seek(file, (off))) \
+		goto end_coredump;

Embedding returns and gotos in macros is evil. For new code it's worth doing it vaguely tastefully.

	ret = dump_write(...);
	if (ret < 0)
		goto actually_return_an_error_code;

Review

Quoted 2 lines
(quoted diff) +2 -0
+	for (vml = current->mm->context.vmlist; vml; vml = vml->next)
+	    segs++;

Does this need locking?

#15 lore raw

Re: [PATCH 5/6] FDPIC: Add coredump capability for the ELF-FDPIC binfmt [try #3]

Quoted 2 lines · Andrew Morton

llseek takes a loff_t and file->f_pos is loff_t. I guess it's a bit moot on such a CPU. Was it deliberate?

It compiles with no error and no warning, so I haven't noticed. This is as binfmt_elf.c is, I believe, so that is probably wrong too.

Quoted 1 line

(how come the kernel doesn't have a SEEK_SET #define?)

I don't know. It probably should.

Quoted 1 line

Three callsites - seems too large to inline.

Again taken from binfmt_elf.c, although I added the debugging stuff. It shouldn't matter as the compiler will make its own decision (or does "inline" get #defined to always-inline nowadays?).

Quoted 1 line

Which seems reasonable to me. I'll steal it from them.

Okay.

Quoted 2 lines

Embedding returns and gotos in macros is evil. For new code it's worth doing it vaguely tastefully.

Again, stolen verbatim from binfmt_elf.c. I'd prefer to keep it comparable by the blink-comparator method if possible.

Quoted 1 line

Does this need locking?

It shouldn't do; we own our own vma chain, and because we're part of exec, we have a fresh mm_struct to play with. The VMAs themselves aren't allowed to change, not even on NOMMU.

David

#16 lore raw

Re: [PATCH 5/6] FDPIC: Add coredump capability for the ELF-FDPIC binfmt [try #3]

Quoted 8 lines · David Howells
Quoted 2 lines · Andrew Morton

llseek takes a loff_t and file->f_pos is loff_t. I guess it's a bit moot on such a CPU. Was it deliberate?

It compiles with no error and no warning, so I haven't noticed. This is as binfmt_elf.c is, I believe, so that is probably wrong too.

binfmt_elf uses loff_t.

Quoted 9 lines
Quoted 1 line

(how come the kernel doesn't have a SEEK_SET #define?)

I don't know. It probably should.

Quoted 1 line

Three callsites - seems too large to inline.

Again taken from binfmt_elf.c, although I added the debugging stuff. It shouldn't matter as the compiler will make its own decision (or does "inline" get #defined to always-inline nowadays?).

Yes, we still play games with inline (include/linux/compiler*.h)

If it has a single callsite, leave it uninlined and gcc will usually inline it. If it has multiple callsites then leave it uninlined and gcc will (hopefully) not inline it. So omitting the inline is usually the right thing to do.

Quoted 9 lines
Quoted 1 line

Which seems reasonable to me. I'll steal it from them.

Okay.

Quoted 2 lines

Embedding returns and gotos in macros is evil. For new code it's worth doing it vaguely tastefully.

Again, stolen verbatim from binfmt_elf.c. I'd prefer to keep it comparable by the blink-comparator method if possible.

Well.. copy-n-paste from a bad source gives a bad dest.

fs/binfmt_elf.c renamed from fs/binfmt_elf.c~binfmt_elf-macro-cleanup +34 -26
diff -puN fs/binfmt_elf.c~binfmt_elf-macro-cleanup fs/binfmt_elf.c
@@ -1207,11 +1207,6 @@ static int notesize(struct memelfnote *e
 	return sz;
 }
 
-#define DUMP_WRITE(addr, nr)	\
-	do { if (!dump_write(file, (addr), (nr))) return 0; } while(0)
-#define DUMP_SEEK(off)	\
-	do { if (!dump_seek(file, (off))) return 0; } while(0)
-
 static int writenote(struct memelfnote *men, struct file *file)
 {
 	struct elf_note en;
@@ -1220,24 +1215,21 @@ static int writenote(struct memelfnote *
 	en.n_descsz = men->datasz;
 	en.n_type = men->type;
 
-	DUMP_WRITE(&en, sizeof(en));
-	DUMP_WRITE(men->name, en.n_namesz);
+	if (!dump_write(&en, sizeof(en)))
+		goto err;
+	if (!dump_write(men->name, en.n_namesz))
+		goto err;
 	/* XXX - cast from long long to long to avoid need for libgcc.a */
-	DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));	/* XXX */
-	DUMP_WRITE(men->data, men->datasz);
-	DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));	/* XXX */
-
+	if (!dump_seek(roundup((unsigned long)file->f_pos, 4)))
+		goto err;
+	if (!dump_write(men->data, men->datasz))
+		goto err;
+	if (!dump_seek(roundup((unsigned long)file->f_pos, 4)))
+		goto err;
 	return 1;
+err:
+	return 0;
 }
-#undef DUMP_WRITE
-#undef DUMP_SEEK
-
-#define DUMP_WRITE(addr, nr)	\
-	if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
-		goto end_coredump;
-#define DUMP_SEEK(off)	\
-	if (!dump_seek(file, (off))) \
-		goto end_coredump;
 
 static void fill_elf_header(struct elfhdr *elf, int segs)
 {
@@ -1555,7 +1547,11 @@ static int elf_core_dump(long signr, str
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 
-	DUMP_WRITE(elf, sizeof(*elf));
+	size += sizeof(*elf);
+	if (size > limit)
+		goto end_coredump;
+	if (!dump_write(file, elf, sizeof(*elf))
+		goto end_coredump;
 	offset += sizeof(*elf);				/* Elf header */
 	offset += (segs+1) * sizeof(struct elf_phdr);	/* Program headers */
 
@@ -1571,7 +1567,11 @@ static int elf_core_dump(long signr, str
 
 		fill_elf_note_phdr(&phdr, sz, offset);
 		offset += sz;
-		DUMP_WRITE(&phdr, sizeof(phdr));
+		size += sizeof(phdr);
+		if (size > limit)
+			goto end_coredump;
+		if (!dump_write(file, &phdr, sizeof(phdr))
+			goto end_coredump;
 	}
 
 	/* Page-align dumped data */
@@ -1598,7 +1598,11 @@ static int elf_core_dump(long signr, str
 			phdr.p_flags |= PF_X;
 		phdr.p_align = ELF_EXEC_PAGESIZE;
 
-		DUMP_WRITE(&phdr, sizeof(phdr));
+		size += sizeof(phdr);
+		if (size > limit)
+			goto end_coredump;
+		if (!dump_write(file, &phdr, sizeof(phdr))
+			goto end_coredump;
 	}
 
 #ifdef ELF_CORE_WRITE_EXTRA_PHDRS
@@ -1620,7 +1624,8 @@ static int elf_core_dump(long signr, str
 				goto end_coredump;
 	}
  
-	DUMP_SEEK(dataoff);
+	if (!dump_seek(file, dataoff))
+		goto end_coredump;
 
 	for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
 		unsigned long addr;
@@ -1636,10 +1641,13 @@ static int elf_core_dump(long signr, str
 
 			if (get_user_pages(current, current->mm, addr, 1, 0, 1,
 						&page, &vma) <= 0) {
-				DUMP_SEEK(file->f_pos + PAGE_SIZE);
+				if (!dump_seek(file, file->f_pos + PAGE_SIZE))
+					goto end_coredump
 			} else {
 				if (page == ZERO_PAGE(addr)) {
-					DUMP_SEEK(file->f_pos + PAGE_SIZE);
+					if (!dump_seek(file,
+						       file->f_pos + PAGE_SIZE))
+						goto end_coredump;
 				} else {
 					void *kaddr;
 					flush_cache_page(vma, addr,

_

#17 lore raw

Re: [PATCH 5/6] FDPIC: Add coredump capability for the ELF-FDPIC binfmt [try #3]

Quoted 1 line · Andrew Morton

binfmt_elf uses loff_t.

Hmmm... It's not consistent about it though:

static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)

David

#18 lore raw

Re: [PATCH 5/6] FDPIC: Add coredump capability for the ELF-FDPIC binfmt [try #3]

In reply to Andrew Morton

fs/binfmt_elf.c static int writenote(struct memelfnote * · line 1226

Quoted 8 lines · Andrew Morton

diff -puN fs/binfmt_elf.c~binfmt_elf-macro-cleanup fs/binfmt_elf.c

fs/binfmt_elf.c renamed from fs/binfmt_elf.c~binfmt_elf-macro-cleanup +4 -0
...
+	if (!dump_seek(roundup((unsigned long)file->f_pos, 4)))
+		goto err;
+	if (!dump_write(men->data, men->datasz))
+		goto err;

That doesn't compile... you're lacking file arguments.

David

#19 lore raw

Re: [PATCH 5/6] FDPIC: Add coredump capability for the ELF-FDPIC binfmt [try #3]

Quoted 1 line · David Howells

That doesn't compile... you're lacking file arguments.

Even more fun:

warthog>grep -r DUMP_WRITE include/

include/asm/elf.h:              DUMP_WRITE(&phdr, sizeof(phdr));                     \
include/asm/elf.h:                      DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr,        \
include/asm-um/elf-i386.h:              DUMP_WRITE(&phdr, sizeof(phdr));             \
include/asm-um/elf-i386.h:                      DUMP_WRITE((void *) phdrp[i].p_vaddr,                 \
include/asm-ia64/elf.h:         DUMP_WRITE(&phdr, sizeof(phdr));               \
include/asm-ia64/elf.h:                 DUMP_WRITE((void *) gate_phdrs[i].p_vaddr,            \
include/asm-i386/elf.h:         DUMP_WRITE(&phdr, sizeof(phdr));                     \
include/asm-i386/elf.h:                 DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr,        \

For another day, I think...

David

#20 lore raw

Re: [PATCH 5/6] FDPIC: Add coredump capability for the ELF-FDPIC binfmt [try #3]

Quoted 7 lines · On Fri, 07 Jul 2006 12:00:13 +0100 David Howells <[email protected]> wrote:
Quoted 1 line · David Howells

That doesn't compile... you're lacking file arguments.

Even more fun:

warthog>grep -r DUMP_WRITE include/

Quoted 9 lines
include/asm/elf.h:              DUMP_WRITE(&phdr, sizeof(phdr));                     \
include/asm/elf.h:                      DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr,        \
include/asm-um/elf-i386.h:              DUMP_WRITE(&phdr, sizeof(phdr));             \
include/asm-um/elf-i386.h:                      DUMP_WRITE((void *) phdrp[i].p_vaddr,                 \
include/asm-ia64/elf.h:         DUMP_WRITE(&phdr, sizeof(phdr));               \
include/asm-ia64/elf.h:                 DUMP_WRITE((void *) gate_phdrs[i].p_vaddr,            \
include/asm-i386/elf.h:         DUMP_WRITE(&phdr, sizeof(phdr));                     \
include/asm-i386/elf.h:                 DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr,        \

all the world's an x86_64 ;)

Who inflicted this crap on us? It looks like gcc code.

Quoted 1 line

For another day, I think...

Yeah.

#21 lore raw

Re: [PATCH 5/6] FDPIC: Add coredump capability for the ELF-FDPIC binfmt [try #3]

In reply to Andrew Morton
Quoted 6 lines · Andrew Morton
Quoted 1 line

+#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))

The GFS2 tree has

...
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))

They aren't exactly equivalent.

In any case, we probably shouldn't be using divide, but should rather be using shifts since the divisors are powers of two. I wonder if the compiler will make the substitution...

David

#22 lore raw

Re: [PATCH 5/6] FDPIC: Add coredump capability for the ELF-FDPIC binfmt [try #3]

Quoted 10 lines · On Fri, 07 Jul 2006 10:54:36 +0100 David Howells <[email protected]> wrote:
Quoted 6 lines · Andrew Morton
Quoted 1 line

+#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))

The GFS2 tree has

...
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))

They aren't exactly equivalent.

OK.

I count 45 different implementations of this in the tree. Ho hum.

Quoted 4 lines

In any case, we probably shouldn't be using divide, but should rather be using shifts since the divisors are powers of two. I wonder if the compiler will make the substitution...

It usually manages to. iirc, less successfully if signed quantities are used.

#23 lore raw

Re: [PATCH 5/6] FDPIC: Add coredump capability for the ELF-FDPIC binfmt [try #3]

Quoted 1 line · Andrew Morton

I count 45 different implementations of this in the tree. Ho hum.

The roundup() macro could just be moved in as well.

David

#24 lore raw

PATCH 6/6 FRV: Introduce asm-offsets for FRV arch [try #3]

In reply to David Howells

From: David Howells <[email protected]>

Introduce the use of asm-offsets into the FRV architecture.

---

 arch/frv/kernel/asm-offsets.c |  116 ++++++++++++++++++++++++++++++
 arch/frv/kernel/break.S       |   34 +++++----
 arch/frv/kernel/debug-stub.c  |   13 ++-
 arch/frv/kernel/entry.S       |    1 
 arch/frv/kernel/gdb-stub.c    |  159 +++++++++++++++++++++++------------------
 arch/frv/kernel/head.S        |    1 
 arch/frv/kernel/process.c     |    3 +
 arch/frv/kernel/switch_to.S   |    3 +
 arch/frv/kernel/traps.c       |   25 +++---
 include/asm-frv/gdb-stub.h    |   22 ++++++
 include/asm-frv/ptrace.h      |   12 +--
 include/asm-frv/registers.h   |   97 ++++++++++---------------
 include/asm-frv/thread_info.h |   24 +-----
 13 files changed, 313 insertions(+), 197 deletions(-)
arch/frv/kernel/asm-offsets.c +115 -1
index 9e26311..fbb19fc 100644
@@ -1 +1,115 @@
-/* Dummy asm-offsets.c file. Required by kbuild and ready to be used - hint! */
+/*
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed
+ * to extract and format the required data.
+ */
+
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/personality.h>
+#include <asm/registers.h>
+#include <asm/ucontext.h>
+#include <asm/processor.h>
+#include <asm/thread_info.h>
+#include <asm/gdb-stub.h>
+
+#define DEFINE(sym, val) \
+        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define DEF_PTREG(sym, reg) \
+        asm volatile("\n->" #sym " %0 offsetof(struct pt_regs, " #reg ")" \
+		     : : "i" (offsetof(struct pt_regs, reg)))
+
+#define DEF_IREG(sym, reg) \
+        asm volatile("\n->" #sym " %0 offsetof(struct user_context, " #reg ")" \
+		     : : "i" (offsetof(struct user_context, reg)))
+
+#define DEF_FREG(sym, reg) \
+        asm volatile("\n->" #sym " %0 offsetof(struct user_context, " #reg ")" \
+		     : : "i" (offsetof(struct user_context, reg)))
+
+#define DEF_0REG(sym, reg) \
+        asm volatile("\n->" #sym " %0 offsetof(struct frv_frame0, " #reg ")" \
+		     : : "i" (offsetof(struct frv_frame0, reg)))
+
+#define BLANK() asm volatile("\n->" : : )
+
+#define OFFSET(sym, str, mem) \
+	DEFINE(sym, offsetof(struct str, mem));
+
+void foo(void)
+{
+	/* offsets into the thread_info structure */
+	OFFSET(TI_TASK,			thread_info, task);
+	OFFSET(TI_EXEC_DOMAIN,		thread_info, exec_domain);
+	OFFSET(TI_FLAGS,		thread_info, flags);
+	OFFSET(TI_STATUS,		thread_info, status);
+	OFFSET(TI_CPU,			thread_info, cpu);
+	OFFSET(TI_PREEMPT_COUNT,	thread_info, preempt_count);
+	OFFSET(TI_ADDR_LIMIT,		thread_info, addr_limit);
+	OFFSET(TI_RESTART_BLOCK,	thread_info, restart_block);
+	BLANK();
+
+	/* offsets into register file storage */
+	DEF_PTREG(REG_PSR,		psr);
+	DEF_PTREG(REG_ISR,		isr);
+	DEF_PTREG(REG_CCR,		ccr);
+	DEF_PTREG(REG_CCCR,		cccr);
+	DEF_PTREG(REG_LR,		lr);
+	DEF_PTREG(REG_LCR,		lcr);
+	DEF_PTREG(REG_PC,		pc);
+	DEF_PTREG(REG__STATUS,		__status);
+	DEF_PTREG(REG_SYSCALLNO,	syscallno);
+	DEF_PTREG(REG_ORIG_GR8,		orig_gr8);
+	DEF_PTREG(REG_GNER0,		gner0);
+	DEF_PTREG(REG_GNER1,		gner1);
+	DEF_PTREG(REG_IACC0,		iacc0);
+	DEF_PTREG(REG_TBR,		tbr);
+	DEF_PTREG(REG_GR0,		tbr);
+	DEFINE(REG__END,		sizeof(struct pt_regs));
+	BLANK();
+
+	DEF_0REG(REG_DCR,		debug.dcr);
+	DEF_0REG(REG_IBAR0,		debug.ibar[0]);
+	DEF_0REG(REG_DBAR0,		debug.dbar[0]);
+	DEF_0REG(REG_DBDR00,		debug.dbdr[0][0]);
+	DEF_0REG(REG_DBMR00,		debug.dbmr[0][0]);
+	BLANK();
+
+	DEF_IREG(__INT_GR0,		i.gr[0]);
+	DEF_FREG(__USER_FPMEDIA,	f);
+	DEF_FREG(__FPMEDIA_FR0,		f.fr[0]);
+	DEF_FREG(__FPMEDIA_FNER0,	f.fner[0]);
+	DEF_FREG(__FPMEDIA_MSR0,	f.msr[0]);
+	DEF_FREG(__FPMEDIA_ACC0,	f.acc[0]);
+	DEF_FREG(__FPMEDIA_ACCG0,	f.accg[0]);
+	DEF_FREG(__FPMEDIA_FSR0,	f.fsr[0]);
+	BLANK();
+
+	DEFINE(NR_PT_REGS,		sizeof(struct pt_regs) / 4);
+	DEFINE(NR_USER_INT_REGS,	sizeof(struct user_int_regs) / 4);
+	DEFINE(NR_USER_FPMEDIA_REGS,	sizeof(struct user_fpmedia_regs) / 4);
+	DEFINE(NR_USER_CONTEXT,		sizeof(struct user_context) / 4);
+	DEFINE(FRV_FRAME0_SIZE,		sizeof(struct frv_frame0));
+	BLANK();
+
+	/* offsets into thread_struct */
+	OFFSET(__THREAD_FRAME,		thread_struct, frame);
+	OFFSET(__THREAD_CURR,		thread_struct, curr);
+	OFFSET(__THREAD_SP,		thread_struct, sp);
+	OFFSET(__THREAD_FP,		thread_struct, fp);
+	OFFSET(__THREAD_LR,		thread_struct, lr);
+	OFFSET(__THREAD_PC,		thread_struct, pc);
+	OFFSET(__THREAD_GR16,		thread_struct, gr[0]);
+	OFFSET(__THREAD_SCHED_LR,	thread_struct, sched_lr);
+	OFFSET(__THREAD_FRAME0,		thread_struct, frame0);
+	OFFSET(__THREAD_USER,		thread_struct, user);
+	BLANK();
+
+	/* offsets into frv_debug_status */
+	OFFSET(DEBUG_BPSR,		frv_debug_status, bpsr);
+	OFFSET(DEBUG_DCR,		frv_debug_status, dcr);
+	OFFSET(DEBUG_BRR,		frv_debug_status, brr);
+	OFFSET(DEBUG_NMAR,		frv_debug_status, nmar);
+	BLANK();
+}
arch/frv/kernel/break.S +19 -15
index ea161f0..dac4a5f 100644
@@ -9,11 +9,11 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/sys.h>
 #include <linux/linkage.h>
 #include <asm/setup.h>
 #include <asm/segment.h>
 #include <asm/ptrace.h>
+#include <asm/thread_info.h>
 #include <asm/spr-regs.h>
 
 #include <asm/errno.h>
@@ -23,13 +23,11 @@ # the break handler has its own stack
 #
 	.section	.bss.stack
 	.globl		__break_user_context
-	.balign		8192
+	.balign		THREAD_SIZE
 __break_stack:
-	.space		(8192 - (USER_CONTEXT_SIZE + REG__DEBUG_XTRA)) & ~7
-__break_stack_tos:
-	.space		REG__DEBUG_XTRA
-__break_user_context:
-	.space		USER_CONTEXT_SIZE
+	.space		THREAD_SIZE - FRV_FRAME0_SIZE
+__break_frame_0:
+	.space		FRV_FRAME0_SIZE
 
 #
 # miscellaneous variables
@@ -74,8 +72,8 @@ #ifdef CONFIG_MMU
 #endif
 	LEDS		0x1001,gr31
 
-	sethi.p		%hi(__break_user_context),gr31
-	setlo		%lo(__break_user_context),gr31
+	sethi.p		%hi(__break_frame_0),gr31
+	setlo		%lo(__break_frame_0),gr31
 
 	stdi		gr2,@(gr31,#REG_GR(2))
 	movsg		ccr,gr3
@@ -585,8 +583,8 @@ __break_continue:
 	# set up the kernel stack pointer
 	sti		sp,@(gr31,#REG_SP)
 
-	sethi.p		%hi(__break_stack_tos),sp
-	setlo		%lo(__break_stack_tos),sp
+	sethi.p		%hi(__break_frame_0),sp
+	setlo		%lo(__break_frame_0),sp
 
 	# finish building the exception frame
 	stdi		gr4 ,@(gr31,#REG_GR(4))
@@ -651,9 +649,12 @@ #endif
 	movsg		nmar,gr5
 	movsg		dcr,gr6
 
-	stdi		gr4 ,@(gr31,#REG_BRR)
-	sti		gr19,@(gr31,#REG_BPSR)
-	sti.p		gr6 ,@(gr31,#REG_DCR)
+	sethi.p		%hi(__debug_status),gr7
+	setlo		%lo(__debug_status),gr7
+
+	stdi		gr4 ,@(gr7,#DEBUG_BRR)
+	sti		gr19,@(gr7,#DEBUG_BPSR)
+	sti.p		gr6 ,@(gr7,#DEBUG_DCR)
 
 	# trap exceptions during break handling and disable h/w breakpoints/watchpoints
 	sethi		%hi(DCR_EBE),gr5
@@ -698,7 +699,10 @@ #endif
 	lddi		@(gr31,#REG_PSR) ,gr22
 	ldi		@(gr31,#REG_PC)  ,gr21
 	ldi		@(gr31,#REG_TBR) ,gr20
-	ldi.p		@(gr31,#REG_DCR) ,gr6
+
+	sethi.p		%hi(__debug_status),gr6
+	setlo		%lo(__debug_status),gr6
+	ldi.p		@(gr6,#DEBUG_DCR) ,gr6
 
 	andi		gr22,#PSR_S,gr19		/* rebuild BPSR */
 	andi.p		gr22,#PSR_ET,gr5
arch/frv/kernel/debug-stub.c +6 -7
index 4761cc4..2f6c60c 100644
@@ -39,10 +39,9 @@ do {						\
 	gdbstub_do_rx();			\
 } while(!FLOWCTL_QUERY(LINE))
 
-static void __init debug_stub_init(void);
+struct frv_debug_status __debug_status;
 
-extern asmlinkage void __break_hijack_kernel_event(void);
-extern asmlinkage void __break_hijack_kernel_event_breaks_here(void);
+static void __init debug_stub_init(void);
 
 /*****************************************************************************/
 /*
@@ -67,7 +66,7 @@ asmlinkage void debug_stub(void)
 		__set_HSR(0, hsr0 & ~HSR0_ETMD);
 
 	/* disable single stepping */
-	__debug_regs->dcr &= ~DCR_SE;
+	__debug_status.dcr &= ~DCR_SE;
 
 	/* kernel mode can propose an exception be handled in debug mode by jumping to a special
 	 * location */
@@ -76,8 +75,8 @@ asmlinkage void debug_stub(void)
 		 * the top kernel context */
 		*__debug_frame = *__frame;
 		__frame = __debug_frame->next_frame;
-		__debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12;
-		__debug_regs->brr |= BRR_EB;
+		__debug_status.brr = (__debug_frame->tbr & TBR_TT) << 12;
+		__debug_status.brr |= BRR_EB;
 	}
 
 	if (__debug_frame->pc == (unsigned long) __debug_bug_trap + 4) {
@@ -124,7 +123,7 @@ static void __init debug_stub_init(void)
 		__debug_frame->pc = (unsigned long) start_kernel;
 
 	/* enable the debug events we want to trap */
-	__debug_regs->dcr = DCR_EBE;
+	__debug_status.dcr = DCR_EBE;
 
 #ifdef CONFIG_GDBSTUB
 	gdbstub_init();
arch/frv/kernel/entry.S +0 -1
index 2a1ff1f..940ac30 100644
@@ -27,7 +27,6 @@
  *
  */
 
-#include <linux/sys.h>
 #include <linux/linkage.h>
 #include <asm/thread_info.h>
 #include <asm/setup.h>
arch/frv/kernel/gdb-stub.c +90 -69

423 lines not on this page · raw message

arch/frv/kernel/head.S +1 -0
index 47c990a..fecf751 100644
@@ -11,6 +11,7 @@
 
 #include <linux/threads.h>
 #include <linux/linkage.h>
+#include <asm/thread_info.h>
 #include <asm/ptrace.h>
 #include <asm/page.h>
 #include <asm/spr-regs.h>
arch/frv/kernel/process.c +2 -1
index f0c767a..515a5ce 100644
@@ -26,6 +26,7 @@ #include <linux/elf.h>
 #include <linux/reboot.h>
 #include <linux/interrupt.h>
 
+#include <asm/asm-offsets.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/setup.h>
@@ -207,7 +208,7 @@ int copy_thread(int nr, unsigned long cl
 
 	regs0 = __kernel_frame0_ptr;
 	childregs0 = (struct pt_regs *)
-		(task_stack_page(p) + THREAD_SIZE - USER_CONTEXT_SIZE);
+		(task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE);
 	childregs = childregs0;
 
 	/* set up the userspace frame (the only place that the USP is stored) */
arch/frv/kernel/switch_to.S +2 -1
index 9e5a583..b5275fa 100644
@@ -11,6 +11,7 @@ # as published by the Free Software Foun
 # 2 of the License, or (at your option) any later version.
 #
 ###############################################################################
+
 #include <linux/linkage.h>
 #include <asm/thread_info.h>
 #include <asm/processor.h>
@@ -30,7 +31,7 @@ #include <asm/spr-regs.h>
 	# address of frame 0 (userspace) on current kernel stack
 	.globl		__kernel_frame0_ptr
 __kernel_frame0_ptr:
-	.long		init_thread_union + THREAD_SIZE - USER_CONTEXT_SIZE
+	.long		init_thread_union + THREAD_SIZE - FRV_FRAME0_SIZE
 
 	# address of current task
 	.globl		__kernel_current_task
arch/frv/kernel/traps.c +13 -12
index 98ce362..2e6098c 100644
@@ -20,6 +20,7 @@ #include <linux/linkage.h>
 #include <linux/init.h>
 #include <linux/module.h>
 
+#include <asm/asm-offsets.h>
 #include <asm/setup.h>
 #include <asm/fpu.h>
 #include <asm/system.h>
@@ -279,20 +280,20 @@ static const char *regnames[] = {
 
 void show_regs(struct pt_regs *regs)
 {
-	uint32_t *reg;
+	unsigned long *reg;
 	int loop;
 
 	printk("\n");
 
-	printk("Frame: @%08x [%s]\n",
-	       (uint32_t) regs,
+	printk("Frame: @%08lx [%s]\n",
+	       (unsigned long) regs,
 	       regs->psr & PSR_S ? "kernel" : "user");
 
-	reg = (uint32_t *) regs;
-	for (loop = 0; loop < REG__END; loop++) {
-		printk("%s %08x", regnames[loop + 0], reg[loop + 0]);
+	reg = (unsigned long *) regs;
+	for (loop = 0; loop < NR_PT_REGS; loop++) {
+		printk("%s %08lx", regnames[loop + 0], reg[loop + 0]);
 
-		if (loop == REG__END - 1 || loop % 5 == 4)
+		if (loop == NR_PT_REGS - 1 || loop % 5 == 4)
 			printk("\n");
 		else
 			printk(" | ");
@@ -328,7 +329,7 @@ void die_if_kernel(const char *str, ...)
  */
 static void show_backtrace_regs(struct pt_regs *frame)
 {
-	uint32_t *reg;
+	unsigned long *reg;
 	int loop;
 
 	/* print the registers for this frame */
@@ -336,11 +337,11 @@ static void show_backtrace_regs(struct p
 	       frame->psr & PSR_S ? "Kernel Mode" : "User Mode",
 	       frame);
 
-	reg = (uint32_t *) frame;
-	for (loop = 0; loop < REG__END; loop++) {
-		printk("%s %08x", regnames[loop + 0], reg[loop + 0]);
+	reg = (unsigned long *) frame;
+	for (loop = 0; loop < NR_PT_REGS; loop++) {
+		printk("%s %08lx", regnames[loop + 0], reg[loop + 0]);
 
-		if (loop == REG__END - 1 || loop % 5 == 4)
+		if (loop == NR_PT_REGS - 1 || loop % 5 == 4)
 			printk("\n");
 		else
 			printk(" | ");
include/asm-frv/gdb-stub.h +22 -0
index c58479a..24f9738 100644
@@ -89,6 +89,7 @@ extern void gdbstub_do_rx(void);
 
 extern asmlinkage void __debug_stub_init_break(void);
 extern asmlinkage void __break_hijack_kernel_event(void);
+extern asmlinkage void __break_hijack_kernel_event_breaks_here(void);
 extern asmlinkage void start_kernel(void);
 
 extern asmlinkage void gdbstub_rx_handler(void);
@@ -114,5 +115,26 @@ #else
 #define gdbstub_proto(FMT,...) ({ 0; })
 #endif
 
+/*
+ * we dedicate GR31 to keeping a pointer to the gdbstub exception frame
+ * - gr31 is destroyed on entry to the gdbstub if !MMU
+ * - gr31 is saved in scr3 on entry to the gdbstub if in !MMU
+ */
+register struct frv_frame0 *__debug_frame0 asm("gr31");
+
+#define __debug_frame		(&__debug_frame0->regs)
+#define __debug_user_context	(&__debug_frame0->uc)
+#define __debug_regs		(&__debug_frame0->debug)
+#define __debug_reg(X)		((unsigned long *) ((unsigned long) &__debug_frame0 + (X)))
+
+struct frv_debug_status {
+	unsigned long		bpsr;
+	unsigned long		dcr;
+	unsigned long		brr;
+	unsigned long		nmar;
+};
+
+extern struct frv_debug_status __debug_status;
+
 #endif /* _LANGUAGE_ASSEMBLY */
 #endif /* __ASM_GDB_STUB_H */
include/asm-frv/ptrace.h +2 -10
index b2cce07..7ff5251 100644
@@ -62,18 +62,10 @@ #define PTRACE_GETFDPIC_INTERP	1	/* [add
 #ifndef __ASSEMBLY__
 
 /*
- * dedicate GR28; to keeping the a pointer to the current exception frame
+ * we dedicate GR28 to keeping a pointer to the current exception frame
+ * - gr28 is destroyed on entry to the kernel from userspace
  */
 register struct pt_regs *__frame asm("gr28");
-register struct pt_regs *__debug_frame asm("gr31");
-
-#ifndef container_of
-#define container_of(ptr, type, member) ({			\
-        const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
-        (type *)( (char *)__mptr - offsetof(type,member) );})
-#endif
-
-#define __debug_regs container_of(__debug_frame, struct pt_debug_regs, normal_regs)
 
 #define user_mode(regs)			(!((regs)->psr & PSR_S))
 #define instruction_pointer(regs)	((regs)->pc)
include/asm-frv/registers.h +37 -60

145 lines not on this page · raw message

include/asm-frv/thread_info.h +4 -20
index ea426ab..d66c48e 100644
@@ -19,6 +19,8 @@ #ifndef __ASSEMBLY__
 #include <asm/processor.h>
 #endif
 
+#define THREAD_SIZE		8192
+
 /*
  * low level task data that entry.S needs immediate access to
  * - this struct should fit entirely inside of one cache line
@@ -46,15 +48,7 @@ struct thread_info {
 
 #else /* !__ASSEMBLY__ */
 
-/* offsets into the thread_info struct for assembly code access */
-#define TI_TASK			0x00000000
-#define TI_EXEC_DOMAIN		0x00000004
-#define TI_FLAGS		0x00000008
-#define TI_STATUS		0x0000000C
-#define TI_CPU			0x00000010
-#define TI_PRE_COUNT		0x00000014
-#define TI_ADDR_LIMIT		0x00000018
-#define TI_RESTART_BLOCK	0x0000001C
+#include <asm/asm-offsets.h>
 
 #endif
 
@@ -83,12 +77,6 @@ #define INIT_THREAD_INFO(tsk)			\
 #define init_thread_info	(init_thread_union.thread_info)
 #define init_stack		(init_thread_union.stack)
 
-#ifdef CONFIG_SMALL_TASKS
-#define THREAD_SIZE		4096
-#else
-#define THREAD_SIZE		8192
-#endif
-
 /* how to get the thread information struct from C */
 register struct thread_info *__current_thread_info asm("gr15");
 
@@ -111,11 +99,7 @@ #endif
 
 #define free_thread_info(info)	kfree(info)
 
-#else /* !__ASSEMBLY__ */
-
-#define THREAD_SIZE	8192
-
-#endif
+#endif /* __ASSEMBLY__ */
 
 /*
  * thread information flags