#ifndef _HPCBOOT_MEMORY_H_
#define _HPCBOOT_MEMORY_H_
#undef MEMORY_MAP_DEBUG
#include <hpcboot.h>
class Console;
template <class T>
inline T
ROUND(const T v, const T x) {
return((v + x - 1) / x) * x;
}
template <class T>
inline T
TRUNC(const T v, const T x) {
return(v / x) * x;
}
#define MAX_MEM_BANK 16
class MemoryManager {
private:
struct bank {
paddr_t addr;
psize_t size;
};
enum { WCE_VMEM_MAX = 32 * 1024 * 1024 };
enum { WCE_REGION_SIZE = 64 * 1024 };
protected:
Console *&_cons;
BOOL _debug;
enum { BLOCK_SIZE = WCE_REGION_SIZE * 64 };
vsize_t _page_size;
int _page_shift;
int _page_per_region;
struct bank _bank[MAX_MEM_BANK];
int _nbank;
vaddr_t _memory;
int _naddr_table;
struct AddressTranslationTable {
vaddr_t vaddr;
paddr_t paddr;
}
*_addr_table;
int _addr_table_idx;
public:
vsize_t getPageSize(void) { return _page_size; }
vsize_t getTaggedPageSize(void)
{ return _page_size - sizeof(struct PageTag); }
vsize_t estimateTaggedPageSize(vsize_t sz) {
vsize_t tsz = getTaggedPageSize();
return ((sz + tsz - 1) / tsz) * _page_size;
}
uint32_t roundPage(uint32_t v) { return ROUND(v, _page_size); }
uint32_t truncPage(uint32_t v) { return TRUNC(v, _page_size); }
uint32_t roundRegion(uint32_t v)
{ return ROUND(v, uint32_t(WCE_REGION_SIZE)); }
uint32_t truncRegion(uint32_t v)
{ return TRUNC(v, uint32_t(WCE_REGION_SIZE)); }
vaddr_t mapPhysicalPage(paddr_t paddr, psize_t size, uint32_t flags);
void unmapPhysicalPage(vaddr_t vaddr);
uint32_t readPhysical4(paddr_t paddr);
virtual paddr_t searchPage(vaddr_t vaddr) = 0;
MemoryManager(Console *&cons, size_t pagesize);
virtual ~MemoryManager(void);
BOOL &setDebug(void) { return _debug; }
virtual BOOL init(void) { return TRUE; }
BOOL reservePage(vsize_t size, BOOL page_commit = FALSE);
void loadBank(paddr_t paddr, psize_t psize);
BOOL getPage(vaddr_t &vaddr, paddr_t &paddr);
BOOL getTaggedPage(vaddr_t &vaddr, paddr_t &paddr);
BOOL getTaggedPage(vaddr_t &v, paddr_t &p, struct PageTag **pvec,
paddr_t &pvec_paddr);
};
class MemoryManager_LockPages : public MemoryManager {
private:
BOOL(*_lock_pages)(LPVOID, DWORD, PDWORD, int);
BOOL(*_unlock_pages)(LPVOID, DWORD);
int _shift;
public:
MemoryManager_LockPages(BOOL(*)(LPVOID, DWORD, PDWORD, int),
BOOL(*)(LPVOID, DWORD), Console *&, size_t, int = 0);
virtual ~MemoryManager_LockPages(void);
paddr_t searchPage(vaddr_t vaddr);
};
class MemoryManager_VirtualCopy : public MemoryManager {
private:
paddr_t _search_guess;
uint32_t _magic0, _magic1;
volatile uint32_t *_magic_addr;
enum {
MAGIC_CHECK_DONE = 0xac1dcafe,
MAGIC_CHECK_DUMMY = 0xa5a5a5a5
};
void setMagic(vaddr_t v) {
_magic_addr =(uint32_t *)v;
while ((_magic0 = Random()) == MAGIC_CHECK_DONE)
;
while ((_magic1 = Random()) == MAGIC_CHECK_DONE)
;
_magic_addr[0] = _magic0;
_magic_addr[1] = _magic1;
}
BOOL checkMagic(vaddr_t v) {
volatile uint32_t *marker =(uint32_t *)v;
return (marker[0] == _magic0) && (marker[1] == _magic1);
}
void clearMagic(void) {
_magic_addr[0] = MAGIC_CHECK_DONE;
_magic_addr[1] = MAGIC_CHECK_DONE;
}
vaddr_t checkMagicRegion(vaddr_t start, vsize_t size,
vsize_t step = 8) {
for (vaddr_t ref = start; ref < start + size; ref += step)
if (checkMagic(ref))
return ref - start;
return ~0;
}
paddr_t searchBank(int banknum);
public:
MemoryManager_VirtualCopy(Console *&, size_t);
virtual ~MemoryManager_VirtualCopy(void);
paddr_t searchPage(vaddr_t vaddr);
};
#endif