next up previous contents
Next: 4.0.4 Multiple page size Up: 4. Exporting the hardware Previous: 4.0.2.1 Freezing memory banks

4.0.3 Kernel pages, reserved pages, and malloc pages

At boot time we have unused pages, pages used by the kernel, pages which should not be used (e.g. those corresponding to ROM devices, or whatever). The free pages can be used for users or for kernel dynamic memory.

Kernel dynamic memory is supported with the OSKit malloc implementation, which relies on an OSKit list memory manager named malloc_lmm. In any case, we have to reflect the current state of core into any core memory banks being created. That is done with allocate_kmem.

<Start other members of off_MBank according to mdep. >+= (<-U) [<-D]
allocate_kmem(mdep);

It is a private method to be used at memory bank startup time.

<Other private methods of off_MBank. >+= (<-U) [<-D]
// Allocates kernel memory and exhausts any malloc free memory
void allocate_kmem(const off_mdepMBank &mdep);

The implementation simply scans through the memory allocated to the kernel by the machine dependent part at boot time and reflects such state into the allocator. Only memory in the range handled by the memory bank being created is considered.

<off_MBank::allocate_kmem implementation. >= (U->)
// Allocates kernel memory and exhausts any malloc free memory
void off_MBank::allocate_kmem(const off_mdepMBank &mdep)
{

  vm_offset_t va;               // starting address
  vm_offset_t fva;              // next free address
  vm_size_t   size=0;           // size of free area

  va=mdep.get_first(); 

  do {
    fva=va;
    mdep.find_free(fva,size);
    <Allocate pages from va to fva. >
    do_debug(kcout << fmt("%x to ",va) << fmt("%x kallocated.",fva) <<nl);
    va = fva+size;
  } while (va < mdep.get_last());
}

To let the kernel know where its used memory ends, a new MBank method, get_kend, is provided for in-kernel use.

<Other public methods of off_MBank. >+= (<-U) [<-D->]
// Where is the page past the last one allocated for the kernel
// by allocate_kmem?
vm_offset_t get_kend(void) const;

Its implementation returns a value stored by allocate_kend.

<off_MBank::get_kend implementation. >= (U->)
// Where is the page past the last one allocated for the kernel
// by allocate_kmem?
vm_offset_t off_MBank::get_kend(void) const 
{
  return m_kend;
}

<Other private members of off_MBank. >+= (<-U) [<-D]
vm_offset_t m_kend; // page past the last one allocated for the kernel.

To allocate memory already being used we register it for kernel usage and update m_kend. The convention is that kernel pages are assigned to the node domain.

<Allocate pages from va to fva. >= (<-U)
{
  off_pg_id_t pg(get_id(),va);
  off_PFrame *pf;
  for ( ; pg < fva; pg += mdep.get_pgsz()  ){
    pf= new(this,pg) off_PFrame(get_protection(),nd.get_domain());
    assert(pf);
  }
  m_kend=fva;
}

\subsection{Memory banks and page frames for plain users}

These are the wrappers for memory banks and page frames:

<Off memory bank for users. >= (U->)
ENTRY class off_uMBank : public off_uHWCompResource {
public:
 off_uPFrame *alloc(off_Protection *prot, 
                   natural_t n=1, off_pg_id_t at=OFF_EU_ID_NULL);
 void free(off_uPFrame *pf, const off_Rights &r, natural_t n=1 );
 off_uPFrame *fetch(off_pg_id_t pfn,const off_Rights &r) const;
 vm_size_t get_pgsize(const off_Rights &r);

};
Defines off_uMBank (links are to index).

<Off memory bank dependencies. >+= (U->) [<-D]
#include <prtl/ex.h>            // for ENTRY

<Off page frame for users. >= (U->)
ENTRY class off_uPFrame : off_uHWResUnit {
public:
  off_pgf_t get_bits(const off_Rights &r);
  off_pgf_t set_bits(const off_pgf_t b, const off_Rights &r);
};
Defines off_uPFrame (links are to index).

<Off page frame dependencies. >+= (U->) [<-D]
#include <prtl/ex.h>            // for ENTRY

\subsection{Memory banks \cpp{} source files}

Memory bank code is kept in hw/MBank.h and hw/MBank.c.

<MBank.h*>=
<Read the literate code instead warning. >
#ifndef __OFF_MBANK_H
#define __OFF_MBANK_H 1

<Off memory bank dependencies. >

#ifdef __KERNEL__
<Off memory bank. >
#endif // __KERNEL__
<Off memory bank for users. >
#endif // __OFF_MBANK_H

<MBank.C*>=
<Read the literate code instead warning. >

#include <hw/MBank.h>           // Exported interface
<Off memory bank implementation dependencies. >

<Off memory bank static members. >

<off_MBank::alloc and free implementation. >
<off_MBank::start implementation. >
<off_MBank::get_pgsize implementation. >
<off_MBank::notify implementation. >
<off_MBank::allocate_kmem implementation. >
<off_MBank::get_url implementation. >
<off_MBank::nameof implementation. >
<off_MBank::operator<< implementation. >
<off_MBank::cleanup implementation. >
<off_MBank::copy_state implementation. >
<off_MBank::restore_state implementation. >
<off_MBank::operator= implementation. >
<off_MBank::can_melt implementation. >
<off_MBank::freeze_state implementation. >
<off_MBank::melt_state implementation. >
<off_MBank::get_inspector implementation. >
<off_MBank::get_navigator implementation. >
<off_MBank::set_core implementation. >
<off_MBank::get_kend implementation. >

Page frame code is kept in hw/PFrame.h and hw/PFrame.C.

<PFrame.h*>=
<Read the literate code instead warning. >
#ifndef __OFF_PFRAME_H
#define __OFF_PFRAME_H 1

<Off page frame dependencies. >
<Off page frame mode bits. >
#ifdef __KERNEL__
<Off page frame. >
#endif // __KERNEL__
<Off page frame for users. >

#endif // __OFF_PFRAME_H

<PFrame.C*>=
<Read the literate code instead warning. >

#include <hw/PFrame.h>          // Exported interface.
<Off page frame implementation dependencies. >

<Off page frame static members. >

<off_PFrame::off_PFrame implementation. >
<off_PFrame::operator<< implementation. >
<off_PFrame::get_url_holder implementation. >
<off_PFrame::copy_state implementation. >
<off_PFrame::restore_state implementation. >
<off_PFrame::operator new implementation. >
<off_PFrame::operator delete implementation. >
<off_PFrame::get_inspector implementation. >

The page allocator can be found in hw/PgAllocator.h and hw/PgAllocator.C.

<PgAllocator.h*>=
<Read the literate code instead warning. >
#ifndef __OFF_PG_ALLOCATOR_H
#define __OFF_PG_ALLOCATOR_H 1

<Off page frame allocator dependencies. >

#ifdef __KERNEL__
<Off linkable page frame. >
<Off page frame allocator. >
#endif // __KERNEL__

#endif // __OFF_PG_ALLOCATOR_H

<PgAllocator.C*>=
<Read the literate code instead warning. >

#include <hw/PgAllocator.h>     // exported interface
<Off page frame allocator implementation dependencies. >

<Off page frame allocator static members. >

<off_PgAllocator::off_PgAllocator implementation. >
<off_PgAllocator::set_core implementation. >

\subsection{Conversion routines}

We provide a couple of methods to convert addresses to page frame numbers and vice-versa. They operate on the minimum preferred page size and are implemented using machine dependent routines.

<Other public methods of off_MBank. >+= (<-U) [<-D->]
// Address to PFN.
static vm_offset_t a2p(vm_offset_t va){ return off_mdepMBank::a2p(va); }
// PFN to address. 
static vm_offset_t p2a(vm_offset_t va){ return off_mdepMBank::p2a(va); }

Besides, a mask to get page offsets is exported too.

<Other public methods of off_MBank. >+= (<-U) [<-D->]
// Returns the mask for page offsets.
static vm_offset_t pmask(void) { return off_mdepMBank::pmask(); }

Some other utilities are implemented using the previous ones.

<Other public methods of off_MBank. >+= (<-U) [<-D]
// Truncate or round to the next page boundary.
static vm_offset_t ptrunc(vm_offset_t va) { 
  return va & ~ off_mdepMBank::pmask();
}
static vm_offset_t pround(vm_offset_t va) { 
  return (va + off_mdepMBank::pmask()) & ~ off_mdepMBank::pmask();
}


next up previous contents
Next: 4.0.4 Multiple page size Up: 4. Exporting the hardware Previous: 4.0.2.1 Freezing memory banks
Francisco J. Ballesteros
1998-05-25