LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] Restrict initial stack space expansion to rlimit
From: Michael Neuling @ 2010-02-09  8:59 UTC (permalink / raw)
  To: KOSAKI Motohiro
  Cc: stable, aeb, Oleg Nesterov, miltonm, James Morris, linuxppc-dev,
	Paul Mackerras, Anton Blanchard, Serge Hallyn, linux-fsdevel,
	Americo Wang, Andrew Morton, Linus Torvalds, Ingo Molnar,
	linux-kernel, Alexander Viro
In-Reply-To: <20100209154141.03F0.A69D9226@jp.fujitsu.com>

In message <20100209154141.03F0.A69D9226@jp.fujitsu.com> you wrote:
> > When reserving stack space for a new process, make sure we're not
> > attempting to expand the stack by more than rlimit allows.
> > 
> > This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba "mm:
> > variable length argument support" and unmasked by
> > fc63cf237078c86214abcb2ee9926d8ad289da9b "exec: setup_arg_pages() fails
> > to return errors".  This bug means when limiting the stack to less the
> > 20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will
> > be killed before they start.  This is particularly bad with 64K pages,
> > where a ulimit below 1280K will kill every process.
> > 
> > Signed-off-by: Michael Neuling <mikey@neuling.org>
> > Cc: stable@kernel.org
> > ---
> > Attempts to answer comments from Kosaki Motohiro.
> > 
> > Tested on PPC only, hence !CONFIG_STACK_GROWSUP.  Someone should
> > probably ACK for an arch with CONFIG_STACK_GROWSUP.
> > 
> > As noted, stable needs the same patch, but 2.6.32 doesn't have the
> > rlimit() helper.
> > 
> >  fs/exec.c |   21 ++++++++++++++++++---
> >  1 file changed, 18 insertions(+), 3 deletions(-)
> > 
> > Index: linux-2.6-ozlabs/fs/exec.c
> > ===================================================================
> > --- linux-2.6-ozlabs.orig/fs/exec.c
> > +++ linux-2.6-ozlabs/fs/exec.c
> > @@ -555,6 +555,7 @@ static int shift_arg_pages(struct vm_are
> >  }
> >  
> >  #define EXTRA_STACK_VM_PAGES	20	/* random */
> > +#define ALIGN_DOWN(addr,size)	((addr)&(~((size)-1)))
> >  
> >  /*
> >   * Finalizes the stack vm_area_struct. The flags and permissions are updat
ed,
> > @@ -570,7 +571,7 @@ int setup_arg_pages(struct linux_binprm 
> >  	struct vm_area_struct *vma = bprm->vma;
> >  	struct vm_area_struct *prev = NULL;
> >  	unsigned long vm_flags;
> > -	unsigned long stack_base;
> > +	unsigned long stack_base, stack_expand, stack_expand_lim, stack_size;
> >  
> >  #ifdef CONFIG_STACK_GROWSUP
> >  	/* Limit stack size to 1GB */
> > @@ -627,10 +628,24 @@ int setup_arg_pages(struct linux_binprm 
> >  			goto out_unlock;
> >  	}
> >  
> > +	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
> > +	stack_size = vma->vm_end - vma->vm_start;
> > +	if (rlimit(RLIMIT_STACK) < stack_size)
> > +		stack_expand_lim = 0; /* don't shrick the stack */
> > +	else
> > +		/*
> > +		 * Align this down to a page boundary as expand_stack
> > +		 * will align it up.
> > +		 */
> > +		stack_expand_lim = ALIGN_DOWN(rlimit(RLIMIT_STACK) - stack_size
,
> > +					      PAGE_SIZE);
> > +	/* Initial stack must not cause stack overflow. */
> > +	if (stack_expand > stack_expand_lim)
> > +		stack_expand = stack_expand_lim;
> >  #ifdef CONFIG_STACK_GROWSUP
> > -	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
> > +	stack_base = vma->vm_end + stack_expand;
> >  #else
> > -	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
> > +	stack_base = vma->vm_start - stack_expand;
> >  #endif
> >  	ret = expand_stack(vma, stack_base);
> >  	if (ret)
> 
> Umm.. It looks correct. but the nested complex if statement seems a bit ugly.
> Instead, How about following?

I don't like the duplicated code in the #ifdef/else but I can live with it.

> note: it's untested.

Works for me on ppc64 with 4k and 64k pages.  Thanks!

I'd still like someone with a CONFIG_STACK_GROWSUP arch to test/ACK it
as well.

Mikey

> 
> 
> 
> ===============
> From: Michael Neuling <mikey@neuling.org>
> Subject: Restrict initial stack space expansion to rlimit
> 
> When reserving stack space for a new process, make sure we're not
> attempting to expand the stack by more than rlimit allows.
> 
> This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba "mm:
> variable length argument support" and unmasked by
> fc63cf237078c86214abcb2ee9926d8ad289da9b "exec: setup_arg_pages() fails
> to return errors".  This bug means when limiting the stack to less the
> 20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will
> be killed before they start.  This is particularly bad with 64K pages,
> where a ulimit below 1280K will kill every process.
> 
> [kosaki.motohiro@jp.fujitsu.com: cleanups]
> Signed-off-by: Michael Neuling <mikey@neuling.org>
> Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
> Cc: stable@kernel.org
> ---
> Attempts to answer comments from Kosaki Motohiro.
> 
> Tested on PPC only, hence !CONFIG_STACK_GROWSUP.  Someone should
> probably ACK for an arch with CONFIG_STACK_GROWSUP.
> 
> As noted, stable needs the same patch, but 2.6.32 doesn't have the
> rlimit() helper.
> 
> diff --git a/fs/exec.c b/fs/exec.c
> index 6f7fb0c..325bad4 100644
> --- a/fs/exec.c
> +++ b/fs/exec.c
> @@ -573,6 +573,9 @@ int setup_arg_pages(struct linux_binprm *bprm,
>  	struct vm_area_struct *prev = NULL;
>  	unsigned long vm_flags;
>  	unsigned long stack_base;
> +	unsigned long stack_size;
> +	unsigned long stack_expand;
> +	unsigned long rlim_stack;
>  
>  #ifdef CONFIG_STACK_GROWSUP
>  	/* Limit stack size to 1GB */
> @@ -629,10 +632,27 @@ int setup_arg_pages(struct linux_binprm *bprm,
>  			goto out_unlock;
>  	}
>  
> +	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
> +	stack_size = vma->vm_end - vma->vm_start;
> +	/*
> +	 * Align this down to a page boundary as expand_stack
> +	 * will align it up.
> +	 */
> +	rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK;
> +	if (rlim_stack < stack_size)
> +		rlim_stack = stack_size;
>  #ifdef CONFIG_STACK_GROWSUP
> -	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
> +	if (stack_size + stack_expand > rlim_stack) {
> +		stack_base = vma->vm_start + rlim_stack;
> +	} else {
> +		stack_base = vma->vm_end + stack_expand;
> +	}
>  #else
> -	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
> +	if (stack_size + stack_expand > rlim_stack) {
> +		stack_base = vma->vm_end - rlim_stack;
> +	} else {
> +		stack_base = vma->vm_start - stack_expand;
> +	}
>  #endif
>  	ret = expand_stack(vma, stack_base);
>  	if (ret)
> 
> 
> 

^ permalink raw reply

* Re: [PATCH v3 00/11] Update support for MPC512x
From: Anatolij Gustschin @ 2010-02-09  8:48 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: wd, dzu, linux-usb, linuxppc-dev, linux-mtd, rtc-linux,
	Dan Williams
In-Reply-To: <1265377377-29327-1-git-send-email-agust@denx.de>

On Fri,  5 Feb 2010 14:42:46 +0100
Anatolij Gustschin <agust@denx.de> wrote:

> The patches are based on v2.6.33-rc6 and cover the following
> items:

These patches can also be pulled from
git://git.denx.de/linux-2.6-denx.git mpc512x-v2.6.33-devel
branch now.

Anatolij

^ permalink raw reply

* Re: [PATCH] Restrict initial stack space expansion to rlimit
From: KOSAKI Motohiro @ 2010-02-09  6:46 UTC (permalink / raw)
  To: Michael Neuling
  Cc: stable, aeb, Oleg Nesterov, miltonm, James Morris, linuxppc-dev,
	Paul Mackerras, Anton Blanchard, kosaki.motohiro, Serge Hallyn,
	linux-fsdevel, Americo Wang, Andrew Morton, Linus Torvalds,
	Ingo Molnar, linux-kernel, Alexander Viro
In-Reply-To: <1273.1265695885@neuling.org>

> When reserving stack space for a new process, make sure we're not
> attempting to expand the stack by more than rlimit allows.
> 
> This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba "mm:
> variable length argument support" and unmasked by
> fc63cf237078c86214abcb2ee9926d8ad289da9b "exec: setup_arg_pages() fails
> to return errors".  This bug means when limiting the stack to less the
> 20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will
> be killed before they start.  This is particularly bad with 64K pages,
> where a ulimit below 1280K will kill every process.
> 
> Signed-off-by: Michael Neuling <mikey@neuling.org>
> Cc: stable@kernel.org
> ---
> Attempts to answer comments from Kosaki Motohiro.
> 
> Tested on PPC only, hence !CONFIG_STACK_GROWSUP.  Someone should
> probably ACK for an arch with CONFIG_STACK_GROWSUP.
> 
> As noted, stable needs the same patch, but 2.6.32 doesn't have the
> rlimit() helper.
> 
>  fs/exec.c |   21 ++++++++++++++++++---
>  1 file changed, 18 insertions(+), 3 deletions(-)
> 
> Index: linux-2.6-ozlabs/fs/exec.c
> ===================================================================
> --- linux-2.6-ozlabs.orig/fs/exec.c
> +++ linux-2.6-ozlabs/fs/exec.c
> @@ -555,6 +555,7 @@ static int shift_arg_pages(struct vm_are
>  }
>  
>  #define EXTRA_STACK_VM_PAGES	20	/* random */
> +#define ALIGN_DOWN(addr,size)	((addr)&(~((size)-1)))
>  
>  /*
>   * Finalizes the stack vm_area_struct. The flags and permissions are updated,
> @@ -570,7 +571,7 @@ int setup_arg_pages(struct linux_binprm 
>  	struct vm_area_struct *vma = bprm->vma;
>  	struct vm_area_struct *prev = NULL;
>  	unsigned long vm_flags;
> -	unsigned long stack_base;
> +	unsigned long stack_base, stack_expand, stack_expand_lim, stack_size;
>  
>  #ifdef CONFIG_STACK_GROWSUP
>  	/* Limit stack size to 1GB */
> @@ -627,10 +628,24 @@ int setup_arg_pages(struct linux_binprm 
>  			goto out_unlock;
>  	}
>  
> +	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
> +	stack_size = vma->vm_end - vma->vm_start;
> +	if (rlimit(RLIMIT_STACK) < stack_size)
> +		stack_expand_lim = 0; /* don't shrick the stack */
> +	else
> +		/*
> +		 * Align this down to a page boundary as expand_stack
> +		 * will align it up.
> +		 */
> +		stack_expand_lim = ALIGN_DOWN(rlimit(RLIMIT_STACK) - stack_size,
> +					      PAGE_SIZE);
> +	/* Initial stack must not cause stack overflow. */
> +	if (stack_expand > stack_expand_lim)
> +		stack_expand = stack_expand_lim;
>  #ifdef CONFIG_STACK_GROWSUP
> -	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
> +	stack_base = vma->vm_end + stack_expand;
>  #else
> -	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
> +	stack_base = vma->vm_start - stack_expand;
>  #endif
>  	ret = expand_stack(vma, stack_base);
>  	if (ret)

Umm.. It looks correct. but the nested complex if statement seems a bit ugly.
Instead, How about following?

note: it's untested.



===============
From: Michael Neuling <mikey@neuling.org>
Subject: Restrict initial stack space expansion to rlimit

When reserving stack space for a new process, make sure we're not
attempting to expand the stack by more than rlimit allows.

This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba "mm:
variable length argument support" and unmasked by
fc63cf237078c86214abcb2ee9926d8ad289da9b "exec: setup_arg_pages() fails
to return errors".  This bug means when limiting the stack to less the
20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will
be killed before they start.  This is particularly bad with 64K pages,
where a ulimit below 1280K will kill every process.

[kosaki.motohiro@jp.fujitsu.com: cleanups]
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: stable@kernel.org
---
Attempts to answer comments from Kosaki Motohiro.

Tested on PPC only, hence !CONFIG_STACK_GROWSUP.  Someone should
probably ACK for an arch with CONFIG_STACK_GROWSUP.

As noted, stable needs the same patch, but 2.6.32 doesn't have the
rlimit() helper.

diff --git a/fs/exec.c b/fs/exec.c
index 6f7fb0c..325bad4 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -573,6 +573,9 @@ int setup_arg_pages(struct linux_binprm *bprm,
 	struct vm_area_struct *prev = NULL;
 	unsigned long vm_flags;
 	unsigned long stack_base;
+	unsigned long stack_size;
+	unsigned long stack_expand;
+	unsigned long rlim_stack;
 
 #ifdef CONFIG_STACK_GROWSUP
 	/* Limit stack size to 1GB */
@@ -629,10 +632,27 @@ int setup_arg_pages(struct linux_binprm *bprm,
 			goto out_unlock;
 	}
 
+	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_size = vma->vm_end - vma->vm_start;
+	/*
+	 * Align this down to a page boundary as expand_stack
+	 * will align it up.
+	 */
+	rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK;
+	if (rlim_stack < stack_size)
+		rlim_stack = stack_size;
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	if (stack_size + stack_expand > rlim_stack) {
+		stack_base = vma->vm_start + rlim_stack;
+	} else {
+		stack_base = vma->vm_end + stack_expand;
+	}
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	if (stack_size + stack_expand > rlim_stack) {
+		stack_base = vma->vm_end - rlim_stack;
+	} else {
+		stack_base = vma->vm_start - stack_expand;
+	}
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)

^ permalink raw reply related

* [PATCH] Restrict initial stack space expansion to rlimit
From: Michael Neuling @ 2010-02-09  6:11 UTC (permalink / raw)
  To: KOSAKI Motohiro
  Cc: stable, aeb, Oleg Nesterov, miltonm, James Morris, linuxppc-dev,
	Paul Mackerras, Anton Blanchard, Serge Hallyn, linux-fsdevel,
	Americo Wang, Andrew Morton, Linus Torvalds, Ingo Molnar,
	linux-kernel, Alexander Viro
In-Reply-To: <20100208161014.7C6D.A69D9226@jp.fujitsu.com>

When reserving stack space for a new process, make sure we're not
attempting to expand the stack by more than rlimit allows.

This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba "mm:
variable length argument support" and unmasked by
fc63cf237078c86214abcb2ee9926d8ad289da9b "exec: setup_arg_pages() fails
to return errors".  This bug means when limiting the stack to less the
20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will
be killed before they start.  This is particularly bad with 64K pages,
where a ulimit below 1280K will kill every process.

Signed-off-by: Michael Neuling <mikey@neuling.org>
Cc: stable@kernel.org
---
Attempts to answer comments from Kosaki Motohiro.

Tested on PPC only, hence !CONFIG_STACK_GROWSUP.  Someone should
probably ACK for an arch with CONFIG_STACK_GROWSUP.

As noted, stable needs the same patch, but 2.6.32 doesn't have the
rlimit() helper.

 fs/exec.c |   21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

Index: linux-2.6-ozlabs/fs/exec.c
===================================================================
--- linux-2.6-ozlabs.orig/fs/exec.c
+++ linux-2.6-ozlabs/fs/exec.c
@@ -555,6 +555,7 @@ static int shift_arg_pages(struct vm_are
 }
 
 #define EXTRA_STACK_VM_PAGES	20	/* random */
+#define ALIGN_DOWN(addr,size)	((addr)&(~((size)-1)))
 
 /*
  * Finalizes the stack vm_area_struct. The flags and permissions are updated,
@@ -570,7 +571,7 @@ int setup_arg_pages(struct linux_binprm 
 	struct vm_area_struct *vma = bprm->vma;
 	struct vm_area_struct *prev = NULL;
 	unsigned long vm_flags;
-	unsigned long stack_base;
+	unsigned long stack_base, stack_expand, stack_expand_lim, stack_size;
 
 #ifdef CONFIG_STACK_GROWSUP
 	/* Limit stack size to 1GB */
@@ -627,10 +628,24 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
+	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_size = vma->vm_end - vma->vm_start;
+	if (rlimit(RLIMIT_STACK) < stack_size)
+		stack_expand_lim = 0; /* don't shrick the stack */
+	else
+		/*
+		 * Align this down to a page boundary as expand_stack
+		 * will align it up.
+		 */
+		stack_expand_lim = ALIGN_DOWN(rlimit(RLIMIT_STACK) - stack_size,
+					      PAGE_SIZE);
+	/* Initial stack must not cause stack overflow. */
+	if (stack_expand > stack_expand_lim)
+		stack_expand = stack_expand_lim;
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_end + stack_expand;
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_start - stack_expand;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)

^ permalink raw reply

* Fix address masking bug in hpte_need_flush()
From: David Gibson @ 2010-02-09  6:09 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Miichael Neuling

Commit f71dc176aa06359681c30ba6877ffccab6fba3a6 'Make
hpte_need_flush() correctly mask for multiple page sizes' introduced
bug, which is triggered when a kernel with a 64k base page size is run
on a system whose hardware does not 64k hash PTEs.  In this case, we
emulate 64k pages with multiple 4k hash PTEs, however in
hpte_need_flush() we incorrectly only mask the hardware page size from
the address, instead of the logical page size.  This causes things to
go wrong when we later attempt to iterate through the hardware
subpages of the logical page.

This patch corrects the error.  It has been tested on pSeries bare
metal by Michael Neuling.

Signed-off-by: David Gibson <dwg@au1.ibm.com>

Index: working-2.6/arch/powerpc/mm/tlb_hash64.c
===================================================================
--- working-2.6.orig/arch/powerpc/mm/tlb_hash64.c	2010-02-09 16:44:58.810336741 +1100
+++ working-2.6/arch/powerpc/mm/tlb_hash64.c	2010-02-09 16:45:58.920721138 +1100
@@ -63,15 +63,21 @@ void hpte_need_flush(struct mm_struct *m
 	if (huge) {
 #ifdef CONFIG_HUGETLB_PAGE
 		psize = get_slice_psize(mm, addr);
+		/* Mask the address for the correct page size */
+		addr &= ~((1UL << mmu_psize_defs[psize].shift) - 1);
 #else
 		BUG();
 		psize = pte_pagesize_index(mm, addr, pte); /* shutup gcc */
 #endif
-	} else
+	} else {
 		psize = pte_pagesize_index(mm, addr, pte);
+		/* Mask the address for the standard page size.  If we
+		 * have a 64k page kernel, but the hardware does not
+		 * support 64k pages, this might be different from the
+		 * hardware page size encoded in the slice table. */
+		addr &= PAGE_MASK;
+	}
 
-	/* Mask the address for the correct page size */
-	addr &= ~((1UL << mmu_psize_defs[psize].shift) - 1);
 
 	/* Build full vaddr */
 	if (!is_kernel_addr(addr)) {

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: tip build problem on powerpc
From: Ingo Molnar @ 2010-02-09  4:22 UTC (permalink / raw)
  To: Stephen Rothwell
  Cc: Peter Zijlstra, Don Zickus, Thomas Gleixner, ppc-dev,
	H. Peter Anvin
In-Reply-To: <20100209100700.81685ffe.sfr@canb.auug.org.au>


* Stephen Rothwell <sfr@canb.auug.org.au> wrote:

> Hi all,
> 
> Last night's build of tip/master on powerpc produced these errors:
> 
> kernel/nmi_watchdog.c:33: error: redefinition of 'touch_nmi_watchdog'
> kernel/nmi_watchdog.c:59: error: 'nmi_watchdog_enabled' undeclared (first use in this function)
> kernel/nmi_watchdog.c:59: error: (Each undeclared identifier is reported only once
> kernel/nmi_watchdog.c:59: error: for each function it appears in.)
> kernel/nmi_watchdog.c:109: error: implicit declaration of function 'die_nmi'
> kernel/nmi_watchdog.c:136: error: 'cpu_khz' undeclared (first use in this function)

yep, i know that already from the -tip cross build tests and reported it to 
Don yesterday. Do you boot -tip or only build test it? If you use -tip 
personally then you can simply disable CONFIG_NMI_WATCHDOG.

Thanks,

	Ingo

^ permalink raw reply

* Re: tip build problem on powerpc
From: Stephen Rothwell @ 2010-02-09  4:41 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Peter Zijlstra, Don Zickus, Thomas Gleixner, ppc-dev,
	H. Peter Anvin
In-Reply-To: <20100209042238.GB11280@elte.hu>

[-- Attachment #1: Type: text/plain, Size: 445 bytes --]

Hi Ingo.

On Tue, 9 Feb 2010 05:22:38 +0100 Ingo Molnar <mingo@elte.hu> wrote:
>
> yep, i know that already from the -tip cross build tests and reported it to 
> Don yesterday. Do you boot -tip or only build test it? If you use -tip 
> personally then you can simply disable CONFIG_NMI_WATCHDOG.

OK, good.  I just build test.

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply

* Re: [PATCH 2/4] Fix G5 thermal shutdown
From: Josh Boyer @ 2010-02-09  2:06 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, dwmw2; +Cc: linuxppc-dev
In-Reply-To: <1265676905.8287.254.camel@pasglop>

On Tue, Feb 09, 2010 at 11:55:05AM +1100, Benjamin Herrenschmidt wrote:
>On Fri, 2010-02-05 at 08:52 -0500, Josh Boyer wrote:
>> This changes the thresholds for the liquid cooled G5 thermal
>> shutdown mechanism to prevent an errant shutdown.
>> 
>> This has been carried since about Fedora Core 5.  I have no idea
>> if it's really needed or not.
>
>Can we have a SoB ?

David?

josh

>
>Cheers,
>Ben.
>
>> ---
>> 
>> --- linux-2.6.15/drivers/macintosh/therm_pm72.c.orig	2006-04-02 21:34:48.000000000 +0100
>> +++ linux-2.6.15/drivers/macintosh/therm_pm72.c	2006-04-02 22:33:27.000000000 +0100
>> @@ -924,10 +925,16 @@ static void do_monitor_cpu_combined(void
>>  		printk(KERN_WARNING "Warning ! Temperature way above maximum (%d) !\n",
>>  		       temp_combi >> 16);
>>  		state0->overtemp += CPU_MAX_OVERTEMP / 4;
>> -	} else if (temp_combi > (state0->mpu.tmax << 16))
>> +	} else if (temp_combi > (state0->mpu.tmax << 16)) {
>>  		state0->overtemp++;
>> -	else
>> +		printk(KERN_WARNING "Temperature %d above max %d. overtemp %d\n",
>> +		       temp_combi >> 16, state0->mpu.tmax, state0->overtemp);
>> +	} else {
>> +		if (state0->overtemp)
>> +			printk(KERN_WARNING "Temperature back down to %d\n",
>> +			       temp_combi >> 16);
>>  		state0->overtemp = 0;
>> +	}
>>  	if (state0->overtemp >= CPU_MAX_OVERTEMP)
>>  		critical_state = 1;
>>  	if (state0->overtemp > 0) {
>> @@ -999,10 +1015,16 @@ static void do_monitor_cpu_split(struct 
>>  		       " (%d) !\n",
>>  		       state->index, temp >> 16);
>>  		state->overtemp += CPU_MAX_OVERTEMP / 4;
>> -	} else if (temp > (state->mpu.tmax << 16))
>> +	} else if (temp > (state->mpu.tmax << 16)) {
>>  		state->overtemp++;
>> -	else
>> +		printk(KERN_WARNING "CPU %d temperature %d above max %d. overtemp %d\n",
>> +		       state->index, temp >> 16, state->mpu.tmax, state->overtemp);
>> +	} else {
>> +		if (state->overtemp)
>> +			printk(KERN_WARNING "CPU %d temperature back down to %d\n",
>> +			       state->index, temp >> 16);
>>  		state->overtemp = 0;
>> +	}
>>  	if (state->overtemp >= CPU_MAX_OVERTEMP)
>>  		critical_state = 1;
>>  	if (state->overtemp > 0) {
>> @@ -1061,10 +1097,16 @@ static void do_monitor_cpu_rack(struct c
>>  		       " (%d) !\n",
>>  		       state->index, temp >> 16);
>>  		state->overtemp = CPU_MAX_OVERTEMP / 4;
>> -	} else if (temp > (state->mpu.tmax << 16))
>> +	} else if (temp > (state->mpu.tmax << 16)) {
>>  		state->overtemp++;
>> -	else
>> +		printk(KERN_WARNING "CPU %d temperature %d above max %d. overtemp %d\n",
>> +		       state->index, temp >> 16, state->mpu.tmax, state->overtemp);
>> +	} else {
>> +		if (state->overtemp)
>> +			printk(KERN_WARNING "CPU %d temperature back down to %d\n",
>> +			       state->index, temp >> 16);
>>  		state->overtemp = 0;
>> +	}
>>  	if (state->overtemp >= CPU_MAX_OVERTEMP)
>>  		critical_state = 1;
>>  	if (state->overtemp > 0) {
>> --- linux-2.6.15/drivers/macintosh/therm_pm72.h~	2006-01-03 03:21:10.000000000 +0000
>> +++ linux-2.6.15/drivers/macintosh/therm_pm72.h	2006-04-02 22:25:58.000000000 +0100
>> @@ -243,7 +243,7 @@ struct dimm_pid_state
>>  #define CPU_TEMP_HISTORY_SIZE		2
>>  #define CPU_POWER_HISTORY_SIZE		10
>>  #define CPU_PID_INTERVAL		1
>> -#define CPU_MAX_OVERTEMP		30
>> +#define CPU_MAX_OVERTEMP		90
>>  
>>  #define CPUA_PUMP_RPM_INDEX		7
>>  #define CPUB_PUMP_RPM_INDEX		8
>> _______________________________________________
>> Linuxppc-dev mailing list
>> Linuxppc-dev@lists.ozlabs.org
>> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
>

^ permalink raw reply

* Re: [PATCH 2/4] Fix G5 thermal shutdown
From: Benjamin Herrenschmidt @ 2010-02-09  0:55 UTC (permalink / raw)
  To: Josh Boyer; +Cc: linuxppc-dev
In-Reply-To: <20100205135216.GH12001@hansolo.jdub.homelinux.org>

On Fri, 2010-02-05 at 08:52 -0500, Josh Boyer wrote:
> This changes the thresholds for the liquid cooled G5 thermal
> shutdown mechanism to prevent an errant shutdown.
> 
> This has been carried since about Fedora Core 5.  I have no idea
> if it's really needed or not.

Can we have a SoB ?

Cheers,
Ben.

> ---
> 
> --- linux-2.6.15/drivers/macintosh/therm_pm72.c.orig	2006-04-02 21:34:48.000000000 +0100
> +++ linux-2.6.15/drivers/macintosh/therm_pm72.c	2006-04-02 22:33:27.000000000 +0100
> @@ -924,10 +925,16 @@ static void do_monitor_cpu_combined(void
>  		printk(KERN_WARNING "Warning ! Temperature way above maximum (%d) !\n",
>  		       temp_combi >> 16);
>  		state0->overtemp += CPU_MAX_OVERTEMP / 4;
> -	} else if (temp_combi > (state0->mpu.tmax << 16))
> +	} else if (temp_combi > (state0->mpu.tmax << 16)) {
>  		state0->overtemp++;
> -	else
> +		printk(KERN_WARNING "Temperature %d above max %d. overtemp %d\n",
> +		       temp_combi >> 16, state0->mpu.tmax, state0->overtemp);
> +	} else {
> +		if (state0->overtemp)
> +			printk(KERN_WARNING "Temperature back down to %d\n",
> +			       temp_combi >> 16);
>  		state0->overtemp = 0;
> +	}
>  	if (state0->overtemp >= CPU_MAX_OVERTEMP)
>  		critical_state = 1;
>  	if (state0->overtemp > 0) {
> @@ -999,10 +1015,16 @@ static void do_monitor_cpu_split(struct 
>  		       " (%d) !\n",
>  		       state->index, temp >> 16);
>  		state->overtemp += CPU_MAX_OVERTEMP / 4;
> -	} else if (temp > (state->mpu.tmax << 16))
> +	} else if (temp > (state->mpu.tmax << 16)) {
>  		state->overtemp++;
> -	else
> +		printk(KERN_WARNING "CPU %d temperature %d above max %d. overtemp %d\n",
> +		       state->index, temp >> 16, state->mpu.tmax, state->overtemp);
> +	} else {
> +		if (state->overtemp)
> +			printk(KERN_WARNING "CPU %d temperature back down to %d\n",
> +			       state->index, temp >> 16);
>  		state->overtemp = 0;
> +	}
>  	if (state->overtemp >= CPU_MAX_OVERTEMP)
>  		critical_state = 1;
>  	if (state->overtemp > 0) {
> @@ -1061,10 +1097,16 @@ static void do_monitor_cpu_rack(struct c
>  		       " (%d) !\n",
>  		       state->index, temp >> 16);
>  		state->overtemp = CPU_MAX_OVERTEMP / 4;
> -	} else if (temp > (state->mpu.tmax << 16))
> +	} else if (temp > (state->mpu.tmax << 16)) {
>  		state->overtemp++;
> -	else
> +		printk(KERN_WARNING "CPU %d temperature %d above max %d. overtemp %d\n",
> +		       state->index, temp >> 16, state->mpu.tmax, state->overtemp);
> +	} else {
> +		if (state->overtemp)
> +			printk(KERN_WARNING "CPU %d temperature back down to %d\n",
> +			       state->index, temp >> 16);
>  		state->overtemp = 0;
> +	}
>  	if (state->overtemp >= CPU_MAX_OVERTEMP)
>  		critical_state = 1;
>  	if (state->overtemp > 0) {
> --- linux-2.6.15/drivers/macintosh/therm_pm72.h~	2006-01-03 03:21:10.000000000 +0000
> +++ linux-2.6.15/drivers/macintosh/therm_pm72.h	2006-04-02 22:25:58.000000000 +0100
> @@ -243,7 +243,7 @@ struct dimm_pid_state
>  #define CPU_TEMP_HISTORY_SIZE		2
>  #define CPU_POWER_HISTORY_SIZE		10
>  #define CPU_PID_INTERVAL		1
> -#define CPU_MAX_OVERTEMP		30
> +#define CPU_MAX_OVERTEMP		90
>  
>  #define CPUA_PUMP_RPM_INDEX		7
>  #define CPUB_PUMP_RPM_INDEX		8
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* Re: simpleImage.XX and large kernels
From: John Williams @ 2010-02-08 23:12 UTC (permalink / raw)
  To: Wolfgang Denk; +Cc: linuxppc-dev
In-Reply-To: <20100208224812.CBED7A87D1A@gemini.denx.de>

Hi Wolfgang,

On Tue, Feb 9, 2010 at 8:48 AM, Wolfgang Denk <wd@denx.de> wrote:
>> I'm looking at the simpleImage.XXX make target (PPC 405/440), and it
>> seems that by default the arch/powerpc/boot/wrapper script places the
>> bootwrapper at 0x400000, effectively setting a limit on the maximum
>> bootable kernel size.
>>
>> For various reasons we'd like to be able to put a fairly complete
>> rootfs as an initramfs, which obviously blows past a 4Mbyte limit very
>> quickly. =A0Short of adding a new 'platform' option and associated
>> hackery through the powerpc/boot Makefiles and wrapper, is there a
>> quick and clean way I can tell the boot wrapper to link at a higher
>> address?
>
> Is there any specific reason why you want to use simpleImage, instead
> of using a normal uImage either bundled with your ramdisk image as a
> classic multifile image, or (recommended) as a FIT image?

Yes, there are a few reasons, though not necessarily very strong ones!
 Although we'll normally be using u-boot, I don't want to make it a
hard requirement.  simpleImage's ability to boot directly with a DTB
already bundled is attractive in this regard.

Another reason is that for compatibility with our MicroBlaze flow
(which also uses a simpleImage target, although a MicroBlaze
simpleImage is actually vmlinux with the DTB stuffed into its own
section).

Also sometimes it's nice to have a single ELF or binary blob we can
just push over JTAG straight to the target.  Having the DTB embedded
simplifies this process, no need to download vmlinux and DTB
separately, setup boot params etc.

I like FIT and think it's an elegant solution, I'm just a bit
reluctant to force its use.  For deeply embedded and flash constrained
systems we sometimes have a requirement to bypass uboot and boot
directly.

I may have to rethink the boot strategy eventually but in the short
term, getting some control over simpleImage as per my original post
would be a good first step.

Regards,

John

^ permalink raw reply

* tip build problem on powerpc
From: Stephen Rothwell @ 2010-02-08 23:07 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Peter Zijlstra
  Cc: Don Zickus, ppc-dev

[-- Attachment #1: Type: text/plain, Size: 1130 bytes --]

Hi all,

Last night's build of tip/master on powerpc produced these errors:

kernel/nmi_watchdog.c:33: error: redefinition of 'touch_nmi_watchdog'
kernel/nmi_watchdog.c:59: error: 'nmi_watchdog_enabled' undeclared (first use in this function)
kernel/nmi_watchdog.c:59: error: (Each undeclared identifier is reported only once
kernel/nmi_watchdog.c:59: error: for each function it appears in.)
kernel/nmi_watchdog.c:109: error: implicit declaration of function 'die_nmi'
kernel/nmi_watchdog.c:136: error: 'cpu_khz' undeclared (first use in this function)

This was from the powerpc pseries_defconfig build (as well as the
pamc32_defconfig, ppc6xx_defconfig and ppc64_defconfig builds).  Caused
by commit 1fb9d6ad2766a1dd70d167552988375049a97f21 ("nmi_watchdog: Add
new, generic implementation, using perf events") but exposed by commit
84e478c6f1eb9c4bfa1fff2f8108e9a061b46428 ("nmi_watchdog: Config option to
enable new nmi_watchdog").

Full logs, configs: http://kisskb.ellerman.id.au/kisskb/branch/12/
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply

* Re: simpleImage.XX and large kernels
From: Wolfgang Denk @ 2010-02-08 22:48 UTC (permalink / raw)
  To: John Williams; +Cc: linuxppc-dev
In-Reply-To: <1d3f23371002080247j17138famcf4e4aebc1ae04f5@mail.gmail.com>

Dear John Williams,

In message <1d3f23371002080247j17138famcf4e4aebc1ae04f5@mail.gmail.com> you wrote:
> 
> I'm looking at the simpleImage.XXX make target (PPC 405/440), and it
> seems that by default the arch/powerpc/boot/wrapper script places the
> bootwrapper at 0x400000, effectively setting a limit on the maximum
> bootable kernel size.
> 
> For various reasons we'd like to be able to put a fairly complete
> rootfs as an initramfs, which obviously blows past a 4Mbyte limit very
> quickly.  Short of adding a new 'platform' option and associated
> hackery through the powerpc/boot Makefiles and wrapper, is there a
> quick and clean way I can tell the boot wrapper to link at a higher
> address?

Is there any specific reason why you want to use simpleImage, instead
of using a normal uImage either bundled with your ramdisk image as a
classic multifile image, or (recommended) as a FIT image?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
It's all Klatchian to me.
        - Terry Pratchett & Stephen Briggs, _The Discworld Companion_

^ permalink raw reply

* Re: [PATCH] leds-gpio: Fix default state handling on OF platforms
From: Anton Vorontsov @ 2010-02-08 22:23 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linuxppc-dev, Trent Piepho, linux-kernel, Richard Purdie
In-Reply-To: <20100208130455.8cb90ff1.akpm@linux-foundation.org>

On Mon, Feb 08, 2010 at 01:04:55PM -0800, Andrew Morton wrote:
> On Fri, 5 Feb 2010 23:54:37 +0300
> Anton Vorontsov <avorontsov@ru.mvista.com> wrote:
> 
> > The driver wrongly sets default state for LEDs that don't specify
> > default-state property.
[...]
> Does this actually happen in any 2.6.33 driver code?

Well, the code that I fixed constructs Linux structures out of
OpenFirmware device tree. OF tree is somewhat similar to ACPI or
DMI tables in x86 world. So, in general, OF isn't kernel version
dependant.

(We have an in-tree depot of device trees for reference/devel boards
in arch/powerpc/boot/dts/, but this is surely not a conclusive
list of device trees in the wild.)

> If so, we might
> want to merge this into 2.6.33.  And perhaps earlier kernels.  Or not. 
> There's no way for me to tell :(

Since the fix is trivial, I'd say 2.6.33. But the issue isn't major,
so no big deal if it won't make it.

Thanks!

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply

* [PATCH 03/04] powerpc/booke: Add definitions for advanced debug registers
From: Dave Kleikamp @ 2010-02-08 21:53 UTC (permalink / raw)
  To: linuxppc-dev list
  Cc: Sergio Durigan Junior, David Gibson, Torez Smith,
	Thiago Jung Bauermann
In-Reply-To: <20100208215049.17930.8586.sendpatchset@norville.austin.ibm.com>

powerpc/booke: Add definitions for advanced debug registers

From: Dave Kleikamp <shaggy@linux.vnet.ibm.com>

Based on patches originally written by Torez Smith.

This patch adds additional definitions for BookE Debug Registers
to the reg_booke.h header file.

Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Acked-by: David Gibson <dwg@au1.ibm.com>
Cc: Torez Smith  <lnxtorez@linux.vnet.ibm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: Sergio Durigan Junior <sergiodj@br.ibm.com>
Cc: Thiago Jung Bauermann <bauerman@br.ibm.com>
Cc: linuxppc-dev list <Linuxppc-dev@ozlabs.org>
---

 arch/powerpc/include/asm/processor.h |   36 ++++++++++++-
 arch/powerpc/include/asm/reg_booke.h |   96 ++++++++++++++++++++++++++++++++++
 2 files changed, 129 insertions(+), 3 deletions(-)


diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 9eed29e..221ba62 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -161,9 +161,41 @@ struct thread_struct {
 #ifdef CONFIG_PPC32
 	void		*pgdir;		/* root of page-table tree */
 #endif
-#if defined(CONFIG_4xx) || defined (CONFIG_BOOKE)
-	unsigned long	dbcr0;		/* debug control register values */
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+	/*
+	 * The following help to manage the use of Debug Control Registers
+	 * om the BookE platforms.
+	 */
+	unsigned long	dbcr0;
 	unsigned long	dbcr1;
+#ifdef CONFIG_BOOKE
+	unsigned long	dbcr2;
+#endif
+	/*
+	 * The stored value of the DBSR register will be the value at the
+	 * last debug interrupt. This register can only be read from the
+	 * user (will never be written to) and has value while helping to
+	 * describe the reason for the last debug trap.  Torez
+	 */
+	unsigned long	dbsr;
+	/*
+	 * The following will contain addresses used by debug applications
+	 * to help trace and trap on particular address locations.
+	 * The bits in the Debug Control Registers above help define which
+	 * of the following registers will contain valid data and/or addresses.
+	 */
+	unsigned long	iac1;
+	unsigned long	iac2;
+#if CONFIG_PPC_ADV_DEBUG_IACS > 2
+	unsigned long	iac3;
+	unsigned long	iac4;
+#endif
+	unsigned long	dac1;
+	unsigned long	dac2;
+#if CONFIG_PPC_ADV_DEBUG_DVCS > 0
+	unsigned long	dvc1;
+	unsigned long	dvc2;
+#endif
 #endif
 	/* FP and VSX 0-31 register set */
 	double		fpr[32][TS_FPRWIDTH];
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index 3bf7835..8808d30 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -248,6 +248,8 @@
 #define DBSR_RET	0x00008000	/* Return Debug Event */
 #define DBSR_CIRPT	0x00000040	/* Critical Interrupt Taken Event */
 #define DBSR_CRET	0x00000020	/* Critical Return Debug Event */
+#define DBSR_IAC12ATS	0x00000002	/* Instr Address Compare 1/2 Toggle */
+#define DBSR_IAC34ATS	0x00000001	/* Instr Address Compare 3/4 Toggle */
 #endif
 #ifdef CONFIG_40x
 #define DBSR_IC		0x80000000	/* Instruction Completion */
@@ -313,6 +315,38 @@
 #define DBCR0_IA12T	0x00008000	/* Instr Addr 1-2 range Toggle */
 #define DBCR0_IA34T	0x00004000	/* Instr Addr 3-4 range Toggle */
 #define DBCR0_FT	0x00000001	/* Freeze Timers on debug event */
+
+#define dbcr_iac_range(task)	((task)->thread.dbcr0)
+#define DBCR_IAC12I	DBCR0_IA12			/* Range Inclusive */
+#define DBCR_IAC12X	(DBCR0_IA12 | DBCR0_IA12X)	/* Range Exclusive */
+#define DBCR_IAC12MODE	(DBCR0_IA12 | DBCR0_IA12X)	/* IAC 1-2 Mode Bits */
+#define DBCR_IAC34I	DBCR0_IA34			/* Range Inclusive */
+#define DBCR_IAC34X	(DBCR0_IA34 | DBCR0_IA34X)	/* Range Exclusive */
+#define DBCR_IAC34MODE	(DBCR0_IA34 | DBCR0_IA34X)	/* IAC 3-4 Mode Bits */
+
+/* Bit definitions related to the DBCR1. */
+#define DBCR1_DAC1R	0x80000000	/* DAC1 Read Debug Event */
+#define DBCR1_DAC2R	0x40000000	/* DAC2 Read Debug Event */
+#define DBCR1_DAC1W	0x20000000	/* DAC1 Write Debug Event */
+#define DBCR1_DAC2W	0x10000000	/* DAC2 Write Debug Event */
+
+#define dbcr_dac(task)	((task)->thread.dbcr1)
+#define DBCR_DAC1R	DBCR1_DAC1R
+#define DBCR_DAC1W	DBCR1_DAC1W
+#define DBCR_DAC2R	DBCR1_DAC2R
+#define DBCR_DAC2W	DBCR1_DAC2W
+
+/*
+ * Are there any active Debug Events represented in the
+ * Debug Control Registers?
+ */
+#define DBCR0_ACTIVE_EVENTS	(DBCR0_ICMP | DBCR0_IAC1 | DBCR0_IAC2 | \
+				 DBCR0_IAC3 | DBCR0_IAC4)
+#define DBCR1_ACTIVE_EVENTS	(DBCR1_DAC1R | DBCR1_DAC2R | \
+				 DBCR1_DAC1W | DBCR1_DAC2W)
+#define DBCR_ACTIVE_EVENTS(dbcr0, dbcr1)  (((dbcr0) & DBCR0_ACTIVE_EVENTS) || \
+					   ((dbcr1) & DBCR1_ACTIVE_EVENTS))
+
 #elif defined(CONFIG_BOOKE)
 #define DBCR0_EDM	0x80000000	/* External Debug Mode */
 #define DBCR0_IDM	0x40000000	/* Internal Debug Mode */
@@ -342,19 +376,79 @@
 #define DBCR0_CRET	0x00000020	/* Critical Return Debug Event */
 #define DBCR0_FT	0x00000001	/* Freeze Timers on debug event */
 
+#define dbcr_dac(task)	((task)->thread.dbcr0)
+#define DBCR_DAC1R	DBCR0_DAC1R
+#define DBCR_DAC1W	DBCR0_DAC1W
+#define DBCR_DAC2R	DBCR0_DAC2R
+#define DBCR_DAC2W	DBCR0_DAC2W
+
 /* Bit definitions related to the DBCR1. */
+#define DBCR1_IAC1US	0xC0000000	/* Instr Addr Cmp 1 Sup/User   */
+#define DBCR1_IAC1ER	0x30000000	/* Instr Addr Cmp 1 Eff/Real */
+#define DBCR1_IAC1ER_01	0x10000000	/* reserved */
+#define DBCR1_IAC1ER_10	0x20000000	/* Instr Addr Cmp 1 Eff/Real MSR[IS]=0 */
+#define DBCR1_IAC1ER_11	0x30000000	/* Instr Addr Cmp 1 Eff/Real MSR[IS]=1 */
+#define DBCR1_IAC2US	0x0C000000	/* Instr Addr Cmp 2 Sup/User   */
+#define DBCR1_IAC2ER	0x03000000	/* Instr Addr Cmp 2 Eff/Real */
+#define DBCR1_IAC2ER_01	0x01000000	/* reserved */
+#define DBCR1_IAC2ER_10	0x02000000	/* Instr Addr Cmp 2 Eff/Real MSR[IS]=0 */
+#define DBCR1_IAC2ER_11	0x03000000	/* Instr Addr Cmp 2 Eff/Real MSR[IS]=1 */
 #define DBCR1_IAC12M	0x00800000	/* Instr Addr 1-2 range enable */
 #define DBCR1_IAC12MX	0x00C00000	/* Instr Addr 1-2 range eXclusive */
 #define DBCR1_IAC12AT	0x00010000	/* Instr Addr 1-2 range Toggle */
+#define DBCR1_IAC3US	0x0000C000	/* Instr Addr Cmp 3 Sup/User   */
+#define DBCR1_IAC3ER	0x00003000	/* Instr Addr Cmp 3 Eff/Real */
+#define DBCR1_IAC3ER_01	0x00001000	/* reserved */
+#define DBCR1_IAC3ER_10	0x00002000	/* Instr Addr Cmp 3 Eff/Real MSR[IS]=0 */
+#define DBCR1_IAC3ER_11	0x00003000	/* Instr Addr Cmp 3 Eff/Real MSR[IS]=1 */
+#define DBCR1_IAC4US	0x00000C00	/* Instr Addr Cmp 4 Sup/User   */
+#define DBCR1_IAC4ER	0x00000300	/* Instr Addr Cmp 4 Eff/Real */
+#define DBCR1_IAC4ER_01	0x00000100	/* Instr Addr Cmp 4 Eff/Real MSR[IS]=0 */
+#define DBCR1_IAC4ER_10	0x00000200	/* Instr Addr Cmp 4 Eff/Real MSR[IS]=0 */
+#define DBCR1_IAC4ER_11	0x00000300	/* Instr Addr Cmp 4 Eff/Real MSR[IS]=1 */
 #define DBCR1_IAC34M	0x00000080	/* Instr Addr 3-4 range enable */
 #define DBCR1_IAC34MX	0x000000C0	/* Instr Addr 3-4 range eXclusive */
 #define DBCR1_IAC34AT	0x00000001	/* Instr Addr 3-4 range Toggle */
 
+#define dbcr_iac_range(task)	((task)->thread.dbcr1)
+#define DBCR_IAC12I	DBCR1_IAC12M	/* Range Inclusive */
+#define DBCR_IAC12X	DBCR1_IAC12MX	/* Range Exclusive */
+#define DBCR_IAC12MODE	DBCR1_IAC12MX	/* IAC 1-2 Mode Bits */
+#define DBCR_IAC34I	DBCR1_IAC34M	/* Range Inclusive */
+#define DBCR_IAC34X	DBCR1_IAC34MX	/* Range Exclusive */
+#define DBCR_IAC34MODE	DBCR1_IAC34MX	/* IAC 3-4 Mode Bits */
+
 /* Bit definitions related to the DBCR2. */
+#define DBCR2_DAC1US	0xC0000000	/* Data Addr Cmp 1 Sup/User   */
+#define DBCR2_DAC1ER	0x30000000	/* Data Addr Cmp 1 Eff/Real */
+#define DBCR2_DAC2US	0x00000000	/* Data Addr Cmp 2 Sup/User   */
+#define DBCR2_DAC2ER	0x00000000	/* Data Addr Cmp 2 Eff/Real */
 #define DBCR2_DAC12M	0x00800000	/* DAC 1-2 range enable */
+#define DBCR2_DAC12MM	0x00400000	/* DAC 1-2 Mask mode*/
 #define DBCR2_DAC12MX	0x00C00000	/* DAC 1-2 range eXclusive */
+#define DBCR2_DAC12MODE	0x00C00000	/* DAC 1-2 Mode Bits */
 #define DBCR2_DAC12A	0x00200000	/* DAC 1-2 Asynchronous */
-#endif
+#define DBCR2_DVC1M	0x000C0000	/* Data Value Comp 1 Mode */
+#define DBCR2_DVC1M_SHIFT	18	/* # of bits to shift DBCR2_DVC1M */
+#define DBCR2_DVC2M	0x00030000	/* Data Value Comp 2 Mode */
+#define DBCR2_DVC2M_SHIFT	16	/* # of bits to shift DBCR2_DVC2M */
+#define DBCR2_DVC1BE	0x00000F00	/* Data Value Comp 1 Byte */
+#define DBCR2_DVC1BE_SHIFT	8	/* # of bits to shift DBCR2_DVC1BE */
+#define DBCR2_DVC2BE	0x0000000F	/* Data Value Comp 2 Byte */
+#define DBCR2_DVC2BE_SHIFT	0	/* # of bits to shift DBCR2_DVC2BE */
+
+/*
+ * Are there any active Debug Events represented in the
+ * Debug Control Registers?
+ */
+#define DBCR0_ACTIVE_EVENTS  (DBCR0_ICMP | DBCR0_IAC1 | DBCR0_IAC2 | \
+			      DBCR0_IAC3 | DBCR0_IAC4 | DBCR0_DAC1R | \
+			      DBCR0_DAC1W  | DBCR0_DAC2R | DBCR0_DAC2W)
+#define DBCR1_ACTIVE_EVENTS	0
+
+#define DBCR_ACTIVE_EVENTS(dbcr0, dbcr1)  (((dbcr0) & DBCR0_ACTIVE_EVENTS) || \
+					   ((dbcr1) & DBCR1_ACTIVE_EVENTS))
+#endif /* #elif defined(CONFIG_BOOKE) */
 
 /* Bit definitions related to the TCR. */
 #define TCR_WP(x)	(((x)&0x3)<<30)	/* WDT Period */

-- 
Dave Kleikamp
IBM Linux Technology Center

^ permalink raw reply related

* [PATCH 04/04] powerpc/booke: Add support for advanced debug registers
From: Dave Kleikamp @ 2010-02-08 21:51 UTC (permalink / raw)
  To: linuxppc-dev list
  Cc: Sergio Durigan Junior, David Gibson, Torez Smith,
	Thiago Jung Bauermann
In-Reply-To: <20100208215049.17930.8586.sendpatchset@norville.austin.ibm.com>

powerpc/booke: Add support for advanced debug registers

From: Dave Kleikamp <shaggy@linux.vnet.ibm.com>

Based on patches originally written by Torez Smith.

This patch defines context switch and trap related functionality
for BookE specific Debug Registers. It adds support to ptrace()
for setting and getting BookE related Debug Registers

Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Cc: Torez Smith  <lnxtorez@linux.vnet.ibm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: David Gibson <dwg@au1.ibm.com>
Cc: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: Sergio Durigan Junior <sergiodj@br.ibm.com>
Cc: Thiago Jung Bauermann <bauerman@br.ibm.com>
Cc: linuxppc-dev list <Linuxppc-dev@ozlabs.org>
---

 arch/powerpc/include/asm/system.h |    5 
 arch/powerpc/kernel/process.c     |  110 ++++++++-
 arch/powerpc/kernel/ptrace.c      |  434 ++++++++++++++++++++++++++++++++++---
 arch/powerpc/kernel/signal.c      |    6 -
 arch/powerpc/kernel/signal_32.c   |    8 +
 arch/powerpc/kernel/traps.c       |   91 ++++++--
 6 files changed, 582 insertions(+), 72 deletions(-)


diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h
index bb8e006..736e08c 100644
--- a/arch/powerpc/include/asm/system.h
+++ b/arch/powerpc/include/asm/system.h
@@ -112,8 +112,13 @@ static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
 #endif
 
 extern int set_dabr(unsigned long dabr);
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+extern void do_send_trap(struct pt_regs *regs, unsigned long address,
+			 unsigned long error_code, int signal_code, int brkpt);
+#else
 extern void do_dabr(struct pt_regs *regs, unsigned long address,
 		    unsigned long error_code);
+#endif
 extern void print_backtrace(unsigned long *);
 extern void show_regs(struct pt_regs * regs);
 extern void flush_instruction_cache(void);
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 9be77e3..e4d71ce 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -245,6 +245,24 @@ void discard_lazy_cpu_state(void)
 }
 #endif /* CONFIG_SMP */
 
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+void do_send_trap(struct pt_regs *regs, unsigned long address,
+		  unsigned long error_code, int signal_code, int breakpt)
+{
+	siginfo_t info;
+
+	if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
+			11, SIGSEGV) == NOTIFY_STOP)
+		return;
+
+	/* Deliver the signal to userspace */
+	info.si_signo = SIGTRAP;
+	info.si_errno = breakpt;	/* breakpoint or watchpoint id */
+	info.si_code = signal_code;
+	info.si_addr = (void __user *)address;
+	force_sig_info(SIGTRAP, &info, current);
+}
+#else	/* !CONFIG_PPC_ADV_DEBUG_REGS */
 void do_dabr(struct pt_regs *regs, unsigned long address,
 		    unsigned long error_code)
 {
@@ -257,12 +275,6 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
 	if (debugger_dabr_match(regs))
 		return;
 
-	/* Clear the DAC and struct entries.  One shot trigger */
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
-	mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W
-							| DBCR0_IDM));
-#endif
-
 	/* Clear the DABR */
 	set_dabr(0);
 
@@ -273,9 +285,82 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
 	info.si_addr = (void __user *)address;
 	force_sig_info(SIGTRAP, &info, current);
 }
+#endif	/* CONFIG_PPC_ADV_DEBUG_REGS */
 
 static DEFINE_PER_CPU(unsigned long, current_dabr);
 
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+/*
+ * Set the debug registers back to their default "safe" values.
+ */
+static void set_debug_reg_defaults(struct thread_struct *thread)
+{
+	thread->iac1 = thread->iac2 = 0;
+#if CONFIG_PPC_ADV_DEBUG_IACS > 2
+	thread->iac3 = thread->iac4 = 0;
+#endif
+	thread->dac1 = thread->dac2 = 0;
+#if CONFIG_PPC_ADV_DEBUG_DVCS > 0
+	thread->dvc1 = thread->dvc2 = 0;
+#endif
+	thread->dbcr0 = 0;
+#ifdef CONFIG_BOOKE
+	/*
+	 * Force User/Supervisor bits to b11 (user-only MSR[PR]=1)
+	 */
+	thread->dbcr1 = DBCR1_IAC1US | DBCR1_IAC2US |	\
+			DBCR1_IAC3US | DBCR1_IAC4US;
+	/*
+	 * Force Data Address Compare User/Supervisor bits to be User-only
+	 * (0b11 MSR[PR]=1) and set all other bits in DBCR2 register to be 0.
+	 */
+	thread->dbcr2 = DBCR2_DAC1US | DBCR2_DAC2US;
+#else
+	thread->dbcr1 = 0;
+#endif
+}
+
+static void prime_debug_regs(struct thread_struct *thread)
+{
+	mtspr(SPRN_IAC1, thread->iac1);
+	mtspr(SPRN_IAC2, thread->iac2);
+#if CONFIG_PPC_ADV_DEBUG_IACS > 2
+	mtspr(SPRN_IAC3, thread->iac3);
+	mtspr(SPRN_IAC4, thread->iac4);
+#endif
+	mtspr(SPRN_DAC1, thread->dac1);
+	mtspr(SPRN_DAC2, thread->dac2);
+#if CONFIG_PPC_ADV_DEBUG_DVCS > 0
+	mtspr(SPRN_DVC1, thread->dvc1);
+	mtspr(SPRN_DVC2, thread->dvc2);
+#endif
+	mtspr(SPRN_DBCR0, thread->dbcr0);
+	mtspr(SPRN_DBCR1, thread->dbcr1);
+#ifdef CONFIG_BOOKE
+	mtspr(SPRN_DBCR2, thread->dbcr2);
+#endif
+}
+/*
+ * Unless neither the old or new thread are making use of the
+ * debug registers, set the debug registers from the values
+ * stored in the new thread.
+ */
+static void switch_booke_debug_regs(struct thread_struct *new_thread)
+{
+	if ((current->thread.dbcr0 & DBCR0_IDM)
+		|| (new_thread->dbcr0 & DBCR0_IDM))
+			prime_debug_regs(new_thread);
+}
+#else	/* !CONFIG_PPC_ADV_DEBUG_REGS */
+static void set_debug_reg_defaults(struct thread_struct *thread)
+{
+	if (thread->dabr) {
+		thread->dabr = 0;
+		set_dabr(0);
+	}
+}
+#endif	/* CONFIG_PPC_ADV_DEBUG_REGS */
+
 int set_dabr(unsigned long dabr)
 {
 	__get_cpu_var(current_dabr) = dabr;
@@ -372,9 +457,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
-	/* If new thread DAC (HW breakpoint) is the same then leave it */
-	if (new->thread.dabr)
-		set_dabr(new->thread.dabr);
+	switch_booke_debug_regs(&new->thread);
 #else
 	if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
 		set_dabr(new->thread.dabr);
@@ -556,14 +639,7 @@ void flush_thread(void)
 {
 	discard_lazy_cpu_state();
 
-	if (current->thread.dabr) {
-		current->thread.dabr = 0;
-		set_dabr(0);
-
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
-		current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W);
-#endif
-	}
+	set_debug_reg_defaults(&current->thread);
 }
 
 void
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 8847bd6..d9b0586 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -738,11 +738,22 @@ void user_disable_single_step(struct task_struct *task)
 
 	if (regs != NULL) {
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
-		/* If DAC don't clear DBCRO_IDM or MSR_DE */
-		if (task->thread.dabr)
-			task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT);
-		else {
-			task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM);
+		/*
+		 * The logic to disable single stepping should be as
+		 * simple as turning off the Instruction Complete flag.
+		 * And, after doing so, if all debug flags are off, turn
+		 * off DBCR0(IDM) and MSR(DE) .... Torez
+		 */
+		task->thread.dbcr0 &= ~DBCR0_IC;
+		/*
+		 * Test to see if any of the DBCR_ACTIVE_EVENTS bits are set.
+		 */
+		if (!DBCR_ACTIVE_EVENTS(task->thread.dbcr0,
+					task->thread.dbcr1)) {
+			/*
+			 * All debug events were off.....
+			 */
+			task->thread.dbcr0 &= ~DBCR0_IDM;
 			regs->msr &= ~MSR_DE;
 		}
 #else
@@ -767,7 +778,6 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
 		return -EIO;
 
 #ifndef CONFIG_PPC_ADV_DEBUG_REGS
-
 	/* For processors using DABR (i.e. 970), the bottom 3 bits are flags.
 	 *  It was assumed, on previous implementations, that 3 bits were
 	 *  passed together with the data address, fitting the design of the
@@ -786,20 +796,22 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
 
 	/* Move contents to the DABR register */
 	task->thread.dabr = data;
-
 #else /* CONFIG_PPC_ADV_DEBUG_REGS */
-
 	/* As described above, it was assumed 3 bits were passed with the data
 	 *  address, but we will assume only the mode bits will be passed
 	 *  as to not cause alignment restrictions for DAC-based processors.
 	 */
 
 	/* DAC's hold the whole address without any mode flags */
-	task->thread.dabr = data & ~0x3UL;
-
-	if (task->thread.dabr == 0) {
-		task->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | DBCR0_IDM);
-		task->thread.regs->msr &= ~MSR_DE;
+	task->thread.dac1 = data & ~0x3UL;
+
+	if (task->thread.dac1 == 0) {
+		dbcr_dac(task) &= ~(DBCR_DAC1R | DBCR_DAC1W);
+		if (!DBCR_ACTIVE_EVENTS(task->thread.dbcr0,
+					task->thread.dbcr1)) {
+			task->thread.regs->msr &= ~MSR_DE;
+			task->thread.dbcr0 &= ~DBCR0_IDM;
+		}
 		return 0;
 	}
 
@@ -810,15 +822,15 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
 
 	/* Set the Internal Debugging flag (IDM bit 1) for the DBCR0
 	   register */
-	task->thread.dbcr0 = DBCR0_IDM;
+	task->thread.dbcr0 |= DBCR0_IDM;
 
 	/* Check for write and read flags and set DBCR0
 	   accordingly */
+	dbcr_dac(task) &= ~(DBCR_DAC1R|DBCR_DAC1W);
 	if (data & 0x1UL)
-		task->thread.dbcr0 |= DBSR_DAC1R;
+		dbcr_dac(task) |= DBCR_DAC1R;
 	if (data & 0x2UL)
-		task->thread.dbcr0 |= DBSR_DAC1W;
-
+		dbcr_dac(task) |= DBCR_DAC1W;
 	task->thread.regs->msr |= MSR_DE;
 #endif /* CONFIG_PPC_ADV_DEBUG_REGS */
 	return 0;
@@ -835,11 +847,344 @@ void ptrace_disable(struct task_struct *child)
 	user_disable_single_step(child);
 }
 
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+static long set_intruction_bp(struct task_struct *child,
+			      struct ppc_hw_breakpoint *bp_info)
+{
+	int slot;
+	int slot1_in_use = ((child->thread.dbcr0 & DBCR0_IAC1) != 0);
+	int slot2_in_use = ((child->thread.dbcr0 & DBCR0_IAC2) != 0);
+	int slot3_in_use = ((child->thread.dbcr0 & DBCR0_IAC3) != 0);
+	int slot4_in_use = ((child->thread.dbcr0 & DBCR0_IAC4) != 0);
+
+	if (dbcr_iac_range(child) & DBCR_IAC12MODE)
+		slot2_in_use = 1;
+	if (dbcr_iac_range(child) & DBCR_IAC34MODE)
+		slot4_in_use = 1;
+
+	if (bp_info->addr >= TASK_SIZE)
+		return -EIO;
+
+	if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) {
+
+		/* Make sure range is valid. */
+		if (bp_info->addr2 >= TASK_SIZE)
+			return -EIO;
+
+		/* We need a pair of IAC regsisters */
+		if ((!slot1_in_use) && (!slot2_in_use)) {
+			slot = 1;
+			child->thread.iac1 = bp_info->addr;
+			child->thread.iac2 = bp_info->addr2;
+			child->thread.dbcr0 |= DBCR0_IAC1;
+			if (bp_info->addr_mode ==
+					PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE)
+				dbcr_iac_range(child) |= DBCR_IAC12X;
+			else
+				dbcr_iac_range(child) |= DBCR_IAC12I;
+#if CONFIG_PPC_ADV_DEBUG_IACS > 2
+		} else if ((!slot3_in_use) && (!slot4_in_use)) {
+			slot = 3;
+			child->thread.iac3 = bp_info->addr;
+			child->thread.iac4 = bp_info->addr2;
+			child->thread.dbcr0 |= DBCR0_IAC3;
+			if (bp_info->addr_mode ==
+					PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE)
+				dbcr_iac_range(child) |= DBCR_IAC34X;
+			else
+				dbcr_iac_range(child) |= DBCR_IAC34I;
+#endif
+		} else
+			return -ENOSPC;
+	} else {
+		/* We only need one.  If possible leave a pair free in
+		 * case a range is needed later
+		 */
+		if (!slot1_in_use) {
+			/*
+			 * Don't use iac1 if iac1-iac2 are free and either
+			 * iac3 or iac4 (but not both) are free
+			 */
+			if (slot2_in_use || (slot3_in_use == slot4_in_use)) {
+				slot = 1;
+				child->thread.iac1 = bp_info->addr;
+				child->thread.dbcr0 |= DBCR0_IAC1;
+				goto out;
+			}
+		}
+		if (!slot2_in_use) {
+			slot = 2;
+			child->thread.iac2 = bp_info->addr;
+			child->thread.dbcr0 |= DBCR0_IAC2;
+#if CONFIG_PPC_ADV_DEBUG_IACS > 2
+		} else if (!slot3_in_use) {
+			slot = 3;
+			child->thread.iac3 = bp_info->addr;
+			child->thread.dbcr0 |= DBCR0_IAC3;
+		} else if (!slot4_in_use) {
+			slot = 4;
+			child->thread.iac4 = bp_info->addr;
+			child->thread.dbcr0 |= DBCR0_IAC4;
+#endif
+		} else
+			return -ENOSPC;
+	}
+out:
+	child->thread.dbcr0 |= DBCR0_IDM;
+	child->thread.regs->msr |= MSR_DE;
+
+	return slot;
+}
+
+static int del_instruction_bp(struct task_struct *child, int slot)
+{
+	switch (slot) {
+	case 1:
+		if (child->thread.iac1 == 0)
+			return -ENOENT;
+
+		if (dbcr_iac_range(child) & DBCR_IAC12MODE) {
+			/* address range - clear slots 1 & 2 */
+			child->thread.iac2 = 0;
+			dbcr_iac_range(child) &= ~DBCR_IAC12MODE;
+		}
+		child->thread.iac1 = 0;
+		child->thread.dbcr0 &= ~DBCR0_IAC1;
+		break;
+	case 2:
+		if (child->thread.iac2 == 0)
+			return -ENOENT;
+
+		if (dbcr_iac_range(child) & DBCR_IAC12MODE)
+			/* used in a range */
+			return -EINVAL;
+		child->thread.iac2 = 0;
+		child->thread.dbcr0 &= ~DBCR0_IAC2;
+		break;
+#if CONFIG_PPC_ADV_DEBUG_IACS > 2
+	case 3:
+		if (child->thread.iac3 == 0)
+			return -ENOENT;
+
+		if (dbcr_iac_range(child) & DBCR_IAC34MODE) {
+			/* address range - clear slots 3 & 4 */
+			child->thread.iac4 = 0;
+			dbcr_iac_range(child) &= ~DBCR_IAC34MODE;
+		}
+		child->thread.iac3 = 0;
+		child->thread.dbcr0 &= ~DBCR0_IAC3;
+		break;
+	case 4:
+		if (child->thread.iac4 == 0)
+			return -ENOENT;
+
+		if (dbcr_iac_range(child) & DBCR_IAC34MODE)
+			/* Used in a range */
+			return -EINVAL;
+		child->thread.iac4 = 0;
+		child->thread.dbcr0 &= ~DBCR0_IAC4;
+		break;
+#endif
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int set_dac(struct task_struct *child, struct ppc_hw_breakpoint *bp_info)
+{
+	int byte_enable =
+		(bp_info->condition_mode >> PPC_BREAKPOINT_CONDITION_BE_SHIFT)
+		& 0xf;
+	int condition_mode =
+		bp_info->condition_mode & PPC_BREAKPOINT_CONDITION_MODE;
+	int slot;
+
+	if (byte_enable && (condition_mode == 0))
+		return -EINVAL;
+
+	if (bp_info->addr >= TASK_SIZE)
+		return -EIO;
+
+	if ((dbcr_dac(child) & (DBCR_DAC1R | DBCR_DAC1W)) == 0) {
+		slot = 1;
+		if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
+			dbcr_dac(child) |= DBCR_DAC1R;
+		if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
+			dbcr_dac(child) |= DBCR_DAC1W;
+		child->thread.dac1 = (unsigned long)bp_info->addr;
+#if CONFIG_PPC_ADV_DEBUG_DVCS > 0
+		if (byte_enable) {
+			child->thread.dvc1 =
+				(unsigned long)bp_info->condition_value;
+			child->thread.dbcr2 |=
+				((byte_enable << DBCR2_DVC1BE_SHIFT) |
+				 (condition_mode << DBCR2_DVC1M_SHIFT));
+		}
+#endif
+#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
+	} else if (child->thread.dbcr2 & DBCR2_DAC12MODE) {
+		/* Both dac1 and dac2 are part of a range */
+		return -ENOSPC;
+#endif
+	} else if ((dbcr_dac(child) & (DBCR_DAC2R | DBCR_DAC2W)) == 0) {
+		slot = 2;
+		if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
+			dbcr_dac(child) |= DBCR_DAC2R;
+		if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
+			dbcr_dac(child) |= DBCR_DAC2W;
+		child->thread.dac2 = (unsigned long)bp_info->addr;
+#if CONFIG_PPC_ADV_DEBUG_DVCS > 0
+		if (byte_enable) {
+			child->thread.dvc2 =
+				(unsigned long)bp_info->condition_value;
+			child->thread.dbcr2 |=
+				((byte_enable << DBCR2_DVC2BE_SHIFT) |
+				 (condition_mode << DBCR2_DVC2M_SHIFT));
+		}
+#endif
+	} else
+		return -ENOSPC;
+	child->thread.dbcr0 |= DBCR0_IDM;
+	child->thread.regs->msr |= MSR_DE;
+
+	return slot + 4;
+}
+
+static int del_dac(struct task_struct *child, int slot)
+{
+	if (slot == 1) {
+		if (child->thread.dac1 == 0)
+			return -ENOENT;
+
+		child->thread.dac1 = 0;
+		dbcr_dac(child) &= ~(DBCR_DAC1R | DBCR_DAC1W);
+#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
+		if (child->thread.dbcr2 & DBCR2_DAC12MODE) {
+			child->thread.dac2 = 0;
+			child->thread.dbcr2 &= ~DBCR2_DAC12MODE;
+		}
+		child->thread.dbcr2 &= ~(DBCR2_DVC1M | DBCR2_DVC1BE);
+#endif
+#if CONFIG_PPC_ADV_DEBUG_DVCS > 0
+		child->thread.dvc1 = 0;
+#endif
+	} else if (slot == 2) {
+		if (child->thread.dac1 == 0)
+			return -ENOENT;
+
+#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
+		if (child->thread.dbcr2 & DBCR2_DAC12MODE)
+			/* Part of a range */
+			return -EINVAL;
+		child->thread.dbcr2 &= ~(DBCR2_DVC2M | DBCR2_DVC2BE);
+#endif
+#if CONFIG_PPC_ADV_DEBUG_DVCS > 0
+		child->thread.dvc2 = 0;
+#endif
+		child->thread.dac2 = 0;
+		dbcr_dac(child) &= ~(DBCR_DAC2R | DBCR_DAC2W);
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
+
+#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
+static int set_dac_range(struct task_struct *child,
+			 struct ppc_hw_breakpoint *bp_info)
+{
+	int mode = bp_info->addr_mode & PPC_BREAKPOINT_MODE_MASK;
+
+	/* We don't allow range watchpoints to be used with DVC */
+	if (bp_info->condition_mode)
+		return -EINVAL;
+
+	/*
+	 * Best effort to verify the address range.  The user/supervisor bits
+	 * prevent trapping in kernel space, but let's fail on an obvious bad
+	 * range.  The simple test on the mask is not fool-proof, and any
+	 * exclusive range will spill over into kernel space.
+	 */
+	if (bp_info->addr >= TASK_SIZE)
+		return -EIO;
+	if (mode == PPC_BREAKPOINT_MODE_MASK) {
+		/*
+		 * dac2 is a bitmask.  Don't allow a mask that makes a
+		 * kernel space address from a valid dac1 value
+		 */
+		if (~((unsigned long)bp_info->addr2) >= TASK_SIZE)
+			return -EIO;
+	} else {
+		/*
+		 * For range breakpoints, addr2 must also be a valid address
+		 */
+		if (bp_info->addr2 >= TASK_SIZE)
+			return -EIO;
+	}
+
+	if (child->thread.dbcr0 &
+	    (DBCR0_DAC1R | DBCR0_DAC1W | DBCR0_DAC2R | DBCR0_DAC2W))
+		return -ENOSPC;
+
+	if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
+		child->thread.dbcr0 |= (DBCR0_DAC1R | DBCR0_IDM);
+	if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
+		child->thread.dbcr0 |= (DBCR0_DAC1W | DBCR0_IDM);
+	child->thread.dac1 = bp_info->addr;
+	child->thread.dac2 = bp_info->addr2;
+	if (mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE)
+		child->thread.dbcr2  |= DBCR2_DAC12M;
+	else if (mode == PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE)
+		child->thread.dbcr2  |= DBCR2_DAC12MX;
+	else	/* PPC_BREAKPOINT_MODE_MASK */
+		child->thread.dbcr2  |= DBCR2_DAC12MM;
+	child->thread.regs->msr |= MSR_DE;
+
+	return 5;
+}
+#endif /* CONFIG_PPC_ADV_DEBUG_DAC_RANGE */
+
 static long ppc_set_hwdebug(struct task_struct *child,
 		     struct ppc_hw_breakpoint *bp_info)
 {
+	if (bp_info->version != 1)
+		return -ENOTSUPP;
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+	/*
+	 * Check for invalid flags and combinations
+	 */
+	if ((bp_info->trigger_type == 0) ||
+	    (bp_info->trigger_type & ~(PPC_BREAKPOINT_TRIGGER_EXECUTE |
+				       PPC_BREAKPOINT_TRIGGER_RW)) ||
+	    (bp_info->addr_mode & ~PPC_BREAKPOINT_MODE_MASK) ||
+	    (bp_info->condition_mode &
+	     ~(PPC_BREAKPOINT_CONDITION_MODE |
+	       PPC_BREAKPOINT_CONDITION_BE_ALL)))
+		return -EINVAL;
+#if CONFIG_PPC_ADV_DEBUG_DVCS == 0
+	if (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE)
+		return -EINVAL;
+#endif
+
+	if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_EXECUTE) {
+		if ((bp_info->trigger_type != PPC_BREAKPOINT_TRIGGER_EXECUTE) ||
+		    (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE))
+			return -EINVAL;
+		return set_intruction_bp(child, bp_info);
+	}
+	if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT)
+		return set_dac(child, bp_info);
+
+#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
+	return set_dac_range(child, bp_info);
+#else
+	return -EINVAL;
+#endif
+#else /* !CONFIG_PPC_ADV_DEBUG_DVCS */
 	/*
-	 * We currently support one data breakpoint
+	 * We only support one data breakpoint
 	 */
 	if (((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0) ||
 	    ((bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0) ||
@@ -855,30 +1200,39 @@ static long ppc_set_hwdebug(struct task_struct *child,
 		return -EIO;
 
 	child->thread.dabr = (unsigned long)bp_info->addr;
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
-	child->thread.dbcr0 = DBCR0_IDM;
-	if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
-		child->thread.dbcr0 |= DBSR_DAC1R;
-	if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
-		child->thread.dbcr0 |= DBSR_DAC1W;
-	child->thread.regs->msr |= MSR_DE;
-#endif
+
 	return 1;
+#endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */
 }
 
 static long ppc_del_hwdebug(struct task_struct *child, long addr, long data)
 {
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+	int rc;
+
+	if (data <= 4)
+		rc = del_instruction_bp(child, (int)data);
+	else
+		rc = del_dac(child, (int)data - 4);
+
+	if (!rc) {
+		if (!DBCR_ACTIVE_EVENTS(child->thread.dbcr0,
+					child->thread.dbcr1)) {
+			child->thread.dbcr0 &= ~DBCR0_IDM;
+			child->thread.regs->msr &= ~MSR_DE;
+		}
+	}
+	return rc;
+#else
 	if (data != 1)
 		return -EINVAL;
 	if (child->thread.dabr == 0)
 		return -ENOENT;
 
 	child->thread.dabr = 0;
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
-	child->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | DBCR0_IDM);
-	child->thread.regs->msr &= ~MSR_DE;
-#endif
+
 	return 0;
+#endif
 }
 
 /*
@@ -978,6 +1332,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 		struct ppc_debug_info dbginfo;
 
 		dbginfo.version = 1;
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+		dbginfo.num_instruction_bps = CONFIG_PPC_ADV_DEBUG_IACS;
+		dbginfo.num_data_bps = CONFIG_PPC_ADV_DEBUG_DACS;
+		dbginfo.num_condition_regs = CONFIG_PPC_ADV_DEBUG_DVCS;
+		dbginfo.data_bp_alignment = 4;
+		dbginfo.sizeof_condition = 4;
+		dbginfo.features = PPC_DEBUG_FEATURE_INSN_BP_RANGE |
+				   PPC_DEBUG_FEATURE_INSN_BP_MASK;
+#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
+		dbginfo.features |=
+				   PPC_DEBUG_FEATURE_DATA_BP_RANGE |
+				   PPC_DEBUG_FEATURE_DATA_BP_MASK;
+#endif
+#else /* !CONFIG_PPC_ADV_DEBUG_REGS */
 		dbginfo.num_instruction_bps = 0;
 		dbginfo.num_data_bps = 1;
 		dbginfo.num_condition_regs = 0;
@@ -988,6 +1356,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 #endif
 		dbginfo.sizeof_condition = 0;
 		dbginfo.features = 0;
+#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
 
 		if (!access_ok(VERIFY_WRITE, data,
 			       sizeof(struct ppc_debug_info)))
@@ -1023,8 +1392,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 		/* We only support one DABR and no IABRS at the moment */
 		if (addr > 0)
 			break;
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+		ret = put_user(child->thread.dac1,
+			       (unsigned long __user *)data);
+#else
 		ret = put_user(child->thread.dabr,
 			       (unsigned long __user *)data);
+#endif
 		break;
 	}
 
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index ad7044b..a0afb55 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -140,17 +140,15 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs)
 		return 0;               /* no signals delivered */
 	}
 
+#ifndef CONFIG_PPC_ADV_DEBUG_REGS
         /*
 	 * Reenable the DABR before delivering the signal to
 	 * user space. The DABR will have been cleared if it
 	 * triggered inside the kernel.
 	 */
-	if (current->thread.dabr) {
+	if (current->thread.dabr)
 		set_dabr(current->thread.dabr);
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
-		mtspr(SPRN_DBCR0, current->thread.dbcr0);
 #endif
-	}
 
 	if (is32) {
         	if (ka.sa.sa_flags & SA_SIGINFO)
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index e4883ae..2666101 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -1092,8 +1092,12 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
 				new_msr |= MSR_DE;
 				new_dbcr0 |= (DBCR0_IDM | DBCR0_IC);
 			} else {
-				new_msr &= ~MSR_DE;
-				new_dbcr0 &= ~(DBCR0_IDM | DBCR0_IC);
+				new_dbcr0 &= ~DBCR0_IC;
+				if (!DBCR_ACTIVE_EVENTS(new_dbcr0,
+						current->thread.dbcr1)) {
+					new_msr &= ~MSR_DE;
+					new_dbcr0 &= ~DBCR0_IDM;
+				}
 			}
 #else
 			if (op.dbg_value)
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 3623530..9545db4 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1025,9 +1025,68 @@ void SoftwareEmulation(struct pt_regs *regs)
 #endif /* CONFIG_8xx */
 
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
+static void handle_debug(struct pt_regs *regs, unsigned long debug_status)
+{
+	int changed = 0;
+	/*
+	 * Determine the cause of the debug event, clear the
+	 * event flags and send a trap to the handler. Torez
+	 */
+	if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) {
+		dbcr_dac(current) &= ~(DBCR_DAC1R | DBCR_DAC1W);
+#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
+		current->thread.dbcr2 &= ~DBCR2_DAC12MODE;
+#endif
+		do_send_trap(regs, mfspr(SPRN_DAC1), debug_status, TRAP_HWBKPT,
+			     5);
+		changed |= 0x01;
+	}  else if (debug_status & (DBSR_DAC2R | DBSR_DAC2W)) {
+		dbcr_dac(current) &= ~(DBCR_DAC2R | DBCR_DAC2W);
+		do_send_trap(regs, mfspr(SPRN_DAC2), debug_status, TRAP_HWBKPT,
+			     6);
+		changed |= 0x01;
+	}  else if (debug_status & DBSR_IAC1) {
+		current->thread.dbcr0 &= ~DBCR0_IAC1;
+		dbcr_iac_range(current) &= ~DBCR_IAC12MODE;
+		do_send_trap(regs, mfspr(SPRN_IAC1), debug_status, TRAP_HWBKPT,
+			     1);
+		changed |= 0x01;
+	}  else if (debug_status & DBSR_IAC2) {
+		current->thread.dbcr0 &= ~DBCR0_IAC2;
+		do_send_trap(regs, mfspr(SPRN_IAC2), debug_status, TRAP_HWBKPT,
+			     2);
+		changed |= 0x01;
+	}  else if (debug_status & DBSR_IAC3) {
+		current->thread.dbcr0 &= ~DBCR0_IAC3;
+		dbcr_iac_range(current) &= ~DBCR_IAC34MODE;
+		do_send_trap(regs, mfspr(SPRN_IAC3), debug_status, TRAP_HWBKPT,
+			     3);
+		changed |= 0x01;
+	}  else if (debug_status & DBSR_IAC4) {
+		current->thread.dbcr0 &= ~DBCR0_IAC4;
+		do_send_trap(regs, mfspr(SPRN_IAC4), debug_status, TRAP_HWBKPT,
+			     4);
+		changed |= 0x01;
+	}
+	/*
+	 * At the point this routine was called, the MSR(DE) was turned off.
+	 * Check all other debug flags and see if that bit needs to be turned
+	 * back on or not.
+	 */
+	if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0, current->thread.dbcr1))
+		regs->msr |= MSR_DE;
+	else
+		/* Make sure the IDM flag is off */
+		current->thread.dbcr0 &= ~DBCR0_IDM;
+
+	if (changed & 0x01)
+		mtspr(SPRN_DBCR0, current->thread.dbcr0);
+}
 
 void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
 {
+	current->thread.dbsr = debug_status;
+
 	/* Hack alert: On BookE, Branch Taken stops on the branch itself, while
 	 * on server, it stops on the target of the branch. In order to simulate
 	 * the server behaviour, we thus restart right away with a single step
@@ -1071,27 +1130,21 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
 		if (debugger_sstep(regs))
 			return;
 
-		if (user_mode(regs))
-			current->thread.dbcr0 &= ~(DBCR0_IC);
-
-		_exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
-	} else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) {
-		regs->msr &= ~MSR_DE;
-
 		if (user_mode(regs)) {
-			current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W |
-								DBCR0_IDM);
-		} else {
-			/* Disable DAC interupts */
-			mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R |
-						DBSR_DAC1W | DBCR0_IDM));
-
-			/* Clear the DAC event */
-			mtspr(SPRN_DBSR, (DBSR_DAC1R | DBSR_DAC1W));
+			current->thread.dbcr0 &= ~DBCR0_IC;
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+			if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0,
+					       current->thread.dbcr1))
+				regs->msr |= MSR_DE;
+			else
+				/* Make sure the IDM bit is off */
+				current->thread.dbcr0 &= ~DBCR0_IDM;
+#endif
 		}
-		/* Setup and send the trap to the handler */
-		do_dabr(regs, mfspr(SPRN_DAC1), debug_status);
-	}
+
+		_exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
+	} else
+		handle_debug(regs, debug_status);
 }
 #endif /* CONFIG_PPC_ADV_DEBUG_REGS */
 

-- 
Dave Kleikamp
IBM Linux Technology Center

^ permalink raw reply related

* [PATCH 02/04] powerpc: Extended ptrace interface
From: Dave Kleikamp @ 2010-02-08 21:51 UTC (permalink / raw)
  To: linuxppc-dev list
  Cc: Sergio Durigan Junior, David Gibson, Torez Smith,
	Thiago Jung Bauermann
In-Reply-To: <20100208215049.17930.8586.sendpatchset@norville.austin.ibm.com>

powerpc: Extended ptrace interface

From: Dave Kleikamp <shaggy@linux.vnet.ibm.com>

Based on patches originally written by Torez Smith.

Add a new extended ptrace interface so that user-space has a single
interface for powerpc, without having to know the specific layout
of the debug registers.

Implement:
PPC_PTRACE_GETHWDEBUGINFO
PPC_PTRACE_SETHWDEBUG
PPC_PTRACE_DELHWDEBUG

Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Acked-by: David Gibson <dwg@au1.ibm.com>
Cc: Torez Smith  <lnxtorez@linux.vnet.ibm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: Sergio Durigan Junior <sergiodj@br.ibm.com>
Cc: Thiago Jung Bauermann <bauerman@br.ibm.com>
Cc: linuxppc-dev list <Linuxppc-dev@ozlabs.org>
---

 Documentation/powerpc/ptrace.txt  |  134 +++++++++++++++++++++++++++++++++++++
 arch/powerpc/include/asm/ptrace.h |   77 +++++++++++++++++++++
 arch/powerpc/kernel/ptrace.c      |   90 +++++++++++++++++++++++++
 3 files changed, 301 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/powerpc/ptrace.txt


diff --git a/Documentation/powerpc/ptrace.txt b/Documentation/powerpc/ptrace.txt
new file mode 100644
index 0000000..f4a5499
--- /dev/null
+++ b/Documentation/powerpc/ptrace.txt
@@ -0,0 +1,134 @@
+GDB intends to support the following hardware debug features of BookE
+processors:
+
+4 hardware breakpoints (IAC)
+2 hardware watchpoints (read, write and read-write) (DAC)
+2 value conditions for the hardware watchpoints (DVC)
+
+For that, we need to extend ptrace so that GDB can query and set these
+resources. Since we're extending, we're trying to create an interface
+that's extendable and that covers both BookE and server processors, so
+that GDB doesn't need to special-case each of them. We added the
+following 3 new ptrace requests.
+
+1. PTRACE_PPC_GETHWDEBUGINFO
+
+Query for GDB to discover the hardware debug features. The main info to
+be returned here is the minimum alignment for the hardware watchpoints.
+BookE processors don't have restrictions here, but server processors have
+an 8-byte alignment restriction for hardware watchpoints. We'd like to avoid
+adding special cases to GDB based on what it sees in AUXV.
+
+Since we're at it, we added other useful info that the kernel can return to
+GDB: this query will return the number of hardware breakpoints, hardware
+watchpoints and whether it supports a range of addresses and a condition.
+The query will fill the following structure provided by the requesting process:
+
+struct ppc_debug_info {
+       unit32_t version;
+       unit32_t num_instruction_bps;
+       unit32_t num_data_bps;
+       unit32_t num_condition_regs;
+       unit32_t data_bp_alignment;
+       unit32_t sizeof_condition; /* size of the DVC register */
+       uint64_t features; /* bitmask of the individual flags */
+};
+
+features will have bits indicating whether there is support for:
+
+#define PPC_DEBUG_FEATURE_INSN_BP_RANGE		0x1
+#define PPC_DEBUG_FEATURE_INSN_BP_MASK		0x2
+#define PPC_DEBUG_FEATURE_DATA_BP_RANGE		0x4
+#define PPC_DEBUG_FEATURE_DATA_BP_MASK		0x8
+
+2. PTRACE_SETHWDEBUG
+
+Sets a hardware breakpoint or watchpoint, according to the provided structure:
+
+struct ppc_hw_breakpoint {
+        uint32_t version;
+#define PPC_BREAKPOINT_TRIGGER_EXECUTE  0x1
+#define PPC_BREAKPOINT_TRIGGER_READ     0x2
+#define PPC_BREAKPOINT_TRIGGER_WRITE    0x4
+        uint32_t trigger_type;       /* only some combinations allowed */
+#define PPC_BREAKPOINT_MODE_EXACT               0x0
+#define PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE     0x1
+#define PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE     0x2
+#define PPC_BREAKPOINT_MODE_MASK                0x3
+        uint32_t addr_mode;          /* address match mode */
+
+#define PPC_BREAKPOINT_CONDITION_MODE   0x3
+#define PPC_BREAKPOINT_CONDITION_NONE   0x0
+#define PPC_BREAKPOINT_CONDITION_AND    0x1
+#define PPC_BREAKPOINT_CONDITION_EXACT  0x1	/* different name for the same thing as above */
+#define PPC_BREAKPOINT_CONDITION_OR     0x2
+#define PPC_BREAKPOINT_CONDITION_AND_OR 0x3
+#define PPC_BREAKPOINT_CONDITION_BE_ALL 0x00ff0000	/* byte enable bits */
+#define PPC_BREAKPOINT_CONDITION_BE(n)  (1<<((n)+16))
+        uint32_t condition_mode;     /* break/watchpoint condition flags */
+
+        uint64_t addr;
+        uint64_t addr2;
+        uint64_t condition_value;
+};
+
+A request specifies one event, not necessarily just one register to be set.
+For instance, if the request is for a watchpoint with a condition, both the
+DAC and DVC registers will be set in the same request.
+
+With this GDB can ask for all kinds of hardware breakpoints and watchpoints
+that the BookE supports. COMEFROM breakpoints available in server processors
+are not contemplated, but that is out of the scope of this work.
+
+ptrace will return an integer (handle) uniquely identifying the breakpoint or
+watchpoint just created. This integer will be used in the PTRACE_DELHWDEBUG
+request to ask for its removal. Return -ENOSPC if the requested breakpoint
+can't be allocated on the registers.
+
+Some examples of using the structure to:
+
+- set a breakpoint in the first breakpoint register
+
+  p.version         = PPC_DEBUG_CURRENT_VERSION;
+  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_EXECUTE;
+  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
+  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
+  p.addr            = (uint64_t) address;
+  p.addr2           = 0;
+  p.condition_value = 0;
+
+- set a watchpoint which triggers on reads in the second watchpoint register
+
+  p.version         = PPC_DEBUG_CURRENT_VERSION;
+  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_READ;
+  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
+  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
+  p.addr            = (uint64_t) address;
+  p.addr2           = 0;
+  p.condition_value = 0;
+
+- set a watchpoint which triggers only with a specific value
+
+  p.version         = PPC_DEBUG_CURRENT_VERSION;
+  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_READ;
+  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
+  p.condition_mode  = PPC_BREAKPOINT_CONDITION_AND | PPC_BREAKPOINT_CONDITION_BE_ALL;
+  p.addr            = (uint64_t) address;
+  p.addr2           = 0;
+  p.condition_value = (uint64_t) condition;
+
+- set a ranged hardware breakpoint
+
+  p.version         = PPC_DEBUG_CURRENT_VERSION;
+  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_EXECUTE;
+  p.addr_mode       = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
+  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
+  p.addr            = (uint64_t) begin_range;
+  p.addr2           = (uint64_t) end_range;
+  p.condition_value = 0;
+
+3. PTRACE_DELHWDEBUG
+
+Takes an integer which identifies an existing breakpoint or watchpoint
+(i.e., the value returned from PTRACE_SETHWDEBUG), and deletes the
+corresponding breakpoint or watchpoint..
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index cbd759e..b451081 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -24,6 +24,12 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#endif
+
 #ifndef __ASSEMBLY__
 
 struct pt_regs {
@@ -294,4 +300,75 @@ extern void user_disable_single_step(struct task_struct *);
 
 #define PTRACE_SINGLEBLOCK	0x100	/* resume execution until next branch */
 
+#define PPC_PTRACE_GETHWDBGINFO	0x89
+#define PPC_PTRACE_SETHWDEBUG	0x88
+#define PPC_PTRACE_DELHWDEBUG	0x87
+
+#ifndef __ASSEMBLY__
+
+struct ppc_debug_info {
+	uint32_t version;		/* Only version 1 exists to date */
+	uint32_t num_instruction_bps;
+	uint32_t num_data_bps;
+	uint32_t num_condition_regs;
+	uint32_t data_bp_alignment;
+	uint32_t sizeof_condition;	/* size of the DVC register */
+	uint64_t features;
+};
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * features will have bits indication whether there is support for:
+ */
+#define PPC_DEBUG_FEATURE_INSN_BP_RANGE		0x0000000000000001
+#define PPC_DEBUG_FEATURE_INSN_BP_MASK		0x0000000000000002
+#define PPC_DEBUG_FEATURE_DATA_BP_RANGE		0x0000000000000004
+#define PPC_DEBUG_FEATURE_DATA_BP_MASK		0x0000000000000008
+
+#ifndef __ASSEMBLY__
+
+struct ppc_hw_breakpoint {
+	uint32_t version;		/* currently, version must be 1 */
+	uint32_t trigger_type;		/* only some combinations allowed */
+	uint32_t addr_mode;		/* address match mode */
+	uint32_t condition_mode;	/* break/watchpoint condition flags */
+	uint64_t addr;			/* break/watchpoint address */
+	uint64_t addr2;			/* range end or mask */
+	uint64_t condition_value;	/* contents of the DVC register */
+};
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Trigger Type
+ */
+#define PPC_BREAKPOINT_TRIGGER_EXECUTE	0x00000001
+#define PPC_BREAKPOINT_TRIGGER_READ	0x00000002
+#define PPC_BREAKPOINT_TRIGGER_WRITE	0x00000004
+#define PPC_BREAKPOINT_TRIGGER_RW	\
+	(PPC_BREAKPOINT_TRIGGER_READ | PPC_BREAKPOINT_TRIGGER_WRITE)
+
+/*
+ * Address Mode
+ */
+#define PPC_BREAKPOINT_MODE_EXACT		0x00000000
+#define PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE	0x00000001
+#define PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE	0x00000002
+#define PPC_BREAKPOINT_MODE_MASK		0x00000003
+
+/*
+ * Condition Mode
+ */
+#define PPC_BREAKPOINT_CONDITION_MODE	0x00000003
+#define PPC_BREAKPOINT_CONDITION_NONE	0x00000000
+#define PPC_BREAKPOINT_CONDITION_AND	0x00000001
+#define PPC_BREAKPOINT_CONDITION_EXACT	PPC_BREAKPOINT_CONDITION_AND
+#define PPC_BREAKPOINT_CONDITION_OR	0x00000002
+#define PPC_BREAKPOINT_CONDITION_AND_OR	0x00000003
+#define PPC_BREAKPOINT_CONDITION_BE_ALL	0x00ff0000
+#define PPC_BREAKPOINT_CONDITION_BE_SHIFT	16
+#define PPC_BREAKPOINT_CONDITION_BE(n)	\
+	(1<<((n)+PPC_BREAKPOINT_CONDITION_BE_SHIFT))
+
 #endif /* _ASM_POWERPC_PTRACE_H */
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 292c814..8847bd6 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -835,6 +835,52 @@ void ptrace_disable(struct task_struct *child)
 	user_disable_single_step(child);
 }
 
+static long ppc_set_hwdebug(struct task_struct *child,
+		     struct ppc_hw_breakpoint *bp_info)
+{
+	/*
+	 * We currently support one data breakpoint
+	 */
+	if (((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0) ||
+	    ((bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0) ||
+	    (bp_info->trigger_type != PPC_BREAKPOINT_TRIGGER_WRITE) ||
+	    (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) ||
+	    (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE))
+		return -EINVAL;
+
+	if (child->thread.dabr)
+		return -ENOSPC;
+
+	if ((unsigned long)bp_info->addr >= TASK_SIZE)
+		return -EIO;
+
+	child->thread.dabr = (unsigned long)bp_info->addr;
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+	child->thread.dbcr0 = DBCR0_IDM;
+	if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
+		child->thread.dbcr0 |= DBSR_DAC1R;
+	if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
+		child->thread.dbcr0 |= DBSR_DAC1W;
+	child->thread.regs->msr |= MSR_DE;
+#endif
+	return 1;
+}
+
+static long ppc_del_hwdebug(struct task_struct *child, long addr, long data)
+{
+	if (data != 1)
+		return -EINVAL;
+	if (child->thread.dabr == 0)
+		return -ENOENT;
+
+	child->thread.dabr = 0;
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+	child->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | DBCR0_IDM);
+	child->thread.regs->msr &= ~MSR_DE;
+#endif
+	return 0;
+}
+
 /*
  * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
  * we mark them as obsolete now, they will be removed in a future version
@@ -928,6 +974,50 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 		break;
 	}
 
+	case PPC_PTRACE_GETHWDBGINFO: {
+		struct ppc_debug_info dbginfo;
+
+		dbginfo.version = 1;
+		dbginfo.num_instruction_bps = 0;
+		dbginfo.num_data_bps = 1;
+		dbginfo.num_condition_regs = 0;
+#ifdef CONFIG_PPC64
+		dbginfo.data_bp_alignment = 8;
+#else
+		dbginfo.data_bp_alignment = 4;
+#endif
+		dbginfo.sizeof_condition = 0;
+		dbginfo.features = 0;
+
+		if (!access_ok(VERIFY_WRITE, data,
+			       sizeof(struct ppc_debug_info)))
+			return -EFAULT;
+		ret = __copy_to_user((struct ppc_debug_info __user *)data,
+				     &dbginfo, sizeof(struct ppc_debug_info)) ?
+		      -EFAULT : 0;
+		break;
+	}
+
+	case PPC_PTRACE_SETHWDEBUG: {
+		struct ppc_hw_breakpoint bp_info;
+
+		if (!access_ok(VERIFY_READ, data,
+			       sizeof(struct ppc_hw_breakpoint)))
+			return -EFAULT;
+		ret = __copy_from_user(&bp_info,
+				       (struct ppc_hw_breakpoint __user *)data,
+				       sizeof(struct ppc_hw_breakpoint)) ?
+		      -EFAULT : 0;
+		if (!ret)
+			ret = ppc_set_hwdebug(child, &bp_info);
+		break;
+	}
+
+	case PPC_PTRACE_DELHWDEBUG: {
+		ret = ppc_del_hwdebug(child, addr, data);
+		break;
+	}
+
 	case PTRACE_GET_DEBUGREG: {
 		ret = -EINVAL;
 		/* We only support one DABR and no IABRS at the moment */

-- 
Dave Kleikamp
IBM Linux Technology Center

^ permalink raw reply related

* [PATCH 01/04] powerpc/booke: Introduce new CONFIG options for advanced debug registers
From: Dave Kleikamp @ 2010-02-08 21:50 UTC (permalink / raw)
  To: linuxppc-dev list
  Cc: Sergio Durigan Junior, David Gibson, Torez Smith,
	Thiago Jung Bauermann
In-Reply-To: <20100208215049.17930.8586.sendpatchset@norville.austin.ibm.com>

powerpc/booke: Introduce new CONFIG options for advanced debug registers

From: Dave Kleikamp <shaggy@linux.vnet.ibm.com>

Introduce new config options to simplify the ifdefs pertaining to the
advanced debug registers for booke and 40x processors:

CONFIG_PPC_ADV_DEBUG_REGS - boolean: true for dac-based processors
CONFIG_PPC_ADV_DEBUG_IACS - number of IAC registers
CONFIG_PPC_ADV_DEBUG_DACS - number of DAC registers
CONFIG_PPC_ADV_DEBUG_DVCS - number of DVC registers
CONFIG_PPC_ADV_DEBUG_DAC_RANGE - DAC ranges supported

Beginning conservatively, since I only have the facilities to test 440
hardware.  I believe all 40x and booke platforms support at least 2 IAC
and 2 DAC registers.  For 440, 4 IAC and 2 DVC registers are enabled, as
well as the DAC ranges.

Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
---

 arch/powerpc/Kconfig            |   27 +++++++++++++++++++++++++++
 arch/powerpc/kernel/kgdb.c      |    2 +-
 arch/powerpc/kernel/kprobes.c   |    4 ++--
 arch/powerpc/kernel/process.c   |   10 +++++-----
 arch/powerpc/kernel/ptrace.c    |   18 +++++++-----------
 arch/powerpc/kernel/signal.c    |    2 +-
 arch/powerpc/kernel/signal_32.c |    8 ++++----
 arch/powerpc/kernel/traps.c     |    6 +++---
 8 files changed, 50 insertions(+), 27 deletions(-)


diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ba3948c..32840fb 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -240,6 +240,33 @@ config PPC_OF_PLATFORM_PCI
 config ARCH_SUPPORTS_DEBUG_PAGEALLOC
 	def_bool y
 
+config PPC_ADV_DEBUG_REGS
+	bool
+	depends on 40x || BOOKE
+	default y
+
+config PPC_ADV_DEBUG_IACS
+	int
+	depends on PPC_ADV_DEBUG_REGS
+	default 4 if 44x
+	default 2
+
+config PPC_ADV_DEBUG_DACS
+	int
+	depends on PPC_ADV_DEBUG_REGS
+	default 2
+
+config PPC_ADV_DEBUG_DVCS
+	int
+	depends on PPC_ADV_DEBUG_REGS
+	default 2 if 44x
+	default 0
+
+config PPC_ADV_DEBUG_DAC_RANGE
+	bool
+	depends on PPC_ADV_DEBUG_REGS && 44x
+	default y
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
index b6bd1ea..41bada0 100644
--- a/arch/powerpc/kernel/kgdb.c
+++ b/arch/powerpc/kernel/kgdb.c
@@ -333,7 +333,7 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,
 		atomic_set(&kgdb_cpu_doing_single_step, -1);
 		/* set the trace bit if we're stepping */
 		if (remcom_in_buffer[0] == 's') {
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 			mtspr(SPRN_DBCR0,
 			      mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
 			linux_regs->msr |= MSR_DE;
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index c932978..3fd1af9 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -36,7 +36,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-#ifdef CONFIG_BOOKE
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 #define MSR_SINGLESTEP	(MSR_DE)
 #else
 #define MSR_SINGLESTEP	(MSR_SE)
@@ -110,7 +110,7 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 	 * like Decrementer or External Interrupt */
 	regs->msr &= ~MSR_EE;
 	regs->msr |= MSR_SINGLESTEP;
-#ifdef CONFIG_BOOKE
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 	regs->msr &= ~MSR_CE;
 	mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
 #endif
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 7b816da..9be77e3 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -258,7 +258,7 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
 		return;
 
 	/* Clear the DAC and struct entries.  One shot trigger */
-#if defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 	mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W
 							| DBCR0_IDM));
 #endif
@@ -284,7 +284,7 @@ int set_dabr(unsigned long dabr)
 		return ppc_md.set_dabr(dabr);
 
 	/* XXX should we have a CPU_FTR_HAS_DABR ? */
-#if defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 	mtspr(SPRN_DAC1, dabr);
 #elif defined(CONFIG_PPC_BOOK3S)
 	mtspr(SPRN_DABR, dabr);
@@ -371,7 +371,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
 
 #endif /* CONFIG_SMP */
 
-#if defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 	/* If new thread DAC (HW breakpoint) is the same then leave it */
 	if (new->thread.dabr)
 		set_dabr(new->thread.dabr);
@@ -514,7 +514,7 @@ void show_regs(struct pt_regs * regs)
 	printk("  CR: %08lx  XER: %08lx\n", regs->ccr, regs->xer);
 	trap = TRAP(regs);
 	if (trap == 0x300 || trap == 0x600)
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 		printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr);
 #else
 		printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr);
@@ -560,7 +560,7 @@ void flush_thread(void)
 		current->thread.dabr = 0;
 		set_dabr(0);
 
-#if defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 		current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W);
 #endif
 	}
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index ef14988..292c814 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -46,7 +46,7 @@
 /*
  * Set of msr bits that gdb can change on behalf of a process.
  */
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 #define MSR_DEBUGCHANGE	0
 #else
 #define MSR_DEBUGCHANGE	(MSR_SE | MSR_BE)
@@ -703,7 +703,7 @@ void user_enable_single_step(struct task_struct *task)
 	struct pt_regs *regs = task->thread.regs;
 
 	if (regs != NULL) {
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 		task->thread.dbcr0 &= ~DBCR0_BT;
 		task->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC;
 		regs->msr |= MSR_DE;
@@ -720,7 +720,7 @@ void user_enable_block_step(struct task_struct *task)
 	struct pt_regs *regs = task->thread.regs;
 
 	if (regs != NULL) {
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 		task->thread.dbcr0 &= ~DBCR0_IC;
 		task->thread.dbcr0 = DBCR0_IDM | DBCR0_BT;
 		regs->msr |= MSR_DE;
@@ -737,7 +737,7 @@ void user_disable_single_step(struct task_struct *task)
 	struct pt_regs *regs = task->thread.regs;
 
 	if (regs != NULL) {
-#if defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 		/* If DAC don't clear DBCRO_IDM or MSR_DE */
 		if (task->thread.dabr)
 			task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT);
@@ -745,9 +745,6 @@ void user_disable_single_step(struct task_struct *task)
 			task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM);
 			regs->msr &= ~MSR_DE;
 		}
-#elif defined(CONFIG_40x)
-		task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM);
-		regs->msr &= ~MSR_DE;
 #else
 		regs->msr &= ~(MSR_SE | MSR_BE);
 #endif
@@ -769,7 +766,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
 	if ((data & ~0x7UL) >= TASK_SIZE)
 		return -EIO;
 
-#ifndef CONFIG_BOOKE
+#ifndef CONFIG_PPC_ADV_DEBUG_REGS
 
 	/* For processors using DABR (i.e. 970), the bottom 3 bits are flags.
 	 *  It was assumed, on previous implementations, that 3 bits were
@@ -790,8 +787,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
 	/* Move contents to the DABR register */
 	task->thread.dabr = data;
 
-#endif
-#if defined(CONFIG_BOOKE)
+#else /* CONFIG_PPC_ADV_DEBUG_REGS */
 
 	/* As described above, it was assumed 3 bits were passed with the data
 	 *  address, but we will assume only the mode bits will be passed
@@ -824,7 +820,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
 		task->thread.dbcr0 |= DBSR_DAC1W;
 
 	task->thread.regs->msr |= MSR_DE;
-#endif
+#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
 	return 0;
 }
 
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index 00b5078..ad7044b 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -147,7 +147,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs)
 	 */
 	if (current->thread.dabr) {
 		set_dabr(current->thread.dabr);
-#if defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 		mtspr(SPRN_DBCR0, current->thread.dbcr0);
 #endif
 	}
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index d670429..e4883ae 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -1078,7 +1078,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
 	int i;
 	unsigned char tmp;
 	unsigned long new_msr = regs->msr;
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 	unsigned long new_dbcr0 = current->thread.dbcr0;
 #endif
 
@@ -1087,7 +1087,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
 			return -EFAULT;
 		switch (op.dbg_type) {
 		case SIG_DBG_SINGLE_STEPPING:
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 			if (op.dbg_value) {
 				new_msr |= MSR_DE;
 				new_dbcr0 |= (DBCR0_IDM | DBCR0_IC);
@@ -1103,7 +1103,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
 #endif
 			break;
 		case SIG_DBG_BRANCH_TRACING:
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 			return -EINVAL;
 #else
 			if (op.dbg_value)
@@ -1124,7 +1124,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
 	   failure is a problem, anyway, and it's very unlikely unless
 	   the user is really doing something wrong. */
 	regs->msr = new_msr;
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 	current->thread.dbcr0 = new_dbcr0;
 #endif
 
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index d069ff8..3623530 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -294,7 +294,7 @@ static inline int check_io_access(struct pt_regs *regs)
 	return 0;
 }
 
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 /* On 4xx, the reason for the machine check or program exception
    is in the ESR. */
 #define get_reason(regs)	((regs)->dsisr)
@@ -1024,7 +1024,7 @@ void SoftwareEmulation(struct pt_regs *regs)
 }
 #endif /* CONFIG_8xx */
 
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
 
 void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
 {
@@ -1093,7 +1093,7 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
 		do_dabr(regs, mfspr(SPRN_DAC1), debug_status);
 	}
 }
-#endif /* CONFIG_4xx || CONFIG_BOOKE */
+#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
 
 #if !defined(CONFIG_TAU_INT)
 void TAUException(struct pt_regs *regs)

-- 
Dave Kleikamp
IBM Linux Technology Center

^ permalink raw reply related

* [PATCH 00/04] powerpc/booke: Expose advanced debug registers through extended ptrace interface
From: Dave Kleikamp @ 2010-02-08 21:50 UTC (permalink / raw)
  To: linuxppc-dev list
  Cc: Sergio Durigan Junior, David Gibson, Torez Smith,
	Thiago Jung Bauermann

These patches implement an extention to the ptrace interface proposed by
Thiago Bauermann and the the PowerPC gdb team.

This is a resubmission of the patches I first sent on December 9th, and
later on January 18th.  The biggest change is that I added new config
options to define the debug register support at compile time.  There were
some suggestions to add cpu features to dynamically determine the specifics
of the architecture, but I think compile-time configuration should be
sufficient.

The first patch defines and explains the new config options.

These patches are based on 2.6.33-rc7.

The following has been added as Documentation/powerpc/ptrace.txt:

GDB intends to support the following hardware debug features of BookE
processors:

4 hardware breakpoints (IAC)
2 hardware watchpoints (read, write and read-write) (DAC)
2 value conditions for the hardware watchpoints (DVC)

For that, we need to extend ptrace so that GDB can query and set these
resources. Since we're extending, we're trying to create an interface
that's extendable and that covers both BookE and server processors, so
that GDB doesn't need to special-case each of them. We added the
following 3 new ptrace requests.

1. PTRACE_PPC_GETHWDEBUGINFO

Query for GDB to discover the hardware debug features. The main info to
be returned here is the minimum alignment for the hardware watchpoints.
BookE processors don't have restrictions here, but server processors have
an 8-byte alignment restriction for hardware watchpoints. We'd like to avoid
adding special cases to GDB based on what it sees in AUXV.

Since we're at it, we added other useful info that the kernel can return to
GDB: this query will return the number of hardware breakpoints, hardware
watchpoints and whether it supports a range of addresses and a condition.
The query will fill the following structure provided by the requesting process:

struct ppc_debug_info {
       unit32_t version;
       unit32_t num_instruction_bps;
       unit32_t num_data_bps;
       unit32_t num_condition_regs;
       unit32_t data_bp_alignment;
       unit32_t sizeof_condition; /* size of the DVC register */
       uint64_t features; /* bitmask of the individual flags */
};

features will have bits indicating whether there is support for:

#define PPC_DEBUG_FEATURE_INSN_BP_RANGE		0x1
#define PPC_DEBUG_FEATURE_INSN_BP_MASK		0x2
#define PPC_DEBUG_FEATURE_DATA_BP_RANGE		0x4
#define PPC_DEBUG_FEATURE_DATA_BP_MASK		0x8

2. PTRACE_SETHWDEBUG

Sets a hardware breakpoint or watchpoint, according to the provided structure:

struct ppc_hw_breakpoint {
        uint32_t version;
#define PPC_BREAKPOINT_TRIGGER_EXECUTE  0x1
#define PPC_BREAKPOINT_TRIGGER_READ     0x2
#define PPC_BREAKPOINT_TRIGGER_WRITE    0x4
        uint32_t trigger_type;       /* only some combinations allowed */
#define PPC_BREAKPOINT_MODE_EXACT               0x0
#define PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE     0x1
#define PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE     0x2
#define PPC_BREAKPOINT_MODE_MASK                0x3
        uint32_t addr_mode;          /* address match mode */

#define PPC_BREAKPOINT_CONDITION_MODE   0x3
#define PPC_BREAKPOINT_CONDITION_NONE   0x0
#define PPC_BREAKPOINT_CONDITION_AND    0x1
#define PPC_BREAKPOINT_CONDITION_EXACT  0x1	/* different name for the same thing as above */
#define PPC_BREAKPOINT_CONDITION_OR     0x2
#define PPC_BREAKPOINT_CONDITION_AND_OR 0x3
#define PPC_BREAKPOINT_CONDITION_BE_ALL 0x00ff0000	/* byte enable bits */
#define PPC_BREAKPOINT_CONDITION_BE(n)  (1<<((n)+16))
        uint32_t condition_mode;     /* break/watchpoint condition flags */

        uint64_t addr;
        uint64_t addr2;
        uint64_t condition_value;
};

A request specifies one event, not necessarily just one register to be set.
For instance, if the request is for a watchpoint with a condition, both the
DAC and DVC registers will be set in the same request.

With this GDB can ask for all kinds of hardware breakpoints and watchpoints
that the BookE supports. COMEFROM breakpoints available in server processors
are not contemplated, but that is out of the scope of this work.

ptrace will return an integer (handle) uniquely identifying the breakpoint or
watchpoint just created. This integer will be used in the PTRACE_DELHWDEBUG
request to ask for its removal. Return -ENOSPC if the requested breakpoint
can't be allocated on the registers.

Some examples of using the structure to:

- set a breakpoint in the first breakpoint register

  p.version         = PPC_DEBUG_CURRENT_VERSION;
  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_EXECUTE;
  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
  p.addr            = (uint64_t) address;
  p.addr2           = 0;
  p.condition_value = 0;

- set a watchpoint which triggers on reads in the second watchpoint register

  p.version         = PPC_DEBUG_CURRENT_VERSION;
  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_READ;
  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
  p.addr            = (uint64_t) address;
  p.addr2           = 0;
  p.condition_value = 0;

- set a watchpoint which triggers only with a specific value

  p.version         = PPC_DEBUG_CURRENT_VERSION;
  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_READ;
  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
  p.condition_mode  = PPC_BREAKPOINT_CONDITION_AND | PPC_BREAKPOINT_CONDITION_BE_ALL;
  p.addr            = (uint64_t) address;
  p.addr2           = 0;
  p.condition_value = (uint64_t) condition;

- set a ranged hardware breakpoint

  p.version         = PPC_DEBUG_CURRENT_VERSION;
  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_EXECUTE;
  p.addr_mode       = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
  p.addr            = (uint64_t) begin_range;
  p.addr2           = (uint64_t) end_range;
  p.condition_value = 0;

3. PTRACE_DELHWDEBUG

Takes an integer which identifies an existing breakpoint or watchpoint
(i.e., the value returned from PTRACE_SETHWDEBUG), and deletes the
corresponding breakpoint or watchpoint..

-- 
Dave Kleikamp
IBM Linux Technology Center

^ permalink raw reply

* Re: [PATCH] leds-gpio: Fix default state handling on OF platforms
From: Andrew Morton @ 2010-02-08 21:04 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linuxppc-dev, Trent Piepho, linux-kernel, Richard Purdie
In-Reply-To: <20100205205437.GA4733@oksana.dev.rtsoft.ru>

On Fri, 5 Feb 2010 23:54:37 +0300
Anton Vorontsov <avorontsov@ru.mvista.com> wrote:

> The driver wrongly sets default state for LEDs that don't specify
> default-state property.
> 
> Currently the driver handles default state this way:
> 
> memset(&led, 0, sizeof(led));
> for_each_child_of_node(np, child) {
> 	state = of_get_property(child, "default-state", NULL);
> 	if (state) {
> 		if (!strcmp(state, "keep"))
> 			led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
> 		...
> 	}
> 	ret = create_gpio_led(&led, ...);
> }
> 
> Which means that all LEDs that do not specify default-state will
> inherit the last value of the default-state property, which is wrong.


Does this actually happen in any 2.6.33 driver code?  If so, we might
want to merge this into 2.6.33.  And perhaps earlier kernels.  Or not. 
There's no way for me to tell :(

^ permalink raw reply

* Re: [PATCH 3/4] of/gpio: Implement GPIOLIB notifier hooks
From: Andrew Morton @ 2010-02-08 21:02 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: David Brownell, Dmitry Eremin-Solenikov, linux-kernel,
	linuxppc-dev, Bill Gatliff
In-Reply-To: <20100205203236.GC1475@oksana.dev.rtsoft.ru>

On Fri, 5 Feb 2010 23:32:36 +0300
Anton Vorontsov <avorontsov@ru.mvista.com> wrote:

> This patch implements GPIOLIB notifier hooks, and thus makes device-enabled
> GPIO chips (i.e. the ones that have gpio_chip->dev specified) automatically
> attached to the OpenFirmware subsystem. Which means that now we can handle
> I2C and SPI GPIO chips almost* transparently.
> 
> * "Almost" because some chips still require platform data, and for these
>   chips OF-glue is still needed, though with this support the glue will
>   be much smaller.
> 

We can clean this up a little with the WARN_ON trick:

diff -puN drivers/of/gpio.c~of-gpio-implement-gpiolib-notifier-hooks-fix drivers/of/gpio.c
--- a/drivers/of/gpio.c~of-gpio-implement-gpiolib-notifier-hooks-fix
+++ a/drivers/of/gpio.c
@@ -255,10 +255,8 @@ static int of_gpiochip_register_simple(s
 {
 	struct of_gpio_chip *of_gc;
 
-	if (np->data) {
-		WARN_ON(1);
+	if (WARN_ON(np->data))
 		return -EBUSY;
-	}
 
 	of_gc = kzalloc(sizeof(*of_gc), GFP_KERNEL);
 	if (!of_gc)
@@ -287,10 +285,8 @@ static int of_gpiochip_unregister(struct
 {
 	struct of_gpio_chip *of_gc = np->data;
 
-	if (!of_gc || of_gc->chip != chip) {
-		WARN_ON(1);
+	if (WARN_ON(!of_gc || of_gc->chip != chip))
 		return -EINVAL;
-	}
 
 	np->data = NULL;
 	kfree(of_gc);
_

^ permalink raw reply

* Re: Kexec support for FSL-BookE, take two
From: Sebastian Andrzej Siewior @ 2010-02-08 14:09 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <80DDCCCD-D62C-4A66-AA8B-E0937266AF55@kernel.crashing.org>

* Kumar Gala | 2010-01-15 11:53:13 [-0600]:

>On Jan 15, 2010, at 10:41 AM, Sebastian Andrzej Siewior wrote:
>
>> This is take two :)
>What do you think we need for SMP support? I'm happy to test out on SMP HW (8572)

I've updated a comment in the last patch which was wrong. I've pushed
the updated patch to my git tree at [0]. I can post the whole patch if
you want :)
Do you have any idea when you will be able to take a look at this
series?

[0] http://git.breakpoint.cc/cgi-bin/gitweb.cgi?p=bigeasy/linux.git;a=shortlog;h=refs/heads/kexec_booke

>- k

Sebastian

^ permalink raw reply

* RE: [PATCH] [V2] net: emaclite: adding MDIO and phy lib support
From: John Linn @ 2010-02-08 14:09 UTC (permalink / raw)
  To: John Linn, netdev, linuxppc-dev, jgarzik, grant.likely, jwboyer
  Cc: Sadanand Mutyala, john.williams
In-Reply-To: <1265409646-11882-1-git-send-email-john.linn@xilinx.com>

> -----Original Message-----
> From: John Linn [mailto:john.linn@xilinx.com]
> Sent: Friday, February 05, 2010 3:41 PM
> To: netdev@vger.kernel.org; linuxppc-dev@ozlabs.org;
jgarzik@pobox.com; grant.likely@secretlab.ca;
> jwboyer@linux.vnet.ibm.com
> Cc: john.williams@petalogix.com; John Linn; Sadanand Mutyala
> Subject: [PATCH] [V2] net: emaclite: adding MDIO and phy lib support
> =

> These changes add MDIO and phy lib support to the driver as the
> IP core now supports the MDIO bus.
> =

> The MDIO bus and phy are added as a child to the emaclite in the
device
> tree as illustrated below.
> =

> mdio {
> 	#address-cells =3D <1>;
> 	#size-cells =3D <0>;
> 	compatible =3D "xlnx,emaclite-mdio";
> 	phy0: phy@7 {
> 		reg =3D <7>;
> 	} ;
> }
> =

> Signed-off-by: Sadanand Mutyala <Sadanand.Mutyala@xilinx.com>
> Signed-off-by: John Linn <john.linn@xilinx.com>
> =

> ---
> =

> V2 - updated it for Grant's comments, except I couldn't find any tabs
> converted to white space issue, let's see if V2 has it also
> ---
>  drivers/net/Kconfig           |    1 +
>  drivers/net/xilinx_emaclite.c |  393
++++++++++++++++++++++++++++++++++++-----
>  2 files changed, 351 insertions(+), 43 deletions(-)
> =

> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index dd9a09c..9509a36 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -1939,6 +1939,7 @@ config ATL2
>  config XILINX_EMACLITE
>  	tristate "Xilinx 10/100 Ethernet Lite support"
>  	depends on PPC32 || MICROBLAZE
> +	select PHYLIB
>  	help
>  	  This driver supports the 10/100 Ethernet Lite from Xilinx.
> =

> diff --git a/drivers/net/xilinx_emaclite.c
b/drivers/net/xilinx_emaclite.c
> index 8c777ba..02f18dd 100644
> --- a/drivers/net/xilinx_emaclite.c
> +++ b/drivers/net/xilinx_emaclite.c
> @@ -22,11 +22,17 @@
> =

>  #include <linux/of_device.h>
>  #include <linux/of_platform.h>
> +#include <linux/of_mdio.h>
> +#include <linux/phy.h>
> =


<snip>

> +static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int
reg)
> +{
> +	struct net_local *lp =3D bus->priv;
> +	u32 ctrl_reg;
> +	u32 rc;
> +
> +	mutex_lock(&lp->mdio_mutex);
> +
> +	if (xemaclite_mdio_wait(lp))
> +		return -ETIMEDOUT;


I already see a problem with this patch as when there's a timeout
waiting for the mdio the mutex won't get unlocked.  This is true
anywhere the timeout happens (other places also).

I tested it with normal operation, but don't have a great way to test
the timeout paths.

I'll wait for other comments then spin it again to unlock the mutex when
there's a timeout.

Thanks,
John


This email and any attachments are intended for the sole use of the named r=
ecipient(s) and contain(s) confidential information that may be proprietary=
, privileged or copyrighted under applicable law. If you are not the intend=
ed recipient, do not read, copy, or forward this email message or any attac=
hments. Delete this email message and any attachments immediately.

^ permalink raw reply

* Re: [PATCH] powerpc: Quieten cede latency printk
From: Vaidyanathan Srinivasan @ 2010-02-08 12:56 UTC (permalink / raw)
  To: Balbir Singh; +Cc: linuxppc-dev, Anton Blanchard, Gautham R Shenoy
In-Reply-To: <661de9471002080307p48e0ff69v6318790eaff1c64c@mail.gmail.com>

* Balbir Singh <balbir@linux.vnet.ibm.com> [2010-02-08 16:37:37]:

> On Mon, Feb 8, 2010 at 5:22 AM, Anton Blanchard <anton@samba.org> wrote:
> >
> > The cede latency stuff is relatively new and we don't need to complain about
> > it not working on older firmware.
> >
> > Signed-off-by: Anton Blanchard <anton@samba.org>
> 
> Acked-by: Balbir Singh <balbir@linux.vnet.ibm.com>
> 
> Seems like a reasonable change. CC'ing Vaidy and Gautham to look even
> more closely at the patch.

Hi Anton,

Removing the printk is reasonable.  The failure case is noise in older
firmware while the success case may not be very informative.

Thanks,
Vaidy

^ permalink raw reply

* Re: resurrecting the mvme5100 ppc platform
From: Gabriel Paubert @ 2010-02-08 11:21 UTC (permalink / raw)
  To: Paride Legovini; +Cc: linuxppc-dev
In-Reply-To: <20100204133935.GA9337@ninthfloor.org>

On Thu, Feb 04, 2010 at 01:39:35PM +0000, Paride Legovini wrote:
> Hello,
> I'm just started working on some mvme5100 boards, and so I discovered
> that support for these cards has been dropped with linux-2.6.27 due to
> lack of interest. Here is the relevent post on linuxppc-embedded:
> 
> http://www.mail-archive.com/linuxppc-embedded@ozlabs.org/msg30049.html
> 
> Well, I'd really like to see support for the mvme5100 to be reintegrated
> in the kernel. I'm willing to help on this, but at the moment I don't
> know how much work is to be done, as I don't know how the switch from
> ppc to powerpc changed things.

A lot, these are PreP platforms. I'm using several MVME24xx/26xx/27xx
here (some have been running continously over a decade). They have 
a lot of similarities with MVME5100 if I remember correctly. 

I don't have time right now (especially if I am alone) to write 
support for them, but I am interested in running a more recent
kernel, provided it's not too bloated (some machines only have
16MB of RAM).

	Regards,
	Gabriel

^ permalink raw reply

* Re: [PATCH] powerpc: Quieten cede latency printk
From: Balbir Singh @ 2010-02-08 11:07 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: linuxppc-dev, Gautham R Shenoy
In-Reply-To: <20100207235205.GI32246@kryten>

On Mon, Feb 8, 2010 at 5:22 AM, Anton Blanchard <anton@samba.org> wrote:
>
> The cede latency stuff is relatively new and we don't need to complain about
> it not working on older firmware.
>
> Signed-off-by: Anton Blanchard <anton@samba.org>

Acked-by: Balbir Singh <balbir@linux.vnet.ibm.com>

Seems like a reasonable change. CC'ing Vaidy and Gautham to look even
more closely at the patch.

Balbir

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox