* Re: [PATCH] ppc32: Remove CONFIG_PMAC_PBOOK
From: Benjamin Herrenschmidt @ 2005-06-28 23:52 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Andrew Morton, linuxppc-dev list, Linux Kernel list
In-Reply-To: <931dc22c9709211c29f2d9d504d8ff9e@kernel.crashing.org>
On Tue, 2005-06-28 at 09:43 +0200, Segher Boessenkool wrote:
> > This patch removes CONFIG_PMAC_PBOOK (PowerBook support). This is now
> > split into CONFIG_PMAC_MEDIABAY for the actual hotswap bay that some
> > powerbooks have, CONFIG_PM for power management related code, and just
> > left out of any CONFIG_* option for some generally useful stuff that
> > can
> > be used on non-laptops as well.
>
> Is there any real reason not to enable CONFIG_PM on all Macs
People using old desktop machines with little memory may want to keep
the RAM footprint low :)
Ben.
^ permalink raw reply
* Re: [PATCH] 8xx: map_page() skip pinned region and tlbie debugging aid
From: Benjamin Herrenschmidt @ 2005-06-28 23:47 UTC (permalink / raw)
To: Dan Malek; +Cc: linux-ppc-embedded
In-Reply-To: <3e7207cd8e98080f2f469a668e37a20f@embeddededge.com>
On Tue, 2005-06-28 at 09:53 -0400, Dan Malek wrote:
> On Jun 28, 2005, at 2:30 AM, Benjamin Herrenschmidt wrote:
>
> > You should consider 8Mb pages the way we do BATs yes,
>
> It's always been considered, just never fully implemented :-)
>
> > Note that I'll soon send the patch I told you about that makes the
> > virtual address picked by io_block_mapping() dynamic, so we no longer
> > have to do crappy assumptions all over the place :)
>
> Whatever, I'll never use it that way and no one else should either.
That is stupid
> All of the io_block_mapping() calls should be used to set these 8M
I think you just never bothered actually reading all I wrote about
that... None of what you describe requires hard coding the virtual
address. This is just plain bad.
> mapped IO spaces, everyone should use ioremap() to map them,
> and ioremap() has to be modified to find them for the 8xx.
We agree here.
^ permalink raw reply
* [Fwd: [PATCH] PPC32 mem_pieces interface cleanup]
From: Jon Loeliger @ 2005-06-28 20:22 UTC (permalink / raw)
To: linuxppc-dev@ozlabs.org
Well, Ben suggested I send it here too...
And Kumar abused me too. Want to see my scar?
jdl
-----Forwarded Message-----
From: Jon Loeliger <jdl@freescale.com>
To: linuxppc-embedded@ozlabs.org <linuxppc-embedded@ozlabs.org>
Subject: [PATCH] PPC32 mem_pieces interface cleanup
Date: Mon, 27 Jun 2005 11:28:50 -0500
Guys,
As an initial step towards getting the OF Flat Dev tree
handled in the PPC32 tree, this patch cleans up some of
the interface parts of the very early mem_pieces manager
and adds some PPC64-LMB-like routines as well.
It has been built and booted on 85xx and pmac boards.
Thanks,
jdl
Signed-off-by: Jon Loeliger <jdl@freescale.com>
Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
Index: arch/ppc/mm/init.c
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/mm/init.c (mode:100644)
+++ uncommitted/arch/ppc/mm/init.c (mode:100644)
@@ -316,7 +316,7 @@
if (init_bootmem_done) {
p = alloc_bootmem_pages(PAGE_SIZE);
} else {
- p = mem_pieces_find(PAGE_SIZE, PAGE_SIZE);
+ p = mem_pieces_find(&phys_avail, PAGE_SIZE, PAGE_SIZE);
}
return p;
}
@@ -495,10 +495,8 @@
* Initially, available physical memory is equivalent to all
* physical memory.
*/
-
- phys_avail.regions[0].address = PPC_MEMSTART;
- phys_avail.regions[0].size = total_memory;
- phys_avail.n_regions = 1;
+ mem_pieces_reset(&phys_avail);
+ mem_pieces_add(&phys_avail, PPC_MEMSTART, total_memory);
/*
* Map out the kernel text/data/bss from the available physical
Index: arch/ppc/mm/mem_pieces.c
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/mm/mem_pieces.c (mode:100644)
+++ uncommitted/arch/ppc/mm/mem_pieces.c (mode:100644)
@@ -22,19 +22,105 @@
#include "mem_pieces.h"
-extern struct mem_pieces phys_avail;
-static void mem_pieces_print(struct mem_pieces *);
+static unsigned int __init mem_pieces_addrs_adjacent(unsigned int base1,
+ unsigned int size1,
+ unsigned int base2,
+ unsigned int size2);
+static int __init mem_pieces_regions_adjacent(struct mem_pieces *mp,
+ unsigned int r1,
+ unsigned int r2);
+static void __init mem_pieces_coalesce_regions(struct mem_pieces *mp,
+ unsigned int r1,
+ unsigned int r2);
+
+
+void __init
+mem_pieces_reset(struct mem_pieces *mp)
+{
+ /*
+ * Create a dummy zero size block which will get coalesced
+ * away later. This simplifies the mem_pieces_add() code below.
+ */
+ mp->regions[0].address = 0;
+ mp->regions[0].size = 0;
+ mp->n_regions = 1;
+}
+
+
+/*
+ * mem_pieces_add() -- Add a memory block to a sorted region table,
+ * merging adjacent blocks if possible.
+ * Returns 0 on straight add, >0 on coallsced, -1 on failure.
+ */
+
+int __init
+mem_pieces_add(struct mem_pieces *mp, unsigned int base, unsigned int size)
+{
+ unsigned int i;
+ unsigned int coalesced;
+
+ /*
+ * First try and coalesce this mem_piece with another.
+ */
+ coalesced = 0;
+ for (i = 0; i < mp->n_regions; i++) {
+ unsigned int rgnbase = mp->regions[i].address;
+ unsigned int rgnsize = mp->regions[i].size;
+ int adjacent = mem_pieces_addrs_adjacent(base, size,
+ rgnbase, rgnsize);
+ if (adjacent > 0) {
+ mp->regions[i].address -= size;
+ mp->regions[i].size += size;
+ coalesced++;
+ break;
+ } else if (adjacent < 0) {
+ mp->regions[i].size += size;
+ coalesced++;
+ break;
+ }
+ }
+
+ if ((i < mp->n_regions-1) && mem_pieces_regions_adjacent(mp, i, i+1)) {
+ mem_pieces_coalesce_regions(mp, i, i+1);
+ coalesced++;
+ }
+
+ if (coalesced) {
+ return coalesced;
+ } else if (mp->n_regions >= MEM_PIECES_MAX ) {
+ return -1;
+ }
+
+ /*
+ * Couldn't coalesce the new mem_piece, so add it to the sorted table.
+ */
+ for (i = mp->n_regions-1; i >= 0; i--) {
+ if (base < mp->regions[i].address) {
+ /* Shift up a slot. */
+ mp->regions[i+1].address = mp->regions[i].address;
+ mp->regions[i+1].size = mp->regions[i].size;
+ } else {
+ /* Insert in newly opened slot. */
+ mp->regions[i+1].address = base;
+ mp->regions[i+1].size = size;
+ break;
+ }
+ }
+ ++mp->n_regions;
+
+ return 0;
+}
+
/*
* Scan a region for a piece of a given size with the required alignment.
*/
void __init *
-mem_pieces_find(unsigned int size, unsigned int align)
+mem_pieces_find(struct mem_pieces *mp, unsigned int size, unsigned int align)
{
int i;
unsigned a, e;
- struct mem_pieces *mp = &phys_avail;
for (i = 0; i < mp->n_regions; ++i) {
a = mp->regions[i].address;
@@ -50,6 +136,7 @@
return NULL;
}
+
/*
* Remove some memory from an array of pieces
*/
@@ -59,7 +146,7 @@
{
int i, j;
unsigned int end, rs, re;
- struct reg_property *rp;
+ struct mem_pieces_property *rp;
end = start + size;
for (i = 0, rp = mp->regions; i < mp->n_regions; ++i, ++rp) {
@@ -109,17 +196,20 @@
}
}
-static void __init
+
+void __init
mem_pieces_print(struct mem_pieces *mp)
{
int i;
- for (i = 0; i < mp->n_regions; ++i)
+ for (i = 0; i < mp->n_regions; ++i) {
printk(" [%x, %x)", mp->regions[i].address,
mp->regions[i].address + mp->regions[i].size);
+ }
printk("\n");
}
+
void __init
mem_pieces_sort(struct mem_pieces *mp)
{
@@ -139,6 +229,7 @@
}
}
+
void __init
mem_pieces_coalesce(struct mem_pieces *mp)
{
@@ -161,3 +252,66 @@
}
mp->n_regions = d;
}
+
+
+unsigned int __init
+mem_pieces_get_phys_mem_size(struct mem_pieces *mp)
+{
+ int i;
+ unsigned int total = 0;
+
+ for (i = 0; i < mp->n_regions; i++) {
+ total += mp->regions[i].size;
+ }
+ return total;
+}
+
+
+static unsigned int __init
+mem_pieces_addrs_adjacent(unsigned int base1, unsigned int size1,
+ unsigned int base2, unsigned int size2)
+{
+ if (base2 == base1 + size1) {
+ return 1;
+ } else if (base1 == base2 + size2) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int __init
+mem_pieces_regions_adjacent(struct mem_pieces *mp,
+ unsigned int r1,
+ unsigned int r2)
+{
+ unsigned int base1 = mp->regions[r1].address;
+ unsigned int size1 = mp->regions[r1].size;
+ unsigned int base2 = mp->regions[r2].address;
+ unsigned int size2 = mp->regions[r2].size;
+
+ return mem_pieces_addrs_adjacent(base1, size1, base2, size2);
+}
+
+
+/*
+ * Coalesce block r2 into block r1.
+ * Assumes base addr of region 1 < base addr of region 2
+ */
+
+static void __init
+mem_pieces_coalesce_regions(struct mem_pieces *mp,
+ unsigned int r1,
+ unsigned int r2)
+{
+ unsigned int i;
+
+ mp->regions[r1].size += mp->regions[r2].size;
+ for (i = r2; i < mp->n_regions-1; i++) {
+ mp->regions[i].address = mp->regions[i+1].address;
+ mp->regions[i].size = mp->regions[i+1].size;
+ }
+ --mp->n_regions;
+
+}
Index: arch/ppc/mm/mem_pieces.h
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/mm/mem_pieces.h (mode:100644)
+++ uncommitted/arch/ppc/mm/mem_pieces.h (mode:100644)
@@ -17,8 +17,6 @@
#ifndef __MEM_PIECES_H__
#define __MEM_PIECES_H__
-#include <asm/prom.h>
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -26,20 +24,34 @@
/* Type Definitions */
+struct mem_pieces_property {
+ unsigned int address;
+ unsigned int size;
+};
+
+
#define MEM_PIECES_MAX 32
struct mem_pieces {
int n_regions;
- struct reg_property regions[MEM_PIECES_MAX];
+ struct mem_pieces_property regions[MEM_PIECES_MAX];
};
/* Function Prototypes */
-extern void *mem_pieces_find(unsigned int size, unsigned int align);
-extern void mem_pieces_remove(struct mem_pieces *mp, unsigned int start,
+extern void mem_pieces_reset(struct mem_pieces *mp);
+extern int mem_pieces_add(struct mem_pieces *mp,
+ unsigned int base, unsigned int size);
+extern void *mem_pieces_find(struct mem_pieces *mp,
+ unsigned int size, unsigned int align);
+extern void mem_pieces_remove(struct mem_pieces *mp,
+ unsigned int start,
unsigned int size, int must_exist);
extern void mem_pieces_coalesce(struct mem_pieces *mp);
extern void mem_pieces_sort(struct mem_pieces *mp);
+extern unsigned int mem_pieces_get_phys_mem_size(struct mem_pieces *mp);
+extern void mem_pieces_print(struct mem_pieces *);
+
#ifdef __cplusplus
}
Index: arch/ppc/mm/ppc_mmu.c
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/mm/ppc_mmu.c (mode:100644)
+++ uncommitted/arch/ppc/mm/ppc_mmu.c (mode:100644)
@@ -186,6 +186,7 @@
unsigned int hmask, mb, mb2;
unsigned int n_hpteg, lg_n_hpteg;
+ extern struct mem_pieces phys_avail;
extern unsigned int hash_page_patch_A[];
extern unsigned int hash_page_patch_B[], hash_page_patch_C[];
extern unsigned int hash_page[];
@@ -245,7 +246,7 @@
* Find some memory for the hash table.
*/
if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
- Hash = mem_pieces_find(Hash_size, Hash_size);
+ Hash = mem_pieces_find(&phys_avail, Hash_size, Hash_size);
cacheable_memzero(Hash, Hash_size);
_SDR1 = __pa(Hash) | SDR1_LOW_BITS;
#endif /* CONFIG_POWER4 */
Index: arch/ppc/platforms/pmac_setup.c
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/platforms/pmac_setup.c (mode:100644)
+++ uncommitted/arch/ppc/platforms/pmac_setup.c (mode:100644)
@@ -575,7 +575,6 @@
static int __init
get_mem_prop(char *name, struct mem_pieces *mp)
{
- struct reg_property *rp;
int i, s;
unsigned int *ip;
int nac = prom_n_addr_cells(memory_node);
@@ -588,18 +587,16 @@
return 0;
}
s /= (nsc + nac) * 4;
- rp = mp->regions;
for (i = 0; i < s; ++i, ip += nac+nsc) {
+ unsigned int size;
if (nac >= 2 && ip[nac-2] != 0)
continue;
- rp->address = ip[nac-1];
if (nsc >= 2 && ip[nac+nsc-2] != 0)
- rp->size = ~0U;
+ size = ~0U;
else
- rp->size = ip[nac+nsc-1];
- ++rp;
+ size = ip[nac+nsc-1];
+ mem_pieces_add(mp, ip[nac-1], size);
}
- mp->n_regions = rp - mp->regions;
/* Make sure the pieces are sorted. */
mem_pieces_sort(mp);
@@ -620,6 +617,8 @@
unsigned long a, total;
struct mem_pieces phys_mem;
+ mem_pieces_reset(&phys_mem);
+
/*
* Find out where physical memory is, and check that it
* starts at 0 and is contiguous. It seems that RAM is
^ permalink raw reply
* Re: 2.6 support for MPC8541(e)
From: Clemens Koller @ 2005-06-28 16:06 UTC (permalink / raw)
To: Kumar Gala; +Cc: <jbi130@yahoo.com>, linuxppc-embedded
In-Reply-To: <A6920FBA-2DBF-4E09-9B8D-1612A4DA6AAD@freescale.com>
Hi!
I had to do the same for my MPC8540 board (Microsys PM854).
It's based on the MPC8540_ADS platform, too with
changes in PCI subsystem and Gigabit Ethernet (gianfar_phy).
Enable early serial and enjoy printk.
Try to find out, where it hangs.
Greets,
Clemens Koller
_______________________________
R&D Imaging Devices
Anagramm GmbH
Rupert-Mayer-Str. 45/1
81379 Muenchen
Germany
http://www.anagramm.de
Phone: +49-89-741518-50
Fax: +49-89-741518-19
Kumar Gala wrote:
> You probably need to port the platform code from 2.4 to 2.6 for this
> board. I'm guessing you are running into some PCI config issue with
> interrupts and the such.
>
> Take a look at arch/ppc/platforms/85xx/* for examples of boards that
> support 85xx processors.
>
> - kumar
>
> On Jun 28, 2005, at 9:03 AM, <jbi130@yahoo.com> <jbi130@yahoo.com> wrote:
>
>> I've recently received a GDA PCI-G8400 evaluation board with an
>> MPC8541E. It came with u-boot 1.1.2 and a 2.4.27 kernel.
>>
>> Our hopes are to get a 2.6 kernel running on this device so it is in
>> sync with out MPC8248 based boards.
>>
>> What is the status of the support for these chips? When I enable
>> CONFIG_SERIAL_TEXT_DEBUG I'm able to get some output, it seems to die
>> when initializing openpic. There also appears to be issues with the
>> serial console as I'm not getting printk output at all, and I think I
>> should be by the time start_kernel is entered.
>>
>> My current 2.6.12 builds use the MPC8540_ADS configs as a base. The
>> 2.4 that was received with the board does as well.
>>
>> For now I'm not concerned with the 'E' part. My main job is to
>> actually add support for the security engine, but I'd like to get 2.6
>> up and running first. Yes, this is my first jump into machine
>> specific code..
>>
>> Thanks.
>>
>> _______________________________________________
>> 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
* Re: porting linux ppc on custom board, stuck in timer loop ?
From: Xavier Grave @ 2005-06-28 15:01 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1119964226.28013.35.camel@ipnnarval>
montavista 2.4.20 kernel code from preview kit boot without any
problems... Thanks to them ! I'll have a look at the 2.6.12 kernel later
once my application run on my embedded board :-)
So sorry for the previous mail...
Le mardi 28 juin 2005 à 15:10 +0200, Xavier Grave a écrit :
> Hi !
>
> I still try to port linux ppc on our ppc405 based hardware, after a look
> at xilinx_ml300.c file that gives the list of function calls I wait for
> a call to start_kernel but I found that start_kernel is never reached...
> In fact the code in head_4xx.S jumps to 0x00001000 which is Decrementer
> exception :
>
> bl machine_init
> bl MMU_init
> /* Go back to running unmapped so we can load up new values
> * and change to using our exception vectors.
> * On the 4xx, all we have to do is invalidate the TLB to clear
> * the old 16M byte TLB mappings.
> */
> lis r4,2f@h
> ori r4,r4,2f@l
> tophys(r4,r4) /* r4 seems to hold 0x00001000 */
> lis r3,(MSR_KERNEL & ~(MSR_IR|MSR_DR))@h
> ori r3,r3,(MSR_KERNEL & ~(MSR_IR|MSR_DR))@l
> mtspr SPRN_SRR0,r4
> mtspr SPRN_SRR1,r3
> rfi
> b . /* prevent prefetch past rfi */
>
> the previous code jump to decrementer and the code after is never
> reached... And so start_kernel also...
>
> /* Load up the kernel context */
> 2:
> sync /* Flush to memory before changing TLB */
> tlbia
> isync /* Flush shadow TLBs */
> /* set up the PTE pointers for the Abatron bdiGDB.
> */
> lis r6, swapper_pg_dir@h
> ori r6, r6, swapper_pg_dir@l
> lis r5, abatron_pteptrs@h
> ori r5, r5, abatron_pteptrs@l
> stw r5, 0xf0(r0) /* Must match your Abatron config file */
> tophys(r5,r5)
> stw r6, 0(r5)
> /* Now turn on the MMU for real! */
> lis r4,MSR_KERNEL@h
> ori r4,r4,MSR_KERNEL@l
> lis r3,start_kernel@h
> ori r3,r3,start_kernel@l
> mtspr SPRN_SRR0,r3
> mtspr SPRN_SRR1,r4
> rfi /* enable MMU and jump to start_kernel */
> b . /* prevent prefetch past rfi */
>
> Is this my hardware implementation that is incorrect ? Or I missed
> something in my kernel configuration ?
>
> Thanks in advance for any answer...
>
> xavier
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: 2.6 support for MPC8541(e)
From: Kumar Gala @ 2005-06-28 14:27 UTC (permalink / raw)
To: <jbi130@yahoo.com>; +Cc: linuxppc-embedded
In-Reply-To: <87zmtavasj.fsf@nimrod.unx.ca>
You probably need to port the platform code from 2.4 to 2.6 for this
board. I'm guessing you are running into some PCI config issue with
interrupts and the such.
Take a look at arch/ppc/platforms/85xx/* for examples of boards that
support 85xx processors.
- kumar
On Jun 28, 2005, at 9:03 AM, <jbi130@yahoo.com> <jbi130@yahoo.com>
wrote:
> I've recently received a GDA PCI-G8400 evaluation board with an
> MPC8541E. It came with u-boot 1.1.2 and a 2.4.27 kernel.
>
> Our hopes are to get a 2.6 kernel running on this device so it is in
> sync with out MPC8248 based boards.
>
> What is the status of the support for these chips? When I enable
> CONFIG_SERIAL_TEXT_DEBUG I'm able to get some output, it seems to die
> when initializing openpic. There also appears to be issues with the
> serial console as I'm not getting printk output at all, and I think I
> should be by the time start_kernel is entered.
>
> My current 2.6.12 builds use the MPC8540_ADS configs as a base. The
> 2.4 that was received with the board does as well.
>
> For now I'm not concerned with the 'E' part. My main job is to
> actually add support for the security engine, but I'd like to get 2.6
> up and running first. Yes, this is my first jump into machine
> specific code..
>
> Thanks.
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
^ permalink raw reply
* 2.6 support for MPC8541(e)
From: jbi130 @ 2005-06-28 14:03 UTC (permalink / raw)
To: linuxppc-embedded
I've recently received a GDA PCI-G8400 evaluation board with an
MPC8541E. It came with u-boot 1.1.2 and a 2.4.27 kernel.
Our hopes are to get a 2.6 kernel running on this device so it is in
sync with out MPC8248 based boards.
What is the status of the support for these chips? When I enable
CONFIG_SERIAL_TEXT_DEBUG I'm able to get some output, it seems to die
when initializing openpic. There also appears to be issues with the
serial console as I'm not getting printk output at all, and I think I
should be by the time start_kernel is entered.
My current 2.6.12 builds use the MPC8540_ADS configs as a base. The
2.4 that was received with the board does as well.
For now I'm not concerned with the 'E' part. My main job is to
actually add support for the security engine, but I'd like to get 2.6
up and running first. Yes, this is my first jump into machine
specific code..
Thanks.
^ permalink raw reply
* Re: [PATCH] 8xx: map_page() skip pinned region and tlbie debugging aid
From: Dan Malek @ 2005-06-28 13:53 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linux-ppc-embedded
In-Reply-To: <1119940208.5133.204.camel@gaston>
On Jun 28, 2005, at 2:30 AM, Benjamin Herrenschmidt wrote:
> You should consider 8Mb pages the way we do BATs yes,
It's always been considered, just never fully implemented :-)
> Note that I'll soon send the patch I told you about that makes the
> virtual address picked by io_block_mapping() dynamic, so we no longer
> have to do crappy assumptions all over the place :)
Whatever, I'll never use it that way and no one else should either.
All of the io_block_mapping() calls should be used to set these 8M
mapped IO spaces, everyone should use ioremap() to map them,
and ioremap() has to be modified to find them for the 8xx.
Thanks.
-- Dan
^ permalink raw reply
* [PATCH] 8xx: get_mmu_context() for (very) FEW_CONTEXTS and KERNEL_PREEMPT race/starvation issue
From: Guillaume Autran @ 2005-06-28 13:42 UTC (permalink / raw)
To: linux-ppc-embedded
In-Reply-To: <1119940208.5133.204.camel@gaston>
[-- Attachment #1: Type: text/plain, Size: 886 bytes --]
Hi,
I happen to notice a race condition in the mmu_context code for the 8xx
with very few context (16 MMU contexts) and kernel preemption enable. It
is hard to reproduce has it shows only when many processes are
created/destroy and the system is doing a lot of IRQ processing.
In short, one process is trying to steal a context that is in the
process of being freed (mm->context == NO_CONTEXT) but not completely
freed (nr_free_contexts == 0).
The steal_context() function does not do anything and the process stays
in the loop forever.
Anyway, I got a patch that fixes this part. Does not seem to affect
scheduling latency at all.
Comments are appreciated.
Guillaume.
--
=======================================
Guillaume Autran
Senior Software Engineer
MRV Communications, Inc.
Tel: (978) 952-4932 office
E-mail: gautran@mrv.com
=======================================
[-- Attachment #2: mmu_context.patch --]
[-- Type: text/plain, Size: 3222 bytes --]
diff -Nru --exclude=CVS linux-2.6.old/arch/ppc/mm/mmu_context.c linux-2.6/arch/ppc/mm/mmu_context.c
--- linux-2.6.old/arch/ppc/mm/mmu_context.c 2004-12-13 16:11:56.000000000 -0500
+++ linux-2.6/arch/ppc/mm/mmu_context.c 2005-06-28 09:08:13.000000000 -0400
@@ -31,9 +31,9 @@
#include <asm/tlbflush.h>
mm_context_t next_mmu_context;
+spinlock_t next_mmu_ctx_lock = SPIN_LOCK_UNLOCKED;
unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
#ifdef FEW_CONTEXTS
-atomic_t nr_free_contexts;
struct mm_struct *context_mm[LAST_CONTEXT+1];
void steal_context(void);
#endif /* FEW_CONTEXTS */
@@ -52,9 +52,6 @@
*/
context_map[0] = (1 << FIRST_CONTEXT) - 1;
next_mmu_context = FIRST_CONTEXT;
-#ifdef FEW_CONTEXTS
- atomic_set(&nr_free_contexts, LAST_CONTEXT - FIRST_CONTEXT + 1);
-#endif /* FEW_CONTEXTS */
}
#ifdef FEW_CONTEXTS
@@ -74,12 +71,21 @@
steal_context(void)
{
struct mm_struct *mm;
+ mm_context_t ctx = 0;
/* free up context `next_mmu_context' */
+ spin_lock(&next_mmu_ctx_lock);
+
/* if we shouldn't free context 0, don't... */
if (next_mmu_context < FIRST_CONTEXT)
next_mmu_context = FIRST_CONTEXT;
- mm = context_mm[next_mmu_context];
+
+ ctx = next_mmu_context;
+ next_mmu_context = (ctx + 1) & LAST_CONTEXT;
+
+ spin_unlock(&next_mmu_ctx_lock);
+
+ mm = context_mm[ctx];
flush_tlb_mm(mm);
destroy_context(mm);
}
diff -Nru --exclude=CVS linux-2.6.old/include/asm-ppc/mmu_context.h linux-2.6/include/asm-ppc/mmu_context.h
--- linux-2.6.old/include/asm-ppc/mmu_context.h 2004-12-13 16:11:21.000000000 -0500
+++ linux-2.6/include/asm-ppc/mmu_context.h 2005-06-28 09:08:13.000000000 -0400
@@ -100,6 +100,7 @@
* number to be free, but it usually will be.
*/
extern mm_context_t next_mmu_context;
+extern spinlock_t next_mmu_ctx_lock;
/*
* If we don't have sufficient contexts to give one to every task
@@ -108,7 +109,6 @@
*/
#if LAST_CONTEXT < 30000
#define FEW_CONTEXTS 1
-extern atomic_t nr_free_contexts;
extern struct mm_struct *context_mm[LAST_CONTEXT+1];
extern void steal_context(void);
#endif
@@ -119,24 +119,36 @@
static inline void get_mmu_context(struct mm_struct *mm)
{
mm_context_t ctx;
+ int flag;
if (mm->context != NO_CONTEXT)
return;
-#ifdef FEW_CONTEXTS
- while (atomic_dec_if_positive(&nr_free_contexts) < 0)
- steal_context();
-#endif
+
ctx = next_mmu_context;
+ flag = 0;
+
while (test_and_set_bit(ctx, context_map)) {
ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx);
- if (ctx > LAST_CONTEXT)
+ if (ctx > LAST_CONTEXT) {
ctx = 0;
+#ifdef FEW_CONTEXTS
+ if( flag == 0 ) {
+ flag = 1;
+ } else {
+ ctx = next_mmu_context;
+ steal_context();
+ }
+#endif
+ }
}
+ spin_lock(&next_mmu_ctx_lock);
next_mmu_context = (ctx + 1) & LAST_CONTEXT;
mm->context = ctx;
#ifdef FEW_CONTEXTS
context_mm[ctx] = mm;
#endif
+ spin_unlock(&next_mmu_ctx_lock);
+
}
/*
@@ -150,11 +162,9 @@
static inline void destroy_context(struct mm_struct *mm)
{
if (mm->context != NO_CONTEXT) {
- clear_bit(mm->context, context_map);
+ mm_context_t ctx = mm->context;
mm->context = NO_CONTEXT;
-#ifdef FEW_CONTEXTS
- atomic_inc(&nr_free_contexts);
-#endif
+ clear_bit(ctx, context_map);
}
}
^ permalink raw reply
* porting linux ppc on custom board, stuck in timer loop ?
From: Xavier Grave @ 2005-06-28 13:10 UTC (permalink / raw)
To: linuxppc-dev
Hi !
I still try to port linux ppc on our ppc405 based hardware, after a look
at xilinx_ml300.c file that gives the list of function calls I wait for
a call to start_kernel but I found that start_kernel is never reached...
In fact the code in head_4xx.S jumps to 0x00001000 which is Decrementer
exception :
bl machine_init
bl MMU_init
/* Go back to running unmapped so we can load up new values
* and change to using our exception vectors.
* On the 4xx, all we have to do is invalidate the TLB to clear
* the old 16M byte TLB mappings.
*/
lis r4,2f@h
ori r4,r4,2f@l
tophys(r4,r4) /* r4 seems to hold 0x00001000 */
lis r3,(MSR_KERNEL & ~(MSR_IR|MSR_DR))@h
ori r3,r3,(MSR_KERNEL & ~(MSR_IR|MSR_DR))@l
mtspr SPRN_SRR0,r4
mtspr SPRN_SRR1,r3
rfi
b . /* prevent prefetch past rfi */
the previous code jump to decrementer and the code after is never
reached... And so start_kernel also...
/* Load up the kernel context */
2:
sync /* Flush to memory before changing TLB */
tlbia
isync /* Flush shadow TLBs */
/* set up the PTE pointers for the Abatron bdiGDB.
*/
lis r6, swapper_pg_dir@h
ori r6, r6, swapper_pg_dir@l
lis r5, abatron_pteptrs@h
ori r5, r5, abatron_pteptrs@l
stw r5, 0xf0(r0) /* Must match your Abatron config file */
tophys(r5,r5)
stw r6, 0(r5)
/* Now turn on the MMU for real! */
lis r4,MSR_KERNEL@h
ori r4,r4,MSR_KERNEL@l
lis r3,start_kernel@h
ori r3,r3,start_kernel@l
mtspr SPRN_SRR0,r3
mtspr SPRN_SRR1,r4
rfi /* enable MMU and jump to start_kernel */
b . /* prevent prefetch past rfi */
Is this my hardware implementation that is incorrect ? Or I missed
something in my kernel configuration ?
Thanks in advance for any answer...
xavier
^ permalink raw reply
* CPM2 reports CRC errors in FCC2 for good packets
From: Alex BASTOS @ 2005-06-28 13:59 UTC (permalink / raw)
To: linuxppc-embedded
Hi guys,
I am working with a MPC8248 custom board. On this, we have mixed
interfaces, with Ethernet on FCC1 working in Full Duplex 100Mbps,
and MII-generic on FCC2, working in Half-Duplex 100Mbps.
On FCC2, CPM2 reports CRC error for each received packet, but
ignoring it, packets arrive correctly. We have tested it with
a known packet (ARP broadcast) through both interfaces, and this
packet reports and CRC error on FCC2, but not in FCC1 ... but the
received packet is the same in both cases !!! (taken from buffer
pointed by RxBD):
# FCC2 : Generic-mii Half Duplex
# ARP Broadcast Packet received on board!!!
FF FF FF FF FF FF 00 10 5A A7 8A F3 08 06 00 01 08 00 06 04 00 01
00 10 5A A7 8A F3 0A 00 00 03 00 00 00 00 00 00 0A 00 00 01 00 00
00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 E7 E0 E9 46
... len: 64
CBD_SC = 1C84 (crc_error)
# FCC1 : ETHERNET Full Duplex
# ARP Broadcast Packet received on board!!!
FF FF FF FF FF FF 00 10 5A A7 8A F3 08 06 00 01 08 00 06 04 00 01
00 10 5A A7 8A F3 0A 00 00 03 00 00 00 00 00 00 0A 00 00 01 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E7 E0 E9 46
... len: 64
So, packet is received ok, but CRC error is reported.
Any idea? May it be a Hardware problem, even if packets are received
OK by the driver?
Thanks,
Alexandre BASTOS
^ permalink raw reply
* GCC 3.3.1 unsigned long long issue on Powerpc 7xx
From: Srivatsan CR @ 2005-06-28 4:41 UTC (permalink / raw)
To: linuxppc-embedded; +Cc: Chandrasekhar C
[-- Attachment #1: Type: text/plain, Size: 798 bytes --]
Dear all,
We are using a third party software (support is not available :-( )
which uses unsigned long long in the code (both
kernel and user space).
We are trying to compile the same using the flag "-std=c99" (Changes
made to the CFLAGS option in Kernel and user
space Makefiles). For this we removed the -ansi option from CFLAGS
(both Kernel and user space Makefiles). The
compiler being used is GCC 3.3.1 on a 7xx platform.
Using the above mentioned method, user space code compiles properly but
the kernel code gives errors. Is there any
workaround to be done on the Kernel Makefile so that it compiles
without errors?
Requesting all your help to solve the issue. Thanks in advance for all
the help extended.
With Best Regards,
C.R.Srivatsan
[-- Attachment #2: Type: text/html, Size: 1610 bytes --]
^ permalink raw reply
* Re: [PATCH] ppc32: Remove CONFIG_PMAC_PBOOK
From: Christoph Hellwig @ 2005-06-28 8:57 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Andrew Morton, linuxppc-dev list, Linux Kernel list
In-Reply-To: <1119847159.5133.106.camel@gaston>
On Mon, Jun 27, 2005 at 02:39:16PM +1000, Benjamin Herrenschmidt wrote:
> This patch removes CONFIG_PMAC_PBOOK (PowerBook support). This is now
> split into CONFIG_PMAC_MEDIABAY for the actual hotswap bay that some
> powerbooks have, CONFIG_PM for power management related code, and just
> left out of any CONFIG_* option for some generally useful stuff that can
> be used on non-laptops as well.
Can you clarify the CONFIG_PMAC_MEDIABAY for which powerbooks this
is needed exactly? AFAIK up to one of the G3 models, but you probably
know better :)
^ permalink raw reply
* pb USB, EP8248
From: FLAMENT David @ 2005-06-28 7:52 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 294 bytes --]
Hello all,
I use a EP8248 and I need USB connection. When I compile with USB option in kernel, there is this message "usb-ohci currently requires PCI-bases controllers". (I use a 2.4.26 kernel Linux)
If you are a suggest or a idea, thank's for your answer .
David Flament
[-- Attachment #2: Type: text/html, Size: 1325 bytes --]
^ permalink raw reply
* Re: [PATCH] ppc32: Remove CONFIG_PMAC_PBOOK
From: Segher Boessenkool @ 2005-06-28 7:43 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Andrew Morton, linuxppc-dev list, Linux Kernel list
In-Reply-To: <1119847159.5133.106.camel@gaston>
> This patch removes CONFIG_PMAC_PBOOK (PowerBook support). This is now
> split into CONFIG_PMAC_MEDIABAY for the actual hotswap bay that some
> powerbooks have, CONFIG_PM for power management related code, and just
> left out of any CONFIG_* option for some generally useful stuff that
> can
> be used on non-laptops as well.
Is there any real reason not to enable CONFIG_PM on all Macs?
Segher
^ permalink raw reply
* Re: [PATCH] PPC32 mem_pieces interface cleanup
From: Benjamin Herrenschmidt @ 2005-06-28 6:30 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-embedded@ozlabs.org
In-Reply-To: <1119889730.25557.19.camel@cashmere.sps.mot.com>
On Mon, 2005-06-27 at 11:28 -0500, Jon Loeliger wrote:
> Guys,
>
> As an initial step towards getting the OF Flat Dev tree
> handled in the PPC32 tree, this patch cleans up some of
> the interface parts of the very early mem_pieces manager
> and adds some PPC64-LMB-like routines as well.
>
> It has been built and booted on 85xx and pmac boards.
Please make sure you CC linuxppc-dev on such patches or they'll be
missed by me and/or paulus most of the time :)
Ben.
^ permalink raw reply
* Re: [PATCH] 8xx: map_page() skip pinned region and tlbie debugging aid
From: Benjamin Herrenschmidt @ 2005-06-28 6:30 UTC (permalink / raw)
To: Dan Malek; +Cc: linux-ppc-embedded
In-Reply-To: <f5d1cb54913dd31385d15fe1f2e5b12d@embeddededge.com>
>
> You see, this just keeps growing in features and complexity :-)
> It would be nice for ioremap() to consider multiple, dynamic 8M
> pages on 8xx like it does BATs on traditional PPC. It will do
> this .... someday soon.
You should consider 8Mb pages the way we do BATs yes, that is have
something like an array of those or use 2 PMD entries to represent them,
and then, have ioremap treat them like it does with BATs. Such 8Mb pages
could then be setup using io_block_mapping().
Note that I'll soon send the patch I told you about that makes the
virtual address picked by io_block_mapping() dynamic, so we no longer
have to do crappy assumptions all over the place :)
> Perhaps I should go back and push some of this dynamic 8M
> page stuff. It would eliminate the tlbie() problems, give us
> more flexibility. Damn, not enough hours in a day ....
Looks like a good idea though :)
Ben.
^ permalink raw reply
* cpm_uart: use dpram for early console
From: Marcelo Tosatti @ 2005-06-27 15:28 UTC (permalink / raw)
To: Kumar Gala, Pantelis Antoniou, Dan Malek; +Cc: linux-ppc-embedded
Panto, Kumar,
Can something semantically equivalent to this be merged please.
m8xx_cpm_hostalloc() can't rely on using the coherent DMA allocator
early on boot because the VM is not fully up yet.
The current code relies on the "bootmem_page" allocated by
m8xx_cpm_reset(), which must be killed.
--- cpm_uart_cpm1.c.orig 2005-06-27 17:51:53.000000000 -0300
+++ cpm_uart_cpm1.c 2005-06-27 17:55:45.000000000 -0300
@@ -155,7 +155,7 @@
memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
if (is_con) {
- mem_addr = (u8 *) m8xx_cpm_hostalloc(memsz);
+ mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
dma_addr = 0;
} else
mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
^ permalink raw reply
* Re: [PATCH] 8xx: tlbie debugging aid (try #2)
From: Dan Malek @ 2005-06-27 20:53 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: linux-ppc-embedded
In-Reply-To: <20050627145603.GB9810@logos.cnet>
On Jun 27, 2005, at 10:56 AM, Marcelo Tosatti wrote:
> Note: this was just a test module doing tlbie(0xc0000100)...
> Hum, it should also print out the address in question...
Oh, I see. I thought it was a bug with loading a module
in general, since it allocates from vmalloc() space.
>> How much real memory on your board?
>
> 128M
No problem.
>> We need to ensure VMALLOC_START is beyond
>> the pinned entries.
>
> Right now VMALLOC_START is before the IMMR pinned space.
Sorry, I wasn't clear :-) I meant we need to ensure VMALLOC_START
is beyond the pinned _data_ area.
> Oh! What are the side effects of such pinning as the
> code is today?
The code maps 24M of data space, plus 8M of IMMR (and anything
that follows). So, if you don't have enough real memory, you can
end up with both a pinned entry and vmalloc() trying to share the same
VM space, which is a bad thing. The problem depends on the amount
of real memory, plus the "offset" hole of the vmalloc() space.
> For what purpose? Sorry I don't get you, please be more
> verbose.
Just to prevent what I mentioned in the previous paragraph.
Since you have lots of real memory, this doesn't affect you.
Thanks.
-- Dan
^ permalink raw reply
* Re: [PATCH] 8xx: map_page() skip pinned region and tlbie debugging aid
From: Dan Malek @ 2005-06-27 20:46 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: linux-ppc-embedded
In-Reply-To: <20050627133930.GA9109@logos.cnet>
On Jun 27, 2005, at 9:39 AM, Marcelo Tosatti wrote:
> Bullshit, map_page()'s call for flush_HPTE() is conditioned by
> "mem_init_done",
> and mapin_ram() is called before mem_init_done is set.
Excuse me?
>> The IMMR space is a 16kB window (correct?), so I wonder if it might
>> be better to the use occupied pinned slot for another more accessed
>> region (an 8MB one preferably!).
>
> Thats still some food for thought...
Actually, most 8xx systems map the IMMR, plus other external
devices (including flash memory), into a packed space at the top
of the address range. The 8M mapping catches the IMMR space,
but also many of these other devices subject to ioremap(). In
some systems, they trade off mapping the IMMR, or data pages,
to get an additional 8M of peripheral IO space.
The data space pinning is the big trade off right now. You can
pin 4 entries, or 32M of space. If you only have 16M of real
memory, the other two 8M entries can be used to cover IO space.
This is one (of a a few) advantages of using dynamic large
pages instead of pinned entries. You could map more 8M
spaces for IO. The problem is all of these have been custom
initialization and mapping code.
You see, this just keeps growing in features and complexity :-)
It would be nice for ioremap() to consider multiple, dynamic 8M
pages on 8xx like it does BATs on traditional PPC. It will do
this .... someday soon.
Perhaps I should go back and push some of this dynamic 8M
page stuff. It would eliminate the tlbie() problems, give us
more flexibility. Damn, not enough hours in a day ....
Thanks.
-- Dan
^ permalink raw reply
* Re: [PATCH] 8xx: tlbie debugging aid (try #2)
From: Marcelo Tosatti @ 2005-06-27 14:56 UTC (permalink / raw)
To: Dan Malek; +Cc: linux-ppc-embedded
In-Reply-To: <014331894c585b85c6bb419d72110125@embeddededge.com>
Hi Dan,
On Mon, Jun 27, 2005 at 04:18:14PM -0400, Dan Malek wrote:
>
> On Jun 27, 2005, at 10:28 AM, Marcelo Tosatti wrote:
>
> >it yields
> >
> >_tlbie on pinned range: c0000000-c1800000
> >Badness in _tlbie at arch/ppc/mm/pgtable.c:527
> >Call trace:
> > [c0005530] dump_stack+0x18/0x28
> > [c0003628] check_bug_trap+0x84/0xac
> > [c00037b0] ProgramCheckException+0x160/0x1a0
> > [c0002d50] ret_from_except_full+0x0/0x4c
> > [c000a91c] _tlbie+0x94/0xa0
> > [c902f018] alloc_init_module+0x18/0x40 [alloc]
> > [c002c4ac] sys_init_module+0x224/0x324
> > [c00026f0] ret_from_syscall+0x0/0x44
Note: this was just a test module doing tlbie(0xc0000100)...
Hum, it should also print out the address in question...
> How much real memory on your board?
128M
> We need to ensure VMALLOC_START is beyond
> the pinned entries.
Right now VMALLOC_START is before the IMMR pinned space.
> We should make all of the code
> much smarter to pin on the real space that is on
> the board.
Oh! What are the side effects of such pinning as the
code is today?
The only issue I see with pinning virtual address translations
farther the the physical addresses (real space) is that we lose
some virtual space, but nothing more than that.
Is it only that?
> For testing now, just make VMALLOC_OFFSET
> 32M, which will push the start to the 32M boundary
> after the kernel.
For what purpose? Sorry I don't get you, please be more
verbose.
^ permalink raw reply
* Re: [PATCH] 8xx: tlbie debugging aid (try #2)
From: Dan Malek @ 2005-06-27 20:18 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: linux-ppc-embedded
In-Reply-To: <20050627142803.GA9810@logos.cnet>
On Jun 27, 2005, at 10:28 AM, Marcelo Tosatti wrote:
> it yields
>
> _tlbie on pinned range: c0000000-c1800000
> Badness in _tlbie at arch/ppc/mm/pgtable.c:527
> Call trace:
> [c0005530] dump_stack+0x18/0x28
> [c0003628] check_bug_trap+0x84/0xac
> [c00037b0] ProgramCheckException+0x160/0x1a0
> [c0002d50] ret_from_except_full+0x0/0x4c
> [c000a91c] _tlbie+0x94/0xa0
> [c902f018] alloc_init_module+0x18/0x40 [alloc]
> [c002c4ac] sys_init_module+0x224/0x324
> [c00026f0] ret_from_syscall+0x0/0x44
How much real memory on your board?
We need to ensure VMALLOC_START is beyond
the pinned entries. We should make all of the code
much smarter to pin on the real space that is on
the board. For testing now, just make VMALLOC_OFFSET
32M, which will push the start to the 32M boundary
after the kernel.
Thanks.
-- Dan
^ permalink raw reply
* Re: [PATCH] 8xx: map_page() skip pinned region and tlbie debugging aid
From: Marcelo Tosatti @ 2005-06-27 13:39 UTC (permalink / raw)
To: Dan Malek; +Cc: linux-ppc-embedded
In-Reply-To: <20050626143004.GA5198@logos.cnet>
On Sun, Jun 26, 2005 at 11:30:04AM -0300, Marcelo Tosatti wrote:
>
> Hi Dan,
>
> On Sat, Jun 25, 2005 at 06:24:47PM -0400, Dan Malek wrote:
> >
> > On Jun 25, 2005, at 10:53 AM, Marcelo Tosatti wrote:
> >
> > >Dan: I dont think ioremap() is an issue because it never works inside
> > >the
> > >kernel's static virtual address space (which is the only one we're
> > >interested
> > >in having pinned at the moment).
> >
> > Take a close look at the initialization code. I believe it also
> > pins the IMMR space, which is subject to ioremap().
>
> OK. Now that makes me think that the IMMR pinned entry is also always
> thrashed by the tlbie at map_page() :(
Bullshit, map_page()'s call for flush_HPTE() is conditioned by "mem_init_done",
and mapin_ram() is called before mem_init_done is set.
> The IMMR space is a 16kB window (correct?), so I wonder if it might
> be better to the use occupied pinned slot for another more accessed
> region (an 8MB one preferably!).
Thats still some food for thought...
^ permalink raw reply
* [PATCH] 8xx: tlbie debugging aid (try #2)
From: Marcelo Tosatti @ 2005-06-27 14:28 UTC (permalink / raw)
To: Dan Malek; +Cc: linux-ppc-embedded
In-Reply-To: <f14f5f5aebd45879c39c6ce69f29c004@embeddededge.com>
On Sat, Jun 25, 2005 at 06:24:47PM -0400, Dan Malek wrote:
> We really want to see this generate an error. We shouldn't be
> calling this on any of the pinned spaces. In the case of initially
> mapping the kernel space, we should set up the page tables but
> not call this far down that we get here.
How about the following addressing your comments:
1) handles more than a single contiguous region by having a list_head (I thought of a
binary tree for storing the ranges but sounds like overkill at first given the
small amount of pinned regions).
2) implement as C code.
it yields
_tlbie on pinned range: c0000000-c1800000
Badness in _tlbie at arch/ppc/mm/pgtable.c:527
Call trace:
[c0005530] dump_stack+0x18/0x28
[c0003628] check_bug_trap+0x84/0xac
[c00037b0] ProgramCheckException+0x160/0x1a0
[c0002d50] ret_from_except_full+0x0/0x4c
[c000a91c] _tlbie+0x94/0xa0
[c902f018] alloc_init_module+0x18/0x40 [alloc]
[c002c4ac] sys_init_module+0x224/0x324
[c00026f0] ret_from_syscall+0x0/0x44
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -1296,6 +1296,11 @@ config BOOT_LOAD
config PIN_TLB
bool "Pinned Kernel TLBs (860 ONLY)"
depends on ADVANCED_OPTIONS && 8xx
+
+config DEBUG_PIN_TLBIE
+ bool "Check for overlapping TLB invalidates inside the pinned area"
+ depends on ADVANCED_OPTIONS && 8xx && PIN_TLB
+
endmenu
source "drivers/Kconfig"
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -494,7 +494,7 @@ _GLOBAL(_tlbia)
/*
* Flush MMU TLB for a particular address
*/
-_GLOBAL(_tlbie)
+_GLOBAL(__tlbie)
#if defined(CONFIG_40x)
tlbsx. r3, 0, r3
bne 10f
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -32,6 +32,7 @@
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/io.h>
+#include <asm/tlb.h>
#include "mmu_decl.h"
@@ -469,3 +470,48 @@ exit:
return ret;
}
+#ifndef CONFIG_DEBUG_PIN_TLBIE
+
+void _tlbie(unsigned long address)
+{
+ __tlbie(address);
+}
+
+#else
+LIST_HEAD(pin_range_root);
+
+static struct pinned_range kernelbase = {
+ start: KERNELBASE,
+ end: KERNELBASE+0x1800000,
+};
+
+static struct pinned_range immr = {
+ start: IMMR,
+ end: IMMR+0x800000,
+};
+
+inline void register_pinned_entries(void)
+{
+ list_add(&kernelbase.pin_list, &pin_range_root);
+ list_add(&immr.pin_list, &pin_range_root);
+}
+
+void _tlbie(unsigned long address)
+{
+ struct list_head *l;
+ struct pinned_range *r;
+
+ list_for_each(l, &pin_range_root) {
+ r = list_entry(l, struct pinned_range, pin_list);
+
+ if (address < r->start)
+ continue;
+ if (address >= r->end)
+ continue;
+ printk("_tlbie on pinned range: %lx-%lx\n", r->start, r->end);
+ WARN_ON(1);
+ }
+
+ __tlbie(address);
+}
+#endif
diff --git a/include/asm-ppc/tlb.h b/include/asm-ppc/tlb.h
--- a/include/asm-ppc/tlb.h
+++ b/include/asm-ppc/tlb.h
@@ -18,6 +18,18 @@
#include <asm/page.h>
#include <asm/mmu.h>
+#ifdef CONFIG_DEBUG_PIN_TLBIE
+struct pinned_range {
+ unsigned long start, end;
+ struct list_head pin_list;
+};
+inline void register_pinned_entries(void);
+#else
+inline void register_pinned_entries(void)
+{
+ return;
+}
+#endif
#ifdef CONFIG_PPC_STD_MMU
/* Classic PPC with hash-table based MMU... */
diff --git a/include/asm-ppc/tlbflush.h b/include/asm-ppc/tlbflush.h
--- a/include/asm-ppc/tlbflush.h
+++ b/include/asm-ppc/tlbflush.h
@@ -13,9 +13,14 @@
#include <linux/config.h>
#include <linux/mm.h>
+extern void __tlbie(unsigned long address);
extern void _tlbie(unsigned long address);
extern void _tlbia(void);
+#ifdef CONFIG_DEBUG_PIN_TLBIE
+extern struct list_head pin_range_root;
+#endif
+
#if defined(CONFIG_4xx)
#ifndef CONFIG_44x
^ permalink raw reply
* [PATCH] PPC32 mem_pieces interface cleanup
From: Jon Loeliger @ 2005-06-27 16:28 UTC (permalink / raw)
To: linuxppc-embedded@ozlabs.org
[-- Attachment #1: Type: text/plain, Size: 396 bytes --]
Guys,
As an initial step towards getting the OF Flat Dev tree
handled in the PPC32 tree, this patch cleans up some of
the interface parts of the very early mem_pieces manager
and adds some PPC64-LMB-like routines as well.
It has been built and booted on 85xx and pmac boards.
Thanks,
jdl
Signed-off-by: Jon Loeliger <jdl@freescale.com>
Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
[-- Attachment #2: mem_pieces_cleanup.patch --]
[-- Type: text/x-patch, Size: 9638 bytes --]
Index: arch/ppc/mm/init.c
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/mm/init.c (mode:100644)
+++ uncommitted/arch/ppc/mm/init.c (mode:100644)
@@ -316,7 +316,7 @@
if (init_bootmem_done) {
p = alloc_bootmem_pages(PAGE_SIZE);
} else {
- p = mem_pieces_find(PAGE_SIZE, PAGE_SIZE);
+ p = mem_pieces_find(&phys_avail, PAGE_SIZE, PAGE_SIZE);
}
return p;
}
@@ -495,10 +495,8 @@
* Initially, available physical memory is equivalent to all
* physical memory.
*/
-
- phys_avail.regions[0].address = PPC_MEMSTART;
- phys_avail.regions[0].size = total_memory;
- phys_avail.n_regions = 1;
+ mem_pieces_reset(&phys_avail);
+ mem_pieces_add(&phys_avail, PPC_MEMSTART, total_memory);
/*
* Map out the kernel text/data/bss from the available physical
Index: arch/ppc/mm/mem_pieces.c
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/mm/mem_pieces.c (mode:100644)
+++ uncommitted/arch/ppc/mm/mem_pieces.c (mode:100644)
@@ -22,19 +22,105 @@
#include "mem_pieces.h"
-extern struct mem_pieces phys_avail;
-static void mem_pieces_print(struct mem_pieces *);
+static unsigned int __init mem_pieces_addrs_adjacent(unsigned int base1,
+ unsigned int size1,
+ unsigned int base2,
+ unsigned int size2);
+static int __init mem_pieces_regions_adjacent(struct mem_pieces *mp,
+ unsigned int r1,
+ unsigned int r2);
+static void __init mem_pieces_coalesce_regions(struct mem_pieces *mp,
+ unsigned int r1,
+ unsigned int r2);
+
+
+void __init
+mem_pieces_reset(struct mem_pieces *mp)
+{
+ /*
+ * Create a dummy zero size block which will get coalesced
+ * away later. This simplifies the mem_pieces_add() code below.
+ */
+ mp->regions[0].address = 0;
+ mp->regions[0].size = 0;
+ mp->n_regions = 1;
+}
+
+
+/*
+ * mem_pieces_add() -- Add a memory block to a sorted region table,
+ * merging adjacent blocks if possible.
+ * Returns 0 on straight add, >0 on coallsced, -1 on failure.
+ */
+
+int __init
+mem_pieces_add(struct mem_pieces *mp, unsigned int base, unsigned int size)
+{
+ unsigned int i;
+ unsigned int coalesced;
+
+ /*
+ * First try and coalesce this mem_piece with another.
+ */
+ coalesced = 0;
+ for (i = 0; i < mp->n_regions; i++) {
+ unsigned int rgnbase = mp->regions[i].address;
+ unsigned int rgnsize = mp->regions[i].size;
+ int adjacent = mem_pieces_addrs_adjacent(base, size,
+ rgnbase, rgnsize);
+ if (adjacent > 0) {
+ mp->regions[i].address -= size;
+ mp->regions[i].size += size;
+ coalesced++;
+ break;
+ } else if (adjacent < 0) {
+ mp->regions[i].size += size;
+ coalesced++;
+ break;
+ }
+ }
+
+ if ((i < mp->n_regions-1) && mem_pieces_regions_adjacent(mp, i, i+1)) {
+ mem_pieces_coalesce_regions(mp, i, i+1);
+ coalesced++;
+ }
+
+ if (coalesced) {
+ return coalesced;
+ } else if (mp->n_regions >= MEM_PIECES_MAX ) {
+ return -1;
+ }
+
+ /*
+ * Couldn't coalesce the new mem_piece, so add it to the sorted table.
+ */
+ for (i = mp->n_regions-1; i >= 0; i--) {
+ if (base < mp->regions[i].address) {
+ /* Shift up a slot. */
+ mp->regions[i+1].address = mp->regions[i].address;
+ mp->regions[i+1].size = mp->regions[i].size;
+ } else {
+ /* Insert in newly opened slot. */
+ mp->regions[i+1].address = base;
+ mp->regions[i+1].size = size;
+ break;
+ }
+ }
+ ++mp->n_regions;
+
+ return 0;
+}
+
/*
* Scan a region for a piece of a given size with the required alignment.
*/
void __init *
-mem_pieces_find(unsigned int size, unsigned int align)
+mem_pieces_find(struct mem_pieces *mp, unsigned int size, unsigned int align)
{
int i;
unsigned a, e;
- struct mem_pieces *mp = &phys_avail;
for (i = 0; i < mp->n_regions; ++i) {
a = mp->regions[i].address;
@@ -50,6 +136,7 @@
return NULL;
}
+
/*
* Remove some memory from an array of pieces
*/
@@ -59,7 +146,7 @@
{
int i, j;
unsigned int end, rs, re;
- struct reg_property *rp;
+ struct mem_pieces_property *rp;
end = start + size;
for (i = 0, rp = mp->regions; i < mp->n_regions; ++i, ++rp) {
@@ -109,17 +196,20 @@
}
}
-static void __init
+
+void __init
mem_pieces_print(struct mem_pieces *mp)
{
int i;
- for (i = 0; i < mp->n_regions; ++i)
+ for (i = 0; i < mp->n_regions; ++i) {
printk(" [%x, %x)", mp->regions[i].address,
mp->regions[i].address + mp->regions[i].size);
+ }
printk("\n");
}
+
void __init
mem_pieces_sort(struct mem_pieces *mp)
{
@@ -139,6 +229,7 @@
}
}
+
void __init
mem_pieces_coalesce(struct mem_pieces *mp)
{
@@ -161,3 +252,66 @@
}
mp->n_regions = d;
}
+
+
+unsigned int __init
+mem_pieces_get_phys_mem_size(struct mem_pieces *mp)
+{
+ int i;
+ unsigned int total = 0;
+
+ for (i = 0; i < mp->n_regions; i++) {
+ total += mp->regions[i].size;
+ }
+ return total;
+}
+
+
+static unsigned int __init
+mem_pieces_addrs_adjacent(unsigned int base1, unsigned int size1,
+ unsigned int base2, unsigned int size2)
+{
+ if (base2 == base1 + size1) {
+ return 1;
+ } else if (base1 == base2 + size2) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int __init
+mem_pieces_regions_adjacent(struct mem_pieces *mp,
+ unsigned int r1,
+ unsigned int r2)
+{
+ unsigned int base1 = mp->regions[r1].address;
+ unsigned int size1 = mp->regions[r1].size;
+ unsigned int base2 = mp->regions[r2].address;
+ unsigned int size2 = mp->regions[r2].size;
+
+ return mem_pieces_addrs_adjacent(base1, size1, base2, size2);
+}
+
+
+/*
+ * Coalesce block r2 into block r1.
+ * Assumes base addr of region 1 < base addr of region 2
+ */
+
+static void __init
+mem_pieces_coalesce_regions(struct mem_pieces *mp,
+ unsigned int r1,
+ unsigned int r2)
+{
+ unsigned int i;
+
+ mp->regions[r1].size += mp->regions[r2].size;
+ for (i = r2; i < mp->n_regions-1; i++) {
+ mp->regions[i].address = mp->regions[i+1].address;
+ mp->regions[i].size = mp->regions[i+1].size;
+ }
+ --mp->n_regions;
+
+}
Index: arch/ppc/mm/mem_pieces.h
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/mm/mem_pieces.h (mode:100644)
+++ uncommitted/arch/ppc/mm/mem_pieces.h (mode:100644)
@@ -17,8 +17,6 @@
#ifndef __MEM_PIECES_H__
#define __MEM_PIECES_H__
-#include <asm/prom.h>
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -26,20 +24,34 @@
/* Type Definitions */
+struct mem_pieces_property {
+ unsigned int address;
+ unsigned int size;
+};
+
+
#define MEM_PIECES_MAX 32
struct mem_pieces {
int n_regions;
- struct reg_property regions[MEM_PIECES_MAX];
+ struct mem_pieces_property regions[MEM_PIECES_MAX];
};
/* Function Prototypes */
-extern void *mem_pieces_find(unsigned int size, unsigned int align);
-extern void mem_pieces_remove(struct mem_pieces *mp, unsigned int start,
+extern void mem_pieces_reset(struct mem_pieces *mp);
+extern int mem_pieces_add(struct mem_pieces *mp,
+ unsigned int base, unsigned int size);
+extern void *mem_pieces_find(struct mem_pieces *mp,
+ unsigned int size, unsigned int align);
+extern void mem_pieces_remove(struct mem_pieces *mp,
+ unsigned int start,
unsigned int size, int must_exist);
extern void mem_pieces_coalesce(struct mem_pieces *mp);
extern void mem_pieces_sort(struct mem_pieces *mp);
+extern unsigned int mem_pieces_get_phys_mem_size(struct mem_pieces *mp);
+extern void mem_pieces_print(struct mem_pieces *);
+
#ifdef __cplusplus
}
Index: arch/ppc/mm/ppc_mmu.c
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/mm/ppc_mmu.c (mode:100644)
+++ uncommitted/arch/ppc/mm/ppc_mmu.c (mode:100644)
@@ -186,6 +186,7 @@
unsigned int hmask, mb, mb2;
unsigned int n_hpteg, lg_n_hpteg;
+ extern struct mem_pieces phys_avail;
extern unsigned int hash_page_patch_A[];
extern unsigned int hash_page_patch_B[], hash_page_patch_C[];
extern unsigned int hash_page[];
@@ -245,7 +246,7 @@
* Find some memory for the hash table.
*/
if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
- Hash = mem_pieces_find(Hash_size, Hash_size);
+ Hash = mem_pieces_find(&phys_avail, Hash_size, Hash_size);
cacheable_memzero(Hash, Hash_size);
_SDR1 = __pa(Hash) | SDR1_LOW_BITS;
#endif /* CONFIG_POWER4 */
Index: arch/ppc/platforms/pmac_setup.c
===================================================================
--- 413e8c09a51b5e4ee6850da2b7a65f9a9af0be9c/arch/ppc/platforms/pmac_setup.c (mode:100644)
+++ uncommitted/arch/ppc/platforms/pmac_setup.c (mode:100644)
@@ -575,7 +575,6 @@
static int __init
get_mem_prop(char *name, struct mem_pieces *mp)
{
- struct reg_property *rp;
int i, s;
unsigned int *ip;
int nac = prom_n_addr_cells(memory_node);
@@ -588,18 +587,16 @@
return 0;
}
s /= (nsc + nac) * 4;
- rp = mp->regions;
for (i = 0; i < s; ++i, ip += nac+nsc) {
+ unsigned int size;
if (nac >= 2 && ip[nac-2] != 0)
continue;
- rp->address = ip[nac-1];
if (nsc >= 2 && ip[nac+nsc-2] != 0)
- rp->size = ~0U;
+ size = ~0U;
else
- rp->size = ip[nac+nsc-1];
- ++rp;
+ size = ip[nac+nsc-1];
+ mem_pieces_add(mp, ip[nac-1], size);
}
- mp->n_regions = rp - mp->regions;
/* Make sure the pieces are sorted. */
mem_pieces_sort(mp);
@@ -620,6 +617,8 @@
unsigned long a, total;
struct mem_pieces phys_mem;
+ mem_pieces_reset(&phys_mem);
+
/*
* Find out where physical memory is, and check that it
* starts at 0 and is contiguous. It seems that RAM is
^ 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