* [patch 0/5] [v3] powerpc: PA Semi PWRficient patches
From: Olof Johansson @ 2006-09-06 19:33 UTC (permalink / raw)
To: paulus, anton; +Cc: linuxppc-dev
Hi,
The following series of patches introduces basic support for PA Semi's
PA6T core, and the base platform support for PWRficient PA6T-1682M.
It is split up in 5 separate patches:
1. Reduce default cacheline size to 64 bytes
2. Divorce CPU_FTR_CTRL from CPU_FTR_PPCAS_ARCH_V2_BASE
3. Cpu table entry, PVR value
4. Basic arch/powerpc/platforms/pasemi contents
5. MAINTAINER entry
Changes since last submission:
* Fix host bridge ioremap typo (Segher)
* Misc IRQ cleanup (Segher)
-Olof
^ permalink raw reply
* [patch 1/5] [v3] powerpc: Reduce default cacheline size to 64 bytes
From: Olof Johansson @ 2006-09-06 19:34 UTC (permalink / raw)
To: paulus, anton; +Cc: linuxppc-dev
In-Reply-To: <20060906143305.05b54abb@localhost.localdomain>
Reduce default cacheline size on 64-bit powerpc from 128 bytes to 64.
This is the architected minimum. In most cases we'll still end up using
cache line information from the device tree, but defaults are used during
early boot and doing a few dcbst/icbi's too many there won't do any harm.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: merge/arch/powerpc/kernel/setup_64.c
===================================================================
--- merge.orig/arch/powerpc/kernel/setup_64.c
+++ merge/arch/powerpc/kernel/setup_64.c
@@ -78,10 +78,10 @@ u64 ppc64_pft_size;
* before we've read this from the device tree.
*/
struct ppc64_caches ppc64_caches = {
- .dline_size = 0x80,
- .log_dline_size = 7,
- .iline_size = 0x80,
- .log_iline_size = 7
+ .dline_size = 0x40,
+ .log_dline_size = 6,
+ .iline_size = 0x40,
+ .log_iline_size = 6
};
EXPORT_SYMBOL_GPL(ppc64_caches);
Index: merge/arch/powerpc/kernel/head_64.S
===================================================================
--- merge.orig/arch/powerpc/kernel/head_64.S
+++ merge/arch/powerpc/kernel/head_64.S
@@ -1748,7 +1748,7 @@ _STATIC(__after_prom_start)
_GLOBAL(copy_and_flush)
addi r5,r5,-8
addi r6,r6,-8
-4: li r0,16 /* Use the least common */
+4: li r0,8 /* Use the smallest common */
/* denominator cache line */
/* size. This results in */
/* extra cache line flushes */
^ permalink raw reply
* [patch 2/5] [v3] powerpc: Divorce CPU_FTR_CTRL from CPU_FTR_PPCAS_ARCH_V2_BASE
From: Olof Johansson @ 2006-09-06 19:35 UTC (permalink / raw)
To: paulus, anton; +Cc: linuxppc-dev
In-Reply-To: <20060906143305.05b54abb@localhost.localdomain>
The performance monitor implementation (including CTRL register behaviour)
is just included in PPC v2 as an example, it's not truly part of the base.
It's actually a somewhat misleading feature, but I'll leave that be for
now: The precense of the register is not what the feature bit is used
for, but instead it's used to determine if it contains the runlatch
bit for idle reporting of the performance monitor. For alternative
implementations, the register might still exist but the bit might have
different meaning (or no meaning at all).
For now, split it off and don't include it in CPU_FTR_PPCAS_ARCH_V2_BASE.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: merge/include/asm-powerpc/cputable.h
===================================================================
--- merge.orig/include/asm-powerpc/cputable.h
+++ merge/include/asm-powerpc/cputable.h
@@ -148,7 +148,7 @@ extern void do_cpu_ftr_fixups(unsigned l
#define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \
CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \
- CPU_FTR_NODSISRALIGN | CPU_FTR_CTRL)
+ CPU_FTR_NODSISRALIGN)
/* iSeries doesn't support large pages */
#ifdef CONFIG_PPC_ISERIES
@@ -313,24 +313,25 @@ extern void do_cpu_ftr_fixups(unsigned l
CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
CPU_FTR_MMCRA | CPU_FTR_CTRL)
#define CPU_FTRS_POWER4 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA)
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
+ CPU_FTR_MMCRA)
#define CPU_FTRS_PPC970 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA)
#define CPU_FTRS_POWER5 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
CPU_FTR_PURR)
#define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_REAL_LE)
#define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
- CPU_FTR_CTRL | CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE)
+ CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE)
#define CPU_FTRS_COMPATIBLE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
#endif
^ permalink raw reply
* [patch 3/5] [v3] powerpc: PA6T cputable entry, PVR value
From: Olof Johansson @ 2006-09-06 19:35 UTC (permalink / raw)
To: paulus, anton; +Cc: linuxppc-dev
In-Reply-To: <20060906143305.05b54abb@localhost.localdomain>
Introduce PWRficient PA6T cputable entries and feature bits.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: merge/arch/powerpc/kernel/cputable.c
===================================================================
--- merge.orig/arch/powerpc/kernel/cputable.c
+++ merge/arch/powerpc/kernel/cputable.c
@@ -58,6 +58,9 @@ extern void __restore_cpu_ppc970(void);
#define COMMON_USER_POWER6 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_05 |\
PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \
PPC_FEATURE_TRUE_LE)
+#define COMMON_USER_PA6T (COMMON_USER_PPC64 | PPC_FEATURE_PA6T |\
+ PPC_FEATURE_TRUE_LE | \
+ PPC_FEATURE_HAS_ALTIVEC_COMP)
#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
PPC_FEATURE_BOOKE)
@@ -286,6 +289,17 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128,
.platform = "ppc-cell-be",
},
+ { /* PA Semi PA6T */
+ .pvr_mask = 0x7fff0000,
+ .pvr_value = 0x00900000,
+ .cpu_name = "PA6T",
+ .cpu_features = CPU_FTRS_PA6T,
+ .cpu_user_features = COMMON_USER_PA6T,
+ .icache_bsize = 64,
+ .dcache_bsize = 64,
+ .num_pmcs = 6,
+ .platform = "pa6t",
+ },
{ /* default match */
.pvr_mask = 0x00000000,
.pvr_value = 0x00000000,
Index: merge/include/asm-powerpc/reg.h
===================================================================
--- merge.orig/include/asm-powerpc/reg.h
+++ merge/include/asm-powerpc/reg.h
@@ -592,6 +592,7 @@
#define PV_630p 0x0041
#define PV_970MP 0x0044
#define PV_BE 0x0070
+#define PV_PA6T 0x0090
/*
* Number of entries in the SLB. If this ever changes we should handle
Index: merge/include/asm-powerpc/cputable.h
===================================================================
--- merge.orig/include/asm-powerpc/cputable.h
+++ merge/include/asm-powerpc/cputable.h
@@ -23,6 +23,7 @@
#define PPC_FEATURE_SMT 0x00004000
#define PPC_FEATURE_ICACHE_SNOOP 0x00002000
#define PPC_FEATURE_ARCH_2_05 0x00001000
+#define PPC_FEATURE_PA6T 0x00000800
#define PPC_FEATURE_TRUE_LE 0x00000002
#define PPC_FEATURE_PPC_LE 0x00000001
@@ -332,6 +333,10 @@ extern void do_cpu_ftr_fixups(unsigned l
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE)
+#define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
+ CPU_FTR_PURR | CPU_FTR_REAL_LE)
#define CPU_FTRS_COMPATIBLE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
#endif
@@ -340,7 +345,7 @@ extern void do_cpu_ftr_fixups(unsigned l
#define CPU_FTRS_POSSIBLE \
(CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | \
CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 | \
- CPU_FTRS_CELL | CPU_FTR_CI_LARGE_PAGE)
+ CPU_FTRS_CELL | CPU_FTRS_PA6T)
#else
enum {
CPU_FTRS_POSSIBLE =
@@ -379,7 +384,7 @@ enum {
#define CPU_FTRS_ALWAYS \
(CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 & \
CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_POWER6 & \
- CPU_FTRS_CELL & CPU_FTRS_POSSIBLE)
+ CPU_FTRS_CELL & CPU_FTRS_PA6T & CPU_FTRS_POSSIBLE)
#else
enum {
CPU_FTRS_ALWAYS =
^ permalink raw reply
* Re: pci error recovery procedure
From: Linas Vepstas @ 2006-09-06 20:01 UTC (permalink / raw)
To: Zhang, Yanmin
Cc: Yanmin Zhang, LKML, Rajesh Shah, linuxppc-dev, linux-pci maillist
In-Reply-To: <1157506016.20092.386.camel@ymzhang-perf.sh.intel.com>
On Wed, Sep 06, 2006 at 09:26:56AM +0800, Zhang, Yanmin wrote:
> > > The
> > > error_detected of the drivers in the latest kernel who support err handlers
> > > always returns PCI_ERS_RESULT_NEED_RESET. They are typical examples.
> >
> > Just because the current drivers do it this way does not mean that this is
> > the best way to do things.
>
> If it's not the best way, why did you choose to reset slot for e1000/e100/ipr
> error handlers? They are typical widely-used devices. To make it easier to
> add error handlers?
I did it that way just to get going, get something working. I do not
have hardware specs for any of these devices, and do not have much of
an idea of what they are capable of; the recovery code I wrote is of
"brute force, hit it with a hammer"-nature. Driver writers who
know thier hardware well, and are interested in a more refined
approach are encouraged to actualy use a more refined approach.
--linas
^ permalink raw reply
* Re: pci error recovery procedure
From: Linas Vepstas @ 2006-09-06 20:39 UTC (permalink / raw)
To: Zhang, Yanmin
Cc: linuxppc-dev, linux-pci maillist, Yanmin Zhang, LKML, Rajesh Shah
In-Reply-To: <1157508270.20092.426.camel@ymzhang-perf.sh.intel.com>
On Wed, Sep 06, 2006 at 10:04:31AM +0800, Zhang, Yanmin wrote:
> On Wed, 2006-09-06 at 03:17, Linas Vepstas wrote:
> > On Mon, Sep 04, 2006 at 01:47:30PM +0800, Zhang, Yanmin wrote:
> > > >
> > > > Again, consider the multi-function cards. On pSeries, I can only enable
> > > > DMA on a per-slot basis, not a per-function basis. So if one driver
> > > > enables DMA before some other driver has reset appropriately, everything
> > > > breaks.
> > > Does here 'reset' mean hardware slot reset?
> >
> > I should have said: If one driver of a multi-function card enables DMA before
> > another driver has stabilized its harware, then everything breaks.
> What's another driver's hardware? A function of the previous multi-function
> card? Or a function of another device?
Yes. Either. Both. Doesn't matter. Enabling DMA is "granular" at a
different size scale than pci functions, and possibly even pci devices
or slots, dependeing on the architecture. Before DMA can be enabled,
*all* affected device drivers have to be approve, and have to be ready
for it.
> > If we enabled both DMA and MMIO at the same time, there are many cases
> > where the card will immediately trap again -- for example, if its
> > DMA'ing to some crazy address. Thus, typically, one wants DMA disabled
> > until after the card reset. Without the mmio_enabled() reset, there
> > is no way of doing this.
>
> Did you asume the card reset is executed by callback mmio_enabled?
I am assuming that, when a driver receives the mmio_enabled() callback,
it will perform some sort of register i/o. For example, I am currently
planning to modify the e1000 driver to do the following:
-- The error_occurred() callback returns PCI_ERS_RESULT_CAN_RECOVER
-- The arch enables mmio, and then calls the mmio_enabled() callback.
-- The mmio_enabled() callback in the driver takes a full dump of all
of the regsters on the card. It then returns PCI_ERS_RESULT_NEED_RESET
-- The arch performs the full electrical #RST of device. Recovery from
this point proceeds as before.
> > Again, consider the multi-function cards. On pSeries, I can only enable
> > DMA on a per-slot basis, not a per-function basis. So if one driver
> > enables DMA before some other driver has reset appropriately, everything
> > breaks.
>
> What does 'I' above stand for? The platform error recovery procedure
Yes. The pSeries platform error recovery procedure can only enable DMA
on a per-slot basis.
> I guess it means platform, that is,
> only platform enables DMA for the whole slot.
Yes.
> But why does the last sentence
> become driver enables DMA?
In your proposal, you were suggesting that MMIO and DMA be enabled with
one and the same routine, and I was attempting to explain why that can't
work.
> Could driver enable DMA for a function?
No, not on pSeries hardware.
> > > If mmio_enabled is not used currently, I think we could delete it firstly. Later on,
> > > if a platform really need it, we could add it, so we could keep the simplied codes.
> >
> > It would be very difficult to add it later. And it would be especially
> > silly, given that someone would find this discussion in the mailing list
> > archives.
> You stick to keep mmio_enabled which is not used currently, but if there will be
> a new platform who uses a more fine-grained steps to recover pci/pci-e, would
> you say 'it would be very difficut' and refuse add new callbacks?
Yes.
> It doesn't prevent software from merging some steps. And, we want
> to implement pci/pci-e error recovery for more platforms instead of just
> pSeries.
Yes. The API was designed so that it could be supported on every
current and future platform we could think of. You haven't yet
claimed that "pci-e can't be supported". Based on what
I understand, changing the API wouldn't make the implementation
any easier. (It is very easy to call a callback, and then
examine its return value. Removing a few callbacks does not
materially simplify the recovery mechanism. Managing these
callbacks is *not* the hard part of implementing this thing.)
--linas
^ permalink raw reply
* Continuous Login Loop
From: Clint Thomas @ 2006-09-06 21:08 UTC (permalink / raw)
To: linuxppc-embedded; +Cc: Jason Lamb
[-- Attachment #1: Type: text/plain, Size: 952 bytes --]
Hey,
I'm running the latest kernel pull from the mvista powerpc 2.4 dev
source. I built a root file system using Busybox 1.2.0 and the mkrootfs
script by Wolfgang Klingauf (removed all DOS carriage returns). When the
system boots up, i'm getting this output.
Mounted devfs on /dev
Freeing unused kernel memory: 44k init
init started: BusyBox v1.2.0 (2006.09.06-19:44+0000) multi-call binary
Starting pid 10, console /dev/console: '/etc/init.d/rcS'
Bummer, could not run '/etc/
PowerPC Linux 2.4.26
(none) login: root
Process '/sbin/getty 38400 tts/0' (pid 11) exited. Scheduling i
PowerPC Linux 2.4.26
(none) login:
it keeps looping through the login every time I try to enter root. I
have the root user in the passwd file, and I believe I have the RFS
setup properly. What would cause this kind of an issue? Is this a
problem related to getty? or just a missing file or device of some kind?
Thanks
Clinton Thomas
[-- Attachment #2: Type: text/html, Size: 1637 bytes --]
^ permalink raw reply
* Re: Continuous Login Loop
From: Steve Iribarne (GMail) @ 2006-09-06 21:20 UTC (permalink / raw)
To: Clint Thomas; +Cc: Jason Lamb, linuxppc-embedded
In-Reply-To: <3C02138692C13C4BB675FE7EA24095291C3C92@bluefin.Soneticom.local>
On 9/6/06, Clint Thomas <cthomas@soneticom.com> wrote:
>
>
> Hey,
>
> I'm running the latest kernel pull from the mvista powerpc 2.4 dev source. I
> built a root file system using Busybox 1.2.0 and the mkrootfs script by
> Wolfgang Klingauf (removed all DOS carriage returns). When the system boots
> up, i'm getting this output.
>
> Mounted devfs on /dev
> Freeing unused kernel memory: 44k init
> init started: BusyBox v1.2.0 (2006.09.06-19:44+0000) multi-call binary
> Starting pid 10, console /dev/console: '/etc/init.d/rcS'
> Bummer, could not run '/etc/
> PowerPC Linux 2.4.26
> (none) login: root
> Process '/sbin/getty 38400 tts/0' (pid 11) exited. Scheduling i
> PowerPC Linux 2.4.26
> (none) login:
>
> it keeps looping through the login every time I try to enter root. I have
> the root user in the passwd file, and I believe I have the RFS setup
> properly. What would cause this kind of an issue? Is this a problem related
> to getty? or just a missing file or device of some kind? Thanks
>
Hi Clint,
You know in the back of my head (very dusty place) I seem to recall
that this is a Busybox issue with getty. Something about security.
Not sure... but I'd check with their forums.
-stv
>
>
> Clinton Thomas
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
>
^ permalink raw reply
* Re: [PATCH] PPC 4xx: Enable XMON on PPC 4xx boards
From: Paul Mackerras @ 2006-09-06 22:55 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev, mporter
In-Reply-To: <1157569083.6098.29.camel@zod.rchland.ibm.com>
Josh Boyer writes:
> - excp->msr |= 0x400;
> + excp->msr |= MSR_SSTEP_ENABLE;
> +#ifdef CONFIG_4xx
> + mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
> +#endif
> } else if (at_breakpoint(excp->nip)) {
> xmon_trace[smp_processor_id()] = BRSTEP;
> - excp->msr |= 0x400;
> + excp->msr |= MSR_SSTEP_ENABLE;
> +#ifdef CONFIG_4xx
> + mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
> +#endif
This would be neater with a little inline xmon_enable_sstep(excp)
function...
Other than that, looks fine.
Paul.
^ permalink raw reply
* [PATCH] powerpc: Instrument Hypervisor Calls
From: Mike Kravetz @ 2006-09-06 23:23 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
Hi Paul,
This patch addresses the issues you brought up with the previous version.
The most important issue being range checking of opcodes so the code does
not write outside the array. You also suggested doing a load from TOC
instead of LOAD_REG_ADDR, because LOAD_REG_ADDR turns into 5 instructions.
I 'think' LOAD_REG_ADDR only turns into 5 instructions on 32 bit systems.
It is a single load from TOC on 64 bits as we are using it.
Here it is:
Add instrumentation for hypervisor calls on pseries. Call statistics
include number of calls, wall time and cpu cycles (if available) and
are made available via debugfs. Instrumentation code is behind the
HCALL_STATS config option and has no impact if not enabled.
--
Signed-off-by: Mike Kravetz <kravetz@us.ibm.com>
diff -Naupr powerpc/arch/powerpc/Kconfig.debug powerpc.work/arch/powerpc/Kconfig.debug
--- powerpc/arch/powerpc/Kconfig.debug 2006-09-06 22:40:53.000000000 +0000
+++ powerpc.work/arch/powerpc/Kconfig.debug 2006-09-06 23:41:40.000000000 +0000
@@ -18,6 +18,20 @@ config DEBUG_STACK_USAGE
This option will slow down process creation somewhat.
+config HCALL_STATS
+ bool "Hypervisor call instrumentation"
+ depends on PPC_PSERIES && DEBUG_FS
+ help
+ Adds code to keep track of the number of hypervisor calls made and
+ the amount of time spent in hypervisor callsr. Wall time spent in
+ each call is always calculated, and if available CPU cycles spent
+ are also calculated. A directory named hcall_inst is added at the
+ root of the debugfs filesystem. Within the hcall_inst directory
+ are files that contain CPU specific call statistics.
+
+ This option will add a small amount of overhead to all hypervisor
+ calls.
+
config DEBUGGER
bool "Enable debugger hooks"
depends on DEBUG_KERNEL
diff -Naupr powerpc/arch/powerpc/kernel/asm-offsets.c powerpc.work/arch/powerpc/kernel/asm-offsets.c
--- powerpc/arch/powerpc/kernel/asm-offsets.c 2006-09-06 22:40:55.000000000 +0000
+++ powerpc.work/arch/powerpc/kernel/asm-offsets.c 2006-09-06 23:41:40.000000000 +0000
@@ -137,6 +137,7 @@ int main(void)
DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr));
+ DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset));
DEFINE(SLBSHADOW_STACKVSID,
offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid));
@@ -165,6 +166,12 @@ int main(void)
/* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */
DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
+
+ /* hcall statistics */
+ DEFINE(HCALL_STAT_SIZE, sizeof(struct hcall_stats));
+ DEFINE(HCALL_STAT_CALLS, offsetof(struct hcall_stats, num_calls));
+ DEFINE(HCALL_STAT_TB, offsetof(struct hcall_stats, tb_total));
+ DEFINE(HCALL_STAT_PURR, offsetof(struct hcall_stats, purr_total));
#endif /* CONFIG_PPC64 */
DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0]));
DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1]));
diff -Naupr powerpc/arch/powerpc/platforms/pseries/Makefile powerpc.work/arch/powerpc/platforms/pseries/Makefile
--- powerpc/arch/powerpc/platforms/pseries/Makefile 2006-09-06 22:41:08.000000000 +0000
+++ powerpc.work/arch/powerpc/platforms/pseries/Makefile 2006-09-06 23:41:40.000000000 +0000
@@ -12,3 +12,4 @@ obj-$(CONFIG_EEH) += eeh.o eeh_cache.o e
obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_HVCS) += hvcserver.o
+obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
diff -Naupr powerpc/arch/powerpc/platforms/pseries/hvCall.S powerpc.work/arch/powerpc/platforms/pseries/hvCall.S
--- powerpc/arch/powerpc/platforms/pseries/hvCall.S 2006-09-06 22:41:08.000000000 +0000
+++ powerpc.work/arch/powerpc/platforms/pseries/hvCall.S 2006-09-06 23:41:40.000000000 +0000
@@ -10,9 +10,69 @@
#include <asm/hvcall.h>
#include <asm/processor.h>
#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
#define STK_PARM(i) (48 + ((i)-3)*8)
+#ifdef CONFIG_HCALL_STATS
+/*
+ * precall must preserve all registers. use unused STK_PARM()
+ * areas to save snapshots and opcode.
+ */
+#define HCALL_INST_PRECALL \
+ std r3,STK_PARM(r3)(r1); /* save opcode */ \
+ mftb r0; /* get timebase and */ \
+ std r0,STK_PARM(r5)(r1); /* save for later */ \
+BEGIN_FTR_SECTION; \
+ mfspr r0,SPRN_PURR; /* get PURR and */ \
+ std r0,STK_PARM(r6)(r1); /* save for later */ \
+END_FTR_SECTION_IFCLR(CPU_FTR_PURR);
+
+/*
+ * postcall is performed immediately before function return which
+ * allows liberal use of volatile registers.
+ */
+#define HCALL_INST_POSTCALL \
+ ld r4,STK_PARM(r3)(r1); /* validate opcode */ \
+ cmpldi cr7,r4,MAX_HCALL_OPCODE; \
+ bgt- cr7,1f; \
+ \
+ /* get time and PURR snapshots after hcall */ \
+ mftb r7; /* timebase after */ \
+BEGIN_FTR_SECTION; \
+ mfspr r8,SPRN_PURR; /* PURR after */ \
+ ld r6,STK_PARM(r6)(r1); /* PURR before */ \
+ subf r6,r6,r8; /* delta */ \
+END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \
+ ld r5,STK_PARM(r5)(r1); /* timebase before */ \
+ subf r5,r5,r7; /* time delta */ \
+ \
+ /* calculate address of stat structure r4 = opcode */ \
+ srdi r4,r4,2; /* index into array */ \
+ mulli r4,r4,HCALL_STAT_SIZE; \
+ LOAD_REG_ADDR(r7, per_cpu__hcall_stats); \
+ add r4,r4,r7; \
+ ld r7,PACA_DATA_OFFSET(r13); /* per cpu offset */ \
+ add r4,r4,r7; \
+ \
+ /* update stats */ \
+ ld r7,HCALL_STAT_CALLS(r4); /* count */ \
+ addi r7,r7,1; \
+ std r7,HCALL_STAT_CALLS(r4); \
+ ld r7,HCALL_STAT_TB(r4); /* timebase */ \
+ add r7,r7,r5; \
+ std r7,HCALL_STAT_TB(r4); \
+BEGIN_FTR_SECTION; \
+ ld r7,HCALL_STAT_PURR(r4); /* PURR */ \
+ add r7,r7,r6; \
+ std r7,HCALL_STAT_PURR(r4); \
+END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \
+1:
+#else
+#define HCALL_INST_PRECALL
+#define HCALL_INST_POSTCALL
+#endif
+
.text
_GLOBAL(plpar_hcall_norets)
@@ -21,8 +81,12 @@ _GLOBAL(plpar_hcall_norets)
mfcr r0
stw r0,8(r1)
+ HCALL_INST_PRECALL
+
HVSC /* invoke the hypervisor */
+ HCALL_INST_POSTCALL
+
lwz r0,8(r1)
mtcrf 0xff,r0
blr /* return r3 = status */
@@ -33,6 +97,8 @@ _GLOBAL(plpar_hcall)
mfcr r0
stw r0,8(r1)
+ HCALL_INST_PRECALL
+
std r4,STK_PARM(r4)(r1) /* Save ret buffer */
mr r4,r5
@@ -50,6 +116,8 @@ _GLOBAL(plpar_hcall)
std r6, 16(r12)
std r7, 24(r12)
+ HCALL_INST_POSTCALL
+
lwz r0,8(r1)
mtcrf 0xff,r0
@@ -61,6 +129,8 @@ _GLOBAL(plpar_hcall9)
mfcr r0
stw r0,8(r1)
+ HCALL_INST_PRECALL
+
std r4,STK_PARM(r4)(r1) /* Save ret buffer */
mr r4,r5
@@ -86,6 +156,8 @@ _GLOBAL(plpar_hcall9)
std r11,56(r12)
std r12,64(r12)
+ HCALL_INST_POSTCALL
+
lwz r0,8(r1)
mtcrf 0xff,r0
diff -Naupr powerpc/arch/powerpc/platforms/pseries/hvCall_inst.c powerpc.work/arch/powerpc/platforms/pseries/hvCall_inst.c
--- powerpc/arch/powerpc/platforms/pseries/hvCall_inst.c 1970-01-01 00:00:00.000000000 +0000
+++ powerpc.work/arch/powerpc/platforms/pseries/hvCall_inst.c 2006-09-06 23:42:55.000000000 +0000
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2006 Mike Kravetz IBM Corporation
+ *
+ * Hypervisor Call Instrumentation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/percpu.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/cpumask.h>
+#include <asm/hvcall.h>
+#include <asm/firmware.h>
+#include <asm/cputable.h>
+
+DEFINE_PER_CPU(struct hcall_stats[HCALL_STAT_ARRAY_SIZE], hcall_stats);
+
+/*
+ * Routines for displaying the statistics in debugfs
+ */
+static void *hc_start(struct seq_file *m, loff_t *pos)
+{
+ if ((int)*pos < HCALL_STAT_ARRAY_SIZE)
+ return (void *)(unsigned long)(*pos + 1);
+
+ return NULL;
+}
+
+static void *hc_next(struct seq_file *m, void *p, loff_t * pos)
+{
+ ++*pos;
+
+ return hc_start(m, pos);
+}
+
+static void hc_stop(struct seq_file *m, void *p)
+{
+}
+
+static int hc_show(struct seq_file *m, void *p)
+{
+ unsigned long h_num = (unsigned long)p;
+ struct hcall_stats *hs = (struct hcall_stats *)m->private;
+
+ if (hs[h_num].num_calls) {
+ if (!cpu_has_feature(CPU_FTR_PURR))
+ seq_printf(m, "%lu %lu %lu %lu\n", h_num<<2,
+ hs[h_num].num_calls,
+ hs[h_num].tb_total,
+ hs[h_num].purr_total);
+ else
+ seq_printf(m, "%lu %lu %lu\n", h_num<<2,
+ hs[h_num].num_calls,
+ hs[h_num].tb_total);
+ }
+
+ return 0;
+}
+
+static struct seq_operations hcall_inst_seq_ops = {
+ .start = hc_start,
+ .next = hc_next,
+ .stop = hc_stop,
+ .show = hc_show
+};
+
+static int hcall_inst_seq_open(struct inode *inode, struct file *file)
+{
+ int rc;
+ struct seq_file *seq;
+
+ rc = seq_open(file, &hcall_inst_seq_ops);
+ seq = file->private_data;
+ seq->private = file->f_dentry->d_inode->u.generic_ip;
+
+ return rc;
+}
+
+static struct file_operations hcall_inst_seq_fops = {
+ .open = hcall_inst_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+#define HCALL_ROOT_DIR "hcall_inst"
+#define CPU_NAME_BUF_SIZE 32
+
+static int __init hcall_inst_init(void)
+{
+ struct dentry *hcall_root;
+ struct dentry *hcall_file;
+ char cpu_name_buf[CPU_NAME_BUF_SIZE];
+ int cpu;
+
+ if (!firmware_has_feature(FW_FEATURE_LPAR))
+ return 0;
+
+ hcall_root = debugfs_create_dir(HCALL_ROOT_DIR, NULL);
+ if (!hcall_root)
+ return -ENOMEM;
+
+ for_each_possible_cpu(cpu) {
+ snprintf(cpu_name_buf, CPU_NAME_BUF_SIZE, "cpu%d", cpu);
+ hcall_file = debugfs_create_file(cpu_name_buf, S_IRUGO,
+ hcall_root,
+ per_cpu(hcall_stats, cpu),
+ &hcall_inst_seq_fops);
+ if (!hcall_file)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+__initcall(hcall_inst_init);
diff -Naupr powerpc/include/asm-powerpc/hvcall.h powerpc.work/include/asm-powerpc/hvcall.h
--- powerpc/include/asm-powerpc/hvcall.h 2006-09-06 22:45:48.000000000 +0000
+++ powerpc.work/include/asm-powerpc/hvcall.h 2006-09-06 23:42:16.000000000 +0000
@@ -208,7 +208,7 @@
#define H_JOIN 0x298
#define H_VASI_STATE 0x2A4
#define H_ENABLE_CRQ 0x2B0
-#define MAX_HCALL_OPCODES (H_ENABLE_CRQ >> 2)
+#define MAX_HCALL_OPCODE H_ENABLE_CRQ
#ifndef __ASSEMBLY__
@@ -246,6 +246,16 @@ long plpar_hcall(unsigned long opcode, u
#define PLPAR_HCALL9_BUFSIZE 9
long plpar_hcall9(unsigned long opcode, unsigned long *retbuf, ...);
+/* For hcall instrumentation. One structure per-hcall, per-CPU */
+struct hcall_stats {
+ unsigned long num_calls; /* number of calls (on this CPU) */
+ unsigned long tb_total; /* total wall time (mftb) of calls. */
+ unsigned long purr_total; /* total cpu time (PURR) of calls. */
+};
+void update_hcall_stats(unsigned long opcode, unsigned long tb_delta,
+ unsigned long purr_delta);
+#define HCALL_STAT_ARRAY_SIZE ((MAX_HCALL_OPCODE >> 2) + 1)
+
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_HVCALL_H */
^ permalink raw reply
* Re: [PATCH] PPC 4xx: Enable XMON on PPC 4xx boards
From: Josh Boyer @ 2006-09-06 23:50 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, mporter
In-Reply-To: <17663.20973.922238.823386@cargo.ozlabs.ibm.com>
On Thu, 2006-09-07 at 08:55 +1000, Paul Mackerras wrote:
> Josh Boyer writes:
>
> > - excp->msr |= 0x400;
> > + excp->msr |= MSR_SSTEP_ENABLE;
> > +#ifdef CONFIG_4xx
> > + mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
> > +#endif
> > } else if (at_breakpoint(excp->nip)) {
> > xmon_trace[smp_processor_id()] = BRSTEP;
> > - excp->msr |= 0x400;
> > + excp->msr |= MSR_SSTEP_ENABLE;
> > +#ifdef CONFIG_4xx
> > + mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
> > +#endif
>
> This would be neater with a little inline xmon_enable_sstep(excp)
> function...
>
> Other than that, looks fine.
Agreed. I'll make that change and resend in the morning.
josh
^ permalink raw reply
* Re: [PATCH] powerpc: Instrument Hypervisor Calls
From: Paul Mackerras @ 2006-09-07 0:34 UTC (permalink / raw)
To: Mike Kravetz; +Cc: linuxppc-dev
In-Reply-To: <20060906232312.GC3283@w-mikek2.ibm.com>
Mike Kravetz writes:
> I 'think' LOAD_REG_ADDR only turns into 5 instructions on 32 bit systems.
> It is a single load from TOC on 64 bits as we are using it.
You're right, David (Gibson) cleaned that up some time ago. In fact
it's only 2 instructions on 32-bit systems, and it is a TOC load on
64-bit systems.
Paul.
^ permalink raw reply
* Re: common flatdevtree code
From: Mark A. Greer @ 2006-09-07 0:36 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, hollisb
In-Reply-To: <17662.17895.852128.729679@cargo.ozlabs.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 1624 bytes --]
On Wed, Sep 06, 2006 at 01:52:07PM +1000, Paul Mackerras wrote:
> Mark A. Greer writes:
>
> > I'm doing some fairly massive rework to my patches so it'll take
> > another day or two (plus 4 day weekend for me). In the meantime,
> > this is what I've done to your code. :)
>
> Any further progress on this? I need an ft library for the prep
> bootwrapper changes I'm planning.
>
> I don't like the approach of doing a malloc for the whole blob every
> time you make a property larger though. I'm going to be adding quite
> a few nodes and properties, potentially, and with a simple-minded
> malloc (such as you get in a bootwrapper) it's likely to chew through
> a lot of memory unnecessarily. I would rather be able to start with
> an existing blob and pull it apart once, add stuff to it, then put it
> back together, doing a small number of mallocs in the process.
>
> > I still plan on changing it a bit to use ft_next in a few more routines
> > (e.g., ft_dump_blob). ft_next has a clumsy interface but I like the fact
>
> The interface might look nicer if we had a structure for the tag,
> name, value and length. Then there would only be one parameter
> instead of the four you have at the moment.
>
> Paul.
Paul,
Here's what I have at the moment...
- flatdevtree.[ch] are copies of what Hollis will be keeping (but I've
edited the ones attached to this email)
- flatdevtree_env.h is a bootwrapper hdr file that contains local
defines that the generic flatdevtree.[ch] need
- flatdevtree_misc.c is other ft stuff that isn't in flatdevtree.c plus
some bootwrapper->flatdevtree.c glue code
Mark
--
[-- Attachment #2: flatdevtree.c --]
[-- Type: text/x-csrc, Size: 15282 bytes --]
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright Pantelis Antoniou 2006
* Copyright (C) IBM Corporation 2006
*
* Authors: Pantelis Antoniou <pantelis@embeddedalley.com>
* Hollis Blanchard <hollisb@us.ibm.com>
*/
#include "flatdevtree.h"
/* Set ptrs to current one's info; return addr of next one */
static u32 *ft_next(u32 *p, const u32 *p_strings, const u32 version,
u32 **tagpp, char **namepp, char **datapp, u32 **sizepp)
{
u32 sz;
*namepp = NULL;
*datapp = NULL;
*sizepp = NULL;
*tagpp = p;
switch (be32_to_cpu(*p++)) { /* Tag */
case OF_DT_BEGIN_NODE:
*namepp = (char *)p;
p = (u32 *)_ALIGN((u32)p + strlen((char *)p) + 1, 4);
break;
case OF_DT_PROP:
sz = be32_to_cpu(*p);
*sizepp = p++;
*namepp = (char *)p_strings + be32_to_cpu(*p++);
if ((version < 0x10) && (sz >= 8))
p = (u32 *)_ALIGN((unsigned long)p, 8);
*datapp = (char *)p;
p = (u32 *)_ALIGN((unsigned long)p + sz, 4);
break;
case OF_DT_END_NODE:
case OF_DT_NOP:
break;
case OF_DT_END:
default:
p = NULL;
break;
}
return p;
}
static void ft_put_word(struct ft_cxt *cxt, u32 v)
{
if (cxt->overflow) /* do nothing */
return;
/* check for overflow */
if (cxt->p + 4 > cxt->pstr) {
cxt->overflow = 1;
return;
}
*(u32 *) cxt->p = cpu_to_be32(v);
cxt->p += 4;
}
static inline void ft_put_bin(struct ft_cxt *cxt, const void *data, int sz)
{
char *p;
if (cxt->overflow) /* do nothing */
return;
/* next pointer pos */
p = (char *) _ALIGN((unsigned long)cxt->p + sz, 4);
/* check for overflow */
if (p > cxt->pstr) {
cxt->overflow = 1;
return;
}
memcpy(cxt->p, data, sz);
if ((sz & 3) != 0)
memset(cxt->p + sz, 0, 4 - (sz & 3));
cxt->p = p;
}
void ft_begin_node(struct ft_cxt *cxt, const char *name)
{
ft_put_word(cxt, OF_DT_BEGIN_NODE);
ft_put_bin(cxt, name, strlen(name) + 1);
}
void ft_end_node(struct ft_cxt *cxt)
{
ft_put_word(cxt, OF_DT_END_NODE);
}
void ft_nop(struct ft_cxt *cxt)
{
ft_put_word(cxt, OF_DT_NOP);
}
static int lookup_string(struct ft_cxt *cxt, const char *name)
{
char *p;
p = cxt->pstr;
while (p < cxt->pstr_begin) {
if (strcmp(p, (char *)name) == 0)
return p - cxt->p_begin;
p += strlen(p) + 1;
}
return -1;
}
void ft_prop(struct ft_cxt *cxt, const char *name,
const void *data, unsigned int sz)
{
int len, off;
if (cxt->overflow)
return;
len = strlen(name) + 1;
off = lookup_string(cxt, name);
if (off == -1) {
/* check if we have space */
if (cxt->p + 12 + sz + len > cxt->pstr) {
cxt->overflow = 1;
return;
}
cxt->pstr -= len;
memcpy(cxt->pstr, name, len);
off = cxt->pstr - cxt->p_begin;
}
/* now put offset from beginning of *STRUCTURE* */
/* will be fixed up at the end */
ft_put_word(cxt, OF_DT_PROP);
ft_put_word(cxt, sz);
ft_put_word(cxt, off);
ft_put_bin(cxt, data, sz);
}
void ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str)
{
ft_prop(cxt, name, str, strlen(str) + 1);
}
void ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val)
{
u32 v = cpu_to_be32((u32) val);
ft_prop(cxt, name, &v, 4);
}
/* start construction of the flat OF tree */
void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size)
{
struct boot_param_header *bph = blob;
u32 off;
/* clear the cxt */
memset(cxt, 0, sizeof(*cxt));
cxt->bph = bph;
cxt->max_size = max_size;
/* zero everything in the header area */
memset(bph, 0, sizeof(*bph));
bph->magic = cpu_to_be32(OF_DT_HEADER);
bph->version = cpu_to_be32(0x10);
bph->last_comp_version = cpu_to_be32(0x10);
/* start pointers */
cxt->pres_begin = (char *) _ALIGN((unsigned long)(bph + 1), 8);
cxt->pres = cxt->pres_begin;
off = (unsigned long)cxt->pres_begin - (unsigned long)bph;
bph->off_mem_rsvmap = cpu_to_be32(off);
((u64 *) cxt->pres)[0] = 0; /* phys = 0, size = 0, terminate */
((u64 *) cxt->pres)[1] = 0;
cxt->p_anchor = cxt->pres + 16; /* over the terminator */
}
/* add a reserver physical area to the rsvmap */
void ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size)
{
((u64 *) cxt->pres)[0] = cpu_to_be64(physaddr); /* phys = 0, size = 0, terminate */
((u64 *) cxt->pres)[1] = cpu_to_be64(size);
cxt->pres += 18; /* advance */
((u64 *) cxt->pres)[0] = 0; /* phys = 0, size = 0, terminate */
((u64 *) cxt->pres)[1] = 0;
/* keep track of size */
cxt->res_size = cxt->pres + 16 - cxt->pres_begin;
cxt->p_anchor = cxt->pres + 16; /* over the terminator */
}
void ft_begin_tree(struct ft_cxt *cxt)
{
cxt->p_begin = cxt->p_anchor;
cxt->pstr_begin = (char *)cxt->bph + cxt->max_size; /* point at the end */
cxt->p = cxt->p_begin;
cxt->pstr = cxt->pstr_begin;
}
int ft_end_tree(struct ft_cxt *cxt)
{
struct boot_param_header *bph = cxt->bph;
int off, sz, sz1;
u32 tag, v;
char *p;
ft_put_word(cxt, OF_DT_END);
if (cxt->overflow)
return -ENOMEM;
/* size of the areas */
cxt->struct_size = cxt->p - cxt->p_begin;
cxt->strings_size = cxt->pstr_begin - cxt->pstr;
/* the offset we must move */
off = (cxt->pstr_begin - cxt->p_begin) - cxt->strings_size;
/* the new strings start */
cxt->pstr_begin = cxt->p_begin + cxt->struct_size;
/* move the whole string area */
memmove(cxt->pstr_begin, cxt->pstr, cxt->strings_size);
/* now perform the fixup of the strings */
p = cxt->p_begin;
while ((tag = be32_to_cpu(*(u32 *) p)) != OF_DT_END) {
p += 4;
if (tag == OF_DT_BEGIN_NODE) {
p = (char *) _ALIGN((unsigned long)p + strlen(p) + 1, 4);
continue;
}
if (tag == OF_DT_END_NODE || tag == OF_DT_NOP)
continue;
if (tag != OF_DT_PROP)
return -EINVAL;
sz = be32_to_cpu(*(u32 *) p);
p += 4;
v = be32_to_cpu(*(u32 *) p);
v -= off;
*(u32 *) p = cpu_to_be32(v); /* move down */
p += 4;
p = (char *) _ALIGN((unsigned long)p + sz, 4);
}
/* fix sizes */
p = (char *)cxt->bph;
sz = (cxt->pstr_begin + cxt->strings_size) - p;
sz1 = _ALIGN(sz, 16); /* align at 16 bytes */
if (sz != sz1)
memset(p + sz, 0, sz1 - sz);
bph->totalsize = cpu_to_be32(sz1);
bph->off_dt_struct = cpu_to_be32(cxt->p_begin - p);
bph->off_dt_strings = cpu_to_be32(cxt->pstr_begin - p);
/* the new strings start */
cxt->pstr_begin = cxt->p_begin + cxt->struct_size;
cxt->pstr = cxt->pstr_begin + cxt->strings_size;
return 0;
}
/**********************************************************************/
static inline int isprint(int c)
{
return c >= 0x20 && c <= 0x7e;
}
static int is_printable_string(const void *data, int len)
{
const char *s = data;
const char *ss;
/* zero length is not */
if (len == 0)
return 0;
/* must terminate with zero */
if (s[len - 1] != '\0')
return 0;
ss = s;
while (*s && isprint(*s))
s++;
/* not zero, or not done yet */
if (*s != '\0' || (s + 1 - ss) < len)
return 0;
return 1;
}
static void print_data(const void *data, int len)
{
int i;
const char *s;
/* no data, don't print */
if (len == 0)
return;
if (is_printable_string(data, len)) {
printf(" = \"%s\"", (char *)data);
return;
}
switch (len) {
case 1: /* byte */
printf(" = <0x%02x>", (*(char *) data) & 0xff);
break;
case 2: /* half-word */
printf(" = <0x%04x>", be16_to_cpu(*(u16 *) data) & 0xffff);
break;
case 4: /* word */
printf(" = <0x%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU);
break;
case 8: /* double-word */
printf(" = <0x%16llx>", be64_to_cpu(*(u64 *) data));
break;
default: /* anything else... hexdump */
printf(" = [");
for (i = 0, s = data; i < len; i++)
printf("%02x%s", s[i], i < len - 1 ? " " : "");
printf("]");
break;
}
}
void ft_dump_blob(const void *bphp)
{
const struct boot_param_header *bph = bphp;
const u64 *p_rsvmap = (const u64 *)
((const char *)bph + be32_to_cpu(bph->off_mem_rsvmap));
const u32 *p_struct = (const u32 *)
((const char *)bph + be32_to_cpu(bph->off_dt_struct));
const u32 *p_strings = (const u32 *)
((const char *)bph + be32_to_cpu(bph->off_dt_strings));
const u32 version = be32_to_cpu(bph->version);
u32 i, *p, *tagp, *sizep;
char *namep, *datap;
int depth, shift;
u64 addr, size;
if (be32_to_cpu(bph->magic) != OF_DT_HEADER) {
/* not valid tree */
return;
}
depth = 0;
shift = 4;
for (i = 0;; i++) {
addr = be64_to_cpu(p_rsvmap[i * 2]);
size = be64_to_cpu(p_rsvmap[i * 2 + 1]);
if (addr == 0 && size == 0)
break;
printf("/memreserve/ 0x%llx 0x%llx;\n", addr, size);
}
p = (u32 *)p_struct;
while ((p = ft_next(p, p_strings, version, &tagp, &namep, &datap,
&sizep)) != NULL)
switch (be32_to_cpu(*tagp)) {
case OF_DT_BEGIN_NODE:
printf("%*s%s {\n", depth * shift, "", namep);
depth++;
break;
case OF_DT_END_NODE:
depth--;
printf("%*s};\n", depth * shift, "");
break;
case OF_DT_NOP:
printf("%*s[NOP]\n", depth * shift, "");
break;
case OF_DT_END:
break;
case OF_DT_PROP:
printf("%*s%s", depth * shift, "", namep);
print_data(datap, *sizep);
printf(";\n");
break;
default:
fprintf(stderr, "%*s ** Unknown tag 0x%08x\n",
depth * shift, "", *tagp);
return;
}
}
void ft_backtrack_node(struct ft_cxt *cxt)
{
if (be32_to_cpu(*(u32 *) (cxt->p - 4)) != OF_DT_END_NODE)
return; /* XXX only for node */
cxt->p -= 4;
}
/* note that the root node of the blob is "peeled" off */
void ft_merge_blob(struct ft_cxt *cxt, void *blob)
{
struct boot_param_header *bph = (struct boot_param_header *)blob;
u32 *p_struct = (u32 *) ((char *)bph + be32_to_cpu(bph->off_dt_struct));
u32 *p_strings =
(u32 *) ((char *)bph + be32_to_cpu(bph->off_dt_strings));
const u32 version = be32_to_cpu(bph->version);
u32 *p, *tagp, *sizep;
char *namep, *datap;
int depth;
if (be32_to_cpu(*(u32 *) (cxt->p - 4)) != OF_DT_END_NODE)
return; /* XXX only for node */
cxt->p -= 4;
depth = 0;
p = p_struct;
while ((p = ft_next(p, p_strings, version, &tagp, &namep, &datap,
&sizep)) != NULL)
switch (be32_to_cpu(*tagp)) {
case OF_DT_BEGIN_NODE:
if (depth++ > 0)
ft_begin_node(cxt, namep);
break;
case OF_DT_END_NODE:
ft_end_node(cxt);
if (--depth == 0)
return;
break;
case OF_DT_PROP:
ft_prop(cxt, namep, datap, *sizep);
break;
}
}
/**********************************************************************/
void *ft_find_device(const void *bphp, const char *srch_path)
{
const struct boot_param_header *bph = bphp;
u32 *p_struct = (u32 *)((char *)bph + be32_to_cpu(bph->off_dt_struct));
u32 *p_strings= (u32 *)((char *)bph + be32_to_cpu(bph->off_dt_strings));
u32 version = be32_to_cpu(bph->version);
u32 *p, *tagp, *sizep;
char *namep, *datap;
static char path[MAX_PATH_LEN];
path[0] = '\0';
p = p_struct;
while ((p = ft_next(p, p_strings, version, &tagp, &namep, &datap,
&sizep)) != NULL)
switch (be32_to_cpu(*tagp)) {
case OF_DT_BEGIN_NODE:
strcat(path, namep);
if (!strcmp(path, srch_path))
return tagp;
strcat(path, "/");
break;
case OF_DT_END_NODE:
ft_parentize(path, 1);
break;
}
return NULL;
}
int ft_get_prop(const void *bphp, const void *node, const char *propname,
void *buf, const unsigned int buflen)
{
const struct boot_param_header *bph = bphp;
u32 *p_strings= (u32 *)((char *)bph + be32_to_cpu(bph->off_dt_strings));
u32 version = be32_to_cpu(bph->version);
u32 *p, *tagp, *sizep, size;
char *namep, *datap;
int depth;
depth = 0;
p = (u32 *)node;
while ((p = ft_next(p, p_strings, version, &tagp, &namep, &datap,
&sizep)) != NULL)
switch (be32_to_cpu(*tagp)) {
case OF_DT_BEGIN_NODE:
depth++;
break;
case OF_DT_PROP:
if ((depth == 1) && !strcmp(namep, propname)) {
size = min(be32_to_cpu(*sizep), (u32)buflen);
memcpy(buf, datap, size);
return size;
}
break;
case OF_DT_END_NODE:
if (--depth <= 0)
return -1;
break;
}
return -1;
}
static void ft_modify_prop(void **bphpp, char *datap, u32 *old_prop_sizep,
const char *buf, const unsigned int buflen)
{
u32 old_prop_data_len, new_prop_data_len;
old_prop_data_len = _ALIGN(be32_to_cpu(*old_prop_sizep), 4);
new_prop_data_len = _ALIGN(buflen, 4);
/* Check if new prop data fits in old prop data area */
if (new_prop_data_len == old_prop_data_len) {
memcpy(datap, buf, buflen);
*old_prop_sizep = cpu_to_be32(buflen);
}
else { /* Need to alloc new area to put larger or smaller ft */
struct boot_param_header *old_bph = *bphpp, *new_bph;
u32 *old_tailp, *new_tailp, *new_datap;
u32 old_total_size, new_total_size, head_len, tail_len, diff, v;
old_total_size = be32_to_cpu(old_bph->totalsize);
head_len = (u32)datap - (u32)old_bph;
tail_len = old_total_size - (head_len + old_prop_data_len);
old_tailp = (u32 *)((u32)datap + old_prop_data_len);
new_total_size = head_len + new_prop_data_len + tail_len;
if (!(new_bph = malloc(new_total_size))) {
printf("Can't alloc space for new ft\n");
exit();
}
new_datap = (u32 *)((u32)new_bph + head_len);
new_tailp = (u32 *)((u32)new_datap + new_prop_data_len);
memcpy(new_bph, *bphpp, head_len);
memcpy(new_datap, buf, buflen);
memcpy(new_tailp, old_tailp, tail_len);
*(new_datap - 2) = cpu_to_be32(buflen); /* Set prop size */
new_bph->totalsize = cpu_to_be32(new_total_size);
diff = new_prop_data_len - old_prop_data_len;
if (be32_to_cpu(old_bph->off_dt_strings)
> be32_to_cpu(old_bph->off_dt_struct)) {
v = be32_to_cpu(new_bph->off_dt_strings);
new_bph->off_dt_strings = cpu_to_be32(v + diff);
}
if (be32_to_cpu(old_bph->off_mem_rsvmap)
> be32_to_cpu(old_bph->off_dt_struct)) {
v = be32_to_cpu(new_bph->off_mem_rsvmap);
new_bph->off_mem_rsvmap = cpu_to_be32(v + diff);
}
free(*bphpp, old_total_size);
*bphpp = new_bph;
}
}
/*
* - Only modifies existing properties.
* - The dev tree passed in may be freed and a new one allocated
* (and *bphpp set to location of new dev tree).
*/
int ft_set_prop(void **bphpp, const void *node, const char *propname,
const void *buf, const unsigned int buflen)
{
struct boot_param_header *bph = *bphpp;
u32 *p_strings= (u32 *)((char *)bph + be32_to_cpu(bph->off_dt_strings));
u32 version = be32_to_cpu(bph->version);
u32 *p, *tagp, *sizep;
char *namep, *datap;
int depth;
depth = 0;
p = (u32 *)node;
while ((p = ft_next(p, p_strings, version, &tagp, &namep, &datap,
&sizep)) != NULL)
switch (be32_to_cpu(*tagp)) {
case OF_DT_BEGIN_NODE:
depth++;
break;
case OF_DT_PROP:
if ((depth == 1) && !strcmp(namep, propname)) {
ft_modify_prop(bphpp, datap, sizep, buf,
buflen);
return be32_to_cpu(*sizep);
}
break;
case OF_DT_END_NODE:
if (--depth <= 0)
return -1;
break;
}
return -1;
}
[-- Attachment #3: flatdevtree_env.h --]
[-- Type: text/x-chdr, Size: 1142 bytes --]
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _PPC_BOOT_FLATDEVTREE_ENV_H_
#define _PPC_BOOT_FLATDEVTREE_ENV_H_
#include <stdarg.h>
#include <stddef.h>
#include "types.h"
#include "page.h"
#include "string.h"
#include "stdio.h"
#include "ops.h"
#define be16_to_cpu(x) (x)
#define cpu_to_be16(x) (x)
#define be32_to_cpu(x) (x)
#define cpu_to_be32(x) (x)
#define be64_to_cpu(x) (x)
#define cpu_to_be64(x) (x)
#endif /* _PPC_BOOT_FLATDEVTREE_ENV_H_ */
[-- Attachment #4: flatdevtree.h --]
[-- Type: text/x-chdr, Size: 3656 bytes --]
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef FLATDEVTREE_H
#define FLATDEVTREE_H
#include <flatdevtree_env.h>
/* Definitions used by the flattened device tree */
#define OF_DT_HEADER 0xd00dfeed /* marker */
#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
#define OF_DT_END_NODE 0x2 /* End node */
#define OF_DT_PROP 0x3 /* Property: name off, size, content */
#define OF_DT_NOP 0x4 /* nop */
#define OF_DT_END 0x9
#define OF_DT_VERSION 0x10
struct boot_param_header {
u32 magic; /* magic word OF_DT_HEADER */
u32 totalsize; /* total size of DT block */
u32 off_dt_struct; /* offset to structure */
u32 off_dt_strings; /* offset to strings */
u32 off_mem_rsvmap; /* offset to memory reserve map */
u32 version; /* format version */
u32 last_comp_version; /* last compatible version */
/* version 2 fields below */
u32 boot_cpuid_phys; /* Physical CPU id we're booting on */
/* version 3 fields below */
u32 dt_strings_size; /* size of the DT strings block */
};
struct ft_cxt {
struct boot_param_header *bph;
int max_size; /* maximum size of tree */
int overflow; /* set when this happens */
char *p, *pstr, *pres; /* running pointers */
char *p_begin, *pstr_begin, *pres_begin; /* starting pointers */
char *p_anchor; /* start of constructed area */
int struct_size, strings_size, res_size;
};
void ft_begin_node(struct ft_cxt *cxt, const char *name);
void ft_end_node(struct ft_cxt *cxt);
void ft_begin_tree(struct ft_cxt *cxt);
int ft_end_tree(struct ft_cxt *cxt);
void ft_nop(struct ft_cxt *cxt);
void ft_prop(struct ft_cxt *cxt, const char *name,
const void *data, unsigned int sz);
void ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str);
void ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val);
void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size);
void ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size);
void ft_dump_blob(const void *bphp);
void ft_merge_blob(struct ft_cxt *cxt, void *blob);
void *ft_find_device(const void *bphp, const char *srch_path);
int ft_get_prop(const void *bphp, const void *node, const char *propname,
void *buf, const unsigned int buflen);
int ft_set_prop(void **bphp, const void *node, const char *propname,
const void *buf, const unsigned int buflen);
static inline char *ft_strrchr(const char *s, int c)
{
const char *p = s + strlen(s);
do {
if (*p == (char)c)
return (char *)p;
} while (--p >= s);
return NULL;
}
/* 'path' is modified */
static inline void ft_parentize(char *path, u8 leave_slash)
{
char *s = &path[strlen(path) - 1];
if (*s == '/')
*s = '\0';
s = ft_strrchr(path, '/');
if (s != NULL) {
if (leave_slash)
s[1] = '\0';
else if (s[0] == '/')
s[0] = '\0';
}
}
#endif /* FLATDEVTREE_H */
[-- Attachment #5: flatdevtree_misc.c --]
[-- Type: text/x-csrc, Size: 6191 bytes --]
/*
* flatdevtree.c and flatdevtree.h come from <xxx> and are shared with Xen
* and eventually u-boot. However, they don't provide all the functionality
* or the exact interface that the bootwrapper needs. This file does the
* necessary interface mapping and provide the functionality not provided
* by flatdevtree.c.
*
* Author: Mark A. Greer <mgreer@mvista.com>
* Many of the routines related to ft_translate_addr() came
* from arch/powerpc/kernel/prom_parse.c which has no author or
* copyright notice.
*
* 2006 (c) MontaVista, Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include "flatdevtree.h"
#define MAX_ADDR_CELLS 4
#define BAD_ADDR ((u64)-1)
struct ft_bus {
u64 (*map)(u32 *addr, u32 *range, int na, int ns, int pna);
int (*translate)(u32 *addr, u64 offset, int na);
};
static u32 ft_find_cells(char *path, char *prop)
{
void *devp;
u32 num;
char p[MAX_PATH_LEN];
strcpy(p, path);
do {
if ((devp = finddevice(p))
&& (getprop(devp, prop, &num, sizeof(num)) > 0))
return num;
ft_parentize(p, 0);
} while (strlen(p) > 0);
return 1; /* default of 1 */
}
static u64 ft_read_addr(u32 *cell, int size)
{
u64 r = 0;
while (size--)
r = (r << 32) | *(cell++);
return r;
}
static u64 ft_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna)
{
u64 cp, s, da;
cp = ft_read_addr(range, na);
s = ft_read_addr(range + na + pna, ns);
da = ft_read_addr(addr, na);
if (da < cp || da >= (cp + s))
return BAD_ADDR;
return da - cp;
}
static int ft_bus_default_translate(u32 *addr, u64 offset, int na)
{
u64 a = ft_read_addr(addr, na);
memset(addr, 0, na * 4);
a += offset;
if (na > 1)
addr[na - 2] = a >> 32;
addr[na - 1] = a & 0xffffffffu;
return 0;
}
static u64 ft_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna)
{
u64 cp, s, da;
/* Check address type match */
if ((addr[0] ^ range[0]) & 0x03000000)
return BAD_ADDR;
/* Read address values, skipping high cell */
cp = ft_read_addr(range + 1, na - 1);
s = ft_read_addr(range + na + pna, ns);
da = ft_read_addr(addr + 1, na - 1);
if (da < cp || da >= (cp + s))
return BAD_ADDR;
return da - cp;
}
static int ft_bus_pci_translate(u32 *addr, u64 offset, int na)
{
return ft_bus_default_translate(addr + 1, offset, na - 1);
}
static u64 ft_bus_isa_map(u32 *addr, u32 *range, int na, int ns, int pna)
{
u64 cp, s, da;
/* Check address type match */
if ((addr[0] ^ range[0]) & 0x00000001)
return BAD_ADDR;
/* Read address values, skipping high cell */
cp = ft_read_addr(range + 1, na - 1);
s = ft_read_addr(range + na + pna, ns);
da = ft_read_addr(addr + 1, na - 1);
if (da < cp || da >= (cp + s))
return BAD_ADDR;
return da - cp;
}
static int ft_bus_isa_translate(u32 *addr, u64 offset, int na)
{
return ft_bus_default_translate(addr + 1, offset, na - 1);
}
static void ft_match_bus(char *path, struct ft_bus *bus)
{
void *devp;
char dtype[128]; /* XXXX */
if ((devp = finddevice(path)) && (getprop(devp, "device_type", dtype,
sizeof(dtype)) > 0)) {
if (!strcmp(dtype, "isa")) {
bus->map = ft_bus_isa_map;
bus->translate = ft_bus_isa_translate;
} else if (!strcmp(dtype, "pci")) {
bus->map = ft_bus_pci_map;
bus->translate = ft_bus_pci_translate;
} else {
bus->map = ft_bus_default_map;
bus->translate = ft_bus_default_translate;
}
}
}
static int ft_translate_one(char *path, struct ft_bus *bus, struct ft_bus *pbus,
u32 *addr, u32 na, u32 ns, u32 pna)
{
void *devp;
u32 ranges[10 * (na + pna + ns)]; /* XXXX */
u32 *rp;
unsigned int rlen;
int rone;
u64 offset = BAD_ADDR;
if (!(devp = finddevice(path))
|| ((rlen = getprop(devp, "ranges", ranges,
sizeof(ranges))) < 0)
|| (rlen == 0)) {
offset = ft_read_addr(addr, na);
memset(addr, 0, pna * 4);
goto finish;
}
rlen /= 4;
rone = na + pna + ns;
rp = ranges;
for (; rlen >= rone; rlen -= rone, rp += rone) {
offset = bus->map(addr, rp, na, ns, pna);
if (offset != BAD_ADDR)
break;
}
if (offset == BAD_ADDR)
return 1;
memcpy(addr, rp + na, 4 * pna);
finish:
/* Translate it into parent bus space */
return pbus->translate(addr, offset, pna);
}
/* 'addr' is modified */
static u64 ft_translate_addr(const char *p, const u32 *in_addr,
const u32 addr_len)
{
struct ft_bus bus, pbus;
int na, ns, pna, pns;
u32 addr[MAX_ADDR_CELLS];
char path[MAX_PATH_LEN], ppath[MAX_PATH_LEN];
strcpy(ppath, p);
ft_parentize(ppath, 0);
ft_match_bus(ppath, &bus);
na = ft_find_cells(ppath, "#address-cells");
ns = ft_find_cells(ppath, "#size-cells");
memcpy(addr, in_addr, na * 4);
for (;;) {
strcpy(path, ppath);
ft_parentize(ppath, 0);
if (strlen(ppath) == 0)
return ft_read_addr(addr, na);
ft_match_bus(ppath, &pbus);
pna = ft_find_cells(ppath, "#address-cells");
pns = ft_find_cells(ppath, "#size-cells");
if (ft_translate_one(path, &bus, &pbus, addr, na, ns, pna))
exit();
na = pna;
ns = pns;
memcpy(&bus, &pbus, sizeof(struct ft_bus));
}
}
static void *dtb;
static void *ft_finddevice(const char *name)
{
return ft_find_device(dtb, name);
}
static int ft_getprop(const void *node, const char *propname, void *buf,
const int buflen)
{
return ft_get_prop(dtb, node, propname, buf, buflen);
}
static int ft_setprop(const void *node, const char *propname, const void *buf,
const int buflen)
{
return ft_set_prop(&dtb, node, propname, buf, buflen);
}
static void ft_call_kernel(void *entry_addr, unsigned long a1, unsigned long a2,
void *promptr, void *sp)
{
void (*kernel_entry)(void *dt_blob, void *start_addr,
void *must_be_null);
#ifdef DEBUG
printf("kernel:\n\r"
" entry addr = 0x%lx\n\r"
" flattened dt = 0x%lx\n\r",
(unsigned long)entry_addr, dtb);
#endif
kernel_entry = entry_addr;
kernel_entry(dtb, entry_addr, NULL);
}
void ft_init(void *dt_blob)
{
dt_ops.finddevice = ft_finddevice;
dt_ops.getprop = ft_getprop;
dt_ops.setprop = ft_setprop;
dt_ops.translate_addr = ft_translate_addr;
dt_ops.call_kernel = ft_call_kernel;
dtb = dt_blob;
}
^ permalink raw reply
* Re: [PATCH] kdump : Support kernels having 64k page size.
From: Benjamin Herrenschmidt @ 2006-09-07 0:51 UTC (permalink / raw)
To: Haren Myneni; +Cc: linuxppc-dev, Sachin P. Sant
In-Reply-To: <44FE6700.8080504@us.ibm.com>
> At present we are doing the backup of 32K. Thus created one ELF PT_LOAD
> segment for this region.
> But, in the case of 64K page size, second segments starts at 32K and the
> first one is not page aligned. __ioremap() (crash_dump.c) getting
> failed if pfn = 0 which is the case for the second PT_LOAD segment. We
> did not hit this issue for 4K page size because the the first page (32K
> backup) is copied to second kernel memory and thus referencing with the
> second kernel pfn.
>
> Here the fix is, backup regions size is max(PAGE_SIZE, 32K) so that
> at least one page will be part of backup ELF segment. Drawback here is,
> we will end up 32K more for backup for 64K page size.
You should always do 64k regardless of the page size. I think we have
some ABI requirements here for ELF sections to be 64k aligned anyway
no ?
> It can also be fixed in copy_oldmem_page() (crash_dump.c), but first
> PT_LOAD segment is not page aligned:
>
> if (pfn > 0)
> vaddr = __ioremap(pfn << PAGE_SHIFT, PAGE_SIZE, 0);
> else
> vaddr = __va(pfn << PAGE_SHIFT);
^ permalink raw reply
* Re: [Fwd: Re: ohci1394: steps to implement suspend/resume]
From: Benjamin Herrenschmidt @ 2006-09-07 0:53 UTC (permalink / raw)
To: Stefan Richter
Cc: linuxppc-dev, linux1394-devel, Bernhard Kaindl, Pavel Machek
In-Reply-To: <44FEDF5D.9060707@s5r6.in-berlin.de>
On Wed, 2006-09-06 at 16:46 +0200, Stefan Richter wrote:
> Hello LinuxPPC-dev,
>
> we have now patches coming in to fix up the lack of generic suspend +
> resume support in drivers/ieee1394/ohci1394. Attached is the latest and
> by far most functional one by Bernhard Kaindl. A big question is how
> this relates to the already existing PPC-PMAC platform code in
> ohci1394's suspend and resume hooks.
>
> - Which functionalities does the existing platform code provide in
> detail?
>
> - Do we have to keep platform code and generic code separate? I.e.
> #ifdef CONFIG_PPC_PMAC
> ...pmac_call_feature...
> #else
> ...new generic code...
> #endif
>
> - Or are parts of the until now missing, new generic code necessary
> for PMacs too? If yes, is the platform code treated to be the lowest
> level as far as the oreder of code is concerned?
>
> - Or would the platform code be obsolete?
>
> We already broke your platform code once by what was meant as a bugfix
> for non-PMacs. It'd be good to know enough to not repeat such mistakes...
The PowerMac code will stop the chip clocks. It should be used as the
last step of the suspend sequence and first step of the return sequence,
in _addition_ to your new code. Note also that the code you posted lacks
calls to pci_set_power_state()...
Ben.
^ permalink raw reply
* Re: [4/5] powerpc: PA Semi PWRficient platform support
From: Benjamin Herrenschmidt @ 2006-09-07 0:58 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, paulus, anton
In-Reply-To: <20060906101034.404014f7@localhost.localdomain>
> How about I keep it this way until Maple is fixed then? It's better to keep it
> fairly common anyway. Functionally there's no difference.
Well, the platform-open-pic thingy comes from the CHRP spec. I'm no fan
of it but it looks like we do need it on pseries and I haven't
completely given up with having common mpic discovery routine...
> > > + mpic = mpic_alloc(mpic_node, openpic_addr, MPIC_PRIMARY, 0, 0,
> > > + " PAS-OPIC ");
> > > + BUG_ON(mpic == NULL);
> > > +
> > > + mpic_assign_isu(mpic, 0, openpic_addr + 0x10000);
> > > + mpic_init(mpic);
> >
> > Very nice, I'll convert maple to do the same (unless someone beats
> > me to it, heh).
>
> Maple isn't that different there. It just has to deal with multiple ISUs,
> while we currently only have one.
Maple doesn't have multiple ISUs
Ben.
^ permalink raw reply
* Re: [4/5] powerpc: PA Semi PWRficient platform support
From: Benjamin Herrenschmidt @ 2006-09-07 0:58 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Olof Johansson, linuxppc-dev, paulus, anton
In-Reply-To: <E2C62E02-AB23-451F-8A82-718A13B675BE@kernel.crashing.org>
On Wed, 2006-09-06 at 17:26 +0200, Segher Boessenkool wrote:
> >> Very nice, I'll convert maple to do the same (unless someone beats
> >> me to it, heh).
> >
> > Maple isn't that different there. It just has to deal with multiple
> > ISUs,
> > while we currently only have one.
>
> Maple has only one as well, that's the point :-)
> It gets the ISU address from that awful platform-open-pic
> property currently, hardcoding it like you did for PA6T is
> just fine though. It simplifies the code quite a bit and
> doesn't depend on this undocumented (and badly defined no
> matter what) device tree property.
It's perfectly documented :)
Ben.
^ permalink raw reply
* RE: Wireless Linux(802.11) for Embedded PowerPC
From: Chun Chung Lo @ 2006-09-07 1:23 UTC (permalink / raw)
To: John W. Linville; +Cc: wei.li4, linuxppc-embedded
Hi,
This project is my university graduation project, so it is now stopped.
(I just finished some ugly prototypes :)
As I said before, I used ELDK for my project (since I am a student at
that moment, I really do not know how to manually build/compile a GNU
cross-platform toolchains), there is no WLAN drivers bundled inside the
toolkit. Also my WLAN card is based on Intersil Prism 2 chipset, so my
only choice is linux-wlan package. I do not know the project status, but
the driver stability seems OK for me. (No crash occurred during I do so
many ugly tests :)
But the performance and the compatibilty is quite good (provided that
the PCMCIA socket drirver is working properly) for a such small system
(MPC860 @ 50MHz).
Also I cannot see any drivers existing in the upstream kernel are really
support the "Intersil Prism 2 WLAN" cards (my card is differ from those
Orinoco cards and Hermes cards, also the drivers are also differ a lot).
If you are going to use Intersil Prism 2 cards/chips, I would suggest
you to use the linux-wlan driver (but seems this driver does not support
AP mode yet...)
Thanks.
Best regards,
Lo Chun Chung
-----Original Message-----
From: John W. Linville [mailto:linville@tuxdriver.com]=0D
Sent: Wednesday, 06 September, 2006 9:58 PM
To: Chun Chung Lo
Cc: wei.li4@elf.mcgill.ca; linuxppc-embedded@ozlabs.org
Subject: Re: Wireless Linux(802.11) for Embedded PowerPC
On Wed, Sep 06, 2006 at 09:30:00AM +0800, Chun Chung Lo wrote:
> 1. WLAN card driver: linux-wlan -- http://www.linux-wlan.org/
Is this project even still active? The last update to the page was 2.5
years ago (2/2004), and many of the links are broken...
Do the prism drivers in the upstream kernel not work for you?
John
--=0D
John W. Linville
linville@tuxdriver.com
This message (including any attachments) is for the named addressee(s)'s=
use only. It may contain
sensitive, confidential, private proprietary or legally privileged=
information intended for a
specific individual and purpose, and is protected by law. If you are not=
the intended recipient,
please immediately delete it and all copies of it from your system, destroy=
any hard copies of it
and notify the sender. Any use, disclosure, copying, or distribution of=
this message and/or any
attachments is strictly prohibited.
^ permalink raw reply
* Re: pci error recovery procedure
From: Zhang, Yanmin @ 2006-09-07 1:56 UTC (permalink / raw)
To: Linas Vepstas
Cc: Yanmin Zhang, LKML, Rajesh Shah, linuxppc-dev, linux-pci maillist
In-Reply-To: <20060906200155.GL7139@austin.ibm.com>
On Thu, 2006-09-07 at 04:01, Linas Vepstas wrote:
> On Wed, Sep 06, 2006 at 09:26:56AM +0800, Zhang, Yanmin wrote:
> > > > The
> > > > error_detected of the drivers in the latest kernel who support err handlers
> > > > always returns PCI_ERS_RESULT_NEED_RESET. They are typical examples.
> > >
> > > Just because the current drivers do it this way does not mean that this is
> > > the best way to do things.
> >
> > If it's not the best way, why did you choose to reset slot for e1000/e100/ipr
> > error handlers? They are typical widely-used devices. To make it easier to
> > add error handlers?
>
> I did it that way just to get going, get something working. I do not
> have hardware specs for any of these devices, and do not have much of
> an idea of what they are capable of;
Yes, it's difficult to add fine-grained error handlers for guys who are not
the driver developers.
> the recovery code I wrote is of
> "brute force, hit it with a hammer"-nature. Driver writers who
> know thier hardware well, and are interested in a more refined
> approach are encouraged to actualy use a more refined approach.
I guess almost no driver developer is happy to spend lots of time to
add refined steps. They would like to focus on normal process (for achievement
feeling? :) ).
In addition, if they use fine-grained steps in error handlers, all these
steps might be rewritten when the device specs is upgraded. Fine-grained steps in
error handlers are more difficut to debug.
It's impossible for you to develop error handlers for all device drivers.
The error handlers look a little like suspend/resume. Of course, it's more
complicated. If we could keep it as simple as suspend/resume, it's more welcomed.
pci error shouldn't happen frequently. And when it happens, I think mostly it's
an endpoint device instead of bridge. When it happens, if we choose always
reset slot, performance could be degraded, but not too much. I just deduce, and
didn't test it on a machine with hundreds of devices.
^ permalink raw reply
* Re: pci error recovery procedure
From: Zhang, Yanmin @ 2006-09-07 3:18 UTC (permalink / raw)
To: Linas Vepstas
Cc: linuxppc-dev, linux-pci maillist, Yanmin Zhang, LKML, Rajesh Shah
In-Reply-To: <20060906203939.GM7139@austin.ibm.com>
On Thu, 2006-09-07 at 04:39, Linas Vepstas wrote:
> On Wed, Sep 06, 2006 at 10:04:31AM +0800, Zhang, Yanmin wrote:
> > On Wed, 2006-09-06 at 03:17, Linas Vepstas wrote:
> > > On Mon, Sep 04, 2006 at 01:47:30PM +0800, Zhang, Yanmin wrote:
> > > > >
> > > > > Again, consider the multi-function cards. On pSeries, I can only enable
> > > > > DMA on a per-slot basis, not a per-function basis. So if one driver
> > > > > enables DMA before some other driver has reset appropriately, everything
> > > > > breaks.
> > > > Does here 'reset' mean hardware slot reset?
> > >
> > > I should have said: If one driver of a multi-function card enables DMA before
> > > another driver has stabilized its harware, then everything breaks.
> > What's another driver's hardware? A function of the previous multi-function
> > card? Or a function of another device?
>
> Yes. Either. Both. Doesn't matter. Enabling DMA is "granular" at a
> different size scale than pci functions, and possibly even pci devices
> or slots, dependeing on the architecture. Before DMA can be enabled,
> *all* affected device drivers have to be approve, and have to be ready
> for it.
> > > If we enabled both DMA and MMIO at the same time, there are many cases
> > > where the card will immediately trap again -- for example, if its
> > > DMA'ing to some crazy address. Thus, typically, one wants DMA disabled
> > > until after the card reset. Without the mmio_enabled() reset, there
> > > is no way of doing this.
> >
> > Did you asume the card reset is executed by callback mmio_enabled?
>
> I am assuming that, when a driver receives the mmio_enabled() callback,
> it will perform some sort of register i/o. For example, I am currently
> planning to modify the e1000 driver to do the following:
>
> -- The error_occurred() callback returns PCI_ERS_RESULT_CAN_RECOVER
> -- The arch enables mmio, and then calls the mmio_enabled() callback.
> -- The mmio_enabled() callback in the driver takes a full dump of all
> of the regsters on the card. It then returns PCI_ERS_RESULT_NEED_RESET
Such dumping are random data and might be useless. The error recovery procedures
are to process pci hardware errors instead of device driver bug.
> -- The arch performs the full electrical #RST of device. Recovery from
> this point proceeds as before.
The steps are exquisite. Scenario:
The e1000 NIC and another device (maybe a function) are on the same bus. The
error_detected of the second device returns PCI_ERS_RESULT_NEED_RESET, so although
error_detected of e1000 returns PCI_ERS_RESULT_CAN_RECOVER, the slot will
be reset immediately, then error recovery will go to call slot_reset callback
directly. The mmio_enabled is not called.
My above scenario is just to say something is easy to be out of control if the steps
are complicated.
>
> > > Again, consider the multi-function cards. On pSeries, I can only enable
> > > DMA on a per-slot basis, not a per-function basis. So if one driver
> > > enables DMA before some other driver has reset appropriately, everything
> > > breaks.
> >
> > What does 'I' above stand for? The platform error recovery procedure
>
> Yes. The pSeries platform error recovery procedure can only enable DMA
> on a per-slot basis.
>
> > I guess it means platform, that is,
> > only platform enables DMA for the whole slot.
>
> Yes.
>
> > But why does the last sentence
> > become driver enables DMA?
>
> In your proposal, you were suggesting that MMIO and DMA be enabled with
> one and the same routine, and I was attempting to explain why that can't
> work.
Thanks for your explanations. My point is that if driver could enable DMA,
it could do so in the new error_resume. Driver should do more checking before
enabling DMA.
Your scenario only exists when:
1) Only platform could enable DMA and enable it per-slot instead of per-function.
2) And at least one device doesn't want a hard slot reset to recover while
all other impacted devices also don't want a hard slot; Because if one device want a
hard reset, mmio_enabled of all impacted drivers won't be called.
3) And at least one device's DMA is crazy.
If using my new API, I just need destroy one condition above. My requirement is:
Only if a device uses DMA and the driver is not sure or sure if DMA is pending,
its error_detected should return PCI_ERS_RESULT_NEED_RESET. Otherwise, error_detected
is allowed to return whatever.
>
> > Could driver enable DMA for a function?
>
> No, not on pSeries hardware.
>
> > > > If mmio_enabled is not used currently, I think we could delete it firstly. Later on,
> > > > if a platform really need it, we could add it, so we could keep the simplied codes.
> > >
> > > It would be very difficult to add it later. And it would be especially
> > > silly, given that someone would find this discussion in the mailing list
> > > archives.
> > You stick to keep mmio_enabled which is not used currently, but if there will be
> > a new platform who uses a more fine-grained steps to recover pci/pci-e, would
> > you say 'it would be very difficut' and refuse add new callbacks?
>
> Yes.
It's not fare to such other platforms although I have no such example now.
>
> > It doesn't prevent software from merging some steps. And, we want
> > to implement pci/pci-e error recovery for more platforms instead of just
> > pSeries.
>
> Yes. The API was designed so that it could be supported on every
> current and future platform we could think of. You haven't yet
> claimed that "pci-e can't be supported".
Current error handler infrastructure could support pci-e, but I want a better
solution to faciliate driver developers to add error handlers more easily. My
startpoint is driver developer. If they are not willing to add error handlers,
it's impossible to do so for all drivers by you and me.
> Based on what
> I understand, changing the API wouldn't make the implementation
> any easier. (It is very easy to call a callback, and then
> examine its return value.
It's not easy. Just like above scenario, mmio_enabled might be jumped over when
coordinating 2 more devices.
Checking current e100/e1000/ipr error handlers, they look ugly.
> Removing a few callbacks does not
> materially simplify the recovery mechanism. Managing these
> callbacks is *not* the hard part of implementing this thing.)
Above comments are totally from error recovery design point of view. No considering
for driver developers.
BTW, most discussion is about if mmio_enabled should be deleted. As for merging
slot_reset and resume, my reason is that there is no platform specific operation
between calling slot_reset and resume.
Yanmin
^ permalink raw reply
* Re: common flatdevtree code
From: Hollis Blanchard @ 2006-09-07 7:43 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20060907003625.GA15533@mag.az.mvista.com>
Thanks Mark!
On Wed, 2006-09-06 at 17:36 -0700, Mark A. Greer wrote:
> void *ft_find_device(const void *bphp, const char *srch_path)
How about "ft_find_node"? I renamed that and made a couple other small
changes. In particular:
- u8->int
- exit and free -> ft_exit and ft_free (so they can be wrapped in
flatdevtree_env.h)
- moved those inlines out of flatdevtree.h, since they don't need to be
exported
I just put up a Mercurial tree. I didn't include your flatdevtree_misc.c
since it's kernel-specific, and I added a userspace flatdevtree_env.h.
To get the source:
hg clone http://unsanctioned.org/flatdevtree/hgweb.py flatdevtree
I'd like to add some unit tests in the near future (e.g. comparing with
dtc output), but I wasted a couple hours screwing with a makefile
instead. :(
By the way, could you send a patch adding your copyright info?
-Hollis
^ permalink raw reply
* MPC8360E USB Host Controller Driver
From: n.balaji @ 2006-09-07 8:03 UTC (permalink / raw)
To: linuxppc-embedded
Hi All,
I am working in MPC8360E processor board. I want the PowerQUICC II's
Pro USB Host controller Driver. In the manual, they told that this
controller does not belong to UHCI or OHCI standard.
I have doubt that whether Freescale has its own USB standard.
Please give the link or patch for that driver.
Thanks,
N.Balaji
^ permalink raw reply
* RE: MPC8360E USB Host Controller Driver
From: Li Yang-r58472 @ 2006-09-07 8:25 UTC (permalink / raw)
To: n.balaji, linuxppc-embedded
In-Reply-To: <16599.202.144.30.226.1157616213.squirrel@mail.gdatech.co.in>
> -----Original Message-----
> From:=20
> linuxppc-embedded-bounces+leoli=3Dfreescale.com@ozlabs.org=20
> [mailto:linuxppc-embedded-bounces+leoli=3Dfreescale.com@ozlabs.o
> rg] On Behalf Of n.balaji@gdatech.co.in
> Sent: Thursday, September 07, 2006 4:04 PM
> To: linuxppc-embedded@ozlabs.org
> Subject: MPC8360E USB Host Controller Driver
>=20
> Hi All,
> I am working in MPC8360E processor board. I want the=20
> PowerQUICC II's Pro USB Host controller Driver. In the=20
> manual, they told that this controller does not belong to=20
> UHCI or OHCI standard.
Yes, you can call it FHCI if you like. :)
>=20
> I have doubt that whether Freescale has its own USB standard.
The interface is stated clearly in the UM.
>=20
> Please give the link or patch for that driver.
There is an 8360 host driver in Freescale LTIB BSP. Please find it on
www.freescale.com, if it has been released.
- Leo
^ permalink raw reply
* Re: could not access the address in linux-System ace driver
From: sudheer @ 2006-09-07 8:40 UTC (permalink / raw)
To: linuxppc-embedded; +Cc: Raja Chidambaram
In-Reply-To: <44F6CB23.3000802@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 8599 bytes --]
Hi
>
> Raja Chidambaram wrote:
>> Hello Sudheer,
>>
>> Sorry for the Late reply.since we faced some
>> complexity in this kind of system Ace setup we have
>> dropped it & moved to different setup.
>>
>> As of now in your case trace the xilinx code which is
>> bascially on adapter.c as for as the xilinix code is
>> concerned the hardware initialization code are done
>> by xilinux, And only the kernel integration code
>> developed by open source developers.So u might to
>> track
>> this cahnges
>>
>> As u said your xilinx is connected to EBC make sure
>> the power on cycles is perfomed with no errrors.
>>
>> As for as your base register for xilinux is concerned
>> the u-boot handle same as linux but the AMCC 440SPe
>> processor have differnet TLB type so please make
>> sure u understand TLB for 440SPe.
>>
>>
>>
I got solved the issue by changing the ioremap function usage. The
PPC440 implements a 36 bit memory map. So i changed my ioremap to
ioremap64 and gave the 36-bit physical address which includes EPN and is
0x5d0000000ULL and it returns a 32-bit virtual pointer with which am
able to access the device registers.
Thanks Raja and all for your kindly help.
Thanks
Sudheer
>>
> Can you please send some links if available that tells about the TLBs
> in 440SPe. I have googled but could not get much information.
>
> Thanks
> Sudheer
>>
>>
>>
>>
>>
>> --- sudheer <urwithsudheer@gmail.com> wrote:
>>
>>
>>> Hello All
>>>
>>> I'm really desperate for some help , I've been
>>> struggling with this
>>> system since few days.
>>>
>>> sudheer wrote:
>>>
>>>> Hello Raja,
>>>>
>>>> We too are working on customized board with amcc
>>>>
>>> 440SPe processor ,
>>>
>>>> xilinx System Ace controller. Compact flash is
>>>>
>>> connected to system
>>>
>>>> ace controller.
>>>> We use u-boot 1.1.2 as bootloader & linux kernel -
>>>>
>>> 2.6.16-2.
>>>
>>>> System ace is connected to amcc440SPE processor
>>>>
>>> via GPIO and External
>>>
>>>> Peripheral Bus Controller(EBC).
>>>>
>>> I am still facing the issue in accessing the address
>>> in linux.
>>>
>>> The physical address given in u-boot init.S
>>> tlbentry for 'system ace'
>>> is 0xE0000000
>>> I am able to access the address in u-boot and
>>> everything is fine in u-boot.
>>> But in linux , I am able to ioremap the the address
>>> 0xE0000000 but the
>>> kernel crashes when i try to access the address .
>>> physical address=0xe0000000
>>> address_after_ioremap = 0xe1000000.
>>> I am trying to read with
>>> readw(address_after_ioremap)
>>> The kernel gives an exception error saying Oops:
>>> machine check, sig: 7
>>> [#2] .
>>> The error dump is as below:
>>>
>>> Instruction dump:
>>> Data machine check in kernel mode.
>>> PLB0: BEAR=0x00000000e0000000 ACR= 0xdb000000 BESR=
>>> 0x0000000000008000
>>> PLB1: BEAR=0xe98d7ad33716ee7e ACR= 0xdb000000 BESR=
>>> 0x0000000000000000
>>> POB0: BEAR=0x0000000fffaebbcd BESR0=0x00000000
>>> BESR1=0x00000000
>>> OPB0: BEAR=0x0000000000000000 BSTAT=0x00000000
>>> Oops: machine check, sig: 7 [#2]
>>> NIP: 00000000 LR: C0002200 CTR: 00000000
>>> REGS: c0241f50 TRAP: 0202 Not tainted (2.6.16.2)
>>> MSR: 00000000 <> CR: 84CA4124 XER: 00000000
>>> TASK = dff6cb70[1] 'swapper' THREAD: c0740000
>>> GPR00: 00000000 C0241E40 DFF6CB70 00000001 FFFFFFD0
>>> 00000000 C0240000
>>> C01F3C0C
>>> GPR08: C01F0000 C0002200 00021002 C0001FF4 DFF6CD38
>>> 802823E0 1FFB9600
>>> 00000000
>>> GPR16: 00000001 FFFFFFFF 00000000 007FFF00 1FFB3540
>>> 1FF63CE0 1FFCEE78
>>> C01C0000
>>> GPR24: C01C0000 C01C0000 C01F0000 C01C0000 BFFFFFFF
>>> FFFFFFD0 00000000
>>> C0241F50
>>> NIP [00000000] 0x0
>>> LR [C0002200] ret_from_except+0x0/0x18
>>> Call Trace:
>>> Instruction dump:
>>> Data machine check in kernel mode.
>>> PLB0: BEAR=0x00000000e0000000 ACR= 0xdb000000 BESR=
>>> 0x0000000000008000
>>> .........and this dump gets print continously.
>>>
>>>
>>> I have checked with TLB entries in u-boot and linux
>>> using BDI:
>>>
>>> BDI_AMCC440SPe>tlb 0 10
>>> IDX TID EPN SIZE VTS RPN USER WIMGE
>>> USRSVC
>>> 0 : 00 ff000000 16MB V0 -> 4_ff000000 U:0000 WI-G-
>>> XWRXWR
>>> 1 : 00 00000000 256MB V0 -> 0_00000000 U:0000 -I-G-
>>> XWRXWR
>>> 2 : 00 10000000 256MB V0 -> 0_10000000 U:0000 -I-G-
>>> XWRXWR
>>> 3 : 00 20000000 256MB V0 -> 0_20000000 U:0000 -I-G-
>>> XWRXWR
>>> 4 : 00 30000000 256MB V0 -> 0_30000000 U:0000 -I-G-
>>> XWRXWR
>>> 5 : 00 90000000 256KB V0 -> 4_00000000 U:0000 -I---
>>> XWRXWR
>>> 6 : 00 e0000000 1KB V0 -> 4_e0000000 U:0000 -I-G-
>>> -WR-WR
>>> 7 : 00 a0000000 4KB V0 -> 4_f0000000 U:0000 -I-G-
>>> -WR-WR
>>> 8 : 00 d0000000 256MB V0 -> c_00000000 U:0000 -I-G-
>>> -WR-WR
>>> 9 : 00 80000000 256MB V0 -> c_10000000 U:0000 -I-G-
>>> -WR-WR
>>> 10 : 00 01080000 1KB -0 -> 0_00000000 U:0000 -----
>>> ------
>>> BDI_AMCC440SPe>
>>>
>>> In Linux the tlb entries are as below.......
>>>
>>> BDI_AMCC440SPe>tlb 0 63
>>> IDX TID EPN SIZE VTS RPN USER WIMGE
>>> USRSVC
>>> 0 : 0e 0ff1a000 4KB V0 -> 0_007ce000 U:0000 --MG-
>>> --R--R
>>> 1 : 0e 0fe94000 4KB V0 -> 0_1ff96000 U:0000 ---G-
>>> X-RX-R
>>> 2 : 0e 30017000 4KB V0 -> 0_007cd000 U:0000 --MG-
>>> --R-WR
>>> 3 : 0e 10039000 4KB V0 -> 0_1ffb8000 U:0000 ---G-
>>> X-RX-R
>>> 4 : 0e 30009000 4KB V0 -> 0_00758000 U:0000 ---G-
>>> X-RX-R
>>> 5 : 0e 30010000 4KB V0 -> 0_0078b000 U:0000 ---G-
>>> X-RX-R
>>> 6 : 0e 00000000 1KB -0 -> 0_1f4e2000 U:0000 ---G-
>>> --R--R
>>> 7 : 0e 0fe3e000 4KB V0 -> 0_1f4e2000 U:0000 ---G-
>>> X-RX-R
>>> 8 : 0e 0ff1c000 4KB V0 -> 0_007ed000 U:0000 --MG-
>>> XWRXWR
>>> 9 : 0e 0ff1e000 4KB V0 -> 0_007ee000 U:0000 --MG-
>>> -WR-WR
>>> 10 : 0e 0ff1f000 4KB V0 -> 0_007ea000 U:0000 --MG-
>>> XWRXWR
>>> 11 : 0e 0fe39000 4KB V0 -> 0_1ff8e000 U:0000 ---G-
>>> X-RX-R
>>> 12 : 0e 0ff21000 4KB V0 -> 0_007a8000 U:0000 --MG-
>>> --R-WR
>>> 13 : 0e 0fe47000 4KB V0 -> 0_1ffa9000 U:0000 ---G-
>>> X-RX-R
>>> 14 : 0e 0fe46000 4KB V0 -> 0_1ffb2000 U:0000 ---G-
>>> X-RX-R
>>> 15 : 0e 30019000 4KB V0 -> 0_007c5000 U:0000 --MG-
>>> -WR-WR
>>> 16 : 0e 0fe45000 4KB V0 -> 0_1ffa8000 U:0000 ---G-
>>> X-RX-R
>>> 17 : 00 fdfff000 4KB V0 -> 4_f0000000 U:0000 -IMG-
>>> ----WR
>>> 18 : 0e 0fe9a000 4KB V0 -> 0_1ff98000 U:0000 ---G-
>>> X-RX-R
>>> 19 : 0e 10067000 4KB V0 -> 0_0078e000 U:0000 --MG-
>>> -WR-WR
>>> 20 : 0e 00000000 4KB -0 -> 0_1f4e5000 U:0000 ---G-
>>> --R--R
>>> 21 : 0e 10030000 4KB V0 -> 0_1f4e5000 U:0000 ---G-
>>> X-RX-R
>>> 22 : 0e 10063000 4KB V0 -> 0_007b7000 U:0000 --MG-
>>> -WR-WR
>>> 23 : 0e 0fe4c000 4KB V0 -> 0_1ff9b000 U:0000 ---G-
>>> X-RX-R
>>> 24 : 0e 1007f000 4KB V0 -> 0_007e0000 U:0000 --MG-
>>> -WR-WR
>>> 25 : 0e 0ff1d000 4KB V0 -> 0_007c6000 U:0000 --MG-
>>> --R-WR
>>> 26 : 0e 0fe4e000 4KB V0 -> 0_1ffa1000 U:0000 ---G-
>>> X-RX-R
>>> 27 : 0e 0fe0f000 4KB V0 -> 0_0077e000 U:0000 ---G-
>>> X-RX-R
>>> 28 : 0e 0fe52000 4KB V0 -> 0_0077f000 U:0000 ---G-
>>> X-RX-R
>>> 29 : 0e 0fe53000 4KB V0 -> 0_1ff80000 U:0000 ---G-
>>> X-RX-R
>>> 30 : 0e 0fef9000 4KB V0 -> 0_1ff81000 U:0000 ---G-
>>> --R--R
>>> 31 : 0e 0fe3b000 4KB V0 -> 0_1ffa7000 U:0000 ---G-
>>> X-RX-R
>>> 32 : 0e 7f901000 4KB V0 -> 0_007db000 U:0000 --MG-
>>> -WR-WR
>>> 33 : 0e 10027000 4KB V0 -> 0_1ffd0000 U:0000 ---G-
>>> X-RX-R
>>> 34 : 0e 1003a000 4KB V0 -> 0_1ffb6000 U:0000 ---G-
>>> X-RX-R
>>> 35 : 0e 0fe51000 4KB V0 -> 0_00775000 U:0000 ---G-
>>> X-RX-R
>>> 36 : 0e 1003b000 4KB V0 -> 0_1ffb7000 U:0000 ---G-
>>> X-RX-R
>>> 37 : 0e 1002a000 4KB V0 -> 0_1ffcf000 U:0000 ---G-
>>> X-RX-R
>>> 38 : 0e 10066000 4KB V0 -> 0_007de000 U:0000 --MG-
>>> -WR-WR
>>> 39 : 0e 1002b000 4KB V0 -> 0_1ffd3000 U:0000 ---G-
>>> X-RX-R
>>> 40 : 0e 1002c000 4KB V0 -> 0_1ffd2000 U:0000 ---G-
>>> X-RX-R
>>> 41 : 0e 1005d000 4KB V0 -> 0_007f4000 U:0000 --MG-
>>> XWRXWR
>>> 42 : 0e 1002d000 4KB V0 -> 0_1ffc2000 U:0000 ---G-
>>> X-RX-R
>>> 43 : 0e 10028000 4KB V0 -> 0_1ffc8000 U:0000 ---G-
>>> X-RX-R
>>> 44 : 0e 10069000 4KB V0 -> 0_0078d000 U:0000 --MG-
>>> -WR-WR
>>>
>>>
>> === message truncated ===
>>
>>
>> __________________________________________________
>> Do You Yahoo!?
>> Tired of spam? Yahoo! Mail has the best spam protection around
>> http://mail.yahoo.com
>>
>>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
[-- Attachment #2: Type: text/html, Size: 9552 bytes --]
^ permalink raw reply
* Re: SystemAce Driver.
From: sudheer @ 2006-09-07 9:05 UTC (permalink / raw)
To: Ameet Patil; +Cc: linuxppc-embedded
In-Reply-To: <44DC4F34.1070308@gmail.com>
Hi Ameet Patil
Ameet Patil wrote:
> Hi Sudheer,
> Frank has already answered your questions. If you have any problems
> with the SysAce patch... do let me know. I have written a small
> tutorial here if it helps...
I have used your SystemAce patch with linux-2.6.16-2. The kernel gets
loaded with the ace module and is fine.
I want the driver in polling mode. So i have commented few lines related
to interrupt in the adapter.c file- xsysace_init function.
When i give the fdisk command, it gives few errors and then enters to
the fdisk commad promt. It prints the partitions, etc.
But when i try to quit from the fdisk, it hangs. I am not able to
complete the request properly (i guess in xsa_thread function in
adapter.c file)
The dump is as follows:
SystemACE: Error 1 when reading sector 60.
end_request: I/O error, dev xsa, sector 56
SystemACE: Error 1351 when reading sector 62.
end_request: I/O error, dev xsa, sector 56
Command (m for help): p
Disk /dev/xsysace: 512 MB, 512483328 bytes
16 heads, 62 sectors/track, 1009 cylinders
Units = cylinders of 992 * 512 = 507904 bytes
Device Boot Start End Blocks Id System
/dev/xsysace1 1 1009 500433 6 FAT16
Command (m for help): q
-------
The fdisk enters into xsysace_ioctl function but no commands are
implemented in the ioctl function and returns an error.
Please help me in this issue and let me know if any other details required.
Thanks
Sudheer
>
> http://linux.get2knowmore.com
>
>
> -Ameet
>
> sudheer wrote:
>> Hello Ameet Patil
>>
>> I am looking for linux kernel source 2.6.16 with system ace
>> controller support. I downloaded the linux-2.6.16 and linux-2.6.17-1
>> source from kernel.org but could not find any files related to system
>> ace controller ( No xilinx_sysace directory in drivers/block/) . I
>> have checked penguinppc.org also but could not get it.
>>
>> Can you please send to me the link where i could download the
>> linuxppc-2.6.16 source with system ace support.
>>
>> Thanks & Regards
>> Sudheer
>>
>> Ameet Patil wrote:
>>> Hi Raja,
>>> I have ported the Xilinx System ACE driver to 2.6 kernel. Find
>>> the latest one here:
>>> http://www.cs.york.ac.uk/rtslab/demos/amos/xupv2pro/patches/linuxppc-2.6.17.1-sysace-1.2.patch
>>>
>>>
>>> NOTE: this patch wouldn't work if you are using the TEMAC driver. In
>>> which case use the -after-TEMAC patch found in the patches folder
>>> above.
>>>
>>> Check the following discussions (threads) for more details:
>>> 1. "Xilinx SystemACE driver for 2.6"
>>> 2. "Xilinx BSP for linux 2.6"
>>> 3. "Kernel hangs after "Now booting the kernel"."
>>>
>>> cheers,
>>> -Ameet
>>>
>>> Raja Chidambaram wrote:
>>>
>>>> Hi all,
>>>> We are working on customized board with amcc 440SPe
>>>> processor & xilinx System Ace controller. The System
>>>> Ace controller is connected to compact flash driver.
>>>>
>>>> We use u-boot 1.2 as bootloader & linux kernel
>>>> 2.6.16-2.
>>>>
>>>> On the process the u-boot is able to detect compact
>>>> flash through Xilinx SystemAce controller & able to
>>>> load the kernel image into compact flash.But when the
>>>> linux boot's up it not able to detect the System Ace
>>>> controller or compact flash.
>>>>
>>>> Note:we need to have the root file system in compact
>>>> flash.
>>>>
>>>> Is their any drivers available for SystemAce
>>>> controller on linux 2.6,if their how to get it.please
>>>> help me in this
>>>> with regards
>>>> raja
>>>>
>>>>
>>>>
>>>> __________________________________________________
>>>> Do You Yahoo!?
>>>> Tired of spam? Yahoo! Mail has the best spam protection around
>>>> http://mail.yahoo.com _______________________________________________
>>>> Linuxppc-embedded mailing list
>>>> Linuxppc-embedded@ozlabs.org
>>>> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>>>>
>>>>
>>> _______________________________________________
>>> Linuxppc-embedded mailing list
>>> Linuxppc-embedded@ozlabs.org
>>> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>>>
>>>
>>
>
^ permalink raw reply
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