Patchwork [RFC,14/19] powerpc: allow ioremap within reserved fake ram regions

login
register
mail settings
Submitter Albert Herranz
Date Nov. 22, 2009, 10:01 p.m.
Message ID <1258927311-4340-15-git-send-email-albert_herranz@yahoo.es>
Download mbox | patch
Permalink /patch/39013/
State Changes Requested
Headers show

Comments

Albert Herranz - Nov. 22, 2009, 10:01 p.m.
The Nintendo Wii has two discontiguous RAM memory areas called
MEM1 and MEM2.
MEM1 starts at 0x00000000 and contains 24MB of 1T-SRAM.
MEM2 starts at 0x10000000 and contains 64MB of DDR2 RAM.
Between both memory address ranges there is an address space
where memory-mapped I/O registers are found.

Currently, Linux 32-bit PowerPC does not support RAM in
discontiguous memory address spaces. Thus, in order to use
both RAM areas, we declare as RAM the range from the start of
MEM1 to the end of useable MEM2 and exclude the needed parts
with /memreserve/ statements, at the expense of wasting a bit
of memory.

As a side effect, we need to allow ioremapping RAM areas
because the I/O address space sits within the memreserve'd part
of the declared RAM region.
Note that this is not safe if the region ioremapped is covered
by an existing BAT mapping used to map RAM, so this is
specifically banned here.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
---
 arch/powerpc/mm/pgtable_32.c |   19 ++++++++++++++++---
 1 files changed, 16 insertions(+), 3 deletions(-)
Grant Likely - Nov. 22, 2009, 11:36 p.m.
On Sun, Nov 22, 2009 at 3:01 PM, Albert Herranz <albert_herranz@yahoo.es> wrote:
> The Nintendo Wii has two discontiguous RAM memory areas called
> MEM1 and MEM2.
> MEM1 starts at 0x00000000 and contains 24MB of 1T-SRAM.
> MEM2 starts at 0x10000000 and contains 64MB of DDR2 RAM.
> Between both memory address ranges there is an address space
> where memory-mapped I/O registers are found.
>
> Currently, Linux 32-bit PowerPC does not support RAM in
> discontiguous memory address spaces. Thus, in order to use
> both RAM areas, we declare as RAM the range from the start of
> MEM1 to the end of useable MEM2 and exclude the needed parts
> with /memreserve/ statements, at the expense of wasting a bit
> of memory.
>
> As a side effect, we need to allow ioremapping RAM areas
> because the I/O address space sits within the memreserve'd part
> of the declared RAM region.
> Note that this is not safe if the region ioremapped is covered
> by an existing BAT mapping used to map RAM, so this is
> specifically banned here.
>
> Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
> ---
>  arch/powerpc/mm/pgtable_32.c |   19 ++++++++++++++++---
>  1 files changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
> index cb96cb2..ba00cb1 100644
> --- a/arch/powerpc/mm/pgtable_32.c
> +++ b/arch/powerpc/mm/pgtable_32.c
> @@ -191,9 +191,22 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
>         * Don't allow anybody to remap normal RAM that we're using.
>         * mem_init() sets high_memory so only do the check after that.
>         */
> -       if (mem_init_done && (p < virt_to_phys(high_memory))) {
> -               printk("__ioremap(): phys addr 0x%llx is RAM lr %p\n",
> -                      (unsigned long long)p, __builtin_return_address(0));
> +       if (mem_init_done && (p < virt_to_phys(high_memory))
> +#ifdef CONFIG_WII
> +               /*
> +                * On some systems, though, we may want to remap an area
> +                * declared as normal RAM that we have memreserve'd at the
> +                * device tree. See wii.dts.
> +                * But we can't do that safely if we are using BATs to map
> +                * part of that area.
> +                */
> +           && !__map_without_bats
> +#endif
> +           ) {
> +               printk(KERN_WARNING
> +                      "__ioremap(): phys addr 0x%llx is RAM lr %p\n",
> +                      (unsigned long long)p,
> +                        __builtin_return_address(0));

This could adversely affect multiplatform kernels.  I'd rather get the
RAM problem fixed and not hack up common code to work around the hack.

g.
Albert Herranz - Nov. 23, 2009, 8:16 p.m.
Grant Likely wrote:
> On Sun, Nov 22, 2009 at 3:01 PM, Albert Herranz <albert_herranz@yahoo.es> wrote:
>> The Nintendo Wii has two discontiguous RAM memory areas called
>> MEM1 and MEM2.
>> MEM1 starts at 0x00000000 and contains 24MB of 1T-SRAM.
>> MEM2 starts at 0x10000000 and contains 64MB of DDR2 RAM.
>> Between both memory address ranges there is an address space
>> where memory-mapped I/O registers are found.
>>
>> Currently, Linux 32-bit PowerPC does not support RAM in
>> discontiguous memory address spaces. Thus, in order to use
>> both RAM areas, we declare as RAM the range from the start of
>> MEM1 to the end of useable MEM2 and exclude the needed parts
>> with /memreserve/ statements, at the expense of wasting a bit
>> of memory.
>>
>> As a side effect, we need to allow ioremapping RAM areas
>> because the I/O address space sits within the memreserve'd part
>> of the declared RAM region.
>> Note that this is not safe if the region ioremapped is covered
>> by an existing BAT mapping used to map RAM, so this is
>> specifically banned here.
>>
>> Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
>> ---
>>  arch/powerpc/mm/pgtable_32.c |   19 ++++++++++++++++---
>>  1 files changed, 16 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
>> index cb96cb2..ba00cb1 100644
>> --- a/arch/powerpc/mm/pgtable_32.c
>> +++ b/arch/powerpc/mm/pgtable_32.c
>> @@ -191,9 +191,22 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
>>         * Don't allow anybody to remap normal RAM that we're using.
>>         * mem_init() sets high_memory so only do the check after that.
>>         */
>> -       if (mem_init_done && (p < virt_to_phys(high_memory))) {
>> -               printk("__ioremap(): phys addr 0x%llx is RAM lr %p\n",
>> -                      (unsigned long long)p, __builtin_return_address(0));
>> +       if (mem_init_done && (p < virt_to_phys(high_memory))
>> +#ifdef CONFIG_WII
>> +               /*
>> +                * On some systems, though, we may want to remap an area
>> +                * declared as normal RAM that we have memreserve'd at the
>> +                * device tree. See wii.dts.
>> +                * But we can't do that safely if we are using BATs to map
>> +                * part of that area.
>> +                */
>> +           && !__map_without_bats
>> +#endif
>> +           ) {
>> +               printk(KERN_WARNING
>> +                      "__ioremap(): phys addr 0x%llx is RAM lr %p\n",
>> +                      (unsigned long long)p,
>> +                        __builtin_return_address(0));
> 
> This could adversely affect multiplatform kernels.  I'd rather get the
> RAM problem fixed and not hack up common code to work around the hack.
> 
> g.
> 

Would it be acceptable to create a global var __allow_ioremap_normal_ram that by default would have a value of 0 and would be set _only_ for those platforms needing it?

The other solutions I see is:
- add support for discontiguous memory to powerpc 32-bits (which is not something that I can look into now)
- don't use the precious second 64MB area (which is a waste)

Do you have any other suggestions?

Thanks,
Albert
Grant Likely - Nov. 23, 2009, 8:41 p.m.
On Mon, Nov 23, 2009 at 1:16 PM, Albert Herranz <albert_herranz@yahoo.es> wrote:
> Grant Likely wrote:
>> On Sun, Nov 22, 2009 at 3:01 PM, Albert Herranz <albert_herranz@yahoo.es> wrote:
>>> The Nintendo Wii has two discontiguous RAM memory areas called
>>> MEM1 and MEM2.
>>> MEM1 starts at 0x00000000 and contains 24MB of 1T-SRAM.
>>> MEM2 starts at 0x10000000 and contains 64MB of DDR2 RAM.
>>> Between both memory address ranges there is an address space
>>> where memory-mapped I/O registers are found.
>>>
>>> Currently, Linux 32-bit PowerPC does not support RAM in
>>> discontiguous memory address spaces. Thus, in order to use
>>> both RAM areas, we declare as RAM the range from the start of
>>> MEM1 to the end of useable MEM2 and exclude the needed parts
>>> with /memreserve/ statements, at the expense of wasting a bit
>>> of memory.
>>>
>>> As a side effect, we need to allow ioremapping RAM areas
>>> because the I/O address space sits within the memreserve'd part
>>> of the declared RAM region.
>>> Note that this is not safe if the region ioremapped is covered
>>> by an existing BAT mapping used to map RAM, so this is
>>> specifically banned here.
>>>
>>> Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
>>> ---
>>>  arch/powerpc/mm/pgtable_32.c |   19 ++++++++++++++++---
>>>  1 files changed, 16 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
>>> index cb96cb2..ba00cb1 100644
>>> --- a/arch/powerpc/mm/pgtable_32.c
>>> +++ b/arch/powerpc/mm/pgtable_32.c
>>> @@ -191,9 +191,22 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
>>>         * Don't allow anybody to remap normal RAM that we're using.
>>>         * mem_init() sets high_memory so only do the check after that.
>>>         */
>>> -       if (mem_init_done && (p < virt_to_phys(high_memory))) {
>>> -               printk("__ioremap(): phys addr 0x%llx is RAM lr %p\n",
>>> -                      (unsigned long long)p, __builtin_return_address(0));
>>> +       if (mem_init_done && (p < virt_to_phys(high_memory))
>>> +#ifdef CONFIG_WII
>>> +               /*
>>> +                * On some systems, though, we may want to remap an area
>>> +                * declared as normal RAM that we have memreserve'd at the
>>> +                * device tree. See wii.dts.
>>> +                * But we can't do that safely if we are using BATs to map
>>> +                * part of that area.
>>> +                */
>>> +           && !__map_without_bats
>>> +#endif
>>> +           ) {
>>> +               printk(KERN_WARNING
>>> +                      "__ioremap(): phys addr 0x%llx is RAM lr %p\n",
>>> +                      (unsigned long long)p,
>>> +                        __builtin_return_address(0));
>>
>> This could adversely affect multiplatform kernels.  I'd rather get the
>> RAM problem fixed and not hack up common code to work around the hack.
>>
>> g.
>>
>
> Would it be acceptable to create a global var __allow_ioremap_normal_ram that by default would have a value of 0 and would be set _only_ for those platforms needing it?

I'm not the best one to answer this since I don't dig into the mm code
very often.  Ben?  Kumar?  Becky?  Thoughts?

> The other solutions I see is:
> - add support for discontiguous memory to powerpc 32-bits (which is not something that I can look into now)

I of course like this option.  :-)

> - don't use the precious second 64MB area (which is a waste)

Not exactly nice, but it might be wise to do this now so that
discussion about how to fix it best won't block getting the bulk of
support into mainline.

g.
Michael Ellerman - Nov. 23, 2009, 11:45 p.m.
On Mon, 2009-11-23 at 21:16 +0100, Albert Herranz wrote:
> >>  arch/powerpc/mm/pgtable_32.c |   19 ++++++++++++++++---
> >>  1 files changed, 16 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
> >> index cb96cb2..ba00cb1 100644
> >> --- a/arch/powerpc/mm/pgtable_32.c
> >> +++ b/arch/powerpc/mm/pgtable_32.c
> >> @@ -191,9 +191,22 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
> >>         * Don't allow anybody to remap normal RAM that we're using.
> >>         * mem_init() sets high_memory so only do the check after that.
> >>         */
> >> -       if (mem_init_done && (p < virt_to_phys(high_memory))) {
> >> -               printk("__ioremap(): phys addr 0x%llx is RAM lr %p\n",
> >> -                      (unsigned long long)p, __builtin_return_address(0));
> >> +       if (mem_init_done && (p < virt_to_phys(high_memory))
> >> +#ifdef CONFIG_WII
> >> +               /*
> >> +                * On some systems, though, we may want to remap an area
> >> +                * declared as normal RAM that we have memreserve'd at the
> >> +                * device tree. See wii.dts.
> >> +                * But we can't do that safely if we are using BATs to map
> >> +                * part of that area.
> >> +                */
> >> +           && !__map_without_bats
> >> +#endif
> >> +           ) {
> >> +               printk(KERN_WARNING
> >> +                      "__ioremap(): phys addr 0x%llx is RAM lr %p\n",
> >> +                      (unsigned long long)p,
> >> +                        __builtin_return_address(0));
> > 
> > This could adversely affect multiplatform kernels.  I'd rather get the
> > RAM problem fixed and not hack up common code to work around the hack.
> > 
> > g.
> > 
> 
> Would it be acceptable to create a global var __allow_ioremap_normal_ram that by default would have a value of 0 and would be set _only_ for those platforms needing it?
> 
> The other solutions I see is:
> - add support for discontiguous memory to powerpc 32-bits (which is not something that I can look into now)
> - don't use the precious second 64MB area (which is a waste)

- Implement your own ppc_md.ioremap(), see iseries & cell for example.

Currently that's only called on 64-bit, but you could change that.

If I'm reading your patch right, you should be able to do that check in
your platform's ioremap() and then call the generic implementation to do
the actual work.

cheers
Albert Herranz - Nov. 24, 2009, 5:09 p.m.
Michael Ellerman wrote:
>> Would it be acceptable to create a global var __allow_ioremap_normal_ram that by default would have a value of 0 and would be set _only_ for those platforms needing it?
>>
>> The other solutions I see is:
>> - add support for discontiguous memory to powerpc 32-bits (which is not something that I can look into now)
>> - don't use the precious second 64MB area (which is a waste)
> 
> - Implement your own ppc_md.ioremap(), see iseries & cell for example.
> 
> Currently that's only called on 64-bit, but you could change that.
> 
> If I'm reading your patch right, you should be able to do that check in
> your platform's ioremap() and then call the generic implementation to do
> the actual work.
> 
> cheers

I could use ppc_md.ioremap to duplicate ioremap except for the ioremap ram check.
But calling the stock ioremap without modifying it is not possible because it checks and bails out when ioremapping a region marked as ram (even if it's not real ram and it's memreserved).

Is the list of memreserved areas preserved once the kernel is running?
If it is preserved another option would be to unban ioremapping ram if memreserved.

Thanks for your input,
Albert
Michael Ellerman - Nov. 25, 2009, 12:38 a.m.
On Tue, 2009-11-24 at 18:09 +0100, Albert Herranz wrote:
> Michael Ellerman wrote:
> >> Would it be acceptable to create a global var __allow_ioremap_normal_ram that by default would have a value of 0 and would be set _only_ for those platforms needing it?
> >>
> >> The other solutions I see is:
> >> - add support for discontiguous memory to powerpc 32-bits (which is not something that I can look into now)
> >> - don't use the precious second 64MB area (which is a waste)
> > 
> > - Implement your own ppc_md.ioremap(), see iseries & cell for example.
> > 
> > Currently that's only called on 64-bit, but you could change that.
> > 
> > If I'm reading your patch right, you should be able to do that check in
> > your platform's ioremap() and then call the generic implementation to do
> > the actual work.
> > 
> > cheers
> 
> I could use ppc_md.ioremap to duplicate ioremap except for the ioremap ram check.
> But calling the stock ioremap without modifying it is not possible
> because it checks and bails out when ioremapping a region marked as
> ram (even if it's not real ram and it's memreserved).

OK, that wasn't clear in your patch. It looks like you're adding a check
(!__map_without_bats) - but whatever.

> Is the list of memreserved areas preserved once the kernel is running?
> If it is preserved another option would be to unban ioremapping ram if memreserved.

Yeah it is, so that might work, though it's still a bit of a hack :)
But if that's just a stop-gap until sparse mem gets going on 32-bit
maybe that's OK.

cheers
Benjamin Herrenschmidt - Nov. 26, 2009, 5:22 a.m.
On Tue, 2009-11-24 at 18:09 +0100, Albert Herranz wrote:
> I could use ppc_md.ioremap to duplicate ioremap except for the ioremap
> ram check.
> But calling the stock ioremap without modifying it is not possible
> because it checks and bails out when ioremapping a region marked as
> ram (even if it's not real ram and it's memreserved).
> 
> Is the list of memreserved areas preserved once the kernel is running?
> If it is preserved another option would be to unban ioremapping ram if
> memreserved.

Yes, check lmb's they should still be around.

Cheers,
Ben.
Albert Herranz - Nov. 26, 2009, 3:35 p.m.
Benjamin Herrenschmidt wrote:
> On Tue, 2009-11-24 at 18:09 +0100, Albert Herranz wrote:
>> I could use ppc_md.ioremap to duplicate ioremap except for the ioremap
>> ram check.
>> But calling the stock ioremap without modifying it is not possible
>> because it checks and bails out when ioremapping a region marked as
>> ram (even if it's not real ram and it's memreserved).
>>
>> Is the list of memreserved areas preserved once the kernel is running?
>> If it is preserved another option would be to unban ioremapping ram if
>> memreserved.
> 
> Yes, check lmb's they should still be around.
> 

Good.
So adding a kconfig option to allow ioremapping memreserved memory marked as ram and adding a proper check (under that kconfig) to unban this case in ioremap would be an acceptable solution?

> Cheers,
> Ben.
> 

Thanks,
Albert
Benjamin Herrenschmidt - Nov. 26, 2009, 9:13 p.m.
On Thu, 2009-11-26 at 16:35 +0100, Albert Herranz wrote:
> Benjamin Herrenschmidt wrote:
> > On Tue, 2009-11-24 at 18:09 +0100, Albert Herranz wrote:
> >> I could use ppc_md.ioremap to duplicate ioremap except for the ioremap
> >> ram check.
> >> But calling the stock ioremap without modifying it is not possible
> >> because it checks and bails out when ioremapping a region marked as
> >> ram (even if it's not real ram and it's memreserved).
> >>
> >> Is the list of memreserved areas preserved once the kernel is running?
> >> If it is preserved another option would be to unban ioremapping ram if
> >> memreserved.
> > 
> > Yes, check lmb's they should still be around.
> > 
> 
> Good.
> So adding a kconfig option to allow ioremapping memreserved memory marked
> as ram and adding a proper check (under that kconfig) to unban this case
> in ioremap would be an acceptable solution?

Don't even make it Kconfig. Stick it under you GAMECUBE_COMMON for now
or CONFIG_WII or whatever. This is temporary until we sort out the whole
disctontig mem issue.

Cheers,
Ben.

> > Cheers,
> > Ben.
> > 
> 
> Thanks,
> Albert

Patch

diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index cb96cb2..ba00cb1 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -191,9 +191,22 @@  __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
 	 * Don't allow anybody to remap normal RAM that we're using.
 	 * mem_init() sets high_memory so only do the check after that.
 	 */
-	if (mem_init_done && (p < virt_to_phys(high_memory))) {
-		printk("__ioremap(): phys addr 0x%llx is RAM lr %p\n",
-		       (unsigned long long)p, __builtin_return_address(0));
+	if (mem_init_done && (p < virt_to_phys(high_memory))
+#ifdef CONFIG_WII
+		/*
+		 * On some systems, though, we may want to remap an area
+		 * declared as normal RAM that we have memreserve'd at the
+		 * device tree. See wii.dts.
+		 * But we can't do that safely if we are using BATs to map
+		 * part of that area.
+		 */
+	    && !__map_without_bats
+#endif
+	    ) {
+		printk(KERN_WARNING
+		       "__ioremap(): phys addr 0x%llx is RAM lr %p\n",
+		       (unsigned long long)p,
+			 __builtin_return_address(0));
 		return NULL;
 	}
 #endif