⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memory.c

📁 C++ 编写的EROS RTOS
💻 C
字号:
/* * Copyright (C) 2001, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <kerninc/BootInfo.h>#include "boot.h"#include "boot-asm.h"#include "debug.h"#define MEM_LIMIT (64 * 1024 * 1024)#define align_down(addr, al) (((uint32_t)(addr)) & ~((al)-1))/* This is the type of the MemInfo structure returned by the Uruk * memory probe function. */struct UrukMemInfo {  uint32_t  len;		/* handed to/from the bios */  uint32_t  BaseAddrLow;	/* low 32 bits of base address */  uint32_t  BaseAddrHigh;	/* high 32 bits of base address */  uint32_t  LengthLow;		/* low 32 bits of length */  uint32_t  LengthHigh;		/* high 32 bits of length */  uint32_t  Type;		/* address type of this range */} ;typedef struct UrukMemInfo UrukMemInfo;/* type codes as returned by the BIOS logic. */#define AddrRangeMemory   1#define AddrRangeReserved 2extern int get_mem_map(UrukMemInfo *umi, uint32_t continuation);/* The ProbeMemory() routine determines what physical memory is * attached to the machine and does the initial setup so that * BootMalloc can later allocate memory that will be reserved to the * boot area. * * Note that we no longer attempt to support machines that do not * implement the BIOS Address Map logic -- such machines may still * (hypothetically) exist, but they aren't worth the bother until * somebody complains.  I haven't actually seen one used for anything * besides a boat anchor in quite some time. * * Hmm. No sooner did I add that then somebody discovered a boat * anchor that was alive and well, and I had to re-introduce the * memory forgery thing. */static MemInfo *mallocSourceRegion;static MemInfo *mallocRegion;BootInfo *ProbeMemory(){  uint32_t nextContinuation;  uint64_t totalMemory = 0;  uint32_t nRegion = 0;  uint32_t mallocRegionBase = 0;  uint32_t mallocRegionBound = 0;  MemInfo *mi;  DivisionInfo *di;  BootInfo *bi;  unsigned haveSMAP = 1;  kpa_t memInfoRgn;  UrukMemInfo bmi;  /* We make two passes over memory.    *    * The first is to determine how many physical memory regions exist   * on the machine so that we know how big a memory region descriptor   * to allocate. In the process, we figure out where the bootstrap   * will allocate memory from.   *   * The present implementation bets that the "top" region of physical   * memory (wherever that may fall) will be sufficient to support all   * of the memory allocations that the bootstrap code will make. A   * more robust allocator would not make this assumption.   *   * Also, note that this bootstrap routine does not cope with   * physical memories larger than 4Gbytes.   */  printf("BIOS System Address Map:\n");  /* See if this BIOS supports the BIOS System Address Map call. There   * should be at least one response with nonzero buffer for low   * memory... */  nextContinuation = 0;  nextContinuation = get_mem_map(&bmi, nextContinuation);  if (bmi.len == 0)     haveSMAP = 0;  if (haveSMAP)  {    /* Pass 1: simply count the regions: */    nextContinuation = 0;    do {      nextContinuation = get_mem_map(&bmi, nextContinuation);      if (bmi.len > 0) {	const char *addrType = "Unk.";	uint64_t base = bmi.BaseAddrHigh;	uint64_t len = bmi.LengthHigh;	uint64_t top;	base <<= 32;	base |= bmi.BaseAddrLow;		len <<= 32;	len |= bmi.LengthLow;	top = base + len;	#ifdef MEM_LIMIT	/* FIX: Ad hoc constraint until I fix the kernel memory	   subsystem. */ 	if (bmi.Type == AddrRangeMemory) {	  if (base >= MEM_LIMIT)	    continue;	  if (top > MEM_LIMIT)	    top = MEM_LIMIT;	  len = top - base;	  if (len == 0)	    continue;	}#endif	if (bmi.Type == AddrRangeMemory)	  addrType = "Mem ";	else if (bmi.Type == AddrRangeReserved)	  addrType = "Rsrv";	printf("  %s base=0x%08lx%08lx len=0x%08lx%08lx (%ld Kbytes)\n",	       addrType, bmi.BaseAddrHigh, bmi.BaseAddrLow, 	       bmi.LengthHigh, bmi.LengthLow,	       (uint32_t) len/1024u);	if (bmi.Type == AddrRangeMemory) {	  totalMemory += len;	  if (top < 0x100000000ull && /* must be low 4G region */	      base > mallocRegionBase) {	    mallocRegionBase = base;	    mallocRegionBound = base + len;	  }	}	nRegion++;      }    } while (nextContinuation);  }   else {    uint32_t hi = old_memsize(1);    uint32_t lo = old_memsize(0);    printf("Newer probe call not supported. lo=%d hi=%d Winging it...\n", lo, hi);    totalMemory = 0x100000;	/* base of extended mem region */    totalMemory += hi * 1024;    mallocRegionBase = 0x100000;    mallocRegionBound = totalMemory;    nRegion = 7;		/* two real plus 5 forged */  }  printf("  Total Memory: 0x%08lx%08lx.\n"	 "  Malloc region [0x%08lx, 0x%08lx)\n",	 (uint32_t) (totalMemory >> 32),	 (uint32_t) totalMemory,	 (uint32_t) mallocRegionBase,	 (uint32_t) mallocRegionBound);  /* The malloc region bound should be word aligned, but better to   * check: */  if (mallocRegionBound != align_down(mallocRegionBound, 4)) {    printf("Boot-time malloc region is mis-aligned!\n");    halt();  }  /* Now, this is a bit tricky. We are grabbing the memory for the   * region list from the top of what will momentarily become the boot    * malloc arena. We will patch up the data structures accordingly   * below.    */  memInfoRgn = mallocRegionBound;  memInfoRgn -= MAX_MEMINFO * sizeof(MemInfo);  memInfoRgn = align_down(memInfoRgn, sizeof(uint64_t));  mi = PA2BOOT((uint32_t) memInfoRgn, MemInfo *);  memset(mi, 0, MAX_MEMINFO * sizeof(MemInfo));  memInfoRgn -= MAX_PRELOAD * sizeof(DivisionInfo);  memInfoRgn = align_down(memInfoRgn, sizeof(uint64_t));  di = PA2BOOT((uint32_t) memInfoRgn, DivisionInfo *);  memset(di, 0, MAX_PRELOAD * sizeof(DivisionInfo));  memInfoRgn -= sizeof(BootInfo);  memInfoRgn = align_down(memInfoRgn, sizeof(uint64_t));  bi = PA2BOOT((uint32_t) memInfoRgn, BootInfo *);  bi->memInfo = mi;  bi->nMemInfo = nRegion + 1;	/* +1 for boot malloc region */  bi->divInfo = di;  bi->nDivInfo = 0;  mallocRegion = &mi[nRegion];  printf("BootInfo 0x%08x, MemInfo 0x%08x mallocRegion 0x%08x\n", 	 BOOT2PA(bi, void *),	 BOOT2PA(mi, void *),	 BOOT2PA(mallocRegion, void *));  printf("bi->memInfo 0x%08x\n", BOOT2PA(bi->memInfo, void *));  mallocRegion->bound = mallocRegionBound;  mallocRegion->base = mallocRegionBound;  mallocRegion->type = MI_BOOT;  if (haveSMAP) {    nRegion = 0;    nextContinuation = 0;    do {      nextContinuation = get_mem_map(&bmi, nextContinuation);      if (bmi.len > 0) {	kpa_t base;	kpa_t len;	kpa_t top;	base = bmi.BaseAddrHigh;	len = bmi.LengthHigh;	base <<= 32;	len <<= 32;	base |= bmi.BaseAddrLow;	len |= bmi.LengthLow;	top = base + len;	#ifdef MEM_LIMIT	/* FIX: Ad hoc constraint until I fix the kernel memory	   subsystem. */ 	if (bmi.Type == AddrRangeMemory) {	  if (base >= MEM_LIMIT)	    continue;	  if (top > MEM_LIMIT)	    top = MEM_LIMIT;	  len = top - base;	  if (len == 0)	    continue;	}#endif	mi[nRegion].base = base;	mi[nRegion].bound = top;	switch(bmi.Type) {	case AddrRangeMemory:	  mi[nRegion].type = MI_MEMORY;	  break;	case AddrRangeReserved:	  /* Check explicitly for the BIOS ROM, which needs to be 	     accessable: */ 	  if (mi[nRegion].base >= 0xc0000 && mi[nRegion].base < 0x100000) {	    if (mi[nRegion].bound > 0x100000) {	      printf("Bad ROM bound\n");	      waitkbd();	    }	    mi[nRegion].type = MI_BOOTROM;	  }	  else	    mi[nRegion].type = MI_RESERVED;	  break;	default:	  mi[nRegion].type = MI_UNKNOWN;	  break;	}	if (bmi.Type == AddrRangeMemory &&	    mi[nRegion].base == mallocRegionBase &&	    mi[nRegion].bound == mallocRegionBound) {	  mallocSourceRegion = &mi[nRegion];	}	nRegion++;      }    } while (nextContinuation);  }  else {    uint32_t low = old_memsize(0); /* mem size in KB */    uint32_t hi = old_memsize(1);    nRegion = 0;    mi[nRegion].base = 0;    mi[nRegion].bound = (low * 1024);    mi[nRegion].type = MI_MEMORY;    nRegion++;    /* Forge an entry for the video region: */    mi[nRegion].base = mi[nRegion-1].bound;    mi[nRegion].bound = 0xa0000;    mi[nRegion].type = MI_RESERVED;    nRegion++;    /* For the BIOS prom. This could be wrong, as it depends on the     * setting of the memory window mapping code, but it should get us     * there for now.: */    mi[nRegion].base = 0xeec00;    mi[nRegion].bound = 0x100000;    mi[nRegion].type = MI_BOOTROM;    nRegion++;    mi[nRegion].base = 0x100000;	/* begins at 1M */    mi[nRegion].bound = 0x100000 + (hi * 1024);    mi[nRegion].type = MI_MEMORY;    mallocSourceRegion = &mi[nRegion];    nRegion++;    /* For the duplicate BIOS prom mapping. This could be wrong, as it     * depends on the setting of the memory window mapping code, but     * it should get us there for now.: */    mi[nRegion].base = 0xfec00000;    mi[nRegion].bound = 0xfec10000;    mi[nRegion].type = MI_RESERVED;    nRegion++;    /* Damned if I remember what this one is for, but I do remember a     * reserved region here too. */    mi[nRegion].base = 0xfee00000;    mi[nRegion].bound = 0xfee01000;    mi[nRegion].type = MI_RESERVED;    nRegion++;    /* And finally, the location of the hardware powerup boot vector: */    mi[nRegion].base = 0xfff80000;    mi[nRegion].bound = 0x100000000ull;    mi[nRegion].type = MI_RESERVED;    nRegion++;  }  /* Shorten the malloc source region to reflect what we have   * already taken out, and likewise set the base of the   * mallocRegion to reflect that.   */  mallocSourceRegion->bound = memInfoRgn;  mallocRegion->base = memInfoRgn;  /* Now we can finally call BootMalloc()! */#if 1  if (haveSMAP == 0) {    ShowMemory(bi);    printf("Press any key to load kernel\n");    waitkbd();  }#endif  return bi;}voidShowMemory(BootInfo *bi){  unsigned i;  printf("In ShowMemory()... %d regions\n", bi->nMemInfo);  for (i = 0; i < bi->nMemInfo; i++) {    const char *addrType;    MemInfo *pmi = &bi->memInfo[i];    switch(pmi->type) {    case MI_UNUSED:      addrType = "Unused!:    ";      break;    case MI_MEMORY:      addrType = "Memory:     ";      break;    case MI_RESERVED:      addrType = "Reserved:   ";      break;    case MI_BOOT:      addrType = "BootMalloc: ";      break;    case MI_RAMDISK:      addrType = "RamDisk:    ";      break;    case MI_DEVICEMEM:      addrType = "Device:     ";      break;    case MI_UNKNOWN:      addrType = "Unknown:    ";      break;    case MI_BOOTROM:      addrType = "BOOTROM:    ";      break;    case MI_PRELOAD:      addrType = "Preload:    ";      break;    default:      addrType = "???:        ";      break;    }    printf("  %s [0x%08lx%08lx, 0x%08lx%08lx)\n",	   addrType, 	   (uint32_t) (pmi->base >> 32),	   (uint32_t) (pmi->base),	   (uint32_t) (pmi->bound >> 32),	   (uint32_t) (pmi->bound));  }}void *BootAlloc(size_t sz, unsigned alignment){  void *dest;  kpsize_t avail;  if ( align_down(mallocSourceRegion->base, alignment) !=        mallocSourceRegion->base ) {    printf("base is misaligned\n");    halt();  }  avail = mallocSourceRegion->bound - mallocSourceRegion->base;  if (avail < sz) {    printf("Unable to allocate %d bytes with %d alignment\n",	   sz, alignment);    halt();  }  mallocSourceRegion->bound -= sz;  mallocSourceRegion->bound = align_down(mallocSourceRegion->bound, alignment);  mallocRegion->base = mallocSourceRegion->bound;  DEBUG(bootalloc)     printf("BootAlloc(%d %% %d) yields 0x%08x\n",	   sz, alignment, (uint32_t) mallocSourceRegion->bound);  dest = (void *) PA2BOOT(mallocSourceRegion->bound, uint32_t);  memset(dest, 0, sz);  return dest;}voidBindRegion(BootInfo *bi, kpa_t base, kpsize_t len, unsigned type){  MemInfo *mi = &bi->memInfo[bi->nMemInfo];  if (bi->nMemInfo == MAX_MEMINFO) {    printf("Total allowable count exceeded.\n");    halt();  }  bi->nMemInfo++;  mi->base = base;  mi->bound = base + len;  mi->type = type;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -