1 #ifndef H_MMU 2 #define H_MMU 3 4 #include "cpu.h" 5 #include "emu.h" 6 7 #ifdef __cplusplus 8 extern "C" { 9 #endif 10 11 /* Translate a VA to a PA, using a page table lookup */ 12 uint32_t mmu_translate(uint32_t addr, bool writing, fault_proc *fault, uint8_t *s_status); 13 14 /* Used for t-type (usermode-like) access */ 15 void mmu_check_priv(uint32_t addr, bool writing); 16 17 /* addr_cache is used to cache the translation of VA to PA per page. 18 * It has two entries per page (1k), one for reading and one for writing. 19 * The format for 32-bit x86 with JIT is different to minimize the needed 20 * registers in the x86 memory access functions and won't work for all 21 * platforms: 22 * 23 * a) Pointer entry 24 * The result of adding the virtual address (VA) to the entry has bit 31 25 * clear, and that sum is a pointer to within mem_and_flags. 26 * It would be cleaner to just use bit 0 or 1 to distinguish this case, but 27 * this way we can simultaneously check both that this is a pointer entry, 28 * and that the address is aligned, with a single bit test instruction. 29 * b) Physical address entry 30 * VA + entry has bit 31 set, and the entry (not the sum) has bit 22 clear. 31 * Bits 0-21 contain the difference between virtual and physical address. 32 * c) Invalid entry 33 * VA + entry has bit 31 set, entry has bit 22 set. Entry is invalid and 34 * addr_cache_miss must be called. 35 * 36 * In all other cases the format is simpler: 37 * a) Pointer entry: Bit 0 clear, rest difference to pointer to start of physical page 38 * b) Physical entry: Bit 0 set, Bit 1 clear, rest difference to physical address 39 * c) Invalid entry: Bit 0 set, Bit 1 set 40 */ 41 42 #define AC_NUM_ENTRIES (((1ull << 32) >> 10) * 2) 43 typedef uint8_t *ac_entry; 44 extern ac_entry *addr_cache __asm__("addr_cache"); 45 46 #if defined(__i386__) && !defined(NO_TRANSLATION) 47 #define AC_SET_ENTRY_PTR(entry, va, ptr) \ 48 entry = (ptr) - (va); 49 #define AC_NOT_PTR 0x80000000 50 #define AC_INVALID (1 << 22) 51 #define AC_SET_ENTRY_PHYS(entry, va, pa) \ 52 entry = (ac_entry)(((pa) - (va)) >> 10); \ 53 entry += (~(uintptr_t)((va) + entry) & AC_NOT_PTR); 54 #define AC_SET_ENTRY_INVALID(entry, va) \ 55 entry = (ac_entry)(AC_INVALID); \ 56 entry += (~(uintptr_t)((va) + entry) & AC_NOT_PTR); 57 #else 58 #define AC_SET_ENTRY_PTR(entry, va, ptr) \ 59 entry = (ptr) - (va); 60 #define AC_NOT_PTR 0x1 61 #define AC_INVALID 0x2 62 #define AC_FLAGS 0x3 63 #define AC_SET_ENTRY_PHYS(entry, va, pa) \ 64 entry = (ac_entry)(((pa) - (va)) | AC_NOT_PTR); 65 #define AC_SET_ENTRY_INVALID(entry, va) \ 66 entry = (ac_entry)(AC_INVALID | AC_NOT_PTR); 67 #endif 68 69 bool addr_cache_pagefault(void *addr); 70 void *addr_cache_miss(uint32_t addr, bool writing, fault_proc *fault) __asm__("addr_cache_miss"); 71 void addr_cache_flush(void); 72 void mmu_dump_tables(void); 73 74 #ifdef __cplusplus 75 } 76 #endif 77 78 #endif 79