From ecf42f1820233cf773f082d1f5983395e60f8091 Mon Sep 17 00:00:00 2001 From: NicJA Date: Tue, 20 Jan 2015 22:55:34 +0000 Subject: [PATCH] Patch hosted memory allocation. some systems will not allow AROS to allocate > 1024MB using mmap and MEM_32BIT, so change the behaviour and split the allocation into two regions. git-svn-id: https://svn.aros.org/svn/aros/trunk/AROS@49919 fb15a70f-31f2-0310-bbcc-cdcc74a49acc --- arch/all-hosted/bootstrap/bootstrap.c | 76 ++++++++++++++++++++++++++--------- arch/all-hosted/bootstrap/memory.c | 8 ++++ arch/all-hosted/bootstrap/memory.h | 1 + arch/all-unix/bootstrap/memory.c | 65 +++++++++++++++++------------- arch/all-unix/kernel/kernel_startup.c | 42 ++++++++++++++++++- 5 files changed, 144 insertions(+), 48 deletions(-) diff --git a/arch/all-hosted/bootstrap/bootstrap.c b/arch/all-hosted/bootstrap/bootstrap.c index a89286ea29..2a42748a45 100644 --- a/arch/all-hosted/bootstrap/bootstrap.c +++ b/arch/all-hosted/bootstrap/bootstrap.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -46,12 +47,16 @@ #define D(x) +#define LOWMEMSIZE (512 * 1024 * 1024) + /* These macros are defined in both UNIX and AROS headers. Get rid of warnings. */ #undef __pure #undef __const #undef __pure2 #undef __deprecated +extern int errno; + extern void *HostIFace; /* @@ -65,16 +70,30 @@ char *KernelArgs = NULL; char *SystemVersion = NULL; char buf[BUFFER_SIZE]; -static struct mb_mmap MemoryMap = +#if (__WORDSIZE != 64) +static struct mb_mmap MemoryMap[1] = +#else +static struct mb_mmap MemoryMap[2] = +#endif { - sizeof(struct mb_mmap) - 4, - 0, - 0, + { + sizeof(struct mb_mmap) - 4, + 0, + 0, #if (__WORDSIZE != 64) - 0, - 0, + 0, + 0, +#endif + MMAP_TYPE_RAM + } +#if (__WORDSIZE == 64) + , { + sizeof(struct mb_mmap) - 4, + 0, + 0, + MMAP_TYPE_RAM + } #endif - MMAP_TYPE_RAM }; /* gdb can pick up kickstart segments from here */ @@ -92,7 +111,7 @@ static struct TagItem km[] = {KRN_DebugInfo , 0 }, {KRN_HostInterface, 0 }, {KRN_MMAPAddress , 0 }, - {KRN_MMAPLength , sizeof(MemoryMap)}, + {KRN_MMAPLength , sizeof(struct mb_mmap)}, {KRN_CmdLine , 0 }, {TAG_DONE , 0 } }; @@ -285,6 +304,36 @@ int bootstrap(int argc, char ** argv) } fclose(file); + D(fprintf(stderr, "[Bootstrap] Allocating %iMB of RAM for AROS\n",memSize)); + +#if (__WORDSIZE == 64) + if ((memSize << 20) > LOWMEMSIZE) + { + MemoryMap[1].len = (memSize << 20) - LOWMEMSIZE; + MemoryMap[1].addr = (IPTR)AllocateRAM((size_t)MemoryMap[1].len); + if (!MemoryMap[1].addr) { + int err = errno; + DisplayError("[Bootstrap] Failed to allocate %iMB of 'High' RAM for AROS: %08x %s\n", memSize, err, strerror(err)); + return -1; + } + fprintf(stderr, "[Bootstrap] RAM memory block allocated: %p - %p (%u bytes)\n", + (void *)(IPTR)MemoryMap[1].addr, (void *)(IPTR)MemoryMap[1].addr + MemoryMap[1].len, MemoryMap[1].len); + + memSize = (LOWMEMSIZE >> 20); + km[7].ti_Data += sizeof(struct mb_mmap); + } +#endif + MemoryMap[0].len = memSize << 20; + MemoryMap[0].addr = (IPTR)AllocateRAM32((size_t)MemoryMap[0].len); + + if (!MemoryMap[0].addr) { + int err = errno; + DisplayError("[Bootstrap] Failed to allocate %iMB of RAM for AROS: %08x %s\n", memSize, err, strerror(err)); + return -1; + } + fprintf(stderr, "[Bootstrap] RAM memory block allocated: %p - %p (%u bytes)\n", + (void *)(IPTR)MemoryMap[0].addr, (void *)(IPTR)MemoryMap[0].addr + MemoryMap[0].len, MemoryMap[0].len); + if (!GetKernelSize(FirstELF, &ro_size, &rw_size, &bss_size)) return -1; @@ -327,17 +376,6 @@ int bootstrap(int argc, char ** argv) return -1; } - D(fprintf(stderr, "[Bootstrap] Allocating %iMB of RAM for AROS\n",memSize)); - - MemoryMap.len = memSize << 20; - MemoryMap.addr = (IPTR)AllocateRAM(MemoryMap.len); - - if (!MemoryMap.addr) { - DisplayError("[Bootstrap] Failed to allocate %iMB of RAM for AROS!\n", memSize); - return -1; - } - D(fprintf(stderr, "[Bootstrap] RAM memory allocated: %p - %p (%u bytes)\n", - (void *)(IPTR)MemoryMap.addr, (void *)(IPTR)MemoryMap.addr + MemoryMap.len, MemoryMap.len)); km[0].ti_Data = (IPTR)ro_addr; km[1].ti_Data = (IPTR)ro_addr + ro_size - 1; diff --git a/arch/all-hosted/bootstrap/memory.c b/arch/all-hosted/bootstrap/memory.c index a4619471c7..96006cf13b 100644 --- a/arch/all-hosted/bootstrap/memory.c +++ b/arch/all-hosted/bootstrap/memory.c @@ -35,6 +35,14 @@ void *AllocateRW(size_t len) /* * Allocate read-write-execute area to be used as AROS RAM */ +void *AllocateRAM32(size_t len) +{ + return malloc(len); +} + +/* + * Allocate read-write-execute area to be used as AROS RAM + */ void *AllocateRAM(size_t len) { return malloc(len); diff --git a/arch/all-hosted/bootstrap/memory.h b/arch/all-hosted/bootstrap/memory.h index f2fb07a9e9..592c387562 100644 --- a/arch/all-hosted/bootstrap/memory.h +++ b/arch/all-hosted/bootstrap/memory.h @@ -1,4 +1,5 @@ void *AllocateRO(size_t len); void *AllocateRW(size_t len); +void *AllocateRAM32(size_t len); void *AllocateRAM(size_t len); int SetRO(void *addr, size_t len); diff --git a/arch/all-unix/bootstrap/memory.c b/arch/all-unix/bootstrap/memory.c index 657cd9f57c..ebd79b5506 100644 --- a/arch/all-unix/bootstrap/memory.c +++ b/arch/all-unix/bootstrap/memory.c @@ -1,8 +1,3 @@ -/* - Copyright © 1995-2014, The AROS Development Team. All rights reserved. - $Id$ -*/ - #include #include #include @@ -13,12 +8,17 @@ #define MAP_32BIT 0 #endif -static void *code = NULL; static void *data = NULL; -static void *RAM = NULL; - +static void *code = NULL; static size_t code_len = 0; + +static void *RAM32 = NULL; +static size_t RAM32_len = 0; + +#if (__WORDSIZE == 64) +static void *RAM = NULL; static size_t RAM_len = 0; +#endif /* * Allocate memory for kickstart's .code and .rodata. We allocate is as writable @@ -30,19 +30,28 @@ static size_t RAM_len = 0; * This causes DisplayError() function to crash on iOS. This also may cause similar effects * on other systems. */ -void *AllocateRO(size_t len) -{ + + void *doMMap(void **addr_store, size_t *size_store, size_t len, int prot, int flags) + { /* There's no sense to set MAP_SHARED for ROM */ - void *ret = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_32BIT, -1, 0); + void *ret = mmap(NULL, len, prot, flags, -1, 0); if (ret == MAP_FAILED) - return NULL; + ret = NULL; else { - code = ret; - code_len = len; - return ret; + if (addr_store) + *addr_store = ret; + if (size_store) + *size_store = len; } + return ret; + } + +void *AllocateRO(size_t len) +{ + /* There's no sense to set MAP_SHARED for ROM */ + return doMMap(&code, &code_len, len, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_32BIT); } /* @@ -66,30 +75,32 @@ void *AllocateRW(size_t len) } /* - * This routine allocates memory usable as AROS ram. This means it + * These routines allocate memory usable as AROS ram. This means it * needs to have full permissions. * Yes, iOS will silently mask out PROT_EXEC here. This is bad. * Well, iOS will be a little bit special story in InternalLoadSeg()... */ -void *AllocateRAM(size_t len) +void *AllocateRAM32(size_t len) { - void *ret = mmap(NULL, len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_SHARED|MAP_32BIT, -1, 0); + return doMMap(&RAM32, &RAM32_len, len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_SHARED|MAP_32BIT); +} - if (ret == MAP_FAILED) - return NULL; - else - { - RAM = ret; - RAM_len = len; - return ret; - } +#if (__WORDSIZE == 64) +void *AllocateRAM(size_t len) +{ + return doMMap(&RAM, &RAM_len, len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_SHARED); } +#endif void Host_FreeMem(void) { munmap(code, code_len); free(data); - munmap(RAM, RAM_len); +#if (__WORDSIZE == 64) + if (RAM) + munmap(RAM, RAM_len); +#endif + munmap(RAM32, RAM32_len); free(SystemVersion); if (KernelArgs) diff --git a/arch/all-unix/kernel/kernel_startup.c b/arch/all-unix/kernel/kernel_startup.c index 5a7c77d5d5..431b7c10bc 100644 --- a/arch/all-unix/kernel/kernel_startup.c +++ b/arch/all-unix/kernel/kernel_startup.c @@ -63,9 +63,15 @@ int __startup startup(struct TagItem *msg, ULONG magic) char *cmdline = NULL; unsigned int mm_PageSize, memsize; struct MemHeader *bootmh = NULL, *chipmh = NULL, *fastmh = NULL; +#if (__WORDSIZE == 64) + struct MemHeader *highmh = NULL; +#endif struct TagItem *tag, *tstate = msg; struct HostInterface *hif = NULL; struct mb_mmap *mmap = NULL; + unsigned long mmap_len = 0; + BOOL mem_tlsf = FALSE; + UWORD *ranges[] = {NULL, NULL, (UWORD *)-1}; /* This bails out if the user started us from within AROS command line, as common executable */ @@ -86,6 +92,13 @@ int __startup startup(struct TagItem *msg, ULONG magic) case KRN_MMAPAddress: mmap = (struct mb_mmap *)tag->ti_Data; + /* we have atleast 1 mmap */ + if (!mmap_len) + mmap_len = sizeof(struct mb_mmap); + break; + + case KRN_MMAPLength: + mmap_len = tag->ti_Data; break; case KRN_KernelBss: @@ -148,6 +161,12 @@ int __startup startup(struct TagItem *msg, ULONG magic) /* Now query memory page size. We need in order to get our memory manager functional. */ mm_PageSize = krnGetPageSize(hostlib); D(nbug("[KRN] Memory page size is %u\n", mm_PageSize)); + if (!(cmdline && strstr(cmdline, "notlsf"))) + { + /* this should probably be handled directly in krnCreateMemHeader */ + mem_tlsf = TRUE; + D(nbug("[KRN] Using TLSF Memory Manager\n")); + } if (!mm_PageSize) { @@ -164,7 +183,7 @@ int __startup startup(struct TagItem *msg, ULONG magic) /* Prepare the simulated mem headers */ /* NOTE: two mem headers are created to cover more cases of memory system */ krnCreateMemHeader("CHIP RAM", -5, chipmh, memsize, MEMF_CHIP|MEMF_PUBLIC|MEMF_LOCAL|MEMF_KICK|ARCH_31BIT); - if (!(cmdline && strstr(cmdline, "notlsf"))) + if (mem_tlsf) chipmh = krnConvertMemHeaderToTLSF(chipmh); bootmh = chipmh; @@ -173,12 +192,26 @@ int __startup startup(struct TagItem *msg, ULONG magic) fastmh = (struct MemHeader *)(mmap->addr + memsize); memsize = mmap->len - memsize; krnCreateMemHeader("Fast RAM", 0, fastmh , memsize, MEMF_FAST|MEMF_PUBLIC|MEMF_LOCAL|MEMF_KICK|ARCH_31BIT); - if (!(cmdline && strstr(cmdline, "notlsf"))) + if (mem_tlsf) fastmh = krnConvertMemHeaderToTLSF(fastmh); if (memsize > (1024 * 1024)) bootmh = fastmh; } +#if (__WORDSIZE == 64) + /* on 64bit platforms, we may be passed an additional mmap */ + if (mmap_len > sizeof(struct mb_mmap)) + { + struct mb_mmap *mmapnxt = &mmap[1]; + + highmh = mmapnxt->addr; + + krnCreateMemHeader("Fast RAM", 0, highmh, mmapnxt->len, MEMF_FAST|MEMF_PUBLIC|MEMF_LOCAL|MEMF_KICK); + if (mem_tlsf) + highmh = krnConvertMemHeaderToTLSF(highmh); + } +#endif + /* * SysBase pre-validation after a warm restart. * This makes sure that it points to a valid accessible memory region. @@ -204,6 +237,11 @@ int __startup startup(struct TagItem *msg, ULONG magic) if (bootmh != fastmh && fastmh) Enqueue(&SysBase->MemList, &fastmh->mh_Node); +#if (__WORDSIZE == 64) + if (bootmh != highmh && highmh) + Enqueue(&SysBase->MemList, &highmh->mh_Node); +#endif + /* * ROM memory header. This special memory header covers all ROM code and data sections * so that TypeOfMem() will not return 0 for addresses pointing into the kernel. -- 2.11.4.GIT