diff --git a/headers/private/kernel/arch/arm/arch_kernel_args.h b/headers/private/kernel/arch/arm/arch_kernel_args.h index 3f39508c7c..39a9316f8b 100644 --- a/headers/private/kernel/arch/arm/arch_kernel_args.h +++ b/headers/private/kernel/arch/arm/arch_kernel_args.h @@ -20,6 +20,7 @@ typedef struct { // architecture specific uint32 phys_pgdir; uint32 vir_pgdir; + uint32 next_pagetable; } arch_kernel_args; #endif /* KERNEL_ARCH_ARM_KERNEL_ARGS_H */ diff --git a/src/system/boot/arch/arm/arch_mmu.cpp b/src/system/boot/arch/arm/arch_mmu.cpp index a0f1693653..715ffc6598 100644 --- a/src/system/boot/arch/arm/arch_mmu.cpp +++ b/src/system/boot/arch/arm/arch_mmu.cpp @@ -61,10 +61,7 @@ TODO: // 8 MB for the kernel, kernel args, modules, driver settings, ... static const size_t kMaxKernelSize = 0x800000; -// Base address for loader -static const size_t kLoaderBaseAddress = KERNEL_LOAD_BASE + kMaxKernelSize; - -// Start and end of ourselfs +// Start and end of ourselfs (from ld script) extern int _start, _end; /* @@ -95,18 +92,6 @@ static struct memblock LOADER_MEMORYMAP[] = { KERNEL_LOAD_BASE + kMaxKernelSize - 1, ARM_MMU_L2_FLAG_C, }, - { - "RAM_pt", // Page Table 1MB - kLoaderBaseAddress + 0x100000, - kLoaderBaseAddress + 0x1FFFFF, - ARM_MMU_L2_FLAG_C, - }, - { - "RAM_free", // 16MB free RAM (more but we don't map it automaticaly) - kLoaderBaseAddress + 0x0200000, - kLoaderBaseAddress + 0x11FFFFF, - ARM_MMU_L2_FLAG_C, - }, #ifdef FB_BASE { @@ -127,7 +112,7 @@ static addr_t sNextVirtualAddress = 0; static addr_t sNextPageTableAddress = 0; //the page directory is in front of the pagetable -static uint32 kPageTableRegionEnd = 0; +static uint32 sPageTableRegionEnd = 0; static uint32 sSmallPageType = ARM_MMU_L2_TYPE_SMALLEXT; @@ -137,16 +122,6 @@ static uint32 *sPageDirectory = 0 ; //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_aligned(size_t size, uint32 mask) { @@ -157,16 +132,6 @@ get_next_virtual_address_aligned(size_t size, uint32 mask) } -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_aligned(size_t size, uint32 mask) { @@ -246,8 +211,8 @@ static uint32 * get_next_page_table(uint32 type) { TRACE(("get_next_page_table, sNextPageTableAddress 0x%" B_PRIxADDR - ", kPageTableRegionEnd 0x%" B_PRIxADDR ", type 0x%" B_PRIx32 "\n", - sNextPageTableAddress, kPageTableRegionEnd, type)); + ", sPageTableRegionEnd 0x%" B_PRIxADDR ", type 0x%" B_PRIx32 "\n", + sNextPageTableAddress, sPageTableRegionEnd, type)); size_t size = 0; size_t entryCount = 0; @@ -266,7 +231,7 @@ get_next_page_table(uint32 type) } addr_t address = sNextPageTableAddress; - if (address < kPageTableRegionEnd) + if (address < sPageTableRegionEnd) sNextPageTableAddress += size; else { TRACE(("page table allocation outside of pagetable region!\n")); @@ -337,7 +302,8 @@ init_page_directory() { TRACE(("init_page_directory\n")); - gKernelArgs.arch_args.phys_pgdir = (uint32)sPageDirectory; + gKernelArgs.arch_args.phys_pgdir = + gKernelArgs.arch_args.vir_pgdir = (uint32)sPageDirectory; // clear out the page directory for (uint32 i = 0; i < ARM_MMU_L1_TABLE_ENTRY_COUNT; i++) @@ -346,6 +312,9 @@ init_page_directory() // map ourselfs first... just to make sure mmu_map_identity((addr_t)&_start, (addr_t)&_end, ARM_MMU_L2_FLAG_C); + // map our page directory region (TODO should not be identity mapped) + mmu_map_identity((addr_t)sPageDirectory, sPageTableRegionEnd, ARM_MMU_L2_FLAG_C); + for (uint32 i = 0; i < ARRAY_SIZE(LOADER_MEMORYMAP); i++) { TRACE(("BLOCK: %s START: %lx END %lx\n", LOADER_MEMORYMAP[i].name, @@ -358,10 +327,6 @@ init_page_directory() LOADER_MEMORYMAP[i].flags); } - // Map the page directory itself. - addr_t virtualPageDirectory = mmu_map_physical_memory( - (addr_t)sPageDirectory, ARM_MMU_L1_TABLE_SIZE, kDefaultPageFlags); - mmu_flush_TLB(); /* set up the translation table base */ @@ -374,10 +339,6 @@ init_page_directory() /* turn on the mmu */ mmu_write_C1(mmu_read_C1() | 0x1); - - // Use the mapped page directory from now on. - sPageDirectory = (uint32 *)virtualPageDirectory; - gKernelArgs.arch_args.vir_pgdir = virtualPageDirectory; } @@ -547,18 +508,16 @@ mmu_init_for_kernel(void) { TRACE(("mmu_init_for_kernel\n")); + // store next available pagetable in our pagedir mapping, for + // the kernel to use in early vm setup + gKernelArgs.arch_args.next_pagetable = sNextPageTableAddress - (addr_t)sPageDirectory; + // save the memory we've physically allocated - int index = gKernelArgs.num_physical_allocated_ranges; - gKernelArgs.physical_allocated_range[index].start = SDRAM_BASE; - gKernelArgs.physical_allocated_range[index].size = sNextPhysicalAddress - SDRAM_BASE; - gKernelArgs.num_physical_allocated_ranges++; + insert_physical_allocated_range((addr_t)sPageDirectory, sNextPhysicalAddress - (addr_t)sPageDirectory); // Save the memory we've virtually allocated (for the kernel and other // stuff) - gKernelArgs.virtual_allocated_range[0].start = KERNEL_LOAD_BASE; - gKernelArgs.virtual_allocated_range[0].size - = sNextVirtualAddress - KERNEL_LOAD_BASE; - gKernelArgs.num_virtual_allocated_ranges = 1; + insert_virtual_allocated_range(KERNEL_LOAD_BASE, sNextVirtualAddress - KERNEL_LOAD_BASE); #ifdef TRACE_MEMORY_MAP { @@ -601,32 +560,18 @@ mmu_init(void) mmu_write_C1(mmu_read_C1() & ~((1 << 29) | (1 << 28) | (1 << 0))); // access flag disabled, TEX remap disabled, mmu disabled - uint32 highestRAMAddress = SDRAM_BASE; + // allocate page directory in memory after loader + sPageDirectory = (uint32 *)ROUNDUP((addr_t)&_end, 0x100000); + sNextPageTableAddress = (addr_t)sPageDirectory + ARM_MMU_L1_TABLE_SIZE; + sPageTableRegionEnd = (addr_t)sPageDirectory + 0x200000; - // 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; - sNextVirtualAddress = LOADER_MEMORYMAP[i].start; - } + // Mark start for dynamic allocation + sNextPhysicalAddress = + sNextVirtualAddress = sPageTableRegionEnd; - if (strcmp("RAM_pt", LOADER_MEMORYMAP[i].name) == 0) { - sNextPageTableAddress = LOADER_MEMORYMAP[i].start - + ARM_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; - } - } - - insert_physical_memory_range(SDRAM_BASE, highestRAMAddress - SDRAM_BASE); - - // mark ourselfs as allocated, so init_page_directory doesn't overwrite us + // mark allocated ranges, so they don't get overwritten insert_physical_allocated_range((addr_t)&_start, (addr_t)&_end - (addr_t)&_start); + insert_physical_allocated_range((addr_t)sPageDirectory, 0x200000); init_page_directory(); @@ -678,7 +623,7 @@ platform_release_heap(struct stage2_args *args, void *base) status_t platform_init_heap(struct stage2_args *args, void **_base, void **_top) { - void *heap = (void *)get_next_physical_address(args->heap_size); + void *heap = mmu_allocate(NULL, args->heap_size); if (heap == NULL) return B_NO_MEMORY; diff --git a/src/system/boot/platform/raspberrypi_arm/start.cpp b/src/system/boot/platform/raspberrypi_arm/start.cpp index 2d64bd7c44..4513b72768 100644 --- a/src/system/boot/platform/raspberrypi_arm/start.cpp +++ b/src/system/boot/platform/raspberrypi_arm/start.cpp @@ -134,6 +134,10 @@ _start(void) // Flick on "OK" led, use pre-mmu firmware base gpio_write(gPeripheralBase + GPIO_BASE, 16, 0); + // specify available physical memory, using 128MB for now + // TODO: support CPU/GPU memory split options + insert_physical_memory_range(SDRAM_BASE, 128 * 1024 * 1024); + // Reserve memory for boot archive before switching on MMU insert_physical_allocated_range(BOOT_ARCHIVE_BASE, BOOT_ARCHIVE_SIZE); diff --git a/src/system/boot/platform/u-boot/start.cpp b/src/system/boot/platform/u-boot/start.cpp index f50c89665e..8e698d491b 100644 --- a/src/system/boot/platform/u-boot/start.cpp +++ b/src/system/boot/platform/u-boot/start.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -272,6 +273,10 @@ start_raw(int argc, const char **argv) args.platform.boot_tgz_size); } + // specify available physical memory, using 32MB for now, since our + // ARMv5 targets have very little by default. TODO get from FDT! + insert_physical_memory_range(SDRAM_BASE, 32 * 1024 * 1024); + mmu_init(); // Handle our tarFS post-mmu diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp index a973bb2e82..eb2cae6e32 100644 --- a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp +++ b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp @@ -346,6 +346,15 @@ ARMPagingMethod32Bit::CreateTranslationMap(bool kernel, VMTranslationMap** _map) } +static phys_addr_t +get_free_pgtable(kernel_args* args) +{ + phys_addr_t phys = args->arch_args.phys_pgdir + args->arch_args.next_pagetable; + //addr_t virt = args->arch_args.vir_pgdir + args->arch_args.next_pagetable; + args->arch_args.next_pagetable += ARM_MMU_L2_COARSE_TABLE_SIZE; + return phys; +} + status_t ARMPagingMethod32Bit::MapEarly(kernel_args* args, addr_t virtualAddress, phys_addr_t physicalAddress, uint8 attributes, @@ -357,9 +366,7 @@ ARMPagingMethod32Bit::MapEarly(kernel_args* args, addr_t virtualAddress, phys_addr_t pgtable; page_directory_entry *e; // we need to allocate a pgtable - pgtable = get_free_page(args); - // pgtable is in pages, convert to physical address - pgtable *= B_PAGE_SIZE; + pgtable = get_free_pgtable(args); TRACE("ARMPagingMethod32Bit::MapEarly(): asked for free page for " "pgtable. %#" B_PRIxPHYSADDR "\n", pgtable);