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 ofoff_MBankaccording tomdep. >+= (<-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_kmemimplementation. >= (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 fromvatofva. > 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 fromvatofva. >= (<-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);
};
Definesoff_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);
};
Definesoff_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::allocandfreeimplementation. > <off_MBank::startimplementation. > <off_MBank::get_pgsizeimplementation. > <off_MBank::notifyimplementation. > <off_MBank::allocate_kmemimplementation. > <off_MBank::get_urlimplementation. > <off_MBank::nameofimplementation. > <off_MBank::operator<<implementation. > <off_MBank::cleanupimplementation. > <off_MBank::copy_stateimplementation. > <off_MBank::restore_stateimplementation. > <off_MBank::operator=implementation. > <off_MBank::can_meltimplementation. > <off_MBank::freeze_stateimplementation. > <off_MBank::melt_stateimplementation. > <off_MBank::get_inspectorimplementation. > <off_MBank::get_navigatorimplementation. > <off_MBank::set_coreimplementation. > <off_MBank::get_kendimplementation. >
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_PFrameimplementation. > <off_PFrame::operator<<implementation. > <off_PFrame::get_url_holderimplementation. > <off_PFrame::copy_stateimplementation. > <off_PFrame::restore_stateimplementation. > <off_PFrame::operator newimplementation. > <off_PFrame::operator deleteimplementation. > <off_PFrame::get_inspectorimplementation. >
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_PgAllocatorimplementation. > <off_PgAllocator::set_coreimplementation. >
\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();
}