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

📄 kern_physmem.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
字号:
/* * Copyright (C) 1998, 1999, 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/kernel.hxx>#include <kerninc/util.h>#include <kerninc/PhysMem.hxx>#include <disk/DiskKey.hxx>#include <kerninc/BootInfo.h>     #define dbg_init	0x1u#define dbg_avail	0x2u#define dbg_alloc	0x4u#define dbg_new		0x8u/* Following should be an OR of some of the above */#define dbg_flags   ( 0u )#define DEBUG(x) if (dbg_##x & dbg_flags)/* Implementation of Memory Constraints */PmemConstraint PhysMem::pages = { (kpa_t) 0u, ~((kpa_t)0u), EROS_PAGE_SIZE };PmemConstraint PhysMem::any = { (kpa_t) 0u, ~((kpa_t)0u), sizeof(uint32_t) };extern "C" {  extern int end;}kpa_t PhysMem::PhysicalPageBound = 0;static PmemInfo PhysicalMemoryInfo[MAX_MEMINFO];PmemInfo *PhysMem::pmemInfo = &PhysicalMemoryInfo[0];unsigned long PhysMem::nPmemInfo;voidPhysMem::Init(){  for (unsigned i = 0; i < BootInfoPtr->nMemInfo; i++) {    MemInfo *pmi = &BootInfoPtr->memInfo[i];    bool readOnly = (pmi->type != MI_MEMORY);    (void) PhysMem::AddRegion(pmi->base, pmi->bound, pmi->type, readOnly);    if ( (pmi->type == MI_MEMORY || pmi->type == MI_RAMDISK ||	  pmi->type == MI_PRELOAD) &&	 PhysicalPageBound < pmi->bound)      PhysicalPageBound = 	align_up(pmi->bound + EROS_PAGE_SIZE - 1, EROS_PAGE_SIZE);  }  DEBUG(init) PrintStatus();  /* Allocate regions to hold the kernel and the primary mapping table: */  PmemConstraint constraint;  constraint.base = KERNPAGEDIR;  constraint.bound = KERNPAGEDIR + EROS_PAGE_SIZE;  constraint.align = EROS_PAGE_SIZE;  Alloc(constraint.bound - constraint.base, &constraint);  constraint.base = KERNPBASE;  constraint.bound = align_up((uint32_t) &end, EROS_PAGE_SIZE);  constraint.align = EROS_PAGE_SIZE;  Alloc(constraint.bound - constraint.base, &constraint);}PmemInfo *PhysMem::AddRegion(kpa_t base, kpa_t bound, uint32_t type, bool readOnly){  PmemInfo *kmi = &pmemInfo[nPmemInfo];  if (type == MI_DEVICEMEM) {    /* Do not do this check for the bootup cases, as some of those     * actually do overlap. */    for (unsigned int i = 0; i < nPmemInfo; i++) {      if (base >= pmemInfo[i].base && base < pmemInfo[i].bound)	return 0;      if (bound > pmemInfo[i].base && bound <= pmemInfo[i].bound)	return 0;    }  }  assert (nPmemInfo < MAX_MEMINFO);  kmi->base = base;  kmi->bound = bound;  kmi->type = type;  kmi->nPages = 0;  kmi->basepa = 0;  kmi->firstObHdr = 0;  kmi->readOnly = readOnly;  if (type == MI_MEMORY) {    kmi->allocBase = base;    kmi->allocBound = bound;  }  else {    kmi->allocBase = 0;    kmi->allocBound = 0;  }  nPmemInfo++;  return kmi;}kpsize_tPhysMem::TotalPhysicalPages(){  return PhysicalPageBound / EROS_PAGE_SIZE;}kpsize_tPhysMem::MemAvailable(PmemConstraint *mc, unsigned unitSize, bool contiguous){  unsigned nUnits = 0;  for (unsigned rgn = 0; rgn < BootInfoPtr->nMemInfo; rgn++) {    PmemInfo *kmi = &pmemInfo[rgn];    if (kmi->type != MI_MEMORY)      continue;    uint32_t base = kmi->allocBase;    uint32_t bound = kmi->allocBound;    base = max(base, mc->base);    bound = min(bound, mc->bound);    if (base >= bound)      continue;    /* The region (partially) overlaps the requested region */    base = align_up(base, mc->align);    unsigned unitsHere = (bound - base) / unitSize;    if (contiguous) {      if (nUnits < unitsHere)	nUnits = unitsHere;    }    else      nUnits += unitsHere;  }  DEBUG(avail) {    printf("%d units of %d %% %d %s bytes available\n",		   nUnits, unitSize, mc->align, 		   contiguous ? "contiguous" : "total");  }  return nUnits;}/* Preferentially allocate out of higher memory, because legacy DMA * controllers tend to have restricted addressable bounds in physical * memory. */static PmemInfo *preferred_region(PmemInfo *rgn1, PmemInfo *rgn2){  if (rgn1 == 0)    return rgn2;  if (rgn2 && rgn1->base < rgn2->base)    return rgn2;  return rgn1;}PmemInfo *PhysMem::ChooseRegion(kpsize_t nBytes, PmemConstraint *mc){  PmemInfo *allocTarget = 0;  for (unsigned rgn = 0; rgn < BootInfoPtr->nMemInfo; rgn++) {    PmemInfo *kmi = &pmemInfo[rgn];    if (kmi->type != MI_MEMORY)      continue;    kpa_t base = kmi->allocBase;    kpa_t bound = kmi->allocBound;    base = max(base, mc->base);    bound = min(bound, mc->bound);    if (base >= bound)      continue;    /* The region (partially) overlaps the requested region. See if it     * has enough suitably aligned space: */        kpa_t where = bound - nBytes;    where = align_down(where, mc->align);    if (where >= base)      allocTarget = preferred_region(allocTarget, kmi);  }  return allocTarget;}/* Allocate nBytes from available physical memory with constraint mc.   nBytes must be a multiple of mc->align. */kpa_tPhysMem::Alloc(kpsize_t nBytes, PmemConstraint *mc){  assert(((unsigned)nBytes & (mc->align - 1)) == 0);  DEBUG(alloc)     printf("PhysMem::Alloc: nBytes=0x%x, "                    "mc->base=0x%x, mc->bound=0x%x, mc->align=0x%x\n",                    (unsigned)nBytes, (unsigned)mc->base,                    (unsigned)mc->bound, mc->align);  PmemInfo *allocTarget = ChooseRegion(nBytes, mc);  if (allocTarget) {    /* We are willing to waste space at either the beginning or the end       if necessary for alignment. */    kpa_t allocTargetBaseAligned = align_up(allocTarget->allocBase, mc->align);    kpa_t allocTargetBoundAligned = align_down(allocTarget->allocBound,                                               mc->align);    /* Apply the constraint. */    kpa_t base  = max(allocTargetBaseAligned, mc->base);    kpa_t bound = min(allocTargetBoundAligned, mc->bound);    /* We will only grab from the end or from the beginning -- not     * from the middle. In fact, we will only grab from the beginning     * if we absolutely have to... */    kpa_t where        /* The following value is used in the "grab from end" case.           We assign it here to avoid a compiler warning. */        = allocTargetBoundAligned - nBytes;    if (bound == allocTargetBoundAligned) { /* grab from end */      /* where = allocTargetBoundAligned - nBytes; */      allocTarget->allocBound = where;    } else if (base == allocTargetBaseAligned) { /* grab from beginning */      where = allocTargetBaseAligned;      allocTarget->allocBase = where + nBytes;    } else {      printf("0x%x 0x%x 0x%x 0x%x\n",                     (unsigned)allocTarget->allocBase,                     (unsigned)allocTarget->allocBound,                     (unsigned)mc->base, (unsigned)mc->bound );      fatal("Physical memory allocator will not split memory regions\n");    }    assert(where >= base);    assert(where + nBytes <= bound);          DEBUG(alloc)      printf("Alloc %u %% %u at 0x%08x. "		     "Rgn 0x%08x now [0x%08x,0x%08x)\n", 		     (uint32_t) nBytes, mc->align, (uint32_t) where, 		     allocTarget, 		     (unsigned) allocTarget->allocBase, 		     (unsigned) allocTarget->allocBound);    return where;  }  return 0;}#ifdef OPTION_DDBvoidPhysMem::ddb_dump(){  extern void db_printf(const char *fmt, ...);  for (unsigned rgn = 0; rgn <nPmemInfo; rgn++) {    PmemInfo *kmi = &pmemInfo[rgn];    kpa_t base = kmi->allocBase;    kpa_t bound = kmi->allocBound;    printf("Rgn 0x%08x ty=%d: [0x%08x,0x%08x) %u bytes unallocated\n", 	   kmi,	   kmi->type,	   (unsigned) kmi->base,	   (unsigned) kmi->bound,	   (unsigned) bound - base);    if (kmi->firstObHdr) {      printf("  allocBase 0x%08x%08x allocBound 0x%08x%08x\n",	     (unsigned) (kmi->allocBase >> 32),	     (unsigned) (kmi->allocBase),	     (unsigned) (kmi->allocBound >> 32),	     (unsigned) (kmi->allocBound));      printf("  nPages 0x%08x (%d) basepa 0x%08x firstObHdr 0x%08x\n",	     kmi->nPages,	     kmi->nPages,	     kmi->basepa,	     kmi->firstObHdr);    }  }}#endif#define NEW_STOP falseextern void *malloc(size_t sz);void *operator new[](size_t sz, void *place){  void *v = 0;    if (place == 0)    v = KPAtoP(void *, PhysMem::Alloc(sz, &PhysMem::any));  else if (place == (void *) 1)    v = malloc(sz);  DEBUG(new)    dprintf(NEW_STOP, "placement vec new grabs "		    "0x%x (%d) at 0x%08x\n", sz,		    sz, v);  return v;}void *operator new(size_t sz, void * place){  void *v = 0;    if (place == 0)    v = KPAtoP(void *, PhysMem::Alloc(sz, &PhysMem::any));  else if (place == (void *) 1)    v = malloc(sz);      DEBUG(new)    dprintf(NEW_STOP, "placement new grabs "		    "0x%x (%d) at 0x%08x\n", sz,		    sz, v);  return v;}void *operator new(size_t sz){  fatal("Inappropriate call to non-placement operator new\n");  return KPAtoP(void *, PhysMem::Alloc(sz, &PhysMem::any));}void *operator new [](size_t sz){  fatal("Inappropriate call to non-placement operator vector new\n");  return KPAtoP(void *, PhysMem::Alloc(sz, &PhysMem::any));}

⌨️ 快捷键说明

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