📄 emumem.h
字号:
memory_fault_t get_last_fault() const {return last_fault;} target_addr_t get_last_faddr() const {return last_faddr;} private: /* a page table entry */ typedef struct memory_page_table_entry_t { unsigned int flag; byte_t *ptr; } memory_page_table_entry_t; // get the permission bits of a page unsigned int get_page_permission(target_addr_t addr) const; void set_page_permission(target_addr_t addr, unsigned int perm); // mark a page as available or unavailable void mark_page_available(target_addr_t addr, unsigned int perm); void mark_page_unavailable(target_addr_t addr); // remap and unmap a page, page is unavailable after successful unmap void remap_page(target_addr_t addr, memory_ext_interface *mif, unsigned int perm); void unmap_page(target_addr_t addr); /* test if an address crosses page boundary, size < MEM_PAGE_SIZE */ bool cross_page_boundary(target_addr_t addr, unsigned int size) const { return (addr & (MEMORY_PAGE_SIZE - 1)) > (MEMORY_PAGE_SIZE - size); } /* some useful utilities */ target_addr_t align_to_page_boundary(target_addr_t addr) const { return addr & ~(MEMORY_PAGE_SIZE-1); } byte_t swap(byte_t val) const { return val; } hword_t swap(hword_t val) const { return (val>>8) | (val<<8); } word_t swap(word_t val) const { return (val>>24) | ((val>>8)&0xFF00) | ((val&0xFF00)<<8) | (val<<24) ; } dword_t swap(dword_t val) const { return ((dword_t)swap((word_t)val)<<32) | (dword_t)swap((word_t)(val>>32)); } /* storage allocated for a normal page */ bool page_allocated(const memory_page_table_entry_t *pte) const { return ((pte->flag & MEMORY_PAGE_SLOW)==0); } /* storage allocated for a normal page */ bool page_allocated(target_addr_t addr) const { target_addr_t page_index = addr >> MEMORY_PAGE_SIZE_BITS; return ((page_table[page_index].flag & MEMORY_PAGE_SLOW)==0); } /* page remapped */ bool page_remapped(const memory_page_table_entry_t *pte) const { return (pte->flag & MEMORY_PAGE_REMAPPED); } /* page remapped */ bool page_remapped(target_addr_t addr) const { target_addr_t page_index = addr >> MEMORY_PAGE_SIZE_BITS; return (page_table[page_index].flag & MEMORY_PAGE_REMAPPED); } const memory_page_table_entry_t *get_page(target_addr_t addr) const { target_addr_t page_index = addr >> MEMORY_PAGE_SIZE_BITS; return page_table + page_index; } memory_page_table_entry_t *get_page(target_addr_t addr) { target_addr_t page_index = addr >> MEMORY_PAGE_SIZE_BITS; return page_table + page_index; } template<class T> T read_base(target_addr_t addr) {#ifdef CHECK_PAGE_BOUNDARY /* if crossing page boundary */ if (sizeof(T) > 1 && cross_page_boundary(addr, sizeof(T))) return read_slow<T>(addr);#endif const memory_page_table_entry_t *pte = get_page(addr); /* if empty (not allocated), remapped, bad, or not readable */ if (!(pte->flag & MEMORY_PAGE_READABLE)) return read_slow<T>(addr);#if WORDS_BIGENDIAN==TARGET_LITTLE_ENDIAN return swap(*reinterpret_cast<T *>(pte->ptr + addr));#else return *reinterpret_cast<T*>(pte->ptr + addr);#endif } template<class T> memory_fault_t read_base(target_addr_t addr, T *pval) {#ifdef CHECK_PAGE_BOUNDARY /* if crossing page boundary */ if (sizeof(T) > 1 && cross_page_boundary(addr, sizeof(T))) return read_slow(addr, pval);#endif const memory_page_table_entry_t *pte = get_page(addr); /* if empty (not allocated), remapped, bad, or not readable */ if (!(pte->flag & MEMORY_PAGE_READABLE)) return read_slow(addr, pval);#if WORDS_BIGENDIAN==TARGET_LITTLE_ENDIAN *pval = swap(*reinterpret_cast<T *>(pte->ptr + addr));#else *pval = *reinterpret_cast<T*>(pte->ptr + addr);#endif return MEM_NO_FAULT; } template<class T> memory_fault_t write_base(target_addr_t addr, T value) {#ifdef CHECK_PAGE_BOUNDARY /* if crossing page boundary */ if (cross_page_boundary(addr, sizeof(T))) return write_slow(addr, value);#endif const memory_page_table_entry_t *pte = get_page(addr); /* if empty (not allocated), remapped, bad, or not writable */ if (!(pte->flag & MEMORY_PAGE_WRITABLE)) return write_slow(addr, value);#if WORDS_BIGENDIAN==TARGET_LITTLE_ENDIAN *reinterpret_cast<T *>(pte->ptr + addr) = swap(value);#else *reinterpret_cast<T *>(pte->ptr + addr) = value;#endif return MEM_NO_FAULT; } /* slow but full featured memory acecss interface * overloading is safer here since these are private */ memory_fault_t write_slow(target_addr_t addr, dword_t value); memory_fault_t write_slow(target_addr_t addr, word_t value); memory_fault_t write_slow(target_addr_t addr, hword_t value); memory_fault_t write_slow(target_addr_t addr, byte_t value); memory_fault_t read_slow(target_addr_t addr, dword_t *pval); memory_fault_t read_slow(target_addr_t addr, word_t *pval); memory_fault_t read_slow(target_addr_t addr, hword_t *pval); memory_fault_t read_slow(target_addr_t addr, byte_t *pval); /* these are the basis of the above _slow functions, * their implementation is hidden in emumem.cpp file */ template <class T> memory_fault_t read_slow_base(target_addr_t addr, T *pval); template <class T> memory_fault_t write_slow_base(target_addr_t addr, T val); template <class T> T read_slow(target_addr_t addr) { T val; read_slow(addr, &val); return val; } /* simple block access functions */ memory_fault_t read_block_within_page(void *buf, target_addr_t addr, unsigned int size, unsigned *psize); memory_fault_t write_block_within_page(void *buf, target_addr_t addr, unsigned int size, unsigned *psize); memory_fault_t set_block_within_page(target_addr_t addr, byte_t value, unsigned int size, unsigned *psize); /* allocate and free space for a page * when memory runs out, allocate_page returns NOMEMORY_FAULT */ memory_fault_t allocate_page(memory_page_table_entry_t *pte); void free_page(memory_page_table_entry_t *pte); /* returns non-zero if there is a permission fault */ memory_fault_t check_page_permission(target_addr_t addr, unsigned int perm) const; memory_fault_t check_page_permission (const memory_page_table_entry_t *pte, unsigned int perm) const; /* Address translation, NULL if remapped or error. * The function is created for MMU's use. * The return value does not point to the actually storage. * Instead, ptr+addr is the actual address. * See allocate page for details. */ byte_t *translate(target_addr_t addr) { memory_fault_t fault; memory_page_table_entry_t *pte = get_page(addr); /* if normal */ if (page_allocated(pte)) return pte->ptr; /* normal page without space */ if (pte->flag & MEMORY_PAGE_EMPTY) { if ((fault = allocate_page(pte)) != MEM_NO_FAULT) report_fault(fault, addr); return pte->ptr; //ptr is NULL when allocate fails } /* IO remap, bad address */ return NULL; } /* report a fault, raise a signal it fault_sig is not -1 */ void report_fault(memory_fault_t f, target_addr_t addr); /* page table */ memory_page_table_entry_t page_table[MEMORY_PAGE_TABLE_SIZE]; /* stats information */ unsigned int page_count; /* signal on fault */ int fault_sig; /* stores the information of the last fault*/ memory_fault_t last_fault; target_addr_t last_faddr; friend class arm_mmu;};} /* namespace simit */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -