[haiku-commits] haiku: hrev44185 - in src/system/boot/platform: raspberrypi_arm u-boot

  • From: kallisti5@xxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 18 May 2012 19:30:28 +0200 (CEST)

hrev44185 adds 2 changesets to branch 'master'
old head: 268816a3cecb914207390291e18720cf757f7368
new head: 77591e9657b29aa1742a54411f8a31696bd0a8a2

----------------------------------------------------------------------------

6d4270e: U-Boot mmu: Style cleanup, no functional change

77591e9: rPi: MMU Work
  
  * Use U-Boot mmu code as base
  * This will be factored out someday into common arch mmu
    code when we can read Flattened Device Trees
  * Move mmu_init after serial_init.
    Temporary change as we will want serial_init to use
    memory mapped addresses... for debugging.

                          [ Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> ]

----------------------------------------------------------------------------

5 files changed, 679 insertions(+), 72 deletions(-)
headers/private/kernel/arch/arm/bcm2708.h        |    9 +-
src/system/boot/platform/raspberrypi_arm/mmu.cpp |  635 +++++++++++++++++-
src/system/boot/platform/raspberrypi_arm/mmu.h   |   24 +-
src/system/boot/platform/raspberrypi_arm/start.c |    8 +-
src/system/boot/platform/u-boot/mmu.cpp          |   75 ++-

############################################################################

Commit:      6d4270e3ce9c0646761b2bd5e5b2e85cba90a975
URL:         http://cgit.haiku-os.org/haiku/commit/?id=6d4270e
Author:      Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Date:        Fri May 18 10:39:52 2012 UTC

U-Boot mmu: Style cleanup, no functional change

----------------------------------------------------------------------------

diff --git a/src/system/boot/platform/u-boot/mmu.cpp 
b/src/system/boot/platform/u-boot/mmu.cpp
index 80405c3..f219d19 100644
--- a/src/system/boot/platform/u-boot/mmu.cpp
+++ b/src/system/boot/platform/u-boot/mmu.cpp
@@ -41,6 +41,7 @@
 
 #ifdef __ARM__
 
+
 /*
 TODO:
        -recycle bit!
@@ -61,70 +62,72 @@ TODO:
 */
 
 
-
-
-
-
 /*
 *defines a block in memory
 */
 struct memblock {
-        const char      name[16]; // the name will be used for debugging etc 
later perhaps...
-        addr_t    start; // start of the block
-        addr_t    end; // end of the block
-       uint32    flags; // which flags should be applied (device/normal etc..)
+       const char name[16];
+               // the name will be used for debugging etc later perhaps...
+       addr_t  start;
+               // start of the block
+       addr_t  end;
+               // end of the block
+       uint32  flags;
+               // which flags should be applied (device/normal etc..)
 };
 
 
 static struct memblock LOADER_MEMORYMAP[] = {
        {
-                "devices",
+               "devices",
                DEVICE_BASE,
                DEVICE_BASE + DEVICE_SIZE - 1,
                MMU_L2_FLAG_B,
-        },
-        {
-                "RAM_loader",//1MB loader
+       },
+       {
+               "RAM_loader", // 1MB loader
                SDRAM_BASE + 0,
                SDRAM_BASE + 0x0fffff,
                MMU_L2_FLAG_C,
-        },
-        {
-                "RAM_pt",//Page Table 1MB
+       },
+       {
+               "RAM_pt", // Page Table 1MB
                SDRAM_BASE + 0x100000,
                SDRAM_BASE + 0x1FFFFF,
                MMU_L2_FLAG_C,
-        },
-        {
-                "RAM_free",//16MB free RAM (actually more but we don't 
identity map it automaticaly)
+       },
+       {
+               "RAM_free", // 16MB free RAM (more but we don't map it 
automaticaly)
                SDRAM_BASE + 0x0200000,
                SDRAM_BASE + 0x11FFFFF,
                MMU_L2_FLAG_C,
-        },
-        {
-                "RAM_stack",//stack
+       },
+       {
+               "RAM_stack", // stack
                SDRAM_BASE + 0x1200000,
                SDRAM_BASE + 0x2000000,
                MMU_L2_FLAG_C,
-        },
-        {
-                "RAM_initrd",//stack
+       },
+       {
+               "RAM_initrd", // stack
                SDRAM_BASE + 0x2000000,
                SDRAM_BASE + 0x2500000,
                MMU_L2_FLAG_C,
-        },
+       },
 
 #ifdef FB_BASE
-        {
-                "framebuffer",//2MB framebuffer ram
+       {
+               "framebuffer", // 2MB framebuffer ram
                FB_BASE,
                FB_BASE + FB_SIZE - 1,
                MMU_L2_FLAG_AP_RW|MMU_L2_FLAG_C,
-        },
+       },
 #endif
 };
 
-//static const uint32 kDefaultPageTableFlags = MMU_FLAG_READWRITE;     // not 
cached not buffered, R/W
+
+//static const uint32 kDefaultPageTableFlags = MMU_FLAG_READWRITE;
+       // not cached not buffered, R/W
 static const size_t kMaxKernelSize = 0x200000;         // 2 MB for the kernel
 
 static addr_t sNextPhysicalAddress = 0; //will be set by mmu_init
@@ -183,22 +186,23 @@ get_next_physical_address_alligned(size_t size, uint32 
mask)
 static addr_t
 get_next_virtual_page(size_t pagesize)
 {
-       return get_next_virtual_address_alligned( pagesize, 0xffffffc0 );
+       return get_next_virtual_address_alligned(pagesize, 0xffffffc0);
 }
 
 
 static addr_t
 get_next_physical_page(size_t pagesize)
 {
-       return get_next_physical_address_alligned( pagesize, 0xffffffc0 );
+       return get_next_physical_address_alligned(pagesize, 0xffffffc0);
 }
 
 
 void
 mmu_set_TTBR(uint32  ttb)
 {
-       ttb &=  0xffffc000;
-       asm volatile( "MCR p15, 0, %[adr], c2, c0, 0"::[adr] "r" (ttb)  ); /* 
set translation table base */
+       ttb &= 0xffffc000;
+       asm volatile("MCR p15, 0, %[adr], c2, c0, 0"::[adr] "r" (ttb));
+               // set translation table base
 }
 
 
@@ -206,7 +210,8 @@ void
 mmu_flush_TLB()
 {
        uint32 bla = 0;
-       asm volatile("MCR p15, 0, %[c8format], c8, c7, 0"::[c8format] "r" (bla) 
); /* flush TLB */
+       asm volatile("MCR p15, 0, %[c8format], c8, c7, 0"::[c8format] "r" 
(bla));
+               // flush TLB
 }
 
 
@@ -239,7 +244,7 @@ get_next_page_table(uint32 type)
        TRACE(("get_next_page_table, sNextPageTableAddress %p, 
kPageTableRegionEnd "
                "%p, type  0x%lx\n", sNextPageTableAddress, 
kPageTableRegionEnd, type));
        size_t size = 0;
-       switch(type){
+       switch(type) {
                case MMU_L1_TYPE_COARSEPAGETABLE:
                        size = 1024;
                break;

############################################################################

Revision:    hrev44185
Commit:      77591e9657b29aa1742a54411f8a31696bd0a8a2
URL:         http://cgit.haiku-os.org/haiku/commit/?id=77591e9
Author:      Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Date:        Fri May 18 11:36:26 2012 UTC

rPi: MMU Work

* Use U-Boot mmu code as base
* This will be factored out someday into common arch mmu
  code when we can read Flattened Device Trees
* Move mmu_init after serial_init.
  Temporary change as we will want serial_init to use
  memory mapped addresses... for debugging.

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/arch/arm/bcm2708.h 
b/headers/private/kernel/arch/arm/bcm2708.h
index 168b8b9..07f0ba6 100644
--- a/headers/private/kernel/arch/arm/bcm2708.h
+++ b/headers/private/kernel/arch/arm/bcm2708.h
@@ -40,7 +40,6 @@
 #define BCM2708_SDRAM_BASE     0x00000000
 #define BCM2708_PERI_BASE      0x20000000
 
-#define SDRAM_BASE             BCM2708_SDRAM_BASE
 #define ST_BASE                        (BCM2708_PERI_BASE + 0x3000)
        // System Timer, sec 12.0, page 172
 #define DMA_BASE               (BCM2708_PERI_BASE + 0x7000)
@@ -80,8 +79,12 @@
 #define VECT_BASE 0xffff0000
 #define VECT_SIZE SIZE_4K
 
-#define DEVICE_BASE            ARM_CTRL_BASE
-#define DEVICE_SIZE            SIZE_4K
+#define PERIPHERAL_BASE                BCM2708_PERI_BASE
+#define PERIPHERAL_SIZE                0x1000000
+
+#define SDRAM_BASE             BCM2708_SDRAM_BASE
+#define SDRAM_SIZE             0x4000000
+       // 64Mb
 
 
 /* UART */
diff --git a/src/system/boot/platform/raspberrypi_arm/mmu.cpp 
b/src/system/boot/platform/raspberrypi_arm/mmu.cpp
index d2178f7..27b78c7 100644
--- a/src/system/boot/platform/raspberrypi_arm/mmu.cpp
+++ b/src/system/boot/platform/raspberrypi_arm/mmu.cpp
@@ -1,6 +1,8 @@
 /*
- * Copyright 2009 Jonas Sundström, jonas@xxxxxxxxxxx
- * All rights reserved. Distributed under the terms of the MIT License.
+ * Copyright 2004-2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * Based on code written by Travis Geiselbrecht for NewOS.
+ *
+ * Distributed under the terms of the MIT License.
  */
 
 
@@ -12,50 +14,626 @@
 #include <boot/stage2.h>
 #include <arch/cpu.h>
 #include <arch_kernel.h>
+#ifdef __ARM__
+#include <arm_mmu.h>
+#endif
 #include <kernel.h>
 
+#include <board_config.h>
+
 #include <OS.h>
 
 #include <string.h>
 
 
+#define TRACE_MMU
+#ifdef TRACE_MMU
+#      define TRACE(x) dprintf x
+#else
+#      define TRACE(x) ;
+#endif
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#define TRACE_MEMORY_MAP
+       // Define this to print the memory map to serial debug,
+       // You also need to define ENABLE_SERIAL in serial.cpp
+       // for output to work.
+
+extern uint8 __stack_start;
+extern uint8 __stack_end;
+
+
+#ifdef __ARM__
+
+
+/*
+TODO:
+       -recycle bit!
+*/
+
+/*!    The (physical) memory layout of the boot loader is currently as follows:
+        0x00000000                     u-boot (run from NOR flash)
+        0xa0000000                     u-boot stuff like kernel arguments afaik
+        0xa0100000 - 0xa0ffffff        boot.tgz (up to 15MB probably never 
needed so big...)
+        0xa1000000 - 0xa1ffffff        pagetables
+        0xa2000000 - ?                 code (up to 1MB)
+        0xa2100000                     boot loader heap / free physical memory
+
+       The kernel is mapped at KERNEL_BASE, all other stuff mapped by the
+       loader (kernel args, modules, driver settings, ...) comes after
+       0x80020000 which means that there is currently only 2 MB reserved for
+       the kernel itself (see kMaxKernelSize).
+*/
+
+
+/*
+*defines a block in memory
+*/
+struct memblock {
+       const char name[16];
+               // the name will be used for debugging etc later perhaps...
+       addr_t  start;
+               // start of the block
+       addr_t  end;
+               // end of the block
+       uint32  flags;
+               // which flags should be applied (device/normal etc..)
+};
+
+
+static struct memblock LOADER_MEMORYMAP[] = {
+       {
+               "devices",
+               PERIPHERAL_BASE,
+               PERIPHERAL_BASE + PERIPHERAL_SIZE - 1,
+               MMU_L2_FLAG_B,
+       },
+       {
+               "RAM_loader", // 1MB loader
+               SDRAM_BASE + 0,
+               SDRAM_BASE + 0x0fffff,
+               MMU_L2_FLAG_C,
+       },
+       {
+               "RAM_pt", // Page Table 1MB
+               SDRAM_BASE + 0x100000,
+               SDRAM_BASE + 0x1FFFFF,
+               MMU_L2_FLAG_C,
+       },
+       {
+               "RAM_free", // 16MB free RAM (more but we don't map it 
automaticaly)
+               SDRAM_BASE + 0x0200000,
+               SDRAM_BASE + 0x11FFFFF,
+               MMU_L2_FLAG_C,
+       },
+#if 0
+       {
+               "RAM_stack", // stack
+               SDRAM_BASE + 0x1200000,
+               SDRAM_BASE + 0x2000000,
+               MMU_L2_FLAG_C,
+       },
+       {
+               "RAM_initrd", // stack
+               SDRAM_BASE + 0x2000000,
+               SDRAM_BASE + 0x2500000,
+               MMU_L2_FLAG_C,
+       },
+
+#ifdef FB_BASE
+       {
+               "framebuffer", // 2MB framebuffer ram
+               FB_BASE,
+               FB_BASE + FB_SIZE - 1,
+               MMU_L2_FLAG_AP_RW|MMU_L2_FLAG_C,
+       },
+#endif
+#endif
+};
+
+
+//static const uint32 kDefaultPageTableFlags = MMU_FLAG_READWRITE;
+       // not cached not buffered, R/W
+static const size_t kMaxKernelSize = 0x200000;         // 2 MB for the kernel
+
+static addr_t sNextPhysicalAddress = 0; //will be set by mmu_init
+static addr_t sNextVirtualAddress = KERNEL_BASE + kMaxKernelSize;
+static addr_t sMaxVirtualAddress = KERNEL_BASE + kMaxKernelSize;
+
+static addr_t sNextPageTableAddress = 0;
+//the page directory is in front of the pagetable
+static uint32 kPageTableRegionEnd = 0;
+
+// working page directory and page table
+static uint32 *sPageDirectory = 0 ;
+//page directory has to be on a multiple of 16MB for
+//some arm processors
+
+
+static addr_t
+get_next_virtual_address(size_t size)
+{
+       addr_t address = sNextVirtualAddress;
+       sNextVirtualAddress += size;
+
+       return address;
+}
+
+
+static addr_t
+get_next_virtual_address_alligned (size_t size, uint32 mask)
+{
+       addr_t address = (sNextVirtualAddress) & mask;
+       sNextVirtualAddress = address + size;
+
+       return address;
+}
+
+
+static addr_t
+get_next_physical_address(size_t size)
+{
+       addr_t address = sNextPhysicalAddress;
+       sNextPhysicalAddress += size;
+
+       return address;
+}
+
+
+static addr_t
+get_next_physical_address_alligned(size_t size, uint32 mask)
+{
+       addr_t address = sNextPhysicalAddress & mask;
+       sNextPhysicalAddress = address + size;
+
+       return address;
+}
+
+
+static addr_t
+get_next_virtual_page(size_t pagesize)
+{
+       return get_next_virtual_address_alligned(pagesize, 0xffffffc0);
+}
+
+
+static addr_t
+get_next_physical_page(size_t pagesize)
+{
+       return get_next_physical_address_alligned(pagesize, 0xffffffc0);
+}
+
+
+void
+mmu_set_TTBR(uint32  ttb)
+{
+       ttb &= 0xffffc000;
+       asm volatile("MCR p15, 0, %[adr], c2, c0, 0"::[adr] "r" (ttb));
+               // set translation table base
+}
+
+
+void
+mmu_flush_TLB()
+{
+       uint32 bla = 0;
+       asm volatile("MCR p15, 0, %[c8format], c8, c7, 0"::[c8format] "r" 
(bla));
+               // flush TLB
+}
+
+
+uint32
+mmu_read_C1()
+{
+       uint32 bla = 0;
+       asm volatile("MRC p15, 0, %[c1out], c1, c0, 0":[c1out] "=r" (bla));
+       return bla;
+}
+
+
+void
+mmu_write_C1(uint32 value)
+{
+       asm volatile("MCR p15, 0, %[c1in], c1, c0, 0"::[c1in] "r" (value));
+}
+
+
+void
+mmu_write_DACR(uint32 value)
+{
+       asm volatile("MCR p15, 0, %[c1in], c3, c0, 0"::[c1in] "r" (value));
+}
+
+
+static uint32 *
+get_next_page_table(uint32 type)
+{
+       TRACE(("get_next_page_table, sNextPageTableAddress %p, 
kPageTableRegionEnd "
+               "%p, type  0x%lx\n", sNextPageTableAddress, 
kPageTableRegionEnd, type));
+       size_t size = 0;
+       switch(type) {
+               case MMU_L1_TYPE_COARSEPAGETABLE:
+                       size = 1024;
+               break;
+               case MMU_L1_TYPE_FINEEPAGETABLE:
+                       size = 4096;
+               break;
+       }
+
+       addr_t address = sNextPageTableAddress;
+       if (address >= kPageTableRegionEnd) {
+               TRACE(("outside of pagetableregion!\n"));
+               return (uint32 *)get_next_physical_address_alligned(size, 
0xffffffc0);
+       }
+
+       sNextPageTableAddress += size;
+       return (uint32 *)address;
+}
+
+
+void
+init_page_directory()
+{
+       TRACE(("init_page_directory\n"));
+       uint32 smalltype;
+
+       // see if subpages disabled
+       if (mmu_read_C1() & (1<<23))
+               smalltype = MMU_L2_TYPE_SMALLNEW;
+       else
+               smalltype = MMU_L2_TYPE_SMALLEXT;
+
+       gKernelArgs.arch_args.phys_pgdir = (uint32)sPageDirectory;
+
+       // clear out the pgdir
+       for (uint32 i = 0; i < 4096; i++)
+       sPageDirectory[i] = 0;
+
+       uint32 *pageTable = NULL;
+       for (uint32 i = 0; i < ARRAY_SIZE(LOADER_MEMORYMAP);i++) {
+
+               pageTable = get_next_page_table(MMU_L1_TYPE_COARSEPAGETABLE);
+               TRACE(("BLOCK: %s START: %lx END %lx\n", 
LOADER_MEMORYMAP[i].name,
+                       LOADER_MEMORYMAP[i].start, LOADER_MEMORYMAP[i].end));
+               addr_t pos = LOADER_MEMORYMAP[i].start;
+
+               int c = 0;
+               while (pos < LOADER_MEMORYMAP[i].end) {
+                       pageTable[c] = pos |  LOADER_MEMORYMAP[i].flags | 
smalltype;
+
+                       c++;
+                       if (c > 255) { // we filled a pagetable => we need a 
new one
+                               // there is 1MB per pagetable so:
+                               sPageDirectory[VADDR_TO_PDENT(pos)]
+                                       = (uint32)pageTable | 
MMU_L1_TYPE_COARSEPAGETABLE;
+                               pageTable = 
get_next_page_table(MMU_L1_TYPE_COARSEPAGETABLE);
+                               c = 0;
+                       }
+
+                       pos += B_PAGE_SIZE;
+               }
+
+               if (c > 0) {
+                       sPageDirectory[VADDR_TO_PDENT(pos)]
+                               = (uint32)pageTable | 
MMU_L1_TYPE_COARSEPAGETABLE;
+               }
+       }
+
+       mmu_flush_TLB();
+
+       /* set up the translation table base */
+       mmu_set_TTBR((uint32)sPageDirectory);
+
+       mmu_flush_TLB();
+
+       /* set up the domain access register */
+       mmu_write_DACR(0xFFFFFFFF);
+
+       /* turn on the mmu */
+       mmu_write_C1(mmu_read_C1() | 0x1);
+}
+
+
+/*!     Adds a new page table for the specified base address */
+static void
+add_page_table(addr_t base)
+{
+       TRACE(("add_page_table(base = %p)\n", (void *)base));
+
+       // Get new page table and clear it out
+       uint32 *pageTable = get_next_page_table(MMU_L1_TYPE_COARSEPAGETABLE);
+/*
+       if (pageTable > (uint32 *)(8 * 1024 * 1024)) {
+               panic("tried to add page table beyond the indentity mapped 8 MB 
"
+                       "region\n");
+       }
+*/
+       for (int32 i = 0; i < 256; i++)
+               pageTable[i] = 0;
+
+       // put the new page table into the page directory
+       sPageDirectory[VADDR_TO_PDENT(base)]
+               = (uint32)pageTable | MMU_L1_TYPE_COARSEPAGETABLE;
+}
+
+
+/*!    Creates an entry to map the specified virtualAddress to the given
+       physicalAddress.
+       If the mapping goes beyond the current page table, it will allocate
+       a new one. If it cannot map the requested page, it panics.
+*/
+static void
+map_page(addr_t virtualAddress, addr_t physicalAddress, uint32 flags)
+{
+       TRACE(("map_page: vaddr 0x%lx, paddr 0x%lx\n", virtualAddress,
+               physicalAddress));
+
+       if (virtualAddress < KERNEL_BASE) {
+               panic("map_page: asked to map invalid page %p!\n",
+                       (void *)virtualAddress);
+       }
+
+       if (virtualAddress >= sMaxVirtualAddress) {
+               // we need to add a new page table
+               add_page_table(sMaxVirtualAddress);
+               sMaxVirtualAddress += B_PAGE_SIZE * 256;
+
+               if (virtualAddress >= sMaxVirtualAddress) {
+                       panic("map_page: asked to map a page to %p\n",
+                               (void *)virtualAddress);
+               }
+       }
+
+       physicalAddress &= ~(B_PAGE_SIZE - 1);
+
+       // map the page to the correct page table
+       uint32 *pageTable
+               = (uint32 *)(sPageDirectory[VADDR_TO_PDENT(virtualAddress)]
+                       & ARM_PDE_ADDRESS_MASK);
+
+       TRACE(("map_page: pageTable 0x%lx\n",
+               sPageDirectory[VADDR_TO_PDENT(virtualAddress)] & 
ARM_PDE_ADDRESS_MASK));
+
+       if (pageTable == NULL) {
+               add_page_table(virtualAddress);
+               pageTable = (uint32 
*)(sPageDirectory[VADDR_TO_PDENT(virtualAddress)]
+                       & ARM_PDE_ADDRESS_MASK);
+       }
+
+       uint32 tableEntry = VADDR_TO_PTENT(virtualAddress);
+
+       TRACE(("map_page: inserting pageTable %p, tableEntry %ld, 
physicalAddress "
+               "%p\n", pageTable, tableEntry, physicalAddress));
+
+       pageTable[tableEntry] = physicalAddress | flags;
+
+       mmu_flush_TLB();
+
+       TRACE(("map_page: done\n"));
+}
+
+
 //     #pragma mark -
 
 
 extern "C" addr_t
 mmu_map_physical_memory(addr_t physicalAddress, size_t size, uint32 flags)
 {
-#warning IMPLEMENT mmu_map_physical_memory
-       return 0;
+       addr_t address = sNextVirtualAddress;
+       addr_t pageOffset = physicalAddress & (B_PAGE_SIZE - 1);
+
+       physicalAddress -= pageOffset;
+
+       for (addr_t offset = 0; offset < size; offset += B_PAGE_SIZE) {
+               map_page(get_next_virtual_page(B_PAGE_SIZE), physicalAddress + 
offset,
+                       flags);
+       }
+
+       return address + pageOffset;
 }
 
 
-extern "C" void*
-mmu_allocate(void* virtualAddress, size_t size)
+static void
+unmap_page(addr_t virtualAddress)
 {
-#warning IMPLEMENT mmu_allocate
-       return 0;
+       TRACE(("unmap_page(virtualAddress = %p)\n", (void *)virtualAddress));
+
+       if (virtualAddress < KERNEL_BASE) {
+               panic("unmap_page: asked to unmap invalid page %p!\n",
+                       (void *)virtualAddress);
+       }
+
+       // unmap the page from the correct page table
+       uint32 *pageTable
+               = (uint32 *)(sPageDirectory[VADDR_TO_PDENT(virtualAddress)]
+                       & ARM_PDE_ADDRESS_MASK);
+
+       pageTable[VADDR_TO_PTENT(virtualAddress)] = 0;
+
+       mmu_flush_TLB();
 }
 
 
+extern "C" void *
+mmu_allocate(void *virtualAddress, size_t size)
+{
+       TRACE(("mmu_allocate: requested vaddr: %p, next free vaddr: 0x%lx, 
size: "
+               "%ld\n", virtualAddress, sNextVirtualAddress, size));
+
+       size = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE;
+               // get number of pages to map
+
+       if (virtualAddress != NULL) {
+               // This special path is almost only useful for loading the
+               // kernel into memory; it will only allow you to map the
+               // 'kMaxKernelSize' bytes following the kernel base address.
+               // Also, it won't check for already mapped addresses, so
+               // you better know why you are here :)
+               addr_t address = (addr_t)virtualAddress;
+
+               // is the address within the valid range?
+               if (address < KERNEL_BASE
+                       || address + size >= KERNEL_BASE + kMaxKernelSize) {
+                       TRACE(("mmu_allocate in illegal range\n address: %lx"
+                               "  KERNELBASE: %lx KERNEL_BASE + 
kMaxKernelSize: %lx"
+                               "  address + size : %lx \n", (uint32)address, 
KERNEL_BASE,
+                               KERNEL_BASE + kMaxKernelSize, (uint32)(address 
+ size)));
+                       return NULL;
+               }
+               for (uint32 i = 0; i < size; i++) {
+                       map_page(address, get_next_physical_page(B_PAGE_SIZE),
+                               kDefaultPageFlags);
+                       address += B_PAGE_SIZE;
+               }
+
+               return virtualAddress;
+       }
+
+       void *address = (void *)sNextVirtualAddress;
+
+       for (uint32 i = 0; i < size; i++) {
+               map_page(get_next_virtual_page(B_PAGE_SIZE),
+                       get_next_physical_page(B_PAGE_SIZE), kDefaultPageFlags);
+       }
+
+       return address;
+}
+
+
+/*!    This will unmap the allocated chunk of memory from the virtual
+       address space. It might not actually free memory (as its implementation
+       is very simple), but it might.
+*/
 extern "C" void
-mmu_free(void* virtualAddress, size_t size)
+mmu_free(void *virtualAddress, size_t size)
 {
-#warning IMPLEMENT mmu_free
+       TRACE(("mmu_free(virtualAddress = %p, size: %ld)\n", virtualAddress, 
size));
+
+       addr_t address = (addr_t)virtualAddress;
+       size = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE;
+               // get number of pages to map
+
+       // is the address within the valid range?
+       if (address < KERNEL_BASE
+               || address + size >= KERNEL_BASE + kMaxKernelSize) {
+               panic("mmu_free: asked to unmap out of range region (%p, size 
%lx)\n",
+                       (void *)address, size);
+       }
+
+       // unmap all pages within the range
+       for (uint32 i = 0; i < size; i++) {
+               unmap_page(address);
+               address += B_PAGE_SIZE;
+       }
+
+       if (address == sNextVirtualAddress) {
+               // we can actually reuse the virtual address space
+               sNextVirtualAddress -= size;
+       }
 }
+#endif
 
 
+/*!    Sets up the final and kernel accessible GDT and IDT tables.
+       BIOS calls won't work any longer after this function has
+       been called.
+*/
 extern "C" void
 mmu_init_for_kernel(void)
 {
-#warning IMPLEMENT mmu_init_for_kernel
+       TRACE(("mmu_init_for_kernel\n"));
+
+       // save the memory we've physically allocated
+       gKernelArgs.physical_allocated_range[0].size
+               = sNextPhysicalAddress - 
gKernelArgs.physical_allocated_range[0].start;
+
+       // Save the memory we've virtually allocated (for the kernel and other
+       // stuff)
+       gKernelArgs.virtual_allocated_range[0].start = KERNEL_BASE;
+       gKernelArgs.virtual_allocated_range[0].size
+               = sNextVirtualAddress - KERNEL_BASE;
+       gKernelArgs.num_virtual_allocated_ranges = 1;
+
+#ifdef TRACE_MEMORY_MAP
+       {
+               uint32 i;
+
+               dprintf("phys memory ranges:\n");
+               for (i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) {
+                       dprintf("    base 0x%08lx, length 0x%08lx\n",
+                               gKernelArgs.physical_memory_range[i].start,
+                               gKernelArgs.physical_memory_range[i].size);
+               }
+
+               dprintf("allocated phys memory ranges:\n");
+               for (i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) 
{
+                       dprintf("    base 0x%08lx, length 0x%08lx\n",
+                               gKernelArgs.physical_allocated_range[i].start,
+                               gKernelArgs.physical_allocated_range[i].size);
+               }
+
+               dprintf("allocated virt memory ranges:\n");
+               for (i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) {
+                       dprintf("    base 0x%08lx, length 0x%08lx\n",
+                               gKernelArgs.virtual_allocated_range[i].start,
+                               gKernelArgs.virtual_allocated_range[i].size);
+               }
+       }
+#endif
 }
 
 
 extern "C" void
 mmu_init(void)
 {
-#warning IMPLEMENT mmu_init
+       TRACE(("mmu_init\n"));
+
+       mmu_write_C1(mmu_read_C1() & ~((1<<29)|(1<<28)|(1<<0)));
+               // access flag disabled, TEX remap disabled, mmu disabled
+
+       uint32 highestRAMAddress = SDRAM_BASE;
+
+       // calculate lowest RAM adress from MEMORYMAP
+       for (uint32 i = 0; i < ARRAY_SIZE(LOADER_MEMORYMAP); i++) {
+               if (strcmp("RAM_free", LOADER_MEMORYMAP[i].name) == 0)
+                       sNextPhysicalAddress = LOADER_MEMORYMAP[i].start;
+
+               if (strcmp("RAM_pt", LOADER_MEMORYMAP[i].name) == 0) {
+                       sNextPageTableAddress = LOADER_MEMORYMAP[i].start
+                               + MMU_L1_TABLE_SIZE;
+                       kPageTableRegionEnd = LOADER_MEMORYMAP[i].end;
+                       sPageDirectory = (uint32 *) LOADER_MEMORYMAP[i].start;
+               }
+
+               if (strncmp("RAM_", LOADER_MEMORYMAP[i].name, 4) == 0) {
+                       if (LOADER_MEMORYMAP[i].end > highestRAMAddress)
+                               highestRAMAddress = LOADER_MEMORYMAP[i].end;
+               }
+       }
+
+       gKernelArgs.physical_memory_range[0].start = SDRAM_BASE;
+       gKernelArgs.physical_memory_range[0].size = highestRAMAddress - 
SDRAM_BASE;
+       gKernelArgs.num_physical_memory_ranges = 1;
+
+       gKernelArgs.physical_allocated_range[0].start = SDRAM_BASE;
+       gKernelArgs.physical_allocated_range[0].size = 0;
+       gKernelArgs.num_physical_allocated_ranges = 1;
+               // remember the start of the allocated physical pages
+
+       init_page_directory();
+
+       // map the page directory on the next vpage
+       gKernelArgs.arch_args.vir_pgdir = mmu_map_physical_memory(
+               (addr_t)sPageDirectory, MMU_L1_TABLE_SIZE, kDefaultPageFlags);
+
+       // map in a kernel stack
+       gKernelArgs.cpu_kstack[0].start = (addr_t)mmu_allocate(NULL,
+               KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE);
+       gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE
+               + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
+
+       TRACE(("kernel stack at 0x%lx to 0x%lx\n", 
gKernelArgs.cpu_kstack[0].start,
+               gKernelArgs.cpu_kstack[0].start + 
gKernelArgs.cpu_kstack[0].size));
 }
 
 
@@ -63,32 +641,43 @@ mmu_init(void)
 
 
 extern "C" status_t
-platform_allocate_region(void** _address, size_t size, uint8 protection,
+platform_allocate_region(void **_address, size_t size, uint8 protection,
        bool /*exactAddress*/)
 {
-#warning IMPLEMENT platform_allocate_region
-       return B_ERROR;
+       void *address = mmu_allocate(*_address, size);
+       if (address == NULL)
+               return B_NO_MEMORY;
+
+       *_address = address;
+       return B_OK;
 }
 
 
 extern "C" status_t
-platform_free_region(void* address, size_t size)
+platform_free_region(void *address, size_t size)
 {
-#warning IMPLEMENT platform_free_region
-       return B_ERROR;
+       mmu_free(address, size);
+       return B_OK;
 }
 
 
 void
-platform_release_heap(struct stage2_args* args, void* base)
+platform_release_heap(struct stage2_args *args, void *base)
 {
-#warning IMPLEMENT platform_release_heap
+       // It will be freed automatically, since it is in the
+       // identity mapped region, and not stored in the kernel's
+       // page tables.
 }
 
 
 status_t
-platform_init_heap(struct stage2_args* args, void** _base, void** _top)
+platform_init_heap(struct stage2_args *args, void **_base, void **_top)
 {
-#warning IMPLEMENT platform_init_heap
-       return B_ERROR;
+       void *heap = (void *)get_next_physical_address(args->heap_size);
+       if (heap == NULL)
+               return B_NO_MEMORY;
+
+       *_base = heap;
+       *_top = (void *)((int8 *)heap + args->heap_size);
+       return B_OK;
 }
diff --git a/src/system/boot/platform/raspberrypi_arm/mmu.h 
b/src/system/boot/platform/raspberrypi_arm/mmu.h
index 219d5a8..cd30040 100644
--- a/src/system/boot/platform/raspberrypi_arm/mmu.h
+++ b/src/system/boot/platform/raspberrypi_arm/mmu.h
@@ -1,29 +1,33 @@
 /*
- * Copyright 2009 Jonas Sundström, jonas@xxxxxxxxxxx
+ * Copyright 2004-2005, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
  * All rights reserved. Distributed under the terms of the MIT License.
  */
-#ifndef _SYSTEM_BOOT_PLATFORM_PI_MMU_H
-#define _SYSTEM_BOOT_PLATFORM_PI_MMU_H
+#ifndef MMU_H
+#define MMU_H
 
 
 #include <SupportDefs.h>
 
 
+// For use with mmu_map_physical_memory()
+static const uint32 kDefaultPageFlags = 0x3;
+       // present, R/W
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 extern void mmu_init(void);
 extern void mmu_init_for_kernel(void);
-
-extern addr_t mmu_map_physical_memory(addr_t physicalAddress, size_t size,
-       uint32 flags);
-
-extern void* mmu_allocate(void* virtualAddress, size_t size);
-extern void mmu_free(void* virtualAddress, size_t size);
+extern addr_t mmu_map_physical_memory(addr_t physicalAddress,
+       size_t size, uint32 flags);
+extern void *mmu_allocate(void *virtualAddress, size_t size);
+extern void mmu_free(void *virtualAddress, size_t size);
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* _SYSTEM_BOOT_PLATFORM_PI_MMU_H */
+
+#endif /* MMU_H */
diff --git a/src/system/boot/platform/raspberrypi_arm/start.c 
b/src/system/boot/platform/raspberrypi_arm/start.c
index 470ac06..7f57ce2 100644
--- a/src/system/boot/platform/raspberrypi_arm/start.c
+++ b/src/system/boot/platform/raspberrypi_arm/start.c
@@ -114,10 +114,16 @@ pi_start(void)
        // Flick on "OK" led
        gpio_write(GPIO_BASE, 16, 0);
 
-       mmu_init();
        serial_init();
        console_init();
 
+       /*
+        * TODO: Move befpre gpio_init
+        * Once memory mapping is working, uart + gpio should
+        * use mapped peripheral addresses
+        */
+       mmu_init();
+
        args.heap_size = HEAP_SIZE;
        args.arguments = NULL;
 


Other related posts:

  • » [haiku-commits] haiku: hrev44185 - in src/system/boot/platform: raspberrypi_arm u-boot - kallisti5