diff mbox

[05/10] powerpc/ps3: Use highmem region from repository

Message ID 1e755c09926de2d9b0e239ba0ce10fdb6835551a.1335379330.git.geoff@infradead.org (mailing list archive)
State Accepted, archived
Commit 1e755c09926de2d9b0e239ba0ce10fdb6835551a
Headers show

Commit Message

Andre Heider April 25, 2012, 7:19 p.m. UTC
Use any preallocated highmem region setup by the bootloader.
This implementation only checks for the existance of a single
region at region_index=0.

This feature allows the bootloader to preallocate highmem
regions and pass the region locations to the kernel through
the repository.  Preallocated regions can be used to hold the
initrd or other large data.  If no region info exists, the
kernel retains the old behavior and attempts to allocate the
highmem region itself.

Based on Hector Martin's patch "Get lv1 high memory region from
devtree".

CC: Hector Martin <hector@marcansoft.com>
Signed-off-by: Andre Heider <a.heider@gmail.com>
CC: Nathan Whitehorn <nwhitehorn@freebsd.org>
Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/powerpc/platforms/ps3/mm.c |   51 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 49 insertions(+), 2 deletions(-)

Comments

Michael Ellerman June 13, 2012, 1:49 a.m. UTC | #1
On Wed, 2012-04-25 at 19:19 +0000, Andre Heider wrote:
> Use any preallocated highmem region setup by the bootloader.
> This implementation only checks for the existance of a single
> region at region_index=0.
> 
> This feature allows the bootloader to preallocate highmem
> regions and pass the region locations to the kernel through
> the repository.  Preallocated regions can be used to hold the
> initrd or other large data.  If no region info exists, the
> kernel retains the old behavior and attempts to allocate the
> highmem region itself.
> 
> Based on Hector Martin's patch "Get lv1 high memory region from
> devtree".

Apologies if this has been covered before, but why not use the device
tree?

cheers
Geoff Levand June 13, 2012, 5:58 p.m. UTC | #2
Hi Michael,

On Wed, 2012-06-13 at 11:49 +1000, Michael Ellerman wrote:
> On Wed, 2012-04-25 at 19:19 +0000, Andre Heider wrote:
> > Use any preallocated highmem region setup by the bootloader.
> > This implementation only checks for the existance of a single
> > region at region_index=0.
> > 
> > This feature allows the bootloader to preallocate highmem
> > regions and pass the region locations to the kernel through
> > the repository.  Preallocated regions can be used to hold the
> > initrd or other large data.  If no region info exists, the
> > kernel retains the old behavior and attempts to allocate the
> > highmem region itself.
> > 
> > Based on Hector Martin's patch "Get lv1 high memory region from
> > devtree".
> 
> Apologies if this has been covered before, but why not use the device
> tree?

FreeBSD (and other OS's) don't know about the Linux device tree.

This mechanism is for the bootloader to tell the OS about a highmem
region it setup, and we want to support more than just Linux.

-Geoff
Nathan Whitehorn June 13, 2012, 6:25 p.m. UTC | #3
On 06/13/12 12:58, Geoff Levand wrote:
> Hi Michael,
>
> On Wed, 2012-06-13 at 11:49 +1000, Michael Ellerman wrote:
>> On Wed, 2012-04-25 at 19:19 +0000, Andre Heider wrote:
>>> Use any preallocated highmem region setup by the bootloader.
>>> This implementation only checks for the existance of a single
>>> region at region_index=0.
>>>
>>> This feature allows the bootloader to preallocate highmem
>>> regions and pass the region locations to the kernel through
>>> the repository.  Preallocated regions can be used to hold the
>>> initrd or other large data.  If no region info exists, the
>>> kernel retains the old behavior and attempts to allocate the
>>> highmem region itself.
>>>
>>> Based on Hector Martin's patch "Get lv1 high memory region from
>>> devtree".
>> Apologies if this has been covered before, but why not use the device
>> tree?
> FreeBSD (and other OS's) don't know about the Linux device tree.
>
> This mechanism is for the bootloader to tell the OS about a highmem
> region it setup, and we want to support more than just Linux.
>
> -Geoff
>
>
FreeBSD actually does have FDT support -- it's just not used for the PS3 
platform at the moment since it is (currently) totally redundant with 
the HV repository. If people decide that FDT has an advantage, FreeBSD 
at least can easily be adapted to use it.
-Nathan
diff mbox

Patch

diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index de2aea4..05a2bcb 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -79,12 +79,14 @@  enum {
  * @base: base address
  * @size: size in bytes
  * @offset: difference between base and rm.size
+ * @destroy: flag if region should be destroyed upon shutdown
  */
 
 struct mem_region {
 	u64 base;
 	u64 size;
 	unsigned long offset;
+	int destroy;
 };
 
 /**
@@ -262,6 +264,7 @@  static int ps3_mm_region_create(struct mem_region *r, unsigned long size)
 		goto zero_region;
 	}
 
+	r->destroy = 1;
 	r->offset = r->base - map.rm.size;
 	return result;
 
@@ -279,7 +282,14 @@  static void ps3_mm_region_destroy(struct mem_region *r)
 {
 	int result;
 
+	if (!r->destroy) {
+		pr_info("%s:%d: Not destroying high region: %llxh %llxh\n",
+			__func__, __LINE__, r->base, r->size);
+		return;
+	}
+
 	DBG("%s:%d: r->base = %llxh\n", __func__, __LINE__, r->base);
+
 	if (r->base) {
 		result = lv1_release_memory(r->base);
 		BUG_ON(result);
@@ -288,6 +298,36 @@  static void ps3_mm_region_destroy(struct mem_region *r)
 	}
 }
 
+static int ps3_mm_get_repository_highmem(struct mem_region *r)
+{
+	int result;
+
+	/* Assume a single highmem region. */
+
+	result = ps3_repository_read_highmem_info(0, &r->base, &r->size);
+
+	if (result)
+		goto zero_region;
+
+	if (!r->base || !r->size) {
+		result = -1;
+		goto zero_region;
+	}
+
+	r->offset = r->base - map.rm.size;
+
+	DBG("%s:%d: Found high region in repository: %llxh %llxh\n",
+	    __func__, __LINE__, r->base, r->size);
+
+	return 0;
+
+zero_region:
+	DBG("%s:%d: No high region in repository.\n", __func__, __LINE__);
+
+	r->size = r->base = r->offset = 0;
+	return result;
+}
+
 /**
  * ps3_mm_add_memory - hot add memory
  */
@@ -304,6 +344,12 @@  static int __init ps3_mm_add_memory(void)
 
 	BUG_ON(!mem_init_done);
 
+	if (!map.r1.size) {
+		DBG("%s:%d: No region 1, not adding memory\n",
+		    __func__, __LINE__);
+		return 0;
+	}
+
 	start_addr = map.rm.size;
 	start_pfn = start_addr >> PAGE_SHIFT;
 	nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -1217,9 +1263,10 @@  void __init ps3_mm_init(void)
 	BUG_ON(map.rm.base);
 	BUG_ON(!map.rm.size);
 
+	/* Check if we got the highmem region from an earlier boot step */
 
-	/* arrange to do this in ps3_mm_add_memory */
-	ps3_mm_region_create(&map.r1, map.total - map.rm.size);
+	if (ps3_mm_get_repository_highmem(&map.r1))
+		ps3_mm_region_create(&map.r1, map.total - map.rm.size);
 
 	/* correct map.total for the real total amount of memory we use */
 	map.total = map.rm.size + map.r1.size;