* Re: [PATCH v3] cpm2_pic: Allow correct flow_types for port C interrupts
From: Scott Wood @ 2009-12-10 17:41 UTC (permalink / raw)
To: avorontsov; +Cc: Linuxppc-dev Development, Mark Ware
In-Reply-To: <20091210145808.GA16421@oksana.dev.rtsoft.ru>
Anton Vorontsov wrote:
> On Thu, Dec 10, 2009 at 08:52:01AM -0600, Kumar Gala wrote:
>> On Dec 10, 2009, at 5:14 AM, Mark Ware wrote:
>>
>>> Port C interrupts can be either falling edge, or either edge.
>>> Other external interrupts are either falling edge or active low.
>>> Tested on a custom 8280 based board.
>>>
>>> Signed-off-by: Mark Ware <mware@elphinstone.net>
>>> ---
>>> Changed in v3:
>>> - Cosmetic improvements as suggested by Anton and Scott
>>> - Added tested note to changelog
>>>
>>> arch/powerpc/sysdev/cpm2_pic.c | 28 +++++++++++++++++++++-------
>>> 1 files changed, 21 insertions(+), 7 deletions(-)
>> Scott, Anton do you want to add an Ack to this version?
>
> Acked-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Acked-by: Scott Wood <scottwood@freescale.com>
-Scott
^ permalink raw reply
* Re: [RFC:PATCH 03/03] powerpc: Add support for BookE Debug Reg. traps, exceptions and ptrace
From: Josh Boyer @ 2009-12-10 17:41 UTC (permalink / raw)
To: Dave Kleikamp
Cc: linuxppc-dev list, Sergio Durigan Junior, Torez Smith,
Thiago Jung Bauermann, David Gibson
In-Reply-To: <20091210172711.GV2937@zod.rchland.ibm.com>
On Thu, Dec 10, 2009 at 12:27:11PM -0500, Josh Boyer wrote:
>On Thu, Dec 10, 2009 at 01:57:27PM -0200, Dave Kleikamp wrote:
>>+static void prime_debug_regs(struct thread_struct *thread)
>>+{
>>+ mtspr(SPRN_IAC1, thread->iac1);
>>+ mtspr(SPRN_IAC2, thread->iac2);
>>+ mtspr(SPRN_IAC3, thread->iac3);
>>+ mtspr(SPRN_IAC4, thread->iac4);
>>+ mtspr(SPRN_DAC1, thread->dac1);
>>+ mtspr(SPRN_DAC2, thread->dac2);
>>+ mtspr(SPRN_DVC1, thread->dvc1);
>>+ mtspr(SPRN_DVC2, thread->dvc2);
>>+ mtspr(SPRN_DBCR0, thread->dbcr0);
>>+ mtspr(SPRN_DBCR1, thread->dbcr1);
>>+ mtspr(SPRN_DBCR2, thread->dbcr2);
>
>405 has no DBCR2, so I doubt setting it via mtspr would be good. Does this
>compile for 40x and did you test it at all?
>
>Also, looking at the current kernel it seems SPRN_DBCR2 is only defined for
>CONFIG_PPC_BOOK3E_64 which is also inaccurate.
I mis-read the code on this part. SPRN_DBCR2 gets defined unconditionally,
so Book-E should be fine. Still seems broken on 405 though.
josh
^ permalink raw reply
* [PATCH 3/5] powerpc: Convert BUG() to use unreachable()
From: David Daney @ 2009-12-10 17:28 UTC (permalink / raw)
To: linux-kernel, linux-arch
Cc: David Daney, linuxppc-dev, Paul Mackerras, akpm, torvalds
In-Reply-To: <4B212EEC.3060808@caviumnetworks.com>
Use the new unreachable() macro instead of for(;;);
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <paulus@samba.org>
CC: linuxppc-dev@ozlabs.org
---
arch/powerpc/include/asm/bug.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h
index 64e1fdc..2c15212 100644
--- a/arch/powerpc/include/asm/bug.h
+++ b/arch/powerpc/include/asm/bug.h
@@ -68,7 +68,7 @@
_EMIT_BUG_ENTRY \
: : "i" (__FILE__), "i" (__LINE__), \
"i" (0), "i" (sizeof(struct bug_entry))); \
- for(;;) ; \
+ unreachable(); \
} while (0)
#define BUG_ON(x) do { \
--
1.6.2.5
^ permalink raw reply related
* [PATCH 0/5] More unreachable() conversions.
From: David Daney @ 2009-12-10 17:25 UTC (permalink / raw)
To: Andrew Morton, David Howells, Koichi Yasutake, linux-am33-list,
Kyle McMartin, Helge Deller, linux-parisc, Benjamin Herrenschmidt,
Paul Mackerras, linuxppc-dev, Richard Henderson, Ivan Kokshaysky,
Matt Turner, linux-alpha, Mike Frysinger, uclinux-dist-devel
Cc: linux-arch, Linus Torvalds, Linux Kernel Mailing List
Back in commit 38938c879eb0c39edf85d5164aa0cffe2874304c the new macro
unreachable() was added. We can use it in BUG instead of a variety of
ad hoc endless loops.
This patch set consists of the patches from the original set that were
never Acked-by anyone. Although they are completely untested, they
seem plausible.
I don't plan on pushing these things out any more, so if you
like them please merge them via your architecture trees.
I will reply with the 5 patches.
David Daney (5):
mn10300: Convert BUG() to use unreachable()
parisc: Convert BUG() to use unreachable()
powerpc: Convert BUG() to use unreachable()
alpha: Convert BUG() to use unreachable()
blackfin: Convert BUG() to use unreachable()
arch/alpha/include/asm/bug.h | 3 ++-
arch/blackfin/include/asm/bug.h | 2 +-
arch/mn10300/include/asm/bug.h | 3 ++-
arch/parisc/include/asm/bug.h | 4 ++--
arch/powerpc/include/asm/bug.h | 2 +-
5 files changed, 8 insertions(+), 6 deletions(-)
^ permalink raw reply
* Re: Ping does not work on my MPC8544 board, using linux2.6.23
From: Scott Wood @ 2009-12-10 17:39 UTC (permalink / raw)
To: 林志平; +Cc: linuxppc-dev
In-Reply-To: <8148211e0912100505r46a813dcgc907a79e153ca8e@mail.gmail.com>
林志平 wrote:
> Yes mcp85xx_defconfig does not work, I can see mpc8540ads in the
> menuconfig, but no mpc8544ds.
>
>
> mpc8544ds is supported by CONFIG_MPC85xx_DS.
> CONFIG_MPC85XX_DS does not exist. Only mpc85xx_defconfig in
> arch/powerpc/configs
I'm looking right at it, in arch/powerpc/platforms/85xx/Kconfig in 2.6.31.
mpc85xx_defconfig selects this option.
-Scott
^ permalink raw reply
* Re: [RFC:PATCH 03/03] powerpc: Add support for BookE Debug Reg. traps, exceptions and ptrace
From: Josh Boyer @ 2009-12-10 17:27 UTC (permalink / raw)
To: Dave Kleikamp
Cc: linuxppc-dev list, Sergio Durigan Junior, Torez Smith,
Thiago Jung Bauermann, David Gibson
In-Reply-To: <20091210155727.6697.74672.sendpatchset@norville.austin.ibm.com>
On Thu, Dec 10, 2009 at 01:57:27PM -0200, Dave Kleikamp wrote:
>powerpc: Add support for BookE Debug Reg. traps, exceptions and ptrace
>
>From: Torez Smith <lnxtorez@linux.vnet.ibm.com>
>
>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: Torez Smith <lnxtorez@linux.vnet.ibm.com>
>Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
>Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>Cc: Thiago Jung Bauermann <bauerman@br.ibm.com>
>Cc: Sergio Durigan Junior <sergiodj@br.ibm.com>
>Cc: David Gibson <dwg@au1.ibm.com>
>Cc: linuxppc-dev list <Linuxppc-dev@ozlabs.org>
>---
>
> arch/powerpc/include/asm/system.h | 2
> arch/powerpc/kernel/process.c | 109 ++++++++-
> arch/powerpc/kernel/ptrace.c | 435 ++++++++++++++++++++++++++++++++++---
> arch/powerpc/kernel/signal.c | 6 -
> arch/powerpc/kernel/signal_32.c | 8 +
> arch/powerpc/kernel/traps.c | 86 ++++++-
> 6 files changed, 564 insertions(+), 82 deletions(-)
>
>
>diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h
>index bb8e006..474bf23 100644
>--- a/arch/powerpc/include/asm/system.h
>+++ b/arch/powerpc/include/asm/system.h
>@@ -114,6 +114,8 @@ static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
> extern int set_dabr(unsigned long dabr);
> extern void do_dabr(struct pt_regs *regs, unsigned long address,
> unsigned long error_code);
>+extern void do_send_trap(struct pt_regs *regs, unsigned long address,
>+ unsigned long error_code, int signal_code, int errno);
> 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 c930ac3..a0dbb09 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 */
>
>+void do_send_trap(struct pt_regs *regs, unsigned long address,
>+ unsigned long error_code, int signal_code, int errno)
>+{
>+ 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 = errno;
>+ info.si_code = signal_code;
>+ info.si_addr = (void __user *)address;
>+ force_sig_info(SIGTRAP, &info, current);
>+}
>+
>+#if !(defined(CONFIG_40x) || defined(CONFIG_BOOKE))
> 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 */
>-#if defined(CONFIG_BOOKE)
>- mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W
>- | DBCR0_IDM));
>-#endif
>-
> /* Clear the DABR */
> set_dabr(0);
>
>@@ -273,9 +285,71 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
> info.si_addr = (void __user *)address;
> force_sig_info(SIGTRAP, &info, current);
> }
>+#endif
>
> static DEFINE_PER_CPU(unsigned long, current_dabr);
>
>+#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
>+/*
>+ * Set the debug registers back to their default "safe" values.
>+ */
>+static void set_debug_reg_defaults(struct thread_struct *thread)
>+{
>+ thread->iac1 = thread->iac2 = thread->iac3 = thread->iac4 = 0;
>+ thread->dac1 = thread->dac2 = 0;
>+ thread->dvc1 = thread->dvc2 = 0;
>+ /*
>+ * reset the DBCR0, DBCR1 and DBCR2 registers. All bits with
>+ * the exception of the reserved bits should be cleared out
>+ * and set to 0.
>+ *
>+ * For the DBCR0 register, the reserved bits are bits 17:30.
>+ * Reserved bits for DBCR1 are bits 10:14 and bits 26:30.
>+ * And, bits 10:11 for DBCR2.
>+ */
>+ thread->dbcr0 = DBCR0_BASE_REG_VALUE;
>+ /*
>+ * First clear all "non reserved" bits from DBCR1 then initialize reg
>+ * to force User/Supervisor bits to b11 (user-only MSR[PR]=1) and
>+ * Effective/Real * bits to b10 (trap only if IS==0)
>+ */
>+ thread->dbcr1 = DBCR1_BASE_REG_VALUE;
>+ /*
>+ * 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.
>+ * This sets the Data Address Compare Effective/Real bits to be 0b00
>+ * (Effective, MSR[DS]=don't care).
>+ */
>+ thread->dbcr2 = DBCR2_BASE_REG_VALUE;
>+}
>+
>+static void prime_debug_regs(struct thread_struct *thread)
>+{
>+ mtspr(SPRN_IAC1, thread->iac1);
>+ mtspr(SPRN_IAC2, thread->iac2);
>+ mtspr(SPRN_IAC3, thread->iac3);
>+ mtspr(SPRN_IAC4, thread->iac4);
>+ mtspr(SPRN_DAC1, thread->dac1);
>+ mtspr(SPRN_DAC2, thread->dac2);
>+ mtspr(SPRN_DVC1, thread->dvc1);
>+ mtspr(SPRN_DVC2, thread->dvc2);
>+ mtspr(SPRN_DBCR0, thread->dbcr0);
>+ mtspr(SPRN_DBCR1, thread->dbcr1);
>+ mtspr(SPRN_DBCR2, thread->dbcr2);
405 has no DBCR2, so I doubt setting it via mtspr would be good. Does this
compile for 40x and did you test it at all?
Also, looking at the current kernel it seems SPRN_DBCR2 is only defined for
CONFIG_PPC_BOOK3E_64 which is also inaccurate. I don't see that fixed in any
of the other patches. Are you missing a patch, or was this generated against
and old kernel or something?
>@@ -514,7 +586,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)
>+#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
> printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr);
> #else
> printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr);
This hunk seems unnecessary.
I need to find some time to sit down and look over the rest still. I do have
some questions on how/if this will interact correctly with an older GDB still,
and some of the things I've pointed out make me wonder how much this has all
been tested and on what platforms.
josh
^ permalink raw reply
* Re: [RFC:PATCH 02/03] powerpc: Add definitions for Debug Registers on BookE Platforms
From: Josh Boyer @ 2009-12-10 17:07 UTC (permalink / raw)
To: Dave Kleikamp
Cc: linuxppc-dev list, Sergio Durigan Junior, Torez Smith,
Thiago Jung Bauermann, David Gibson
In-Reply-To: <20091210155721.6697.40863.sendpatchset@norville.austin.ibm.com>
On Thu, Dec 10, 2009 at 01:57:21PM -0200, Dave Kleikamp wrote:
>diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
>index 9eed29e..1393307 100644
>--- a/arch/powerpc/include/asm/processor.h
>+++ b/arch/powerpc/include/asm/processor.h
>@@ -161,9 +161,35 @@ 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 */
>+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
>+ /*
>+ * The following help to manage the use of Debug Control Registers
>+ * om the BookE platforms.
>+ */
>+ unsigned long dbcr0;
> unsigned long dbcr1;
>+ unsigned long dbcr2;
This is wrong for 405. 405 only has dbcr0 and dbcr1. I don't see why you'd
change the #define values to be more explicit and then include things that
don't make sense.
>+ /*
>+ * 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;
>+ unsigned long iac3;
>+ unsigned long iac4;
>+ unsigned long dac1;
>+ unsigned long dac2;
>+ unsigned long dvc1;
>+ unsigned long dvc2;
> #endif
Without digging much, I'm wondering if we could just use a pointer to a debug
register structure here instead of growing struct thread more.
> /* 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..7f8c71f 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 */
>@@ -294,25 +296,68 @@
> #define DBCR0_IC 0x08000000 /* Instruction Completion */
> #define DBCR0_ICMP DBCR0_IC
> #define DBCR0_BT 0x04000000 /* Branch Taken */
>-#define DBCR0_BRT DBCR0_BT
> #define DBCR0_EDE 0x02000000 /* Exception Debug Event */
> #define DBCR0_IRPT DBCR0_EDE
> #define DBCR0_TDE 0x01000000 /* TRAP Debug Event */
>-#define DBCR0_IA1 0x00800000 /* Instr Addr compare 1 enable */
>-#define DBCR0_IAC1 DBCR0_IA1
>-#define DBCR0_IA2 0x00400000 /* Instr Addr compare 2 enable */
>-#define DBCR0_IAC2 DBCR0_IA2
>-#define DBCR0_IA12 0x00200000 /* Instr Addr 1-2 range enable */
>-#define DBCR0_IA12X 0x00100000 /* Instr Addr 1-2 range eXclusive */
>-#define DBCR0_IA3 0x00080000 /* Instr Addr compare 3 enable */
>-#define DBCR0_IAC3 DBCR0_IA3
>-#define DBCR0_IA4 0x00040000 /* Instr Addr compare 4 enable */
>-#define DBCR0_IAC4 DBCR0_IA4
>-#define DBCR0_IA34 0x00020000 /* Instr Addr 3-4 range Enable */
>-#define DBCR0_IA34X 0x00010000 /* Instr Addr 3-4 range eXclusive */
>-#define DBCR0_IA12T 0x00008000 /* Instr Addr 1-2 range Toggle */
>-#define DBCR0_IA34T 0x00004000 /* Instr Addr 3-4 range Toggle */
>+#define DBCR0_IAC1 0x00800000 /* Instr Addr compare 1 enable */
>+#define DBCR0_IAC2 0x00400000 /* Instr Addr compare 2 enable */
>+#define DBCR0_IAC12M 0x00300000 /* Instr Addr 1-2 range enable */
>+#define DBCR0_IAC12M_R 0x00100000 /* Instr Addr 1-2 Reserved state */
>+#define DBCR0_IAC12M_I 0x00200000 /* Instr Addr 1-2 range Inclusive */
>+#define DBCR0_IAC12M_X 0x00300000 /* Instr Addr 1-2 range eXclusive */
>+#define DBCR0_IAC3 0x00080000 /* Instr Addr compare 3 enable */
>+#define DBCR0_IAC4 0x00040000 /* Instr Addr compare 4 enable */
>+#define DBCR0_IAC34 0x00020000 /* Instr Addr 3-4 range Enable */
>+#define DBCR0_IAC34X 0x00010000 /* Instr Addr 3-4 range eXclusive */
>+#define DBCR0_IAC12T 0x00008000 /* Instr Addr 1-2 range Toggle */
>+#define DBCR0_IAC34T 0x00004000 /* Instr Addr 3-4 range Toggle */
A lot of this seems to just be cleanup... would it be possible to factor out
the cleanup parts so that the additions are easier to review?
> #define DBCR0_FT 0x00000001 /* Freeze Timers on debug event */
>+
>+#define DBCR0_USER_DEBUG (DBCR0_IDM | DBCR0_ICMP | DBCR0_IAC1 | \
>+ DBCR0_IAC2 | DBCR0_IAC3 | DBCR0_IAC4)
>+#define DBCR0_BASE_REG_VALUE 0
>+
>+#define dbcr_iac_range(task) ((task)->thread.dbcr0)
>+#define DBCR_IAC12M DBCR0_IAC12M
>+#define DBCR_IAC12M_I DBCR0_IAC12M_I
>+#define DBCR_IAC12M_X DBCR0_IAC12M_X
>+#define DBCR_IAC34M DBCR0_IAC34M
>+#define DBCR_IAC34M_I DBCR0_IAC34M_I
>+#define DBCR_IAC34M_X DBCR0_IAC34M_X
>+
>+/* Bit definitions related to the DBCR1. */
>+#define DBCR1_D1R 0x80000000 /* DAC1 Read Debug Event */
>+#define DBCR1_DAC1R DBCR1_D1R
>+#define DBCR1_D2R 0x40000000 /* DAC2 Read Debug Event */
>+#define DBCR1_DAC2R DBCR1_D2R
>+#define DBCR1_D1W 0x20000000 /* DAC1 Write Debug Event */
>+#define DBCR1_DAC1W DBCR1_D1W
>+#define DBCR1_D2W 0x10000000 /* DAC2 Write Debug Event */
>+#define DBCR1_DAC2W DBCR1_D2W
>+
>+#define DBCR1_USER_DEBUG (DBCR1_DAC1R | DBCR1_DAC2R | DBCR1_DAC1W | \
>+ DBCR1_DAC2W)
>+#define DBCR1_BASE_REG_VALUE 0
>+
>+#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
>+
>+#define DBCR2_USER_DEBUG 0
>+#define DBCR2_BASE_REG_VALUE 0
Why are these defined for 405?
>+/*
>+ * 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_D1R | DBCR1_D2R | DBCR1_D1W | DBCR1_D2W)
>+#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 */
>@@ -324,8 +369,7 @@
> #define DBCR0_RST_NONE 0x00000000 /* No Reset */
> #define DBCR0_ICMP 0x08000000 /* Instruction Completion */
> #define DBCR0_IC DBCR0_ICMP
>-#define DBCR0_BRT 0x04000000 /* Branch Taken */
>-#define DBCR0_BT DBCR0_BRT
>+#define DBCR0_BT 0x04000000 /* Branch Taken */
This seems like just cleanup of DBCR0_BRT?
> #define DBCR0_IRPT 0x02000000 /* Exception Debug Event */
> #define DBCR0_TDE 0x01000000 /* TRAP Debug Event */
> #define DBCR0_TIE DBCR0_TDE
>@@ -342,19 +386,99 @@
> #define DBCR0_CRET 0x00000020 /* Critical Return Debug Event */
> #define DBCR0_FT 0x00000001 /* Freeze Timers on debug event */
>
>+#define DBCR0_USER_DEBUG (DBCR0_IDM | DBCR0_ICMP | DBCR0_IAC1 | \
>+ DBCR0_IAC2 | DBCR0_IAC3 | DBCR0_IAC4 | \
>+ DBCR0_DAC1R | DBCR0_DAC1W | DBCR0_DAC2R | \
>+ DBCR0_DAC2W)
>+#define DBCR0_BASE_REG_VALUE 0
>+
>+#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. */
I'll try to review these a bit later. Changing #defines makes for hard patch
review :)
josh
^ permalink raw reply
* Re: [PATCH] [SCSI] mpt fusion: Fix 32 bit platforms with 64 bit resources.
From: Anatolij Gustschin @ 2009-12-10 16:36 UTC (permalink / raw)
To: James Bottomley; +Cc: linuxppc-dev, Eric.Moore, Pravin Bathija, linux-scsi
In-Reply-To: <1260459818.2457.77.camel@mulgrave.site>
On Thu, 10 Dec 2009 09:43:38 -0600
James Bottomley <James.Bottomley@suse.de> wrote:
> On Wed, 2009-12-02 at 17:51 -0800, Pravin Bathija wrote:
> > Powerpc 44x uses 36 bit real address while the real address defined
> > in MPT Fusion driver is of type 32 bit. This causes ioremap to fail and driver
> > fails to initialize. This fix changes the data types representing the real
> > address from unsigned long 32-bit types to resource_size_t which is 64-bit. The
> > driver has been tested, the disks get discovered correctly and can do IO.
> >
> > Signed-off-by: Pravin Bathija <pbathija@amcc.com>
> > Acked-by: Feng Kan <fkan@amcc.com>
> > Acked-by: Fushen Chen <fchen@amcc.com>
> > Acked-by: Loc Ho <lho@amcc.com>
> > Acked-by: Tirumala Reddy Marri <tmarri@amcc.com>
> > Acked-by: Victor Gallardo <vgallardo@amcc.com>
> > ---
> > drivers/message/fusion/mptbase.c | 2 +-
> > 1 files changed, 1 insertions(+), 1 deletions(-)
> >
> > diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
> > index 5d496a9..9f14a60 100644
> > --- a/drivers/message/fusion/mptbase.c
> > +++ b/drivers/message/fusion/mptbase.c
> > @@ -1511,7 +1511,7 @@ mpt_mapresources(MPT_ADAPTER *ioc)
> > {
> > u8 __iomem *mem;
> > int ii;
> > - unsigned long mem_phys;
> > + resource_size_t mem_phys;
>
> You never actually compiled this, did you?
>
> drivers/message/fusion/mptbase.c: In function 'mpt_mapresources':
> drivers/message/fusion/mptbase.c:1680: warning: format '%lx' expects type 'long unsigned int', but argument 4 has type 'resource_size_t'
>
> I'll just fold the fix in
another patch (inlined below) should probably also go in as 'mem_phys' is
assigned to ioc->mem_phys which is 'u32'. ioc->mem_phys is never used in
the driver, however.
Some time ago I posted a patch which enables using second LSI SAS HBA on
PPC440SPe based katmai board again:
http://thread.gmane.org/gmane.linux.scsi/54839
Could someone comment on this patch, please. Thanks!
Anatolij
---
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 8dd4d21..8dc58e3 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -605,7 +605,7 @@ typedef struct _MPT_ADAPTER
SYSIF_REGS __iomem *chip; /* == c8817000 (mmap) */
SYSIF_REGS __iomem *pio_chip; /* Programmed IO (downloadboot) */
u8 bus_type;
- u32 mem_phys; /* == f4020000 (mmap) */
+ resource_size_t mem_phys; /* == f4020000 (mmap) */
u32 pio_mem_phys; /* Programmed IO (downloadboot) */
int mem_size; /* mmap memory size */
int number_of_buses;
^ permalink raw reply related
* [RFC:PATCH 03/03] powerpc: Add support for BookE Debug Reg. traps, exceptions and ptrace
From: Dave Kleikamp @ 2009-12-10 15:57 UTC (permalink / raw)
To: linuxppc-dev list
Cc: Sergio Durigan Junior, Thiago Jung Bauermann, Torez Smith,
David Gibson
In-Reply-To: <20091210155709.6697.4635.sendpatchset@norville.austin.ibm.com>
powerpc: Add support for BookE Debug Reg. traps, exceptions and ptrace
From: Torez Smith <lnxtorez@linux.vnet.ibm.com>
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: Torez Smith <lnxtorez@linux.vnet.ibm.com>
Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Thiago Jung Bauermann <bauerman@br.ibm.com>
Cc: Sergio Durigan Junior <sergiodj@br.ibm.com>
Cc: David Gibson <dwg@au1.ibm.com>
Cc: linuxppc-dev list <Linuxppc-dev@ozlabs.org>
---
arch/powerpc/include/asm/system.h | 2
arch/powerpc/kernel/process.c | 109 ++++++++-
arch/powerpc/kernel/ptrace.c | 435 ++++++++++++++++++++++++++++++++++---
arch/powerpc/kernel/signal.c | 6 -
arch/powerpc/kernel/signal_32.c | 8 +
arch/powerpc/kernel/traps.c | 86 ++++++-
6 files changed, 564 insertions(+), 82 deletions(-)
diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h
index bb8e006..474bf23 100644
--- a/arch/powerpc/include/asm/system.h
+++ b/arch/powerpc/include/asm/system.h
@@ -114,6 +114,8 @@ static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
extern int set_dabr(unsigned long dabr);
extern void do_dabr(struct pt_regs *regs, unsigned long address,
unsigned long error_code);
+extern void do_send_trap(struct pt_regs *regs, unsigned long address,
+ unsigned long error_code, int signal_code, int errno);
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 c930ac3..a0dbb09 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 */
+void do_send_trap(struct pt_regs *regs, unsigned long address,
+ unsigned long error_code, int signal_code, int errno)
+{
+ 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 = errno;
+ info.si_code = signal_code;
+ info.si_addr = (void __user *)address;
+ force_sig_info(SIGTRAP, &info, current);
+}
+
+#if !(defined(CONFIG_40x) || defined(CONFIG_BOOKE))
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 */
-#if defined(CONFIG_BOOKE)
- mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W
- | DBCR0_IDM));
-#endif
-
/* Clear the DABR */
set_dabr(0);
@@ -273,9 +285,71 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
info.si_addr = (void __user *)address;
force_sig_info(SIGTRAP, &info, current);
}
+#endif
static DEFINE_PER_CPU(unsigned long, current_dabr);
+#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
+/*
+ * Set the debug registers back to their default "safe" values.
+ */
+static void set_debug_reg_defaults(struct thread_struct *thread)
+{
+ thread->iac1 = thread->iac2 = thread->iac3 = thread->iac4 = 0;
+ thread->dac1 = thread->dac2 = 0;
+ thread->dvc1 = thread->dvc2 = 0;
+ /*
+ * reset the DBCR0, DBCR1 and DBCR2 registers. All bits with
+ * the exception of the reserved bits should be cleared out
+ * and set to 0.
+ *
+ * For the DBCR0 register, the reserved bits are bits 17:30.
+ * Reserved bits for DBCR1 are bits 10:14 and bits 26:30.
+ * And, bits 10:11 for DBCR2.
+ */
+ thread->dbcr0 = DBCR0_BASE_REG_VALUE;
+ /*
+ * First clear all "non reserved" bits from DBCR1 then initialize reg
+ * to force User/Supervisor bits to b11 (user-only MSR[PR]=1) and
+ * Effective/Real * bits to b10 (trap only if IS==0)
+ */
+ thread->dbcr1 = DBCR1_BASE_REG_VALUE;
+ /*
+ * 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.
+ * This sets the Data Address Compare Effective/Real bits to be 0b00
+ * (Effective, MSR[DS]=don't care).
+ */
+ thread->dbcr2 = DBCR2_BASE_REG_VALUE;
+}
+
+static void prime_debug_regs(struct thread_struct *thread)
+{
+ mtspr(SPRN_IAC1, thread->iac1);
+ mtspr(SPRN_IAC2, thread->iac2);
+ mtspr(SPRN_IAC3, thread->iac3);
+ mtspr(SPRN_IAC4, thread->iac4);
+ mtspr(SPRN_DAC1, thread->dac1);
+ mtspr(SPRN_DAC2, thread->dac2);
+ mtspr(SPRN_DVC1, thread->dvc1);
+ mtspr(SPRN_DVC2, thread->dvc2);
+ mtspr(SPRN_DBCR0, thread->dbcr0);
+ mtspr(SPRN_DBCR1, thread->dbcr1);
+ mtspr(SPRN_DBCR2, thread->dbcr2);
+}
+/*
+ * 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);
+}
+#endif
+
int set_dabr(unsigned long dabr)
{
__get_cpu_var(current_dabr) = dabr;
@@ -284,7 +358,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)
+#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
mtspr(SPRN_DAC1, dabr);
#elif defined(CONFIG_PPC_BOOK3S)
mtspr(SPRN_DABR, dabr);
@@ -371,10 +445,8 @@ struct task_struct *__switch_to(struct task_struct *prev,
#endif /* CONFIG_SMP */
-#if defined(CONFIG_BOOKE)
- /* If new thread DAC (HW breakpoint) is the same then leave it */
- if (new->thread.dabr)
- set_dabr(new->thread.dabr);
+#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
+ switch_booke_debug_regs(&new->thread);
#else
if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
set_dabr(new->thread.dabr);
@@ -514,7 +586,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)
+#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr);
#else
printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr);
@@ -568,14 +640,19 @@ void flush_thread(void)
discard_lazy_cpu_state();
+#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
+ /*
+ * flush_thread() is called on exec() to reset the
+ * thread's status. Set all debug regs back to their
+ * default values....Torez
+ */
+ set_debug_reg_defaults(¤t->thread);
+#else
if (current->thread.dabr) {
current->thread.dabr = 0;
set_dabr(0);
-
-#if defined(CONFIG_BOOKE)
- current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W);
-#endif
}
+#endif
}
void
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 6be2ce0..6710a69 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -737,17 +737,25 @@ void user_disable_single_step(struct task_struct *task)
struct pt_regs *regs = task->thread.regs;
if (regs != NULL) {
-#if defined(CONFIG_BOOKE)
- /* 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);
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ /*
+ * 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;
}
-#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,8 +777,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
if ((data & ~0x7UL) >= TASK_SIZE)
return -EIO;
-#ifndef CONFIG_BOOKE
-
+#if !(defined(CONFIG_40x) || defined(CONFIG_BOOKE))
/* 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
@@ -789,21 +796,22 @@ 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
/* 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;
}
@@ -814,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
return 0;
@@ -839,11 +847,324 @@ void ptrace_disable(struct task_struct *child)
user_disable_single_step(child);
}
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+static long set_intruction_bp(struct task_struct *child,
+ struct ppc_hw_breakpoint *bp_info)
+{
+ int slots_needed;
+ int slot;
+ int free_slot = 0;
+
+ /*
+ * Find an avalailable slot for the breakpoint.
+ * If possible, reserve consecutive slots, 1 & 2, for a range
+ * breakpoint. (Can this be done simpler?)
+ */
+ if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT)
+ slots_needed = 1;
+ else
+ slots_needed = 2;
+
+ if ((child->thread.dbcr0 & DBCR0_IAC1) == 0) {
+ if (slots_needed == 1) {
+ if (child->thread.dbcr0 & DBCR0_IAC2) {
+ slot = 1;
+ goto found;
+ }
+ /* Try to save slots 1 & 2 for range */
+ free_slot = 1;
+ } else
+ if ((child->thread.dbcr0 & DBCR0_IAC2) == 0) {
+ slot = 1;
+ goto found;
+ }
+ } else if ((slots_needed == 1) &&
+ ((child->thread.dbcr0 & DBCR0_IAC2) == 0)) {
+ slot = 2;
+ goto found;
+ }
+ if ((child->thread.dbcr0 & DBCR0_IAC3) == 0) {
+ if (slots_needed == 1) {
+ slot = 3;
+ goto found;
+ }
+ if ((child->thread.dbcr0 & DBCR0_IAC4) == 0) {
+ slot = 3;
+ goto found;
+ }
+ return -ENOSPC;
+ } else if (slots_needed == 2)
+ return -ENOSPC;
+ if ((child->thread.dbcr0 & DBCR0_IAC4) == 0) {
+ slot = 4;
+ } else if (free_slot)
+ slot = free_slot;
+ else
+ return -ENOSPC;
+found:
+ if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT) {
+ switch (slot) {
+ case 1:
+ child->thread.iac1 = bp_info->addr;
+ child->thread.dbcr0 |= DBCR0_IAC1;
+ break;
+ case 2:
+ child->thread.iac2 = bp_info->addr;
+ child->thread.dbcr0 |= DBCR0_IAC2;
+ break;
+ case 3:
+ child->thread.iac3 = bp_info->addr;
+ child->thread.dbcr0 |= DBCR0_IAC3;
+ break;
+ case 4:
+ child->thread.iac4 = bp_info->addr;
+ child->thread.dbcr0 |= DBCR0_IAC4;
+ break;
+ }
+ } else if (slot == 1) {
+ child->thread.iac1 = bp_info->addr;
+ child->thread.iac2 = bp_info->addr2;
+ child->thread.dbcr0 |= (DBCR0_IAC1 | DBCR0_IAC2);
+ if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE)
+ dbcr_iac_range(child) |= DBCR_IAC12M_X;
+ else
+ dbcr_iac_range(child) |= DBCR_IAC12M_I;
+ } else { /* slot == 3 */
+ child->thread.iac3 = bp_info->addr;
+ child->thread.iac4 = bp_info->addr2;
+ child->thread.dbcr0 |= (DBCR0_IAC3 | DBCR0_IAC4);
+ if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE)
+ dbcr_iac_range(child) |= DBCR_IAC34M_X;
+ else
+ dbcr_iac_range(child) |= DBCR_IAC34M_I;
+ }
+ 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 (dbcr_iac_range(child) & DBCR_IAC12M) {
+ /* address range - clear slots 1 & 2 */
+ child->thread.iac2 = 0;
+ child->thread.dbcr0 &= ~DBCR0_IAC2;
+ dbcr_iac_range(child) &= ~DBCR_IAC12M;
+ }
+ child->thread.iac1 = 0;
+ child->thread.dbcr0 &= ~DBCR0_IAC1;
+ break;
+ case 2:
+ if (dbcr_iac_range(child) & DBCR_IAC12M)
+ /* used in a range */
+ return -EINVAL;
+ child->thread.iac2 = 0;
+ child->thread.dbcr0 &= ~DBCR0_IAC2;
+ break;
+ case 3:
+ if (dbcr_iac_range(child) & DBCR_IAC34M) {
+ /* address range - clear slots 3 & 4 */
+ child->thread.iac4 = 0;
+ child->thread.dbcr0 &= ~DBCR0_IAC4;
+ dbcr_iac_range(child) &= ~DBCR_IAC34M;
+ }
+ child->thread.iac3 = 0;
+ child->thread.dbcr0 &= ~DBCR0_IAC3;
+ break;
+ case 4:
+ if (dbcr_iac_range(child) & DBCR_IAC34M)
+ /* Used in a range */
+ return -EINVAL;
+ child->thread.iac4 = 0;
+ child->thread.dbcr0 &= ~DBCR0_IAC4;
+ break;
+ 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_AND_OR;
+ 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) {
+ 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;
+#ifdef CONFIG_BOOKE
+ 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
+ slot = 1;
+ } else if ((dbcr_dac(child) & (DBCR_DAC2R | DBCR_DAC2W)) == 0) {
+ 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;
+#ifdef CONFIG_BOOKE
+ 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
+ slot = 2;
+ } 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) {
+#ifdef CONFIG_BOOKE
+ if (child->thread.dbcr2 & DBCR2_DAC12MODE) {
+ child->thread.dac1 = 0;
+ child->thread.dac2 = 0;
+ child->thread.dbcr0 &= ~(DBCR0_DAC1R | DBCR0_DAC1W |
+ DBCR0_DAC2R | DBCR0_DAC2W);
+ child->thread.dbcr2 &= ~DBCR2_DAC12MODE;
+ return 0;
+ }
+ child->thread.dbcr2 &= ~(DBCR2_DVC1M | DBCR2_DVC1BE);
+ child->thread.dvc1 = 0;
+#endif
+ child->thread.dac1 = 0;
+ dbcr_dac(child) &= ~(DBCR_DAC1R | DBCR_DAC1W);
+ } else if (slot == 2) {
+#ifdef CONFIG_BOOKE
+ if (child->thread.dbcr2 & DBCR2_DAC12MODE)
+ /* Part of a range */
+ return -EINVAL;
+ child->thread.dbcr2 &= ~(DBCR2_DVC2M | DBCR2_DVC2BE);
+ child->thread.dvc2 = 0;
+#endif
+ child->thread.dac2 = 0;
+ dbcr_dac(child) &= ~(DBCR_DAC2R | DBCR_DAC2W);
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+#endif /* CONFIG_40x || CONFIG_BOOKE */
+
+#ifdef CONFIG_BOOKE
+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 && PPC_BREAKPOINT_CONDITION_BE_ALL)
+ return -EINVAL;
+
+ if (bp_info->addr >= 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_DAC2R | DBCR0_IDM);
+ if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
+ child->thread.dbcr0 |= (DBCR0_DAC1W | DBCR0_DAC2W | 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_DAC12R;
+ else if (mode == PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE)
+ child->thread.dbcr2 |= DBCR2_DAC12RX;
+ else /* PPC_BREAKPOINT_MODE_MASK */
+ child->thread.dbcr2 |= DBCR2_DAC12MASK;
+ child->thread.regs->msr |= MSR_DE;
+
+ return 5;
+}
+#endif /* CONFIG_BOOKE */
+
static long ppc_set_hwdebug(struct task_struct *child,
struct ppc_hw_breakpoint *bp_info)
{
+ if (bp_info->version != 1)
+ return -ENOTSUPP;
+
+#ifdef CONFIG_BOOKE
+ /*
+ * 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_AND_OR |
+ PPC_BREAKPOINT_CONDITION_BE_ALL)))
+ return -EINVAL;
+
+ if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_EXECUTE) {
+ if (bp_info->trigger_type != PPC_BREAKPOINT_TRIGGER_EXECUTE)
+ /* At least another bit was set */
+ return -EINVAL;
+ return set_intruction_bp(child, bp_info);
+ }
+
+ if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT)
+ return set_dac(child, bp_info);
+
+ return set_dac_range(child, bp_info);
+#elif defined(CONFIG_40x)
+ /*
+ * 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_NONE))
+ return -EINVAL;
+
+ if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_EXECUTE) {
+ if (bp_info->trigger_type != PPC_BREAKPOINT_TRIGGER_EXECUTE)
+ /* At least another bit was set */
+ return -EINVAL;
+ return set_intruction_bp(child, bp_info);
+ }
+ if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT)
+ return -EINVAL;
+
+ return set_dac(child, bp_info);
+#else
/*
- * 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) ||
@@ -859,28 +1180,35 @@ static long ppc_set_hwdebug(struct task_struct *child,
return -EIO;
child->thread.dabr = (unsigned long)bp_info->addr;
-#ifdef CONFIG_BOOKE
- 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
}
static long ppc_del_hwdebug(struct task_struct *child, long addr, long data)
{
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ 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) || (child->thread.dabr == 0))
return -EINVAL;
child->thread.dabr = 0;
-#ifdef CONFIG_BOOKE
- child->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | DBCR0_IDM);
- child->thread.regs->msr &= ~MSR_DE;
-#endif
return 0;
+#endif
}
/*
@@ -980,16 +1308,36 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
struct ppc_debug_info dbginfo;
dbginfo.version = 1;
+#ifdef CONFIG_BOOKE
+ dbginfo.num_instruction_bps = 4;
+ dbginfo.num_data_bps = 2;
+ dbginfo.num_condition_regs = 2;
+ dbginfo.data_bp_alignment = 0;
+ dbginfo.sizeof_condition = 4;
+ dbginfo.features = PPC_DEBUG_FEATURE_INSN_BP_RANGE |
+ PPC_DEBUG_FEATURE_INSN_BP_MASK |
+ PPC_DEBUG_FEATURE_DATA_BP_RANGE |
+ PPC_DEBUG_FEATURE_DATA_BP_MASK;
+#elif defined(CONFIG_40x)
+ /*
+ * I don't know how the DVCs work on 40x, I'm not going
+ * to support it now. -- Shaggy
+ */
+ dbginfo.num_instruction_bps = 4;
+ dbginfo.num_data_bps = 2;
+ dbginfo.num_condition_regs = 0;
+ dbginfo.data_bp_alignment = 0;
+ dbginfo.sizeof_condition = 0;
+ dbginfo.features = PPC_DEBUG_FEATURE_INSN_BP_RANGE |
+ PPC_DEBUG_FEATURE_INSN_BP_MASK;
+#else
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 = 0;
-#endif
dbginfo.sizeof_condition = 0;
dbginfo.features = 0;
+#endif
if (!access_ok(VERIFY_WRITE, data,
sizeof(struct ppc_debug_info)))
@@ -1025,8 +1373,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;
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ 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 00b5078..94df779 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 */
}
+#if !(defined(CONFIG_BOOKE) || defined(CONFIG_40x))
/*
* 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);
-#if defined(CONFIG_BOOKE)
- 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 d670429..6cc6e81 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 a81c743..d919571 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1016,9 +1016,63 @@ void SoftwareEmulation(struct pt_regs *regs)
#endif /* CONFIG_8xx */
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+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);
+ 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;
+ 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;
+ 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
@@ -1062,27 +1116,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;
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ 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_4xx || CONFIG_BOOKE */
--
Dave Kleikamp
IBM Linux Technology Center
^ permalink raw reply related
* [RFC:PATCH 02/03] powerpc: Add definitions for Debug Registers on BookE Platforms
From: Dave Kleikamp @ 2009-12-10 15:57 UTC (permalink / raw)
To: linuxppc-dev list
Cc: Sergio Durigan Junior, Torez Smith, David Gibson,
Thiago Jung Bauermann
In-Reply-To: <20091210155709.6697.4635.sendpatchset@norville.austin.ibm.com>
powerpc: Add definitions for Debug Registers on BookE Platforms
From: Torez Smith <lnxtorez@linux.vnet.ibm.com>
This patch adds additional definitions for BookE Debug Registers
to the reg_booke.h header file.
Signed-off-by: Torez Smith <lnxtorez@linux.vnet.ibm.com>
Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Thiago Jung Bauermann <bauerman@br.ibm.com>
Cc: Sergio Durigan Junior <sergiodj@br.ibm.com>
Cc: David Gibson <dwg@au1.ibm.com>
Cc: linuxppc-dev list <Linuxppc-dev@ozlabs.org>
---
arch/powerpc/include/asm/processor.h | 30 +++++-
arch/powerpc/include/asm/reg_booke.h | 176 +++++++++++++++++++++++++++++-----
2 files changed, 178 insertions(+), 28 deletions(-)
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 9eed29e..1393307 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -161,9 +161,35 @@ 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 */
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ /*
+ * The following help to manage the use of Debug Control Registers
+ * om the BookE platforms.
+ */
+ unsigned long dbcr0;
unsigned long dbcr1;
+ unsigned long dbcr2;
+ /*
+ * 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;
+ unsigned long iac3;
+ unsigned long iac4;
+ unsigned long dac1;
+ unsigned long dac2;
+ unsigned long dvc1;
+ unsigned long dvc2;
#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..7f8c71f 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 */
@@ -294,25 +296,68 @@
#define DBCR0_IC 0x08000000 /* Instruction Completion */
#define DBCR0_ICMP DBCR0_IC
#define DBCR0_BT 0x04000000 /* Branch Taken */
-#define DBCR0_BRT DBCR0_BT
#define DBCR0_EDE 0x02000000 /* Exception Debug Event */
#define DBCR0_IRPT DBCR0_EDE
#define DBCR0_TDE 0x01000000 /* TRAP Debug Event */
-#define DBCR0_IA1 0x00800000 /* Instr Addr compare 1 enable */
-#define DBCR0_IAC1 DBCR0_IA1
-#define DBCR0_IA2 0x00400000 /* Instr Addr compare 2 enable */
-#define DBCR0_IAC2 DBCR0_IA2
-#define DBCR0_IA12 0x00200000 /* Instr Addr 1-2 range enable */
-#define DBCR0_IA12X 0x00100000 /* Instr Addr 1-2 range eXclusive */
-#define DBCR0_IA3 0x00080000 /* Instr Addr compare 3 enable */
-#define DBCR0_IAC3 DBCR0_IA3
-#define DBCR0_IA4 0x00040000 /* Instr Addr compare 4 enable */
-#define DBCR0_IAC4 DBCR0_IA4
-#define DBCR0_IA34 0x00020000 /* Instr Addr 3-4 range Enable */
-#define DBCR0_IA34X 0x00010000 /* Instr Addr 3-4 range eXclusive */
-#define DBCR0_IA12T 0x00008000 /* Instr Addr 1-2 range Toggle */
-#define DBCR0_IA34T 0x00004000 /* Instr Addr 3-4 range Toggle */
+#define DBCR0_IAC1 0x00800000 /* Instr Addr compare 1 enable */
+#define DBCR0_IAC2 0x00400000 /* Instr Addr compare 2 enable */
+#define DBCR0_IAC12M 0x00300000 /* Instr Addr 1-2 range enable */
+#define DBCR0_IAC12M_R 0x00100000 /* Instr Addr 1-2 Reserved state */
+#define DBCR0_IAC12M_I 0x00200000 /* Instr Addr 1-2 range Inclusive */
+#define DBCR0_IAC12M_X 0x00300000 /* Instr Addr 1-2 range eXclusive */
+#define DBCR0_IAC3 0x00080000 /* Instr Addr compare 3 enable */
+#define DBCR0_IAC4 0x00040000 /* Instr Addr compare 4 enable */
+#define DBCR0_IAC34 0x00020000 /* Instr Addr 3-4 range Enable */
+#define DBCR0_IAC34X 0x00010000 /* Instr Addr 3-4 range eXclusive */
+#define DBCR0_IAC12T 0x00008000 /* Instr Addr 1-2 range Toggle */
+#define DBCR0_IAC34T 0x00004000 /* Instr Addr 3-4 range Toggle */
#define DBCR0_FT 0x00000001 /* Freeze Timers on debug event */
+
+#define DBCR0_USER_DEBUG (DBCR0_IDM | DBCR0_ICMP | DBCR0_IAC1 | \
+ DBCR0_IAC2 | DBCR0_IAC3 | DBCR0_IAC4)
+#define DBCR0_BASE_REG_VALUE 0
+
+#define dbcr_iac_range(task) ((task)->thread.dbcr0)
+#define DBCR_IAC12M DBCR0_IAC12M
+#define DBCR_IAC12M_I DBCR0_IAC12M_I
+#define DBCR_IAC12M_X DBCR0_IAC12M_X
+#define DBCR_IAC34M DBCR0_IAC34M
+#define DBCR_IAC34M_I DBCR0_IAC34M_I
+#define DBCR_IAC34M_X DBCR0_IAC34M_X
+
+/* Bit definitions related to the DBCR1. */
+#define DBCR1_D1R 0x80000000 /* DAC1 Read Debug Event */
+#define DBCR1_DAC1R DBCR1_D1R
+#define DBCR1_D2R 0x40000000 /* DAC2 Read Debug Event */
+#define DBCR1_DAC2R DBCR1_D2R
+#define DBCR1_D1W 0x20000000 /* DAC1 Write Debug Event */
+#define DBCR1_DAC1W DBCR1_D1W
+#define DBCR1_D2W 0x10000000 /* DAC2 Write Debug Event */
+#define DBCR1_DAC2W DBCR1_D2W
+
+#define DBCR1_USER_DEBUG (DBCR1_DAC1R | DBCR1_DAC2R | DBCR1_DAC1W | \
+ DBCR1_DAC2W)
+#define DBCR1_BASE_REG_VALUE 0
+
+#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
+
+#define DBCR2_USER_DEBUG 0
+#define DBCR2_BASE_REG_VALUE 0
+
+/*
+ * 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_D1R | DBCR1_D2R | DBCR1_D1W | DBCR1_D2W)
+#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 */
@@ -324,8 +369,7 @@
#define DBCR0_RST_NONE 0x00000000 /* No Reset */
#define DBCR0_ICMP 0x08000000 /* Instruction Completion */
#define DBCR0_IC DBCR0_ICMP
-#define DBCR0_BRT 0x04000000 /* Branch Taken */
-#define DBCR0_BT DBCR0_BRT
+#define DBCR0_BT 0x04000000 /* Branch Taken */
#define DBCR0_IRPT 0x02000000 /* Exception Debug Event */
#define DBCR0_TDE 0x01000000 /* TRAP Debug Event */
#define DBCR0_TIE DBCR0_TDE
@@ -342,19 +386,99 @@
#define DBCR0_CRET 0x00000020 /* Critical Return Debug Event */
#define DBCR0_FT 0x00000001 /* Freeze Timers on debug event */
+#define DBCR0_USER_DEBUG (DBCR0_IDM | DBCR0_ICMP | DBCR0_IAC1 | \
+ DBCR0_IAC2 | DBCR0_IAC3 | DBCR0_IAC4 | \
+ DBCR0_DAC1R | DBCR0_DAC1W | DBCR0_DAC2R | \
+ DBCR0_DAC2W)
+#define DBCR0_BASE_REG_VALUE 0
+
+#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_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_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 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 0x00C00000 /* Instr Addr 1-2 range enable */
+#define DBCR1_IAC12M_R 0x00400000 /* Instr Addr 1-2 reserved state */
+#define DBCR1_IAC12M_I 0x00800000 /* Instr Addr 1-2 range inclusive */
+#define DBCR1_IAC12M_X 0x00C00000 /* Instr Addr 1-2 range eXclusive */
+#define DBCR1_IAC12A_T 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 0x000000C0 /* Instr Addr 3-4 range enable */
+#define DBCR1_IAC34M_R 0x00000040 /* Instr Addr 3-4 reserved state */
+#define DBCR1_IAC34M_I 0x00000080 /* Instr Addr 3-4 range inclusive */
+#define DBCR1_IAC34M_X 0x000000C0 /* Instr Addr 3-4 range eXclusive */
+#define DBCR1_IAC34A_T 0x00000001 /* Instr Addr 3-4 range Toggle */
+
+#define DBCR1_USER_DEBUG (DBCR1_IAC12M | DBCR1_IAC34M)
+#define DBCR1_BASE_REG_VALUE (DBCR1_IAC1US | DBCR1_IAC1ER_10 | \
+ DBCR1_IAC2US | DBCR1_IAC2ER_10 | \
+ DBCR1_IAC3US | DBCR1_IAC3ER_10 | \
+ DBCR1_IAC4US | DBCR1_IAC4ER_10)
+
+#define dbcr_iac_range(task) ((task)->thread.dbcr1)
+#define DBCR_IAC12M DBCR1_IAC12M
+#define DBCR_IAC12M_I DBCR1_IAC12M_I
+#define DBCR_IAC12M_X DBCR1_IAC12M_X
+#define DBCR_IAC34M DBCR1_IAC34M
+#define DBCR_IAC34M_I DBCR1_IAC34M_I
+#define DBCR_IAC34M_X DBCR1_IAC34M_X
/* Bit definitions related to the DBCR2. */
-#define DBCR2_DAC12M 0x00800000 /* DAC 1-2 range enable */
-#define DBCR2_DAC12MX 0x00C00000 /* DAC 1-2 range eXclusive */
+#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_DAC12MODE 0x00C00000 /* DAC 1-2 Mode Bits */
+#define DBCR2_DAC12MASK 0x00400000 /* DAC 1-2 Mask mode*/
+#define DBCR2_DAC12R 0x00800000 /* DAC 1-2 range enable */
+#define DBCR2_DAC12RX 0x00C00000 /* DAC 1-2 range eXclusive */
#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 */
+
+#define DBCR2_USER_DEBUG (DBCR2_DAC12MODE | DBCR2_DVC1M | DBCR2_DVC2M | \
+ DBCR2_DVC1BE | DBCR2_DVC2BE)
+#define DBCR2_BASE_REG_VALUE (DBCR2_DAC1US | DBCR2_DAC2US)
+
+/*
+ * 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
* [RFC:PATCH 01/03] powerpc: Extended ptrace interface
From: Dave Kleikamp @ 2009-12-10 15:57 UTC (permalink / raw)
To: linuxppc-dev list
Cc: Sergio Durigan Junior, Thiago Jung Bauermann, Torez Smith,
David Gibson
In-Reply-To: <20091210155709.6697.4635.sendpatchset@norville.austin.ibm.com>
powerpc: Extended ptrace interface
From: Torez Smith <lnxtorez@linux.vnet.ibm.com>
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>
Signed-off-by: Torez Smith <lnxtorez@linux.vnet.ibm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Thiago Jung Bauermann <bauerman@br.ibm.com>
Cc: Sergio Durigan Junior <sergiodj@br.ibm.com>
Cc: David Gibson <dwg@au1.ibm.com>
Cc: linuxppc-dev list <Linuxppc-dev@ozlabs.org>
---
arch/powerpc/include/asm/ptrace.h | 75 ++++++++++++++++++++++++++++++++
arch/powerpc/kernel/ptrace.c | 88 +++++++++++++++++++++++++++++++++++++
2 files changed, 163 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 8c34149..7ae887b 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 {
@@ -292,4 +298,73 @@ 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 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
+
+#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 0x1
+#define PPC_BREAKPOINT_TRIGGER_READ 0x2
+#define PPC_BREAKPOINT_TRIGGER_WRITE 0x4
+#define PPC_BREAKPOINT_TRIGGER_RW 0x6
+
+/*
+ * Address Mode
+ */
+#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
+
+/*
+ * Condition Mode
+ */
+#define PPC_BREAKPOINT_CONDITION_NONE 0x0
+#define PPC_BREAKPOINT_CONDITION_AND 0x1
+#define PPC_BREAKPOINT_CONDITION_EXACT 0x1
+#define PPC_BREAKPOINT_CONDITION_OR 0x2
+#define PPC_BREAKPOINT_CONDITION_AND_OR 0x3
+#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 ef14988..6be2ce0 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -839,6 +839,50 @@ 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_BOOKE
+ 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) || (child->thread.dabr == 0))
+ return -EINVAL;
+
+ child->thread.dabr = 0;
+#ifdef CONFIG_BOOKE
+ 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
@@ -932,6 +976,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 = 0;
+#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
* [RFC:PATCH 00/03] powerpc: Expose BookE debug registers through extended ptrace interface
From: Dave Kleikamp @ 2009-12-10 15:57 UTC (permalink / raw)
To: linuxppc-dev list
Cc: Sergio Durigan Junior, Torez Smith, David Gibson,
Thiago Jung Bauermann
These patches implement an extention to the ptrace interface proposed by
Thiago Bauermann and the the PowerPC gdb team.
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 propose the
following 3 new ptrace requests described below.
There have been discussions of a generic hardware debug interface for the
kernel which would hopefully contemplate all the functionality below and
supersede it. But we need something that works now, and which enables GDB
to be simpler and work with both Server and Embedded processors without
special cases.
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_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] [SCSI] mpt fusion: Fix 32 bit platforms with 64 bit resources.
From: James Bottomley @ 2009-12-10 15:43 UTC (permalink / raw)
To: Pravin Bathija; +Cc: linuxppc-dev, Eric.Moore, linux-scsi
In-Reply-To: <1259805106-23636-1-git-send-email-pbathija@amcc.com>
On Wed, 2009-12-02 at 17:51 -0800, Pravin Bathija wrote:
> Powerpc 44x uses 36 bit real address while the real address defined
> in MPT Fusion driver is of type 32 bit. This causes ioremap to fail and driver
> fails to initialize. This fix changes the data types representing the real
> address from unsigned long 32-bit types to resource_size_t which is 64-bit. The
> driver has been tested, the disks get discovered correctly and can do IO.
>
> Signed-off-by: Pravin Bathija <pbathija@amcc.com>
> Acked-by: Feng Kan <fkan@amcc.com>
> Acked-by: Fushen Chen <fchen@amcc.com>
> Acked-by: Loc Ho <lho@amcc.com>
> Acked-by: Tirumala Reddy Marri <tmarri@amcc.com>
> Acked-by: Victor Gallardo <vgallardo@amcc.com>
> ---
> drivers/message/fusion/mptbase.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
> index 5d496a9..9f14a60 100644
> --- a/drivers/message/fusion/mptbase.c
> +++ b/drivers/message/fusion/mptbase.c
> @@ -1511,7 +1511,7 @@ mpt_mapresources(MPT_ADAPTER *ioc)
> {
> u8 __iomem *mem;
> int ii;
> - unsigned long mem_phys;
> + resource_size_t mem_phys;
You never actually compiled this, did you?
drivers/message/fusion/mptbase.c: In function 'mpt_mapresources':
drivers/message/fusion/mptbase.c:1680: warning: format '%lx' expects type 'long unsigned int', but argument 4 has type 'resource_size_t'
I'll just fold the fix in
James
---
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 162923f..85bc6a6 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1677,8 +1677,8 @@ mpt_mapresources(MPT_ADAPTER *ioc)
return -EINVAL;
}
ioc->memmap = mem;
- dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n",
- ioc->name, mem, mem_phys));
+ dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %llx\n",
+ ioc->name, mem, (unsigned long long)mem_phys));
ioc->mem_phys = mem_phys;
ioc->chip = (SYSIF_REGS __iomem *)mem;
^ permalink raw reply related
* Re: [PATCH v3] cpm2_pic: Allow correct flow_types for port C interrupts
From: Anton Vorontsov @ 2009-12-10 14:58 UTC (permalink / raw)
To: Kumar Gala; +Cc: Scott Wood, Linuxppc-dev Development, Mark Ware
In-Reply-To: <9DDC31C7-6AEE-498C-BE18-C286C950BB51@kernel.crashing.org>
On Thu, Dec 10, 2009 at 08:52:01AM -0600, Kumar Gala wrote:
>
> On Dec 10, 2009, at 5:14 AM, Mark Ware wrote:
>
> > Port C interrupts can be either falling edge, or either edge.
> > Other external interrupts are either falling edge or active low.
> > Tested on a custom 8280 based board.
> >
> > Signed-off-by: Mark Ware <mware@elphinstone.net>
> > ---
> > Changed in v3:
> > - Cosmetic improvements as suggested by Anton and Scott
> > - Added tested note to changelog
> >
> > arch/powerpc/sysdev/cpm2_pic.c | 28 +++++++++++++++++++++-------
> > 1 files changed, 21 insertions(+), 7 deletions(-)
>
> Scott, Anton do you want to add an Ack to this version?
Acked-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Thanks!
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: [PATCH v3] cpm2_pic: Allow correct flow_types for port C interrupts
From: Kumar Gala @ 2009-12-10 14:52 UTC (permalink / raw)
To: Scott Wood, Mark Ware; +Cc: Linuxppc-dev Development, Anton Vorontsov
In-Reply-To: <4B20D81A.7010503@elphinstone.net>
On Dec 10, 2009, at 5:14 AM, Mark Ware wrote:
> Port C interrupts can be either falling edge, or either edge.
> Other external interrupts are either falling edge or active low.
> Tested on a custom 8280 based board.
>
> Signed-off-by: Mark Ware <mware@elphinstone.net>
> ---
> Changed in v3:
> - Cosmetic improvements as suggested by Anton and Scott
> - Added tested note to changelog
>
> arch/powerpc/sysdev/cpm2_pic.c | 28 +++++++++++++++++++++-------
> 1 files changed, 21 insertions(+), 7 deletions(-)
Scott, Anton do you want to add an Ack to this version?
- k
^ permalink raw reply
* Re: Ping does not work on my MPC8544 board, using linux2.6.23
From: 林志平 @ 2009-12-10 13:05 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <4B2001A3.9010002@freescale.com>
[-- Attachment #1: Type: text/plain, Size: 1719 bytes --]
2009/12/10 Scott Wood <scottwood@freescale.com>
> 林志平 wrote:
>
>> > Another question is that I found linux2.6.31 does not support
>> > board mpc8544ds,
>>
>> It should. What problems do you see?
>>
>> => bootm 0x1000000 0x1800000 0x800000
>> ## Booting kernel from Legacy Image at 01000000 ...
>> Image Name: Linux-2.6.31
>> Image Type: PowerPC Linux Kernel Image (gzip compressed)
>> Data Size: 2185099 Bytes = 2.1 MB
>> Load Address: 00000000
>> Entry Point: 00000000
>> Verifying Checksum ... OK
>> ## Loading init Ramdisk from Legacy Image at 01800000 ...
>> Image Name: Simple Embedded Linux Framework
>> Image Type: PowerPC Linux RAMDisk Image (gzip compressed)
>> Data Size: 1859256 Bytes = 1.8 MB
>> Load Address: 00000000
>> Entry Point: 00000000
>> Verifying Checksum ... OK
>> ## Flattened Device Tree blob at 00800000
>> Booting using the fdt blob at 0x800000
>> Uncompressing Kernel Image ... OK
>> Loading Ramdisk to 1fca7000, end 1fe6ceb8 ... OK
>> booting kernel using flat tree
>> It then stops and never print any more, I use mpc85xx_defconfig, I select
>> mpc85xxds in the menuconfig and deselect other options like mpc8540ads etc.
>>
>
> Are you using the mpc8544ds device tree from 2.6.31, unchanged? Try
> turning on CONFIG_PPC_EARLY_DEBUG.
>
> No need to deselect the others, BTW.
> Does mpc85xx_defconfig not work?
>>
>> Yes mcp85xx_defconfig does not work, I can see mpc8540ads in the
>> menuconfig, but no mpc8544ds.
>>
>
> mpc8544ds is supported by CONFIG_MPC85xx_DS.
> CONFIG_MPC85XX_DS does not exist. Only mpc85xx_defconfig in
> arch/powerpc/configs
> -Scott
>
[-- Attachment #2: Type: text/html, Size: 2750 bytes --]
^ permalink raw reply
* [ibm_emac] rx_dropped_stack
From: Bross Stephan (LWE) @ 2009-12-10 12:36 UTC (permalink / raw)
To: linuxppc-dev
Hi all,
I am using linux version 2.6.25.20 on
cpu : 440GRX
revision : 24.212 (pvr 2162 18d4)
bogomips : 995.32
vendor : AMCC
machine : PPC440EPx LWMON5
I am using ethtool to read out NIC statistics. On every tested board I =
saw the counter increasing for 'rx_dropped_stack', on some boards also =
for 'rx_bd_errors', 'rx_bd_bad_fcs' and on few boards for 'tx_underrun' =
or 'tx_dropped'. Can you help me interpret those values? Which values =
are nice for information, which are really bad?
thanks in advance,
Stephan
Liebherr-Werk Ehingen GmbH
Dr.-Hans-Liebherr-Str. 1
89584 Ehingen
E-Mail: Stephan.Bross@liebherr.com
Internet: http://www.liebherr.com
Vorsitzender des Aufsichtsrats: Dipl.-Volksw. Henning Rapp
Gesch=E4ftsf=FChrer: Dr.-Ing. Ulrich Hamme, Dr.-Ing. Hubert Hummel, =
Dipl.-Ing. (FH) Christoph Kleiner, Dipl.-Kfm. Mario Trunzer
Sitz: 89584 Ehingen/Donau, Amtsgericht Ulm/Donau, HRB 490123, Ust-Id. =
Nr.: DE 811120093
LIEBHERRB2B4EM@IL
^ permalink raw reply
* [PATCH 2/2] pseries: Make declarations of cpu_hotplug_driver_lock() ANSI compatible.
From: Gautham R Shenoy @ 2009-12-10 11:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Benjamin Herrenschmidt
In-Reply-To: <20091210111937.18281.5146.stgit@sofia.in.ibm.com>
And add the __acquires() and __releases() annotations, while at it.
Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
---
arch/powerpc/platforms/pseries/dlpar.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index 12df9e8..67b7a10 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -346,12 +346,14 @@ int dlpar_release_drc(u32 drc_index)
static DEFINE_MUTEX(pseries_cpu_hotplug_mutex);
-void cpu_hotplug_driver_lock()
+void cpu_hotplug_driver_lock(void)
+__acquires(pseries_cpu_hotplug_mutex)
{
mutex_lock(&pseries_cpu_hotplug_mutex);
}
-void cpu_hotplug_driver_unlock()
+void cpu_hotplug_driver_unlock(void)
+__releases(pseries_cpu_hotplug_mutex)
{
mutex_unlock(&pseries_cpu_hotplug_mutex);
}
^ permalink raw reply related
* [PATCH 1/2] pseries: Don't panic when H_PROD fails during cpu-online.
From: Gautham R Shenoy @ 2009-12-10 11:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Benjamin Herrenschmidt
If an online-attempt on a CPU which has been offlined using H_CEDE
with an appropriate cede latency hint fails, don't panic.
Instead print the error message and let the __cpu_up() code notify the
CPU Hotplug framework of the failure, which in turn can notify the
other subsystem through CPU_UP_CANCELED.
Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
---
arch/powerpc/platforms/pseries/smp.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 8868c01..b488663 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -144,8 +144,8 @@ static void __devinit smp_pSeries_kick_cpu(int nr)
hcpuid = get_hard_smp_processor_id(nr);
rc = plpar_hcall_norets(H_PROD, hcpuid);
if (rc != H_SUCCESS)
- panic("Error: Prod to wake up processor %d Ret= %ld\n",
- nr, rc);
+ printk(KERN_ERR "Error: Prod to wake up processor %d\
+ Ret= %ld\n", nr, rc);
}
}
^ permalink raw reply related
* [PATCH v3] cpm2_pic: Allow correct flow_types for port C interrupts
From: Mark Ware @ 2009-12-10 11:14 UTC (permalink / raw)
To: Linuxppc-dev Development; +Cc: Scott Wood, avorontsov
Port C interrupts can be either falling edge, or either edge.
Other external interrupts are either falling edge or active low.
Tested on a custom 8280 based board.
Signed-off-by: Mark Ware <mware@elphinstone.net>
---
Changed in v3:
- Cosmetic improvements as suggested by Anton and Scott
- Added tested note to changelog
arch/powerpc/sysdev/cpm2_pic.c | 28 +++++++++++++++++++++-------
1 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index 78f1f7c..b1e9206 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -141,13 +141,23 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type)
struct irq_desc *desc = get_irq_desc(virq);
unsigned int vold, vnew, edibit;
- if (flow_type == IRQ_TYPE_NONE)
- flow_type = IRQ_TYPE_LEVEL_LOW;
-
- if (flow_type & IRQ_TYPE_EDGE_RISING) {
- printk(KERN_ERR "CPM2 PIC: sense type 0x%x not supported\n",
- flow_type);
- return -EINVAL;
+ /* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or
+ * IRQ_TYPE_EDGE_BOTH (default). All others are IRQ_TYPE_EDGE_FALLING
+ * or IRQ_TYPE_LEVEL_LOW (default)
+ */
+ if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0) {
+ if (flow_type == IRQ_TYPE_NONE)
+ flow_type = IRQ_TYPE_EDGE_BOTH;
+
+ if (flow_type != IRQ_TYPE_EDGE_BOTH &&
+ flow_type != IRQ_TYPE_EDGE_FALLING)
+ goto err_sense;
+ } else {
+ if (flow_type == IRQ_TYPE_NONE)
+ flow_type = IRQ_TYPE_LEVEL_LOW;
+
+ if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
+ goto err_sense;
}
desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
@@ -179,6 +189,10 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type)
if (vold != vnew)
out_be32(&cpm2_intctl->ic_siexr, vnew);
return 0;
+
+err_sense:
+ pr_err("CPM2 PIC: sense type 0x%x not supported\n", flow_type);
+ return -EINVAL;
}
static struct irq_chip cpm2_pic = {
--
1.5.6.5
^ permalink raw reply related
* Re: [PATCH v2] cpm2_pic: Allow correct flow_types for port C interrupts
From: Mark Ware @ 2009-12-10 11:10 UTC (permalink / raw)
To: Scott Wood; +Cc: Linuxppc-dev Development, avorontsov
In-Reply-To: <4B201D67.4070802@freescale.com>
Scott Wood wrote:
> Anton Vorontsov wrote:
>>> + if ((flow_type != IRQ_TYPE_EDGE_BOTH) && +
>>> (flow_type != IRQ_TYPE_EDGE_FALLING)) {
>>
>> I'd place one more tab here.
>
> Or better, align one "flow_type" with the other.
>
> -Scott
>
Thanks Anton and Scott.
Scott's suggestion is also my preferred style, but a (brief) search through the source didn't reveal much support.
I'll send a new version shortly including you suggestions.
- Mark
^ permalink raw reply
* Re: MPC5200B XLB Configuration Issues, FEC RFIFO Events, ATA Crashes
From: Roman Fietze @ 2009-12-10 6:09 UTC (permalink / raw)
To: Wolfram Sang; +Cc: linuxppc-dev
In-Reply-To: <20091209145748.GB3112@pengutronix.de>
Hello Wolfram,
On Wednesday 09 December 2009 15:57:48 Wolfram Sang wrote:
> Do you have a way to measure performance penalties?
Yes, I do. I am using an SCLPC test driver derived from a driver
written or posted by Grant Likely named mpc5200-localplus-test. This
gives me some useful output about the SCLPC BestComm FIFO read
throughput.
Additional to that I'm running I relatively dumb ATA stress test
writing large files to an ext3 that gives me the data rate, as well as
an NFS mount where I read data from.
I will now run all three tests in a few combinations, those that do
not crash my system with the old setup, adding NFS writes and ATA
reads.
I will post the numbers here as soon as I'm done, please give me 2 or
3 days, and as soon as I have the confidence they reflect the reality
at least somewhat.
> I know that stability comes before performance, still I am wondering
> as it looks to me that the most interesting features are simply
> switched off.
We are seeing the same problem in our device, but having a return rate
of almost 100% due to corrupt file systems that can not be repaired in
the field is no alternative.
But, something that never happened before, the system is now running
SCLPC read, ATA write and NFS read for more that 20 hours without any
crash. That's an argument.
Probably the XLB setup has to be done in the U-Boot anyway, and here
the configuration can be flexible enough to enable those positive
features on boards that use only component that do not conflict. The
only thing left is the the cache coherency switch in the kernel
config.
Roman
=2D-=20
Roman Fietze Telemotive AG B=FCro M=FChlhausen
Breitwiesen 73347 M=FChlhausen
Tel.: +49(0)7335/18493-45 http://www.telemotive.de
^ permalink raw reply
* Re: [PATCH] cardbus: Add a fixup hook and fix powerpc
From: Benjamin Herrenschmidt @ 2009-12-10 3:53 UTC (permalink / raw)
To: Dominik Brodowski
Cc: linux-pci, linux-kernel@vger.kernel.org, Jesse Barnes, blofeldus,
Olof Johansson, linuxppc-dev
In-Reply-To: <20091209213736.GA25968@comet.dominikbrodowski.net>
On Wed, 2009-12-09 at 22:37 +0100, Dominik Brodowski wrote:
> Acked-by: Dominik Brodowski <linux@dominikbrodowski.net> (for PCMCIA)
>
> > Note: In the long run we might want to streamline the hooks for fixing
> > up new devices vs. new busses and make some stuff common between cardbus
> > and PCI hotplug which is actually a mess.
>
> ... though I'd prefer such a generic approach.
Thanks. Yes that would be better. I don't have the bandwidth right now
to look at that though, maybe early next year.
Cheers,
Ben.
^ permalink raw reply
* [PATCH] of: merge of_find_node_by_phandle
From: Jeremy Kerr @ 2009-12-10 2:47 UTC (permalink / raw)
To: devicetree-discuss; +Cc: sparclinux, microblaze-uclinux, linuxppc-dev
Merge common function between powerpc, sparc and microblaze. Code is
identical for powerpc and microblaze, but adds a lock (and release) of
the devtree_lock on sparc.
Currently untested.
Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
---
v2: update iterator, fix subject, post to arch lists
---
arch/microblaze/kernel/prom.c | 21 ---------------------
arch/powerpc/kernel/prom.c | 21 ---------------------
arch/sparc/kernel/prom_common.c | 12 ------------
drivers/of/base.c | 21 +++++++++++++++++++++
4 files changed, 21 insertions(+), 54 deletions(-)
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index 9b4a20b..3fac1e2 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -238,27 +238,6 @@ void __init early_init_devtree_arch(void)
*
*******/
-/**
- * of_find_node_by_phandle - Find a node given a phandle
- * @handle: phandle of the node to find
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_find_node_by_phandle(phandle handle)
-{
- struct device_node *np;
-
- read_lock(&devtree_lock);
- for (np = allnodes; np != NULL; np = np->allnext)
- if (np->phandle == handle)
- break;
- of_node_get(np);
- read_unlock(&devtree_lock);
- return np;
-}
-EXPORT_SYMBOL(of_find_node_by_phandle);
-
#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
static struct debugfs_blob_wrapper flat_dt_blob;
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index d3ce311..83161d0 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -689,27 +689,6 @@ void __init early_init_devtree_arch(void)
*******/
/**
- * of_find_node_by_phandle - Find a node given a phandle
- * @handle: phandle of the node to find
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_find_node_by_phandle(phandle handle)
-{
- struct device_node *np;
-
- read_lock(&devtree_lock);
- for (np = allnodes; np != 0; np = np->allnext)
- if (np->phandle == handle)
- break;
- of_node_get(np);
- read_unlock(&devtree_lock);
- return np;
-}
-EXPORT_SYMBOL(of_find_node_by_phandle);
-
-/**
* of_find_next_cache_node - Find a node's subsidiary cache
* @np: node of type "cpu" or "cache"
*
diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c
index 5832e13..57ac9e2 100644
--- a/arch/sparc/kernel/prom_common.c
+++ b/arch/sparc/kernel/prom_common.c
@@ -37,18 +37,6 @@ EXPORT_SYMBOL(of_console_path);
char *of_console_options;
EXPORT_SYMBOL(of_console_options);
-struct device_node *of_find_node_by_phandle(phandle handle)
-{
- struct device_node *np;
-
- for (np = allnodes; np; np = np->allnext)
- if (np->phandle == handle)
- break;
-
- return np;
-}
-EXPORT_SYMBOL(of_find_node_by_phandle);
-
int of_getintprop_default(struct device_node *np, const char *name, int def)
{
struct property *prop;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 9212b87..7432011 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -672,6 +672,27 @@ int of_modalias_node(struct device_node *node, char *modalias, int len)
EXPORT_SYMBOL_GPL(of_modalias_node);
/**
+ * of_find_node_by_phandle - Find a node given a phandle
+ * @handle: phandle of the node to find
+ *
+ * Returns a node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+ struct device_node *np;
+
+ read_lock(&devtree_lock);
+ for (np = allnodes; np; np = np->allnext)
+ if (np->phandle == handle)
+ break;
+ of_node_get(np);
+ read_unlock(&devtree_lock);
+ return np;
+}
+EXPORT_SYMBOL(of_find_node_by_phandle);
+
+/**
* of_parse_phandle - Resolve a phandle property to a device_node pointer
* @np: Pointer to device node holding phandle property
* @phandle_name: Name of property holding a phandle value
^ permalink raw reply related
* RE: [PATCH] Adding PCI-E support for 460SX based redwood board.
From: Tirumala Reddy Marri @ 2009-12-10 2:22 UTC (permalink / raw)
To: tmarr, benh; +Cc: linuxppc-dev
In-Reply-To: <1259615732-20272-1-git-send-email-tmarr@amcc.com>
Testing and other information for this patch.
1. Kernel version: 2.6.32-rc6=20
2. Board: AMCC redwood validation board.
3. tests
a. Configured redwood boards PCI-E ports as root ports. And plugged
in 2 HBA sas cards with 8 drives each. XDD and IO =20
meter tests were ran. No issues found.
b. Configured redwood board PCI-E port as Endpoint and configured
second board as root complex. Boards were interconnected using PCI-E
cable. Then did lspci on root complex configured redwood board to see if
the endpoint can be scanned. Also using BDI I was able to do read and
writes to & from root complex as well as endpoint.
Regards,
Marri
-----Original Message-----
From: tmarr@amcc.com [mailto:tmarr@amcc.com]=20
Sent: Monday, November 30, 2009 1:16 PM
To: benh@kernel.crashing.org
Cc: linuxppc-dev@ozlabs.org; Tirumala Reddy Marri
Subject: [PATCH] Adding PCI-E support for 460SX based redwood board.
From: Tirumala Marri <tmarri@amcc.com>
This patch would add PCI-E support for AMCC 460SX processor based=20
redwood board.
Signed-off-by: Tirumala Marri <tmarri@amcc.com>
---
arch/powerpc/boot/dts/redwood.dts | 122
+++++++++++++++++++++++++++++++++++++
arch/powerpc/sysdev/ppc4xx_pci.c | 119
++++++++++++++++++++++++++++++++++++
arch/powerpc/sysdev/ppc4xx_pci.h | 58 +++++++++++++++++
3 files changed, 299 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/boot/dts/redwood.dts
b/arch/powerpc/boot/dts/redwood.dts
index ad402c4..9eeec28 100644
--- a/arch/powerpc/boot/dts/redwood.dts
+++ b/arch/powerpc/boot/dts/redwood.dts
@@ -233,6 +233,128 @@
has-inverted-stacr-oc;
has-new-stacr-staopc;
};
+ PCIE0: pciex@d00000000 {
+ device_type =3D "pci";
+ #interrupt-cells =3D <1>;
+ #size-cells =3D <2>;
+ #address-cells =3D <3>;
+ compatible =3D "ibm,plb-pciex-460sx",
"ibm,plb-pciex";
+ primary;
+ port =3D <0x0>; /* port number */
+ reg =3D <0x0000000d 0x00000000 0x20000000
/* Config space access */
+ 0x0000000c 0x10000000
0x00001000>; /* Registers */
+ dcr-reg =3D <0x100 0x020>;
+ sdr-base =3D <0x300>;
+
+ /* Outbound ranges, one memory and one
IO,
+ * later cannot be changed
+ */
+ ranges =3D <0x02000000 0x00000000
0x80000000 0x0000000e 0x00000000 0x00000000 0x80000000
+ 0x01000000 0x00000000
0x00000000 0x0000000f 0x80000000 0x00000000 0x00010000>;
+
+ /* Inbound 2GB range starting at 0 */
+ dma-ranges =3D <0x42000000 0x0 0x0 0x0 0x0
0x0 0x80000000>;
+
+ /* This drives busses 10 to 0x1f */
+ bus-range =3D <0x10 0x1f>;
+
+ /* Legacy interrupts (note the weird
polarity, the bridge seems
+ * to invert PCIe legacy interrupts).
+ * We are de-swizzling here because the
numbers are actually for
+ * port of the root complex virtual P2P
bridge. But I want
+ * to avoid putting a node for it in the
tree, so the numbers
+ * below are basically de-swizzled
numbers.
+ * The real slot is on idsel 0, so the
swizzling is 1:1
+ */
+ interrupt-map-mask =3D <0x0 0x0 0x0 0x7>;
+ interrupt-map =3D <
+ 0x0 0x0 0x0 0x1 &UIC3 0x0 0x4 /*
swizzled int A */
+ 0x0 0x0 0x0 0x2 &UIC3 0x1 0x4 /*
swizzled int B */
+ 0x0 0x0 0x0 0x3 &UIC3 0x2 0x4 /*
swizzled int C */
+ 0x0 0x0 0x0 0x4 &UIC3 0x3 0x4 /*
swizzled int D */>;
+ };
+
+ PCIE1: pciex@d20000000 {
+ device_type =3D "pci";
+ #interrupt-cells =3D <1>;
+ #size-cells =3D <2>;
+ #address-cells =3D <3>;
+ compatible =3D "ibm,plb-pciex-460sx",
"ibm,plb-pciex";
+ primary;
+ port =3D <0x1>; /* port number */
+ reg =3D <0x0000000d 0x20000000 0x20000000
/* Config space access */
+ 0x0000000c 0x10001000
0x00001000>; /* Registers */
+ dcr-reg =3D <0x120 0x020>;
+ sdr-base =3D <0x340>;
+
+ /* Outbound ranges, one memory and one
IO,
+ * later cannot be changed
+ */
+ ranges =3D <0x02000000 0x00000000
0x80000000 0x0000000e 0x80000000 0x00000000 0x80000000
+ 0x01000000 0x00000000
0x00000000 0x0000000f 0x80010000 0x00000000 0x00010000>;
+
+ /* Inbound 2GB range starting at 0 */
+ dma-ranges =3D <0x42000000 0x0 0x0 0x0 0x0
0x0 0x80000000>;
+
+ /* This drives busses 10 to 0x1f */
+ bus-range =3D <0x20 0x2f>;
+
+ /* Legacy interrupts (note the weird
polarity, the bridge seems
+ * to invert PCIe legacy interrupts).
+ * We are de-swizzling here because the
numbers are actually for
+ * port of the root complex virtual P2P
bridge. But I want
+ * to avoid putting a node for it in the
tree, so the numbers
+ * below are basically de-swizzled
numbers.
+ * The real slot is on idsel 0, so the
swizzling is 1:1
+ */
+ interrupt-map-mask =3D <0x0 0x0 0x0 0x7>;
+ interrupt-map =3D <
+ 0x0 0x0 0x0 0x1 &UIC3 0x4 0x4 /*
swizzled int A */
+ 0x0 0x0 0x0 0x2 &UIC3 0x5 0x4 /*
swizzled int B */
+ 0x0 0x0 0x0 0x3 &UIC3 0x6 0x4 /*
swizzled int C */
+ 0x0 0x0 0x0 0x4 &UIC3 0x7 0x4 /*
swizzled int D */>;
+ };
+
+ PCIE2: pciex@d40000000 {
+ device_type =3D "pci";
+ #interrupt-cells =3D <1>;
+ #size-cells =3D <2>;
+ #address-cells =3D <3>;
+ compatible =3D "ibm,plb-pciex-460sx",
"ibm,plb-pciex";
+ primary;
+ port =3D <0x2>; /* port number */
+ reg =3D <0x0000000d 0x40000000 0x20000000
/* Config space access */
+ 0x0000000c 0x10002000
0x00001000>; /* Registers */
+ dcr-reg =3D <0x140 0x020>;
+ sdr-base =3D <0x370>;
+
+ /* Outbound ranges, one memory and one
IO,
+ * later cannot be changed
+ */
+ ranges =3D <0x02000000 0x00000000
0x80000000 0x0000000f 0x00000000 0x00000000 0x80000000
+ 0x01000000 0x00000000
0x00000000 0x0000000f 0x80020000 0x00000000 0x00010000>;
+
+ /* Inbound 2GB range starting at 0 */
+ dma-ranges =3D <0x42000000 0x0 0x0 0x0 0x0
0x0 0x80000000>;
+
+ /* This drives busses 10 to 0x1f */
+ bus-range =3D <0x30 0x3f>;
+
+ /* Legacy interrupts (note the weird
polarity, the bridge seems
+ * to invert PCIe legacy interrupts).
+ * We are de-swizzling here because the
numbers are actually for
+ * port of the root complex virtual P2P
bridge. But I want
+ * to avoid putting a node for it in the
tree, so the numbers
+ * below are basically de-swizzled
numbers.
+ * The real slot is on idsel 0, so the
swizzling is 1:1
+ */
+ interrupt-map-mask =3D <0x0 0x0 0x0 0x7>;
+ interrupt-map =3D <
+ 0x0 0x0 0x0 0x1 &UIC3 0x8 0x4 /*
swizzled int A */
+ 0x0 0x0 0x0 0x2 &UIC3 0x9 0x4 /*
swizzled int B */
+ 0x0 0x0 0x0 0x3 &UIC3 0xa 0x4 /*
swizzled int C */
+ 0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /*
swizzled int D */>;
+ };
=20
};
=20
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c
b/arch/powerpc/sysdev/ppc4xx_pci.c
index 6ff9d71..64cd020 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -972,6 +972,123 @@ static struct ppc4xx_pciex_hwops
ppc460ex_pcie_hwops __initdata =3D
.setup_utl =3D ppc460ex_pciex_init_utl,
};
=20
+static int __init ppc460sx_pciex_core_init(struct device_node *np)
+{
+ /* HSS drive amplitude */
+ mtdcri(SDR0, PESDR0_460SX_HSSL0DAMP, 0xB9843211);
+ mtdcri(SDR0, PESDR0_460SX_HSSL1DAMP, 0xB9843211);
+ mtdcri(SDR0, PESDR0_460SX_HSSL2DAMP, 0xB9843211);
+ mtdcri(SDR0, PESDR0_460SX_HSSL3DAMP, 0xB9843211);
+ mtdcri(SDR0, PESDR0_460SX_HSSL4DAMP, 0xB9843211);
+ mtdcri(SDR0, PESDR0_460SX_HSSL5DAMP, 0xB9843211);
+ mtdcri(SDR0, PESDR0_460SX_HSSL6DAMP, 0xB9843211);
+ mtdcri(SDR0, PESDR0_460SX_HSSL7DAMP, 0xB9843211);
+
+ mtdcri(SDR0, PESDR1_460SX_HSSL0DAMP, 0xB9843211);
+ mtdcri(SDR0, PESDR1_460SX_HSSL1DAMP, 0xB9843211);
+ mtdcri(SDR0, PESDR1_460SX_HSSL2DAMP, 0xB9843211);
+ mtdcri(SDR0, PESDR1_460SX_HSSL3DAMP, 0xB9843211);
+
+ mtdcri(SDR0, PESDR2_460SX_HSSL0DAMP, 0xB9843211);
+ mtdcri(SDR0, PESDR2_460SX_HSSL1DAMP, 0xB9843211);
+ mtdcri(SDR0, PESDR2_460SX_HSSL2DAMP, 0xB9843211);
+ mtdcri(SDR0, PESDR2_460SX_HSSL3DAMP, 0xB9843211);
+
+ /* HSS TX pre-emphasis */
+ mtdcri(SDR0, PESDR0_460SX_HSSL0COEFA, 0xDCB98987);
+ mtdcri(SDR0, PESDR0_460SX_HSSL1COEFA, 0xDCB98987);
+ mtdcri(SDR0, PESDR0_460SX_HSSL2COEFA, 0xDCB98987);
+ mtdcri(SDR0, PESDR0_460SX_HSSL3COEFA, 0xDCB98987);
+ mtdcri(SDR0, PESDR0_460SX_HSSL4COEFA, 0xDCB98987);
+ mtdcri(SDR0, PESDR0_460SX_HSSL5COEFA, 0xDCB98987);
+ mtdcri(SDR0, PESDR0_460SX_HSSL6COEFA, 0xDCB98987);
+ mtdcri(SDR0, PESDR0_460SX_HSSL7COEFA, 0xDCB98987);
+
+ mtdcri(SDR0, PESDR1_460SX_HSSL0COEFA, 0xDCB98987);
+ mtdcri(SDR0, PESDR1_460SX_HSSL1COEFA, 0xDCB98987);
+ mtdcri(SDR0, PESDR1_460SX_HSSL2COEFA, 0xDCB98987);
+ mtdcri(SDR0, PESDR1_460SX_HSSL3COEFA, 0xDCB98987);
+
+ mtdcri(SDR0, PESDR2_460SX_HSSL0COEFA, 0xDCB98987);
+ mtdcri(SDR0, PESDR2_460SX_HSSL1COEFA, 0xDCB98987);
+ mtdcri(SDR0, PESDR2_460SX_HSSL2COEFA, 0xDCB98987);
+ mtdcri(SDR0, PESDR2_460SX_HSSL3COEFA, 0xDCB98987);
+
+ /* HSS TX calibration control */
+ mtdcri(SDR0, PESDR0_460SX_HSSL1CALDRV, 0x22222222);
+ mtdcri(SDR0, PESDR1_460SX_HSSL1CALDRV, 0x22220000);
+ mtdcri(SDR0, PESDR2_460SX_HSSL1CALDRV, 0x22220000);
+
+ /* HSS TX slew control */
+ mtdcri(SDR0, PESDR0_460SX_HSSSLEW, 0xFFFFFFFF);
+ mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000);
+ mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000);
+
+ udelay(100);
+
+ /* De-assert PLLRESET */
+ dcri_clrset(SDR0, PESDR0_PLLLCT2, 0x00000100, 0);
+
+ /* Reset DL, UTL, GPL before configuration */
+ mtdcri(SDR0, PESDR0_460SX_RCSSET,
+ PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
+ mtdcri(SDR0, PESDR1_460SX_RCSSET,
+ PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
+ mtdcri(SDR0, PESDR2_460SX_RCSSET,
+ PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
+
+ udelay(100);
+
+ /*
+ * If bifurcation is not enabled, u-boot would have disabled the
+ * third PCIe port
+ */
+ if (((mfdcri(SDR0, PESDR1_460SX_HSSCTLSET) & 0x00000001) =3D=3D
+ 0x00000001)) {
+ printk(KERN_INFO "PCI: PCIE bifurcation setup
successfully.\n");
+ printk(KERN_INFO "PCI: Total 3 PCIE ports are
present\n");
+ return 3;
+ }
+
+ printk(KERN_INFO "PCI: Total 2 PCIE ports are present\n");
+ return 2;
+}
+
+static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+{
+
+ if (port->endpoint)
+ dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
+ 0x01000000, 0);
+ else
+ dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
+ 0, 0x01000000);
+
+ /*Gen-1*/
+ mtdcri(SDR0, port->sdr_base + PESDRn_460SX_RCEI, 0x08000000);
+
+ dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
+ (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL),
+ PESDRx_RCSSET_RSTPYN);
+
+ port->has_ibpre =3D 1;
+
+ return 0;
+}
+
+static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port)
+{
+ /* Max 128 Bytes */
+ out_be32 (port->utl_base + PEUTL_PBBSZ, 0x00000000);
+ return 0;
+}
+
+static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata =3D {
+ .core_init =3D ppc460sx_pciex_core_init,
+ .port_init_hw =3D ppc460sx_pciex_init_port_hw,
+ .setup_utl =3D ppc460sx_pciex_init_utl,
+};
+
#endif /* CONFIG_44x */
=20
#ifdef CONFIG_40x
@@ -1087,6 +1204,8 @@ static int __init
ppc4xx_pciex_check_core_init(struct device_node *np)
}
if (of_device_is_compatible(np, "ibm,plb-pciex-460ex"))
ppc4xx_pciex_hwops =3D &ppc460ex_pcie_hwops;
+ if (of_device_is_compatible(np, "ibm,plb-pciex-460sx"))
+ ppc4xx_pciex_hwops =3D &ppc460sx_pcie_hwops;
#endif /* CONFIG_44x */
#ifdef CONFIG_40x
if (of_device_is_compatible(np, "ibm,plb-pciex-405ex"))
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.h
b/arch/powerpc/sysdev/ppc4xx_pci.h
index d04e40b..56d9e5d 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.h
+++ b/arch/powerpc/sysdev/ppc4xx_pci.h
@@ -324,6 +324,64 @@
#define PESDR0_460EX_IHS2 0x036D
=20
/*
+ * 460SX addtional DCRs
+ */
+#define PESDRn_460SX_RCEI 0x02
+
+#define PESDR0_460SX_HSSL0DAMP 0x320
+#define PESDR0_460SX_HSSL1DAMP 0x321
+#define PESDR0_460SX_HSSL2DAMP 0x322
+#define PESDR0_460SX_HSSL3DAMP 0x323
+#define PESDR0_460SX_HSSL4DAMP 0x324
+#define PESDR0_460SX_HSSL5DAMP 0x325
+#define PESDR0_460SX_HSSL6DAMP 0x326
+#define PESDR0_460SX_HSSL7DAMP 0x327
+
+#define PESDR1_460SX_HSSL0DAMP 0x354
+#define PESDR1_460SX_HSSL1DAMP 0x355
+#define PESDR1_460SX_HSSL2DAMP 0x356
+#define PESDR1_460SX_HSSL3DAMP 0x357
+
+#define PESDR2_460SX_HSSL0DAMP 0x384
+#define PESDR2_460SX_HSSL1DAMP 0x385
+#define PESDR2_460SX_HSSL2DAMP 0x386
+#define PESDR2_460SX_HSSL3DAMP 0x387
+
+#define PESDR0_460SX_HSSL0COEFA 0x328
+#define PESDR0_460SX_HSSL1COEFA 0x329
+#define PESDR0_460SX_HSSL2COEFA 0x32A
+#define PESDR0_460SX_HSSL3COEFA 0x32B
+#define PESDR0_460SX_HSSL4COEFA 0x32C
+#define PESDR0_460SX_HSSL5COEFA 0x32D
+#define PESDR0_460SX_HSSL6COEFA 0x32E
+#define PESDR0_460SX_HSSL7COEFA 0x32F
+
+#define PESDR1_460SX_HSSL0COEFA 0x358
+#define PESDR1_460SX_HSSL1COEFA 0x359
+#define PESDR1_460SX_HSSL2COEFA 0x35A
+#define PESDR1_460SX_HSSL3COEFA 0x35B
+
+#define PESDR2_460SX_HSSL0COEFA 0x388
+#define PESDR2_460SX_HSSL1COEFA 0x389
+#define PESDR2_460SX_HSSL2COEFA 0x38A
+#define PESDR2_460SX_HSSL3COEFA 0x38B
+
+#define PESDR0_460SX_HSSL1CALDRV 0x339
+#define PESDR1_460SX_HSSL1CALDRV 0x361
+#define PESDR2_460SX_HSSL1CALDRV 0x391
+
+#define PESDR0_460SX_HSSSLEW 0x338
+#define PESDR1_460SX_HSSSLEW 0x360
+#define PESDR2_460SX_HSSSLEW 0x390
+
+#define PESDR0_460SX_HSSCTLSET 0x31E
+#define PESDR1_460SX_HSSCTLSET 0x352
+#define PESDR2_460SX_HSSCTLSET 0x382
+
+#define PESDR0_460SX_RCSSET 0x304
+#define PESDR1_460SX_RCSSET 0x344
+#define PESDR2_460SX_RCSSET 0x374
+/*
* Of the above, some are common offsets from the base
*/
#define PESDRn_UTLSET1 0x00
--=20
1.6.3.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox