Subject: Reserving a part of the system ram.

From: Ronny Meeus <[email-masked]>
Date: Sat, 9 Feb 2013 14:23:03 +0100

Hello

I have a board that has 4Gb of RAM which can completely be used by
Linux, except for a 64Mb block located just below the 2G boundary.
This block will be used to implement a kind of persistent storage.

On PPC we do this with a memreserve in the device tree but this does
not seem to work on MIPS.
Another option I found is the memmap kernel parameter, which  can also
be used the reserve a piece of memory that is reserved (something like
memmap=size$addres would do the trick, but no luck, this is also not
supported.

This is the Linux version I'm using for my project:
Linux version 2.6.32.27-Cavium-Octeon

What is the correct way to make this work?

Thanks,
Ronny

---

From: Ronny Meeus <[email-masked]>
Date: Mon, 11 Feb 2013 20:00:20 +0100

Hello

I had a look to the code over the weekend and I was able to
understand how it works.
Today I changed the code and it looks like it works. The change I have
made can be found in the patch below.

The clue is that the complete memory of the Cavium board is
managed/known by uboot.
It creates a bootmemory structure that is used by Linux to configure
its memory during init.

It basically allocates blocks of 4MB from this bootmem until the size
specified in the mem parameter is reached.
If 0 is passed to the mem command line parameter, it allocates all
available memory.

Uboot knows already about the memreserves done in the device tree so
the only thing
that was missing is to allocate the memory specified in the
memreserves from the bootmemory.
Once this was done, Linux does not touch the memreserved memory anymore.

The patch below is not a Linux patch, but a uboot one.
Is this way of working a standard solution or is it dedicated to Mips or Cavium?

Regards,
Ronny

diff --git a/arch/mips/cpu/octeon/commands/cmd_octeon_linux.c
b/arch/mips/cpu/octeon/commands/cmd_octeon_linux.c
--- a/arch/mips/cpu/octeon/commands/cmd_octeon_linux.c
+++ b/arch/mips/cpu/octeon/commands/cmd_octeon_linux.c
@@ -189,6 +189,8 @@ int do_bootoctlinux(cmd_tbl_t * cmdtp, i
         */
        cvmx_bootmem_phy_named_block_free(OCTEON_LINUX_RESERVED_MEM_NAME, 0);

+       octeon_alloc_memreserves_from_bootmem();
+
        if (((Elf32_Ehdr *)addr)->e_ident[EI_CLASS] == ELFCLASS32) {
                if (alloc_elf32_image(addr)) {
                        entry_addr = load_elf_image(addr);
diff --git a/arch/mips/cpu/octeon/octeon_fdt.c
b/arch/mips/cpu/octeon/octeon_fdt.c
--- a/arch/mips/cpu/octeon/octeon_fdt.c
+++ b/arch/mips/cpu/octeon/octeon_fdt.c
@@ -344,3 +344,30 @@ int __board_fixup_fdt(void)
 }
 int board_fixup_fdt(void)
        __attribute__((weak, alias("__board_fixup_fdt")));
+
+
+void octeon_alloc_memreserves_from_bootmem(void)
+{
+       uint64_t addr, size;
+       int j, err;
+       char name[32];
+       int total = fdt_num_mem_rsv(working_fdt);
+       for (j = 0; j < total; j++) {
+               int64_t mem = 0;
+               err = fdt_get_mem_rsv(working_fdt, j, &addr, &size);
+               if (err < 0) {
+                       printf("libfdt fdt_get_mem_rsv():  %s\n",
+                       fdt_strerror(err));
+                       return err;
+               }
+               sprintf(name,"fdt_memreserve%d",j);
+               printf("alloc_bootmem %16s %08x%08x %08x%08x\n",name,
+                       (u32)(addr >> 32),(u32)(addr & 0xffffffff),
+                       (u32)(size >> 32),(u32)(size & 0xffffffff));
+               mem =
cvmx_bootmem_phy_named_block_alloc(size,addr,addr+size,0,name,0);
+               if (mem < 0) {
+                       printf("Named allocation failed!\n");
+               }
+       }
+}
+
diff --git a/arch/mips/include/asm/arch-octeon/octeon_fdt.h
b/arch/mips/include/asm/arch-octeon/octeon_fdt.h
--- a/arch/mips/include/asm/arch-octeon/octeon_fdt.h
+++ b/arch/mips/include/asm/arch-octeon/octeon_fdt.h
@@ -77,5 +77,6 @@
 int octeon_fdt_patch(void *fdt, const char *fdt_key, const char *trim_name);
 int board_fixup_fdt(void);
 void octeon_fixup_fdt(void);
+void octeon_alloc_memreserves_from_bootmem(void);

-#endif /* __OCTEON_FDT_H__ */
\ No newline at end of file
+#endif /* __OCTEON_FDT_H__ */